@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.
Files changed (611) hide show
  1. package/README.md +896 -513
  2. package/dist/AgentAbout.d.ts +186 -0
  3. package/dist/AgentAbout.js +1020 -0
  4. package/dist/AgentAbout.js.map +1 -0
  5. package/dist/AgentCard.d.ts +49 -0
  6. package/dist/AgentCard.js +77 -0
  7. package/dist/AgentCard.js.map +1 -0
  8. package/dist/AgentChat.d.ts +233 -0
  9. package/dist/AgentChat.js +1127 -0
  10. package/dist/AgentChat.js.map +1 -0
  11. package/dist/AgentSpace.d.ts +112 -0
  12. package/dist/AgentSpace.js +339 -0
  13. package/dist/AgentSpace.js.map +1 -0
  14. package/dist/AgentTasks.d.ts +48 -0
  15. package/dist/AgentTasks.js +120 -0
  16. package/dist/AgentTasks.js.map +1 -0
  17. package/dist/BrowserView.d.ts +52 -0
  18. package/dist/BrowserView.js +328 -0
  19. package/dist/BrowserView.js.map +1 -0
  20. package/dist/FileView.d.ts +63 -0
  21. package/dist/FileView.js +449 -0
  22. package/dist/FileView.js.map +1 -0
  23. package/dist/Modes.d.ts +13 -0
  24. package/dist/Modes.js +75 -0
  25. package/dist/Modes.js.map +1 -0
  26. package/dist/VoiceCall.d.ts +91 -0
  27. package/dist/VoiceCall.js +302 -0
  28. package/dist/VoiceCall.js.map +1 -0
  29. package/dist/about.d.ts +212 -0
  30. package/dist/about.js +136 -0
  31. package/dist/about.js.map +1 -0
  32. package/dist/agentIcons.d.ts +33 -0
  33. package/dist/agentIcons.js +36 -0
  34. package/dist/agentIcons.js.map +1 -0
  35. package/dist/automation/Automation.d.ts +35 -0
  36. package/dist/automation/Automation.js +268 -0
  37. package/dist/automation/Automation.js.map +1 -0
  38. package/dist/automation/RunView.d.ts +25 -0
  39. package/dist/automation/RunView.js +187 -0
  40. package/dist/automation/RunView.js.map +1 -0
  41. package/dist/automation/cron.d.ts +41 -0
  42. package/dist/automation/cron.js +169 -0
  43. package/dist/automation/cron.js.map +1 -0
  44. package/dist/automation/marks.js +121 -0
  45. package/dist/automation/marks.js.map +1 -0
  46. package/dist/automation/messages.d.ts +113 -0
  47. package/dist/automation/messages.js +113 -0
  48. package/dist/automation/messages.js.map +1 -0
  49. package/dist/automation/record.d.ts +47 -0
  50. package/dist/automation/record.js +177 -0
  51. package/dist/automation/record.js.map +1 -0
  52. package/dist/automation/types.d.ts +143 -0
  53. package/dist/automation/when.d.ts +36 -0
  54. package/dist/automation/when.js +168 -0
  55. package/dist/automation/when.js.map +1 -0
  56. package/dist/blocks.d.ts +185 -0
  57. package/dist/browser.js +292 -0
  58. package/dist/browser.js.map +1 -0
  59. package/dist/call.d.ts +89 -0
  60. package/dist/call.js +218 -0
  61. package/dist/call.js.map +1 -0
  62. package/dist/channelParts.js +26 -0
  63. package/dist/channelParts.js.map +1 -0
  64. package/dist/classes.js +8 -3
  65. package/dist/classes.js.map +1 -0
  66. package/dist/client.d.ts +146 -54
  67. package/dist/client.js +204 -1
  68. package/dist/client.js.map +1 -0
  69. package/dist/conversationFiles.js +46 -0
  70. package/dist/conversationFiles.js.map +1 -0
  71. package/dist/credentials.d.ts +45 -0
  72. package/dist/credentials.js +98 -0
  73. package/dist/credentials.js.map +1 -0
  74. package/dist/dev.js +17 -0
  75. package/dist/dev.js.map +1 -0
  76. package/dist/es.d.ts +17 -0
  77. package/dist/es.js +382 -0
  78. package/dist/es.js.map +1 -0
  79. package/dist/files.d.ts +21 -0
  80. package/dist/files.js +214 -0
  81. package/dist/files.js.map +1 -0
  82. package/dist/frames.d.ts +115 -0
  83. package/dist/frames.js +219 -0
  84. package/dist/frames.js.map +1 -0
  85. package/dist/icons.js +29 -0
  86. package/dist/icons.js.map +1 -0
  87. package/dist/index.d.ts +63 -60
  88. package/dist/index.js +59 -45
  89. package/dist/kit/AudioPlayer.d.ts +20 -0
  90. package/dist/kit/AudioPlayer.js +116 -0
  91. package/dist/kit/AudioPlayer.js.map +1 -0
  92. package/dist/kit/Button.d.ts +29 -0
  93. package/dist/kit/Button.js +59 -0
  94. package/dist/kit/Button.js.map +1 -0
  95. package/dist/kit/Card.d.ts +16 -0
  96. package/dist/kit/Card.js +36 -0
  97. package/dist/kit/Card.js.map +1 -0
  98. package/dist/kit/Chart.js +152 -0
  99. package/dist/kit/Chart.js.map +1 -0
  100. package/dist/kit/Choices.d.ts +21 -0
  101. package/dist/kit/Choices.js +99 -0
  102. package/dist/kit/Choices.js.map +1 -0
  103. package/dist/kit/Combobox.d.ts +26 -0
  104. package/dist/kit/Combobox.js +190 -0
  105. package/dist/kit/Combobox.js.map +1 -0
  106. package/dist/kit/DateField.d.ts +17 -0
  107. package/dist/kit/DateField.js +133 -0
  108. package/dist/kit/DateField.js.map +1 -0
  109. package/dist/kit/Field.d.ts +40 -0
  110. package/dist/kit/Field.js +98 -0
  111. package/dist/kit/Field.js.map +1 -0
  112. package/dist/kit/FileField.d.ts +113 -0
  113. package/dist/kit/FileField.js +341 -0
  114. package/dist/kit/FileField.js.map +1 -0
  115. package/dist/kit/FileMark.d.ts +15 -0
  116. package/dist/kit/FileMark.js +39 -0
  117. package/dist/kit/FileMark.js.map +1 -0
  118. package/dist/kit/Inputs.d.ts +59 -0
  119. package/dist/kit/Inputs.js +205 -0
  120. package/dist/kit/Inputs.js.map +1 -0
  121. package/dist/kit/List.d.ts +47 -0
  122. package/dist/kit/List.js +85 -0
  123. package/dist/kit/List.js.map +1 -0
  124. package/dist/kit/Mark.d.ts +30 -0
  125. package/dist/kit/Mark.js +27 -0
  126. package/dist/kit/Mark.js.map +1 -0
  127. package/dist/kit/MarkStack.d.ts +15 -0
  128. package/dist/kit/MarkStack.js +26 -0
  129. package/dist/kit/MarkStack.js.map +1 -0
  130. package/dist/kit/Note.d.ts +11 -0
  131. package/dist/kit/Note.js +31 -0
  132. package/dist/kit/Note.js.map +1 -0
  133. package/dist/kit/Popover.js +90 -0
  134. package/dist/kit/Popover.js.map +1 -0
  135. package/dist/kit/RangeField.d.ts +14 -0
  136. package/dist/kit/RangeField.js +47 -0
  137. package/dist/kit/RangeField.js.map +1 -0
  138. package/dist/kit/RatingField.d.ts +14 -0
  139. package/dist/kit/RatingField.js +50 -0
  140. package/dist/kit/RatingField.js.map +1 -0
  141. package/dist/kit/Stat.d.ts +26 -0
  142. package/dist/kit/Stat.js +46 -0
  143. package/dist/kit/Stat.js.map +1 -0
  144. package/dist/kit/Switch.d.ts +14 -0
  145. package/dist/kit/Switch.js +21 -0
  146. package/dist/kit/Switch.js.map +1 -0
  147. package/dist/kit/Tag.d.ts +16 -0
  148. package/dist/kit/Tag.js +20 -0
  149. package/dist/kit/Tag.js.map +1 -0
  150. package/dist/kit/Tile.d.ts +34 -0
  151. package/dist/kit/Tile.js +52 -0
  152. package/dist/kit/Tile.js.map +1 -0
  153. package/dist/kit/TimeField.d.ts +31 -0
  154. package/dist/kit/TimeField.js +109 -0
  155. package/dist/kit/TimeField.js.map +1 -0
  156. package/dist/kit/context.d.ts +22 -0
  157. package/dist/kit/context.js +46 -0
  158. package/dist/kit/context.js.map +1 -0
  159. package/dist/kit/dates.d.ts +14 -0
  160. package/dist/kit/dates.js +129 -0
  161. package/dist/kit/dates.js.map +1 -0
  162. package/dist/kit/messages.d.ts +99 -0
  163. package/dist/kit/messages.js +66 -0
  164. package/dist/kit/messages.js.map +1 -0
  165. package/dist/kit/numbers.d.ts +12 -0
  166. package/dist/kit/numbers.js +40 -0
  167. package/dist/kit/numbers.js.map +1 -0
  168. package/dist/kit/options.d.ts +10 -0
  169. package/dist/kit/options.js +23 -0
  170. package/dist/kit/options.js.map +1 -0
  171. package/dist/kit/uploads.d.ts +42 -0
  172. package/dist/kit/uploads.js +165 -0
  173. package/dist/kit/uploads.js.map +1 -0
  174. package/dist/kit/waveform.js +76 -0
  175. package/dist/kit/waveform.js.map +1 -0
  176. package/dist/locale.d.ts +1 -0
  177. package/dist/locale.js +1 -0
  178. package/dist/markdown.js +84 -0
  179. package/dist/markdown.js.map +1 -0
  180. package/dist/marks.js +217 -0
  181. package/dist/marks.js.map +1 -0
  182. package/dist/reveal.js +48 -0
  183. package/dist/reveal.js.map +1 -0
  184. package/dist/stepGlyphs.js +62 -0
  185. package/dist/stepGlyphs.js.map +1 -0
  186. package/dist/surface/Form.js +264 -0
  187. package/dist/surface/Form.js.map +1 -0
  188. package/dist/surface/Markdown.js +42 -0
  189. package/dist/surface/Markdown.js.map +1 -0
  190. package/dist/surface/Surface.d.ts +31 -17
  191. package/dist/surface/Surface.js +480 -57
  192. package/dist/surface/Surface.js.map +1 -0
  193. package/dist/surface/scope.d.ts +32 -0
  194. package/dist/surface/scope.js +23 -0
  195. package/dist/surface/scope.js.map +1 -0
  196. package/dist/surface/values.d.ts +44 -0
  197. package/dist/surface/values.js +237 -0
  198. package/dist/surface/values.js.map +1 -0
  199. package/dist/tint.d.ts +10 -0
  200. package/dist/tint.js +19 -0
  201. package/dist/tint.js.map +1 -0
  202. package/dist/types.d.ts +541 -0
  203. package/dist/types.js +16 -0
  204. package/dist/types.js.map +1 -0
  205. package/dist/useAgentFace.d.ts +18 -0
  206. package/dist/useAgentFace.js +45 -0
  207. package/dist/useAgentFace.js.map +1 -0
  208. package/dist/useCall.d.ts +39 -0
  209. package/dist/useCall.js +273 -0
  210. package/dist/useCall.js.map +1 -0
  211. package/dist/useConversation.d.ts +77 -0
  212. package/dist/useConversation.js +523 -0
  213. package/dist/useConversation.js.map +1 -0
  214. package/dist/useDictation.d.ts +17 -0
  215. package/dist/useDictation.js +68 -0
  216. package/dist/useDictation.js.map +1 -0
  217. package/dist/useLive.d.ts +26 -0
  218. package/dist/useLive.js +88 -0
  219. package/dist/useLive.js.map +1 -0
  220. package/dist/usePolled.js +68 -0
  221. package/dist/usePolled.js.map +1 -0
  222. package/dist/voice/Orb.d.ts +10 -9
  223. package/dist/voice/Orb.js +43 -39
  224. package/dist/voice/Orb.js.map +1 -0
  225. package/dist/voice/StillOrb.js +33 -0
  226. package/dist/voice/StillOrb.js.map +1 -0
  227. package/dist/voice/WebGLOrb.js +98 -0
  228. package/dist/voice/WebGLOrb.js.map +1 -0
  229. package/dist/voice/fluidDots.js +161 -0
  230. package/dist/voice/fluidDots.js.map +1 -0
  231. package/dist/voice/motion.js +84 -0
  232. package/dist/voice/motion.js.map +1 -0
  233. package/dist/voice/orbs.d.ts +32 -0
  234. package/dist/voice/orbs.js +16 -0
  235. package/dist/voice/orbs.js.map +1 -0
  236. package/dist/voice/useReducedMotion.js +16 -16
  237. package/dist/voice/useReducedMotion.js.map +1 -0
  238. package/dist/voice/wave.js +116 -0
  239. package/dist/voice/wave.js.map +1 -0
  240. package/dist/voice/webgl.js +177 -0
  241. package/dist/voice/webgl.js.map +1 -0
  242. package/dist/widget.js +284 -8
  243. package/package.json +49 -39
  244. package/src/AgentAbout.tsx +1621 -0
  245. package/src/AgentCard.tsx +123 -0
  246. package/src/AgentChat.tsx +1812 -0
  247. package/src/AgentSpace.tsx +540 -0
  248. package/src/AgentTasks.tsx +163 -0
  249. package/src/BrowserView.tsx +442 -0
  250. package/src/FileView.tsx +620 -0
  251. package/src/Modes.tsx +112 -0
  252. package/src/VoiceCall.tsx +411 -0
  253. package/src/about.ts +355 -0
  254. package/src/agentIcons.ts +56 -0
  255. package/src/automation/Automation.tsx +308 -0
  256. package/src/automation/RunView.tsx +213 -0
  257. package/src/automation/cron.ts +196 -0
  258. package/src/automation/marks.tsx +144 -0
  259. package/src/automation/messages.ts +231 -0
  260. package/src/automation/record.ts +206 -0
  261. package/src/automation/types.ts +146 -0
  262. package/src/automation/when.ts +195 -0
  263. package/src/blocks.ts +249 -0
  264. package/src/browser.ts +334 -0
  265. package/src/call.ts +300 -0
  266. package/src/channelParts.ts +17 -0
  267. package/src/classes.ts +10 -0
  268. package/src/client.ts +397 -0
  269. package/src/conversationFiles.ts +54 -0
  270. package/src/credentials.ts +158 -0
  271. package/src/dev.ts +20 -0
  272. package/src/es.ts +423 -0
  273. package/src/files.ts +238 -0
  274. package/src/frames.ts +291 -0
  275. package/src/icons.tsx +49 -0
  276. package/src/index.ts +271 -0
  277. package/src/kit/AudioPlayer.tsx +129 -0
  278. package/src/kit/Button.tsx +97 -0
  279. package/src/kit/Card.tsx +47 -0
  280. package/src/kit/Chart.tsx +129 -0
  281. package/src/kit/Choices.tsx +131 -0
  282. package/src/kit/Combobox.tsx +247 -0
  283. package/src/kit/DateField.tsx +156 -0
  284. package/src/kit/Field.tsx +137 -0
  285. package/src/kit/FileField.tsx +492 -0
  286. package/src/kit/FileMark.tsx +56 -0
  287. package/src/kit/Inputs.tsx +250 -0
  288. package/src/kit/List.tsx +135 -0
  289. package/src/kit/Mark.tsx +64 -0
  290. package/src/kit/MarkStack.tsx +29 -0
  291. package/src/kit/Note.tsx +42 -0
  292. package/src/kit/Popover.tsx +121 -0
  293. package/src/kit/RangeField.tsx +53 -0
  294. package/src/kit/RatingField.tsx +62 -0
  295. package/src/kit/Stat.tsx +60 -0
  296. package/src/kit/Switch.tsx +28 -0
  297. package/src/kit/Tag.tsx +32 -0
  298. package/src/kit/Tile.tsx +74 -0
  299. package/src/kit/TimeField.tsx +157 -0
  300. package/src/kit/context.tsx +246 -0
  301. package/src/kit/dates.ts +150 -0
  302. package/src/kit/messages.ts +160 -0
  303. package/src/kit/numbers.ts +44 -0
  304. package/src/kit/options.ts +30 -0
  305. package/src/kit/uploads.ts +244 -0
  306. package/src/kit/waveform.ts +84 -0
  307. package/src/locale.ts +6 -0
  308. package/src/markdown.ts +69 -0
  309. package/src/marks.tsx +328 -0
  310. package/src/reveal.ts +52 -0
  311. package/src/stepGlyphs.ts +83 -0
  312. package/src/styles.css +6970 -0
  313. package/src/surface/Form.tsx +299 -0
  314. package/src/surface/Markdown.tsx +55 -0
  315. package/src/surface/Surface.tsx +605 -0
  316. package/src/surface/scope.ts +82 -0
  317. package/src/surface/values.ts +361 -0
  318. package/src/tint.ts +14 -0
  319. package/src/types.ts +604 -0
  320. package/src/useAgentFace.ts +47 -0
  321. package/src/useCall.ts +292 -0
  322. package/src/useConversation.ts +627 -0
  323. package/src/useDictation.ts +83 -0
  324. package/src/useLive.ts +115 -0
  325. package/src/usePolled.ts +60 -0
  326. package/src/voice/Orb.tsx +45 -0
  327. package/src/voice/StillOrb.tsx +29 -0
  328. package/src/voice/WebGLOrb.tsx +98 -0
  329. package/src/voice/fluidDots.tsx +171 -0
  330. package/src/voice/motion.ts +112 -0
  331. package/src/voice/orbs.ts +39 -0
  332. package/src/voice/useReducedMotion.ts +24 -0
  333. package/src/voice/wave.tsx +129 -0
  334. package/src/voice/webgl.ts +209 -0
  335. package/src/widget/css.d.ts +5 -0
  336. package/src/widget/element.tsx +535 -0
  337. package/src/widget/index.ts +10 -0
  338. package/src/widget/mount.ts +27 -0
  339. package/src/widget/widget.css +253 -0
  340. package/dist/SignalcoreProvider.d.ts +0 -113
  341. package/dist/SignalcoreProvider.js +0 -84
  342. package/dist/automations/AppMarks.d.ts +0 -11
  343. package/dist/automations/AppMarks.js +0 -18
  344. package/dist/automations/AutomationCard.d.ts +0 -27
  345. package/dist/automations/AutomationCard.js +0 -53
  346. package/dist/automations/AutomationsWindow.d.ts +0 -38
  347. package/dist/automations/AutomationsWindow.js +0 -57
  348. package/dist/automations/Card.d.ts +0 -46
  349. package/dist/automations/Card.js +0 -45
  350. package/dist/automations/ScheduleMarks.d.ts +0 -13
  351. package/dist/automations/ScheduleMarks.js +0 -24
  352. package/dist/automations/presentationIcons.d.ts +0 -7
  353. package/dist/automations/presentationIcons.js +0 -67
  354. package/dist/automations/schedule.d.ts +0 -25
  355. package/dist/automations/schedule.js +0 -59
  356. package/dist/automations/time.d.ts +0 -3
  357. package/dist/automations/time.js +0 -25
  358. package/dist/browser/BrowserView.d.ts +0 -43
  359. package/dist/browser/BrowserView.js +0 -94
  360. package/dist/browser/room.d.ts +0 -21
  361. package/dist/browser/room.js +0 -33
  362. package/dist/browser/useBrowserSession.d.ts +0 -17
  363. package/dist/browser/useBrowserSession.js +0 -67
  364. package/dist/builder/BuilderChat.d.ts +0 -32
  365. package/dist/builder/BuilderChat.js +0 -41
  366. package/dist/builder/BuilderTranscript.d.ts +0 -49
  367. package/dist/builder/BuilderTranscript.js +0 -62
  368. package/dist/builder/StatusLine.d.ts +0 -8
  369. package/dist/builder/StatusLine.js +0 -17
  370. package/dist/builder/answer.d.ts +0 -7
  371. package/dist/builder/answer.js +0 -8
  372. package/dist/builder/blocks.d.ts +0 -31
  373. package/dist/builder/blocks.js +0 -74
  374. package/dist/builder/items.d.ts +0 -15
  375. package/dist/builder/items.js +0 -21
  376. package/dist/builder/steps.d.ts +0 -20
  377. package/dist/builder/steps.js +0 -120
  378. package/dist/builder/time.d.ts +0 -4
  379. package/dist/builder/time.js +0 -24
  380. package/dist/builder/useBuildSession.d.ts +0 -36
  381. package/dist/builder/useBuildSession.js +0 -130
  382. package/dist/builder/workingOn.d.ts +0 -7
  383. package/dist/builder/workingOn.js +0 -15
  384. package/dist/chat/AgentChat.d.ts +0 -37
  385. package/dist/chat/AgentChat.js +0 -21
  386. package/dist/chat/ChatView.d.ts +0 -25
  387. package/dist/chat/ChatView.js +0 -34
  388. package/dist/chat/Composer.d.ts +0 -20
  389. package/dist/chat/Composer.js +0 -22
  390. package/dist/chat/MessageRow.d.ts +0 -22
  391. package/dist/chat/MessageRow.js +0 -32
  392. package/dist/chat/arrival.d.ts +0 -15
  393. package/dist/chat/arrival.js +0 -25
  394. package/dist/chat/history.d.ts +0 -24
  395. package/dist/chat/history.js +0 -45
  396. package/dist/chat/moments.d.ts +0 -25
  397. package/dist/chat/moments.js +0 -72
  398. package/dist/chat/types.d.ts +0 -12
  399. package/dist/chat/types.js +0 -1
  400. package/dist/chat/useComposer.d.ts +0 -46
  401. package/dist/chat/useComposer.js +0 -62
  402. package/dist/chat/useConversation.d.ts +0 -35
  403. package/dist/chat/useConversation.js +0 -71
  404. package/dist/chat/useStickToBottom.d.ts +0 -9
  405. package/dist/chat/useStickToBottom.js +0 -33
  406. package/dist/chat/useTurns.d.ts +0 -49
  407. package/dist/chat/useTurns.js +0 -111
  408. package/dist/classes.d.ts +0 -2
  409. package/dist/development.d.ts +0 -5
  410. package/dist/development.js +0 -8
  411. package/dist/flow/FlowWindow.d.ts +0 -42
  412. package/dist/flow/FlowWindow.js +0 -126
  413. package/dist/flow/index.d.ts +0 -16
  414. package/dist/flow/index.js +0 -16
  415. package/dist/flow/kinds.d.ts +0 -23
  416. package/dist/flow/kinds.js +0 -48
  417. package/dist/flow/map.d.ts +0 -44
  418. package/dist/flow/map.js +0 -225
  419. package/dist/flow/nodePaths.d.ts +0 -7
  420. package/dist/flow/nodePaths.js +0 -17
  421. package/dist/flow/relations.d.ts +0 -42
  422. package/dist/flow/relations.js +0 -174
  423. package/dist/host.d.ts +0 -124
  424. package/dist/host.js +0 -1
  425. package/dist/live/LiveView.d.ts +0 -28
  426. package/dist/live/LiveView.js +0 -55
  427. package/dist/live/capture.d.ts +0 -20
  428. package/dist/live/capture.js +0 -100
  429. package/dist/live/follow.d.ts +0 -26
  430. package/dist/live/follow.js +0 -72
  431. package/dist/live/paint.d.ts +0 -13
  432. package/dist/live/paint.js +0 -77
  433. package/dist/live/useLiveStream.d.ts +0 -16
  434. package/dist/live/useLiveStream.js +0 -57
  435. package/dist/look.d.ts +0 -33
  436. package/dist/look.js +0 -241
  437. package/dist/messages/en.d.ts +0 -3
  438. package/dist/messages/en.js +0 -251
  439. package/dist/messages/es.d.ts +0 -3
  440. package/dist/messages/es.js +0 -251
  441. package/dist/messages/index.d.ts +0 -16
  442. package/dist/messages/index.js +0 -33
  443. package/dist/messages/types.d.ts +0 -246
  444. package/dist/messages/types.js +0 -1
  445. package/dist/parts/Button.d.ts +0 -18
  446. package/dist/parts/Button.js +0 -17
  447. package/dist/parts/Icon.d.ts +0 -39
  448. package/dist/parts/Icon.js +0 -37
  449. package/dist/parts/Input.d.ts +0 -6
  450. package/dist/parts/Input.js +0 -11
  451. package/dist/parts/Spinner.d.ts +0 -2
  452. package/dist/parts/Spinner.js +0 -7
  453. package/dist/patterns.d.ts +0 -15
  454. package/dist/patterns.js +0 -5
  455. package/dist/presets.d.ts +0 -82
  456. package/dist/presets.js +0 -81
  457. package/dist/primitives.d.ts +0 -22
  458. package/dist/primitives.js +0 -58
  459. package/dist/request/RequestCard.d.ts +0 -34
  460. package/dist/request/RequestCard.js +0 -101
  461. package/dist/request/approval/ApprovalPreview.d.ts +0 -5
  462. package/dist/request/approval/ApprovalPreview.js +0 -27
  463. package/dist/request/approval/shapes.d.ts +0 -32
  464. package/dist/request/approval/shapes.js +0 -68
  465. package/dist/request/apps.d.ts +0 -11
  466. package/dist/request/apps.js +0 -27
  467. package/dist/request/cards.d.ts +0 -12
  468. package/dist/request/cards.js +0 -24
  469. package/dist/request/deliver.d.ts +0 -12
  470. package/dist/request/deliver.js +0 -21
  471. package/dist/request/handOver.d.ts +0 -18
  472. package/dist/request/handOver.js +0 -33
  473. package/dist/request/kinds/Approval.d.ts +0 -3
  474. package/dist/request/kinds/Approval.js +0 -9
  475. package/dist/request/kinds/Choice.d.ts +0 -3
  476. package/dist/request/kinds/Choice.js +0 -8
  477. package/dist/request/kinds/Connect.d.ts +0 -9
  478. package/dist/request/kinds/Connect.js +0 -119
  479. package/dist/request/kinds/FreeText.d.ts +0 -3
  480. package/dist/request/kinds/FreeText.js +0 -20
  481. package/dist/request/kinds/HandOver.d.ts +0 -13
  482. package/dist/request/kinds/HandOver.js +0 -20
  483. package/dist/request/kinds/Secret.d.ts +0 -7
  484. package/dist/request/kinds/Secret.js +0 -49
  485. package/dist/request/kinds/Upload.d.ts +0 -6
  486. package/dist/request/kinds/Upload.js +0 -47
  487. package/dist/request/types.d.ts +0 -83
  488. package/dist/request/types.js +0 -1
  489. package/dist/safeUrl.d.ts +0 -6
  490. package/dist/safeUrl.js +0 -8
  491. package/dist/stream/builder.d.ts +0 -176
  492. package/dist/stream/builder.js +0 -202
  493. package/dist/stream/reduce.d.ts +0 -51
  494. package/dist/stream/reduce.js +0 -58
  495. package/dist/stream/untilAborted.d.ts +0 -7
  496. package/dist/stream/untilAborted.js +0 -32
  497. package/dist/stream/useRunStream.d.ts +0 -26
  498. package/dist/stream/useRunStream.js +0 -137
  499. package/dist/styles.css +0 -2318
  500. package/dist/surface/HostNode.d.ts +0 -14
  501. package/dist/surface/HostNode.js +0 -30
  502. package/dist/surface/Node.d.ts +0 -7
  503. package/dist/surface/Node.js +0 -49
  504. package/dist/surface/SurfaceBoundary.d.ts +0 -26
  505. package/dist/surface/SurfaceBoundary.js +0 -20
  506. package/dist/surface/bindings.d.ts +0 -14
  507. package/dist/surface/bindings.js +0 -37
  508. package/dist/surface/check.d.ts +0 -27
  509. package/dist/surface/check.js +0 -102
  510. package/dist/surface/format.d.ts +0 -10
  511. package/dist/surface/format.js +0 -32
  512. package/dist/surface/hosts.d.ts +0 -6
  513. package/dist/surface/hosts.js +0 -11
  514. package/dist/surface/scene.d.ts +0 -21
  515. package/dist/surface/scene.js +0 -8
  516. package/dist/surface/templates/Browser.d.ts +0 -6
  517. package/dist/surface/templates/Browser.js +0 -11
  518. package/dist/surface/templates/Chart.d.ts +0 -6
  519. package/dist/surface/templates/Chart.js +0 -13
  520. package/dist/surface/templates/Choices.d.ts +0 -3
  521. package/dist/surface/templates/Choices.js +0 -12
  522. package/dist/surface/templates/Form.d.ts +0 -3
  523. package/dist/surface/templates/Form.js +0 -44
  524. package/dist/surface/templates/KeyValue.d.ts +0 -3
  525. package/dist/surface/templates/KeyValue.js +0 -7
  526. package/dist/surface/templates/Layout.d.ts +0 -5
  527. package/dist/surface/templates/Layout.js +0 -16
  528. package/dist/surface/templates/Live.d.ts +0 -6
  529. package/dist/surface/templates/Live.js +0 -9
  530. package/dist/surface/templates/Media.d.ts +0 -5
  531. package/dist/surface/templates/Media.js +0 -13
  532. package/dist/surface/templates/Slots.d.ts +0 -3
  533. package/dist/surface/templates/Slots.js +0 -19
  534. package/dist/surface/templates/Table.d.ts +0 -3
  535. package/dist/surface/templates/Table.js +0 -12
  536. package/dist/surface/templates/Text.d.ts +0 -4
  537. package/dist/surface/templates/Text.js +0 -15
  538. package/dist/surface/templates/index.d.ts +0 -7
  539. package/dist/surface/templates/index.js +0 -32
  540. package/dist/surface/types.d.ts +0 -68
  541. package/dist/surface/types.js +0 -6
  542. package/dist/theme.d.ts +0 -62
  543. package/dist/theme.js +0 -9
  544. package/dist/useTokens.d.ts +0 -7
  545. package/dist/useTokens.js +0 -41
  546. package/dist/voice/VoiceWindow.d.ts +0 -18
  547. package/dist/voice/VoiceWindow.js +0 -35
  548. package/dist/voice/index.d.ts +0 -13
  549. package/dist/voice/index.js +0 -12
  550. package/dist/voice/meter.d.ts +0 -16
  551. package/dist/voice/meter.js +0 -52
  552. package/dist/voice/orbColors.d.ts +0 -16
  553. package/dist/voice/orbColors.js +0 -75
  554. package/dist/voice/pushable.d.ts +0 -16
  555. package/dist/voice/pushable.js +0 -56
  556. package/dist/voice/useDictation.d.ts +0 -24
  557. package/dist/voice/useDictation.js +0 -60
  558. package/dist/voice/useReducedMotion.d.ts +0 -5
  559. package/dist/voice/useVoice.d.ts +0 -70
  560. package/dist/voice/useVoice.js +0 -197
  561. package/dist/voice/useVoicePrimitives.d.ts +0 -7
  562. package/dist/voice/useVoicePrimitives.js +0 -11
  563. package/dist/voice/voice.d.ts +0 -55
  564. package/dist/voice/voice.js +0 -9
  565. package/dist/voice/webSpeech.d.ts +0 -33
  566. package/dist/voice/webSpeech.js +0 -258
  567. package/dist/widget.js.map +0 -1
  568. package/dist/windows/AgentSpace.d.ts +0 -78
  569. package/dist/windows/AgentSpace.js +0 -135
  570. package/dist/windows/Captions.d.ts +0 -13
  571. package/dist/windows/Captions.js +0 -22
  572. package/dist/windows/Dock.d.ts +0 -37
  573. package/dist/windows/Dock.js +0 -22
  574. package/dist/windows/Journal.d.ts +0 -15
  575. package/dist/windows/Journal.js +0 -19
  576. package/dist/windows/KindMark.d.ts +0 -7
  577. package/dist/windows/KindMark.js +0 -31
  578. package/dist/windows/Pending.d.ts +0 -8
  579. package/dist/windows/Pending.js +0 -17
  580. package/dist/windows/Stage.d.ts +0 -18
  581. package/dist/windows/Stage.js +0 -21
  582. package/dist/windows/StatusLabel.d.ts +0 -9
  583. package/dist/windows/StatusLabel.js +0 -7
  584. package/dist/windows/Strip.d.ts +0 -17
  585. package/dist/windows/Strip.js +0 -42
  586. package/dist/windows/SurfaceWindow.d.ts +0 -20
  587. package/dist/windows/SurfaceWindow.js +0 -12
  588. package/dist/windows/WindowFrame.d.ts +0 -23
  589. package/dist/windows/WindowFrame.js +0 -22
  590. package/dist/windows/hearing.d.ts +0 -11
  591. package/dist/windows/hearing.js +0 -26
  592. package/dist/windows/kinds.d.ts +0 -47
  593. package/dist/windows/kinds.js +0 -28
  594. package/dist/windows/reduce.d.ts +0 -98
  595. package/dist/windows/reduce.js +0 -151
  596. package/dist/windows/registry.d.ts +0 -18
  597. package/dist/windows/registry.js +0 -61
  598. package/dist/windows/reveal.d.ts +0 -9
  599. package/dist/windows/reveal.js +0 -6
  600. package/dist/windows/space.d.ts +0 -21
  601. package/dist/windows/space.js +0 -6
  602. package/dist/windows/status.d.ts +0 -11
  603. package/dist/windows/status.js +0 -30
  604. package/dist/windows/types.d.ts +0 -15
  605. package/dist/windows/types.js +0 -1
  606. package/dist/windows/useLoaded.d.ts +0 -44
  607. package/dist/windows/useLoaded.js +0 -58
  608. package/dist/windows/useUnread.d.ts +0 -7
  609. package/dist/windows/useUnread.js +0 -21
  610. package/dist/windows/useWindows.d.ts +0 -70
  611. 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
