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.
- package/LICENSE +21 -0
- package/dist/assets/cell-renderer-CLTRlCa5-DIlwS99c.js +1 -0
- package/dist/assets/chart-D8ctp-_1.js +36 -0
- package/dist/assets/code-BMuLQBYq.js +2 -0
- package/dist/assets/column.service-C6hByxPy-XG9X0y3N.js +1 -0
- package/dist/assets/debounce-PCRWZliA-BjJpj_P7.js +32 -0
- package/dist/assets/dimension.helpers-CGKwSvw6-D_czicbS.js +1 -0
- package/dist/assets/dist-1hsZpGRf.js +23 -0
- package/dist/assets/dist-B-y4Etc5.js +1 -0
- package/dist/assets/dist-B8BXgMDk.js +10 -0
- package/dist/assets/dist-BJlXPLNt.js +1 -0
- package/dist/assets/dist-ByhR2UY_.js +1 -0
- package/dist/assets/dist-C0bxYHYH.js +2 -0
- package/dist/assets/dist-C8dagUDy.js +6 -0
- package/dist/assets/dist-CtLpohkg.js +1 -0
- package/dist/assets/dist-D00mNtIr.js +1 -0
- package/dist/assets/dist-Dh1Dvy3h.js +1 -0
- package/dist/assets/dist-DlwQ1Qqm.js +1 -0
- package/dist/assets/dist-DtZDI7jp.js +1 -0
- package/dist/assets/dist-thZFs69d.js +9 -0
- package/dist/assets/edit.utils-Dnnbd0xG-OAxDw8WC.js +1 -0
- package/dist/assets/events-BvSmBueA-4kqQ57iN.js +1 -0
- package/dist/assets/filter.button-BFwo1uvz-CyvQhOO5.js +1 -0
- package/dist/assets/header-cell-renderer-BMmXRsd_-BHbC7fao.js +1 -0
- package/dist/assets/index-Db3qZoW5-peeY7EGw.js +1 -0
- package/dist/assets/markdown-dDCgur7g.js +29 -0
- package/dist/assets/revo-grid.entry-CfI6s-uT.js +1 -0
- package/dist/assets/revogr-attribution_7.entry-6fUjzImt.js +1 -0
- package/dist/assets/revogr-clipboard_3.entry-DmI7LkER.js +2 -0
- package/dist/assets/revogr-data_4.entry-CYZIiXNw.js +1 -0
- package/dist/assets/revogr-filter-panel.entry-TmQHTQxw.js +1 -0
- package/dist/assets/table-Zn7rpfG-.js +1 -0
- package/dist/assets/text-editor-C3RUSwH5-DuDr9wKc.js +1 -0
- package/dist/assets/theme.service-BmnDvr6P-DftEgmbe.js +3 -0
- package/dist/assets/throttle-CaUDyxyU-Djj__DCp.js +1 -0
- package/dist/assets/viewport.helpers-CoCAvmZs-ByVRjjkF.js +1 -0
- package/dist/assets/viewport.store-_c579YyM-B_ZSqqka.js +1 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.js +82 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +77 -0
- package/dist/cli/mount.d.ts +2 -0
- package/dist/cli/mount.js +26 -0
- package/dist/cli/serve.d.ts +1 -0
- package/dist/cli/serve.js +21 -0
- package/dist/client/app.d.ts +8 -0
- package/dist/client/app.js +40 -0
- package/dist/client/context.d.ts +2 -0
- package/dist/client/context.js +16 -0
- package/dist/client/mount.d.ts +3 -0
- package/dist/client/mount.js +42 -0
- package/dist/client/runtime.d.ts +19 -0
- package/dist/client/runtime.js +88 -0
- package/dist/client/view.d.ts +12 -0
- package/dist/client/view.js +1 -0
- package/dist/client/widgets/accordion/index.d.ts +5 -0
- package/dist/client/widgets/accordion/index.js +8 -0
- package/dist/client/widgets/annotated-image/index.d.ts +8 -0
- package/dist/client/widgets/annotated-image/index.js +34 -0
- package/dist/client/widgets/audio/index.d.ts +5 -0
- package/dist/client/widgets/audio/index.js +5 -0
- package/dist/client/widgets/button/index.d.ts +4 -0
- package/dist/client/widgets/button/index.js +5 -0
- package/dist/client/widgets/chart/index.d.ts +5 -0
- package/dist/client/widgets/chart/index.js +23 -0
- package/dist/client/widgets/chart/lazy.d.ts +3 -0
- package/dist/client/widgets/chart/lazy.js +9 -0
- package/dist/client/widgets/chat/index.d.ts +6 -0
- package/dist/client/widgets/chat/index.js +77 -0
- package/dist/client/widgets/checkbox/index.d.ts +6 -0
- package/dist/client/widgets/checkbox/index.js +9 -0
- package/dist/client/widgets/checkbox-group/index.d.ts +6 -0
- package/dist/client/widgets/checkbox-group/index.js +12 -0
- package/dist/client/widgets/code/index.d.ts +5 -0
- package/dist/client/widgets/code/index.js +101 -0
- package/dist/client/widgets/code/lazy.d.ts +3 -0
- package/dist/client/widgets/code/lazy.js +10 -0
- package/dist/client/widgets/dropdown/index.d.ts +5 -0
- package/dist/client/widgets/dropdown/index.js +9 -0
- package/dist/client/widgets/file/index.d.ts +6 -0
- package/dist/client/widgets/file/index.js +7 -0
- package/dist/client/widgets/frame/index.d.ts +6 -0
- package/dist/client/widgets/frame/index.js +11 -0
- package/dist/client/widgets/gallery/index.d.ts +6 -0
- package/dist/client/widgets/gallery/index.js +8 -0
- package/dist/client/widgets/highlighted-text/index.d.ts +7 -0
- package/dist/client/widgets/highlighted-text/index.js +20 -0
- package/dist/client/widgets/html/index.d.ts +4 -0
- package/dist/client/widgets/html/index.js +8 -0
- package/dist/client/widgets/image/index.d.ts +4 -0
- package/dist/client/widgets/image/index.js +4 -0
- package/dist/client/widgets/json/index.d.ts +4 -0
- package/dist/client/widgets/json/index.js +4 -0
- package/dist/client/widgets/label/index.d.ts +7 -0
- package/dist/client/widgets/label/index.js +8 -0
- package/dist/client/widgets/layout/index.d.ts +4 -0
- package/dist/client/widgets/layout/index.js +7 -0
- package/dist/client/widgets/log/index.d.ts +4 -0
- package/dist/client/widgets/log/index.js +4 -0
- package/dist/client/widgets/mic/index.d.ts +6 -0
- package/dist/client/widgets/mic/index.js +70 -0
- package/dist/client/widgets/number/index.d.ts +5 -0
- package/dist/client/widgets/number/index.js +8 -0
- package/dist/client/widgets/output/index.d.ts +6 -0
- package/dist/client/widgets/output/index.js +13 -0
- package/dist/client/widgets/output/markdown.d.ts +3 -0
- package/dist/client/widgets/output/markdown.js +8 -0
- package/dist/client/widgets/progress/index.d.ts +6 -0
- package/dist/client/widgets/progress/index.js +6 -0
- package/dist/client/widgets/radio/index.d.ts +6 -0
- package/dist/client/widgets/radio/index.js +10 -0
- package/dist/client/widgets/registry.d.ts +2 -0
- package/dist/client/widgets/registry.js +69 -0
- package/dist/client/widgets/slider/index.d.ts +6 -0
- package/dist/client/widgets/slider/index.js +9 -0
- package/dist/client/widgets/table/index.d.ts +6 -0
- package/dist/client/widgets/table/index.js +72 -0
- package/dist/client/widgets/table/lazy.d.ts +3 -0
- package/dist/client/widgets/table/lazy.js +16 -0
- package/dist/client/widgets/tabs/index.d.ts +5 -0
- package/dist/client/widgets/tabs/index.js +10 -0
- package/dist/client/widgets/text/index.d.ts +6 -0
- package/dist/client/widgets/text/index.js +10 -0
- package/dist/client/widgets/upload/index.d.ts +6 -0
- package/dist/client/widgets/upload/index.js +16 -0
- package/dist/client/widgets/video/index.d.ts +5 -0
- package/dist/client/widgets/video/index.js +5 -0
- package/dist/client/widgets/webcam/index.d.ts +6 -0
- package/dist/client/widgets/webcam/index.js +62 -0
- package/dist/client.css +1 -0
- package/dist/client.js +11 -0
- package/dist/knobkit.browser.css +2 -0
- package/dist/knobkit.browser.js +151 -0
- package/dist/lib/bound.d.ts +12 -0
- package/dist/lib/bound.js +10 -0
- package/dist/lib/controls.d.ts +9 -0
- package/dist/lib/controls.js +35 -0
- package/dist/lib/ctx.d.ts +9 -0
- package/dist/lib/ctx.js +22 -0
- package/dist/lib/declare.d.ts +18 -0
- package/dist/lib/declare.js +43 -0
- package/dist/lib/event.d.ts +2 -0
- package/dist/lib/event.js +9 -0
- package/dist/lib/index.d.ts +10 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/knobkit.d.ts +19 -0
- package/dist/lib/knobkit.js +48 -0
- package/dist/lib/on.d.ts +2 -0
- package/dist/lib/on.js +1 -0
- package/dist/lib/stream.d.ts +1 -0
- package/dist/lib/stream.js +33 -0
- package/dist/lib/types.d.ts +48 -0
- package/dist/lib/types.js +1 -0
- package/dist/lib/widget.d.ts +7 -0
- package/dist/lib/widget.js +4 -0
- package/dist/lib/widgets/annotated-image.d.ts +14 -0
- package/dist/lib/widgets/annotated-image.js +16 -0
- package/dist/lib/widgets/audio.d.ts +10 -0
- package/dist/lib/widgets/audio.js +13 -0
- package/dist/lib/widgets/button.d.ts +11 -0
- package/dist/lib/widgets/button.js +17 -0
- package/dist/lib/widgets/chart.d.ts +20 -0
- package/dist/lib/widgets/chart.js +24 -0
- package/dist/lib/widgets/chat.d.ts +26 -0
- package/dist/lib/widgets/chat.js +24 -0
- package/dist/lib/widgets/checkbox-group.d.ts +4 -0
- package/dist/lib/widgets/checkbox-group.js +5 -0
- package/dist/lib/widgets/checkbox.d.ts +4 -0
- package/dist/lib/widgets/checkbox.js +4 -0
- package/dist/lib/widgets/code.d.ts +5 -0
- package/dist/lib/widgets/code.js +10 -0
- package/dist/lib/widgets/dropdown.d.ts +4 -0
- package/dist/lib/widgets/dropdown.js +4 -0
- package/dist/lib/widgets/embed.d.ts +5 -0
- package/dist/lib/widgets/embed.js +23 -0
- package/dist/lib/widgets/file.d.ts +11 -0
- package/dist/lib/widgets/file.js +15 -0
- package/dist/lib/widgets/frame.d.ts +18 -0
- package/dist/lib/widgets/frame.js +25 -0
- package/dist/lib/widgets/gallery.d.ts +12 -0
- package/dist/lib/widgets/gallery.js +17 -0
- package/dist/lib/widgets/highlighted-text.d.ts +12 -0
- package/dist/lib/widgets/highlighted-text.js +15 -0
- package/dist/lib/widgets/html.d.ts +9 -0
- package/dist/lib/widgets/html.js +12 -0
- package/dist/lib/widgets/image.d.ts +7 -0
- package/dist/lib/widgets/image.js +12 -0
- package/dist/lib/widgets/index.d.ts +31 -0
- package/dist/lib/widgets/index.js +31 -0
- package/dist/lib/widgets/json.d.ts +7 -0
- package/dist/lib/widgets/json.js +12 -0
- package/dist/lib/widgets/label.d.ts +15 -0
- package/dist/lib/widgets/label.js +18 -0
- package/dist/lib/widgets/layout.d.ts +21 -0
- package/dist/lib/widgets/layout.js +29 -0
- package/dist/lib/widgets/log.d.ts +8 -0
- package/dist/lib/widgets/log.js +15 -0
- package/dist/lib/widgets/mic.d.ts +19 -0
- package/dist/lib/widgets/mic.js +28 -0
- package/dist/lib/widgets/number.d.ts +5 -0
- package/dist/lib/widgets/number.js +4 -0
- package/dist/lib/widgets/output.d.ts +10 -0
- package/dist/lib/widgets/output.js +13 -0
- package/dist/lib/widgets/progress.d.ts +10 -0
- package/dist/lib/widgets/progress.js +15 -0
- package/dist/lib/widgets/radio.d.ts +4 -0
- package/dist/lib/widgets/radio.js +5 -0
- package/dist/lib/widgets/slider.d.ts +6 -0
- package/dist/lib/widgets/slider.js +6 -0
- package/dist/lib/widgets/table.d.ts +32 -0
- package/dist/lib/widgets/table.js +36 -0
- package/dist/lib/widgets/text.d.ts +4 -0
- package/dist/lib/widgets/text.js +4 -0
- package/dist/lib/widgets/upload.d.ts +3 -0
- package/dist/lib/widgets/upload.js +5 -0
- package/dist/lib/widgets/value.d.ts +9 -0
- package/dist/lib/widgets/value.js +20 -0
- package/dist/lib/widgets/video.d.ts +12 -0
- package/dist/lib/widgets/video.js +14 -0
- package/dist/lib/widgets/webcam.d.ts +21 -0
- package/dist/lib/widgets/webcam.js +29 -0
- package/dist/server/context.d.ts +2 -0
- package/dist/server/context.js +10 -0
- package/dist/server/serve.d.ts +5 -0
- package/dist/server/serve.js +131 -0
- package/package.json +71 -0
- package/src/cli/config.ts +83 -0
- package/src/cli/index.ts +82 -0
- package/src/cli/mount.ts +25 -0
- package/src/cli/serve.ts +22 -0
- package/src/client/app.test.tsx +70 -0
- package/src/client/app.tsx +62 -0
- package/src/client/browser-runtime.test.ts +22 -0
- package/src/client/browser.ts +3 -0
- package/src/client/context.ts +17 -0
- package/src/client/embed.test.tsx +58 -0
- package/src/client/entry.tsx +25 -0
- package/src/client/mount.test.tsx +36 -0
- package/src/client/mount.tsx +48 -0
- package/src/client/runtime.test.ts +64 -0
- package/src/client/runtime.ts +112 -0
- package/src/client/serve-stub.ts +3 -0
- package/src/client/styles.css +131 -0
- package/src/client/view.ts +16 -0
- package/src/client/widgets/accordion/accordion.css +35 -0
- package/src/client/widgets/accordion/index.tsx +17 -0
- package/src/client/widgets/annotated-image/annotated-image.css +62 -0
- package/src/client/widgets/annotated-image/index.tsx +73 -0
- package/src/client/widgets/audio/audio.css +6 -0
- package/src/client/widgets/audio/index.tsx +6 -0
- package/src/client/widgets/button/button.css +25 -0
- package/src/client/widgets/button/index.tsx +11 -0
- package/src/client/widgets/chart/chart.css +12 -0
- package/src/client/widgets/chart/index.tsx +63 -0
- package/src/client/widgets/chart/lazy.tsx +15 -0
- package/src/client/widgets/chat/chat.css +97 -0
- package/src/client/widgets/chat/index.tsx +121 -0
- package/src/client/widgets/checkbox/checkbox.css +15 -0
- package/src/client/widgets/checkbox/index.tsx +15 -0
- package/src/client/widgets/checkbox-group/checkbox-group.css +20 -0
- package/src/client/widgets/checkbox-group/index.tsx +22 -0
- package/src/client/widgets/code/code.css +31 -0
- package/src/client/widgets/code/index.tsx +108 -0
- package/src/client/widgets/code/lazy.tsx +16 -0
- package/src/client/widgets/dropdown/dropdown.css +0 -0
- package/src/client/widgets/dropdown/index.tsx +19 -0
- package/src/client/widgets/file/file.css +26 -0
- package/src/client/widgets/file/index.tsx +12 -0
- package/src/client/widgets/frame/frame.css +17 -0
- package/src/client/widgets/frame/index.tsx +15 -0
- package/src/client/widgets/gallery/gallery.css +26 -0
- package/src/client/widgets/gallery/index.tsx +18 -0
- package/src/client/widgets/highlighted-text/highlighted-text.css +21 -0
- package/src/client/widgets/highlighted-text/index.tsx +42 -0
- package/src/client/widgets/html/index.tsx +8 -0
- package/src/client/widgets/image/index.tsx +5 -0
- package/src/client/widgets/json/index.tsx +5 -0
- package/src/client/widgets/json/json.css +0 -0
- package/src/client/widgets/label/index.tsx +20 -0
- package/src/client/widgets/label/label.css +39 -0
- package/src/client/widgets/layout/index.tsx +14 -0
- package/src/client/widgets/log/index.tsx +5 -0
- package/src/client/widgets/log/log.css +0 -0
- package/src/client/widgets/mic/index.tsx +85 -0
- package/src/client/widgets/mic/mic.css +8 -0
- package/src/client/widgets/number/index.tsx +10 -0
- package/src/client/widgets/number/number.css +0 -0
- package/src/client/widgets/output/index.tsx +19 -0
- package/src/client/widgets/output/markdown.tsx +12 -0
- package/src/client/widgets/output/output.css +75 -0
- package/src/client/widgets/progress/index.tsx +14 -0
- package/src/client/widgets/progress/progress.css +26 -0
- package/src/client/widgets/radio/index.tsx +20 -0
- package/src/client/widgets/radio/radio.css +20 -0
- package/src/client/widgets/registry.tsx +71 -0
- package/src/client/widgets/slider/index.tsx +23 -0
- package/src/client/widgets/slider/slider.css +18 -0
- package/src/client/widgets/table/index.tsx +95 -0
- package/src/client/widgets/table/lazy.tsx +23 -0
- package/src/client/widgets/table/table.css +15 -0
- package/src/client/widgets/tabs/index.tsx +28 -0
- package/src/client/widgets/tabs/tabs.css +30 -0
- package/src/client/widgets/text/index.tsx +16 -0
- package/src/client/widgets/text/text.css +21 -0
- package/src/client/widgets/upload/index.tsx +30 -0
- package/src/client/widgets/upload/upload.css +30 -0
- package/src/client/widgets/video/index.tsx +10 -0
- package/src/client/widgets/video/video.css +8 -0
- package/src/client/widgets/webcam/index.tsx +81 -0
- package/src/client/widgets/webcam/webcam.css +46 -0
- package/src/css.d.ts +1 -0
- package/src/env.d.ts +1 -0
- package/src/lib/bound.ts +30 -0
- package/src/lib/controls.ts +36 -0
- package/src/lib/ctx.ts +31 -0
- package/src/lib/declare.test.ts +46 -0
- package/src/lib/declare.ts +74 -0
- package/src/lib/event.ts +12 -0
- package/src/lib/index.ts +21 -0
- package/src/lib/knobkit.ts +57 -0
- package/src/lib/on.ts +3 -0
- package/src/lib/stream.ts +38 -0
- package/src/lib/types.ts +63 -0
- package/src/lib/widget.ts +11 -0
- package/src/lib/widgets/annotated-image.ts +34 -0
- package/src/lib/widgets/audio.ts +20 -0
- package/src/lib/widgets/button.ts +27 -0
- package/src/lib/widgets/chart.ts +44 -0
- package/src/lib/widgets/chat.ts +43 -0
- package/src/lib/widgets/checkbox-group.ts +6 -0
- package/src/lib/widgets/checkbox.ts +5 -0
- package/src/lib/widgets/code.ts +11 -0
- package/src/lib/widgets/dropdown.ts +5 -0
- package/src/lib/widgets/embed.ts +26 -0
- package/src/lib/widgets/file.ts +23 -0
- package/src/lib/widgets/frame.ts +36 -0
- package/src/lib/widgets/gallery.ts +29 -0
- package/src/lib/widgets/highlighted-text.ts +29 -0
- package/src/lib/widgets/html.ts +18 -0
- package/src/lib/widgets/image.ts +18 -0
- package/src/lib/widgets/index.ts +31 -0
- package/src/lib/widgets/json.ts +18 -0
- package/src/lib/widgets/label.ts +29 -0
- package/src/lib/widgets/layout.ts +47 -0
- package/src/lib/widgets/log.ts +22 -0
- package/src/lib/widgets/mic.ts +42 -0
- package/src/lib/widgets/number.ts +5 -0
- package/src/lib/widgets/output.ts +20 -0
- package/src/lib/widgets/progress.ts +21 -0
- package/src/lib/widgets/radio.ts +6 -0
- package/src/lib/widgets/slider.ts +7 -0
- package/src/lib/widgets/table.ts +58 -0
- package/src/lib/widgets/text.ts +5 -0
- package/src/lib/widgets/upload.ts +6 -0
- package/src/lib/widgets/value.ts +28 -0
- package/src/lib/widgets/video.ts +22 -0
- package/src/lib/widgets/webcam.ts +46 -0
- package/src/server/context.ts +12 -0
- package/src/server/serve.test.ts +121 -0
- package/src/server/serve.ts +130 -0
- 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,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;
|
package/dist/lib/ctx.js
ADDED
|
@@ -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,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,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
|
+
}
|
package/dist/lib/on.d.ts
ADDED
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,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,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,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
|
+
}
|