agentic-zi-ui 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/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ All notable changes to this package will be documented in this file.
4
+
5
+ ## [Unreleased]
6
+ - Initial renderer extraction as `agentic-zi-ui`
7
+ - Export branded component `ZijusCustomWidget`
package/RELEASE.md ADDED
@@ -0,0 +1,10 @@
1
+ # Release checklist (agentic-zi-ui)
2
+
3
+ 1) Update `CHANGELOG.md`
4
+ 2) Bump version
5
+ - `pnpm -C packages/ui-renderer release:patch`
6
+ - or `release:minor` / `release:major`
7
+ 3) Build
8
+ - `pnpm -C packages/ui-renderer build`
9
+ 4) Publish
10
+ - `pnpm -C packages/ui-renderer publish:public`
@@ -0,0 +1,16 @@
1
+ import type { UiNode, UiTemplate, UiActionType, WidgetDefinition } from "@acme/ui-schema";
2
+ export type RenderPolicy = {
3
+ allowedTags?: string[];
4
+ allowedProps?: string[];
5
+ allowedActions?: UiActionType[];
6
+ };
7
+ export type UiRendererProps = {
8
+ template: UiTemplate;
9
+ data?: Record<string, unknown>;
10
+ onFlowEvent: (name: string, payload?: Record<string, unknown>) => void;
11
+ resolveWidget?: (widgetId: string) => Promise<WidgetDefinition>;
12
+ slots?: Record<string, Array<UiNode | string>>;
13
+ policy?: RenderPolicy;
14
+ };
15
+ export declare function UiRenderer({ template, data, onFlowEvent, resolveWidget, slots, policy, }: UiRendererProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=UiRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UiRenderer.d.ts","sourceRoot":"","sources":["../src/UiRenderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EAEV,YAAY,EACZ,gBAAgB,EACjB,MAAM,iBAAiB,CAAC;AAczB,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,cAAc,CAAC,EAAE,YAAY,EAAE,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,UAAU,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACvE,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAChE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAkQF,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,IAAI,EACJ,WAAW,EACX,aAAa,EACb,KAAK,EACL,MAAM,GACP,EAAE,eAAe,2CAkPjB"}
@@ -0,0 +1,384 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import React, { useMemo, useReducer, useEffect, useState } from "react";
4
+ import { UI_ALLOWED_TAGS, UI_ALLOWED_PROPS, UiActionTypeSchema, } from "@acme/ui-schema";
5
+ import { runAction } from "./actions";
6
+ const BASE_ALLOWED_TAGS = new Set(UI_ALLOWED_TAGS);
7
+ const BASE_ALLOWED_PROPS = new Set(UI_ALLOWED_PROPS);
8
+ const BASE_ALLOWED_ACTIONS = new Set(UiActionTypeSchema.options);
9
+ function reducer(state, action) {
10
+ switch (action.type) {
11
+ case "patch":
12
+ return { ...state, [action.key]: action.value };
13
+ default:
14
+ return state;
15
+ }
16
+ }
17
+ function resolvePath(data, keyPath) {
18
+ const parts = keyPath.split(".").map((p) => p.trim()).filter(Boolean);
19
+ let current = data;
20
+ for (const part of parts) {
21
+ if (current == null)
22
+ return undefined;
23
+ current = current[part];
24
+ }
25
+ return current;
26
+ }
27
+ function interpolateValue(s, data) {
28
+ const fullMatch = s.match(/^\s*\{\{([^}]+)\}\}\s*$/);
29
+ if (fullMatch) {
30
+ const keyPath = fullMatch[1].trim();
31
+ const v = resolvePath(data, keyPath);
32
+ return v === undefined || v === null ? "" : v;
33
+ }
34
+ return s.replace(/\{\{([^}]+)\}\}/g, (_m, rawKey) => {
35
+ const keyPath = String(rawKey).trim();
36
+ const v = resolvePath(data, keyPath);
37
+ return v === undefined || v === null ? "" : String(v);
38
+ });
39
+ }
40
+ function interpolateString(s, data) {
41
+ const v = interpolateValue(s, data);
42
+ return typeof v === "string" ? v : v === undefined || v === null ? "" : String(v);
43
+ }
44
+ function deepInterpolate(value, data) {
45
+ if (typeof value === "string")
46
+ return interpolateValue(value, data);
47
+ if (Array.isArray(value))
48
+ return value.map((v) => deepInterpolate(v, data));
49
+ if (value && typeof value === "object") {
50
+ const out = {};
51
+ for (const [k, v] of Object.entries(value)) {
52
+ out[k] = deepInterpolate(v, data);
53
+ }
54
+ return out;
55
+ }
56
+ return value;
57
+ }
58
+ function isSafeHttpUrl(url) {
59
+ try {
60
+ const parsed = new URL(url);
61
+ return parsed.protocol === "https:" || parsed.protocol === "http:";
62
+ }
63
+ catch {
64
+ return false;
65
+ }
66
+ }
67
+ function isSafeImageUrl(url) {
68
+ if (url.startsWith("data:image/"))
69
+ return true;
70
+ return isSafeHttpUrl(url);
71
+ }
72
+ function pickSafeProps(raw) {
73
+ if (!raw || typeof raw !== "object")
74
+ return {};
75
+ // Only allow a small safe subset
76
+ const out = {};
77
+ for (const k of Object.keys(raw)) {
78
+ if (BASE_ALLOWED_PROPS.has(k) ||
79
+ k.startsWith("aria-") ||
80
+ k.startsWith("data-")) {
81
+ out[k] = raw[k];
82
+ }
83
+ }
84
+ for (const key of ["disabled", "checked", "aria-disabled", "aria-hidden"]) {
85
+ const value = out[key];
86
+ if (typeof value === "string") {
87
+ const normalized = value.trim().toLowerCase();
88
+ if (normalized === "true")
89
+ out[key] = true;
90
+ if (normalized === "false")
91
+ out[key] = false;
92
+ }
93
+ }
94
+ return out;
95
+ }
96
+ function intersect(left, right) {
97
+ if (!right || right.length === 0)
98
+ return new Set(left);
99
+ const rightSet = new Set(right);
100
+ const out = new Set();
101
+ for (const item of left) {
102
+ if (rightSet.has(item))
103
+ out.add(item);
104
+ }
105
+ return out;
106
+ }
107
+ function mergePolicies(base, next) {
108
+ if (!base && !next)
109
+ return undefined;
110
+ return {
111
+ allowedTags: base?.allowedTags && next?.allowedTags
112
+ ? base.allowedTags.filter((t) => next.allowedTags?.includes(t))
113
+ : base?.allowedTags ?? next?.allowedTags,
114
+ allowedProps: base?.allowedProps && next?.allowedProps
115
+ ? base.allowedProps.filter((p) => next.allowedProps?.includes(p))
116
+ : base?.allowedProps ?? next?.allowedProps,
117
+ allowedActions: base?.allowedActions && next?.allowedActions
118
+ ? base.allowedActions.filter((a) => next.allowedActions?.includes(a))
119
+ : base?.allowedActions ?? next?.allowedActions,
120
+ };
121
+ }
122
+ function normalizeWidgetProps(widget, raw) {
123
+ if (!widget.props) {
124
+ return { props: raw };
125
+ }
126
+ const props = {};
127
+ for (const [key, def] of Object.entries(widget.props)) {
128
+ if (!(key in raw)) {
129
+ if (def.default !== undefined) {
130
+ props[key] = def.default;
131
+ continue;
132
+ }
133
+ if (def.required) {
134
+ return { props: {}, error: `Missing required prop: ${key}` };
135
+ }
136
+ continue;
137
+ }
138
+ const value = raw[key];
139
+ if (def.type === "string" && typeof value !== "string") {
140
+ return { props: {}, error: `Invalid prop type for ${key}` };
141
+ }
142
+ if (def.type === "number" && typeof value !== "number") {
143
+ return { props: {}, error: `Invalid prop type for ${key}` };
144
+ }
145
+ if (def.type === "boolean" && typeof value !== "boolean") {
146
+ return { props: {}, error: `Invalid prop type for ${key}` };
147
+ }
148
+ if (def.type === "json") {
149
+ props[key] = value;
150
+ continue;
151
+ }
152
+ props[key] = value;
153
+ }
154
+ return { props };
155
+ }
156
+ function normalizeWidgetSlots(widget, slots) {
157
+ const provided = slots ?? {};
158
+ if (widget.slots) {
159
+ for (const [name, cfg] of Object.entries(widget.slots)) {
160
+ if (cfg.required && (!provided[name] || provided[name].length === 0)) {
161
+ return { slots: {}, error: `Missing required slot: ${name}` };
162
+ }
163
+ }
164
+ }
165
+ return { slots: provided };
166
+ }
167
+ function WidgetNode(props) {
168
+ const { node, resolveWidget } = props;
169
+ const [widget, setWidget] = useState(null);
170
+ const [error, setError] = useState(null);
171
+ const widgetId = typeof node.widgetId === "string" ? node.widgetId : "";
172
+ useEffect(() => {
173
+ if (!widgetId) {
174
+ // eslint-disable-next-line react-hooks/set-state-in-effect
175
+ setError("Missing widgetId.");
176
+ return;
177
+ }
178
+ if (!resolveWidget) {
179
+ setError("Widget resolver not configured.");
180
+ return;
181
+ }
182
+ let cancelled = false;
183
+ setWidget(null);
184
+ setError(null);
185
+ resolveWidget(widgetId)
186
+ .then((def) => {
187
+ if (!cancelled)
188
+ setWidget(def);
189
+ })
190
+ .catch((e) => {
191
+ if (!cancelled)
192
+ setError(e?.message ?? String(e));
193
+ });
194
+ return () => {
195
+ cancelled = true;
196
+ };
197
+ }, [widgetId, resolveWidget]);
198
+ if (error) {
199
+ return _jsxs("div", { className: "text-xs text-red-600", children: ["Widget error: ", error] });
200
+ }
201
+ if (!widget) {
202
+ return _jsx("div", { className: "text-xs text-slate-500", children: "Loading widget\u2026" });
203
+ }
204
+ const { props: widgetProps, error: propError } = normalizeWidgetProps(widget, node.widgetProps ?? {});
205
+ if (propError) {
206
+ return _jsx("div", { className: "text-xs text-red-600", children: propError });
207
+ }
208
+ const { slots, error: slotError } = normalizeWidgetSlots(widget, node.slots);
209
+ if (slotError) {
210
+ return _jsx("div", { className: "text-xs text-red-600", children: slotError });
211
+ }
212
+ const mergedData = { ...props.data, ...widgetProps };
213
+ const mergedPolicy = mergePolicies(props.policy, widget.policy);
214
+ return (_jsx(UiRenderer, { template: widget.template, data: mergedData, onFlowEvent: props.onFlowEvent, resolveWidget: props.resolveWidget, slots: slots, policy: mergedPolicy }));
215
+ }
216
+ export function UiRenderer({ template, data, onFlowEvent, resolveWidget, slots, policy, }) {
217
+ const [state, dispatch] = useReducer(reducer, {});
218
+ const mergedData = useMemo(() => ({ ...(data ?? {}), state }), [data, state]);
219
+ const allowedTags = useMemo(() => intersect(BASE_ALLOWED_TAGS, policy?.allowedTags), [policy?.allowedTags]);
220
+ const allowedProps = useMemo(() => intersect(BASE_ALLOWED_PROPS, policy?.allowedProps), [policy?.allowedProps]);
221
+ const allowedActions = useMemo(() => intersect(BASE_ALLOWED_ACTIONS, policy?.allowedActions), [policy?.allowedActions]);
222
+ const ctx = useMemo(() => ({
223
+ sendFlowEvent: (name, payload) => {
224
+ const interpolatedPayload = deepInterpolate(payload ?? {}, mergedData);
225
+ onFlowEvent(name, interpolatedPayload);
226
+ },
227
+ patchState: (key, value) => dispatch({ type: "patch", key, value }),
228
+ getState: (key) => state[key],
229
+ toast: (message) => {
230
+ // POC: swap with your notification system
231
+ alert(message);
232
+ },
233
+ }), [mergedData, onFlowEvent, state]);
234
+ function attachEvent(action, handler) {
235
+ if (!action)
236
+ return undefined;
237
+ return handler;
238
+ }
239
+ function renderNode(node, idxPath) {
240
+ const tag = node.type;
241
+ if (tag === "slot") {
242
+ const slotNodes = slots?.[node.slotName] ?? [];
243
+ if (slotNodes.length === 0)
244
+ return null;
245
+ return (_jsx(React.Fragment, { children: slotNodes.map((c, i) => {
246
+ const childPath = `${idxPath}.slot.${i}`;
247
+ if (typeof c === "string")
248
+ return interpolateString(c, mergedData);
249
+ return renderNode(c, childPath);
250
+ }) }, idxPath));
251
+ }
252
+ if (tag === "widget") {
253
+ return (_jsx(WidgetNode, { node: node, data: mergedData, onFlowEvent: (name, payload) => ctx.sendFlowEvent(name, payload), resolveWidget: resolveWidget, policy: policy }, idxPath));
254
+ }
255
+ if (!allowedTags.has(tag)) {
256
+ return (_jsxs("div", { className: "text-xs text-red-600", children: ["Blocked tag: ", _jsx("span", { className: "font-mono", children: tag })] }, idxPath));
257
+ }
258
+ const className = node.className
259
+ ? interpolateString(node.className, mergedData)
260
+ : undefined;
261
+ const rawProps = node.props
262
+ ? deepInterpolate(node.props, mergedData)
263
+ : undefined;
264
+ const safeProps = pickSafeProps(rawProps);
265
+ for (const k of Object.keys(safeProps)) {
266
+ if (!allowedProps.has(k))
267
+ delete safeProps[k];
268
+ }
269
+ // Bindings (POC)
270
+ if (tag === "input") {
271
+ if (node.bind?.valueKey) {
272
+ safeProps.value = (ctx.getState(node.bind.valueKey) ?? "");
273
+ }
274
+ if (node.bind?.checkedKey) {
275
+ safeProps.checked = !!ctx.getState(node.bind.checkedKey);
276
+ }
277
+ }
278
+ // Events
279
+ const onClick = attachEvent(node.events?.onClick, async () => {
280
+ if (node.events?.onClick)
281
+ await runAction(node.events.onClick, ctx, undefined, allowedActions);
282
+ });
283
+ const onChange = attachEvent(node.events?.onChange, async (ev) => {
284
+ if (node.events?.onChange)
285
+ await runAction(node.events.onChange, ctx, ev, allowedActions);
286
+ });
287
+ const onSubmit = attachEvent(node.events?.onSubmit, async (ev) => {
288
+ ev?.preventDefault?.();
289
+ if (node.events?.onSubmit)
290
+ await runAction(node.events.onSubmit, ctx, ev, allowedActions);
291
+ });
292
+ const onMouseEnter = attachEvent(node.events?.onMouseEnter, async (ev) => {
293
+ if (node.events?.onMouseEnter)
294
+ await runAction(node.events.onMouseEnter, ctx, ev, allowedActions);
295
+ });
296
+ const onMouseLeave = attachEvent(node.events?.onMouseLeave, async (ev) => {
297
+ if (node.events?.onMouseLeave)
298
+ await runAction(node.events.onMouseLeave, ctx, ev, allowedActions);
299
+ });
300
+ const onMouseOver = attachEvent(node.events?.onMouseOver, async (ev) => {
301
+ if (node.events?.onMouseOver)
302
+ await runAction(node.events.onMouseOver, ctx, ev, allowedActions);
303
+ });
304
+ const onMouseOut = attachEvent(node.events?.onMouseOut, async (ev) => {
305
+ if (node.events?.onMouseOut)
306
+ await runAction(node.events.onMouseOut, ctx, ev, allowedActions);
307
+ });
308
+ const onMouseDown = attachEvent(node.events?.onMouseDown, async (ev) => {
309
+ if (node.events?.onMouseDown)
310
+ await runAction(node.events.onMouseDown, ctx, ev, allowedActions);
311
+ });
312
+ const onMouseUp = attachEvent(node.events?.onMouseUp, async (ev) => {
313
+ if (node.events?.onMouseUp)
314
+ await runAction(node.events.onMouseUp, ctx, ev, allowedActions);
315
+ });
316
+ const onMouseMove = attachEvent(node.events?.onMouseMove, async (ev) => {
317
+ if (node.events?.onMouseMove)
318
+ await runAction(node.events.onMouseMove, ctx, ev, allowedActions);
319
+ });
320
+ const onFocus = attachEvent(node.events?.onFocus, async (ev) => {
321
+ if (node.events?.onFocus)
322
+ await runAction(node.events.onFocus, ctx, ev, allowedActions);
323
+ });
324
+ const onBlur = attachEvent(node.events?.onBlur, async (ev) => {
325
+ if (node.events?.onBlur)
326
+ await runAction(node.events.onBlur, ctx, ev, allowedActions);
327
+ });
328
+ // Children
329
+ const children = (node.children ?? []).map((c, i) => {
330
+ const childPath = `${idxPath}.${i}`;
331
+ if (typeof c === "string")
332
+ return interpolateString(c, mergedData);
333
+ return renderNode(c, childPath);
334
+ });
335
+ if (tag === "a") {
336
+ if (typeof safeProps.href === "string") {
337
+ if (!isSafeHttpUrl(safeProps.href)) {
338
+ delete safeProps.href;
339
+ }
340
+ }
341
+ else {
342
+ delete safeProps.href;
343
+ }
344
+ if (safeProps.target !== "_blank" && safeProps.target !== "_self") {
345
+ delete safeProps.target;
346
+ }
347
+ if (safeProps.target === "_blank") {
348
+ safeProps.rel = "noopener noreferrer";
349
+ }
350
+ }
351
+ if (tag === "img") {
352
+ if (typeof safeProps.src === "string") {
353
+ if (!isSafeImageUrl(safeProps.src)) {
354
+ delete safeProps.src;
355
+ }
356
+ }
357
+ else {
358
+ delete safeProps.src;
359
+ }
360
+ if (typeof safeProps.alt !== "string") {
361
+ safeProps.alt = "";
362
+ }
363
+ }
364
+ const props = {
365
+ ...safeProps,
366
+ className,
367
+ onClick,
368
+ onChange,
369
+ onSubmit,
370
+ onMouseEnter,
371
+ onMouseLeave,
372
+ onMouseOver,
373
+ onMouseOut,
374
+ onMouseDown,
375
+ onMouseUp,
376
+ onMouseMove,
377
+ onFocus,
378
+ onBlur,
379
+ key: idxPath,
380
+ };
381
+ return React.createElement(tag, props, ...children);
382
+ }
383
+ return _jsx(_Fragment, { children: renderNode(template.root, "0") });
384
+ }
@@ -0,0 +1,9 @@
1
+ import type { UiAction, UiActionType } from "@acme/ui-schema";
2
+ export type ActionContext = {
3
+ sendFlowEvent: (name: string, payload?: Record<string, unknown>) => void;
4
+ patchState: (key: string, value: unknown) => void;
5
+ getState: (key: string) => unknown;
6
+ toast: (message: string) => void;
7
+ };
8
+ export declare function runAction(action: UiAction, ctx: ActionContext, ev?: unknown, allowedActions?: Set<UiActionType>): Promise<void>;
9
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG;IAC1B,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACzE,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AAWF,wBAAsB,SAAS,CAC7B,MAAM,EAAE,QAAQ,EAChB,GAAG,EAAE,aAAa,EAClB,EAAE,CAAC,EAAE,OAAO,EACZ,cAAc,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CAuDf"}
@@ -0,0 +1,84 @@
1
+ function isSafeHttpUrl(url) {
2
+ try {
3
+ const u = new URL(url);
4
+ return u.protocol === "https:" || u.protocol === "http:";
5
+ }
6
+ catch {
7
+ return false;
8
+ }
9
+ }
10
+ export async function runAction(action, ctx, ev, allowedActions) {
11
+ if (allowedActions && !allowedActions.has(action.type)) {
12
+ ctx.toast("Blocked action");
13
+ return;
14
+ }
15
+ switch (action.type) {
16
+ case "FLOW_EVENT": {
17
+ const payload = substituteEventValues(action.payload ?? {}, ev);
18
+ ctx.sendFlowEvent(action.name, payload);
19
+ return;
20
+ }
21
+ case "OPEN_URL": {
22
+ if (!isSafeHttpUrl(action.url)) {
23
+ ctx.toast("Blocked unsafe URL");
24
+ return;
25
+ }
26
+ const target = action.target ?? "_blank";
27
+ window.open(action.url, target, "noopener,noreferrer");
28
+ return;
29
+ }
30
+ case "COPY": {
31
+ await navigator.clipboard.writeText(action.text);
32
+ ctx.toast("Copied");
33
+ return;
34
+ }
35
+ case "TOAST": {
36
+ ctx.toast(action.message);
37
+ return;
38
+ }
39
+ case "PATCH_STATE": {
40
+ if (action.value !== undefined) {
41
+ ctx.patchState(action.key, action.value);
42
+ return;
43
+ }
44
+ // valueFrom reads from event
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const e = ev;
47
+ if (action.valueFrom === "event.target.value") {
48
+ ctx.patchState(action.key, e?.target?.value);
49
+ }
50
+ else if (action.valueFrom === "event.target.checked") {
51
+ ctx.patchState(action.key, !!e?.target?.checked);
52
+ }
53
+ else {
54
+ ctx.patchState(action.key, null);
55
+ }
56
+ return;
57
+ }
58
+ default:
59
+ return;
60
+ }
61
+ }
62
+ function substituteEventValues(payload, ev) {
63
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
+ const e = ev;
65
+ const value = e?.target?.value;
66
+ const checked = e?.target?.checked;
67
+ function walk(input) {
68
+ if (input === "$event.target.value")
69
+ return value ?? null;
70
+ if (input === "$event.target.checked")
71
+ return !!checked;
72
+ if (Array.isArray(input))
73
+ return input.map(walk);
74
+ if (input && typeof input === "object") {
75
+ const out = {};
76
+ for (const [k, v] of Object.entries(input)) {
77
+ out[k] = walk(v);
78
+ }
79
+ return out;
80
+ }
81
+ return input;
82
+ }
83
+ return walk(payload);
84
+ }
@@ -0,0 +1,5 @@
1
+ import type { UiRendererProps } from "./UiRenderer";
2
+ export type { UiRendererProps, RenderPolicy } from "./UiRenderer";
3
+ export type { UiRendererProps as ZijusCustomWidgetProps } from "./UiRenderer";
4
+ export declare function ZijusCustomWidget(props: UiRendererProps): import("react/jsx-runtime").JSX.Element;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAElE,YAAY,EAAE,eAAe,IAAI,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE9E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,2CAEvD"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { UiRenderer } from "./UiRenderer";
3
+ export function ZijusCustomWidget(props) {
4
+ return _jsx(UiRenderer, { ...props });
5
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "agentic-zi-ui",
3
+ "version": "0.0.1",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "private": false,
7
+ "type": "module",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "dev": "tsc -w",
16
+ "build": "tsc",
17
+ "prepublishOnly": "pnpm -C . build",
18
+ "release:patch": "npm version patch -m \"chore(release): %s\"",
19
+ "release:minor": "npm version minor -m \"chore(release): %s\"",
20
+ "release:major": "npm version major -m \"chore(release): %s\"",
21
+ "publish:public": "npm publish --access public"
22
+ },
23
+ "dependencies": {
24
+ "@acme/ui-schema": "workspace:*"
25
+ },
26
+ "peerDependencies": {
27
+ "react": "^18 || ^19"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^19.2.5",
31
+ "typescript": "~5.9.3"
32
+ }
33
+ }