@@ -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"}
@@ -1,11 +1,12 @@
1
- import type { OrbProps } from "../host.js";
1
+ import { OrbProps } from "./orbs.js";
2
+ //#region src/voice/Orb.d.ts
2
3
  /**
3
- * Our orb, the default of the `Orb` primitive: the `circle` theme of `orb-ui` (MIT, drawn from a
4
- * signal, so there is no shader of our own to keep), in our colors. The microphone's level drives
5
- * it while listening and the voice's while speaking.
6
- *
7
- * Under `prefers-reduced-motion` the library is not drawn at all: a still disc inside a ring,
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({ state, level, size, label, className }: OrbProps): import("react").JSX.Element;
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 { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Orb as OrbArt } from "orb-ui";
3
- import { useMemo, useState } from "react";
4
- import { useParts } from "../SignalcoreProvider.js";
5
- import { FALLBACK_COLORS, resolveColor } from "./orbColors.js";
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
- * Our orb, the default of the `Orb` primitive: the `circle` theme of `orb-ui` (MIT, drawn from a
11
- * signal, so there is no shader of our own to keep), in our colors. The microphone's level drives
12
- * it while listening and the voice's while speaking.
13
- *
14
- * Under `prefers-reduced-motion` the library is not drawn at all: a still disc inside a ring,
15
- * which says the state by its outline (thin at rest, solid while listening, dashed while
16
- * thinking, double while speaking) and by the words the window puts under it, never by movement.
17
- */
18
- export function Orb({ state, level, size = SIZE, label, className }) {
19
- const part = useParts();
20
- const still = useReducedMotion();
21
- const box = {
22
- ...part("orb", [state, still && "still"], className),
23
- style: { width: size, height: size },
24
- };
25
- if (still) {
26
- return (_jsxs("div", { role: "img", "aria-label": label, ...box, children: [_jsx("span", { "aria-hidden": true, ...part("orb__ring") }), _jsx("span", { "aria-hidden": true, ...part("orb__core") })] }));
27
- }
28
- return _jsx(MovingOrb, { box: box, state: state, level: level, size: size, label: label });
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
- function MovingOrb({ box, state, level, size, label, }) {
31
- const [stage, setStage] = useState(null);
32
- // The library blends colors it is given as hex, so ours are read where the orb stands (our
33
- // tokens, the host's, the page's scheme) when the orb is drawn and when its state changes,
34
- // which is also when a theme switched in between is picked up.
35
- const color = useMemo(() => (stage ? resolveColor(stage, state) : FALLBACK_COLORS[state]), [stage, state]);
36
- const theme = useMemo(() => ({ name: "circle", appearance: { colors: { [state]: color } } }), [state, color]);
37
- return (_jsx("div", { ref: setStage, ...box, children: _jsx(OrbArt, { signal: {
38
- state,
39
- inputVolume: state === "listening" ? level : 0,
40
- outputVolume: state === "speaking" ? level : 0,
41
- }, theme: theme, size: size, role: "img", "aria-label": label }) }));
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"}