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,12 @@
1
+ import type { Widget } from "./types.js";
2
+ export type Path = (string | number)[];
3
+ export type EditOp = "set" | "append" | "appendText";
4
+ export interface Bound {
5
+ read<T>(widget: Widget<any>, path: Path): Promise<T>;
6
+ edit(widget: Widget<any>, op: EditOp, path: Path, value: unknown): void;
7
+ enable(widget: Widget<any>, value: boolean): void;
8
+ busy(widget: Widget<any>, value: boolean): void;
9
+ key(widget: Widget<any>): string;
10
+ }
11
+ export declare function setBoundResolver(fn: () => Bound | undefined): void;
12
+ export declare function bound(_widget: Widget<any>): Bound;
@@ -0,0 +1,10 @@
1
+ let resolve = () => undefined;
2
+ export function setBoundResolver(fn) {
3
+ resolve = fn;
4
+ }
5
+ export function bound(_widget) {
6
+ const b = resolve();
7
+ if (!b)
8
+ throw new Error("widget method called outside a knobkit handler");
9
+ return b;
10
+ }
@@ -0,0 +1,9 @@
1
+ import type { Widget } from "./types.js";
2
+ export declare const controls: {
3
+ enable(this: Widget): void;
4
+ disable(this: Widget): void;
5
+ setEnabled(this: Widget, value: boolean): void;
6
+ busyStart(this: Widget): void;
7
+ busyEnd(this: Widget): void;
8
+ busy(this: Widget, run: (payload: any) => any): (payload: any) => Promise<any>;
9
+ };
@@ -0,0 +1,35 @@
1
+ import { bound } from "./bound.js";
2
+ // Spread into every widget factory so enable()/disable()/busy() are uniform. `enabled` and `busy` are
3
+ // two orthogonal runtime flags (both separate from state, both drop the widget's input events): enabled
4
+ // is a persistent "can't use this" (dimmed); busy is a transient "this is working" (a loading bar).
5
+ // `busyStart`/`busyEnd` mark a busy span by hand (e.g. across a setup() load); `busy(fn)` wraps an
6
+ // async fn in the same span. `this` is the widget at call time.
7
+ export const controls = {
8
+ enable() {
9
+ bound(this).enable(this, true);
10
+ },
11
+ disable() {
12
+ bound(this).enable(this, false);
13
+ },
14
+ setEnabled(value) {
15
+ bound(this).enable(this, value);
16
+ },
17
+ busyStart() {
18
+ bound(this).busy(this, true);
19
+ },
20
+ busyEnd() {
21
+ bound(this).busy(this, false);
22
+ },
23
+ busy(run) {
24
+ const self = this;
25
+ return async (payload) => {
26
+ self.busyStart();
27
+ try {
28
+ return await run(payload);
29
+ }
30
+ finally {
31
+ self.busyEnd();
32
+ }
33
+ };
34
+ },
35
+ };
@@ -0,0 +1,9 @@
1
+ import type { Bound, EditOp, Path } from "./bound.js";
2
+ import type { Widget } from "./types.js";
3
+ export declare function makeBound(opts: {
4
+ read: (key: string, path: Path) => Promise<unknown>;
5
+ edit: (key: string, op: EditOp, path: Path, value: unknown) => void;
6
+ enable: (key: string, value: boolean) => void;
7
+ busy: (key: string, value: boolean) => void;
8
+ keyFor: (widget: Widget<any>) => string;
9
+ }): Bound;
@@ -0,0 +1,22 @@
1
+ // Builds a handler-time Bound from low-level transport functions. Reads proxy to wherever the state
2
+ // lives (the client, over the socket); edits/enables are sent for the client to apply. Translates the
3
+ // widget object to its key; the handler never sees keys.
4
+ export function makeBound(opts) {
5
+ return {
6
+ read(widget, path) {
7
+ return opts.read(opts.keyFor(widget), path);
8
+ },
9
+ edit(widget, op, path, value) {
10
+ opts.edit(opts.keyFor(widget), op, path, value);
11
+ },
12
+ enable(widget, value) {
13
+ opts.enable(opts.keyFor(widget), value);
14
+ },
15
+ busy(widget, value) {
16
+ opts.busy(opts.keyFor(widget), value);
17
+ },
18
+ key(widget) {
19
+ return opts.keyFor(widget);
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,18 @@
1
+ import type { AppConfig, Widget } from "./types.js";
2
+ export interface WidgetDecl {
3
+ key: string;
4
+ type: string;
5
+ state: unknown;
6
+ enabled: boolean;
7
+ props: Record<string, unknown>;
8
+ events: Record<string, string>;
9
+ }
10
+ export interface AppDecl {
11
+ title?: string;
12
+ description?: string;
13
+ widgets: WidgetDecl[];
14
+ root: string;
15
+ serverEvents: string[];
16
+ }
17
+ export declare function widgetKeys(widgets: Widget<any> | Widget<any>[]): Map<Widget<any>, string>;
18
+ export declare function declare(config: AppConfig, serverEvents?: string[]): AppDecl;
@@ -0,0 +1,43 @@
1
+ const SKIP = new Set(["state", "behavior", "view", "fold", "type", "children", "__subapp"]);
2
+ function buildTree(widgets) {
3
+ let n = 0;
4
+ const visit = (w) => ({
5
+ widget: w,
6
+ key: `${w.type || "widget"}-${n++}`,
7
+ children: (w.children ?? []).map(visit),
8
+ });
9
+ const root = Array.isArray(widgets) ? { type: "col", state: {}, children: widgets } : widgets;
10
+ return visit(root);
11
+ }
12
+ function flatten(node) {
13
+ return [node, ...node.children.flatMap(flatten)];
14
+ }
15
+ export function widgetKeys(widgets) {
16
+ const map = new Map();
17
+ for (const node of flatten(buildTree(widgets)))
18
+ map.set(node.widget, node.key);
19
+ return map;
20
+ }
21
+ function toDecl(node) {
22
+ const w = node.widget;
23
+ const props = {};
24
+ const events = {};
25
+ for (const [k, v] of Object.entries(w)) {
26
+ if (SKIP.has(k))
27
+ continue;
28
+ if (typeof v === "function" && typeof v.type === "string") {
29
+ events[k] = v.type;
30
+ }
31
+ else if (typeof v !== "function") {
32
+ props[k] = v;
33
+ }
34
+ }
35
+ const isContainer = Array.isArray(w.children);
36
+ const state = isContainer ? { items: node.children.map((c) => c.key) } : w.state;
37
+ return { key: node.key, type: w.type ?? "", state, enabled: true, props, events };
38
+ }
39
+ export function declare(config, serverEvents = []) {
40
+ const root = buildTree(config.widgets);
41
+ const widgets = flatten(root).map(toDecl);
42
+ return { title: config.title, description: config.description, widgets, root: root.key, serverEvents };
43
+ }
@@ -0,0 +1,2 @@
1
+ import type { EventCtor } from "./types.js";
2
+ export declare function event<P = void>(name?: string): EventCtor<P>;
@@ -0,0 +1,9 @@
1
+ let counter = 0;
2
+ // Declare an event. Each call is a distinct event with a unique `type`; the optional name is only
3
+ // for readability. The returned constructor makes instances: `Token("hi") -> { type, payload }`.
4
+ export function event(name) {
5
+ const type = `${name ?? "event"}#${counter++}`;
6
+ const ctor = ((payload) => ({ type, payload }));
7
+ ctor.type = type;
8
+ return ctor;
9
+ }
@@ -0,0 +1,10 @@
1
+ export type { Event, EventCtor, Emit, On, Widget, SelfListen, Produce, Listen, AppConfig, KnobkitServer, } from "./types.js";
2
+ export type { Handler } from "./on.js";
3
+ export type { Bound } from "./bound.js";
4
+ export { event } from "./event.js";
5
+ export { widget } from "./widget.js";
6
+ export { bound } from "./bound.js";
7
+ export { stream } from "./stream.js";
8
+ export { Knobkit, knobkit } from "./knobkit.js";
9
+ export type { KnobkitApp } from "./knobkit.js";
10
+ export * from "./widgets/index.js";
@@ -0,0 +1,6 @@
1
+ export { event } from "./event.js";
2
+ export { widget } from "./widget.js";
3
+ export { bound } from "./bound.js";
4
+ export { stream } from "./stream.js";
5
+ export { Knobkit, knobkit } from "./knobkit.js";
6
+ export * from "./widgets/index.js";
@@ -0,0 +1,19 @@
1
+ import type { AppConfig, KnobkitServer, EventCtor, Widget } from "./types.js";
2
+ import type { Handler } from "./on.js";
3
+ export declare class Knobkit {
4
+ config: AppConfig;
5
+ readonly handlers: Map<string, Handler<any>[]>;
6
+ readonly setups: Array<() => void | Promise<void>>;
7
+ private readonly keys;
8
+ constructor(config: AppConfig);
9
+ keyFor(widget: Widget<any>): string;
10
+ on<P>(source: EventCtor<P>, handler: Handler<P>): this;
11
+ setup(fn: () => void | Promise<void>): this;
12
+ serverEvents(): string[];
13
+ mount(selector: string): void;
14
+ serve(opts?: {
15
+ port?: number;
16
+ }): Promise<KnobkitServer>;
17
+ }
18
+ export type KnobkitApp = Knobkit;
19
+ export declare function knobkit(config: AppConfig): Knobkit;
@@ -0,0 +1,48 @@
1
+ import { widgetKeys } from "./declare.js";
2
+ import { collectSubapps } from "./widgets/embed.js";
3
+ // The knobkit is the authored app: a set of widgets plus the `on(event, handler)` handlers registered
4
+ // against their events. It holds no state — the browser owns that. Handlers run on the server (serve)
5
+ // or in-browser (mount); both resolve a handler by the event's `type`.
6
+ export class Knobkit {
7
+ config;
8
+ handlers = new Map();
9
+ setups = [];
10
+ keys;
11
+ constructor(config) {
12
+ this.config = config;
13
+ this.keys = widgetKeys(config.widgets);
14
+ for (const sub of collectSubapps(config.widgets)) {
15
+ for (const [type, hs] of sub.handlers)
16
+ this.handlers.set(type, [...(this.handlers.get(type) ?? []), ...hs]);
17
+ this.setups.push(...sub.setups);
18
+ }
19
+ }
20
+ keyFor(widget) {
21
+ const key = this.keys.get(widget);
22
+ if (!key)
23
+ throw new Error("widget is not part of this knobkit — pass it to knobkit({ widgets })");
24
+ return key;
25
+ }
26
+ on(source, handler) {
27
+ const list = this.handlers.get(source.type) ?? [];
28
+ list.push(handler);
29
+ this.handlers.set(source.type, list);
30
+ return this;
31
+ }
32
+ setup(fn) {
33
+ this.setups.push(fn);
34
+ return this;
35
+ }
36
+ serverEvents() {
37
+ return [...this.handlers.keys()];
38
+ }
39
+ mount(selector) {
40
+ void import("../client/mount.js").then(({ mount }) => mount(this, selector));
41
+ }
42
+ serve(opts) {
43
+ return import("../server/serve.js").then(({ serve }) => serve(this, opts));
44
+ }
45
+ }
46
+ export function knobkit(config) {
47
+ return new Knobkit(config);
48
+ }
@@ -0,0 +1,2 @@
1
+ import type { Event } from "./types.js";
2
+ export type Handler<P> = (payload: P) => void | Event | Promise<void | Event>;
package/dist/lib/on.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function stream<T>(run: (push: (value: T) => void) => Promise<void> | void): AsyncGenerator<T>;
@@ -0,0 +1,33 @@
1
+ export async function* stream(run) {
2
+ const buffer = [];
3
+ let wake = null;
4
+ let done = false;
5
+ let failure = null;
6
+ const push = (value) => {
7
+ buffer.push(value);
8
+ wake?.();
9
+ wake = null;
10
+ };
11
+ Promise.resolve(run(push)).then(() => {
12
+ done = true;
13
+ wake?.();
14
+ }, (err) => {
15
+ failure = err;
16
+ done = true;
17
+ wake?.();
18
+ });
19
+ while (true) {
20
+ if (buffer.length) {
21
+ yield buffer.shift();
22
+ continue;
23
+ }
24
+ if (done) {
25
+ if (failure)
26
+ throw failure;
27
+ return;
28
+ }
29
+ await new Promise((resolve) => {
30
+ wake = resolve;
31
+ });
32
+ }
33
+ }
@@ -0,0 +1,48 @@
1
+ export interface Event<P = unknown> {
2
+ type: string;
3
+ payload: P;
4
+ }
5
+ export interface EventCtor<P = void> {
6
+ (payload: P): Event<P>;
7
+ type: string;
8
+ }
9
+ export type Emit = <P>(event: Event<P>) => void;
10
+ export type On<P = any> = EventCtor<P> | Widget<any>;
11
+ export type Produce<P = any, I = any, V = any> = (payload: P, inputs: I) => V | Promise<V> | AsyncIterable<V>;
12
+ export interface Widget<S = unknown> {
13
+ type?: string;
14
+ state: S;
15
+ children?: Widget<any>[];
16
+ fold?: (state: any, value: any) => S;
17
+ behavior?: SelfListen<any, any>[];
18
+ view?: (state: S, emit: Emit) => unknown;
19
+ enable(): void;
20
+ disable(): void;
21
+ setEnabled(value: boolean): void;
22
+ busyStart(): void;
23
+ busyEnd(): void;
24
+ busy<P = unknown>(run: (payload: P) => void | Event | Promise<void | Event>): (payload: P) => Promise<void | Event>;
25
+ [key: string]: unknown;
26
+ }
27
+ export interface SelfListen<P = any, V = any> {
28
+ on: EventCtor<P>;
29
+ from?: Record<string, Widget<any>>;
30
+ respond: Produce<P, any, V>;
31
+ }
32
+ export interface Listen<P = any, I = any, V = any> {
33
+ on: On<P>;
34
+ in: Widget<any>;
35
+ from?: Record<string, Widget<any>>;
36
+ respond: Produce<P, I, V>;
37
+ }
38
+ export interface AppConfig {
39
+ title?: string;
40
+ description?: string;
41
+ events?: EventCtor<any>[];
42
+ widgets: Widget<any> | Widget<any>[];
43
+ loading?: string;
44
+ }
45
+ export interface KnobkitServer {
46
+ url: string;
47
+ stop(): Promise<void>;
48
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { Emit, SelfListen, Widget } from "./types.js";
2
+ export declare function widget<S>(init: {
3
+ state: S;
4
+ fold?: (state: S, value: any) => S;
5
+ view?: (state: S, emit: Emit) => unknown;
6
+ behavior?: SelfListen<any, any>[];
7
+ }): Widget<S>;
@@ -0,0 +1,4 @@
1
+ import { controls } from "./controls.js";
2
+ export function widget(init) {
3
+ return { state: init.state, fold: init.fold, view: init.view, behavior: init.behavior, ...controls };
4
+ }
@@ -0,0 +1,14 @@
1
+ import type { Widget } from "../types.js";
2
+ export interface Annotation {
3
+ label: string;
4
+ box?: [number, number, number, number];
5
+ mask?: string;
6
+ }
7
+ export interface AnnotatedImageWidget extends Widget<{
8
+ src: string;
9
+ annotations: Annotation[];
10
+ colorMap: Record<string, string>;
11
+ }> {
12
+ set(src: string, annotations?: Annotation[], colorMap?: Record<string, string>): void;
13
+ }
14
+ export declare function annotatedImage(): AnnotatedImageWidget;
@@ -0,0 +1,16 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ export function annotatedImage() {
4
+ return {
5
+ type: "annotatedImage",
6
+ state: { src: "", annotations: [], colorMap: {} },
7
+ ...controls,
8
+ set(src, annotations, colorMap) {
9
+ const b = bound(this);
10
+ if (colorMap !== undefined)
11
+ b.edit(this, "set", ["colorMap"], colorMap);
12
+ b.edit(this, "set", ["annotations"], annotations ?? []);
13
+ b.edit(this, "set", ["src"], src);
14
+ },
15
+ };
16
+ }
@@ -0,0 +1,10 @@
1
+ import type { Widget } from "../types.js";
2
+ export interface AudioWidget extends Widget<{
3
+ src: string;
4
+ }> {
5
+ autoplay: boolean;
6
+ set(value: string): void;
7
+ }
8
+ export declare function audio(opts?: {
9
+ autoplay?: boolean;
10
+ }): AudioWidget;
@@ -0,0 +1,13 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ export function audio(opts = {}) {
4
+ return {
5
+ type: "audio",
6
+ state: { src: "" },
7
+ autoplay: opts.autoplay ?? false,
8
+ ...controls,
9
+ set(value) {
10
+ bound(this).edit(this, "set", ["src"], value);
11
+ },
12
+ };
13
+ }
@@ -0,0 +1,11 @@
1
+ import type { EventCtor, Widget } from "../types.js";
2
+ export interface ButtonState {
3
+ label: string;
4
+ }
5
+ export interface ButtonWidget extends Widget<ButtonState> {
6
+ clicked: EventCtor;
7
+ set(patch: Partial<ButtonState>): void;
8
+ }
9
+ export declare function button(opts: {
10
+ label: string;
11
+ }): ButtonWidget;
@@ -0,0 +1,17 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ // state is the label it shows; whether it's interactive is the framework-level enabled flag (controls)
5
+ export function button(opts) {
6
+ return {
7
+ type: "button",
8
+ state: { label: opts.label },
9
+ clicked: event("button.clicked"),
10
+ ...controls,
11
+ set(patch) {
12
+ const rt = bound(this);
13
+ for (const [k, v] of Object.entries(patch))
14
+ rt.edit(this, "set", [k], v);
15
+ },
16
+ };
17
+ }
@@ -0,0 +1,20 @@
1
+ import type { Widget } from "../types.js";
2
+ export type Point = Record<string, unknown>;
3
+ export interface ChartWidget extends Widget<{
4
+ data: Point[];
5
+ }> {
6
+ kind: "bar" | "line" | "area";
7
+ x: string;
8
+ y: string | string[];
9
+ maxHeight: number;
10
+ data(): Promise<Point[]>;
11
+ setData(data: Point[]): void;
12
+ push(point: Point): void;
13
+ }
14
+ export declare function chart(opts: {
15
+ x: string;
16
+ y: string | string[];
17
+ kind?: "bar" | "line" | "area";
18
+ data?: Point[];
19
+ maxHeight?: number;
20
+ }): ChartWidget;
@@ -0,0 +1,24 @@
1
+ import { bound } from "../bound.js";
2
+ import { controls } from "../controls.js";
3
+ // A read-only chart rendered by Recharts. Pure output: state is `{ data }` (an array of row objects)
4
+ // and the view reads it; nothing rounds-trips back. `x`/`y` name which keys map to the axes/series.
5
+ export function chart(opts) {
6
+ return {
7
+ type: "chart",
8
+ state: { data: opts.data ?? [] },
9
+ kind: opts.kind ?? "bar",
10
+ x: opts.x,
11
+ y: opts.y,
12
+ maxHeight: opts.maxHeight ?? 300,
13
+ ...controls,
14
+ data() {
15
+ return bound(this).read(this, ["data"]);
16
+ },
17
+ setData(data) {
18
+ bound(this).edit(this, "set", ["data"], data);
19
+ },
20
+ push(point) {
21
+ bound(this).edit(this, "append", ["data"], point);
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,26 @@
1
+ import type { EventCtor, Widget } from "../types.js";
2
+ export interface Message {
3
+ role: "user" | "assistant" | "system";
4
+ content: string;
5
+ image?: string;
6
+ }
7
+ export interface ChatWidget extends Widget<{
8
+ messages: Message[];
9
+ }> {
10
+ sent: EventCtor<{
11
+ text: string;
12
+ image?: string;
13
+ }>;
14
+ recorded: EventCtor<Float32Array>;
15
+ placeholder: string;
16
+ voice: boolean;
17
+ images: boolean;
18
+ history(): Promise<Message[]>;
19
+ say(message: Message): void;
20
+ append(token: string): void;
21
+ }
22
+ export declare function chat(opts?: {
23
+ placeholder?: string;
24
+ voice?: boolean;
25
+ images?: boolean;
26
+ }): ChatWidget;
@@ -0,0 +1,24 @@
1
+ import { event } from "../event.js";
2
+ import { bound } from "../bound.js";
3
+ import { controls } from "../controls.js";
4
+ export function chat(opts = {}) {
5
+ return {
6
+ type: "chat",
7
+ state: { messages: [] },
8
+ sent: event("chat.sent"),
9
+ recorded: event("chat.recorded"),
10
+ placeholder: opts.placeholder ?? "Say something…",
11
+ voice: opts.voice ?? false,
12
+ images: opts.images ?? false,
13
+ ...controls,
14
+ history() {
15
+ return bound(this).read(this, ["messages"]);
16
+ },
17
+ say(message) {
18
+ bound(this).edit(this, "append", ["messages"], message);
19
+ },
20
+ append(token) {
21
+ bound(this).edit(this, "appendText", ["messages", -1, "content"], token);
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,4 @@
1
+ export declare function checkboxGroup(opts: {
2
+ choices: string[];
3
+ value?: string[];
4
+ }): import("./value.js").ValueWidget<string[]>;
@@ -0,0 +1,5 @@
1
+ import { value } from "./value.js";
2
+ // Multi-select from a fixed set; its `value` is the array of checked choices.
3
+ export function checkboxGroup(opts) {
4
+ return value("checkboxGroup", opts.value ?? [], { choices: opts.choices });
5
+ }
@@ -0,0 +1,4 @@
1
+ export declare function checkbox(opts?: {
2
+ label?: string;
3
+ value?: boolean;
4
+ }): import("./value.js").ValueWidget<boolean>;
@@ -0,0 +1,4 @@
1
+ import { value } from "./value.js";
2
+ export function checkbox(opts = {}) {
3
+ return value("checkbox", opts.value ?? false, { label: opts.label });
4
+ }
@@ -0,0 +1,5 @@
1
+ export declare function code(opts?: {
2
+ value?: string;
3
+ language?: string;
4
+ editable?: boolean;
5
+ }): import("./value.js").ValueWidget<string>;
@@ -0,0 +1,10 @@
1
+ import { value } from "./value.js";
2
+ // A code editor over the uniform `value` attribute: holds `{ value: string }`, plus `language` (syntax
3
+ // highlighting) and `editable` (false = a read-only, still-highlighted viewer) as static props. The
4
+ // CodeMirror instance lives in the view; this stays a plain value widget (changed/value()/set()).
5
+ export function code(opts = {}) {
6
+ return value("code", opts.value ?? "", {
7
+ language: opts.language ?? "",
8
+ editable: opts.editable ?? true,
9
+ });
10
+ }
@@ -0,0 +1,4 @@
1
+ export declare function dropdown(opts: {
2
+ choices: string[];
3
+ value?: string;
4
+ }): import("./value.js").ValueWidget<string>;
@@ -0,0 +1,4 @@
1
+ import { value } from "./value.js";
2
+ export function dropdown(opts) {
3
+ return value("dropdown", opts.value ?? opts.choices[0], { choices: opts.choices });
4
+ }
@@ -0,0 +1,5 @@
1
+ import type { Knobkit } from "../knobkit.js";
2
+ import type { Widget } from "../types.js";
3
+ export declare const SUBAPP = "__subapp";
4
+ export declare function embed(app: Knobkit): Widget;
5
+ export declare function collectSubapps(widgets: Widget | Widget[]): Knobkit[];