@signalcore/ui 0.1.0 → 1.0.0-beta.0

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 +1119 -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 +534 -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 +1795 -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 +270 -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 +6961 -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 +596 -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,23 @@
1
+ import { classes } from "../classes.js";
2
+ import { createContext, useContext } from "react";
3
+ //#region src/surface/scope.ts
4
+ const ScopeContext = createContext({
5
+ active: false,
6
+ answered: void 0,
7
+ onAction: () => void 0,
8
+ components: void 0,
9
+ classNames: void 0,
10
+ files: void 0
11
+ });
12
+ function useScope() {
13
+ return useContext(ScopeContext);
14
+ }
15
+ /** The classes of the surface's own parts, with the host's own under each. */
16
+ function useSurfaceParts() {
17
+ const { classNames } = useScope();
18
+ return (...parts) => classes(classNames, ...parts);
19
+ }
20
+ //#endregion
21
+ export { ScopeContext, useScope, useSurfaceParts };
22
+
23
+ //# sourceMappingURL=scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope.js","names":[],"sources":["../../src/surface/scope.ts"],"sourcesContent":["import { createContext, useContext, type ComponentType, type ReactNode } from \"react\";\n\nimport type { Block } from \"../blocks\";\nimport { classes } from \"../classes\";\nimport type { KitPart } from \"../kit/context\";\nimport type { FileHost } from \"../kit/uploads\";\nimport type { SurfaceAction } from \"./values\";\n\n/**\n * The surface's own parts, by the class each carries: the blocks that are not a kit primitive,\n * and the form's layout. `classNames` takes these and the kit's (`KitPart`) under the same keys.\n */\nexport type SurfacePart =\n | \"sc-surface\"\n | \"sc-surface__stack\"\n | \"sc-surface__stack--row\"\n | \"sc-surface__divider\"\n | \"sc-surface__text\"\n | \"sc-surface__fields\"\n | \"sc-surface__table\"\n | \"sc-surface__image\"\n | \"sc-surface__media\"\n | \"sc-surface__choice\"\n | \"sc-surface__choice--list\"\n | \"sc-surface__option\"\n | \"sc-surface__option--other\"\n | \"sc-surface__other\"\n | \"sc-surface__form\"\n | \"sc-surface__submit\"\n | \"sc-surface__foot\"\n | \"sc-surface__sent\";\n\nexport type SurfaceClassNames = Partial<Record<SurfacePart | KitPart, string>> | undefined;\n\n/**\n * What a host's component for a block type receives: the block itself, whether the surface still\n * takes input, and `onAction` to send what the person did; a container's `children` come drawn.\n */\nexport type BlockProps<Type extends Block[\"type\"]> = Omit<\n Extract<Block, { type: Type }>,\n \"children\"\n> &\n (Extract<Block, { type: Type }> extends { children: Block[] }\n ? { children: ReactNode }\n : unknown) & {\n active: boolean;\n onAction: (action: SurfaceAction) => void;\n };\n\n/** The host's own drawing of a block type, in place of the package's: `{ table: TheirTable }`. */\nexport type SurfaceComponents = { [Type in Block[\"type\"]]?: ComponentType<BlockProps<Type>> };\n\n/** What every block of one surface shares: whether it takes input, what was done on it. */\nexport interface Scope {\n active: boolean;\n /** What the person already did on the surface. */\n answered: SurfaceAction | undefined;\n onAction: (action: SurfaceAction) => void;\n components: SurfaceComponents | undefined;\n classNames: SurfaceClassNames;\n /** Where its file fields' files go and are found; none: they take none. */\n files: FileHost | undefined;\n}\n\nexport const ScopeContext = createContext<Scope>({\n active: false,\n answered: undefined,\n onAction: () => undefined,\n components: undefined,\n classNames: undefined,\n files: undefined,\n});\n\nexport function useScope(): Scope {\n return useContext(ScopeContext);\n}\n\n/** The classes of the surface's own parts, with the host's own under each. */\nexport function useSurfaceParts(): (...parts: SurfacePart[]) => string {\n const { classNames } = useScope();\n return (...parts) => classes(classNames, ...parts);\n}\n"],"mappings":";;;AAgEA,MAAa,eAAe,cAAqB;CAC/C,QAAQ;CACR,UAAU,KAAA;CACV,gBAAgB,KAAA;CAChB,YAAY,KAAA;CACZ,YAAY,KAAA;CACZ,OAAO,KAAA;AACT,CAAC;AAED,SAAgB,WAAkB;CAChC,OAAO,WAAW,YAAY;AAChC;;AAGA,SAAgB,kBAAuD;CACrE,MAAM,EAAE,eAAe,SAAS;CAChC,QAAQ,GAAG,UAAU,QAAQ,YAAY,GAAG,KAAK;AACnD"}
@@ -0,0 +1,44 @@
1
+ import { ButtonBlock, ChoiceBlock, Entry, FieldValue, FormBlock, FormField, ListBlock, Option } from "../blocks.js";
2
+ import { Action, Attachment } from "../types.js";
3
+ import { KitMessages } from "../kit/messages.js";
4
+ //#region src/surface/values.d.ts
5
+ /**
6
+ * What a block sends when the person uses it: its action's name, what it carries, and the words
7
+ * the app shows for it (the option picked, the button, the form's answer).
8
+ */
9
+ export type SurfaceAction = Omit<Action, "surface">;
10
+ /** A form's values by field name, as its controls hold them. */
11
+ export type Values = Record<string, FieldValue>;
12
+ /** A button's action: its name, nothing more, under its label. */
13
+ export declare function pressed(block: ButtonBlock & {
14
+ action: string;
15
+ }): SurfaceAction;
16
+ /** A choice's action: the option's id, under its label. */
17
+ export declare function picked(block: ChoiceBlock, option: Option): SurfaceAction;
18
+ /** A list's action: the entry's id, under its title. */
19
+ export declare function chosen(block: ListBlock & {
20
+ action: string;
21
+ }, entry: Entry): SurfaceAction;
22
+ /**
23
+ * A form's action: its values by field name (an empty field as null), under the words of its
24
+ * one answer when it asks one thing (the day, the slot, the options picked, the files' names,
25
+ * read from `files`), its submit's when it asks more.
26
+ */
27
+ export declare function filled(block: FormBlock, values: Values, code: string, messages: KitMessages, files?: ReadonlyMap<string, Attachment>): SurfaceAction;
28
+ /**
29
+ * A value in words, as the person's answer reads in the chat: a day and a time in the host's
30
+ * language (against `today`), the options' labels joined, the files' names (from `files`), a
31
+ * number with its unit; "" when it is empty. A secret is never shown.
32
+ */
33
+ export declare function labelOf(field: FormField, value: FieldValue, code: string, messages: KitMessages, { today, files }?: {
34
+ today?: Date | undefined;
35
+ files?: ReadonlyMap<string, Attachment> | undefined;
36
+ }): string;
37
+ /**
38
+ * What is wrong with a value, in words, or null: empty when it must be filled, a shape that is
39
+ * not an email, a phone or an address, a number out of its bounds, a day or a time the field
40
+ * does not offer.
41
+ */
42
+ export declare function problemOf(field: FormField, value: FieldValue, code: string, messages: KitMessages): string | null;
43
+ //#endregion
44
+ //# sourceMappingURL=values.d.ts.map
@@ -0,0 +1,237 @@
1
+ import { formatNumber, withUnit } from "../kit/numbers.js";
2
+ import { DAY, MOMENT, TIME, dayAllowed, formatDay, formatMoment, formatTime, momentParts, slotAllowed } from "../kit/dates.js";
3
+ //#region src/surface/values.ts
4
+ /** The field kinds this renderer draws; a surface with another falls back to its text. */
5
+ const FIELD_KINDS = /* @__PURE__ */ new Set([
6
+ "text",
7
+ "textarea",
8
+ "email",
9
+ "phone",
10
+ "url",
11
+ "number",
12
+ "date",
13
+ "time",
14
+ "datetime",
15
+ "select",
16
+ "multiselect",
17
+ "checkbox",
18
+ "range",
19
+ "rating",
20
+ "file",
21
+ "secret"
22
+ ]);
23
+ /** What a secret reads as, anywhere it is shown. */
24
+ const MASK = "••••••••";
25
+ /** The longest answer label the API takes. */
26
+ const LABEL_MAX = 2e3;
27
+ const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
28
+ const PHONE = /^\+?[\d\s().-]+$/;
29
+ const URL_SHAPE = /^(https?:\/\/)?[^\s/.]+(\.[^\s/.]+)+(\/\S*)?$/i;
30
+ /** A button's action: its name, nothing more, under its label. */
31
+ function pressed(block) {
32
+ return {
33
+ name: block.action,
34
+ data: {},
35
+ label: block.label
36
+ };
37
+ }
38
+ /** A choice's action: the option's id, under its label. */
39
+ function picked(block, option) {
40
+ return {
41
+ name: block.action,
42
+ data: { option: option.id },
43
+ label: option.label
44
+ };
45
+ }
46
+ /** A choice answered in the person's own words, under them. */
47
+ function answeredIn(block, text) {
48
+ return {
49
+ name: block.action,
50
+ data: { text },
51
+ label: text
52
+ };
53
+ }
54
+ /** A list's action: the entry's id, under its title. */
55
+ function chosen(block, entry) {
56
+ return {
57
+ name: block.action,
58
+ data: { item: entry.id },
59
+ label: entry.title
60
+ };
61
+ }
62
+ /**
63
+ * A form's action: its values by field name (an empty field as null), under the words of its
64
+ * one answer when it asks one thing (the day, the slot, the options picked, the files' names,
65
+ * read from `files`), its submit's when it asks more.
66
+ */
67
+ function filled(block, values, code, messages, files) {
68
+ const data = {};
69
+ for (const field of block.fields) data[field.name] = sent(field, values[field.name] ?? null);
70
+ const only = block.fields.length === 1 ? block.fields[0] : void 0;
71
+ const answer = only ? labelOf(only, data[only.name] ?? null, code, messages, { files }) : "";
72
+ return {
73
+ name: block.action,
74
+ data,
75
+ label: clip(answer) || (block.submit ?? messages.send)
76
+ };
77
+ }
78
+ /** A value as it goes: words trimmed, an empty one as null, a moment only once whole. */
79
+ function sent(field, value) {
80
+ if (typeof value === "string") {
81
+ const text = value.trim();
82
+ if (field.kind === "datetime") return MOMENT.test(text) ? text : null;
83
+ return text === "" ? null : text;
84
+ }
85
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
86
+ return value;
87
+ }
88
+ /**
89
+ * Each field's first value: what the person already sent (`answered`, the form's own action's
90
+ * data), else what the agent gave it, else empty; a value that does not fit its kind is left out.
91
+ */
92
+ function startValues(fields, answered) {
93
+ const values = {};
94
+ for (const field of fields) {
95
+ const given = answered && field.name in answered ? answered[field.name] : field.value;
96
+ values[field.name] = fit(field, given) ?? emptyOf(field);
97
+ }
98
+ return values;
99
+ }
100
+ /** A field with nothing given: unticked, none picked, a slider at its least, else nothing. */
101
+ function emptyOf(field) {
102
+ switch (field.kind) {
103
+ case "checkbox": return false;
104
+ case "multiselect":
105
+ case "file": return [];
106
+ case "range": return field.min ?? 0;
107
+ default: return null;
108
+ }
109
+ }
110
+ /** A value read as the field's kind holds it, or null when it does not fit. */
111
+ function fit(field, raw) {
112
+ switch (field.kind) {
113
+ case "checkbox": return raw === true || raw === "true" ? true : raw === false || raw === "false" ? false : null;
114
+ case "number":
115
+ case "range":
116
+ case "rating": {
117
+ const number = typeof raw === "string" && raw.trim() !== "" ? Number(raw) : raw;
118
+ return typeof number === "number" && Number.isFinite(number) ? number : null;
119
+ }
120
+ case "multiselect": return (Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : []).filter((id) => typeof id === "string" && hasOption(field, id));
121
+ case "file": {
122
+ const strings = (Array.isArray(raw) ? raw : typeof raw === "string" ? [raw] : []).filter((id) => typeof id === "string" && id !== "");
123
+ return field.multiple ? strings : strings.slice(0, 1);
124
+ }
125
+ case "select": return typeof raw === "string" && hasOption(field, raw) ? raw : null;
126
+ case "date": return typeof raw === "string" && DAY.test(raw) ? raw : null;
127
+ case "time": return typeof raw === "string" && TIME.test(raw) ? raw : null;
128
+ case "datetime": return typeof raw === "string" && MOMENT.test(raw.slice(0, 16)) ? raw.slice(0, 16) : null;
129
+ default: return typeof raw === "string" || typeof raw === "number" ? String(raw) : null;
130
+ }
131
+ }
132
+ /**
133
+ * A value in words, as the person's answer reads in the chat: a day and a time in the host's
134
+ * language (against `today`), the options' labels joined, the files' names (from `files`), a
135
+ * number with its unit; "" when it is empty. A secret is never shown.
136
+ */
137
+ function labelOf(field, value, code, messages, { today = /* @__PURE__ */ new Date(), files } = {}) {
138
+ if (field.kind === "secret") return value === null || value === "" ? "" : MASK;
139
+ if (field.kind === "checkbox") return value === true ? messages.yes : messages.no;
140
+ if (value === null) return "";
141
+ if (Array.isArray(value)) {
142
+ const labels = value.map((id) => field.kind === "file" ? files?.get(id)?.name ?? messages.file : optionOf(field, id)?.label ?? id);
143
+ return labels.length === 0 ? "" : new Intl.ListFormat(code, { type: "conjunction" }).format(labels);
144
+ }
145
+ if (typeof value === "number") {
146
+ if (field.kind === "rating") return messages.rated(value, field.max ?? 5);
147
+ return withUnit(formatNumber(value, code), field.unit);
148
+ }
149
+ if (typeof value !== "string") return "";
150
+ switch (field.kind) {
151
+ case "select": return optionOf(field, value)?.label ?? value;
152
+ case "date": return formatDay(value, code, today);
153
+ case "time": return TIME.test(value) ? formatTime(value, code) : value;
154
+ case "datetime": return formatMoment(value, code, today);
155
+ default: return value.trim();
156
+ }
157
+ }
158
+ function clip(text) {
159
+ return text.length > LABEL_MAX ? `${text.slice(0, 1999)}…` : text;
160
+ }
161
+ /** What is wrong with each field's value, by name; a field with nothing wrong is not in it. */
162
+ function problemsOf(fields, values, code, messages) {
163
+ const problems = {};
164
+ for (const field of fields) {
165
+ const problem = problemOf(field, values[field.name] ?? null, code, messages);
166
+ if (problem !== null) problems[field.name] = problem;
167
+ }
168
+ return problems;
169
+ }
170
+ /**
171
+ * What is wrong with a value, in words, or null: empty when it must be filled, a shape that is
172
+ * not an email, a phone or an address, a number out of its bounds, a day or a time the field
173
+ * does not offer.
174
+ */
175
+ function problemOf(field, value, code, messages) {
176
+ if (isEmpty(field, value)) return field.required ? emptyWords(field, messages) : null;
177
+ const text = typeof value === "string" ? value.trim() : "";
178
+ switch (field.kind) {
179
+ case "email": return EMAIL.test(text) ? null : messages.invalidEmail;
180
+ case "phone": return PHONE.test(text) && text.replace(/\D/g, "").length >= 6 ? null : messages.invalidPhone;
181
+ case "url": return URL_SHAPE.test(text) ? null : messages.invalidUrl;
182
+ case "number":
183
+ case "range":
184
+ case "rating": return typeof value === "number" && Number.isFinite(value) ? outOfBounds(field, value, code, messages) : messages.invalidNumber;
185
+ case "date": return dayAllowed(field, text) ? null : messages.unavailableDate;
186
+ case "time":
187
+ if (!TIME.test(text)) return messages.invalidTime;
188
+ return slotAllowed(field.times, text) ? null : messages.unavailableTime;
189
+ case "datetime": {
190
+ const [date, time] = momentParts(text);
191
+ if (date === "" || time === "") return messages.chooseMoment;
192
+ if (!dayAllowed(field, date)) return messages.unavailableDate;
193
+ if (!TIME.test(time)) return messages.invalidTime;
194
+ return slotAllowed(field.times, time) ? null : messages.unavailableTime;
195
+ }
196
+ case "select": return hasOption(field, text) ? null : messages.chooseOption;
197
+ case "multiselect": return Array.isArray(value) && value.every((id) => hasOption(field, id)) ? null : messages.chooseOption;
198
+ default: return null;
199
+ }
200
+ }
201
+ /** Whether nothing was given: no words, no pick, an unticked box, no stars. */
202
+ function isEmpty(field, value) {
203
+ if (value === null) return true;
204
+ if (field.kind === "checkbox") return value !== true;
205
+ if (typeof value === "string") return value.trim() === "";
206
+ if (Array.isArray(value)) return value.length === 0;
207
+ return false;
208
+ }
209
+ function emptyWords(field, messages) {
210
+ switch (field.kind) {
211
+ case "date": return messages.chooseDate;
212
+ case "time": return messages.chooseTime;
213
+ case "datetime": return messages.chooseMoment;
214
+ case "select":
215
+ case "multiselect": return messages.chooseOption;
216
+ case "rating": return messages.chooseRating;
217
+ case "checkbox": return messages.check;
218
+ case "file": return messages.chooseFile;
219
+ default: return messages.required;
220
+ }
221
+ }
222
+ function outOfBounds(field, value, code, messages) {
223
+ const { min, max } = field;
224
+ if (min !== void 0 && value < min) return messages.atLeast(formatNumber(min, code));
225
+ if (max !== void 0 && value > max) return messages.atMost(formatNumber(max, code));
226
+ return null;
227
+ }
228
+ function optionOf(field, id) {
229
+ return field.options?.find((option) => option.id === id);
230
+ }
231
+ function hasOption(field, id) {
232
+ return optionOf(field, id) !== void 0;
233
+ }
234
+ //#endregion
235
+ export { FIELD_KINDS, MASK, answeredIn, chosen, emptyOf, filled, fit, isEmpty, labelOf, optionOf, picked, pressed, problemOf, problemsOf, sent, startValues };
236
+
237
+ //# sourceMappingURL=values.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"values.js","names":[],"sources":["../../src/surface/values.ts"],"sourcesContent":["/**\n * What a surface sends, as pure functions: each block's action, a form's values from its fields,\n * the words the person's answer reads as, and what is wrong with a value. The controls hold\n * values in the shapes the contract sends (`blocks.ts`); nothing here touches the page.\n */\nimport type {\n ButtonBlock,\n ChoiceBlock,\n Entry,\n FieldValue,\n FormBlock,\n FormField,\n ListBlock,\n Option,\n} from \"../blocks\";\nimport {\n DAY,\n dayAllowed,\n formatDay,\n formatMoment,\n formatTime,\n MOMENT,\n momentParts,\n slotAllowed,\n TIME,\n} from \"../kit/dates\";\nimport type { KitMessages } from \"../kit/messages\";\nimport { formatNumber, withUnit } from \"../kit/numbers\";\nimport { STARS } from \"../kit/RatingField\";\nimport type { Action, Attachment } from \"../types\";\n\n/**\n * What a block sends when the person uses it: its action's name, what it carries, and the words\n * the app shows for it (the option picked, the button, the form's answer).\n */\nexport type SurfaceAction = Omit<Action, \"surface\">;\n\n/** A form's values by field name, as its controls hold them. */\nexport type Values = Record<string, FieldValue>;\n\n/** The field kinds this renderer draws; a surface with another falls back to its text. */\nexport const FIELD_KINDS: ReadonlySet<string> = new Set([\n \"text\",\n \"textarea\",\n \"email\",\n \"phone\",\n \"url\",\n \"number\",\n \"date\",\n \"time\",\n \"datetime\",\n \"select\",\n \"multiselect\",\n \"checkbox\",\n \"range\",\n \"rating\",\n \"file\",\n \"secret\",\n]);\n\n/** Up to this many options, a select shows them all; more go in a list to search. */\nexport const FEW_OPTIONS = 5;\n/** Up to this many, a multiselect is chips; more go in a list to search. */\nexport const FEW_CHIPS = 8;\n/** What a secret reads as, anywhere it is shown. */\nexport const MASK = \"••••••••\";\n/** The longest answer label the API takes. */\nconst LABEL_MAX = 2000;\n\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/;\nconst PHONE = /^\\+?[\\d\\s().-]+$/;\nconst URL_SHAPE = /^(https?:\\/\\/)?[^\\s/.]+(\\.[^\\s/.]+)+(\\/\\S*)?$/i;\n\n// --- The blocks' actions ------------------------------------------------------------------\n\n/** A button's action: its name, nothing more, under its label. */\nexport function pressed(block: ButtonBlock & { action: string }): SurfaceAction {\n return { name: block.action, data: {}, label: block.label };\n}\n\n/** A choice's action: the option's id, under its label. */\nexport function picked(block: ChoiceBlock, option: Option): SurfaceAction {\n return { name: block.action, data: { option: option.id }, label: option.label };\n}\n\n/** A choice answered in the person's own words, under them. */\nexport function answeredIn(block: ChoiceBlock, text: string): SurfaceAction {\n return { name: block.action, data: { text }, label: text };\n}\n\n/** A list's action: the entry's id, under its title. */\nexport function chosen(block: ListBlock & { action: string }, entry: Entry): SurfaceAction {\n return { name: block.action, data: { item: entry.id }, label: entry.title };\n}\n\n/**\n * A form's action: its values by field name (an empty field as null), under the words of its\n * one answer when it asks one thing (the day, the slot, the options picked, the files' names,\n * read from `files`), its submit's when it asks more.\n */\nexport function filled(\n block: FormBlock,\n values: Values,\n code: string,\n messages: KitMessages,\n files?: ReadonlyMap<string, Attachment>,\n): SurfaceAction {\n const data: Values = {};\n for (const field of block.fields) data[field.name] = sent(field, values[field.name] ?? null);\n const only = block.fields.length === 1 ? block.fields[0] : undefined;\n const answer = only ? labelOf(only, data[only.name] ?? null, code, messages, { files }) : \"\";\n return { name: block.action, data, label: clip(answer) || (block.submit ?? messages.send) };\n}\n\n/** A value as it goes: words trimmed, an empty one as null, a moment only once whole. */\nexport function sent(field: FormField, value: FieldValue): FieldValue {\n if (typeof value === \"string\") {\n const text = value.trim();\n if (field.kind === \"datetime\") return MOMENT.test(text) ? text : null;\n return text === \"\" ? null : text;\n }\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n return value;\n}\n\n// --- Where a form starts ------------------------------------------------------------------\n\n/**\n * Each field's first value: what the person already sent (`answered`, the form's own action's\n * data), else what the agent gave it, else empty; a value that does not fit its kind is left out.\n */\nexport function startValues(fields: FormField[], answered?: Record<string, unknown>): Values {\n const values: Values = {};\n for (const field of fields) {\n const given = answered && field.name in answered ? answered[field.name] : field.value;\n values[field.name] = fit(field, given) ?? emptyOf(field);\n }\n return values;\n}\n\n/** A field with nothing given: unticked, none picked, a slider at its least, else nothing. */\nexport function emptyOf(field: FormField): FieldValue {\n switch (field.kind) {\n case \"checkbox\":\n return false;\n case \"multiselect\":\n case \"file\":\n return [];\n case \"range\":\n return field.min ?? 0;\n default:\n return null;\n }\n}\n\n/** A value read as the field's kind holds it, or null when it does not fit. */\nexport function fit(field: FormField, raw: unknown): FieldValue {\n switch (field.kind) {\n case \"checkbox\":\n return raw === true || raw === \"true\"\n ? true\n : raw === false || raw === \"false\"\n ? false\n : null;\n case \"number\":\n case \"range\":\n case \"rating\": {\n const number = typeof raw === \"string\" && raw.trim() !== \"\" ? Number(raw) : raw;\n return typeof number === \"number\" && Number.isFinite(number) ? number : null;\n }\n case \"multiselect\": {\n const ids = Array.isArray(raw) ? raw : typeof raw === \"string\" ? [raw] : [];\n return ids.filter((id): id is string => typeof id === \"string\" && hasOption(field, id));\n }\n case \"file\": {\n const ids = Array.isArray(raw) ? raw : typeof raw === \"string\" ? [raw] : [];\n const strings = ids.filter((id): id is string => typeof id === \"string\" && id !== \"\");\n return field.multiple ? strings : strings.slice(0, 1);\n }\n case \"select\":\n return typeof raw === \"string\" && hasOption(field, raw) ? raw : null;\n case \"date\":\n return typeof raw === \"string\" && DAY.test(raw) ? raw : null;\n case \"time\":\n return typeof raw === \"string\" && TIME.test(raw) ? raw : null;\n case \"datetime\":\n return typeof raw === \"string\" && MOMENT.test(raw.slice(0, 16)) ? raw.slice(0, 16) : null;\n default:\n return typeof raw === \"string\" || typeof raw === \"number\" ? String(raw) : null;\n }\n}\n\n// --- What a value reads as ----------------------------------------------------------------\n\n/**\n * A value in words, as the person's answer reads in the chat: a day and a time in the host's\n * language (against `today`), the options' labels joined, the files' names (from `files`), a\n * number with its unit; \"\" when it is empty. A secret is never shown.\n */\nexport function labelOf(\n field: FormField,\n value: FieldValue,\n code: string,\n messages: KitMessages,\n {\n today = new Date(),\n files,\n }: { today?: Date | undefined; files?: ReadonlyMap<string, Attachment> | undefined } = {},\n): string {\n if (field.kind === \"secret\") return value === null || value === \"\" ? \"\" : MASK;\n if (field.kind === \"checkbox\") return value === true ? messages.yes : messages.no;\n if (value === null) return \"\";\n if (Array.isArray(value)) {\n const labels = value.map((id) =>\n field.kind === \"file\"\n ? (files?.get(id)?.name ?? messages.file)\n : (optionOf(field, id)?.label ?? id),\n );\n return labels.length === 0\n ? \"\"\n : new Intl.ListFormat(code, { type: \"conjunction\" }).format(labels);\n }\n if (typeof value === \"number\") {\n if (field.kind === \"rating\") return messages.rated(value, field.max ?? STARS);\n return withUnit(formatNumber(value, code), field.unit);\n }\n if (typeof value !== \"string\") return \"\";\n switch (field.kind) {\n case \"select\":\n return optionOf(field, value)?.label ?? value;\n case \"date\":\n return formatDay(value, code, today);\n case \"time\":\n return TIME.test(value) ? formatTime(value, code) : value;\n case \"datetime\":\n return formatMoment(value, code, today);\n default:\n return value.trim();\n }\n}\n\nfunction clip(text: string): string {\n return text.length > LABEL_MAX ? `${text.slice(0, LABEL_MAX - 1)}…` : text;\n}\n\n// --- What is wrong with a value -----------------------------------------------------------\n\n/** What is wrong with each field's value, by name; a field with nothing wrong is not in it. */\nexport function problemsOf(\n fields: FormField[],\n values: Values,\n code: string,\n messages: KitMessages,\n): Record<string, string> {\n const problems: Record<string, string> = {};\n for (const field of fields) {\n const problem = problemOf(field, values[field.name] ?? null, code, messages);\n if (problem !== null) problems[field.name] = problem;\n }\n return problems;\n}\n\n/**\n * What is wrong with a value, in words, or null: empty when it must be filled, a shape that is\n * not an email, a phone or an address, a number out of its bounds, a day or a time the field\n * does not offer.\n */\nexport function problemOf(\n field: FormField,\n value: FieldValue,\n code: string,\n messages: KitMessages,\n): string | null {\n if (isEmpty(field, value)) return field.required ? emptyWords(field, messages) : null;\n const text = typeof value === \"string\" ? value.trim() : \"\";\n switch (field.kind) {\n case \"email\":\n return EMAIL.test(text) ? null : messages.invalidEmail;\n case \"phone\":\n return PHONE.test(text) && text.replace(/\\D/g, \"\").length >= 6 ? null : messages.invalidPhone;\n case \"url\":\n return URL_SHAPE.test(text) ? null : messages.invalidUrl;\n case \"number\":\n case \"range\":\n case \"rating\":\n return typeof value === \"number\" && Number.isFinite(value)\n ? outOfBounds(field, value, code, messages)\n : messages.invalidNumber;\n case \"date\":\n return dayAllowed(field, text) ? null : messages.unavailableDate;\n case \"time\":\n if (!TIME.test(text)) return messages.invalidTime;\n return slotAllowed(field.times, text) ? null : messages.unavailableTime;\n case \"datetime\": {\n const [date, time] = momentParts(text);\n if (date === \"\" || time === \"\") return messages.chooseMoment;\n if (!dayAllowed(field, date)) return messages.unavailableDate;\n if (!TIME.test(time)) return messages.invalidTime;\n return slotAllowed(field.times, time) ? null : messages.unavailableTime;\n }\n case \"select\":\n return hasOption(field, text) ? null : messages.chooseOption;\n case \"multiselect\":\n return Array.isArray(value) && value.every((id) => hasOption(field, id))\n ? null\n : messages.chooseOption;\n default:\n return null;\n }\n}\n\n/** Whether nothing was given: no words, no pick, an unticked box, no stars. */\nexport function isEmpty(field: FormField, value: FieldValue): boolean {\n if (value === null) return true;\n if (field.kind === \"checkbox\") return value !== true;\n if (typeof value === \"string\") return value.trim() === \"\";\n if (Array.isArray(value)) return value.length === 0;\n return false;\n}\n\nfunction emptyWords(field: FormField, messages: KitMessages): string {\n switch (field.kind) {\n case \"date\":\n return messages.chooseDate;\n case \"time\":\n return messages.chooseTime;\n case \"datetime\":\n return messages.chooseMoment;\n case \"select\":\n case \"multiselect\":\n return messages.chooseOption;\n case \"rating\":\n return messages.chooseRating;\n case \"checkbox\":\n return messages.check;\n case \"file\":\n return messages.chooseFile;\n default:\n return messages.required;\n }\n}\n\nfunction outOfBounds(\n field: FormField,\n value: number,\n code: string,\n messages: KitMessages,\n): string | null {\n const { min, max } = field;\n if (min !== undefined && value < min) return messages.atLeast(formatNumber(min, code));\n if (max !== undefined && value > max) return messages.atMost(formatNumber(max, code));\n return null;\n}\n\nexport function optionOf(field: FormField, id: string): Option | undefined {\n return field.options?.find((option) => option.id === id);\n}\n\nfunction hasOption(field: FormField, id: string): boolean {\n return optionOf(field, id) !== undefined;\n}\n"],"mappings":"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"}
package/dist/tint.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ //#region src/tint.d.ts
2
+ /** The tints an agent's tile can take: the soft ones, never a state or the accent. */
3
+ export type AgentTint = "sky" | "rose" | "sand";
4
+ /**
5
+ * The tint an agent keeps wherever it appears (a squad's map, its profile, its card): picked from
6
+ * its id, so a rename changes nothing, and spread evenly over the three.
7
+ */
8
+ export declare function agentTint(id: string): AgentTint;
9
+ //#endregion
10
+ //# sourceMappingURL=tint.d.ts.map
package/dist/tint.js ADDED
@@ -0,0 +1,19 @@
1
+ //#region src/tint.ts
2
+ const TINTS = [
3
+ "sky",
4
+ "rose",
5
+ "sand"
6
+ ];
7
+ /**
8
+ * The tint an agent keeps wherever it appears (a squad's map, its profile, its card): picked from
9
+ * its id, so a rename changes nothing, and spread evenly over the three.
10
+ */
11
+ function agentTint(id) {
12
+ let hash = 0;
13
+ for (const char of id) hash = hash * 31 + (char.codePointAt(0) ?? 0) >>> 0;
14
+ return TINTS[hash % TINTS.length] ?? "sky";
15
+ }
16
+ //#endregion
17
+ export { agentTint };
18
+
19
+ //# sourceMappingURL=tint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tint.js","names":[],"sources":["../src/tint.ts"],"sourcesContent":["/** The tints an agent's tile can take: the soft ones, never a state or the accent. */\nexport type AgentTint = \"sky\" | \"rose\" | \"sand\";\n\nconst TINTS: readonly AgentTint[] = [\"sky\", \"rose\", \"sand\"];\n\n/**\n * The tint an agent keeps wherever it appears (a squad's map, its profile, its card): picked from\n * its id, so a rename changes nothing, and spread evenly over the three.\n */\nexport function agentTint(id: string): AgentTint {\n let hash = 0;\n for (const char of id) hash = (hash * 31 + (char.codePointAt(0) ?? 0)) >>> 0;\n return TINTS[hash % TINTS.length] ?? \"sky\";\n}\n"],"mappings":";AAGA,MAAM,QAA8B;CAAC;CAAO;CAAQ;AAAM;;;;;AAM1D,SAAgB,UAAU,IAAuB;CAC/C,IAAI,OAAO;CACX,KAAK,MAAM,QAAQ,IAAI,OAAQ,OAAO,MAAM,KAAK,YAAY,CAAC,KAAK,OAAQ;CAC3E,OAAO,MAAM,OAAO,MAAM,WAAW;AACvC"}