@xmachines/play-solid 1.0.0-beta.31 → 1.0.0-beta.33

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.
@@ -10,11 +10,9 @@ var p = (n) => {
10
10
  let a = i(), o = (e) => {
11
11
  let t = a.getSnapshot();
12
12
  a.update(e(t));
13
- }, s = () => n.registryResult.handlers(() => o, () => a.getSnapshot());
13
+ };
14
14
  return c(e, {
15
- get handlers() {
16
- return s();
17
- },
15
+ handlers: n.registryResult.handlers(() => o, () => a.getSnapshot()),
18
16
  get children() {
19
17
  return c(r, { get children() {
20
18
  return c(t, {
@@ -29,11 +27,22 @@ var p = (n) => {
29
27
  }
30
28
  });
31
29
  }, m = (e) => {
32
- let [t, r] = u(e.actor.currentView.get()), i = null, m = null, h = f(e.actor.currentView, (e) => {
30
+ let [t, r] = u(e.actor.currentView.get()), i = () => {
31
+ if (!e.onRenderError) return e.registryResult;
32
+ let t = { ...e.registryResult.registry };
33
+ return Object.defineProperty(t, "onRenderError", {
34
+ value: e.onRenderError,
35
+ enumerable: !1,
36
+ configurable: !0
37
+ }), {
38
+ ...e.registryResult,
39
+ registry: t
40
+ };
41
+ }, m = null, h = null, g = f(e.actor.currentView, (e) => {
33
42
  r(e);
34
43
  });
35
44
  return d(() => {
36
- h();
45
+ g();
37
46
  }), c(s, {
38
47
  get value() {
39
48
  return e.actor;
@@ -46,12 +55,12 @@ var p = (n) => {
46
55
  let r = t();
47
56
  if (!r) return e.fallback ?? null;
48
57
  let s;
49
- return e.store ? s = e.store : ((i === null || m !== r) && (i = o({ atom: a(r.spec.state ?? {}) }), m = r), s = i), c(n, {
58
+ return e.store ? s = e.store : ((m === null || h !== r) && (m = o({ atom: a(r.spec?.state ?? {}) }), h = r), s = m), c(n, {
50
59
  store: s,
51
60
  get children() {
52
61
  return c(p, {
53
62
  get registryResult() {
54
- return e.registryResult;
63
+ return i();
55
64
  },
56
65
  get spec() {
57
66
  return r.spec;
@@ -1 +1 @@
1
- {"version":3,"file":"PlayRenderer.js","names":["createSignal","onCleanup","ErrorBoundary","Component","Renderer","StateProvider","ActionProvider","VisibilityProvider","useStateStore","ActionHandler","StateStore","DefineRegistryResult","SetState","createAtom","xstateStoreStateStore","watchSignal","PlayRendererProps","ViewMetadata","ActorProvider","PlayActor","PlayRendererInner","registryResult","spec","Spec","innerProps","stateCtx","setStateAdapter","updater","prev","getSnapshot","update","handlers","Record","_$createComponent","children","registry","PlayRenderer","props","view","setView","actor","currentView","get","internalStore","lastView","unwatch","nextView","value","fallback","err","onError","store","initialState","state","atom"],"sources":["../src/PlayRenderer.tsx"],"sourcesContent":["/**\n * PlayRenderer - Main SolidJS renderer component for XMachines Play architecture\n *\n * @packageDocumentation\n */\n\nimport { createSignal, onCleanup, ErrorBoundary, type Component } from \"solid-js\";\nimport {\n\tRenderer,\n\tStateProvider,\n\tActionProvider,\n\tVisibilityProvider,\n\tuseStateStore,\n} from \"@json-render/solid\";\nimport type { ActionHandler, StateStore } from \"@json-render/core\";\nimport type { DefineRegistryResult, SetState } from \"@json-render/solid\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@json-render/xstate\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport type { PlayRendererProps } from \"./types.js\";\nimport type { ViewMetadata } from \"@xmachines/play-actor\";\nimport { ActorProvider, type PlayActor } from \"./useActor.js\";\n\n/**\n * Inner component that renders inside StateProvider so it can call useStateStore()\n * to get the live set/getSnapshot functions needed by registryResult.handlers().\n */\nconst PlayRendererInner: Component<{\n\tregistryResult: DefineRegistryResult;\n\tspec: import(\"@json-render/core\").Spec | null;\n}> = (innerProps) => {\n\tconst stateCtx = useStateStore();\n\n\t// Build a SetState adapter: the handlers factory expects an updater-function pattern\n\t// ((prev) => next), while stateCtx provides path-based set/update. This adapter\n\t// bridges the two so action functions can use setState if needed.\n\tconst setStateAdapter: SetState = (updater) => {\n\t\tconst prev = stateCtx.getSnapshot();\n\t\tstateCtx.update(updater(prev));\n\t};\n\n\tconst handlers = (): Record<string, ActionHandler> =>\n\t\tinnerProps.registryResult.handlers(\n\t\t\t() => setStateAdapter,\n\t\t\t() => stateCtx.getSnapshot(),\n\t\t);\n\n\treturn (\n\t\t<ActionProvider handlers={handlers()}>\n\t\t\t<VisibilityProvider>\n\t\t\t\t<Renderer spec={innerProps.spec} registry={innerProps.registryResult.registry} />\n\t\t\t</VisibilityProvider>\n\t\t</ActionProvider>\n\t);\n};\n\n/**\n * Main renderer component that subscribes to actor signals and renders UI\n *\n * Architecture:\n * - Subscribes to actor.currentView signal via TC39 Signal.subtle.Watcher\n * - Renders view.spec via StateProvider → PlayRendererInner (with ActionProvider + handlers)\n * - Routes actions to actor.send() via registryResult.handlers() — real async functions\n * - SolidJS signal only for triggering renders, NOT business logic\n * - State store: uses external `store` prop if provided (controlled mode); otherwise\n * creates a fresh @xstate/store atom per view transition seeded from spec.state.\n * - Wraps the render path in a SolidJS `ErrorBoundary` to contain catalog component\n * render failures. The `fallback` prop is shown on error; `onError` is called for\n * observability forwarding (Sentry, Datadog, etc.).\n *\n * Invariant: Actor Authority - Actor decides all state transitions via guards.\n * Invariant: Passive Infrastructure - Component observes signals and sends events.\n * Invariant: Signal-Only Reactivity - Business logic state lives in actor signals.\n */\nexport const PlayRenderer: Component<PlayRendererProps> = (props) => {\n\t// Create SolidJS signal for view\n\tconst [view, setView] = createSignal<ViewMetadata | null>(\n\t\tprops.actor.currentView.get() as ViewMetadata | null,\n\t);\n\n\t// Internal per-view store — recreated on each view transition when no external store.\n\tlet internalStore: StateStore | null = null;\n\tlet lastView: ViewMetadata | null = null;\n\n\t// Bridge TC39 Signal to SolidJS signal — subscribe synchronously during setup\n\tconst unwatch = watchSignal(props.actor.currentView, (nextView: ViewMetadata | null) => {\n\t\tsetView(nextView);\n\t});\n\tonCleanup(() => {\n\t\tunwatch();\n\t});\n\n\treturn (\n\t\t<ActorProvider value={props.actor as PlayActor}>\n\t\t\t<ErrorBoundary\n\t\t\t\tfallback={(err: unknown) => {\n\t\t\t\t\tprops.onError?.(err);\n\t\t\t\t\treturn props.fallback ?? null;\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{(() => {\n\t\t\t\t\tconst currentView = view();\n\t\t\t\t\tif (!currentView) return props.fallback ?? null;\n\n\t\t\t\t\t// Resolve the store: external (controlled) or internal per-view atom\n\t\t\t\t\tlet store: StateStore;\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tstore = props.store;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (internalStore === null || lastView !== currentView) {\n\t\t\t\t\t\t\tconst initialState =\n\t\t\t\t\t\t\t\t(currentView.spec.state as Record<string, unknown>) ?? {};\n\t\t\t\t\t\t\tinternalStore = xstateStoreStateStore({\n\t\t\t\t\t\t\t\tatom: createAtom(initialState),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlastView = currentView;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstore = internalStore;\n\t\t\t\t\t}\n\n\t\t\t\t\t// PlayRendererInner renders inside StateProvider so useStateStore() works\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<StateProvider store={store}>\n\t\t\t\t\t\t\t<PlayRendererInner\n\t\t\t\t\t\t\t\tregistryResult={props.registryResult}\n\t\t\t\t\t\t\t\tspec={currentView.spec}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</StateProvider>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\t\t\t</ErrorBoundary>\n\t\t</ActorProvider>\n\t);\n};\n"],"mappings":";;;;;;;;AA2BA,IAAMoB,KAGAI,MAAe;CACpB,IAAMC,IAAWjB,GAAe,EAK1BkB,KAA6BC,MAAY;EAC9C,IAAMC,IAAOH,EAASI,aAAa;AACnCJ,IAASK,OAAOH,EAAQC,EAAK,CAAC;IAGzBG,UACLP,EAAWH,eAAeU,eACnBL,SACAD,EAASI,aAChB,CAAC;AAEF,QAAAI,EACE3B,GAAc;EAAA,IAACyB,WAAQ;AAAA,UAAEA,GAAU;;EAAA,IAAAG,WAAA;AAAA,UAAAD,EAClC1B,GAAkB,EAAA,IAAA2B,WAAA;AAAA,WAAAD,EACjB7B,GAAQ;KAAA,IAACkB,OAAI;AAAA,aAAEE,EAAWF;;KAAI,IAAEa,WAAQ;AAAA,aAAEX,EAAWH,eAAec;;KAAQ,CAAA;MAAA,CAAA;;EAAA,CAAA;GAwBpEC,KAA8CC,MAAU;CAEpE,IAAM,CAACC,GAAMC,KAAWvC,EACvBqC,EAAMG,MAAMC,YAAYC,KAAK,CAC7B,EAGGC,IAAmC,MACnCC,IAAgC,MAG9BC,IAAU9B,EAAYsB,EAAMG,MAAMC,cAAcK,MAAkC;AACvFP,IAAQO,EAAS;GAChB;AAKF,QAJA7C,QAAgB;AACf4C,KAAS;GACR,EAEFZ,EACEf,GAAa;EAAA,IAAC6B,QAAK;AAAA,UAAEV,EAAMG;;EAAkB,IAAAN,WAAA;AAAA,UAAAD,EAC5C/B,GAAa;IACb8C,WAAWC,OACVZ,EAAMa,UAAUD,EAAI,EACbZ,EAAMW,YAAY;IACzB,IAAAd,WAAA;AAAA,mBAEO;MACP,IAAMO,IAAcH,GAAM;AAC1B,UAAI,CAACG,EAAa,QAAOJ,EAAMW,YAAY;MAG3C,IAAIG;AAgBJ,aAfId,EAAMc,QACTA,IAAQd,EAAMc,UAEVR,MAAkB,QAAQC,MAAaH,OAG1CE,IAAgB7B,EAAsB,EACrCwC,MAAMzC,EAFL4B,EAAYnB,KAAK+B,SAAqC,EAAE,CAE5B,EAC7B,CAAC,EACFT,IAAWH,IAEZU,IAAQR,IAITV,EACE5B,GAAa;OAAQ8C;OAAK,IAAAjB,WAAA;AAAA,eAAAD,EACzBb,GAAiB;SAAA,IACjBC,iBAAc;AAAA,iBAAEgB,EAAMhB;;SAAc,IACpCC,OAAI;AAAA,iBAAEmB,EAAYnB;;SAAI,CAAA;;OAAA,CAAA;SAItB;;IAAA,CAAA;;EAAA,CAAA"}
1
+ {"version":3,"file":"PlayRenderer.js","names":["createSignal","onCleanup","ErrorBoundary","Component","Renderer","StateProvider","ActionProvider","VisibilityProvider","useStateStore","StateStore","DefineRegistryResult","SetState","createAtom","xstateStoreStateStore","watchSignal","PlayRendererProps","ViewMetadata","ActorProvider","PlayActor","PlayRendererInner","registryResult","spec","Spec","innerProps","stateCtx","setStateAdapter","updater","prev","getSnapshot","update","handlers","_$createComponent","children","registry","PlayRenderer","props","view","setView","actor","currentView","get","activeRegistryResult","onRenderError","r","Object","defineProperty","value","enumerable","configurable","internalStore","lastView","unwatch","nextView","fallback","err","onError","store","initialState","state","Record","atom"],"sources":["../src/PlayRenderer.tsx"],"sourcesContent":["/**\n * PlayRenderer - Main SolidJS renderer component for XMachines Play architecture\n *\n * @packageDocumentation\n */\n\nimport { createSignal, onCleanup, ErrorBoundary, type Component } from \"solid-js\";\nimport {\n\tRenderer,\n\tStateProvider,\n\tActionProvider,\n\tVisibilityProvider,\n\tuseStateStore,\n} from \"@json-render/solid\";\nimport type { StateStore } from \"@json-render/core\";\nimport type { DefineRegistryResult, SetState } from \"@json-render/solid\";\nimport { createAtom } from \"@xstate/store\";\nimport { xstateStoreStateStore } from \"@json-render/xstate\";\nimport { watchSignal } from \"@xmachines/play-signals\";\nimport type { PlayRendererProps } from \"./types.js\";\nimport type { ViewMetadata } from \"@xmachines/play-actor\";\nimport { ActorProvider, type PlayActor } from \"./useActor.js\";\n\n/**\n * Inner component that renders inside StateProvider so it can call useStateStore()\n * to get the live set/getSnapshot functions needed by registryResult.handlers().\n */\nconst PlayRendererInner: Component<{\n\tregistryResult: DefineRegistryResult;\n\tspec: import(\"@json-render/core\").Spec | null;\n}> = (innerProps) => {\n\tconst stateCtx = useStateStore();\n\n\t// Build a SetState adapter: the handlers factory expects an updater-function pattern\n\t// ((prev) => next), while stateCtx provides path-based set/update. This adapter\n\t// bridges the two so action functions can use setState if needed.\n\tconst setStateAdapter: SetState = (updater) => {\n\t\tconst prev = stateCtx.getSnapshot();\n\t\tstateCtx.update(updater(prev));\n\t};\n\n\tconst handlers = innerProps.registryResult.handlers(\n\t\t() => setStateAdapter,\n\t\t() => stateCtx.getSnapshot(),\n\t);\n\n\treturn (\n\t\t<ActionProvider handlers={handlers}>\n\t\t\t<VisibilityProvider>\n\t\t\t\t<Renderer spec={innerProps.spec} registry={innerProps.registryResult.registry} />\n\t\t\t</VisibilityProvider>\n\t\t</ActionProvider>\n\t);\n};\n\n/**\n * Main renderer component that subscribes to actor signals and renders UI\n *\n * Architecture:\n * - Subscribes to actor.currentView signal via TC39 Signal.subtle.Watcher\n * - Renders view.spec via StateProvider → PlayRendererInner (with ActionProvider + handlers)\n * - Routes actions to actor.send() via registryResult.handlers() — real async functions\n * - SolidJS signal only for triggering renders, NOT business logic\n * - State store: uses external `store` prop if provided (controlled mode); otherwise\n * creates a fresh @xstate/store atom per view transition seeded from spec.state.\n * - Wraps the render path in a SolidJS `ErrorBoundary` to contain catalog component\n * render failures. The `fallback` prop is shown on error; `onError` is called for\n * observability forwarding (Sentry, Datadog, etc.).\n *\n * Invariant: Actor Authority - Actor decides all state transitions via guards.\n * Invariant: Passive Infrastructure - Component observes signals and sends events.\n * Invariant: Signal-Only Reactivity - Business logic state lives in actor signals.\n */\nexport const PlayRenderer: Component<PlayRendererProps> = (props) => {\n\t// Create SolidJS signal for view\n\tconst [view, setView] = createSignal<ViewMetadata | null>(\n\t\tprops.actor.currentView.get() as ViewMetadata | null,\n\t);\n\n\t// Inject onRenderError prop into registry (non-enumerable, overrides defineRegistry-level handler)\n\tconst activeRegistryResult = () => {\n\t\tif (!props.onRenderError) return props.registryResult;\n\t\tconst r = { ...props.registryResult.registry };\n\t\tObject.defineProperty(r, \"onRenderError\", {\n\t\t\tvalue: props.onRenderError,\n\t\t\tenumerable: false,\n\t\t\tconfigurable: true,\n\t\t});\n\t\treturn { ...props.registryResult, registry: r };\n\t};\n\n\t// Internal per-view store — recreated on each view transition when no external store.\n\tlet internalStore: StateStore | null = null;\n\tlet lastView: ViewMetadata | null = null;\n\n\t// Bridge TC39 Signal to SolidJS signal — subscribe synchronously during setup\n\tconst unwatch = watchSignal(props.actor.currentView, (nextView: ViewMetadata | null) => {\n\t\tsetView(nextView);\n\t});\n\tonCleanup(() => {\n\t\tunwatch();\n\t});\n\n\treturn (\n\t\t<ActorProvider value={props.actor as PlayActor}>\n\t\t\t<ErrorBoundary\n\t\t\t\tfallback={(err: unknown) => {\n\t\t\t\t\tprops.onError?.(err);\n\t\t\t\t\treturn props.fallback ?? null;\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{(() => {\n\t\t\t\t\tconst currentView = view();\n\t\t\t\t\tif (!currentView) return props.fallback ?? null;\n\n\t\t\t\t\t// Resolve the store: external (controlled) or internal per-view atom\n\t\t\t\t\tlet store: StateStore;\n\t\t\t\t\tif (props.store) {\n\t\t\t\t\t\tstore = props.store;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (internalStore === null || lastView !== currentView) {\n\t\t\t\t\t\t\tconst initialState =\n\t\t\t\t\t\t\t\t(currentView.spec?.state as Record<string, unknown>) ?? {};\n\t\t\t\t\t\t\tinternalStore = xstateStoreStateStore({\n\t\t\t\t\t\t\t\tatom: createAtom(initialState),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tlastView = currentView;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstore = internalStore;\n\t\t\t\t\t}\n\n\t\t\t\t\t// PlayRendererInner renders inside StateProvider so useStateStore() works\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<StateProvider store={store}>\n\t\t\t\t\t\t\t<PlayRendererInner\n\t\t\t\t\t\t\t\tregistryResult={activeRegistryResult()}\n\t\t\t\t\t\t\t\tspec={currentView.spec}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</StateProvider>\n\t\t\t\t\t);\n\t\t\t\t})()}\n\t\t\t</ErrorBoundary>\n\t\t</ActorProvider>\n\t);\n};\n"],"mappings":";;;;;;;;AA2BA,IAAMmB,KAGAI,MAAe;CACpB,IAAMC,IAAWhB,GAAe,EAK1BiB,KAA6BC,MAAY;EAC9C,IAAMC,IAAOH,EAASI,aAAa;AACnCJ,IAASK,OAAOH,EAAQC,EAAK,CAAC;;AAQ/B,QAAAI,EACEzB,GAAc;EAAWwB,UANVP,EAAWH,eAAeU,eACpCL,SACAD,EAASI,aAChB,CAAC;EAGkC,IAAAI,WAAA;AAAA,UAAAD,EAChCxB,GAAkB,EAAA,IAAAyB,WAAA;AAAA,WAAAD,EACjB3B,GAAQ;KAAA,IAACiB,OAAI;AAAA,aAAEE,EAAWF;;KAAI,IAAEY,WAAQ;AAAA,aAAEV,EAAWH,eAAea;;KAAQ,CAAA;MAAA,CAAA;;EAAA,CAAA;GAwBpEC,KAA8CC,MAAU;CAEpE,IAAM,CAACC,GAAMC,KAAWrC,EACvBmC,EAAMG,MAAMC,YAAYC,KAAK,CAC7B,EAGKC,UAA6B;AAClC,MAAI,CAACN,EAAMO,cAAe,QAAOP,EAAMf;EACvC,IAAMuB,IAAI,EAAE,GAAGR,EAAMf,eAAea,UAAU;AAM9C,SALAW,OAAOC,eAAeF,GAAG,iBAAiB;GACzCG,OAAOX,EAAMO;GACbK,YAAY;GACZC,cAAc;GACd,CAAC,EACK;GAAE,GAAGb,EAAMf;GAAgBa,UAAUU;GAAG;IAI5CM,IAAmC,MACnCC,IAAgC,MAG9BC,IAAUrC,EAAYqB,EAAMG,MAAMC,cAAca,MAAkC;AACvFf,IAAQe,EAAS;GAChB;AAKF,QAJAnD,QAAgB;AACfkD,KAAS;GACR,EAEFpB,EACEd,GAAa;EAAA,IAAC6B,QAAK;AAAA,UAAEX,EAAMG;;EAAkB,IAAAN,WAAA;AAAA,UAAAD,EAC5C7B,GAAa;IACbmD,WAAWC,OACVnB,EAAMoB,UAAUD,EAAI,EACbnB,EAAMkB,YAAY;IACzB,IAAArB,WAAA;AAAA,mBAEO;MACP,IAAMO,IAAcH,GAAM;AAC1B,UAAI,CAACG,EAAa,QAAOJ,EAAMkB,YAAY;MAG3C,IAAIG;AAgBJ,aAfIrB,EAAMqB,QACTA,IAAQrB,EAAMqB,UAEVP,MAAkB,QAAQC,MAAaX,OAG1CU,IAAgBpC,EAAsB,EACrC+C,MAAMhD,EAFL2B,EAAYlB,MAAMqC,SAAqC,EAAE,CAE7B,EAC7B,CAAC,EACFR,IAAWX,IAEZiB,IAAQP,IAITlB,EACE1B,GAAa;OAAQmD;OAAK,IAAAxB,WAAA;AAAA,eAAAD,EACzBZ,GAAiB;SAAA,IACjBC,iBAAc;AAAA,iBAAEqB,GAAsB;;SAAA,IACtCpB,OAAI;AAAA,iBAAEkB,EAAYlB;;SAAI,CAAA;;OAAA,CAAA;SAItB;;IAAA,CAAA;;EAAA,CAAA"}
@@ -84,102 +84,142 @@ function k(e) {
84
84
  function A(e) {
85
85
  return typeof e == "object" && !!e && "$bindItem" in e && typeof e.$bindItem == "string";
86
86
  }
87
- function j(e) {
87
+ function te(e) {
88
88
  return typeof e == "object" && !!e && "$cond" in e && "$then" in e && "$else" in e;
89
89
  }
90
- function te(e) {
90
+ function ne(e) {
91
91
  return typeof e == "object" && !!e && "$computed" in e && typeof e.$computed == "string";
92
92
  }
93
- function ne(e) {
93
+ function re(e) {
94
94
  return typeof e == "object" && !!e && "$template" in e && typeof e.$template == "string";
95
95
  }
96
- var re = 100, M = /* @__PURE__ */ new Set(), ie = 100, N = /* @__PURE__ */ new Set();
97
- function P(e, t) {
96
+ var ie = 100, j = /* @__PURE__ */ new Set();
97
+ function M(e, t) {
98
98
  if (t.repeatBasePath == null) {
99
99
  console.warn(`$bindItem used outside repeat scope: "${e}"`);
100
100
  return;
101
101
  }
102
102
  return e === "" ? t.repeatBasePath : t.repeatBasePath + "/" + e;
103
103
  }
104
- function F(e, t) {
104
+ function N(e, t) {
105
105
  if (e == null) return e;
106
106
  if (ee(e)) return p(t.stateModel, e.$state);
107
107
  if (D(e)) return t.repeatItem === void 0 ? void 0 : e.$item === "" ? t.repeatItem : p(t.repeatItem, e.$item);
108
108
  if (O(e)) return t.repeatIndex;
109
109
  if (k(e)) return p(t.stateModel, e.$bindState);
110
110
  if (A(e)) {
111
- let n = P(e.$bindItem, t);
111
+ let n = M(e.$bindItem, t);
112
112
  return n === void 0 ? void 0 : p(t.stateModel, n);
113
113
  }
114
- if (j(e)) return F(E(e.$cond, t) ? e.$then : e.$else, t);
115
- if (te(e)) {
114
+ if (te(e)) return N(E(e.$cond, t) ? e.$then : e.$else, t);
115
+ if (ne(e)) {
116
116
  let n = t.functions?.[e.$computed];
117
117
  if (!n) {
118
- M.has(e.$computed) || (M.size < re && M.add(e.$computed), console.warn(`Unknown $computed function: "${e.$computed}"`));
118
+ j.has(e.$computed) || (j.size < ie && j.add(e.$computed), console.warn(`Unknown $computed function: "${e.$computed}"`));
119
119
  return;
120
120
  }
121
121
  let r = {};
122
- if (e.args) for (let [n, i] of Object.entries(e.args)) r[n] = F(i, t);
122
+ if (e.args) for (let [n, i] of Object.entries(e.args)) r[n] = N(i, t);
123
123
  return n(r);
124
124
  }
125
- if (ne(e)) return e.$template.replace(/\$\{([^}]+)\}/g, (e, n) => {
126
- let r = n;
127
- r.startsWith("/") || (N.has(r) || (N.size < ie && N.add(r), console.warn(`$template path "${r}" should be a JSON Pointer starting with "/". Automatically resolving as "/${r}".`)), r = "/" + r);
128
- let i = p(t.stateModel, r);
129
- return i == null ? "" : String(i);
125
+ if (re(e)) return e.$template.replace(/\$\{([^}]+)\}/g, (e, n) => {
126
+ if (n.startsWith("/")) {
127
+ let e = p(t.stateModel, n);
128
+ return e == null ? "" : String(e);
129
+ }
130
+ if (t.repeatItem !== void 0) {
131
+ let e = p(t.repeatItem, n);
132
+ if (e != null) return String(e);
133
+ }
134
+ let r = p(t.stateModel, "/" + n);
135
+ return r == null ? "" : String(r);
130
136
  });
131
- if (Array.isArray(e)) return e.map((e) => F(e, t));
137
+ if (Array.isArray(e)) return e.map((e) => N(e, t));
132
138
  if (typeof e == "object") {
133
139
  let n = {};
134
- for (let [r, i] of Object.entries(e)) n[r] = F(i, t);
140
+ for (let [r, i] of Object.entries(e)) n[r] = N(i, t);
135
141
  return n;
136
142
  }
137
143
  return e;
138
144
  }
139
145
  function ae(e, t) {
140
146
  let n = {};
141
- for (let [r, i] of Object.entries(e)) n[r] = F(i, t);
147
+ for (let [r, i] of Object.entries(e)) n[r] = N(i, t);
142
148
  return n;
143
149
  }
144
150
  function oe(e, t) {
145
151
  let n;
146
152
  for (let [r, i] of Object.entries(e)) if (k(i)) n ||= {}, n[r] = i.$bindState;
147
153
  else if (A(i)) {
148
- let e = P(i.$bindItem, t);
154
+ let e = M(i.$bindItem, t);
149
155
  e !== void 0 && (n ||= {}, n[r] = e);
150
156
  }
151
157
  return n;
152
158
  }
153
159
  function se(e, t) {
154
- return D(e) ? P(e.$item, t) : O(e) ? t.repeatIndex : F(e, t);
160
+ return D(e) ? M(e.$item, t) : O(e) ? t.repeatIndex : N(e, t);
161
+ }
162
+ var P = /* @__PURE__ */ new Set();
163
+ function ce(e) {
164
+ for (let t of P) {
165
+ let n = t.onDispatch;
166
+ if (n) try {
167
+ n(e);
168
+ } catch (e) {
169
+ process.env.NODE_ENV !== "production" && console.error("[json-render] action observer threw in onDispatch:", e);
170
+ }
171
+ }
155
172
  }
156
- var ce = s({
173
+ function le(e) {
174
+ for (let t of P) {
175
+ let n = t.onSettle;
176
+ if (n) try {
177
+ n(e);
178
+ } catch (e) {
179
+ process.env.NODE_ENV !== "production" && console.error("[json-render] action observer threw in onSettle:", e);
180
+ }
181
+ }
182
+ }
183
+ var F = 0;
184
+ function ue() {
185
+ return F += 1, `${Date.now()}-${F}`;
186
+ }
187
+ var de = 0, I = /* @__PURE__ */ new Set();
188
+ function L() {
189
+ return de > 0;
190
+ }
191
+ function R(e) {
192
+ return I.add(e), () => {
193
+ I.delete(e);
194
+ };
195
+ }
196
+ var z = s({
157
197
  title: l(),
158
198
  message: l(),
159
199
  confirmLabel: l().optional(),
160
200
  cancelLabel: l().optional(),
161
201
  variant: e(["default", "danger"]).optional()
162
- }), le = u([
202
+ }), B = u([
163
203
  s({ navigate: l() }),
164
204
  s({ set: c(l(), d()) }),
165
205
  s({ action: l() })
166
- ]), I = u([s({ set: c(l(), d()) }), s({ action: l() })]);
206
+ ]), V = u([s({ set: c(l(), d()) }), s({ action: l() })]);
167
207
  s({
168
208
  action: l(),
169
209
  params: c(l(), f).optional(),
170
- confirm: ce.optional(),
171
- onSuccess: le.optional(),
172
- onError: I.optional(),
210
+ confirm: z.optional(),
211
+ onSuccess: B.optional(),
212
+ onError: V.optional(),
173
213
  preventDefault: r().optional()
174
214
  });
175
- function L(e, t) {
215
+ function H(e, t) {
176
216
  let n = {};
177
217
  if (e.params) for (let [r, i] of Object.entries(e.params)) n[r] = m(i, t);
178
218
  let r = e.confirm;
179
219
  return r &&= {
180
220
  ...r,
181
- message: R(r.message, t),
182
- title: R(r.title, t)
221
+ message: U(r.message, t),
222
+ title: U(r.title, t)
183
223
  }, {
184
224
  action: e.action,
185
225
  params: n,
@@ -188,13 +228,13 @@ function L(e, t) {
188
228
  onError: e.onError
189
229
  };
190
230
  }
191
- function R(e, t) {
231
+ function U(e, t) {
192
232
  return e.replace(/\$\{([^}]+)\}/g, (e, n) => {
193
233
  let r = m({ $state: n }, t);
194
234
  return String(r ?? "");
195
235
  });
196
236
  }
197
- async function z(e) {
237
+ async function fe(e) {
198
238
  let { action: t, handler: n, setState: r, navigate: i, executeAction: a } = e;
199
239
  try {
200
240
  if (await n(t.params), t.onSuccess) if ("navigate" in t.onSuccess && i) i(t.onSuccess.navigate);
@@ -219,11 +259,11 @@ s({
219
259
  ]).optional(),
220
260
  enabled: v.optional()
221
261
  });
222
- var B = ["patch"];
223
- function V(e) {
224
- return e?.modes?.length ? e.modes : B;
262
+ var pe = ["patch"];
263
+ function me(e) {
264
+ return e?.modes?.length ? e.modes : pe;
225
265
  }
226
- function H() {
266
+ function he() {
227
267
  return [
228
268
  "PATCH MODE (RFC 6902 JSON Patch):",
229
269
  "Output one JSON object per line. Each line is a patch operation.",
@@ -233,7 +273,7 @@ function H() {
233
273
  "Only output patches for what needs to change."
234
274
  ].join("\n");
235
275
  }
236
- function U() {
276
+ function ge() {
237
277
  return [
238
278
  "MERGE MODE (RFC 7396 JSON Merge Patch):",
239
279
  "Output a single JSON object on one line with __json_edit set to true.",
@@ -247,7 +287,7 @@ function U() {
247
287
  "{\"__json_edit\":true,\"elements\":{\"old-widget\":null}}"
248
288
  ].join("\n");
249
289
  }
250
- function ue() {
290
+ function _e() {
251
291
  return [
252
292
  "DIFF MODE (unified diff):",
253
293
  "Output a unified diff inside a ```diff code fence.",
@@ -263,7 +303,7 @@ function ue() {
263
303
  "```"
264
304
  ].join("\n");
265
305
  }
266
- function de() {
306
+ function ve() {
267
307
  return [
268
308
  "PATCH MODE (RFC 6902 JSON Patch):",
269
309
  "Output RFC 6902 JSON Patch lines inside a ```yaml-patch code fence.",
@@ -276,7 +316,7 @@ function de() {
276
316
  "```"
277
317
  ].join("\n");
278
318
  }
279
- function fe() {
319
+ function ye() {
280
320
  return [
281
321
  "MERGE MODE (RFC 7396 JSON Merge Patch):",
282
322
  "Output only the changed parts in a ```yaml-edit code fence.",
@@ -302,7 +342,7 @@ function fe() {
302
342
  "```"
303
343
  ].join("\n");
304
344
  }
305
- function pe() {
345
+ function be() {
306
346
  return [
307
347
  "DIFF MODE (unified diff):",
308
348
  "Output a unified diff inside a ```diff code fence.",
@@ -318,44 +358,44 @@ function pe() {
318
358
  "```"
319
359
  ].join("\n");
320
360
  }
321
- function me(e) {
361
+ function xe(e) {
322
362
  if (e.length === 1) return "";
323
363
  let t = ["Choose the best edit strategy for the requested change:"];
324
364
  return e.includes("patch") && t.push("- PATCH: best for precise, targeted single-field updates"), e.includes("merge") && t.push("- MERGE: best for structural changes (add/remove elements, reparent children, update multiple props at once)"), e.includes("diff") && t.push("- DIFF: best for small text-level changes when you can see the exact lines to change"), t.join("\n");
325
365
  }
326
- function he(e, t) {
327
- let n = V(e), r = [];
366
+ function Se(e, t) {
367
+ let n = me(e), r = [];
328
368
  r.push("EDITING EXISTING SPECS:"), r.push("");
329
- let i = me(n);
369
+ let i = xe(n);
330
370
  i && (r.push(i), r.push(""));
331
371
  for (let e of n) {
332
372
  if (t === "json") switch (e) {
333
373
  case "patch":
334
- r.push(H());
374
+ r.push(he());
335
375
  break;
336
376
  case "merge":
337
- r.push(U());
377
+ r.push(ge());
338
378
  break;
339
379
  case "diff":
340
- r.push(ue());
380
+ r.push(_e());
341
381
  break;
342
382
  }
343
383
  else switch (e) {
344
384
  case "patch":
345
- r.push(de());
385
+ r.push(ve());
346
386
  break;
347
387
  case "merge":
348
- r.push(fe());
388
+ r.push(ye());
349
389
  break;
350
390
  case "diff":
351
- r.push(pe());
391
+ r.push(be());
352
392
  break;
353
393
  }
354
394
  r.push("");
355
395
  }
356
396
  return r.join("\n");
357
397
  }
358
- function ge() {
398
+ function Ce() {
359
399
  return {
360
400
  string: () => ({ kind: "string" }),
361
401
  number: () => ({ kind: "number" }),
@@ -389,26 +429,26 @@ function ge() {
389
429
  optional: () => ({ optional: !0 })
390
430
  };
391
431
  }
392
- function _e(e, t) {
432
+ function we(e, t) {
393
433
  return {
394
- definition: e(ge()),
434
+ definition: e(Ce()),
395
435
  promptTemplate: t?.promptTemplate,
396
436
  defaultRules: t?.defaultRules,
397
437
  builtInActions: t?.builtInActions,
398
438
  createCatalog(e) {
399
- return ve(this, e);
439
+ return Te(this, e);
400
440
  }
401
441
  };
402
442
  }
403
- function ve(e, t) {
404
- let n = t.components, r = t.actions, i = n ? Object.keys(n) : [], a = r ? Object.keys(r) : [], o = ye(e.definition, t);
443
+ function Te(e, t) {
444
+ let n = t.components, r = t.actions, i = n ? Object.keys(n) : [], a = r ? Object.keys(r) : [], o = Ee(e.definition, t);
405
445
  return {
406
446
  schema: e,
407
447
  data: t,
408
448
  componentNames: i,
409
449
  actionNames: a,
410
450
  prompt(e = {}) {
411
- return Se(this, e);
451
+ return G(this, e);
412
452
  },
413
453
  jsonSchema(e = {}) {
414
454
  return $(o, e.strict ?? !1);
@@ -431,7 +471,7 @@ function ve(e, t) {
431
471
  }
432
472
  };
433
473
  }
434
- function ye(e, t) {
474
+ function Ee(e, t) {
435
475
  return W(e.spec, t);
436
476
  }
437
477
  function W(i, u) {
@@ -454,29 +494,29 @@ function W(i, u) {
454
494
  return c(l(), e);
455
495
  }
456
496
  case "ref": {
457
- let t = i.inner, n = be(t, u);
497
+ let t = i.inner, n = De(t, u);
458
498
  return n.length === 0 ? l() : n.length === 1 ? a(n[0]) : e(n);
459
499
  }
460
500
  case "propsOf": {
461
- let e = i.inner, t = xe(e, u);
501
+ let e = i.inner, t = Oe(e, u);
462
502
  return t.length === 0 ? c(l(), d()) : t.length === 1 ? t[0] : c(l(), d());
463
503
  }
464
504
  default: return d();
465
505
  }
466
506
  }
467
- function be(e, t) {
507
+ function De(e, t) {
468
508
  let n = e.split("."), r = { catalog: t };
469
509
  for (let e of n) if (r && typeof r == "object") r = r[e];
470
510
  else return [];
471
511
  return r && typeof r == "object" ? Object.keys(r) : [];
472
512
  }
473
- function xe(e, t) {
513
+ function Oe(e, t) {
474
514
  let n = e.split("."), r = { catalog: t };
475
515
  for (let e of n) if (r && typeof r == "object") r = r[e];
476
516
  else return [];
477
517
  return r && typeof r == "object" ? Object.values(r).map((e) => e.props).filter((e) => e !== void 0) : [];
478
518
  }
479
- function Se(e, t) {
519
+ function G(e, t) {
480
520
  if (e.schema.promptTemplate) {
481
521
  let n = {
482
522
  catalog: e.data,
@@ -489,7 +529,7 @@ function Se(e, t) {
489
529
  }
490
530
  let { system: n = "You are a UI generator that outputs JSON.", customRules: r = [], mode: i = "standalone" } = t, a = i === "chat" ? (console.warn("[json-render] mode \"chat\" is deprecated, use \"inline\" instead"), "inline") : i === "generate" ? (console.warn("[json-render] mode \"generate\" is deprecated, use \"standalone\" instead"), "standalone") : i, o = [];
491
531
  o.push(n), o.push(""), a === "inline" ? (o.push("OUTPUT FORMAT (text + JSONL, RFC 6902 JSON Patch):"), o.push("You respond conversationally. When generating UI, first write a brief explanation (1-3 sentences), then output JSONL patch lines wrapped in a ```spec code fence."), o.push("The JSONL lines use RFC 6902 JSON Patch operations to build a UI tree. Always wrap them in a ```spec fence block:"), o.push(" ```spec"), o.push(" {\"op\":\"add\",\"path\":\"/root\",\"value\":\"main\"}"), o.push(" {\"op\":\"add\",\"path\":\"/elements/main\",\"value\":{\"type\":\"Card\",\"props\":{\"title\":\"Hello\"},\"children\":[]}}"), o.push(" ```"), o.push("If the user's message does not require a UI (e.g. a greeting or clarifying question), respond with text only — no JSONL.")) : (o.push("OUTPUT FORMAT (JSONL, RFC 6902 JSON Patch):"), o.push("Output JSONL (one JSON object per line) using RFC 6902 JSON Patch operations to build a UI tree.")), o.push("Each line is a JSON patch operation (add, remove, replace). Start with /root, then stream /elements and /state patches interleaved so the UI fills in progressively as it streams."), o.push(""), o.push("Example output (each line is a separate JSON object):"), o.push("");
492
- let s = e.data.components, c = e.componentNames, l = c[0] || "Component", u = c.length > 1 ? c[1] : l, d = s?.[l], f = s?.[u], p = d ? G(d) : {}, m = f ? G(f) : {}, h = f?.props ? J(f.props) : null, g = h ? {
532
+ let s = e.data.components, c = e.componentNames, l = c[0] || "Component", u = c.length > 1 ? c[1] : l, d = s?.[l], f = s?.[u], p = d ? K(d) : {}, m = f ? K(f) : {}, h = f?.props ? ke(f.props) : null, g = h ? {
493
533
  ...m,
494
534
  [h]: { $item: "title" }
495
535
  } : m, _ = [
@@ -606,7 +646,7 @@ Note: state patches appear right after the elements that use them, so the UI fil
606
646
  eq: "home"
607
647
  },
608
648
  children: ["..."]
609
- })}`), o.push("- `{ \"$state\": \"/path\" }` - visible when state at path is truthy"), o.push("- `{ \"$state\": \"/path\", \"not\": true }` - visible when state at path is falsy"), o.push("- `{ \"$state\": \"/path\", \"eq\": \"value\" }` - visible when state equals value"), o.push("- `{ \"$state\": \"/path\", \"neq\": \"value\" }` - visible when state does not equal value"), o.push("- `{ \"$state\": \"/path\", \"gt\": N }` / `gte` / `lt` / `lte` - numeric comparisons"), o.push("- Use ONE operator per condition (eq, neq, gt, gte, lt, lte). Do not combine multiple operators."), o.push("- Any condition can add `\"not\": true` to invert its result"), o.push("- `[condition, condition]` - all conditions must be true (implicit AND)"), o.push("- `{ \"$and\": [condition, condition] }` - explicit AND (use when nesting inside $or)"), o.push("- `{ \"$or\": [condition, condition] }` - at least one must be true (OR)"), o.push("- `true` / `false` - always visible/hidden"), o.push(""), o.push("Use a component with on.press bound to setState to update state and drive visibility."), o.push(`Example: A ${l} with on: { "press": { "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } } } sets state, then a container with visible: { "$state": "/activeTab", "eq": "home" } shows only when that tab is active.`), o.push(""), o.push("For tab patterns where the first/default tab should be visible when no tab is selected yet, use $or to handle both cases: visible: { \"$or\": [{ \"$state\": \"/activeTab\", \"eq\": \"home\" }, { \"$state\": \"/activeTab\", \"not\": true }] }. This ensures the first tab is visible both when explicitly selected AND when /activeTab is not yet set."), o.push(""), o.push("DYNAMIC PROPS:"), o.push("Any prop value can be a dynamic expression that resolves based on state. Three forms are supported:"), o.push(""), o.push("1. Read-only state: `{ \"$state\": \"/statePath\" }` - resolves to the value at that state path (one-way read)."), o.push(" Example: `\"color\": { \"$state\": \"/theme/primary\" }` reads the color from state."), o.push(""), o.push("2. Two-way binding: `{ \"$bindState\": \"/statePath\" }` - resolves to the value at the state path AND enables write-back. Use on form input props (value, checked, pressed, etc.)."), o.push(" Example: `\"value\": { \"$bindState\": \"/form/email\" }` binds the input value to /form/email."), o.push(" Inside repeat scopes: `\"checked\": { \"$bindItem\": \"completed\" }` binds to the current item's completed field."), o.push(""), o.push("3. Conditional: `{ \"$cond\": <condition>, \"$then\": <value>, \"$else\": <value> }` - evaluates the condition (same syntax as visibility conditions) and picks the matching value."), o.push(" Example: `\"color\": { \"$cond\": { \"$state\": \"/activeTab\", \"eq\": \"home\" }, \"$then\": \"#007AFF\", \"$else\": \"#8E8E93\" }`"), o.push(""), o.push("Use $bindState for form inputs (text fields, checkboxes, selects, sliders, etc.) and $state for read-only data display. Inside repeat scopes, use $bindItem for form inputs bound to the current item. Use dynamic props instead of duplicating elements with opposing visible conditions when only prop values differ."), o.push(""), o.push("4. Template: `{ \"$template\": \"Hello, ${/name}!\" }` - interpolates `${/path}` references in the string with values from the state model."), o.push(" Example: `\"label\": { \"$template\": \"Items: ${/cart/count} | Total: ${/cart/total}\" }` renders \"Items: 3 | Total: 42.00\" when /cart/count is 3 and /cart/total is 42.00."), o.push("");
649
+ })}`), o.push("- `{ \"$state\": \"/path\" }` - visible when state at path is truthy"), o.push("- `{ \"$state\": \"/path\", \"not\": true }` - visible when state at path is falsy"), o.push("- `{ \"$state\": \"/path\", \"eq\": \"value\" }` - visible when state equals value"), o.push("- `{ \"$state\": \"/path\", \"neq\": \"value\" }` - visible when state does not equal value"), o.push("- `{ \"$state\": \"/path\", \"gt\": N }` / `gte` / `lt` / `lte` - numeric comparisons"), o.push("- Use ONE operator per condition (eq, neq, gt, gte, lt, lte). Do not combine multiple operators."), o.push("- Any condition can add `\"not\": true` to invert its result"), o.push("- `[condition, condition]` - all conditions must be true (implicit AND)"), o.push("- `{ \"$and\": [condition, condition] }` - explicit AND (use when nesting inside $or)"), o.push("- `{ \"$or\": [condition, condition] }` - at least one must be true (OR)"), o.push("- `true` / `false` - always visible/hidden"), o.push(""), o.push("Use a component with on.press bound to setState to update state and drive visibility."), o.push(`Example: A ${l} with on: { "press": { "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } } } sets state, then a container with visible: { "$state": "/activeTab", "eq": "home" } shows only when that tab is active.`), o.push(""), o.push("For tab patterns where the first/default tab should be visible when no tab is selected yet, use $or to handle both cases: visible: { \"$or\": [{ \"$state\": \"/activeTab\", \"eq\": \"home\" }, { \"$state\": \"/activeTab\", \"not\": true }] }. This ensures the first tab is visible both when explicitly selected AND when /activeTab is not yet set."), o.push(""), o.push("DYNAMIC PROPS:"), o.push("Any prop value can be a dynamic expression that resolves based on state. Three forms are supported:"), o.push(""), o.push("1. Read-only state: `{ \"$state\": \"/statePath\" }` - resolves to the value at that state path (one-way read)."), o.push(" Example: `\"color\": { \"$state\": \"/theme/primary\" }` reads the color from state."), o.push(""), o.push("2. Two-way binding: `{ \"$bindState\": \"/statePath\" }` - resolves to the value at the state path AND enables write-back. Use on form input props (value, checked, pressed, etc.)."), o.push(" Example: `\"value\": { \"$bindState\": \"/form/email\" }` binds the input value to /form/email."), o.push(" Inside repeat scopes: `\"checked\": { \"$bindItem\": \"completed\" }` binds to the current item's completed field."), o.push(""), o.push("3. Conditional: `{ \"$cond\": <condition>, \"$then\": <value>, \"$else\": <value> }` - evaluates the condition (same syntax as visibility conditions) and picks the matching value."), o.push(" Example: `\"color\": { \"$cond\": { \"$state\": \"/activeTab\", \"eq\": \"home\" }, \"$then\": \"#007AFF\", \"$else\": \"#8E8E93\" }`"), o.push(""), o.push("Use $bindState for form inputs (text fields, checkboxes, selects, sliders, etc.) and $state for read-only data display. Inside repeat scopes, use $bindItem for form inputs bound to the current item. Use dynamic props instead of duplicating elements with opposing visible conditions when only prop values differ."), o.push(""), o.push("4. Template: `{ \"$template\": \"Hello, ${/name}!\" }` - interpolates references in the string. Absolute paths like `${/path}` resolve against the state model. Bare names like `${field}` resolve against the current repeat item first, then fall back to the state model at `/<field>`."), o.push(" Example: `\"label\": { \"$template\": \"Items: ${/cart/count} | Total: ${/cart/total}\" }` renders \"Items: 3 | Total: 42.00\" when /cart/count is 3 and /cart/total is 42.00. Inside a repeat, `{ \"$template\": \"${name} - ${email}\" }` reads name and email from each item."), o.push("");
610
650
  let C = e.data.functions;
611
651
  if (C && Object.keys(C).length > 0) {
612
652
  o.push("5. Computed: `{ \"$computed\": \"<functionName>\", \"args\": { \"key\": <expression> } }` - calls a registered function with resolved args and returns the result."), o.push(" Example: `\"value\": { \"$computed\": \"fullName\", \"args\": { \"first\": { \"$state\": \"/form/firstName\" }, \"last\": { \"$state\": \"/form/lastName\" } } }`"), o.push(" Available functions:");
@@ -630,7 +670,7 @@ Note: state patches appear right after the elements that use them, so the UI fil
630
670
  children: []
631
671
  })}`), o.push(""), o.push("Use `watch` for cascading dependencies where changing one field should trigger side effects (loading data, resetting dependent fields, computing derived values)."), o.push("IMPORTANT: `watch` is a top-level field on the element (sibling of type/props/children), NOT inside props. Watchers only fire when the value changes, not on initial render."), o.push(""));
632
672
  let w = t.editModes;
633
- w && w.length > 0 && o.push(he({ modes: w }, "json")), o.push("RULES:");
673
+ w && w.length > 0 && o.push(Se({ modes: w }, "json")), o.push("RULES:");
634
674
  let T = a === "inline" ? [
635
675
  "When generating UI, wrap all JSONL patches in a ```spec code fence - one JSON object per line inside the fence",
636
676
  "Write a brief conversational response before any JSONL output",
@@ -657,10 +697,10 @@ Note: state patches appear right after the elements that use them, so the UI fil
657
697
  o.push(`${t + 1}. ${e}`);
658
698
  }), o.join("\n");
659
699
  }
660
- function G(e) {
661
- return e.example && Object.keys(e.example).length > 0 ? e.example : e.props ? K(e.props) : {};
662
- }
663
700
  function K(e) {
701
+ return e.example && Object.keys(e.example).length > 0 ? e.example : e.props ? q(e.props) : {};
702
+ }
703
+ function q(e) {
664
704
  if (!e || !e._def) return {};
665
705
  let t = e._def, n = Y(e);
666
706
  if (n !== "ZodObject" && n !== "object") return {};
@@ -669,11 +709,11 @@ function K(e) {
669
709
  let i = {};
670
710
  for (let [e, t] of Object.entries(r)) {
671
711
  let n = Y(t);
672
- n === "ZodOptional" || n === "optional" || n === "ZodNullable" || n === "nullable" || (i[e] = q(t));
712
+ n === "ZodOptional" || n === "optional" || n === "ZodNullable" || n === "nullable" || (i[e] = J(t));
673
713
  }
674
714
  return i;
675
715
  }
676
- function q(e) {
716
+ function J(e) {
677
717
  if (!e || !e._def) return "...";
678
718
  let t = e._def;
679
719
  switch (Y(e)) {
@@ -700,21 +740,21 @@ function q(e) {
700
740
  case "ZodDefault":
701
741
  case "default": {
702
742
  let e = t.innerType ?? t.wrapped;
703
- return e ? q(e) : null;
743
+ return e ? J(e) : null;
704
744
  }
705
745
  case "ZodArray":
706
746
  case "array": return [];
707
747
  case "ZodObject":
708
- case "object": return K(e);
748
+ case "object": return q(e);
709
749
  case "ZodUnion":
710
750
  case "union": {
711
751
  let e = t.options;
712
- return e && e.length > 0 ? q(e[0]) : "...";
752
+ return e && e.length > 0 ? J(e[0]) : "...";
713
753
  }
714
754
  default: return "...";
715
755
  }
716
756
  }
717
- function J(e) {
757
+ function ke(e) {
718
758
  if (!e || !e._def) return null;
719
759
  let t = e._def, n = Y(e);
720
760
  if (n !== "ZodObject" && n !== "object") return null;
@@ -742,7 +782,10 @@ function X(e) {
742
782
  case "ZodBoolean":
743
783
  case "boolean": return "boolean";
744
784
  case "ZodLiteral":
745
- case "literal": return JSON.stringify(t.value);
785
+ case "literal": {
786
+ let e = t.values?.[0] ?? t.value;
787
+ return JSON.stringify(e);
788
+ }
746
789
  case "ZodEnum":
747
790
  case "enum": {
748
791
  let e;
@@ -776,6 +819,16 @@ function X(e) {
776
819
  let e = t.options;
777
820
  return e ? e.map((e) => X(e)).join(" | ") : "unknown";
778
821
  }
822
+ case "ZodRecord":
823
+ case "record": {
824
+ let e = t.keyType ?? void 0, n = t.valueType ?? t.element ?? void 0;
825
+ return `Record<${e ? X(e) : "string"}, ${n ? X(n) : "unknown"}>`;
826
+ }
827
+ case "ZodDefault":
828
+ case "default": {
829
+ let e = t.innerType ?? t.wrapped;
830
+ return e ? X(e) : "unknown";
831
+ }
779
832
  default: return "unknown";
780
833
  }
781
834
  }
@@ -858,6 +911,6 @@ function $(e, t = !1) {
858
911
  }
859
912
  }
860
913
  //#endregion
861
- export { _e as defineSchema, E as evaluateVisibility, z as executeAction, L as resolveAction, se as resolveActionParam, oe as resolveBindings, ae as resolveElementProps };
914
+ export { we as defineSchema, E as evaluateVisibility, fe as executeAction, L as isDevtoolsActive, ue as nextActionDispatchId, ce as notifyActionDispatch, le as notifyActionSettle, H as resolveAction, se as resolveActionParam, oe as resolveBindings, ae as resolveElementProps, R as subscribeDevtoolsActive };
862
915
 
863
916
  //# sourceMappingURL=index.js.map