@druid-ui/component 1.0.0-next.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/dist/index.js ADDED
@@ -0,0 +1,108 @@
1
+ // src/index.ts
2
+ import { d as dfunc } from "druid:ui/ui";
3
+
4
+ // src/utils.ts
5
+ import { log, rerender, setHook } from "druid:ui/ui";
6
+ var callbackMap = {};
7
+ function emit(nodeid, event, e) {
8
+ log(`Emit called for nodeid: ${nodeid}, event: ${event}`);
9
+ const callbacks = callbackMap[nodeid];
10
+ callbacks?.[event]?.(e);
11
+ }
12
+ var registerHooks = (id, fnresult) => {
13
+ switch (true) {
14
+ case !!fnresult.init:
15
+ setHook(id, "init");
16
+ callbackMap[id] = {
17
+ ...callbackMap[id],
18
+ init: fnresult.init
19
+ };
20
+ break;
21
+ }
22
+ };
23
+ var createDFunc = (dfunc2) => {
24
+ return (tag, props, ...children) => {
25
+ children = children.flat();
26
+ if (typeof tag !== "string") {
27
+ if (typeof tag === "function") {
28
+ const fnresult = tag(props);
29
+ if (fnresult?.view) {
30
+ const id3 = fnresult.view(props);
31
+ registerHooks(id3, fnresult);
32
+ return id3;
33
+ } else {
34
+ return tag(props);
35
+ }
36
+ }
37
+ const id2 = tag.view(props);
38
+ registerHooks(id2, tag);
39
+ return id2;
40
+ }
41
+ const ps = { prop: [], on: [] };
42
+ const cbObj = {};
43
+ if (props) {
44
+ for (const [key, value] of Object.entries(props)) {
45
+ if (value instanceof Function) {
46
+ const eventKey = key.startsWith("on") ? key.slice(2).toLowerCase() : key;
47
+ cbObj[eventKey] = value;
48
+ ps.on.push(eventKey);
49
+ } else {
50
+ if (typeof value === "boolean") {
51
+ if (value) {
52
+ ps.prop.push({ key, value: "true" });
53
+ }
54
+ continue;
55
+ }
56
+ ps.prop.push({ key, value });
57
+ }
58
+ }
59
+ }
60
+ const id = dfunc2(
61
+ tag,
62
+ ps,
63
+ children.filter((c) => typeof c !== "boolean").map((c) => c?.toString())
64
+ );
65
+ callbackMap[id] = {
66
+ ...callbackMap[id],
67
+ ...cbObj
68
+ };
69
+ return id;
70
+ };
71
+ };
72
+ var pendingOperations = /* @__PURE__ */ new Map();
73
+ var asyncCallback = (id, result) => {
74
+ log(`Async callback received for id: ${id} with result: ${result.tag}`);
75
+ const pending = pendingOperations.get(id);
76
+ if (pending) {
77
+ if (result.tag === "ok") {
78
+ pending.resolve(result.val);
79
+ } else {
80
+ pending.reject(new Error(result.val));
81
+ }
82
+ pendingOperations.delete(id);
83
+ rerender();
84
+ }
85
+ };
86
+ var rawAsyncToPromise = (fn) => (...args) => {
87
+ return new Promise((resolve, reject) => {
88
+ const asyncId = fn(...args);
89
+ pendingOperations.set(asyncId, { resolve, reject });
90
+ });
91
+ };
92
+ var createComponent = (j) => ({
93
+ init: (ctx) => j(ctx),
94
+ emit,
95
+ asyncComplete: asyncCallback
96
+ });
97
+
98
+ // src/index.ts
99
+ import { Event } from "druid:ui/utils";
100
+ import { log as log2 } from "druid:ui/ui";
101
+ var d2 = createDFunc(dfunc);
102
+ export {
103
+ Event,
104
+ createComponent,
105
+ d2 as d,
106
+ log2 as log,
107
+ rawAsyncToPromise
108
+ };
package/dist/raw.js ADDED
@@ -0,0 +1,106 @@
1
+ // src/utils.ts
2
+ import { log, rerender, setHook } from "druid:ui/ui";
3
+ var callbackMap = {};
4
+ function emit(nodeid, event, e) {
5
+ log(`Emit called for nodeid: ${nodeid}, event: ${event}`);
6
+ const callbacks = callbackMap[nodeid];
7
+ callbacks?.[event]?.(e);
8
+ }
9
+ var registerHooks = (id, fnresult) => {
10
+ switch (true) {
11
+ case !!fnresult.init:
12
+ setHook(id, "init");
13
+ callbackMap[id] = {
14
+ ...callbackMap[id],
15
+ init: fnresult.init
16
+ };
17
+ break;
18
+ }
19
+ };
20
+ var createDFunc = (dfunc2) => {
21
+ return (tag, props, ...children) => {
22
+ children = children.flat();
23
+ if (typeof tag !== "string") {
24
+ if (typeof tag === "function") {
25
+ const fnresult = tag(props);
26
+ if (fnresult?.view) {
27
+ const id3 = fnresult.view(props);
28
+ registerHooks(id3, fnresult);
29
+ return id3;
30
+ } else {
31
+ return tag(props);
32
+ }
33
+ }
34
+ const id2 = tag.view(props);
35
+ registerHooks(id2, tag);
36
+ return id2;
37
+ }
38
+ const ps = { prop: [], on: [] };
39
+ const cbObj = {};
40
+ if (props) {
41
+ for (const [key, value] of Object.entries(props)) {
42
+ if (value instanceof Function) {
43
+ const eventKey = key.startsWith("on") ? key.slice(2).toLowerCase() : key;
44
+ cbObj[eventKey] = value;
45
+ ps.on.push(eventKey);
46
+ } else {
47
+ if (typeof value === "boolean") {
48
+ if (value) {
49
+ ps.prop.push({ key, value: "true" });
50
+ }
51
+ continue;
52
+ }
53
+ ps.prop.push({ key, value });
54
+ }
55
+ }
56
+ }
57
+ const id = dfunc2(
58
+ tag,
59
+ ps,
60
+ children.filter((c) => typeof c !== "boolean").map((c) => c?.toString())
61
+ );
62
+ callbackMap[id] = {
63
+ ...callbackMap[id],
64
+ ...cbObj
65
+ };
66
+ return id;
67
+ };
68
+ };
69
+ var pendingOperations = /* @__PURE__ */ new Map();
70
+ var asyncCallback = (id, result) => {
71
+ log(`Async callback received for id: ${id} with result: ${result.tag}`);
72
+ const pending = pendingOperations.get(id);
73
+ if (pending) {
74
+ if (result.tag === "ok") {
75
+ pending.resolve(result.val);
76
+ } else {
77
+ pending.reject(new Error(result.val));
78
+ }
79
+ pendingOperations.delete(id);
80
+ rerender();
81
+ }
82
+ };
83
+ var rawAsyncToPromise = (fn) => (...args) => {
84
+ return new Promise((resolve, reject) => {
85
+ const asyncId = fn(...args);
86
+ pendingOperations.set(asyncId, { resolve, reject });
87
+ });
88
+ };
89
+ var createComponent = (j) => ({
90
+ init: (ctx) => j(ctx),
91
+ emit,
92
+ asyncComplete: asyncCallback
93
+ });
94
+
95
+ // src/raw.ts
96
+ var dfunc = window["druid-ui"]?.d || (() => {
97
+ throw new Error("druid.d function not defined");
98
+ });
99
+ var d2 = createDFunc(dfunc);
100
+ var log2 = (msg) => console.log("UI LOG:", msg);
101
+ export {
102
+ createComponent,
103
+ d2 as d,
104
+ log2 as log,
105
+ rawAsyncToPromise
106
+ };
@@ -0,0 +1,47 @@
1
+ /// <reference path="./interfaces/druid-ui-component.d.ts" />
2
+ /// <reference path="./interfaces/druid-ui-ui.d.ts" />
3
+ /// <reference path="./interfaces/druid-ui-utils.d.ts" />
4
+ declare module 'druid:ui/druid-ui' {
5
+ import type * as DruidUiUi from 'druid:ui/ui'; // druid:ui/ui
6
+ import type * as DruidUiUtils from 'druid:ui/utils'; // druid:ui/utils
7
+ import type * as DruidUiComponent from 'druid:ui/component'; // druid:ui/component
8
+ export interface ImportObject {
9
+ 'druid:ui/ui': typeof DruidUiUi,
10
+ 'druid:ui/utils': typeof DruidUiUtils,
11
+ }
12
+ export interface DruidUi {
13
+ 'druid:ui/component': typeof DruidUiComponent,
14
+ component: typeof DruidUiComponent,
15
+ }
16
+
17
+ /**
18
+ * Instantiates this component with the provided imports and
19
+ * returns a map of all the exports of the component.
20
+ *
21
+ * This function is intended to be similar to the
22
+ * `WebAssembly.instantiate` function. The second `imports`
23
+ * argument is the "import object" for wasm, except here it
24
+ * uses component-model-layer types instead of core wasm
25
+ * integers/numbers/etc.
26
+ *
27
+ * The first argument to this function, `getCoreModule`, is
28
+ * used to compile core wasm modules within the component.
29
+ * Components are composed of core wasm modules and this callback
30
+ * will be invoked per core wasm module. The caller of this
31
+ * function is responsible for reading the core wasm module
32
+ * identified by `path` and returning its compiled
33
+ * `WebAssembly.Module` object. This would use `compileStreaming`
34
+ * on the web, for example.
35
+ */
36
+ export function instantiate(
37
+ getCoreModule: (path: string) => WebAssembly.Module,
38
+ imports: ImportObject,
39
+ instantiateCore?: (module: WebAssembly.Module, imports: Record<string, any>) => WebAssembly.Instance
40
+ ): DruidUi;
41
+ export function instantiate(
42
+ getCoreModule: (path: string) => WebAssembly.Module | Promise<WebAssembly.Module>,
43
+ imports: ImportObject,
44
+ instantiateCore?: (module: WebAssembly.Module, imports: Record<string, any>) => WebAssembly.Instance | Promise<WebAssembly.Instance>
45
+ ): DruidUi | Promise<DruidUi>;
46
+
47
+ }
@@ -0,0 +1,14 @@
1
+ export { Event, type Context } from "druid:ui/utils";
2
+ export { log } from "druid:ui/ui";
3
+ export declare const d: (tag: string | {
4
+ view: (props?: any) => string;
5
+ init?: () => void;
6
+ } | ((props?: any) => void) | ((props?: any) => {
7
+ view: (props?: any) => string;
8
+ init?: () => void;
9
+ }), props?: Record<string, any>, ...children: string[] | Array<string[]>) => string | void | {
10
+ view: (props?: any) => string;
11
+ init?: () => void;
12
+ };
13
+ export { createComponent, rawAsyncToPromise } from "./utils";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC,eAAO,MAAM,CAAC;gBAEy3B,CAAC;QAAsB,CAAC;WAA8B,CAAC,yBAA+B,CAAC;gBAAwB,CAAC;QAAsB,CAAC;;gBAAxB,CAAC;;CAFp9B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,9 @@
1
+ /// <reference path="./druid-ui-utils.d.ts" />
2
+ declare module 'druid:ui/component' {
3
+ export function init(ctx: Context): string;
4
+ export function emit(nodeid: string, event: string, e: Event): void;
5
+ export function asyncComplete(id: string, value: Result<string, void>): void;
6
+ export type Event = import('druid:ui/utils').Event;
7
+ export type Context = import('druid:ui/utils').Context;
8
+ export type Result<T, E> = { tag: 'ok', val: T } | { tag: 'err', val: E };
9
+ }
@@ -0,0 +1,16 @@
1
+ declare module 'druid:ui/ui' {
2
+ export function d(element: string, props: Props, children: Children): string;
3
+ export function log(msg: string): void;
4
+ export function setHook(id: AsyncId, hook: string): void;
5
+ export function rerender(): void;
6
+ export interface Prop {
7
+ key: string,
8
+ value: string,
9
+ }
10
+ export interface Props {
11
+ prop: Array<Prop>,
12
+ on: Array<string>,
13
+ }
14
+ export type AsyncId = string;
15
+ export type Children = Array<string> | undefined;
16
+ }
@@ -0,0 +1,14 @@
1
+ declare module 'druid:ui/utils' {
2
+ export interface Context {
3
+ path: string,
4
+ }
5
+
6
+ export class Event implements Disposable {
7
+ constructor(value: string, checked: boolean)
8
+ preventDefault(): void;
9
+ stopPropagation(): void;
10
+ value(): string;
11
+ checked(): boolean;
12
+ [Symbol.dispose](): void;
13
+ }
14
+ }
@@ -0,0 +1,13 @@
1
+ export declare const d: (tag: string | {
2
+ view: (props?: any) => string;
3
+ init?: () => void;
4
+ } | ((props?: any) => void) | ((props?: any) => {
5
+ view: (props?: any) => string;
6
+ init?: () => void;
7
+ }), props?: Record<string, any>, ...children: string[] | Array<string[]>) => string | void | {
8
+ view: (props?: any) => string;
9
+ init?: () => void;
10
+ };
11
+ export declare const log: (msg: string) => void;
12
+ export { createComponent, rawAsyncToPromise } from "./utils";
13
+ //# sourceMappingURL=raw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/raw.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,CAAC;gBAKouB,CAAC;QAAsB,CAAC;WAA8B,CAAC,yBAA+B,CAAC;gBAAwB,CAAC;QAAsB,CAAC;;gBAAxB,CAAC;;CAL/zB,CAAC;AAEpC,eAAO,MAAM,GAAG,GAAI,KAAK,MAAM,SAAgC,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { d } from "druid:ui/ui";
2
+ import type { Event } from "@druid-ui/host";
3
+ import type { Context } from "druid:ui/component";
4
+ export declare function fnv1aHash(str: string): string;
5
+ export declare const callbackMap: Record<string, Record<string, Function>>;
6
+ export declare function emit(nodeid: string, event: string, e: Event): void;
7
+ export declare const createDFunc: (dfunc: typeof d) => (tag: string | {
8
+ view: (props?: any) => string;
9
+ init?: () => void;
10
+ } | ((props?: any) => void) | ((props?: any) => {
11
+ view: (props?: any) => string;
12
+ init?: () => void;
13
+ }), props?: Record<string, any>, ...children: string[] | Array<string[]>) => string | void | {
14
+ view: (props?: any) => string;
15
+ init?: () => void;
16
+ };
17
+ export declare const asyncCallback: (id: string, result: {
18
+ tag: "ok" | "err";
19
+ val: any;
20
+ }) => void;
21
+ export declare const rawAsyncToPromise: <T>(fn: (...args: any[]) => any) => (...args: any[]) => Promise<T>;
22
+ export declare const createComponent: (j: (ctx: Context) => string | JSX.Element) => {
23
+ init: (ctx: Context) => string | JSX.Element;
24
+ emit: typeof emit;
25
+ asyncComplete: (id: string, result: {
26
+ tag: "ok" | "err";
27
+ val: any;
28
+ }) => void;
29
+ };
30
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,CAAC,EAAW,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,UAQpC;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAM,CAAC;AAExE,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,QAI3D;AAoBD,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,CAAC,MAEvC,KACI,MAAM,GACN;IAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,GACpD,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GACvB,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK;IAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC,EAC3E,QAAQ,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,GAAG,UAAU,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;UAFT,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,MAAM;WAAS,MAAM,IAAI;CAyD3E,CAAC;AAQF,eAAO,MAAM,aAAa,GACxB,IAAI,MAAM,EACV,QAAQ;IAAE,GAAG,EAAE,IAAI,GAAG,KAAK,CAAC;IAAC,GAAG,EAAE,GAAG,CAAA;CAAE,SAaxC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC3B,CAAC,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,MAC9B,GAAG,MAAM,GAAG,EAAE,eAKd,CAAC;AAEJ,eAAO,MAAM,eAAe,GAAI,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,GAAG,GAAG,CAAC,OAAO;gBAC3D,OAAO;;wBA1Bf,MAAM,UACF;QAAE,GAAG,EAAE,IAAI,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE;CA4BvC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@druid-ui/component",
3
+ "version": "1.0.0-next.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/types/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/types/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./raw": {
14
+ "types": "./dist/types/raw.d.ts",
15
+ "import": "./dist/raw.js",
16
+ "default": "./dist/raw.js"
17
+ },
18
+ "./jsx": {
19
+ "types": "./src/jsx.d.ts"
20
+ },
21
+ "./types": {
22
+ "types": "./dist/types/druid-ui.d.ts"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "src"
28
+ ],
29
+ "scripts": {
30
+ "build": "npm run build:types-ui && npm run build:lib && npm run build:raw && npm run build:types",
31
+ "build:lib": "esbuild src/index.ts --bundle --outfile=dist/index.js --format=esm --external:druid:ui/ui --external:druid:ui/utils --external:druid:ui/component --external:@druid-ui/host",
32
+ "build:raw": "esbuild src/raw.ts --bundle --outfile=dist/raw.js --format=esm --external:@druid-ui/host --external:druid:ui/ui --external:druid:ui/utils --external:druid:ui/component",
33
+ "build:types": "tsc --emitDeclarationOnly --outDir dist/types",
34
+ "build:types-ui": "druid-ui-gen-types druid-ui --out-dir=dist/types"
35
+ },
36
+ "dependencies": {
37
+ "@druid-ui/build": "1.0.0-next.1",
38
+ "@druid-ui/host": "1.0.0-next.1"
39
+ },
40
+ "devDependencies": {
41
+ "esbuild": "^0.25.11",
42
+ "typescript": "~5.8.3"
43
+ }
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { d as dfunc } from "druid:ui/ui";
2
+ import { createDFunc } from "./utils";
3
+
4
+ export { Event, type Context } from "druid:ui/utils";
5
+ export { log } from "druid:ui/ui";
6
+
7
+ export const d = createDFunc(dfunc);
8
+ export { createComponent, rawAsyncToPromise } from "./utils";
package/src/jsx.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ type DruidComponent<T = any> = () => {
2
+ init?: () => void;
3
+ view: (props: T) => JSX.Element;
4
+ };
5
+ type DruidFC<T = any> = (props: T) => JSX.Element;
6
+
7
+ declare namespace JSX {
8
+ interface Element {}
9
+
10
+ interface ElementAttributesProperty {
11
+ view: any; // TS will infer props from `view`
12
+ }
13
+
14
+ interface IntrinsicElements {
15
+ [key: string]: any;
16
+ }
17
+
18
+ interface ElementChildrenAttribute {
19
+ children: {};
20
+ }
21
+
22
+ type ElementType = string | DruidFC | DruidComponent;
23
+ }
package/src/raw.ts ADDED
@@ -0,0 +1,14 @@
1
+ //this file fully works in the browser, this hopefully can be remvoved in the future and unified with
2
+ import { createDFunc } from "./utils";
3
+
4
+ const dfunc =
5
+ window["druid-ui"]?.d ||
6
+ (() => {
7
+ throw new Error("druid.d function not defined");
8
+ });
9
+
10
+ export const d = createDFunc(dfunc);
11
+
12
+ export const log = (msg: string) => console.log("UI LOG:", msg);
13
+
14
+ export { createComponent, rawAsyncToPromise } from "./utils";
package/src/utils.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import type { Props } from "druid:ui/ui";
2
+ import type { Event } from "../types";
3
+ import type { Context } from "druid:ui/component";
4
+ export declare function fnv1aHash(str: string): string;
5
+ export declare const eventMap: Record<string, Record<string, Function>>;
6
+ export declare function emit(nodeid: string, event: string, e: Event): void;
7
+ export declare const createDFunc: (dfunc: (element: string, props: Props, children: string[]) => string) => (tag: string | {
8
+ view: (props?: any) => void;
9
+ } | ((props?: any) => void), props?: Record<string, any>, ...children: string[]) => string | void;
10
+ export declare const asyncCallback: (id: string, result: {
11
+ tag: "ok" | "err";
12
+ val: any;
13
+ }) => void;
14
+ export declare const rawAsyncToPromise: <T>(fn: (...args: any[]) => any) => (...args: any[]) => Promise<T>;
15
+ export declare const createComponent: (j: (ctx: Context) => string | JSX.Element) => {
16
+ init: (ctx: Context) => string | JSX.Element;
17
+ emit: typeof emit;
18
+ asyncComplete: (id: string, result: {
19
+ tag: "ok" | "err";
20
+ val: any;
21
+ }) => void;
22
+ };
package/src/utils.ts ADDED
@@ -0,0 +1,143 @@
1
+ import type { Prop, Props } from "druid:ui/ui";
2
+ import { log, rerender, d, setHook } from "druid:ui/ui";
3
+ import type { Event } from "@druid-ui/host";
4
+ import type { Context } from "druid:ui/component";
5
+
6
+ export function fnv1aHash(str: string) {
7
+ let hash = 0x811c9dc5; // FNV offset basis
8
+ for (let i = 0; i < str.length; i++) {
9
+ hash ^= str.charCodeAt(i);
10
+ hash +=
11
+ (hash << 1) + (hash << 4) + (hash << 7) + (hash << 8) + (hash << 24);
12
+ }
13
+ return (hash >>> 0).toString(36);
14
+ }
15
+
16
+ export const callbackMap: Record<string, Record<string, Function>> = {};
17
+
18
+ export function emit(nodeid: string, event: string, e: Event) {
19
+ log(`Emit called for nodeid: ${nodeid}, event: ${event}`);
20
+ const callbacks = callbackMap[nodeid];
21
+ callbacks?.[event]?.(e);
22
+ }
23
+
24
+ const registerHooks = (
25
+ id: string,
26
+ fnresult: {
27
+ view: (props?: any) => string;
28
+ init?: () => void;
29
+ },
30
+ ) => {
31
+ switch (true) {
32
+ case !!fnresult.init:
33
+ setHook(id, "init");
34
+ callbackMap[id] = {
35
+ ...callbackMap[id],
36
+ init: fnresult.init,
37
+ };
38
+ break;
39
+ }
40
+ };
41
+
42
+ export const createDFunc = (dfunc: typeof d) => {
43
+ return (
44
+ tag:
45
+ | string
46
+ | { view: (props?: any) => string; init?: () => void }
47
+ | ((props?: any) => void)
48
+ | ((props?: any) => { view: (props?: any) => string; init?: () => void }),
49
+ props?: Record<string, any>,
50
+ ...children: string[] | Array<string[]>
51
+ ) => {
52
+ //flatten children, e.g. .map(...) returns array of arrays
53
+ children = children.flat();
54
+ if (typeof tag !== "string") {
55
+ if (typeof tag === "function") {
56
+ const fnresult = tag(props);
57
+ if (fnresult?.view) {
58
+ const id = fnresult.view(props);
59
+ registerHooks(id, fnresult);
60
+ return id;
61
+ } else {
62
+ return tag(props);
63
+ }
64
+ }
65
+ const id = tag.view(props);
66
+ registerHooks(id, tag);
67
+ return id;
68
+ }
69
+
70
+ const ps: Props = { prop: [] as Prop[], on: [] };
71
+ const cbObj: Record<string, Function> = {};
72
+ if (props) {
73
+ for (const [key, value] of Object.entries(props)) {
74
+ if (value instanceof Function) {
75
+ const eventKey = key.startsWith("on")
76
+ ? key.slice(2).toLowerCase()
77
+ : key;
78
+
79
+ cbObj[eventKey] = value;
80
+
81
+ ps.on.push(eventKey);
82
+ } else {
83
+ if (typeof value === "boolean") {
84
+ //e.g. disabled, checked does not have a "false"
85
+ if (value) {
86
+ ps.prop.push({ key, value: "true" });
87
+ }
88
+ continue;
89
+ }
90
+ ps.prop.push({ key, value });
91
+ }
92
+ }
93
+ }
94
+ const id = dfunc(
95
+ tag,
96
+ ps,
97
+ children.filter((c) => typeof c !== "boolean").map((c) => c?.toString()),
98
+ );
99
+ callbackMap[id] = {
100
+ ...callbackMap[id],
101
+ ...cbObj,
102
+ };
103
+ return id;
104
+ };
105
+ };
106
+
107
+ // Module-level map that tracks pending async operations initiated through wrappers
108
+ const pendingOperations = new Map<
109
+ string,
110
+ { resolve: (value: any) => void; reject: (error: any) => void }
111
+ >();
112
+
113
+ export const asyncCallback = (
114
+ id: string,
115
+ result: { tag: "ok" | "err"; val: any },
116
+ ) => {
117
+ log(`Async callback received for id: ${id} with result: ${result.tag}`);
118
+ const pending = pendingOperations.get(id);
119
+ if (pending) {
120
+ if (result.tag === "ok") {
121
+ pending.resolve(result.val);
122
+ } else {
123
+ pending.reject(new Error(result.val));
124
+ }
125
+ pendingOperations.delete(id);
126
+ rerender();
127
+ }
128
+ };
129
+
130
+ export const rawAsyncToPromise =
131
+ <T>(fn: (...args: any[]) => any) =>
132
+ (...args: any[]) => {
133
+ return new Promise<T>((resolve, reject) => {
134
+ const asyncId = fn(...args);
135
+ pendingOperations.set(asyncId, { resolve, reject });
136
+ });
137
+ };
138
+
139
+ export const createComponent = (j: (ctx: Context) => string | JSX.Element) => ({
140
+ init: (ctx: Context) => j(ctx),
141
+ emit: emit,
142
+ asyncComplete: asyncCallback,
143
+ });