knobkit 0.0.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 (361) hide show
  1. package/LICENSE +21 -0
  2. package/dist/assets/cell-renderer-CLTRlCa5-DIlwS99c.js +1 -0
  3. package/dist/assets/chart-D8ctp-_1.js +36 -0
  4. package/dist/assets/code-BMuLQBYq.js +2 -0
  5. package/dist/assets/column.service-C6hByxPy-XG9X0y3N.js +1 -0
  6. package/dist/assets/debounce-PCRWZliA-BjJpj_P7.js +32 -0
  7. package/dist/assets/dimension.helpers-CGKwSvw6-D_czicbS.js +1 -0
  8. package/dist/assets/dist-1hsZpGRf.js +23 -0
  9. package/dist/assets/dist-B-y4Etc5.js +1 -0
  10. package/dist/assets/dist-B8BXgMDk.js +10 -0
  11. package/dist/assets/dist-BJlXPLNt.js +1 -0
  12. package/dist/assets/dist-ByhR2UY_.js +1 -0
  13. package/dist/assets/dist-C0bxYHYH.js +2 -0
  14. package/dist/assets/dist-C8dagUDy.js +6 -0
  15. package/dist/assets/dist-CtLpohkg.js +1 -0
  16. package/dist/assets/dist-D00mNtIr.js +1 -0
  17. package/dist/assets/dist-Dh1Dvy3h.js +1 -0
  18. package/dist/assets/dist-DlwQ1Qqm.js +1 -0
  19. package/dist/assets/dist-DtZDI7jp.js +1 -0
  20. package/dist/assets/dist-thZFs69d.js +9 -0
  21. package/dist/assets/edit.utils-Dnnbd0xG-OAxDw8WC.js +1 -0
  22. package/dist/assets/events-BvSmBueA-4kqQ57iN.js +1 -0
  23. package/dist/assets/filter.button-BFwo1uvz-CyvQhOO5.js +1 -0
  24. package/dist/assets/header-cell-renderer-BMmXRsd_-BHbC7fao.js +1 -0
  25. package/dist/assets/index-Db3qZoW5-peeY7EGw.js +1 -0
  26. package/dist/assets/markdown-dDCgur7g.js +29 -0
  27. package/dist/assets/revo-grid.entry-CfI6s-uT.js +1 -0
  28. package/dist/assets/revogr-attribution_7.entry-6fUjzImt.js +1 -0
  29. package/dist/assets/revogr-clipboard_3.entry-DmI7LkER.js +2 -0
  30. package/dist/assets/revogr-data_4.entry-CYZIiXNw.js +1 -0
  31. package/dist/assets/revogr-filter-panel.entry-TmQHTQxw.js +1 -0
  32. package/dist/assets/table-Zn7rpfG-.js +1 -0
  33. package/dist/assets/text-editor-C3RUSwH5-DuDr9wKc.js +1 -0
  34. package/dist/assets/theme.service-BmnDvr6P-DftEgmbe.js +3 -0
  35. package/dist/assets/throttle-CaUDyxyU-Djj__DCp.js +1 -0
  36. package/dist/assets/viewport.helpers-CoCAvmZs-ByVRjjkF.js +1 -0
  37. package/dist/assets/viewport.store-_c579YyM-B_ZSqqka.js +1 -0
  38. package/dist/cli/config.d.ts +5 -0
  39. package/dist/cli/config.js +82 -0
  40. package/dist/cli/index.d.ts +2 -0
  41. package/dist/cli/index.js +77 -0
  42. package/dist/cli/mount.d.ts +2 -0
  43. package/dist/cli/mount.js +26 -0
  44. package/dist/cli/serve.d.ts +1 -0
  45. package/dist/cli/serve.js +21 -0
  46. package/dist/client/app.d.ts +8 -0
  47. package/dist/client/app.js +40 -0
  48. package/dist/client/context.d.ts +2 -0
  49. package/dist/client/context.js +16 -0
  50. package/dist/client/mount.d.ts +3 -0
  51. package/dist/client/mount.js +42 -0
  52. package/dist/client/runtime.d.ts +19 -0
  53. package/dist/client/runtime.js +88 -0
  54. package/dist/client/view.d.ts +12 -0
  55. package/dist/client/view.js +1 -0
  56. package/dist/client/widgets/accordion/index.d.ts +5 -0
  57. package/dist/client/widgets/accordion/index.js +8 -0
  58. package/dist/client/widgets/annotated-image/index.d.ts +8 -0
  59. package/dist/client/widgets/annotated-image/index.js +34 -0
  60. package/dist/client/widgets/audio/index.d.ts +5 -0
  61. package/dist/client/widgets/audio/index.js +5 -0
  62. package/dist/client/widgets/button/index.d.ts +4 -0
  63. package/dist/client/widgets/button/index.js +5 -0
  64. package/dist/client/widgets/chart/index.d.ts +5 -0
  65. package/dist/client/widgets/chart/index.js +23 -0
  66. package/dist/client/widgets/chart/lazy.d.ts +3 -0
  67. package/dist/client/widgets/chart/lazy.js +9 -0
  68. package/dist/client/widgets/chat/index.d.ts +6 -0
  69. package/dist/client/widgets/chat/index.js +77 -0
  70. package/dist/client/widgets/checkbox/index.d.ts +6 -0
  71. package/dist/client/widgets/checkbox/index.js +9 -0
  72. package/dist/client/widgets/checkbox-group/index.d.ts +6 -0
  73. package/dist/client/widgets/checkbox-group/index.js +12 -0
  74. package/dist/client/widgets/code/index.d.ts +5 -0
  75. package/dist/client/widgets/code/index.js +101 -0
  76. package/dist/client/widgets/code/lazy.d.ts +3 -0
  77. package/dist/client/widgets/code/lazy.js +10 -0
  78. package/dist/client/widgets/dropdown/index.d.ts +5 -0
  79. package/dist/client/widgets/dropdown/index.js +9 -0
  80. package/dist/client/widgets/file/index.d.ts +6 -0
  81. package/dist/client/widgets/file/index.js +7 -0
  82. package/dist/client/widgets/frame/index.d.ts +6 -0
  83. package/dist/client/widgets/frame/index.js +11 -0
  84. package/dist/client/widgets/gallery/index.d.ts +6 -0
  85. package/dist/client/widgets/gallery/index.js +8 -0
  86. package/dist/client/widgets/highlighted-text/index.d.ts +7 -0
  87. package/dist/client/widgets/highlighted-text/index.js +20 -0
  88. package/dist/client/widgets/html/index.d.ts +4 -0
  89. package/dist/client/widgets/html/index.js +8 -0
  90. package/dist/client/widgets/image/index.d.ts +4 -0
  91. package/dist/client/widgets/image/index.js +4 -0
  92. package/dist/client/widgets/json/index.d.ts +4 -0
  93. package/dist/client/widgets/json/index.js +4 -0
  94. package/dist/client/widgets/label/index.d.ts +7 -0
  95. package/dist/client/widgets/label/index.js +8 -0
  96. package/dist/client/widgets/layout/index.d.ts +4 -0
  97. package/dist/client/widgets/layout/index.js +7 -0
  98. package/dist/client/widgets/log/index.d.ts +4 -0
  99. package/dist/client/widgets/log/index.js +4 -0
  100. package/dist/client/widgets/mic/index.d.ts +6 -0
  101. package/dist/client/widgets/mic/index.js +70 -0
  102. package/dist/client/widgets/number/index.d.ts +5 -0
  103. package/dist/client/widgets/number/index.js +8 -0
  104. package/dist/client/widgets/output/index.d.ts +6 -0
  105. package/dist/client/widgets/output/index.js +13 -0
  106. package/dist/client/widgets/output/markdown.d.ts +3 -0
  107. package/dist/client/widgets/output/markdown.js +8 -0
  108. package/dist/client/widgets/progress/index.d.ts +6 -0
  109. package/dist/client/widgets/progress/index.js +6 -0
  110. package/dist/client/widgets/radio/index.d.ts +6 -0
  111. package/dist/client/widgets/radio/index.js +10 -0
  112. package/dist/client/widgets/registry.d.ts +2 -0
  113. package/dist/client/widgets/registry.js +69 -0
  114. package/dist/client/widgets/slider/index.d.ts +6 -0
  115. package/dist/client/widgets/slider/index.js +9 -0
  116. package/dist/client/widgets/table/index.d.ts +6 -0
  117. package/dist/client/widgets/table/index.js +72 -0
  118. package/dist/client/widgets/table/lazy.d.ts +3 -0
  119. package/dist/client/widgets/table/lazy.js +16 -0
  120. package/dist/client/widgets/tabs/index.d.ts +5 -0
  121. package/dist/client/widgets/tabs/index.js +10 -0
  122. package/dist/client/widgets/text/index.d.ts +6 -0
  123. package/dist/client/widgets/text/index.js +10 -0
  124. package/dist/client/widgets/upload/index.d.ts +6 -0
  125. package/dist/client/widgets/upload/index.js +16 -0
  126. package/dist/client/widgets/video/index.d.ts +5 -0
  127. package/dist/client/widgets/video/index.js +5 -0
  128. package/dist/client/widgets/webcam/index.d.ts +6 -0
  129. package/dist/client/widgets/webcam/index.js +62 -0
  130. package/dist/client.css +1 -0
  131. package/dist/client.js +11 -0
  132. package/dist/knobkit.browser.css +2 -0
  133. package/dist/knobkit.browser.js +151 -0
  134. package/dist/lib/bound.d.ts +12 -0
  135. package/dist/lib/bound.js +10 -0
  136. package/dist/lib/controls.d.ts +9 -0
  137. package/dist/lib/controls.js +35 -0
  138. package/dist/lib/ctx.d.ts +9 -0
  139. package/dist/lib/ctx.js +22 -0
  140. package/dist/lib/declare.d.ts +18 -0
  141. package/dist/lib/declare.js +43 -0
  142. package/dist/lib/event.d.ts +2 -0
  143. package/dist/lib/event.js +9 -0
  144. package/dist/lib/index.d.ts +10 -0
  145. package/dist/lib/index.js +6 -0
  146. package/dist/lib/knobkit.d.ts +19 -0
  147. package/dist/lib/knobkit.js +48 -0
  148. package/dist/lib/on.d.ts +2 -0
  149. package/dist/lib/on.js +1 -0
  150. package/dist/lib/stream.d.ts +1 -0
  151. package/dist/lib/stream.js +33 -0
  152. package/dist/lib/types.d.ts +48 -0
  153. package/dist/lib/types.js +1 -0
  154. package/dist/lib/widget.d.ts +7 -0
  155. package/dist/lib/widget.js +4 -0
  156. package/dist/lib/widgets/annotated-image.d.ts +14 -0
  157. package/dist/lib/widgets/annotated-image.js +16 -0
  158. package/dist/lib/widgets/audio.d.ts +10 -0
  159. package/dist/lib/widgets/audio.js +13 -0
  160. package/dist/lib/widgets/button.d.ts +11 -0
  161. package/dist/lib/widgets/button.js +17 -0
  162. package/dist/lib/widgets/chart.d.ts +20 -0
  163. package/dist/lib/widgets/chart.js +24 -0
  164. package/dist/lib/widgets/chat.d.ts +26 -0
  165. package/dist/lib/widgets/chat.js +24 -0
  166. package/dist/lib/widgets/checkbox-group.d.ts +4 -0
  167. package/dist/lib/widgets/checkbox-group.js +5 -0
  168. package/dist/lib/widgets/checkbox.d.ts +4 -0
  169. package/dist/lib/widgets/checkbox.js +4 -0
  170. package/dist/lib/widgets/code.d.ts +5 -0
  171. package/dist/lib/widgets/code.js +10 -0
  172. package/dist/lib/widgets/dropdown.d.ts +4 -0
  173. package/dist/lib/widgets/dropdown.js +4 -0
  174. package/dist/lib/widgets/embed.d.ts +5 -0
  175. package/dist/lib/widgets/embed.js +23 -0
  176. package/dist/lib/widgets/file.d.ts +11 -0
  177. package/dist/lib/widgets/file.js +15 -0
  178. package/dist/lib/widgets/frame.d.ts +18 -0
  179. package/dist/lib/widgets/frame.js +25 -0
  180. package/dist/lib/widgets/gallery.d.ts +12 -0
  181. package/dist/lib/widgets/gallery.js +17 -0
  182. package/dist/lib/widgets/highlighted-text.d.ts +12 -0
  183. package/dist/lib/widgets/highlighted-text.js +15 -0
  184. package/dist/lib/widgets/html.d.ts +9 -0
  185. package/dist/lib/widgets/html.js +12 -0
  186. package/dist/lib/widgets/image.d.ts +7 -0
  187. package/dist/lib/widgets/image.js +12 -0
  188. package/dist/lib/widgets/index.d.ts +31 -0
  189. package/dist/lib/widgets/index.js +31 -0
  190. package/dist/lib/widgets/json.d.ts +7 -0
  191. package/dist/lib/widgets/json.js +12 -0
  192. package/dist/lib/widgets/label.d.ts +15 -0
  193. package/dist/lib/widgets/label.js +18 -0
  194. package/dist/lib/widgets/layout.d.ts +21 -0
  195. package/dist/lib/widgets/layout.js +29 -0
  196. package/dist/lib/widgets/log.d.ts +8 -0
  197. package/dist/lib/widgets/log.js +15 -0
  198. package/dist/lib/widgets/mic.d.ts +19 -0
  199. package/dist/lib/widgets/mic.js +28 -0
  200. package/dist/lib/widgets/number.d.ts +5 -0
  201. package/dist/lib/widgets/number.js +4 -0
  202. package/dist/lib/widgets/output.d.ts +10 -0
  203. package/dist/lib/widgets/output.js +13 -0
  204. package/dist/lib/widgets/progress.d.ts +10 -0
  205. package/dist/lib/widgets/progress.js +15 -0
  206. package/dist/lib/widgets/radio.d.ts +4 -0
  207. package/dist/lib/widgets/radio.js +5 -0
  208. package/dist/lib/widgets/slider.d.ts +6 -0
  209. package/dist/lib/widgets/slider.js +6 -0
  210. package/dist/lib/widgets/table.d.ts +32 -0
  211. package/dist/lib/widgets/table.js +36 -0
  212. package/dist/lib/widgets/text.d.ts +4 -0
  213. package/dist/lib/widgets/text.js +4 -0
  214. package/dist/lib/widgets/upload.d.ts +3 -0
  215. package/dist/lib/widgets/upload.js +5 -0
  216. package/dist/lib/widgets/value.d.ts +9 -0
  217. package/dist/lib/widgets/value.js +20 -0
  218. package/dist/lib/widgets/video.d.ts +12 -0
  219. package/dist/lib/widgets/video.js +14 -0
  220. package/dist/lib/widgets/webcam.d.ts +21 -0
  221. package/dist/lib/widgets/webcam.js +29 -0
  222. package/dist/server/context.d.ts +2 -0
  223. package/dist/server/context.js +10 -0
  224. package/dist/server/serve.d.ts +5 -0
  225. package/dist/server/serve.js +131 -0
  226. package/package.json +71 -0
  227. package/src/cli/config.ts +83 -0
  228. package/src/cli/index.ts +82 -0
  229. package/src/cli/mount.ts +25 -0
  230. package/src/cli/serve.ts +22 -0
  231. package/src/client/app.test.tsx +70 -0
  232. package/src/client/app.tsx +62 -0
  233. package/src/client/browser-runtime.test.ts +22 -0
  234. package/src/client/browser.ts +3 -0
  235. package/src/client/context.ts +17 -0
  236. package/src/client/embed.test.tsx +58 -0
  237. package/src/client/entry.tsx +25 -0
  238. package/src/client/mount.test.tsx +36 -0
  239. package/src/client/mount.tsx +48 -0
  240. package/src/client/runtime.test.ts +64 -0
  241. package/src/client/runtime.ts +112 -0
  242. package/src/client/serve-stub.ts +3 -0
  243. package/src/client/styles.css +131 -0
  244. package/src/client/view.ts +16 -0
  245. package/src/client/widgets/accordion/accordion.css +35 -0
  246. package/src/client/widgets/accordion/index.tsx +17 -0
  247. package/src/client/widgets/annotated-image/annotated-image.css +62 -0
  248. package/src/client/widgets/annotated-image/index.tsx +73 -0
  249. package/src/client/widgets/audio/audio.css +6 -0
  250. package/src/client/widgets/audio/index.tsx +6 -0
  251. package/src/client/widgets/button/button.css +25 -0
  252. package/src/client/widgets/button/index.tsx +11 -0
  253. package/src/client/widgets/chart/chart.css +12 -0
  254. package/src/client/widgets/chart/index.tsx +63 -0
  255. package/src/client/widgets/chart/lazy.tsx +15 -0
  256. package/src/client/widgets/chat/chat.css +97 -0
  257. package/src/client/widgets/chat/index.tsx +121 -0
  258. package/src/client/widgets/checkbox/checkbox.css +15 -0
  259. package/src/client/widgets/checkbox/index.tsx +15 -0
  260. package/src/client/widgets/checkbox-group/checkbox-group.css +20 -0
  261. package/src/client/widgets/checkbox-group/index.tsx +22 -0
  262. package/src/client/widgets/code/code.css +31 -0
  263. package/src/client/widgets/code/index.tsx +108 -0
  264. package/src/client/widgets/code/lazy.tsx +16 -0
  265. package/src/client/widgets/dropdown/dropdown.css +0 -0
  266. package/src/client/widgets/dropdown/index.tsx +19 -0
  267. package/src/client/widgets/file/file.css +26 -0
  268. package/src/client/widgets/file/index.tsx +12 -0
  269. package/src/client/widgets/frame/frame.css +17 -0
  270. package/src/client/widgets/frame/index.tsx +15 -0
  271. package/src/client/widgets/gallery/gallery.css +26 -0
  272. package/src/client/widgets/gallery/index.tsx +18 -0
  273. package/src/client/widgets/highlighted-text/highlighted-text.css +21 -0
  274. package/src/client/widgets/highlighted-text/index.tsx +42 -0
  275. package/src/client/widgets/html/index.tsx +8 -0
  276. package/src/client/widgets/image/index.tsx +5 -0
  277. package/src/client/widgets/json/index.tsx +5 -0
  278. package/src/client/widgets/json/json.css +0 -0
  279. package/src/client/widgets/label/index.tsx +20 -0
  280. package/src/client/widgets/label/label.css +39 -0
  281. package/src/client/widgets/layout/index.tsx +14 -0
  282. package/src/client/widgets/log/index.tsx +5 -0
  283. package/src/client/widgets/log/log.css +0 -0
  284. package/src/client/widgets/mic/index.tsx +85 -0
  285. package/src/client/widgets/mic/mic.css +8 -0
  286. package/src/client/widgets/number/index.tsx +10 -0
  287. package/src/client/widgets/number/number.css +0 -0
  288. package/src/client/widgets/output/index.tsx +19 -0
  289. package/src/client/widgets/output/markdown.tsx +12 -0
  290. package/src/client/widgets/output/output.css +75 -0
  291. package/src/client/widgets/progress/index.tsx +14 -0
  292. package/src/client/widgets/progress/progress.css +26 -0
  293. package/src/client/widgets/radio/index.tsx +20 -0
  294. package/src/client/widgets/radio/radio.css +20 -0
  295. package/src/client/widgets/registry.tsx +71 -0
  296. package/src/client/widgets/slider/index.tsx +23 -0
  297. package/src/client/widgets/slider/slider.css +18 -0
  298. package/src/client/widgets/table/index.tsx +95 -0
  299. package/src/client/widgets/table/lazy.tsx +23 -0
  300. package/src/client/widgets/table/table.css +15 -0
  301. package/src/client/widgets/tabs/index.tsx +28 -0
  302. package/src/client/widgets/tabs/tabs.css +30 -0
  303. package/src/client/widgets/text/index.tsx +16 -0
  304. package/src/client/widgets/text/text.css +21 -0
  305. package/src/client/widgets/upload/index.tsx +30 -0
  306. package/src/client/widgets/upload/upload.css +30 -0
  307. package/src/client/widgets/video/index.tsx +10 -0
  308. package/src/client/widgets/video/video.css +8 -0
  309. package/src/client/widgets/webcam/index.tsx +81 -0
  310. package/src/client/widgets/webcam/webcam.css +46 -0
  311. package/src/css.d.ts +1 -0
  312. package/src/env.d.ts +1 -0
  313. package/src/lib/bound.ts +30 -0
  314. package/src/lib/controls.ts +36 -0
  315. package/src/lib/ctx.ts +31 -0
  316. package/src/lib/declare.test.ts +46 -0
  317. package/src/lib/declare.ts +74 -0
  318. package/src/lib/event.ts +12 -0
  319. package/src/lib/index.ts +21 -0
  320. package/src/lib/knobkit.ts +57 -0
  321. package/src/lib/on.ts +3 -0
  322. package/src/lib/stream.ts +38 -0
  323. package/src/lib/types.ts +63 -0
  324. package/src/lib/widget.ts +11 -0
  325. package/src/lib/widgets/annotated-image.ts +34 -0
  326. package/src/lib/widgets/audio.ts +20 -0
  327. package/src/lib/widgets/button.ts +27 -0
  328. package/src/lib/widgets/chart.ts +44 -0
  329. package/src/lib/widgets/chat.ts +43 -0
  330. package/src/lib/widgets/checkbox-group.ts +6 -0
  331. package/src/lib/widgets/checkbox.ts +5 -0
  332. package/src/lib/widgets/code.ts +11 -0
  333. package/src/lib/widgets/dropdown.ts +5 -0
  334. package/src/lib/widgets/embed.ts +26 -0
  335. package/src/lib/widgets/file.ts +23 -0
  336. package/src/lib/widgets/frame.ts +36 -0
  337. package/src/lib/widgets/gallery.ts +29 -0
  338. package/src/lib/widgets/highlighted-text.ts +29 -0
  339. package/src/lib/widgets/html.ts +18 -0
  340. package/src/lib/widgets/image.ts +18 -0
  341. package/src/lib/widgets/index.ts +31 -0
  342. package/src/lib/widgets/json.ts +18 -0
  343. package/src/lib/widgets/label.ts +29 -0
  344. package/src/lib/widgets/layout.ts +47 -0
  345. package/src/lib/widgets/log.ts +22 -0
  346. package/src/lib/widgets/mic.ts +42 -0
  347. package/src/lib/widgets/number.ts +5 -0
  348. package/src/lib/widgets/output.ts +20 -0
  349. package/src/lib/widgets/progress.ts +21 -0
  350. package/src/lib/widgets/radio.ts +6 -0
  351. package/src/lib/widgets/slider.ts +7 -0
  352. package/src/lib/widgets/table.ts +58 -0
  353. package/src/lib/widgets/text.ts +5 -0
  354. package/src/lib/widgets/upload.ts +6 -0
  355. package/src/lib/widgets/value.ts +28 -0
  356. package/src/lib/widgets/video.ts +22 -0
  357. package/src/lib/widgets/webcam.ts +46 -0
  358. package/src/server/context.ts +12 -0
  359. package/src/server/serve.test.ts +121 -0
  360. package/src/server/serve.ts +130 -0
  361. package/tsconfig.base.json +14 -0
