@ctrl-ui/react 0.8.0
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 +70 -0
- package/dist/action-bar.d.ts +44 -0
- package/dist/action-bar.js +89 -0
- package/dist/activity.d.ts +53 -0
- package/dist/activity.js +188 -0
- package/dist/audio-recorder.d.ts +32 -0
- package/dist/audio-recorder.js +235 -0
- package/dist/audio-visualizer.d.ts +12 -0
- package/dist/audio-visualizer.js +58 -0
- package/dist/blocks/chat.d.ts +10 -0
- package/dist/blocks/chat.js +12 -0
- package/dist/blocks/coding-agent.d.ts +61 -0
- package/dist/blocks/coding-agent.js +255 -0
- package/dist/blocks/file-explorer-data.d.ts +57 -0
- package/dist/blocks/file-explorer-data.js +74 -0
- package/dist/blocks/file-explorer.d.ts +24 -0
- package/dist/blocks/file-explorer.js +427 -0
- package/dist/blocks/settings-data.d.ts +36 -0
- package/dist/blocks/settings-data.js +66 -0
- package/dist/blocks/settings.d.ts +19 -0
- package/dist/blocks/settings.js +282 -0
- package/dist/blocks/theme-toggle.d.ts +43 -0
- package/dist/blocks/theme-toggle.js +180 -0
- package/dist/chat-composer-attachment.d.ts +55 -0
- package/dist/chat-composer-attachment.js +267 -0
- package/dist/chat-composer-editor/extensions/mention.d.ts +14 -0
- package/dist/chat-composer-editor/extensions/mention.js +278 -0
- package/dist/chat-composer-editor/ghost.d.ts +5 -0
- package/dist/chat-composer-editor/ghost.js +55 -0
- package/dist/chat-composer-editor/schema.d.ts +6 -0
- package/dist/chat-composer-editor/schema.js +25 -0
- package/dist/chat-composer-editor/serialize.d.ts +6 -0
- package/dist/chat-composer-editor/serialize.js +16 -0
- package/dist/chat-composer-editor/types.d.ts +29 -0
- package/dist/chat-composer-editor/types.js +0 -0
- package/dist/chat-composer-editor.d.ts +9 -0
- package/dist/chat-composer-editor.js +154 -0
- package/dist/chat-composer.d.ts +60 -0
- package/dist/chat-composer.js +134 -0
- package/dist/chat-layout.d.ts +27 -0
- package/dist/chat-layout.js +114 -0
- package/dist/chat-message.d.ts +31 -0
- package/dist/chat-message.js +95 -0
- package/dist/code-block-editor.d.ts +59 -0
- package/dist/code-block-editor.js +250 -0
- package/dist/context-model.d.ts +33 -0
- package/dist/context-model.js +52 -0
- package/dist/context.d.ts +47 -0
- package/dist/context.js +335 -0
- package/dist/control-props.d.ts +28 -0
- package/dist/control-props.js +4 -0
- package/dist/control-variants.d.ts +8 -0
- package/dist/control-variants.js +14 -0
- package/dist/dynamic-notification-glass.d.ts +10 -0
- package/dist/dynamic-notification-glass.js +311 -0
- package/dist/dynamic-notification-liquid.d.ts +24 -0
- package/dist/dynamic-notification-liquid.js +682 -0
- package/dist/dynamic-notification-siri-wave.d.ts +4 -0
- package/dist/dynamic-notification-siri-wave.js +82 -0
- package/dist/dynamic-notification.d.ts +74 -0
- package/dist/dynamic-notification.js +342 -0
- package/dist/environment-variables.d.ts +124 -0
- package/dist/environment-variables.js +492 -0
- package/dist/extensions/create-track-highlight.d.ts +12 -0
- package/dist/extensions/create-track-highlight.js +147 -0
- package/dist/extensions/track-highlight.d.ts +22 -0
- package/dist/extensions/track-highlight.js +52 -0
- package/dist/hooks/use-audio-recorder.d.ts +107 -0
- package/dist/hooks/use-audio-recorder.js +577 -0
- package/dist/hooks/use-chat-composer.d.ts +56 -0
- package/dist/hooks/use-chat-composer.js +63 -0
- package/dist/hooks/use-chat-message.d.ts +28 -0
- package/dist/hooks/use-chat-message.js +24 -0
- package/dist/hooks/use-color-area.d.ts +18 -0
- package/dist/hooks/use-color-area.js +60 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +22 -0
- package/dist/hooks/use-copy-to-clipboard.js +90 -0
- package/dist/hooks/use-dropzone.d.ts +59 -0
- package/dist/hooks/use-dropzone.js +372 -0
- package/dist/hooks/use-dynamic-notification.d.ts +37 -0
- package/dist/hooks/use-dynamic-notification.js +87 -0
- package/dist/hooks/use-environment-variables.d.ts +51 -0
- package/dist/hooks/use-environment-variables.js +188 -0
- package/dist/hooks/use-mobile.d.ts +5 -0
- package/dist/hooks/use-mobile.js +29 -0
- package/dist/hooks/use-textarea-trigger-menu.d.ts +8 -0
- package/dist/hooks/use-textarea-trigger-menu.js +69 -0
- package/dist/hooks/use-trigger-menu.d.ts +49 -0
- package/dist/hooks/use-trigger-menu.js +102 -0
- package/dist/hooks/use-user-ask.d.ts +48 -0
- package/dist/hooks/use-user-ask.js +167 -0
- package/dist/inline-attachment.d.ts +37 -0
- package/dist/inline-attachment.js +192 -0
- package/dist/inline-citation.d.ts +56 -0
- package/dist/inline-citation.js +319 -0
- package/dist/knob-contracts/accordion-knobs.d.ts +5 -0
- package/dist/knob-contracts/accordion-knobs.js +9 -0
- package/dist/knob-contracts/action-bar-knobs.d.ts +5 -0
- package/dist/knob-contracts/action-bar-knobs.js +4 -0
- package/dist/knob-contracts/activity-knobs.d.ts +5 -0
- package/dist/knob-contracts/activity-knobs.js +9 -0
- package/dist/knob-contracts/alert-knobs.d.ts +5 -0
- package/dist/knob-contracts/alert-knobs.js +9 -0
- package/dist/knob-contracts/audio-recorder-knobs.d.ts +5 -0
- package/dist/knob-contracts/audio-recorder-knobs.js +9 -0
- package/dist/knob-contracts/audio-visualizer-knobs.d.ts +5 -0
- package/dist/knob-contracts/audio-visualizer-knobs.js +9 -0
- package/dist/knob-contracts/avatar-knobs.d.ts +5 -0
- package/dist/knob-contracts/avatar-knobs.js +9 -0
- package/dist/knob-contracts/badge-knobs.d.ts +5 -0
- package/dist/knob-contracts/badge-knobs.js +9 -0
- package/dist/knob-contracts/button-group-knobs.d.ts +5 -0
- package/dist/knob-contracts/button-group-knobs.js +9 -0
- package/dist/knob-contracts/button-knobs.d.ts +5 -0
- package/dist/knob-contracts/button-knobs.js +25 -0
- package/dist/knob-contracts/calendar-knobs.d.ts +5 -0
- package/dist/knob-contracts/calendar-knobs.js +10 -0
- package/dist/knob-contracts/card-knobs.d.ts +5 -0
- package/dist/knob-contracts/card-knobs.js +11 -0
- package/dist/knob-contracts/chat-composer-attachment-knobs.d.ts +5 -0
- package/dist/knob-contracts/chat-composer-attachment-knobs.js +11 -0
- package/dist/knob-contracts/chat-composer-knobs.d.ts +5 -0
- package/dist/knob-contracts/chat-composer-knobs.js +18 -0
- package/dist/knob-contracts/chat-layout-knobs.d.ts +5 -0
- package/dist/knob-contracts/chat-layout-knobs.js +11 -0
- package/dist/knob-contracts/chat-message-knobs.d.ts +5 -0
- package/dist/knob-contracts/chat-message-knobs.js +17 -0
- package/dist/knob-contracts/choice-knobs.d.ts +5 -0
- package/dist/knob-contracts/choice-knobs.js +9 -0
- package/dist/knob-contracts/code-block-editor-knobs.d.ts +5 -0
- package/dist/knob-contracts/code-block-editor-knobs.js +11 -0
- package/dist/knob-contracts/code-diff-knobs.d.ts +5 -0
- package/dist/knob-contracts/code-diff-knobs.js +18 -0
- package/dist/knob-contracts/code-knobs.d.ts +5 -0
- package/dist/knob-contracts/code-knobs.js +11 -0
- package/dist/knob-contracts/collapsible-knobs.d.ts +5 -0
- package/dist/knob-contracts/collapsible-knobs.js +4 -0
- package/dist/knob-contracts/color-picker-knobs.d.ts +5 -0
- package/dist/knob-contracts/color-picker-knobs.js +12 -0
- package/dist/knob-contracts/context-knobs.d.ts +5 -0
- package/dist/knob-contracts/context-knobs.js +13 -0
- package/dist/knob-contracts/dockable-panel-knobs.d.ts +5 -0
- package/dist/knob-contracts/dockable-panel-knobs.js +12 -0
- package/dist/knob-contracts/dropzone-knobs.d.ts +5 -0
- package/dist/knob-contracts/dropzone-knobs.js +11 -0
- package/dist/knob-contracts/dynamic-notification-knobs.d.ts +5 -0
- package/dist/knob-contracts/dynamic-notification-knobs.js +18 -0
- package/dist/knob-contracts/empty-knobs.d.ts +5 -0
- package/dist/knob-contracts/empty-knobs.js +12 -0
- package/dist/knob-contracts/environment-variables-knobs.d.ts +5 -0
- package/dist/knob-contracts/environment-variables-knobs.js +11 -0
- package/dist/knob-contracts/field-knobs.d.ts +5 -0
- package/dist/knob-contracts/field-knobs.js +16 -0
- package/dist/knob-contracts/gradient-editor-knobs.d.ts +5 -0
- package/dist/knob-contracts/gradient-editor-knobs.js +13 -0
- package/dist/knob-contracts/infinite-canvas-knobs.d.ts +5 -0
- package/dist/knob-contracts/infinite-canvas-knobs.js +13 -0
- package/dist/knob-contracts/inline-attachment-knobs.d.ts +5 -0
- package/dist/knob-contracts/inline-attachment-knobs.js +14 -0
- package/dist/knob-contracts/inline-citation-knobs.d.ts +5 -0
- package/dist/knob-contracts/inline-citation-knobs.js +14 -0
- package/dist/knob-contracts/item-knobs.d.ts +5 -0
- package/dist/knob-contracts/item-knobs.js +10 -0
- package/dist/knob-contracts/kbd-knobs.d.ts +5 -0
- package/dist/knob-contracts/kbd-knobs.js +10 -0
- package/dist/knob-contracts/markdown-block-knobs.d.ts +5 -0
- package/dist/knob-contracts/markdown-block-knobs.js +11 -0
- package/dist/knob-contracts/markdown-knobs.d.ts +5 -0
- package/dist/knob-contracts/markdown-knobs.js +14 -0
- package/dist/knob-contracts/morphing-panel-knobs.d.ts +5 -0
- package/dist/knob-contracts/morphing-panel-knobs.js +11 -0
- package/dist/knob-contracts/pagination-knobs.d.ts +5 -0
- package/dist/knob-contracts/pagination-knobs.js +10 -0
- package/dist/knob-contracts/phone-input-knobs.d.ts +5 -0
- package/dist/knob-contracts/phone-input-knobs.js +10 -0
- package/dist/knob-contracts/popup-knobs.d.ts +5 -0
- package/dist/knob-contracts/popup-knobs.js +21 -0
- package/dist/knob-contracts/range-knobs.d.ts +5 -0
- package/dist/knob-contracts/range-knobs.js +13 -0
- package/dist/knob-contracts/resizable-knobs.d.ts +5 -0
- package/dist/knob-contracts/resizable-knobs.js +14 -0
- package/dist/knob-contracts/rich-tooltip-knobs.d.ts +5 -0
- package/dist/knob-contracts/rich-tooltip-knobs.js +13 -0
- package/dist/knob-contracts/scroll-area-knobs.d.ts +5 -0
- package/dist/knob-contracts/scroll-area-knobs.js +8 -0
- package/dist/knob-contracts/separator-knobs.d.ts +5 -0
- package/dist/knob-contracts/separator-knobs.js +4 -0
- package/dist/knob-contracts/sidebar-knobs.d.ts +5 -0
- package/dist/knob-contracts/sidebar-knobs.js +26 -0
- package/dist/knob-contracts/skeleton-knobs.d.ts +5 -0
- package/dist/knob-contracts/skeleton-knobs.js +4 -0
- package/dist/knob-contracts/source-badge-knobs.d.ts +5 -0
- package/dist/knob-contracts/source-badge-knobs.js +11 -0
- package/dist/knob-contracts/spinner-knobs.d.ts +5 -0
- package/dist/knob-contracts/spinner-knobs.js +4 -0
- package/dist/knob-contracts/stepper-knobs.d.ts +5 -0
- package/dist/knob-contracts/stepper-knobs.js +11 -0
- package/dist/knob-contracts/switch-knobs.d.ts +5 -0
- package/dist/knob-contracts/switch-knobs.js +12 -0
- package/dist/knob-contracts/table-knobs.d.ts +5 -0
- package/dist/knob-contracts/table-knobs.js +12 -0
- package/dist/knob-contracts/table-of-contents-knobs.d.ts +5 -0
- package/dist/knob-contracts/table-of-contents-knobs.js +8 -0
- package/dist/knob-contracts/tabs-knobs.d.ts +5 -0
- package/dist/knob-contracts/tabs-knobs.js +16 -0
- package/dist/knob-contracts/task-list-knobs.d.ts +5 -0
- package/dist/knob-contracts/task-list-knobs.js +14 -0
- package/dist/knob-contracts/thread-rail-knobs.d.ts +5 -0
- package/dist/knob-contracts/thread-rail-knobs.js +14 -0
- package/dist/knob-contracts/timeline-knobs.d.ts +5 -0
- package/dist/knob-contracts/timeline-knobs.js +12 -0
- package/dist/knob-contracts/toolbar-knobs.d.ts +5 -0
- package/dist/knob-contracts/toolbar-knobs.js +20 -0
- package/dist/knob-contracts/track-highlight-knobs.d.ts +5 -0
- package/dist/knob-contracts/track-highlight-knobs.js +11 -0
- package/dist/knob-contracts/transcript-divider-knobs.d.ts +5 -0
- package/dist/knob-contracts/transcript-divider-knobs.js +10 -0
- package/dist/knob-contracts/tree-knobs.d.ts +5 -0
- package/dist/knob-contracts/tree-knobs.js +13 -0
- package/dist/knob-contracts/user-ask-knobs.d.ts +5 -0
- package/dist/knob-contracts/user-ask-knobs.js +17 -0
- package/dist/lib/cn.d.ts +5 -0
- package/dist/lib/cn.js +34 -0
- package/dist/lib/code-block-shiki.d.ts +9 -0
- package/dist/lib/code-block-shiki.js +6 -0
- package/dist/lib/code-tokens.d.ts +28 -0
- package/dist/lib/code-tokens.js +160 -0
- package/dist/lib/color.d.ts +72 -0
- package/dist/lib/color.js +490 -0
- package/dist/lib/contrast.d.ts +30 -0
- package/dist/lib/contrast.js +64 -0
- package/dist/lib/diff.d.ts +50 -0
- package/dist/lib/diff.js +315 -0
- package/dist/lib/dropzone-validation.d.ts +66 -0
- package/dist/lib/dropzone-validation.js +228 -0
- package/dist/lib/env-file.d.ts +28 -0
- package/dist/lib/env-file.js +218 -0
- package/dist/lib/format-audio-recorder-duration.d.ts +4 -0
- package/dist/lib/format-audio-recorder-duration.js +7 -0
- package/dist/lib/liquid-glass-optics.d.ts +4 -0
- package/dist/lib/liquid-glass-optics.js +96 -0
- package/dist/lib/phone-input-format.d.ts +6 -0
- package/dist/lib/phone-input-format.js +26 -0
- package/dist/lib/phone-number.d.ts +18 -0
- package/dist/lib/phone-number.js +28 -0
- package/dist/lib/trigger-detect.d.ts +15 -0
- package/dist/lib/trigger-detect.js +77 -0
- package/dist/markdown-block.d.ts +25 -0
- package/dist/markdown-block.js +77 -0
- package/dist/skin.config.d.ts +5 -0
- package/dist/skin.config.js +4 -0
- package/dist/skin.d.ts +69 -0
- package/dist/skin.js +62 -0
- package/dist/source-badge.d.ts +23 -0
- package/dist/source-badge.js +72 -0
- package/dist/styles/chat-composer-editor.css +44 -0
- package/dist/styles/code.css +57 -0
- package/dist/styles/effects.css +126 -0
- package/dist/styles/index.css +81 -0
- package/dist/styles/recipes/accordion.css +87 -0
- package/dist/styles/recipes/action-bar.css +19 -0
- package/dist/styles/recipes/activity.css +129 -0
- package/dist/styles/recipes/alert.css +75 -0
- package/dist/styles/recipes/audio-recorder.css +102 -0
- package/dist/styles/recipes/audio-visualizer.css +90 -0
- package/dist/styles/recipes/avatar.css +52 -0
- package/dist/styles/recipes/badge.css +110 -0
- package/dist/styles/recipes/button-group.css +64 -0
- package/dist/styles/recipes/button.css +305 -0
- package/dist/styles/recipes/calendar.css +152 -0
- package/dist/styles/recipes/card.css +93 -0
- package/dist/styles/recipes/chat-composer-attachment.css +177 -0
- package/dist/styles/recipes/chat-composer.css +195 -0
- package/dist/styles/recipes/chat-layout.css +108 -0
- package/dist/styles/recipes/chat-message.css +160 -0
- package/dist/styles/recipes/choice.css +108 -0
- package/dist/styles/recipes/code-block-editor.css +136 -0
- package/dist/styles/recipes/code-diff.css +256 -0
- package/dist/styles/recipes/code.css +136 -0
- package/dist/styles/recipes/collapsible.css +27 -0
- package/dist/styles/recipes/color-picker-details.css +61 -0
- package/dist/styles/recipes/color-picker-values.css +117 -0
- package/dist/styles/recipes/color-picker.css +158 -0
- package/dist/styles/recipes/context.css +237 -0
- package/dist/styles/recipes/dockable-panel.css +106 -0
- package/dist/styles/recipes/dropzone.css +149 -0
- package/dist/styles/recipes/dynamic-notification-input.css +29 -0
- package/dist/styles/recipes/dynamic-notification-motion.css +298 -0
- package/dist/styles/recipes/dynamic-notification.css +241 -0
- package/dist/styles/recipes/empty.css +96 -0
- package/dist/styles/recipes/environment-variables.css +173 -0
- package/dist/styles/recipes/field-parts.css +148 -0
- package/dist/styles/recipes/field.css +234 -0
- package/dist/styles/recipes/gradient-editor.css +109 -0
- package/dist/styles/recipes/infinite-canvas.css +78 -0
- package/dist/styles/recipes/inline-attachment.css +182 -0
- package/dist/styles/recipes/inline-citation.css +174 -0
- package/dist/styles/recipes/item.css +107 -0
- package/dist/styles/recipes/kbd.css +55 -0
- package/dist/styles/recipes/markdown-block.css +75 -0
- package/dist/styles/recipes/markdown.css +204 -0
- package/dist/styles/recipes/morphing-panel.css +123 -0
- package/dist/styles/recipes/pagination.css +86 -0
- package/dist/styles/recipes/phone-input.css +105 -0
- package/dist/styles/recipes/popup-controls.css +59 -0
- package/dist/styles/recipes/popup-drawer.css +162 -0
- package/dist/styles/recipes/popup-lists.css +198 -0
- package/dist/styles/recipes/popup-motion.css +94 -0
- package/dist/styles/recipes/popup-toast.css +126 -0
- package/dist/styles/recipes/popup.css +396 -0
- package/dist/styles/recipes/range.css +259 -0
- package/dist/styles/recipes/resizable.css +170 -0
- package/dist/styles/recipes/rich-tooltip.css +272 -0
- package/dist/styles/recipes/scroll-area.css +59 -0
- package/dist/styles/recipes/separator.css +12 -0
- package/dist/styles/recipes/sidebar.css +345 -0
- package/dist/styles/recipes/skeleton.css +23 -0
- package/dist/styles/recipes/source-badge.css +77 -0
- package/dist/styles/recipes/spinner.css +33 -0
- package/dist/styles/recipes/stepper.css +178 -0
- package/dist/styles/recipes/switch.css +149 -0
- package/dist/styles/recipes/table-of-contents.css +107 -0
- package/dist/styles/recipes/table.css +124 -0
- package/dist/styles/recipes/tabs.css +235 -0
- package/dist/styles/recipes/task-list.css +146 -0
- package/dist/styles/recipes/thread-rail.css +247 -0
- package/dist/styles/recipes/timeline.css +107 -0
- package/dist/styles/recipes/toolbar.css +260 -0
- package/dist/styles/recipes/track-highlight.css +73 -0
- package/dist/styles/recipes/transcript-divider.css +64 -0
- package/dist/styles/recipes/tree.css +137 -0
- package/dist/styles/recipes/user-ask-details.css +45 -0
- package/dist/styles/recipes/user-ask.css +204 -0
- package/dist/styles/skin-theme.css +137 -0
- package/dist/styles/skin.css +143 -0
- package/dist/styles/theme.css +628 -0
- package/dist/styles/type-scale.css +45 -0
- package/dist/surface-variants.d.ts +6 -0
- package/dist/surface-variants.js +16 -0
- package/dist/task-list.d.ts +34 -0
- package/dist/task-list.js +177 -0
- package/dist/thread-rail.d.ts +52 -0
- package/dist/thread-rail.js +190 -0
- package/dist/transcript-divider.d.ts +15 -0
- package/dist/transcript-divider.js +25 -0
- package/dist/ui/accordion.d.ts +31 -0
- package/dist/ui/accordion.js +60 -0
- package/dist/ui/alert-dialog.d.ts +36 -0
- package/dist/ui/alert-dialog.js +100 -0
- package/dist/ui/alert.d.ts +21 -0
- package/dist/ui/alert.js +36 -0
- package/dist/ui/aspect-ratio.d.ts +8 -0
- package/dist/ui/aspect-ratio.js +17 -0
- package/dist/ui/autocomplete.d.ts +70 -0
- package/dist/ui/autocomplete.js +150 -0
- package/dist/ui/avatar.d.ts +24 -0
- package/dist/ui/avatar.js +44 -0
- package/dist/ui/badge.d.ts +20 -0
- package/dist/ui/badge.js +36 -0
- package/dist/ui/button-group.d.ts +24 -0
- package/dist/ui/button-group.js +45 -0
- package/dist/ui/button.d.ts +36 -0
- package/dist/ui/button.js +104 -0
- package/dist/ui/calendar.d.ts +11 -0
- package/dist/ui/calendar.js +160 -0
- package/dist/ui/card.d.ts +36 -0
- package/dist/ui/card.js +70 -0
- package/dist/ui/checkbox-group.d.ts +11 -0
- package/dist/ui/checkbox-group.js +16 -0
- package/dist/ui/checkbox.d.ts +23 -0
- package/dist/ui/checkbox.js +58 -0
- package/dist/ui/code-diff.d.ts +28 -0
- package/dist/ui/code-diff.js +561 -0
- package/dist/ui/code.d.ts +62 -0
- package/dist/ui/code.js +292 -0
- package/dist/ui/collapsible.d.ts +31 -0
- package/dist/ui/collapsible.js +72 -0
- package/dist/ui/color-picker.d.ts +137 -0
- package/dist/ui/color-picker.js +797 -0
- package/dist/ui/combobox-disabled-selection.d.ts +5 -0
- package/dist/ui/combobox-disabled-selection.js +11 -0
- package/dist/ui/combobox.d.ts +70 -0
- package/dist/ui/combobox.js +194 -0
- package/dist/ui/command.d.ts +44 -0
- package/dist/ui/command.js +166 -0
- package/dist/ui/context-menu.d.ts +86 -0
- package/dist/ui/context-menu.js +202 -0
- package/dist/ui/dialog.d.ts +38 -0
- package/dist/ui/dialog.js +124 -0
- package/dist/ui/dockable-panel-geometry.d.ts +18 -0
- package/dist/ui/dockable-panel-geometry.js +17 -0
- package/dist/ui/dockable-panel.d.ts +58 -0
- package/dist/ui/dockable-panel.js +366 -0
- package/dist/ui/drawer.d.ts +42 -0
- package/dist/ui/drawer.js +182 -0
- package/dist/ui/dropdown-menu.d.ts +46 -0
- package/dist/ui/dropdown-menu.js +89 -0
- package/dist/ui/dropzone.d.ts +66 -0
- package/dist/ui/dropzone.js +311 -0
- package/dist/ui/empty.d.ts +28 -0
- package/dist/ui/empty.js +59 -0
- package/dist/ui/field.d.ts +64 -0
- package/dist/ui/field.js +166 -0
- package/dist/ui/form.d.ts +10 -0
- package/dist/ui/form.js +17 -0
- package/dist/ui/gradient-editor.d.ts +47 -0
- package/dist/ui/gradient-editor.js +301 -0
- package/dist/ui/hover-card.d.ts +25 -0
- package/dist/ui/hover-card.js +46 -0
- package/dist/ui/infinite-canvas.d.ts +40 -0
- package/dist/ui/infinite-canvas.js +278 -0
- package/dist/ui/input-group.d.ts +21 -0
- package/dist/ui/input-group.js +44 -0
- package/dist/ui/input-otp.d.ts +38 -0
- package/dist/ui/input-otp.js +45 -0
- package/dist/ui/input.d.ts +12 -0
- package/dist/ui/input.js +18 -0
- package/dist/ui/item.d.ts +46 -0
- package/dist/ui/item.js +110 -0
- package/dist/ui/kbd.d.ts +12 -0
- package/dist/ui/kbd.js +23 -0
- package/dist/ui/markdown-elements.d.ts +52 -0
- package/dist/ui/markdown-elements.js +211 -0
- package/dist/ui/markdown.d.ts +14 -0
- package/dist/ui/markdown.js +31 -0
- package/dist/ui/menubar.d.ts +74 -0
- package/dist/ui/menubar.js +162 -0
- package/dist/ui/meter.d.ts +34 -0
- package/dist/ui/meter.js +57 -0
- package/dist/ui/morphing-panel.d.ts +24 -0
- package/dist/ui/morphing-panel.js +87 -0
- package/dist/ui/native-select.d.ts +12 -0
- package/dist/ui/native-select.js +41 -0
- package/dist/ui/navigation-menu.d.ts +51 -0
- package/dist/ui/navigation-menu.js +135 -0
- package/dist/ui/number-field.d.ts +72 -0
- package/dist/ui/number-field.js +124 -0
- package/dist/ui/pagination.d.ts +26 -0
- package/dist/ui/pagination.js +77 -0
- package/dist/ui/phone-input.d.ts +30 -0
- package/dist/ui/phone-input.js +263 -0
- package/dist/ui/popover.d.ts +34 -0
- package/dist/ui/popover.js +87 -0
- package/dist/ui/progress.d.ts +34 -0
- package/dist/ui/progress.js +57 -0
- package/dist/ui/radio-group.d.ts +29 -0
- package/dist/ui/radio-group.js +37 -0
- package/dist/ui/resizable.d.ts +56 -0
- package/dist/ui/resizable.js +82 -0
- package/dist/ui/responsive-dialog.d.ts +18 -0
- package/dist/ui/responsive-dialog.js +121 -0
- package/dist/ui/rich-tooltip-tour.d.ts +12 -0
- package/dist/ui/rich-tooltip-tour.js +20 -0
- package/dist/ui/rich-tooltip.d.ts +83 -0
- package/dist/ui/rich-tooltip.js +331 -0
- package/dist/ui/scroll-area.d.ts +25 -0
- package/dist/ui/scroll-area.js +93 -0
- package/dist/ui/select.d.ts +44 -0
- package/dist/ui/select.js +124 -0
- package/dist/ui/separator.d.ts +9 -0
- package/dist/ui/separator.js +16 -0
- package/dist/ui/sheet.d.ts +25 -0
- package/dist/ui/sheet.js +76 -0
- package/dist/ui/sidebar.d.ts +88 -0
- package/dist/ui/sidebar.js +362 -0
- package/dist/ui/skeleton.d.ts +8 -0
- package/dist/ui/skeleton.js +13 -0
- package/dist/ui/slider.d.ts +24 -0
- package/dist/ui/slider.js +114 -0
- package/dist/ui/spinner.d.ts +12 -0
- package/dist/ui/spinner.js +26 -0
- package/dist/ui/stepper.d.ts +58 -0
- package/dist/ui/stepper.js +232 -0
- package/dist/ui/switch.d.ts +26 -0
- package/dist/ui/switch.js +71 -0
- package/dist/ui/table-of-contents.d.ts +22 -0
- package/dist/ui/table-of-contents.js +181 -0
- package/dist/ui/table.d.ts +37 -0
- package/dist/ui/table.js +83 -0
- package/dist/ui/tabs.d.ts +36 -0
- package/dist/ui/tabs.js +127 -0
- package/dist/ui/textarea.d.ts +9 -0
- package/dist/ui/textarea.js +16 -0
- package/dist/ui/timeline.d.ts +40 -0
- package/dist/ui/timeline.js +80 -0
- package/dist/ui/toast.d.ts +28 -0
- package/dist/ui/toast.js +132 -0
- package/dist/ui/toggle.d.ts +20 -0
- package/dist/ui/toggle.js +71 -0
- package/dist/ui/toolbar.d.ts +40 -0
- package/dist/ui/toolbar.js +72 -0
- package/dist/ui/tooltip.d.ts +27 -0
- package/dist/ui/tooltip.js +93 -0
- package/dist/ui/tree.d.ts +56 -0
- package/dist/ui/tree.js +438 -0
- package/dist/ui/trigger-menu.d.ts +46 -0
- package/dist/ui/trigger-menu.js +116 -0
- package/dist/user-ask.d.ts +50 -0
- package/dist/user-ask.js +398 -0
- package/package.json +115 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { FormSubmitEvent, OpenChangeEventDetails, OpenChangeReason } from "../control-props.js";
|
|
2
|
+
import { DynamicNotificationKnobStyle } from "../knob-contracts/dynamic-notification-knobs.js";
|
|
3
|
+
import { CSSProperties, ComponentProps } from "react";
|
|
4
|
+
//#region src/hooks/use-dynamic-notification.d.ts
|
|
5
|
+
type DynamicNotificationVariant = "surface" | "glass" | "liquid";
|
|
6
|
+
type DynamicNotificationReplyPayload = {
|
|
7
|
+
value: string;
|
|
8
|
+
clear: () => void;
|
|
9
|
+
};
|
|
10
|
+
type DynamicNotificationProps = Omit<ComponentProps<"div">, "onChange" | "style"> & {
|
|
11
|
+
open?: boolean;
|
|
12
|
+
defaultOpen?: boolean;
|
|
13
|
+
onOpenChange?: (open: boolean, eventDetails: OpenChangeEventDetails) => void;
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
replyValue?: string;
|
|
16
|
+
defaultReplyValue?: string;
|
|
17
|
+
onReplyValueChange?: (value: string) => void;
|
|
18
|
+
onReply?: (payload: DynamicNotificationReplyPayload) => void | Promise<void>;
|
|
19
|
+
variant?: DynamicNotificationVariant;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
style?: CSSProperties & DynamicNotificationKnobStyle;
|
|
22
|
+
};
|
|
23
|
+
type DynamicNotificationController = {
|
|
24
|
+
open: boolean;
|
|
25
|
+
disabled: boolean;
|
|
26
|
+
setOpen: (nextOpen: boolean, reason: OpenChangeReason, event: Event, trigger?: Element) => void;
|
|
27
|
+
reply: string;
|
|
28
|
+
setReply: (nextValue: string) => void;
|
|
29
|
+
normalizedReply: string;
|
|
30
|
+
canSubmit: boolean;
|
|
31
|
+
clear: () => void;
|
|
32
|
+
submitReply: () => void;
|
|
33
|
+
handleReplySubmit: (event: FormSubmitEvent) => void;
|
|
34
|
+
};
|
|
35
|
+
declare function useDynamicNotification({ open, defaultOpen, onOpenChange, replyValue, defaultReplyValue, onReplyValueChange, onReply, disabled }: Pick<DynamicNotificationProps, "open" | "defaultOpen" | "onOpenChange" | "replyValue" | "defaultReplyValue" | "onReplyValueChange" | "onReply" | "disabled">): DynamicNotificationController;
|
|
36
|
+
//#endregion
|
|
37
|
+
export { DynamicNotificationController, DynamicNotificationProps, DynamicNotificationReplyPayload, DynamicNotificationVariant, useDynamicNotification };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
//#region src/hooks/use-dynamic-notification.ts
|
|
3
|
+
function createOpenChangeEventDetails(reason, event, trigger) {
|
|
4
|
+
let canceled = false;
|
|
5
|
+
let propagationAllowed = false;
|
|
6
|
+
return {
|
|
7
|
+
reason,
|
|
8
|
+
event,
|
|
9
|
+
cancel() {
|
|
10
|
+
canceled = true;
|
|
11
|
+
},
|
|
12
|
+
allowPropagation() {
|
|
13
|
+
propagationAllowed = true;
|
|
14
|
+
},
|
|
15
|
+
get isCanceled() {
|
|
16
|
+
return canceled;
|
|
17
|
+
},
|
|
18
|
+
get isPropagationAllowed() {
|
|
19
|
+
return propagationAllowed;
|
|
20
|
+
},
|
|
21
|
+
trigger
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function useControllableText({ value, defaultValue = "", onValueChange }) {
|
|
25
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
26
|
+
const isControlled = value !== void 0;
|
|
27
|
+
return [isControlled ? value : internalValue, useMemo(() => (nextValue) => {
|
|
28
|
+
if (!isControlled) setInternalValue(nextValue);
|
|
29
|
+
onValueChange?.(nextValue);
|
|
30
|
+
}, [isControlled, onValueChange])];
|
|
31
|
+
}
|
|
32
|
+
function useDynamicNotification({ open, defaultOpen = false, onOpenChange, replyValue, defaultReplyValue, onReplyValueChange, onReply, disabled = false }) {
|
|
33
|
+
const [internalOpen, setInternalOpen] = useState(defaultOpen);
|
|
34
|
+
const isControlled = open !== void 0;
|
|
35
|
+
const isOpen = isControlled ? open : internalOpen;
|
|
36
|
+
const [reply, setReply] = useControllableText({
|
|
37
|
+
value: replyValue,
|
|
38
|
+
defaultValue: defaultReplyValue,
|
|
39
|
+
onValueChange: onReplyValueChange
|
|
40
|
+
});
|
|
41
|
+
const normalizedReply = reply.trim();
|
|
42
|
+
const canSubmit = normalizedReply.length > 0 && !disabled;
|
|
43
|
+
const setOpen = useMemo(() => (nextOpen, reason, event, trigger) => {
|
|
44
|
+
if (disabled || nextOpen === isOpen) return;
|
|
45
|
+
const details = createOpenChangeEventDetails(reason, event, trigger);
|
|
46
|
+
onOpenChange?.(nextOpen, details);
|
|
47
|
+
if (details.isCanceled) return;
|
|
48
|
+
if (!isControlled) setInternalOpen(nextOpen);
|
|
49
|
+
}, [
|
|
50
|
+
disabled,
|
|
51
|
+
isControlled,
|
|
52
|
+
isOpen,
|
|
53
|
+
onOpenChange
|
|
54
|
+
]);
|
|
55
|
+
const clear = useMemo(() => () => {
|
|
56
|
+
setReply("");
|
|
57
|
+
}, [setReply]);
|
|
58
|
+
const submitReply = useMemo(() => () => {
|
|
59
|
+
if (!canSubmit) return;
|
|
60
|
+
onReply?.({
|
|
61
|
+
value: normalizedReply,
|
|
62
|
+
clear
|
|
63
|
+
});
|
|
64
|
+
}, [
|
|
65
|
+
canSubmit,
|
|
66
|
+
clear,
|
|
67
|
+
normalizedReply,
|
|
68
|
+
onReply
|
|
69
|
+
]);
|
|
70
|
+
return {
|
|
71
|
+
open: isOpen,
|
|
72
|
+
disabled,
|
|
73
|
+
setOpen,
|
|
74
|
+
reply,
|
|
75
|
+
setReply,
|
|
76
|
+
normalizedReply,
|
|
77
|
+
canSubmit,
|
|
78
|
+
clear,
|
|
79
|
+
submitReply,
|
|
80
|
+
handleReplySubmit: useMemo(() => (event) => {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
submitReply();
|
|
83
|
+
}, [submitReply])
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
//#endregion
|
|
87
|
+
export { useDynamicNotification };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { EnvironmentVariableEntry } from "../lib/env-file.js";
|
|
2
|
+
//#region src/hooks/use-environment-variables.d.ts
|
|
3
|
+
type EnvironmentVariableRow = EnvironmentVariableEntry;
|
|
4
|
+
type EnvironmentVariablesImportMode = "auto" | "bulk";
|
|
5
|
+
interface UseEnvironmentVariablesOptions<TRow extends EnvironmentVariableRow = EnvironmentVariableRow> {
|
|
6
|
+
initialRows?: readonly TRow[];
|
|
7
|
+
rows?: readonly TRow[];
|
|
8
|
+
onRowsChange?: (rows: TRow[]) => void;
|
|
9
|
+
createDefaultRow?: () => TRow;
|
|
10
|
+
createRow?: (entry: EnvironmentVariableEntry) => TRow;
|
|
11
|
+
getEditableRows?: (rows: readonly TRow[]) => readonly TRow[];
|
|
12
|
+
getPreservedRows?: (rows: readonly TRow[]) => readonly TRow[];
|
|
13
|
+
maxUploadSize?: number;
|
|
14
|
+
}
|
|
15
|
+
interface EnvironmentVariablesFileUploadEvent {
|
|
16
|
+
target: {
|
|
17
|
+
files?: FileList | readonly File[] | null;
|
|
18
|
+
value: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
interface EnvironmentVariablesImportOptions {
|
|
22
|
+
targetIndex?: number;
|
|
23
|
+
mode?: EnvironmentVariablesImportMode;
|
|
24
|
+
}
|
|
25
|
+
interface EnvironmentVariablesController<TRow extends EnvironmentVariableRow = EnvironmentVariableRow> {
|
|
26
|
+
rows: readonly TRow[];
|
|
27
|
+
uploadError: string | null;
|
|
28
|
+
duplicateKeys: Set<string>;
|
|
29
|
+
hasDuplicateKeys: boolean;
|
|
30
|
+
isDirty: boolean;
|
|
31
|
+
setRows: (rows: readonly TRow[]) => TRow[];
|
|
32
|
+
resetRows: (rows?: readonly TRow[]) => TRow[];
|
|
33
|
+
appendRow: (row?: TRow) => TRow[];
|
|
34
|
+
updateRow: (index: number, patch: Partial<EnvironmentVariableEntry>) => TRow[];
|
|
35
|
+
removeRow: (index: number) => TRow[];
|
|
36
|
+
getRowsForSubmit: () => TRow[];
|
|
37
|
+
getEnvironmentVariablesForSubmit: () => Record<string, string>;
|
|
38
|
+
getEnvFileTextForSubmit: () => string;
|
|
39
|
+
importText: (text: string, options?: EnvironmentVariablesImportOptions) => boolean;
|
|
40
|
+
handleFileUpload: (event: EnvironmentVariablesFileUploadEvent) => Promise<void>;
|
|
41
|
+
handlePaste: (index: number, text: string) => boolean;
|
|
42
|
+
clearUploadError: () => void;
|
|
43
|
+
getRowId: (index: number) => string;
|
|
44
|
+
isValueRevealed: (index: number) => boolean;
|
|
45
|
+
toggleValueVisibility: (index: number) => void;
|
|
46
|
+
rowHasDuplicateKey: (index: number) => boolean;
|
|
47
|
+
}
|
|
48
|
+
declare function useEnvironmentVariables<TRow extends EnvironmentVariableRow = EnvironmentVariableRow>(options?: UseEnvironmentVariablesOptions<TRow>): EnvironmentVariablesController<TRow>;
|
|
49
|
+
declare function parseEnvironmentVariablesImportText(text: string, mode?: EnvironmentVariablesImportMode): EnvironmentVariableEntry[];
|
|
50
|
+
//#endregion
|
|
51
|
+
export { EnvironmentVariableRow, EnvironmentVariablesController, EnvironmentVariablesFileUploadEvent, EnvironmentVariablesImportMode, EnvironmentVariablesImportOptions, UseEnvironmentVariablesOptions, parseEnvironmentVariablesImportText, useEnvironmentVariables };
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { collectEnvironmentVariables, createEmptyEnvironmentVariableEntry, getDuplicateEnvironmentVariableKeys, parseEnvFileText, readEnvFile, rowsToEnvFileText } from "../lib/env-file.js";
|
|
3
|
+
import { useRef, useState } from "react";
|
|
4
|
+
//#region src/hooks/use-environment-variables.ts
|
|
5
|
+
function defaultCreateRow(entry) {
|
|
6
|
+
return {
|
|
7
|
+
key: entry.key,
|
|
8
|
+
value: entry.value
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function defaultEditableRows(rows) {
|
|
12
|
+
return rows;
|
|
13
|
+
}
|
|
14
|
+
function defaultPreservedRows() {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
function normalizeRows(rows, createDefaultRow) {
|
|
18
|
+
return rows && rows.length > 0 ? rows.map((row) => ({ ...row })) : [createDefaultRow()];
|
|
19
|
+
}
|
|
20
|
+
function hasOnlyEmptyRow(rows) {
|
|
21
|
+
if (rows.length !== 1) return false;
|
|
22
|
+
const [firstRow] = rows;
|
|
23
|
+
if (!firstRow) return false;
|
|
24
|
+
return !firstRow.key.trim() && !firstRow.value;
|
|
25
|
+
}
|
|
26
|
+
function areRowsEqual(a, b) {
|
|
27
|
+
if (a.length !== b.length) return false;
|
|
28
|
+
for (let index = 0; index < a.length; index++) {
|
|
29
|
+
const aRow = a[index];
|
|
30
|
+
const bRow = b[index];
|
|
31
|
+
if (!aRow || !bRow || aRow.key !== bRow.key || aRow.value !== bRow.value) return false;
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
function useEnvironmentVariables({ initialRows, rows: controlledRows, onRowsChange, createDefaultRow = createEmptyEnvironmentVariableEntry, createRow = defaultCreateRow, getEditableRows = defaultEditableRows, getPreservedRows = defaultPreservedRows, maxUploadSize } = {}) {
|
|
36
|
+
const initialSourceRows = controlledRows ?? initialRows;
|
|
37
|
+
const nextRowId = useRef(0);
|
|
38
|
+
const fallbackRowIds = useRef({});
|
|
39
|
+
const [uncontrolledRows, setUncontrolledRows] = useState(() => normalizeRows(initialSourceRows, createDefaultRow));
|
|
40
|
+
const [baselineRows, setBaselineRows] = useState(() => normalizeRows(initialSourceRows, createDefaultRow));
|
|
41
|
+
const [rowIds, setRowIds] = useState(() => normalizeRows(initialSourceRows, createDefaultRow).map(() => createRowId()));
|
|
42
|
+
const [uploadError, setUploadError] = useState(null);
|
|
43
|
+
const [revealedValues, setRevealedValues] = useState({});
|
|
44
|
+
const rows = controlledRows ? normalizeRows(controlledRows, createDefaultRow) : uncontrolledRows;
|
|
45
|
+
const editableRows = (sourceRows = rows) => getEditableRows(sourceRows);
|
|
46
|
+
const preservedRows = (sourceRows = rows) => getPreservedRows(sourceRows);
|
|
47
|
+
function createRowId() {
|
|
48
|
+
const rowId = nextRowId.current;
|
|
49
|
+
nextRowId.current += 1;
|
|
50
|
+
return `environment-variable-row-${rowId}`;
|
|
51
|
+
}
|
|
52
|
+
function commitRows(nextRows, nextRowIds) {
|
|
53
|
+
const normalizedRows = normalizeRows(nextRows, createDefaultRow);
|
|
54
|
+
const normalizedRowIds = normalizedRows.map((_, index) => nextRowIds?.[index] ?? rowIds[index] ?? createRowId());
|
|
55
|
+
if (!controlledRows) setUncontrolledRows(normalizedRows);
|
|
56
|
+
setRowIds(normalizedRowIds);
|
|
57
|
+
onRowsChange?.(normalizedRows);
|
|
58
|
+
return normalizedRows;
|
|
59
|
+
}
|
|
60
|
+
function setRows(nextRows) {
|
|
61
|
+
return commitRows(nextRows);
|
|
62
|
+
}
|
|
63
|
+
function resetRows(nextRows = baselineRows) {
|
|
64
|
+
const normalizedRows = normalizeRows(nextRows, createDefaultRow);
|
|
65
|
+
commitRows(normalizedRows, normalizedRows.map(() => createRowId()));
|
|
66
|
+
setBaselineRows(normalizedRows);
|
|
67
|
+
setRevealedValues({});
|
|
68
|
+
setUploadError(null);
|
|
69
|
+
return normalizedRows;
|
|
70
|
+
}
|
|
71
|
+
function getRowsForSubmit() {
|
|
72
|
+
return [...rows];
|
|
73
|
+
}
|
|
74
|
+
function appendRow(row = createDefaultRow()) {
|
|
75
|
+
return commitRows([...rows, row], [...rowIds, createRowId()]);
|
|
76
|
+
}
|
|
77
|
+
function updateRow(index, patch) {
|
|
78
|
+
return commitRows(rows.map((row, rowIndex) => rowIndex === index ? {
|
|
79
|
+
...row,
|
|
80
|
+
...patch
|
|
81
|
+
} : row), rowIds);
|
|
82
|
+
}
|
|
83
|
+
function removeRow(index) {
|
|
84
|
+
const nextRows = rows.filter((_, rowIndex) => rowIndex !== index);
|
|
85
|
+
const nextRowIds = rowIds.filter((_, rowIndex) => rowIndex !== index);
|
|
86
|
+
setRevealedValues({});
|
|
87
|
+
return commitRows(nextRows.length > 0 ? nextRows : [createDefaultRow()], nextRows.length > 0 ? nextRowIds : [createRowId()]);
|
|
88
|
+
}
|
|
89
|
+
function mergeParsedRows(parsedRows, targetIndex) {
|
|
90
|
+
const newRows = parsedRows.map(createRow);
|
|
91
|
+
const newRowIds = newRows.map(() => createRowId());
|
|
92
|
+
if (hasOnlyEmptyRow(editableRows(rows))) {
|
|
93
|
+
const preserved = preservedRows(rows);
|
|
94
|
+
return commitRows([...preserved, ...newRows], [...rowIds.slice(0, preserved.length), ...newRowIds]);
|
|
95
|
+
}
|
|
96
|
+
if (typeof targetIndex !== "number") return commitRows([...rows, ...newRows], [...rowIds, ...newRowIds]);
|
|
97
|
+
const targetRow = rows[targetIndex];
|
|
98
|
+
if (!targetRow) return commitRows([...rows, ...newRows], [...rowIds, ...newRowIds]);
|
|
99
|
+
const targetIsEmpty = !targetRow.key.trim() && !targetRow.value;
|
|
100
|
+
const before = rows.slice(0, targetIndex + (targetIsEmpty ? 0 : 1));
|
|
101
|
+
const after = rows.slice(targetIndex + 1);
|
|
102
|
+
const beforeIds = rowIds.slice(0, targetIndex + (targetIsEmpty ? 0 : 1));
|
|
103
|
+
const afterIds = rowIds.slice(targetIndex + 1);
|
|
104
|
+
return commitRows([
|
|
105
|
+
...before,
|
|
106
|
+
...newRows,
|
|
107
|
+
...after
|
|
108
|
+
], [
|
|
109
|
+
...beforeIds,
|
|
110
|
+
...newRowIds,
|
|
111
|
+
...afterIds
|
|
112
|
+
]);
|
|
113
|
+
}
|
|
114
|
+
function importText(text, options = {}) {
|
|
115
|
+
const entries = parseEnvironmentVariablesImportText(text, options.mode ?? "bulk");
|
|
116
|
+
if (entries.length === 0) return false;
|
|
117
|
+
mergeParsedRows(entries, options.targetIndex);
|
|
118
|
+
setRevealedValues({});
|
|
119
|
+
setUploadError(null);
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
function handlePaste(index, text) {
|
|
123
|
+
return importText(text, {
|
|
124
|
+
targetIndex: index,
|
|
125
|
+
mode: "auto"
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
async function handleFileUpload(event) {
|
|
129
|
+
setUploadError(null);
|
|
130
|
+
const file = event.target.files?.[0];
|
|
131
|
+
if (!file) return;
|
|
132
|
+
const result = await readEnvFile(file, { maxSize: maxUploadSize });
|
|
133
|
+
if (!result.ok) {
|
|
134
|
+
setUploadError(result.error);
|
|
135
|
+
event.target.value = "";
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
mergeParsedRows(result.entries);
|
|
139
|
+
setRevealedValues({});
|
|
140
|
+
event.target.value = "";
|
|
141
|
+
}
|
|
142
|
+
function getRowId(index) {
|
|
143
|
+
const rowId = rowIds[index] ?? fallbackRowIds.current[index];
|
|
144
|
+
if (rowId) return rowId;
|
|
145
|
+
const fallbackRowId = createRowId();
|
|
146
|
+
fallbackRowIds.current[index] = fallbackRowId;
|
|
147
|
+
return fallbackRowId;
|
|
148
|
+
}
|
|
149
|
+
const duplicateKeys = getDuplicateEnvironmentVariableKeys(rows);
|
|
150
|
+
const rowsDirty = !areRowsEqual(rows, baselineRows);
|
|
151
|
+
return {
|
|
152
|
+
rows,
|
|
153
|
+
uploadError,
|
|
154
|
+
duplicateKeys,
|
|
155
|
+
hasDuplicateKeys: duplicateKeys.size > 0,
|
|
156
|
+
isDirty: rowsDirty,
|
|
157
|
+
setRows,
|
|
158
|
+
resetRows,
|
|
159
|
+
appendRow,
|
|
160
|
+
updateRow,
|
|
161
|
+
removeRow,
|
|
162
|
+
getRowsForSubmit,
|
|
163
|
+
getEnvironmentVariablesForSubmit: () => collectEnvironmentVariables(getRowsForSubmit()),
|
|
164
|
+
getEnvFileTextForSubmit: () => rowsToEnvFileText(getRowsForSubmit()),
|
|
165
|
+
importText,
|
|
166
|
+
handleFileUpload,
|
|
167
|
+
handlePaste,
|
|
168
|
+
clearUploadError: () => setUploadError(null),
|
|
169
|
+
getRowId,
|
|
170
|
+
isValueRevealed: (index) => Boolean(revealedValues[index]),
|
|
171
|
+
toggleValueVisibility: (index) => setRevealedValues((previous) => ({
|
|
172
|
+
...previous,
|
|
173
|
+
[index]: !previous[index]
|
|
174
|
+
})),
|
|
175
|
+
rowHasDuplicateKey: (index) => duplicateKeys.has(rows[index]?.key.trim() ?? "")
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function parseEnvironmentVariablesImportText(text, mode = "bulk") {
|
|
179
|
+
const trimmedText = text.trim();
|
|
180
|
+
if (!trimmedText.includes("=")) return [];
|
|
181
|
+
const entries = parseEnvFileText(trimmedText);
|
|
182
|
+
if (entries.length === 0) return [];
|
|
183
|
+
if (mode === "bulk") return entries;
|
|
184
|
+
const firstAssignmentLooksLikeEnvVar = /^(?:export\s+)?[A-Z_][A-Z0-9_]*\s*=/.test(trimmedText);
|
|
185
|
+
return entries.length > 1 || trimmedText.includes("\n") || firstAssignmentLooksLikeEnvVar ? entries : [];
|
|
186
|
+
}
|
|
187
|
+
//#endregion
|
|
188
|
+
export { parseEnvironmentVariablesImportText, useEnvironmentVariables };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
//#region src/hooks/use-mobile.ts
|
|
3
|
+
const MOBILE_BREAKPOINT = 768;
|
|
4
|
+
const viewportStores = /* @__PURE__ */ new Map();
|
|
5
|
+
function viewportStore(breakpoint) {
|
|
6
|
+
const cached = viewportStores.get(breakpoint);
|
|
7
|
+
if (cached) return cached;
|
|
8
|
+
const mobileQuery = `(max-width: ${breakpoint - 1}px)`;
|
|
9
|
+
const store = {
|
|
10
|
+
subscribe(onChange) {
|
|
11
|
+
const query = window.matchMedia(mobileQuery);
|
|
12
|
+
query.addEventListener("change", onChange);
|
|
13
|
+
return () => query.removeEventListener("change", onChange);
|
|
14
|
+
},
|
|
15
|
+
getSnapshot: () => window.matchMedia(mobileQuery).matches
|
|
16
|
+
};
|
|
17
|
+
viewportStores.set(breakpoint, store);
|
|
18
|
+
return store;
|
|
19
|
+
}
|
|
20
|
+
function getServerViewportSnapshot() {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
/** True below `breakpoint` px (Tailwind `md` by default); pass another breakpoint to match layout that switches elsewhere. */
|
|
24
|
+
function useIsMobile(breakpoint = MOBILE_BREAKPOINT) {
|
|
25
|
+
const store = viewportStore(breakpoint);
|
|
26
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot, getServerViewportSnapshot);
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { useIsMobile };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TriggerConfig, TriggerMenuController, TriggerMenuItemData } from "./use-trigger-menu.js";
|
|
2
|
+
import { RefObject } from "react";
|
|
3
|
+
//#region src/hooks/use-textarea-trigger-menu.d.ts
|
|
4
|
+
declare function useTextareaTriggerMenu<Item extends TriggerMenuItemData>(ref: RefObject<HTMLTextAreaElement | null>, options: {
|
|
5
|
+
triggers: readonly TriggerConfig<Item>[];
|
|
6
|
+
}): TriggerMenuController<Item>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { useTextareaTriggerMenu };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { caretRectInTextarea, detectTrigger } from "../lib/trigger-detect.js";
|
|
3
|
+
import { useTriggerMenu } from "./use-trigger-menu.js";
|
|
4
|
+
import { useEffect, useEffectEvent } from "react";
|
|
5
|
+
//#region src/hooks/use-textarea-trigger-menu.ts
|
|
6
|
+
function replaceRange(element, start, end, text) {
|
|
7
|
+
element.focus();
|
|
8
|
+
element.setSelectionRange(start, end);
|
|
9
|
+
if (document.execCommand("insertText", false, text)) return;
|
|
10
|
+
const next = element.value.slice(0, start) + text + element.value.slice(end);
|
|
11
|
+
(Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, "value")?.set)?.call(element, next);
|
|
12
|
+
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
13
|
+
const caret = start + text.length;
|
|
14
|
+
element.setSelectionRange(caret, caret);
|
|
15
|
+
}
|
|
16
|
+
function useTextareaTriggerMenu(ref, options) {
|
|
17
|
+
const controller = useTriggerMenu({
|
|
18
|
+
triggers: options.triggers,
|
|
19
|
+
onCommit: (item, trigger, match) => {
|
|
20
|
+
const element = ref.current;
|
|
21
|
+
if (!element) return;
|
|
22
|
+
const text = (trigger.insert ?? "replace") === "none" ? "" : trigger.insertText?.(item) ?? `${trigger.char}${item.label} `;
|
|
23
|
+
replaceRange(element, match.start, match.end, text);
|
|
24
|
+
trigger.onSelect?.(item, {
|
|
25
|
+
char: trigger.char,
|
|
26
|
+
query: match.query
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const syncTrigger = useEffectEvent(() => {
|
|
31
|
+
const element = ref.current;
|
|
32
|
+
if (!element) return;
|
|
33
|
+
const caret = element.selectionStart ?? element.value.length;
|
|
34
|
+
const chars = options.triggers.map((trigger) => trigger.char);
|
|
35
|
+
const match = detectTrigger(element.value.slice(0, caret), chars);
|
|
36
|
+
controller.report(match, match === null ? null : caretRectInTextarea(element, match.start));
|
|
37
|
+
});
|
|
38
|
+
const handleKeyDown = useEffectEvent((event) => {
|
|
39
|
+
if (controller.open && controller.handleKeyDown(event.key)) event.preventDefault();
|
|
40
|
+
});
|
|
41
|
+
const closeAfterBlur = useEffectEvent(() => {
|
|
42
|
+
controller.close();
|
|
43
|
+
});
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const element = ref.current;
|
|
46
|
+
if (!element) return;
|
|
47
|
+
function onKeyDown(event) {
|
|
48
|
+
handleKeyDown(event);
|
|
49
|
+
}
|
|
50
|
+
function onBlur() {
|
|
51
|
+
window.setTimeout(closeAfterBlur, 120);
|
|
52
|
+
}
|
|
53
|
+
element.addEventListener("input", syncTrigger);
|
|
54
|
+
element.addEventListener("keydown", onKeyDown);
|
|
55
|
+
element.addEventListener("keyup", syncTrigger);
|
|
56
|
+
element.addEventListener("click", syncTrigger);
|
|
57
|
+
element.addEventListener("blur", onBlur);
|
|
58
|
+
return () => {
|
|
59
|
+
element.removeEventListener("input", syncTrigger);
|
|
60
|
+
element.removeEventListener("keydown", onKeyDown);
|
|
61
|
+
element.removeEventListener("keyup", syncTrigger);
|
|
62
|
+
element.removeEventListener("click", syncTrigger);
|
|
63
|
+
element.removeEventListener("blur", onBlur);
|
|
64
|
+
};
|
|
65
|
+
}, [ref]);
|
|
66
|
+
return controller;
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
export { useTextareaTriggerMenu };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TriggerMatch } from "../lib/trigger-detect.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/hooks/use-trigger-menu.d.ts
|
|
4
|
+
type TriggerMenuItemData = {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
icon?: ReactNode;
|
|
9
|
+
keywords?: readonly string[];
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
kind?: string;
|
|
12
|
+
image?: string;
|
|
13
|
+
};
|
|
14
|
+
type TriggerSelectContext = {
|
|
15
|
+
char: string;
|
|
16
|
+
query: string;
|
|
17
|
+
};
|
|
18
|
+
type TriggerConfig<Item extends TriggerMenuItemData = TriggerMenuItemData> = {
|
|
19
|
+
char: string;
|
|
20
|
+
items: readonly Item[] | ((query: string) => readonly Item[]);
|
|
21
|
+
filter?: (item: Item, query: string) => boolean;
|
|
22
|
+
insert?: "replace" | "none";
|
|
23
|
+
insertText?: (item: Item) => string;
|
|
24
|
+
onSelect?: (item: Item, ctx: TriggerSelectContext) => void;
|
|
25
|
+
};
|
|
26
|
+
type UseTriggerMenuOptions<Item extends TriggerMenuItemData> = {
|
|
27
|
+
triggers: readonly TriggerConfig<Item>[];
|
|
28
|
+
onCommit: (item: Item, trigger: TriggerConfig<Item>, match: TriggerMatch) => void;
|
|
29
|
+
};
|
|
30
|
+
type TriggerMenuController<Item extends TriggerMenuItemData> = {
|
|
31
|
+
open: boolean;
|
|
32
|
+
items: readonly Item[];
|
|
33
|
+
activeIndex: number;
|
|
34
|
+
anchorRect: DOMRect | null;
|
|
35
|
+
activeChar: string | null;
|
|
36
|
+
query: string;
|
|
37
|
+
/** Binding → engine: publish current trigger match (or null) and caret rect to anchor to. */
|
|
38
|
+
report: (match: TriggerMatch | null, anchorRect: DOMRect | null) => void;
|
|
39
|
+
/** Binding → engine: route keydown while open. Returns true when engine consumed key. */
|
|
40
|
+
handleKeyDown: (key: string) => boolean;
|
|
41
|
+
/** View → engine. */
|
|
42
|
+
setActiveIndex: (index: number) => void;
|
|
43
|
+
select: (item: Item) => void;
|
|
44
|
+
close: () => void;
|
|
45
|
+
setOpen: (open: boolean) => void;
|
|
46
|
+
};
|
|
47
|
+
declare function useTriggerMenu<Item extends TriggerMenuItemData>({ triggers, onCommit }: UseTriggerMenuOptions<Item>): TriggerMenuController<Item>;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { TriggerConfig, TriggerMenuController, TriggerMenuItemData, TriggerSelectContext, UseTriggerMenuOptions, useTriggerMenu };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { useRef, useState } from "react";
|
|
2
|
+
//#region src/hooks/use-trigger-menu.ts
|
|
3
|
+
const CLOSED = {
|
|
4
|
+
open: false,
|
|
5
|
+
char: null,
|
|
6
|
+
query: "",
|
|
7
|
+
anchorRect: null,
|
|
8
|
+
activeIndex: 0
|
|
9
|
+
};
|
|
10
|
+
function matchesQuery(item, query) {
|
|
11
|
+
if (query === "") return true;
|
|
12
|
+
const needle = query.toLowerCase();
|
|
13
|
+
if (item.label.toLowerCase().includes(needle)) return true;
|
|
14
|
+
return (item.keywords ?? []).some((keyword) => keyword.toLowerCase().includes(needle));
|
|
15
|
+
}
|
|
16
|
+
function resolveItems(trigger, query) {
|
|
17
|
+
if (typeof trigger.items === "function") return trigger.items(query);
|
|
18
|
+
const filter = trigger.filter ?? matchesQuery;
|
|
19
|
+
return trigger.items.filter((item) => filter(item, query));
|
|
20
|
+
}
|
|
21
|
+
function useTriggerMenu({ triggers, onCommit }) {
|
|
22
|
+
const [state, setState] = useState(CLOSED);
|
|
23
|
+
const lastMatch = useRef(null);
|
|
24
|
+
const activeTrigger = state.char === null ? null : triggers.find((trigger) => trigger.char === state.char) ?? null;
|
|
25
|
+
const items = activeTrigger === null ? [] : resolveItems(activeTrigger, state.query);
|
|
26
|
+
function close() {
|
|
27
|
+
lastMatch.current = null;
|
|
28
|
+
setState(CLOSED);
|
|
29
|
+
}
|
|
30
|
+
function select(item) {
|
|
31
|
+
const match = lastMatch.current;
|
|
32
|
+
if (activeTrigger !== null && match !== null) onCommit(item, activeTrigger, match);
|
|
33
|
+
close();
|
|
34
|
+
}
|
|
35
|
+
function report(match, anchorRect) {
|
|
36
|
+
lastMatch.current = match;
|
|
37
|
+
const open = match !== null && triggers.some((trigger) => trigger.char === match.char);
|
|
38
|
+
setState((current) => {
|
|
39
|
+
if (!open || match === null) return CLOSED;
|
|
40
|
+
const activeIndex = current.char === match.char && current.query === match.query ? current.activeIndex : 0;
|
|
41
|
+
return {
|
|
42
|
+
open: true,
|
|
43
|
+
char: match.char,
|
|
44
|
+
query: match.query,
|
|
45
|
+
anchorRect,
|
|
46
|
+
activeIndex
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function handleKeyDown(key) {
|
|
51
|
+
if (!state.open) return false;
|
|
52
|
+
if (key === "ArrowDown") {
|
|
53
|
+
setState((current) => ({
|
|
54
|
+
...current,
|
|
55
|
+
activeIndex: items.length === 0 ? 0 : (current.activeIndex + 1) % items.length
|
|
56
|
+
}));
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (key === "ArrowUp") {
|
|
60
|
+
setState((current) => ({
|
|
61
|
+
...current,
|
|
62
|
+
activeIndex: items.length === 0 ? 0 : (current.activeIndex - 1 + items.length) % items.length
|
|
63
|
+
}));
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (key === "Enter" || key === "Tab") {
|
|
67
|
+
const item = items[state.activeIndex];
|
|
68
|
+
if (item && !item.disabled) select(item);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (key === "Escape") {
|
|
72
|
+
close();
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
function setOpen(open) {
|
|
78
|
+
if (!open) close();
|
|
79
|
+
}
|
|
80
|
+
function setActiveIndex(activeIndex) {
|
|
81
|
+
setState((current) => ({
|
|
82
|
+
...current,
|
|
83
|
+
activeIndex
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
open: state.open,
|
|
88
|
+
items,
|
|
89
|
+
activeIndex: state.activeIndex,
|
|
90
|
+
anchorRect: state.anchorRect,
|
|
91
|
+
activeChar: state.char,
|
|
92
|
+
query: state.query,
|
|
93
|
+
report,
|
|
94
|
+
handleKeyDown,
|
|
95
|
+
setActiveIndex,
|
|
96
|
+
select,
|
|
97
|
+
close,
|
|
98
|
+
setOpen
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
102
|
+
export { useTriggerMenu };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { UserAskKnobStyle } from "../knob-contracts/user-ask-knobs.js";
|
|
2
|
+
import { CSSProperties, ComponentProps, KeyboardEvent, ReactNode } from "react";
|
|
3
|
+
//#region src/hooks/use-user-ask.d.ts
|
|
4
|
+
type UserAskAnswers = Record<string, string>;
|
|
5
|
+
type UserAskProps = Omit<ComponentProps<"section">, "style"> & {
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
onComplete?: (answers: UserAskAnswers) => void;
|
|
8
|
+
onDismiss?: () => void;
|
|
9
|
+
style?: CSSProperties & UserAskKnobStyle;
|
|
10
|
+
};
|
|
11
|
+
type UserAskQuestionEntry = {
|
|
12
|
+
key: string;
|
|
13
|
+
id: string;
|
|
14
|
+
title: string;
|
|
15
|
+
defaultValue?: string;
|
|
16
|
+
};
|
|
17
|
+
type UserAskOptionEntry = {
|
|
18
|
+
key: string;
|
|
19
|
+
value: string;
|
|
20
|
+
disabled?: boolean;
|
|
21
|
+
/** Freeform options resolve to user's typed text instead of `value`. */
|
|
22
|
+
freeform?: boolean;
|
|
23
|
+
};
|
|
24
|
+
declare function useUserAsk({ onComplete, onDismiss }: Pick<UserAskProps, "onComplete" | "onDismiss">): {
|
|
25
|
+
questions: UserAskQuestionEntry[];
|
|
26
|
+
activeIndex: number;
|
|
27
|
+
activeQuestion: UserAskQuestionEntry;
|
|
28
|
+
canContinue: boolean;
|
|
29
|
+
isLastQuestion: boolean;
|
|
30
|
+
registerQuestion: (entry: UserAskQuestionEntry) => void;
|
|
31
|
+
unregisterQuestion: (key: string) => void;
|
|
32
|
+
registerOption: (questionId: string, entry: UserAskOptionEntry) => void;
|
|
33
|
+
unregisterOption: (questionId: string, key: string) => void;
|
|
34
|
+
optionsFor: (questionId: string) => UserAskOptionEntry[];
|
|
35
|
+
selectionFor: (questionId: string) => string | undefined;
|
|
36
|
+
isSelected: (questionId: string, optionKey: string) => boolean;
|
|
37
|
+
select: (questionId: string, optionKey: string) => void;
|
|
38
|
+
freeformTextFor: (questionId: string) => string;
|
|
39
|
+
setFreeformText: (questionId: string, text: string) => void;
|
|
40
|
+
answerFor: (questionId: string) => string | undefined;
|
|
41
|
+
resolveAnswers: () => UserAskAnswers;
|
|
42
|
+
goTo: (index: number) => void;
|
|
43
|
+
advance: () => void;
|
|
44
|
+
dismiss: () => void;
|
|
45
|
+
handleKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
export { UserAskAnswers, UserAskOptionEntry, UserAskProps, UserAskQuestionEntry, useUserAsk };
|