@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
package/src/blocks.ts ADDED
@@ -0,0 +1,249 @@
1
+ /**
2
+ * What an agent can draw: a surface, a tree of blocks from one kit, with a text twin for channels
3
+ * that have no screen. The agent composes each screen from these pieces only; the renderer draws
4
+ * every piece in the host's style, and nothing the agent sends runs as code. Written by hand, one
5
+ * to one with `v3/api/app/ui/blocks.py`, the one source (the API validates every surface against
6
+ * it at `show`). Keys the API leaves out when unset are optional here.
7
+ */
8
+
9
+ import type { AutomationView } from "./automation/types";
10
+ import type { FileBlock } from "./types";
11
+
12
+ export type Tone = "info" | "success" | "warning" | "danger";
13
+
14
+ // --- Display ------------------------------------------------------------------------------
15
+
16
+ /** Words, as Markdown. */
17
+ export interface TextBlock {
18
+ type: "text";
19
+ text: string;
20
+ }
21
+
22
+ /** Label and value pairs: a summary a person reads at a glance. */
23
+ export interface FieldsBlock {
24
+ type: "fields";
25
+ items: { label: string; value: string }[];
26
+ }
27
+
28
+ /** Rows under named columns; a row's cells come in the columns' order. */
29
+ export interface TableBlock {
30
+ type: "table";
31
+ columns: string[];
32
+ rows: string[][];
33
+ }
34
+
35
+ export interface Entry {
36
+ id: string;
37
+ title: string;
38
+ subtitle?: string;
39
+ /** At its right: a price, a time, a status. */
40
+ meta?: string;
41
+ /** A small picture at its left (https). */
42
+ image?: string;
43
+ }
44
+
45
+ /** Things in a column; with `action`, picking one sends it with `{item: id}`. */
46
+ export interface ListBlock {
47
+ type: "list";
48
+ items: Entry[];
49
+ action?: string;
50
+ }
51
+
52
+ /** One number that matters, under its label, with a line of context in its tone. */
53
+ export interface StatBlock {
54
+ type: "stat";
55
+ label: string;
56
+ value: string;
57
+ hint?: string;
58
+ tone?: Tone;
59
+ }
60
+
61
+ export interface ChartPoint {
62
+ label: string;
63
+ value: number;
64
+ }
65
+
66
+ /**
67
+ * Figures over a few labels: bars to compare them (by state, by who), a line to follow them in
68
+ * time (by day, by week), the labels in their order.
69
+ */
70
+ export interface ChartBlock {
71
+ type: "chart";
72
+ kind: "bar" | "line";
73
+ points: ChartPoint[];
74
+ }
75
+
76
+ /** A line that stands out: what the person should notice. */
77
+ export interface NoteBlock {
78
+ type: "note";
79
+ tone: Tone;
80
+ text: string;
81
+ }
82
+
83
+ export interface ImageBlock {
84
+ type: "image";
85
+ /** https only. */
86
+ url: string;
87
+ alt: string;
88
+ caption?: string;
89
+ }
90
+
91
+ /**
92
+ * One of an agent's automations, as its page shows it, read only: the agent names it (`agent`,
93
+ * its name or id, and `name`), and the API fills in `view` before the surface is shown or kept,
94
+ * with its newest 5 runs; null when there is no such automation.
95
+ */
96
+ export interface AutomationBlock {
97
+ type: "automation";
98
+ agent: string;
99
+ name: string;
100
+ view: AutomationView | null;
101
+ }
102
+
103
+ // --- Action -------------------------------------------------------------------------------
104
+
105
+ /** One thing the person can do: pressing it sends `action`, or, with `url`, opens that page. */
106
+ export interface ButtonBlock {
107
+ type: "button";
108
+ label: string;
109
+ action?: string;
110
+ url?: string;
111
+ tone: "primary" | "neutral" | "danger";
112
+ }
113
+
114
+ export interface Option {
115
+ id: string;
116
+ label: string;
117
+ hint?: string;
118
+ }
119
+
120
+ /**
121
+ * Pick one of a few, at once; picking sends `action` with `{option: id}`. With `other`, a last
122
+ * row takes an answer in the person's own words instead: `{text}`.
123
+ */
124
+ export interface ChoiceBlock {
125
+ type: "choice";
126
+ options: Option[];
127
+ action: string;
128
+ other?: boolean;
129
+ }
130
+
131
+ // --- Input --------------------------------------------------------------------------------
132
+
133
+ export type FieldKind =
134
+ | "text"
135
+ | "textarea"
136
+ | "email"
137
+ | "phone"
138
+ | "url"
139
+ | "number"
140
+ | "date"
141
+ | "time"
142
+ | "datetime"
143
+ | "select"
144
+ | "multiselect"
145
+ | "checkbox"
146
+ | "range"
147
+ | "rating"
148
+ /** Files the person uploads to the conversation as they pick them; the value is their ids. */
149
+ | "file"
150
+ /** A value typed once and never stored by the conversation (`ask_person` only). */
151
+ | "secret";
152
+
153
+ /** What a field holds: words, a number, yes or no, option ids; dates and times as ISO text. */
154
+ export type FieldValue = string | number | boolean | string[] | null;
155
+
156
+ /**
157
+ * One thing to fill. Its `kind` picks the control; the rest narrows it: `options` for a select or
158
+ * multiselect; `min`, `max`, `step` and `unit` for a number, range or rating (stars up to `max`,
159
+ * 5 by default); `dates` (the only days to pick, "YYYY-MM-DD"), `earliest` and `latest` for a
160
+ * date or datetime; `times` (the only slots, "HH:MM") for a time or datetime; `accept`,
161
+ * `multiple` and `max_mb` for a file.
162
+ */
163
+ export interface FormField {
164
+ name: string;
165
+ /** None: the field stands alone, its question above it. */
166
+ label?: string;
167
+ kind: FieldKind;
168
+ required: boolean;
169
+ placeholder?: string;
170
+ /** A quiet line under it. */
171
+ help?: string;
172
+ options?: Option[];
173
+ min?: number;
174
+ max?: number;
175
+ step?: number;
176
+ unit?: string;
177
+ dates?: string[];
178
+ earliest?: string;
179
+ latest?: string;
180
+ times?: string[];
181
+ /** The kinds of file it takes: types, families ("image/*"), extensions (".xlsx"); none: any. */
182
+ accept?: string[];
183
+ /** More than one file. */
184
+ multiple?: boolean;
185
+ /** The most a file may weigh, in MB (50, the ceiling, by default). */
186
+ max_mb?: number;
187
+ /** What it starts with. */
188
+ value?: FieldValue;
189
+ }
190
+
191
+ /**
192
+ * Fields to fill; sending them sends `action` with the values by field name: words, a number,
193
+ * true or false, a date "YYYY-MM-DD", a time "HH:MM", a moment "YYYY-MM-DDTHH:MM", a
194
+ * multiselect's option ids, a file field's file ids.
195
+ */
196
+ export interface FormBlock {
197
+ type: "form";
198
+ fields: FormField[];
199
+ /** None: the host's own word for sending (`KitMessages.send`). */
200
+ submit?: string;
201
+ action: string;
202
+ }
203
+
204
+ // --- Layout -------------------------------------------------------------------------------
205
+
206
+ export interface DividerBlock {
207
+ type: "divider";
208
+ }
209
+
210
+ /** Blocks under a title: one thing, set apart. */
211
+ export interface CardBlock {
212
+ type: "card";
213
+ title?: string;
214
+ subtitle?: string;
215
+ /** At its head's start: an app's logo, a product's picture (https). */
216
+ image?: string;
217
+ children: Block[];
218
+ }
219
+
220
+ /** Blocks laid out together: down, or across (wrapping on a narrow screen). */
221
+ export interface StackBlock {
222
+ type: "stack";
223
+ direction: "column" | "row";
224
+ children: Block[];
225
+ }
226
+
227
+ export type Block =
228
+ | CardBlock
229
+ | StackBlock
230
+ | DividerBlock
231
+ | TextBlock
232
+ | FieldsBlock
233
+ | TableBlock
234
+ | ListBlock
235
+ | StatBlock
236
+ | ChartBlock
237
+ | NoteBlock
238
+ | ImageBlock
239
+ | AutomationBlock
240
+ | FileBlock
241
+ | ButtonBlock
242
+ | ChoiceBlock
243
+ | FormBlock;
244
+
245
+ /** What the agent shows: blocks, and the words a channel without a screen gets instead. */
246
+ export interface Surface {
247
+ blocks: Block[];
248
+ text: string;
249
+ }
package/src/browser.ts ADDED
@@ -0,0 +1,334 @@
1
+ /**
2
+ * The conversation's browser, apart from how it is drawn: its screen as pictures to watch, the
3
+ * person's pointer and keys as the input it takes, and where it is in a few words.
4
+ */
5
+
6
+ import type { BrowserFrame, BrowserInput, Message } from "./types";
7
+
8
+ /** The action that hands the person the browser; the turn waits on it until they give it back. */
9
+ export const HAND_OVER = "browser_hand_over";
10
+
11
+ /**
12
+ * The browser's screen as it comes: the latest picture, and whoever watches. Kept out of the
13
+ * conversation's state, so a picture repaints a canvas and nothing else.
14
+ */
15
+ export interface Screen {
16
+ /** A new picture: each watcher hears it. */
17
+ show: (frame: BrowserFrame) => void;
18
+ /** The browser closed: no picture any more. */
19
+ clear: () => void;
20
+ /** Hears each picture from now on, the latest at once; returns how to stop. */
21
+ watch: (listener: (frame: BrowserFrame) => void) => () => void;
22
+ }
23
+
24
+ export function createScreen(): Screen {
25
+ let latest: BrowserFrame | null = null;
26
+ const listeners = new Set<(frame: BrowserFrame) => void>();
27
+ return {
28
+ show: (frame) => {
29
+ latest = frame;
30
+ for (const listener of listeners) listener(frame);
31
+ },
32
+ clear: () => {
33
+ latest = null;
34
+ },
35
+ watch: (listener) => {
36
+ listeners.add(listener);
37
+ if (latest) listener(latest);
38
+ return () => {
39
+ listeners.delete(listener);
40
+ };
41
+ },
42
+ };
43
+ }
44
+
45
+ /**
46
+ * The hand-over the turn waits on (its step's id) when the browser it handed over is no longer
47
+ * there to give back: the person can still go on.
48
+ */
49
+ export function handOverWaiting(
50
+ messages: readonly Message[],
51
+ awaiting: string | null,
52
+ ): string | null {
53
+ if (awaiting === null) return null;
54
+ const step = messages.flatMap((message) => message.steps).find((one) => one.id === awaiting);
55
+ return step?.action === HAND_OVER ? awaiting : null;
56
+ }
57
+
58
+ /** "es.wikipedia.org" and the rest of the address apart, for an address bar; nothing for a blank page. */
59
+ export function siteOf(url: string): { host: string; rest: string } {
60
+ try {
61
+ const { protocol, host, pathname, search } = new URL(url);
62
+ if (!protocol.startsWith("http")) return { host: "", rest: "" };
63
+ return { host, rest: pathname === "/" && !search ? "" : `${pathname}${search}` };
64
+ } catch {
65
+ return { host: "", rest: "" };
66
+ }
67
+ }
68
+
69
+ export interface Size {
70
+ width: number;
71
+ height: number;
72
+ }
73
+
74
+ /** Where a pointer event is on the page: scaled from the element as shown, kept inside it. */
75
+ export function pointOf(
76
+ event: { clientX: number; clientY: number },
77
+ box: { left: number; top: number; width: number; height: number },
78
+ size: Size,
79
+ ): { x: number; y: number } {
80
+ const along = (at: number, from: number, shown: number, real: number) =>
81
+ shown > 0 ? Math.round(Math.min(Math.max((at - from) / shown, 0), 1) * real) : 0;
82
+ return {
83
+ x: along(event.clientX, box.left, box.width, size.width),
84
+ y: along(event.clientY, box.top, box.height, size.height),
85
+ };
86
+ }
87
+
88
+ /** DevTools' mask of the keys held with another: Alt 1, Ctrl 2, Meta 4, Shift 8. */
89
+ export function modifiersOf(event: {
90
+ altKey: boolean;
91
+ ctrlKey: boolean;
92
+ metaKey: boolean;
93
+ shiftKey: boolean;
94
+ }): number {
95
+ return (
96
+ (event.altKey ? 1 : 0) |
97
+ (event.ctrlKey ? 2 : 0) |
98
+ (event.metaKey ? 4 : 0) |
99
+ (event.shiftKey ? 8 : 0)
100
+ );
101
+ }
102
+
103
+ type KeyInput = Extract<BrowserInput, { kind: "key" }>;
104
+
105
+ /**
106
+ * A key as the browser takes it; nothing for a key that stays here: Tab (the focus leaves the
107
+ * screen) and paste (the text comes in its own event, from this computer's clipboard).
108
+ */
109
+ export function keyOf(
110
+ event: Pick<
111
+ KeyboardEvent,
112
+ "key" | "code" | "keyCode" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey"
113
+ >,
114
+ action: "down" | "up",
115
+ ): KeyInput | null {
116
+ if (event.key === "Tab") return null;
117
+ if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "v") return null;
118
+ return {
119
+ kind: "key",
120
+ action,
121
+ key: event.key.slice(0, 32),
122
+ code: event.code.slice(0, 32),
123
+ keyCode: Math.min(Math.max(event.keyCode, 0), 255),
124
+ modifiers: modifiersOf(event),
125
+ };
126
+ }
127
+
128
+ const BUTTONS: Readonly<Record<number, "left" | "middle" | "right">> = {
129
+ 0: "left",
130
+ 1: "middle",
131
+ 2: "right",
132
+ };
133
+ const MOVE_EVERY_MS = 40; // where the pointer is, 25 times a second at most
134
+ // A trackpad fires the wheel 60 times a second, and each one waits on the hosted browser: what
135
+ // turns within this long goes as one, so the page keeps up with the hand instead of trailing it.
136
+ const WHEEL_EVERY_MS = 50;
137
+ const LINE_PX = 16; // a wheel that scrolls by lines, in pixels
138
+ const MAX_DELTA = 10_000;
139
+ const MAX_PASTE = 4_000;
140
+
141
+ const clamp = (value: number, limit: number) => Math.min(Math.max(value, -limit), limit);
142
+
143
+ /**
144
+ * Sends what the person does on `element` (the screen) to `send`, in the page's pixels; the
145
+ * returned function stops it. The pointer goes as down, move and up (drags and double clicks
146
+ * work as on the page; a drag that leaves the screen still ends), the wheel as wheel (the page
147
+ * around does not scroll; the turns of `WHEEL_EVERY_MS` summed into one), keys while the screen
148
+ * has the focus, and text pasted there as text. A key still held when the focus goes is let go.
149
+ * The context menu is the page's.
150
+ */
151
+ export function capture(
152
+ element: HTMLElement,
153
+ size: Size,
154
+ send: (input: BrowserInput) => void,
155
+ ): () => void {
156
+ const held = new Map<string, KeyInput>();
157
+ let lastMove = Number.NEGATIVE_INFINITY;
158
+ const at = (event: { clientX: number; clientY: number }) =>
159
+ pointOf(event, element.getBoundingClientRect(), size);
160
+ // The wheel's turns not sent yet, where the pointer was, and when the last went.
161
+ const turned = { x: 0, y: 0, dx: 0, dy: 0 };
162
+ let lastWheel = Number.NEGATIVE_INFINITY;
163
+ let wheelTimer: ReturnType<typeof setTimeout> | undefined;
164
+ const flushWheel = () => {
165
+ wheelTimer = undefined;
166
+ lastWheel = performance.now();
167
+ const { x, y, dx, dy } = turned;
168
+ turned.dx = 0;
169
+ turned.dy = 0;
170
+ if (dx !== 0 || dy !== 0) {
171
+ send({ kind: "wheel", x, y, dx: clamp(dx, MAX_DELTA), dy: clamp(dy, MAX_DELTA) });
172
+ }
173
+ };
174
+
175
+ const down = (event: PointerEvent) => {
176
+ const button = BUTTONS[event.button];
177
+ if (!button) return;
178
+ event.preventDefault(); // the page would select the screen, and keep the focus where it was
179
+ element.focus({ preventScroll: true });
180
+ element.setPointerCapture(event.pointerId);
181
+ const clicks = Math.min(Math.max(event.detail, 1), 3);
182
+ send({ kind: "mouse", action: "down", ...at(event), button, clicks });
183
+ };
184
+ const up = (event: PointerEvent) => {
185
+ const button = BUTTONS[event.button];
186
+ if (!button) return;
187
+ const clicks = Math.min(Math.max(event.detail, 1), 3);
188
+ send({ kind: "mouse", action: "up", ...at(event), button, clicks });
189
+ };
190
+ const move = (event: PointerEvent) => {
191
+ if (event.timeStamp - lastMove < MOVE_EVERY_MS) return;
192
+ lastMove = event.timeStamp;
193
+ send({ kind: "mouse", action: "move", ...at(event) });
194
+ };
195
+ const wheel = (event: WheelEvent) => {
196
+ event.preventDefault();
197
+ const unit = event.deltaMode === 1 ? LINE_PX : event.deltaMode === 2 ? size.height : 1;
198
+ Object.assign(turned, at(event));
199
+ turned.dx += event.deltaX * unit;
200
+ turned.dy += event.deltaY * unit;
201
+ if (wheelTimer !== undefined) return;
202
+ // The first turn goes at once; what follows it within the window, together at its end.
203
+ const wait = lastWheel + WHEEL_EVERY_MS - performance.now();
204
+ if (wait <= 0) flushWheel();
205
+ else wheelTimer = setTimeout(flushWheel, wait);
206
+ };
207
+ const keyed = (action: "down" | "up") => (event: KeyboardEvent) => {
208
+ if (event.isComposing) return;
209
+ const key = keyOf(event, action);
210
+ if (!key) return;
211
+ event.preventDefault();
212
+ if (action === "down") held.set(event.code || event.key, { ...key, action: "up" });
213
+ else held.delete(event.code || event.key);
214
+ send(key);
215
+ };
216
+ const paste = (event: ClipboardEvent) => {
217
+ const text = event.clipboardData?.getData("text/plain") ?? "";
218
+ if (text === "") return;
219
+ event.preventDefault();
220
+ send({ kind: "paste", text: text.slice(0, MAX_PASTE) });
221
+ };
222
+ const letGo = () => {
223
+ for (const key of held.values()) send(key);
224
+ held.clear();
225
+ };
226
+ const noMenu = (event: Event) => {
227
+ event.preventDefault();
228
+ };
229
+ const keyDown = keyed("down");
230
+ const keyUp = keyed("up");
231
+
232
+ element.addEventListener("pointerdown", down);
233
+ element.addEventListener("pointerup", up);
234
+ element.addEventListener("pointermove", move);
235
+ element.addEventListener("wheel", wheel, { passive: false });
236
+ element.addEventListener("keydown", keyDown);
237
+ element.addEventListener("keyup", keyUp);
238
+ element.addEventListener("paste", paste);
239
+ element.addEventListener("blur", letGo);
240
+ element.addEventListener("contextmenu", noMenu);
241
+ return () => {
242
+ clearTimeout(wheelTimer);
243
+ element.removeEventListener("pointerdown", down);
244
+ element.removeEventListener("pointerup", up);
245
+ element.removeEventListener("pointermove", move);
246
+ element.removeEventListener("wheel", wheel);
247
+ element.removeEventListener("keydown", keyDown);
248
+ element.removeEventListener("keyup", keyUp);
249
+ element.removeEventListener("paste", paste);
250
+ element.removeEventListener("blur", letGo);
251
+ element.removeEventListener("contextmenu", noMenu);
252
+ };
253
+ }
254
+
255
+ /**
256
+ * The bytes in a base64 string: the platform's own decoder where it has one, else a plain loop
257
+ * (`Uint8Array.from` with a mapper walks a frame's 100,000 characters through an iterator, a
258
+ * callback each, on the main thread, as the next picture is due).
259
+ */
260
+ export function bytesOf(base64: string): Uint8Array<ArrayBuffer> {
261
+ const native = (Uint8Array as { fromBase64?: (text: string) => Uint8Array<ArrayBuffer> })
262
+ .fromBase64;
263
+ if (native) return native(base64);
264
+ const text = atob(base64);
265
+ const bytes = new Uint8Array(text.length);
266
+ for (let at = 0; at < text.length; at += 1) bytes[at] = text.charCodeAt(at);
267
+ return bytes;
268
+ }
269
+
270
+ /** Draws a picture on a canvas, unless a newer one comes while it is still being decoded. */
271
+ export interface Painter {
272
+ paint: (jpeg: string) => void;
273
+ dispose: () => void;
274
+ }
275
+
276
+ /**
277
+ * Paints JPEGs (base64) on `canvas`, stretched to its size, v2's way: decoded off the main thread
278
+ * (`createImageBitmap`), one at a time, and drawn on the screen's next frame, so a picture never
279
+ * lands mid-paint. A picture that comes while another is being decoded waits, and a newer one
280
+ * replaces it, as a newer decoded one replaces one not drawn yet: a slow device skips to the
281
+ * present instead of falling behind. The canvas keeps the last picture until the next is ready,
282
+ * so it never flickers; one that does not decode is skipped. `onPaint` hears each one drawn.
283
+ */
284
+ export function painterOn(canvas: HTMLCanvasElement, onPaint?: () => void): Painter {
285
+ let decoding = false;
286
+ let waiting: string | undefined;
287
+ let ready: ImageBitmap | undefined; // decoded, for the next frame
288
+ let frame = 0; // the animation frame asked for, if one is
289
+ let disposed = false;
290
+
291
+ const draw = () => {
292
+ frame = 0;
293
+ const bitmap = ready;
294
+ ready = undefined;
295
+ if (!bitmap) return;
296
+ canvas.getContext("2d")?.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
297
+ bitmap.close();
298
+ onPaint?.();
299
+ };
300
+
301
+ const decode = async (jpeg: string): Promise<void> => {
302
+ decoding = true;
303
+ try {
304
+ const bitmap = await createImageBitmap(new Blob([bytesOf(jpeg)], { type: "image/jpeg" }));
305
+ if (disposed) {
306
+ bitmap.close();
307
+ } else {
308
+ ready?.close();
309
+ ready = bitmap;
310
+ if (frame === 0) frame = requestAnimationFrame(draw);
311
+ }
312
+ } catch {
313
+ // Cut off or damaged: the next picture replaces it.
314
+ }
315
+ decoding = false;
316
+ const next = waiting;
317
+ waiting = undefined;
318
+ if (next !== undefined && !disposed) await decode(next);
319
+ };
320
+
321
+ return {
322
+ paint: (jpeg) => {
323
+ if (decoding) waiting = jpeg;
324
+ else void decode(jpeg);
325
+ },
326
+ dispose: () => {
327
+ disposed = true;
328
+ waiting = undefined;
329
+ if (frame !== 0) cancelAnimationFrame(frame);
330
+ ready?.close();
331
+ ready = undefined;
332
+ },
333
+ };
334
+ }