@flanksource/clicky-ui 0.3.40 → 0.3.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/ai.cjs +10 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +10 -0
- package/dist/ai.js.map +1 -1
- package/dist/components/AccordionList.cjs +5 -1
- package/dist/components/AccordionList.cjs.map +1 -1
- package/dist/components/AccordionList.d.ts +3 -1
- package/dist/components/AccordionList.d.ts.map +1 -1
- package/dist/components/AccordionList.js +5 -1
- package/dist/components/AccordionList.js.map +1 -1
- package/dist/components/JsonSchemaForm.cjs +9 -4
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +8 -3
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/json-schema-form-accordion-array.cjs +3 -1
- package/dist/components/json-schema-form-accordion-array.cjs.map +1 -1
- package/dist/components/json-schema-form-accordion-array.d.ts +4 -1
- package/dist/components/json-schema-form-accordion-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-accordion-array.js +3 -1
- package/dist/components/json-schema-form-accordion-array.js.map +1 -1
- package/dist/components/json-schema-form-array-view.cjs +63 -0
- package/dist/components/json-schema-form-array-view.cjs.map +1 -0
- package/dist/components/json-schema-form-array-view.d.ts +21 -0
- package/dist/components/json-schema-form-array-view.d.ts.map +1 -0
- package/dist/components/json-schema-form-array-view.js +63 -0
- package/dist/components/json-schema-form-array-view.js.map +1 -0
- package/dist/components/json-schema-form-array.cjs +3 -7
- package/dist/components/json-schema-form-array.cjs.map +1 -1
- package/dist/components/json-schema-form-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-array.js +3 -7
- package/dist/components/json-schema-form-array.js.map +1 -1
- package/dist/components/json-schema-form-conditionals.cjs +67 -0
- package/dist/components/json-schema-form-conditionals.cjs.map +1 -0
- package/dist/components/json-schema-form-conditionals.d.ts +9 -0
- package/dist/components/json-schema-form-conditionals.d.ts.map +1 -0
- package/dist/components/json-schema-form-conditionals.js +67 -0
- package/dist/components/json-schema-form-conditionals.js.map +1 -0
- package/dist/components/json-schema-form-defaults.cjs +68 -0
- package/dist/components/json-schema-form-defaults.cjs.map +1 -0
- package/dist/components/json-schema-form-defaults.d.ts +4 -0
- package/dist/components/json-schema-form-defaults.d.ts.map +1 -0
- package/dist/components/json-schema-form-defaults.js +68 -0
- package/dist/components/json-schema-form-defaults.js.map +1 -0
- package/dist/components/json-schema-form-errors.cjs +49 -31
- package/dist/components/json-schema-form-errors.cjs.map +1 -1
- package/dist/components/json-schema-form-errors.d.ts +4 -2
- package/dist/components/json-schema-form-errors.d.ts.map +1 -1
- package/dist/components/json-schema-form-errors.js +51 -33
- package/dist/components/json-schema-form-errors.js.map +1 -1
- package/dist/components/json-schema-form-filter.cjs +2 -1
- package/dist/components/json-schema-form-filter.cjs.map +1 -1
- package/dist/components/json-schema-form-filter.js +2 -1
- package/dist/components/json-schema-form-filter.js.map +1 -1
- package/dist/components/json-schema-form-item-summary.cjs +6 -2
- package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
- package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
- package/dist/components/json-schema-form-item-summary.js +6 -2
- package/dist/components/json-schema-form-item-summary.js.map +1 -1
- package/dist/components/json-schema-form-layout.cjs +28 -19
- package/dist/components/json-schema-form-layout.cjs.map +1 -1
- package/dist/components/json-schema-form-layout.d.ts +8 -6
- package/dist/components/json-schema-form-layout.d.ts.map +1 -1
- package/dist/components/json-schema-form-layout.js +29 -20
- package/dist/components/json-schema-form-layout.js.map +1 -1
- package/dist/components/json-schema-form-listener-paths.cjs +52 -0
- package/dist/components/json-schema-form-listener-paths.cjs.map +1 -0
- package/dist/components/json-schema-form-listener-paths.d.ts +10 -0
- package/dist/components/json-schema-form-listener-paths.d.ts.map +1 -0
- package/dist/components/json-schema-form-listener-paths.js +52 -0
- package/dist/components/json-schema-form-listener-paths.js.map +1 -0
- package/dist/components/json-schema-form-listener-types.d.ts +22 -0
- package/dist/components/json-schema-form-listener-types.d.ts.map +1 -0
- package/dist/components/json-schema-form-listeners.cjs +250 -0
- package/dist/components/json-schema-form-listeners.cjs.map +1 -0
- package/dist/components/json-schema-form-listeners.d.ts +13 -0
- package/dist/components/json-schema-form-listeners.d.ts.map +1 -0
- package/dist/components/json-schema-form-listeners.js +250 -0
- package/dist/components/json-schema-form-listeners.js.map +1 -0
- package/dist/components/json-schema-form-object-array-view.cjs +62 -0
- package/dist/components/json-schema-form-object-array-view.cjs.map +1 -0
- package/dist/components/json-schema-form-object-array-view.d.ts +14 -0
- package/dist/components/json-schema-form-object-array-view.d.ts.map +1 -0
- package/dist/components/json-schema-form-object-array-view.js +62 -0
- package/dist/components/json-schema-form-object-array-view.js.map +1 -0
- package/dist/components/json-schema-form-object.cjs +3 -0
- package/dist/components/json-schema-form-object.cjs.map +1 -1
- package/dist/components/json-schema-form-object.d.ts.map +1 -1
- package/dist/components/json-schema-form-object.js +3 -0
- package/dist/components/json-schema-form-object.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +17 -9
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +19 -11
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +6 -99
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts +1 -8
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +5 -98
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +15 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-table-array.cjs +67 -16
- package/dist/components/json-schema-form-table-array.cjs.map +1 -1
- package/dist/components/json-schema-form-table-array.d.ts +4 -1
- package/dist/components/json-schema-form-table-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-table-array.js +70 -19
- package/dist/components/json-schema-form-table-array.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +16 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.cjs +7 -1
- package/dist/components/json-schema-form-utils.cjs.map +1 -1
- package/dist/components/json-schema-form-utils.d.ts +2 -1
- package/dist/components/json-schema-form-utils.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.js +7 -1
- package/dist/components/json-schema-form-utils.js.map +1 -1
- package/dist/components.cjs +3 -2
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +3 -2
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +2 -1
- package/dist/components.js.map +1 -1
- package/dist/data/DataTable.cjs +9 -3
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +6 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +9 -3
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.cjs +43 -24
- package/dist/data/FixtureEditor/FixtureEditor.cjs.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.d.ts.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.js +43 -24
- package/dist/data/FixtureEditor/FixtureEditor.js.map +1 -1
- package/dist/data/Tree.cjs +10 -2
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.d.ts +6 -1
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +10 -2
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +143 -167
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.collection-types.d.ts +5 -0
- package/dist/data/ai/SessionInspector.collection-types.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.collection.cjs +18 -5
- package/dist/data/ai/SessionInspector.collection.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.collection.d.ts +2 -0
- package/dist/data/ai/SessionInspector.collection.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.collection.fixtures.d.ts +6 -0
- package/dist/data/ai/SessionInspector.collection.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.collection.js +18 -5
- package/dist/data/ai/SessionInspector.collection.js.map +1 -1
- package/dist/data/ai/SessionInspector.d.ts +24 -2
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.cjs +105 -7
- package/dist/data/ai/SessionInspector.hierarchy-state.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.d.ts +12 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.js +107 -9
- package/dist/data/ai/SessionInspector.hierarchy-state.js.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.cjs +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.js +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.js.map +1 -1
- package/dist/data/ai/SessionInspector.js +144 -168
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.cjs +116 -0
- package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.legacy.d.ts +19 -0
- package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.legacy.js +116 -0
- package/dist/data/ai/SessionInspector.legacy.js.map +1 -0
- package/dist/data/ai/SessionInspector.panels.cjs +3 -0
- package/dist/data/ai/SessionInspector.panels.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.panels.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.panels.js +3 -0
- package/dist/data/ai/SessionInspector.panels.js.map +1 -1
- package/dist/data/ai/SessionInspector.plan.cjs +29 -12
- package/dist/data/ai/SessionInspector.plan.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.plan.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.plan.js +30 -13
- package/dist/data/ai/SessionInspector.plan.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.cjs +44 -0
- package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.remote-view.d.ts +11 -0
- package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.remote-view.js +44 -0
- package/dist/data/ai/SessionInspector.remote-view.js.map +1 -0
- package/dist/data/ai/SessionInspector.remote.cjs +275 -0
- package/dist/data/ai/SessionInspector.remote.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.remote.d.ts +57 -0
- package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.remote.js +275 -0
- package/dist/data/ai/SessionInspector.remote.js.map +1 -0
- package/dist/data/ai/SessionInspector.summary.cjs +0 -156
- package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.summary.d.ts +0 -3
- package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.summary.js +2 -158
- package/dist/data/ai/SessionInspector.summary.js.map +1 -1
- package/dist/data/ai/SessionInspector.tab-state.cjs +15 -0
- package/dist/data/ai/SessionInspector.tab-state.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.tab-state.d.ts +3 -0
- package/dist/data/ai/SessionInspector.tab-state.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.tab-state.js +15 -0
- package/dist/data/ai/SessionInspector.tab-state.js.map +1 -0
- package/dist/data/ai/SessionInspector.tabs.model.cjs +31 -18
- package/dist/data/ai/SessionInspector.tabs.model.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.tabs.model.d.ts +3 -1
- package/dist/data/ai/SessionInspector.tabs.model.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.tabs.model.js +32 -19
- package/dist/data/ai/SessionInspector.tabs.model.js.map +1 -1
- package/dist/data/ai/SessionInspector.verification.cjs +53 -0
- package/dist/data/ai/SessionInspector.verification.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.verification.d.ts +7 -0
- package/dist/data/ai/SessionInspector.verification.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.verification.js +53 -0
- package/dist/data/ai/SessionInspector.verification.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +7 -1
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +21 -3
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +7 -1
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +13 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/index.d.ts +3 -1
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/devtools/useDebugStream.cjs +5 -1
- package/dist/devtools/useDebugStream.cjs.map +1 -1
- package/dist/devtools/useDebugStream.d.ts.map +1 -1
- package/dist/devtools/useDebugStream.js +6 -2
- package/dist/devtools/useDebugStream.js.map +1 -1
- package/dist/hooks/event-source-provider.cjs +9 -0
- package/dist/hooks/event-source-provider.cjs.map +1 -0
- package/dist/hooks/event-source-provider.d.ts +15 -0
- package/dist/hooks/event-source-provider.d.ts.map +1 -0
- package/dist/hooks/event-source-provider.js +9 -0
- package/dist/hooks/event-source-provider.js.map +1 -0
- package/dist/hooks/event-source.cjs +11 -0
- package/dist/hooks/event-source.cjs.map +1 -0
- package/dist/hooks/event-source.d.ts +22 -0
- package/dist/hooks/event-source.d.ts.map +1 -0
- package/dist/hooks/event-source.js +11 -0
- package/dist/hooks/event-source.js.map +1 -0
- package/dist/hooks/use-log-tail.cjs +5 -1
- package/dist/hooks/use-log-tail.cjs.map +1 -1
- package/dist/hooks/use-log-tail.d.ts.map +1 -1
- package/dist/hooks/use-log-tail.js +5 -1
- package/dist/hooks/use-log-tail.js.map +1 -1
- package/dist/hooks/use-prompts.cjs +5 -1
- package/dist/hooks/use-prompts.cjs.map +1 -1
- package/dist/hooks/use-prompts.d.ts.map +1 -1
- package/dist/hooks/use-prompts.js +6 -2
- package/dist/hooks/use-prompts.js.map +1 -1
- package/dist/hooks/use-task-run.cjs +9 -2
- package/dist/hooks/use-task-run.cjs.map +1 -1
- package/dist/hooks/use-task-run.d.ts.map +1 -1
- package/dist/hooks/use-task-run.js +10 -3
- package/dist/hooks/use-task-run.js.map +1 -1
- package/dist/hooks.cjs +4 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +4 -0
- package/dist/hooks.js.map +1 -1
- package/dist/icons/programmingCatalog.cjs +34 -34
- package/dist/icons/programmingCatalog.cjs.map +1 -1
- package/dist/icons/programmingCatalog.js +34 -34
- package/dist/icons/programmingCatalog.js.map +1 -1
- package/dist/index.cjs +9 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/monaco/MonacoEditor.cjs +4 -1
- package/dist/monaco/MonacoEditor.cjs.map +1 -1
- package/dist/monaco/MonacoEditor.d.ts +1 -1
- package/dist/monaco/MonacoEditor.d.ts.map +1 -1
- package/dist/monaco/MonacoEditor.js +4 -1
- package/dist/monaco/MonacoEditor.js.map +1 -1
- package/dist/monaco/types.d.ts +2 -1
- package/dist/monaco/types.d.ts.map +1 -1
- package/dist/overlay/CommandPalette.cjs +14 -4
- package/dist/overlay/CommandPalette.cjs.map +1 -1
- package/dist/overlay/CommandPalette.d.ts +5 -1
- package/dist/overlay/CommandPalette.d.ts.map +1 -1
- package/dist/overlay/CommandPalette.js +14 -4
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/CommandPaletteList.cjs +5 -0
- package/dist/overlay/CommandPaletteList.cjs.map +1 -1
- package/dist/overlay/CommandPaletteList.d.ts +4 -2
- package/dist/overlay/CommandPaletteList.d.ts.map +1 -1
- package/dist/overlay/CommandPaletteList.js +5 -0
- package/dist/overlay/CommandPaletteList.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.js +1 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +29 -26
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +9 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +29 -26
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.cjs +62 -256
- package/dist/rpc/OperationEntityContextPicker.cjs.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.d.ts.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.js +64 -258
- package/dist/rpc/OperationEntityContextPicker.js.map +1 -1
- package/dist/rpc/OperationEntityPicker.cjs +185 -0
- package/dist/rpc/OperationEntityPicker.cjs.map +1 -0
- package/dist/rpc/OperationEntityPicker.d.ts +51 -0
- package/dist/rpc/OperationEntityPicker.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPicker.js +185 -0
- package/dist/rpc/OperationEntityPicker.js.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.cjs +39 -0
- package/dist/rpc/OperationEntityPicker.model.cjs.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.d.ts +27 -0
- package/dist/rpc/OperationEntityPicker.model.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.js +39 -0
- package/dist/rpc/OperationEntityPicker.model.js.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.cjs +85 -0
- package/dist/rpc/operationCatalogRowSelection.cjs.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.d.ts +57 -0
- package/dist/rpc/operationCatalogRowSelection.d.ts.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.js +85 -0
- package/dist/rpc/operationCatalogRowSelection.js.map +1 -0
- package/dist/rpc/operationEntityPicker.fixtures.d.ts +13 -0
- package/dist/rpc/operationEntityPicker.fixtures.d.ts.map +1 -0
- package/dist/rpc.cjs +2 -0
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +2 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -0
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -1
- package/schemas/json-schema-form.schema.json +566 -0
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,8 @@ const useDensity = require("./hooks/use-density.cjs");
|
|
|
21
21
|
const densityProvider = require("./hooks/density-provider.cjs");
|
|
22
22
|
const useSort = require("./hooks/use-sort.cjs");
|
|
23
23
|
const useHistoryRoute = require("./hooks/use-history-route.cjs");
|
|
24
|
+
const eventSource = require("./hooks/event-source.cjs");
|
|
25
|
+
const eventSourceProvider = require("./hooks/event-source-provider.cjs");
|
|
24
26
|
const useTaskRun = require("./hooks/use-task-run.cjs");
|
|
25
27
|
const usePrompts = require("./hooks/use-prompts.cjs");
|
|
26
28
|
const useHotkey = require("./hooks/use-hotkey.cjs");
|
|
@@ -91,6 +93,7 @@ const formLookupContext = require("./components/form-lookup-context.cjs");
|
|
|
91
93
|
const jsonSchemaFormSize = require("./components/json-schema-form-size.cjs");
|
|
92
94
|
const jsonSchemaFormPreferences = require("./components/json-schema-form-preferences.cjs");
|
|
93
95
|
const jsonSchemaFormResolve = require("./components/json-schema-form-resolve.cjs");
|
|
96
|
+
const jsonSchemaFormConditionals = require("./components/json-schema-form-conditionals.cjs");
|
|
94
97
|
const jsonSchemaFormRefs = require("./components/json-schema-form-refs.cjs");
|
|
95
98
|
const jsonSchemaFormTemplate = require("./components/json-schema-form-template.cjs");
|
|
96
99
|
const jsonSchemaFormExtensions = require("./components/json-schema-form-extensions.cjs");
|
|
@@ -245,6 +248,7 @@ const CommentFilterBar = require("./comments/CommentFilterBar.cjs");
|
|
|
245
248
|
const CommentProgress = require("./comments/CommentProgress.cjs");
|
|
246
249
|
const Clicky = require("./data/Clicky.cjs");
|
|
247
250
|
const OperationCatalog = require("./rpc/OperationCatalog.cjs");
|
|
251
|
+
const OperationEntityPicker = require("./rpc/OperationEntityPicker.cjs");
|
|
248
252
|
const SessionsCatalog = require("./rpc/SessionsCatalog.cjs");
|
|
249
253
|
const SessionHeader = require("./rpc/SessionHeader.cjs");
|
|
250
254
|
const useSession = require("./rpc/useSession.cjs");
|
|
@@ -978,6 +982,8 @@ exports.DensityProvider = densityProvider.DensityProvider;
|
|
|
978
982
|
exports.DensityValueProvider = densityProvider.DensityValueProvider;
|
|
979
983
|
exports.useSort = useSort.useSort;
|
|
980
984
|
exports.useHistoryRoute = useHistoryRoute.useHistoryRoute;
|
|
985
|
+
exports.useEventSourceFactory = eventSource.useEventSourceFactory;
|
|
986
|
+
exports.EventSourceProvider = eventSourceProvider.EventSourceProvider;
|
|
981
987
|
exports.useTaskRun = useTaskRun.useTaskRun;
|
|
982
988
|
exports.useTaskRuns = useTaskRun.useTaskRuns;
|
|
983
989
|
exports.answerPrompt = usePrompts.answerPrompt;
|
|
@@ -1083,10 +1089,10 @@ exports.DEFAULT_FORM_SIZE = jsonSchemaFormSize.DEFAULT_FORM_SIZE;
|
|
|
1083
1089
|
exports.DEFAULT_PREFERENCES_STORAGE_KEY = jsonSchemaFormPreferences.DEFAULT_PREFERENCES_STORAGE_KEY;
|
|
1084
1090
|
exports.readPreferences = jsonSchemaFormPreferences.readPreferences;
|
|
1085
1091
|
exports.writePreferences = jsonSchemaFormPreferences.writePreferences;
|
|
1086
|
-
exports.effectiveProperties = jsonSchemaFormResolve.effectiveProperties;
|
|
1087
1092
|
exports.isOpenStringMap = jsonSchemaFormResolve.isOpenStringMap;
|
|
1088
|
-
exports.matchesIf = jsonSchemaFormResolve.matchesIf;
|
|
1089
1093
|
exports.resolveControl = jsonSchemaFormResolve.resolveControl;
|
|
1094
|
+
exports.effectiveProperties = jsonSchemaFormConditionals.effectiveProperties;
|
|
1095
|
+
exports.matchesIf = jsonSchemaFormConditionals.matchesIf;
|
|
1090
1096
|
exports.rehydrateRefs = jsonSchemaFormRefs.rehydrateRefs;
|
|
1091
1097
|
exports.templateValuePre = jsonSchemaFormTemplate.templateValuePre;
|
|
1092
1098
|
exports.applyPostExtensions = jsonSchemaFormExtensions.applyPostExtensions;
|
|
@@ -1381,6 +1387,7 @@ exports.Clicky = Clicky.Clicky;
|
|
|
1381
1387
|
exports.ClickyNodeView = Clicky.ClickyNodeView;
|
|
1382
1388
|
exports.ClickyTable = Clicky.ClickyTable;
|
|
1383
1389
|
exports.OperationCatalog = OperationCatalog.OperationCatalog;
|
|
1390
|
+
exports.OperationEntityPicker = OperationEntityPicker.OperationEntityPicker;
|
|
1384
1391
|
exports.SESSIONS_SURFACE_KEY = SessionsCatalog.SESSIONS_SURFACE_KEY;
|
|
1385
1392
|
exports.SessionsCatalog = SessionsCatalog.SessionsCatalog;
|
|
1386
1393
|
exports.SessionHeader = SessionHeader.SessionHeader;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,8 @@ import { useDensity, useDensityValue } from "./hooks/use-density.js";
|
|
|
19
19
|
import { DensityProvider, DensityValueProvider } from "./hooks/density-provider.js";
|
|
20
20
|
import { useSort } from "./hooks/use-sort.js";
|
|
21
21
|
import { useHistoryRoute } from "./hooks/use-history-route.js";
|
|
22
|
+
import { useEventSourceFactory } from "./hooks/event-source.js";
|
|
23
|
+
import { EventSourceProvider } from "./hooks/event-source-provider.js";
|
|
22
24
|
import { useTaskRun, useTaskRuns } from "./hooks/use-task-run.js";
|
|
23
25
|
import { answerPrompt, usePrompts } from "./hooks/use-prompts.js";
|
|
24
26
|
import { formatHotkey, parseHotkey, useHotkey } from "./hooks/use-hotkey.js";
|
|
@@ -88,7 +90,8 @@ import { FormLookupProvider } from "./components/FormLookupProvider.js";
|
|
|
88
90
|
import { resolveLookupScope, useLookupFetcher } from "./components/form-lookup-context.js";
|
|
89
91
|
import { DEFAULT_FORM_SIZE } from "./components/json-schema-form-size.js";
|
|
90
92
|
import { DEFAULT_PREFERENCES_STORAGE_KEY, readPreferences, writePreferences } from "./components/json-schema-form-preferences.js";
|
|
91
|
-
import {
|
|
93
|
+
import { isOpenStringMap, resolveControl } from "./components/json-schema-form-resolve.js";
|
|
94
|
+
import { effectiveProperties, matchesIf } from "./components/json-schema-form-conditionals.js";
|
|
92
95
|
import { rehydrateRefs } from "./components/json-schema-form-refs.js";
|
|
93
96
|
import { templateValuePre } from "./components/json-schema-form-template.js";
|
|
94
97
|
import { applyPostExtensions } from "./components/json-schema-form-extensions.js";
|
|
@@ -243,6 +246,7 @@ import { CommentFilterBar } from "./comments/CommentFilterBar.js";
|
|
|
243
246
|
import { CommentProgress } from "./comments/CommentProgress.js";
|
|
244
247
|
import { Clicky, ClickyNodeView, ClickyTable } from "./data/Clicky.js";
|
|
245
248
|
import { OperationCatalog } from "./rpc/OperationCatalog.js";
|
|
249
|
+
import { OperationEntityPicker } from "./rpc/OperationEntityPicker.js";
|
|
246
250
|
import { SESSIONS_SURFACE_KEY, SessionsCatalog } from "./rpc/SessionsCatalog.js";
|
|
247
251
|
import { SessionHeader } from "./rpc/SessionHeader.js";
|
|
248
252
|
import { SESSION_POLL_MS, useSession } from "./rpc/useSession.js";
|
|
@@ -980,6 +984,7 @@ export {
|
|
|
980
984
|
EntityExplorerApp,
|
|
981
985
|
ErrorDetails,
|
|
982
986
|
ErrorWrapper,
|
|
987
|
+
EventSourceProvider,
|
|
983
988
|
ExecutionTree,
|
|
984
989
|
Field,
|
|
985
990
|
FieldErrorText,
|
|
@@ -1052,6 +1057,7 @@ export {
|
|
|
1052
1057
|
OperationCommandPage,
|
|
1053
1058
|
OperationEntityContextPicker,
|
|
1054
1059
|
OperationEntityPage,
|
|
1060
|
+
OperationEntityPicker,
|
|
1055
1061
|
OperationPicker,
|
|
1056
1062
|
OperationResultView,
|
|
1057
1063
|
OperationScheduleDialog,
|
|
@@ -2549,6 +2555,7 @@ export {
|
|
|
2549
2555
|
useDensity,
|
|
2550
2556
|
useDensityValue,
|
|
2551
2557
|
useEscapeLayer,
|
|
2558
|
+
useEventSourceFactory,
|
|
2552
2559
|
useFloatingZIndex,
|
|
2553
2560
|
useForm,
|
|
2554
2561
|
useHistoryRoute,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -27,6 +27,7 @@ Editor.loader.config({ monaco: monacoEditor__namespace });
|
|
|
27
27
|
function MonacoEditor({
|
|
28
28
|
value,
|
|
29
29
|
onChange,
|
|
30
|
+
readOnly = false,
|
|
30
31
|
language,
|
|
31
32
|
path,
|
|
32
33
|
height = "20rem",
|
|
@@ -34,6 +35,7 @@ function MonacoEditor({
|
|
|
34
35
|
onMount,
|
|
35
36
|
onValidate
|
|
36
37
|
}) {
|
|
38
|
+
if (!readOnly && !onChange) throw new Error("MonacoEditor requires onChange when editing");
|
|
37
39
|
const workers = useMonacoWorker.useMonacoWorkerFactory();
|
|
38
40
|
const theme = useTheme.useResolvedTheme() === "dark" ? "vs-dark" : "light";
|
|
39
41
|
const latestValue = react.useRef(value);
|
|
@@ -45,7 +47,7 @@ function MonacoEditor({
|
|
|
45
47
|
Editor,
|
|
46
48
|
{
|
|
47
49
|
value,
|
|
48
|
-
onChange: (next) => onChange(next ?? ""),
|
|
50
|
+
onChange: (next) => onChange == null ? void 0 : onChange(next ?? ""),
|
|
49
51
|
language,
|
|
50
52
|
path,
|
|
51
53
|
height,
|
|
@@ -58,6 +60,7 @@ function MonacoEditor({
|
|
|
58
60
|
},
|
|
59
61
|
...onValidate ? { onValidate } : {},
|
|
60
62
|
options: {
|
|
63
|
+
readOnly,
|
|
61
64
|
automaticLayout: true,
|
|
62
65
|
fontFamily: "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)",
|
|
63
66
|
fontSize: 13,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonacoEditor.cjs","sources":["../../src/monaco/MonacoEditor.tsx"],"sourcesContent":["import Editor, { loader, type Monaco } from \"@monaco-editor/react\";\nimport * as monaco from \"monaco-editor\";\nimport { useRef } from \"react\";\nimport { useResolvedTheme } from \"../hooks/use-theme\";\nimport { useMonacoWorkerFactory } from \"./use-monaco-worker\";\nimport type { MonacoEditorProps } from \"./types\";\n\nloader.config({ monaco });\n\nexport function MonacoEditor({\n value,\n onChange,\n language,\n path,\n height = \"20rem\",\n beforeMount,\n onMount,\n onValidate,\n}: MonacoEditorProps) {\n const workers = useMonacoWorkerFactory();\n const theme = useResolvedTheme() === \"dark\" ? \"vs-dark\" : \"light\";\n // @monaco-editor/react keeps the first onMount it sees, so read the value at\n // mount time through a ref rather than that render's closure.\n const latestValue = useRef(value);\n latestValue.current = value;\n\n if (!workers) {\n return <div role=\"alert\" className=\"rounded-md border border-destructive/40 p-3 text-sm text-destructive\">Monaco workers are not configured.</div>;\n }\n\n return (\n <div className=\"overflow-hidden rounded-md border border-input\" data-slot=\"monaco-editor\">\n <Editor\n value={value}\n onChange={(next) => onChange(next ?? \"\")}\n language={language}\n path={path}\n height={height}\n theme={theme}\n keepCurrentModel\n {...(beforeMount ? { beforeMount } : {})}\n onMount={(instance, monacoInstance) => {\n // keepCurrentModel remounts onto the model already at `path`, which\n // still holds the text from when the previous editor unmounted.\n if (instance.getValue() !== latestValue.current) instance.setValue(latestValue.current);\n onMount?.(instance, monacoInstance);\n }}\n {...(onValidate ? { onValidate } : {})}\n options={{\n automaticLayout: true,\n fontFamily: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)\",\n fontSize: 13,\n lineHeight: 20,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n tabSize: 2,\n wordWrap: \"on\",\n quickSuggestions: { other: true, comments: true, strings: true },\n }}\n />\n </div>\n );\n}\n\nexport type { Monaco };\n"],"names":["loader","monaco","useMonacoWorkerFactory","useResolvedTheme","useRef","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAOAA,OAAAA,OAAO,OAAO,EAAA,QAAEC,yBAAQ;AAEjB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,UAAUC,gBAAAA,uBAAA;AAChB,QAAM,QAAQC,SAAAA,iBAAA,MAAuB,SAAS,YAAY;AAG1D,QAAM,cAAcC,MAAAA,OAAO,KAAK;AAChC,cAAY,UAAU;AAEtB,MAAI,CAAC,SAAS;AACZ,0CAAQ,OAAA,EAAI,MAAK,SAAQ,WAAU,wEAAuE,UAAA,sCAAkC;AAAA,EAC9I;AAEA,SACEC,2BAAAA,IAAC,OAAA,EAAI,WAAU,kDAAiD,aAAU,iBACxE,UAAAA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"MonacoEditor.cjs","sources":["../../src/monaco/MonacoEditor.tsx"],"sourcesContent":["import Editor, { loader, type Monaco } from \"@monaco-editor/react\";\nimport * as monaco from \"monaco-editor\";\nimport { useRef } from \"react\";\nimport { useResolvedTheme } from \"../hooks/use-theme\";\nimport { useMonacoWorkerFactory } from \"./use-monaco-worker\";\nimport type { MonacoEditorProps } from \"./types\";\n\nloader.config({ monaco });\n\nexport function MonacoEditor({\n value,\n onChange,\n readOnly = false,\n language,\n path,\n height = \"20rem\",\n beforeMount,\n onMount,\n onValidate,\n}: MonacoEditorProps) {\n if (!readOnly && !onChange) throw new Error(\"MonacoEditor requires onChange when editing\");\n const workers = useMonacoWorkerFactory();\n const theme = useResolvedTheme() === \"dark\" ? \"vs-dark\" : \"light\";\n // @monaco-editor/react keeps the first onMount it sees, so read the value at\n // mount time through a ref rather than that render's closure.\n const latestValue = useRef(value);\n latestValue.current = value;\n\n if (!workers) {\n return <div role=\"alert\" className=\"rounded-md border border-destructive/40 p-3 text-sm text-destructive\">Monaco workers are not configured.</div>;\n }\n\n return (\n <div className=\"overflow-hidden rounded-md border border-input\" data-slot=\"monaco-editor\">\n <Editor\n value={value}\n onChange={(next) => onChange?.(next ?? \"\")}\n language={language}\n path={path}\n height={height}\n theme={theme}\n keepCurrentModel\n {...(beforeMount ? { beforeMount } : {})}\n onMount={(instance, monacoInstance) => {\n // keepCurrentModel remounts onto the model already at `path`, which\n // still holds the text from when the previous editor unmounted.\n if (instance.getValue() !== latestValue.current) instance.setValue(latestValue.current);\n onMount?.(instance, monacoInstance);\n }}\n {...(onValidate ? { onValidate } : {})}\n options={{\n readOnly,\n automaticLayout: true,\n fontFamily: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)\",\n fontSize: 13,\n lineHeight: 20,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n tabSize: 2,\n wordWrap: \"on\",\n quickSuggestions: { other: true, comments: true, strings: true },\n }}\n />\n </div>\n );\n}\n\nexport type { Monaco };\n"],"names":["loader","monaco","useMonacoWorkerFactory","useResolvedTheme","useRef","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAOAA,OAAAA,OAAO,OAAO,EAAA,QAAEC,yBAAQ;AAEjB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,CAAC,YAAY,CAAC,SAAU,OAAM,IAAI,MAAM,6CAA6C;AACzF,QAAM,UAAUC,gBAAAA,uBAAA;AAChB,QAAM,QAAQC,SAAAA,iBAAA,MAAuB,SAAS,YAAY;AAG1D,QAAM,cAAcC,MAAAA,OAAO,KAAK;AAChC,cAAY,UAAU;AAEtB,MAAI,CAAC,SAAS;AACZ,0CAAQ,OAAA,EAAI,MAAK,SAAQ,WAAU,wEAAuE,UAAA,sCAAkC;AAAA,EAC9I;AAEA,SACEC,2BAAAA,IAAC,OAAA,EAAI,WAAU,kDAAiD,aAAU,iBACxE,UAAAA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU,CAAC,SAAS,qCAAW,QAAQ;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAgB;AAAA,MACf,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,MACrC,SAAS,CAAC,UAAU,mBAAmB;AAGrC,YAAI,SAAS,eAAe,YAAY,QAAS,UAAS,SAAS,YAAY,OAAO;AACtF,2CAAU,UAAU;AAAA,MACtB;AAAA,MACC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC,SAAS;AAAA,QACP;AAAA,QACA,iBAAiB;AAAA,QACjB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,SAAS,EAAE,SAAS,MAAA;AAAA,QACpB,sBAAsB;AAAA,QACtB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,kBAAkB,EAAE,OAAO,MAAM,UAAU,MAAM,SAAS,KAAA;AAAA,MAAK;AAAA,IACjE;AAAA,EAAA,GAEJ;AAEJ;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Monaco } from '@monaco-editor/react';
|
|
2
2
|
import { MonacoEditorProps } from './types.js';
|
|
3
|
-
export declare function MonacoEditor({ value, onChange, language, path, height, beforeMount, onMount, onValidate, }: MonacoEditorProps): import("react").JSX.Element;
|
|
3
|
+
export declare function MonacoEditor({ value, onChange, readOnly, language, path, height, beforeMount, onMount, onValidate, }: MonacoEditorProps): import("react").JSX.Element;
|
|
4
4
|
export type { Monaco };
|
|
5
5
|
//# sourceMappingURL=MonacoEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonacoEditor.d.ts","sourceRoot":"","sources":["../../src/monaco/MonacoEditor.tsx"],"names":[],"mappings":"AAAA,OAAe,EAAU,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAKnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIjD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,MAAgB,EAChB,WAAW,EACX,OAAO,EACP,UAAU,GACX,EAAE,iBAAiB,+
|
|
1
|
+
{"version":3,"file":"MonacoEditor.d.ts","sourceRoot":"","sources":["../../src/monaco/MonacoEditor.tsx"],"names":[],"mappings":"AAAA,OAAe,EAAU,KAAK,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAKnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIjD,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,QAAgB,EAChB,QAAQ,EACR,IAAI,EACJ,MAAgB,EAChB,WAAW,EACX,OAAO,EACP,UAAU,GACX,EAAE,iBAAiB,+BA8CnB;AAED,YAAY,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -8,6 +8,7 @@ loader.config({ monaco: monacoEditor });
|
|
|
8
8
|
function MonacoEditor({
|
|
9
9
|
value,
|
|
10
10
|
onChange,
|
|
11
|
+
readOnly = false,
|
|
11
12
|
language,
|
|
12
13
|
path,
|
|
13
14
|
height = "20rem",
|
|
@@ -15,6 +16,7 @@ function MonacoEditor({
|
|
|
15
16
|
onMount,
|
|
16
17
|
onValidate
|
|
17
18
|
}) {
|
|
19
|
+
if (!readOnly && !onChange) throw new Error("MonacoEditor requires onChange when editing");
|
|
18
20
|
const workers = useMonacoWorkerFactory();
|
|
19
21
|
const theme = useResolvedTheme() === "dark" ? "vs-dark" : "light";
|
|
20
22
|
const latestValue = useRef(value);
|
|
@@ -26,7 +28,7 @@ function MonacoEditor({
|
|
|
26
28
|
Editor,
|
|
27
29
|
{
|
|
28
30
|
value,
|
|
29
|
-
onChange: (next) => onChange(next ?? ""),
|
|
31
|
+
onChange: (next) => onChange == null ? void 0 : onChange(next ?? ""),
|
|
30
32
|
language,
|
|
31
33
|
path,
|
|
32
34
|
height,
|
|
@@ -39,6 +41,7 @@ function MonacoEditor({
|
|
|
39
41
|
},
|
|
40
42
|
...onValidate ? { onValidate } : {},
|
|
41
43
|
options: {
|
|
44
|
+
readOnly,
|
|
42
45
|
automaticLayout: true,
|
|
43
46
|
fontFamily: "var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)",
|
|
44
47
|
fontSize: 13,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonacoEditor.js","sources":["../../src/monaco/MonacoEditor.tsx"],"sourcesContent":["import Editor, { loader, type Monaco } from \"@monaco-editor/react\";\nimport * as monaco from \"monaco-editor\";\nimport { useRef } from \"react\";\nimport { useResolvedTheme } from \"../hooks/use-theme\";\nimport { useMonacoWorkerFactory } from \"./use-monaco-worker\";\nimport type { MonacoEditorProps } from \"./types\";\n\nloader.config({ monaco });\n\nexport function MonacoEditor({\n value,\n onChange,\n language,\n path,\n height = \"20rem\",\n beforeMount,\n onMount,\n onValidate,\n}: MonacoEditorProps) {\n const workers = useMonacoWorkerFactory();\n const theme = useResolvedTheme() === \"dark\" ? \"vs-dark\" : \"light\";\n // @monaco-editor/react keeps the first onMount it sees, so read the value at\n // mount time through a ref rather than that render's closure.\n const latestValue = useRef(value);\n latestValue.current = value;\n\n if (!workers) {\n return <div role=\"alert\" className=\"rounded-md border border-destructive/40 p-3 text-sm text-destructive\">Monaco workers are not configured.</div>;\n }\n\n return (\n <div className=\"overflow-hidden rounded-md border border-input\" data-slot=\"monaco-editor\">\n <Editor\n value={value}\n onChange={(next) => onChange(next ?? \"\")}\n language={language}\n path={path}\n height={height}\n theme={theme}\n keepCurrentModel\n {...(beforeMount ? { beforeMount } : {})}\n onMount={(instance, monacoInstance) => {\n // keepCurrentModel remounts onto the model already at `path`, which\n // still holds the text from when the previous editor unmounted.\n if (instance.getValue() !== latestValue.current) instance.setValue(latestValue.current);\n onMount?.(instance, monacoInstance);\n }}\n {...(onValidate ? { onValidate } : {})}\n options={{\n automaticLayout: true,\n fontFamily: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)\",\n fontSize: 13,\n lineHeight: 20,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n tabSize: 2,\n wordWrap: \"on\",\n quickSuggestions: { other: true, comments: true, strings: true },\n }}\n />\n </div>\n );\n}\n\nexport type { Monaco };\n"],"names":["monaco"],"mappings":";;;;;;AAOA,OAAO,OAAO,EAAA,QAAEA,cAAQ;AAEjB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,QAAM,UAAU,uBAAA;AAChB,QAAM,QAAQ,iBAAA,MAAuB,SAAS,YAAY;AAG1D,QAAM,cAAc,OAAO,KAAK;AAChC,cAAY,UAAU;AAEtB,MAAI,CAAC,SAAS;AACZ,+BAAQ,OAAA,EAAI,MAAK,SAAQ,WAAU,wEAAuE,UAAA,sCAAkC;AAAA,EAC9I;AAEA,SACE,oBAAC,OAAA,EAAI,WAAU,kDAAiD,aAAU,iBACxE,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"MonacoEditor.js","sources":["../../src/monaco/MonacoEditor.tsx"],"sourcesContent":["import Editor, { loader, type Monaco } from \"@monaco-editor/react\";\nimport * as monaco from \"monaco-editor\";\nimport { useRef } from \"react\";\nimport { useResolvedTheme } from \"../hooks/use-theme\";\nimport { useMonacoWorkerFactory } from \"./use-monaco-worker\";\nimport type { MonacoEditorProps } from \"./types\";\n\nloader.config({ monaco });\n\nexport function MonacoEditor({\n value,\n onChange,\n readOnly = false,\n language,\n path,\n height = \"20rem\",\n beforeMount,\n onMount,\n onValidate,\n}: MonacoEditorProps) {\n if (!readOnly && !onChange) throw new Error(\"MonacoEditor requires onChange when editing\");\n const workers = useMonacoWorkerFactory();\n const theme = useResolvedTheme() === \"dark\" ? \"vs-dark\" : \"light\";\n // @monaco-editor/react keeps the first onMount it sees, so read the value at\n // mount time through a ref rather than that render's closure.\n const latestValue = useRef(value);\n latestValue.current = value;\n\n if (!workers) {\n return <div role=\"alert\" className=\"rounded-md border border-destructive/40 p-3 text-sm text-destructive\">Monaco workers are not configured.</div>;\n }\n\n return (\n <div className=\"overflow-hidden rounded-md border border-input\" data-slot=\"monaco-editor\">\n <Editor\n value={value}\n onChange={(next) => onChange?.(next ?? \"\")}\n language={language}\n path={path}\n height={height}\n theme={theme}\n keepCurrentModel\n {...(beforeMount ? { beforeMount } : {})}\n onMount={(instance, monacoInstance) => {\n // keepCurrentModel remounts onto the model already at `path`, which\n // still holds the text from when the previous editor unmounted.\n if (instance.getValue() !== latestValue.current) instance.setValue(latestValue.current);\n onMount?.(instance, monacoInstance);\n }}\n {...(onValidate ? { onValidate } : {})}\n options={{\n readOnly,\n automaticLayout: true,\n fontFamily: \"var(--font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace)\",\n fontSize: 13,\n lineHeight: 20,\n minimap: { enabled: false },\n scrollBeyondLastLine: false,\n tabSize: 2,\n wordWrap: \"on\",\n quickSuggestions: { other: true, comments: true, strings: true },\n }}\n />\n </div>\n );\n}\n\nexport type { Monaco };\n"],"names":["monaco"],"mappings":";;;;;;AAOA,OAAO,OAAO,EAAA,QAAEA,cAAQ;AAEjB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AACF,GAAsB;AACpB,MAAI,CAAC,YAAY,CAAC,SAAU,OAAM,IAAI,MAAM,6CAA6C;AACzF,QAAM,UAAU,uBAAA;AAChB,QAAM,QAAQ,iBAAA,MAAuB,SAAS,YAAY;AAG1D,QAAM,cAAc,OAAO,KAAK;AAChC,cAAY,UAAU;AAEtB,MAAI,CAAC,SAAS;AACZ,+BAAQ,OAAA,EAAI,MAAK,SAAQ,WAAU,wEAAuE,UAAA,sCAAkC;AAAA,EAC9I;AAEA,SACE,oBAAC,OAAA,EAAI,WAAU,kDAAiD,aAAU,iBACxE,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,UAAU,CAAC,SAAS,qCAAW,QAAQ;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAgB;AAAA,MACf,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,MACrC,SAAS,CAAC,UAAU,mBAAmB;AAGrC,YAAI,SAAS,eAAe,YAAY,QAAS,UAAS,SAAS,YAAY,OAAO;AACtF,2CAAU,UAAU;AAAA,MACtB;AAAA,MACC,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MACnC,SAAS;AAAA,QACP;AAAA,QACA,iBAAiB;AAAA,QACjB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,SAAS,EAAE,SAAS,MAAA;AAAA,QACpB,sBAAsB;AAAA,QACtB,SAAS;AAAA,QACT,UAAU;AAAA,QACV,kBAAkB,EAAE,OAAO,MAAM,UAAU,MAAM,SAAS,KAAA;AAAA,MAAK;AAAA,IACjE;AAAA,EAAA,GAEJ;AAEJ;"}
|
package/dist/monaco/types.d.ts
CHANGED
|
@@ -14,7 +14,8 @@ export type MonacoProviderProps = {
|
|
|
14
14
|
};
|
|
15
15
|
export type MonacoEditorProps = {
|
|
16
16
|
value: string;
|
|
17
|
-
onChange
|
|
17
|
+
onChange?: (value: string) => void;
|
|
18
|
+
readOnly?: boolean;
|
|
18
19
|
language: string;
|
|
19
20
|
path: string;
|
|
20
21
|
height?: string | number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/monaco/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAErF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAE5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/monaco/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,MAAM,MAAM,sBAAsB,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,aAAa,CAAC;AAErF,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAE5D,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,GAAG,YAAY,CAAC,GAAG;IACrH,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;CAC5D,CAAC"}
|
|
@@ -21,6 +21,8 @@ function CommandPalette({
|
|
|
21
21
|
groups,
|
|
22
22
|
query,
|
|
23
23
|
onQueryChange,
|
|
24
|
+
customInput,
|
|
25
|
+
focusListKey,
|
|
24
26
|
hotkey = "mod+k",
|
|
25
27
|
placeholder = "Type a command or search…",
|
|
26
28
|
loading,
|
|
@@ -45,6 +47,7 @@ function CommandPalette({
|
|
|
45
47
|
const restoreFocusRef = react.useRef(null);
|
|
46
48
|
const isOpen = open ?? selfOpen;
|
|
47
49
|
const currentQuery = query ?? selfQuery;
|
|
50
|
+
const usesCustomInput = customInput !== void 0;
|
|
48
51
|
const setOpen = react.useCallback(
|
|
49
52
|
(next) => {
|
|
50
53
|
if (open === void 0) setSelfOpen(next);
|
|
@@ -80,7 +83,11 @@ function CommandPalette({
|
|
|
80
83
|
}
|
|
81
84
|
restoreFocusRef.current = document.activeElement;
|
|
82
85
|
(_c = inputRef.current) == null ? void 0 : _c.focus();
|
|
83
|
-
}, [isOpen, resetQueryOnClose, query]);
|
|
86
|
+
}, [isOpen, resetQueryOnClose, query, usesCustomInput]);
|
|
87
|
+
react.useEffect(() => {
|
|
88
|
+
var _a;
|
|
89
|
+
if (isOpen && focusListKey !== void 0) (_a = listRef.current) == null ? void 0 : _a.focus();
|
|
90
|
+
}, [isOpen, focusListKey]);
|
|
84
91
|
react.useEffect(() => {
|
|
85
92
|
var _a;
|
|
86
93
|
if (activeIndex < 0) return;
|
|
@@ -151,14 +158,15 @@ function CommandPalette({
|
|
|
151
158
|
"aria-modal": "true",
|
|
152
159
|
"aria-label": ariaLabel,
|
|
153
160
|
className: utils.cn(
|
|
154
|
-
"flex h-fit w-full flex-col
|
|
161
|
+
"flex h-fit w-full flex-col rounded-lg border border-border bg-background shadow-xl",
|
|
162
|
+
usesCustomInput ? "overflow-visible" : "overflow-hidden",
|
|
155
163
|
SIZE_CLASS[size],
|
|
156
164
|
className
|
|
157
165
|
),
|
|
158
166
|
style: { marginTop: topOffset },
|
|
159
167
|
onClick: (event) => event.stopPropagation(),
|
|
160
168
|
children: [
|
|
161
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-density-2 border-b border-border px-density-3", children: [
|
|
169
|
+
!usesCustomInput ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-density-2 border-b border-border px-density-3", children: [
|
|
162
170
|
/* @__PURE__ */ jsxRuntime.jsx(Icon.Icon, { icon: UiSearch.UiSearch, className: "shrink-0 text-muted-foreground" }),
|
|
163
171
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
164
172
|
"input",
|
|
@@ -178,7 +186,7 @@ function CommandPalette({
|
|
|
178
186
|
className: "h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder"
|
|
179
187
|
}
|
|
180
188
|
)
|
|
181
|
-
] }),
|
|
189
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border p-density-3", children: customInput }),
|
|
182
190
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
183
191
|
CommandPaletteList.CommandPaletteList,
|
|
184
192
|
{
|
|
@@ -189,6 +197,8 @@ function CommandPalette({
|
|
|
189
197
|
optionId,
|
|
190
198
|
onActivate: activate,
|
|
191
199
|
onHover: setActiveIndex,
|
|
200
|
+
onKeyDown,
|
|
201
|
+
activeItemId: activeItem ? optionId(activeItem) : void 0,
|
|
192
202
|
listRef,
|
|
193
203
|
loading,
|
|
194
204
|
emptyState,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandPalette.cjs","sources":["../../src/overlay/CommandPalette.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiSearch } from \"../icons\";\nimport { useHotkey } from \"../hooks/use-hotkey\";\nimport { useEscapeLayer, useModalStack } from \"./modalStack\";\nimport { zIndex } from \"./zIndex\";\nimport { CommandPaletteList } from \"./CommandPaletteList\";\nimport {\n defaultCommandFilter,\n filterCommandGroups,\n firstEnabledIndex,\n flattenCommands,\n lastEnabledIndex,\n nextEnabledIndex,\n type CommandFilter,\n type CommandGroup,\n type CommandItem,\n} from \"./CommandPalette.model\";\n\nexport type {\n CommandFilter,\n CommandGroup,\n CommandItem,\n CommandSelectContext,\n} from \"./CommandPalette.model\";\n\nconst SIZE_CLASS = {\n md: \"max-w-[40rem]\",\n lg: \"max-w-[48rem]\",\n} as const;\n\nexport type CommandPaletteProps = {\n /**\n * Controls visibility. Omit to run uncontrolled — the palette then owns its\n * open state and the built-in hotkey works with no wiring beyond mounting it.\n */\n open?: boolean;\n /** Called with the next open state on hotkey, Escape, backdrop click, and selection. */\n onOpenChange?: (open: boolean) => void;\n /** Command groups, rendered top to bottom in array order. */\n groups: CommandGroup[];\n /** Controlled query. Omit to let the palette own the input. */\n query?: string;\n /** Called with the next query on every keystroke. Required for server-side search. */\n onQueryChange?: (query: string) => void;\n /**\n * Global shortcut that opens (and, while open, closes) the palette, in\n * `useHotkey` syntax — `\"mod+k\"` by default, where `mod` is ⌘ on macOS and\n * Ctrl elsewhere. Pass `null` when an ancestor owns the binding.\n */\n hotkey?: string | null;\n /** Ghost text in the search input. Defaults to \"Type a command or search…\". */\n placeholder?: string;\n /** Shows a loading row instead of the empty state while results are in flight. */\n loading?: boolean;\n /** Replaces the default \"No results\" body. */\n emptyState?: ReactNode;\n /** Non-interactive hint strip pinned below the list. */\n footer?: ReactNode;\n /**\n * How rows are matched. Defaults to a case-insensitive substring match over\n * label, description and keywords, ranked by hit position. Pass `false` when\n * the caller already filtered `groups` server-side.\n */\n filter?: CommandFilter | false;\n /** Fallback handler for items with no own `onSelect`. */\n onSelect?: (context: { item: CommandItem; query: string; close: () => void }) => void;\n /** Close after a successful activation. Defaults to true. */\n closeOnSelect?: boolean;\n /** Clear the query when the palette closes. Defaults to true. */\n resetQueryOnClose?: boolean;\n /** Panel width preset. Defaults to \"md\". */\n size?: \"md\" | \"lg\";\n /** Distance from the viewport top. Defaults to \"12vh\". Applied as an inline style. */\n topOffset?: string | number;\n /** Max height of the scrolling list. Defaults to \"min(24rem, 50dvh)\". Inline style. */\n listMaxHeight?: string | number;\n /** Accessible name for the dialog. Defaults to \"Command palette\". */\n ariaLabel?: string;\n /** Classes applied to the palette panel. */\n className?: string;\n};\n\n/**\n * A ⌘K command palette: a top-anchored overlay with a search field over a\n * grouped, keyboard-navigable command list.\n *\n * It renders its own portal rather than building on `Modal`, which centres its\n * panel, focuses the dialog element instead of an input, forces body padding,\n * and pins an inline max-height — none of which a palette can override. The\n * stacking primitives are shared though (`useModalStack`, `useEscapeLayer`, the\n * `zIndex` scale), so a palette opened over a modal sits above it and Escape\n * still dismisses exactly one layer.\n */\nexport function CommandPalette({\n open,\n onOpenChange,\n groups,\n query,\n onQueryChange,\n hotkey = \"mod+k\",\n placeholder = \"Type a command or search…\",\n loading,\n emptyState,\n footer,\n filter = defaultCommandFilter,\n onSelect,\n closeOnSelect = true,\n resetQueryOnClose = true,\n size = \"md\",\n topOffset = \"12vh\",\n listMaxHeight = \"min(24rem, 50dvh)\",\n ariaLabel = \"Command palette\",\n className,\n}: CommandPaletteProps) {\n const baseId = useId();\n const [selfOpen, setSelfOpen] = useState(false);\n const [selfQuery, setSelfQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const restoreFocusRef = useRef<HTMLElement | null>(null);\n\n const isOpen = open ?? selfOpen;\n const currentQuery = query ?? selfQuery;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setSelfOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const setQuery = useCallback(\n (next: string) => {\n if (query === undefined) setSelfQuery(next);\n onQueryChange?.(next);\n },\n [query, onQueryChange],\n );\n\n const visibleGroups = useMemo(\n () => filterCommandGroups(groups, currentQuery, filter),\n [groups, currentQuery, filter],\n );\n const items = useMemo(() => flattenCommands(visibleGroups), [visibleGroups]);\n\n // Priority keeps the palette ahead of any page-level ⌘K search field, whose\n // binding would otherwise win purely by mounting later.\n useHotkey(hotkey, () => setOpen(!isOpen), { priority: 10 });\n useEscapeLayer(isOpen, () => setOpen(false));\n\n const { depth } = useModalStack(isOpen);\n\n // Enter-runs-the-top-result is the point of a palette, so the active row\n // resets to the first selectable one whenever the result set changes.\n useEffect(() => {\n setActiveIndex(firstEnabledIndex(items));\n }, [items]);\n\n useEffect(() => {\n if (!isOpen) {\n if (resetQueryOnClose && query === undefined) setSelfQuery(\"\");\n restoreFocusRef.current?.focus?.();\n restoreFocusRef.current = null;\n return;\n }\n restoreFocusRef.current = document.activeElement as HTMLElement | null;\n inputRef.current?.focus();\n }, [isOpen, resetQueryOnClose, query]);\n\n // Keep the active row in view without stealing focus from the input.\n useEffect(() => {\n if (activeIndex < 0) return;\n const option = listRef.current?.querySelectorAll('[role=\"option\"]')[activeIndex];\n // jsdom does not implement scrollIntoView; scrolling is a progressive\n // enhancement, so skip it rather than crash a consumer's test run.\n if (option instanceof HTMLElement && typeof option.scrollIntoView === \"function\") {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }, [activeIndex]);\n\n const optionId = useCallback((item: CommandItem) => `${baseId}-option-${item.id}`, [baseId]);\n\n const activate = useCallback(\n (item: CommandItem) => {\n if (item.disabled) return;\n const close = () => setOpen(false);\n const context = { item, query: currentQuery.trim(), close };\n if (item.onSelect) item.onSelect(context);\n else onSelect?.(context);\n if (closeOnSelect) close();\n },\n [currentQuery, onSelect, closeOnSelect, setOpen],\n );\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, 1));\n break;\n case \"ArrowUp\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, -1));\n break;\n case \"Home\":\n event.preventDefault();\n setActiveIndex(firstEnabledIndex(items));\n break;\n case \"End\":\n event.preventDefault();\n setActiveIndex(lastEnabledIndex(items));\n break;\n case \"Enter\": {\n event.preventDefault();\n const index = activeIndex >= 0 ? activeIndex : firstEnabledIndex(items);\n const item = index >= 0 ? items[index] : undefined;\n if (item) activate(item);\n break;\n }\n case \"Tab\":\n // Nothing else in the panel is focusable, and letting Tab escape an\n // aria-modal dialog would strand focus behind the backdrop.\n if (!footer) event.preventDefault();\n break;\n default:\n break;\n }\n };\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const listId = `${baseId}-list`;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex justify-center p-density-4\",\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: zIndex.modal + depth * zIndex.modalStep }}\n role=\"presentation\"\n onClick={() => setOpen(false)}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n className={cn(\n \"flex h-fit w-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\",\n SIZE_CLASS[size],\n className,\n )}\n style={{ marginTop: topOffset }}\n onClick={(event) => event.stopPropagation()}\n >\n <div className=\"flex items-center gap-density-2 border-b border-border px-density-3\">\n <Icon icon={UiSearch} className=\"shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={ariaLabel}\n value={currentQuery}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onKeyDown}\n className=\"h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder\"\n />\n </div>\n\n <CommandPaletteList\n groups={visibleGroups}\n items={items}\n activeIndex={activeIndex}\n listId={listId}\n optionId={optionId}\n onActivate={activate}\n onHover={setActiveIndex}\n listRef={listRef}\n loading={loading}\n emptyState={emptyState}\n listMaxHeight={listMaxHeight}\n />\n\n {footer && (\n <div className=\"border-t border-border px-density-3 py-density-2 text-xs text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n\n return createPortal(overlay, document.body);\n}\n"],"names":["defaultCommandFilter","useId","useState","useRef","useCallback","useMemo","filterCommandGroups","flattenCommands","useHotkey","useEscapeLayer","useModalStack","useEffect","firstEnabledIndex","nextEnabledIndex","lastEnabledIndex","jsx","cn","zIndex","jsxs","Icon","UiSearch","CommandPaletteList","createPortal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommandPalette.cjs","sources":["../../src/overlay/CommandPalette.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiSearch } from \"../icons\";\nimport { useHotkey } from \"../hooks/use-hotkey\";\nimport { useEscapeLayer, useModalStack } from \"./modalStack\";\nimport { zIndex } from \"./zIndex\";\nimport { CommandPaletteList } from \"./CommandPaletteList\";\nimport {\n defaultCommandFilter,\n filterCommandGroups,\n firstEnabledIndex,\n flattenCommands,\n lastEnabledIndex,\n nextEnabledIndex,\n type CommandFilter,\n type CommandGroup,\n type CommandItem,\n} from \"./CommandPalette.model\";\n\nexport type {\n CommandFilter,\n CommandGroup,\n CommandItem,\n CommandSelectContext,\n} from \"./CommandPalette.model\";\n\nconst SIZE_CLASS = {\n md: \"max-w-[40rem]\",\n lg: \"max-w-[48rem]\",\n} as const;\n\nexport type CommandPaletteProps = {\n /**\n * Controls visibility. Omit to run uncontrolled — the palette then owns its\n * open state and the built-in hotkey works with no wiring beyond mounting it.\n */\n open?: boolean;\n /** Called with the next open state on hotkey, Escape, backdrop click, and selection. */\n onOpenChange?: (open: boolean) => void;\n /** Command groups, rendered top to bottom in array order. */\n groups: CommandGroup[];\n /** Controlled query. Omit to let the palette own the input. */\n query?: string;\n /** Called with the next query on every keystroke. Required for server-side search. */\n onQueryChange?: (query: string) => void;\n /** Replaces the built-in search field while preserving the palette and result list. */\n customInput?: ReactNode;\n /** Changing this value focuses the result list for keyboard selection. */\n focusListKey?: number;\n /**\n * Global shortcut that opens (and, while open, closes) the palette, in\n * `useHotkey` syntax — `\"mod+k\"` by default, where `mod` is ⌘ on macOS and\n * Ctrl elsewhere. Pass `null` when an ancestor owns the binding.\n */\n hotkey?: string | null;\n /** Ghost text in the search input. Defaults to \"Type a command or search…\". */\n placeholder?: string;\n /** Shows a loading row instead of the empty state while results are in flight. */\n loading?: boolean;\n /** Replaces the default \"No results\" body. */\n emptyState?: ReactNode;\n /** Non-interactive hint strip pinned below the list. */\n footer?: ReactNode;\n /**\n * How rows are matched. Defaults to a case-insensitive substring match over\n * label, description and keywords, ranked by hit position. Pass `false` when\n * the caller already filtered `groups` server-side.\n */\n filter?: CommandFilter | false;\n /** Fallback handler for items with no own `onSelect`. */\n onSelect?: (context: { item: CommandItem; query: string; close: () => void }) => void;\n /** Close after a successful activation. Defaults to true. */\n closeOnSelect?: boolean;\n /** Clear the query when the palette closes. Defaults to true. */\n resetQueryOnClose?: boolean;\n /** Panel width preset. Defaults to \"md\". */\n size?: \"md\" | \"lg\";\n /** Distance from the viewport top. Defaults to \"12vh\". Applied as an inline style. */\n topOffset?: string | number;\n /** Max height of the scrolling list. Defaults to \"min(24rem, 50dvh)\". Inline style. */\n listMaxHeight?: string | number;\n /** Accessible name for the dialog. Defaults to \"Command palette\". */\n ariaLabel?: string;\n /** Classes applied to the palette panel. */\n className?: string;\n};\n\n/**\n * A ⌘K command palette: a top-anchored overlay with a search field over a\n * grouped, keyboard-navigable command list.\n *\n * It renders its own portal rather than building on `Modal`, which centres its\n * panel, focuses the dialog element instead of an input, forces body padding,\n * and pins an inline max-height — none of which a palette can override. The\n * stacking primitives are shared though (`useModalStack`, `useEscapeLayer`, the\n * `zIndex` scale), so a palette opened over a modal sits above it and Escape\n * still dismisses exactly one layer.\n */\nexport function CommandPalette({\n open,\n onOpenChange,\n groups,\n query,\n onQueryChange,\n customInput,\n focusListKey,\n hotkey = \"mod+k\",\n placeholder = \"Type a command or search…\",\n loading,\n emptyState,\n footer,\n filter = defaultCommandFilter,\n onSelect,\n closeOnSelect = true,\n resetQueryOnClose = true,\n size = \"md\",\n topOffset = \"12vh\",\n listMaxHeight = \"min(24rem, 50dvh)\",\n ariaLabel = \"Command palette\",\n className,\n}: CommandPaletteProps) {\n const baseId = useId();\n const [selfOpen, setSelfOpen] = useState(false);\n const [selfQuery, setSelfQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const restoreFocusRef = useRef<HTMLElement | null>(null);\n\n const isOpen = open ?? selfOpen;\n const currentQuery = query ?? selfQuery;\n const usesCustomInput = customInput !== undefined;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setSelfOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const setQuery = useCallback(\n (next: string) => {\n if (query === undefined) setSelfQuery(next);\n onQueryChange?.(next);\n },\n [query, onQueryChange],\n );\n\n const visibleGroups = useMemo(\n () => filterCommandGroups(groups, currentQuery, filter),\n [groups, currentQuery, filter],\n );\n const items = useMemo(() => flattenCommands(visibleGroups), [visibleGroups]);\n\n // Priority keeps the palette ahead of any page-level ⌘K search field, whose\n // binding would otherwise win purely by mounting later.\n useHotkey(hotkey, () => setOpen(!isOpen), { priority: 10 });\n useEscapeLayer(isOpen, () => setOpen(false));\n\n const { depth } = useModalStack(isOpen);\n\n // Enter-runs-the-top-result is the point of a palette, so the active row\n // resets to the first selectable one whenever the result set changes.\n useEffect(() => {\n setActiveIndex(firstEnabledIndex(items));\n }, [items]);\n\n useEffect(() => {\n if (!isOpen) {\n if (resetQueryOnClose && query === undefined) setSelfQuery(\"\");\n restoreFocusRef.current?.focus?.();\n restoreFocusRef.current = null;\n return;\n }\n restoreFocusRef.current = document.activeElement as HTMLElement | null;\n inputRef.current?.focus();\n }, [isOpen, resetQueryOnClose, query, usesCustomInput]);\n\n useEffect(() => {\n if (isOpen && focusListKey !== undefined) listRef.current?.focus();\n }, [isOpen, focusListKey]);\n\n // Keep the active row in view without stealing focus from the input.\n useEffect(() => {\n if (activeIndex < 0) return;\n const option = listRef.current?.querySelectorAll('[role=\"option\"]')[activeIndex];\n // jsdom does not implement scrollIntoView; scrolling is a progressive\n // enhancement, so skip it rather than crash a consumer's test run.\n if (option instanceof HTMLElement && typeof option.scrollIntoView === \"function\") {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }, [activeIndex]);\n\n const optionId = useCallback((item: CommandItem) => `${baseId}-option-${item.id}`, [baseId]);\n\n const activate = useCallback(\n (item: CommandItem) => {\n if (item.disabled) return;\n const close = () => setOpen(false);\n const context = { item, query: currentQuery.trim(), close };\n if (item.onSelect) item.onSelect(context);\n else onSelect?.(context);\n if (closeOnSelect) close();\n },\n [currentQuery, onSelect, closeOnSelect, setOpen],\n );\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, 1));\n break;\n case \"ArrowUp\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, -1));\n break;\n case \"Home\":\n event.preventDefault();\n setActiveIndex(firstEnabledIndex(items));\n break;\n case \"End\":\n event.preventDefault();\n setActiveIndex(lastEnabledIndex(items));\n break;\n case \"Enter\": {\n event.preventDefault();\n const index = activeIndex >= 0 ? activeIndex : firstEnabledIndex(items);\n const item = index >= 0 ? items[index] : undefined;\n if (item) activate(item);\n break;\n }\n case \"Tab\":\n // Nothing else in the panel is focusable, and letting Tab escape an\n // aria-modal dialog would strand focus behind the backdrop.\n if (!footer) event.preventDefault();\n break;\n default:\n break;\n }\n };\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const listId = `${baseId}-list`;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex justify-center p-density-4\",\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: zIndex.modal + depth * zIndex.modalStep }}\n role=\"presentation\"\n onClick={() => setOpen(false)}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n className={cn(\n \"flex h-fit w-full flex-col rounded-lg border border-border bg-background shadow-xl\",\n usesCustomInput ? \"overflow-visible\" : \"overflow-hidden\",\n SIZE_CLASS[size],\n className,\n )}\n style={{ marginTop: topOffset }}\n onClick={(event) => event.stopPropagation()}\n >\n {!usesCustomInput ? <div className=\"flex items-center gap-density-2 border-b border-border px-density-3\">\n <Icon icon={UiSearch} className=\"shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={ariaLabel}\n value={currentQuery}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onKeyDown}\n className=\"h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder\"\n />\n </div> : <div className=\"border-b border-border p-density-3\">{customInput}</div>}\n\n <CommandPaletteList\n groups={visibleGroups}\n items={items}\n activeIndex={activeIndex}\n listId={listId}\n optionId={optionId}\n onActivate={activate}\n onHover={setActiveIndex}\n onKeyDown={onKeyDown}\n activeItemId={activeItem ? optionId(activeItem) : undefined}\n listRef={listRef}\n loading={loading}\n emptyState={emptyState}\n listMaxHeight={listMaxHeight}\n />\n\n {footer && (\n <div className=\"border-t border-border px-density-3 py-density-2 text-xs text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n\n return createPortal(overlay, document.body);\n}\n"],"names":["defaultCommandFilter","useId","useState","useRef","useCallback","useMemo","filterCommandGroups","flattenCommands","useHotkey","useEscapeLayer","useModalStack","useEffect","firstEnabledIndex","nextEnabledIndex","lastEnabledIndex","jsx","cn","zIndex","jsxs","Icon","UiSearch","CommandPaletteList","createPortal"],"mappings":"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"}
|
|
@@ -15,6 +15,10 @@ export type CommandPaletteProps = {
|
|
|
15
15
|
query?: string;
|
|
16
16
|
/** Called with the next query on every keystroke. Required for server-side search. */
|
|
17
17
|
onQueryChange?: (query: string) => void;
|
|
18
|
+
/** Replaces the built-in search field while preserving the palette and result list. */
|
|
19
|
+
customInput?: ReactNode;
|
|
20
|
+
/** Changing this value focuses the result list for keyboard selection. */
|
|
21
|
+
focusListKey?: number;
|
|
18
22
|
/**
|
|
19
23
|
* Global shortcut that opens (and, while open, closes) the palette, in
|
|
20
24
|
* `useHotkey` syntax — `"mod+k"` by default, where `mod` is ⌘ on macOS and
|
|
@@ -67,5 +71,5 @@ export type CommandPaletteProps = {
|
|
|
67
71
|
* `zIndex` scale), so a palette opened over a modal sits above it and Escape
|
|
68
72
|
* still dismisses exactly one layer.
|
|
69
73
|
*/
|
|
70
|
-
export declare function CommandPalette({ open, onOpenChange, groups, query, onQueryChange, hotkey, placeholder, loading, emptyState, footer, filter, onSelect, closeOnSelect, resetQueryOnClose, size, topOffset, listMaxHeight, ariaLabel, className, }: CommandPaletteProps): import('react').ReactPortal | null;
|
|
74
|
+
export declare function CommandPalette({ open, onOpenChange, groups, query, onQueryChange, customInput, focusListKey, hotkey, placeholder, loading, emptyState, footer, filter, onSelect, closeOnSelect, resetQueryOnClose, size, topOffset, listMaxHeight, ariaLabel, className, }: CommandPaletteProps): import('react').ReactPortal | null;
|
|
71
75
|
//# sourceMappingURL=CommandPalette.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandPalette.d.ts","sourceRoot":"","sources":["../../src/overlay/CommandPalette.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASjG,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAOhC,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wFAAwF;IACxF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,6DAA6D;IAC7D,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,GAAG,KAAK,CAAC;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,aAAa,EACb,MAAgB,EAChB,WAAyC,EACzC,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAA6B,EAC7B,QAAQ,EACR,aAAoB,EACpB,iBAAwB,EACxB,IAAW,EACX,SAAkB,EAClB,aAAmC,EACnC,SAA6B,EAC7B,SAAS,GACV,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"CommandPalette.d.ts","sourceRoot":"","sources":["../../src/overlay/CommandPalette.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AASjG,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,WAAW,EACjB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACV,aAAa,EACb,YAAY,EACZ,WAAW,EACX,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAOhC,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wFAAwF;IACxF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,6DAA6D;IAC7D,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,uFAAuF;IACvF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,wDAAwD;IACxD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,GAAG,KAAK,CAAC;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,IAAI,CAAA;KAAE,KAAK,IAAI,CAAC;IACtF,6DAA6D;IAC7D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,uFAAuF;IACvF,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,MAAgB,EAChB,WAAyC,EACzC,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAA6B,EAC7B,QAAQ,EACR,aAAoB,EACpB,iBAAwB,EACxB,IAAW,EACX,SAAkB,EAClB,aAAmC,EACnC,SAA6B,EAC7B,SAAS,GACV,EAAE,mBAAmB,sCAqMrB"}
|
|
@@ -19,6 +19,8 @@ function CommandPalette({
|
|
|
19
19
|
groups,
|
|
20
20
|
query,
|
|
21
21
|
onQueryChange,
|
|
22
|
+
customInput,
|
|
23
|
+
focusListKey,
|
|
22
24
|
hotkey = "mod+k",
|
|
23
25
|
placeholder = "Type a command or search…",
|
|
24
26
|
loading,
|
|
@@ -43,6 +45,7 @@ function CommandPalette({
|
|
|
43
45
|
const restoreFocusRef = useRef(null);
|
|
44
46
|
const isOpen = open ?? selfOpen;
|
|
45
47
|
const currentQuery = query ?? selfQuery;
|
|
48
|
+
const usesCustomInput = customInput !== void 0;
|
|
46
49
|
const setOpen = useCallback(
|
|
47
50
|
(next) => {
|
|
48
51
|
if (open === void 0) setSelfOpen(next);
|
|
@@ -78,7 +81,11 @@ function CommandPalette({
|
|
|
78
81
|
}
|
|
79
82
|
restoreFocusRef.current = document.activeElement;
|
|
80
83
|
(_c = inputRef.current) == null ? void 0 : _c.focus();
|
|
81
|
-
}, [isOpen, resetQueryOnClose, query]);
|
|
84
|
+
}, [isOpen, resetQueryOnClose, query, usesCustomInput]);
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
var _a;
|
|
87
|
+
if (isOpen && focusListKey !== void 0) (_a = listRef.current) == null ? void 0 : _a.focus();
|
|
88
|
+
}, [isOpen, focusListKey]);
|
|
82
89
|
useEffect(() => {
|
|
83
90
|
var _a;
|
|
84
91
|
if (activeIndex < 0) return;
|
|
@@ -149,14 +156,15 @@ function CommandPalette({
|
|
|
149
156
|
"aria-modal": "true",
|
|
150
157
|
"aria-label": ariaLabel,
|
|
151
158
|
className: cn(
|
|
152
|
-
"flex h-fit w-full flex-col
|
|
159
|
+
"flex h-fit w-full flex-col rounded-lg border border-border bg-background shadow-xl",
|
|
160
|
+
usesCustomInput ? "overflow-visible" : "overflow-hidden",
|
|
153
161
|
SIZE_CLASS[size],
|
|
154
162
|
className
|
|
155
163
|
),
|
|
156
164
|
style: { marginTop: topOffset },
|
|
157
165
|
onClick: (event) => event.stopPropagation(),
|
|
158
166
|
children: [
|
|
159
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-density-2 border-b border-border px-density-3", children: [
|
|
167
|
+
!usesCustomInput ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-density-2 border-b border-border px-density-3", children: [
|
|
160
168
|
/* @__PURE__ */ jsx(Icon, { icon: UiSearch, className: "shrink-0 text-muted-foreground" }),
|
|
161
169
|
/* @__PURE__ */ jsx(
|
|
162
170
|
"input",
|
|
@@ -176,7 +184,7 @@ function CommandPalette({
|
|
|
176
184
|
className: "h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder"
|
|
177
185
|
}
|
|
178
186
|
)
|
|
179
|
-
] }),
|
|
187
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "border-b border-border p-density-3", children: customInput }),
|
|
180
188
|
/* @__PURE__ */ jsx(
|
|
181
189
|
CommandPaletteList,
|
|
182
190
|
{
|
|
@@ -187,6 +195,8 @@ function CommandPalette({
|
|
|
187
195
|
optionId,
|
|
188
196
|
onActivate: activate,
|
|
189
197
|
onHover: setActiveIndex,
|
|
198
|
+
onKeyDown,
|
|
199
|
+
activeItemId: activeItem ? optionId(activeItem) : void 0,
|
|
190
200
|
listRef,
|
|
191
201
|
loading,
|
|
192
202
|
emptyState,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommandPalette.js","sources":["../../src/overlay/CommandPalette.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiSearch } from \"../icons\";\nimport { useHotkey } from \"../hooks/use-hotkey\";\nimport { useEscapeLayer, useModalStack } from \"./modalStack\";\nimport { zIndex } from \"./zIndex\";\nimport { CommandPaletteList } from \"./CommandPaletteList\";\nimport {\n defaultCommandFilter,\n filterCommandGroups,\n firstEnabledIndex,\n flattenCommands,\n lastEnabledIndex,\n nextEnabledIndex,\n type CommandFilter,\n type CommandGroup,\n type CommandItem,\n} from \"./CommandPalette.model\";\n\nexport type {\n CommandFilter,\n CommandGroup,\n CommandItem,\n CommandSelectContext,\n} from \"./CommandPalette.model\";\n\nconst SIZE_CLASS = {\n md: \"max-w-[40rem]\",\n lg: \"max-w-[48rem]\",\n} as const;\n\nexport type CommandPaletteProps = {\n /**\n * Controls visibility. Omit to run uncontrolled — the palette then owns its\n * open state and the built-in hotkey works with no wiring beyond mounting it.\n */\n open?: boolean;\n /** Called with the next open state on hotkey, Escape, backdrop click, and selection. */\n onOpenChange?: (open: boolean) => void;\n /** Command groups, rendered top to bottom in array order. */\n groups: CommandGroup[];\n /** Controlled query. Omit to let the palette own the input. */\n query?: string;\n /** Called with the next query on every keystroke. Required for server-side search. */\n onQueryChange?: (query: string) => void;\n /**\n * Global shortcut that opens (and, while open, closes) the palette, in\n * `useHotkey` syntax — `\"mod+k\"` by default, where `mod` is ⌘ on macOS and\n * Ctrl elsewhere. Pass `null` when an ancestor owns the binding.\n */\n hotkey?: string | null;\n /** Ghost text in the search input. Defaults to \"Type a command or search…\". */\n placeholder?: string;\n /** Shows a loading row instead of the empty state while results are in flight. */\n loading?: boolean;\n /** Replaces the default \"No results\" body. */\n emptyState?: ReactNode;\n /** Non-interactive hint strip pinned below the list. */\n footer?: ReactNode;\n /**\n * How rows are matched. Defaults to a case-insensitive substring match over\n * label, description and keywords, ranked by hit position. Pass `false` when\n * the caller already filtered `groups` server-side.\n */\n filter?: CommandFilter | false;\n /** Fallback handler for items with no own `onSelect`. */\n onSelect?: (context: { item: CommandItem; query: string; close: () => void }) => void;\n /** Close after a successful activation. Defaults to true. */\n closeOnSelect?: boolean;\n /** Clear the query when the palette closes. Defaults to true. */\n resetQueryOnClose?: boolean;\n /** Panel width preset. Defaults to \"md\". */\n size?: \"md\" | \"lg\";\n /** Distance from the viewport top. Defaults to \"12vh\". Applied as an inline style. */\n topOffset?: string | number;\n /** Max height of the scrolling list. Defaults to \"min(24rem, 50dvh)\". Inline style. */\n listMaxHeight?: string | number;\n /** Accessible name for the dialog. Defaults to \"Command palette\". */\n ariaLabel?: string;\n /** Classes applied to the palette panel. */\n className?: string;\n};\n\n/**\n * A ⌘K command palette: a top-anchored overlay with a search field over a\n * grouped, keyboard-navigable command list.\n *\n * It renders its own portal rather than building on `Modal`, which centres its\n * panel, focuses the dialog element instead of an input, forces body padding,\n * and pins an inline max-height — none of which a palette can override. The\n * stacking primitives are shared though (`useModalStack`, `useEscapeLayer`, the\n * `zIndex` scale), so a palette opened over a modal sits above it and Escape\n * still dismisses exactly one layer.\n */\nexport function CommandPalette({\n open,\n onOpenChange,\n groups,\n query,\n onQueryChange,\n hotkey = \"mod+k\",\n placeholder = \"Type a command or search…\",\n loading,\n emptyState,\n footer,\n filter = defaultCommandFilter,\n onSelect,\n closeOnSelect = true,\n resetQueryOnClose = true,\n size = \"md\",\n topOffset = \"12vh\",\n listMaxHeight = \"min(24rem, 50dvh)\",\n ariaLabel = \"Command palette\",\n className,\n}: CommandPaletteProps) {\n const baseId = useId();\n const [selfOpen, setSelfOpen] = useState(false);\n const [selfQuery, setSelfQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const restoreFocusRef = useRef<HTMLElement | null>(null);\n\n const isOpen = open ?? selfOpen;\n const currentQuery = query ?? selfQuery;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setSelfOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const setQuery = useCallback(\n (next: string) => {\n if (query === undefined) setSelfQuery(next);\n onQueryChange?.(next);\n },\n [query, onQueryChange],\n );\n\n const visibleGroups = useMemo(\n () => filterCommandGroups(groups, currentQuery, filter),\n [groups, currentQuery, filter],\n );\n const items = useMemo(() => flattenCommands(visibleGroups), [visibleGroups]);\n\n // Priority keeps the palette ahead of any page-level ⌘K search field, whose\n // binding would otherwise win purely by mounting later.\n useHotkey(hotkey, () => setOpen(!isOpen), { priority: 10 });\n useEscapeLayer(isOpen, () => setOpen(false));\n\n const { depth } = useModalStack(isOpen);\n\n // Enter-runs-the-top-result is the point of a palette, so the active row\n // resets to the first selectable one whenever the result set changes.\n useEffect(() => {\n setActiveIndex(firstEnabledIndex(items));\n }, [items]);\n\n useEffect(() => {\n if (!isOpen) {\n if (resetQueryOnClose && query === undefined) setSelfQuery(\"\");\n restoreFocusRef.current?.focus?.();\n restoreFocusRef.current = null;\n return;\n }\n restoreFocusRef.current = document.activeElement as HTMLElement | null;\n inputRef.current?.focus();\n }, [isOpen, resetQueryOnClose, query]);\n\n // Keep the active row in view without stealing focus from the input.\n useEffect(() => {\n if (activeIndex < 0) return;\n const option = listRef.current?.querySelectorAll('[role=\"option\"]')[activeIndex];\n // jsdom does not implement scrollIntoView; scrolling is a progressive\n // enhancement, so skip it rather than crash a consumer's test run.\n if (option instanceof HTMLElement && typeof option.scrollIntoView === \"function\") {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }, [activeIndex]);\n\n const optionId = useCallback((item: CommandItem) => `${baseId}-option-${item.id}`, [baseId]);\n\n const activate = useCallback(\n (item: CommandItem) => {\n if (item.disabled) return;\n const close = () => setOpen(false);\n const context = { item, query: currentQuery.trim(), close };\n if (item.onSelect) item.onSelect(context);\n else onSelect?.(context);\n if (closeOnSelect) close();\n },\n [currentQuery, onSelect, closeOnSelect, setOpen],\n );\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, 1));\n break;\n case \"ArrowUp\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, -1));\n break;\n case \"Home\":\n event.preventDefault();\n setActiveIndex(firstEnabledIndex(items));\n break;\n case \"End\":\n event.preventDefault();\n setActiveIndex(lastEnabledIndex(items));\n break;\n case \"Enter\": {\n event.preventDefault();\n const index = activeIndex >= 0 ? activeIndex : firstEnabledIndex(items);\n const item = index >= 0 ? items[index] : undefined;\n if (item) activate(item);\n break;\n }\n case \"Tab\":\n // Nothing else in the panel is focusable, and letting Tab escape an\n // aria-modal dialog would strand focus behind the backdrop.\n if (!footer) event.preventDefault();\n break;\n default:\n break;\n }\n };\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const listId = `${baseId}-list`;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex justify-center p-density-4\",\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: zIndex.modal + depth * zIndex.modalStep }}\n role=\"presentation\"\n onClick={() => setOpen(false)}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n className={cn(\n \"flex h-fit w-full flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl\",\n SIZE_CLASS[size],\n className,\n )}\n style={{ marginTop: topOffset }}\n onClick={(event) => event.stopPropagation()}\n >\n <div className=\"flex items-center gap-density-2 border-b border-border px-density-3\">\n <Icon icon={UiSearch} className=\"shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={ariaLabel}\n value={currentQuery}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onKeyDown}\n className=\"h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder\"\n />\n </div>\n\n <CommandPaletteList\n groups={visibleGroups}\n items={items}\n activeIndex={activeIndex}\n listId={listId}\n optionId={optionId}\n onActivate={activate}\n onHover={setActiveIndex}\n listRef={listRef}\n loading={loading}\n emptyState={emptyState}\n listMaxHeight={listMaxHeight}\n />\n\n {footer && (\n <div className=\"border-t border-border px-density-3 py-density-2 text-xs text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n\n return createPortal(overlay, document.body);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CommandPalette.js","sources":["../../src/overlay/CommandPalette.tsx"],"sourcesContent":["import { useCallback, useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiSearch } from \"../icons\";\nimport { useHotkey } from \"../hooks/use-hotkey\";\nimport { useEscapeLayer, useModalStack } from \"./modalStack\";\nimport { zIndex } from \"./zIndex\";\nimport { CommandPaletteList } from \"./CommandPaletteList\";\nimport {\n defaultCommandFilter,\n filterCommandGroups,\n firstEnabledIndex,\n flattenCommands,\n lastEnabledIndex,\n nextEnabledIndex,\n type CommandFilter,\n type CommandGroup,\n type CommandItem,\n} from \"./CommandPalette.model\";\n\nexport type {\n CommandFilter,\n CommandGroup,\n CommandItem,\n CommandSelectContext,\n} from \"./CommandPalette.model\";\n\nconst SIZE_CLASS = {\n md: \"max-w-[40rem]\",\n lg: \"max-w-[48rem]\",\n} as const;\n\nexport type CommandPaletteProps = {\n /**\n * Controls visibility. Omit to run uncontrolled — the palette then owns its\n * open state and the built-in hotkey works with no wiring beyond mounting it.\n */\n open?: boolean;\n /** Called with the next open state on hotkey, Escape, backdrop click, and selection. */\n onOpenChange?: (open: boolean) => void;\n /** Command groups, rendered top to bottom in array order. */\n groups: CommandGroup[];\n /** Controlled query. Omit to let the palette own the input. */\n query?: string;\n /** Called with the next query on every keystroke. Required for server-side search. */\n onQueryChange?: (query: string) => void;\n /** Replaces the built-in search field while preserving the palette and result list. */\n customInput?: ReactNode;\n /** Changing this value focuses the result list for keyboard selection. */\n focusListKey?: number;\n /**\n * Global shortcut that opens (and, while open, closes) the palette, in\n * `useHotkey` syntax — `\"mod+k\"` by default, where `mod` is ⌘ on macOS and\n * Ctrl elsewhere. Pass `null` when an ancestor owns the binding.\n */\n hotkey?: string | null;\n /** Ghost text in the search input. Defaults to \"Type a command or search…\". */\n placeholder?: string;\n /** Shows a loading row instead of the empty state while results are in flight. */\n loading?: boolean;\n /** Replaces the default \"No results\" body. */\n emptyState?: ReactNode;\n /** Non-interactive hint strip pinned below the list. */\n footer?: ReactNode;\n /**\n * How rows are matched. Defaults to a case-insensitive substring match over\n * label, description and keywords, ranked by hit position. Pass `false` when\n * the caller already filtered `groups` server-side.\n */\n filter?: CommandFilter | false;\n /** Fallback handler for items with no own `onSelect`. */\n onSelect?: (context: { item: CommandItem; query: string; close: () => void }) => void;\n /** Close after a successful activation. Defaults to true. */\n closeOnSelect?: boolean;\n /** Clear the query when the palette closes. Defaults to true. */\n resetQueryOnClose?: boolean;\n /** Panel width preset. Defaults to \"md\". */\n size?: \"md\" | \"lg\";\n /** Distance from the viewport top. Defaults to \"12vh\". Applied as an inline style. */\n topOffset?: string | number;\n /** Max height of the scrolling list. Defaults to \"min(24rem, 50dvh)\". Inline style. */\n listMaxHeight?: string | number;\n /** Accessible name for the dialog. Defaults to \"Command palette\". */\n ariaLabel?: string;\n /** Classes applied to the palette panel. */\n className?: string;\n};\n\n/**\n * A ⌘K command palette: a top-anchored overlay with a search field over a\n * grouped, keyboard-navigable command list.\n *\n * It renders its own portal rather than building on `Modal`, which centres its\n * panel, focuses the dialog element instead of an input, forces body padding,\n * and pins an inline max-height — none of which a palette can override. The\n * stacking primitives are shared though (`useModalStack`, `useEscapeLayer`, the\n * `zIndex` scale), so a palette opened over a modal sits above it and Escape\n * still dismisses exactly one layer.\n */\nexport function CommandPalette({\n open,\n onOpenChange,\n groups,\n query,\n onQueryChange,\n customInput,\n focusListKey,\n hotkey = \"mod+k\",\n placeholder = \"Type a command or search…\",\n loading,\n emptyState,\n footer,\n filter = defaultCommandFilter,\n onSelect,\n closeOnSelect = true,\n resetQueryOnClose = true,\n size = \"md\",\n topOffset = \"12vh\",\n listMaxHeight = \"min(24rem, 50dvh)\",\n ariaLabel = \"Command palette\",\n className,\n}: CommandPaletteProps) {\n const baseId = useId();\n const [selfOpen, setSelfOpen] = useState(false);\n const [selfQuery, setSelfQuery] = useState(\"\");\n const [activeIndex, setActiveIndex] = useState(0);\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const listRef = useRef<HTMLDivElement>(null);\n const restoreFocusRef = useRef<HTMLElement | null>(null);\n\n const isOpen = open ?? selfOpen;\n const currentQuery = query ?? selfQuery;\n const usesCustomInput = customInput !== undefined;\n\n const setOpen = useCallback(\n (next: boolean) => {\n if (open === undefined) setSelfOpen(next);\n onOpenChange?.(next);\n },\n [open, onOpenChange],\n );\n\n const setQuery = useCallback(\n (next: string) => {\n if (query === undefined) setSelfQuery(next);\n onQueryChange?.(next);\n },\n [query, onQueryChange],\n );\n\n const visibleGroups = useMemo(\n () => filterCommandGroups(groups, currentQuery, filter),\n [groups, currentQuery, filter],\n );\n const items = useMemo(() => flattenCommands(visibleGroups), [visibleGroups]);\n\n // Priority keeps the palette ahead of any page-level ⌘K search field, whose\n // binding would otherwise win purely by mounting later.\n useHotkey(hotkey, () => setOpen(!isOpen), { priority: 10 });\n useEscapeLayer(isOpen, () => setOpen(false));\n\n const { depth } = useModalStack(isOpen);\n\n // Enter-runs-the-top-result is the point of a palette, so the active row\n // resets to the first selectable one whenever the result set changes.\n useEffect(() => {\n setActiveIndex(firstEnabledIndex(items));\n }, [items]);\n\n useEffect(() => {\n if (!isOpen) {\n if (resetQueryOnClose && query === undefined) setSelfQuery(\"\");\n restoreFocusRef.current?.focus?.();\n restoreFocusRef.current = null;\n return;\n }\n restoreFocusRef.current = document.activeElement as HTMLElement | null;\n inputRef.current?.focus();\n }, [isOpen, resetQueryOnClose, query, usesCustomInput]);\n\n useEffect(() => {\n if (isOpen && focusListKey !== undefined) listRef.current?.focus();\n }, [isOpen, focusListKey]);\n\n // Keep the active row in view without stealing focus from the input.\n useEffect(() => {\n if (activeIndex < 0) return;\n const option = listRef.current?.querySelectorAll('[role=\"option\"]')[activeIndex];\n // jsdom does not implement scrollIntoView; scrolling is a progressive\n // enhancement, so skip it rather than crash a consumer's test run.\n if (option instanceof HTMLElement && typeof option.scrollIntoView === \"function\") {\n option.scrollIntoView({ block: \"nearest\" });\n }\n }, [activeIndex]);\n\n const optionId = useCallback((item: CommandItem) => `${baseId}-option-${item.id}`, [baseId]);\n\n const activate = useCallback(\n (item: CommandItem) => {\n if (item.disabled) return;\n const close = () => setOpen(false);\n const context = { item, query: currentQuery.trim(), close };\n if (item.onSelect) item.onSelect(context);\n else onSelect?.(context);\n if (closeOnSelect) close();\n },\n [currentQuery, onSelect, closeOnSelect, setOpen],\n );\n\n const onKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n switch (event.key) {\n case \"ArrowDown\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, 1));\n break;\n case \"ArrowUp\":\n event.preventDefault();\n setActiveIndex((current) => nextEnabledIndex(items, current, -1));\n break;\n case \"Home\":\n event.preventDefault();\n setActiveIndex(firstEnabledIndex(items));\n break;\n case \"End\":\n event.preventDefault();\n setActiveIndex(lastEnabledIndex(items));\n break;\n case \"Enter\": {\n event.preventDefault();\n const index = activeIndex >= 0 ? activeIndex : firstEnabledIndex(items);\n const item = index >= 0 ? items[index] : undefined;\n if (item) activate(item);\n break;\n }\n case \"Tab\":\n // Nothing else in the panel is focusable, and letting Tab escape an\n // aria-modal dialog would strand focus behind the backdrop.\n if (!footer) event.preventDefault();\n break;\n default:\n break;\n }\n };\n\n if (!isOpen || typeof document === \"undefined\") return null;\n\n const activeItem = activeIndex >= 0 ? items[activeIndex] : undefined;\n const listId = `${baseId}-list`;\n\n const overlay = (\n <div\n className={cn(\n \"fixed inset-0 flex justify-center p-density-4\",\n depth === 0 ? \"bg-black/40\" : \"bg-black/20\",\n )}\n style={{ zIndex: zIndex.modal + depth * zIndex.modalStep }}\n role=\"presentation\"\n onClick={() => setOpen(false)}\n >\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n className={cn(\n \"flex h-fit w-full flex-col rounded-lg border border-border bg-background shadow-xl\",\n usesCustomInput ? \"overflow-visible\" : \"overflow-hidden\",\n SIZE_CLASS[size],\n className,\n )}\n style={{ marginTop: topOffset }}\n onClick={(event) => event.stopPropagation()}\n >\n {!usesCustomInput ? <div className=\"flex items-center gap-density-2 border-b border-border px-density-3\">\n <Icon icon={UiSearch} className=\"shrink-0 text-muted-foreground\" />\n <input\n ref={inputRef}\n type=\"text\"\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={activeItem ? optionId(activeItem) : undefined}\n aria-label={ariaLabel}\n value={currentQuery}\n placeholder={placeholder}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={onKeyDown}\n className=\"h-12 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-placeholder\"\n />\n </div> : <div className=\"border-b border-border p-density-3\">{customInput}</div>}\n\n <CommandPaletteList\n groups={visibleGroups}\n items={items}\n activeIndex={activeIndex}\n listId={listId}\n optionId={optionId}\n onActivate={activate}\n onHover={setActiveIndex}\n onKeyDown={onKeyDown}\n activeItemId={activeItem ? optionId(activeItem) : undefined}\n listRef={listRef}\n loading={loading}\n emptyState={emptyState}\n listMaxHeight={listMaxHeight}\n />\n\n {footer && (\n <div className=\"border-t border-border px-density-3 py-density-2 text-xs text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>\n </div>\n );\n\n return createPortal(overlay, document.body);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,8 @@ function CommandPaletteList({
|
|
|
12
12
|
optionId,
|
|
13
13
|
onActivate,
|
|
14
14
|
onHover,
|
|
15
|
+
onKeyDown,
|
|
16
|
+
activeItemId,
|
|
15
17
|
listRef,
|
|
16
18
|
loading,
|
|
17
19
|
emptyState,
|
|
@@ -25,6 +27,9 @@ function CommandPaletteList({
|
|
|
25
27
|
id: listId,
|
|
26
28
|
role: "listbox",
|
|
27
29
|
"aria-label": "Commands",
|
|
30
|
+
"aria-activedescendant": activeItemId,
|
|
31
|
+
tabIndex: -1,
|
|
32
|
+
onKeyDown,
|
|
28
33
|
className: "overflow-y-auto overscroll-contain py-density-1",
|
|
29
34
|
style: { maxHeight: listMaxHeight },
|
|
30
35
|
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-density-3 py-density-3 text-sm text-muted-foreground", children: "Searching…" }) : items.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-density-3 py-density-4 text-center text-sm text-muted-foreground", children: emptyState ?? "No results" }) : groups.map((group) => {
|