@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,535 @@
|
|
|
1
|
+
/// <reference path="./css.d.ts" />
|
|
2
|
+
import { ChatCircleDotsIcon, XIcon } from "@phosphor-icons/react";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
5
|
+
|
|
6
|
+
import type { ChatSteps } from "../AgentChat";
|
|
7
|
+
import { AgentSpace, SPACE_MESSAGES } from "../AgentSpace";
|
|
8
|
+
import { createClient } from "../client";
|
|
9
|
+
import type { Credentials } from "../credentials";
|
|
10
|
+
import { SPACE_MESSAGES_ES } from "../es";
|
|
11
|
+
import { es } from "../locale";
|
|
12
|
+
import styles from "../styles.css?inline";
|
|
13
|
+
import type { WidgetConfig, WidgetLook } from "../types";
|
|
14
|
+
import own from "./widget.css?inline";
|
|
15
|
+
|
|
16
|
+
/** The tag the widget registers. */
|
|
17
|
+
export const TAG = "signalcore-chat";
|
|
18
|
+
|
|
19
|
+
/** What the page says on the element; a change to any of them draws it again. */
|
|
20
|
+
const ATTRIBUTES = [
|
|
21
|
+
"base-url",
|
|
22
|
+
"agent",
|
|
23
|
+
"publishable-key",
|
|
24
|
+
"token",
|
|
25
|
+
"theme",
|
|
26
|
+
"locale",
|
|
27
|
+
"mode",
|
|
28
|
+
"header",
|
|
29
|
+
"steps",
|
|
30
|
+
"stylesheet",
|
|
31
|
+
"unstyled",
|
|
32
|
+
"shadow",
|
|
33
|
+
"contained",
|
|
34
|
+
] as const;
|
|
35
|
+
|
|
36
|
+
type Attribute = (typeof ATTRIBUTES)[number];
|
|
37
|
+
|
|
38
|
+
/** The two languages the widget speaks. */
|
|
39
|
+
type Language = "es" | "en";
|
|
40
|
+
|
|
41
|
+
/** What the widget is drawn from, as its attributes say it. */
|
|
42
|
+
export interface WidgetSettings {
|
|
43
|
+
/** The public API: its origin and `/v1`. */
|
|
44
|
+
baseUrl: string;
|
|
45
|
+
/** The agent; null: the web channel its publishable key belongs to names it. */
|
|
46
|
+
agent: string | null;
|
|
47
|
+
/**
|
|
48
|
+
* Who the page speaks for: a person, by the token the host minted; a visitor of the site; or,
|
|
49
|
+
* with neither, the page's own sign-in (SignalCore's app, previewing the widget).
|
|
50
|
+
*/
|
|
51
|
+
credential: Credentials;
|
|
52
|
+
language: Language;
|
|
53
|
+
/** A button at the page's corner that opens a panel; or the panel in the page's flow. */
|
|
54
|
+
mode: "floating" | "inline";
|
|
55
|
+
/** The agent's face over the space (`header`); off unless the page asks. */
|
|
56
|
+
header: boolean;
|
|
57
|
+
/** Whether the agent's steps show (`steps`); as the page speaks (hidden for its people) unless said. */
|
|
58
|
+
steps: ChatSteps | undefined;
|
|
59
|
+
/** Floating within the element's own box (`contained`), not at the page's corner: a preview. */
|
|
60
|
+
contained: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The launcher's words, by language. */
|
|
64
|
+
const LAUNCHER: Readonly<Record<Language, { open: string; close: string; chat: string }>> = {
|
|
65
|
+
en: { open: "Open the chat", close: "Close the chat", chat: "Chat" },
|
|
66
|
+
es: { open: "Abrir el chat", close: "Cerrar el chat", chat: "Chat" },
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The language asked for (`locale`), else the page's own (`<html lang>`), else the browser's:
|
|
71
|
+
* Spanish for any `es`, English otherwise.
|
|
72
|
+
*/
|
|
73
|
+
export function languageOf(locale: string | null): Language {
|
|
74
|
+
const asked = locale || document.documentElement.lang || navigator.language;
|
|
75
|
+
return asked.toLowerCase().startsWith("es") ? "es" : "en";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Whether a boolean attribute is on: present, and not `"false"`. */
|
|
79
|
+
const on = (element: Element, name: Attribute): boolean =>
|
|
80
|
+
element.hasAttribute(name) && element.getAttribute(name) !== "false";
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The settings an element's attributes give, or null while one it needs is missing: the API, and
|
|
84
|
+
* the agent, which only a publishable key may leave to its web channel.
|
|
85
|
+
*/
|
|
86
|
+
export function settingsOf(element: Element): WidgetSettings | null {
|
|
87
|
+
const read = (name: Attribute) => element.getAttribute(name) || null;
|
|
88
|
+
const baseUrl = read("base-url");
|
|
89
|
+
const agent = read("agent");
|
|
90
|
+
const token = read("token");
|
|
91
|
+
const publishableKey = read("publishable-key");
|
|
92
|
+
const credential: Credentials =
|
|
93
|
+
token !== null
|
|
94
|
+
? { token }
|
|
95
|
+
: publishableKey !== null
|
|
96
|
+
? { publishableKey }
|
|
97
|
+
: { credentials: "cookie" };
|
|
98
|
+
if (baseUrl === null || (agent === null && publishableKey === null)) return null;
|
|
99
|
+
const steps = read("steps");
|
|
100
|
+
return {
|
|
101
|
+
baseUrl,
|
|
102
|
+
agent,
|
|
103
|
+
credential,
|
|
104
|
+
language: languageOf(read("locale")),
|
|
105
|
+
mode: read("mode") === "inline" ? "inline" : "floating",
|
|
106
|
+
header: on(element, "header"),
|
|
107
|
+
steps: steps === "shown" || steps === "hidden" ? steps : undefined,
|
|
108
|
+
contained: on(element, "contained"),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A look as the widget's own stylesheet: its tokens on the host (`:host` in its shadow root, the
|
|
114
|
+
* element itself when drawn into the page), where the page's own rules for the element still
|
|
115
|
+
* win, then its CSS. The font is the face's name; `loadFont` brings the face.
|
|
116
|
+
*/
|
|
117
|
+
export function lookCss(look: WidgetLook, host: string): string {
|
|
118
|
+
const px = (value: number | null | undefined) => (value == null ? null : `${String(value)}px`);
|
|
119
|
+
const tokens: [string, string | null | undefined][] = [
|
|
120
|
+
["--sc-accent", look.accent],
|
|
121
|
+
["--sc-accent-fg", look.accent_fg],
|
|
122
|
+
["--sc-font", look.font && `"${look.font}", ui-sans-serif, system-ui, sans-serif`],
|
|
123
|
+
["--sc-radius", px(look.radius)],
|
|
124
|
+
["--sc-launcher-size", px(look.launcher_size)],
|
|
125
|
+
["--sc-panel-width", px(look.panel_width)],
|
|
126
|
+
["--sc-panel-height", px(look.panel_height)],
|
|
127
|
+
["color-scheme", look.theme === "light" || look.theme === "dark" ? look.theme : null],
|
|
128
|
+
];
|
|
129
|
+
const said = tokens.flatMap(([name, value]) => (value ? [`${name}: ${value};`] : []));
|
|
130
|
+
const rule = said.length > 0 ? `${host} { ${said.join(" ")} }` : "";
|
|
131
|
+
return [rule, look.css ?? ""].filter(Boolean).join("\n");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** The face from Google Fonts, in the page's head (where a shadow root's text finds it), once. */
|
|
135
|
+
export function loadFont(font: string) {
|
|
136
|
+
if (document.querySelector(`link[data-signalcore-font="${font}"]`) !== null) return;
|
|
137
|
+
const family = encodeURIComponent(font).replace(/%20/g, "+");
|
|
138
|
+
const link = linkTo(
|
|
139
|
+
`https://fonts.googleapis.com/css2?family=${family}:wght@400;500;600&display=swap`,
|
|
140
|
+
);
|
|
141
|
+
link.setAttribute("data-signalcore-font", font);
|
|
142
|
+
document.head.append(link);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* How light a CSS colour is, from 0 (black) to 1 (white), as a browser gives a computed one:
|
|
147
|
+
* `rgb()`, `rgba()`, `color(srgb …)`, `oklab()`, `oklch()`, `lab()`, `lch()`; null for any other.
|
|
148
|
+
*/
|
|
149
|
+
export function lightnessOf(color: string): number | null {
|
|
150
|
+
const open = color.indexOf("(");
|
|
151
|
+
if (open < 0) return null;
|
|
152
|
+
const space = color.slice(0, open).trim().toLowerCase();
|
|
153
|
+
const inside = color.slice(open + 1);
|
|
154
|
+
// `color()` names its space first: only sRGB's channels are read as they are.
|
|
155
|
+
if (space === "color" && !/^\s*srgb\s/i.test(inside)) return null;
|
|
156
|
+
const values = inside
|
|
157
|
+
.replace(/^\s*srgb\s/i, "")
|
|
158
|
+
.match(/-?\d*\.?\d+(?:e-?\d+)?%?/gi)
|
|
159
|
+
?.map((value) => (value.endsWith("%") ? Number.parseFloat(value) / 100 : Number(value)));
|
|
160
|
+
if (values === undefined) return null;
|
|
161
|
+
const [a, b, c] = values;
|
|
162
|
+
const luminance = (red: number, green: number, blue: number) =>
|
|
163
|
+
0.2126 * red + 0.7152 * green + 0.0722 * blue;
|
|
164
|
+
if (a === undefined) return null;
|
|
165
|
+
switch (space) {
|
|
166
|
+
case "rgb":
|
|
167
|
+
case "rgba":
|
|
168
|
+
return b === undefined || c === undefined ? null : luminance(a, b, c) / 255;
|
|
169
|
+
case "color":
|
|
170
|
+
return b === undefined || c === undefined ? null : luminance(a, b, c);
|
|
171
|
+
case "oklab":
|
|
172
|
+
case "oklch":
|
|
173
|
+
return a;
|
|
174
|
+
case "lab":
|
|
175
|
+
case "lch":
|
|
176
|
+
return a / 100;
|
|
177
|
+
default:
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Whether the widget wears its dark palette by the page's text: only where the page names no
|
|
184
|
+
* `color-scheme` (`normal`) and its text is light, as on a page made dark by its own classes.
|
|
185
|
+
*/
|
|
186
|
+
export function darkByInk(colorScheme: string, color: string): boolean {
|
|
187
|
+
if (colorScheme !== "" && colorScheme !== "normal") return false;
|
|
188
|
+
const lightness = lightnessOf(color);
|
|
189
|
+
return lightness !== null && lightness > 0.6;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Whether the page's stylesheet for the widget is CSS itself, or the address of one. */
|
|
193
|
+
const isCss = (stylesheet: string): boolean => stylesheet.includes("{");
|
|
194
|
+
|
|
195
|
+
/** A stylesheet of this CSS. */
|
|
196
|
+
function cssOf(text: string): HTMLStyleElement {
|
|
197
|
+
const style = document.createElement("style");
|
|
198
|
+
style.textContent = text;
|
|
199
|
+
return style;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The stylesheet at this address. */
|
|
203
|
+
function linkTo(address: string): HTMLLinkElement {
|
|
204
|
+
const link = document.createElement("link");
|
|
205
|
+
link.rel = "stylesheet";
|
|
206
|
+
link.href = address;
|
|
207
|
+
return link;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Where the page keeps the visitor's conversation with an agent, so a visit goes on with it. */
|
|
211
|
+
const conversationKey = (agent: string): string => `signalcore.conversation.${agent}`;
|
|
212
|
+
|
|
213
|
+
function keptConversation(agent: string): string | undefined {
|
|
214
|
+
try {
|
|
215
|
+
return localStorage.getItem(conversationKey(agent)) ?? undefined;
|
|
216
|
+
} catch {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function keepConversation(agent: string, id: string) {
|
|
222
|
+
try {
|
|
223
|
+
localStorage.setItem(conversationKey(agent), id);
|
|
224
|
+
} catch {
|
|
225
|
+
// A page that can't keep anything starts a new conversation each visit.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Our stylesheet in the page itself, once, first in its head so the page's own CSS wins. */
|
|
230
|
+
function stylePage() {
|
|
231
|
+
if (document.querySelector("style[data-signalcore-ui]") !== null) return;
|
|
232
|
+
const style = document.createElement("style");
|
|
233
|
+
style.setAttribute("data-signalcore-ui", "");
|
|
234
|
+
style.textContent = `${styles}\n${own}`;
|
|
235
|
+
document.head.prepend(style);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** What the widget draws: its settings with the agent known, and its look, if it has one. */
|
|
239
|
+
export interface WidgetProps {
|
|
240
|
+
settings: WidgetSettings & { agent: string };
|
|
241
|
+
look?: WidgetLook | null | undefined;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* The widget: the agent's space (`AgentSpace`) in a panel, opened from a round button at the
|
|
246
|
+
* page's corner (the left one if its look says so), or (`inline`) in the page's flow at the
|
|
247
|
+
* element's size. The conversation it opens is kept in the page's storage for the next visit.
|
|
248
|
+
*/
|
|
249
|
+
export function Widget({ settings, look = null }: WidgetProps) {
|
|
250
|
+
const { baseUrl, agent, credential, language, mode, steps, contained } = settings;
|
|
251
|
+
const signedAs = credential.token ?? credential.publishableKey ?? "cookie";
|
|
252
|
+
// One client while the page says the same; a new token (the host's, renewed) makes another.
|
|
253
|
+
const client = useMemo(() => createClient({ baseUrl, ...credential }), [baseUrl, signedAs]);
|
|
254
|
+
const [open, setOpen] = useState(false);
|
|
255
|
+
const words = LAUNCHER[language];
|
|
256
|
+
const floating = mode === "floating";
|
|
257
|
+
const header = settings.header || look?.header === true;
|
|
258
|
+
|
|
259
|
+
const space = (
|
|
260
|
+
<div part="panel" role="dialog" aria-label={words.chat} className="sc-widget__panel">
|
|
261
|
+
<AgentSpace
|
|
262
|
+
key={agent}
|
|
263
|
+
client={client}
|
|
264
|
+
agentId={agent}
|
|
265
|
+
conversationId={keptConversation(agent)}
|
|
266
|
+
onConversation={(id) => {
|
|
267
|
+
keepConversation(agent, id);
|
|
268
|
+
}}
|
|
269
|
+
layout={floating ? "compact" : "full"}
|
|
270
|
+
header={header}
|
|
271
|
+
steps={steps}
|
|
272
|
+
messages={language === "es" ? SPACE_MESSAGES_ES : SPACE_MESSAGES}
|
|
273
|
+
locale={language === "es" ? es : undefined}
|
|
274
|
+
onClose={
|
|
275
|
+
floating
|
|
276
|
+
? () => {
|
|
277
|
+
setOpen(false);
|
|
278
|
+
}
|
|
279
|
+
: undefined
|
|
280
|
+
}
|
|
281
|
+
/>
|
|
282
|
+
</div>
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
if (!floating) return <div className="sc sc-widget sc-widget--inline">{space}</div>;
|
|
286
|
+
const classes = [
|
|
287
|
+
"sc sc-widget sc-widget--floating",
|
|
288
|
+
open && "sc-widget--open",
|
|
289
|
+
look?.position === "left" && "sc-widget--left",
|
|
290
|
+
contained && "sc-widget--contained",
|
|
291
|
+
];
|
|
292
|
+
return (
|
|
293
|
+
<div className={classes.filter(Boolean).join(" ")}>
|
|
294
|
+
{open && space}
|
|
295
|
+
<button
|
|
296
|
+
type="button"
|
|
297
|
+
part="launcher"
|
|
298
|
+
aria-label={open ? words.close : words.open}
|
|
299
|
+
aria-expanded={open}
|
|
300
|
+
onClick={() => {
|
|
301
|
+
setOpen(!open);
|
|
302
|
+
}}
|
|
303
|
+
className="sc-widget__launcher"
|
|
304
|
+
>
|
|
305
|
+
{open ? (
|
|
306
|
+
<XIcon aria-hidden weight="bold" />
|
|
307
|
+
) : (
|
|
308
|
+
<ChatCircleDotsIcon aria-hidden weight="fill" />
|
|
309
|
+
)}
|
|
310
|
+
</button>
|
|
311
|
+
</div>
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* `<signalcore-chat>`: the widget as a web component, for a page built without React. It draws
|
|
317
|
+
* into a shadow root holding the package's stylesheet (or, `shadow="none"`, into the page, the
|
|
318
|
+
* stylesheet first in its head), takes the page's type and ink, and lets in its `--sc-*` tokens,
|
|
319
|
+
* `::part()` and its own stylesheet (`stylesheet`: CSS, or its address). Its attributes say where
|
|
320
|
+
* the API is (`base-url`), the agent, who the page speaks for (`publishable-key`, or `token`),
|
|
321
|
+
* `theme` (`light`, `dark`; the page's by default), `locale` (`es`, `en`), `mode` (`inline`;
|
|
322
|
+
* floating by default), `header` (the agent's face), `steps` (`shown`, `hidden`), `unstyled`
|
|
323
|
+
* (our look's defaults dropped, the layout kept) and `contained` (floating in its own box).
|
|
324
|
+
*
|
|
325
|
+
* With a publishable key and no `agent`, it is a web channel's widget: it reads its agent and
|
|
326
|
+
* its look by the key as it loads (`GET /channels/web/widget`), so a change the business makes
|
|
327
|
+
* reaches every site. A look set on it (`look`) stands over its channel's: SignalCore's preview.
|
|
328
|
+
*/
|
|
329
|
+
export class SignalCoreChat extends HTMLElement {
|
|
330
|
+
static observedAttributes = [...ATTRIBUTES];
|
|
331
|
+
|
|
332
|
+
#mount: HTMLElement | null = null;
|
|
333
|
+
#root: Root | null = null;
|
|
334
|
+
/** The page's own stylesheet for the widget, and what it was made from. */
|
|
335
|
+
#sheet: { from: string; element: HTMLStyleElement | HTMLLinkElement } | null = null;
|
|
336
|
+
/** The look as a stylesheet, before the page's own. */
|
|
337
|
+
#lookSheet: HTMLStyleElement | null = null;
|
|
338
|
+
/** The look set on the element, over its channel's. */
|
|
339
|
+
#look: WidgetLook | null = null;
|
|
340
|
+
/** The web channel its publishable key belongs to, as read for that key (null while read). */
|
|
341
|
+
#channel: { key: string; config: WidgetConfig | null } | null = null;
|
|
342
|
+
/** The page's type and ink as last given to the widget. */
|
|
343
|
+
#adopted = "";
|
|
344
|
+
#unwatch: (() => void) | null = null;
|
|
345
|
+
|
|
346
|
+
/** The page's own stylesheet for the widget: CSS, or the address of one (`stylesheet`). */
|
|
347
|
+
get stylesheet(): string | null {
|
|
348
|
+
return this.getAttribute("stylesheet");
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
set stylesheet(value: string | null) {
|
|
352
|
+
if (value === null) this.removeAttribute("stylesheet");
|
|
353
|
+
else this.setAttribute("stylesheet", value);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** A look over its channel's (or the only one, with an `agent`); null: its channel's. */
|
|
357
|
+
get look(): WidgetLook | null {
|
|
358
|
+
return this.#look;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
set look(value: WidgetLook | null) {
|
|
362
|
+
this.#look = value;
|
|
363
|
+
this.#draw();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
connectedCallback() {
|
|
367
|
+
this.#mount ??= this.#build();
|
|
368
|
+
this.#root = createRoot(this.#mount);
|
|
369
|
+
this.#unwatch = this.#watch();
|
|
370
|
+
this.#draw();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
disconnectedCallback() {
|
|
374
|
+
this.#unwatch?.();
|
|
375
|
+
this.#unwatch = null;
|
|
376
|
+
this.#root?.unmount();
|
|
377
|
+
this.#root = null;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
attributeChangedCallback() {
|
|
381
|
+
this.#draw();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Where the widget draws (and the kit's panels go): in a shadow root after the package's styles,
|
|
386
|
+
* or (`shadow="none"`, read once, as the element first connects) in the element itself.
|
|
387
|
+
*/
|
|
388
|
+
#build(): HTMLElement {
|
|
389
|
+
const mount = document.createElement("div");
|
|
390
|
+
mount.setAttribute("data-sc-portal", "");
|
|
391
|
+
mount.setAttribute("data-sc-widget", "");
|
|
392
|
+
if (this.getAttribute("shadow") === "none") {
|
|
393
|
+
stylePage();
|
|
394
|
+
this.append(mount);
|
|
395
|
+
return mount;
|
|
396
|
+
}
|
|
397
|
+
const shadow = this.attachShadow({ mode: "open" });
|
|
398
|
+
const style = document.createElement("style");
|
|
399
|
+
style.textContent = `${styles}\n${own}`;
|
|
400
|
+
shadow.append(style, mount);
|
|
401
|
+
return mount;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Follows the page: its type and ink again whenever `<html>` or `<body>` change (a class that
|
|
406
|
+
* makes it dark, say) and when the system's scheme does.
|
|
407
|
+
*/
|
|
408
|
+
#watch(): () => void {
|
|
409
|
+
const adopt = () => {
|
|
410
|
+
this.#adopt();
|
|
411
|
+
};
|
|
412
|
+
const observer = new MutationObserver(adopt);
|
|
413
|
+
for (const node of [document.documentElement, document.body]) {
|
|
414
|
+
if (node) observer.observe(node, { attributes: true });
|
|
415
|
+
}
|
|
416
|
+
const scheme =
|
|
417
|
+
typeof window.matchMedia === "function"
|
|
418
|
+
? window.matchMedia("(prefers-color-scheme: dark)")
|
|
419
|
+
: null;
|
|
420
|
+
scheme?.addEventListener("change", adopt);
|
|
421
|
+
return () => {
|
|
422
|
+
observer.disconnect();
|
|
423
|
+
scheme?.removeEventListener("change", adopt);
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** The look it wears: the one set on it, else its channel's, else none. */
|
|
428
|
+
get #worn(): WidgetLook | null {
|
|
429
|
+
return this.#look ?? this.#channel?.config?.appearance ?? null;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* The page's type and ink, as the element inherits them, given to the widget for its defaults
|
|
434
|
+
* (`--_host-font`, `--_host-font-size`, `--_host-fg`); and its dark palette where the page
|
|
435
|
+
* names no scheme but its text is light. A theme named (`theme`, or the look's) wears its own
|
|
436
|
+
* ink, not the page's.
|
|
437
|
+
*/
|
|
438
|
+
#adopt() {
|
|
439
|
+
const mount = this.#mount;
|
|
440
|
+
if (mount === null) return;
|
|
441
|
+
const page = getComputedStyle(this);
|
|
442
|
+
const themed = this.hasAttribute("theme") || (this.#worn?.theme ?? "auto") !== "auto";
|
|
443
|
+
const dark = !themed && darkByInk(page.colorScheme, page.color);
|
|
444
|
+
const adopted = [page.fontFamily, page.fontSize, page.color, dark, themed].join("|");
|
|
445
|
+
if (adopted === this.#adopted) return;
|
|
446
|
+
this.#adopted = adopted;
|
|
447
|
+
mount.style.setProperty("--_host-font", page.fontFamily);
|
|
448
|
+
mount.style.setProperty("--_host-font-size", page.fontSize);
|
|
449
|
+
if (themed) mount.style.removeProperty("--_host-fg");
|
|
450
|
+
else mount.style.setProperty("--_host-fg", page.color);
|
|
451
|
+
if (dark) mount.setAttribute("data-scheme", "dark");
|
|
452
|
+
else mount.removeAttribute("data-scheme");
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Its look as a stylesheet (and its face loaded), then the page's own stylesheet beside ours
|
|
457
|
+
* (`stylesheet`), and ours bare (`unstyled`).
|
|
458
|
+
*/
|
|
459
|
+
#dress() {
|
|
460
|
+
const mount = this.#mount;
|
|
461
|
+
if (mount === null) return;
|
|
462
|
+
mount.toggleAttribute("data-sc-unstyled", on(this, "unstyled"));
|
|
463
|
+
this.#wear(mount, this.#worn);
|
|
464
|
+
const from = this.getAttribute("stylesheet")?.trim() || null;
|
|
465
|
+
if (from === (this.#sheet?.from ?? null)) return;
|
|
466
|
+
this.#sheet?.element.remove();
|
|
467
|
+
this.#sheet = null;
|
|
468
|
+
if (from === null) return;
|
|
469
|
+
const element = isCss(from) ? cssOf(from) : linkTo(from);
|
|
470
|
+
// After ours, so it wins where it says the same as loudly.
|
|
471
|
+
mount.before(element);
|
|
472
|
+
this.#sheet = { from, element };
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
#wear(mount: HTMLElement, look: WidgetLook | null) {
|
|
476
|
+
if (look?.font) loadFont(look.font);
|
|
477
|
+
const css = look === null ? "" : lookCss(look, this.shadowRoot === null ? TAG : ":host");
|
|
478
|
+
if (css === "") {
|
|
479
|
+
this.#lookSheet?.remove();
|
|
480
|
+
this.#lookSheet = null;
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
this.#lookSheet ??= document.createElement("style");
|
|
484
|
+
if (this.#lookSheet.textContent !== css) this.#lookSheet.textContent = css;
|
|
485
|
+
// After ours and before the page's own, which wins over it.
|
|
486
|
+
if (!this.#lookSheet.isConnected) (this.#sheet?.element ?? mount).before(this.#lookSheet);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Its web channel's agent and look, read once for its key: null while read, and when it has
|
|
491
|
+
* an `agent` of its own (it needs no channel then).
|
|
492
|
+
*/
|
|
493
|
+
#channelOf(settings: WidgetSettings): WidgetConfig | null {
|
|
494
|
+
const key = settings.credential.publishableKey;
|
|
495
|
+
if (settings.agent !== null || key === undefined) return null;
|
|
496
|
+
if (this.#channel?.key === key) return this.#channel.config;
|
|
497
|
+
this.#channel = { key, config: null };
|
|
498
|
+
createClient({ baseUrl: settings.baseUrl, publishableKey: key })
|
|
499
|
+
.widget()
|
|
500
|
+
.then(
|
|
501
|
+
(config) => {
|
|
502
|
+
if (this.#channel?.key !== key) return;
|
|
503
|
+
this.#channel = { key, config };
|
|
504
|
+
this.#draw();
|
|
505
|
+
},
|
|
506
|
+
(error: unknown) => {
|
|
507
|
+
console.warn(`<${TAG}> could not read its web channel`, error);
|
|
508
|
+
},
|
|
509
|
+
);
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
#draw() {
|
|
514
|
+
if (this.#root === null) return;
|
|
515
|
+
const settings = settingsOf(this);
|
|
516
|
+
const config = settings && this.#channelOf(settings);
|
|
517
|
+
this.#adopt();
|
|
518
|
+
this.#dress();
|
|
519
|
+
if (settings === null) {
|
|
520
|
+
console.warn(`<${TAG}> needs base-url, and an agent or a publishable key`);
|
|
521
|
+
}
|
|
522
|
+
const agent = settings?.agent ?? config?.agent_id ?? null;
|
|
523
|
+
this.#root.render(
|
|
524
|
+
settings && agent && <Widget settings={{ ...settings, agent }} look={this.#worn} />,
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/** Registers `<signalcore-chat>`, once however often it is asked. */
|
|
530
|
+
export function defineSignalCoreChat(): CustomElementConstructor {
|
|
531
|
+
const known = customElements.get(TAG);
|
|
532
|
+
if (known) return known;
|
|
533
|
+
customElements.define(TAG, SignalCoreChat);
|
|
534
|
+
return SignalCoreChat;
|
|
535
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The widget's script (`dist/widget.js`): React and the package in one file, which registers
|
|
3
|
+
* `<signalcore-chat>` as it loads. A page puts the element where it wants it, or, with the one
|
|
4
|
+
* line a web channel gives, lets the script put it (`mountFromScript`).
|
|
5
|
+
*/
|
|
6
|
+
import { defineSignalCoreChat } from "./element";
|
|
7
|
+
import { mountFromScript } from "./mount";
|
|
8
|
+
|
|
9
|
+
defineSignalCoreChat();
|
|
10
|
+
mountFromScript(document.currentScript);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { TAG } from "./element";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The web channel's one line, `<script src="https://signalcore.ai/v1/widget.js" data-key="pk_…"
|
|
5
|
+
* async>`: the script puts the widget on the page itself, speaking to the API it was loaded from
|
|
6
|
+
* with that key, which names the agent and the look. `data-locale` and `data-theme` say what
|
|
7
|
+
* the element's `locale` and `theme` would. Once per key, however often the line is pasted.
|
|
8
|
+
*/
|
|
9
|
+
export function mountFromScript(script: HTMLOrSVGScriptElement | null): HTMLElement | null {
|
|
10
|
+
if (!(script instanceof HTMLScriptElement)) return null;
|
|
11
|
+
const key = script.dataset.key;
|
|
12
|
+
if (!key || !script.src) return null;
|
|
13
|
+
if (document.querySelector(`${TAG}[publishable-key="${CSS.escape(key)}"]`) !== null) return null;
|
|
14
|
+
const element = document.createElement(TAG);
|
|
15
|
+
element.setAttribute("base-url", `${new URL(script.src).origin}/v1`);
|
|
16
|
+
element.setAttribute("publishable-key", key);
|
|
17
|
+
for (const name of ["locale", "theme"] as const) {
|
|
18
|
+
const value = script.dataset[name];
|
|
19
|
+
if (value) element.setAttribute(name, value);
|
|
20
|
+
}
|
|
21
|
+
const place = () => {
|
|
22
|
+
document.body.append(element);
|
|
23
|
+
};
|
|
24
|
+
if (document.body === null) document.addEventListener("DOMContentLoaded", place, { once: true });
|
|
25
|
+
else place();
|
|
26
|
+
return element;
|
|
27
|
+
}
|