@moldable-ai/ui 0.2.19 → 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog/catalog-manifest.d.ts +6 -0
- package/dist/catalog/catalog-manifest.d.ts.map +1 -0
- package/dist/catalog/catalog-manifest.js +105 -0
- package/dist/catalog/catalog-types.d.ts +54 -0
- package/dist/catalog/catalog-types.d.ts.map +1 -0
- package/dist/catalog/catalog-types.js +14 -0
- package/dist/catalog/component-catalog.d.ts +14 -0
- package/dist/catalog/component-catalog.d.ts.map +1 -0
- package/dist/catalog/component-catalog.js +39 -0
- package/dist/catalog/core-catalog.d.ts +6 -0
- package/dist/catalog/core-catalog.d.ts.map +1 -0
- package/dist/catalog/core-catalog.js +105 -0
- package/dist/catalog/index.d.ts +5 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +4 -0
- package/dist/components/app-error-boundary.d.ts +1 -0
- package/dist/components/app-error-boundary.d.ts.map +1 -1
- package/dist/components/app-error-boundary.js +13 -0
- package/dist/components/chat/chat-image-lightbox.d.ts +9 -0
- package/dist/components/chat/chat-image-lightbox.d.ts.map +1 -0
- package/dist/components/chat/chat-image-lightbox.js +9 -0
- package/dist/components/chat/chat-message.d.ts +19 -1
- package/dist/components/chat/chat-message.d.ts.map +1 -1
- package/dist/components/chat/chat-message.js +66 -16
- package/dist/components/chat/chat-messages.d.ts +5 -2
- package/dist/components/chat/chat-messages.d.ts.map +1 -1
- package/dist/components/chat/chat-messages.js +61 -6
- package/dist/components/chat/chat-panel.d.ts +50 -6
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +200 -163
- package/dist/components/chat/conversation-history.d.ts +39 -5
- package/dist/components/chat/conversation-history.d.ts.map +1 -1
- package/dist/components/chat/conversation-history.js +192 -26
- package/dist/components/chat/index.d.ts +2 -2
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +1 -1
- package/dist/components/chat/tool-handlers.d.ts.map +1 -1
- package/dist/components/chat/tool-handlers.js +40 -2
- package/dist/components/chat/vertical-scroll-fade.d.ts +6 -0
- package/dist/components/chat/vertical-scroll-fade.d.ts.map +1 -0
- package/dist/components/chat/vertical-scroll-fade.js +12 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts +9 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.d.ts.map +1 -0
- package/dist/components/native-capabilities/bluetooth-panel-helpers.js +37 -0
- package/dist/components/native-capabilities/bluetooth-panel.d.ts +56 -0
- package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/bluetooth-panel.js +470 -0
- package/dist/components/native-capabilities/camera-preview.d.ts +39 -0
- package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -0
- package/dist/components/native-capabilities/camera-preview.js +228 -0
- package/dist/components/native-capabilities/capability-badge.d.ts +23 -0
- package/dist/components/native-capabilities/capability-badge.d.ts.map +1 -0
- package/dist/components/native-capabilities/capability-badge.js +39 -0
- package/dist/components/native-capabilities/capability-matrix.d.ts +14 -0
- package/dist/components/native-capabilities/capability-matrix.d.ts.map +1 -0
- package/dist/components/native-capabilities/capability-matrix.js +97 -0
- package/dist/components/native-capabilities/clipboard-button.d.ts +26 -0
- package/dist/components/native-capabilities/clipboard-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/clipboard-button.js +99 -0
- package/dist/components/native-capabilities/device-io-controls.d.ts +4 -0
- package/dist/components/native-capabilities/device-io-controls.d.ts.map +1 -0
- package/dist/components/native-capabilities/device-io-controls.js +28 -0
- package/dist/components/native-capabilities/device-list.d.ts +20 -0
- package/dist/components/native-capabilities/device-list.d.ts.map +1 -0
- package/dist/components/native-capabilities/device-list.js +14 -0
- package/dist/components/native-capabilities/display-map.d.ts +23 -0
- package/dist/components/native-capabilities/display-map.d.ts.map +1 -0
- package/dist/components/native-capabilities/display-map.js +114 -0
- package/dist/components/native-capabilities/haptic-button.d.ts +26 -0
- package/dist/components/native-capabilities/haptic-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/haptic-button.js +94 -0
- package/dist/components/native-capabilities/hid-panel.d.ts +40 -0
- package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/hid-panel.js +373 -0
- package/dist/components/native-capabilities/index.d.ts +27 -0
- package/dist/components/native-capabilities/index.d.ts.map +1 -0
- package/dist/components/native-capabilities/index.js +26 -0
- package/dist/components/native-capabilities/live-indicator.d.ts +15 -0
- package/dist/components/native-capabilities/live-indicator.d.ts.map +1 -0
- package/dist/components/native-capabilities/live-indicator.js +26 -0
- package/dist/components/native-capabilities/local-auth-button.d.ts +33 -0
- package/dist/components/native-capabilities/local-auth-button.d.ts.map +1 -0
- package/dist/components/native-capabilities/local-auth-button.js +115 -0
- package/dist/components/native-capabilities/location-panel.d.ts +29 -0
- package/dist/components/native-capabilities/location-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/location-panel.js +146 -0
- package/dist/components/native-capabilities/microphone-meter.d.ts +35 -0
- package/dist/components/native-capabilities/microphone-meter.d.ts.map +1 -0
- package/dist/components/native-capabilities/microphone-meter.js +244 -0
- package/dist/components/native-capabilities/midi-monitor.d.ts +54 -0
- package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -0
- package/dist/components/native-capabilities/midi-monitor.js +534 -0
- package/dist/components/native-capabilities/native-capability-panel.d.ts +11 -0
- package/dist/components/native-capabilities/native-capability-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/native-capability-panel.js +28 -0
- package/dist/components/native-capabilities/notification-panel.d.ts +24 -0
- package/dist/components/native-capabilities/notification-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/notification-panel.js +124 -0
- package/dist/components/native-capabilities/power-blocker-controller.d.ts +19 -0
- package/dist/components/native-capabilities/power-blocker-controller.d.ts.map +1 -0
- package/dist/components/native-capabilities/power-blocker-controller.js +83 -0
- package/dist/components/native-capabilities/power-panel.d.ts +67 -0
- package/dist/components/native-capabilities/power-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/power-panel.js +309 -0
- package/dist/components/native-capabilities/readout.d.ts +10 -0
- package/dist/components/native-capabilities/readout.d.ts.map +1 -0
- package/dist/components/native-capabilities/readout.js +11 -0
- package/dist/components/native-capabilities/screen-share-preview.d.ts +36 -0
- package/dist/components/native-capabilities/screen-share-preview.d.ts.map +1 -0
- package/dist/components/native-capabilities/screen-share-preview.js +191 -0
- package/dist/components/native-capabilities/secure-storage-panel.d.ts +36 -0
- package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/secure-storage-panel.js +193 -0
- package/dist/components/native-capabilities/serial-console.d.ts +64 -0
- package/dist/components/native-capabilities/serial-console.d.ts.map +1 -0
- package/dist/components/native-capabilities/serial-console.js +399 -0
- package/dist/components/native-capabilities/shortcut-recorder.d.ts +35 -0
- package/dist/components/native-capabilities/shortcut-recorder.d.ts.map +1 -0
- package/dist/components/native-capabilities/shortcut-recorder.js +217 -0
- package/dist/components/native-capabilities/stream-log.d.ts +35 -0
- package/dist/components/native-capabilities/stream-log.d.ts.map +1 -0
- package/dist/components/native-capabilities/stream-log.js +65 -0
- package/dist/components/native-capabilities/system-audio-monitor.d.ts +34 -0
- package/dist/components/native-capabilities/system-audio-monitor.d.ts.map +1 -0
- package/dist/components/native-capabilities/system-audio-monitor.js +275 -0
- package/dist/components/native-capabilities/usb-panel.d.ts +54 -0
- package/dist/components/native-capabilities/usb-panel.d.ts.map +1 -0
- package/dist/components/native-capabilities/usb-panel.js +363 -0
- package/dist/components/native-capabilities/use-capability.d.ts +20 -0
- package/dist/components/native-capabilities/use-capability.d.ts.map +1 -0
- package/dist/components/native-capabilities/use-capability.js +61 -0
- package/dist/components/ui/app-frame.d.ts +22 -0
- package/dist/components/ui/app-frame.d.ts.map +1 -0
- package/dist/components/ui/app-frame.js +56 -0
- package/dist/components/ui/button-group.d.ts +1 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/color-well.d.ts +13 -0
- package/dist/components/ui/color-well.d.ts.map +1 -0
- package/dist/components/ui/color-well.js +30 -0
- package/dist/components/ui/date-field.d.ts +19 -0
- package/dist/components/ui/date-field.d.ts.map +1 -0
- package/dist/components/ui/date-field.js +54 -0
- package/dist/components/ui/edge-fade.d.ts +11 -0
- package/dist/components/ui/edge-fade.d.ts.map +1 -0
- package/dist/components/ui/edge-fade.js +41 -0
- package/dist/components/ui/empty.js +1 -1
- package/dist/components/ui/field.d.ts +1 -1
- package/dist/components/ui/grid.d.ts +24 -0
- package/dist/components/ui/grid.d.ts.map +1 -0
- package/dist/components/ui/grid.js +234 -0
- package/dist/components/ui/icon-button.d.ts +15 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +15 -0
- package/dist/components/ui/index.d.ts +19 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +19 -0
- package/dist/components/ui/input-group.d.ts +1 -1
- package/dist/components/ui/inspector.d.ts +15 -0
- package/dist/components/ui/inspector.d.ts.map +1 -0
- package/dist/components/ui/inspector.js +26 -0
- package/dist/components/ui/kbd.d.ts +1 -1
- package/dist/components/ui/list.d.ts +24 -0
- package/dist/components/ui/list.d.ts.map +1 -0
- package/dist/components/ui/list.js +224 -0
- package/dist/components/ui/message-scroller-layout-stability.d.ts +33 -0
- package/dist/components/ui/message-scroller-layout-stability.d.ts.map +1 -0
- package/dist/components/ui/message-scroller-layout-stability.js +153 -0
- package/dist/components/ui/message-scroller.d.ts +11 -0
- package/dist/components/ui/message-scroller.d.ts.map +1 -0
- package/dist/components/ui/message-scroller.js +37 -0
- package/dist/components/ui/notification-dot.d.ts +4 -0
- package/dist/components/ui/notification-dot.d.ts.map +1 -0
- package/dist/components/ui/notification-dot.js +7 -0
- package/dist/components/ui/number-input.d.ts +16 -0
- package/dist/components/ui/number-input.d.ts.map +1 -0
- package/dist/components/ui/number-input.js +56 -0
- package/dist/components/ui/panel.d.ts +18 -0
- package/dist/components/ui/panel.d.ts.map +1 -0
- package/dist/components/ui/panel.js +40 -0
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/search-field.d.ts +19 -0
- package/dist/components/ui/search-field.d.ts.map +1 -0
- package/dist/components/ui/search-field.js +64 -0
- package/dist/components/ui/segmented-control.d.ts +21 -0
- package/dist/components/ui/segmented-control.d.ts.map +1 -0
- package/dist/components/ui/segmented-control.js +61 -0
- package/dist/components/ui/sidebar.js +1 -1
- package/dist/components/ui/sonner.d.ts +4 -3
- package/dist/components/ui/sonner.d.ts.map +1 -1
- package/dist/components/ui/sonner.js +7 -6
- package/dist/components/ui/split-view.d.ts +11 -0
- package/dist/components/ui/split-view.d.ts.map +1 -0
- package/dist/components/ui/split-view.js +13 -0
- package/dist/components/ui/status.d.ts +13 -0
- package/dist/components/ui/status.d.ts.map +1 -0
- package/dist/components/ui/status.js +36 -0
- package/dist/components/ui/table.d.ts +11 -2
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/table.js +28 -6
- package/dist/components/ui/text.d.ts +17 -0
- package/dist/components/ui/text.d.ts.map +1 -0
- package/dist/components/ui/text.js +55 -0
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/toolbar.d.ts +20 -0
- package/dist/components/ui/toolbar.d.ts.map +1 -0
- package/dist/components/ui/toolbar.js +52 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/lib/frame-lifecycle.d.ts +28 -0
- package/dist/lib/frame-lifecycle.d.ts.map +1 -1
- package/dist/lib/frame-lifecycle.js +84 -0
- package/dist/lib/native-capabilities/access.d.ts +13 -0
- package/dist/lib/native-capabilities/access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/access.js +53 -0
- package/dist/lib/native-capabilities/bluetooth-access.d.ts +14 -0
- package/dist/lib/native-capabilities/bluetooth-access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-access.js +43 -0
- package/dist/lib/native-capabilities/bluetooth-connection.d.ts +19 -0
- package/dist/lib/native-capabilities/bluetooth-connection.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-connection.js +88 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +7 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-gatt.js +77 -0
- package/dist/lib/native-capabilities/bluetooth-internal.d.ts +10 -0
- package/dist/lib/native-capabilities/bluetooth-internal.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-internal.js +105 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +33 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-native-fallback.js +214 -0
- package/dist/lib/native-capabilities/bluetooth-types.d.ts +85 -0
- package/dist/lib/native-capabilities/bluetooth-types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth-types.js +2 -0
- package/dist/lib/native-capabilities/bluetooth.d.ts +7 -0
- package/dist/lib/native-capabilities/bluetooth.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bluetooth.js +4 -0
- package/dist/lib/native-capabilities/bridge.d.ts +23 -0
- package/dist/lib/native-capabilities/bridge.d.ts.map +1 -0
- package/dist/lib/native-capabilities/bridge.js +266 -0
- package/dist/lib/native-capabilities/capabilities.d.ts +7 -0
- package/dist/lib/native-capabilities/capabilities.d.ts.map +1 -0
- package/dist/lib/native-capabilities/capabilities.js +95 -0
- package/dist/lib/native-capabilities/clipboard.d.ts +11 -0
- package/dist/lib/native-capabilities/clipboard.d.ts.map +1 -0
- package/dist/lib/native-capabilities/clipboard.js +58 -0
- package/dist/lib/native-capabilities/device-io-errors.d.ts +11 -0
- package/dist/lib/native-capabilities/device-io-errors.d.ts.map +1 -0
- package/dist/lib/native-capabilities/device-io-errors.js +82 -0
- package/dist/lib/native-capabilities/displays.d.ts +38 -0
- package/dist/lib/native-capabilities/displays.d.ts.map +1 -0
- package/dist/lib/native-capabilities/displays.js +12 -0
- package/dist/lib/native-capabilities/global-shortcuts.d.ts +86 -0
- package/dist/lib/native-capabilities/global-shortcuts.d.ts.map +1 -0
- package/dist/lib/native-capabilities/global-shortcuts.js +351 -0
- package/dist/lib/native-capabilities/haptics.d.ts +25 -0
- package/dist/lib/native-capabilities/haptics.d.ts.map +1 -0
- package/dist/lib/native-capabilities/haptics.js +18 -0
- package/dist/lib/native-capabilities/hid-native.d.ts +26 -0
- package/dist/lib/native-capabilities/hid-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/hid-native.js +229 -0
- package/dist/lib/native-capabilities/hid.d.ts +52 -0
- package/dist/lib/native-capabilities/hid.d.ts.map +1 -0
- package/dist/lib/native-capabilities/hid.js +163 -0
- package/dist/lib/native-capabilities/index.d.ts +40 -0
- package/dist/lib/native-capabilities/index.d.ts.map +1 -0
- package/dist/lib/native-capabilities/index.js +21 -0
- package/dist/lib/native-capabilities/local-authentication.d.ts +32 -0
- package/dist/lib/native-capabilities/local-authentication.d.ts.map +1 -0
- package/dist/lib/native-capabilities/local-authentication.js +46 -0
- package/dist/lib/native-capabilities/location.d.ts +49 -0
- package/dist/lib/native-capabilities/location.d.ts.map +1 -0
- package/dist/lib/native-capabilities/location.js +114 -0
- package/dist/lib/native-capabilities/media-permissions.d.ts +28 -0
- package/dist/lib/native-capabilities/media-permissions.d.ts.map +1 -0
- package/dist/lib/native-capabilities/media-permissions.js +37 -0
- package/dist/lib/native-capabilities/media.d.ts +17 -0
- package/dist/lib/native-capabilities/media.d.ts.map +1 -0
- package/dist/lib/native-capabilities/media.js +104 -0
- package/dist/lib/native-capabilities/midi-access.d.ts +13 -0
- package/dist/lib/native-capabilities/midi-access.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-access.js +68 -0
- package/dist/lib/native-capabilities/midi-internal.d.ts +12 -0
- package/dist/lib/native-capabilities/midi-internal.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-internal.js +88 -0
- package/dist/lib/native-capabilities/midi-native-fallback.d.ts +27 -0
- package/dist/lib/native-capabilities/midi-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-native-fallback.js +127 -0
- package/dist/lib/native-capabilities/midi-ports.d.ts +6 -0
- package/dist/lib/native-capabilities/midi-ports.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-ports.js +115 -0
- package/dist/lib/native-capabilities/midi-types.d.ts +25 -0
- package/dist/lib/native-capabilities/midi-types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi-types.js +1 -0
- package/dist/lib/native-capabilities/midi.d.ts +6 -0
- package/dist/lib/native-capabilities/midi.d.ts.map +1 -0
- package/dist/lib/native-capabilities/midi.js +3 -0
- package/dist/lib/native-capabilities/native-device-io.d.ts +28 -0
- package/dist/lib/native-capabilities/native-device-io.d.ts.map +1 -0
- package/dist/lib/native-capabilities/native-device-io.js +91 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.d.ts +13 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.d.ts.map +1 -0
- package/dist/lib/native-capabilities/native-device-lifecycle.js +40 -0
- package/dist/lib/native-capabilities/notifications.d.ts +38 -0
- package/dist/lib/native-capabilities/notifications.d.ts.map +1 -0
- package/dist/lib/native-capabilities/notifications.js +50 -0
- package/dist/lib/native-capabilities/power-session.d.ts +113 -0
- package/dist/lib/native-capabilities/power-session.d.ts.map +1 -0
- package/dist/lib/native-capabilities/power-session.js +264 -0
- package/dist/lib/native-capabilities/secure-storage.d.ts +36 -0
- package/dist/lib/native-capabilities/secure-storage.d.ts.map +1 -0
- package/dist/lib/native-capabilities/secure-storage.js +64 -0
- package/dist/lib/native-capabilities/serial-native.d.ts +23 -0
- package/dist/lib/native-capabilities/serial-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/serial-native.js +181 -0
- package/dist/lib/native-capabilities/serial.d.ts +76 -0
- package/dist/lib/native-capabilities/serial.d.ts.map +1 -0
- package/dist/lib/native-capabilities/serial.js +215 -0
- package/dist/lib/native-capabilities/system-audio.d.ts +127 -0
- package/dist/lib/native-capabilities/system-audio.d.ts.map +1 -0
- package/dist/lib/native-capabilities/system-audio.js +330 -0
- package/dist/lib/native-capabilities/types.d.ts +62 -0
- package/dist/lib/native-capabilities/types.d.ts.map +1 -0
- package/dist/lib/native-capabilities/types.js +27 -0
- package/dist/lib/native-capabilities/usb-native.d.ts +39 -0
- package/dist/lib/native-capabilities/usb-native.d.ts.map +1 -0
- package/dist/lib/native-capabilities/usb-native.js +217 -0
- package/dist/lib/native-capabilities/usb.d.ts +85 -0
- package/dist/lib/native-capabilities/usb.d.ts.map +1 -0
- package/dist/lib/native-capabilities/usb.js +225 -0
- package/docs/README.md +37 -0
- package/docs/accessibility.md +32 -0
- package/docs/app-anatomy.md +72 -0
- package/docs/component-catalog.md +59 -0
- package/docs/component-guide-template.md +37 -0
- package/docs/design-tokens.md +172 -0
- package/docs/foundations.md +56 -0
- package/docs/native-integration.md +33 -0
- package/docs/standalone-app-windows.md +128 -0
- package/package.json +9 -3
- package/src/components/ui/alert.md +55 -0
- package/src/components/ui/app-frame.md +33 -0
- package/src/components/ui/badge.md +57 -0
- package/src/components/ui/button.md +76 -0
- package/src/components/ui/color-well.md +11 -0
- package/src/components/ui/combobox.md +43 -0
- package/src/components/ui/date-field.md +32 -0
- package/src/components/ui/edge-fade.md +7 -0
- package/src/components/ui/empty.md +82 -0
- package/src/components/ui/field.md +77 -0
- package/src/components/ui/grid.md +105 -0
- package/src/components/ui/icon-button.md +36 -0
- package/src/components/ui/inspector.md +11 -0
- package/src/components/ui/item.md +87 -0
- package/src/components/ui/list.md +107 -0
- package/src/components/ui/notification-dot.md +7 -0
- package/src/components/ui/number-input.md +19 -0
- package/src/components/ui/panel.md +11 -0
- package/src/components/ui/resizable.md +66 -0
- package/src/components/ui/scroll-area.md +68 -0
- package/src/components/ui/search-field.md +33 -0
- package/src/components/ui/segmented-control.md +39 -0
- package/src/components/ui/sidebar.md +113 -0
- package/src/components/ui/sonner.md +37 -0
- package/src/components/ui/split-view.md +15 -0
- package/src/components/ui/status.md +12 -0
- package/src/components/ui/table.md +35 -0
- package/src/components/ui/tabs.md +66 -0
- package/src/components/ui/text.md +17 -0
- package/src/components/ui/toggle-group.md +80 -0
- package/src/components/ui/toggle.md +73 -0
- package/src/components/ui/toolbar.md +21 -0
- package/src/styles/index.css +491 -3
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
import { Text } from './text';
|
|
5
|
+
function Inspector({ className, ...props }) {
|
|
6
|
+
return (_jsx("aside", { "data-slot": "inspector", className: cn('bg-background flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden', className), ...props }));
|
|
7
|
+
}
|
|
8
|
+
function InspectorHeader({ className, ...props }) {
|
|
9
|
+
return (_jsx("div", { "data-slot": "inspector-header", className: cn('border-border/70 flex min-h-9 shrink-0 items-center gap-2 border-b px-3 py-1.5', className), ...props }));
|
|
10
|
+
}
|
|
11
|
+
function InspectorContent({ className, ...props }) {
|
|
12
|
+
return (_jsx("div", { "data-slot": "inspector-content", className: cn('min-h-0 flex-1 overflow-y-auto pb-[calc(var(--chat-safe-padding,0px)+0.75rem)]', className), ...props }));
|
|
13
|
+
}
|
|
14
|
+
function InspectorSection({ title, actions, className, children, ...props }) {
|
|
15
|
+
return (_jsxs("section", { "data-slot": "inspector-section", className: cn('border-border/60 border-b px-3 py-3 last:border-b-0', className), ...props, children: [title || actions ? (_jsxs("div", { "data-slot": "inspector-section-header", className: "mb-2 flex min-w-0 items-center gap-2", children: [title ? (_jsx(Text, { variant: "small-strong", color: "secondary", truncate: true, className: "uppercase tracking-wide", children: title })) : null, actions ? (_jsx("div", { className: "ml-auto flex shrink-0 items-center gap-1", children: actions })) : null] })) : null, _jsx("div", { "data-slot": "inspector-section-content", className: "space-y-2", children: children })] }));
|
|
16
|
+
}
|
|
17
|
+
function InspectorRow({ className, ...props }) {
|
|
18
|
+
return (_jsx("div", { "data-slot": "inspector-row", className: cn('grid min-h-7 grid-cols-[minmax(5rem,0.8fr)_minmax(0,1.2fr)] items-center gap-3', className), ...props }));
|
|
19
|
+
}
|
|
20
|
+
function InspectorLabel({ className, ...props }) {
|
|
21
|
+
return (_jsx(Text, { as: "label", variant: "small", color: "secondary", "data-slot": "inspector-label", className: cn('truncate', className), ...props }));
|
|
22
|
+
}
|
|
23
|
+
function InspectorValue({ className, ...props }) {
|
|
24
|
+
return (_jsx("div", { "data-slot": "inspector-value", className: cn('min-w-0 justify-self-stretch', className), ...props }));
|
|
25
|
+
}
|
|
26
|
+
export { Inspector, InspectorContent, InspectorHeader, InspectorLabel, InspectorRow, InspectorSection, InspectorValue, };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
declare function Kbd({ className, ...props }: React.ComponentProps<'kbd'>): import("react/jsx-runtime").JSX.Element;
|
|
2
|
-
declare function KbdGroup({ className, ...props }: React.ComponentProps<'
|
|
2
|
+
declare function KbdGroup({ className, ...props }: React.ComponentProps<'kbd'>): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
export { Kbd, KbdGroup };
|
|
4
4
|
//# sourceMappingURL=kbd.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
type ListSelectionMode = 'none' | 'single' | 'multiple';
|
|
3
|
+
type ListProps = Omit<React.ComponentProps<'div'>, 'defaultValue' | 'onChange'> & {
|
|
4
|
+
selectionMode?: ListSelectionMode;
|
|
5
|
+
selectedValues?: Iterable<string>;
|
|
6
|
+
defaultSelectedValues?: Iterable<string>;
|
|
7
|
+
onSelectionChange?: (values: ReadonlySet<string>) => void;
|
|
8
|
+
onAction?: (value: string) => void;
|
|
9
|
+
orientation?: 'horizontal' | 'vertical';
|
|
10
|
+
loop?: boolean;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare function List({ className, children, selectionMode, selectedValues, defaultSelectedValues, onSelectionChange, onAction, orientation, loop, disabled, role, onKeyDown, ref, ...props }: ListProps): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
type ListItemProps = Omit<React.ComponentProps<'div'>, 'value'> & {
|
|
15
|
+
value: string;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
};
|
|
18
|
+
declare function ListItem({ className, children, value, disabled, onClick, onDoubleClick, onFocus, ref, role, ...props }: ListItemProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
declare function ListItemContent({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
declare function ListItemTitle({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
declare function ListItemDescription({ className, ...props }: React.ComponentProps<'p'>): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
declare function ListItemActions({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export { List, ListItem, ListItemActions, ListItemContent, ListItemDescription, ListItemTitle, type ListProps, type ListSelectionMode, };
|
|
24
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/components/ui/list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,KAAK,iBAAiB,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAA;AAmDvD,KAAK,SAAS,GAAG,IAAI,CACnB,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAC3B,cAAc,GAAG,UAAU,CAC5B,GAAG;IACF,aAAa,CAAC,EAAE,iBAAiB,CAAA;IACjC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IACjC,qBAAqB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IACxC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAA;IACzD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IACvC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,iBAAS,IAAI,CAAC,EACZ,SAAS,EACT,QAAQ,EACR,aAAsB,EACtB,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,QAAQ,EACR,WAAwB,EACxB,IAAY,EACZ,QAAgB,EAChB,IAAI,EACJ,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,SAAS,2CAsMX;AAED,KAAK,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,GAAG;IAChE,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,QAAQ,EACR,KAAK,EACL,QAAgB,EAChB,OAAO,EACP,aAAa,EACb,OAAO,EACP,GAAG,EACH,IAAI,EACJ,GAAG,KAAK,EACT,EAAE,aAAa,2CAmFf;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,2CAQ3B;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAQ7B;AAED,OAAO,EACL,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,KAAK,SAAS,EACd,KAAK,iBAAiB,GACvB,CAAA"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { cn } from '../../lib/utils';
|
|
5
|
+
const ListContext = React.createContext(null);
|
|
6
|
+
function useListContext(component) {
|
|
7
|
+
const context = React.useContext(ListContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error(`${component} must be used inside List`);
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
}
|
|
13
|
+
function toSelection(values) {
|
|
14
|
+
return new Set(values ?? []);
|
|
15
|
+
}
|
|
16
|
+
function sameSelection(a, b) {
|
|
17
|
+
if (a.size !== b.size)
|
|
18
|
+
return false;
|
|
19
|
+
for (const value of a) {
|
|
20
|
+
if (!b.has(value))
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
function isInteractiveDescendant(target, currentTarget) {
|
|
26
|
+
if (!(target instanceof HTMLElement) || target === currentTarget)
|
|
27
|
+
return false;
|
|
28
|
+
return Boolean(target.closest('a,button,input,select,textarea,[contenteditable="true"],[role="button"],[role="link"]'));
|
|
29
|
+
}
|
|
30
|
+
function List({ className, children, selectionMode = 'none', selectedValues, defaultSelectedValues, onSelectionChange, onAction, orientation = 'vertical', loop = false, disabled = false, role, onKeyDown, ref, ...props }) {
|
|
31
|
+
const rootRef = React.useRef(null);
|
|
32
|
+
const itemsRef = React.useRef(new Map());
|
|
33
|
+
const [activeValue, setActiveValueState] = React.useState(null);
|
|
34
|
+
const [uncontrolledSelection, setUncontrolledSelection] = React.useState(() => toSelection(defaultSelectedValues));
|
|
35
|
+
const controlledSelection = React.useMemo(() => selectedValues === undefined ? undefined : toSelection(selectedValues), [selectedValues]);
|
|
36
|
+
const selection = controlledSelection ?? uncontrolledSelection;
|
|
37
|
+
const setRef = React.useCallback((node) => {
|
|
38
|
+
rootRef.current = node;
|
|
39
|
+
if (typeof ref === 'function')
|
|
40
|
+
ref(node);
|
|
41
|
+
else if (ref)
|
|
42
|
+
ref.current = node;
|
|
43
|
+
}, [ref]);
|
|
44
|
+
const registerItem = React.useCallback((value, node, itemDisabled) => {
|
|
45
|
+
if (!node)
|
|
46
|
+
return () => undefined;
|
|
47
|
+
itemsRef.current.set(value, { node, disabled: itemDisabled });
|
|
48
|
+
if (!disabled && !itemDisabled) {
|
|
49
|
+
setActiveValueState((current) => current ?? value);
|
|
50
|
+
}
|
|
51
|
+
return () => {
|
|
52
|
+
itemsRef.current.delete(value);
|
|
53
|
+
setActiveValueState((current) => {
|
|
54
|
+
if (current !== value)
|
|
55
|
+
return current;
|
|
56
|
+
return ([...itemsRef.current.entries()].find(([, item]) => !disabled && !item.disabled)?.[0] ?? null);
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
}, [disabled]);
|
|
60
|
+
const setActiveValue = React.useCallback((value) => {
|
|
61
|
+
const item = itemsRef.current.get(value);
|
|
62
|
+
if (item && !item.disabled)
|
|
63
|
+
setActiveValueState(value);
|
|
64
|
+
}, []);
|
|
65
|
+
const commitSelection = React.useCallback((next) => {
|
|
66
|
+
if (sameSelection(selection, next))
|
|
67
|
+
return;
|
|
68
|
+
if (controlledSelection === undefined)
|
|
69
|
+
setUncontrolledSelection(next);
|
|
70
|
+
onSelectionChange?.(next);
|
|
71
|
+
}, [controlledSelection, onSelectionChange, selection]);
|
|
72
|
+
const select = React.useCallback((value) => {
|
|
73
|
+
if (disabled || selectionMode === 'none')
|
|
74
|
+
return;
|
|
75
|
+
const item = itemsRef.current.get(value);
|
|
76
|
+
if (!item || item.disabled)
|
|
77
|
+
return;
|
|
78
|
+
if (selectionMode === 'single') {
|
|
79
|
+
commitSelection(new Set([value]));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const next = new Set(selection);
|
|
83
|
+
if (next.has(value))
|
|
84
|
+
next.delete(value);
|
|
85
|
+
else
|
|
86
|
+
next.add(value);
|
|
87
|
+
commitSelection(next);
|
|
88
|
+
}, [commitSelection, disabled, selection, selectionMode]);
|
|
89
|
+
const activate = React.useCallback((value) => {
|
|
90
|
+
if (disabled || itemsRef.current.get(value)?.disabled)
|
|
91
|
+
return;
|
|
92
|
+
onAction?.(value);
|
|
93
|
+
}, [disabled, onAction]);
|
|
94
|
+
const moveFocus = React.useCallback((direction) => {
|
|
95
|
+
const items = [...itemsRef.current.entries()].filter(([, item]) => !disabled && !item.disabled);
|
|
96
|
+
if (items.length === 0)
|
|
97
|
+
return;
|
|
98
|
+
const currentIndex = items.findIndex(([value]) => value === activeValue);
|
|
99
|
+
let nextIndex = currentIndex;
|
|
100
|
+
if (direction === 'first')
|
|
101
|
+
nextIndex = 0;
|
|
102
|
+
if (direction === 'last')
|
|
103
|
+
nextIndex = items.length - 1;
|
|
104
|
+
if (direction === 'next') {
|
|
105
|
+
nextIndex = currentIndex < 0 ? 0 : currentIndex + 1;
|
|
106
|
+
if (nextIndex >= items.length)
|
|
107
|
+
nextIndex = loop ? 0 : items.length - 1;
|
|
108
|
+
}
|
|
109
|
+
if (direction === 'previous') {
|
|
110
|
+
nextIndex = currentIndex < 0 ? items.length - 1 : currentIndex - 1;
|
|
111
|
+
if (nextIndex < 0)
|
|
112
|
+
nextIndex = loop ? items.length - 1 : 0;
|
|
113
|
+
}
|
|
114
|
+
const [value, item] = items[nextIndex];
|
|
115
|
+
setActiveValueState(value);
|
|
116
|
+
item.node.focus();
|
|
117
|
+
}, [activeValue, disabled, loop]);
|
|
118
|
+
const handleKeyDown = (event) => {
|
|
119
|
+
onKeyDown?.(event);
|
|
120
|
+
if (event.defaultPrevented || disabled)
|
|
121
|
+
return;
|
|
122
|
+
const target = event.target;
|
|
123
|
+
if (target.dataset.slot !== 'list-item')
|
|
124
|
+
return;
|
|
125
|
+
const previousKey = orientation === 'vertical' ? 'ArrowUp' : 'ArrowLeft';
|
|
126
|
+
const nextKey = orientation === 'vertical' ? 'ArrowDown' : 'ArrowRight';
|
|
127
|
+
if (event.key === previousKey || event.key === nextKey) {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
moveFocus(event.key === previousKey ? 'previous' : 'next');
|
|
130
|
+
}
|
|
131
|
+
else if (event.key === 'Home' || event.key === 'End') {
|
|
132
|
+
event.preventDefault();
|
|
133
|
+
moveFocus(event.key === 'Home' ? 'first' : 'last');
|
|
134
|
+
}
|
|
135
|
+
else if (event.key === ' ') {
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
if (activeValue)
|
|
138
|
+
select(activeValue);
|
|
139
|
+
}
|
|
140
|
+
else if (event.key === 'Enter' && activeValue) {
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
if (selectionMode !== 'none')
|
|
143
|
+
select(activeValue);
|
|
144
|
+
activate(activeValue);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const context = React.useMemo(() => ({
|
|
148
|
+
activeValue,
|
|
149
|
+
disabled,
|
|
150
|
+
isSelected: (value) => selection.has(value),
|
|
151
|
+
registerItem,
|
|
152
|
+
select,
|
|
153
|
+
selectionMode,
|
|
154
|
+
setActiveValue,
|
|
155
|
+
activate,
|
|
156
|
+
}), [
|
|
157
|
+
activeValue,
|
|
158
|
+
activate,
|
|
159
|
+
disabled,
|
|
160
|
+
registerItem,
|
|
161
|
+
select,
|
|
162
|
+
selection,
|
|
163
|
+
selectionMode,
|
|
164
|
+
setActiveValue,
|
|
165
|
+
]);
|
|
166
|
+
const resolvedRole = role ?? (selectionMode === 'none' ? 'list' : 'listbox');
|
|
167
|
+
return (_jsx(ListContext.Provider, { value: context, children: _jsx("div", { ref: setRef, role: resolvedRole, "aria-disabled": disabled || undefined, "aria-multiselectable": selectionMode === 'multiple' ? true : undefined, "aria-orientation": resolvedRole === 'listbox' ? orientation : undefined, "data-slot": "list", "data-disabled": disabled || undefined, "data-orientation": orientation, "data-selection-mode": selectionMode, className: cn('flex min-w-0 outline-none', orientation === 'vertical'
|
|
168
|
+
? 'flex-col gap-0.5'
|
|
169
|
+
: 'flex-row items-center gap-1', className), onKeyDown: handleKeyDown, ...props, children: children }) }));
|
|
170
|
+
}
|
|
171
|
+
function ListItem({ className, children, value, disabled = false, onClick, onDoubleClick, onFocus, ref, role, ...props }) {
|
|
172
|
+
const context = useListContext('ListItem');
|
|
173
|
+
const { registerItem } = context;
|
|
174
|
+
const itemRef = React.useRef(null);
|
|
175
|
+
const isDisabled = context.disabled || disabled;
|
|
176
|
+
const isSelected = context.isSelected(value);
|
|
177
|
+
const isActive = context.activeValue === value;
|
|
178
|
+
const setRef = React.useCallback((node) => {
|
|
179
|
+
itemRef.current = node;
|
|
180
|
+
if (typeof ref === 'function')
|
|
181
|
+
ref(node);
|
|
182
|
+
else if (ref)
|
|
183
|
+
ref.current = node;
|
|
184
|
+
}, [ref]);
|
|
185
|
+
React.useLayoutEffect(() => registerItem(value, itemRef.current, isDisabled), [isDisabled, registerItem, value]);
|
|
186
|
+
const resolvedRole = role ?? (context.selectionMode === 'none' ? 'listitem' : 'option');
|
|
187
|
+
return (_jsx("div", { ref: setRef, role: resolvedRole, tabIndex: isDisabled ? -1 : isActive ? 0 : -1, "aria-disabled": isDisabled || undefined, "aria-selected": context.selectionMode === 'none' ? undefined : isSelected, "data-slot": "list-item", "data-active": isActive || undefined, "data-disabled": isDisabled || undefined, "data-selected": context.selectionMode === 'none' ? undefined : isSelected, "data-value": value, className: cn('group/list-item relative flex min-w-0 cursor-default select-none items-center gap-2 rounded-md px-2.5 py-2 text-sm outline-none transition-colors duration-100', 'hover:bg-accent/60 focus-visible:bg-accent focus-visible:ring-ring/50 focus-visible:ring-[3px]', 'data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground', 'data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50', className), onClick: (event) => {
|
|
188
|
+
onClick?.(event);
|
|
189
|
+
if (event.defaultPrevented ||
|
|
190
|
+
isDisabled ||
|
|
191
|
+
isInteractiveDescendant(event.target, event.currentTarget)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
context.setActiveValue(value);
|
|
195
|
+
event.currentTarget.focus();
|
|
196
|
+
context.select(value);
|
|
197
|
+
}, onDoubleClick: (event) => {
|
|
198
|
+
onDoubleClick?.(event);
|
|
199
|
+
if (event.defaultPrevented ||
|
|
200
|
+
isDisabled ||
|
|
201
|
+
isInteractiveDescendant(event.target, event.currentTarget)) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
context.activate(value);
|
|
205
|
+
}, onFocus: (event) => {
|
|
206
|
+
onFocus?.(event);
|
|
207
|
+
if (!event.defaultPrevented && !isDisabled) {
|
|
208
|
+
context.setActiveValue(value);
|
|
209
|
+
}
|
|
210
|
+
}, ...props, children: children }));
|
|
211
|
+
}
|
|
212
|
+
function ListItemContent({ className, ...props }) {
|
|
213
|
+
return (_jsx("div", { "data-slot": "list-item-content", className: cn('min-w-0 flex-1', className), ...props }));
|
|
214
|
+
}
|
|
215
|
+
function ListItemTitle({ className, ...props }) {
|
|
216
|
+
return (_jsx("div", { "data-slot": "list-item-title", className: cn('truncate font-medium', className), ...props }));
|
|
217
|
+
}
|
|
218
|
+
function ListItemDescription({ className, ...props }) {
|
|
219
|
+
return (_jsx("p", { "data-slot": "list-item-description", className: cn('text-muted-foreground truncate text-xs', className), ...props }));
|
|
220
|
+
}
|
|
221
|
+
function ListItemActions({ className, ...props }) {
|
|
222
|
+
return (_jsx("div", { "data-slot": "list-item-actions", className: cn('ml-auto flex shrink-0 items-center gap-1', className), ...props }));
|
|
223
|
+
}
|
|
224
|
+
export { List, ListItem, ListItemActions, ListItemContent, ListItemDescription, ListItemTitle, };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
type ScrollToEnd = (options?: {
|
|
3
|
+
behavior?: ScrollBehavior;
|
|
4
|
+
}) => boolean;
|
|
5
|
+
type AnchorPosition = {
|
|
6
|
+
element: HTMLElement;
|
|
7
|
+
top: number;
|
|
8
|
+
bottom: number;
|
|
9
|
+
};
|
|
10
|
+
export type MessageScrollerLayoutSnapshot = {
|
|
11
|
+
anchors: AnchorPosition[];
|
|
12
|
+
atEnd: boolean;
|
|
13
|
+
scrollHeight: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function isMessageScrollerAtEnd(viewport: HTMLElement): boolean;
|
|
16
|
+
export declare function captureMessageScrollerLayout(viewport: HTMLElement): MessageScrollerLayoutSnapshot;
|
|
17
|
+
/**
|
|
18
|
+
* Preserve the first previously visible stable leaf when content above it
|
|
19
|
+
* changes height. Native scroll anchoring may already have done this; in that
|
|
20
|
+
* case the measured delta is zero and this is deliberately a no-op.
|
|
21
|
+
*/
|
|
22
|
+
export declare function restoreMessageScrollerAnchor(viewport: HTMLElement, snapshot: MessageScrollerLayoutSnapshot): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Complements shadcn's message scroller for mutable chat rows. The upstream
|
|
25
|
+
* primitive handles appends, prepends, and explicit jumps well, but a nested
|
|
26
|
+
* disclosure shrinking inside an existing row can look like user scroll
|
|
27
|
+
* intent. We remember whether the viewport was following the end before the
|
|
28
|
+
* resize and restore that mode, or preserve a visible content leaf when the
|
|
29
|
+
* user is reading higher in the transcript.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useMessageScrollerLayoutStability(viewportRef: RefObject<HTMLElement | null>, scrollToEnd: ScrollToEnd): void;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=message-scroller-layout-stability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-scroller-layout-stability.d.ts","sourceRoot":"","sources":["../../../src/components/ui/message-scroller-layout-stability.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAA;AAQzD,KAAK,WAAW,GAAG,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,cAAc,CAAA;CAAE,KAAK,OAAO,CAAA;AAEvE,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,WAAW,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,KAAK,EAAE,OAAO,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAWD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAKrE;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,WAAW,GACpB,6BAA6B,CAoB/B;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,6BAA6B,GACtC,OAAO,CAcT;AAED;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAC1C,WAAW,EAAE,WAAW,QAqGzB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
const END_THRESHOLD_PX = 8;
|
|
3
|
+
const POSITION_EPSILON_PX = 0.5;
|
|
4
|
+
const USER_SCROLL_GRACE_MS = 300;
|
|
5
|
+
const CONTENT_ANCHOR_SELECTOR = '[data-message-scroll-anchor]';
|
|
6
|
+
const MESSAGE_ANCHOR_SELECTOR = '[data-message-id]';
|
|
7
|
+
function relativePosition(element, viewport) {
|
|
8
|
+
const elementRect = element.getBoundingClientRect();
|
|
9
|
+
const viewportRect = viewport.getBoundingClientRect();
|
|
10
|
+
return {
|
|
11
|
+
top: elementRect.top - viewportRect.top,
|
|
12
|
+
bottom: elementRect.bottom - viewportRect.top,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function isMessageScrollerAtEnd(viewport) {
|
|
16
|
+
return (viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight <=
|
|
17
|
+
END_THRESHOLD_PX);
|
|
18
|
+
}
|
|
19
|
+
export function captureMessageScrollerLayout(viewport) {
|
|
20
|
+
// Prefer stable leaves within a message. A top-level message's own top does
|
|
21
|
+
// not move when content collapses inside it, so it is only a fallback when
|
|
22
|
+
// the visible leaf itself was removed by the disclosure transition.
|
|
23
|
+
const contentAnchors = Array.from(viewport.querySelectorAll(CONTENT_ANCHOR_SELECTOR));
|
|
24
|
+
const messageAnchors = Array.from(viewport.querySelectorAll(MESSAGE_ANCHOR_SELECTOR));
|
|
25
|
+
const anchors = [...contentAnchors, ...messageAnchors].map((element) => ({
|
|
26
|
+
element,
|
|
27
|
+
...relativePosition(element, viewport),
|
|
28
|
+
}));
|
|
29
|
+
return {
|
|
30
|
+
anchors,
|
|
31
|
+
atEnd: isMessageScrollerAtEnd(viewport),
|
|
32
|
+
scrollHeight: viewport.scrollHeight,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Preserve the first previously visible stable leaf when content above it
|
|
37
|
+
* changes height. Native scroll anchoring may already have done this; in that
|
|
38
|
+
* case the measured delta is zero and this is deliberately a no-op.
|
|
39
|
+
*/
|
|
40
|
+
export function restoreMessageScrollerAnchor(viewport, snapshot) {
|
|
41
|
+
const anchor = snapshot.anchors.find(({ element, top, bottom }) => {
|
|
42
|
+
if (!element.isConnected)
|
|
43
|
+
return false;
|
|
44
|
+
const current = element.getBoundingClientRect();
|
|
45
|
+
return current.height > 0 && bottom > 0 && top < viewport.clientHeight;
|
|
46
|
+
});
|
|
47
|
+
if (!anchor)
|
|
48
|
+
return false;
|
|
49
|
+
const current = relativePosition(anchor.element, viewport);
|
|
50
|
+
const delta = current.top - anchor.top;
|
|
51
|
+
if (Math.abs(delta) <= POSITION_EPSILON_PX)
|
|
52
|
+
return false;
|
|
53
|
+
viewport.scrollTop += delta;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Complements shadcn's message scroller for mutable chat rows. The upstream
|
|
58
|
+
* primitive handles appends, prepends, and explicit jumps well, but a nested
|
|
59
|
+
* disclosure shrinking inside an existing row can look like user scroll
|
|
60
|
+
* intent. We remember whether the viewport was following the end before the
|
|
61
|
+
* resize and restore that mode, or preserve a visible content leaf when the
|
|
62
|
+
* user is reading higher in the transcript.
|
|
63
|
+
*/
|
|
64
|
+
export function useMessageScrollerLayoutStability(viewportRef, scrollToEnd) {
|
|
65
|
+
const snapshotRef = useRef(null);
|
|
66
|
+
const followEndRef = useRef(true);
|
|
67
|
+
const userInteractingRef = useRef(false);
|
|
68
|
+
const suspendStabilityUntilRef = useRef(0);
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const viewport = viewportRef.current;
|
|
71
|
+
if (!viewport || typeof ResizeObserver === 'undefined')
|
|
72
|
+
return;
|
|
73
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
74
|
+
followEndRef.current = snapshotRef.current.atEnd;
|
|
75
|
+
let frame = 0;
|
|
76
|
+
const suspendForUserScroll = () => {
|
|
77
|
+
suspendStabilityUntilRef.current = Date.now() + USER_SCROLL_GRACE_MS;
|
|
78
|
+
};
|
|
79
|
+
const isUserScrolling = () => userInteractingRef.current ||
|
|
80
|
+
Date.now() < suspendStabilityUntilRef.current;
|
|
81
|
+
const handleWheel = (event) => {
|
|
82
|
+
suspendForUserScroll();
|
|
83
|
+
if (event.deltaY < 0)
|
|
84
|
+
followEndRef.current = false;
|
|
85
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
86
|
+
};
|
|
87
|
+
const handlePointerDown = () => {
|
|
88
|
+
userInteractingRef.current = true;
|
|
89
|
+
suspendForUserScroll();
|
|
90
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
91
|
+
};
|
|
92
|
+
const handlePointerUp = () => {
|
|
93
|
+
userInteractingRef.current = false;
|
|
94
|
+
suspendForUserScroll();
|
|
95
|
+
};
|
|
96
|
+
const captureAfterIntentionalScroll = () => {
|
|
97
|
+
const previous = snapshotRef.current;
|
|
98
|
+
const heightChanged = previous &&
|
|
99
|
+
Math.abs(previous.scrollHeight - viewport.scrollHeight) >
|
|
100
|
+
POSITION_EPSILON_PX;
|
|
101
|
+
// A browser clamp caused by content shrinking is layout, not user intent.
|
|
102
|
+
// Explicit wheel or scrollbar interaction always wins over that heuristic.
|
|
103
|
+
if (isUserScrolling() || !heightChanged) {
|
|
104
|
+
if (isUserScrolling())
|
|
105
|
+
suspendForUserScroll();
|
|
106
|
+
followEndRef.current = isMessageScrollerAtEnd(viewport);
|
|
107
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
111
|
+
window.cancelAnimationFrame(frame);
|
|
112
|
+
frame = window.requestAnimationFrame(() => {
|
|
113
|
+
const previous = snapshotRef.current;
|
|
114
|
+
if (isUserScrolling()) {
|
|
115
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (previous) {
|
|
119
|
+
if (followEndRef.current) {
|
|
120
|
+
// Public API resets the primitive's internal mode as well as the
|
|
121
|
+
// DOM position after a shrink was mistaken for an upward scroll.
|
|
122
|
+
scrollToEnd({ behavior: 'auto' });
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
restoreMessageScrollerAnchor(viewport, previous);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
snapshotRef.current = captureMessageScrollerLayout(viewport);
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
const content = viewport.querySelector('[data-slot="message-scroller-content"]');
|
|
132
|
+
if (content)
|
|
133
|
+
resizeObserver.observe(content);
|
|
134
|
+
viewport.addEventListener('wheel', handleWheel, { passive: true });
|
|
135
|
+
viewport.addEventListener('pointerdown', handlePointerDown, {
|
|
136
|
+
passive: true,
|
|
137
|
+
});
|
|
138
|
+
window.addEventListener('pointerup', handlePointerUp, { passive: true });
|
|
139
|
+
window.addEventListener('pointercancel', handlePointerUp, { passive: true });
|
|
140
|
+
viewport.addEventListener('scroll', captureAfterIntentionalScroll, {
|
|
141
|
+
passive: true,
|
|
142
|
+
});
|
|
143
|
+
return () => {
|
|
144
|
+
window.cancelAnimationFrame(frame);
|
|
145
|
+
resizeObserver.disconnect();
|
|
146
|
+
viewport.removeEventListener('wheel', handleWheel);
|
|
147
|
+
viewport.removeEventListener('pointerdown', handlePointerDown);
|
|
148
|
+
window.removeEventListener('pointerup', handlePointerUp);
|
|
149
|
+
window.removeEventListener('pointercancel', handlePointerUp);
|
|
150
|
+
viewport.removeEventListener('scroll', captureAfterIntentionalScroll);
|
|
151
|
+
};
|
|
152
|
+
}, [scrollToEnd, viewportRef]);
|
|
153
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { MessageScroller as MessageScrollerPrimitive, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility } from '@shadcn/react/message-scroller';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Button } from './button';
|
|
4
|
+
declare function MessageScrollerProvider(props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
declare function MessageScroller({ className, ...props }: React.ComponentProps<typeof MessageScrollerPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
declare function MessageScrollerViewport({ className, ref, ...props }: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare function MessageScrollerContent({ className, ...props }: React.ComponentProps<typeof MessageScrollerPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
declare function MessageScrollerItem({ className, scrollAnchor, ...props }: React.ComponentProps<typeof MessageScrollerPrimitive.Item>): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare function MessageScrollerButton({ direction, className, children, render, variant, size, ...props }: React.ComponentProps<typeof MessageScrollerPrimitive.Button> & Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, };
|
|
11
|
+
//# sourceMappingURL=message-scroller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-scroller.d.ts","sourceRoot":"","sources":["../../../src/components/ui/message-scroller.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,IAAI,wBAAwB,EAC3C,kBAAkB,EAClB,4BAA4B,EAC5B,4BAA4B,EAC7B,MAAM,gCAAgC,CAAA;AAEvC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAGjC,iBAAS,uBAAuB,CAC9B,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,QAAQ,CAAC,2CAGtE;AAED,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,IAAI,CAAC,2CAW5D;AAED,iBAAS,uBAAuB,CAAC,EAC/B,SAAS,EACT,GAAG,EACH,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,QAAQ,CAAC,2CAyBhE;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,OAAO,CAAC,2CAQ/D;AAED,iBAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,YAAoB,EACpB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,IAAI,CAAC,2CAY5D;AAED,iBAAS,qBAAqB,CAAC,EAC7B,SAAiB,EACjB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,OAAqB,EACrB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,wBAAwB,CAAC,MAAM,CAAC,GAC7D,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC,2CAyB9D;AAED,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,4BAA4B,GAC7B,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { MessageScroller as MessageScrollerPrimitive, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, } from '@shadcn/react/message-scroller';
|
|
4
|
+
import { ArrowDown } from 'lucide-react';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Button } from './button';
|
|
8
|
+
import { useMessageScrollerLayoutStability } from './message-scroller-layout-stability';
|
|
9
|
+
function MessageScrollerProvider(props) {
|
|
10
|
+
return _jsx(MessageScrollerPrimitive.Provider, { ...props });
|
|
11
|
+
}
|
|
12
|
+
function MessageScroller({ className, ...props }) {
|
|
13
|
+
return (_jsx(MessageScrollerPrimitive.Root, { "data-slot": "message-scroller", className: cn('group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden', className), ...props }));
|
|
14
|
+
}
|
|
15
|
+
function MessageScrollerViewport({ className, ref, ...props }) {
|
|
16
|
+
const viewportRef = React.useRef(null);
|
|
17
|
+
const { scrollToEnd } = useMessageScroller();
|
|
18
|
+
useMessageScrollerLayoutStability(viewportRef, scrollToEnd);
|
|
19
|
+
const setViewportRef = React.useCallback((element) => {
|
|
20
|
+
viewportRef.current = element;
|
|
21
|
+
if (typeof ref === 'function')
|
|
22
|
+
ref(element);
|
|
23
|
+
else if (ref)
|
|
24
|
+
ref.current = element;
|
|
25
|
+
}, [ref]);
|
|
26
|
+
return (_jsx(MessageScrollerPrimitive.Viewport, { ref: setViewportRef, "data-slot": "message-scroller-viewport", className: cn('message-scroller-viewport size-full min-h-0 min-w-0 overflow-y-auto overscroll-contain [contain:content] [scrollbar-gutter:stable]', className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
function MessageScrollerContent({ className, ...props }) {
|
|
29
|
+
return (_jsx(MessageScrollerPrimitive.Content, { "data-slot": "message-scroller-content", className: cn('flex h-max min-h-full flex-col', className), ...props }));
|
|
30
|
+
}
|
|
31
|
+
function MessageScrollerItem({ className, scrollAnchor = false, ...props }) {
|
|
32
|
+
return (_jsx(MessageScrollerPrimitive.Item, { "data-slot": "message-scroller-item", scrollAnchor: scrollAnchor, className: cn('min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]', className), ...props }));
|
|
33
|
+
}
|
|
34
|
+
function MessageScrollerButton({ direction = 'end', className, children, render, variant = 'secondary', size = 'icon-sm', ...props }) {
|
|
35
|
+
return (_jsx(MessageScrollerPrimitive.Button, { "data-slot": "message-scroller-button", "data-direction": direction, "data-variant": variant, "data-size": size, direction: direction, className: cn('border-border bg-background text-foreground hover:bg-muted hover:text-foreground absolute left-1/2 -translate-x-1/2 cursor-pointer transition-[translate,scale,opacity] duration-200 data-[active=false]:pointer-events-none data-[direction=end]:bottom-4 data-[direction=start]:top-4 data-[active=true]:translate-y-0 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:data-[active=false]:-translate-y-full data-[active=false]:scale-95 data-[active=true]:scale-100 data-[active=false]:opacity-0 data-[active=true]:opacity-100 data-[direction=start]:[&_svg]:rotate-180', className), render: render ?? _jsx(Button, { variant: variant, size: size }), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(ArrowDown, {}), _jsx("span", { className: "sr-only", children: direction === 'end' ? 'Scroll to end' : 'Scroll to start' })] })) }));
|
|
36
|
+
}
|
|
37
|
+
export { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-dot.d.ts","sourceRoot":"","sources":["../../../src/components/ui/notification-dot.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,2CAY9B;AAED,OAAO,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
function NotificationDot({ className, ...props }) {
|
|
5
|
+
return (_jsx("span", { "aria-hidden": "true", "data-slot": "notification-dot", className: cn('bg-primary inline-block size-1.5 shrink-0 rounded-full', className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
export { NotificationDot };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
3
|
+
declare const numberInputVariants: (props?: ({
|
|
4
|
+
variant?: "default" | "filled" | null | undefined;
|
|
5
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
export interface NumberInputProps extends Omit<React.ComponentProps<'input'>, 'defaultValue' | 'onChange' | 'size' | 'type' | 'value'>, VariantProps<typeof numberInputVariants> {
|
|
8
|
+
value?: number | null;
|
|
9
|
+
defaultValue?: number;
|
|
10
|
+
onValueChange?: (value: number | null) => void;
|
|
11
|
+
unit?: React.ReactNode;
|
|
12
|
+
steppers?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare function NumberInput({ className, value, defaultValue, onValueChange, unit, steppers, variant, size, min, max, step, disabled, ...props }: NumberInputProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export { NumberInput, numberInputVariants };
|
|
16
|
+
//# sourceMappingURL=number-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../../src/components/ui/number-input.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,OAAO,EAAE,KAAK,YAAY,EAAO,MAAM,0BAA0B,CAAA;AAEjE,QAAA,MAAM,mBAAmB;;;8EAmBxB,CAAA;AAED,MAAM,WAAW,gBACf,SAAQ,IAAI,CACR,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,EAC7B,cAAc,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CACxD,EACD,YAAY,CAAC,OAAO,mBAAmB,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC9C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,iBAAS,WAAW,CAAC,EACnB,SAAS,EACT,KAAK,EACL,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,QAAe,EACf,OAAO,EACP,IAAI,EACJ,GAAG,EACH,GAAG,EACH,IAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,2CAmGlB;AAED,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAA"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
import { Button } from './button';
|
|
7
|
+
import { cva } from 'class-variance-authority';
|
|
8
|
+
const numberInputVariants = cva('border-input bg-transparent focus-within:border-ring focus-within:ring-ring/50 flex items-stretch overflow-hidden rounded-md border shadow-xs transition-[color,box-shadow] focus-within:ring-[3px] has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:ring-destructive/20', {
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default: 'bg-background',
|
|
12
|
+
filled: 'bg-muted/60 border-transparent shadow-none',
|
|
13
|
+
},
|
|
14
|
+
size: {
|
|
15
|
+
sm: 'h-8',
|
|
16
|
+
default: 'h-9',
|
|
17
|
+
lg: 'h-10',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: {
|
|
21
|
+
variant: 'default',
|
|
22
|
+
size: 'default',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
function NumberInput({ className, value, defaultValue, onValueChange, unit, steppers = true, variant, size, min, max, step = 1, disabled, ...props }) {
|
|
26
|
+
const controlled = value !== undefined;
|
|
27
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue ?? null);
|
|
28
|
+
const currentValue = controlled ? value : internalValue;
|
|
29
|
+
const commitValue = React.useCallback((nextValue) => {
|
|
30
|
+
if (!controlled)
|
|
31
|
+
setInternalValue(nextValue);
|
|
32
|
+
onValueChange?.(nextValue);
|
|
33
|
+
}, [controlled, onValueChange]);
|
|
34
|
+
const changeByStep = React.useCallback((direction) => {
|
|
35
|
+
const numericStep = typeof step === 'number' ? step : Number(step);
|
|
36
|
+
const safeStep = Number.isFinite(numericStep) ? numericStep : 1;
|
|
37
|
+
const baseValue = currentValue ?? 0;
|
|
38
|
+
let nextValue = baseValue + safeStep * direction;
|
|
39
|
+
const numericMin = min === undefined ? undefined : Number(min);
|
|
40
|
+
const numericMax = max === undefined ? undefined : Number(max);
|
|
41
|
+
if (numericMin !== undefined && Number.isFinite(numericMin)) {
|
|
42
|
+
nextValue = Math.max(numericMin, nextValue);
|
|
43
|
+
}
|
|
44
|
+
if (numericMax !== undefined && Number.isFinite(numericMax)) {
|
|
45
|
+
nextValue = Math.min(numericMax, nextValue);
|
|
46
|
+
}
|
|
47
|
+
commitValue(nextValue);
|
|
48
|
+
}, [commitValue, currentValue, max, min, step]);
|
|
49
|
+
return (_jsxs("div", { "data-slot": "number-input", "data-size": size ?? 'default', "data-variant": variant ?? 'default', className: cn(numberInputVariants({ variant, size }), className), children: [_jsx("input", { "data-slot": "number-input-field", type: "number", value: currentValue ?? '', min: min, max: max, step: step, disabled: disabled, className: "placeholder:text-muted-foreground min-w-0 flex-1 bg-transparent px-3 text-sm outline-none disabled:cursor-not-allowed", onChange: (event) => {
|
|
50
|
+
const nextValue = event.currentTarget.value === ''
|
|
51
|
+
? null
|
|
52
|
+
: event.currentTarget.valueAsNumber;
|
|
53
|
+
commitValue(Number.isNaN(nextValue) ? null : nextValue);
|
|
54
|
+
}, ...props }), unit ? (_jsx("span", { "data-slot": "number-input-unit", className: "text-muted-foreground flex shrink-0 items-center pr-2 text-xs", children: unit })) : null, steppers ? (_jsxs("span", { "data-slot": "number-input-steppers", className: "border-border/70 flex w-6 shrink-0 flex-col border-l", children: [_jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", disabled: disabled, "aria-label": "Increase value", className: "h-1/2 min-h-0 w-full rounded-none border-b", onClick: () => changeByStep(1), children: _jsx(ChevronUpIcon, {}) }), _jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", disabled: disabled, "aria-label": "Decrease value", className: "h-1/2 min-h-0 w-full rounded-none", onClick: () => changeByStep(-1), children: _jsx(ChevronDownIcon, {}) })] })) : null] }));
|
|
55
|
+
}
|
|
56
|
+
export { NumberInput, numberInputVariants };
|