@signalcore/ui 0.1.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +896 -513
- package/dist/AgentAbout.d.ts +186 -0
- package/dist/AgentAbout.js +1020 -0
- package/dist/AgentAbout.js.map +1 -0
- package/dist/AgentCard.d.ts +49 -0
- package/dist/AgentCard.js +77 -0
- package/dist/AgentCard.js.map +1 -0
- package/dist/AgentChat.d.ts +233 -0
- package/dist/AgentChat.js +1127 -0
- package/dist/AgentChat.js.map +1 -0
- package/dist/AgentSpace.d.ts +112 -0
- package/dist/AgentSpace.js +339 -0
- package/dist/AgentSpace.js.map +1 -0
- package/dist/AgentTasks.d.ts +48 -0
- package/dist/AgentTasks.js +120 -0
- package/dist/AgentTasks.js.map +1 -0
- package/dist/BrowserView.d.ts +52 -0
- package/dist/BrowserView.js +328 -0
- package/dist/BrowserView.js.map +1 -0
- package/dist/FileView.d.ts +63 -0
- package/dist/FileView.js +449 -0
- package/dist/FileView.js.map +1 -0
- package/dist/Modes.d.ts +13 -0
- package/dist/Modes.js +75 -0
- package/dist/Modes.js.map +1 -0
- package/dist/VoiceCall.d.ts +91 -0
- package/dist/VoiceCall.js +302 -0
- package/dist/VoiceCall.js.map +1 -0
- package/dist/about.d.ts +212 -0
- package/dist/about.js +136 -0
- package/dist/about.js.map +1 -0
- package/dist/agentIcons.d.ts +33 -0
- package/dist/agentIcons.js +36 -0
- package/dist/agentIcons.js.map +1 -0
- package/dist/automation/Automation.d.ts +35 -0
- package/dist/automation/Automation.js +268 -0
- package/dist/automation/Automation.js.map +1 -0
- package/dist/automation/RunView.d.ts +25 -0
- package/dist/automation/RunView.js +187 -0
- package/dist/automation/RunView.js.map +1 -0
- package/dist/automation/cron.d.ts +41 -0
- package/dist/automation/cron.js +169 -0
- package/dist/automation/cron.js.map +1 -0
- package/dist/automation/marks.js +121 -0
- package/dist/automation/marks.js.map +1 -0
- package/dist/automation/messages.d.ts +113 -0
- package/dist/automation/messages.js +113 -0
- package/dist/automation/messages.js.map +1 -0
- package/dist/automation/record.d.ts +47 -0
- package/dist/automation/record.js +177 -0
- package/dist/automation/record.js.map +1 -0
- package/dist/automation/types.d.ts +143 -0
- package/dist/automation/when.d.ts +36 -0
- package/dist/automation/when.js +168 -0
- package/dist/automation/when.js.map +1 -0
- package/dist/blocks.d.ts +185 -0
- package/dist/browser.js +292 -0
- package/dist/browser.js.map +1 -0
- package/dist/call.d.ts +89 -0
- package/dist/call.js +218 -0
- package/dist/call.js.map +1 -0
- package/dist/channelParts.js +26 -0
- package/dist/channelParts.js.map +1 -0
- package/dist/classes.js +8 -3
- package/dist/classes.js.map +1 -0
- package/dist/client.d.ts +146 -54
- package/dist/client.js +204 -1
- package/dist/client.js.map +1 -0
- package/dist/conversationFiles.js +46 -0
- package/dist/conversationFiles.js.map +1 -0
- package/dist/credentials.d.ts +45 -0
- package/dist/credentials.js +98 -0
- package/dist/credentials.js.map +1 -0
- package/dist/dev.js +17 -0
- package/dist/dev.js.map +1 -0
- package/dist/es.d.ts +17 -0
- package/dist/es.js +382 -0
- package/dist/es.js.map +1 -0
- package/dist/files.d.ts +21 -0
- package/dist/files.js +214 -0
- package/dist/files.js.map +1 -0
- package/dist/frames.d.ts +115 -0
- package/dist/frames.js +219 -0
- package/dist/frames.js.map +1 -0
- package/dist/icons.js +29 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +63 -60
- package/dist/index.js +59 -45
- package/dist/kit/AudioPlayer.d.ts +20 -0
- package/dist/kit/AudioPlayer.js +116 -0
- package/dist/kit/AudioPlayer.js.map +1 -0
- package/dist/kit/Button.d.ts +29 -0
- package/dist/kit/Button.js +59 -0
- package/dist/kit/Button.js.map +1 -0
- package/dist/kit/Card.d.ts +16 -0
- package/dist/kit/Card.js +36 -0
- package/dist/kit/Card.js.map +1 -0
- package/dist/kit/Chart.js +152 -0
- package/dist/kit/Chart.js.map +1 -0
- package/dist/kit/Choices.d.ts +21 -0
- package/dist/kit/Choices.js +99 -0
- package/dist/kit/Choices.js.map +1 -0
- package/dist/kit/Combobox.d.ts +26 -0
- package/dist/kit/Combobox.js +190 -0
- package/dist/kit/Combobox.js.map +1 -0
- package/dist/kit/DateField.d.ts +17 -0
- package/dist/kit/DateField.js +133 -0
- package/dist/kit/DateField.js.map +1 -0
- package/dist/kit/Field.d.ts +40 -0
- package/dist/kit/Field.js +98 -0
- package/dist/kit/Field.js.map +1 -0
- package/dist/kit/FileField.d.ts +113 -0
- package/dist/kit/FileField.js +341 -0
- package/dist/kit/FileField.js.map +1 -0
- package/dist/kit/FileMark.d.ts +15 -0
- package/dist/kit/FileMark.js +39 -0
- package/dist/kit/FileMark.js.map +1 -0
- package/dist/kit/Inputs.d.ts +59 -0
- package/dist/kit/Inputs.js +205 -0
- package/dist/kit/Inputs.js.map +1 -0
- package/dist/kit/List.d.ts +47 -0
- package/dist/kit/List.js +85 -0
- package/dist/kit/List.js.map +1 -0
- package/dist/kit/Mark.d.ts +30 -0
- package/dist/kit/Mark.js +27 -0
- package/dist/kit/Mark.js.map +1 -0
- package/dist/kit/MarkStack.d.ts +15 -0
- package/dist/kit/MarkStack.js +26 -0
- package/dist/kit/MarkStack.js.map +1 -0
- package/dist/kit/Note.d.ts +11 -0
- package/dist/kit/Note.js +31 -0
- package/dist/kit/Note.js.map +1 -0
- package/dist/kit/Popover.js +90 -0
- package/dist/kit/Popover.js.map +1 -0
- package/dist/kit/RangeField.d.ts +14 -0
- package/dist/kit/RangeField.js +47 -0
- package/dist/kit/RangeField.js.map +1 -0
- package/dist/kit/RatingField.d.ts +14 -0
- package/dist/kit/RatingField.js +50 -0
- package/dist/kit/RatingField.js.map +1 -0
- package/dist/kit/Stat.d.ts +26 -0
- package/dist/kit/Stat.js +46 -0
- package/dist/kit/Stat.js.map +1 -0
- package/dist/kit/Switch.d.ts +14 -0
- package/dist/kit/Switch.js +21 -0
- package/dist/kit/Switch.js.map +1 -0
- package/dist/kit/Tag.d.ts +16 -0
- package/dist/kit/Tag.js +20 -0
- package/dist/kit/Tag.js.map +1 -0
- package/dist/kit/Tile.d.ts +34 -0
- package/dist/kit/Tile.js +52 -0
- package/dist/kit/Tile.js.map +1 -0
- package/dist/kit/TimeField.d.ts +31 -0
- package/dist/kit/TimeField.js +109 -0
- package/dist/kit/TimeField.js.map +1 -0
- package/dist/kit/context.d.ts +22 -0
- package/dist/kit/context.js +46 -0
- package/dist/kit/context.js.map +1 -0
- package/dist/kit/dates.d.ts +14 -0
- package/dist/kit/dates.js +129 -0
- package/dist/kit/dates.js.map +1 -0
- package/dist/kit/messages.d.ts +99 -0
- package/dist/kit/messages.js +66 -0
- package/dist/kit/messages.js.map +1 -0
- package/dist/kit/numbers.d.ts +12 -0
- package/dist/kit/numbers.js +40 -0
- package/dist/kit/numbers.js.map +1 -0
- package/dist/kit/options.d.ts +10 -0
- package/dist/kit/options.js +23 -0
- package/dist/kit/options.js.map +1 -0
- package/dist/kit/uploads.d.ts +42 -0
- package/dist/kit/uploads.js +165 -0
- package/dist/kit/uploads.js.map +1 -0
- package/dist/kit/waveform.js +76 -0
- package/dist/kit/waveform.js.map +1 -0
- package/dist/locale.d.ts +1 -0
- package/dist/locale.js +1 -0
- package/dist/markdown.js +84 -0
- package/dist/markdown.js.map +1 -0
- package/dist/marks.js +217 -0
- package/dist/marks.js.map +1 -0
- package/dist/reveal.js +48 -0
- package/dist/reveal.js.map +1 -0
- package/dist/stepGlyphs.js +62 -0
- package/dist/stepGlyphs.js.map +1 -0
- package/dist/surface/Form.js +264 -0
- package/dist/surface/Form.js.map +1 -0
- package/dist/surface/Markdown.js +42 -0
- package/dist/surface/Markdown.js.map +1 -0
- package/dist/surface/Surface.d.ts +31 -17
- package/dist/surface/Surface.js +480 -57
- package/dist/surface/Surface.js.map +1 -0
- package/dist/surface/scope.d.ts +32 -0
- package/dist/surface/scope.js +23 -0
- package/dist/surface/scope.js.map +1 -0
- package/dist/surface/values.d.ts +44 -0
- package/dist/surface/values.js +237 -0
- package/dist/surface/values.js.map +1 -0
- package/dist/tint.d.ts +10 -0
- package/dist/tint.js +19 -0
- package/dist/tint.js.map +1 -0
- package/dist/types.d.ts +541 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/dist/useAgentFace.d.ts +18 -0
- package/dist/useAgentFace.js +45 -0
- package/dist/useAgentFace.js.map +1 -0
- package/dist/useCall.d.ts +39 -0
- package/dist/useCall.js +273 -0
- package/dist/useCall.js.map +1 -0
- package/dist/useConversation.d.ts +77 -0
- package/dist/useConversation.js +523 -0
- package/dist/useConversation.js.map +1 -0
- package/dist/useDictation.d.ts +17 -0
- package/dist/useDictation.js +68 -0
- package/dist/useDictation.js.map +1 -0
- package/dist/useLive.d.ts +26 -0
- package/dist/useLive.js +88 -0
- package/dist/useLive.js.map +1 -0
- package/dist/usePolled.js +68 -0
- package/dist/usePolled.js.map +1 -0
- package/dist/voice/Orb.d.ts +10 -9
- package/dist/voice/Orb.js +43 -39
- package/dist/voice/Orb.js.map +1 -0
- package/dist/voice/StillOrb.js +33 -0
- package/dist/voice/StillOrb.js.map +1 -0
- package/dist/voice/WebGLOrb.js +98 -0
- package/dist/voice/WebGLOrb.js.map +1 -0
- package/dist/voice/fluidDots.js +161 -0
- package/dist/voice/fluidDots.js.map +1 -0
- package/dist/voice/motion.js +84 -0
- package/dist/voice/motion.js.map +1 -0
- package/dist/voice/orbs.d.ts +32 -0
- package/dist/voice/orbs.js +16 -0
- package/dist/voice/orbs.js.map +1 -0
- package/dist/voice/useReducedMotion.js +16 -16
- package/dist/voice/useReducedMotion.js.map +1 -0
- package/dist/voice/wave.js +116 -0
- package/dist/voice/wave.js.map +1 -0
- package/dist/voice/webgl.js +177 -0
- package/dist/voice/webgl.js.map +1 -0
- package/dist/widget.js +284 -8
- package/package.json +49 -39
- package/src/AgentAbout.tsx +1621 -0
- package/src/AgentCard.tsx +123 -0
- package/src/AgentChat.tsx +1812 -0
- package/src/AgentSpace.tsx +540 -0
- package/src/AgentTasks.tsx +163 -0
- package/src/BrowserView.tsx +442 -0
- package/src/FileView.tsx +620 -0
- package/src/Modes.tsx +112 -0
- package/src/VoiceCall.tsx +411 -0
- package/src/about.ts +355 -0
- package/src/agentIcons.ts +56 -0
- package/src/automation/Automation.tsx +308 -0
- package/src/automation/RunView.tsx +213 -0
- package/src/automation/cron.ts +196 -0
- package/src/automation/marks.tsx +144 -0
- package/src/automation/messages.ts +231 -0
- package/src/automation/record.ts +206 -0
- package/src/automation/types.ts +146 -0
- package/src/automation/when.ts +195 -0
- package/src/blocks.ts +249 -0
- package/src/browser.ts +334 -0
- package/src/call.ts +300 -0
- package/src/channelParts.ts +17 -0
- package/src/classes.ts +10 -0
- package/src/client.ts +397 -0
- package/src/conversationFiles.ts +54 -0
- package/src/credentials.ts +158 -0
- package/src/dev.ts +20 -0
- package/src/es.ts +423 -0
- package/src/files.ts +238 -0
- package/src/frames.ts +291 -0
- package/src/icons.tsx +49 -0
- package/src/index.ts +271 -0
- package/src/kit/AudioPlayer.tsx +129 -0
- package/src/kit/Button.tsx +97 -0
- package/src/kit/Card.tsx +47 -0
- package/src/kit/Chart.tsx +129 -0
- package/src/kit/Choices.tsx +131 -0
- package/src/kit/Combobox.tsx +247 -0
- package/src/kit/DateField.tsx +156 -0
- package/src/kit/Field.tsx +137 -0
- package/src/kit/FileField.tsx +492 -0
- package/src/kit/FileMark.tsx +56 -0
- package/src/kit/Inputs.tsx +250 -0
- package/src/kit/List.tsx +135 -0
- package/src/kit/Mark.tsx +64 -0
- package/src/kit/MarkStack.tsx +29 -0
- package/src/kit/Note.tsx +42 -0
- package/src/kit/Popover.tsx +121 -0
- package/src/kit/RangeField.tsx +53 -0
- package/src/kit/RatingField.tsx +62 -0
- package/src/kit/Stat.tsx +60 -0
- package/src/kit/Switch.tsx +28 -0
- package/src/kit/Tag.tsx +32 -0
- package/src/kit/Tile.tsx +74 -0
- package/src/kit/TimeField.tsx +157 -0
- package/src/kit/context.tsx +246 -0
- package/src/kit/dates.ts +150 -0
- package/src/kit/messages.ts +160 -0
- package/src/kit/numbers.ts +44 -0
- package/src/kit/options.ts +30 -0
- package/src/kit/uploads.ts +244 -0
- package/src/kit/waveform.ts +84 -0
- package/src/locale.ts +6 -0
- package/src/markdown.ts +69 -0
- package/src/marks.tsx +328 -0
- package/src/reveal.ts +52 -0
- package/src/stepGlyphs.ts +83 -0
- package/src/styles.css +6970 -0
- package/src/surface/Form.tsx +299 -0
- package/src/surface/Markdown.tsx +55 -0
- package/src/surface/Surface.tsx +605 -0
- package/src/surface/scope.ts +82 -0
- package/src/surface/values.ts +361 -0
- package/src/tint.ts +14 -0
- package/src/types.ts +604 -0
- package/src/useAgentFace.ts +47 -0
- package/src/useCall.ts +292 -0
- package/src/useConversation.ts +627 -0
- package/src/useDictation.ts +83 -0
- package/src/useLive.ts +115 -0
- package/src/usePolled.ts +60 -0
- package/src/voice/Orb.tsx +45 -0
- package/src/voice/StillOrb.tsx +29 -0
- package/src/voice/WebGLOrb.tsx +98 -0
- package/src/voice/fluidDots.tsx +171 -0
- package/src/voice/motion.ts +112 -0
- package/src/voice/orbs.ts +39 -0
- package/src/voice/useReducedMotion.ts +24 -0
- package/src/voice/wave.tsx +129 -0
- package/src/voice/webgl.ts +209 -0
- package/src/widget/css.d.ts +5 -0
- package/src/widget/element.tsx +535 -0
- package/src/widget/index.ts +10 -0
- package/src/widget/mount.ts +27 -0
- package/src/widget/widget.css +253 -0
- package/dist/SignalcoreProvider.d.ts +0 -113
- package/dist/SignalcoreProvider.js +0 -84
- package/dist/automations/AppMarks.d.ts +0 -11
- package/dist/automations/AppMarks.js +0 -18
- package/dist/automations/AutomationCard.d.ts +0 -27
- package/dist/automations/AutomationCard.js +0 -53
- package/dist/automations/AutomationsWindow.d.ts +0 -38
- package/dist/automations/AutomationsWindow.js +0 -57
- package/dist/automations/Card.d.ts +0 -46
- package/dist/automations/Card.js +0 -45
- package/dist/automations/ScheduleMarks.d.ts +0 -13
- package/dist/automations/ScheduleMarks.js +0 -24
- package/dist/automations/presentationIcons.d.ts +0 -7
- package/dist/automations/presentationIcons.js +0 -67
- package/dist/automations/schedule.d.ts +0 -25
- package/dist/automations/schedule.js +0 -59
- package/dist/automations/time.d.ts +0 -3
- package/dist/automations/time.js +0 -25
- package/dist/browser/BrowserView.d.ts +0 -43
- package/dist/browser/BrowserView.js +0 -94
- package/dist/browser/room.d.ts +0 -21
- package/dist/browser/room.js +0 -33
- package/dist/browser/useBrowserSession.d.ts +0 -17
- package/dist/browser/useBrowserSession.js +0 -67
- package/dist/builder/BuilderChat.d.ts +0 -32
- package/dist/builder/BuilderChat.js +0 -41
- package/dist/builder/BuilderTranscript.d.ts +0 -49
- package/dist/builder/BuilderTranscript.js +0 -62
- package/dist/builder/StatusLine.d.ts +0 -8
- package/dist/builder/StatusLine.js +0 -17
- package/dist/builder/answer.d.ts +0 -7
- package/dist/builder/answer.js +0 -8
- package/dist/builder/blocks.d.ts +0 -31
- package/dist/builder/blocks.js +0 -74
- package/dist/builder/items.d.ts +0 -15
- package/dist/builder/items.js +0 -21
- package/dist/builder/steps.d.ts +0 -20
- package/dist/builder/steps.js +0 -120
- package/dist/builder/time.d.ts +0 -4
- package/dist/builder/time.js +0 -24
- package/dist/builder/useBuildSession.d.ts +0 -36
- package/dist/builder/useBuildSession.js +0 -130
- package/dist/builder/workingOn.d.ts +0 -7
- package/dist/builder/workingOn.js +0 -15
- package/dist/chat/AgentChat.d.ts +0 -37
- package/dist/chat/AgentChat.js +0 -21
- package/dist/chat/ChatView.d.ts +0 -25
- package/dist/chat/ChatView.js +0 -34
- package/dist/chat/Composer.d.ts +0 -20
- package/dist/chat/Composer.js +0 -22
- package/dist/chat/MessageRow.d.ts +0 -22
- package/dist/chat/MessageRow.js +0 -32
- package/dist/chat/arrival.d.ts +0 -15
- package/dist/chat/arrival.js +0 -25
- package/dist/chat/history.d.ts +0 -24
- package/dist/chat/history.js +0 -45
- package/dist/chat/moments.d.ts +0 -25
- package/dist/chat/moments.js +0 -72
- package/dist/chat/types.d.ts +0 -12
- package/dist/chat/types.js +0 -1
- package/dist/chat/useComposer.d.ts +0 -46
- package/dist/chat/useComposer.js +0 -62
- package/dist/chat/useConversation.d.ts +0 -35
- package/dist/chat/useConversation.js +0 -71
- package/dist/chat/useStickToBottom.d.ts +0 -9
- package/dist/chat/useStickToBottom.js +0 -33
- package/dist/chat/useTurns.d.ts +0 -49
- package/dist/chat/useTurns.js +0 -111
- package/dist/classes.d.ts +0 -2
- package/dist/development.d.ts +0 -5
- package/dist/development.js +0 -8
- package/dist/flow/FlowWindow.d.ts +0 -42
- package/dist/flow/FlowWindow.js +0 -126
- package/dist/flow/index.d.ts +0 -16
- package/dist/flow/index.js +0 -16
- package/dist/flow/kinds.d.ts +0 -23
- package/dist/flow/kinds.js +0 -48
- package/dist/flow/map.d.ts +0 -44
- package/dist/flow/map.js +0 -225
- package/dist/flow/nodePaths.d.ts +0 -7
- package/dist/flow/nodePaths.js +0 -17
- package/dist/flow/relations.d.ts +0 -42
- package/dist/flow/relations.js +0 -174
- package/dist/host.d.ts +0 -124
- package/dist/host.js +0 -1
- package/dist/live/LiveView.d.ts +0 -28
- package/dist/live/LiveView.js +0 -55
- package/dist/live/capture.d.ts +0 -20
- package/dist/live/capture.js +0 -100
- package/dist/live/follow.d.ts +0 -26
- package/dist/live/follow.js +0 -72
- package/dist/live/paint.d.ts +0 -13
- package/dist/live/paint.js +0 -77
- package/dist/live/useLiveStream.d.ts +0 -16
- package/dist/live/useLiveStream.js +0 -57
- package/dist/look.d.ts +0 -33
- package/dist/look.js +0 -241
- package/dist/messages/en.d.ts +0 -3
- package/dist/messages/en.js +0 -251
- package/dist/messages/es.d.ts +0 -3
- package/dist/messages/es.js +0 -251
- package/dist/messages/index.d.ts +0 -16
- package/dist/messages/index.js +0 -33
- package/dist/messages/types.d.ts +0 -246
- package/dist/messages/types.js +0 -1
- package/dist/parts/Button.d.ts +0 -18
- package/dist/parts/Button.js +0 -17
- package/dist/parts/Icon.d.ts +0 -39
- package/dist/parts/Icon.js +0 -37
- package/dist/parts/Input.d.ts +0 -6
- package/dist/parts/Input.js +0 -11
- package/dist/parts/Spinner.d.ts +0 -2
- package/dist/parts/Spinner.js +0 -7
- package/dist/patterns.d.ts +0 -15
- package/dist/patterns.js +0 -5
- package/dist/presets.d.ts +0 -82
- package/dist/presets.js +0 -81
- package/dist/primitives.d.ts +0 -22
- package/dist/primitives.js +0 -58
- package/dist/request/RequestCard.d.ts +0 -34
- package/dist/request/RequestCard.js +0 -101
- package/dist/request/approval/ApprovalPreview.d.ts +0 -5
- package/dist/request/approval/ApprovalPreview.js +0 -27
- package/dist/request/approval/shapes.d.ts +0 -32
- package/dist/request/approval/shapes.js +0 -68
- package/dist/request/apps.d.ts +0 -11
- package/dist/request/apps.js +0 -27
- package/dist/request/cards.d.ts +0 -12
- package/dist/request/cards.js +0 -24
- package/dist/request/deliver.d.ts +0 -12
- package/dist/request/deliver.js +0 -21
- package/dist/request/handOver.d.ts +0 -18
- package/dist/request/handOver.js +0 -33
- package/dist/request/kinds/Approval.d.ts +0 -3
- package/dist/request/kinds/Approval.js +0 -9
- package/dist/request/kinds/Choice.d.ts +0 -3
- package/dist/request/kinds/Choice.js +0 -8
- package/dist/request/kinds/Connect.d.ts +0 -9
- package/dist/request/kinds/Connect.js +0 -119
- package/dist/request/kinds/FreeText.d.ts +0 -3
- package/dist/request/kinds/FreeText.js +0 -20
- package/dist/request/kinds/HandOver.d.ts +0 -13
- package/dist/request/kinds/HandOver.js +0 -20
- package/dist/request/kinds/Secret.d.ts +0 -7
- package/dist/request/kinds/Secret.js +0 -49
- package/dist/request/kinds/Upload.d.ts +0 -6
- package/dist/request/kinds/Upload.js +0 -47
- package/dist/request/types.d.ts +0 -83
- package/dist/request/types.js +0 -1
- package/dist/safeUrl.d.ts +0 -6
- package/dist/safeUrl.js +0 -8
- package/dist/stream/builder.d.ts +0 -176
- package/dist/stream/builder.js +0 -202
- package/dist/stream/reduce.d.ts +0 -51
- package/dist/stream/reduce.js +0 -58
- package/dist/stream/untilAborted.d.ts +0 -7
- package/dist/stream/untilAborted.js +0 -32
- package/dist/stream/useRunStream.d.ts +0 -26
- package/dist/stream/useRunStream.js +0 -137
- package/dist/styles.css +0 -2318
- package/dist/surface/HostNode.d.ts +0 -14
- package/dist/surface/HostNode.js +0 -30
- package/dist/surface/Node.d.ts +0 -7
- package/dist/surface/Node.js +0 -49
- package/dist/surface/SurfaceBoundary.d.ts +0 -26
- package/dist/surface/SurfaceBoundary.js +0 -20
- package/dist/surface/bindings.d.ts +0 -14
- package/dist/surface/bindings.js +0 -37
- package/dist/surface/check.d.ts +0 -27
- package/dist/surface/check.js +0 -102
- package/dist/surface/format.d.ts +0 -10
- package/dist/surface/format.js +0 -32
- package/dist/surface/hosts.d.ts +0 -6
- package/dist/surface/hosts.js +0 -11
- package/dist/surface/scene.d.ts +0 -21
- package/dist/surface/scene.js +0 -8
- package/dist/surface/templates/Browser.d.ts +0 -6
- package/dist/surface/templates/Browser.js +0 -11
- package/dist/surface/templates/Chart.d.ts +0 -6
- package/dist/surface/templates/Chart.js +0 -13
- package/dist/surface/templates/Choices.d.ts +0 -3
- package/dist/surface/templates/Choices.js +0 -12
- package/dist/surface/templates/Form.d.ts +0 -3
- package/dist/surface/templates/Form.js +0 -44
- package/dist/surface/templates/KeyValue.d.ts +0 -3
- package/dist/surface/templates/KeyValue.js +0 -7
- package/dist/surface/templates/Layout.d.ts +0 -5
- package/dist/surface/templates/Layout.js +0 -16
- package/dist/surface/templates/Live.d.ts +0 -6
- package/dist/surface/templates/Live.js +0 -9
- package/dist/surface/templates/Media.d.ts +0 -5
- package/dist/surface/templates/Media.js +0 -13
- package/dist/surface/templates/Slots.d.ts +0 -3
- package/dist/surface/templates/Slots.js +0 -19
- package/dist/surface/templates/Table.d.ts +0 -3
- package/dist/surface/templates/Table.js +0 -12
- package/dist/surface/templates/Text.d.ts +0 -4
- package/dist/surface/templates/Text.js +0 -15
- package/dist/surface/templates/index.d.ts +0 -7
- package/dist/surface/templates/index.js +0 -32
- package/dist/surface/types.d.ts +0 -68
- package/dist/surface/types.js +0 -6
- package/dist/theme.d.ts +0 -62
- package/dist/theme.js +0 -9
- package/dist/useTokens.d.ts +0 -7
- package/dist/useTokens.js +0 -41
- package/dist/voice/VoiceWindow.d.ts +0 -18
- package/dist/voice/VoiceWindow.js +0 -35
- package/dist/voice/index.d.ts +0 -13
- package/dist/voice/index.js +0 -12
- package/dist/voice/meter.d.ts +0 -16
- package/dist/voice/meter.js +0 -52
- package/dist/voice/orbColors.d.ts +0 -16
- package/dist/voice/orbColors.js +0 -75
- package/dist/voice/pushable.d.ts +0 -16
- package/dist/voice/pushable.js +0 -56
- package/dist/voice/useDictation.d.ts +0 -24
- package/dist/voice/useDictation.js +0 -60
- package/dist/voice/useReducedMotion.d.ts +0 -5
- package/dist/voice/useVoice.d.ts +0 -70
- package/dist/voice/useVoice.js +0 -197
- package/dist/voice/useVoicePrimitives.d.ts +0 -7
- package/dist/voice/useVoicePrimitives.js +0 -11
- package/dist/voice/voice.d.ts +0 -55
- package/dist/voice/voice.js +0 -9
- package/dist/voice/webSpeech.d.ts +0 -33
- package/dist/voice/webSpeech.js +0 -258
- package/dist/widget.js.map +0 -1
- package/dist/windows/AgentSpace.d.ts +0 -78
- package/dist/windows/AgentSpace.js +0 -135
- package/dist/windows/Captions.d.ts +0 -13
- package/dist/windows/Captions.js +0 -22
- package/dist/windows/Dock.d.ts +0 -37
- package/dist/windows/Dock.js +0 -22
- package/dist/windows/Journal.d.ts +0 -15
- package/dist/windows/Journal.js +0 -19
- package/dist/windows/KindMark.d.ts +0 -7
- package/dist/windows/KindMark.js +0 -31
- package/dist/windows/Pending.d.ts +0 -8
- package/dist/windows/Pending.js +0 -17
- package/dist/windows/Stage.d.ts +0 -18
- package/dist/windows/Stage.js +0 -21
- package/dist/windows/StatusLabel.d.ts +0 -9
- package/dist/windows/StatusLabel.js +0 -7
- package/dist/windows/Strip.d.ts +0 -17
- package/dist/windows/Strip.js +0 -42
- package/dist/windows/SurfaceWindow.d.ts +0 -20
- package/dist/windows/SurfaceWindow.js +0 -12
- package/dist/windows/WindowFrame.d.ts +0 -23
- package/dist/windows/WindowFrame.js +0 -22
- package/dist/windows/hearing.d.ts +0 -11
- package/dist/windows/hearing.js +0 -26
- package/dist/windows/kinds.d.ts +0 -47
- package/dist/windows/kinds.js +0 -28
- package/dist/windows/reduce.d.ts +0 -98
- package/dist/windows/reduce.js +0 -151
- package/dist/windows/registry.d.ts +0 -18
- package/dist/windows/registry.js +0 -61
- package/dist/windows/reveal.d.ts +0 -9
- package/dist/windows/reveal.js +0 -6
- package/dist/windows/space.d.ts +0 -21
- package/dist/windows/space.js +0 -6
- package/dist/windows/status.d.ts +0 -11
- package/dist/windows/status.js +0 -30
- package/dist/windows/types.d.ts +0 -15
- package/dist/windows/types.js +0 -1
- package/dist/windows/useLoaded.d.ts +0 -44
- package/dist/windows/useLoaded.js +0 -58
- package/dist/windows/useUnread.d.ts +0 -7
- package/dist/windows/useUnread.js +0 -21
- package/dist/windows/useWindows.d.ts +0 -70
- package/dist/windows/useWindows.js +0 -60
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
//#region src/useDictation.ts
|
|
3
|
+
/**
|
|
4
|
+
* Dictation in the composer: a press opens the microphone, the next one closes it and hands the
|
|
5
|
+
* recording to the host's `dictate`, whose words go to `onWords`. Without `dictate`, or in a
|
|
6
|
+
* browser that cannot record, it is not `available`. Leaving mid-recording stops the microphone.
|
|
7
|
+
*/
|
|
8
|
+
function useDictation(dictate, onWords) {
|
|
9
|
+
const [state, setState] = useState("idle");
|
|
10
|
+
const recorder = useRef(null);
|
|
11
|
+
const said = useRef(onWords);
|
|
12
|
+
said.current = onWords;
|
|
13
|
+
const available = dictate !== void 0 && typeof MediaRecorder !== "undefined" && typeof navigator !== "undefined" && navigator.mediaDevices !== void 0;
|
|
14
|
+
useEffect(() => () => {
|
|
15
|
+
const open = recorder.current;
|
|
16
|
+
recorder.current = null;
|
|
17
|
+
if (open !== null && open.state !== "inactive") {
|
|
18
|
+
open.onstop = null;
|
|
19
|
+
open.stop();
|
|
20
|
+
open.stream.getTracks().forEach((track) => {
|
|
21
|
+
track.stop();
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}, []);
|
|
25
|
+
const start = useCallback(async () => {
|
|
26
|
+
if (dictate === void 0) return;
|
|
27
|
+
let stream;
|
|
28
|
+
try {
|
|
29
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
30
|
+
} catch {
|
|
31
|
+
setState("failed");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const open = new MediaRecorder(stream);
|
|
35
|
+
const chunks = [];
|
|
36
|
+
open.ondataavailable = (event) => {
|
|
37
|
+
if (event.data.size > 0) chunks.push(event.data);
|
|
38
|
+
};
|
|
39
|
+
open.onstop = () => {
|
|
40
|
+
stream.getTracks().forEach((track) => {
|
|
41
|
+
track.stop();
|
|
42
|
+
});
|
|
43
|
+
recorder.current = null;
|
|
44
|
+
setState("writing");
|
|
45
|
+
dictate(new Blob(chunks, { type: open.mimeType || "audio/webm" })).then((words) => {
|
|
46
|
+
if (words !== "") said.current(words);
|
|
47
|
+
setState("idle");
|
|
48
|
+
}).catch(() => {
|
|
49
|
+
setState("failed");
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
recorder.current = open;
|
|
53
|
+
open.start();
|
|
54
|
+
setState("listening");
|
|
55
|
+
}, [dictate]);
|
|
56
|
+
return {
|
|
57
|
+
available,
|
|
58
|
+
state,
|
|
59
|
+
toggle: useCallback(() => {
|
|
60
|
+
if (state === "listening") recorder.current?.stop();
|
|
61
|
+
else if (state === "idle" || state === "failed") start();
|
|
62
|
+
}, [state, start])
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { useDictation };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=useDictation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDictation.js","names":[],"sources":["../src/useDictation.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\n/** Turns a recording into words: the host's (its server's speech to text). */\nexport type Dictate = (audio: Blob) => Promise<string>;\n\n/** Where a dictation is: nothing, the microphone open, the words on their way, or refused. */\nexport type Dictation = \"idle\" | \"listening\" | \"writing\" | \"failed\";\n\n/**\n * Dictation in the composer: a press opens the microphone, the next one closes it and hands the\n * recording to the host's `dictate`, whose words go to `onWords`. Without `dictate`, or in a\n * browser that cannot record, it is not `available`. Leaving mid-recording stops the microphone.\n */\nexport function useDictation(\n dictate: Dictate | undefined,\n onWords: (words: string) => void,\n): { available: boolean; state: Dictation; toggle: () => void } {\n const [state, setState] = useState<Dictation>(\"idle\");\n const recorder = useRef<MediaRecorder | null>(null);\n const said = useRef(onWords);\n said.current = onWords;\n const available =\n dictate !== undefined &&\n typeof MediaRecorder !== \"undefined\" &&\n typeof navigator !== \"undefined\" &&\n navigator.mediaDevices !== undefined;\n\n useEffect(\n () => () => {\n const open = recorder.current;\n recorder.current = null;\n if (open !== null && open.state !== \"inactive\") {\n open.onstop = null;\n open.stop();\n open.stream.getTracks().forEach((track) => {\n track.stop();\n });\n }\n },\n [],\n );\n\n const start = useCallback(async () => {\n if (dictate === undefined) return;\n let stream: MediaStream;\n try {\n stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n } catch {\n setState(\"failed\");\n return;\n }\n const open = new MediaRecorder(stream);\n const chunks: Blob[] = [];\n open.ondataavailable = (event) => {\n if (event.data.size > 0) chunks.push(event.data);\n };\n open.onstop = () => {\n stream.getTracks().forEach((track) => {\n track.stop();\n });\n recorder.current = null;\n setState(\"writing\");\n dictate(new Blob(chunks, { type: open.mimeType || \"audio/webm\" }))\n .then((words) => {\n if (words !== \"\") said.current(words);\n setState(\"idle\");\n })\n .catch(() => {\n setState(\"failed\");\n });\n };\n recorder.current = open;\n open.start();\n setState(\"listening\");\n }, [dictate]);\n\n const toggle = useCallback(() => {\n if (state === \"listening\") recorder.current?.stop();\n else if (state === \"idle\" || state === \"failed\") void start();\n }, [state, start]);\n\n return { available, state, toggle };\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,aACd,SACA,SAC8D;CAC9D,MAAM,CAAC,OAAO,YAAY,SAAoB,MAAM;CACpD,MAAM,WAAW,OAA6B,IAAI;CAClD,MAAM,OAAO,OAAO,OAAO;CAC3B,KAAK,UAAU;CACf,MAAM,YACJ,YAAY,KAAA,KACZ,OAAO,kBAAkB,eACzB,OAAO,cAAc,eACrB,UAAU,iBAAiB,KAAA;CAE7B,sBACc;EACV,MAAM,OAAO,SAAS;EACtB,SAAS,UAAU;EACnB,IAAI,SAAS,QAAQ,KAAK,UAAU,YAAY;GAC9C,KAAK,SAAS;GACd,KAAK,KAAK;GACV,KAAK,OAAO,UAAU,CAAC,CAAC,SAAS,UAAU;IACzC,MAAM,KAAK;GACb,CAAC;EACH;CACF,GACA,CAAC,CACH;CAEA,MAAM,QAAQ,YAAY,YAAY;EACpC,IAAI,YAAY,KAAA,GAAW;EAC3B,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,UAAU,aAAa,aAAa,EAAE,OAAO,KAAK,CAAC;EACpE,QAAQ;GACN,SAAS,QAAQ;GACjB;EACF;EACA,MAAM,OAAO,IAAI,cAAc,MAAM;EACrC,MAAM,SAAiB,CAAC;EACxB,KAAK,mBAAmB,UAAU;GAChC,IAAI,MAAM,KAAK,OAAO,GAAG,OAAO,KAAK,MAAM,IAAI;EACjD;EACA,KAAK,eAAe;GAClB,OAAO,UAAU,CAAC,CAAC,SAAS,UAAU;IACpC,MAAM,KAAK;GACb,CAAC;GACD,SAAS,UAAU;GACnB,SAAS,SAAS;GAClB,QAAQ,IAAI,KAAK,QAAQ,EAAE,MAAM,KAAK,YAAY,aAAa,CAAC,CAAC,CAAC,CAC/D,MAAM,UAAU;IACf,IAAI,UAAU,IAAI,KAAK,QAAQ,KAAK;IACpC,SAAS,MAAM;GACjB,CAAC,CAAC,CACD,YAAY;IACX,SAAS,QAAQ;GACnB,CAAC;EACL;EACA,SAAS,UAAU;EACnB,KAAK,MAAM;EACX,SAAS,WAAW;CACtB,GAAG,CAAC,OAAO,CAAC;CAOZ,OAAO;EAAE;EAAW;EAAO,QALZ,kBAAkB;GAC/B,IAAI,UAAU,aAAa,SAAS,SAAS,KAAK;QAC7C,IAAI,UAAU,UAAU,UAAU,UAAU,MAAW;EAC9D,GAAG,CAAC,OAAO,KAAK,CAEgB;CAAE;AACpC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Client } from "./client.js";
|
|
2
|
+
import { Frame, UpFrame } from "./frames.js";
|
|
3
|
+
//#region src/useLive.d.ts
|
|
4
|
+
export interface LiveHandlers {
|
|
5
|
+
/** Every frame the socket sends, as it comes. */
|
|
6
|
+
onFrame: (frame: Frame) => void;
|
|
7
|
+
/** The socket is open; `again` when it had been before, so what was stored meanwhile can be read. */
|
|
8
|
+
onOpen?: ((again: boolean) => void) | undefined;
|
|
9
|
+
}
|
|
10
|
+
/** A conversation's socket: whether it is open, and the way to speak up it. */
|
|
11
|
+
export interface Live {
|
|
12
|
+
open: boolean;
|
|
13
|
+
/** Sends a frame up; false when the socket is not open. */
|
|
14
|
+
send: (frame: UpFrame) => boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The socket of conversation `conversationId`, held for as long as the component lives: frames
|
|
18
|
+
* down to `onFrame`, `send` up. A turn runs on the server apart from the socket, so a socket that
|
|
19
|
+
* drops opens again, waiting longer each time; `onOpen` then says it is not the first time, and a
|
|
20
|
+
* turn still running is told again from its start. A socket that could not open may have carried
|
|
21
|
+
* a token that expired: the next try asks the client for a fresh one, once until one opens. The
|
|
22
|
+
* raw layer: what a host draws its own things over.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useLive(client: Client, conversationId: string, { onFrame, onOpen }: LiveHandlers): Live;
|
|
25
|
+
//#endregion
|
|
26
|
+
//# sourceMappingURL=useLive.d.ts.map
|
package/dist/useLive.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { frameOf } from "./frames.js";
|
|
2
|
+
import { useEffect, useEffectEvent, useRef, useState } from "react";
|
|
3
|
+
//#region src/useLive.ts
|
|
4
|
+
/** How long to wait before trying again after the nth failure in a row: 1s, 2s, 4s, 8s, then 10s. */
|
|
5
|
+
function retryDelay(failures) {
|
|
6
|
+
return Math.min(1e3 * 2 ** failures, 1e4);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The socket of conversation `conversationId`, held for as long as the component lives: frames
|
|
10
|
+
* down to `onFrame`, `send` up. A turn runs on the server apart from the socket, so a socket that
|
|
11
|
+
* drops opens again, waiting longer each time; `onOpen` then says it is not the first time, and a
|
|
12
|
+
* turn still running is told again from its start. A socket that could not open may have carried
|
|
13
|
+
* a token that expired: the next try asks the client for a fresh one, once until one opens. The
|
|
14
|
+
* raw layer: what a host draws its own things over.
|
|
15
|
+
*/
|
|
16
|
+
function useLive(client, conversationId, { onFrame, onOpen }) {
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const socket = useRef(null);
|
|
19
|
+
const frame = useEffectEvent(onFrame);
|
|
20
|
+
const opened = useEffectEvent((again) => onOpen?.(again));
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
let current = null;
|
|
23
|
+
let failures = 0;
|
|
24
|
+
let before = false;
|
|
25
|
+
let stopped = false;
|
|
26
|
+
let fresh = false;
|
|
27
|
+
let renewed = false;
|
|
28
|
+
let retry;
|
|
29
|
+
const again = () => {
|
|
30
|
+
setOpen(false);
|
|
31
|
+
retry = setTimeout(connect, retryDelay(failures));
|
|
32
|
+
failures += 1;
|
|
33
|
+
};
|
|
34
|
+
const open = (url) => {
|
|
35
|
+
const live = new WebSocket(url);
|
|
36
|
+
let opens = false;
|
|
37
|
+
current = live;
|
|
38
|
+
socket.current = live;
|
|
39
|
+
live.onopen = () => {
|
|
40
|
+
opens = true;
|
|
41
|
+
failures = 0;
|
|
42
|
+
renewed = false;
|
|
43
|
+
setOpen(true);
|
|
44
|
+
opened(before);
|
|
45
|
+
before = true;
|
|
46
|
+
};
|
|
47
|
+
live.onmessage = (event) => {
|
|
48
|
+
const next = frameOf(event.data);
|
|
49
|
+
if (next) frame(next);
|
|
50
|
+
};
|
|
51
|
+
live.onclose = () => {
|
|
52
|
+
if (stopped) return;
|
|
53
|
+
fresh = !opens && !renewed;
|
|
54
|
+
again();
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
function connect() {
|
|
58
|
+
renewed ||= fresh;
|
|
59
|
+
client.liveUrl(conversationId, { fresh }).then((url) => {
|
|
60
|
+
if (!stopped) open(url);
|
|
61
|
+
}, () => {
|
|
62
|
+
if (!stopped) again();
|
|
63
|
+
});
|
|
64
|
+
fresh = false;
|
|
65
|
+
}
|
|
66
|
+
connect();
|
|
67
|
+
return () => {
|
|
68
|
+
stopped = true;
|
|
69
|
+
clearTimeout(retry);
|
|
70
|
+
socket.current = null;
|
|
71
|
+
current?.close();
|
|
72
|
+
};
|
|
73
|
+
}, [client, conversationId]);
|
|
74
|
+
const send = (up) => {
|
|
75
|
+
const live = socket.current;
|
|
76
|
+
if (live?.readyState !== WebSocket.OPEN) return false;
|
|
77
|
+
live.send(JSON.stringify(up));
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
open,
|
|
82
|
+
send
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
export { retryDelay, useLive };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=useLive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLive.js","names":[],"sources":["../src/useLive.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from \"react\";\n\nimport type { Client } from \"./client\";\nimport { frameOf, type Frame, type UpFrame } from \"./frames\";\n\nexport interface LiveHandlers {\n /** Every frame the socket sends, as it comes. */\n onFrame: (frame: Frame) => void;\n /** The socket is open; `again` when it had been before, so what was stored meanwhile can be read. */\n onOpen?: ((again: boolean) => void) | undefined;\n}\n\n/** A conversation's socket: whether it is open, and the way to speak up it. */\nexport interface Live {\n open: boolean;\n /** Sends a frame up; false when the socket is not open. */\n send: (frame: UpFrame) => boolean;\n}\n\n/** How long to wait before trying again after the nth failure in a row: 1s, 2s, 4s, 8s, then 10s. */\nexport function retryDelay(failures: number): number {\n return Math.min(1000 * 2 ** failures, 10_000);\n}\n\n/**\n * The socket of conversation `conversationId`, held for as long as the component lives: frames\n * down to `onFrame`, `send` up. A turn runs on the server apart from the socket, so a socket that\n * drops opens again, waiting longer each time; `onOpen` then says it is not the first time, and a\n * turn still running is told again from its start. A socket that could not open may have carried\n * a token that expired: the next try asks the client for a fresh one, once until one opens. The\n * raw layer: what a host draws its own things over.\n */\nexport function useLive(\n client: Client,\n conversationId: string,\n { onFrame, onOpen }: LiveHandlers,\n): Live {\n const [open, setOpen] = useState(false);\n const socket = useRef<WebSocket | null>(null);\n // The handlers as the host last gave them, without the socket opening again for each render.\n const frame = useEffectEvent(onFrame);\n const opened = useEffectEvent((again: boolean) => onOpen?.(again));\n\n useEffect(() => {\n let current: WebSocket | null = null;\n let failures = 0;\n let before = false;\n let stopped = false;\n // Whether the next try asks for a fresh credential: once after a socket that never opened.\n let fresh = false;\n let renewed = false;\n let retry: ReturnType<typeof setTimeout> | undefined;\n\n const again = () => {\n setOpen(false);\n retry = setTimeout(connect, retryDelay(failures));\n failures += 1;\n };\n\n const open = (url: string) => {\n const live = new WebSocket(url);\n let opens = false;\n current = live;\n socket.current = live;\n live.onopen = () => {\n opens = true;\n failures = 0;\n renewed = false;\n setOpen(true);\n opened(before);\n before = true;\n };\n live.onmessage = (event: MessageEvent) => {\n const next = frameOf(event.data);\n if (next) frame(next);\n };\n live.onclose = () => {\n if (stopped) return;\n fresh = !opens && !renewed;\n again();\n };\n };\n\n function connect() {\n renewed ||= fresh;\n client.liveUrl(conversationId, { fresh }).then(\n (url) => {\n if (!stopped) open(url);\n },\n // No address (the host's backend gave no token): tried again like a socket that dropped.\n () => {\n if (!stopped) again();\n },\n );\n fresh = false;\n }\n\n connect();\n return () => {\n stopped = true;\n clearTimeout(retry);\n socket.current = null;\n current?.close();\n };\n }, [client, conversationId]);\n\n const send = (up: UpFrame): boolean => {\n const live = socket.current;\n if (live?.readyState !== WebSocket.OPEN) return false;\n live.send(JSON.stringify(up));\n return true;\n };\n\n return { open, send };\n}\n"],"mappings":";;;;AAoBA,SAAgB,WAAW,UAA0B;CACnD,OAAO,KAAK,IAAI,MAAO,KAAK,UAAU,GAAM;AAC9C;;;;;;;;;AAUA,SAAgB,QACd,QACA,gBACA,EAAE,SAAS,UACL;CACN,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,SAAS,OAAyB,IAAI;CAE5C,MAAM,QAAQ,eAAe,OAAO;CACpC,MAAM,SAAS,gBAAgB,UAAmB,SAAS,KAAK,CAAC;CAEjE,gBAAgB;EACd,IAAI,UAA4B;EAChC,IAAI,WAAW;EACf,IAAI,SAAS;EACb,IAAI,UAAU;EAEd,IAAI,QAAQ;EACZ,IAAI,UAAU;EACd,IAAI;EAEJ,MAAM,cAAc;GAClB,QAAQ,KAAK;GACb,QAAQ,WAAW,SAAS,WAAW,QAAQ,CAAC;GAChD,YAAY;EACd;EAEA,MAAM,QAAQ,QAAgB;GAC5B,MAAM,OAAO,IAAI,UAAU,GAAG;GAC9B,IAAI,QAAQ;GACZ,UAAU;GACV,OAAO,UAAU;GACjB,KAAK,eAAe;IAClB,QAAQ;IACR,WAAW;IACX,UAAU;IACV,QAAQ,IAAI;IACZ,OAAO,MAAM;IACb,SAAS;GACX;GACA,KAAK,aAAa,UAAwB;IACxC,MAAM,OAAO,QAAQ,MAAM,IAAI;IAC/B,IAAI,MAAM,MAAM,IAAI;GACtB;GACA,KAAK,gBAAgB;IACnB,IAAI,SAAS;IACb,QAAQ,CAAC,SAAS,CAAC;IACnB,MAAM;GACR;EACF;EAEA,SAAS,UAAU;GACjB,YAAY;GACZ,OAAO,QAAQ,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,MACvC,QAAQ;IACP,IAAI,CAAC,SAAS,KAAK,GAAG;GACxB,SAEM;IACJ,IAAI,CAAC,SAAS,MAAM;GACtB,CACF;GACA,QAAQ;EACV;EAEA,QAAQ;EACR,aAAa;GACX,UAAU;GACV,aAAa,KAAK;GAClB,OAAO,UAAU;GACjB,SAAS,MAAM;EACjB;CACF,GAAG,CAAC,QAAQ,cAAc,CAAC;CAE3B,MAAM,QAAQ,OAAyB;EACrC,MAAM,OAAO,OAAO;EACpB,IAAI,MAAM,eAAe,UAAU,MAAM,OAAO;EAChD,KAAK,KAAK,KAAK,UAAU,EAAE,CAAC;EAC5B,OAAO;CACT;CAEA,OAAO;EAAE;EAAM;CAAK;AACtB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ApiError } from "./client.js";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
//#region src/usePolled.ts
|
|
4
|
+
/** How often something still moving (a run under way) is read again. */
|
|
5
|
+
const POLL_MS = 3e3;
|
|
6
|
+
/**
|
|
7
|
+
* Reads `load` when `key` changes, and again every `POLL_MS` while `moving` says what it gave is
|
|
8
|
+
* still moving (a run under way). What was read stays while a new read is on its way, so nothing
|
|
9
|
+
* flickers; a 404 reads as gone.
|
|
10
|
+
*/
|
|
11
|
+
function usePolled(load, key, moving) {
|
|
12
|
+
const [polled, setPolled] = useState({
|
|
13
|
+
key,
|
|
14
|
+
value: null,
|
|
15
|
+
problem: null,
|
|
16
|
+
gone: false
|
|
17
|
+
});
|
|
18
|
+
const latest = useRef({
|
|
19
|
+
load,
|
|
20
|
+
moving
|
|
21
|
+
});
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
latest.current = {
|
|
24
|
+
load,
|
|
25
|
+
moving
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
let stopped = false;
|
|
30
|
+
let timer;
|
|
31
|
+
const read = async () => {
|
|
32
|
+
try {
|
|
33
|
+
const value = await latest.current.load();
|
|
34
|
+
if (stopped) return;
|
|
35
|
+
setPolled({
|
|
36
|
+
key,
|
|
37
|
+
value,
|
|
38
|
+
problem: null,
|
|
39
|
+
gone: false
|
|
40
|
+
});
|
|
41
|
+
if (latest.current.moving(value)) timer = setTimeout(() => void read(), POLL_MS);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (stopped) return;
|
|
44
|
+
const gone = error instanceof ApiError && error.status === 404;
|
|
45
|
+
setPolled((last) => ({
|
|
46
|
+
...last,
|
|
47
|
+
key,
|
|
48
|
+
problem: gone ? null : error,
|
|
49
|
+
gone
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
read();
|
|
54
|
+
return () => {
|
|
55
|
+
stopped = true;
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
};
|
|
58
|
+
}, [key]);
|
|
59
|
+
return polled.key === key ? polled : {
|
|
60
|
+
value: null,
|
|
61
|
+
problem: null,
|
|
62
|
+
gone: false
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
export { POLL_MS, usePolled };
|
|
67
|
+
|
|
68
|
+
//# sourceMappingURL=usePolled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePolled.js","names":[],"sources":["../src/usePolled.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport { ApiError } from \"./client\";\n\n/** What a read gave: the value once it came, why it failed, or that it is no longer there. */\nexport interface Polled<T> {\n value: T | null;\n problem: unknown;\n gone: boolean;\n}\n\n/** How often something still moving (a run under way) is read again. */\nexport const POLL_MS = 3000;\n\n/**\n * Reads `load` when `key` changes, and again every `POLL_MS` while `moving` says what it gave is\n * still moving (a run under way). What was read stays while a new read is on its way, so nothing\n * flickers; a 404 reads as gone.\n */\nexport function usePolled<T>(\n load: () => Promise<T>,\n key: string,\n moving: (value: T) => boolean,\n): Polled<T> {\n const [polled, setPolled] = useState<Polled<T> & { key: string }>({\n key,\n value: null,\n problem: null,\n gone: false,\n });\n const latest = useRef({ load, moving });\n useEffect(() => {\n latest.current = { load, moving };\n });\n\n useEffect(() => {\n let stopped = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const read = async () => {\n try {\n const value = await latest.current.load();\n if (stopped) return;\n setPolled({ key, value, problem: null, gone: false });\n if (latest.current.moving(value)) timer = setTimeout(() => void read(), POLL_MS);\n } catch (error) {\n if (stopped) return;\n const gone = error instanceof ApiError && error.status === 404;\n setPolled((last) => ({ ...last, key, problem: gone ? null : error, gone }));\n }\n };\n void read();\n return () => {\n stopped = true;\n clearTimeout(timer);\n };\n }, [key]);\n\n // Another key's value is not this one's: until its own comes, nothing is shown.\n return polled.key === key ? polled : { value: null, problem: null, gone: false };\n}\n"],"mappings":";;;;AAYA,MAAa,UAAU;;;;;;AAOvB,SAAgB,UACd,MACA,KACA,QACW;CACX,MAAM,CAAC,QAAQ,aAAa,SAAsC;EAChE;EACA,OAAO;EACP,SAAS;EACT,MAAM;CACR,CAAC;CACD,MAAM,SAAS,OAAO;EAAE;EAAM;CAAO,CAAC;CACtC,gBAAgB;EACd,OAAO,UAAU;GAAE;GAAM;EAAO;CAClC,CAAC;CAED,gBAAgB;EACd,IAAI,UAAU;EACd,IAAI;EACJ,MAAM,OAAO,YAAY;GACvB,IAAI;IACF,MAAM,QAAQ,MAAM,OAAO,QAAQ,KAAK;IACxC,IAAI,SAAS;IACb,UAAU;KAAE;KAAK;KAAO,SAAS;KAAM,MAAM;IAAM,CAAC;IACpD,IAAI,OAAO,QAAQ,OAAO,KAAK,GAAG,QAAQ,iBAAiB,KAAK,KAAK,GAAG,OAAO;GACjF,SAAS,OAAO;IACd,IAAI,SAAS;IACb,MAAM,OAAO,iBAAiB,YAAY,MAAM,WAAW;IAC3D,WAAW,UAAU;KAAE,GAAG;KAAM;KAAK,SAAS,OAAO,OAAO;KAAO;IAAK,EAAE;GAC5E;EACF;EACA,KAAU;EACV,aAAa;GACX,UAAU;GACV,aAAa,KAAK;EACpB;CACF,GAAG,CAAC,GAAG,CAAC;CAGR,OAAO,OAAO,QAAQ,MAAM,SAAS;EAAE,OAAO;EAAM,SAAS;EAAM,MAAM;CAAM;AACjF"}
|
package/dist/voice/Orb.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { OrbProps } from "./orbs.js";
|
|
2
|
+
//#region src/voice/Orb.d.ts
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* which says the state by its outline (thin at rest, solid while listening, dashed while
|
|
9
|
-
* thinking, double while speaking) and by the words the window puts under it, never by movement.
|
|
4
|
+
* The orb of a voice conversation with an agent: a shape that shows where it stands and how loud
|
|
5
|
+
* it is, in one of two styles (`wave`, the default; `fluid-dots`). Both follow the level while
|
|
6
|
+
* listening and speaking, rest when nothing happens, and stand still under
|
|
7
|
+
* `prefers-reduced-motion`, one frame per state. They are shaders: each paints its own colours,
|
|
8
|
+
* on a transparent canvas. Where WebGL is missing or lost, a still disc in a ring takes its place.
|
|
10
9
|
*/
|
|
11
|
-
export declare function Orb({
|
|
10
|
+
export declare function Orb({ style, ...props }: OrbProps): import("react").JSX.Element;
|
|
11
|
+
//#endregion
|
|
12
|
+
//# sourceMappingURL=Orb.d.ts.map
|
package/dist/voice/Orb.js
CHANGED
|
@@ -1,42 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { useReducedMotion } from "./useReducedMotion.js";
|
|
7
|
-
/** The diameter when the voice window does not say: room for the orb and the glow it gives off. */
|
|
8
|
-
const SIZE = 200;
|
|
1
|
+
import { joined, useParts } from "../kit/context.js";
|
|
2
|
+
import { DEFAULT_ORB } from "./orbs.js";
|
|
3
|
+
import { Suspense, lazy } from "react";
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
//#region src/voice/Orb.tsx
|
|
9
6
|
/**
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
* Each style is a module of its own, loaded when an orb of that style is first drawn: a host that
|
|
8
|
+
* never calls loads none of them, and one that does loads the one it uses (a fragment shader
|
|
9
|
+
* each, and the little WebGL they share).
|
|
10
|
+
*/
|
|
11
|
+
const STYLES = {
|
|
12
|
+
wave: lazy(() => import("./wave.js")),
|
|
13
|
+
"fluid-dots": lazy(() => import("./fluidDots.js"))
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* The orb of a voice conversation with an agent: a shape that shows where it stands and how loud
|
|
17
|
+
* it is, in one of two styles (`wave`, the default; `fluid-dots`). Both follow the level while
|
|
18
|
+
* listening and speaking, rest when nothing happens, and stand still under
|
|
19
|
+
* `prefers-reduced-motion`, one frame per state. They are shaders: each paints its own colours,
|
|
20
|
+
* on a transparent canvas. Where WebGL is missing or lost, a still disc in a ring takes its place.
|
|
21
|
+
*/
|
|
22
|
+
function Orb({ style = DEFAULT_ORB, ...props }) {
|
|
23
|
+
const Style = STYLES[style] ?? STYLES["wave"];
|
|
24
|
+
return /* @__PURE__ */ jsx(Suspense, {
|
|
25
|
+
fallback: /* @__PURE__ */ jsx(Waiting, { ...props }),
|
|
26
|
+
children: /* @__PURE__ */ jsx(Style, { ...props })
|
|
27
|
+
});
|
|
29
28
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
/** What stands where the orb will be while its style loads: its box, named, with nothing in it. */
|
|
30
|
+
function Waiting({ state, size = 200, label, className }) {
|
|
31
|
+
const part = useParts();
|
|
32
|
+
return /* @__PURE__ */ jsx("div", {
|
|
33
|
+
role: "img",
|
|
34
|
+
"aria-label": label,
|
|
35
|
+
part: "orb",
|
|
36
|
+
className: joined(part("sc-orb", `sc-orb--${state}`, "sc-orb--loading"), className),
|
|
37
|
+
style: {
|
|
38
|
+
width: size,
|
|
39
|
+
height: size
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
42
|
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { Orb };
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=Orb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Orb.js","names":[],"sources":["../../src/voice/Orb.tsx"],"sourcesContent":["import { lazy, Suspense, type ComponentType } from \"react\";\n\nimport { joined, useParts } from \"../kit/context\";\nimport { DEFAULT_ORB, ORB_SIZE, type OrbProps, type OrbStyle } from \"./orbs\";\n\n/**\n * Each style is a module of its own, loaded when an orb of that style is first drawn: a host that\n * never calls loads none of them, and one that does loads the one it uses (a fragment shader\n * each, and the little WebGL they share).\n */\nconst STYLES: Readonly<Record<OrbStyle, ComponentType<OrbProps>>> = {\n wave: lazy(() => import(\"./wave\")),\n \"fluid-dots\": lazy(() => import(\"./fluidDots\")),\n};\n\n/**\n * The orb of a voice conversation with an agent: a shape that shows where it stands and how loud\n * it is, in one of two styles (`wave`, the default; `fluid-dots`). Both follow the level while\n * listening and speaking, rest when nothing happens, and stand still under\n * `prefers-reduced-motion`, one frame per state. They are shaders: each paints its own colours,\n * on a transparent canvas. Where WebGL is missing or lost, a still disc in a ring takes its place.\n */\nexport function Orb({ style = DEFAULT_ORB, ...props }: OrbProps) {\n // A style the package does not have (a host's data, say) is drawn as the default.\n const Style = STYLES[style] ?? STYLES[DEFAULT_ORB];\n return (\n <Suspense fallback={<Waiting {...props} />}>\n <Style {...props} />\n </Suspense>\n );\n}\n\n/** What stands where the orb will be while its style loads: its box, named, with nothing in it. */\nfunction Waiting({ state, size = ORB_SIZE, label, className }: Omit<OrbProps, \"style\">) {\n const part = useParts();\n return (\n <div\n role=\"img\"\n aria-label={label}\n part=\"orb\"\n className={joined(part(\"sc-orb\", `sc-orb--${state}`, \"sc-orb--loading\"), className)}\n style={{ width: size, height: size }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,MAAM,SAA8D;CAClE,MAAM,WAAW,OAAO,YAAS;CACjC,cAAc,WAAW,OAAO,iBAAc;AAChD;;;;;;;;AASA,SAAgB,IAAI,EAAE,QAAQ,aAAa,GAAG,SAAmB;CAE/D,MAAM,QAAQ,OAAO,UAAU,OAAA;CAC/B,OACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,SAAD,EAAS,GAAI,MAAQ,CAAA;EACvC,UAAA,oBAAC,OAAD,EAAO,GAAI,MAAQ,CAAA;CACX,CAAA;AAEd;;AAGA,SAAS,QAAQ,EAAE,OAAO,OAAA,KAAiB,OAAO,aAAsC;CACtF,MAAM,OAAO,SAAS;CACtB,OACE,oBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,MAAK;EACL,WAAW,OAAO,KAAK,UAAU,WAAW,SAAS,iBAAiB,GAAG,SAAS;EAClF,OAAO;GAAE,OAAO;GAAM,QAAQ;EAAK;CACpC,CAAA;AAEL"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { joined, useParts } from "../kit/context.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/voice/StillOrb.tsx
|
|
4
|
+
/**
|
|
5
|
+
* An orb that does not move: a disc inside a ring, which says the state by its outline (thin at
|
|
6
|
+
* rest, solid while listening, dashed while thinking, double while speaking) and by the words
|
|
7
|
+
* around it, never by movement. It is what the shader styles are where WebGL is not there (no
|
|
8
|
+
* context, a shader that does not compile, a context the browser took away).
|
|
9
|
+
*/
|
|
10
|
+
function StillOrb({ state, size = 200, label, className }) {
|
|
11
|
+
const part = useParts();
|
|
12
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
13
|
+
role: "img",
|
|
14
|
+
"aria-label": label,
|
|
15
|
+
part: "orb",
|
|
16
|
+
className: joined(part("sc-orb", `sc-orb--${state}`, "sc-orb--still"), className),
|
|
17
|
+
style: {
|
|
18
|
+
width: size,
|
|
19
|
+
height: size
|
|
20
|
+
},
|
|
21
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
22
|
+
"aria-hidden": true,
|
|
23
|
+
className: part("sc-orb__ring")
|
|
24
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
25
|
+
"aria-hidden": true,
|
|
26
|
+
className: part("sc-orb__core")
|
|
27
|
+
})]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { StillOrb };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=StillOrb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StillOrb.js","names":[],"sources":["../../src/voice/StillOrb.tsx"],"sourcesContent":["import { joined, useParts } from \"../kit/context\";\nimport { ORB_SIZE, type OrbProps } from \"./orbs\";\n\n/**\n * An orb that does not move: a disc inside a ring, which says the state by its outline (thin at\n * rest, solid while listening, dashed while thinking, double while speaking) and by the words\n * around it, never by movement. It is what the shader styles are where WebGL is not there (no\n * context, a shader that does not compile, a context the browser took away).\n */\nexport function StillOrb({\n state,\n size = ORB_SIZE,\n label,\n className,\n}: Pick<OrbProps, \"state\" | \"size\" | \"label\" | \"className\">) {\n const part = useParts();\n return (\n <div\n role=\"img\"\n aria-label={label}\n part=\"orb\"\n className={joined(part(\"sc-orb\", `sc-orb--${state}`, \"sc-orb--still\"), className)}\n style={{ width: size, height: size }}\n >\n <span aria-hidden className={part(\"sc-orb__ring\")} />\n <span aria-hidden className={part(\"sc-orb__core\")} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,SAAS,EACvB,OACA,OAAA,KACA,OACA,aAC2D;CAC3D,MAAM,OAAO,SAAS;CACtB,OACE,qBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,MAAK;EACL,WAAW,OAAO,KAAK,UAAU,WAAW,SAAS,eAAe,GAAG,SAAS;EAChF,OAAO;GAAE,OAAO;GAAM,QAAQ;EAAK;EALrC,UAAA,CAOE,oBAAC,QAAD;GAAM,eAAA;GAAY,WAAW,KAAK,cAAc;EAAI,CAAA,GACpD,oBAAC,QAAD;GAAM,eAAA;GAAY,WAAW,KAAK,cAAc;EAAI,CAAA,CACjD;;AAET"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { joined, useParts } from "../kit/context.js";
|
|
2
|
+
import { animate, drawStill, motionOf } from "./motion.js";
|
|
3
|
+
import { StillOrb } from "./StillOrb.js";
|
|
4
|
+
import { useReducedMotion } from "./useReducedMotion.js";
|
|
5
|
+
import { createRenderer, inkOf } from "./webgl.js";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
//#region src/voice/WebGLOrb.tsx
|
|
9
|
+
/** The canvas is drawn at this fraction of its size and scaled up by the browser: the shaders are soft. */
|
|
10
|
+
const RENDER_SCALE = .75;
|
|
11
|
+
/** The level as it is now: given, or read off its meter. */
|
|
12
|
+
const read = (level) => typeof level === "function" ? level() : level;
|
|
13
|
+
/**
|
|
14
|
+
* The body both shader styles share: a box that carries the orb's name and a canvas the shader
|
|
15
|
+
* paints on, frame by frame, from refs. Nothing here renders again in React for a frame: the level
|
|
16
|
+
* and the state are read by the loop (`animate`) when a frame is due.
|
|
17
|
+
*
|
|
18
|
+
* The loop runs only while something moves. It asks for no frame while the tab is hidden, and
|
|
19
|
+
* stops three seconds after the state became `idle`; a new state, the tab coming back or a new
|
|
20
|
+
* size starts it again. Under `prefers-reduced-motion` there is no loop at all: one frame per
|
|
21
|
+
* state, at a fixed moment. Where WebGL is missing, the shader does not compile or the browser
|
|
22
|
+
* takes the context away, the orb is the still one, with the same name. A host's colour
|
|
23
|
+
* (`--sc-orb-color`) is read off the canvas with each state, and the shader paints in it.
|
|
24
|
+
*/
|
|
25
|
+
function WebGLOrb({ shader, state, level, size = 200, label, className }) {
|
|
26
|
+
const part = useParts();
|
|
27
|
+
const still = useReducedMotion();
|
|
28
|
+
const [broken, setBroken] = useState(false);
|
|
29
|
+
const surface = useRef(null);
|
|
30
|
+
const renderer = useRef(void 0);
|
|
31
|
+
const loud = useRef(level);
|
|
32
|
+
const motion = useRef(null);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
loud.current = level;
|
|
35
|
+
});
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const canvas = surface.current;
|
|
38
|
+
if (!canvas) return void 0;
|
|
39
|
+
const made = createRenderer(canvas, shader.fragment, Math.round(size * RENDER_SCALE), () => {
|
|
40
|
+
setBroken(true);
|
|
41
|
+
});
|
|
42
|
+
if (!made) {
|
|
43
|
+
setBroken(true);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
renderer.current = made;
|
|
47
|
+
return () => {
|
|
48
|
+
made.dispose();
|
|
49
|
+
renderer.current = void 0;
|
|
50
|
+
};
|
|
51
|
+
}, [shader, size]);
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
const gl = renderer.current;
|
|
54
|
+
const canvas = surface.current;
|
|
55
|
+
if (!gl || !canvas || broken) return void 0;
|
|
56
|
+
gl.ink(inkOf(canvas));
|
|
57
|
+
if (still) {
|
|
58
|
+
drawStill(gl, state);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
motion.current ??= motionOf(state, read(loud.current));
|
|
62
|
+
return animate(gl, shader, state, () => read(loud.current), motion.current);
|
|
63
|
+
}, [
|
|
64
|
+
broken,
|
|
65
|
+
shader,
|
|
66
|
+
size,
|
|
67
|
+
state,
|
|
68
|
+
still
|
|
69
|
+
]);
|
|
70
|
+
if (broken) return /* @__PURE__ */ jsx(StillOrb, {
|
|
71
|
+
state,
|
|
72
|
+
size,
|
|
73
|
+
label,
|
|
74
|
+
className
|
|
75
|
+
});
|
|
76
|
+
return /* @__PURE__ */ jsx("div", {
|
|
77
|
+
role: "img",
|
|
78
|
+
"aria-label": label,
|
|
79
|
+
part: "orb",
|
|
80
|
+
className: joined(part("sc-orb", `sc-orb--${state}`, ...still ? ["sc-orb--still"] : []), className),
|
|
81
|
+
style: {
|
|
82
|
+
width: size,
|
|
83
|
+
height: size
|
|
84
|
+
},
|
|
85
|
+
children: /* @__PURE__ */ jsx("canvas", {
|
|
86
|
+
ref: surface,
|
|
87
|
+
"aria-hidden": true,
|
|
88
|
+
style: {
|
|
89
|
+
width: size,
|
|
90
|
+
height: size
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { WebGLOrb };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=WebGLOrb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebGLOrb.js","names":[],"sources":["../../src/voice/WebGLOrb.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\n\nimport { joined, useParts } from \"../kit/context\";\nimport { animate, drawStill, motionOf, type Motion } from \"./motion\";\nimport { ORB_SIZE, type OrbProps } from \"./orbs\";\nimport { StillOrb } from \"./StillOrb\";\nimport { useReducedMotion } from \"./useReducedMotion\";\nimport { createRenderer, inkOf, type Renderer, type Shader } from \"./webgl\";\n\n/** The canvas is drawn at this fraction of its size and scaled up by the browser: the shaders are soft. */\nconst RENDER_SCALE = 0.75;\n\n/** The level as it is now: given, or read off its meter. */\nconst read = (level: OrbProps[\"level\"]): number => (typeof level === \"function\" ? level() : level);\n\ntype WebGLOrbProps = Omit<OrbProps, \"style\"> & { shader: Shader };\n\n/**\n * The body both shader styles share: a box that carries the orb's name and a canvas the shader\n * paints on, frame by frame, from refs. Nothing here renders again in React for a frame: the level\n * and the state are read by the loop (`animate`) when a frame is due.\n *\n * The loop runs only while something moves. It asks for no frame while the tab is hidden, and\n * stops three seconds after the state became `idle`; a new state, the tab coming back or a new\n * size starts it again. Under `prefers-reduced-motion` there is no loop at all: one frame per\n * state, at a fixed moment. Where WebGL is missing, the shader does not compile or the browser\n * takes the context away, the orb is the still one, with the same name. A host's colour\n * (`--sc-orb-color`) is read off the canvas with each state, and the shader paints in it.\n */\nexport function WebGLOrb({\n shader,\n state,\n level,\n size = ORB_SIZE,\n label,\n className,\n}: WebGLOrbProps) {\n const part = useParts();\n const still = useReducedMotion();\n const [broken, setBroken] = useState(false);\n const surface = useRef<HTMLCanvasElement>(null);\n const renderer = useRef<Renderer | undefined>(undefined);\n const loud = useRef(level);\n const motion = useRef<Motion | null>(null);\n\n useEffect(() => {\n loud.current = level;\n });\n\n // The program is made when the orb appears (once for its shader and size), not for each state.\n useEffect(() => {\n const canvas = surface.current;\n if (!canvas) return undefined;\n const made = createRenderer(canvas, shader.fragment, Math.round(size * RENDER_SCALE), () => {\n setBroken(true);\n });\n if (!made) {\n setBroken(true);\n return undefined;\n }\n renderer.current = made;\n return () => {\n made.dispose();\n renderer.current = undefined;\n };\n }, [shader, size]);\n\n useEffect(() => {\n const gl = renderer.current;\n const canvas = surface.current;\n if (!gl || !canvas || broken) return undefined;\n // The host's colour (`--sc-orb-color`), read again with each state: a theme changed since\n // shows by the next one.\n gl.ink(inkOf(canvas));\n if (still) {\n drawStill(gl, state);\n return undefined;\n }\n motion.current ??= motionOf(state, read(loud.current));\n return animate(gl, shader, state, () => read(loud.current), motion.current);\n }, [broken, shader, size, state, still]);\n\n if (broken) return <StillOrb state={state} size={size} label={label} className={className} />;\n return (\n <div\n role=\"img\"\n aria-label={label}\n part=\"orb\"\n className={joined(\n part(\"sc-orb\", `sc-orb--${state}`, ...(still ? ([\"sc-orb--still\"] as const) : [])),\n className,\n )}\n style={{ width: size, height: size }}\n >\n <canvas ref={surface} aria-hidden style={{ width: size, height: size }} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,eAAe;;AAGrB,MAAM,QAAQ,UAAsC,OAAO,UAAU,aAAa,MAAM,IAAI;;;;;;;;;;;;;AAgB5F,SAAgB,SAAS,EACvB,QACA,OACA,OACA,OAAA,KACA,OACA,aACgB;CAChB,MAAM,OAAO,SAAS;CACtB,MAAM,QAAQ,iBAAiB;CAC/B,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK;CAC1C,MAAM,UAAU,OAA0B,IAAI;CAC9C,MAAM,WAAW,OAA6B,KAAA,CAAS;CACvD,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,SAAS,OAAsB,IAAI;CAEzC,gBAAgB;EACd,KAAK,UAAU;CACjB,CAAC;CAGD,gBAAgB;EACd,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,QAAQ,OAAO,KAAA;EACpB,MAAM,OAAO,eAAe,QAAQ,OAAO,UAAU,KAAK,MAAM,OAAO,YAAY,SAAS;GAC1F,UAAU,IAAI;EAChB,CAAC;EACD,IAAI,CAAC,MAAM;GACT,UAAU,IAAI;GACd;EACF;EACA,SAAS,UAAU;EACnB,aAAa;GACX,KAAK,QAAQ;GACb,SAAS,UAAU,KAAA;EACrB;CACF,GAAG,CAAC,QAAQ,IAAI,CAAC;CAEjB,gBAAgB;EACd,MAAM,KAAK,SAAS;EACpB,MAAM,SAAS,QAAQ;EACvB,IAAI,CAAC,MAAM,CAAC,UAAU,QAAQ,OAAO,KAAA;EAGrC,GAAG,IAAI,MAAM,MAAM,CAAC;EACpB,IAAI,OAAO;GACT,UAAU,IAAI,KAAK;GACnB;EACF;EACA,OAAO,YAAY,SAAS,OAAO,KAAK,KAAK,OAAO,CAAC;EACrD,OAAO,QAAQ,IAAI,QAAQ,aAAa,KAAK,KAAK,OAAO,GAAG,OAAO,OAAO;CAC5E,GAAG;EAAC;EAAQ;EAAQ;EAAM;EAAO;CAAK,CAAC;CAEvC,IAAI,QAAQ,OAAO,oBAAC,UAAD;EAAiB;EAAa;EAAa;EAAkB;CAAY,CAAA;CAC5F,OACE,oBAAC,OAAD;EACE,MAAK;EACL,cAAY;EACZ,MAAK;EACL,WAAW,OACT,KAAK,UAAU,WAAW,SAAS,GAAI,QAAS,CAAC,eAAe,IAAc,CAAC,CAAE,GACjF,SACF;EACA,OAAO;GAAE,OAAO;GAAM,QAAQ;EAAK;EAEnC,UAAA,oBAAC,UAAD;GAAQ,KAAK;GAAS,eAAA;GAAY,OAAO;IAAE,OAAO;IAAM,QAAQ;GAAK;EAAI,CAAA;CACtE,CAAA;AAET"}
|