From 7cdefe3f6ef1ee24e2066028cdfd24247f98982c Mon Sep 17 00:00:00 2001 From: Chris Kruining Date: Wed, 5 Mar 2025 15:48:21 +0100 Subject: [PATCH] fix error with circular reactivity --- src/components/textarea/textarea.tsx | 27 +++++++++++++++++++++------ src/features/file/grid.tsx | 21 ++++++++++----------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/components/textarea/textarea.tsx b/src/components/textarea/textarea.tsx index 80433d2..c04480d 100644 --- a/src/components/textarea/textarea.tsx +++ b/src/components/textarea/textarea.tsx @@ -1,4 +1,4 @@ -import { Component, createEffect, createMemo, createSignal, For, onMount, untrack } from 'solid-js'; +import { Component, createEffect, createMemo, createSignal, For, on, onMount, untrack } from 'solid-js'; import { debounce } from '@solid-primitives/scheduled'; import { createSelection, getTextNodes } from '@solid-primitives/selection'; import { createSource } from '~/features/source'; @@ -18,12 +18,21 @@ interface TextareaProps { export function Textarea(props: TextareaProps) { const [selection, setSelection] = createSelection(); const [editorRef, setEditorRef] = createSignal(); + let mounted = false; const source = createSource(props.value); - createEffect(() => { - props.oninput?.(source.in); - }); + createEffect(on(() => [props.oninput, source.in] as const, ([oninput, text]) => { + if (!mounted) { + return; + } + + oninput?.(text); + })); + + onMount((() => { + mounted = true; + })); createEffect(() => { source.in = props.value; @@ -109,13 +118,19 @@ const Suggestions: Component = () => { const ref = untrack(() => suggestionRef()!); if (m === undefined) { - ref.hidePopover(); + if (ref.matches(':popover-open')) { + ref.hidePopover(); + } return; } m.style.setProperty('anchor-name', '--suggestions'); - ref.showPopover(); + + if (ref.matches(':not(:popover-open)')) { + ref.showPopover(); + } + ref.focus() return m; diff --git a/src/features/file/grid.tsx b/src/features/file/grid.tsx index 59696f7..0deb756 100644 --- a/src/features/file/grid.tsx +++ b/src/features/file/grid.tsx @@ -29,7 +29,7 @@ const groupBy = (rows: DataSetRowNode[]) => { : ({ kind: 'group', key, groupedBy: 'key', nodes: group(nodes.map(n => ({ ...n, _key: n._key.slice(key.length + 1) }))) }) ); - return group(rows.map(r => ({ ...r, _key: r.value.key }))) as any; + return group(rows.filter(r => r.value.key).map(r => ({ ...r, _key: r.value.key }))) as any; } export function Grid(props: { class?: string, rows: Entry[], locales: string[], api?: (api: GridApi) => any, children?: (key: string) => JSX.Element }) { @@ -65,19 +65,18 @@ export function Grid(props: { class?: string, rows: Entry[], locales: string[], const [api, setApi] = createSignal>(); // Normalize dataset in order to make sure all the files have the correct structure - createEffect(() => { - // For tracking - props.rows; - // const value = untrack(() => rows.value); + // createEffect(() => { + // // For tracking + // props.rows; - rows.mutateEach(({ key, ...locales }) => ({ key, ...Object.fromEntries(Object.entries(locales).map(([locale, value]) => [locale, value ?? ''])) })) - }); + // rows.mutateEach(({ key, ...locales }) => ({ key, ...Object.fromEntries(Object.entries(locales).map(([locale, value]) => [locale, value ?? ''])) })) + // }); - createEffect(() => { - const l = addedLocales(); + // createEffect(() => { + // const l = addedLocales(); - rows.mutateEach(({ key, ...rest }) => ({ key, ...rest, ...Object.fromEntries(l.map(locale => [locale, rest[locale] ?? ''])) })); - }); + // rows.mutateEach(({ key, ...rest }) => ({ key, ...rest, ...Object.fromEntries(l.map(locale => [locale, rest[locale] ?? ''])) })); + // }); createEffect(() => { props.api?.({