@@ -0,0 +1,23 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface FileWidget extends Widget<{ name: string; url: string }> {
6
+ // Offer a file for download — the output counterpart to `upload`. Pass a URL (or data URL) and an
7
+ // optional display name; the name defaults to the URL's last path segment.
8
+ set(value: { name?: string; url: string } | string): void;
9
+ }
10
+
11
+ export function file(): FileWidget {
12
+ return {
13
+ type: "file",
14
+ state: { name: "", url: "" },
15
+ ...controls,
16
+ set(value: { name?: string; url: string } | string): void {
17
+ const v = typeof value === "string" ? { url: value } : value;
18
+ const b = bound(this);
19
+ b.edit(this, "set", ["url"], v.url);
20
+ b.edit(this, "set", ["name"], v.name ?? v.url.split("/").pop()?.split("?")[0] ?? "download");
21
+ },
22
+ };
23
+ }
@@ -0,0 +1,36 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ import type { EventCtor, Widget } from "../types.js";
5
+
6
+ export interface FrameWidget extends Widget<{ src: string; doc: string }> {
7
+ sandbox?: string;
8
+ title: string;
9
+ loaded: EventCtor;
10
+ load(url: string): void;
11
+ show(doc: string): void;
12
+ clear(): void;
13
+ }
14
+
15
+ export function frame(opts: { src?: string; doc?: string; sandbox?: string; title?: string } = {}): FrameWidget {
16
+ return {
17
+ type: "frame",
18
+ state: { src: opts.src ?? "", doc: opts.doc ?? "" },
19
+ sandbox: opts.sandbox,
20
+ title: opts.title ?? "frame",
21
+ loaded: event("frame.loaded"),
22
+ ...controls,
23
+ load(url: string): void {
24
+ bound(this).edit(this, "set", ["doc"], "");
25
+ bound(this).edit(this, "set", ["src"], url);
26
+ },
27
+ show(doc: string): void {
28
+ bound(this).edit(this, "set", ["src"], "");
29
+ bound(this).edit(this, "set", ["doc"], doc);
30
+ },
31
+ clear(): void {
32
+ bound(this).edit(this, "set", ["src"], "");
33
+ bound(this).edit(this, "set", ["doc"], "");
34
+ },
35
+ };
36
+ }
@@ -0,0 +1,29 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface GalleryItem {
6
+ src: string; // URL or data URL
7
+ caption?: string;
8
+ }
9
+
10
+ export interface GalleryWidget extends Widget<{ items: GalleryItem[] }> {
11
+ set(items: GalleryItem[]): void; // replace the whole grid
12
+ add(item: GalleryItem): void; // append one image
13
+ }
14
+
15
+ // A grid of images (the canonical output for batched image generation). Not a layout container — its
16
+ // `items` are image records, not child widget keys.
17
+ export function gallery(): GalleryWidget {
18
+ return {
19
+ type: "gallery",
20
+ state: { items: [] },
21
+ ...controls,
22
+ set(items: GalleryItem[]): void {
23
+ bound(this).edit(this, "set", ["items"], items);
24
+ },
25
+ add(item: GalleryItem): void {
26
+ bound(this).edit(this, "append", ["items"], item);
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,29 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface HighlightSpan {
6
+ text: string;
7
+ label?: string | null; // null/omitted => plain, unhighlighted run of text
8
+ }
9
+
10
+ export interface HighlightedTextWidget
11
+ extends Widget<{ value: HighlightSpan[]; colorMap: Record<string, string> }> {
12
+ // The canonical output for token classification / NER / diff: a sequence of text runs, each
13
+ // optionally tagged with a label that colors it. `colorMap` pins a color per label; unmapped
14
+ // labels get a stable auto color in the view.
15
+ set(value: HighlightSpan[], colorMap?: Record<string, string>): void;
16
+ }
17
+
18
+ export function highlightedText(): HighlightedTextWidget {
19
+ return {
20
+ type: "highlightedText",
21
+ state: { value: [], colorMap: {} },
22
+ ...controls,
23
+ set(value: HighlightSpan[], colorMap?: Record<string, string>): void {
24
+ const b = bound(this);
25
+ if (colorMap !== undefined) b.edit(this, "set", ["colorMap"], colorMap);
26
+ b.edit(this, "set", ["value"], value);
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,18 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface HtmlWidget extends Widget<{ value: string }> {
6
+ set(value: string): void; // replace the rendered HTML (the escape hatch for custom markup)
7
+ }
8
+
9
+ export function html(opts: { value?: string } = {}): HtmlWidget {
10
+ return {
11
+ type: "html",
12
+ state: { value: opts.value ?? "" },
13
+ ...controls,
14
+ set(value: string): void {
15
+ bound(this).edit(this, "set", ["value"], value);
16
+ },
17
+ };
18
+ }
@@ -0,0 +1,18 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface ImageWidget extends Widget<{ src: string }> {
6
+ set(value: string): void; // set the displayed image (URL or data URL)
7
+ }
8
+
9
+ export function image(): ImageWidget {
10
+ return {
11
+ type: "image",
12
+ state: { src: "" },
13
+ ...controls,
14
+ set(value: string): void {
15
+ bound(this).edit(this, "set", ["src"], value);
16
+ },
17
+ };
18
+ }
@@ -0,0 +1,31 @@
1
+ export * from "./text.js";
2
+ export * from "./number.js";
3
+ export * from "./slider.js";
4
+ export * from "./code.js";
5
+ export * from "./table.js";
6
+ export * from "./chart.js";
7
+ export * from "./dropdown.js";
8
+ export * from "./checkbox.js";
9
+ export * from "./checkbox-group.js";
10
+ export * from "./radio.js";
11
+ export * from "./gallery.js";
12
+ export * from "./video.js";
13
+ export * from "./label.js";
14
+ export * from "./highlighted-text.js";
15
+ export * from "./annotated-image.js";
16
+ export * from "./file.js";
17
+ export * from "./progress.js";
18
+ export * from "./html.js";
19
+ export * from "./frame.js";
20
+ export * from "./upload.js";
21
+ export * from "./image.js";
22
+ export * from "./button.js";
23
+ export * from "./mic.js";
24
+ export * from "./chat.js";
25
+ export * from "./output.js";
26
+ export * from "./json.js";
27
+ export * from "./log.js";
28
+ export * from "./audio.js";
29
+ export * from "./webcam.js";
30
+ export * from "./layout.js";
31
+ export { embed } from "./embed.js";
@@ -0,0 +1,18 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface JsonWidget extends Widget<{ value: unknown }> {
6
+ set(value: unknown): void; // replace the displayed value
7
+ }
8
+
9
+ export function json(): JsonWidget {
10
+ return {
11
+ type: "json",
12
+ state: { value: null },
13
+ ...controls,
14
+ set(value: unknown): void {
15
+ bound(this).edit(this, "set", ["value"], value);
16
+ },
17
+ };
18
+ }
@@ -0,0 +1,29 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface LabelClass {
6
+ label: string;
7
+ score: number; // 0..1
8
+ }
9
+
10
+ export interface LabelWidget extends Widget<{ label: string; confidences: LabelClass[] }> {
11
+ // The classifier result: either a bare label, or a label with per-class confidences (rendered as
12
+ // bars). When only confidences are given, the top-scoring class becomes the headline label.
13
+ set(value: string | { label?: string; confidences?: LabelClass[] }): void;
14
+ }
15
+
16
+ export function label(): LabelWidget {
17
+ return {
18
+ type: "label",
19
+ state: { label: "", confidences: [] },
20
+ ...controls,
21
+ set(value: string | { label?: string; confidences?: LabelClass[] }): void {
22
+ const v = typeof value === "string" ? { label: value, confidences: [] as LabelClass[] } : value;
23
+ const b = bound(this);
24
+ if (v.confidences !== undefined) b.edit(this, "set", ["confidences"], v.confidences);
25
+ const top = v.label ?? v.confidences?.reduce((a, c) => (c.score > a.score ? c : a), v.confidences[0])?.label;
26
+ if (top !== undefined) b.edit(this, "set", ["label"], top);
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,47 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface LayoutWidget extends Widget<{ items: string[] }> {
6
+ children: Widget<any>[];
7
+ add(child: Widget<any>): void;
8
+ remove(child: Widget<any>): Promise<void>;
9
+ }
10
+
11
+ function container(type: string, children: Widget<any>[], props: Record<string, unknown> = {}): LayoutWidget {
12
+ return {
13
+ type,
14
+ state: { items: [] },
15
+ children,
16
+ ...controls,
17
+ add(child: Widget<any>): void {
18
+ const b = bound(this);
19
+ b.edit(this, "append", ["items"], b.key(child));
20
+ },
21
+ async remove(child: Widget<any>): Promise<void> {
22
+ const b = bound(this);
23
+ const key = b.key(child);
24
+ const items = await b.read<string[]>(this, ["items"]);
25
+ b.edit(this, "set", ["items"], items.filter((k) => k !== key));
26
+ },
27
+ ...props,
28
+ };
29
+ }
30
+
31
+ export const row = (...children: Widget<any>[]): LayoutWidget => container("row", children);
32
+ export const col = (...children: Widget<any>[]): LayoutWidget => container("col", children);
33
+ export const grid = (children: Widget<any>[], opts: { cols?: number } = {}): LayoutWidget =>
34
+ container("grid", children, { cols: opts.cols ?? 2 });
35
+
36
+ // Tabbed container: each panel is a labelled child. `labels` rides alongside `items` (the child keys)
37
+ // in the same order; the active tab is view-local state, so switching tabs never round-trips.
38
+ export const tabs = (panels: { label: string; content: Widget<any> }[]): LayoutWidget =>
39
+ container(
40
+ "tabs",
41
+ panels.map((p) => p.content),
42
+ { labels: panels.map((p) => p.label) },
43
+ );
44
+
45
+ // A single collapsible section. `open` is the initial state; toggling it is view-local.
46
+ export const accordion = (opts: { label: string; open?: boolean }, ...children: Widget<any>[]): LayoutWidget =>
47
+ container("accordion", children, { label: opts.label, open: opts.open ?? true });
@@ -0,0 +1,22 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface LogWidget extends Widget<{ lines: string[] }> {
6
+ push(line: string): void;
7
+ all(): Promise<string[]>;
8
+ }
9
+
10
+ export function log(): LogWidget {
11
+ return {
12
+ type: "log",
13
+ state: { lines: [] },
14
+ ...controls,
15
+ push(line: string): void {
16
+ bound(this).edit(this, "append", ["lines"], line);
17
+ },
18
+ all(): Promise<string[]> {
19
+ return bound(this).read<string[]>(this, ["lines"]);
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,42 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ import type { EventCtor, Widget } from "../types.js";
5
+
6
+ export interface MicWidget extends Widget<{ live: boolean }> {
7
+ clip: EventCtor<Float32Array>;
8
+ toggled: EventCtor<boolean>;
9
+ every: number;
10
+ control: boolean;
11
+ hold: boolean;
12
+ start(): void;
13
+ stop(): void;
14
+ toggle(): Promise<void>;
15
+ live(): Promise<boolean>;
16
+ }
17
+
18
+ export function mic(opts: { every?: number; control?: boolean; hold?: boolean } = {}): MicWidget {
19
+ return {
20
+ type: "mic",
21
+ state: { live: false },
22
+ clip: event<Float32Array>("mic.clip"),
23
+ toggled: event<boolean>("mic.toggled"),
24
+ every: opts.every ?? 0,
25
+ control: opts.control ?? true,
26
+ hold: opts.hold ?? true,
27
+ ...controls,
28
+ start(): void {
29
+ bound(this).edit(this, "set", ["live"], true);
30
+ },
31
+ stop(): void {
32
+ bound(this).edit(this, "set", ["live"], false);
33
+ },
34
+ async toggle(): Promise<void> {
35
+ const live = await bound(this).read<boolean>(this, ["live"]);
36
+ bound(this).edit(this, "set", ["live"], !live);
37
+ },
38
+ live(): Promise<boolean> {
39
+ return bound(this).read<boolean>(this, ["live"]);
40
+ },
41
+ };
42
+ }
@@ -0,0 +1,5 @@
1
+ import { value } from "./value.js";
2
+
3
+ export function number(opts: { value?: number; min?: number; max?: number } = {}) {
4
+ return value("number", opts.value ?? 0, { min: opts.min, max: opts.max });
5
+ }
@@ -0,0 +1,20 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface OutputWidget extends Widget<{ value: string }> {
6
+ format: "text" | "markdown"; // how the view renders `value`; "text" is plain, "markdown" renders GFM
7
+ set(value: string): void; // replace the displayed text
8
+ }
9
+
10
+ export function output(opts: { format?: "text" | "markdown" } = {}): OutputWidget {
11
+ return {
12
+ type: "output",
13
+ state: { value: "" },
14
+ format: opts.format ?? "text",
15
+ ...controls,
16
+ set(value: string): void {
17
+ bound(this).edit(this, "set", ["value"], value);
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,21 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface ProgressWidget extends Widget<{ value: number; label: string }> {
6
+ // Drive a determinate bar: `value` is a 0..1 fraction, with an optional caption.
7
+ set(value: number, label?: string): void;
8
+ }
9
+
10
+ export function progress(opts: { label?: string } = {}): ProgressWidget {
11
+ return {
12
+ type: "progress",
13
+ state: { value: 0, label: opts.label ?? "" },
14
+ ...controls,
15
+ set(value: number, label?: string): void {
16
+ const b = bound(this);
17
+ b.edit(this, "set", ["value"], value);
18
+ if (label !== undefined) b.edit(this, "set", ["label"], label);
19
+ },
20
+ };
21
+ }
@@ -0,0 +1,6 @@
1
+ import { value } from "./value.js";
2
+
3
+ // Single-select from a fixed set, like dropdown but rendered as radios.
4
+ export function radio(opts: { choices: string[]; value?: string }) {
5
+ return value("radio", opts.value ?? opts.choices[0]!, { choices: opts.choices });
6
+ }
@@ -0,0 +1,7 @@
1
+ import { value } from "./value.js";
2
+
3
+ export function slider(opts: { value?: number; min?: number; max?: number; step?: number } = {}) {
4
+ const min = opts.min ?? 0;
5
+ const max = opts.max ?? 100;
6
+ return value("slider", opts.value ?? min, { min, max, step: opts.step ?? 1 });
7
+ }
@@ -0,0 +1,58 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ import type { EventCtor, Widget } from "../types.js";
5
+
6
+ export interface Column {
7
+ key: string; // maps a column to the per-row object key (RevoGrid `prop`)
8
+ label?: string; // header text; defaults to `key`
9
+ type?: "text" | "number"; // cell editor/parsing hint
10
+ width?: number;
11
+ }
12
+ export type Row = Record<string, unknown>;
13
+
14
+ export interface TableWidget extends Widget<{ columns: Column[]; rows: Row[] }> {
15
+ edited: EventCtor<{ row: number; key: string; value: unknown }>; // a cell (or pasted cell) changed
16
+ editable: boolean;
17
+ maxHeight: number; // height ceiling in px; the grid fits its rows up to this, then scrolls
18
+ data(): Promise<Row[]>; // read all rows
19
+ columnsOf(): Promise<Column[]>; // read the column defs
20
+ setRows(rows: Row[]): void; // replace all rows
21
+ setColumns(columns: Column[]): void; // replace the column defs
22
+ addRow(row: Row): void; // append one row
23
+ setCell(row: number, key: string, value: unknown): void; // set one cell by row index + column key
24
+ }
25
+
26
+ // A tabular widget rendered by RevoGrid (virtualized, range-select, copy/paste, in-cell editing). State
27
+ // is the uniform shape — `{ columns, rows }` — and every mutation is a structured edit by path, so a
28
+ // cell edit is `set ["rows", r, key]` and a new row is `append ["rows"]`; the grid stays controlled by
29
+ // the store on both tiers. Defaults to read-only (a display table); pass `editable: true` to let the
30
+ // user edit cells.
31
+ export function table(opts: { columns?: Column[]; rows?: Row[]; editable?: boolean; maxHeight?: number } = {}): TableWidget {
32
+ return {
33
+ type: "table",
34
+ state: { columns: opts.columns ?? [], rows: opts.rows ?? [] },
35
+ edited: event<{ row: number; key: string; value: unknown }>("table.edited"),
36
+ editable: opts.editable ?? false,
37
+ maxHeight: opts.maxHeight ?? 500,
38
+ ...controls,
39
+ data(): Promise<Row[]> {
40
+ return bound(this).read<Row[]>(this, ["rows"]);
41
+ },
42
+ columnsOf(): Promise<Column[]> {
43
+ return bound(this).read<Column[]>(this, ["columns"]);
44
+ },
45
+ setRows(rows: Row[]): void {
46
+ bound(this).edit(this, "set", ["rows"], rows);
47
+ },
48
+ setColumns(columns: Column[]): void {
49
+ bound(this).edit(this, "set", ["columns"], columns);
50
+ },
51
+ addRow(row: Row): void {
52
+ bound(this).edit(this, "append", ["rows"], row);
53
+ },
54
+ setCell(row: number, key: string, value: unknown): void {
55
+ bound(this).edit(this, "set", ["rows", row, key], value);
56
+ },
57
+ };
58
+ }
@@ -0,0 +1,5 @@
1
+ import { value } from "./value.js";
2
+
3
+ export function text(opts: { placeholder?: string; lines?: number } = {}) {
4
+ return value("text", "", { placeholder: opts.placeholder, lines: opts.lines ?? 1 });
5
+ }
@@ -0,0 +1,6 @@
1
+ import { value } from "./value.js";
2
+
3
+ // state is the chosen image as a data URL
4
+ export function upload(opts: { accept?: string } = {}) {
5
+ return value<string | null>("upload", null, { accept: opts.accept ?? "image/*" });
6
+ }
@@ -0,0 +1,28 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ import type { EventCtor, Widget } from "../types.js";
5
+
6
+ export interface ValueWidget<S> extends Widget<{ value: S }> {
7
+ changed: EventCtor<S>;
8
+ value(): Promise<S>; // read the current input value
9
+ set(value: S): void; // set it programmatically
10
+ }
11
+
12
+ // A self-managing value input: it holds a single `value` attribute; its view (in `client`) edits that
13
+ // value locally as the user types and emits `changed` for handlers that care.
14
+ export function value<S>(type: string, initial: S, props: Record<string, unknown> = {}): ValueWidget<S> {
15
+ return {
16
+ type,
17
+ state: { value: initial },
18
+ changed: event<S>(`${type}.changed`),
19
+ ...controls,
20
+ value(): Promise<S> {
21
+ return bound(this).read<S>(this, ["value"]);
22
+ },
23
+ set(v: S): void {
24
+ bound(this).edit(this, "set", ["value"], v);
25
+ },
26
+ ...props,
27
+ };
28
+ }
@@ -0,0 +1,22 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ import type { Widget } from "../types.js";
4
+
5
+ export interface VideoWidget extends Widget<{ src: string }> {
6
+ autoplay: boolean;
7
+ loop: boolean;
8
+ set(value: string): void; // set the video source (URL or data URL)
9
+ }
10
+
11
+ export function video(opts: { autoplay?: boolean; loop?: boolean } = {}): VideoWidget {
12
+ return {
13
+ type: "video",
14
+ state: { src: "" },
15
+ autoplay: opts.autoplay ?? false,
16
+ loop: opts.loop ?? false,
17
+ ...controls,
18
+ set(value: string): void {
19
+ bound(this).edit(this, "set", ["src"], value);
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,46 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ import type { EventCtor, Widget } from "../types.js";
5
+
6
+ export interface WebcamWidget extends Widget<{ live: boolean }> {
7
+ frame: EventCtor<string>;
8
+ toggled: EventCtor<boolean>;
9
+ every: number;
10
+ control: boolean;
11
+ preview: boolean;
12
+ facing: "user" | "environment";
13
+ start(): void;
14
+ stop(): void;
15
+ toggle(): Promise<void>;
16
+ live(): Promise<boolean>;
17
+ }
18
+
19
+ export function webcam(
20
+ opts: { every?: number; control?: boolean; preview?: boolean; facing?: "user" | "environment" } = {},
21
+ ): WebcamWidget {
22
+ return {
23
+ type: "webcam",
24
+ state: { live: false },
25
+ frame: event<string>("webcam.frame"),
26
+ toggled: event<boolean>("webcam.toggled"),
27
+ every: opts.every ?? 0, // 0 = preview only; >0 = a frame every N ms
28
+ control: opts.control ?? true,
29
+ preview: opts.preview ?? true,
30
+ facing: opts.facing ?? "user",
31
+ ...controls,
32
+ start(): void {
33
+ bound(this).edit(this, "set", ["live"], true);
34
+ },
35
+ stop(): void {
36
+ bound(this).edit(this, "set", ["live"], false);
37
+ },
38
+ async toggle(): Promise<void> {
39
+ const live = await bound(this).read<boolean>(this, ["live"]);
40
+ bound(this).edit(this, "set", ["live"], !live);
41
+ },
42
+ live(): Promise<boolean> {
43
+ return bound(this).read<boolean>(this, ["live"]);
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,12 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import { setBoundResolver, type Bound } from "../lib/bound.js";
3
+
4
+ // Per-request context binding for handlers. Each socket request runs inside `run(bound, …)`, so a
5
+ // widget method's `bound(this)` resolves to that request's snapshot reader / event sender even across
6
+ // awaits and concurrent requests.
7
+ const store = new AsyncLocalStorage<Bound>();
8
+ setBoundResolver(() => store.getStore());
9
+
10
+ export function run<T>(bound: Bound, fn: () => T): T {
11
+ return store.run(bound, fn);
12
+ }