@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,124 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Bell, Send } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { NATIVE_NOTIFICATION_MAX_BODY_LENGTH, NATIVE_NOTIFICATION_MAX_TAG_LENGTH, NATIVE_NOTIFICATION_MAX_TITLE_LENGTH, getMoldableNotificationPermission, requestMoldableNotificationPermission, sendMoldableNotification, } from '../../lib/native-capabilities';
|
|
6
|
+
import { Button } from '../ui/button';
|
|
7
|
+
import { Input } from '../ui/input';
|
|
8
|
+
import { Spinner } from '../ui/spinner';
|
|
9
|
+
import { Switch } from '../ui/switch';
|
|
10
|
+
import { CapabilityBadge } from './capability-badge';
|
|
11
|
+
import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
|
|
12
|
+
import { useMoldableCapability, } from './use-capability';
|
|
13
|
+
/**
|
|
14
|
+
* Notification state machine behind `NotificationsPanel`: permission loading,
|
|
15
|
+
* explicit permission requests, and sends with the library's length limits
|
|
16
|
+
* enforced by truncation.
|
|
17
|
+
*/
|
|
18
|
+
export function useMoldableNotifications() {
|
|
19
|
+
const [permission, setPermission] = useState('unknown');
|
|
20
|
+
const [status, setStatus] = useState('idle');
|
|
21
|
+
const [sentAt, setSentAt] = useState(null);
|
|
22
|
+
const [error, setError] = useState(null);
|
|
23
|
+
const tokenRef = useRef(0);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
let live = true;
|
|
26
|
+
getMoldableNotificationPermission()
|
|
27
|
+
.then((result) => {
|
|
28
|
+
if (live)
|
|
29
|
+
setPermission(result.permission);
|
|
30
|
+
})
|
|
31
|
+
.catch(() => {
|
|
32
|
+
// Best-effort: outside Moldable the permission stays unknown.
|
|
33
|
+
});
|
|
34
|
+
return () => {
|
|
35
|
+
live = false;
|
|
36
|
+
};
|
|
37
|
+
}, []);
|
|
38
|
+
const request = useCallback(async () => {
|
|
39
|
+
const token = ++tokenRef.current;
|
|
40
|
+
try {
|
|
41
|
+
const result = await requestMoldableNotificationPermission();
|
|
42
|
+
if (tokenRef.current !== token)
|
|
43
|
+
return null;
|
|
44
|
+
setPermission(result.permission);
|
|
45
|
+
return result.permission;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}, []);
|
|
51
|
+
const send = useCallback(async (options) => {
|
|
52
|
+
const token = ++tokenRef.current;
|
|
53
|
+
setStatus('sending');
|
|
54
|
+
setError(null);
|
|
55
|
+
try {
|
|
56
|
+
await sendMoldableNotification({
|
|
57
|
+
...options,
|
|
58
|
+
title: options.title.slice(0, NATIVE_NOTIFICATION_MAX_TITLE_LENGTH),
|
|
59
|
+
body: options.body?.slice(0, NATIVE_NOTIFICATION_MAX_BODY_LENGTH),
|
|
60
|
+
tag: options.tag?.slice(0, NATIVE_NOTIFICATION_MAX_TAG_LENGTH),
|
|
61
|
+
});
|
|
62
|
+
if (tokenRef.current !== token)
|
|
63
|
+
return false;
|
|
64
|
+
setSentAt(Date.now());
|
|
65
|
+
setStatus('sent');
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (cause) {
|
|
69
|
+
if (tokenRef.current !== token)
|
|
70
|
+
return false;
|
|
71
|
+
setError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
72
|
+
setStatus('error');
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}, []);
|
|
76
|
+
useEffect(() => () => {
|
|
77
|
+
tokenRef.current++;
|
|
78
|
+
}, []);
|
|
79
|
+
return { permission, status, sentAt, error, request, send };
|
|
80
|
+
}
|
|
81
|
+
const PERMISSION_CHIP = {
|
|
82
|
+
granted: { status: 'supported', label: 'Granted' },
|
|
83
|
+
prompt: { status: 'partial', label: 'Not requested' },
|
|
84
|
+
denied: { status: 'unsupported', label: 'Denied' },
|
|
85
|
+
};
|
|
86
|
+
function formatClock(timestamp) {
|
|
87
|
+
const date = new Date(timestamp);
|
|
88
|
+
const pad = (value) => value.toString().padStart(2, '0');
|
|
89
|
+
return `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Notification composer panel: permission chip with an inline allow flow, a
|
|
93
|
+
* compact title/body/silent composer, and delivery feedback.
|
|
94
|
+
*/
|
|
95
|
+
function NotificationsPanel({ className, ...props }) {
|
|
96
|
+
const notifications = useMoldableNotifications();
|
|
97
|
+
const capability = useMoldableCapability('notifications');
|
|
98
|
+
const [title, setTitle] = useState('Hello from Moldable');
|
|
99
|
+
const [body, setBody] = useState('');
|
|
100
|
+
const [silent, setSilent] = useState(false);
|
|
101
|
+
const [requesting, setRequesting] = useState(false);
|
|
102
|
+
const sending = notifications.status === 'sending';
|
|
103
|
+
const canSend = title.trim().length > 0 && !sending;
|
|
104
|
+
const sendNotification = async () => {
|
|
105
|
+
await notifications.send({
|
|
106
|
+
title,
|
|
107
|
+
body: body.trim().length > 0 ? body : undefined,
|
|
108
|
+
tag: 'moldable-native-capabilities',
|
|
109
|
+
silent,
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
const requestPermission = async () => {
|
|
113
|
+
setRequesting(true);
|
|
114
|
+
await notifications.request();
|
|
115
|
+
setRequesting(false);
|
|
116
|
+
};
|
|
117
|
+
const chip = notifications.permission === 'unknown'
|
|
118
|
+
? null
|
|
119
|
+
: PERMISSION_CHIP[notifications.permission];
|
|
120
|
+
return (_jsxs(NativeCapabilityPanel, { "data-slot": "notifications-panel", "data-status": notifications.status, "data-permission": notifications.permission, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(Bell, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Notifications" }), _jsx(CapabilityBadge, { capability: "notifications" }), _jsx(NativeCapabilityPanelAction, { children: notifications.permission === 'prompt' ? (_jsxs(Button, { size: "sm", variant: "outline", disabled: requesting, onClick: () => void requestPermission(), children: [requesting ? _jsx(Spinner, {}) : null, "Allow"] })) : chip ? (_jsx(CapabilityBadge, { status: chip.status, label: chip.label })) : null })] }), _jsxs(NativeCapabilityPanelContent, { className: "space-y-3", children: [_jsxs("div", { className: "grid gap-2", children: [_jsx(Input, { value: title, maxLength: NATIVE_NOTIFICATION_MAX_TITLE_LENGTH, placeholder: "Title", "aria-label": "Notification title", onChange: (event) => setTitle(event.target.value) }), _jsx(Input, { value: body, maxLength: NATIVE_NOTIFICATION_MAX_BODY_LENGTH, placeholder: "Body (optional)", "aria-label": "Notification body", onChange: (event) => setBody(event.target.value) })] }), _jsxs("div", { className: "flex items-center justify-between gap-3", children: [_jsxs("label", { className: "text-muted-foreground flex items-center gap-2 text-xs", children: [_jsx(Switch, { size: "sm", checked: silent, onCheckedChange: setSilent }), "Silent"] }), _jsxs(Button, { size: "sm", disabled: !canSend, onClick: () => void sendNotification(), children: [sending ? _jsx(Spinner, {}) : _jsx(Send, {}), "Send notification"] })] }), notifications.status === 'sent' && notifications.sentAt !== null ? (_jsxs("p", { className: "text-success animate-in fade-in font-mono text-xs tabular-nums duration-300 motion-reduce:animate-none", children: ["Delivered ", formatClock(notifications.sentAt)] })) : notifications.status === 'error' ? (_jsx("p", { className: "text-status-error text-xs", children: notifications.error?.message ??
|
|
121
|
+
'The notification could not be sent.' })) : null] }), _jsx(NativeCapabilityPanelFooter, { children: _jsx("span", { className: "truncate", children: capability.descriptor?.reason ??
|
|
122
|
+
'Notifications appear via the OS notification center.' }) })] }));
|
|
123
|
+
}
|
|
124
|
+
export { NotificationsPanel };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type MoldableSleepBlocker, type MoldableSleepBlockerType } from '../../lib/native-capabilities';
|
|
2
|
+
type StartSleepBlocker = (type: MoldableSleepBlockerType) => Promise<MoldableSleepBlocker>;
|
|
3
|
+
declare const BLOCKER_TYPES: readonly ["prevent-display-sleep", "prevent-app-suspension"];
|
|
4
|
+
/**
|
|
5
|
+
* Owns sleep-blocker handles independently from React state. Handles are only
|
|
6
|
+
* discarded after the host confirms they stopped, so a failed cleanup remains
|
|
7
|
+
* retryable.
|
|
8
|
+
*/
|
|
9
|
+
export declare class MoldableSleepBlockerController {
|
|
10
|
+
#private;
|
|
11
|
+
private readonly startSleepBlocker;
|
|
12
|
+
constructor(startSleepBlocker?: StartSleepBlocker);
|
|
13
|
+
has(type: MoldableSleepBlockerType): boolean;
|
|
14
|
+
toggle(type: MoldableSleepBlockerType): Promise<boolean>;
|
|
15
|
+
check(type: MoldableSleepBlockerType): Promise<boolean>;
|
|
16
|
+
stopAll(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export { BLOCKER_TYPES };
|
|
19
|
+
//# sourceMappingURL=power-blocker-controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-blocker-controller.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/power-blocker-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAE9B,MAAM,+BAA+B,CAAA;AAEtC,KAAK,iBAAiB,GAAG,CACvB,IAAI,EAAE,wBAAwB,KAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAElC,QAAA,MAAM,aAAa,8DAGqC,CAAA;AAExD;;;;GAIG;AACH,qBAAa,8BAA8B;;IAkBvC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;gBAAjB,iBAAiB,GAAE,iBAA6C;IAGnF,GAAG,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO;IAI5C,MAAM,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBxD,KAAK,CAAC,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA+B/B;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { startMoldableSleepBlocker, } from '../../lib/native-capabilities';
|
|
2
|
+
const BLOCKER_TYPES = [
|
|
3
|
+
'prevent-display-sleep',
|
|
4
|
+
'prevent-app-suspension',
|
|
5
|
+
];
|
|
6
|
+
/**
|
|
7
|
+
* Owns sleep-blocker handles independently from React state. Handles are only
|
|
8
|
+
* discarded after the host confirms they stopped, so a failed cleanup remains
|
|
9
|
+
* retryable.
|
|
10
|
+
*/
|
|
11
|
+
export class MoldableSleepBlockerController {
|
|
12
|
+
startSleepBlocker;
|
|
13
|
+
#handles = {
|
|
14
|
+
'prevent-display-sleep': null,
|
|
15
|
+
'prevent-app-suspension': null,
|
|
16
|
+
};
|
|
17
|
+
#operations = {
|
|
18
|
+
'prevent-display-sleep': null,
|
|
19
|
+
'prevent-app-suspension': null,
|
|
20
|
+
};
|
|
21
|
+
constructor(startSleepBlocker = startMoldableSleepBlocker) {
|
|
22
|
+
this.startSleepBlocker = startSleepBlocker;
|
|
23
|
+
}
|
|
24
|
+
has(type) {
|
|
25
|
+
return this.#handles[type] !== null;
|
|
26
|
+
}
|
|
27
|
+
toggle(type) {
|
|
28
|
+
return this.#enqueue(type, async () => {
|
|
29
|
+
const current = this.#handles[type];
|
|
30
|
+
if (current) {
|
|
31
|
+
await current.stop();
|
|
32
|
+
if (this.#handles[type] === current)
|
|
33
|
+
this.#handles[type] = null;
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const blocker = await this.startSleepBlocker(type);
|
|
37
|
+
this.#handles[type] = blocker;
|
|
38
|
+
const started = await blocker.isStarted();
|
|
39
|
+
if (!started && this.#handles[type] === blocker) {
|
|
40
|
+
this.#handles[type] = null;
|
|
41
|
+
}
|
|
42
|
+
return started;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
check(type) {
|
|
46
|
+
return this.#enqueue(type, async () => {
|
|
47
|
+
const blocker = this.#handles[type];
|
|
48
|
+
if (!blocker)
|
|
49
|
+
return false;
|
|
50
|
+
const started = await blocker.isStarted();
|
|
51
|
+
if (!started && this.#handles[type] === blocker) {
|
|
52
|
+
this.#handles[type] = null;
|
|
53
|
+
}
|
|
54
|
+
return started;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async stopAll() {
|
|
58
|
+
const results = await Promise.allSettled(BLOCKER_TYPES.map((type) => this.#enqueue(type, async () => {
|
|
59
|
+
const blocker = this.#handles[type];
|
|
60
|
+
if (!blocker)
|
|
61
|
+
return;
|
|
62
|
+
await blocker.stop();
|
|
63
|
+
if (this.#handles[type] === blocker)
|
|
64
|
+
this.#handles[type] = null;
|
|
65
|
+
})));
|
|
66
|
+
const failed = results.find((result) => result.status === 'rejected');
|
|
67
|
+
if (failed)
|
|
68
|
+
throw failed.reason;
|
|
69
|
+
}
|
|
70
|
+
#enqueue(type, operation) {
|
|
71
|
+
const previous = this.#operations[type] ?? Promise.resolve();
|
|
72
|
+
const current = previous.catch(() => undefined).then(operation);
|
|
73
|
+
this.#operations[type] = current;
|
|
74
|
+
void current
|
|
75
|
+
.finally(() => {
|
|
76
|
+
if (this.#operations[type] === current)
|
|
77
|
+
this.#operations[type] = null;
|
|
78
|
+
})
|
|
79
|
+
.catch(() => undefined);
|
|
80
|
+
return current;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export { BLOCKER_TYPES };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type MoldablePowerSessionEvent, type MoldablePowerState, type MoldableSleepBlockerType, type MoldableSystemIdleState, type MoldableThermalState } from '../../lib/native-capabilities';
|
|
3
|
+
export interface MoldablePowerSessionLogEntry {
|
|
4
|
+
/** Monotonic id, stable across the rolling window. */
|
|
5
|
+
id: number;
|
|
6
|
+
/** Epoch millis parsed from the event's `occurredAt`. */
|
|
7
|
+
timestamp: number;
|
|
8
|
+
event: MoldablePowerSessionEvent;
|
|
9
|
+
}
|
|
10
|
+
export interface MoldablePowerIdleSnapshot {
|
|
11
|
+
state: MoldableSystemIdleState;
|
|
12
|
+
seconds: number;
|
|
13
|
+
}
|
|
14
|
+
export interface UseMoldablePowerOptions {
|
|
15
|
+
/** Poll cadence for power/thermal/idle state. Defaults to 30 000 ms. */
|
|
16
|
+
pollIntervalMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Power/session state machine behind `PowerPanel`: polled power + thermal +
|
|
20
|
+
* idle state, live session events, and a managed sleep blocker. Every native
|
|
21
|
+
* failure degrades to nulls so it is safe outside Moldable.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useMoldablePower(options?: UseMoldablePowerOptions): {
|
|
24
|
+
power: MoldablePowerState | null;
|
|
25
|
+
thermal: MoldableThermalState | null;
|
|
26
|
+
idle: MoldablePowerIdleSnapshot | null;
|
|
27
|
+
events: MoldablePowerSessionLogEntry[];
|
|
28
|
+
updatedAt: number | null;
|
|
29
|
+
error: Error | null;
|
|
30
|
+
refresh: () => void;
|
|
31
|
+
sleepBlocker: {
|
|
32
|
+
active: boolean;
|
|
33
|
+
type: "prevent-display-sleep" | null;
|
|
34
|
+
toggle: (type?: MoldableSleepBlockerType) => Promise<void>;
|
|
35
|
+
};
|
|
36
|
+
sleepBlockers: Record<MoldableSleepBlockerType, {
|
|
37
|
+
active: boolean;
|
|
38
|
+
busy: boolean;
|
|
39
|
+
toggle: () => Promise<void>;
|
|
40
|
+
check: () => Promise<void>;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
export interface BatteryGaugeProps extends React.ComponentProps<'span'> {
|
|
44
|
+
/** Controlled charge percent (0-100). Omit all data props to self-manage. */
|
|
45
|
+
percent?: number;
|
|
46
|
+
/** Controlled charging flag. */
|
|
47
|
+
charging?: boolean;
|
|
48
|
+
/** The machine has no battery — renders an AC power presentation. */
|
|
49
|
+
noBattery?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Compact inline battery glyph + percent. Pass `percent`/`charging` (and
|
|
53
|
+
* optionally `noBattery`) to control it, or no data props to let it poll
|
|
54
|
+
* `useMoldablePower` itself.
|
|
55
|
+
*/
|
|
56
|
+
declare function BatteryGauge({ percent, charging, noBattery, ...props }: BatteryGaugeProps): import("react/jsx-runtime").JSX.Element;
|
|
57
|
+
export interface PowerPanelProps extends React.ComponentProps<'div'> {
|
|
58
|
+
/** Poll cadence for power/thermal/idle state. Defaults to 30 000 ms. */
|
|
59
|
+
pollIntervalMs?: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Power panel: battery gauge, source/thermal/idle readout, live session event
|
|
63
|
+
* log, and a "keep awake" sleep-blocker switch.
|
|
64
|
+
*/
|
|
65
|
+
declare function PowerPanel({ className, pollIntervalMs, ...props }: PowerPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
66
|
+
export { PowerPanel, BatteryGauge };
|
|
67
|
+
//# sourceMappingURL=power-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"power-panel.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/power-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,oBAAoB,EAO1B,MAAM,+BAA+B,CAAA;AAuBtC,MAAM,WAAW,4BAA4B;IAC3C,sDAAsD;IACtD,EAAE,EAAE,MAAM,CAAA;IACV,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,yBAAyB,CAAA;CACjC;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,uBAAuB,CAAA;IAC9B,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B;;;;;;;;;;;wBA0HrD,wBAAwB;;mBAwEhC,MAAM,CACT,wBAAwB,EACxB;QACE,MAAM,EAAE,OAAO,CAAA;QACf,IAAI,EAAE,OAAO,CAAA;QACb,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;QAC3B,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAC3B,CACF;EAEJ;AA0DD,MAAM,WAAW,iBAAkB,SAAQ,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC;IACrE,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gCAAgC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AA2DD;;;;GAIG;AACH,iBAAS,YAAY,CAAC,EACpB,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,iBAAiB,2CAgBnB;AAsCD,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IAClE,wEAAwE;IACxE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED;;;GAGG;AACH,iBAAS,UAAU,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,KAAK,EAAE,EAAE,eAAe,2CA0J3E;AAED,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { BatteryCharging, Plug, RefreshCw, Zap } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { getMoldableCurrentThermalState, getMoldablePowerState, getMoldableSystemIdleState, getMoldableSystemIdleTime, watchMoldablePowerSession, } from '../../lib/native-capabilities';
|
|
6
|
+
import { cn } from '../../lib/utils';
|
|
7
|
+
import { Button } from '../ui/button';
|
|
8
|
+
import { Switch } from '../ui/switch';
|
|
9
|
+
import { CapabilityBadge } from './capability-badge';
|
|
10
|
+
import { NativeCapabilityPanel, NativeCapabilityPanelAction, NativeCapabilityPanelContent, NativeCapabilityPanelFooter, NativeCapabilityPanelHeader, NativeCapabilityPanelIcon, NativeCapabilityPanelTitle, } from './native-capability-panel';
|
|
11
|
+
import { BLOCKER_TYPES, MoldableSleepBlockerController, } from './power-blocker-controller';
|
|
12
|
+
import { Readout, ReadoutItem } from './readout';
|
|
13
|
+
import { StreamLog, useStreamLog } from './stream-log';
|
|
14
|
+
const MAX_POWER_EVENTS = 100;
|
|
15
|
+
function toError(cause) {
|
|
16
|
+
return cause instanceof Error ? cause : new Error(String(cause));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Power/session state machine behind `PowerPanel`: polled power + thermal +
|
|
20
|
+
* idle state, live session events, and a managed sleep blocker. Every native
|
|
21
|
+
* failure degrades to nulls so it is safe outside Moldable.
|
|
22
|
+
*/
|
|
23
|
+
export function useMoldablePower(options = {}) {
|
|
24
|
+
const { pollIntervalMs = 30_000 } = options;
|
|
25
|
+
const [power, setPower] = useState(null);
|
|
26
|
+
const [thermal, setThermal] = useState(null);
|
|
27
|
+
const [idle, setIdle] = useState(null);
|
|
28
|
+
const [events, setEvents] = useState([]);
|
|
29
|
+
const [updatedAt, setUpdatedAt] = useState(null);
|
|
30
|
+
const [error, setError] = useState(null);
|
|
31
|
+
const [blockerActive, setBlockerActive] = useState({
|
|
32
|
+
'prevent-display-sleep': false,
|
|
33
|
+
'prevent-app-suspension': false,
|
|
34
|
+
});
|
|
35
|
+
const [blockerBusy, setBlockerBusy] = useState({
|
|
36
|
+
'prevent-display-sleep': false,
|
|
37
|
+
'prevent-app-suspension': false,
|
|
38
|
+
});
|
|
39
|
+
const generationRef = useRef(0);
|
|
40
|
+
const eventIdRef = useRef(0);
|
|
41
|
+
const mountedRef = useRef(true);
|
|
42
|
+
const blockerControllerRef = useRef(null);
|
|
43
|
+
blockerControllerRef.current ??= new MoldableSleepBlockerController();
|
|
44
|
+
const refresh = useCallback(() => {
|
|
45
|
+
const generation = ++generationRef.current;
|
|
46
|
+
void Promise.allSettled([
|
|
47
|
+
getMoldablePowerState(),
|
|
48
|
+
getMoldableCurrentThermalState(),
|
|
49
|
+
getMoldableSystemIdleState(60),
|
|
50
|
+
getMoldableSystemIdleTime(),
|
|
51
|
+
]).then(([powerResult, thermalResult, idleStateResult, idleTimeResult]) => {
|
|
52
|
+
if (generationRef.current !== generation)
|
|
53
|
+
return;
|
|
54
|
+
setPower(powerResult.status === 'fulfilled' ? powerResult.value : null);
|
|
55
|
+
setThermal(thermalResult.status === 'fulfilled' ? thermalResult.value : null);
|
|
56
|
+
setIdle(idleStateResult.status === 'fulfilled'
|
|
57
|
+
? {
|
|
58
|
+
state: idleStateResult.value.state,
|
|
59
|
+
seconds: idleTimeResult.status === 'fulfilled'
|
|
60
|
+
? idleTimeResult.value
|
|
61
|
+
: idleStateResult.value.seconds,
|
|
62
|
+
}
|
|
63
|
+
: null);
|
|
64
|
+
const failed = [
|
|
65
|
+
powerResult,
|
|
66
|
+
thermalResult,
|
|
67
|
+
idleStateResult,
|
|
68
|
+
idleTimeResult,
|
|
69
|
+
].find((result) => result.status === 'rejected');
|
|
70
|
+
setError(failed ? toError(failed.reason) : null);
|
|
71
|
+
setUpdatedAt(Date.now());
|
|
72
|
+
});
|
|
73
|
+
}, []);
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
refresh();
|
|
76
|
+
const interval = window.setInterval(refresh, Math.max(1000, pollIntervalMs));
|
|
77
|
+
const liveGeneration = generationRef;
|
|
78
|
+
return () => {
|
|
79
|
+
window.clearInterval(interval);
|
|
80
|
+
liveGeneration.current++;
|
|
81
|
+
};
|
|
82
|
+
}, [pollIntervalMs, refresh]);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
let cancelled = false;
|
|
85
|
+
let stopWatching = null;
|
|
86
|
+
watchMoldablePowerSession((event) => {
|
|
87
|
+
if (cancelled)
|
|
88
|
+
return;
|
|
89
|
+
const parsed = Date.parse(event.occurredAt);
|
|
90
|
+
const entry = {
|
|
91
|
+
id: ++eventIdRef.current,
|
|
92
|
+
timestamp: Number.isNaN(parsed) ? Date.now() : parsed,
|
|
93
|
+
event,
|
|
94
|
+
};
|
|
95
|
+
setEvents((previous) => {
|
|
96
|
+
const next = [...previous, entry];
|
|
97
|
+
return next.length > MAX_POWER_EVENTS
|
|
98
|
+
? next.slice(next.length - MAX_POWER_EVENTS)
|
|
99
|
+
: next;
|
|
100
|
+
});
|
|
101
|
+
if (event.kind === 'power-source-change')
|
|
102
|
+
setPower(event.powerState);
|
|
103
|
+
if (event.kind === 'thermal-state-change')
|
|
104
|
+
setThermal(event.state);
|
|
105
|
+
})
|
|
106
|
+
.then((stop) => {
|
|
107
|
+
if (cancelled) {
|
|
108
|
+
// Unmounted before the subscription resolved — stop immediately.
|
|
109
|
+
void stop().catch(() => undefined);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
stopWatching = stop;
|
|
113
|
+
})
|
|
114
|
+
.catch(() => {
|
|
115
|
+
// Session events are unavailable outside Moldable.
|
|
116
|
+
});
|
|
117
|
+
return () => {
|
|
118
|
+
cancelled = true;
|
|
119
|
+
if (stopWatching)
|
|
120
|
+
void stopWatching().catch(() => undefined);
|
|
121
|
+
};
|
|
122
|
+
}, []);
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
mountedRef.current = true;
|
|
125
|
+
const liveMounted = mountedRef;
|
|
126
|
+
const controller = blockerControllerRef.current;
|
|
127
|
+
return () => {
|
|
128
|
+
liveMounted.current = false;
|
|
129
|
+
if (controller)
|
|
130
|
+
void controller.stopAll().catch(() => undefined);
|
|
131
|
+
};
|
|
132
|
+
}, []);
|
|
133
|
+
const toggleSleepBlocker = useCallback(async (type = 'prevent-display-sleep') => {
|
|
134
|
+
const controller = blockerControllerRef.current;
|
|
135
|
+
if (!controller)
|
|
136
|
+
return;
|
|
137
|
+
setBlockerBusy((previous) => ({ ...previous, [type]: true }));
|
|
138
|
+
try {
|
|
139
|
+
const active = await controller.toggle(type);
|
|
140
|
+
if (!mountedRef.current)
|
|
141
|
+
return;
|
|
142
|
+
setBlockerActive((previous) => ({ ...previous, [type]: active }));
|
|
143
|
+
setError(null);
|
|
144
|
+
}
|
|
145
|
+
catch (cause) {
|
|
146
|
+
if (!mountedRef.current)
|
|
147
|
+
return;
|
|
148
|
+
setBlockerActive((previous) => ({
|
|
149
|
+
...previous,
|
|
150
|
+
[type]: controller.has(type),
|
|
151
|
+
}));
|
|
152
|
+
setError(toError(cause));
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
if (mountedRef.current) {
|
|
156
|
+
setBlockerBusy((previous) => ({ ...previous, [type]: false }));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, []);
|
|
160
|
+
const checkSleepBlocker = useCallback(async (type) => {
|
|
161
|
+
const controller = blockerControllerRef.current;
|
|
162
|
+
if (!controller)
|
|
163
|
+
return;
|
|
164
|
+
setBlockerBusy((previous) => ({ ...previous, [type]: true }));
|
|
165
|
+
try {
|
|
166
|
+
const active = await controller.check(type);
|
|
167
|
+
if (!mountedRef.current)
|
|
168
|
+
return;
|
|
169
|
+
setBlockerActive((previous) => ({ ...previous, [type]: active }));
|
|
170
|
+
setError(null);
|
|
171
|
+
}
|
|
172
|
+
catch (cause) {
|
|
173
|
+
if (!mountedRef.current)
|
|
174
|
+
return;
|
|
175
|
+
setError(toError(cause));
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
if (mountedRef.current) {
|
|
179
|
+
setBlockerBusy((previous) => ({ ...previous, [type]: false }));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}, []);
|
|
183
|
+
return {
|
|
184
|
+
power,
|
|
185
|
+
thermal,
|
|
186
|
+
idle,
|
|
187
|
+
events,
|
|
188
|
+
updatedAt,
|
|
189
|
+
error,
|
|
190
|
+
refresh,
|
|
191
|
+
sleepBlocker: {
|
|
192
|
+
active: blockerActive['prevent-display-sleep'],
|
|
193
|
+
type: blockerActive['prevent-display-sleep']
|
|
194
|
+
? 'prevent-display-sleep'
|
|
195
|
+
: null,
|
|
196
|
+
toggle: toggleSleepBlocker,
|
|
197
|
+
},
|
|
198
|
+
sleepBlockers: Object.fromEntries(BLOCKER_TYPES.map((type) => [
|
|
199
|
+
type,
|
|
200
|
+
{
|
|
201
|
+
active: blockerActive[type],
|
|
202
|
+
busy: blockerBusy[type],
|
|
203
|
+
toggle: () => toggleSleepBlocker(type),
|
|
204
|
+
check: () => checkSleepBlocker(type),
|
|
205
|
+
},
|
|
206
|
+
])),
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function BatteryGlyph({ percent, charging, className, }) {
|
|
210
|
+
const clamped = Math.max(0, Math.min(100, percent));
|
|
211
|
+
const fillClass = charging
|
|
212
|
+
? 'text-status-running'
|
|
213
|
+
: clamped < 15
|
|
214
|
+
? 'text-status-error'
|
|
215
|
+
: 'text-foreground';
|
|
216
|
+
return (_jsxs("svg", { viewBox: "0 0 28 14", "aria-hidden": true, className: cn('h-[1em] w-[2em] shrink-0', className), children: [_jsx("rect", { x: "1", y: "1.5", width: "23", height: "11", rx: "3", fill: "none", stroke: "currentColor", strokeWidth: "1.5", className: "opacity-50" }), _jsx("rect", { x: "25.5", y: "4.75", width: "2", height: "4.5", rx: "1", fill: "currentColor", className: "opacity-50" }), _jsx("rect", { x: "3.5", y: "4", width: (clamped / 100) * 18, height: "6", rx: "1.5", className: cn('fill-current transition-all duration-500 motion-reduce:transition-none', fillClass) })] }));
|
|
217
|
+
}
|
|
218
|
+
function BatteryGaugeBase({ percent, charging = false, noBattery = false, className, ...props }) {
|
|
219
|
+
return (_jsx("span", { "data-slot": "battery-gauge", "data-status": noBattery ? 'ac' : percent === undefined ? 'unknown' : 'battery', className: cn('inline-flex items-center gap-2 text-sm', className), ...props, children: noBattery ? (_jsxs(_Fragment, { children: [_jsx(Plug, { "aria-hidden": true, className: "text-muted-foreground size-[1.15em]" }), _jsx("span", { className: "font-mono tabular-nums", children: "AC power" })] })) : percent === undefined ? (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: 0, charging: false }), _jsx("span", { className: "text-muted-foreground/60 font-mono tabular-nums", children: "\u2014" })] })) : (_jsxs(_Fragment, { children: [_jsx(BatteryGlyph, { percent: percent, charging: charging }), _jsxs("span", { className: "font-mono tabular-nums", children: [Math.round(percent), "%"] }), charging ? (_jsx(Zap, { "aria-label": "Charging", className: "text-status-running size-3 fill-current" })) : null] })) }));
|
|
220
|
+
}
|
|
221
|
+
function ManagedBatteryGauge(props) {
|
|
222
|
+
const { power } = useMoldablePower();
|
|
223
|
+
const battery = power?.batteries[0] ?? null;
|
|
224
|
+
return (_jsx(BatteryGaugeBase, { percent: battery?.chargePercent, charging: battery?.state === 'charging', noBattery: power !== null && power.batteries.length === 0, ...props }));
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Compact inline battery glyph + percent. Pass `percent`/`charging` (and
|
|
228
|
+
* optionally `noBattery`) to control it, or no data props to let it poll
|
|
229
|
+
* `useMoldablePower` itself.
|
|
230
|
+
*/
|
|
231
|
+
function BatteryGauge({ percent, charging, noBattery, ...props }) {
|
|
232
|
+
if (percent === undefined &&
|
|
233
|
+
charging === undefined &&
|
|
234
|
+
noBattery === undefined) {
|
|
235
|
+
return _jsx(ManagedBatteryGauge, { ...props });
|
|
236
|
+
}
|
|
237
|
+
return (_jsx(BatteryGaugeBase, { percent: percent, charging: charging, noBattery: noBattery, ...props }));
|
|
238
|
+
}
|
|
239
|
+
const POWER_SOURCE_LABEL = {
|
|
240
|
+
ac: 'AC',
|
|
241
|
+
battery: 'Battery',
|
|
242
|
+
unknown: 'Unknown',
|
|
243
|
+
};
|
|
244
|
+
function capitalize(value) {
|
|
245
|
+
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
246
|
+
}
|
|
247
|
+
function formatIdleSeconds(value) {
|
|
248
|
+
const seconds = Math.max(0, Math.floor(value));
|
|
249
|
+
if (seconds < 60)
|
|
250
|
+
return `${seconds}s`;
|
|
251
|
+
if (seconds < 3600)
|
|
252
|
+
return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
253
|
+
return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
|
|
254
|
+
}
|
|
255
|
+
function formatClock(timestamp) {
|
|
256
|
+
return new Date(timestamp).toLocaleTimeString(undefined, { hour12: false });
|
|
257
|
+
}
|
|
258
|
+
function describePowerSessionEvent(event) {
|
|
259
|
+
switch (event.kind) {
|
|
260
|
+
case 'power-source-change':
|
|
261
|
+
return event.powerState.source === 'battery'
|
|
262
|
+
? 'on-battery'
|
|
263
|
+
: event.powerState.source === 'ac'
|
|
264
|
+
? 'on-ac'
|
|
265
|
+
: 'power-source-change';
|
|
266
|
+
case 'thermal-state-change':
|
|
267
|
+
return `thermal-${event.state}`;
|
|
268
|
+
default:
|
|
269
|
+
return event.kind;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Power panel: battery gauge, source/thermal/idle readout, live session event
|
|
274
|
+
* log, and a "keep awake" sleep-blocker switch.
|
|
275
|
+
*/
|
|
276
|
+
function PowerPanel({ className, pollIntervalMs, ...props }) {
|
|
277
|
+
const power = useMoldablePower({ pollIntervalMs });
|
|
278
|
+
const log = useStreamLog(MAX_POWER_EVENTS);
|
|
279
|
+
const appendRef = useRef(log.append);
|
|
280
|
+
appendRef.current = log.append;
|
|
281
|
+
const lastEventIdRef = useRef(0);
|
|
282
|
+
const { events } = power;
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
for (const entry of events) {
|
|
285
|
+
if (entry.id <= lastEventIdRef.current)
|
|
286
|
+
continue;
|
|
287
|
+
lastEventIdRef.current = entry.id;
|
|
288
|
+
appendRef.current({
|
|
289
|
+
id: entry.id,
|
|
290
|
+
timestamp: entry.timestamp,
|
|
291
|
+
direction: 'info',
|
|
292
|
+
data: describePowerSessionEvent(entry.event),
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}, [events]);
|
|
296
|
+
const battery = power.power?.batteries[0] ?? null;
|
|
297
|
+
const noBattery = power.power !== null && power.power.batteries.length === 0;
|
|
298
|
+
const status = power.power !== null || power.thermal !== null
|
|
299
|
+
? 'ready'
|
|
300
|
+
: power.error
|
|
301
|
+
? 'unavailable'
|
|
302
|
+
: 'loading';
|
|
303
|
+
return (_jsxs(NativeCapabilityPanel, { "data-slot": "power-panel", "data-status": status, className: className, ...props, children: [_jsxs(NativeCapabilityPanelHeader, { children: [_jsx(NativeCapabilityPanelIcon, { children: _jsx(BatteryCharging, {}) }), _jsx(NativeCapabilityPanelTitle, { children: "Power" }), _jsx(CapabilityBadge, { capability: "power-monitor" }), _jsx(NativeCapabilityPanelAction, { children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("label", { className: "text-muted-foreground flex items-center gap-2 text-xs font-medium", children: ["Display", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-display-sleep'].active, disabled: power.sleepBlockers['prevent-display-sleep'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-display-sleep'].toggle(), "aria-label": "Keep the display awake" })] }), _jsxs("label", { className: "text-muted-foreground flex items-center gap-2 text-xs font-medium", children: ["App", _jsx(Switch, { size: "sm", checked: power.sleepBlockers['prevent-app-suspension'].active, disabled: power.sleepBlockers['prevent-app-suspension'].busy, onCheckedChange: () => void power.sleepBlockers['prevent-app-suspension'].toggle(), "aria-label": "Keep the app active" })] })] }) })] }), _jsx(NativeCapabilityPanelContent, { children: _jsxs("div", { className: "animate-in fade-in space-y-4 duration-300 motion-reduce:animate-none", children: [_jsx(BatteryGauge, { className: "text-xl font-medium tracking-tight sm:text-2xl", percent: battery?.chargePercent, charging: battery?.state === 'charging', noBattery: noBattery }), _jsxs(Readout, { className: "grid-cols-2 sm:grid-cols-4", children: [_jsx(ReadoutItem, { label: "Source", value: power.power ? POWER_SOURCE_LABEL[power.power.source] : null }), _jsx(ReadoutItem, { label: "State", value: battery ? capitalize(battery.state) : null }), _jsx(ReadoutItem, { label: "Thermal", value: power.thermal ? capitalize(power.thermal) : null }), _jsx(ReadoutItem, { label: "Idle", value: power.idle
|
|
304
|
+
? `${formatIdleSeconds(power.idle.seconds)} · ${power.idle.state}`
|
|
305
|
+
: null })] }), power.error ? (_jsx("p", { className: "text-status-error text-xs", children: power.error.message })) : null, _jsxs("div", { className: "space-y-1.5", children: [_jsx("div", { className: "text-muted-foreground text-[10px] font-medium uppercase tracking-wider", children: "Session events" }), _jsx(StreamLog, { entries: log.entries, maxHeight: 160, emptyLabel: "No session events yet" })] })] }) }), _jsxs(NativeCapabilityPanelFooter, { children: [_jsx("span", { className: "truncate font-mono tabular-nums", children: power.updatedAt
|
|
306
|
+
? `Updated ${formatClock(power.updatedAt)}`
|
|
307
|
+
: 'Waiting for first reading' }), _jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "Refresh power state", className: "ml-auto", onClick: power.refresh, children: _jsx(RefreshCw, {}) }), _jsx(Button, { variant: "ghost", size: "xs", className: "gap-1", disabled: BLOCKER_TYPES.some((type) => power.sleepBlockers[type].busy), onClick: () => void Promise.all(BLOCKER_TYPES.map((type) => power.sleepBlockers[type].check())), children: "Check blockers" })] })] }));
|
|
308
|
+
}
|
|
309
|
+
export { PowerPanel, BatteryGauge };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
declare function Readout({ className, ...props }: React.ComponentProps<'div'>): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export interface ReadoutItemProps extends React.ComponentProps<'div'> {
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
value?: React.ReactNode;
|
|
6
|
+
unit?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
declare function ReadoutItem({ label, value, unit, className, children, ...props }: ReadoutItemProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export { Readout, ReadoutItem };
|
|
10
|
+
//# sourceMappingURL=readout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readout.d.ts","sourceRoot":"","sources":["../../../src/components/native-capabilities/readout.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,iBAAS,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,2CAWpE;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;IACnE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACvB;AAED,iBAAS,WAAW,CAAC,EACnB,KAAK,EACL,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,gBAAgB,2CA6BlB;AAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
function Readout({ className, ...props }) {
|
|
5
|
+
return (_jsx("div", { "data-slot": "readout", className: cn('grid grid-cols-2 gap-x-6 gap-y-4 sm:grid-cols-3', className), ...props }));
|
|
6
|
+
}
|
|
7
|
+
function ReadoutItem({ label, value, unit, className, children, ...props }) {
|
|
8
|
+
const content = children ?? value;
|
|
9
|
+
return (_jsxs("div", { "data-slot": "readout-item", className: cn('min-w-0', className), ...props, children: [_jsx("div", { "data-slot": "readout-label", className: "text-muted-foreground text-[10px] font-medium uppercase tracking-wider", children: label }), _jsxs("div", { "data-slot": "readout-value", className: "mt-1 truncate font-mono text-sm tabular-nums", children: [content === null || content === undefined ? (_jsx("span", { className: "text-muted-foreground/60", children: "\u2014" })) : (content), unit !== undefined && content !== null && content !== undefined ? (_jsx("span", { className: "text-muted-foreground ml-1 text-xs", children: unit })) : null] })] }));
|
|
10
|
+
}
|
|
11
|
+
export { Readout, ReadoutItem };
|