@flanksource/clicky-ui 0.3.33 → 0.3.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/ai.cjs +3 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +3 -0
- package/dist/ai.js.map +1 -1
- package/dist/comments/CommentCard.cjs +9 -8
- package/dist/comments/CommentCard.cjs.map +1 -1
- package/dist/comments/CommentCard.d.ts +1 -1
- package/dist/comments/CommentCard.d.ts.map +1 -1
- package/dist/comments/CommentCard.js +2 -1
- package/dist/comments/CommentCard.js.map +1 -1
- package/dist/comments/CommentCardParts.cjs +2 -1
- package/dist/comments/CommentCardParts.cjs.map +1 -1
- package/dist/comments/CommentCardParts.d.ts.map +1 -1
- package/dist/comments/CommentCardParts.js +2 -1
- package/dist/comments/CommentCardParts.js.map +1 -1
- package/dist/comments/CommentProvider.d.ts +1 -1
- package/dist/comments/CommentSidePanel.cjs +3 -2
- package/dist/comments/CommentSidePanel.cjs.map +1 -1
- package/dist/comments/CommentSidePanel.d.ts.map +1 -1
- package/dist/comments/CommentSidePanel.js +2 -1
- package/dist/comments/CommentSidePanel.js.map +1 -1
- package/dist/comments/CommentThread.d.ts +1 -1
- package/dist/comments/CommentThreadList.d.ts +1 -1
- package/dist/comments/MentionTextarea.d.ts +1 -1
- package/dist/comments/comment-context.d.ts +4 -4
- package/dist/comments/comment-fixtures.d.ts +1 -1
- package/dist/comments/comment-types.d.ts +1 -1
- package/dist/comments/comment-utils.cjs +0 -27
- package/dist/comments/comment-utils.cjs.map +1 -1
- package/dist/comments/comment-utils.d.ts +1 -7
- package/dist/comments/comment-utils.d.ts.map +1 -1
- package/dist/comments/comment-utils.js +0 -27
- package/dist/comments/comment-utils.js.map +1 -1
- package/dist/comments.cjs +4 -3
- package/dist/comments.cjs.map +1 -1
- package/dist/comments.d.ts +1 -0
- package/dist/comments.d.ts.map +1 -1
- package/dist/comments.js +2 -1
- package/dist/comments.js.map +1 -1
- package/dist/components/AccordionList.d.ts +1 -1
- package/dist/components/ComboboxControl.d.ts +1 -1
- package/dist/components/ComboboxMenu.d.ts +2 -2
- package/dist/components/ComboboxTags.cjs +41 -11
- package/dist/components/ComboboxTags.cjs.map +1 -1
- package/dist/components/ComboboxTags.d.ts +6 -0
- package/dist/components/ComboboxTags.d.ts.map +1 -1
- package/dist/components/ComboboxTags.js +41 -11
- package/dist/components/ComboboxTags.js.map +1 -1
- package/dist/components/DateField.d.ts +3 -3
- package/dist/components/DatePicker.d.ts +3 -3
- package/dist/components/DateTimePicker.d.ts +3 -3
- package/dist/components/ErrorWrapper.d.ts +2 -2
- package/dist/components/Field.d.ts +1 -1
- package/dist/components/FilterBar.d.ts +1 -1
- package/dist/components/FormLookupProvider.d.ts +1 -1
- package/dist/components/FormatOptionsDropdown.d.ts +1 -1
- package/dist/components/IconButton.d.ts +3 -3
- package/dist/components/InputField.d.ts +2 -2
- package/dist/components/ItemActions.d.ts +1 -1
- package/dist/components/JsonSchemaForm.cjs +17 -36
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +17 -36
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/ListMenu.d.ts +1 -1
- package/dist/components/MultiSelect.d.ts +1 -1
- package/dist/components/RangeSlider.cjs +15 -1
- package/dist/components/RangeSlider.cjs.map +1 -1
- package/dist/components/RangeSlider.d.ts.map +1 -1
- package/dist/components/RangeSlider.js +15 -1
- package/dist/components/RangeSlider.js.map +1 -1
- package/dist/components/SearchInput.d.ts +1 -1
- package/dist/components/SegmentedControl.d.ts +1 -1
- package/dist/components/SplitButton.d.ts +1 -1
- package/dist/components/Switch.d.ts +1 -1
- package/dist/components/TreePickerField.cjs +11 -2
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts +13 -4
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +11 -2
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/UnitStepControls.d.ts +1 -1
- package/dist/components/button.d.ts +3 -3
- package/dist/components/combobox-types.d.ts +1 -1
- package/dist/components/density-switcher.d.ts +1 -1
- package/dist/components/filter-bar-context.d.ts +1 -1
- package/dist/components/filter-bar-field-utils.d.ts +2 -2
- package/dist/components/form-lookup-context.d.ts +1 -1
- package/dist/components/icon-menu-picker.d.ts +1 -1
- package/dist/components/json-schema-form-accordion-array.cjs +44 -21
- package/dist/components/json-schema-form-accordion-array.cjs.map +1 -1
- package/dist/components/json-schema-form-accordion-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-accordion-array.js +47 -24
- package/dist/components/json-schema-form-accordion-array.js.map +1 -1
- package/dist/components/json-schema-form-array.cjs +53 -30
- package/dist/components/json-schema-form-array.cjs.map +1 -1
- package/dist/components/json-schema-form-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-array.js +54 -31
- package/dist/components/json-schema-form-array.js.map +1 -1
- package/dist/components/json-schema-form-cards-array.cjs +32 -22
- package/dist/components/json-schema-form-cards-array.cjs.map +1 -1
- package/dist/components/json-schema-form-cards-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-cards-array.js +33 -23
- package/dist/components/json-schema-form-cards-array.js.map +1 -1
- package/dist/components/json-schema-form-collection-layouts.fixtures.d.ts +44 -0
- package/dist/components/json-schema-form-collection-layouts.fixtures.d.ts.map +1 -0
- package/dist/components/json-schema-form-discriminator.d.ts +1 -1
- package/dist/components/json-schema-form-errors.cjs +5 -1
- package/dist/components/json-schema-form-errors.cjs.map +1 -1
- package/dist/components/json-schema-form-errors.d.ts +2 -1
- package/dist/components/json-schema-form-errors.d.ts.map +1 -1
- package/dist/components/json-schema-form-errors.js +6 -2
- package/dist/components/json-schema-form-errors.js.map +1 -1
- package/dist/components/json-schema-form-extensions.d.ts +1 -1
- package/dist/components/json-schema-form-filter-input.cjs +50 -0
- package/dist/components/json-schema-form-filter-input.cjs.map +1 -0
- package/dist/components/json-schema-form-filter-input.d.ts +5 -0
- package/dist/components/json-schema-form-filter-input.d.ts.map +1 -0
- package/dist/components/json-schema-form-filter-input.js +50 -0
- package/dist/components/json-schema-form-filter-input.js.map +1 -0
- package/dist/components/json-schema-form-filter.cjs +49 -0
- package/dist/components/json-schema-form-filter.cjs.map +1 -0
- package/dist/components/json-schema-form-filter.d.ts +8 -0
- package/dist/components/json-schema-form-filter.d.ts.map +1 -0
- package/dist/components/json-schema-form-filter.js +49 -0
- package/dist/components/json-schema-form-filter.js.map +1 -0
- package/dist/components/json-schema-form-layout.cjs +84 -17
- package/dist/components/json-schema-form-layout.cjs.map +1 -1
- package/dist/components/json-schema-form-layout.d.ts +1 -1
- package/dist/components/json-schema-form-layout.d.ts.map +1 -1
- package/dist/components/json-schema-form-layout.js +84 -17
- package/dist/components/json-schema-form-layout.js.map +1 -1
- package/dist/components/json-schema-form-list-array.cjs +16 -5
- package/dist/components/json-schema-form-list-array.cjs.map +1 -1
- package/dist/components/json-schema-form-list-array.d.ts +2 -1
- package/dist/components/json-schema-form-list-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-list-array.js +16 -5
- package/dist/components/json-schema-form-list-array.js.map +1 -1
- package/dist/components/json-schema-form-object.cjs +239 -85
- package/dist/components/json-schema-form-object.cjs.map +1 -1
- package/dist/components/json-schema-form-object.d.ts +2 -2
- package/dist/components/json-schema-form-object.d.ts.map +1 -1
- package/dist/components/json-schema-form-object.js +241 -87
- package/dist/components/json-schema-form-object.js.map +1 -1
- package/dist/components/json-schema-form-preferences.cjs +1 -1
- package/dist/components/json-schema-form-preferences.cjs.map +1 -1
- package/dist/components/json-schema-form-preferences.d.ts +1 -1
- package/dist/components/json-schema-form-preferences.d.ts.map +1 -1
- package/dist/components/json-schema-form-preferences.js +1 -1
- package/dist/components/json-schema-form-preferences.js.map +1 -1
- package/dist/components/json-schema-form-properties-errors.fixtures.d.ts +14 -0
- package/dist/components/json-schema-form-properties-errors.fixtures.d.ts.map +1 -0
- package/dist/components/json-schema-form-properties-size.cjs +19 -0
- package/dist/components/json-schema-form-properties-size.cjs.map +1 -0
- package/dist/components/json-schema-form-properties-size.d.ts +4 -0
- package/dist/components/json-schema-form-properties-size.d.ts.map +1 -0
- package/dist/components/json-schema-form-properties-size.js +19 -0
- package/dist/components/json-schema-form-properties-size.js.map +1 -0
- package/dist/components/json-schema-form-properties.cjs +305 -0
- package/dist/components/json-schema-form-properties.cjs.map +1 -0
- package/dist/components/json-schema-form-properties.d.ts +20 -0
- package/dist/components/json-schema-form-properties.d.ts.map +1 -0
- package/dist/components/json-schema-form-properties.fixtures.d.ts +157 -0
- package/dist/components/json-schema-form-properties.fixtures.d.ts.map +1 -0
- package/dist/components/json-schema-form-properties.js +305 -0
- package/dist/components/json-schema-form-properties.js.map +1 -0
- package/dist/components/json-schema-form-property-actions-context.cjs +6 -0
- package/dist/components/json-schema-form-property-actions-context.cjs.map +1 -0
- package/dist/components/json-schema-form-property-actions-context.d.ts +2 -0
- package/dist/components/json-schema-form-property-actions-context.d.ts.map +1 -0
- package/dist/components/json-schema-form-property-actions-context.js +6 -0
- package/dist/components/json-schema-form-property-actions-context.js.map +1 -0
- package/dist/components/json-schema-form-property-collection.cjs +31 -0
- package/dist/components/json-schema-form-property-collection.cjs.map +1 -0
- package/dist/components/json-schema-form-property-collection.d.ts +6 -0
- package/dist/components/json-schema-form-property-collection.d.ts.map +1 -0
- package/dist/components/json-schema-form-property-collection.js +31 -0
- package/dist/components/json-schema-form-property-collection.js.map +1 -0
- package/dist/components/json-schema-form-property-draft.cjs +45 -0
- package/dist/components/json-schema-form-property-draft.cjs.map +1 -0
- package/dist/components/json-schema-form-property-draft.d.ts +8 -0
- package/dist/components/json-schema-form-property-draft.d.ts.map +1 -0
- package/dist/components/json-schema-form-property-draft.js +45 -0
- package/dist/components/json-schema-form-property-draft.js.map +1 -0
- package/dist/components/json-schema-form-property-preview.cjs +68 -0
- package/dist/components/json-schema-form-property-preview.cjs.map +1 -0
- package/dist/components/json-schema-form-property-preview.d.ts +7 -0
- package/dist/components/json-schema-form-property-preview.d.ts.map +1 -0
- package/dist/components/json-schema-form-property-preview.js +68 -0
- package/dist/components/json-schema-form-property-preview.js.map +1 -0
- package/dist/components/json-schema-form-property-selection.cjs +89 -0
- package/dist/components/json-schema-form-property-selection.cjs.map +1 -0
- package/dist/components/json-schema-form-property-selection.d.ts +6 -0
- package/dist/components/json-schema-form-property-selection.d.ts.map +1 -0
- package/dist/components/json-schema-form-property-selection.js +89 -0
- package/dist/components/json-schema-form-property-selection.js.map +1 -0
- package/dist/components/json-schema-form-render.cjs +41 -4
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +42 -5
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +2 -0
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +2 -0
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +222 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -0
- package/dist/components/json-schema-form-table-array.cjs +82 -51
- package/dist/components/json-schema-form-table-array.cjs.map +1 -1
- package/dist/components/json-schema-form-table-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-table-array.js +84 -53
- package/dist/components/json-schema-form-table-array.js.map +1 -1
- package/dist/components/json-schema-form-template-menu.d.ts +1 -1
- package/dist/components/json-schema-form-template.d.ts +1 -1
- package/dist/components/json-schema-form-types.d.ts +7 -179
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.cjs +10 -9
- package/dist/components/json-schema-form-utils.cjs.map +1 -1
- package/dist/components/json-schema-form-utils.d.ts +11 -1
- package/dist/components/json-schema-form-utils.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.js +10 -9
- package/dist/components/json-schema-form-utils.js.map +1 -1
- package/dist/components/loading.d.ts +4 -4
- package/dist/components/mdx-editor-callout.d.ts +1 -1
- package/dist/components/mdx-editor-options.d.ts +1 -1
- package/dist/components/select.d.ts +3 -3
- package/dist/components/theme-switcher.d.ts +1 -1
- package/dist/components/use-list-menu-selection.d.ts +1 -1
- package/dist/components/useComboboxLayout.d.ts +1 -1
- package/dist/components/workload-picker-utils.d.ts +1 -1
- package/dist/data/Avatar.d.ts +1 -1
- package/dist/data/AvatarBadge.d.ts +1 -1
- package/dist/data/Badge.d.ts +1 -1
- package/dist/data/Callout.d.ts +1 -1
- package/dist/data/DataTable.cjs +575 -435
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +21 -13
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.grouping.d.ts +1 -1
- package/dist/data/DataTable.js +575 -435
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/ExecutionTree.d.ts +1 -1
- package/dist/data/FilterPill.d.ts +1 -1
- package/dist/data/FixtureEditor/RawFenceEditor.d.ts +1 -1
- package/dist/data/FixtureEditor/types.d.ts +1 -1
- package/dist/data/Gauge.d.ts +1 -1
- package/dist/data/GaugeHoverCard.d.ts +1 -1
- package/dist/data/Icon.d.ts +1 -1
- package/dist/data/KeyValueList.d.ts +1 -1
- package/dist/data/MarkdownEditor.d.ts +1 -1
- package/dist/data/MatrixTable.d.ts +1 -1
- package/dist/data/ObjectGraph.d.ts +1 -1
- package/dist/data/ProgressBars.d.ts +1 -1
- package/dist/data/Properties.cjs +86 -35
- package/dist/data/Properties.cjs.map +1 -1
- package/dist/data/Properties.d.ts +2 -2
- package/dist/data/Properties.d.ts.map +1 -1
- package/dist/data/Properties.js +87 -36
- package/dist/data/Properties.js.map +1 -1
- package/dist/data/RadialGauge.d.ts +1 -1
- package/dist/data/SchemaViewer.d.ts +1 -1
- package/dist/data/SortableHeader.d.ts +1 -1
- package/dist/data/StatStrip.d.ts +1 -1
- package/dist/data/StatusBreakdown.d.ts +1 -1
- package/dist/data/TabButton.d.ts +1 -1
- package/dist/data/TaskManager.cjs +9 -17
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +9 -17
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskManagerButton.cjs +17 -34
- package/dist/data/TaskManagerButton.cjs.map +1 -1
- package/dist/data/TaskManagerButton.d.ts.map +1 -1
- package/dist/data/TaskManagerButton.js +18 -35
- package/dist/data/TaskManagerButton.js.map +1 -1
- package/dist/data/TaskProcessDetails.cjs +5 -26
- package/dist/data/TaskProcessDetails.cjs.map +1 -1
- package/dist/data/TaskProcessDetails.d.ts +2 -1
- package/dist/data/TaskProcessDetails.d.ts.map +1 -1
- package/dist/data/TaskProcessDetails.js +5 -26
- package/dist/data/TaskProcessDetails.js.map +1 -1
- package/dist/data/TaskProgress.cjs +24 -15
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +2 -1
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +24 -15
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/TaskResourceReadings.cjs +42 -0
- package/dist/data/TaskResourceReadings.cjs.map +1 -0
- package/dist/data/TaskResourceReadings.d.ts +6 -0
- package/dist/data/TaskResourceReadings.d.ts.map +1 -0
- package/dist/data/TaskResourceReadings.js +42 -0
- package/dist/data/TaskResourceReadings.js.map +1 -0
- package/dist/data/TaskSnapshot.cjs.map +1 -1
- package/dist/data/TaskSnapshot.d.ts +14 -1
- package/dist/data/TaskSnapshot.d.ts.map +1 -1
- package/dist/data/TaskSnapshot.js.map +1 -1
- package/dist/data/Timeline.d.ts +1 -1
- package/dist/data/Tree.d.ts +1 -1
- package/dist/data/TreeGroupHeader.d.ts +1 -1
- package/dist/data/TreeNode.d.ts +1 -1
- package/dist/data/Version.d.ts +3 -3
- package/dist/data/ai/ChatWindow.cjs +22 -12
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +22 -12
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/ChatWindow.test-utils.d.ts +4 -2
- package/dist/data/ai/ChatWindow.test-utils.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.types.d.ts +1 -1
- package/dist/data/ai/ChatWindowManager.cjs +2 -0
- package/dist/data/ai/ChatWindowManager.cjs.map +1 -1
- package/dist/data/ai/ChatWindowManager.d.ts +1 -1
- package/dist/data/ai/ChatWindowManager.d.ts.map +1 -1
- package/dist/data/ai/ChatWindowManager.js +2 -0
- package/dist/data/ai/ChatWindowManager.js.map +1 -1
- package/dist/data/ai/PolicyTree.d.ts +1 -1
- package/dist/data/ai/PromptCatalog/PromptPageHeader.d.ts +1 -1
- package/dist/data/ai/PromptCatalog/types.d.ts +1 -1
- package/dist/data/ai/PromptRunEditor/index.cjs +4 -0
- package/dist/data/ai/PromptRunEditor/index.cjs.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.d.ts +5 -2
- package/dist/data/ai/PromptRunEditor/index.d.ts.map +1 -1
- package/dist/data/ai/PromptRunEditor/index.js +4 -0
- package/dist/data/ai/PromptRunEditor/index.js.map +1 -1
- package/dist/data/ai/SessionChatComposer.d.ts +1 -1
- package/dist/data/ai/SessionInspector.approvals.cjs +147 -0
- package/dist/data/ai/SessionInspector.approvals.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.approvals.d.ts +21 -0
- package/dist/data/ai/SessionInspector.approvals.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.approvals.js +147 -0
- package/dist/data/ai/SessionInspector.approvals.js.map +1 -0
- package/dist/data/ai/SessionInspector.cjs +21 -8
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.d.ts +6 -2
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.d.ts +1 -1
- package/dist/data/ai/SessionInspector.js +21 -8
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.panel-parts.cjs +47 -0
- package/dist/data/ai/SessionInspector.panel-parts.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.panel-parts.d.ts +20 -0
- package/dist/data/ai/SessionInspector.panel-parts.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.panel-parts.js +47 -0
- package/dist/data/ai/SessionInspector.panel-parts.js.map +1 -0
- package/dist/data/ai/SessionInspector.panels.cjs +40 -99
- package/dist/data/ai/SessionInspector.panels.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.panels.d.ts +3 -1
- package/dist/data/ai/SessionInspector.panels.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.panels.js +12 -71
- package/dist/data/ai/SessionInspector.panels.js.map +1 -1
- package/dist/data/ai/SessionViewer.d.ts +1 -1
- package/dist/data/ai/SessionViewer.rows.d.ts +1 -1
- package/dist/data/ai/SessionViewer.tool-details.d.ts +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +23 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/Footer.d.ts +1 -1
- package/dist/data/ai/SpecRuntimeEditor/Rail.d.ts +1 -1
- package/dist/data/ai/SpecRuntimeEditor/SectionCard.d.ts +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs +3 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts +3 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js +3 -1
- package/dist/data/ai/SpecRuntimeEditor/VerifySection.js.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/fields.d.ts +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs +3 -1
- package/dist/data/ai/SpecRuntimeEditor/index.cjs.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts +5 -2
- package/dist/data/ai/SpecRuntimeEditor/index.d.ts.map +1 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js +3 -1
- package/dist/data/ai/SpecRuntimeEditor/index.js.map +1 -1
- package/dist/data/ai/chat-window-context.cjs +1 -0
- package/dist/data/ai/chat-window-context.cjs.map +1 -1
- package/dist/data/ai/chat-window-context.d.ts +13 -5
- package/dist/data/ai/chat-window-context.d.ts.map +1 -1
- package/dist/data/ai/chat-window-context.js +1 -0
- package/dist/data/ai/chat-window-context.js.map +1 -1
- package/dist/data/ai/index.d.ts +2 -1
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/use-session-scroll.d.ts +1 -1
- package/dist/data/badge-variants.d.ts +2 -2
- package/dist/data/cache-browser/adapter.d.ts +1 -1
- package/dist/data/cells/CellFilterActions.d.ts +1 -1
- package/dist/data/cells/EntityCell.d.ts +1 -1
- package/dist/data/cells/tag-utils.d.ts +1 -1
- package/dist/data/chat/Chat.cjs +42 -46
- package/dist/data/chat/Chat.cjs.map +1 -1
- package/dist/data/chat/Chat.d.ts +16 -5
- package/dist/data/chat/Chat.d.ts.map +1 -1
- package/dist/data/chat/Chat.js +43 -47
- package/dist/data/chat/Chat.js.map +1 -1
- package/dist/data/chat/ModelSelector.d.ts +1 -1
- package/dist/data/chat/PromptInput.cjs +13 -0
- package/dist/data/chat/PromptInput.cjs.map +1 -1
- package/dist/data/chat/PromptInput.d.ts +8 -2
- package/dist/data/chat/PromptInput.d.ts.map +1 -1
- package/dist/data/chat/PromptInput.js +14 -1
- package/dist/data/chat/PromptInput.js.map +1 -1
- package/dist/data/chat/tool-render/ToolArgs.d.ts +1 -1
- package/dist/data/chat/tool-render/ToolParams.d.ts +1 -1
- package/dist/data/chat/tool-render/ToolValue.d.ts +1 -1
- package/dist/data/chat/tool-render/adapter.d.ts +1 -1
- package/dist/data/chat/tool-render/context.d.ts +1 -1
- package/dist/data/chat/tool-render/defaults.d.ts +1 -1
- package/dist/data/chat/tool-render/known-tool-views.d.ts +1 -1
- package/dist/data/chat/tool-render/summary.d.ts +1 -1
- package/dist/data/chat/types.d.ts +1 -1
- package/dist/data/clicky-export/useClickyExport.d.ts +1 -1
- package/dist/data/data-table-server-filters.d.ts +1 -1
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +1 -1
- package/dist/data/diagnostics/ErrorDetails.d.ts +1 -1
- package/dist/data/diagnostics/StackFrameRow.d.ts +1 -1
- package/dist/data/git/GitChangeList.d.ts +1 -1
- package/dist/data/icon-fallback.d.ts +1 -1
- package/dist/data/properties-context.cjs +6 -0
- package/dist/data/properties-context.cjs.map +1 -0
- package/dist/data/properties-context.d.ts +7 -0
- package/dist/data/properties-context.d.ts.map +1 -0
- package/dist/data/properties-context.js +6 -0
- package/dist/data/properties-context.js.map +1 -0
- package/dist/data/query-browser/QueryBrowser.types.d.ts +1 -1
- package/dist/data/runtime/RuntimeBar.cjs +7 -3
- package/dist/data/runtime/RuntimeBar.cjs.map +1 -1
- package/dist/data/runtime/RuntimeBar.d.ts.map +1 -1
- package/dist/data/runtime/RuntimeBar.js +7 -3
- package/dist/data/runtime/RuntimeBar.js.map +1 -1
- package/dist/data/task-copy.cjs +1 -1
- package/dist/data/task-copy.cjs.map +1 -1
- package/dist/data/task-copy.js +1 -1
- package/dist/data/task-copy.js.map +1 -1
- package/dist/data/task-resource-summary.cjs +30 -0
- package/dist/data/task-resource-summary.cjs.map +1 -0
- package/dist/data/task-resource-summary.d.ts +15 -0
- package/dist/data/task-resource-summary.d.ts.map +1 -0
- package/dist/data/task-resource-summary.js +30 -0
- package/dist/data/task-resource-summary.js.map +1 -0
- package/dist/data/task-status.cjs +8 -2
- package/dist/data/task-status.cjs.map +1 -1
- package/dist/data/task-status.d.ts +3 -0
- package/dist/data/task-status.d.ts.map +1 -1
- package/dist/data/task-status.js +8 -2
- package/dist/data/task-status.js.map +1 -1
- package/dist/data/task-work-progress.cjs +24 -0
- package/dist/data/task-work-progress.cjs.map +1 -0
- package/dist/data/task-work-progress.d.ts +21 -0
- package/dist/data/task-work-progress.d.ts.map +1 -0
- package/dist/data/task-work-progress.js +24 -0
- package/dist/data/task-work-progress.js.map +1 -0
- package/dist/data/test-runner/TestRunner.d.ts +1 -1
- package/dist/data/test-runner/adapter.d.ts +1 -1
- package/dist/data/test-runner/context.d.ts +1 -1
- package/dist/data/use-data-table-virtual.cjs +73 -0
- package/dist/data/use-data-table-virtual.cjs.map +1 -0
- package/dist/data/use-data-table-virtual.d.ts +40 -0
- package/dist/data/use-data-table-virtual.d.ts.map +1 -0
- package/dist/data/use-data-table-virtual.js +73 -0
- package/dist/data/use-data-table-virtual.js.map +1 -0
- package/dist/data/verification/VerificationResults.d.ts +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/expressions/lang/attributes.cjs +56 -0
- package/dist/expressions/lang/attributes.cjs.map +1 -0
- package/dist/expressions/lang/attributes.d.ts +22 -0
- package/dist/expressions/lang/attributes.d.ts.map +1 -0
- package/dist/expressions/lang/attributes.js +56 -0
- package/dist/expressions/lang/attributes.js.map +1 -0
- package/dist/expressions/lang/completion.cjs +164 -0
- package/dist/expressions/lang/completion.cjs.map +1 -0
- package/dist/expressions/lang/completion.d.ts +29 -0
- package/dist/expressions/lang/completion.d.ts.map +1 -0
- package/dist/expressions/lang/completion.js +164 -0
- package/dist/expressions/lang/completion.js.map +1 -0
- package/dist/expressions/lang/environment.cjs +115 -0
- package/dist/expressions/lang/environment.cjs.map +1 -0
- package/dist/expressions/lang/environment.d.ts +54 -0
- package/dist/expressions/lang/environment.d.ts.map +1 -0
- package/dist/expressions/lang/environment.js +115 -0
- package/dist/expressions/lang/environment.js.map +1 -0
- package/dist/expressions/lang/generated/conformance.json.d.ts +4962 -0
- package/dist/expressions/lang/generated/index.cjs +18 -0
- package/dist/expressions/lang/generated/index.cjs.map +1 -0
- package/dist/expressions/lang/generated/index.d.ts +9 -0
- package/dist/expressions/lang/generated/index.d.ts.map +1 -0
- package/dist/expressions/lang/generated/index.js +18 -0
- package/dist/expressions/lang/generated/index.js.map +1 -0
- package/dist/expressions/lang/generated/languages.json.cjs +18 -0
- package/dist/expressions/lang/generated/languages.json.cjs.map +1 -0
- package/dist/expressions/lang/generated/languages.json.d.ts +2305 -0
- package/dist/expressions/lang/generated/languages.json.js +18 -0
- package/dist/expressions/lang/generated/languages.json.js.map +1 -0
- package/dist/expressions/lang/generated/spec.json.cjs +12 -0
- package/dist/expressions/lang/generated/spec.json.cjs.map +1 -0
- package/dist/expressions/lang/generated/spec.json.d.ts +6260 -0
- package/dist/expressions/lang/generated/spec.json.js +12 -0
- package/dist/expressions/lang/generated/spec.json.js.map +1 -0
- package/dist/expressions/lang/hover.cjs +106 -0
- package/dist/expressions/lang/hover.cjs.map +1 -0
- package/dist/expressions/lang/hover.d.ts +54 -0
- package/dist/expressions/lang/hover.d.ts.map +1 -0
- package/dist/expressions/lang/hover.js +106 -0
- package/dist/expressions/lang/hover.js.map +1 -0
- package/dist/expressions/lang/index.cjs +87 -0
- package/dist/expressions/lang/index.cjs.map +1 -0
- package/dist/expressions/lang/index.d.ts +65 -0
- package/dist/expressions/lang/index.d.ts.map +1 -0
- package/dist/expressions/lang/index.js +90 -0
- package/dist/expressions/lang/index.js.map +1 -0
- package/dist/expressions/lang/merge.cjs +52 -0
- package/dist/expressions/lang/merge.cjs.map +1 -0
- package/dist/expressions/lang/merge.d.ts +12 -0
- package/dist/expressions/lang/merge.d.ts.map +1 -0
- package/dist/expressions/lang/merge.js +52 -0
- package/dist/expressions/lang/merge.js.map +1 -0
- package/dist/expressions/lang/prefix.cjs +91 -0
- package/dist/expressions/lang/prefix.cjs.map +1 -0
- package/dist/expressions/lang/prefix.d.ts +36 -0
- package/dist/expressions/lang/prefix.d.ts.map +1 -0
- package/dist/expressions/lang/prefix.js +91 -0
- package/dist/expressions/lang/prefix.js.map +1 -0
- package/dist/expressions/lang/spec.d.ts +13 -0
- package/dist/expressions/lang/spec.d.ts.map +1 -0
- package/dist/expressions/lang/theme.cjs +97 -0
- package/dist/expressions/lang/theme.cjs.map +1 -0
- package/dist/expressions/lang/theme.d.ts +6 -0
- package/dist/expressions/lang/theme.d.ts.map +1 -0
- package/dist/expressions/lang/theme.js +97 -0
- package/dist/expressions/lang/theme.js.map +1 -0
- package/dist/expressions/lang/types.d.ts +81 -0
- package/dist/expressions/lang/types.d.ts.map +1 -0
- package/dist/expressions/playground/ExpressionPlayground.cjs +308 -0
- package/dist/expressions/playground/ExpressionPlayground.cjs.map +1 -0
- package/dist/expressions/playground/ExpressionPlayground.d.ts +42 -0
- package/dist/expressions/playground/ExpressionPlayground.d.ts.map +1 -0
- package/dist/expressions/playground/ExpressionPlayground.js +291 -0
- package/dist/expressions/playground/ExpressionPlayground.js.map +1 -0
- package/dist/expressions/playground/RunControls.cjs +51 -0
- package/dist/expressions/playground/RunControls.cjs.map +1 -0
- package/dist/expressions/playground/RunControls.d.ts +7 -0
- package/dist/expressions/playground/RunControls.d.ts.map +1 -0
- package/dist/expressions/playground/RunControls.js +51 -0
- package/dist/expressions/playground/RunControls.js.map +1 -0
- package/dist/expressions/playground/VerticalSplit.cjs +109 -0
- package/dist/expressions/playground/VerticalSplit.cjs.map +1 -0
- package/dist/expressions/playground/VerticalSplit.d.ts +23 -0
- package/dist/expressions/playground/VerticalSplit.d.ts.map +1 -0
- package/dist/expressions/playground/VerticalSplit.js +109 -0
- package/dist/expressions/playground/VerticalSplit.js.map +1 -0
- package/dist/expressions/playground/api.cjs +49 -0
- package/dist/expressions/playground/api.cjs.map +1 -0
- package/dist/expressions/playground/api.d.ts +53 -0
- package/dist/expressions/playground/api.d.ts.map +1 -0
- package/dist/expressions/playground/api.js +49 -0
- package/dist/expressions/playground/api.js.map +1 -0
- package/dist/expressions/playground/languages.cjs +88 -0
- package/dist/expressions/playground/languages.cjs.map +1 -0
- package/dist/expressions/playground/languages.d.ts +43 -0
- package/dist/expressions/playground/languages.d.ts.map +1 -0
- package/dist/expressions/playground/languages.js +88 -0
- package/dist/expressions/playground/languages.js.map +1 -0
- package/dist/expressions/playground/panels/GraphPanel.cjs +72 -0
- package/dist/expressions/playground/panels/GraphPanel.cjs.map +1 -0
- package/dist/expressions/playground/panels/GraphPanel.d.ts +19 -0
- package/dist/expressions/playground/panels/GraphPanel.d.ts.map +1 -0
- package/dist/expressions/playground/panels/GraphPanel.js +72 -0
- package/dist/expressions/playground/panels/GraphPanel.js.map +1 -0
- package/dist/expressions/playground/panels/ResultPanel.cjs +82 -0
- package/dist/expressions/playground/panels/ResultPanel.cjs.map +1 -0
- package/dist/expressions/playground/panels/ResultPanel.d.ts +11 -0
- package/dist/expressions/playground/panels/ResultPanel.d.ts.map +1 -0
- package/dist/expressions/playground/panels/ResultPanel.js +82 -0
- package/dist/expressions/playground/panels/ResultPanel.js.map +1 -0
- package/dist/expressions/playground/panels/SpecPanel.cjs +76 -0
- package/dist/expressions/playground/panels/SpecPanel.cjs.map +1 -0
- package/dist/expressions/playground/panels/SpecPanel.d.ts +18 -0
- package/dist/expressions/playground/panels/SpecPanel.d.ts.map +1 -0
- package/dist/expressions/playground/panels/SpecPanel.js +76 -0
- package/dist/expressions/playground/panels/SpecPanel.js.map +1 -0
- package/dist/expressions/playground/panels/TokensPanel.cjs +89 -0
- package/dist/expressions/playground/panels/TokensPanel.cjs.map +1 -0
- package/dist/expressions/playground/panels/TokensPanel.d.ts +15 -0
- package/dist/expressions/playground/panels/TokensPanel.d.ts.map +1 -0
- package/dist/expressions/playground/panels/TokensPanel.js +72 -0
- package/dist/expressions/playground/panels/TokensPanel.js.map +1 -0
- package/dist/expressions/playground/panels/graphNodes.cjs +35 -0
- package/dist/expressions/playground/panels/graphNodes.cjs.map +1 -0
- package/dist/expressions/playground/panels/graphNodes.d.ts +19 -0
- package/dist/expressions/playground/panels/graphNodes.d.ts.map +1 -0
- package/dist/expressions/playground/panels/graphNodes.js +35 -0
- package/dist/expressions/playground/panels/graphNodes.js.map +1 -0
- package/dist/expressions/playground/runAction.cjs +12 -0
- package/dist/expressions/playground/runAction.cjs.map +1 -0
- package/dist/expressions/playground/runAction.d.ts +15 -0
- package/dist/expressions/playground/runAction.d.ts.map +1 -0
- package/dist/expressions/playground/runAction.js +12 -0
- package/dist/expressions/playground/runAction.js.map +1 -0
- package/dist/expressions/playground/runShortcut.cjs +9 -0
- package/dist/expressions/playground/runShortcut.cjs.map +1 -0
- package/dist/expressions/playground/runShortcut.d.ts +2 -0
- package/dist/expressions/playground/runShortcut.d.ts.map +1 -0
- package/dist/expressions/playground/runShortcut.js +9 -0
- package/dist/expressions/playground/runShortcut.js.map +1 -0
- package/dist/expressions/playground/useEditorTheme.cjs +40 -0
- package/dist/expressions/playground/useEditorTheme.cjs.map +1 -0
- package/dist/expressions/playground/useEditorTheme.d.ts +16 -0
- package/dist/expressions/playground/useEditorTheme.d.ts.map +1 -0
- package/dist/expressions/playground/useEditorTheme.js +23 -0
- package/dist/expressions/playground/useEditorTheme.js.map +1 -0
- package/dist/expressions/playground/useEvaluator.cjs +72 -0
- package/dist/expressions/playground/useEvaluator.cjs.map +1 -0
- package/dist/expressions/playground/useEvaluator.d.ts +25 -0
- package/dist/expressions/playground/useEvaluator.d.ts.map +1 -0
- package/dist/expressions/playground/useEvaluator.js +72 -0
- package/dist/expressions/playground/useEvaluator.js.map +1 -0
- package/dist/expressions/playground/useParsedInput.cjs +22 -0
- package/dist/expressions/playground/useParsedInput.cjs.map +1 -0
- package/dist/expressions/playground/useParsedInput.d.ts +20 -0
- package/dist/expressions/playground/useParsedInput.d.ts.map +1 -0
- package/dist/expressions/playground/useParsedInput.js +22 -0
- package/dist/expressions/playground/useParsedInput.js.map +1 -0
- package/dist/expressions/playground/verticalSplitModel.cjs +11 -0
- package/dist/expressions/playground/verticalSplitModel.cjs.map +1 -0
- package/dist/expressions/playground/verticalSplitModel.d.ts +3 -0
- package/dist/expressions/playground/verticalSplitModel.d.ts.map +1 -0
- package/dist/expressions/playground/verticalSplitModel.js +11 -0
- package/dist/expressions/playground/verticalSplitModel.js.map +1 -0
- package/dist/expressions/playground.cjs +18 -0
- package/dist/expressions/playground.cjs.map +1 -0
- package/dist/expressions/playground.d.ts +18 -0
- package/dist/expressions/playground.d.ts.map +1 -0
- package/dist/expressions/playground.js +18 -0
- package/dist/expressions/playground.js.map +1 -0
- package/dist/expressions.cjs +28 -0
- package/dist/expressions.cjs.map +1 -0
- package/dist/expressions.d.ts +10 -0
- package/dist/expressions.d.ts.map +1 -0
- package/dist/expressions.js +28 -0
- package/dist/expressions.js.map +1 -0
- package/dist/hooks/density-provider.d.ts +1 -1
- package/dist/hooks/theme-provider.d.ts +1 -1
- package/dist/hooks/use-density.d.ts +1 -1
- package/dist/hooks/use-resource-clock.cjs +14 -0
- package/dist/hooks/use-resource-clock.cjs.map +1 -0
- package/dist/hooks/use-resource-clock.d.ts +2 -0
- package/dist/hooks/use-resource-clock.d.ts.map +1 -0
- package/dist/hooks/use-resource-clock.js +14 -0
- package/dist/hooks/use-resource-clock.js.map +1 -0
- package/dist/hooks/use-task-run.cjs +12 -3
- package/dist/hooks/use-task-run.cjs.map +1 -1
- package/dist/hooks/use-task-run.d.ts.map +1 -1
- package/dist/hooks/use-task-run.js +12 -3
- package/dist/hooks/use-task-run.js.map +1 -1
- package/dist/hooks/use-theme.d.ts +1 -1
- package/dist/icons/registry.d.ts +1 -1
- package/dist/icons/types.d.ts +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.d.ts +1 -1
- package/dist/layout/AppShell.nav.drag.d.ts +1 -1
- package/dist/layout/AppSidebar.d.ts +1 -1
- package/dist/layout/Panel.d.ts +1 -1
- package/dist/layout/PanelFrame.d.ts +1 -1
- package/dist/layout/Section.d.ts +1 -1
- package/dist/layout/SplitPane.d.ts +1 -1
- package/dist/layout/Tabs.d.ts +1 -1
- package/dist/layout/Workspace.d.ts +1 -1
- package/dist/layout/Workspace.model.d.ts +1 -1
- package/dist/lib/combobox-values.d.ts +1 -1
- package/dist/lib/comment-stage.cjs +31 -0
- package/dist/lib/comment-stage.cjs.map +1 -0
- package/dist/lib/comment-stage.d.ts +8 -0
- package/dist/lib/comment-stage.d.ts.map +1 -0
- package/dist/lib/comment-stage.js +31 -0
- package/dist/lib/comment-stage.js.map +1 -0
- package/dist/monaco/MonacoEditor.cjs +3 -3
- package/dist/monaco/MonacoEditor.cjs.map +1 -1
- package/dist/monaco/MonacoEditor.js +2 -2
- package/dist/monaco/MonacoEditor.js.map +1 -1
- package/dist/monaco/types.d.ts +1 -1
- package/dist/monaco/use-monaco-worker.d.ts +1 -1
- package/dist/overlay/CellActions.d.ts +1 -1
- package/dist/overlay/CommandPalette.d.ts +2 -2
- package/dist/overlay/CommandPalette.model.d.ts +1 -1
- package/dist/overlay/CommandPaletteList.d.ts +1 -1
- package/dist/overlay/DropdownMenu.d.ts +1 -1
- package/dist/overlay/HoverCard.d.ts +1 -1
- package/dist/overlay/Modal.d.ts +2 -2
- package/dist/overlay/Toast.d.ts +1 -1
- package/dist/overlay/TourCard.d.ts +1 -1
- package/dist/overlay/TourProvider.d.ts +1 -1
- package/dist/overlay/dropdownMenuContext.d.ts +1 -1
- package/dist/overlay/toast-context.d.ts +2 -2
- package/dist/overlay/tour-context.d.ts +1 -1
- package/dist/overlay/tour-types.d.ts +1 -1
- package/dist/profiles/connections/connectionBrowserModel.d.ts +1 -1
- package/dist/profiles/connections/connectionQueryWorkspace.d.ts +1 -1
- package/dist/profiles/editor/profileBuilder.d.ts +1 -1
- package/dist/profiles/elasticsearch/esParamOperandExtension.d.ts +1 -1
- package/dist/profiles/fields/profileFieldControls.d.ts +1 -1
- package/dist/profiles/fields/profileFieldIcons.d.ts +1 -1
- package/dist/profiles/fields/profileFieldState.d.ts +1 -1
- package/dist/profiles/query/jsonPathSample.d.ts +1 -1
- package/dist/profiles/query/jsonPathSampleRow.d.ts +1 -1
- package/dist/profiles/query/prometheusResults.d.ts +2 -2
- package/dist/rpc/EndpointList.d.ts +1 -1
- package/dist/rpc/EntityExplorerApp.d.ts +1 -1
- package/dist/rpc/OperationCatalog.d.ts +1 -1
- package/dist/rpc/OperationEntityContextPicker.d.ts +1 -1
- package/dist/rpc/OperationEntityPage.d.ts +1 -1
- package/dist/rpc/OperationResultView.d.ts +1 -1
- package/dist/rpc/RouterProvider.d.ts +1 -1
- package/dist/rpc/SchemaActionForm.d.ts +1 -1
- package/dist/rpc/formMetadata.d.ts +1 -1
- package/dist/rpc/router.d.ts +1 -1
- package/dist/rpc/rpc-story.fixtures.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/dist/utils.cjs +4 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +1 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -1
- package/package.json +21 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RangeSlider.cjs","sources":["../../src/components/RangeSlider.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\n\nexport type RangeSliderValue = [number, number];\n\nexport type RangeSliderProps = {\n min: number;\n max: number;\n value: RangeSliderValue;\n onChange: (value: RangeSliderValue) => void;\n step?: number;\n ariaLabelMin?: string;\n ariaLabelMax?: string;\n /** Shows number fields below the track for exact keyboard entry. */\n editable?: boolean;\n className?: string;\n trackClassName?: string;\n rangeClassName?: string;\n thumbClassName?: string;\n};\n\nconst thumbClassName =\n \"[&::-webkit-slider-thumb]:pointer-events-auto [&::-webkit-slider-thumb]:mt-[-5px] [&::-webkit-slider-thumb]:size-3.5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-background/80 [&::-webkit-slider-thumb]:bg-muted-foreground [&::-webkit-slider-thumb]:shadow-sm [&::-moz-range-thumb]:pointer-events-auto [&::-moz-range-thumb]:size-3.5 [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border [&::-moz-range-thumb]:border-background/80 [&::-moz-range-thumb]:bg-muted-foreground [&::-moz-range-thumb]:shadow-sm\";\n\nexport function RangeSlider({\n min,\n max,\n value,\n onChange,\n step = 1,\n ariaLabelMin = \"Minimum value\",\n ariaLabelMax = \"Maximum value\",\n editable = false,\n className,\n trackClassName,\n rangeClassName,\n thumbClassName: thumbOverrideClassName,\n}: RangeSliderProps) {\n const [lower, upper] = normalizeRangeValue(value, min, max);\n\n return (\n <div className={cn(editable && \"space-y-2\", className)}>\n <div className=\"relative h-6\">\n <div\n className={cn(\n \"absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border\",\n trackClassName,\n )}\n />\n <div\n className={cn(\n \"absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70\",\n rangeClassName,\n )}\n style={{\n left: `${valueToPercent(lower, min, max)}%`,\n right: `${100 - valueToPercent(upper, min, max)}%`,\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMin}\n min={min}\n max={max}\n step={step}\n value={lower}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n style={{ zIndex: lower >= max ? 30 : 20 }}\n onChange={(event) => {\n const nextLower = clampNumber(Number(event.target.value), min, max);\n onChange([Math.min(nextLower, upper), upper]);\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMax}\n min={min}\n max={max}\n step={step}\n value={upper}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n onChange={(event) => {\n const nextUpper = clampNumber(Number(event.target.value), min, max);\n onChange([lower, Math.max(nextUpper, lower)]);\n }}\n />\n </div>\n {editable ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <EditableBound\n label=\"Min\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMin)}`}\n min={min}\n max={upper}\n step={step}\n value={lower}\n onChange={(next) => onChange([next, upper])}\n />\n <EditableBound\n label=\"Max\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMax)}`}\n min={lower}\n max={max}\n step={step}\n value={upper}\n onChange={(next) => onChange([lower, next])}\n />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction EditableBound({\n label,\n ariaLabel,\n min,\n max,\n step,\n value,\n onChange,\n}: {\n label: string;\n ariaLabel: string;\n min: number;\n max: number;\n step: number;\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <label className=\"grid grid-cols-[auto_minmax(0,1fr)] items-center gap-1.5 text-[11px] text-muted-foreground\">\n <span>{label}</span>\n <input\n aria-label={ariaLabel}\n className=\"h-7 min-w-0 rounded-md border border-input bg-background px-2 text-right font-mono text-xs tabular-nums text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n max={max}\n min={min}\n step={step}\n type=\"number\"\n value={value}\n onChange={(event) => {\n if (event.currentTarget.value === \"\") return;\n const next = Number(event.currentTarget.value);\n if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);\n onChange(clampNumber(next, min, max));\n }}\n />\n </label>\n );\n}\n\nconst baseSliderClassName =\n \"pointer-events-none absolute inset-0 h-6 w-full appearance-none bg-transparent [&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-transparent [&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-transparent\";\n\nfunction normalizeRangeValue(value: RangeSliderValue, min: number, max: number): RangeSliderValue {\n const lower = clampNumber(Math.min(value[0], value[1]), min, max);\n const upper = clampNumber(Math.max(value[0], value[1]), min, max);\n return [lower, upper];\n}\n\nfunction clampNumber(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction valueToPercent(value: number, min: number, max: number) {\n if (max <= min) return 0;\n return ((value - min) / (max - min)) * 100;\n}\n\nfunction lowercaseFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"names":["cn","jsxs","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RangeSlider.cjs","sources":["../../src/components/RangeSlider.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\n\nexport type RangeSliderValue = [number, number];\n\nexport type RangeSliderProps = {\n min: number;\n max: number;\n value: RangeSliderValue;\n onChange: (value: RangeSliderValue) => void;\n step?: number;\n ariaLabelMin?: string;\n ariaLabelMax?: string;\n /** Shows number fields below the track for exact keyboard entry. */\n editable?: boolean;\n className?: string;\n trackClassName?: string;\n rangeClassName?: string;\n thumbClassName?: string;\n};\n\nconst thumbClassName =\n \"[&::-webkit-slider-thumb]:pointer-events-auto [&::-webkit-slider-thumb]:mt-[-5px] [&::-webkit-slider-thumb]:size-3.5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-background/80 [&::-webkit-slider-thumb]:bg-muted-foreground [&::-webkit-slider-thumb]:shadow-sm [&::-moz-range-thumb]:pointer-events-auto [&::-moz-range-thumb]:size-3.5 [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border [&::-moz-range-thumb]:border-background/80 [&::-moz-range-thumb]:bg-muted-foreground [&::-moz-range-thumb]:shadow-sm\";\n\nexport function RangeSlider({\n min,\n max,\n value,\n onChange,\n step = 1,\n ariaLabelMin = \"Minimum value\",\n ariaLabelMax = \"Maximum value\",\n editable = false,\n className,\n trackClassName,\n rangeClassName,\n thumbClassName: thumbOverrideClassName,\n}: RangeSliderProps) {\n const [lower, upper] = normalizeRangeValue(value, min, max);\n\n return (\n <div className={cn(editable && \"space-y-2\", className)}>\n <div className=\"relative h-6\">\n <div\n className={cn(\n \"absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border\",\n trackClassName,\n )}\n />\n <div\n className={cn(\n \"absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70\",\n rangeClassName,\n )}\n style={{\n left: `${valueToPercent(lower, min, max)}%`,\n right: `${100 - valueToPercent(upper, min, max)}%`,\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMin}\n min={min}\n max={max}\n step={step}\n value={lower}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n style={{ zIndex: lower >= max ? 30 : 20 }}\n onChange={(event) => {\n const nextLower = clampNumber(Number(event.target.value), min, max);\n onChange([Math.min(nextLower, upper), upper]);\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMax}\n min={min}\n max={max}\n step={step}\n value={upper}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n onChange={(event) => {\n const nextUpper = clampNumber(Number(event.target.value), min, max);\n onChange([lower, Math.max(nextUpper, lower)]);\n }}\n />\n </div>\n {editable ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <EditableBound\n label=\"Min\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMin)}`}\n min={min}\n max={upper}\n step={step}\n stepBase={min}\n value={lower}\n onChange={(next) => onChange([next, upper])}\n />\n <EditableBound\n label=\"Max\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMax)}`}\n min={lower}\n max={max}\n step={step}\n stepBase={min}\n value={upper}\n onChange={(next) => onChange([lower, next])}\n />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction EditableBound({\n label,\n ariaLabel,\n min,\n max,\n step,\n stepBase,\n value,\n onChange,\n}: {\n label: string;\n ariaLabel: string;\n min: number;\n max: number;\n step: number;\n /** Origin the `step` grid is measured from — the slider's own `min`. */\n stepBase: number;\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <label className=\"grid grid-cols-[auto_minmax(0,1fr)] items-center gap-1.5 text-[11px] text-muted-foreground\">\n <span>{label}</span>\n <input\n aria-label={ariaLabel}\n className=\"h-7 min-w-0 rounded-md border border-input bg-background px-2 text-right font-mono text-xs tabular-nums text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n max={max}\n min={min}\n step={step}\n type=\"number\"\n value={value}\n onChange={(event) => {\n if (event.currentTarget.value === \"\") return;\n const next = Number(event.currentTarget.value);\n if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);\n onChange(snapToStep(next, { base: stepBase, step, min, max }));\n }}\n />\n </label>\n );\n}\n\nconst baseSliderClassName =\n \"pointer-events-none absolute inset-0 h-6 w-full appearance-none bg-transparent [&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-transparent [&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-transparent\";\n\nfunction normalizeRangeValue(value: RangeSliderValue, min: number, max: number): RangeSliderValue {\n const lower = clampNumber(Math.min(value[0], value[1]), min, max);\n const upper = clampNumber(Math.max(value[0], value[1]), min, max);\n return [lower, upper];\n}\n\nfunction clampNumber(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value));\n}\n\n/**\n * Nearest `step`-aligned value measured from `base`, kept inside `[min, max]`.\n * Mirrors what the range inputs enforce, so typed entry cannot produce a value\n * the thumbs could never reach.\n */\nfunction snapToStep(\n value: number,\n { base, step, min, max }: { base: number; step: number; min: number; max: number },\n): number {\n if (!(step > 0)) return clampNumber(value, min, max);\n const aligned = base + Math.round((value - base) / step) * step;\n if (aligned < min) {\n return clampNumber(base + Math.ceil((min - base) / step) * step, min, max);\n }\n if (aligned > max) {\n return clampNumber(base + Math.floor((max - base) / step) * step, min, max);\n }\n return aligned;\n}\n\nfunction valueToPercent(value: number, min: number, max: number) {\n if (max <= min) return 0;\n return ((value - min) / (max - min)) * 100;\n}\n\nfunction lowercaseFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"names":["cn","jsxs","jsx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../src/components/RangeSlider.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAKF,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAQ,EACR,YAA8B,EAC9B,YAA8B,EAC9B,QAAgB,EAChB,SAAS,EACT,cAAc,EACd,cAAc,EACd,cAAc,EAAE,sBAAsB,GACvC,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"RangeSlider.d.ts","sourceRoot":"","sources":["../../src/components/RangeSlider.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEhD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,gBAAgB,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAKF,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,GAAG,EACH,KAAK,EACL,QAAQ,EACR,IAAQ,EACR,YAA8B,EAC9B,YAA8B,EAC9B,QAAgB,EAChB,SAAS,EACT,cAAc,EACd,cAAc,EACd,cAAc,EAAE,sBAAsB,GACvC,EAAE,gBAAgB,+BA4ElB"}
|
|
@@ -83,6 +83,7 @@ function RangeSlider({
|
|
|
83
83
|
min,
|
|
84
84
|
max: upper,
|
|
85
85
|
step,
|
|
86
|
+
stepBase: min,
|
|
86
87
|
value: lower,
|
|
87
88
|
onChange: (next) => onChange([next, upper])
|
|
88
89
|
}
|
|
@@ -95,6 +96,7 @@ function RangeSlider({
|
|
|
95
96
|
min: lower,
|
|
96
97
|
max,
|
|
97
98
|
step,
|
|
99
|
+
stepBase: min,
|
|
98
100
|
value: upper,
|
|
99
101
|
onChange: (next) => onChange([lower, next])
|
|
100
102
|
}
|
|
@@ -108,6 +110,7 @@ function EditableBound({
|
|
|
108
110
|
min,
|
|
109
111
|
max,
|
|
110
112
|
step,
|
|
113
|
+
stepBase,
|
|
111
114
|
value,
|
|
112
115
|
onChange
|
|
113
116
|
}) {
|
|
@@ -127,7 +130,7 @@ function EditableBound({
|
|
|
127
130
|
if (event.currentTarget.value === "") return;
|
|
128
131
|
const next = Number(event.currentTarget.value);
|
|
129
132
|
if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);
|
|
130
|
-
onChange(
|
|
133
|
+
onChange(snapToStep(next, { base: stepBase, step, min, max }));
|
|
131
134
|
}
|
|
132
135
|
}
|
|
133
136
|
)
|
|
@@ -142,6 +145,17 @@ function normalizeRangeValue(value, min, max) {
|
|
|
142
145
|
function clampNumber(value, min, max) {
|
|
143
146
|
return Math.min(max, Math.max(min, value));
|
|
144
147
|
}
|
|
148
|
+
function snapToStep(value, { base, step, min, max }) {
|
|
149
|
+
if (!(step > 0)) return clampNumber(value, min, max);
|
|
150
|
+
const aligned = base + Math.round((value - base) / step) * step;
|
|
151
|
+
if (aligned < min) {
|
|
152
|
+
return clampNumber(base + Math.ceil((min - base) / step) * step, min, max);
|
|
153
|
+
}
|
|
154
|
+
if (aligned > max) {
|
|
155
|
+
return clampNumber(base + Math.floor((max - base) / step) * step, min, max);
|
|
156
|
+
}
|
|
157
|
+
return aligned;
|
|
158
|
+
}
|
|
145
159
|
function valueToPercent(value, min, max) {
|
|
146
160
|
if (max <= min) return 0;
|
|
147
161
|
return (value - min) / (max - min) * 100;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RangeSlider.js","sources":["../../src/components/RangeSlider.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\n\nexport type RangeSliderValue = [number, number];\n\nexport type RangeSliderProps = {\n min: number;\n max: number;\n value: RangeSliderValue;\n onChange: (value: RangeSliderValue) => void;\n step?: number;\n ariaLabelMin?: string;\n ariaLabelMax?: string;\n /** Shows number fields below the track for exact keyboard entry. */\n editable?: boolean;\n className?: string;\n trackClassName?: string;\n rangeClassName?: string;\n thumbClassName?: string;\n};\n\nconst thumbClassName =\n \"[&::-webkit-slider-thumb]:pointer-events-auto [&::-webkit-slider-thumb]:mt-[-5px] [&::-webkit-slider-thumb]:size-3.5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-background/80 [&::-webkit-slider-thumb]:bg-muted-foreground [&::-webkit-slider-thumb]:shadow-sm [&::-moz-range-thumb]:pointer-events-auto [&::-moz-range-thumb]:size-3.5 [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border [&::-moz-range-thumb]:border-background/80 [&::-moz-range-thumb]:bg-muted-foreground [&::-moz-range-thumb]:shadow-sm\";\n\nexport function RangeSlider({\n min,\n max,\n value,\n onChange,\n step = 1,\n ariaLabelMin = \"Minimum value\",\n ariaLabelMax = \"Maximum value\",\n editable = false,\n className,\n trackClassName,\n rangeClassName,\n thumbClassName: thumbOverrideClassName,\n}: RangeSliderProps) {\n const [lower, upper] = normalizeRangeValue(value, min, max);\n\n return (\n <div className={cn(editable && \"space-y-2\", className)}>\n <div className=\"relative h-6\">\n <div\n className={cn(\n \"absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border\",\n trackClassName,\n )}\n />\n <div\n className={cn(\n \"absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70\",\n rangeClassName,\n )}\n style={{\n left: `${valueToPercent(lower, min, max)}%`,\n right: `${100 - valueToPercent(upper, min, max)}%`,\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMin}\n min={min}\n max={max}\n step={step}\n value={lower}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n style={{ zIndex: lower >= max ? 30 : 20 }}\n onChange={(event) => {\n const nextLower = clampNumber(Number(event.target.value), min, max);\n onChange([Math.min(nextLower, upper), upper]);\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMax}\n min={min}\n max={max}\n step={step}\n value={upper}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n onChange={(event) => {\n const nextUpper = clampNumber(Number(event.target.value), min, max);\n onChange([lower, Math.max(nextUpper, lower)]);\n }}\n />\n </div>\n {editable ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <EditableBound\n label=\"Min\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMin)}`}\n min={min}\n max={upper}\n step={step}\n value={lower}\n onChange={(next) => onChange([next, upper])}\n />\n <EditableBound\n label=\"Max\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMax)}`}\n min={lower}\n max={max}\n step={step}\n value={upper}\n onChange={(next) => onChange([lower, next])}\n />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction EditableBound({\n label,\n ariaLabel,\n min,\n max,\n step,\n value,\n onChange,\n}: {\n label: string;\n ariaLabel: string;\n min: number;\n max: number;\n step: number;\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <label className=\"grid grid-cols-[auto_minmax(0,1fr)] items-center gap-1.5 text-[11px] text-muted-foreground\">\n <span>{label}</span>\n <input\n aria-label={ariaLabel}\n className=\"h-7 min-w-0 rounded-md border border-input bg-background px-2 text-right font-mono text-xs tabular-nums text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n max={max}\n min={min}\n step={step}\n type=\"number\"\n value={value}\n onChange={(event) => {\n if (event.currentTarget.value === \"\") return;\n const next = Number(event.currentTarget.value);\n if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);\n onChange(clampNumber(next, min, max));\n }}\n />\n </label>\n );\n}\n\nconst baseSliderClassName =\n \"pointer-events-none absolute inset-0 h-6 w-full appearance-none bg-transparent [&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-transparent [&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-transparent\";\n\nfunction normalizeRangeValue(value: RangeSliderValue, min: number, max: number): RangeSliderValue {\n const lower = clampNumber(Math.min(value[0], value[1]), min, max);\n const upper = clampNumber(Math.max(value[0], value[1]), min, max);\n return [lower, upper];\n}\n\nfunction clampNumber(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value));\n}\n\nfunction valueToPercent(value: number, min: number, max: number) {\n if (max <= min) return 0;\n return ((value - min) / (max - min)) * 100;\n}\n\nfunction lowercaseFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RangeSlider.js","sources":["../../src/components/RangeSlider.tsx"],"sourcesContent":["import { cn } from \"../lib/utils\";\n\nexport type RangeSliderValue = [number, number];\n\nexport type RangeSliderProps = {\n min: number;\n max: number;\n value: RangeSliderValue;\n onChange: (value: RangeSliderValue) => void;\n step?: number;\n ariaLabelMin?: string;\n ariaLabelMax?: string;\n /** Shows number fields below the track for exact keyboard entry. */\n editable?: boolean;\n className?: string;\n trackClassName?: string;\n rangeClassName?: string;\n thumbClassName?: string;\n};\n\nconst thumbClassName =\n \"[&::-webkit-slider-thumb]:pointer-events-auto [&::-webkit-slider-thumb]:mt-[-5px] [&::-webkit-slider-thumb]:size-3.5 [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border [&::-webkit-slider-thumb]:border-background/80 [&::-webkit-slider-thumb]:bg-muted-foreground [&::-webkit-slider-thumb]:shadow-sm [&::-moz-range-thumb]:pointer-events-auto [&::-moz-range-thumb]:size-3.5 [&::-moz-range-thumb]:appearance-none [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border [&::-moz-range-thumb]:border-background/80 [&::-moz-range-thumb]:bg-muted-foreground [&::-moz-range-thumb]:shadow-sm\";\n\nexport function RangeSlider({\n min,\n max,\n value,\n onChange,\n step = 1,\n ariaLabelMin = \"Minimum value\",\n ariaLabelMax = \"Maximum value\",\n editable = false,\n className,\n trackClassName,\n rangeClassName,\n thumbClassName: thumbOverrideClassName,\n}: RangeSliderProps) {\n const [lower, upper] = normalizeRangeValue(value, min, max);\n\n return (\n <div className={cn(editable && \"space-y-2\", className)}>\n <div className=\"relative h-6\">\n <div\n className={cn(\n \"absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border\",\n trackClassName,\n )}\n />\n <div\n className={cn(\n \"absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70\",\n rangeClassName,\n )}\n style={{\n left: `${valueToPercent(lower, min, max)}%`,\n right: `${100 - valueToPercent(upper, min, max)}%`,\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMin}\n min={min}\n max={max}\n step={step}\n value={lower}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n style={{ zIndex: lower >= max ? 30 : 20 }}\n onChange={(event) => {\n const nextLower = clampNumber(Number(event.target.value), min, max);\n onChange([Math.min(nextLower, upper), upper]);\n }}\n />\n <input\n type=\"range\"\n aria-label={ariaLabelMax}\n min={min}\n max={max}\n step={step}\n value={upper}\n className={cn(baseSliderClassName, thumbClassName, thumbOverrideClassName)}\n onChange={(event) => {\n const nextUpper = clampNumber(Number(event.target.value), min, max);\n onChange([lower, Math.max(nextUpper, lower)]);\n }}\n />\n </div>\n {editable ? (\n <div className=\"grid grid-cols-2 gap-2\">\n <EditableBound\n label=\"Min\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMin)}`}\n min={min}\n max={upper}\n step={step}\n stepBase={min}\n value={lower}\n onChange={(next) => onChange([next, upper])}\n />\n <EditableBound\n label=\"Max\"\n ariaLabel={`Edit ${lowercaseFirst(ariaLabelMax)}`}\n min={lower}\n max={max}\n step={step}\n stepBase={min}\n value={upper}\n onChange={(next) => onChange([lower, next])}\n />\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction EditableBound({\n label,\n ariaLabel,\n min,\n max,\n step,\n stepBase,\n value,\n onChange,\n}: {\n label: string;\n ariaLabel: string;\n min: number;\n max: number;\n step: number;\n /** Origin the `step` grid is measured from — the slider's own `min`. */\n stepBase: number;\n value: number;\n onChange: (value: number) => void;\n}) {\n return (\n <label className=\"grid grid-cols-[auto_minmax(0,1fr)] items-center gap-1.5 text-[11px] text-muted-foreground\">\n <span>{label}</span>\n <input\n aria-label={ariaLabel}\n className=\"h-7 min-w-0 rounded-md border border-input bg-background px-2 text-right font-mono text-xs tabular-nums text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n max={max}\n min={min}\n step={step}\n type=\"number\"\n value={value}\n onChange={(event) => {\n if (event.currentTarget.value === \"\") return;\n const next = Number(event.currentTarget.value);\n if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);\n onChange(snapToStep(next, { base: stepBase, step, min, max }));\n }}\n />\n </label>\n );\n}\n\nconst baseSliderClassName =\n \"pointer-events-none absolute inset-0 h-6 w-full appearance-none bg-transparent [&::-webkit-slider-runnable-track]:h-1 [&::-webkit-slider-runnable-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-transparent [&::-moz-range-track]:h-1 [&::-moz-range-track]:rounded-full [&::-moz-range-track]:bg-transparent\";\n\nfunction normalizeRangeValue(value: RangeSliderValue, min: number, max: number): RangeSliderValue {\n const lower = clampNumber(Math.min(value[0], value[1]), min, max);\n const upper = clampNumber(Math.max(value[0], value[1]), min, max);\n return [lower, upper];\n}\n\nfunction clampNumber(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value));\n}\n\n/**\n * Nearest `step`-aligned value measured from `base`, kept inside `[min, max]`.\n * Mirrors what the range inputs enforce, so typed entry cannot produce a value\n * the thumbs could never reach.\n */\nfunction snapToStep(\n value: number,\n { base, step, min, max }: { base: number; step: number; min: number; max: number },\n): number {\n if (!(step > 0)) return clampNumber(value, min, max);\n const aligned = base + Math.round((value - base) / step) * step;\n if (aligned < min) {\n return clampNumber(base + Math.ceil((min - base) / step) * step, min, max);\n }\n if (aligned > max) {\n return clampNumber(base + Math.floor((max - base) / step) * step, min, max);\n }\n return aligned;\n}\n\nfunction valueToPercent(value: number, min: number, max: number) {\n if (max <= min) return 0;\n return ((value - min) / (max - min)) * 100;\n}\n\nfunction lowercaseFirst(value: string): string {\n return value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from '
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { InputFieldInputProps } from './InputField';
|
|
3
3
|
export type SearchInputProps = Omit<InputFieldInputProps, "onChange" | "prefix" | "type" | "value"> & {
|
|
4
4
|
/** Controlled query value. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from '
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { StaticIconComponent } from '../data/Icon';
|
|
3
3
|
export type SegmentedSize = "sm" | "md" | "lg";
|
|
4
4
|
export type SegmentedOption<T extends string = string> = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from '
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { ButtonProps } from './button';
|
|
3
3
|
import { StaticIconComponent } from '../data/Icon';
|
|
4
4
|
import { DropdownMenuItem } from '../overlay/DropdownMenu';
|
|
@@ -17,11 +17,15 @@ function TreePickerField({
|
|
|
17
17
|
roots,
|
|
18
18
|
getKey,
|
|
19
19
|
getChildren,
|
|
20
|
+
getAriaLabel,
|
|
20
21
|
renderRow,
|
|
21
22
|
getSearchText,
|
|
22
23
|
defaultOpen,
|
|
24
|
+
hasMoreChildren,
|
|
25
|
+
loadChildren,
|
|
23
26
|
isSelectable,
|
|
24
27
|
onSelect,
|
|
28
|
+
closeOnSelect = true,
|
|
25
29
|
selected,
|
|
26
30
|
revealSelected,
|
|
27
31
|
showControls,
|
|
@@ -35,7 +39,8 @@ function TreePickerField({
|
|
|
35
39
|
triggerClassName,
|
|
36
40
|
panelClassName,
|
|
37
41
|
renderTrigger,
|
|
38
|
-
renderFooter
|
|
42
|
+
renderFooter,
|
|
43
|
+
triggerAriaLabel
|
|
39
44
|
}) {
|
|
40
45
|
const [open, setOpen] = react.useState(false);
|
|
41
46
|
const floatingZ = modalStack.useFloatingZIndex();
|
|
@@ -106,6 +111,7 @@ function TreePickerField({
|
|
|
106
111
|
ref: anchorRef,
|
|
107
112
|
type: "button",
|
|
108
113
|
disabled,
|
|
114
|
+
"aria-label": triggerAriaLabel,
|
|
109
115
|
"aria-haspopup": "tree",
|
|
110
116
|
"aria-expanded": open,
|
|
111
117
|
onClick: () => setOpen((current) => !current),
|
|
@@ -161,8 +167,11 @@ function TreePickerField({
|
|
|
161
167
|
getKey,
|
|
162
168
|
getChildren,
|
|
163
169
|
renderRow,
|
|
170
|
+
...getAriaLabel ? { getAriaLabel } : {},
|
|
164
171
|
...getSearchText ? { getSearchText } : {},
|
|
165
172
|
...defaultOpen ? { defaultOpen } : {},
|
|
173
|
+
...hasMoreChildren ? { hasMoreChildren } : {},
|
|
174
|
+
...loadChildren ? { loadChildren } : {},
|
|
166
175
|
...selected !== void 0 ? { selected } : {},
|
|
167
176
|
...revealSelected !== void 0 ? { revealSelected } : {},
|
|
168
177
|
...showControls !== void 0 ? { showControls } : {},
|
|
@@ -171,7 +180,7 @@ function TreePickerField({
|
|
|
171
180
|
onSelect: (node) => {
|
|
172
181
|
if (!isSelectable || isSelectable(node)) {
|
|
173
182
|
onSelect(node);
|
|
174
|
-
setOpen(false);
|
|
183
|
+
if (closeOnSelect) setOpen(false);
|
|
175
184
|
}
|
|
176
185
|
}
|
|
177
186
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreePickerField.cjs","sources":["../../src/components/TreePickerField.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronDown } from \"../icons\";\nimport { Tree, type TreeProps } from \"../data/Tree\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\nimport { inputSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// Upper bound the open panel grows to so wide trees show full labels before\n// truncating; the panel is never narrower than the trigger.\nconst PANEL_MAX_WIDTH_PX = 480;\n// Tallest the panel gets when the viewport allows it.\nconst PANEL_MAX_HEIGHT_PX = 480;\n// Below this there is not enough room to be worth opening downward, so the panel\n// flips above the trigger instead.\nconst PANEL_MIN_HEIGHT_PX = 200;\n// Breathing room kept between the panel and the viewport edge.\nconst VIEWPORT_MARGIN_PX = 8;\n\nexport interface TreePickerFieldProps<T> {\n /** Root nodes of the tree to browse. */\n roots: T[];\n getKey: (node: T) => string | number;\n getChildren: (node: T) => T[] | undefined;\n renderRow: TreeProps<T>[\"renderRow\"];\n getSearchText?: (node: T) => string;\n defaultOpen?: (node: T, depth: number) => boolean;\n /**\n * Decides which nodes commit a selection when clicked. A click on a\n * non-selectable node still toggles its expansion (it never closes the\n * picker). Defaults to every node selectable.\n */\n isSelectable?: (node: T) => boolean;\n /** Fires for a selectable node, then closes the dropdown. */\n onSelect: (node: T) => void;\n /** Highlights the committed node inside the open tree. */\n selected?: T | null;\n /**\n * Force-opens the `selected` node's ancestors so the current value is always\n * visible when the panel opens, however deep its branch. Requires `selected`.\n */\n revealSelected?: boolean;\n /** Renders the tree's expand/collapse + filter toolbar. */\n showControls?: boolean;\n /** Accessible name for the tree inside the panel. */\n ariaLabel?: string;\n /** Empty-state content when `roots` is empty. */\n empty?: ReactNode;\n /** Current-selection display in the trigger; falls back to `placeholder`. */\n label?: ReactNode;\n placeholder?: string;\n disabled?: boolean;\n size?: FormSize;\n className?: string;\n triggerClassName?: string;\n panelClassName?: string;\n renderTrigger?: (props: TreePickerTriggerProps) => ReactNode;\n /**\n * Sticky row pinned below the tree inside the open panel — an escape hatch\n * from a dropdown that has run out of room (a fuller browser, a \"create new\")\n * rather than another node. It is handed `close` because acting on it almost\n * always means leaving the dropdown behind.\n */\n renderFooter?: (props: { close: () => void }) => ReactNode;\n}\n\nexport interface TreePickerTriggerProps {\n open: boolean;\n disabled: boolean;\n triggerRef: Ref<HTMLButtonElement>;\n toggle: () => void;\n}\n\n// TreePickerField is a form-field-styled trigger (matching Combobox's closed\n// input) that opens a portal-anchored dropdown holding a Tree. The dropdown is\n// positioned with fixed coordinates measured from the trigger so it escapes any\n// overflow-hidden / scroll ancestor (e.g. a modal body). A click on a selectable\n// node commits and closes; a non-selectable node only toggles expansion.\nexport function TreePickerField<T>({\n roots,\n getKey,\n getChildren,\n renderRow,\n getSearchText,\n defaultOpen,\n isSelectable,\n onSelect,\n selected,\n revealSelected,\n showControls,\n ariaLabel,\n empty,\n label,\n placeholder = \"Select…\",\n disabled,\n size,\n className,\n triggerClassName,\n panelClassName,\n renderTrigger,\n renderFooter,\n}: TreePickerFieldProps<T>) {\n const [open, setOpen] = useState(false);\n const floatingZ = useFloatingZIndex();\n const [pos, setPos] = useState<\n { top: number; left: number; width: number; maxWidth: number; maxHeight: number } | null\n >(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEscapeLayer(open, () => {\n setOpen(false);\n anchorRef.current?.focus();\n });\n\n // Position the portaled panel from the trigger rect, repositioning while open.\n useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = rootRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const viewportCap = window.innerWidth - rect.left - VIEWPORT_MARGIN_PX;\n const maxWidth = Math.max(rect.width, Math.min(PANEL_MAX_WIDTH_PX, viewportCap));\n // Fit the panel to the room the trigger actually has, and flip it above\n // when there is more room up there. Without this the panel keeps its full\n // height wherever the trigger sits, so a trigger low on the page pushes\n // the panel's bottom past the viewport — taking the sticky footer, and\n // any escape hatch pinned to it, out of reach entirely.\n const below = window.innerHeight - rect.bottom - VIEWPORT_MARGIN_PX - 4;\n const above = rect.top - VIEWPORT_MARGIN_PX - 4;\n const flip = below < PANEL_MIN_HEIGHT_PX && above > below;\n const available = Math.max(flip ? above : below, PANEL_MIN_HEIGHT_PX);\n const maxHeight = Math.min(PANEL_MAX_HEIGHT_PX, available);\n setPos({\n top: flip ? Math.max(VIEWPORT_MARGIN_PX, rect.top - 4 - maxHeight) : rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n maxWidth,\n maxHeight,\n });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open]);\n\n // Dismiss on an outside pointer-down (the trigger and panel are exempt).\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!rootRef.current?.contains(target) && !panelRef.current?.contains(target)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n {renderTrigger ? (\n renderTrigger({\n open,\n disabled: Boolean(disabled),\n triggerRef: anchorRef,\n toggle: () => {\n if (!disabled) setOpen((current) => !current);\n },\n })\n ) : (\n <button\n ref={anchorRef}\n type=\"button\"\n disabled={disabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={() => setOpen((current) => !current)}\n className={cn(\n \"relative flex w-full items-center rounded-md border border-input bg-background text-left text-foreground\",\n size ? inputSizeClass[size] : \"h-control-h px-control-px text-sm\",\n \"pr-8\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n triggerClassName,\n )}\n >\n <span className={cn(\"min-w-0 flex-1 truncate\", label == null && \"text-muted-foreground\")}>\n {label ?? placeholder}\n </span>\n <span className=\"pointer-events-none absolute right-0 flex h-full items-center px-2 text-muted-foreground\">\n <Icon icon={UiChevronDown} className=\"text-xs\" />\n </span>\n </button>\n )}\n\n {open &&\n pos &&\n createPortal(\n <div\n ref={panelRef}\n data-slot=\"tree-picker-popup\"\n style={{\n position: \"fixed\",\n top: pos.top,\n left: pos.left,\n // Computed rather than constant: the popup has to clear whatever\n // modal is open, and a modal sits at zIndex.modal (10000). A\n // hardcoded z-50 renders the tree behind any dialog it is opened\n // in — see ../overlay/zIndex.\n zIndex: floatingZ,\n // Grow to fit the widest row/toolbar, but never narrower than the\n // trigger nor wider than maxWidth — so labels show in full and the\n // toolbar's intrinsic-width search input never forces a scrollbar.\n minWidth: pos.width,\n width: \"max-content\",\n maxWidth: pos.maxWidth,\n maxHeight: pos.maxHeight,\n }}\n className={cn(\n // Height comes from the measured maxHeight above, not a viewport\n // fraction: 60vh is the same number wherever the trigger sits, and\n // a trigger low on the page needs a shorter panel, not an equal one.\n \"flex flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md\",\n panelClassName,\n )}\n >\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <Tree<T>\n roots={roots}\n getKey={getKey}\n getChildren={getChildren}\n renderRow={renderRow}\n {...(getSearchText ? { getSearchText } : {})}\n {...(defaultOpen ? { defaultOpen } : {})}\n {...(selected !== undefined ? { selected } : {})}\n {...(revealSelected !== undefined ? { revealSelected } : {})}\n {...(showControls !== undefined ? { showControls } : {})}\n {...(ariaLabel !== undefined ? { ariaLabel } : {})}\n {...(empty !== undefined ? { empty } : {})}\n onSelect={(node) => {\n if (!isSelectable || isSelectable(node)) {\n onSelect(node);\n setOpen(false);\n }\n }}\n />\n </div>\n {renderFooter && (\n <div className=\"shrink-0 border-t border-border bg-popover\">\n {renderFooter({ close: () => setOpen(false) })}\n </div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n"],"names":["useState","useFloatingZIndex","useRef","useEscapeLayer","useLayoutEffect","useEffect","jsxs","cn","inputSizeClass","jsx","Icon","UiChevronDown","createPortal","Tree"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreePickerField.cjs","sources":["../../src/components/TreePickerField.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronDown } from \"../icons\";\nimport { Tree, type TreeProps } from \"../data/Tree\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\nimport { inputSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// Upper bound the open panel grows to so wide trees show full labels before\n// truncating; the panel is never narrower than the trigger.\nconst PANEL_MAX_WIDTH_PX = 480;\n// Tallest the panel gets when the viewport allows it.\nconst PANEL_MAX_HEIGHT_PX = 480;\n// Below this there is not enough room to be worth opening downward, so the panel\n// flips above the trigger instead.\nconst PANEL_MIN_HEIGHT_PX = 200;\n// Breathing room kept between the panel and the viewport edge.\nconst VIEWPORT_MARGIN_PX = 8;\n\nexport interface TreePickerFieldProps<T> {\n /** Root nodes of the tree to browse. */\n roots: T[];\n getKey: (node: T) => string | number;\n getChildren: (node: T) => T[] | undefined;\n getAriaLabel?: TreeProps<T>[\"getAriaLabel\"];\n renderRow: TreeProps<T>[\"renderRow\"];\n getSearchText?: (node: T) => string;\n defaultOpen?: (node: T, depth: number) => boolean;\n /** Reports nodes whose children should be fetched when first expanded. */\n hasMoreChildren?: TreeProps<T>[\"hasMoreChildren\"];\n /** Fetches a lazy node's children when it is first expanded. */\n loadChildren?: TreeProps<T>[\"loadChildren\"];\n /**\n * Decides which nodes commit a selection when clicked. A click on a\n * non-selectable node still toggles its expansion (it never closes the\n * picker). Defaults to every node selectable.\n */\n isSelectable?: (node: T) => boolean;\n /** Fires when a selectable node is clicked. */\n onSelect: (node: T) => void;\n /** Close after a row selection. Disable when a footer explicitly commits the pending node. */\n closeOnSelect?: boolean;\n /** Highlights the selected node inside the open tree. */\n selected?: T | null;\n /**\n * Force-opens the `selected` node's ancestors so the current value is always\n * visible when the panel opens, however deep its branch. Requires `selected`.\n */\n revealSelected?: boolean;\n /** Renders the tree's expand/collapse + filter toolbar. */\n showControls?: boolean;\n /** Accessible name for the tree inside the panel. */\n ariaLabel?: string;\n /** Empty-state content when `roots` is empty. */\n empty?: ReactNode;\n /** Current-selection display in the trigger; falls back to `placeholder`. */\n label?: ReactNode;\n placeholder?: string;\n disabled?: boolean;\n size?: FormSize;\n className?: string;\n triggerClassName?: string;\n panelClassName?: string;\n renderTrigger?: (props: TreePickerTriggerProps) => ReactNode;\n /**\n * Sticky row pinned below the tree inside the open panel — an escape hatch\n * from a dropdown that has run out of room (a fuller browser, a \"create new\")\n * rather than another node. It is handed `close` because acting on it almost\n * always means leaving the dropdown behind.\n */\n renderFooter?: (props: { close: () => void }) => ReactNode;\n /** Accessible name for the closed picker trigger. */\n triggerAriaLabel?: string;\n}\n\nexport interface TreePickerTriggerProps {\n open: boolean;\n disabled: boolean;\n triggerRef: Ref<HTMLButtonElement>;\n toggle: () => void;\n}\n\n// TreePickerField is a form-field-styled trigger (matching Combobox's closed\n// input) that opens a portal-anchored dropdown holding a Tree. The dropdown is\n// positioned with fixed coordinates measured from the trigger so it escapes any\n// overflow-hidden / scroll ancestor (e.g. a modal body). A click on a selectable\n// node commits and closes; a non-selectable node only toggles expansion.\nexport function TreePickerField<T>({\n roots,\n getKey,\n getChildren,\n getAriaLabel,\n renderRow,\n getSearchText,\n defaultOpen,\n hasMoreChildren,\n loadChildren,\n isSelectable,\n onSelect,\n closeOnSelect = true,\n selected,\n revealSelected,\n showControls,\n ariaLabel,\n empty,\n label,\n placeholder = \"Select…\",\n disabled,\n size,\n className,\n triggerClassName,\n panelClassName,\n renderTrigger,\n renderFooter,\n triggerAriaLabel,\n}: TreePickerFieldProps<T>) {\n const [open, setOpen] = useState(false);\n const floatingZ = useFloatingZIndex();\n const [pos, setPos] = useState<\n { top: number; left: number; width: number; maxWidth: number; maxHeight: number } | null\n >(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEscapeLayer(open, () => {\n setOpen(false);\n anchorRef.current?.focus();\n });\n\n // Position the portaled panel from the trigger rect, repositioning while open.\n useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = rootRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const viewportCap = window.innerWidth - rect.left - VIEWPORT_MARGIN_PX;\n const maxWidth = Math.max(rect.width, Math.min(PANEL_MAX_WIDTH_PX, viewportCap));\n // Fit the panel to the room the trigger actually has, and flip it above\n // when there is more room up there. Without this the panel keeps its full\n // height wherever the trigger sits, so a trigger low on the page pushes\n // the panel's bottom past the viewport — taking the sticky footer, and\n // any escape hatch pinned to it, out of reach entirely.\n const below = window.innerHeight - rect.bottom - VIEWPORT_MARGIN_PX - 4;\n const above = rect.top - VIEWPORT_MARGIN_PX - 4;\n const flip = below < PANEL_MIN_HEIGHT_PX && above > below;\n const available = Math.max(flip ? above : below, PANEL_MIN_HEIGHT_PX);\n const maxHeight = Math.min(PANEL_MAX_HEIGHT_PX, available);\n setPos({\n top: flip ? Math.max(VIEWPORT_MARGIN_PX, rect.top - 4 - maxHeight) : rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n maxWidth,\n maxHeight,\n });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open]);\n\n // Dismiss on an outside pointer-down (the trigger and panel are exempt).\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!rootRef.current?.contains(target) && !panelRef.current?.contains(target)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n {renderTrigger ? (\n renderTrigger({\n open,\n disabled: Boolean(disabled),\n triggerRef: anchorRef,\n toggle: () => {\n if (!disabled) setOpen((current) => !current);\n },\n })\n ) : (\n <button\n ref={anchorRef}\n type=\"button\"\n disabled={disabled}\n aria-label={triggerAriaLabel}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={() => setOpen((current) => !current)}\n className={cn(\n \"relative flex w-full items-center rounded-md border border-input bg-background text-left text-foreground\",\n size ? inputSizeClass[size] : \"h-control-h px-control-px text-sm\",\n \"pr-8\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n triggerClassName,\n )}\n >\n <span className={cn(\"min-w-0 flex-1 truncate\", label == null && \"text-muted-foreground\")}>\n {label ?? placeholder}\n </span>\n <span className=\"pointer-events-none absolute right-0 flex h-full items-center px-2 text-muted-foreground\">\n <Icon icon={UiChevronDown} className=\"text-xs\" />\n </span>\n </button>\n )}\n\n {open &&\n pos &&\n createPortal(\n <div\n ref={panelRef}\n data-slot=\"tree-picker-popup\"\n style={{\n position: \"fixed\",\n top: pos.top,\n left: pos.left,\n // Computed rather than constant: the popup has to clear whatever\n // modal is open, and a modal sits at zIndex.modal (10000). A\n // hardcoded z-50 renders the tree behind any dialog it is opened\n // in — see ../overlay/zIndex.\n zIndex: floatingZ,\n // Grow to fit the widest row/toolbar, but never narrower than the\n // trigger nor wider than maxWidth — so labels show in full and the\n // toolbar's intrinsic-width search input never forces a scrollbar.\n minWidth: pos.width,\n width: \"max-content\",\n maxWidth: pos.maxWidth,\n maxHeight: pos.maxHeight,\n }}\n className={cn(\n // Height comes from the measured maxHeight above, not a viewport\n // fraction: 60vh is the same number wherever the trigger sits, and\n // a trigger low on the page needs a shorter panel, not an equal one.\n \"flex flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md\",\n panelClassName,\n )}\n >\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <Tree<T>\n roots={roots}\n getKey={getKey}\n getChildren={getChildren}\n renderRow={renderRow}\n {...(getAriaLabel ? { getAriaLabel } : {})}\n {...(getSearchText ? { getSearchText } : {})}\n {...(defaultOpen ? { defaultOpen } : {})}\n {...(hasMoreChildren ? { hasMoreChildren } : {})}\n {...(loadChildren ? { loadChildren } : {})}\n {...(selected !== undefined ? { selected } : {})}\n {...(revealSelected !== undefined ? { revealSelected } : {})}\n {...(showControls !== undefined ? { showControls } : {})}\n {...(ariaLabel !== undefined ? { ariaLabel } : {})}\n {...(empty !== undefined ? { empty } : {})}\n onSelect={(node) => {\n if (!isSelectable || isSelectable(node)) {\n onSelect(node);\n if (closeOnSelect) setOpen(false);\n }\n }}\n />\n </div>\n {renderFooter && (\n <div className=\"shrink-0 border-t border-border bg-popover\">\n {renderFooter({ close: () => setOpen(false) })}\n </div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n"],"names":["useState","useFloatingZIndex","useRef","useEscapeLayer","useLayoutEffect","useEffect","jsxs","cn","inputSizeClass","jsx","Icon","UiChevronDown","createPortal","Tree"],"mappings":";;;;;;;;;;;AAWA,MAAM,qBAAqB;AAE3B,MAAM,sBAAsB;AAG5B,MAAM,sBAAsB;AAE5B,MAAM,qBAAqB;AAsEpB,SAAS,gBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,CAAC,MAAM,OAAO,IAAIA,MAAAA,SAAS,KAAK;AACtC,QAAM,YAAYC,WAAAA,kBAAA;AAClB,QAAM,CAAC,KAAK,MAAM,IAAID,MAAAA,SAEpB,IAAI;AACN,QAAM,UAAUE,MAAAA,OAAuB,IAAI;AAC3C,QAAM,YAAYA,MAAAA,OAA0B,IAAI;AAChD,QAAM,WAAWA,MAAAA,OAAuB,IAAI;AAE5CC,aAAAA,eAAe,MAAM,MAAM;;AACzB,YAAQ,KAAK;AACb,oBAAU,YAAV,mBAAmB;AAAA,EACrB,CAAC;AAGDC,QAAAA,gBAAgB,MAAM;AACpB,QAAI,CAAC,MAAM;AACT,aAAO,IAAI;AACX;AAAA,IACF;AACA,UAAM,SAAS,MAAM;AACnB,YAAM,SAAS,QAAQ;AACvB,UAAI,CAAC,OAAQ;AACb,YAAM,OAAO,OAAO,sBAAA;AACpB,YAAM,cAAc,OAAO,aAAa,KAAK,OAAO;AACpD,YAAM,WAAW,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,oBAAoB,WAAW,CAAC;AAM/E,YAAM,QAAQ,OAAO,cAAc,KAAK,SAAS,qBAAqB;AACtE,YAAM,QAAQ,KAAK,MAAM,qBAAqB;AAC9C,YAAM,OAAO,QAAQ,uBAAuB,QAAQ;AACpD,YAAM,YAAY,KAAK,IAAI,OAAO,QAAQ,OAAO,mBAAmB;AACpE,YAAM,YAAY,KAAK,IAAI,qBAAqB,SAAS;AACzD,aAAO;AAAA,QACL,KAAK,OAAO,KAAK,IAAI,oBAAoB,KAAK,MAAM,IAAI,SAAS,IAAI,KAAK,SAAS;AAAA,QACnF,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IACH;AACA,WAAA;AACA,WAAO,iBAAiB,UAAU,QAAQ,IAAI;AAC9C,WAAO,iBAAiB,UAAU,MAAM;AACxC,WAAO,MAAM;AACX,aAAO,oBAAoB,UAAU,QAAQ,IAAI;AACjD,aAAO,oBAAoB,UAAU,MAAM;AAAA,IAC7C;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAGTC,QAAAA,UAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,gBAAgB,CAAC,MAAkB;;AACvC,YAAM,SAAS,EAAE;AACjB,UAAI,GAAC,aAAQ,YAAR,mBAAiB,SAAS,YAAW,GAAC,cAAS,YAAT,mBAAkB,SAAS,UAAS;AAC7E,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AACA,aAAS,iBAAiB,aAAa,aAAa;AACpD,WAAO,MAAM,SAAS,oBAAoB,aAAa,aAAa;AAAA,EACtE,GAAG,CAAC,IAAI,CAAC;AAET,SACEC,gCAAC,SAAI,KAAK,SAAS,WAAWC,MAAAA,GAAG,YAAY,SAAS,GACnD,UAAA;AAAA,IAAA,gBACC,cAAc;AAAA,MACZ;AAAA,MACA,UAAU,QAAQ,QAAQ;AAAA,MAC1B,YAAY;AAAA,MACZ,QAAQ,MAAM;AACZ,YAAI,CAAC,SAAU,SAAQ,CAAC,YAAY,CAAC,OAAO;AAAA,MAC9C;AAAA,IAAA,CACD,IAEDD,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL;AAAA,QACA,cAAY;AAAA,QACZ,iBAAc;AAAA,QACd,iBAAe;AAAA,QACf,SAAS,MAAM,QAAQ,CAAC,YAAY,CAAC,OAAO;AAAA,QAC5C,WAAWC,MAAAA;AAAAA,UACT;AAAA,UACA,OAAOC,mBAAAA,eAAe,IAAI,IAAI;AAAA,UAC9B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGF,UAAA;AAAA,UAAAC,2BAAAA,IAAC,QAAA,EAAK,WAAWF,MAAAA,GAAG,2BAA2B,SAAS,QAAQ,uBAAuB,GACpF,UAAA,SAAS,YAAA,CACZ;AAAA,UACAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,4FACd,UAAAA,2BAAAA,IAACC,KAAAA,QAAK,MAAMC,cAAAA,eAAe,WAAU,UAAA,CAAU,EAAA,CACjD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAIH,QACC,OACAC,SAAAA;AAAAA,MACEN,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,aAAU;AAAA,UACV,OAAO;AAAA,YACL,UAAU;AAAA,YACV,KAAK,IAAI;AAAA,YACT,MAAM,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,YAKV,QAAQ;AAAA;AAAA;AAAA;AAAA,YAIR,UAAU,IAAI;AAAA,YACd,OAAO;AAAA,YACP,UAAU,IAAI;AAAA,YACd,WAAW,IAAI;AAAA,UAAA;AAAA,UAEjB,WAAWC,MAAAA;AAAAA;AAAAA;AAAAA;AAAAA,YAIT;AAAA,YACA;AAAA,UAAA;AAAA,UAGF,UAAA;AAAA,YAAAE,2BAAAA,IAAC,OAAA,EAAI,WAAU,gCACb,UAAAA,2BAAAA;AAAAA,cAACI,KAAAA;AAAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACC,GAAI,eAAe,EAAE,aAAA,IAAiB,CAAA;AAAA,gBACtC,GAAI,gBAAgB,EAAE,cAAA,IAAkB,CAAA;AAAA,gBACxC,GAAI,cAAc,EAAE,YAAA,IAAgB,CAAA;AAAA,gBACpC,GAAI,kBAAkB,EAAE,gBAAA,IAAoB,CAAA;AAAA,gBAC5C,GAAI,eAAe,EAAE,aAAA,IAAiB,CAAA;AAAA,gBACtC,GAAI,aAAa,SAAY,EAAE,SAAA,IAAa,CAAA;AAAA,gBAC5C,GAAI,mBAAmB,SAAY,EAAE,eAAA,IAAmB,CAAA;AAAA,gBACxD,GAAI,iBAAiB,SAAY,EAAE,aAAA,IAAiB,CAAA;AAAA,gBACpD,GAAI,cAAc,SAAY,EAAE,UAAA,IAAc,CAAA;AAAA,gBAC9C,GAAI,UAAU,SAAY,EAAE,MAAA,IAAU,CAAA;AAAA,gBACvC,UAAU,CAAC,SAAS;AAClB,sBAAI,CAAC,gBAAgB,aAAa,IAAI,GAAG;AACvC,6BAAS,IAAI;AACb,wBAAI,uBAAuB,KAAK;AAAA,kBAClC;AAAA,gBACF;AAAA,cAAA;AAAA,YAAA,GAEJ;AAAA,YACC,gBACCJ,2BAAAA,IAAC,OAAA,EAAI,WAAU,8CACZ,UAAA,aAAa,EAAE,OAAO,MAAM,QAAQ,KAAK,EAAA,CAAG,EAAA,CAC/C;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGJ,SAAS;AAAA,IAAA;AAAA,EACX,GACJ;AAEJ;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, Ref } from '
|
|
1
|
+
import { ReactNode, Ref } from 'react';
|
|
2
2
|
import { TreeProps } from '../data/Tree';
|
|
3
3
|
import { FormSize } from './json-schema-form-size';
|
|
4
4
|
export interface TreePickerFieldProps<T> {
|
|
@@ -6,18 +6,25 @@ export interface TreePickerFieldProps<T> {
|
|
|
6
6
|
roots: T[];
|
|
7
7
|
getKey: (node: T) => string | number;
|
|
8
8
|
getChildren: (node: T) => T[] | undefined;
|
|
9
|
+
getAriaLabel?: TreeProps<T>["getAriaLabel"];
|
|
9
10
|
renderRow: TreeProps<T>["renderRow"];
|
|
10
11
|
getSearchText?: (node: T) => string;
|
|
11
12
|
defaultOpen?: (node: T, depth: number) => boolean;
|
|
13
|
+
/** Reports nodes whose children should be fetched when first expanded. */
|
|
14
|
+
hasMoreChildren?: TreeProps<T>["hasMoreChildren"];
|
|
15
|
+
/** Fetches a lazy node's children when it is first expanded. */
|
|
16
|
+
loadChildren?: TreeProps<T>["loadChildren"];
|
|
12
17
|
/**
|
|
13
18
|
* Decides which nodes commit a selection when clicked. A click on a
|
|
14
19
|
* non-selectable node still toggles its expansion (it never closes the
|
|
15
20
|
* picker). Defaults to every node selectable.
|
|
16
21
|
*/
|
|
17
22
|
isSelectable?: (node: T) => boolean;
|
|
18
|
-
/** Fires
|
|
23
|
+
/** Fires when a selectable node is clicked. */
|
|
19
24
|
onSelect: (node: T) => void;
|
|
20
|
-
/**
|
|
25
|
+
/** Close after a row selection. Disable when a footer explicitly commits the pending node. */
|
|
26
|
+
closeOnSelect?: boolean;
|
|
27
|
+
/** Highlights the selected node inside the open tree. */
|
|
21
28
|
selected?: T | null;
|
|
22
29
|
/**
|
|
23
30
|
* Force-opens the `selected` node's ancestors so the current value is always
|
|
@@ -48,6 +55,8 @@ export interface TreePickerFieldProps<T> {
|
|
|
48
55
|
renderFooter?: (props: {
|
|
49
56
|
close: () => void;
|
|
50
57
|
}) => ReactNode;
|
|
58
|
+
/** Accessible name for the closed picker trigger. */
|
|
59
|
+
triggerAriaLabel?: string;
|
|
51
60
|
}
|
|
52
61
|
export interface TreePickerTriggerProps {
|
|
53
62
|
open: boolean;
|
|
@@ -55,5 +64,5 @@ export interface TreePickerTriggerProps {
|
|
|
55
64
|
triggerRef: Ref<HTMLButtonElement>;
|
|
56
65
|
toggle: () => void;
|
|
57
66
|
}
|
|
58
|
-
export declare function TreePickerField<T>({ roots, getKey, getChildren, renderRow, getSearchText, defaultOpen, isSelectable, onSelect, selected, revealSelected, showControls, ariaLabel, empty, label, placeholder, disabled, size, className, triggerClassName, panelClassName, renderTrigger, renderFooter, }: TreePickerFieldProps<T>): import("react").JSX.Element;
|
|
67
|
+
export declare function TreePickerField<T>({ roots, getKey, getChildren, getAriaLabel, renderRow, getSearchText, defaultOpen, hasMoreChildren, loadChildren, isSelectable, onSelect, closeOnSelect, selected, revealSelected, showControls, ariaLabel, empty, label, placeholder, disabled, size, className, triggerClassName, panelClassName, renderTrigger, renderFooter, triggerAriaLabel, }: TreePickerFieldProps<T>): import("react").JSX.Element;
|
|
59
68
|
//# sourceMappingURL=TreePickerField.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreePickerField.d.ts","sourceRoot":"","sources":["../../src/components/TreePickerField.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgD,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAK/F,OAAO,EAAQ,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAaxE,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,wCAAwC;IACxC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,CAAC;IACrC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IACpC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IAClD;;;;OAIG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC;IACpC
|
|
1
|
+
{"version":3,"file":"TreePickerField.d.ts","sourceRoot":"","sources":["../../src/components/TreePickerField.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,11 +15,15 @@ function TreePickerField({
|
|
|
15
15
|
roots,
|
|
16
16
|
getKey,
|
|
17
17
|
getChildren,
|
|
18
|
+
getAriaLabel,
|
|
18
19
|
renderRow,
|
|
19
20
|
getSearchText,
|
|
20
21
|
defaultOpen,
|
|
22
|
+
hasMoreChildren,
|
|
23
|
+
loadChildren,
|
|
21
24
|
isSelectable,
|
|
22
25
|
onSelect,
|
|
26
|
+
closeOnSelect = true,
|
|
23
27
|
selected,
|
|
24
28
|
revealSelected,
|
|
25
29
|
showControls,
|
|
@@ -33,7 +37,8 @@ function TreePickerField({
|
|
|
33
37
|
triggerClassName,
|
|
34
38
|
panelClassName,
|
|
35
39
|
renderTrigger,
|
|
36
|
-
renderFooter
|
|
40
|
+
renderFooter,
|
|
41
|
+
triggerAriaLabel
|
|
37
42
|
}) {
|
|
38
43
|
const [open, setOpen] = useState(false);
|
|
39
44
|
const floatingZ = useFloatingZIndex();
|
|
@@ -104,6 +109,7 @@ function TreePickerField({
|
|
|
104
109
|
ref: anchorRef,
|
|
105
110
|
type: "button",
|
|
106
111
|
disabled,
|
|
112
|
+
"aria-label": triggerAriaLabel,
|
|
107
113
|
"aria-haspopup": "tree",
|
|
108
114
|
"aria-expanded": open,
|
|
109
115
|
onClick: () => setOpen((current) => !current),
|
|
@@ -159,8 +165,11 @@ function TreePickerField({
|
|
|
159
165
|
getKey,
|
|
160
166
|
getChildren,
|
|
161
167
|
renderRow,
|
|
168
|
+
...getAriaLabel ? { getAriaLabel } : {},
|
|
162
169
|
...getSearchText ? { getSearchText } : {},
|
|
163
170
|
...defaultOpen ? { defaultOpen } : {},
|
|
171
|
+
...hasMoreChildren ? { hasMoreChildren } : {},
|
|
172
|
+
...loadChildren ? { loadChildren } : {},
|
|
164
173
|
...selected !== void 0 ? { selected } : {},
|
|
165
174
|
...revealSelected !== void 0 ? { revealSelected } : {},
|
|
166
175
|
...showControls !== void 0 ? { showControls } : {},
|
|
@@ -169,7 +178,7 @@ function TreePickerField({
|
|
|
169
178
|
onSelect: (node) => {
|
|
170
179
|
if (!isSelectable || isSelectable(node)) {
|
|
171
180
|
onSelect(node);
|
|
172
|
-
setOpen(false);
|
|
181
|
+
if (closeOnSelect) setOpen(false);
|
|
173
182
|
}
|
|
174
183
|
}
|
|
175
184
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TreePickerField.js","sources":["../../src/components/TreePickerField.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronDown } from \"../icons\";\nimport { Tree, type TreeProps } from \"../data/Tree\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\nimport { inputSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// Upper bound the open panel grows to so wide trees show full labels before\n// truncating; the panel is never narrower than the trigger.\nconst PANEL_MAX_WIDTH_PX = 480;\n// Tallest the panel gets when the viewport allows it.\nconst PANEL_MAX_HEIGHT_PX = 480;\n// Below this there is not enough room to be worth opening downward, so the panel\n// flips above the trigger instead.\nconst PANEL_MIN_HEIGHT_PX = 200;\n// Breathing room kept between the panel and the viewport edge.\nconst VIEWPORT_MARGIN_PX = 8;\n\nexport interface TreePickerFieldProps<T> {\n /** Root nodes of the tree to browse. */\n roots: T[];\n getKey: (node: T) => string | number;\n getChildren: (node: T) => T[] | undefined;\n renderRow: TreeProps<T>[\"renderRow\"];\n getSearchText?: (node: T) => string;\n defaultOpen?: (node: T, depth: number) => boolean;\n /**\n * Decides which nodes commit a selection when clicked. A click on a\n * non-selectable node still toggles its expansion (it never closes the\n * picker). Defaults to every node selectable.\n */\n isSelectable?: (node: T) => boolean;\n /** Fires for a selectable node, then closes the dropdown. */\n onSelect: (node: T) => void;\n /** Highlights the committed node inside the open tree. */\n selected?: T | null;\n /**\n * Force-opens the `selected` node's ancestors so the current value is always\n * visible when the panel opens, however deep its branch. Requires `selected`.\n */\n revealSelected?: boolean;\n /** Renders the tree's expand/collapse + filter toolbar. */\n showControls?: boolean;\n /** Accessible name for the tree inside the panel. */\n ariaLabel?: string;\n /** Empty-state content when `roots` is empty. */\n empty?: ReactNode;\n /** Current-selection display in the trigger; falls back to `placeholder`. */\n label?: ReactNode;\n placeholder?: string;\n disabled?: boolean;\n size?: FormSize;\n className?: string;\n triggerClassName?: string;\n panelClassName?: string;\n renderTrigger?: (props: TreePickerTriggerProps) => ReactNode;\n /**\n * Sticky row pinned below the tree inside the open panel — an escape hatch\n * from a dropdown that has run out of room (a fuller browser, a \"create new\")\n * rather than another node. It is handed `close` because acting on it almost\n * always means leaving the dropdown behind.\n */\n renderFooter?: (props: { close: () => void }) => ReactNode;\n}\n\nexport interface TreePickerTriggerProps {\n open: boolean;\n disabled: boolean;\n triggerRef: Ref<HTMLButtonElement>;\n toggle: () => void;\n}\n\n// TreePickerField is a form-field-styled trigger (matching Combobox's closed\n// input) that opens a portal-anchored dropdown holding a Tree. The dropdown is\n// positioned with fixed coordinates measured from the trigger so it escapes any\n// overflow-hidden / scroll ancestor (e.g. a modal body). A click on a selectable\n// node commits and closes; a non-selectable node only toggles expansion.\nexport function TreePickerField<T>({\n roots,\n getKey,\n getChildren,\n renderRow,\n getSearchText,\n defaultOpen,\n isSelectable,\n onSelect,\n selected,\n revealSelected,\n showControls,\n ariaLabel,\n empty,\n label,\n placeholder = \"Select…\",\n disabled,\n size,\n className,\n triggerClassName,\n panelClassName,\n renderTrigger,\n renderFooter,\n}: TreePickerFieldProps<T>) {\n const [open, setOpen] = useState(false);\n const floatingZ = useFloatingZIndex();\n const [pos, setPos] = useState<\n { top: number; left: number; width: number; maxWidth: number; maxHeight: number } | null\n >(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEscapeLayer(open, () => {\n setOpen(false);\n anchorRef.current?.focus();\n });\n\n // Position the portaled panel from the trigger rect, repositioning while open.\n useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = rootRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const viewportCap = window.innerWidth - rect.left - VIEWPORT_MARGIN_PX;\n const maxWidth = Math.max(rect.width, Math.min(PANEL_MAX_WIDTH_PX, viewportCap));\n // Fit the panel to the room the trigger actually has, and flip it above\n // when there is more room up there. Without this the panel keeps its full\n // height wherever the trigger sits, so a trigger low on the page pushes\n // the panel's bottom past the viewport — taking the sticky footer, and\n // any escape hatch pinned to it, out of reach entirely.\n const below = window.innerHeight - rect.bottom - VIEWPORT_MARGIN_PX - 4;\n const above = rect.top - VIEWPORT_MARGIN_PX - 4;\n const flip = below < PANEL_MIN_HEIGHT_PX && above > below;\n const available = Math.max(flip ? above : below, PANEL_MIN_HEIGHT_PX);\n const maxHeight = Math.min(PANEL_MAX_HEIGHT_PX, available);\n setPos({\n top: flip ? Math.max(VIEWPORT_MARGIN_PX, rect.top - 4 - maxHeight) : rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n maxWidth,\n maxHeight,\n });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open]);\n\n // Dismiss on an outside pointer-down (the trigger and panel are exempt).\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!rootRef.current?.contains(target) && !panelRef.current?.contains(target)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n {renderTrigger ? (\n renderTrigger({\n open,\n disabled: Boolean(disabled),\n triggerRef: anchorRef,\n toggle: () => {\n if (!disabled) setOpen((current) => !current);\n },\n })\n ) : (\n <button\n ref={anchorRef}\n type=\"button\"\n disabled={disabled}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={() => setOpen((current) => !current)}\n className={cn(\n \"relative flex w-full items-center rounded-md border border-input bg-background text-left text-foreground\",\n size ? inputSizeClass[size] : \"h-control-h px-control-px text-sm\",\n \"pr-8\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n triggerClassName,\n )}\n >\n <span className={cn(\"min-w-0 flex-1 truncate\", label == null && \"text-muted-foreground\")}>\n {label ?? placeholder}\n </span>\n <span className=\"pointer-events-none absolute right-0 flex h-full items-center px-2 text-muted-foreground\">\n <Icon icon={UiChevronDown} className=\"text-xs\" />\n </span>\n </button>\n )}\n\n {open &&\n pos &&\n createPortal(\n <div\n ref={panelRef}\n data-slot=\"tree-picker-popup\"\n style={{\n position: \"fixed\",\n top: pos.top,\n left: pos.left,\n // Computed rather than constant: the popup has to clear whatever\n // modal is open, and a modal sits at zIndex.modal (10000). A\n // hardcoded z-50 renders the tree behind any dialog it is opened\n // in — see ../overlay/zIndex.\n zIndex: floatingZ,\n // Grow to fit the widest row/toolbar, but never narrower than the\n // trigger nor wider than maxWidth — so labels show in full and the\n // toolbar's intrinsic-width search input never forces a scrollbar.\n minWidth: pos.width,\n width: \"max-content\",\n maxWidth: pos.maxWidth,\n maxHeight: pos.maxHeight,\n }}\n className={cn(\n // Height comes from the measured maxHeight above, not a viewport\n // fraction: 60vh is the same number wherever the trigger sits, and\n // a trigger low on the page needs a shorter panel, not an equal one.\n \"flex flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md\",\n panelClassName,\n )}\n >\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <Tree<T>\n roots={roots}\n getKey={getKey}\n getChildren={getChildren}\n renderRow={renderRow}\n {...(getSearchText ? { getSearchText } : {})}\n {...(defaultOpen ? { defaultOpen } : {})}\n {...(selected !== undefined ? { selected } : {})}\n {...(revealSelected !== undefined ? { revealSelected } : {})}\n {...(showControls !== undefined ? { showControls } : {})}\n {...(ariaLabel !== undefined ? { ariaLabel } : {})}\n {...(empty !== undefined ? { empty } : {})}\n onSelect={(node) => {\n if (!isSelectable || isSelectable(node)) {\n onSelect(node);\n setOpen(false);\n }\n }}\n />\n </div>\n {renderFooter && (\n <div className=\"shrink-0 border-t border-border bg-popover\">\n {renderFooter({ close: () => setOpen(false) })}\n </div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TreePickerField.js","sources":["../../src/components/TreePickerField.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type Ref } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../data/Icon\";\nimport { UiChevronDown } from \"../icons\";\nimport { Tree, type TreeProps } from \"../data/Tree\";\nimport { useEscapeLayer, useFloatingZIndex } from \"../overlay/modalStack\";\nimport { inputSizeClass, type FormSize } from \"./json-schema-form-size\";\n\n// Upper bound the open panel grows to so wide trees show full labels before\n// truncating; the panel is never narrower than the trigger.\nconst PANEL_MAX_WIDTH_PX = 480;\n// Tallest the panel gets when the viewport allows it.\nconst PANEL_MAX_HEIGHT_PX = 480;\n// Below this there is not enough room to be worth opening downward, so the panel\n// flips above the trigger instead.\nconst PANEL_MIN_HEIGHT_PX = 200;\n// Breathing room kept between the panel and the viewport edge.\nconst VIEWPORT_MARGIN_PX = 8;\n\nexport interface TreePickerFieldProps<T> {\n /** Root nodes of the tree to browse. */\n roots: T[];\n getKey: (node: T) => string | number;\n getChildren: (node: T) => T[] | undefined;\n getAriaLabel?: TreeProps<T>[\"getAriaLabel\"];\n renderRow: TreeProps<T>[\"renderRow\"];\n getSearchText?: (node: T) => string;\n defaultOpen?: (node: T, depth: number) => boolean;\n /** Reports nodes whose children should be fetched when first expanded. */\n hasMoreChildren?: TreeProps<T>[\"hasMoreChildren\"];\n /** Fetches a lazy node's children when it is first expanded. */\n loadChildren?: TreeProps<T>[\"loadChildren\"];\n /**\n * Decides which nodes commit a selection when clicked. A click on a\n * non-selectable node still toggles its expansion (it never closes the\n * picker). Defaults to every node selectable.\n */\n isSelectable?: (node: T) => boolean;\n /** Fires when a selectable node is clicked. */\n onSelect: (node: T) => void;\n /** Close after a row selection. Disable when a footer explicitly commits the pending node. */\n closeOnSelect?: boolean;\n /** Highlights the selected node inside the open tree. */\n selected?: T | null;\n /**\n * Force-opens the `selected` node's ancestors so the current value is always\n * visible when the panel opens, however deep its branch. Requires `selected`.\n */\n revealSelected?: boolean;\n /** Renders the tree's expand/collapse + filter toolbar. */\n showControls?: boolean;\n /** Accessible name for the tree inside the panel. */\n ariaLabel?: string;\n /** Empty-state content when `roots` is empty. */\n empty?: ReactNode;\n /** Current-selection display in the trigger; falls back to `placeholder`. */\n label?: ReactNode;\n placeholder?: string;\n disabled?: boolean;\n size?: FormSize;\n className?: string;\n triggerClassName?: string;\n panelClassName?: string;\n renderTrigger?: (props: TreePickerTriggerProps) => ReactNode;\n /**\n * Sticky row pinned below the tree inside the open panel — an escape hatch\n * from a dropdown that has run out of room (a fuller browser, a \"create new\")\n * rather than another node. It is handed `close` because acting on it almost\n * always means leaving the dropdown behind.\n */\n renderFooter?: (props: { close: () => void }) => ReactNode;\n /** Accessible name for the closed picker trigger. */\n triggerAriaLabel?: string;\n}\n\nexport interface TreePickerTriggerProps {\n open: boolean;\n disabled: boolean;\n triggerRef: Ref<HTMLButtonElement>;\n toggle: () => void;\n}\n\n// TreePickerField is a form-field-styled trigger (matching Combobox's closed\n// input) that opens a portal-anchored dropdown holding a Tree. The dropdown is\n// positioned with fixed coordinates measured from the trigger so it escapes any\n// overflow-hidden / scroll ancestor (e.g. a modal body). A click on a selectable\n// node commits and closes; a non-selectable node only toggles expansion.\nexport function TreePickerField<T>({\n roots,\n getKey,\n getChildren,\n getAriaLabel,\n renderRow,\n getSearchText,\n defaultOpen,\n hasMoreChildren,\n loadChildren,\n isSelectable,\n onSelect,\n closeOnSelect = true,\n selected,\n revealSelected,\n showControls,\n ariaLabel,\n empty,\n label,\n placeholder = \"Select…\",\n disabled,\n size,\n className,\n triggerClassName,\n panelClassName,\n renderTrigger,\n renderFooter,\n triggerAriaLabel,\n}: TreePickerFieldProps<T>) {\n const [open, setOpen] = useState(false);\n const floatingZ = useFloatingZIndex();\n const [pos, setPos] = useState<\n { top: number; left: number; width: number; maxWidth: number; maxHeight: number } | null\n >(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const anchorRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n\n useEscapeLayer(open, () => {\n setOpen(false);\n anchorRef.current?.focus();\n });\n\n // Position the portaled panel from the trigger rect, repositioning while open.\n useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = rootRef.current;\n if (!anchor) return;\n const rect = anchor.getBoundingClientRect();\n const viewportCap = window.innerWidth - rect.left - VIEWPORT_MARGIN_PX;\n const maxWidth = Math.max(rect.width, Math.min(PANEL_MAX_WIDTH_PX, viewportCap));\n // Fit the panel to the room the trigger actually has, and flip it above\n // when there is more room up there. Without this the panel keeps its full\n // height wherever the trigger sits, so a trigger low on the page pushes\n // the panel's bottom past the viewport — taking the sticky footer, and\n // any escape hatch pinned to it, out of reach entirely.\n const below = window.innerHeight - rect.bottom - VIEWPORT_MARGIN_PX - 4;\n const above = rect.top - VIEWPORT_MARGIN_PX - 4;\n const flip = below < PANEL_MIN_HEIGHT_PX && above > below;\n const available = Math.max(flip ? above : below, PANEL_MIN_HEIGHT_PX);\n const maxHeight = Math.min(PANEL_MAX_HEIGHT_PX, available);\n setPos({\n top: flip ? Math.max(VIEWPORT_MARGIN_PX, rect.top - 4 - maxHeight) : rect.bottom + 4,\n left: rect.left,\n width: rect.width,\n maxWidth,\n maxHeight,\n });\n };\n update();\n window.addEventListener(\"scroll\", update, true);\n window.addEventListener(\"resize\", update);\n return () => {\n window.removeEventListener(\"scroll\", update, true);\n window.removeEventListener(\"resize\", update);\n };\n }, [open]);\n\n // Dismiss on an outside pointer-down (the trigger and panel are exempt).\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!rootRef.current?.contains(target) && !panelRef.current?.contains(target)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n return () => document.removeEventListener(\"mousedown\", onPointerDown);\n }, [open]);\n\n return (\n <div ref={rootRef} className={cn(\"relative\", className)}>\n {renderTrigger ? (\n renderTrigger({\n open,\n disabled: Boolean(disabled),\n triggerRef: anchorRef,\n toggle: () => {\n if (!disabled) setOpen((current) => !current);\n },\n })\n ) : (\n <button\n ref={anchorRef}\n type=\"button\"\n disabled={disabled}\n aria-label={triggerAriaLabel}\n aria-haspopup=\"tree\"\n aria-expanded={open}\n onClick={() => setOpen((current) => !current)}\n className={cn(\n \"relative flex w-full items-center rounded-md border border-input bg-background text-left text-foreground\",\n size ? inputSizeClass[size] : \"h-control-h px-control-px text-sm\",\n \"pr-8\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n triggerClassName,\n )}\n >\n <span className={cn(\"min-w-0 flex-1 truncate\", label == null && \"text-muted-foreground\")}>\n {label ?? placeholder}\n </span>\n <span className=\"pointer-events-none absolute right-0 flex h-full items-center px-2 text-muted-foreground\">\n <Icon icon={UiChevronDown} className=\"text-xs\" />\n </span>\n </button>\n )}\n\n {open &&\n pos &&\n createPortal(\n <div\n ref={panelRef}\n data-slot=\"tree-picker-popup\"\n style={{\n position: \"fixed\",\n top: pos.top,\n left: pos.left,\n // Computed rather than constant: the popup has to clear whatever\n // modal is open, and a modal sits at zIndex.modal (10000). A\n // hardcoded z-50 renders the tree behind any dialog it is opened\n // in — see ../overlay/zIndex.\n zIndex: floatingZ,\n // Grow to fit the widest row/toolbar, but never narrower than the\n // trigger nor wider than maxWidth — so labels show in full and the\n // toolbar's intrinsic-width search input never forces a scrollbar.\n minWidth: pos.width,\n width: \"max-content\",\n maxWidth: pos.maxWidth,\n maxHeight: pos.maxHeight,\n }}\n className={cn(\n // Height comes from the measured maxHeight above, not a viewport\n // fraction: 60vh is the same number wherever the trigger sits, and\n // a trigger low on the page needs a shorter panel, not an equal one.\n \"flex flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md\",\n panelClassName,\n )}\n >\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <Tree<T>\n roots={roots}\n getKey={getKey}\n getChildren={getChildren}\n renderRow={renderRow}\n {...(getAriaLabel ? { getAriaLabel } : {})}\n {...(getSearchText ? { getSearchText } : {})}\n {...(defaultOpen ? { defaultOpen } : {})}\n {...(hasMoreChildren ? { hasMoreChildren } : {})}\n {...(loadChildren ? { loadChildren } : {})}\n {...(selected !== undefined ? { selected } : {})}\n {...(revealSelected !== undefined ? { revealSelected } : {})}\n {...(showControls !== undefined ? { showControls } : {})}\n {...(ariaLabel !== undefined ? { ariaLabel } : {})}\n {...(empty !== undefined ? { empty } : {})}\n onSelect={(node) => {\n if (!isSelectable || isSelectable(node)) {\n onSelect(node);\n if (closeOnSelect) setOpen(false);\n }\n }}\n />\n </div>\n {renderFooter && (\n <div className=\"shrink-0 border-t border-border bg-popover\">\n {renderFooter({ close: () => setOpen(false) })}\n </div>\n )}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
|
-
import { ButtonHTMLAttributes, ReactNode } from '
|
|
2
|
+
import { ButtonHTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
import { buttonVariants } from './button-variants';
|
|
4
4
|
export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants> & {
|
|
5
5
|
/** Render the button styles onto the child element via Radix Slot. */
|
|
@@ -9,7 +9,7 @@ export type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & VariantProps
|
|
|
9
9
|
/** Label to render while loading; defaults to the normal children. */
|
|
10
10
|
loadingLabel?: ReactNode;
|
|
11
11
|
};
|
|
12
|
-
export declare const Button: import('
|
|
12
|
+
export declare const Button: import('react').ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
|
|
13
13
|
variant?: "link" | "default" | "outline" | "destructive" | "secondary" | "ghost" | null | undefined;
|
|
14
14
|
size?: "sm" | "lg" | "icon" | "default" | null | undefined;
|
|
15
15
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string> & {
|
|
@@ -19,5 +19,5 @@ export declare const Button: import('../../../../node_modules/@types/react/index
|
|
|
19
19
|
loading?: boolean;
|
|
20
20
|
/** Label to render while loading; defaults to the normal children. */
|
|
21
21
|
loadingLabel?: ReactNode;
|
|
22
|
-
} & import('
|
|
22
|
+
} & import('react').RefAttributes<HTMLButtonElement>>;
|
|
23
23
|
//# sourceMappingURL=button.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KeyboardEvent, ReactNode } from '
|
|
1
|
+
import { KeyboardEvent, ReactNode } from 'react';
|
|
2
2
|
import { LabelIconSpec } from '../data/Icon';
|
|
3
3
|
import { FormSize } from './json-schema-form-size';
|
|
4
4
|
export type ComboboxOption = {
|
|
@@ -6,5 +6,5 @@ export type DensitySwitcherProps = {
|
|
|
6
6
|
/** Classes applied to the popup menu. */
|
|
7
7
|
menuClassName?: string;
|
|
8
8
|
};
|
|
9
|
-
export declare const DensitySwitcher: import('
|
|
9
|
+
export declare const DensitySwitcher: import('react').ForwardRefExoticComponent<DensitySwitcherProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
10
10
|
//# sourceMappingURL=density-switcher.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const FILTER_INPUT_DEBOUNCE_MS = 500;
|
|
2
|
-
export declare const FilterBarContext: import('
|
|
2
|
+
export declare const FilterBarContext: import('react').Context<{
|
|
3
3
|
autoSubmit: boolean;
|
|
4
4
|
}>;
|
|
5
5
|
//# sourceMappingURL=filter-bar-context.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode } from '
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
import { FilterMode } from '../data/FilterPill';
|
|
3
3
|
import { LabelIconSpec } from '../data/Icon';
|
|
4
4
|
import { MultiSelectOption } from './MultiSelect';
|
|
@@ -6,7 +6,7 @@ export type FilterBarMultiFilterMode = Extract<FilterMode, "include" | "exclude"
|
|
|
6
6
|
export declare function mergeMultiSelectOptions(head: MultiSelectOption[], extra: MultiSelectOption[]): MultiSelectOption[];
|
|
7
7
|
export declare function multiSelectOptionText(option: MultiSelectOption): string;
|
|
8
8
|
export declare function summarizeMultiFilter(label: string, value: Record<string, FilterBarMultiFilterMode>): string;
|
|
9
|
-
export declare function useDebouncedMultiDraft(value: Record<string, FilterBarMultiFilterMode>, onChange: (value: Record<string, FilterBarMultiFilterMode>) => void): readonly [Record<string, FilterBarMultiFilterMode>, import('
|
|
9
|
+
export declare function useDebouncedMultiDraft(value: Record<string, FilterBarMultiFilterMode>, onChange: (value: Record<string, FilterBarMultiFilterMode>) => void): readonly [Record<string, FilterBarMultiFilterMode>, import('react').Dispatch<import('react').SetStateAction<Record<string, FilterBarMultiFilterMode>>>];
|
|
10
10
|
export declare function updateMultiFilterValue(current: Record<string, FilterBarMultiFilterMode>, optionValue: string, nextMode: FilterMode): Record<string, FilterBarMultiFilterMode>;
|
|
11
11
|
export declare function nextFilterMode(mode: FilterMode): FilterMode;
|
|
12
12
|
export declare function sizedIcon(icon: LabelIconSpec | undefined, px: number): LabelIconSpec | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LookupDescriptor, LookupFetcher } from './json-schema-form-types';
|
|
2
|
-
export declare const FormLookupContext: import('
|
|
2
|
+
export declare const FormLookupContext: import('react').Context<LookupFetcher | undefined>;
|
|
3
3
|
export declare function useLookupFetcher(): LookupFetcher | undefined;
|
|
4
4
|
export declare function resolveLookupScope(descriptor: LookupDescriptor, rootValue: Record<string, unknown> | undefined): Record<string, string>;
|
|
5
5
|
//# sourceMappingURL=form-lookup-context.d.ts.map
|