From 5f6138d30b34008fcdd64f65271b4d46e3562b4f Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Tue, 25 Feb 2025 17:02:11 +1100 Subject: [PATCH] quick and dirty search and replace --- package.json | 2 +- src/components/textarea/textarea.module.css | 4 + src/components/textarea/textarea.tsx | 93 +++--------------- .../createEditor-should-create-1.png | Bin 21680 -> 0 bytes src/features/editor/context.ts | 19 +++- vitest.config.ts | 1 + 6 files changed, 36 insertions(+), 83 deletions(-) delete mode 100644 src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png diff --git a/package.json b/package.json index ae5ab32..8bc887c 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "build": "vinxi build", "start": "vinxi start", "version": "vinxi version", - "test": "vitest --coverage --browser=chromium", + "test": "vitest --coverage", "test:ci": "vitest run" } } \ No newline at end of file diff --git a/src/components/textarea/textarea.module.css b/src/components/textarea/textarea.module.css index 70e634e..fadd9e2 100644 --- a/src/components/textarea/textarea.module.css +++ b/src/components/textarea/textarea.module.css @@ -27,6 +27,10 @@ position: absolute; inset-inline-end: 0; inset-block-start: 0; + + display: block grid; + grid-auto-flow: row; + gap: .5em; } .suggestions { diff --git a/src/components/textarea/textarea.tsx b/src/components/textarea/textarea.tsx index 39c20f8..34a2a29 100644 --- a/src/components/textarea/textarea.tsx +++ b/src/components/textarea/textarea.tsx @@ -4,6 +4,7 @@ import { isServer } from 'solid-js/web'; import { createEditContext } from '~/features/editor'; import { createSource } from '~/features/source'; import css from './textarea.module.css'; +import { debounce } from '@solid-primitives/scheduled'; interface TextareaProps { class?: string; @@ -17,9 +18,11 @@ interface TextareaProps { } export function Textarea(props: TextareaProps) { + const [replacement, setReplacement] = createSignal(''); const [editorRef, setEditorRef] = createSignal(); + const source = createSource(() => props.value); - const [text] = createEditContext(editorRef, () => source.out); + const [text, { mutate }] = createEditContext(editorRef, () => source.out); createEffect(() => { source.out = text(); @@ -41,9 +44,17 @@ export function Textarea(props: TextareaProps) { createHighlights(ref, 'search-results', errors); })); + const replace = () => { + mutate(text => text.replaceAll(source.query, replacement())); + }; + return <> - - source.query = e.target.value} /> +
+ source.query = e.target.value} /> + setReplacement(e.target.value)} /> + +
+
; } -const Suggestions: Component = () => { - const [selection] = createSelection(); - const [suggestionRef, setSuggestionRef] = createSignal(); - const [suggestions, setSuggestions] = createSignal([]); - - const marker = createMemo(() => { - if (isServer) { - return; - } - - const [n] = selection(); - const s = window.getSelection(); - - if (n === null || s === null || s.rangeCount < 1) { - return; - } - - return (findMarkerNode(s.getRangeAt(0)?.commonAncestorContainer) ?? undefined) as HTMLElement | undefined; - }); - - createEffect((prev) => { - if (prev) { - prev.style.setProperty('anchor-name', null); - } - - const m = marker(); - const ref = untrack(() => suggestionRef()!); - - if (m === undefined) { - ref.hidePopover(); - - return; - } - - m.style.setProperty('anchor-name', '--suggestions'); - ref.showPopover(); - ref.focus() - - return m; - }); - - createEffect(() => { - marker(); - - setSuggestions(Array(Math.ceil(Math.random() * 5)).fill('').map((_, i) => `suggestion ${i}`)); - }); - - const onPointerDown = (e: PointerEvent) => { - marker()?.replaceWith(document.createTextNode(e.target.textContent)); - }; - - const onKeyDown = (e: KeyboardEvent) => { - console.log(e); - } - - return - { - suggestion =>
  • {suggestion}
  • - }
    -
    ; -}; - -const findMarkerNode = (node: Node | null) => { - while (node !== null) { - if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).hasAttribute('data-marker')) { - break; - } - - node = node.parentNode; - } - - return node; -}; - - - const createHighlights = (node: Node, type: string, ranges: [number, number][]) => { queueMicrotask(() => { const nodes = getTextNodes(node); diff --git a/src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png b/src/features/editor/__screenshots__/context.spec.tsx/createEditor-should-create-1.png deleted file mode 100644 index d550b179e792a20f920f7d097106d1693bee6d8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21680 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]; +type Editor = [Accessor, { select(range: Range): void, mutate(setter: (text: string) => string): void }]; export function createEditor(ref: Accessor, value: Accessor): Editor { if (isServer) { - return [value]; + return [value, { + select(range) { }, + mutate() { }, + }]; } if (!("EditContext" in window)) { @@ -187,7 +190,17 @@ export function createEditor(ref: Accessor, value: Accessor } }); - return [createMemo(() => store.text)]; + return [ + createMemo(() => store.text), + { + select(range: Range) { + updateSelection(range); + }, + + mutate(setter) { + setStore('text', setter); + }, + }]; } const equals = (a: Range, b: Range): boolean => { diff --git a/vitest.config.ts b/vitest.config.ts index b74bc35..8debf4c 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -43,6 +43,7 @@ function reportWith(...reporter: CoverageReporter[]): Plugin { provider: 'playwright', enabled: true, headless: true, + screenshotFailures: false, instances: [{ browser: 'chromium' }] }; }