@flanksource/clicky-ui 0.3.41 → 0.3.42
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/dist/ai.cjs +4 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +4 -0
- package/dist/ai.js.map +1 -1
- package/dist/comments/CommentCard.cjs +3 -1
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +4 -2
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +16 -0
- package/dist/comments/CommentCardParts.cjs.map +1 -1
- package/dist/comments/CommentCardParts.d.ts +4 -1
- package/dist/comments/CommentCardParts.d.ts.map +1 -1
- package/dist/comments/CommentCardParts.js +16 -0
- package/dist/comments/CommentCardParts.js.map +1 -1
- package/dist/comments/comment-types.cjs.map +1 -1
- package/dist/comments/comment-types.d.ts +4 -0
- package/dist/comments/comment-types.d.ts.map +1 -1
- package/dist/comments/comment-types.js.map +1 -1
- package/dist/components/Combobox.cjs +54 -8
- package/dist/components/Combobox.cjs.map +1 -1
- package/dist/components/Combobox.d.ts.map +1 -1
- package/dist/components/Combobox.js +56 -10
- package/dist/components/Combobox.js.map +1 -1
- package/dist/components/ComboboxMenu.cjs +139 -113
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts +3 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +139 -113
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/ComboboxMenuTrigger.cjs +87 -0
- package/dist/components/ComboboxMenuTrigger.cjs.map +1 -0
- package/dist/components/ComboboxMenuTrigger.d.ts +23 -0
- package/dist/components/ComboboxMenuTrigger.d.ts.map +1 -0
- package/dist/components/ComboboxMenuTrigger.js +87 -0
- package/dist/components/ComboboxMenuTrigger.js.map +1 -0
- package/dist/components/JsonSchemaForm.cjs +30 -7
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +30 -7
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/SegmentedControl.cjs +20 -3
- package/dist/components/SegmentedControl.cjs.map +1 -1
- package/dist/components/SegmentedControl.d.ts +11 -0
- package/dist/components/SegmentedControl.d.ts.map +1 -1
- package/dist/components/SegmentedControl.js +21 -4
- package/dist/components/SegmentedControl.js.map +1 -1
- package/dist/components/combobox-types.d.ts +8 -0
- package/dist/components/combobox-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-debug-badge.cjs +108 -0
- package/dist/components/json-schema-form-debug-badge.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-badge.d.ts +10 -0
- package/dist/components/json-schema-form-debug-badge.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-badge.js +108 -0
- package/dist/components/json-schema-form-debug-badge.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts +20 -0
- package/dist/components/json-schema-form-debug-glyph-map.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph-map.js +129 -0
- package/dist/components/json-schema-form-debug-glyph-map.js.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.cjs +13 -0
- package/dist/components/json-schema-form-debug-glyph.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts +6 -0
- package/dist/components/json-schema-form-debug-glyph.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-glyph.js +13 -0
- package/dist/components/json-schema-form-debug-glyph.js.map +1 -0
- package/dist/components/json-schema-form-debug-groups.cjs +56 -0
- package/dist/components/json-schema-form-debug-groups.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-groups.d.ts +8 -0
- package/dist/components/json-schema-form-debug-groups.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-groups.js +56 -0
- package/dist/components/json-schema-form-debug-groups.js.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.cjs +159 -0
- package/dist/components/json-schema-form-debug-keywords.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts +6 -0
- package/dist/components/json-schema-form-debug-keywords.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-keywords.js +159 -0
- package/dist/components/json-schema-form-debug-keywords.js.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.cjs +102 -0
- package/dist/components/json-schema-form-debug-listeners.cjs.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts +6 -0
- package/dist/components/json-schema-form-debug-listeners.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug-listeners.js +102 -0
- package/dist/components/json-schema-form-debug-listeners.js.map +1 -0
- package/dist/components/json-schema-form-debug.cjs +31 -0
- package/dist/components/json-schema-form-debug.cjs.map +1 -0
- package/dist/components/json-schema-form-debug.d.ts +11 -0
- package/dist/components/json-schema-form-debug.d.ts.map +1 -0
- package/dist/components/json-schema-form-debug.js +31 -0
- package/dist/components/json-schema-form-debug.js.map +1 -0
- package/dist/components/json-schema-form-enum-choice.cjs +114 -0
- package/dist/components/json-schema-form-enum-choice.cjs.map +1 -0
- package/dist/components/json-schema-form-enum-choice.d.ts +14 -0
- package/dist/components/json-schema-form-enum-choice.d.ts.map +1 -0
- package/dist/components/json-schema-form-enum-choice.js +114 -0
- package/dist/components/json-schema-form-enum-choice.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +3 -93
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +1 -91
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-listeners.cjs +7 -1
- package/dist/components/json-schema-form-listeners.cjs.map +1 -1
- package/dist/components/json-schema-form-listeners.d.ts.map +1 -1
- package/dist/components/json-schema-form-listeners.js +7 -1
- package/dist/components/json-schema-form-listeners.js.map +1 -1
- package/dist/components/json-schema-form-preferences.cjs +1 -0
- package/dist/components/json-schema-form-preferences.cjs.map +1 -1
- package/dist/components/json-schema-form-preferences.d.ts +1 -0
- package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
- package/dist/components/json-schema-form-preferences.js +1 -0
- package/dist/components/json-schema-form-preferences.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +21 -5
- 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 +21 -5
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +1 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-tone.cjs +12 -0
- package/dist/components/json-schema-form-tone.cjs.map +1 -1
- package/dist/components/json-schema-form-tone.js +12 -0
- package/dist/components/json-schema-form-tone.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +1 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/data/GraphDiagram.cjs +125 -138
- package/dist/data/GraphDiagram.cjs.map +1 -1
- package/dist/data/GraphDiagram.d.ts +30 -23
- package/dist/data/GraphDiagram.d.ts.map +1 -1
- package/dist/data/GraphDiagram.js +128 -141
- package/dist/data/GraphDiagram.js.map +1 -1
- package/dist/data/GraphDiagramEdges.cjs +208 -0
- package/dist/data/GraphDiagramEdges.cjs.map +1 -0
- package/dist/data/GraphDiagramEdges.d.ts +40 -0
- package/dist/data/GraphDiagramEdges.d.ts.map +1 -0
- package/dist/data/GraphDiagramEdges.js +208 -0
- package/dist/data/GraphDiagramEdges.js.map +1 -0
- package/dist/data/GraphDiagramNodes.cjs +142 -0
- package/dist/data/GraphDiagramNodes.cjs.map +1 -0
- package/dist/data/GraphDiagramNodes.d.ts +22 -0
- package/dist/data/GraphDiagramNodes.d.ts.map +1 -0
- package/dist/data/GraphDiagramNodes.js +142 -0
- package/dist/data/GraphDiagramNodes.js.map +1 -0
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js +8 -3
- package/dist/data/ai/PromptRunEditor/RuntimeRows.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.cjs +37 -43
- package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts +3 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.js +38 -44
- package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs +16 -5
- package/dist/data/ai/PromptRunEditor/runtimeActions.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts +4 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/runtimeActions.js +17 -6
- package/dist/data/ai/PromptRunEditor/runtimeActions.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.cjs +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.d.ts +11 -2
- package/dist/data/ai/SessionInspector.approvals-model.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals-model.js +12 -0
- package/dist/data/ai/SessionInspector.approvals-model.js.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +25 -1
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.approvals.js +26 -2
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -1
- package/dist/data/ai/SessionInspector.summary.cjs +9 -3
- package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.summary.js +9 -3
- package/dist/data/ai/SessionInspector.summary.js.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.cjs +4 -0
- package/dist/data/ai/SessionInspector.transcript.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.transcript.js +4 -0
- package/dist/data/ai/SessionInspector.transcript.js.map +1 -1
- package/dist/data/ai/SessionViewer.approval-body.cjs +146 -0
- package/dist/data/ai/SessionViewer.approval-body.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts +11 -0
- package/dist/data/ai/SessionViewer.approval-body.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-body.js +146 -0
- package/dist/data/ai/SessionViewer.approval-body.js.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts +23 -0
- package/dist/data/ai/SessionViewer.approval-forms.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.approval-forms.js +150 -0
- package/dist/data/ai/SessionViewer.approval-forms.js.map +1 -0
- package/dist/data/ai/SessionViewer.cjs +57 -20
- package/dist/data/ai/SessionViewer.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +13 -3
- package/dist/data/ai/SessionViewer.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.decision-controls.cjs +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts +43 -0
- package/dist/data/ai/SessionViewer.decision-controls.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision-controls.js +313 -0
- package/dist/data/ai/SessionViewer.decision-controls.js.map +1 -0
- package/dist/data/ai/SessionViewer.decision.cjs +21 -0
- package/dist/data/ai/SessionViewer.decision.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.decision.d.ts +12 -0
- package/dist/data/ai/SessionViewer.decision.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.decision.js +21 -0
- package/dist/data/ai/SessionViewer.decision.js.map +1 -0
- package/dist/data/ai/SessionViewer.input.cjs +14 -0
- package/dist/data/ai/SessionViewer.input.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.input.d.ts +5 -0
- package/dist/data/ai/SessionViewer.input.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.input.js +14 -0
- package/dist/data/ai/SessionViewer.input.js.map +1 -1
- package/dist/data/ai/SessionViewer.js +58 -21
- package/dist/data/ai/SessionViewer.js.map +1 -1
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +4 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.rows.cjs +6 -3
- package/dist/data/ai/SessionViewer.rows.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +2 -1
- package/dist/data/ai/SessionViewer.rows.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.rows.js +6 -3
- package/dist/data/ai/SessionViewer.rows.js.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.cjs +29 -237
- package/dist/data/ai/SessionViewer.tool-row.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.tool-row.js +27 -235
- package/dist/data/ai/SessionViewer.tool-row.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +4 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.cjs +8 -2
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -1
- package/dist/data/ai/SessionViewerMenu.d.ts +4 -1
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -1
- package/dist/data/ai/SessionViewerMenu.js +8 -2
- package/dist/data/ai/SessionViewerMenu.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs +28 -17
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts +10 -2
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js +29 -18
- package/dist/data/ai/SpecRuntimeEditor/CommitSection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts +9 -2
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js +9 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.cjs +1 -1
- package/dist/data/ai/SpecRuntimeEditor/permission-mode-visuals.js +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts +8 -2
- package/dist/data/ai/SpecRuntimeEditor/summaries.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/summaries.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.cjs +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts +1 -0
- package/dist/data/ai/SpecRuntimeEditor/update.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/update.js +14 -6
- package/dist/data/ai/SpecRuntimeEditor/update.js.map +1 -1
- package/dist/data/ai/approval-request.cjs +75 -0
- package/dist/data/ai/approval-request.cjs.map +1 -0
- package/dist/data/ai/approval-request.d.ts +155 -0
- package/dist/data/ai/approval-request.d.ts.map +1 -0
- package/dist/data/ai/approval-request.js +75 -0
- package/dist/data/ai/approval-request.js.map +1 -0
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts +11 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js +125 -0
- package/dist/data/ai/runtime-preset-menu/SavePresetDialog.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts +3 -0
- package/dist/data/ai/runtime-preset-menu/index.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs +73 -0
- package/dist/data/ai/runtime-preset-menu/model.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts +13 -0
- package/dist/data/ai/runtime-preset-menu/model.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/model.js +73 -0
- package/dist/data/ai/runtime-preset-menu/model.js.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.cjs.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts +15 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.d.ts.map +1 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js +149 -0
- package/dist/data/ai/runtime-preset-menu/use-runtime-preset-menu.js.map +1 -0
- package/dist/data/ai/runtime-spec-fields.cjs +166 -0
- package/dist/data/ai/runtime-spec-fields.cjs.map +1 -0
- package/dist/data/ai/runtime-spec-fields.d.ts +13 -0
- package/dist/data/ai/runtime-spec-fields.d.ts.map +1 -0
- package/dist/data/ai/runtime-spec-fields.js +166 -0
- package/dist/data/ai/runtime-spec-fields.js.map +1 -0
- package/dist/data/ai/session-categories.cjs +4 -0
- package/dist/data/ai/session-categories.cjs.map +1 -1
- package/dist/data/ai/session-categories.d.ts +1 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -1
- package/dist/data/ai/session-categories.js +4 -0
- package/dist/data/ai/session-categories.js.map +1 -1
- package/dist/data/ai/use-session-scroll.cjs +49 -21
- package/dist/data/ai/use-session-scroll.cjs.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +2 -0
- package/dist/data/ai/use-session-scroll.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.js +49 -21
- package/dist/data/ai/use-session-scroll.js.map +1 -1
- package/dist/data/chat/Chat.runtime.cjs +1 -1
- package/dist/data/chat/Chat.runtime.cjs.map +1 -1
- package/dist/data/chat/Chat.runtime.d.ts.map +1 -1
- package/dist/data/chat/Chat.runtime.js +1 -1
- package/dist/data/chat/Chat.runtime.js.map +1 -1
- package/dist/data/graph-columns-layout.cjs +216 -0
- package/dist/data/graph-columns-layout.cjs.map +1 -0
- package/dist/data/graph-columns-layout.d.ts +56 -0
- package/dist/data/graph-columns-layout.d.ts.map +1 -0
- package/dist/data/graph-columns-layout.js +216 -0
- package/dist/data/graph-columns-layout.js.map +1 -0
- package/dist/data/graph-diagram-model.cjs +73 -0
- package/dist/data/graph-diagram-model.cjs.map +1 -0
- package/dist/data/graph-diagram-model.d.ts +90 -0
- package/dist/data/graph-diagram-model.d.ts.map +1 -0
- package/dist/data/graph-diagram-model.js +73 -0
- package/dist/data/graph-diagram-model.js.map +1 -0
- package/dist/data/graph-edge-routing.cjs +235 -0
- package/dist/data/graph-edge-routing.cjs.map +1 -0
- package/dist/data/graph-edge-routing.d.ts +73 -0
- package/dist/data/graph-edge-routing.d.ts.map +1 -0
- package/dist/data/graph-edge-routing.js +235 -0
- package/dist/data/graph-edge-routing.js.map +1 -0
- package/dist/data/graph-layout.cjs +0 -82
- package/dist/data/graph-layout.cjs.map +1 -1
- package/dist/data/graph-layout.d.ts +1 -28
- package/dist/data/graph-layout.d.ts.map +1 -1
- package/dist/data/graph-layout.js +1 -83
- package/dist/data/graph-layout.js.map +1 -1
- package/dist/data/har/HarPanel.cjs +129 -33
- package/dist/data/har/HarPanel.cjs.map +1 -1
- package/dist/data/har/HarPanel.d.ts +13 -1
- package/dist/data/har/HarPanel.d.ts.map +1 -1
- package/dist/data/har/HarPanel.js +130 -34
- package/dist/data/har/HarPanel.js.map +1 -1
- package/dist/data/har/fixtures.d.ts +12 -0
- package/dist/data/har/fixtures.d.ts.map +1 -1
- package/dist/data/har/types.d.ts +12 -0
- package/dist/data/har/types.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.cjs +67 -84
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts +4 -5
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.fields.cjs +170 -0
- package/dist/data/runtime/RuntimeBar.fields.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts +16 -0
- package/dist/data/runtime/RuntimeBar.fields.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.fields.js +170 -0
- package/dist/data/runtime/RuntimeBar.fields.js.map +1 -0
- package/dist/data/runtime/RuntimeBar.js +70 -87
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/runtime/RuntimeBar.selection.cjs +56 -0
- package/dist/data/runtime/RuntimeBar.selection.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts +20 -0
- package/dist/data/runtime/RuntimeBar.selection.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBar.selection.js +56 -0
- package/dist/data/runtime/RuntimeBar.selection.js.map +1 -0
- package/dist/data/runtime/RuntimeBarActions.cjs +10 -6
- package/dist/data/runtime/RuntimeBarActions.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts +8 -1
- package/dist/data/runtime/RuntimeBarActions.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarActions.js +10 -6
- package/dist/data/runtime/RuntimeBarActions.js.map +1 -1
- package/dist/data/runtime/RuntimeBarIdentity.cjs +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts +25 -0
- package/dist/data/runtime/RuntimeBarIdentity.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarIdentity.js +166 -0
- package/dist/data/runtime/RuntimeBarIdentity.js.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs +95 -0
- package/dist/data/runtime/RuntimeBarLayout.cjs.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts +9 -0
- package/dist/data/runtime/RuntimeBarLayout.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeBarLayout.js +95 -0
- package/dist/data/runtime/RuntimeBarLayout.js.map +1 -0
- package/dist/data/runtime/RuntimeBarSegment.cjs +25 -14
- package/dist/data/runtime/RuntimeBarSegment.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.d.ts +4 -0
- package/dist/data/runtime/RuntimeBarSegment.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBarSegment.js +25 -14
- package/dist/data/runtime/RuntimeBarSegment.js.map +1 -1
- package/dist/data/runtime/RuntimeLimitInput.cjs +41 -0
- package/dist/data/runtime/RuntimeLimitInput.cjs.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts +9 -0
- package/dist/data/runtime/RuntimeLimitInput.d.ts.map +1 -0
- package/dist/data/runtime/RuntimeLimitInput.js +41 -0
- package/dist/data/runtime/RuntimeLimitInput.js.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.cjs.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts +13 -0
- package/dist/data/runtime/use-runtime-bar-overflow.d.ts.map +1 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js +70 -0
- package/dist/data/runtime/use-runtime-bar-overflow.js.map +1 -0
- package/dist/data/use-edge-focus.cjs +20 -0
- package/dist/data/use-edge-focus.cjs.map +1 -0
- package/dist/data/use-edge-focus.d.ts +23 -0
- package/dist/data/use-edge-focus.d.ts.map +1 -0
- package/dist/data/use-edge-focus.js +20 -0
- package/dist/data/use-edge-focus.js.map +1 -0
- package/dist/data/use-pan-zoom.cjs +159 -0
- package/dist/data/use-pan-zoom.cjs.map +1 -0
- package/dist/data/use-pan-zoom.d.ts +79 -0
- package/dist/data/use-pan-zoom.d.ts.map +1 -0
- package/dist/data/use-pan-zoom.js +159 -0
- package/dist/data/use-pan-zoom.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +5 -1
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +4 -3
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +6 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +5 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.d.ts +4 -0
- package/dist/overlay/DropdownMenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenu.js +1 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.cjs +31 -15
- package/dist/overlay/DropdownMenuSubmenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.d.ts.map +1 -1
- package/dist/overlay/DropdownMenuSubmenu.js +31 -15
- package/dist/overlay/DropdownMenuSubmenu.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +3 -1
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +3 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +3 -1
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/useOperationPages.cjs +6 -1
- package/dist/rpc/useOperationPages.cjs.map +1 -1
- package/dist/rpc/useOperationPages.d.ts +3 -1
- package/dist/rpc/useOperationPages.d.ts.map +1 -1
- package/dist/rpc/useOperationPages.js +6 -1
- package/dist/rpc/useOperationPages.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/schemas/json-schema-form.schema.json +5 -0
- package/dist/data/runtime/RuntimeBarCombo.cjs +0 -423
- package/dist/data/runtime/RuntimeBarCombo.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.d.ts +0 -33
- package/dist/data/runtime/RuntimeBarCombo.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarCombo.js +0 -423
- package/dist/data/runtime/RuntimeBarCombo.js.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.cjs +0 -262
- package/dist/data/runtime/RuntimeBarLimits.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.d.ts +0 -17
- package/dist/data/runtime/RuntimeBarLimits.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarLimits.js +0 -262
- package/dist/data/runtime/RuntimeBarLimits.js.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.cjs +0 -346
- package/dist/data/runtime/RuntimeBarSegments.cjs.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.d.ts +0 -37
- package/dist/data/runtime/RuntimeBarSegments.d.ts.map +0 -1
- package/dist/data/runtime/RuntimeBarSegments.js +0 -346
- package/dist/data/runtime/RuntimeBarSegments.js.map +0 -1
|
@@ -121,7 +121,8 @@ function JsonSchemaForm({
|
|
|
121
121
|
render: jsonSchemaFormRender.renderApi,
|
|
122
122
|
...expressionEvaluator ? { expressionEvaluator } : {},
|
|
123
123
|
...idPrefix ? { idPrefix } : {},
|
|
124
|
-
...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}
|
|
124
|
+
...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {},
|
|
125
|
+
...prefs.debug ? { debug: true } : {}
|
|
125
126
|
};
|
|
126
127
|
const discKey = typeof resolvedSchema["x-discriminator"] === "string" ? resolvedSchema["x-discriminator"] : void 0;
|
|
127
128
|
const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === "");
|
|
@@ -139,7 +140,9 @@ function JsonSchemaForm({
|
|
|
139
140
|
onFilterChange: setFieldFilter,
|
|
140
141
|
onSelectSize: (next) => applyPrefs({ ...prefs, size: next }),
|
|
141
142
|
onSelectLayout: (next) => applyPrefs({ ...prefs, layoutMode: next }),
|
|
142
|
-
onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next })
|
|
143
|
+
onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next }),
|
|
144
|
+
debug: prefs.debug === true,
|
|
145
|
+
onToggleDebug: () => applyPrefs({ ...prefs, debug: !prefs.debug })
|
|
143
146
|
}
|
|
144
147
|
),
|
|
145
148
|
title && /* @__PURE__ */ jsxRuntime.jsx("h3", { className: utils.cn("font-semibold", jsonSchemaFormSize.labelSizeClass[effectiveSize]), children: title }),
|
|
@@ -199,9 +202,11 @@ function PreferencesMenu({
|
|
|
199
202
|
onFilterChange,
|
|
200
203
|
onSelectSize,
|
|
201
204
|
onSelectLayout,
|
|
202
|
-
onSelectSort
|
|
205
|
+
onSelectSort,
|
|
206
|
+
debug,
|
|
207
|
+
onToggleDebug
|
|
203
208
|
}) {
|
|
204
|
-
const filterActive = fieldFilter.trim() !== "";
|
|
209
|
+
const filterActive = fieldFilter.trim() !== "" || debug;
|
|
205
210
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
206
211
|
DropdownMenu.DropdownMenu,
|
|
207
212
|
{
|
|
@@ -261,7 +266,20 @@ function PreferencesMenu({
|
|
|
261
266
|
}
|
|
262
267
|
},
|
|
263
268
|
opt.value
|
|
264
|
-
))
|
|
269
|
+
)),
|
|
270
|
+
/* @__PURE__ */ jsxRuntime.jsx(PreferenceSection, { title: "Debug" }),
|
|
271
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
272
|
+
PreferenceItem,
|
|
273
|
+
{
|
|
274
|
+
role: "menuitemcheckbox",
|
|
275
|
+
label: "Show hidden fields & sources",
|
|
276
|
+
selected: debug,
|
|
277
|
+
onSelect: () => {
|
|
278
|
+
onToggleDebug();
|
|
279
|
+
closeMenu();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
)
|
|
265
283
|
] })
|
|
266
284
|
}
|
|
267
285
|
);
|
|
@@ -269,12 +287,17 @@ function PreferencesMenu({
|
|
|
269
287
|
function PreferenceSection({ title }) {
|
|
270
288
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: title });
|
|
271
289
|
}
|
|
272
|
-
function PreferenceItem({
|
|
290
|
+
function PreferenceItem({
|
|
291
|
+
label,
|
|
292
|
+
selected,
|
|
293
|
+
onSelect,
|
|
294
|
+
role = "menuitemradio"
|
|
295
|
+
}) {
|
|
273
296
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
274
297
|
"button",
|
|
275
298
|
{
|
|
276
299
|
type: "button",
|
|
277
|
-
role
|
|
300
|
+
role,
|
|
278
301
|
"aria-checked": selected,
|
|
279
302
|
className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
|
|
280
303
|
onClick: onSelect,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonSchemaForm.cjs","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\";\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({ label, selected, onSelect }: { label: string; selected: boolean; onSelect: () => void }) {\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":["DEFAULT_FORM_SIZE","DEFAULT_PREFERENCES_STORAGE_KEY","useState","readPreferences","writePreferences","useMemo","rehydrateRefs","applySchemaDefaults","unmatchedFormErrors","useEffect","renderApi","renderObjectFields","jsx","FormLookupProvider","cn","fieldInnerGapClass","labelSizeClass","FormFieldFilter","FormErrorSummary","FieldsGrid","normalizeColumns","cssLength","DEFAULT_COLUMN_MIN_WIDTH","DiscriminatedForm","DropdownMenu","Icon","UiEllipsisBold","jsxs","Fragment","UiCheck"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BA,MAAM,0BAA0B;AAChC,MAAM,0BAA0B;AAQhC,SAAS,kBACP,QACA,QACA,cACY;AACZ,QAAM,YAAW,iCAAQ,UAAS,SAAS,WAAW;AACtD,QAAM,OAAO,gBAAgB;AAC7B,QAAM,iBAAgB,iCAAQ,kBAAiB;AAE/C,QAAM,QAAO,iCAAQ,QAAO,EAAE,MAAM,OAAO,KAAA,IAAS,CAAA;AACpD,MAAI,SAAS,aAAc,QAAO,EAAE,GAAG,QAAQ,MAAM,GAAG,KAAA;AACxD,MAAI,SAAS,SAAU,QAAO,EAAE,MAAM,WAAW,eAAe,GAAG,KAAA;AACnE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,gBAAe,iCAAQ,kBAAiB;AAAA,IACxC;AAAA,IACA,GAAG;AAAA,EAAA;AAEP;AAOO,SAAS,eAAe;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,SAAS,CAAA;AAAA,EACT,WAAW;AAAA,EACX,SAAS;AAAA,EACT;AAAA,EACA,OAAOA,mBAAAA;AAAAA,EACP;AAAA,EACA,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB;AAAA,EACA,qBAAqB;AAAA,EACrB,wBAAwBC,0BAAAA;AAAAA,EACxB;AAAA,EACA;AAAA,EACA,gBAAgB;AAClB,GAAwB;AAGtB,QAAM,CAAC,OAAO,QAAQ,IAAIC,MAAAA;AAAAA,IAA0B,MAClD,uBAAuB,qBAAqBC,0BAAAA,gBAAgB,qBAAqB,IAAI,CAAA;AAAA,EAAC;AAIxF,QAAM,CAAC,aAAa,cAAc,IAAID,MAAAA,SAAS,EAAE;AAEjD,QAAM,gBAAgB,MAAM,QAAQ;AACpC,QAAM,iBAAiB,kBAAkB,QAAQ,QAAQ,MAAM,UAAU;AACzE,QAAM,gBAAgB,eAAe,uBAAuB,eAAe,SAAS;AAEpF,QAAM,oBAAoB,MAAM,aAAa,gBAAgB,mBAAmB;AAEhF,QAAM,aAAa,CAAC,SAA0B;AAC5C,aAAS,IAAI;AACb,QAAI,mBAAoBE,2BAAAA,iBAAiB,uBAAuB,IAAI;AAAA,EACtE;AAKA,QAAM,iBAAiBC,MAAAA,QAAQ,MAAMC,mBAAAA,cAAc,MAAM,GAAG,CAAC,MAAM,CAAC;AAIpE,QAAM,iBAAiBD,MAAAA;AAAAA,IACrB,MAAO,gBAAgBE,uBAAAA,oBAAoB,gBAAgB,KAAK,IAAI;AAAA,IACpE,CAAC,eAAe,gBAAgB,KAAK;AAAA,EAAA;AAEvC,QAAM,gBAAgB,OAAO,CAAA;AAC7B,QAAM,kBAAkBF,MAAAA;AAAAA,IACtB,MACEG,yCAAoB;AAAA,MAClB,QAAQ;AAAA,MACR,OAAO;AAAA,MACP;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,WAAW,aAAa;AAAA,MACxB;AAAA,MACA,GAAI,aAAa,EAAE,WAAA,IAAe,CAAA;AAAA,MAClC,GAAI,YAAY,SAAS,EAAE,aAAa,YAAY,KAAA,EAAK,IAAM,CAAA;AAAA,MAC/D,GAAI,sBAAsB,EAAE,wBAAwB,CAAA;AAAA,IAAC,CACtD;AAAA,IACH,CAAC,gBAAgB,QAAQ,qBAAqB,aAAa,YAAY,WAAW,oBAAoB,cAAc,eAAe,UAAU,gBAAgB,SAAS;AAAA,EAAA;AAKxKC,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,YAAY,mBAAmB,gBAAgB,cAAc;AAAA,EACpE,GAAG,CAAC,gBAAgB,UAAU,UAAU,KAAK,CAAC;AAE9C,QAAM,MAAqB;AAAA,IACzB;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM,QAAQ,CAAA;AAAA,IACd,WAAW,aAAa;AAAA,IACxB,cAAc,gBAAgB;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,QAAQC,qBAAAA;AAAAA,IACR,GAAI,sBAAsB,EAAE,oBAAA,IAAwB,CAAA;AAAA,IACpD,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,IAC9B,GAAI,YAAY,SAAS,EAAE,aAAa,YAAY,KAAA,MAAW,CAAA;AAAA,EAAC;AAIlE,QAAM,UAAU,OAAO,eAAe,iBAAiB,MAAM,WAAW,eAAe,iBAAiB,IAAI;AAC5G,QAAM,gBAAgB,WAAW,SAAS,eAAe,OAAO,KAAK,QAAQ,eAAe,OAAO,MAAM;AAEzG,QAAM,aAAa,UACf,OACAC,qBAAAA,mBAAmB,gBAAgB,gBAAgB,UAAU,KAAK,aAAa,EAAE,WAAA,IAAe,MAAS;AAC7G,QAAM,YAAY,cAAc,QAAQ,WAAW,WAAW,KAAK,YAAY,WAAW;AAE1F,SACEC,2BAAAA,IAACC,yCAAoB,GAAI,gBAAgB,EAAE,SAAS,cAAA,IAAkB,CAAA,GACpE,0CAAC,OAAA,EAAI,yBAAqB,MAAC,WAAWC,MAAAA,GAAG,0BAA0BC,sCAAmB,aAAa,CAAC,GACjG,UAAA;AAAA,IAAA,uBAAuB,CAAC,iBACvBH,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAM;AAAA,QACN,YAAY,eAAe;AAAA,QAC3B,UAAU;AAAA,QACV;AAAA,QACA,cAAc,CAAC;AAAA,QACf,gBAAgB;AAAA,QAChB,cAAc,CAAC,SAAS,WAAW,EAAE,GAAG,OAAO,MAAM,MAAM;AAAA,QAC3D,gBAAgB,CAAC,SAAS,WAAW,EAAE,GAAG,OAAO,YAAY,MAAM;AAAA,QACnE,cAAc,CAAC,SAAS,WAAW,EAAE,GAAG,OAAO,UAAU,KAAA,CAAM;AAAA,MAAA;AAAA,IAAA;AAAA,IAGlE,SAASA,2BAAAA,IAAC,MAAA,EAAG,WAAWE,MAAAA,GAAG,iBAAiBE,mBAAAA,eAAe,aAAa,CAAC,GAAI,UAAA,MAAA,CAAM;AAAA,IACnF,iBAAiB,CAAC,iBACjBJ,2BAAAA,IAAC,OAAA,EAAI,WAAU,iBACb,UAAAA,2BAAAA,IAACK,0BAAAA,iBAAA,EAAgB,OAAO,aAAa,UAAU,gBAAgB,GACjE;AAAA,IAEFL,2BAAAA,IAACM,2BAAAA,kBAAA,EAAiB,QAAQ,gBAAA,CAAiB;AAAA,IAC3CN,2BAAAA;AAAAA,MAACO,qBAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAASC,oBAAAA,iBAAiB,eAAe,WAAW,CAAC;AAAA,QACrD,gBAAgBC,oBAAAA,UAAU,eAAe,oBAAoB,GAAGC,oBAAAA,wBAAwB;AAAA,QACvF,GAAI,OAAO,eAAe,qBAAqB,MAAM,WAClD,EAAE,iBAAiB,eAAe,qBAAqB,EAAA,IACvD,CAAA;AAAA,QACH,GAAI,OAAO,eAAe,WAAW,MAAM,WAAW,EAAE,WAAW,eAAe,WAAW,EAAA,IAAM,CAAA;AAAA,QAEnG,UAAA,UACCV,2BAAAA;AAAAA,UAACW,4BAAAA;AAAAA,UAAA;AAAA,YACC,QAAQ;AAAA,YACR,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAAA,QAAA,IAGF;AAAA,MAAA;AAAA,IAAA;AAAA,IAGH,6CACE,KAAA,EAAE,WAAWT,MAAAA,GAAG,yBAAyBE,kCAAe,aAAa,CAAC,GAAG,UAAA;AAAA,MAAA;AAAA,MACtD,YAAY,KAAA;AAAA,MAAO;AAAA,IAAA,EAAA,CACvC;AAAA,EAAA,EAAA,CAEJ,EAAA,CACF;AAEJ;AAEA,MAAM,eAAqD;AAAA,EACzD,EAAE,OAAO,MAAM,OAAO,cAAA;AAAA,EACtB,EAAE,OAAO,MAAM,OAAO,QAAA;AAAA,EACtB,EAAE,OAAO,MAAM,OAAO,SAAA;AAAA,EACtB,EAAE,OAAO,MAAM,OAAO,QAAA;AAAA,EACtB,EAAE,OAAO,MAAM,OAAO,cAAA;AACxB;AAEA,MAAM,iBAAyD;AAAA,EAC7D,EAAE,OAAO,WAAW,OAAO,UAAA;AAAA,EAC3B,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,EAC1B,EAAE,OAAO,cAAc,OAAO,aAAA;AAChC;AAEA,MAAM,eAAqD;AAAA,EACzD,EAAE,OAAO,UAAU,OAAO,eAAA;AAAA,EAC1B,EAAE,OAAO,kBAAkB,OAAO,iBAAA;AAAA,EAClC,EAAE,OAAO,YAAY,OAAO,0BAAA;AAC9B;AAMA,SAAS,gBAAgB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAUG;AACD,QAAM,eAAe,YAAY,KAAA,MAAW;AAC5C,SACEJ,2BAAAA;AAAAA,IAACY,aAAAA;AAAAA,IAAA;AAAA,MACC,OAAM;AAAA,MACN,WAAU;AAAA,MACV,WAAU;AAAA,MACV,SACEZ,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAW;AAAA,UACX,iBAAc;AAAA,UACd,WAAWE,MAAAA;AAAAA,YACT;AAAA,YACA,eAAe,iBAAiB;AAAA,UAAA;AAAA,UAGlC,UAAAF,2BAAAA,IAACa,WAAA,EAAK,MAAMC,eAAAA,gBAAgB,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAInD,UAAA,CAAC,cACAC,2BAAAA,KAAAC,WAAAA,UAAA,EACG,UAAA;AAAA,QAAA,gBAAgBhB,2BAAAA,IAAC,OAAA,EAAI,WAAU,oBAC9B,UAAAA,2BAAAA,IAACK,0BAAAA,mBAAgB,OAAO,aAAa,UAAU,eAAA,CAAgB,EAAA,CACjE;AAAA,QACAL,2BAAAA,IAAC,mBAAA,EAAkB,OAAM,OAAA,CAAO;AAAA,QAC/B,aAAa,IAAI,CAAC,QACjBA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,OAAO,IAAI;AAAA,YACX,UAAU,IAAI,UAAU;AAAA,YACxB,UAAU,MAAM;AACd,2BAAa,IAAI,KAAK;AACtB,wBAAA;AAAA,YACF;AAAA,UAAA;AAAA,UANK,IAAI;AAAA,QAAA,CAQZ;AAAA,QACDA,2BAAAA,IAAC,mBAAA,EAAkB,OAAM,SAAA,CAAS;AAAA,QACjC,eAAe,IAAI,CAAC,QACnBA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,OAAO,IAAI;AAAA,YACX,UAAU,IAAI,UAAU;AAAA,YACxB,UAAU,MAAM;AACd,6BAAe,IAAI,KAAK;AACxB,wBAAA;AAAA,YACF;AAAA,UAAA;AAAA,UANK,IAAI;AAAA,QAAA,CAQZ;AAAA,QACDA,2BAAAA,IAAC,mBAAA,EAAkB,OAAM,OAAA,CAAO;AAAA,QAC/B,aAAa,IAAI,CAAC,QACjBA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YAEC,OAAO,IAAI;AAAA,YACX,UAAU,IAAI,UAAU;AAAA,YACxB,UAAU,MAAM;AACd,2BAAa,IAAI,KAAK;AACtB,wBAAA;AAAA,YACF;AAAA,UAAA;AAAA,UANK,IAAI;AAAA,QAAA,CAQZ;AAAA,MAAA,EAAA,CACH;AAAA,IAAA;AAAA,EAAA;AAIR;AAEA,SAAS,kBAAkB,EAAE,SAA4B;AACvD,SACEA,2BAAAA,IAAC,OAAA,EAAI,WAAU,0FACZ,UAAA,OACH;AAEJ;AAEA,SAAS,eAAe,EAAE,OAAO,UAAU,YAAwE;AACjH,SACEe,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,MAAK;AAAA,MACL,gBAAc;AAAA,MACd,WAAU;AAAA,MACV,SAAS;AAAA,MAET,UAAA;AAAA,QAAAf,2BAAAA,IAAC,QAAA,EAAK,WAAU,sCACb,UAAA,YAAYA,2BAAAA,IAACa,KAAAA,QAAK,MAAMI,QAAAA,SAAS,WAAU,UAAA,CAAU,EAAA,CACxD;AAAA,QACC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP;;"}
|
|
1
|
+
{"version":3,"file":"JsonSchemaForm.cjs","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(prefs.debug ? { debug: true } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n debug={prefs.debug === true}\n onToggleDebug={() => applyPrefs({ ...prefs, debug: !prefs.debug })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n debug,\n onToggleDebug,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n debug: boolean;\n onToggleDebug: () => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\" || debug;\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Debug\" />\n <PreferenceItem\n role=\"menuitemcheckbox\"\n label=\"Show hidden fields & sources\"\n selected={debug}\n onSelect={() => {\n onToggleDebug();\n closeMenu();\n }}\n />\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({\n label,\n selected,\n onSelect,\n role = \"menuitemradio\",\n}: {\n label: string;\n selected: boolean;\n onSelect: () => void;\n role?: \"menuitemradio\" | \"menuitemcheckbox\";\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":["DEFAULT_FORM_SIZE","DEFAULT_PREFERENCES_STORAGE_KEY","useState","readPreferences","writePreferences","useMemo","rehydrateRefs","applySchemaDefaults","unmatchedFormErrors","useEffect","renderApi","renderObjectFields","jsx","FormLookupProvider","cn","fieldInnerGapClass","labelSizeClass","FormFieldFilter","FormErrorSummary","FieldsGrid","normalizeColumns","cssLength","DEFAULT_COLUMN_MIN_WIDTH","DiscriminatedForm","DropdownMenu","Icon","UiEllipsisBold","jsxs","Fragment","UiCheck"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonSchemaForm.d.ts","sourceRoot":"","sources":["../../src/components/JsonSchemaForm.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAc,mBAAmB,EAAiB,MAAM,0BAA0B,CAAC;AAoC/F,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAiB,EACjB,MAAW,EACX,QAAgB,EAChB,MAAc,EACd,MAAM,EACN,IAAwB,EACxB,QAAQ,EACR,kBAA0B,EAC1B,SAAiB,EACjB,QAAgB,EAChB,UAAU,EACV,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,IAAI,EACJ,mBAA0B,EAC1B,UAAU,EACV,kBAAyB,EACzB,qBAAuD,EACvD,aAAa,EACb,mBAAmB,EACnB,aAAoB,GACrB,EAAE,mBAAmB,+
|
|
1
|
+
{"version":3,"file":"JsonSchemaForm.d.ts","sourceRoot":"","sources":["../../src/components/JsonSchemaForm.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAc,mBAAmB,EAAiB,MAAM,0BAA0B,CAAC;AAoC/F,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,YAAiB,EACjB,MAAW,EACX,QAAgB,EAChB,MAAc,EACd,MAAM,EACN,IAAwB,EACxB,QAAQ,EACR,kBAA0B,EAC1B,SAAiB,EACjB,QAAgB,EAChB,UAAU,EACV,aAAqB,EACrB,KAAK,EACL,GAAG,EACH,IAAI,EACJ,mBAA0B,EAC1B,UAAU,EACV,kBAAyB,EACzB,qBAAuD,EACvD,aAAa,EACb,mBAAmB,EACnB,aAAoB,GACrB,EAAE,mBAAmB,+BAiJrB"}
|
|
@@ -119,7 +119,8 @@ function JsonSchemaForm({
|
|
|
119
119
|
render: renderApi,
|
|
120
120
|
...expressionEvaluator ? { expressionEvaluator } : {},
|
|
121
121
|
...idPrefix ? { idPrefix } : {},
|
|
122
|
-
...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}
|
|
122
|
+
...fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {},
|
|
123
|
+
...prefs.debug ? { debug: true } : {}
|
|
123
124
|
};
|
|
124
125
|
const discKey = typeof resolvedSchema["x-discriminator"] === "string" ? resolvedSchema["x-discriminator"] : void 0;
|
|
125
126
|
const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === "");
|
|
@@ -137,7 +138,9 @@ function JsonSchemaForm({
|
|
|
137
138
|
onFilterChange: setFieldFilter,
|
|
138
139
|
onSelectSize: (next) => applyPrefs({ ...prefs, size: next }),
|
|
139
140
|
onSelectLayout: (next) => applyPrefs({ ...prefs, layoutMode: next }),
|
|
140
|
-
onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next })
|
|
141
|
+
onSelectSort: (next) => applyPrefs({ ...prefs, sortMode: next }),
|
|
142
|
+
debug: prefs.debug === true,
|
|
143
|
+
onToggleDebug: () => applyPrefs({ ...prefs, debug: !prefs.debug })
|
|
141
144
|
}
|
|
142
145
|
),
|
|
143
146
|
title && /* @__PURE__ */ jsx("h3", { className: cn("font-semibold", labelSizeClass[effectiveSize]), children: title }),
|
|
@@ -197,9 +200,11 @@ function PreferencesMenu({
|
|
|
197
200
|
onFilterChange,
|
|
198
201
|
onSelectSize,
|
|
199
202
|
onSelectLayout,
|
|
200
|
-
onSelectSort
|
|
203
|
+
onSelectSort,
|
|
204
|
+
debug,
|
|
205
|
+
onToggleDebug
|
|
201
206
|
}) {
|
|
202
|
-
const filterActive = fieldFilter.trim() !== "";
|
|
207
|
+
const filterActive = fieldFilter.trim() !== "" || debug;
|
|
203
208
|
return /* @__PURE__ */ jsx(
|
|
204
209
|
DropdownMenu,
|
|
205
210
|
{
|
|
@@ -259,7 +264,20 @@ function PreferencesMenu({
|
|
|
259
264
|
}
|
|
260
265
|
},
|
|
261
266
|
opt.value
|
|
262
|
-
))
|
|
267
|
+
)),
|
|
268
|
+
/* @__PURE__ */ jsx(PreferenceSection, { title: "Debug" }),
|
|
269
|
+
/* @__PURE__ */ jsx(
|
|
270
|
+
PreferenceItem,
|
|
271
|
+
{
|
|
272
|
+
role: "menuitemcheckbox",
|
|
273
|
+
label: "Show hidden fields & sources",
|
|
274
|
+
selected: debug,
|
|
275
|
+
onSelect: () => {
|
|
276
|
+
onToggleDebug();
|
|
277
|
+
closeMenu();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
)
|
|
263
281
|
] })
|
|
264
282
|
}
|
|
265
283
|
);
|
|
@@ -267,12 +285,17 @@ function PreferencesMenu({
|
|
|
267
285
|
function PreferenceSection({ title }) {
|
|
268
286
|
return /* @__PURE__ */ jsx("div", { className: "px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: title });
|
|
269
287
|
}
|
|
270
|
-
function PreferenceItem({
|
|
288
|
+
function PreferenceItem({
|
|
289
|
+
label,
|
|
290
|
+
selected,
|
|
291
|
+
onSelect,
|
|
292
|
+
role = "menuitemradio"
|
|
293
|
+
}) {
|
|
271
294
|
return /* @__PURE__ */ jsxs(
|
|
272
295
|
"button",
|
|
273
296
|
{
|
|
274
297
|
type: "button",
|
|
275
|
-
role
|
|
298
|
+
role,
|
|
276
299
|
"aria-checked": selected,
|
|
277
300
|
className: "flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground",
|
|
278
301
|
onClick: onSelect,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsonSchemaForm.js","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\";\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({ label, selected, onSelect }: { label: string; selected: boolean; onSelect: () => void }) {\n return (\n <button\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JsonSchemaForm.js","sources":["../../src/components/JsonSchemaForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiEllipsisBold } from \"../icons\";\nimport { FormFieldFilter } from \"./json-schema-form-filter-input\";\nimport { DropdownMenu } from \"../overlay/DropdownMenu\";\nimport { FieldsGrid } from \"./json-schema-form-layout\";\nimport { FormErrorSummary } from \"./json-schema-form-error-display\";\nimport { unmatchedFormErrors } from \"./json-schema-form-errors\";\nimport { FormLookupProvider } from \"./FormLookupProvider\";\nimport { DiscriminatedForm } from \"./json-schema-form-discriminator\";\nimport { rehydrateRefs } from \"./json-schema-form-refs\";\nimport { renderApi, renderObjectFields } from \"./json-schema-form-render\";\nimport { applySchemaDefaults } from \"./json-schema-form-defaults\";\nimport {\n cssLength,\n DEFAULT_COLUMN_MIN_WIDTH,\n normalizeColumns,\n} from \"./json-schema-form-utils\";\nimport { DEFAULT_FORM_SIZE, fieldInnerGapClass, labelSizeClass, type FormSize } from \"./json-schema-form-size\";\nimport {\n DEFAULT_PREFERENCES_STORAGE_KEY,\n readPreferences,\n writePreferences,\n type FormPreferences,\n type LayoutMode,\n type SortMode,\n} from \"./json-schema-form-preferences\";\nimport type { FormLayout, JsonSchemaFormProps, RenderContext } from \"./json-schema-form-types\";\n\nconst DEFAULT_LABEL_MAX_WIDTH = \"40ch\";\nconst DEFAULT_VALUE_MAX_WIDTH = \"600px\";\n\n// resolveFormLayout maps the `layout`/`inline` props plus an optional menu-driven\n// `modeOverride` to a single resolved FormLayout. An explicit `layout` sets the\n// base; `inline` is the shorthand for it; `modeOverride` (from the preferences\n// menu) wins over both but only flips the mode — width caps from `layout` are\n// preserved. Both modes fill valueMaxWidth (inline value column / stacked\n// label+value stack); the label cap only applies inline.\nfunction resolveFormLayout(\n layout: FormLayout | undefined,\n inline: boolean,\n modeOverride: LayoutMode | undefined,\n): FormLayout {\n const baseMode = layout?.mode ?? (inline ? \"inline\" : \"stacked\");\n const mode = modeOverride ?? baseMode;\n const valueMaxWidth = layout?.valueMaxWidth ?? DEFAULT_VALUE_MAX_WIDTH;\n // `help` is orthogonal to mode, so it survives a menu-driven mode flip.\n const help = layout?.help ? { help: layout.help } : {};\n if (mode === \"properties\") return { ...layout, mode, ...help };\n if (mode !== \"inline\") return { mode: \"stacked\", valueMaxWidth, ...help };\n return {\n mode: \"inline\",\n labelMaxWidth: layout?.labelMaxWidth ?? DEFAULT_LABEL_MAX_WIDTH,\n valueMaxWidth,\n ...help,\n };\n}\n\n// JsonSchemaForm renders an object subschema as a form: one control per\n// (effective) property. It resolves if/then conditionals internally and recurses\n// through array items and object/map values; every other behaviour is layered on\n// by the pre/post extension functions the consumer supplies. The component holds\n// no domain knowledge.\nexport function JsonSchemaForm({\n schema,\n value,\n onChange,\n rootValue,\n onRootChange,\n instancePath = \"\",\n errors = [],\n readOnly = false,\n inline = false,\n layout,\n size = DEFAULT_FORM_SIZE,\n idPrefix,\n hideReadOnlyFields = false,\n hideEmpty = false,\n autoSave = false,\n hiddenKeys,\n requiredFirst = false,\n title,\n pre,\n post,\n showPreferencesMenu = true,\n showFilter,\n persistPreferences = true,\n preferencesStorageKey = DEFAULT_PREFERENCES_STORAGE_KEY,\n lookupFetcher,\n expressionEvaluator,\n applyDefaults = true,\n}: JsonSchemaFormProps) {\n // When the menu is hidden, never touch localStorage and start from an empty\n // override so behaviour is identical to before this feature existed.\n const [prefs, setPrefs] = useState<FormPreferences>(() =>\n showPreferencesMenu && persistPreferences ? readPreferences(preferencesStorageKey) : {},\n );\n // The field filter is transient view state (a \"find\" over the fields), never\n // persisted — reopening the form should never start with fields hidden.\n const [fieldFilter, setFieldFilter] = useState(\"\");\n\n const effectiveSize = prefs.size ?? size;\n const resolvedLayout = resolveFormLayout(layout, inline, prefs.layoutMode);\n const filterVisible = showFilter ?? (showPreferencesMenu && resolvedLayout.mode === \"properties\");\n // The `requiredFirst` prop sets the base sort; a menu selection overrides it.\n const effectiveSortMode = prefs.sortMode ?? (requiredFirst ? \"required-first\" : \"schema\");\n\n const applyPrefs = (next: FormPreferences) => {\n setPrefs(next);\n if (persistPreferences) writePreferences(preferencesStorageKey, next);\n };\n\n // A bundled schema (components under `$defs`, referenced by local `#/$defs`\n // pointers) is resolved once into a self-contained tree the renderer walks\n // directly; a non-bundled schema passes through untouched.\n const resolvedSchema = useMemo(() => rehydrateRefs(schema), [schema]);\n // Suppressing at the value (not only at the commit effect below) is deliberate:\n // renderObjectFields spreads `effectiveValue` when a single field changes, so a\n // render-only application would still leak the defaults on the first edit.\n const effectiveValue = useMemo(\n () => (applyDefaults ? applySchemaDefaults(resolvedSchema, value) : value),\n [applyDefaults, resolvedSchema, value],\n );\n const preExtensions = pre ?? [];\n const unmatchedErrors = useMemo(\n () =>\n unmatchedFormErrors({\n schema: resolvedSchema,\n value: effectiveValue,\n errors,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n pre: preExtensions,\n rootValue: rootValue ?? effectiveValue,\n instancePath,\n ...(hiddenKeys ? { hiddenKeys } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n }),\n [effectiveValue, errors, expressionEvaluator, fieldFilter, hiddenKeys, hideEmpty, hideReadOnlyFields, instancePath, preExtensions, readOnly, resolvedSchema, rootValue],\n );\n // Defaults are part of the submitted form value, not only presentation. This\n // is especially important for required discriminator fields whose default\n // selects an if/then branch.\n useEffect(() => {\n if (!readOnly && effectiveValue !== value) onChange(effectiveValue);\n }, [effectiveValue, onChange, readOnly, value]);\n\n const ctx: RenderContext = {\n readOnly,\n viewOnly: readOnly,\n hideReadOnlyFields,\n hideEmpty,\n autoSave,\n layout: resolvedLayout,\n size: effectiveSize,\n sortMode: effectiveSortMode,\n pre: preExtensions,\n post: post ?? [],\n rootValue: rootValue ?? effectiveValue,\n onRootChange: onRootChange ?? onChange,\n instancePath,\n errors,\n depth: 0,\n render: renderApi,\n ...(expressionEvaluator ? { expressionEvaluator } : {}),\n ...(idPrefix ? { idPrefix } : {}),\n ...(fieldFilter.trim() ? { fieldFilter: fieldFilter.trim() } : {}),\n ...(prefs.debug ? { debug: true } : {}),\n };\n // A schema may name a discriminator property whose value selects a \"kind\"; the\n // form then runs a two-phase pick-then-fill flow (see DiscriminatedForm).\n const discKey = typeof resolvedSchema[\"x-discriminator\"] === \"string\" ? resolvedSchema[\"x-discriminator\"] : undefined;\n const inPickerPhase = discKey != null && (effectiveValue[discKey] == null || effectiveValue[discKey] === \"\");\n\n const objectRows = discKey\n ? null\n : renderObjectFields(resolvedSchema, effectiveValue, onChange, ctx, hiddenKeys ? { hiddenKeys } : undefined);\n const noMatches = objectRows != null && objectRows.length === 0 && fieldFilter.trim() !== \"\";\n\n return (\n <FormLookupProvider {...(lookupFetcher ? { fetcher: lookupFetcher } : {})}>\n <div data-json-schema-form className={cn(\"relative flex flex-col\", fieldInnerGapClass[effectiveSize])}>\n {showPreferencesMenu && !inPickerPhase && (\n <PreferencesMenu\n size={effectiveSize}\n layoutMode={resolvedLayout.mode}\n sortMode={effectiveSortMode}\n fieldFilter={fieldFilter}\n filterInMenu={!filterVisible}\n onFilterChange={setFieldFilter}\n onSelectSize={(next) => applyPrefs({ ...prefs, size: next })}\n onSelectLayout={(next) => applyPrefs({ ...prefs, layoutMode: next })}\n onSelectSort={(next) => applyPrefs({ ...prefs, sortMode: next })}\n debug={prefs.debug === true}\n onToggleDebug={() => applyPrefs({ ...prefs, debug: !prefs.debug })}\n />\n )}\n {title && <h3 className={cn(\"font-semibold\", labelSizeClass[effectiveSize])}>{title}</h3>}\n {filterVisible && !inPickerPhase && (\n <div className=\"max-w-md pr-9\">\n <FormFieldFilter value={fieldFilter} onChange={setFieldFilter} />\n </div>\n )}\n <FormErrorSummary errors={unmatchedErrors} />\n <FieldsGrid\n layout={resolvedLayout}\n size={effectiveSize}\n columns={normalizeColumns(resolvedSchema[\"x-columns\"])}\n columnMinWidth={cssLength(resolvedSchema[\"x-column-min-width\"], DEFAULT_COLUMN_MIN_WIDTH)}\n {...(typeof resolvedSchema[\"x-columns-max-width\"] === \"string\"\n ? { columnsMaxWidth: resolvedSchema[\"x-columns-max-width\"] }\n : {})}\n {...(typeof resolvedSchema[\"x-classes\"] === \"string\" ? { className: resolvedSchema[\"x-classes\"] } : {})}\n >\n {discKey ? (\n <DiscriminatedForm\n schema={resolvedSchema}\n value={effectiveValue}\n onChange={onChange}\n ctx={ctx}\n discKey={discKey}\n />\n ) : (\n objectRows\n )}\n </FieldsGrid>\n {noMatches && (\n <p className={cn(\"text-muted-foreground\", labelSizeClass[effectiveSize])}>\n No fields match “{fieldFilter.trim()}”.\n </p>\n )}\n </div>\n </FormLookupProvider>\n );\n}\n\nconst SIZE_OPTIONS: { value: FormSize; label: string }[] = [\n { value: \"xs\", label: \"Extra small\" },\n { value: \"sm\", label: \"Small\" },\n { value: \"md\", label: \"Medium\" },\n { value: \"lg\", label: \"Large\" },\n { value: \"xl\", label: \"Extra large\" },\n];\n\nconst LAYOUT_OPTIONS: { value: LayoutMode; label: string }[] = [\n { value: \"stacked\", label: \"Stacked\" },\n { value: \"inline\", label: \"Inline\" },\n { value: \"properties\", label: \"Properties\" },\n];\n\nconst SORT_OPTIONS: { value: SortMode; label: string }[] = [\n { value: \"schema\", label: \"Schema order\" },\n { value: \"required-first\", label: \"Required first\" },\n { value: \"priority\", label: \"Required & filled first\" },\n];\n\n// PreferencesMenu is the compact top-right ellipsis menu controlling this form's\n// size, layout, sort, and a live field filter. Selecting an option fires the\n// matching callback and closes the menu; typing in the filter updates fields\n// live without closing. The parent decides whether to persist.\nfunction PreferencesMenu({\n size,\n layoutMode,\n sortMode,\n fieldFilter,\n filterInMenu,\n onFilterChange,\n onSelectSize,\n onSelectLayout,\n onSelectSort,\n debug,\n onToggleDebug,\n}: {\n size: FormSize;\n layoutMode: LayoutMode;\n sortMode: SortMode;\n fieldFilter: string;\n filterInMenu: boolean;\n onFilterChange: (value: string) => void;\n onSelectSize: (size: FormSize) => void;\n onSelectLayout: (mode: LayoutMode) => void;\n onSelectSort: (mode: SortMode) => void;\n debug: boolean;\n onToggleDebug: () => void;\n}) {\n const filterActive = fieldFilter.trim() !== \"\" || debug;\n return (\n <DropdownMenu\n align=\"right\"\n menuLabel=\"Form display options\"\n className=\"absolute right-0 top-0 z-10\"\n trigger={\n <button\n type=\"button\"\n aria-label=\"Form display options\"\n aria-haspopup=\"menu\"\n className={cn(\n \"inline-flex h-7 w-7 items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n filterActive ? \"text-primary\" : \"text-muted-foreground hover:text-foreground\",\n )}\n >\n <Icon icon={UiEllipsisBold} className=\"text-lg\" />\n </button>\n }\n >\n {(closeMenu) => (\n <>\n {filterInMenu && <div className=\"px-2 pb-1.5 pt-1\">\n <FormFieldFilter value={fieldFilter} onChange={onFilterChange} />\n </div>}\n <PreferenceSection title=\"Size\" />\n {SIZE_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === size}\n onSelect={() => {\n onSelectSize(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Layout\" />\n {LAYOUT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === layoutMode}\n onSelect={() => {\n onSelectLayout(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Sort\" />\n {SORT_OPTIONS.map((opt) => (\n <PreferenceItem\n key={opt.value}\n label={opt.label}\n selected={opt.value === sortMode}\n onSelect={() => {\n onSelectSort(opt.value);\n closeMenu();\n }}\n />\n ))}\n <PreferenceSection title=\"Debug\" />\n <PreferenceItem\n role=\"menuitemcheckbox\"\n label=\"Show hidden fields & sources\"\n selected={debug}\n onSelect={() => {\n onToggleDebug();\n closeMenu();\n }}\n />\n </>\n )}\n </DropdownMenu>\n );\n}\n\nfunction PreferenceSection({ title }: { title: string }) {\n return (\n <div className=\"px-3 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground\">\n {title}\n </div>\n );\n}\n\nfunction PreferenceItem({\n label,\n selected,\n onSelect,\n role = \"menuitemradio\",\n}: {\n label: string;\n selected: boolean;\n onSelect: () => void;\n role?: \"menuitemradio\" | \"menuitemcheckbox\";\n}) {\n return (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n className=\"flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs text-popover-foreground hover:bg-accent hover:text-accent-foreground\"\n onClick={onSelect}\n >\n <span className=\"flex w-3.5 shrink-0 justify-center\">\n {selected && <Icon icon={UiCheck} className=\"text-xs\" />}\n </span>\n {label}\n </button>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,8 @@ function SegmentedControl({
|
|
|
19
19
|
"aria-label": ariaLabel
|
|
20
20
|
}) {
|
|
21
21
|
const btnRefs = react.useRef([]);
|
|
22
|
+
const markerIdBase = react.useId();
|
|
23
|
+
const hasSelection = options.some((option) => option.id === value);
|
|
22
24
|
const move = (from, dir) => {
|
|
23
25
|
var _a;
|
|
24
26
|
const n = options.length;
|
|
@@ -47,6 +49,8 @@ function SegmentedControl({
|
|
|
47
49
|
),
|
|
48
50
|
children: options.map((option, index) => {
|
|
49
51
|
const active = option.id === value;
|
|
52
|
+
const implied = !hasSelection && option.implied === true;
|
|
53
|
+
const markerId = option.marker ? `${markerIdBase}-marker-${index}` : void 0;
|
|
50
54
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
51
55
|
"button",
|
|
52
56
|
{
|
|
@@ -56,9 +60,11 @@ function SegmentedControl({
|
|
|
56
60
|
type: "button",
|
|
57
61
|
role: "radio",
|
|
58
62
|
"aria-checked": active,
|
|
63
|
+
"aria-describedby": markerId,
|
|
64
|
+
"data-implied": implied ? "true" : void 0,
|
|
59
65
|
title: option.title,
|
|
60
66
|
disabled: option.disabled,
|
|
61
|
-
tabIndex: active ? 0 : -1,
|
|
67
|
+
tabIndex: active || implied ? 0 : -1,
|
|
62
68
|
onClick: () => !option.disabled && onChange(option.id),
|
|
63
69
|
onKeyDown: (e) => {
|
|
64
70
|
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
@@ -76,7 +82,7 @@ function SegmentedControl({
|
|
|
76
82
|
size === "lg" && "rounded-lg text-left",
|
|
77
83
|
option.description ? "whitespace-normal" : "whitespace-nowrap",
|
|
78
84
|
SIZE_CLASSES[size],
|
|
79
|
-
active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
|
|
85
|
+
active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : implied ? size === "lg" ? "border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm" : "border-dashed border-primary/60 text-foreground hover:bg-background/60" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
|
|
80
86
|
active && option.activeClassName
|
|
81
87
|
),
|
|
82
88
|
children: [
|
|
@@ -99,7 +105,18 @@ function SegmentedControl({
|
|
|
99
105
|
size === "lg" && "flex flex-col items-start text-left leading-tight"
|
|
100
106
|
),
|
|
101
107
|
children: [
|
|
102
|
-
/* @__PURE__ */ jsxRuntime.
|
|
108
|
+
option.marker ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label }),
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
111
|
+
"span",
|
|
112
|
+
{
|
|
113
|
+
id: markerId,
|
|
114
|
+
"aria-hidden": "true",
|
|
115
|
+
className: "shrink-0 text-[11px] font-normal opacity-70",
|
|
116
|
+
children: option.marker
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: option.label }),
|
|
103
120
|
option.description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
104
121
|
"span",
|
|
105
122
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.cjs","sources":["../../src/components/SegmentedControl.tsx"],"sourcesContent":["import { useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\n\nexport type SegmentedSize = \"sm\" | \"md\" | \"lg\";\n\nexport type SegmentedOption<T extends string = string> = {\n /** Stable value emitted on selection. */\n id: T;\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (imported `Ui*` component or runtime name). */\n icon?: string | StaticIconComponent;\n /** Classes applied to the leading icon. */\n iconClassName?: string;\n /** Classes applied to this segment only while selected. */\n activeClassName?: string;\n /** Optional secondary line, used by larger card-like segmented controls. */\n description?: ReactNode;\n /** Native title attribute. */\n title?: string;\n /** Disable this segment. */\n disabled?: boolean;\n};\n\nexport type SegmentedControlProps<T extends string = string> = {\n /** Currently selected option id. */\n value: T;\n /** Mutually-exclusive options rendered left to right. */\n options: SegmentedOption<T>[];\n /** Called with the newly selected id. */\n onChange: (id: T) => void;\n /** Control size. `md` (default) matches form controls; `sm` is denser and `lg` is card-like. */\n size?: SegmentedSize;\n /** Allows segments to wrap instead of overflowing horizontally. */\n wrap?: boolean;\n /** Accessible group label. */\n \"aria-label\"?: string;\n /** Classes applied to the track. */\n className?: string;\n};\n\nconst SIZE_CLASSES: Record<SegmentedSize, string> = {\n sm: \"text-xs px-density-2 py-density-1 gap-1\",\n md: \"h-full px-control-px text-sm gap-1.5\",\n lg: \"min-h-[4.25rem] min-w-44 flex-1 px-density-3 py-density-3 gap-density-2 text-sm\",\n};\n\n/**\n * Single-select toggle group (the Gavel `Segmented` \"Mine / All / Bots\"\n * pattern). A muted track holds mutually-exclusive segments; the active\n * segment lifts onto the card surface. Built on clicky tokens so it inherits\n * dark-mode and density. Use for small, flat choice sets — reach for `Select`\n * when the option count grows.\n */\nexport function SegmentedControl<T extends string = string>({\n value,\n options,\n onChange,\n size = \"md\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n const btnRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const move = (from: number, dir: 1 | -1) => {\n const n = options.length;\n let i = from;\n for (let step = 0; step < n; step++) {\n i = (i + dir + n) % n;\n const opt = options[i];\n if (opt && !opt.disabled) {\n onChange(opt.id);\n btnRefs.current[i]?.focus();\n return;\n }\n }\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className={cn(\n \"inline-flex items-center rounded-md bg-muted p-0.5\",\n size === \"md\" && \"h-control-h\",\n size === \"lg\" && \"gap-density-2 bg-transparent p-0\",\n wrap && \"flex-wrap\",\n className,\n )}\n >\n {options.map((option, index) => {\n const active = option.id === value;\n return (\n <button\n key={option.id}\n ref={(el) => {\n btnRefs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n title={option.title}\n disabled={option.disabled}\n tabIndex={active ? 0 : -1}\n onClick={() => !option.disabled && onChange(option.id)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(index, 1);\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(index, -1);\n }\n }}\n className={cn(\n \"inline-flex items-center rounded-[5px] border border-transparent font-medium transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"lg\" && \"rounded-lg text-left\",\n option.description ? \"whitespace-normal\" : \"whitespace-nowrap\",\n SIZE_CLASSES[size],\n active\n ? size === \"lg\"\n ? \"border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25\"\n : \"border-border bg-card text-foreground shadow-sm\"\n : size === \"lg\"\n ? \"border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm\"\n : \"text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground\",\n active && option.activeClassName,\n )}\n >\n {option.icon && (\n <Icon\n {...(typeof option.icon === \"string\"\n ? { name: option.icon }\n : { icon: option.icon })}\n className={cn(\n size === \"lg\" ? \"size-4 shrink-0\" : \"size-3.5 shrink-0\",\n size === \"lg\" &&\n (active ? \"text-primary\" : \"text-muted-foreground\"),\n option.iconClassName,\n )}\n />\n )}\n <span\n className={cn(\n \"min-w-0\",\n size === \"lg\" &&\n \"flex flex-col items-start text-left leading-tight\",\n )}\n >\n <span className=\"min-w-0 truncate\">{option.label}</span>\n {option.description && (\n <span\n className={cn(\n \"mt-0.5 max-w-56 whitespace-normal break-words text-[11px] font-normal leading-snug\",\n active\n ? \"text-muted-foreground\"\n : \"text-muted-foreground/80\",\n )}\n >\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["useRef","jsx","cn","jsxs","Icon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SegmentedControl.cjs","sources":["../../src/components/SegmentedControl.tsx"],"sourcesContent":["import { useId, useRef, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../data/Icon\";\n\nexport type SegmentedSize = \"sm\" | \"md\" | \"lg\";\n\nexport type SegmentedOption<T extends string = string> = {\n /** Stable value emitted on selection. */\n id: T;\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (imported `Ui*` component or runtime name). */\n icon?: string | StaticIconComponent;\n /** Classes applied to the leading icon. */\n iconClassName?: string;\n /** Classes applied to this segment only while selected. */\n activeClassName?: string;\n /** Optional secondary line, used by larger card-like segmented controls. */\n description?: ReactNode;\n /** Native title attribute. */\n title?: string;\n /**\n * Short muted tag rendered after the label (e.g. \"default\"). It is exposed to\n * assistive tech as the segment's accessible description, not its name.\n */\n marker?: string;\n /**\n * Render this segment as the implied choice while no option is selected (e.g.\n * a schema default the value has not been set to). It is outlined, not\n * filled, and stays `aria-checked=false` because nothing is selected.\n */\n implied?: boolean;\n /** Disable this segment. */\n disabled?: boolean;\n};\n\nexport type SegmentedControlProps<T extends string = string> = {\n /** Currently selected option id. */\n value: T;\n /** Mutually-exclusive options rendered left to right. */\n options: SegmentedOption<T>[];\n /** Called with the newly selected id. */\n onChange: (id: T) => void;\n /** Control size. `md` (default) matches form controls; `sm` is denser and `lg` is card-like. */\n size?: SegmentedSize;\n /** Allows segments to wrap instead of overflowing horizontally. */\n wrap?: boolean;\n /** Accessible group label. */\n \"aria-label\"?: string;\n /** Classes applied to the track. */\n className?: string;\n};\n\nconst SIZE_CLASSES: Record<SegmentedSize, string> = {\n sm: \"text-xs px-density-2 py-density-1 gap-1\",\n md: \"h-full px-control-px text-sm gap-1.5\",\n lg: \"min-h-[4.25rem] min-w-44 flex-1 px-density-3 py-density-3 gap-density-2 text-sm\",\n};\n\n/**\n * Single-select toggle group (the Gavel `Segmented` \"Mine / All / Bots\"\n * pattern). A muted track holds mutually-exclusive segments; the active\n * segment lifts onto the card surface. Built on clicky tokens so it inherits\n * dark-mode and density. Use for small, flat choice sets — reach for `Select`\n * when the option count grows.\n */\nexport function SegmentedControl<T extends string = string>({\n value,\n options,\n onChange,\n size = \"md\",\n wrap = false,\n className,\n \"aria-label\": ariaLabel,\n}: SegmentedControlProps<T>) {\n const btnRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const markerIdBase = useId();\n const hasSelection = options.some((option) => option.id === value);\n\n const move = (from: number, dir: 1 | -1) => {\n const n = options.length;\n let i = from;\n for (let step = 0; step < n; step++) {\n i = (i + dir + n) % n;\n const opt = options[i];\n if (opt && !opt.disabled) {\n onChange(opt.id);\n btnRefs.current[i]?.focus();\n return;\n }\n }\n };\n\n return (\n <div\n role=\"radiogroup\"\n aria-label={ariaLabel}\n className={cn(\n \"inline-flex items-center rounded-md bg-muted p-0.5\",\n size === \"md\" && \"h-control-h\",\n size === \"lg\" && \"gap-density-2 bg-transparent p-0\",\n wrap && \"flex-wrap\",\n className,\n )}\n >\n {options.map((option, index) => {\n const active = option.id === value;\n const implied = !hasSelection && option.implied === true;\n const markerId = option.marker ? `${markerIdBase}-marker-${index}` : undefined;\n return (\n <button\n key={option.id}\n ref={(el) => {\n btnRefs.current[index] = el;\n }}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-describedby={markerId}\n data-implied={implied ? \"true\" : undefined}\n title={option.title}\n disabled={option.disabled}\n tabIndex={active || implied ? 0 : -1}\n onClick={() => !option.disabled && onChange(option.id)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n move(index, 1);\n } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n move(index, -1);\n }\n }}\n className={cn(\n \"inline-flex items-center rounded-[5px] border border-transparent font-medium transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n size === \"lg\" && \"rounded-lg text-left\",\n option.description ? \"whitespace-normal\" : \"whitespace-nowrap\",\n SIZE_CLASSES[size],\n active\n ? size === \"lg\"\n ? \"border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25\"\n : \"border-border bg-card text-foreground shadow-sm\"\n : implied\n ? size === \"lg\"\n ? \"border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm\"\n : \"border-dashed border-primary/60 text-foreground hover:bg-background/60\"\n : size === \"lg\"\n ? \"border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm\"\n : \"text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground\",\n active && option.activeClassName,\n )}\n >\n {option.icon && (\n <Icon\n {...(typeof option.icon === \"string\"\n ? { name: option.icon }\n : { icon: option.icon })}\n className={cn(\n size === \"lg\" ? \"size-4 shrink-0\" : \"size-3.5 shrink-0\",\n size === \"lg\" &&\n (active ? \"text-primary\" : \"text-muted-foreground\"),\n option.iconClassName,\n )}\n />\n )}\n <span\n className={cn(\n \"min-w-0\",\n size === \"lg\" &&\n \"flex flex-col items-start text-left leading-tight\",\n )}\n >\n {option.marker ? (\n <span className=\"inline-flex min-w-0 max-w-full items-baseline gap-1\">\n <span className=\"min-w-0 truncate\">{option.label}</span>\n <span\n id={markerId}\n aria-hidden=\"true\"\n className=\"shrink-0 text-[11px] font-normal opacity-70\"\n >\n {option.marker}\n </span>\n </span>\n ) : (\n <span className=\"min-w-0 truncate\">{option.label}</span>\n )}\n {option.description && (\n <span\n className={cn(\n \"mt-0.5 max-w-56 whitespace-normal break-words text-[11px] font-normal leading-snug\",\n active\n ? \"text-muted-foreground\"\n : \"text-muted-foreground/80\",\n )}\n >\n {option.description}\n </span>\n )}\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["useRef","useId","jsx","cn","jsxs","Icon"],"mappings":"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"}
|
|
@@ -16,6 +16,17 @@ export type SegmentedOption<T extends string = string> = {
|
|
|
16
16
|
description?: ReactNode;
|
|
17
17
|
/** Native title attribute. */
|
|
18
18
|
title?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Short muted tag rendered after the label (e.g. "default"). It is exposed to
|
|
21
|
+
* assistive tech as the segment's accessible description, not its name.
|
|
22
|
+
*/
|
|
23
|
+
marker?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Render this segment as the implied choice while no option is selected (e.g.
|
|
26
|
+
* a schema default the value has not been set to). It is outlined, not
|
|
27
|
+
* filled, and stays `aria-checked=false` because nothing is selected.
|
|
28
|
+
*/
|
|
29
|
+
implied?: boolean;
|
|
19
30
|
/** Disable this segment. */
|
|
20
31
|
disabled?: boolean;
|
|
21
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../src/components/SegmentedControl.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../src/components/SegmentedControl.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IACvD,yCAAyC;IACzC,EAAE,EAAE,CAAC,CAAC;IACN,qBAAqB;IACrB,KAAK,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,IAAI;IAC7D,oCAAoC;IACpC,KAAK,EAAE,CAAC,CAAC;IACT,yDAAyD;IACzD,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,gGAAgG;IAChG,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,mEAAmE;IACnE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAQF;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,EAC1D,KAAK,EACL,OAAO,EACP,QAAQ,EACR,IAAW,EACX,IAAY,EACZ,SAAS,EACT,YAAY,EAAE,SAAS,GACxB,EAAE,qBAAqB,CAAC,CAAC,CAAC,+BAoI1B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useRef } from "react";
|
|
2
|
+
import { useRef, useId } from "react";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { Icon } from "../data/Icon.js";
|
|
5
5
|
const SIZE_CLASSES = {
|
|
@@ -17,6 +17,8 @@ function SegmentedControl({
|
|
|
17
17
|
"aria-label": ariaLabel
|
|
18
18
|
}) {
|
|
19
19
|
const btnRefs = useRef([]);
|
|
20
|
+
const markerIdBase = useId();
|
|
21
|
+
const hasSelection = options.some((option) => option.id === value);
|
|
20
22
|
const move = (from, dir) => {
|
|
21
23
|
var _a;
|
|
22
24
|
const n = options.length;
|
|
@@ -45,6 +47,8 @@ function SegmentedControl({
|
|
|
45
47
|
),
|
|
46
48
|
children: options.map((option, index) => {
|
|
47
49
|
const active = option.id === value;
|
|
50
|
+
const implied = !hasSelection && option.implied === true;
|
|
51
|
+
const markerId = option.marker ? `${markerIdBase}-marker-${index}` : void 0;
|
|
48
52
|
return /* @__PURE__ */ jsxs(
|
|
49
53
|
"button",
|
|
50
54
|
{
|
|
@@ -54,9 +58,11 @@ function SegmentedControl({
|
|
|
54
58
|
type: "button",
|
|
55
59
|
role: "radio",
|
|
56
60
|
"aria-checked": active,
|
|
61
|
+
"aria-describedby": markerId,
|
|
62
|
+
"data-implied": implied ? "true" : void 0,
|
|
57
63
|
title: option.title,
|
|
58
64
|
disabled: option.disabled,
|
|
59
|
-
tabIndex: active ? 0 : -1,
|
|
65
|
+
tabIndex: active || implied ? 0 : -1,
|
|
60
66
|
onClick: () => !option.disabled && onChange(option.id),
|
|
61
67
|
onKeyDown: (e) => {
|
|
62
68
|
if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
@@ -74,7 +80,7 @@ function SegmentedControl({
|
|
|
74
80
|
size === "lg" && "rounded-lg text-left",
|
|
75
81
|
option.description ? "whitespace-normal" : "whitespace-nowrap",
|
|
76
82
|
SIZE_CLASSES[size],
|
|
77
|
-
active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
|
|
83
|
+
active ? size === "lg" ? "border-primary/70 bg-primary/10 text-foreground shadow-sm ring-1 ring-primary/25" : "border-border bg-card text-foreground shadow-sm" : implied ? size === "lg" ? "border-dashed border-primary/60 bg-card text-foreground hover:shadow-sm" : "border-dashed border-primary/60 text-foreground hover:bg-background/60" : size === "lg" ? "border-border bg-card text-muted-foreground hover:border-muted-foreground/40 hover:bg-card hover:text-foreground hover:shadow-sm" : "text-muted-foreground hover:border-border hover:bg-background/60 hover:text-foreground",
|
|
78
84
|
active && option.activeClassName
|
|
79
85
|
),
|
|
80
86
|
children: [
|
|
@@ -97,7 +103,18 @@ function SegmentedControl({
|
|
|
97
103
|
size === "lg" && "flex flex-col items-start text-left leading-tight"
|
|
98
104
|
),
|
|
99
105
|
children: [
|
|
100
|
-
/* @__PURE__ */
|
|
106
|
+
option.marker ? /* @__PURE__ */ jsxs("span", { className: "inline-flex min-w-0 max-w-full items-baseline gap-1", children: [
|
|
107
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
"span",
|
|
110
|
+
{
|
|
111
|
+
id: markerId,
|
|
112
|
+
"aria-hidden": "true",
|
|
113
|
+
className: "shrink-0 text-[11px] font-normal opacity-70",
|
|
114
|
+
children: option.marker
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: option.label }),
|
|
101
118
|
option.description && /* @__PURE__ */ jsx(
|
|
102
119
|
"span",
|
|
103
120
|
{
|