@moldable-ai/ui 0.2.18 → 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 +67 -17
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +250 -159
- 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 +3 -2
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +3 -2
- package/dist/components/chat/model-effort-power-effects.d.ts +7 -0
- package/dist/components/chat/model-effort-power-effects.d.ts.map +1 -0
- package/dist/components/chat/model-effort-power-effects.js +54 -0
- package/dist/components/chat/model-effort-selector.d.ts +26 -0
- package/dist/components/chat/model-effort-selector.d.ts.map +1 -0
- package/dist/components/chat/model-effort-selector.js +179 -0
- package/dist/components/chat/model-effort-ultra-effects.d.ts +5 -0
- package/dist/components/chat/model-effort-ultra-effects.d.ts.map +1 -0
- package/dist/components/chat/model-effort-ultra-effects.js +56 -0
- 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/hardware/bluetooth-panel-helpers.d.ts +9 -0
- package/dist/components/hardware/bluetooth-panel-helpers.d.ts.map +1 -0
- package/dist/components/hardware/bluetooth-panel-helpers.js +37 -0
- package/dist/components/hardware/bluetooth-panel.d.ts +56 -0
- package/dist/components/hardware/bluetooth-panel.d.ts.map +1 -0
- package/dist/components/hardware/bluetooth-panel.js +470 -0
- package/dist/components/hardware/camera-preview.d.ts +39 -0
- package/dist/components/hardware/camera-preview.d.ts.map +1 -0
- package/dist/components/hardware/camera-preview.js +228 -0
- package/dist/components/hardware/capability-badge.d.ts +23 -0
- package/dist/components/hardware/capability-badge.d.ts.map +1 -0
- package/dist/components/hardware/capability-badge.js +39 -0
- package/dist/components/hardware/capability-matrix.d.ts +14 -0
- package/dist/components/hardware/capability-matrix.d.ts.map +1 -0
- package/dist/components/hardware/capability-matrix.js +97 -0
- package/dist/components/hardware/clipboard-button.d.ts +26 -0
- package/dist/components/hardware/clipboard-button.d.ts.map +1 -0
- package/dist/components/hardware/clipboard-button.js +114 -0
- package/dist/components/hardware/device-io-controls.d.ts +4 -0
- package/dist/components/hardware/device-io-controls.d.ts.map +1 -0
- package/dist/components/hardware/device-io-controls.js +28 -0
- package/dist/components/hardware/device-list.d.ts +20 -0
- package/dist/components/hardware/device-list.d.ts.map +1 -0
- package/dist/components/hardware/device-list.js +14 -0
- package/dist/components/hardware/display-map.d.ts +23 -0
- package/dist/components/hardware/display-map.d.ts.map +1 -0
- package/dist/components/hardware/display-map.js +114 -0
- package/dist/components/hardware/haptic-button.d.ts +26 -0
- package/dist/components/hardware/haptic-button.d.ts.map +1 -0
- package/dist/components/hardware/haptic-button.js +94 -0
- package/dist/components/hardware/hardware-panel.d.ts +11 -0
- package/dist/components/hardware/hardware-panel.d.ts.map +1 -0
- package/dist/components/hardware/hardware-panel.js +28 -0
- package/dist/components/hardware/hid-panel.d.ts +40 -0
- package/dist/components/hardware/hid-panel.d.ts.map +1 -0
- package/dist/components/hardware/hid-panel.js +373 -0
- package/dist/components/hardware/index.d.ts +27 -0
- package/dist/components/hardware/index.d.ts.map +1 -0
- package/dist/components/hardware/index.js +26 -0
- package/dist/components/hardware/live-indicator.d.ts +15 -0
- package/dist/components/hardware/live-indicator.d.ts.map +1 -0
- package/dist/components/hardware/live-indicator.js +26 -0
- package/dist/components/hardware/local-auth-button.d.ts +33 -0
- package/dist/components/hardware/local-auth-button.d.ts.map +1 -0
- package/dist/components/hardware/local-auth-button.js +115 -0
- package/dist/components/hardware/location-panel.d.ts +29 -0
- package/dist/components/hardware/location-panel.d.ts.map +1 -0
- package/dist/components/hardware/location-panel.js +154 -0
- package/dist/components/hardware/microphone-meter.d.ts +35 -0
- package/dist/components/hardware/microphone-meter.d.ts.map +1 -0
- package/dist/components/hardware/microphone-meter.js +244 -0
- package/dist/components/hardware/midi-monitor.d.ts +54 -0
- package/dist/components/hardware/midi-monitor.d.ts.map +1 -0
- package/dist/components/hardware/midi-monitor.js +534 -0
- package/dist/components/hardware/notification-panel.d.ts +24 -0
- package/dist/components/hardware/notification-panel.d.ts.map +1 -0
- package/dist/components/hardware/notification-panel.js +124 -0
- package/dist/components/hardware/power-blocker-controller.d.ts +19 -0
- package/dist/components/hardware/power-blocker-controller.d.ts.map +1 -0
- package/dist/components/hardware/power-blocker-controller.js +83 -0
- package/dist/components/hardware/power-panel.d.ts +67 -0
- package/dist/components/hardware/power-panel.d.ts.map +1 -0
- package/dist/components/hardware/power-panel.js +309 -0
- package/dist/components/hardware/readout.d.ts +10 -0
- package/dist/components/hardware/readout.d.ts.map +1 -0
- package/dist/components/hardware/readout.js +11 -0
- package/dist/components/hardware/screen-share-preview.d.ts +36 -0
- package/dist/components/hardware/screen-share-preview.d.ts.map +1 -0
- package/dist/components/hardware/screen-share-preview.js +191 -0
- package/dist/components/hardware/secure-storage-panel.d.ts +36 -0
- package/dist/components/hardware/secure-storage-panel.d.ts.map +1 -0
- package/dist/components/hardware/secure-storage-panel.js +193 -0
- package/dist/components/hardware/serial-console.d.ts +64 -0
- package/dist/components/hardware/serial-console.d.ts.map +1 -0
- package/dist/components/hardware/serial-console.js +399 -0
- package/dist/components/hardware/shortcut-recorder.d.ts +35 -0
- package/dist/components/hardware/shortcut-recorder.d.ts.map +1 -0
- package/dist/components/hardware/shortcut-recorder.js +217 -0
- package/dist/components/hardware/stream-log.d.ts +35 -0
- package/dist/components/hardware/stream-log.d.ts.map +1 -0
- package/dist/components/hardware/stream-log.js +65 -0
- package/dist/components/hardware/system-audio-monitor.d.ts +34 -0
- package/dist/components/hardware/system-audio-monitor.d.ts.map +1 -0
- package/dist/components/hardware/system-audio-monitor.js +275 -0
- package/dist/components/hardware/usb-panel.d.ts +54 -0
- package/dist/components/hardware/usb-panel.d.ts.map +1 -0
- package/dist/components/hardware/usb-panel.js +363 -0
- package/dist/components/hardware/use-capability.d.ts +20 -0
- package/dist/components/hardware/use-capability.d.ts.map +1 -0
- package/dist/components/hardware/use-capability.js +61 -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/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/slider.d.ts +4 -1
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/slider.js +2 -2
- 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 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- 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/dist/lib/native-hardware/bluetooth-access.d.ts +14 -0
- package/dist/lib/native-hardware/bluetooth-access.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-access.js +40 -0
- package/dist/lib/native-hardware/bluetooth-connection.d.ts +19 -0
- package/dist/lib/native-hardware/bluetooth-connection.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-connection.js +88 -0
- package/dist/lib/native-hardware/bluetooth-gatt.d.ts +7 -0
- package/dist/lib/native-hardware/bluetooth-gatt.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-gatt.js +77 -0
- package/dist/lib/native-hardware/bluetooth-internal.d.ts +10 -0
- package/dist/lib/native-hardware/bluetooth-internal.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-internal.js +105 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +33 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-native-fallback.js +214 -0
- package/dist/lib/native-hardware/bluetooth-types.d.ts +85 -0
- package/dist/lib/native-hardware/bluetooth-types.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth-types.js +2 -0
- package/dist/lib/native-hardware/bluetooth.d.ts +7 -0
- package/dist/lib/native-hardware/bluetooth.d.ts.map +1 -0
- package/dist/lib/native-hardware/bluetooth.js +4 -0
- package/dist/lib/native-hardware/bridge.d.ts +23 -0
- package/dist/lib/native-hardware/bridge.d.ts.map +1 -0
- package/dist/lib/native-hardware/bridge.js +266 -0
- package/dist/lib/native-hardware/capabilities.d.ts +7 -0
- package/dist/lib/native-hardware/capabilities.d.ts.map +1 -0
- package/dist/lib/native-hardware/capabilities.js +95 -0
- package/dist/lib/native-hardware/clipboard.d.ts +11 -0
- package/dist/lib/native-hardware/clipboard.d.ts.map +1 -0
- package/dist/lib/native-hardware/clipboard.js +55 -0
- package/dist/lib/native-hardware/device-io-errors.d.ts +11 -0
- package/dist/lib/native-hardware/device-io-errors.d.ts.map +1 -0
- package/dist/lib/native-hardware/device-io-errors.js +82 -0
- package/dist/lib/native-hardware/displays.d.ts +38 -0
- package/dist/lib/native-hardware/displays.d.ts.map +1 -0
- package/dist/lib/native-hardware/displays.js +12 -0
- package/dist/lib/native-hardware/global-shortcuts.d.ts +86 -0
- package/dist/lib/native-hardware/global-shortcuts.d.ts.map +1 -0
- package/dist/lib/native-hardware/global-shortcuts.js +351 -0
- package/dist/lib/native-hardware/haptics.d.ts +25 -0
- package/dist/lib/native-hardware/haptics.d.ts.map +1 -0
- package/dist/lib/native-hardware/haptics.js +18 -0
- package/dist/lib/native-hardware/hid-native.d.ts +26 -0
- package/dist/lib/native-hardware/hid-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/hid-native.js +229 -0
- package/dist/lib/native-hardware/hid.d.ts +52 -0
- package/dist/lib/native-hardware/hid.d.ts.map +1 -0
- package/dist/lib/native-hardware/hid.js +160 -0
- package/dist/lib/native-hardware/index.d.ts +38 -0
- package/dist/lib/native-hardware/index.d.ts.map +1 -0
- package/dist/lib/native-hardware/index.js +20 -0
- package/dist/lib/native-hardware/local-authentication.d.ts +32 -0
- package/dist/lib/native-hardware/local-authentication.d.ts.map +1 -0
- package/dist/lib/native-hardware/local-authentication.js +46 -0
- package/dist/lib/native-hardware/location.d.ts +49 -0
- package/dist/lib/native-hardware/location.d.ts.map +1 -0
- package/dist/lib/native-hardware/location.js +114 -0
- package/dist/lib/native-hardware/media-permissions.d.ts +28 -0
- package/dist/lib/native-hardware/media-permissions.d.ts.map +1 -0
- package/dist/lib/native-hardware/media-permissions.js +37 -0
- package/dist/lib/native-hardware/media.d.ts +17 -0
- package/dist/lib/native-hardware/media.d.ts.map +1 -0
- package/dist/lib/native-hardware/media.js +99 -0
- package/dist/lib/native-hardware/midi-access.d.ts +13 -0
- package/dist/lib/native-hardware/midi-access.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-access.js +66 -0
- package/dist/lib/native-hardware/midi-internal.d.ts +12 -0
- package/dist/lib/native-hardware/midi-internal.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-internal.js +88 -0
- package/dist/lib/native-hardware/midi-native-fallback.d.ts +27 -0
- package/dist/lib/native-hardware/midi-native-fallback.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-native-fallback.js +127 -0
- package/dist/lib/native-hardware/midi-ports.d.ts +6 -0
- package/dist/lib/native-hardware/midi-ports.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-ports.js +115 -0
- package/dist/lib/native-hardware/midi-types.d.ts +25 -0
- package/dist/lib/native-hardware/midi-types.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi-types.js +1 -0
- package/dist/lib/native-hardware/midi.d.ts +6 -0
- package/dist/lib/native-hardware/midi.d.ts.map +1 -0
- package/dist/lib/native-hardware/midi.js +3 -0
- package/dist/lib/native-hardware/native-device-io.d.ts +28 -0
- package/dist/lib/native-hardware/native-device-io.d.ts.map +1 -0
- package/dist/lib/native-hardware/native-device-io.js +91 -0
- package/dist/lib/native-hardware/native-device-lifecycle.d.ts +13 -0
- package/dist/lib/native-hardware/native-device-lifecycle.d.ts.map +1 -0
- package/dist/lib/native-hardware/native-device-lifecycle.js +40 -0
- package/dist/lib/native-hardware/notifications.d.ts +38 -0
- package/dist/lib/native-hardware/notifications.d.ts.map +1 -0
- package/dist/lib/native-hardware/notifications.js +50 -0
- package/dist/lib/native-hardware/power-session.d.ts +113 -0
- package/dist/lib/native-hardware/power-session.d.ts.map +1 -0
- package/dist/lib/native-hardware/power-session.js +264 -0
- package/dist/lib/native-hardware/secure-storage.d.ts +36 -0
- package/dist/lib/native-hardware/secure-storage.d.ts.map +1 -0
- package/dist/lib/native-hardware/secure-storage.js +64 -0
- package/dist/lib/native-hardware/serial-native.d.ts +23 -0
- package/dist/lib/native-hardware/serial-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/serial-native.js +181 -0
- package/dist/lib/native-hardware/serial.d.ts +76 -0
- package/dist/lib/native-hardware/serial.d.ts.map +1 -0
- package/dist/lib/native-hardware/serial.js +212 -0
- package/dist/lib/native-hardware/system-audio.d.ts +127 -0
- package/dist/lib/native-hardware/system-audio.d.ts.map +1 -0
- package/dist/lib/native-hardware/system-audio.js +330 -0
- package/dist/lib/native-hardware/types.d.ts +62 -0
- package/dist/lib/native-hardware/types.d.ts.map +1 -0
- package/dist/lib/native-hardware/types.js +27 -0
- package/dist/lib/native-hardware/usb-native.d.ts +39 -0
- package/dist/lib/native-hardware/usb-native.d.ts.map +1 -0
- package/dist/lib/native-hardware/usb-native.js +217 -0
- package/dist/lib/native-hardware/usb.d.ts +85 -0
- package/dist/lib/native-hardware/usb.d.ts.map +1 -0
- package/dist/lib/native-hardware/usb.js +222 -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 +868 -3
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Camera, CameraOff, RefreshCw, Square } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { NativeHardwareBridgeError, enumerateMoldableMediaDevices, getMoldableCameraStream, getMoldableMediaPermissionStatus, requestMoldableMediaPermission, stopMoldableMediaStream, } from '../../lib/native-hardware';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Button } from '../ui/button';
|
|
8
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/select';
|
|
9
|
+
import { Spinner } from '../ui/spinner';
|
|
10
|
+
import { LiveIndicator } from './live-indicator';
|
|
11
|
+
function isPermissionDenied(error) {
|
|
12
|
+
if (error instanceof NativeHardwareBridgeError) {
|
|
13
|
+
return error.code === 'permission_denied';
|
|
14
|
+
}
|
|
15
|
+
return (error instanceof DOMException &&
|
|
16
|
+
(error.name === 'NotAllowedError' || error.name === 'SecurityError'));
|
|
17
|
+
}
|
|
18
|
+
function assertMediaPermissionGranted(status) {
|
|
19
|
+
if (status.status !== 'denied' && status.status !== 'restricted')
|
|
20
|
+
return;
|
|
21
|
+
throw new NativeHardwareBridgeError({
|
|
22
|
+
code: 'permission_denied',
|
|
23
|
+
message: status.detail ?? 'Camera access was denied.',
|
|
24
|
+
retryable: false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Camera state machine behind `CameraPreview`. Use directly to build custom
|
|
29
|
+
* camera UI on the same permission/device/stream handling.
|
|
30
|
+
*/
|
|
31
|
+
export function useMoldableCamera(options = {}) {
|
|
32
|
+
const [status, setStatus] = useState('idle');
|
|
33
|
+
const [stream, setStream] = useState(null);
|
|
34
|
+
const [devices, setDevices] = useState([]);
|
|
35
|
+
const [deviceId, setDeviceIdState] = useState(null);
|
|
36
|
+
const [error, setError] = useState(null);
|
|
37
|
+
const streamRef = useRef(null);
|
|
38
|
+
const deviceIdRef = useRef(null);
|
|
39
|
+
const tokenRef = useRef(0);
|
|
40
|
+
const constraintsRef = useRef(options.constraints);
|
|
41
|
+
const onStreamChangeRef = useRef(options.onStreamChange);
|
|
42
|
+
const detachTrackListenersRef = useRef(null);
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
constraintsRef.current = options.constraints;
|
|
45
|
+
onStreamChangeRef.current = options.onStreamChange;
|
|
46
|
+
}, [options.constraints, options.onStreamChange]);
|
|
47
|
+
const dropStream = useCallback((updateState = true) => {
|
|
48
|
+
detachTrackListenersRef.current?.();
|
|
49
|
+
detachTrackListenersRef.current = null;
|
|
50
|
+
const previousStream = streamRef.current;
|
|
51
|
+
if (!previousStream)
|
|
52
|
+
return false;
|
|
53
|
+
streamRef.current = null;
|
|
54
|
+
stopMoldableMediaStream(previousStream);
|
|
55
|
+
if (updateState)
|
|
56
|
+
setStream(null);
|
|
57
|
+
onStreamChangeRef.current?.(null);
|
|
58
|
+
return true;
|
|
59
|
+
}, []);
|
|
60
|
+
const stop = useCallback(() => {
|
|
61
|
+
tokenRef.current++;
|
|
62
|
+
dropStream();
|
|
63
|
+
setStatus('idle');
|
|
64
|
+
}, [dropStream]);
|
|
65
|
+
const refreshDevices = useCallback(async () => {
|
|
66
|
+
try {
|
|
67
|
+
const all = await enumerateMoldableMediaDevices();
|
|
68
|
+
setDevices(all.filter((device) => device.kind === 'videoinput'));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Device labels are best-effort; enumeration can fail outside Moldable.
|
|
72
|
+
}
|
|
73
|
+
}, []);
|
|
74
|
+
const start = useCallback(async (nextDeviceId) => {
|
|
75
|
+
const token = ++tokenRef.current;
|
|
76
|
+
dropStream();
|
|
77
|
+
setStatus('starting');
|
|
78
|
+
setError(null);
|
|
79
|
+
try {
|
|
80
|
+
// Nudge the native permission first so macOS prompts before the
|
|
81
|
+
// webview does. Outside Moldable this fails and the browser prompt
|
|
82
|
+
// covers it on getUserMedia.
|
|
83
|
+
try {
|
|
84
|
+
const permission = await getMoldableMediaPermissionStatus('camera');
|
|
85
|
+
assertMediaPermissionGranted(permission);
|
|
86
|
+
if (permission.status === 'not-determined' && permission.canRequest) {
|
|
87
|
+
assertMediaPermissionGranted(await requestMoldableMediaPermission('camera'));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (cause) {
|
|
91
|
+
if (isPermissionDenied(cause))
|
|
92
|
+
throw cause;
|
|
93
|
+
// Not in Moldable — proceed straight to the stream request.
|
|
94
|
+
}
|
|
95
|
+
if (tokenRef.current !== token)
|
|
96
|
+
return;
|
|
97
|
+
const target = nextDeviceId ?? deviceIdRef.current;
|
|
98
|
+
const media = await getMoldableCameraStream({
|
|
99
|
+
width: { ideal: 1920 },
|
|
100
|
+
height: { ideal: 1080 },
|
|
101
|
+
...constraintsRef.current,
|
|
102
|
+
...(target ? { deviceId: { exact: target } } : {}),
|
|
103
|
+
});
|
|
104
|
+
if (tokenRef.current !== token) {
|
|
105
|
+
stopMoldableMediaStream(media);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
streamRef.current = media;
|
|
109
|
+
const [track] = media.getVideoTracks();
|
|
110
|
+
if (track) {
|
|
111
|
+
const handleEnded = () => {
|
|
112
|
+
if (tokenRef.current !== token)
|
|
113
|
+
return;
|
|
114
|
+
tokenRef.current++;
|
|
115
|
+
dropStream();
|
|
116
|
+
setStatus('idle');
|
|
117
|
+
};
|
|
118
|
+
const handleMute = () => {
|
|
119
|
+
if (tokenRef.current === token)
|
|
120
|
+
setStatus('muted');
|
|
121
|
+
};
|
|
122
|
+
const handleUnmute = () => {
|
|
123
|
+
if (tokenRef.current === token)
|
|
124
|
+
setStatus('live');
|
|
125
|
+
};
|
|
126
|
+
track.addEventListener('ended', handleEnded, { once: true });
|
|
127
|
+
track.addEventListener('mute', handleMute);
|
|
128
|
+
track.addEventListener('unmute', handleUnmute);
|
|
129
|
+
detachTrackListenersRef.current = () => {
|
|
130
|
+
track.removeEventListener('ended', handleEnded);
|
|
131
|
+
track.removeEventListener('mute', handleMute);
|
|
132
|
+
track.removeEventListener('unmute', handleUnmute);
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
setStream(media);
|
|
136
|
+
if (nextDeviceId !== undefined) {
|
|
137
|
+
deviceIdRef.current = nextDeviceId;
|
|
138
|
+
setDeviceIdState(nextDeviceId);
|
|
139
|
+
}
|
|
140
|
+
setStatus('live');
|
|
141
|
+
onStreamChangeRef.current?.(media);
|
|
142
|
+
void refreshDevices();
|
|
143
|
+
}
|
|
144
|
+
catch (cause) {
|
|
145
|
+
if (tokenRef.current !== token)
|
|
146
|
+
return;
|
|
147
|
+
setError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
148
|
+
setStatus(isPermissionDenied(cause) ? 'denied' : 'error');
|
|
149
|
+
}
|
|
150
|
+
}, [dropStream, refreshDevices]);
|
|
151
|
+
const selectDevice = useCallback((id) => {
|
|
152
|
+
deviceIdRef.current = id;
|
|
153
|
+
setDeviceIdState(id);
|
|
154
|
+
if (streamRef.current)
|
|
155
|
+
void start(id);
|
|
156
|
+
}, [start]);
|
|
157
|
+
useEffect(() => () => {
|
|
158
|
+
tokenRef.current++;
|
|
159
|
+
dropStream(false);
|
|
160
|
+
}, [dropStream]);
|
|
161
|
+
return {
|
|
162
|
+
status,
|
|
163
|
+
stream,
|
|
164
|
+
devices,
|
|
165
|
+
deviceId,
|
|
166
|
+
error,
|
|
167
|
+
start,
|
|
168
|
+
stop,
|
|
169
|
+
selectDevice,
|
|
170
|
+
refreshDevices,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Full-bleed live camera surface: black media well, hover scrim controls,
|
|
175
|
+
* device switching, permission and error states, optional snapshots.
|
|
176
|
+
*/
|
|
177
|
+
function CameraPreview({ className, constraints, mirrored = true, autoStart = false, onSnapshot, onStreamChange, ...props }) {
|
|
178
|
+
const camera = useMoldableCamera({ constraints, onStreamChange });
|
|
179
|
+
const videoRef = useRef(null);
|
|
180
|
+
const [flash, setFlash] = useState(false);
|
|
181
|
+
const autoStartedRef = useRef(false);
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (autoStart && !autoStartedRef.current) {
|
|
184
|
+
autoStartedRef.current = true;
|
|
185
|
+
void camera.start();
|
|
186
|
+
}
|
|
187
|
+
}, [autoStart, camera]);
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
const video = videoRef.current;
|
|
190
|
+
if (!video)
|
|
191
|
+
return;
|
|
192
|
+
video.srcObject = camera.stream;
|
|
193
|
+
if (camera.stream) {
|
|
194
|
+
void video.play().catch(() => {
|
|
195
|
+
// Autoplay rejections resolve once the stream attaches.
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}, [camera.stream]);
|
|
199
|
+
const capture = () => {
|
|
200
|
+
const video = videoRef.current;
|
|
201
|
+
if (!video || !onSnapshot || video.videoWidth === 0)
|
|
202
|
+
return;
|
|
203
|
+
const canvas = document.createElement('canvas');
|
|
204
|
+
canvas.width = video.videoWidth;
|
|
205
|
+
canvas.height = video.videoHeight;
|
|
206
|
+
const context = canvas.getContext('2d');
|
|
207
|
+
if (!context)
|
|
208
|
+
return;
|
|
209
|
+
if (mirrored) {
|
|
210
|
+
context.translate(canvas.width, 0);
|
|
211
|
+
context.scale(-1, 1);
|
|
212
|
+
}
|
|
213
|
+
context.drawImage(video, 0, 0);
|
|
214
|
+
setFlash(true);
|
|
215
|
+
window.setTimeout(() => setFlash(false), 160);
|
|
216
|
+
canvas.toBlob((blob) => {
|
|
217
|
+
if (blob)
|
|
218
|
+
onSnapshot(blob);
|
|
219
|
+
}, 'image/png');
|
|
220
|
+
};
|
|
221
|
+
const active = camera.status === 'live' || camera.status === 'muted';
|
|
222
|
+
const settings = active
|
|
223
|
+
? camera.stream?.getVideoTracks()[0]?.getSettings()
|
|
224
|
+
: undefined;
|
|
225
|
+
return (_jsxs("div", { "data-slot": "camera-preview", "data-status": camera.status, className: cn('group relative isolate aspect-video w-full overflow-hidden rounded-xl border', active ? 'bg-black' : 'bg-muted/30', className), ...props, children: [_jsx("video", { ref: videoRef, muted: true, playsInline: true, className: cn('absolute inset-0 size-full object-cover', mirrored && '-scale-x-100', !active && 'invisible') }), _jsx("div", { "aria-hidden": true, className: "pointer-events-none absolute inset-0 z-30 bg-white transition-opacity duration-150", style: { opacity: flash ? 0.9 : 0 } }), active ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "absolute left-3 top-3 z-20", children: _jsx(LiveIndicator, { variant: "rec", label: camera.status === 'muted' ? 'Paused' : 'Live' }) }), settings?.width && settings.height ? (_jsxs("div", { className: "absolute right-3 top-3 z-20 rounded-full border border-white/15 bg-black/60 px-2 py-0.5 font-mono text-[10px] tabular-nums text-white/90 backdrop-blur-sm", children: [settings.width, "\u00D7", settings.height] })) : null, _jsxs("div", { className: "absolute inset-x-0 bottom-0 z-20 flex items-end justify-between gap-3 bg-gradient-to-t from-black/70 via-black/25 to-transparent p-3 pt-10 opacity-0 transition-opacity duration-200 focus-within:opacity-100 group-hover:opacity-100", children: [_jsx("div", { className: "min-w-0", children: camera.devices.length > 1 ? (_jsxs(Select, { value: camera.deviceId ?? undefined, onValueChange: camera.selectDevice, children: [_jsx(SelectTrigger, { size: "sm", className: "h-7 w-auto max-w-56 border-white/15 bg-white/10 text-xs text-white backdrop-blur-md hover:bg-white/15 [&_svg]:text-white/70", children: _jsx(SelectValue, { placeholder: "Camera" }) }), _jsx(SelectContent, { children: camera.devices.map((device, index) => (_jsx(SelectItem, { value: device.deviceId, children: device.label || `Camera ${index + 1}` }, device.deviceId))) })] })) : null }), _jsxs("div", { className: "flex items-center gap-2", children: [onSnapshot ? (_jsx("button", { type: "button", onClick: capture, "aria-label": "Take snapshot", className: "size-9 rounded-full border-2 border-white/40 bg-white shadow-md transition-transform duration-150 hover:scale-105 active:scale-95 motion-reduce:transition-none" })) : null, _jsx(Button, { variant: "secondary", size: "icon-sm", "aria-label": "Stop camera", onClick: camera.stop, className: "border border-white/15 bg-white/10 text-white backdrop-blur-md hover:bg-white/20", children: _jsx(Square, { className: "fill-current" }) })] })] })] })) : (_jsx("div", { className: "animate-in fade-in absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 p-6 text-center duration-300 motion-reduce:animate-none", children: camera.status === 'starting' ? (_jsxs(_Fragment, { children: [_jsx(Spinner, { className: "text-muted-foreground" }), _jsx("p", { className: "text-muted-foreground text-xs", children: "Starting camera\u2026" })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "text-muted-foreground bg-background shadow-xs flex size-10 items-center justify-center rounded-lg border [&_svg]:size-5", children: camera.status === 'idle' ? _jsx(Camera, {}) : _jsx(CameraOff, {}) }), camera.status === 'idle' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: "Camera is off" }), _jsxs(Button, { size: "sm", onClick: () => void camera.start(), children: [_jsx(Camera, {}), " Start camera"] })] })) : camera.status === 'denied' ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm font-medium", children: "Camera access denied" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: "Enable camera access for Moldable in System Settings, then try again." }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void camera.start(), children: [_jsx(RefreshCw, {}), " Try again"] })] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm font-medium", children: "Camera unavailable" }), _jsx("p", { className: "text-muted-foreground max-w-64 text-xs", children: camera.error?.message ??
|
|
226
|
+
'The camera could not be started.' }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void camera.start(), children: [_jsx(RefreshCw, {}), " Try again"] })] }))] })) }))] }));
|
|
227
|
+
}
|
|
228
|
+
export { CameraPreview };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NativeHardwareCapabilityId } from '../../lib/native-hardware';
|
|
3
|
+
import { type MoldableCapabilityStatus } from './use-capability';
|
|
4
|
+
declare function CapabilityDot({ status, className, ...props }: React.ComponentProps<'span'> & {
|
|
5
|
+
status: MoldableCapabilityStatus;
|
|
6
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
interface CapabilityBadgeBaseProps extends React.ComponentProps<'span'> {
|
|
8
|
+
/** Override the automatic status label. */
|
|
9
|
+
label?: React.ReactNode;
|
|
10
|
+
}
|
|
11
|
+
export interface CapabilityBadgeProps extends CapabilityBadgeBaseProps {
|
|
12
|
+
/** Self-manage: fetch the manifest and show this capability's support. */
|
|
13
|
+
capability?: NativeHardwareCapabilityId;
|
|
14
|
+
/** Controlled: render a specific status directly. */
|
|
15
|
+
status?: MoldableCapabilityStatus;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Support-status pill. Pass `capability` to let it fetch the manifest itself,
|
|
19
|
+
* or `status` to control it.
|
|
20
|
+
*/
|
|
21
|
+
declare function CapabilityBadge({ capability, status, ...props }: CapabilityBadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export { CapabilityBadge, CapabilityDot };
|
|
23
|
+
//# sourceMappingURL=capability-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-badge.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/capability-badge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAA;AAE3E,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,kBAAkB,CAAA;AAkBzB,iBAAS,aAAa,CAAC,EACrB,MAAM,EACN,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG;IAAE,MAAM,EAAE,wBAAwB,CAAA;CAAE,2CAcrE;AAED,UAAU,wBAAyB,SAAQ,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;IACrE,2CAA2C;IAC3C,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACxB;AAgCD,MAAM,WAAW,oBAAqB,SAAQ,wBAAwB;IACpE,0EAA0E;IAC1E,UAAU,CAAC,EAAE,0BAA0B,CAAA;IACvC,qDAAqD;IACrD,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAClC;AAED;;;GAGG;AACH,iBAAS,eAAe,CAAC,EACvB,UAAU,EACV,MAAM,EACN,GAAG,KAAK,EACT,EAAE,oBAAoB,2CAKtB;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
import { useMoldableCapability, } from './use-capability';
|
|
5
|
+
const STATUS_LABEL = {
|
|
6
|
+
checking: 'Checking',
|
|
7
|
+
supported: 'Supported',
|
|
8
|
+
partial: 'Partial',
|
|
9
|
+
unsupported: 'Unsupported',
|
|
10
|
+
unavailable: 'Unavailable',
|
|
11
|
+
};
|
|
12
|
+
const STATUS_DOT = {
|
|
13
|
+
checking: 'bg-muted-foreground/40 animate-pulse motion-reduce:animate-none',
|
|
14
|
+
supported: 'bg-status-running',
|
|
15
|
+
partial: 'bg-status-pending',
|
|
16
|
+
unsupported: 'bg-status-error',
|
|
17
|
+
unavailable: 'bg-status-stopped',
|
|
18
|
+
};
|
|
19
|
+
function CapabilityDot({ status, className, ...props }) {
|
|
20
|
+
return (_jsx("span", { "data-slot": "capability-dot", "data-status": status, "aria-hidden": true, className: cn('size-1.5 shrink-0 rounded-full', STATUS_DOT[status], className), ...props }));
|
|
21
|
+
}
|
|
22
|
+
function CapabilityBadgeBase({ status, label, className, ...props }) {
|
|
23
|
+
return (_jsxs("span", { "data-slot": "capability-badge", "data-status": status, className: cn('text-muted-foreground inline-flex w-fit shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-2 py-0.5 text-[11px] font-medium', className), ...props, children: [_jsx(CapabilityDot, { status: status }), label ?? STATUS_LABEL[status]] }));
|
|
24
|
+
}
|
|
25
|
+
function ManagedCapabilityBadge({ capability, ...props }) {
|
|
26
|
+
const { status } = useMoldableCapability(capability);
|
|
27
|
+
return _jsx(CapabilityBadgeBase, { status: status, ...props });
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Support-status pill. Pass `capability` to let it fetch the manifest itself,
|
|
31
|
+
* or `status` to control it.
|
|
32
|
+
*/
|
|
33
|
+
function CapabilityBadge({ capability, status, ...props }) {
|
|
34
|
+
if (capability && status === undefined) {
|
|
35
|
+
return _jsx(ManagedCapabilityBadge, { capability: capability, ...props });
|
|
36
|
+
}
|
|
37
|
+
return _jsx(CapabilityBadgeBase, { status: status ?? 'checking', ...props });
|
|
38
|
+
}
|
|
39
|
+
export { CapabilityBadge, CapabilityDot };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type NativeHardwareCapabilityId } from '../../lib/native-hardware';
|
|
3
|
+
export interface CapabilityMatrixProps extends React.ComponentProps<'div'> {
|
|
4
|
+
/** Subset of capabilities to show; defaults to every known capability. */
|
|
5
|
+
capabilities?: NativeHardwareCapabilityId[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Responsive support grid for every native capability: icon, humanized name,
|
|
9
|
+
* status dot, support level, and transport. Renders skeleton cells while the
|
|
10
|
+
* manifest loads and a quiet note when it is unavailable outside Moldable.
|
|
11
|
+
*/
|
|
12
|
+
declare function CapabilityMatrix({ capabilities, className, ...props }: CapabilityMatrixProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export { CapabilityMatrix };
|
|
14
|
+
//# sourceMappingURL=capability-matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-matrix.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/capability-matrix.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAEL,KAAK,0BAA0B,EAEhC,MAAM,2BAA2B,CAAA;AAyDlC,MAAM,WAAW,qBAAsB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACxE,0EAA0E;IAC1E,YAAY,CAAC,EAAE,0BAA0B,EAAE,CAAA;CAC5C;AAED;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,EACxB,YAAY,EACZ,SAAS,EACT,GAAG,KAAK,EACT,EAAE,qBAAqB,2CAgGvB;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Activity, BatteryCharging, Bell, Bluetooth, Cable, Camera, Clipboard, ClipboardCopy, Fingerprint, Gamepad2, KeyRound, Keyboard, MapPin, Mic, Monitor, MonitorUp, Moon, Music, Timer, Usb, Vibrate, Volume2, } from 'lucide-react';
|
|
4
|
+
import { useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { NATIVE_HARDWARE_CAPABILITY_IDS, } from '../../lib/native-hardware';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Skeleton } from '../ui/skeleton';
|
|
8
|
+
import { CapabilityDot } from './capability-badge';
|
|
9
|
+
import { loadMoldableCapabilities, } from './use-capability';
|
|
10
|
+
const CAPABILITY_ICON = {
|
|
11
|
+
camera: Camera,
|
|
12
|
+
microphone: Mic,
|
|
13
|
+
'screen-capture': MonitorUp,
|
|
14
|
+
'system-audio': Volume2,
|
|
15
|
+
location: MapPin,
|
|
16
|
+
'clipboard-read': Clipboard,
|
|
17
|
+
'clipboard-write': ClipboardCopy,
|
|
18
|
+
notifications: Bell,
|
|
19
|
+
displays: Monitor,
|
|
20
|
+
'global-shortcuts': Keyboard,
|
|
21
|
+
'power-monitor': BatteryCharging,
|
|
22
|
+
'idle-state': Timer,
|
|
23
|
+
'session-events': Activity,
|
|
24
|
+
'sleep-blocker': Moon,
|
|
25
|
+
'local-authentication': Fingerprint,
|
|
26
|
+
haptics: Vibrate,
|
|
27
|
+
'secure-storage': KeyRound,
|
|
28
|
+
usb: Usb,
|
|
29
|
+
hid: Gamepad2,
|
|
30
|
+
serial: Cable,
|
|
31
|
+
midi: Music,
|
|
32
|
+
bluetooth: Bluetooth,
|
|
33
|
+
};
|
|
34
|
+
const SPECIAL_NAME = {
|
|
35
|
+
usb: 'USB',
|
|
36
|
+
hid: 'HID',
|
|
37
|
+
midi: 'MIDI',
|
|
38
|
+
};
|
|
39
|
+
const SUPPORT_LABEL = {
|
|
40
|
+
checking: 'Checking',
|
|
41
|
+
supported: 'Supported',
|
|
42
|
+
partial: 'Partial',
|
|
43
|
+
unsupported: 'Unsupported',
|
|
44
|
+
unavailable: 'Unavailable',
|
|
45
|
+
};
|
|
46
|
+
function humanizeCapabilityId(id) {
|
|
47
|
+
const special = SPECIAL_NAME[id];
|
|
48
|
+
if (special)
|
|
49
|
+
return special;
|
|
50
|
+
return id
|
|
51
|
+
.split('-')
|
|
52
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
53
|
+
.join(' ');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Responsive support grid for every native capability: icon, humanized name,
|
|
57
|
+
* status dot, support level, and transport. Renders skeleton cells while the
|
|
58
|
+
* manifest loads and a quiet note when it is unavailable outside Moldable.
|
|
59
|
+
*/
|
|
60
|
+
function CapabilityMatrix({ capabilities, className, ...props }) {
|
|
61
|
+
const [manifest, setManifest] = useState(null);
|
|
62
|
+
const [checking, setChecking] = useState(true);
|
|
63
|
+
const generationRef = useRef(0);
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const generation = ++generationRef.current;
|
|
66
|
+
loadMoldableCapabilities()
|
|
67
|
+
.then((value) => {
|
|
68
|
+
if (generationRef.current !== generation)
|
|
69
|
+
return;
|
|
70
|
+
setManifest(value);
|
|
71
|
+
setChecking(false);
|
|
72
|
+
})
|
|
73
|
+
.catch(() => {
|
|
74
|
+
if (generationRef.current !== generation)
|
|
75
|
+
return;
|
|
76
|
+
setManifest(null);
|
|
77
|
+
setChecking(false);
|
|
78
|
+
});
|
|
79
|
+
const liveGeneration = generationRef;
|
|
80
|
+
return () => {
|
|
81
|
+
liveGeneration.current++;
|
|
82
|
+
};
|
|
83
|
+
}, []);
|
|
84
|
+
const ids = capabilities ?? NATIVE_HARDWARE_CAPABILITY_IDS;
|
|
85
|
+
const unavailable = !checking && manifest === null;
|
|
86
|
+
return (_jsxs("div", { "data-slot": "capability-matrix", "data-status": checking ? 'checking' : unavailable ? 'unavailable' : 'ready', className: cn('grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4', className), ...props, children: [ids.map((id, index) => {
|
|
87
|
+
const Icon = CAPABILITY_ICON[id];
|
|
88
|
+
const descriptor = manifest?.capabilities[id] ?? null;
|
|
89
|
+
const status = checking
|
|
90
|
+
? 'checking'
|
|
91
|
+
: descriptor
|
|
92
|
+
? descriptor.support
|
|
93
|
+
: 'unavailable';
|
|
94
|
+
return (_jsx("div", { "data-slot": "capability-matrix-cell", "data-capability": id, "data-status": status, className: "animate-in fade-in slide-in-from-bottom-1 bg-card rounded-lg border p-3 duration-300 [animation-fill-mode:backwards] motion-reduce:animate-none", style: { animationDelay: `${index * 25}ms` }, children: checking ? (_jsxs("div", { className: "space-y-2", children: [_jsx(Skeleton, { className: "h-3.5 w-2/3" }), _jsx(Skeleton, { className: "h-3 w-1/2" })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(Icon, { className: "text-muted-foreground size-3.5 shrink-0" }), _jsx("span", { className: "truncate text-xs font-medium", children: humanizeCapabilityId(id) }), _jsx(CapabilityDot, { status: status, className: "ml-auto" })] }), _jsxs("div", { className: "mt-1.5 flex items-center justify-between gap-2", children: [_jsx("span", { className: "text-muted-foreground text-[10px]", children: SUPPORT_LABEL[status] }), descriptor ? (_jsx("span", { className: "text-muted-foreground/70 truncate font-mono text-[10px]", children: descriptor.transport.name })) : null] })] })) }, id));
|
|
95
|
+
}), unavailable ? (_jsx("p", { "data-slot": "capability-matrix-note", className: "text-muted-foreground/70 col-span-full text-center text-xs", children: "Native capabilities require the Moldable desktop app." })) : null] }));
|
|
96
|
+
}
|
|
97
|
+
export { CapabilityMatrix };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Button } from '../ui/button';
|
|
3
|
+
/**
|
|
4
|
+
* Clipboard state machine behind `ClipboardCopyButton`. Prefers the Moldable
|
|
5
|
+
* bridge helpers and falls back to the plain web Clipboard API, so it never
|
|
6
|
+
* throws — writes report success as a boolean and reads report `null`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useMoldableClipboard(): {
|
|
9
|
+
writeText: (text: string) => Promise<boolean>;
|
|
10
|
+
readText: () => Promise<string | null>;
|
|
11
|
+
lastRead: string | null;
|
|
12
|
+
error: Error | null;
|
|
13
|
+
};
|
|
14
|
+
export interface ClipboardCopyButtonProps extends Omit<React.ComponentProps<typeof Button>, 'value'> {
|
|
15
|
+
/** Text to copy, or a resolver invoked at click time. */
|
|
16
|
+
value: string | (() => string | Promise<string>);
|
|
17
|
+
onCopied?: (text: string) => void;
|
|
18
|
+
onCopyError?: (error: Error) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Copy-to-clipboard button: resolves `value`, writes it, and morphs the copy
|
|
22
|
+
* icon into a success check for a moment.
|
|
23
|
+
*/
|
|
24
|
+
declare function ClipboardCopyButton({ value, onCopied, onCopyError, variant, size, onClick, children, ...props }: ClipboardCopyButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export { ClipboardCopyButton };
|
|
26
|
+
//# sourceMappingURL=clipboard-button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clipboard-button.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/clipboard-button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC;;;;GAIG;AACH,wBAAgB,oBAAoB;sBAIS,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;oBAsB7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;;;EAyB9D;AAED,MAAM,WAAW,wBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1D,yDAAyD;IACzD,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAA;IAChD,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACrC;AAED;;;GAGG;AACH,iBAAS,mBAAmB,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,WAAW,EACX,OAAiB,EACjB,IAAgB,EAChB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,wBAAwB,2CAqE1B;AAED,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Check, Copy } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { readMoldableClipboardText, writeMoldableClipboardText, } from '../../lib/native-hardware';
|
|
6
|
+
import { Button } from '../ui/button';
|
|
7
|
+
/**
|
|
8
|
+
* Clipboard state machine behind `ClipboardCopyButton`. Prefers the Moldable
|
|
9
|
+
* bridge helpers and falls back to the plain web Clipboard API, so it never
|
|
10
|
+
* throws — writes report success as a boolean and reads report `null`.
|
|
11
|
+
*/
|
|
12
|
+
export function useMoldableClipboard() {
|
|
13
|
+
const [lastRead, setLastRead] = useState(null);
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
const writeText = useCallback(async (text) => {
|
|
16
|
+
setError(null);
|
|
17
|
+
try {
|
|
18
|
+
await writeMoldableClipboardText(text);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (nativeCause) {
|
|
22
|
+
try {
|
|
23
|
+
await navigator.clipboard.writeText(text);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch (browserCause) {
|
|
27
|
+
setError(browserCause instanceof Error
|
|
28
|
+
? browserCause
|
|
29
|
+
: nativeCause instanceof Error
|
|
30
|
+
? nativeCause
|
|
31
|
+
: new Error('Could not write clipboard text.'));
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}, []);
|
|
36
|
+
const readText = useCallback(async () => {
|
|
37
|
+
setError(null);
|
|
38
|
+
let text;
|
|
39
|
+
try {
|
|
40
|
+
text = await readMoldableClipboardText();
|
|
41
|
+
}
|
|
42
|
+
catch (nativeCause) {
|
|
43
|
+
try {
|
|
44
|
+
text = await navigator.clipboard.readText();
|
|
45
|
+
}
|
|
46
|
+
catch (browserCause) {
|
|
47
|
+
setLastRead(null);
|
|
48
|
+
setError(browserCause instanceof Error
|
|
49
|
+
? browserCause
|
|
50
|
+
: nativeCause instanceof Error
|
|
51
|
+
? nativeCause
|
|
52
|
+
: new Error('Could not read clipboard text.'));
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
setLastRead(text);
|
|
57
|
+
return text;
|
|
58
|
+
}, []);
|
|
59
|
+
return { writeText, readText, lastRead, error };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Copy-to-clipboard button: resolves `value`, writes it, and morphs the copy
|
|
63
|
+
* icon into a success check for a moment.
|
|
64
|
+
*/
|
|
65
|
+
function ClipboardCopyButton({ value, onCopied, onCopyError, variant = 'ghost', size = 'icon-sm', onClick, children, ...props }) {
|
|
66
|
+
const { writeText } = useMoldableClipboard();
|
|
67
|
+
const [copied, setCopied] = useState(false);
|
|
68
|
+
const [copyFailed, setCopyFailed] = useState(false);
|
|
69
|
+
const tokenRef = useRef(0);
|
|
70
|
+
const timeoutRef = useRef(null);
|
|
71
|
+
useEffect(() => () => {
|
|
72
|
+
tokenRef.current++;
|
|
73
|
+
if (timeoutRef.current !== null)
|
|
74
|
+
window.clearTimeout(timeoutRef.current);
|
|
75
|
+
}, []);
|
|
76
|
+
const copy = useCallback(async () => {
|
|
77
|
+
const token = ++tokenRef.current;
|
|
78
|
+
setCopied(false);
|
|
79
|
+
setCopyFailed(false);
|
|
80
|
+
let text;
|
|
81
|
+
try {
|
|
82
|
+
const source = value;
|
|
83
|
+
text = typeof source === 'function' ? await source() : source;
|
|
84
|
+
}
|
|
85
|
+
catch (cause) {
|
|
86
|
+
if (tokenRef.current !== token)
|
|
87
|
+
return;
|
|
88
|
+
const error = cause instanceof Error ? cause : new Error('Could not resolve text.');
|
|
89
|
+
setCopyFailed(true);
|
|
90
|
+
onCopyError?.(error);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const written = await writeText(text);
|
|
94
|
+
if (tokenRef.current !== token)
|
|
95
|
+
return;
|
|
96
|
+
if (!written) {
|
|
97
|
+
const error = new Error('Could not write clipboard text.');
|
|
98
|
+
setCopyFailed(true);
|
|
99
|
+
onCopyError?.(error);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
onCopied?.(text);
|
|
103
|
+
setCopied(true);
|
|
104
|
+
if (timeoutRef.current !== null)
|
|
105
|
+
window.clearTimeout(timeoutRef.current);
|
|
106
|
+
timeoutRef.current = window.setTimeout(() => setCopied(false), 1500);
|
|
107
|
+
}, [onCopied, onCopyError, value, writeText]);
|
|
108
|
+
return (_jsxs(Button, { "data-slot": "clipboard-copy-button", "data-copied": copied || undefined, "data-copy-status": copied ? 'success' : copyFailed ? 'error' : 'idle', variant: variant, size: size, "aria-label": copied ? 'Copied' : copyFailed ? 'Copy failed; try again' : 'Copy', onClick: (event) => {
|
|
109
|
+
onClick?.(event);
|
|
110
|
+
if (!event.defaultPrevented)
|
|
111
|
+
void copy();
|
|
112
|
+
}, ...props, children: [copied ? (_jsx(Check, { className: "text-success animate-in zoom-in-50 duration-200 motion-reduce:animate-none" })) : (_jsx(Copy, {})), children] }));
|
|
113
|
+
}
|
|
114
|
+
export { ClipboardCopyButton };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function parseIntegerInput(value: string, label: string, minimum: number, maximum: number): number;
|
|
2
|
+
export declare function parseHexBytes(value: string): Uint8Array<ArrayBuffer>;
|
|
3
|
+
export declare function formatHexBytes(data: ArrayBufferView | null | undefined): string;
|
|
4
|
+
//# sourceMappingURL=device-io-controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-io-controls.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/device-io-controls.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd,MAAM,CASR;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAepE;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GACvC,MAAM,CAMR"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function parseIntegerInput(value, label, minimum, maximum) {
|
|
2
|
+
const normalized = value.trim();
|
|
3
|
+
const parsed = normalized.length > 0 ? Number(normalized) : Number.NaN;
|
|
4
|
+
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) {
|
|
5
|
+
throw new Error(`${label} must be an integer from ${minimum} to ${maximum}.`);
|
|
6
|
+
}
|
|
7
|
+
return parsed;
|
|
8
|
+
}
|
|
9
|
+
export function parseHexBytes(value) {
|
|
10
|
+
const normalized = value.trim();
|
|
11
|
+
if (normalized.length === 0)
|
|
12
|
+
return new Uint8Array(0);
|
|
13
|
+
const tokens = normalized.split(/[\s,]+/u);
|
|
14
|
+
const bytes = tokens.map((token) => {
|
|
15
|
+
const digits = token.replace(/^0x/iu, '');
|
|
16
|
+
if (!/^[\da-f]{1,2}$/iu.test(digits)) {
|
|
17
|
+
throw new Error('Payload must contain hexadecimal bytes such as 01 A0 FF.');
|
|
18
|
+
}
|
|
19
|
+
return Number.parseInt(digits, 16);
|
|
20
|
+
});
|
|
21
|
+
return new Uint8Array(bytes);
|
|
22
|
+
}
|
|
23
|
+
export function formatHexBytes(data) {
|
|
24
|
+
if (!data || data.byteLength === 0)
|
|
25
|
+
return '(empty)';
|
|
26
|
+
const bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
27
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, '0').toUpperCase()).join(' ');
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare function DeviceList({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export interface DeviceListItemProps extends React.ComponentProps<'div'> {
|
|
4
|
+
/** Icon shown in the leading square well. */
|
|
5
|
+
icon?: React.ReactNode;
|
|
6
|
+
name: React.ReactNode;
|
|
7
|
+
/** Secondary line, rendered in mono (IDs, vendor codes, paths). */
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
/** Shows a green dot + "Connected" next to the name. */
|
|
10
|
+
connected?: boolean;
|
|
11
|
+
/** Trailing actions (buttons, badges). */
|
|
12
|
+
action?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
declare function DeviceListItem({ icon, name, description, connected, action, className, children, ...props }: DeviceListItemProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export interface DeviceListEmptyProps extends React.ComponentProps<'div'> {
|
|
16
|
+
icon?: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
declare function DeviceListEmpty({ icon, className, children, ...props }: DeviceListEmptyProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export { DeviceList, DeviceListItem, DeviceListEmpty };
|
|
20
|
+
//# sourceMappingURL=device-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-list.d.ts","sourceRoot":"","sources":["../../../src/components/hardware/device-list.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAYvE;AAED,MAAM,WAAW,mBAAoB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACtE,6CAA6C;IAC7C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAA;IACrB,mEAAmE;IACnE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC7B,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB;AAED,iBAAS,cAAc,CAAC,EACtB,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,SAAiB,EACjB,MAAM,EACN,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,mBAAmB,2CA2DrB;AAED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACvE,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,iBAAS,eAAe,CAAC,EACvB,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,2CAkBtB;AAED,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
function DeviceList({ className, ...props }) {
|
|
5
|
+
return (_jsx("div", { "data-slot": "device-list", role: "list", className: cn('divide-border divide-y overflow-hidden rounded-lg border', className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
function DeviceListItem({ icon, name, description, connected = false, action, className, children, ...props }) {
|
|
8
|
+
return (_jsxs("div", { "data-slot": "device-list-item", role: "listitem", className: cn('animate-in fade-in slide-in-from-bottom-1 flex items-center gap-3 px-3 py-2.5 duration-300 motion-reduce:animate-none', props.onClick &&
|
|
9
|
+
'hover:bg-muted/50 focus-visible:bg-muted/50 cursor-pointer outline-none transition-colors', className), ...props, children: [icon ? (_jsx("div", { "data-slot": "device-list-item-icon", className: "text-muted-foreground bg-muted/50 flex size-8 shrink-0 items-center justify-center rounded-md border [&_svg:not([class*='size-'])]:size-4", children: icon })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { "data-slot": "device-list-item-name", className: "truncate text-sm font-medium", children: name }), connected ? (_jsxs("span", { "data-slot": "device-list-item-connected", className: "text-status-running inline-flex shrink-0 items-center gap-1 text-[10px] font-medium uppercase tracking-wide", children: [_jsx("span", { className: "bg-status-running size-1.5 rounded-full" }), "Connected"] })) : null] }), description ? (_jsx("div", { "data-slot": "device-list-item-description", className: "text-muted-foreground mt-0.5 truncate font-mono text-xs", children: description })) : null, children] }), action ? (_jsx("div", { "data-slot": "device-list-item-action", className: "flex shrink-0 items-center gap-1.5", children: action })) : null] }));
|
|
10
|
+
}
|
|
11
|
+
function DeviceListEmpty({ icon, className, children, ...props }) {
|
|
12
|
+
return (_jsxs("div", { "data-slot": "device-list-empty", className: cn('text-muted-foreground flex flex-col items-center gap-2 px-4 py-8 text-center text-sm', className), ...props, children: [icon ? (_jsx("div", { className: "opacity-60 [&_svg:not([class*='size-'])]:size-5", children: icon })) : null, children] }));
|
|
13
|
+
}
|
|
14
|
+
export { DeviceList, DeviceListItem, DeviceListEmpty };
|