@moldable-ai/ui 0.2.22 → 0.2.25
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-coverage.d.ts +1 -1
- package/dist/catalog/catalog-manifest.d.ts +1 -1
- package/dist/catalog/catalog-manifest.js +1 -1
- package/dist/catalog/component-catalog.d.ts +1 -1
- package/dist/catalog/component-catalog.js +2 -2
- package/dist/catalog/core-catalog-exclusions.d.ts +1 -1
- package/dist/catalog/core-catalog-exclusions.d.ts.map +1 -1
- package/dist/catalog/core-catalog-exclusions.js +1 -150
- package/dist/catalog/core-catalog.d.ts +1 -1
- package/dist/catalog/core-catalog.d.ts.map +1 -1
- package/dist/catalog/core-catalog.js +11 -7
- package/dist/catalog/core-collection-stories.d.ts +1 -1
- package/dist/catalog/core-collection-stories.d.ts.map +1 -1
- package/dist/catalog/core-collection-stories.js +40 -8
- package/dist/catalog/core-control-stories.d.ts +1 -1
- package/dist/catalog/core-control-stories.d.ts.map +1 -1
- package/dist/catalog/core-control-stories.js +48 -20
- package/dist/catalog/core-feedback-stories.d.ts +1 -1
- package/dist/catalog/core-feedback-stories.d.ts.map +1 -1
- package/dist/catalog/core-feedback-stories.js +89 -10
- package/dist/catalog/core-form-stories.d.ts +3 -0
- package/dist/catalog/core-form-stories.d.ts.map +1 -0
- package/dist/catalog/core-form-stories.js +56 -0
- package/dist/catalog/core-foundation-stories.d.ts +1 -1
- package/dist/catalog/core-foundation-stories.js +7 -7
- package/dist/catalog/core-layout-stories.d.ts +3 -0
- package/dist/catalog/core-layout-stories.d.ts.map +1 -0
- package/dist/catalog/core-layout-stories.js +78 -0
- package/dist/catalog/core-navigation-stories.d.ts +1 -1
- package/dist/catalog/core-navigation-stories.d.ts.map +1 -1
- package/dist/catalog/core-navigation-stories.js +25 -3
- package/dist/catalog/core-overlay-stories.d.ts +1 -1
- package/dist/catalog/core-overlay-stories.d.ts.map +1 -1
- package/dist/catalog/core-overlay-stories.js +113 -8
- package/dist/catalog/index.d.ts +6 -6
- package/dist/catalog/index.js +6 -6
- package/dist/components/app-error-boundary.js +2 -2
- package/dist/components/chat/chat-image-lightbox.js +3 -3
- package/dist/components/chat/chat-input.js +5 -5
- package/dist/components/chat/chat-message.js +17 -17
- package/dist/components/chat/chat-messages.d.ts +1 -1
- package/dist/components/chat/chat-messages.js +3 -3
- package/dist/components/chat/chat-panel.d.ts +6 -6
- package/dist/components/chat/chat-panel.d.ts.map +1 -1
- package/dist/components/chat/chat-panel.js +33 -33
- package/dist/components/chat/checkpoint-badge.js +3 -3
- package/dist/components/chat/conversation-history.d.ts.map +1 -1
- package/dist/components/chat/conversation-history.js +13 -13
- package/dist/components/chat/index.d.ts +20 -15
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +20 -15
- package/dist/components/chat/markdown.js +1 -1
- package/dist/components/chat/model-effort-selector.js +10 -10
- package/dist/components/chat/model-selector.js +4 -4
- package/dist/components/chat/reasoning-effort-selector.js +4 -4
- package/dist/components/chat/restore-dialog.js +3 -3
- package/dist/components/chat/thinking-timeline.js +2 -2
- package/dist/components/chat/tool-approval.d.ts +1 -1
- package/dist/components/chat/tool-approval.d.ts.map +1 -1
- package/dist/components/chat/tool-approval.js +9 -9
- package/dist/components/chat/tool-handlers.d.ts +2 -2
- package/dist/components/chat/tool-handlers.js +90 -90
- package/dist/components/chat/voice-orb-audio.d.ts +16 -0
- package/dist/components/chat/voice-orb-audio.d.ts.map +1 -0
- package/dist/components/chat/voice-orb-audio.js +110 -0
- package/dist/components/chat/voice-orb-renderer.d.ts +51 -0
- package/dist/components/chat/voice-orb-renderer.d.ts.map +1 -0
- package/dist/components/chat/voice-orb-renderer.js +410 -0
- package/dist/components/chat/voice-orb-shaders.d.ts +3 -0
- package/dist/components/chat/voice-orb-shaders.d.ts.map +1 -0
- package/dist/components/chat/voice-orb-shaders.js +355 -0
- package/dist/components/chat/voice-orb-types.d.ts +24 -0
- package/dist/components/chat/voice-orb-types.d.ts.map +1 -0
- package/dist/components/chat/voice-orb-types.js +73 -0
- package/dist/components/chat/voice-orb.d.ts +20 -0
- package/dist/components/chat/voice-orb.d.ts.map +1 -0
- package/dist/components/chat/voice-orb.js +67 -0
- package/dist/components/code-block.js +1 -1
- package/dist/components/hardware/bluetooth-panel.d.ts +2 -2
- package/dist/components/hardware/bluetooth-panel.js +10 -10
- package/dist/components/hardware/camera-preview.js +6 -6
- package/dist/components/hardware/capability-badge.d.ts +2 -2
- package/dist/components/hardware/capability-badge.js +2 -2
- package/dist/components/hardware/capability-matrix.d.ts +1 -1
- package/dist/components/hardware/capability-matrix.js +5 -5
- package/dist/components/hardware/clipboard-button.d.ts +1 -1
- package/dist/components/hardware/clipboard-button.js +2 -2
- package/dist/components/hardware/device-list.js +1 -1
- package/dist/components/hardware/display-map.d.ts +1 -1
- package/dist/components/hardware/display-map.js +7 -7
- package/dist/components/hardware/haptic-button.d.ts +2 -2
- package/dist/components/hardware/haptic-button.js +3 -3
- package/dist/components/hardware/hardware-panel.js +1 -1
- package/dist/components/hardware/hid-panel.d.ts +2 -2
- package/dist/components/hardware/hid-panel.js +10 -10
- package/dist/components/hardware/index.d.ts +26 -26
- package/dist/components/hardware/index.js +26 -26
- package/dist/components/hardware/live-indicator.js +1 -1
- package/dist/components/hardware/local-auth-button.d.ts +2 -2
- package/dist/components/hardware/local-auth-button.js +4 -4
- package/dist/components/hardware/location-panel.d.ts +1 -1
- package/dist/components/hardware/location-panel.js +6 -6
- package/dist/components/hardware/microphone-meter.js +7 -7
- package/dist/components/hardware/midi-monitor.d.ts +2 -2
- package/dist/components/hardware/midi-monitor.js +9 -9
- package/dist/components/hardware/notification-panel.d.ts +1 -1
- package/dist/components/hardware/notification-panel.js +8 -8
- package/dist/components/hardware/power-blocker-controller.d.ts +1 -1
- package/dist/components/hardware/power-blocker-controller.js +1 -1
- package/dist/components/hardware/power-panel.d.ts +1 -1
- package/dist/components/hardware/power-panel.js +9 -9
- package/dist/components/hardware/readout.js +1 -1
- package/dist/components/hardware/screen-share-preview.js +5 -5
- package/dist/components/hardware/secure-storage-panel.d.ts +1 -1
- package/dist/components/hardware/secure-storage-panel.js +9 -9
- package/dist/components/hardware/serial-console.d.ts +2 -2
- package/dist/components/hardware/serial-console.js +10 -10
- package/dist/components/hardware/shortcut-recorder.d.ts +1 -1
- package/dist/components/hardware/shortcut-recorder.js +4 -4
- package/dist/components/hardware/stream-log.js +1 -1
- package/dist/components/hardware/system-audio-monitor.d.ts +1 -1
- package/dist/components/hardware/system-audio-monitor.js +9 -9
- package/dist/components/hardware/usb-panel.d.ts +5 -5
- package/dist/components/hardware/usb-panel.js +10 -10
- package/dist/components/hardware/use-capability.d.ts +1 -1
- package/dist/components/hardware/use-capability.js +1 -1
- package/dist/components/markdown.js +5 -5
- package/dist/components/native-capabilities/bluetooth-panel.d.ts +2 -2
- package/dist/components/native-capabilities/bluetooth-panel.d.ts.map +1 -1
- package/dist/components/native-capabilities/bluetooth-panel.js +17 -17
- package/dist/components/native-capabilities/camera-preview.d.ts.map +1 -1
- package/dist/components/native-capabilities/camera-preview.js +7 -7
- package/dist/components/native-capabilities/capability-badge.d.ts +2 -2
- package/dist/components/native-capabilities/capability-badge.js +4 -4
- package/dist/components/native-capabilities/capability-matrix.d.ts +1 -1
- package/dist/components/native-capabilities/capability-matrix.js +7 -7
- package/dist/components/native-capabilities/clipboard-button.d.ts +1 -1
- package/dist/components/native-capabilities/clipboard-button.js +2 -2
- package/dist/components/native-capabilities/device-list.js +4 -4
- package/dist/components/native-capabilities/display-map.d.ts +1 -1
- package/dist/components/native-capabilities/display-map.d.ts.map +1 -1
- package/dist/components/native-capabilities/display-map.js +11 -11
- package/dist/components/native-capabilities/haptic-button.d.ts +2 -2
- package/dist/components/native-capabilities/haptic-button.js +3 -3
- package/dist/components/native-capabilities/hid-panel.d.ts +2 -2
- package/dist/components/native-capabilities/hid-panel.d.ts.map +1 -1
- package/dist/components/native-capabilities/hid-panel.js +14 -14
- package/dist/components/native-capabilities/index.d.ts +26 -26
- package/dist/components/native-capabilities/index.js +26 -26
- package/dist/components/native-capabilities/live-indicator.js +3 -3
- package/dist/components/native-capabilities/local-auth-button.d.ts +2 -2
- package/dist/components/native-capabilities/local-auth-button.js +4 -4
- package/dist/components/native-capabilities/location-panel.d.ts +1 -1
- package/dist/components/native-capabilities/location-panel.d.ts.map +1 -1
- package/dist/components/native-capabilities/location-panel.js +8 -8
- package/dist/components/native-capabilities/microphone-meter.js +9 -9
- package/dist/components/native-capabilities/midi-monitor.d.ts +2 -2
- package/dist/components/native-capabilities/midi-monitor.d.ts.map +1 -1
- package/dist/components/native-capabilities/midi-monitor.js +11 -11
- package/dist/components/native-capabilities/native-capability-panel.js +6 -6
- package/dist/components/native-capabilities/notification-panel.d.ts +1 -1
- package/dist/components/native-capabilities/notification-panel.js +9 -9
- package/dist/components/native-capabilities/power-blocker-controller.d.ts +1 -1
- package/dist/components/native-capabilities/power-blocker-controller.js +1 -1
- package/dist/components/native-capabilities/power-panel.d.ts +1 -1
- package/dist/components/native-capabilities/power-panel.d.ts.map +1 -1
- package/dist/components/native-capabilities/power-panel.js +12 -12
- package/dist/components/native-capabilities/readout.d.ts.map +1 -1
- package/dist/components/native-capabilities/readout.js +2 -2
- package/dist/components/native-capabilities/screen-share-preview.js +6 -6
- package/dist/components/native-capabilities/secure-storage-panel.d.ts +1 -1
- package/dist/components/native-capabilities/secure-storage-panel.d.ts.map +1 -1
- package/dist/components/native-capabilities/secure-storage-panel.js +11 -11
- package/dist/components/native-capabilities/serial-console.d.ts +2 -2
- package/dist/components/native-capabilities/serial-console.d.ts.map +1 -1
- package/dist/components/native-capabilities/serial-console.js +11 -11
- package/dist/components/native-capabilities/shortcut-recorder.d.ts +1 -1
- package/dist/components/native-capabilities/shortcut-recorder.js +5 -5
- package/dist/components/native-capabilities/stream-log.js +3 -3
- package/dist/components/native-capabilities/system-audio-monitor.d.ts +1 -1
- package/dist/components/native-capabilities/system-audio-monitor.js +12 -12
- package/dist/components/native-capabilities/usb-panel.d.ts +5 -5
- package/dist/components/native-capabilities/usb-panel.js +15 -15
- package/dist/components/native-capabilities/use-capability.d.ts +1 -1
- package/dist/components/native-capabilities/use-capability.js +1 -1
- package/dist/components/rich-media-player.js +3 -3
- package/dist/components/ui/accordion.js +3 -3
- package/dist/components/ui/alert-dialog.d.ts +2 -2
- package/dist/components/ui/alert-dialog.d.ts.map +1 -1
- package/dist/components/ui/alert-dialog.js +16 -10
- package/dist/components/ui/alert.d.ts +1 -1
- package/dist/components/ui/alert.d.ts.map +1 -1
- package/dist/components/ui/alert.js +11 -11
- package/dist/components/ui/app-frame.d.ts +7 -1
- package/dist/components/ui/app-frame.d.ts.map +1 -1
- package/dist/components/ui/app-frame.js +52 -16
- package/dist/components/ui/avatar.js +5 -5
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.js +4 -4
- package/dist/components/ui/breadcrumb.js +2 -2
- package/dist/components/ui/button-group.d.ts +1 -1
- package/dist/components/ui/button-group.js +4 -4
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +16 -16
- package/dist/components/ui/calendar.d.ts +1 -1
- package/dist/components/ui/calendar.d.ts.map +1 -1
- package/dist/components/ui/calendar.js +15 -15
- package/dist/components/ui/card.js +3 -3
- package/dist/components/ui/carousel.d.ts +1 -1
- package/dist/components/ui/carousel.js +4 -4
- package/dist/components/ui/chart.js +5 -5
- package/dist/components/ui/checkbox.d.ts.map +1 -1
- package/dist/components/ui/checkbox.js +2 -2
- package/dist/components/ui/collapsible.js +3 -3
- package/dist/components/ui/color-well.js +2 -2
- package/dist/components/ui/combobox.js +9 -9
- package/dist/components/ui/command.d.ts +1 -1
- package/dist/components/ui/command.d.ts.map +1 -1
- package/dist/components/ui/command.js +9 -9
- package/dist/components/ui/confirm-dialog.d.ts +1 -1
- package/dist/components/ui/confirm-dialog.js +2 -2
- package/dist/components/ui/context-menu.d.ts +16 -5
- package/dist/components/ui/context-menu.d.ts.map +1 -1
- package/dist/components/ui/context-menu.js +92 -16
- package/dist/components/ui/date-field.d.ts.map +1 -1
- package/dist/components/ui/date-field.js +8 -8
- package/dist/components/ui/date-picker.d.ts +2 -2
- package/dist/components/ui/date-picker.js +7 -7
- package/dist/components/ui/dialog.d.ts +2 -2
- package/dist/components/ui/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog.js +16 -8
- package/dist/components/ui/drawer.js +4 -4
- package/dist/components/ui/dropdown-menu.d.ts +15 -5
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu.js +98 -16
- package/dist/components/ui/edge-fade.js +1 -1
- package/dist/components/ui/empty.d.ts +1 -1
- package/dist/components/ui/empty.js +5 -5
- package/dist/components/ui/error-boundary-view.d.ts.map +1 -1
- package/dist/components/ui/error-boundary-view.js +3 -3
- package/dist/components/ui/field.d.ts +1 -1
- package/dist/components/ui/field.d.ts.map +1 -1
- package/dist/components/ui/field.js +9 -9
- package/dist/components/ui/form.js +4 -4
- package/dist/components/ui/grid.d.ts.map +1 -1
- package/dist/components/ui/grid.js +5 -5
- package/dist/components/ui/hover-card.js +2 -2
- package/dist/components/ui/icon-button.d.ts +1 -1
- package/dist/components/ui/icon-button.js +3 -3
- package/dist/components/ui/index.d.ts +77 -77
- package/dist/components/ui/index.js +77 -77
- package/dist/components/ui/input-group.d.ts +2 -2
- package/dist/components/ui/input-group.js +14 -14
- package/dist/components/ui/input-otp.js +3 -3
- package/dist/components/ui/input.js +2 -2
- package/dist/components/ui/inspector.d.ts +1 -1
- package/dist/components/ui/inspector.js +6 -6
- package/dist/components/ui/item.d.ts +1 -1
- package/dist/components/ui/item.js +7 -7
- package/dist/components/ui/kbd.js +2 -2
- package/dist/components/ui/label.js +2 -2
- package/dist/components/ui/list.d.ts.map +1 -1
- package/dist/components/ui/list.js +5 -5
- package/dist/components/ui/material.js +3 -3
- package/dist/components/ui/menu-items.d.ts +28 -0
- package/dist/components/ui/menu-items.d.ts.map +1 -0
- package/dist/components/ui/menu-items.js +111 -0
- package/dist/components/ui/menubar.js +11 -11
- package/dist/components/ui/message-scroller-controller.d.ts +1 -1
- package/dist/components/ui/message-scroller-controller.js +1 -1
- package/dist/components/ui/message-scroller-primitive.d.ts +1 -1
- package/dist/components/ui/message-scroller-primitive.js +1 -1
- package/dist/components/ui/message-scroller.d.ts +2 -2
- package/dist/components/ui/message-scroller.js +3 -3
- package/dist/components/ui/navigation-button-group.d.ts +2 -2
- package/dist/components/ui/navigation-button-group.js +2 -2
- package/dist/components/ui/navigation-menu.js +6 -6
- package/dist/components/ui/notification-dot.js +2 -2
- package/dist/components/ui/number-input.js +8 -8
- package/dist/components/ui/pagination.d.ts +1 -1
- package/dist/components/ui/pagination.js +2 -2
- package/dist/components/ui/panel.d.ts +1 -1
- package/dist/components/ui/panel.js +3 -3
- package/dist/components/ui/popover.d.ts +1 -1
- package/dist/components/ui/popover.js +3 -3
- package/dist/components/ui/progress.js +2 -2
- package/dist/components/ui/radio-group.d.ts.map +1 -1
- package/dist/components/ui/radio-group.js +2 -2
- package/dist/components/ui/resizable.d.ts +1 -1
- package/dist/components/ui/resizable.d.ts.map +1 -1
- package/dist/components/ui/resizable.js +15 -4
- package/dist/components/ui/scroll-area.d.ts.map +1 -1
- package/dist/components/ui/scroll-area.js +3 -3
- package/dist/components/ui/search-field.js +7 -7
- package/dist/components/ui/segmented-control.js +9 -9
- package/dist/components/ui/select.d.ts.map +1 -1
- package/dist/components/ui/select.js +6 -6
- package/dist/components/ui/separator.js +1 -1
- package/dist/components/ui/sheet.js +4 -4
- package/dist/components/ui/sidebar.d.ts +5 -5
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +111 -24
- package/dist/components/ui/skeleton.js +2 -2
- package/dist/components/ui/slider.d.ts +3 -1
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/slider.js +3 -3
- package/dist/components/ui/sonner.js +1 -1
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/split-view.js +1 -1
- package/dist/components/ui/status.d.ts +1 -1
- package/dist/components/ui/status.d.ts.map +1 -1
- package/dist/components/ui/status.js +10 -9
- package/dist/components/ui/switch.js +2 -2
- package/dist/components/ui/table.d.ts.map +1 -1
- package/dist/components/ui/table.js +7 -7
- package/dist/components/ui/tabs.js +3 -3
- package/dist/components/ui/text.d.ts +2 -2
- package/dist/components/ui/text.js +19 -19
- package/dist/components/ui/textarea.js +2 -2
- package/dist/components/ui/toggle-group.d.ts +1 -1
- package/dist/components/ui/toggle-group.js +4 -4
- package/dist/components/ui/toggle.d.ts +1 -1
- package/dist/components/ui/toggle.js +10 -10
- package/dist/components/ui/toolbar.d.ts +7 -7
- package/dist/components/ui/toolbar.js +7 -7
- package/dist/components/ui/tooltip.d.ts +2 -2
- package/dist/components/ui/tooltip.js +5 -5
- package/dist/index.d.ts +21 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -20
- package/dist/lib/frame-lifecycle.d.ts +27 -0
- package/dist/lib/frame-lifecycle.d.ts.map +1 -1
- package/dist/lib/frame-lifecycle.js +136 -0
- package/dist/lib/host-date-time-picker.d.ts +1 -1
- package/dist/lib/host-date-time-picker.js +1 -1
- package/dist/lib/host-file-dialog.d.ts +1 -1
- package/dist/lib/host-file-dialog.js +1 -1
- package/dist/lib/host-native-menu.d.ts +48 -7
- package/dist/lib/host-native-menu.d.ts.map +1 -1
- package/dist/lib/host-native-menu.js +56 -1
- package/dist/lib/host-services.js +1 -1
- package/dist/lib/host-share.d.ts +1 -1
- package/dist/lib/host-share.js +1 -1
- package/dist/lib/host-web-surface.d.ts +31 -0
- package/dist/lib/host-web-surface.d.ts.map +1 -0
- package/dist/lib/host-web-surface.js +116 -0
- package/dist/lib/native-capabilities/access.d.ts +2 -2
- package/dist/lib/native-capabilities/access.js +2 -2
- package/dist/lib/native-capabilities/bluetooth-access.d.ts +1 -1
- package/dist/lib/native-capabilities/bluetooth-access.js +2 -2
- package/dist/lib/native-capabilities/bluetooth-connection.d.ts +1 -1
- package/dist/lib/native-capabilities/bluetooth-connection.js +1 -1
- package/dist/lib/native-capabilities/bluetooth-gatt.d.ts +1 -1
- package/dist/lib/native-capabilities/bluetooth-gatt.js +1 -1
- package/dist/lib/native-capabilities/bluetooth-internal.d.ts +2 -2
- package/dist/lib/native-capabilities/bluetooth-internal.js +1 -1
- package/dist/lib/native-capabilities/bluetooth-native-fallback.d.ts +2 -2
- package/dist/lib/native-capabilities/bluetooth-native-fallback.js +2 -2
- package/dist/lib/native-capabilities/bluetooth.d.ts +6 -6
- package/dist/lib/native-capabilities/bluetooth.js +4 -4
- package/dist/lib/native-capabilities/bridge.d.ts +1 -1
- package/dist/lib/native-capabilities/bridge.js +2 -2
- package/dist/lib/native-capabilities/capabilities.d.ts +1 -1
- package/dist/lib/native-capabilities/capabilities.js +1 -1
- package/dist/lib/native-capabilities/clipboard.js +2 -2
- package/dist/lib/native-capabilities/device-io-errors.d.ts +1 -1
- package/dist/lib/native-capabilities/device-io-errors.js +1 -1
- package/dist/lib/native-capabilities/displays.d.ts +1 -1
- package/dist/lib/native-capabilities/displays.js +1 -1
- package/dist/lib/native-capabilities/global-shortcuts.d.ts +2 -2
- package/dist/lib/native-capabilities/global-shortcuts.js +1 -1
- package/dist/lib/native-capabilities/haptics.d.ts +1 -1
- package/dist/lib/native-capabilities/haptics.js +1 -1
- package/dist/lib/native-capabilities/hid-native.d.ts +2 -2
- package/dist/lib/native-capabilities/hid-native.js +3 -3
- package/dist/lib/native-capabilities/hid.js +5 -5
- package/dist/lib/native-capabilities/index.d.ts +39 -39
- package/dist/lib/native-capabilities/index.js +21 -21
- package/dist/lib/native-capabilities/local-authentication.d.ts +1 -1
- package/dist/lib/native-capabilities/local-authentication.js +1 -1
- package/dist/lib/native-capabilities/location.js +1 -1
- package/dist/lib/native-capabilities/media-permissions.d.ts +1 -1
- package/dist/lib/native-capabilities/media-permissions.js +1 -1
- package/dist/lib/native-capabilities/media.d.ts +1 -1
- package/dist/lib/native-capabilities/media.js +2 -2
- package/dist/lib/native-capabilities/midi-access.d.ts +1 -1
- package/dist/lib/native-capabilities/midi-access.js +3 -3
- package/dist/lib/native-capabilities/midi-internal.d.ts +1 -1
- package/dist/lib/native-capabilities/midi-internal.js +1 -1
- package/dist/lib/native-capabilities/midi-native-fallback.d.ts +1 -1
- package/dist/lib/native-capabilities/midi-native-fallback.js +2 -2
- package/dist/lib/native-capabilities/midi-ports.d.ts +1 -1
- package/dist/lib/native-capabilities/midi-ports.js +1 -1
- package/dist/lib/native-capabilities/midi.d.ts +5 -5
- package/dist/lib/native-capabilities/midi.js +3 -3
- package/dist/lib/native-capabilities/native-device-io.d.ts +1 -1
- package/dist/lib/native-capabilities/native-device-io.js +1 -1
- package/dist/lib/native-capabilities/native-device-lifecycle.js +1 -1
- package/dist/lib/native-capabilities/notifications.d.ts +2 -2
- package/dist/lib/native-capabilities/notifications.js +1 -1
- package/dist/lib/native-capabilities/power-session.d.ts +2 -2
- package/dist/lib/native-capabilities/power-session.js +1 -1
- package/dist/lib/native-capabilities/secure-storage.d.ts +1 -1
- package/dist/lib/native-capabilities/secure-storage.js +1 -1
- package/dist/lib/native-capabilities/serial-native.d.ts +2 -2
- package/dist/lib/native-capabilities/serial-native.js +3 -3
- package/dist/lib/native-capabilities/serial.js +5 -5
- package/dist/lib/native-capabilities/system-audio.d.ts +1 -1
- package/dist/lib/native-capabilities/system-audio.js +1 -1
- package/dist/lib/native-capabilities/usb-native.d.ts +2 -2
- package/dist/lib/native-capabilities/usb-native.js +3 -3
- package/dist/lib/native-capabilities/usb.js +5 -5
- package/dist/lib/native-hardware/bluetooth-access.d.ts +1 -1
- package/dist/lib/native-hardware/bluetooth-access.js +1 -1
- package/dist/lib/native-hardware/bluetooth-connection.d.ts +1 -1
- package/dist/lib/native-hardware/bluetooth-connection.js +1 -1
- package/dist/lib/native-hardware/bluetooth-gatt.d.ts +1 -1
- package/dist/lib/native-hardware/bluetooth-gatt.js +1 -1
- package/dist/lib/native-hardware/bluetooth-internal.d.ts +2 -2
- package/dist/lib/native-hardware/bluetooth-internal.js +1 -1
- package/dist/lib/native-hardware/bluetooth-native-fallback.d.ts +2 -2
- package/dist/lib/native-hardware/bluetooth-native-fallback.js +2 -2
- package/dist/lib/native-hardware/bluetooth.d.ts +6 -6
- package/dist/lib/native-hardware/bluetooth.js +4 -4
- package/dist/lib/native-hardware/bridge.d.ts +1 -1
- package/dist/lib/native-hardware/bridge.js +2 -2
- package/dist/lib/native-hardware/capabilities.d.ts +1 -1
- package/dist/lib/native-hardware/capabilities.js +1 -1
- package/dist/lib/native-hardware/clipboard.js +1 -1
- package/dist/lib/native-hardware/device-io-errors.d.ts +1 -1
- package/dist/lib/native-hardware/device-io-errors.js +1 -1
- package/dist/lib/native-hardware/displays.d.ts +1 -1
- package/dist/lib/native-hardware/displays.js +1 -1
- package/dist/lib/native-hardware/global-shortcuts.d.ts +2 -2
- package/dist/lib/native-hardware/global-shortcuts.js +1 -1
- package/dist/lib/native-hardware/haptics.d.ts +1 -1
- package/dist/lib/native-hardware/haptics.js +1 -1
- package/dist/lib/native-hardware/hid-native.d.ts +2 -2
- package/dist/lib/native-hardware/hid-native.js +3 -3
- package/dist/lib/native-hardware/hid.js +4 -4
- package/dist/lib/native-hardware/index.d.ts +37 -37
- package/dist/lib/native-hardware/index.js +20 -20
- package/dist/lib/native-hardware/local-authentication.d.ts +1 -1
- package/dist/lib/native-hardware/local-authentication.js +1 -1
- package/dist/lib/native-hardware/location.js +1 -1
- package/dist/lib/native-hardware/media-permissions.d.ts +1 -1
- package/dist/lib/native-hardware/media-permissions.js +1 -1
- package/dist/lib/native-hardware/media.d.ts +1 -1
- package/dist/lib/native-hardware/media.js +1 -1
- package/dist/lib/native-hardware/midi-access.d.ts +1 -1
- package/dist/lib/native-hardware/midi-access.js +2 -2
- package/dist/lib/native-hardware/midi-internal.d.ts +1 -1
- package/dist/lib/native-hardware/midi-internal.js +1 -1
- package/dist/lib/native-hardware/midi-native-fallback.d.ts +1 -1
- package/dist/lib/native-hardware/midi-native-fallback.js +2 -2
- package/dist/lib/native-hardware/midi-ports.d.ts +1 -1
- package/dist/lib/native-hardware/midi-ports.js +1 -1
- package/dist/lib/native-hardware/midi.d.ts +5 -5
- package/dist/lib/native-hardware/midi.js +3 -3
- package/dist/lib/native-hardware/native-device-io.d.ts +1 -1
- package/dist/lib/native-hardware/native-device-io.js +1 -1
- package/dist/lib/native-hardware/native-device-lifecycle.js +1 -1
- package/dist/lib/native-hardware/notifications.d.ts +2 -2
- package/dist/lib/native-hardware/notifications.js +1 -1
- package/dist/lib/native-hardware/power-session.d.ts +2 -2
- package/dist/lib/native-hardware/power-session.js +1 -1
- package/dist/lib/native-hardware/secure-storage.d.ts +1 -1
- package/dist/lib/native-hardware/secure-storage.js +1 -1
- package/dist/lib/native-hardware/serial-native.d.ts +2 -2
- package/dist/lib/native-hardware/serial-native.js +3 -3
- package/dist/lib/native-hardware/serial.js +4 -4
- package/dist/lib/native-hardware/system-audio.d.ts +1 -1
- package/dist/lib/native-hardware/system-audio.js +1 -1
- package/dist/lib/native-hardware/usb-native.d.ts +2 -2
- package/dist/lib/native-hardware/usb-native.js +3 -3
- package/dist/lib/native-hardware/usb.js +4 -4
- package/dist/lib/theme.js +1 -1
- package/docs/design-tokens.md +28 -6
- package/docs/foundations.md +4 -2
- package/package.json +4 -2
- package/src/components/ui/confirm-dialog.md +97 -0
- package/src/components/ui/context-menu.md +158 -0
- package/src/components/ui/dropdown-menu.md +165 -0
- package/src/components/ui/hover-card.md +90 -0
- package/src/components/ui/select.md +111 -0
- package/src/lib/host-date-time-picker.md +29 -0
- package/src/lib/host-file-dialog.md +76 -0
- package/src/lib/host-native-menu.md +67 -0
- package/src/lib/host-share.md +36 -0
- package/src/lib/host-web-surface.md +66 -0
- package/src/styles/index.css +141 -68
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type VoiceOrbAudioLevels } from './voice-orb-types.js';
|
|
2
|
+
export declare function summarizeVoiceOrbSpectrum(spectrum: Float32Array): VoiceOrbAudioLevels;
|
|
3
|
+
export declare class VoiceOrbStreamAnalyser {
|
|
4
|
+
private readonly publish;
|
|
5
|
+
private analyser;
|
|
6
|
+
private context;
|
|
7
|
+
private source;
|
|
8
|
+
private spectrum;
|
|
9
|
+
private stream;
|
|
10
|
+
private timer;
|
|
11
|
+
constructor(publish: (levels: VoiceOrbAudioLevels) => void);
|
|
12
|
+
setStream(stream: MediaStream | null): void;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
private readonly sample;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=voice-orb-audio.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-orb-audio.d.ts","sourceRoot":"","sources":["../../../src/components/chat/voice-orb-audio.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAA;AAoC1B,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,YAAY,GACrB,mBAAmB,CAiBrB;AAED,qBAAa,sBAAsB;IAS/B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAR1B,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,KAAK,CAA8C;gBAGxC,OAAO,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI;IAGjE,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI;IA8C3C,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,QAAQ,CAAC,MAAM,CAItB;CACF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { silentVoiceOrbAudioLevels, } from './voice-orb-types.js';
|
|
2
|
+
const BAND_END_BINS = [9, 96, 400];
|
|
3
|
+
const BAND_GAINS = [10, 1, 1];
|
|
4
|
+
const SAMPLE_INTERVAL_MS = 1_000 / 30;
|
|
5
|
+
function clamp(value, minimum, maximum) {
|
|
6
|
+
return Math.max(minimum, Math.min(maximum, value));
|
|
7
|
+
}
|
|
8
|
+
function medianBandEnergy(spectrum, start, end) {
|
|
9
|
+
const values = [];
|
|
10
|
+
const boundedEnd = Math.min(end, spectrum.length);
|
|
11
|
+
for (let index = start; index < boundedEnd; index += 1) {
|
|
12
|
+
const decibels = clamp(spectrum[index] ?? -100, -100, -10);
|
|
13
|
+
values.push(Math.sqrt(1 - Math.abs(decibels) / 100));
|
|
14
|
+
}
|
|
15
|
+
if (values.length === 0)
|
|
16
|
+
return 0;
|
|
17
|
+
values.sort((left, right) => left - right);
|
|
18
|
+
const middle = Math.floor(values.length / 2);
|
|
19
|
+
if (values.length % 2 === 0) {
|
|
20
|
+
return ((values[middle - 1] ?? 0) + (values[middle] ?? 0)) / 2;
|
|
21
|
+
}
|
|
22
|
+
return values[middle] ?? 0;
|
|
23
|
+
}
|
|
24
|
+
function compressEnergy(value) {
|
|
25
|
+
return value / (value + 1);
|
|
26
|
+
}
|
|
27
|
+
export function summarizeVoiceOrbSpectrum(spectrum) {
|
|
28
|
+
const bands = [0, 0, 0];
|
|
29
|
+
let start = 0;
|
|
30
|
+
for (let index = 0; index < BAND_END_BINS.length; index += 1) {
|
|
31
|
+
const end = BAND_END_BINS[index];
|
|
32
|
+
const gain = BAND_GAINS[index];
|
|
33
|
+
bands[index] = compressEnergy(medianBandEnergy(spectrum, start, end) * gain);
|
|
34
|
+
start = end;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
low: bands[0] ?? 0,
|
|
38
|
+
mid: bands[1] ?? 0,
|
|
39
|
+
high: bands[2] ?? 0,
|
|
40
|
+
overall: compressEnergy(medianBandEnergy(spectrum, 0, 400)),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export class VoiceOrbStreamAnalyser {
|
|
44
|
+
publish;
|
|
45
|
+
analyser = null;
|
|
46
|
+
context = null;
|
|
47
|
+
source = null;
|
|
48
|
+
spectrum = new Float32Array();
|
|
49
|
+
stream = null;
|
|
50
|
+
timer = null;
|
|
51
|
+
constructor(publish) {
|
|
52
|
+
this.publish = publish;
|
|
53
|
+
}
|
|
54
|
+
setStream(stream) {
|
|
55
|
+
if (this.stream === stream) {
|
|
56
|
+
void this.context?.resume().catch(() => undefined);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.source?.disconnect();
|
|
60
|
+
this.source = null;
|
|
61
|
+
const hadStream = this.stream !== null;
|
|
62
|
+
this.stream = stream;
|
|
63
|
+
if (!stream || typeof AudioContext === 'undefined') {
|
|
64
|
+
if (this.timer)
|
|
65
|
+
clearInterval(this.timer);
|
|
66
|
+
this.timer = null;
|
|
67
|
+
if (hadStream)
|
|
68
|
+
this.publish(silentVoiceOrbAudioLevels);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const context = this.context ?? new AudioContext();
|
|
73
|
+
const analyser = this.analyser ?? context.createAnalyser();
|
|
74
|
+
if (!this.analyser) {
|
|
75
|
+
analyser.fftSize = 2_048;
|
|
76
|
+
analyser.minDecibels = -100;
|
|
77
|
+
analyser.maxDecibels = -10;
|
|
78
|
+
analyser.smoothingTimeConstant = 0.86;
|
|
79
|
+
this.analyser = analyser;
|
|
80
|
+
this.spectrum = new Float32Array(analyser.frequencyBinCount);
|
|
81
|
+
}
|
|
82
|
+
this.context = context;
|
|
83
|
+
const source = context.createMediaStreamSource(stream);
|
|
84
|
+
source.connect(analyser);
|
|
85
|
+
this.source = source;
|
|
86
|
+
void context.resume().catch(() => undefined);
|
|
87
|
+
this.timer ??= setInterval(() => this.sample(), SAMPLE_INTERVAL_MS);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
this.stream = null;
|
|
91
|
+
if (this.timer)
|
|
92
|
+
clearInterval(this.timer);
|
|
93
|
+
this.timer = null;
|
|
94
|
+
this.publish(silentVoiceOrbAudioLevels);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
dispose() {
|
|
98
|
+
this.setStream(null);
|
|
99
|
+
void this.context?.close().catch(() => undefined);
|
|
100
|
+
this.context = null;
|
|
101
|
+
this.analyser = null;
|
|
102
|
+
this.spectrum = new Float32Array();
|
|
103
|
+
}
|
|
104
|
+
sample = () => {
|
|
105
|
+
if (!this.analyser || !this.stream)
|
|
106
|
+
return;
|
|
107
|
+
this.analyser.getFloatFrequencyData(this.spectrum);
|
|
108
|
+
this.publish(summarizeVoiceOrbSpectrum(this.spectrum));
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type VoiceOrbAudioLevels, type VoiceOrbState, type VoiceOrbStateTargets } from './voice-orb-types.js';
|
|
2
|
+
export declare function stepVoiceOrbState(current: VoiceOrbStateTargets, state: VoiceOrbState, deltaSeconds: number, immediate?: boolean): VoiceOrbStateTargets;
|
|
3
|
+
export declare function stepVoiceOrbEnergyEnvelopes(micLevel: number, outputLevel: number, levels: VoiceOrbAudioLevels, deltaSeconds: number): {
|
|
4
|
+
micLevel: number;
|
|
5
|
+
outputLevel: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function getVoiceOrbPreviewAudio(state: VoiceOrbState, previewAudioLevel: number, live: boolean, time: number): Float32Array;
|
|
8
|
+
export declare class VoiceOrbRenderer {
|
|
9
|
+
private readonly canvas;
|
|
10
|
+
private animationFrame;
|
|
11
|
+
private audio;
|
|
12
|
+
private audioLevels;
|
|
13
|
+
private buffer;
|
|
14
|
+
private canvasContext;
|
|
15
|
+
private cumulativeAudio;
|
|
16
|
+
private gl;
|
|
17
|
+
private hasAudioInput;
|
|
18
|
+
private hasStateInput;
|
|
19
|
+
private lastFrameTime;
|
|
20
|
+
private micLevel;
|
|
21
|
+
private outputLevel;
|
|
22
|
+
private previewAudioLevel;
|
|
23
|
+
private previewTimeMs;
|
|
24
|
+
private program;
|
|
25
|
+
private reducedMotion;
|
|
26
|
+
private state;
|
|
27
|
+
private stateValues;
|
|
28
|
+
private uniforms;
|
|
29
|
+
constructor(canvas: HTMLCanvasElement);
|
|
30
|
+
setState(state: VoiceOrbState): void;
|
|
31
|
+
setAudioLevels(levels: VoiceOrbAudioLevels | null): void;
|
|
32
|
+
setPreview(previewAudioLevel: number, previewTimeMs?: number): void;
|
|
33
|
+
setReducedMotion(reducedMotion: boolean): void;
|
|
34
|
+
dispose(): void;
|
|
35
|
+
private start;
|
|
36
|
+
private readonly renderFrame;
|
|
37
|
+
private shouldContinueAnimation;
|
|
38
|
+
private hasVisibleState;
|
|
39
|
+
private isStateSettled;
|
|
40
|
+
private hasResidualAudio;
|
|
41
|
+
private createProgram;
|
|
42
|
+
private render;
|
|
43
|
+
private updateState;
|
|
44
|
+
private updateAudio;
|
|
45
|
+
private resizeCanvas;
|
|
46
|
+
private renderCanvasFallback;
|
|
47
|
+
private updatePreviewAudio;
|
|
48
|
+
private readonly handleContextLost;
|
|
49
|
+
private readonly handleContextRestored;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=voice-orb-renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-orb-renderer.d.ts","sourceRoot":"","sources":["../../../src/components/chat/voice-orb-renderer.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAK1B,MAAM,mBAAmB,CAAA;AAyB1B,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,oBAAoB,EAC7B,KAAK,EAAE,aAAa,EACpB,YAAY,EAAE,MAAM,EACpB,SAAS,UAAQ,GAChB,oBAAoB,CAYtB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,mBAAmB,EAC3B,YAAY,EAAE,MAAM,GACnB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAY3C;AAsCD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,aAAa,EACpB,iBAAiB,EAAE,MAAM,EACzB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,GACX,YAAY,CA4Bd;AA6BD,qBAAa,gBAAgB;IAsBf,OAAO,CAAC,QAAQ,CAAC,MAAM;IArBnC,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,EAAE,CAAqC;IAC/C,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,WAAW,CAAI;IACvB,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAAoB;IACzC,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,WAAW,CACkB;IACrC,OAAO,CAAC,QAAQ,CAAgC;gBAEnB,MAAM,EAAE,iBAAiB;IAkBtD,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IASpC,cAAc,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI,GAAG,IAAI;IAQxD,UAAU,CAAC,iBAAiB,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI;IAWnE,gBAAgB,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI;IAK9C,OAAO,IAAI,IAAI;IAiBf,OAAO,CAAC,KAAK;IAYb,OAAO,CAAC,QAAQ,CAAC,WAAW,CAM3B;IAED,OAAO,CAAC,uBAAuB;IAO/B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,aAAa;IAkDrB,OAAO,CAAC,MAAM;IAqCd,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,WAAW;IAkCnB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,kBAAkB;IA4C1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAIjC;IAED,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAarC;CACF"}
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { voiceOrbFragmentShader, voiceOrbVertexShader, } from './voice-orb-shaders.js';
|
|
2
|
+
import { getVoiceOrbStateTargets, normalizeVoiceOrbAudioLevels, silentVoiceOrbAudioLevels, voiceOrbStateTransitionSeconds, } from './voice-orb-types.js';
|
|
3
|
+
const QUAD_VERTICES = new Float32Array([
|
|
4
|
+
-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1,
|
|
5
|
+
]);
|
|
6
|
+
function interpolationFactor(deltaSeconds, duration) {
|
|
7
|
+
return 1 - Math.exp(-deltaSeconds / duration);
|
|
8
|
+
}
|
|
9
|
+
export function stepVoiceOrbState(current, state, deltaSeconds, immediate = false) {
|
|
10
|
+
const targets = getVoiceOrbStateTargets(state);
|
|
11
|
+
const factor = immediate
|
|
12
|
+
? 1
|
|
13
|
+
: interpolationFactor(deltaSeconds, voiceOrbStateTransitionSeconds);
|
|
14
|
+
const next = { ...current };
|
|
15
|
+
for (const key of Object.keys(targets)) {
|
|
16
|
+
next[key] += (targets[key] - next[key]) * factor;
|
|
17
|
+
}
|
|
18
|
+
if (state === 'connecting')
|
|
19
|
+
next.think = Math.max(next.think, 0.6);
|
|
20
|
+
return next;
|
|
21
|
+
}
|
|
22
|
+
export function stepVoiceOrbEnergyEnvelopes(micLevel, outputLevel, levels, deltaSeconds) {
|
|
23
|
+
const maximum = Math.max(levels.low, levels.mid, levels.high, levels.overall);
|
|
24
|
+
const micDuration = maximum > micLevel ? 0.12 : 0.32;
|
|
25
|
+
const nextMicLevel = micLevel +
|
|
26
|
+
(maximum - micLevel) * interpolationFactor(deltaSeconds, micDuration);
|
|
27
|
+
const outputDuration = levels.overall > outputLevel ? 0.09 : 0.3;
|
|
28
|
+
const nextOutputLevel = outputLevel +
|
|
29
|
+
(levels.overall - outputLevel) *
|
|
30
|
+
interpolationFactor(deltaSeconds, outputDuration);
|
|
31
|
+
return { micLevel: nextMicLevel, outputLevel: nextOutputLevel };
|
|
32
|
+
}
|
|
33
|
+
function smoothstep(minimum, maximum, value) {
|
|
34
|
+
const normalized = Math.max(0, Math.min(1, (value - minimum) / (maximum - minimum)));
|
|
35
|
+
return normalized * normalized * (3 - 2 * normalized);
|
|
36
|
+
}
|
|
37
|
+
function mixColor(base, target, amount) {
|
|
38
|
+
return base.map((value, index) => Math.round(value + ((target[index] ?? value) - value) * amount));
|
|
39
|
+
}
|
|
40
|
+
function getFallbackColor(base, muted, error, alpha = 1) {
|
|
41
|
+
const luminance = Math.round(base[0] * 0.299 + base[1] * 0.587 + base[2] * 0.114);
|
|
42
|
+
const desaturated = mixColor(base, [luminance, luminance, luminance], muted * 0.72);
|
|
43
|
+
const tinted = mixColor(desaturated, [255, 89, 79], error * 0.58);
|
|
44
|
+
return `rgba(${tinted[0]}, ${tinted[1]}, ${tinted[2]}, ${alpha})`;
|
|
45
|
+
}
|
|
46
|
+
export function getVoiceOrbPreviewAudio(state, previewAudioLevel, live, time) {
|
|
47
|
+
const normalizedPreviewLevel = Number.isFinite(previewAudioLevel)
|
|
48
|
+
? Math.max(0, Math.min(1, previewAudioLevel))
|
|
49
|
+
: 0;
|
|
50
|
+
const intensity = Math.max(live && state === 'speaking' ? 0.42 : 0, normalizedPreviewLevel);
|
|
51
|
+
const breath = smoothstep(0.08, 0.72, Math.sin(time * 0.78) * 0.5 + 0.5);
|
|
52
|
+
const speechShape = 0.58 + Math.sin(time * 3.1 + 0.6) * 0.17 + Math.sin(time * 4.2 + 2.1) * 0.12;
|
|
53
|
+
const speaking = state === 'speaking'
|
|
54
|
+
? intensity * (0.08 + breath * Math.max(0.24, speechShape))
|
|
55
|
+
: 0;
|
|
56
|
+
const thinking = state === 'thinking'
|
|
57
|
+
? intensity * (0.1 + (Math.sin(time * 1.4) * 0.5 + 0.5) * 0.06)
|
|
58
|
+
: 0;
|
|
59
|
+
const listening = state === 'listening' ? intensity * 0.08 : 0;
|
|
60
|
+
const overall = Math.min(1, Math.max(speaking, thinking, listening));
|
|
61
|
+
return new Float32Array([
|
|
62
|
+
overall * (0.82 + Math.sin(time * 1.1) * 0.14),
|
|
63
|
+
overall * (0.76 + Math.sin(time * 1.5 + 1.2) * 0.16),
|
|
64
|
+
overall * (0.68 + Math.sin(time * 1.9 + 2.1) * 0.18),
|
|
65
|
+
overall,
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
function requireUniform(gl, program, name) {
|
|
69
|
+
const location = gl.getUniformLocation(program, name);
|
|
70
|
+
if (!location)
|
|
71
|
+
throw new Error(`Voice orb shader is missing ${name}`);
|
|
72
|
+
return location;
|
|
73
|
+
}
|
|
74
|
+
function compileShader(gl, type, source) {
|
|
75
|
+
const shader = gl.createShader(type);
|
|
76
|
+
if (!shader)
|
|
77
|
+
throw new Error('Unable to create voice orb shader');
|
|
78
|
+
gl.shaderSource(shader, source);
|
|
79
|
+
gl.compileShader(shader);
|
|
80
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
81
|
+
const message = gl.getShaderInfoLog(shader) ?? 'Shader compilation failed';
|
|
82
|
+
gl.deleteShader(shader);
|
|
83
|
+
throw new Error(message);
|
|
84
|
+
}
|
|
85
|
+
return shader;
|
|
86
|
+
}
|
|
87
|
+
export class VoiceOrbRenderer {
|
|
88
|
+
canvas;
|
|
89
|
+
animationFrame = null;
|
|
90
|
+
audio = new Float32Array(4);
|
|
91
|
+
audioLevels = silentVoiceOrbAudioLevels;
|
|
92
|
+
buffer = null;
|
|
93
|
+
canvasContext = null;
|
|
94
|
+
cumulativeAudio = new Float32Array(4);
|
|
95
|
+
gl = null;
|
|
96
|
+
hasAudioInput = false;
|
|
97
|
+
hasStateInput = false;
|
|
98
|
+
lastFrameTime = 0;
|
|
99
|
+
micLevel = 0;
|
|
100
|
+
outputLevel = 0;
|
|
101
|
+
previewAudioLevel = 0;
|
|
102
|
+
previewTimeMs;
|
|
103
|
+
program = null;
|
|
104
|
+
reducedMotion = false;
|
|
105
|
+
state = 'inactive';
|
|
106
|
+
stateValues = getVoiceOrbStateTargets('inactive');
|
|
107
|
+
uniforms = null;
|
|
108
|
+
constructor(canvas) {
|
|
109
|
+
this.canvas = canvas;
|
|
110
|
+
canvas.addEventListener('webglcontextlost', this.handleContextLost);
|
|
111
|
+
canvas.addEventListener('webglcontextrestored', this.handleContextRestored);
|
|
112
|
+
try {
|
|
113
|
+
this.gl = canvas.getContext('webgl', {
|
|
114
|
+
alpha: true,
|
|
115
|
+
antialias: false,
|
|
116
|
+
depth: false,
|
|
117
|
+
premultipliedAlpha: false,
|
|
118
|
+
});
|
|
119
|
+
if (this.gl)
|
|
120
|
+
this.createProgram(this.gl);
|
|
121
|
+
else
|
|
122
|
+
this.canvasContext = canvas.getContext('2d');
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
this.gl = null;
|
|
126
|
+
this.canvasContext = canvas.getContext('2d');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
setState(state) {
|
|
130
|
+
this.state = state;
|
|
131
|
+
if (!this.hasStateInput) {
|
|
132
|
+
this.stateValues = getVoiceOrbStateTargets(state);
|
|
133
|
+
this.hasStateInput = true;
|
|
134
|
+
}
|
|
135
|
+
this.start();
|
|
136
|
+
}
|
|
137
|
+
setAudioLevels(levels) {
|
|
138
|
+
this.hasAudioInput = levels !== null;
|
|
139
|
+
this.audioLevels = levels
|
|
140
|
+
? normalizeVoiceOrbAudioLevels(levels)
|
|
141
|
+
: silentVoiceOrbAudioLevels;
|
|
142
|
+
this.start();
|
|
143
|
+
}
|
|
144
|
+
setPreview(previewAudioLevel, previewTimeMs) {
|
|
145
|
+
this.previewAudioLevel = Number.isFinite(previewAudioLevel)
|
|
146
|
+
? Math.max(0, Math.min(1, previewAudioLevel))
|
|
147
|
+
: 0;
|
|
148
|
+
this.previewTimeMs =
|
|
149
|
+
previewTimeMs === undefined || Number.isFinite(previewTimeMs)
|
|
150
|
+
? previewTimeMs
|
|
151
|
+
: undefined;
|
|
152
|
+
this.start();
|
|
153
|
+
}
|
|
154
|
+
setReducedMotion(reducedMotion) {
|
|
155
|
+
this.reducedMotion = reducedMotion;
|
|
156
|
+
this.start();
|
|
157
|
+
}
|
|
158
|
+
dispose() {
|
|
159
|
+
if (this.animationFrame !== null)
|
|
160
|
+
cancelAnimationFrame(this.animationFrame);
|
|
161
|
+
this.animationFrame = null;
|
|
162
|
+
if (this.gl) {
|
|
163
|
+
if (this.buffer)
|
|
164
|
+
this.gl.deleteBuffer(this.buffer);
|
|
165
|
+
if (this.program)
|
|
166
|
+
this.gl.deleteProgram(this.program);
|
|
167
|
+
}
|
|
168
|
+
this.buffer = null;
|
|
169
|
+
this.program = null;
|
|
170
|
+
this.uniforms = null;
|
|
171
|
+
this.canvas.removeEventListener('webglcontextlost', this.handleContextLost);
|
|
172
|
+
this.canvas.removeEventListener('webglcontextrestored', this.handleContextRestored);
|
|
173
|
+
}
|
|
174
|
+
start() {
|
|
175
|
+
if (this.previewTimeMs !== undefined) {
|
|
176
|
+
if (this.animationFrame !== null) {
|
|
177
|
+
cancelAnimationFrame(this.animationFrame);
|
|
178
|
+
this.animationFrame = null;
|
|
179
|
+
}
|
|
180
|
+
this.render(this.previewTimeMs / 1_000);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this.animationFrame ??= requestAnimationFrame(this.renderFrame);
|
|
184
|
+
}
|
|
185
|
+
renderFrame = (milliseconds) => {
|
|
186
|
+
this.animationFrame = null;
|
|
187
|
+
this.render(milliseconds / 1_000);
|
|
188
|
+
if (this.shouldContinueAnimation()) {
|
|
189
|
+
this.animationFrame = requestAnimationFrame(this.renderFrame);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
shouldContinueAnimation() {
|
|
193
|
+
if (this.previewTimeMs !== undefined)
|
|
194
|
+
return false;
|
|
195
|
+
if (this.state === 'inactive')
|
|
196
|
+
return this.hasVisibleState();
|
|
197
|
+
if (!this.reducedMotion)
|
|
198
|
+
return true;
|
|
199
|
+
return !this.isStateSettled() || this.hasResidualAudio();
|
|
200
|
+
}
|
|
201
|
+
hasVisibleState() {
|
|
202
|
+
return Object.values(this.stateValues).some((value) => value > 0.001);
|
|
203
|
+
}
|
|
204
|
+
isStateSettled() {
|
|
205
|
+
const target = getVoiceOrbStateTargets(this.state);
|
|
206
|
+
return Object.keys(target).every((key) => Math.abs(target[key] - this.stateValues[key]) <= 0.001);
|
|
207
|
+
}
|
|
208
|
+
hasResidualAudio() {
|
|
209
|
+
if (this.hasAudioInput || this.state === 'speaking')
|
|
210
|
+
return false;
|
|
211
|
+
return (this.micLevel > 0.001 ||
|
|
212
|
+
this.outputLevel > 0.001 ||
|
|
213
|
+
[...this.audio].some((value) => value > 0.001));
|
|
214
|
+
}
|
|
215
|
+
createProgram(gl) {
|
|
216
|
+
const program = gl.createProgram();
|
|
217
|
+
if (!program)
|
|
218
|
+
throw new Error('Unable to create voice orb program');
|
|
219
|
+
const vertex = compileShader(gl, gl.VERTEX_SHADER, voiceOrbVertexShader);
|
|
220
|
+
const fragment = compileShader(gl, gl.FRAGMENT_SHADER, voiceOrbFragmentShader);
|
|
221
|
+
gl.attachShader(program, vertex);
|
|
222
|
+
gl.attachShader(program, fragment);
|
|
223
|
+
gl.linkProgram(program);
|
|
224
|
+
gl.deleteShader(vertex);
|
|
225
|
+
gl.deleteShader(fragment);
|
|
226
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
227
|
+
const message = gl.getProgramInfoLog(program) ?? 'Shader linking failed';
|
|
228
|
+
gl.deleteProgram(program);
|
|
229
|
+
throw new Error(message);
|
|
230
|
+
}
|
|
231
|
+
const position = gl.getAttribLocation(program, 'a_position');
|
|
232
|
+
const buffer = gl.createBuffer();
|
|
233
|
+
if (!buffer)
|
|
234
|
+
throw new Error('Unable to create voice orb geometry');
|
|
235
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
236
|
+
gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTICES, gl.STATIC_DRAW);
|
|
237
|
+
gl.useProgram(program);
|
|
238
|
+
gl.enableVertexAttribArray(position);
|
|
239
|
+
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
|
|
240
|
+
gl.enable(gl.BLEND);
|
|
241
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
242
|
+
this.buffer = buffer;
|
|
243
|
+
this.program = program;
|
|
244
|
+
this.uniforms = {
|
|
245
|
+
audio: requireUniform(gl, program, 'u_audio'),
|
|
246
|
+
cumulativeAudio: requireUniform(gl, program, 'u_cumulativeAudio'),
|
|
247
|
+
micLevel: requireUniform(gl, program, 'u_micLevel'),
|
|
248
|
+
motionScale: requireUniform(gl, program, 'u_motionScale'),
|
|
249
|
+
outputLevel: requireUniform(gl, program, 'u_outputLevel'),
|
|
250
|
+
resolution: requireUniform(gl, program, 'u_resolution'),
|
|
251
|
+
stateError: requireUniform(gl, program, 'u_stateError'),
|
|
252
|
+
stateListen: requireUniform(gl, program, 'u_stateListen'),
|
|
253
|
+
stateMuted: requireUniform(gl, program, 'u_stateMuted'),
|
|
254
|
+
stateSpeak: requireUniform(gl, program, 'u_stateSpeak'),
|
|
255
|
+
stateThink: requireUniform(gl, program, 'u_stateThink'),
|
|
256
|
+
time: requireUniform(gl, program, 'u_time'),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
render(time) {
|
|
260
|
+
const deltaSeconds = this.lastFrameTime === 0
|
|
261
|
+
? 0.016
|
|
262
|
+
: Math.max(0, Math.min(0.05, time - this.lastFrameTime));
|
|
263
|
+
this.lastFrameTime = time;
|
|
264
|
+
this.updateState(deltaSeconds);
|
|
265
|
+
this.updateAudio(deltaSeconds, time);
|
|
266
|
+
this.resizeCanvas();
|
|
267
|
+
const gl = this.gl;
|
|
268
|
+
const program = this.program;
|
|
269
|
+
const uniforms = this.uniforms;
|
|
270
|
+
if (!gl || !program || !uniforms) {
|
|
271
|
+
this.renderCanvasFallback(time);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
gl.clearColor(0, 0, 0, 0);
|
|
275
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
276
|
+
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
277
|
+
gl.useProgram(program);
|
|
278
|
+
gl.uniform1f(uniforms.time, time);
|
|
279
|
+
gl.uniform1f(uniforms.micLevel, this.micLevel);
|
|
280
|
+
gl.uniform1f(uniforms.motionScale, this.reducedMotion ? 0 : 1);
|
|
281
|
+
gl.uniform1f(uniforms.outputLevel, this.outputLevel);
|
|
282
|
+
gl.uniform1f(uniforms.stateListen, this.stateValues.listen);
|
|
283
|
+
gl.uniform1f(uniforms.stateThink, this.stateValues.think);
|
|
284
|
+
gl.uniform1f(uniforms.stateSpeak, this.stateValues.speak);
|
|
285
|
+
gl.uniform1f(uniforms.stateMuted, this.stateValues.muted);
|
|
286
|
+
gl.uniform1f(uniforms.stateError, this.stateValues.error);
|
|
287
|
+
gl.uniform2f(uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
288
|
+
gl.uniform4fv(uniforms.audio, this.audio);
|
|
289
|
+
gl.uniform4fv(uniforms.cumulativeAudio, this.cumulativeAudio);
|
|
290
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
291
|
+
}
|
|
292
|
+
updateState(deltaSeconds) {
|
|
293
|
+
this.stateValues = stepVoiceOrbState(this.stateValues, this.state, deltaSeconds, this.previewTimeMs !== undefined);
|
|
294
|
+
}
|
|
295
|
+
updateAudio(deltaSeconds, time) {
|
|
296
|
+
if (!this.hasAudioInput) {
|
|
297
|
+
this.updatePreviewAudio(deltaSeconds, time);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const source = [
|
|
301
|
+
this.audioLevels.low,
|
|
302
|
+
this.audioLevels.mid,
|
|
303
|
+
this.audioLevels.high,
|
|
304
|
+
this.audioLevels.overall,
|
|
305
|
+
];
|
|
306
|
+
const frameScale = deltaSeconds * 60;
|
|
307
|
+
const audioFactor = interpolationFactor(deltaSeconds, 2);
|
|
308
|
+
for (let index = 0; index < this.audio.length; index += 1) {
|
|
309
|
+
const value = (source[index] ?? 0) * frameScale;
|
|
310
|
+
this.audio[index] += (value - this.audio[index]) * audioFactor;
|
|
311
|
+
if (!this.reducedMotion) {
|
|
312
|
+
this.cumulativeAudio[index] +=
|
|
313
|
+
(source[index] ?? 0) * frameScale * 40 * audioFactor;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
const envelopes = stepVoiceOrbEnergyEnvelopes(this.micLevel, this.outputLevel, this.audioLevels, deltaSeconds);
|
|
317
|
+
this.micLevel = envelopes.micLevel;
|
|
318
|
+
this.outputLevel = envelopes.outputLevel;
|
|
319
|
+
}
|
|
320
|
+
resizeCanvas() {
|
|
321
|
+
const pixelRatio = Math.min(window.devicePixelRatio || 1, 1.5);
|
|
322
|
+
const width = Math.max(1, Math.round(this.canvas.clientWidth * pixelRatio));
|
|
323
|
+
const height = Math.max(1, Math.round(this.canvas.clientHeight * pixelRatio));
|
|
324
|
+
if (this.canvas.width !== width)
|
|
325
|
+
this.canvas.width = width;
|
|
326
|
+
if (this.canvas.height !== height)
|
|
327
|
+
this.canvas.height = height;
|
|
328
|
+
}
|
|
329
|
+
renderCanvasFallback(time) {
|
|
330
|
+
const context = this.canvasContext;
|
|
331
|
+
if (!context)
|
|
332
|
+
return;
|
|
333
|
+
const stateAmount = Math.max(...Object.values(this.stateValues));
|
|
334
|
+
const radius = Math.min(this.canvas.width, this.canvas.height) *
|
|
335
|
+
0.29 *
|
|
336
|
+
(1 + this.outputLevel * 0.12) *
|
|
337
|
+
stateAmount;
|
|
338
|
+
const centerX = this.canvas.width / 2;
|
|
339
|
+
const centerY = this.canvas.height / 2 +
|
|
340
|
+
(this.reducedMotion ? 0 : Math.sin(time * 0.36) * 1.5);
|
|
341
|
+
context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
342
|
+
if (radius <= 0.1)
|
|
343
|
+
return;
|
|
344
|
+
const gradient = context.createLinearGradient(centerX - radius * 0.7, centerY - radius, centerX + radius * 0.55, centerY + radius);
|
|
345
|
+
gradient.addColorStop(0, getFallbackColor([1, 129, 254], this.stateValues.muted, this.stateValues.error));
|
|
346
|
+
gradient.addColorStop(0.46, getFallbackColor([164, 239, 255], this.stateValues.muted, this.stateValues.error, 0.98));
|
|
347
|
+
gradient.addColorStop(1, getFallbackColor([255, 253, 239], this.stateValues.muted, this.stateValues.error, 0.98));
|
|
348
|
+
context.fillStyle = gradient;
|
|
349
|
+
context.beginPath();
|
|
350
|
+
context.arc(centerX, centerY, radius, 0, Math.PI * 2);
|
|
351
|
+
context.fill();
|
|
352
|
+
}
|
|
353
|
+
updatePreviewAudio(deltaSeconds, time) {
|
|
354
|
+
const preview = getVoiceOrbPreviewAudio(this.state, this.previewAudioLevel, this.previewTimeMs === undefined, time);
|
|
355
|
+
if (this.previewTimeMs !== undefined) {
|
|
356
|
+
for (let index = 0; index < this.audio.length; index += 1) {
|
|
357
|
+
this.audio[index] = preview[index] ?? 0;
|
|
358
|
+
this.cumulativeAudio[index] = (preview[index] ?? 0) * time * 2.5;
|
|
359
|
+
}
|
|
360
|
+
this.micLevel = preview[3] ?? 0;
|
|
361
|
+
this.outputLevel = preview[3] ?? 0;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
for (let index = 0; index < this.audio.length; index += 1) {
|
|
365
|
+
const target = preview[index] ?? 0;
|
|
366
|
+
const duration = target > this.audio[index] ? 0.24 : 0.72;
|
|
367
|
+
this.audio[index] +=
|
|
368
|
+
(target - this.audio[index]) *
|
|
369
|
+
interpolationFactor(deltaSeconds, duration);
|
|
370
|
+
if (!this.reducedMotion) {
|
|
371
|
+
this.cumulativeAudio[index] +=
|
|
372
|
+
this.audio[index] *
|
|
373
|
+
deltaSeconds *
|
|
374
|
+
(this.state === 'speaking' ? 7 : 3.5);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const previewOverall = preview[3] ?? 0;
|
|
378
|
+
const micDuration = previewOverall > this.micLevel ? 0.26 : 0.8;
|
|
379
|
+
this.micLevel +=
|
|
380
|
+
(previewOverall - this.micLevel) *
|
|
381
|
+
interpolationFactor(deltaSeconds, micDuration);
|
|
382
|
+
const outputTarget = this.previewAudioLevel > 0 ? previewOverall : 0;
|
|
383
|
+
const outputDuration = outputTarget > this.outputLevel ? 0.09 : 0.3;
|
|
384
|
+
this.outputLevel +=
|
|
385
|
+
(outputTarget - this.outputLevel) *
|
|
386
|
+
interpolationFactor(deltaSeconds, outputDuration);
|
|
387
|
+
}
|
|
388
|
+
handleContextLost = (event) => {
|
|
389
|
+
event.preventDefault();
|
|
390
|
+
if (this.animationFrame !== null)
|
|
391
|
+
cancelAnimationFrame(this.animationFrame);
|
|
392
|
+
this.animationFrame = null;
|
|
393
|
+
};
|
|
394
|
+
handleContextRestored = () => {
|
|
395
|
+
const gl = this.gl;
|
|
396
|
+
if (!gl)
|
|
397
|
+
return;
|
|
398
|
+
this.buffer = null;
|
|
399
|
+
this.program = null;
|
|
400
|
+
this.uniforms = null;
|
|
401
|
+
try {
|
|
402
|
+
this.createProgram(gl);
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
this.gl = null;
|
|
406
|
+
this.canvasContext = this.canvas.getContext('2d');
|
|
407
|
+
}
|
|
408
|
+
this.start();
|
|
409
|
+
};
|
|
410
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const voiceOrbVertexShader = "\nattribute vec2 a_position;\nvarying vec2 v_uv;\n\nvoid main() {\n v_uv = (a_position + 1.0) * 0.5;\n gl_Position = vec4(a_position, 0.0, 1.0);\n}\n";
|
|
2
|
+
export declare const voiceOrbFragmentShader = "\nprecision highp float;\n\nvarying vec2 v_uv;\n\nuniform vec2 u_resolution;\nuniform float u_time;\nuniform float u_micLevel;\nuniform float u_outputLevel;\nuniform float u_stateListen;\nuniform float u_stateThink;\nuniform float u_stateSpeak;\nuniform float u_stateMuted;\nuniform float u_stateError;\nuniform float u_motionScale;\nuniform vec4 u_audio;\nuniform vec4 u_cumulativeAudio;\n\n#define PI 3.141592653589793\n#define NUM_OCTAVES 5\n\nfloat rand(vec2 n) {\n return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);\n}\n\nfloat noise(vec2 p) {\n vec2 ip = floor(p);\n vec2 u = fract(p);\n u = u * u * (3.0 - 2.0 * u);\n float value = mix(\n mix(rand(ip), rand(ip + vec2(1.0, 0.0)), u.x),\n mix(rand(ip + vec2(0.0, 1.0)), rand(ip + vec2(1.0, 1.0)), u.x),\n u.y\n );\n return value * value;\n}\n\nfloat fbm(vec2 point) {\n float value = 0.0;\n float amplitude = 0.5;\n vec2 shift = vec2(100.0);\n mat2 rotation = mat2(cos(0.5), sin(0.5), -sin(0.5), cos(0.5));\n for (int index = 0; index < NUM_OCTAVES; index++) {\n value += amplitude * noise(point);\n point = rotation * point * 2.0 + shift;\n amplitude *= 0.5;\n }\n return value;\n}\n\nvec3 blendLinearBurn(vec3 base, vec3 blend, float opacity) {\n vec3 burned = max(base + blend - vec3(1.0), vec3(0.0));\n return burned * opacity + base * (1.0 - opacity);\n}\n\nvec4 permute(vec4 value) {\n return mod((value * 34.0 + 1.0) * value, 289.0);\n}\n\nvec4 taylorInvSqrt(vec4 value) {\n return 1.79284291400159 - 0.85373472095314 * value;\n}\n\nvec3 fade(vec3 value) {\n return value * value * value * (value * (value * 6.0 - 15.0) + 10.0);\n}\n\nfloat cnoise(vec3 point) {\n vec3 cell0 = floor(point);\n vec3 cell1 = cell0 + vec3(1.0);\n cell0 = mod(cell0, 289.0);\n cell1 = mod(cell1, 289.0);\n vec3 offset0 = fract(point);\n vec3 offset1 = offset0 - vec3(1.0);\n vec4 x = vec4(cell0.x, cell1.x, cell0.x, cell1.x);\n vec4 y = vec4(cell0.yy, cell1.yy);\n vec4 z0 = vec4(cell0.z);\n vec4 z1 = vec4(cell1.z);\n vec4 xy = permute(permute(x) + y);\n vec4 xy0 = permute(xy + z0);\n vec4 xy1 = permute(xy + z1);\n\n vec4 gx0 = xy0 / 7.0;\n vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;\n gx0 = fract(gx0);\n vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);\n vec4 sz0 = step(gz0, vec4(0.0));\n gx0 -= sz0 * (step(vec4(0.0), gx0) - 0.5);\n gy0 -= sz0 * (step(vec4(0.0), gy0) - 0.5);\n\n vec4 gx1 = xy1 / 7.0;\n vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;\n gx1 = fract(gx1);\n vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);\n vec4 sz1 = step(gz1, vec4(0.0));\n gx1 -= sz1 * (step(vec4(0.0), gx1) - 0.5);\n gy1 -= sz1 * (step(vec4(0.0), gy1) - 0.5);\n\n vec3 g000 = vec3(gx0.x, gy0.x, gz0.x);\n vec3 g100 = vec3(gx0.y, gy0.y, gz0.y);\n vec3 g010 = vec3(gx0.z, gy0.z, gz0.z);\n vec3 g110 = vec3(gx0.w, gy0.w, gz0.w);\n vec3 g001 = vec3(gx1.x, gy1.x, gz1.x);\n vec3 g101 = vec3(gx1.y, gy1.y, gz1.y);\n vec3 g011 = vec3(gx1.z, gy1.z, gz1.z);\n vec3 g111 = vec3(gx1.w, gy1.w, gz1.w);\n\n vec4 norm0 = taylorInvSqrt(\n vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))\n );\n g000 *= norm0.x;\n g010 *= norm0.y;\n g100 *= norm0.z;\n g110 *= norm0.w;\n vec4 norm1 = taylorInvSqrt(\n vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))\n );\n g001 *= norm1.x;\n g011 *= norm1.y;\n g101 *= norm1.z;\n g111 *= norm1.w;\n\n float n000 = dot(g000, offset0);\n float n100 = dot(g100, vec3(offset1.x, offset0.yz));\n float n010 = dot(g010, vec3(offset0.x, offset1.y, offset0.z));\n float n110 = dot(g110, vec3(offset1.xy, offset0.z));\n float n001 = dot(g001, vec3(offset0.xy, offset1.z));\n float n101 = dot(g101, vec3(offset1.x, offset0.y, offset1.z));\n float n011 = dot(g011, vec3(offset0.x, offset1.yz));\n float n111 = dot(g111, offset1);\n\n vec3 fadePoint = fade(offset0);\n vec4 noiseZ = mix(\n vec4(n000, n100, n010, n110),\n vec4(n001, n101, n011, n111),\n fadePoint.z\n );\n vec2 noiseYZ = mix(noiseZ.xy, noiseZ.zw, fadePoint.y);\n return 2.2 * mix(noiseYZ.x, noiseYZ.y, fadePoint.x);\n}\n\nvoid main() {\n vec2 st = v_uv - 0.5;\n st.x *= u_resolution.x / u_resolution.y;\n\n float sound = max(max(u_audio.x, u_audio.y), max(u_audio.z, u_audio.w));\n float stateAmount = max(\n max(u_stateListen, u_stateThink),\n max(u_stateSpeak, max(u_stateMuted, u_stateError))\n );\n float audioEnergy = smoothstep(0.08, 0.72, max(sound, u_micLevel));\n float outputEnergy = smoothstep(0.04, 0.46, u_outputLevel);\n float animatedTime = u_time * u_motionScale;\n float breath = sin(animatedTime * PI * 0.34) * 0.5 + 0.5;\n float entry = smoothstep(0.0, 0.9, stateAmount);\n float maxRadius = min(\n 0.36,\n min(0.5, 0.5 * u_resolution.x / u_resolution.y) - 0.16\n );\n float baseRadius = mix(maxRadius * 0.88, maxRadius * 0.94, u_stateThink);\n float radius = baseRadius * mix(0.82, 1.0, entry);\n radius += outputEnergy * maxRadius * 0.12;\n radius +=\n (1.0 - u_stateThink) *\n (1.0 - outputEnergy) *\n breath *\n maxRadius *\n 0.01;\n radius = min(maxRadius, radius);\n\n vec2 drift = vec2(\n sin(animatedTime * 0.43) * 0.0028,\n sin(animatedTime * 0.36 + 1.7) * 0.0035\n );\n vec2 lifted = st - drift;\n float distanceToEdge = length(lifted) - radius;\n float edgeWidth = max(1.25 / min(u_resolution.x, u_resolution.y), 0.0014);\n if (distanceToEdge > edgeWidth) discard;\n float edge = 1.0 - smoothstep(-edgeWidth, edgeWidth, distanceToEdge);\n\n vec2 uv = lifted / (2.0 * radius) + 0.5;\n float soundScale = 1.0 + audioEnergy * 0.22;\n float time = animatedTime * 0.34;\n float noiseX = cnoise(vec3(\n uv + vec2(0.0, 74.8572),\n (time + u_cumulativeAudio.x * 0.05 * soundScale) * 0.3\n ));\n float noiseY = cnoise(vec3(\n uv + vec2(203.91282, 10.0),\n (time + u_cumulativeAudio.z * 0.05 * soundScale) * 0.3\n ));\n uv += vec2(noiseX * 2.0, noiseY) * 0.19;\n\n float voiceWarpX = cnoise(vec3(\n uv * 3.1 + vec2(0.0, 17.3),\n u_cumulativeAudio.x * 0.085 + u_cumulativeAudio.z * 0.035\n ));\n float voiceWarpY = cnoise(vec3(\n uv * 3.4 + vec2(31.7, 0.0),\n u_cumulativeAudio.y * 0.075 + u_cumulativeAudio.w * 0.045\n ));\n uv += vec2(voiceWarpX, voiceWarpY) * audioEnergy * 0.04;\n uv.y +=\n sin(uv.x * 5.4 + u_cumulativeAudio.w * 0.19) *\n audioEnergy *\n 0.016;\n\n float watercolor =\n cnoise(vec3(uv * 18.0 + vec2(344.91282, 0.0), time * 0.3)) +\n cnoise(vec3(uv * 39.6 + vec2(723.937, 0.0), time * 0.4)) * 0.5;\n uv += watercolor * 0.006;\n\n float textureA = noise(\n uv * 22.0 + vec2(time * 0.08, u_cumulativeAudio.x * 0.025)\n );\n float textureB = noise(\n vec2(1.0 - uv.x, uv.y) * 41.0 +\n vec2(u_cumulativeAudio.z * 0.018, -time * 0.11)\n );\n float texture = mix(\n textureA,\n textureB,\n sin(time + u_cumulativeAudio.w * 0.12) * 0.5 + 0.5\n ) - 0.5;\n uv += texture * (0.012 + audioEnergy * 0.004);\n\n uv.y = 1.0 - uv.y;\n vec2 centeredUv = uv - 0.5;\n float angle = -0.16;\n uv = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)) * centeredUv + 0.5;\n uv.y -= 0.03;\n\n vec2 stNoise = uv * 1.25;\n vec2 q = vec2(\n fbm(\n stNoise * 0.5 +\n 0.075 * (time + u_cumulativeAudio.w * 0.175 * soundScale)\n ),\n fbm(\n stNoise * 0.5 +\n 0.075 * (time + u_cumulativeAudio.x * 0.136 * soundScale)\n )\n );\n vec2 r = vec2(\n fbm(\n stNoise + q + vec2(0.3, 9.2) +\n 0.15 * (time + u_cumulativeAudio.y * 0.234 * soundScale)\n ),\n fbm(\n stNoise + q + vec2(8.3, 0.8) +\n 0.126 * (time + u_cumulativeAudio.z * 0.165 * soundScale)\n )\n );\n float field = fbm(stNoise + r - q);\n float fullField = pow(\n ((field + 0.6 * field * field + 0.7 * field) + 0.5) * 0.5,\n 0.55\n );\n\n vec3 mainColor = mix(\n vec3(0.94, 0.965, 1.0),\n vec3(1.0, 0.99, 0.96),\n u_micLevel\n );\n vec3 lowColor = vec3(0.36, 0.34, 0.96);\n vec3 midColor = mix(\n vec3(0.57, 0.64, 1.0),\n vec3(0.96, 0.92, 1.0),\n u_micLevel\n );\n vec3 highColor = vec3(1.0, 0.99, 0.97);\n\n vec3 offsets = vec3(\n u_cumulativeAudio.x * 0.15 * soundScale,\n -u_cumulativeAudio.y * 0.5 * soundScale,\n u_cumulativeAudio.z * 1.5 * soundScale\n );\n\n vec2 lowUv = uv + vec2((fullField - 0.5) * 1.2, 0.025);\n float lowNoise = noise(\n lowUv * 2.0 + vec2(sin(offsets.x * 0.25), time * 0.5 + offsets.x)\n ) * 2.0;\n float lowMask = smoothstep(\n lowNoise - 1.8,\n lowNoise + 1.8,\n ((lowUv.y - 0.5) * (5.0 - u_audio.x * 0.05 * soundScale)) + 0.5\n );\n\n vec2 midUv = uv + vec2((fullField - 0.5) * 0.85, 0.025);\n float midNoise = noise(\n midUv * 4.0 +\n vec2(sin(offsets.y * 0.15) * 2.4 + 293.0, time + offsets.y * 0.5)\n ) * 2.0;\n float midMask = smoothstep(\n midNoise - ((0.9 + u_audio.y * 0.4) * 1.5),\n midNoise + ((0.9 + u_audio.y * 0.8) * 1.5),\n ((midUv.y - 0.6) * (5.0 - u_audio.y * 0.75)) + 0.5\n );\n\n vec2 highUv = uv + vec2((fullField - 0.5) * 1.1);\n float highNoise = noise(\n highUv * 6.0 +\n vec2(sin(offsets.z * 0.1) * 2.4 + 153.0, time * 1.2 + offsets.z * 0.8)\n ) * 2.0;\n float highMask = smoothstep(\n highNoise - 1.05,\n highNoise + 1.05,\n ((highUv.y - 0.9) * 6.0) + 0.5\n );\n\n lowMask = pow(lowMask, 0.8);\n midMask = pow(midMask, 0.9);\n vec3 color = blendLinearBurn(mainColor, lowColor, 1.0 - lowMask);\n color = blendLinearBurn(\n color,\n mix(mainColor, midColor, 1.0 - midMask),\n lowMask\n );\n color = mix(\n color,\n mix(mainColor, highColor, 1.0 - highMask),\n lowMask * midMask\n );\n\n float fineNoise = fbm(\n uv * 12.0 + vec2(time * 0.13, -time * 0.09) + r * 0.4\n );\n color = mix(\n color,\n highColor,\n smoothstep(0.58, 0.9, fineNoise) * (0.035 + audioEnergy * 0.025)\n );\n color = mix(\n color,\n lowColor,\n smoothstep(0.42, 0.12, fineNoise) * 0.018\n );\n\n float luminance = dot(color, vec3(0.299, 0.587, 0.114));\n color = mix(color, vec3(luminance), u_stateMuted * 0.72);\n color = mix(color, vec3(1.0, 0.35, 0.31), u_stateError * 0.58);\n\n float alpha = edge * smoothstep(0.0, 0.18, stateAmount + 0.3);\n gl_FragColor = vec4(color, alpha);\n}\n";
|
|
3
|
+
//# sourceMappingURL=voice-orb-shaders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voice-orb-shaders.d.ts","sourceRoot":"","sources":["../../../src/components/chat/voice-orb-shaders.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,4JAQhC,CAAA;AAED,eAAO,MAAM,sBAAsB,g/TAyVlC,CAAA"}
|