From bca2135104c778b8dfacec385cc9636cae7850a2 Mon Sep 17 00:00:00 2001 From: Danila Susak Date: Wed, 14 Jan 2026 20:48:43 +0300 Subject: [PATCH 1/2] fix: atomic save for option properties and color scheme Fixes issue where editing options in table properties would not save correctly. Changes: - Fix PropertyValue.tsx: Save options and colorScheme atomically to prevent data loss - Fix EditOptionsModal.tsx: Auto-close color picker menu after color selection - Fix OptionCell.tsx: Prioritize individual option colors over color scheme - Fix package.json: Correct typo in dev script (nnode -> node) - Update tsconfig.json: Change target from es6 to es2020 to support regex dotall flag - Update .gitignore: Add data.json to ignore user settings The main issue was that calling saveParsedValue twice would overwrite the first save with stale data. Now both fields are saved in a single atomic operation. --- .gitignore | 3 ++- package.json | 2 +- .../SpaceView/Contexts/DataTypeView/OptionCell.tsx | 6 +++--- .../react/components/UI/Menus/contexts/PropertyValue.tsx | 5 +++-- src/core/react/components/UI/Modals/EditOptionsModal.tsx | 6 +++++- tsconfig.json | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index ece2d46..33f510e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules .env .DS_Store undefined -.vscode \ No newline at end of file +.vscode +data.json diff --git a/package.json b/package.json index b197fb9..ef61587 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "make.md", "main": "main.js", "scripts": { - "dev": "nnode esbuild.config.mjs", + "dev": "node esbuild.config.mjs", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", "preview": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs preview", "demo": "&& node esbuild.config.mjs demo", diff --git a/src/core/react/components/SpaceView/Contexts/DataTypeView/OptionCell.tsx b/src/core/react/components/SpaceView/Contexts/DataTypeView/OptionCell.tsx index a244844..fb410d1 100644 --- a/src/core/react/components/SpaceView/Contexts/DataTypeView/OptionCell.tsx +++ b/src/core/react/components/SpaceView/Contexts/DataTypeView/OptionCell.tsx @@ -66,11 +66,11 @@ export const OptionCell = ( .map((t, index) => ({ ...t, color: editable - ? schemeColors + ? t.color?.length > 0 + ? t.color // Use individual option color if set + : schemeColors ? schemeColors[index % schemeColors.length]?.value || "var(--mk-color-none)" - : t.color?.length > 0 - ? t.color : undefined : undefined, removeable: editable ? editMode >= CellEditMode.EditModeView : false, diff --git a/src/core/react/components/UI/Menus/contexts/PropertyValue.tsx b/src/core/react/components/UI/Menus/contexts/PropertyValue.tsx index 77bc6d9..ee98931 100644 --- a/src/core/react/components/UI/Menus/contexts/PropertyValue.tsx +++ b/src/core/react/components/UI/Menus/contexts/PropertyValue.tsx @@ -444,10 +444,11 @@ export const PropertyValueComponent = (props: { const options = parseOptions(parsedValue.options ?? []); const saveOptionsHandler = (newOptions: SelectOption[], colorScheme?: string) => { - saveParsedValue("options", newOptions); + const updated: Record = { ...parsedValue, options: newOptions }; if (colorScheme !== undefined) { - saveParsedValue("colorScheme", colorScheme); + updated.colorScheme = colorScheme; } + props.saveValue(JSON.stringify(updated)); }; props.superstate.ui.openModal( diff --git a/src/core/react/components/UI/Modals/EditOptionsModal.tsx b/src/core/react/components/UI/Modals/EditOptionsModal.tsx index ef3e72f..a1e78ea 100644 --- a/src/core/react/components/UI/Modals/EditOptionsModal.tsx +++ b/src/core/react/components/UI/Modals/EditOptionsModal.tsx @@ -78,13 +78,17 @@ const SortableOptionItem: React.FC = ({ e.preventDefault(); // Always show color picker menu regardless of color scheme - showColorPickerMenu( + const menu = showColorPickerMenu( superstate, (e.target as HTMLElement).getBoundingClientRect(), windowFromDocument(e.view.document), option.color || "var(--mk-color-none)", (color: string) => { onEdit({ ...option, color }); + // Auto-close menu after color selection + if (menu) { + menu.hide(); + } } ); }; diff --git a/tsconfig.json b/tsconfig.json index c96f121..5d54678 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,7 @@ "inlineSources": true, "isolatedModules": true, "module": "ESNext", - "target": "es6", + "target": "es2020", "allowJs": true, "alwaysStrict": true, "noImplicitAny": true, From 92e1e4e906bcc0df72720bfbf23dbd3d38c3f9e7 Mon Sep 17 00:00:00 2001 From: Danila Susak Date: Wed, 14 Jan 2026 21:31:08 +0300 Subject: [PATCH 2/2] fix: sync checkbox state between properties sections Fixed issue where checkbox properties in the top section (inline properties) were not updating when changed in the bottom Properties section. Root cause: PropertiesView component was only listening to 'contextStateUpdated' events, which are not triggered when individual file properties are saved via saveProperties(). When a checkbox is toggled, it saves via saveProperties() which triggers 'pathStateUpdated' event instead. Solution: Added listener for 'pathStateUpdated' event to refresh property values when the current path's properties change. This ensures both property sections stay in sync. Changes: - Added pathChanged() handler to listen for pathStateUpdated events - Added pathState to useEffect dependencies for proper cleanup - Properties now refresh immediately when any property is saved --- .../react/components/Explorer/PropertiesView.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/core/react/components/Explorer/PropertiesView.tsx b/src/core/react/components/Explorer/PropertiesView.tsx index ac9c1eb..a829486 100644 --- a/src/core/react/components/Explorer/PropertiesView.tsx +++ b/src/core/react/components/Explorer/PropertiesView.tsx @@ -128,20 +128,34 @@ export const PropertiesView = (props: { } }; + const pathChanged = (payload: { path: string }) => { + if (payload.path == pathState?.path) { + refreshData(); + } + }; + useEffect(() => { refreshData(); props.superstate.eventsDispatcher.addListener( "contextStateUpdated", mdbChanged ); + props.superstate.eventsDispatcher.addListener( + "pathStateUpdated", + pathChanged + ); return () => { props.superstate.eventsDispatcher.removeListener( "contextStateUpdated", mdbChanged ); + props.superstate.eventsDispatcher.removeListener( + "pathStateUpdated", + pathChanged + ); }; - }, [props.spaces, tableData]); + }, [props.spaces, tableData, pathState]); const savePropertyValue = (value: string, f: SpaceTableColumn) => { if (saveProperty) { const property = tableData?.cols?.find((g) => g.name == f.name);