autoui-react 0.0.4-alpha → 0.1.0

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 CHANGED
@@ -1,111 +1,26 @@
1
1
  'use strict';
2
2
 
3
- var clsx = require('clsx');
4
- var tailwindMerge = require('tailwind-merge');
5
- var reactSlot = require('@radix-ui/react-slot');
6
- var classVarianceAuthority = require('class-variance-authority');
7
- var jsxRuntime = require('react/jsx-runtime');
8
- var React = require('react');
9
- var openai = require('@ai-sdk/openai');
10
- var ai = require('ai');
3
+ var react = require('react');
11
4
  var zod = require('zod');
12
-
13
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
-
15
- var React__default = /*#__PURE__*/_interopDefault(React);
16
-
17
- var __defProp = Object.defineProperty;
18
- var __getOwnPropNames = Object.getOwnPropertyNames;
19
- var __esm = (fn, res) => function __init() {
20
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
21
- };
22
- var __export = (target, all) => {
23
- for (var name in all)
24
- __defProp(target, name, { get: all[name], enumerable: true });
25
- };
26
- function cn(...inputs) {
27
- return tailwindMerge.twMerge(clsx.clsx(inputs));
28
- }
29
- var init_utils = __esm({
30
- "src/lib/utils.ts"() {
31
- }
32
- });
33
-
34
- // components/ui/button.tsx
35
- var button_exports = {};
36
- __export(button_exports, {
37
- Button: () => Button2,
38
- buttonVariants: () => buttonVariants
39
- });
40
- function Button2({
41
- className,
42
- variant,
43
- size,
44
- asChild = false,
45
- ...props
46
- }) {
47
- const Comp = asChild ? reactSlot.Slot : "button";
48
- return /* @__PURE__ */ jsxRuntime.jsx(
49
- Comp,
50
- {
51
- "data-slot": "button",
52
- className: cn(buttonVariants({ variant, size, className })),
53
- ...props
54
- }
55
- );
56
- }
57
- var buttonVariants;
58
- var init_button = __esm({
59
- "components/ui/button.tsx"() {
60
- init_utils();
61
- buttonVariants = classVarianceAuthority.cva(
62
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
63
- {
64
- variants: {
65
- variant: {
66
- default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
67
- destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
68
- outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
69
- secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
70
- ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
71
- link: "text-primary underline-offset-4 hover:underline"
72
- },
73
- size: {
74
- default: "h-9 px-4 py-2 has-[>svg]:px-3",
75
- sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
76
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
77
- icon: "size-9"
78
- }
79
- },
80
- defaultVariants: {
81
- variant: "default",
82
- size: "default"
83
- }
84
- }
85
- );
86
- }
87
- });
5
+ var jsxRuntime = require('react/jsx-runtime');
88
6
 
89
7
  // src/core/reducer.ts
90
8
  function cloneNode(node) {
91
9
  return {
92
10
  ...node,
93
- props: node.props ? { ...node.props } : null,
94
- bindings: node.bindings ? { ...node.bindings } : null,
95
- events: node.events ? { ...node.events } : null,
96
- children: node.children ? node.children.map((child) => cloneNode(child)) : null
11
+ props: node.props ? { ...node.props } : void 0,
12
+ bindings: node.bindings ? { ...node.bindings } : void 0,
13
+ events: node.events ? { ...node.events } : void 0,
14
+ children: node.children?.map((child) => cloneNode(child))
97
15
  };
98
16
  }
99
17
  function findNodeById(tree, nodeId) {
100
- if (!tree)
101
- return void 0;
102
- if (tree.id === nodeId)
103
- return tree;
18
+ if (!tree) return void 0;
19
+ if (tree.id === nodeId) return tree;
104
20
  if (tree.children) {
105
21
  for (const child of tree.children) {
106
22
  const found = findNodeById(child, nodeId);
107
- if (found)
108
- return found;
23
+ if (found) return found;
109
24
  }
110
25
  }
111
26
  return void 0;
@@ -120,15 +35,13 @@ function updateNodeById(tree, nodeId, updater) {
120
35
  if (node.children) {
121
36
  for (const child of node.children) {
122
37
  const path2 = findPath(child, id, newPath);
123
- if (path2)
124
- return path2;
38
+ if (path2) return path2;
125
39
  }
126
40
  }
127
41
  return null;
128
42
  }
129
43
  const path = findPath(result, nodeId);
130
- if (!path)
131
- return result;
44
+ if (!path) return result;
132
45
  const nodeToUpdate = path[path.length - 1];
133
46
  const updatedNode = updater(nodeToUpdate);
134
47
  if (path.length === 1) {
@@ -137,14 +50,18 @@ function updateNodeById(tree, nodeId, updater) {
137
50
  const parent = path[path.length - 2];
138
51
  const updatedParent = {
139
52
  ...parent,
140
- children: parent.children ? parent.children.map(
53
+ children: parent.children?.map(
141
54
  (child) => child.id === nodeId ? updatedNode : child
142
- ) : null
55
+ )
143
56
  };
144
57
  if (path.length === 2) {
145
58
  return updatedParent;
146
59
  }
147
- return updateNodeById(result, parent.id, () => updatedParent);
60
+ return updateNodeById(
61
+ result,
62
+ parent.id,
63
+ () => updatedParent
64
+ );
148
65
  }
149
66
  function replaceNodeById(tree, nodeId, newNode) {
150
67
  return updateNodeById(tree, nodeId, () => newNode);
@@ -171,8 +88,7 @@ function removeNodeById(tree, nodeId) {
171
88
  }
172
89
  for (const child of node.children) {
173
90
  const parent2 = findParent(child, id);
174
- if (parent2)
175
- return parent2;
91
+ if (parent2) return parent2;
176
92
  }
177
93
  }
178
94
  return null;
@@ -182,11 +98,10 @@ function removeNodeById(tree, nodeId) {
182
98
  throw new Error("Cannot remove root node");
183
99
  }
184
100
  const parent = findParent(result, nodeId);
185
- if (!parent)
186
- return result;
101
+ if (!parent) return result;
187
102
  return updateNodeById(result, parent.id, (node) => ({
188
103
  ...node,
189
- children: node.children ? node.children.filter((child) => child.id !== nodeId) : null
104
+ children: node.children?.filter((child) => child.id !== nodeId)
190
105
  }));
191
106
  }
192
107
  function uiReducer(state, action) {
@@ -203,7 +118,7 @@ function uiReducer(state, action) {
203
118
  ...state,
204
119
  layout: action.node,
205
120
  loading: false,
206
- error: null
121
+ error: void 0
207
122
  };
208
123
  }
209
124
  case "PARTIAL_UPDATE": {
@@ -212,7 +127,7 @@ function uiReducer(state, action) {
212
127
  ...state,
213
128
  layout: action.node,
214
129
  loading: false,
215
- error: null
130
+ error: void 0
216
131
  };
217
132
  }
218
133
  if (action.nodeId === "root" || action.nodeId === state.layout.id) {
@@ -220,23 +135,19 @@ function uiReducer(state, action) {
220
135
  ...state,
221
136
  layout: action.node,
222
137
  loading: false,
223
- error: null
138
+ error: void 0
224
139
  };
225
140
  }
226
141
  return {
227
142
  ...state,
228
143
  layout: replaceNodeById(state.layout, action.nodeId, action.node),
229
144
  loading: false,
230
- error: null
145
+ error: void 0
231
146
  };
232
147
  }
233
148
  case "ADD_NODE": {
234
149
  if (!state.layout) {
235
- return {
236
- ...state,
237
- error: "Cannot add node: Layout is empty.",
238
- loading: false
239
- };
150
+ return state;
240
151
  }
241
152
  return {
242
153
  ...state,
@@ -244,41 +155,21 @@ function uiReducer(state, action) {
244
155
  state.layout,
245
156
  action.parentId,
246
157
  action.node,
247
- action.index === null ? void 0 : action.index
158
+ action.index
248
159
  ),
249
160
  loading: false,
250
- error: null
161
+ error: void 0
251
162
  };
252
163
  }
253
164
  case "REMOVE_NODE": {
254
165
  if (!state.layout) {
255
- return {
256
- ...state,
257
- error: "Cannot remove node: Layout is empty.",
258
- loading: false
259
- };
166
+ return state;
260
167
  }
261
- try {
262
- return {
263
- ...state,
264
- layout: removeNodeById(state.layout, action.nodeId),
265
- loading: false,
266
- error: null
267
- };
268
- } catch (e) {
269
- const errorMessage = e instanceof Error ? e.message : "Failed to remove node.";
270
- return {
271
- ...state,
272
- error: errorMessage,
273
- loading: false
274
- };
275
- }
276
- }
277
- case "ERROR": {
278
168
  return {
279
169
  ...state,
280
- error: action.message,
281
- loading: false
170
+ layout: removeNodeById(state.layout, action.nodeId),
171
+ loading: false,
172
+ error: void 0
282
173
  };
283
174
  }
284
175
  case "LOADING": {
@@ -287,15 +178,20 @@ function uiReducer(state, action) {
287
178
  loading: action.isLoading
288
179
  };
289
180
  }
181
+ case "ERROR": {
182
+ return {
183
+ ...state,
184
+ error: action.message,
185
+ loading: false
186
+ };
187
+ }
290
188
  default:
291
189
  return state;
292
190
  }
293
191
  }
294
192
  var initialState = {
295
- layout: null,
296
- loading: false,
297
- history: [],
298
- error: null
193
+ loading: true,
194
+ history: []
299
195
  };
300
196
 
301
197
  // src/core/action-router.ts
@@ -342,7 +238,7 @@ var ActionRouter = class {
342
238
  schema,
343
239
  goal,
344
240
  history: [event],
345
- userContext: userContext || null
241
+ userContext
346
242
  },
347
243
  prompt: `Generate a new UI for the goal: "${goal}". The user just triggered: ${event.type} on node ${event.nodeId}`
348
244
  };
@@ -391,20 +287,16 @@ var ActionRouter = class {
391
287
  ...additionalContext
392
288
  }
393
289
  };
394
- const templateValues = {
395
- goal,
396
- eventType: event.type,
397
- nodeId: event.nodeId,
398
- targetNodeId,
399
- actionType: matchingRoute.actionType,
400
- ...userContext || {},
401
- // Spread the original userContext (passed to resolveRoute)
402
- ...additionalContext
403
- // Spread additionalContext afterwards (can override userContext keys)
404
- };
405
290
  const prompt = this.processTemplate(
406
291
  matchingRoute.promptTemplate,
407
- templateValues
292
+ {
293
+ goal,
294
+ eventType: event.type,
295
+ nodeId: event.nodeId,
296
+ targetNodeId,
297
+ actionType: matchingRoute.actionType,
298
+ ...additionalContext
299
+ }
408
300
  );
409
301
  return {
410
302
  actionType: matchingRoute.actionType,
@@ -472,58 +364,27 @@ var uiEventType = zod.z.enum([
472
364
  var uiEvent = zod.z.object({
473
365
  type: uiEventType,
474
366
  nodeId: zod.z.string(),
475
- timestamp: zod.z.number().nullable(),
476
- payload: zod.z.record(zod.z.unknown()).nullable()
477
- });
478
- zod.z.enum(["AI_RESPONSE", "ERROR"]);
479
- var runtimeRecord = zod.z.record(zod.z.any()).nullable();
480
- var openAISimplifiedValue = zod.z.string().nullable();
481
- var openAIRecordSimplifiedNullable = zod.z.record(openAISimplifiedValue).nullable();
482
- var openAIEventPayloadSimplifiedNullable = zod.z.record(openAISimplifiedValue).nullable();
483
- var openAIBaseNode = zod.z.object({
484
- id: zod.z.string(),
485
- node_type: zod.z.string(),
486
- props: openAIRecordSimplifiedNullable,
487
- // Nullable record
488
- bindings: openAIRecordSimplifiedNullable,
489
- // Nullable record
490
- events: zod.z.record(
491
- zod.z.string(),
492
- zod.z.object({
493
- action: zod.z.string(),
494
- target: zod.z.string(),
495
- payload: openAIEventPayloadSimplifiedNullable
496
- })
497
- ).nullable(),
498
- // Entire events object is nullable
499
- children: zod.z.null()
500
- // Base children are null. When extended, it will be an array or null.
501
- });
502
- var openAINodeL4 = openAIBaseNode;
503
- var openAINodeL3 = openAIBaseNode.extend({
504
- children: zod.z.array(openAINodeL4).nullable()
367
+ timestamp: zod.z.number().optional(),
368
+ payload: zod.z.record(zod.z.any()).optional()
505
369
  });
506
- var openAINodeL2 = openAIBaseNode.extend({
507
- children: zod.z.array(openAINodeL3).nullable()
508
- });
509
- var openAIUISpec = openAIBaseNode.extend({
510
- children: zod.z.array(openAINodeL2).nullable()
511
- });
512
- var uiSpecNode = zod.z.object({
370
+ zod.z.enum([
371
+ "AI_RESPONSE",
372
+ "ERROR"
373
+ ]);
374
+ var uiSpecNode = zod.z.lazy(() => zod.z.object({
513
375
  id: zod.z.string(),
514
- node_type: zod.z.string(),
515
- props: runtimeRecord,
516
- bindings: runtimeRecord,
517
- events: zod.z.record(
518
- zod.z.string(),
519
- zod.z.object({
520
- action: zod.z.string(),
521
- target: zod.z.string(),
522
- payload: runtimeRecord
523
- })
524
- ).nullable(),
525
- children: zod.z.lazy(() => zod.z.array(uiSpecNode)).nullable()
526
- });
376
+ type: zod.z.string(),
377
+ // e.g., "ListView", "Button", "TextField"
378
+ props: zod.z.record(zod.z.any()).optional(),
379
+ bindings: zod.z.record(zod.z.any()).optional(),
380
+ // Data bindings
381
+ events: zod.z.record(zod.z.string(), zod.z.object({
382
+ action: zod.z.string(),
383
+ target: zod.z.string().optional(),
384
+ payload: zod.z.record(zod.z.any()).optional()
385
+ })).optional(),
386
+ children: zod.z.array(uiSpecNode).optional()
387
+ }));
527
388
  zod.z.discriminatedUnion("type", [
528
389
  zod.z.object({
529
390
  type: zod.z.literal("UI_EVENT"),
@@ -542,7 +403,7 @@ zod.z.discriminatedUnion("type", [
542
403
  type: zod.z.literal("ADD_NODE"),
543
404
  parentId: zod.z.string(),
544
405
  node: uiSpecNode,
545
- index: zod.z.number().nullable()
406
+ index: zod.z.number().optional()
546
407
  }),
547
408
  zod.z.object({
548
409
  type: zod.z.literal("REMOVE_NODE"),
@@ -558,16 +419,16 @@ zod.z.discriminatedUnion("type", [
558
419
  })
559
420
  ]);
560
421
  zod.z.object({
561
- layout: uiSpecNode.nullable(),
422
+ layout: uiSpecNode.optional(),
562
423
  loading: zod.z.boolean(),
563
424
  history: zod.z.array(uiEvent),
564
- error: zod.z.string().nullable()
425
+ error: zod.z.string().optional()
565
426
  });
566
427
  zod.z.object({
567
428
  schema: zod.z.record(zod.z.unknown()),
568
429
  goal: zod.z.string(),
569
- history: zod.z.array(uiEvent).nullable(),
570
- userContext: zod.z.record(zod.z.unknown()).nullable().optional()
430
+ history: zod.z.array(uiEvent).optional(),
431
+ userContext: zod.z.record(zod.z.unknown()).optional()
571
432
  });
572
433
 
573
434
  // src/core/system-events.ts
@@ -593,7 +454,7 @@ var SystemEventManager = class {
593
454
  }
594
455
  /**
595
456
  * Register a listener for a specific system event type
596
- *
457
+ *
597
458
  * @param eventType - The system event type to listen for
598
459
  * @param listener - The listener function
599
460
  * @returns Function to unregister the listener
@@ -613,7 +474,7 @@ var SystemEventManager = class {
613
474
  }
614
475
  /**
615
476
  * Emit a system event to all registered listeners
616
- *
477
+ *
617
478
  * @param event - The system event to emit
618
479
  */
619
480
  async emit(event) {
@@ -633,22 +494,14 @@ function createSystemEvent(type, data) {
633
494
  }
634
495
 
635
496
  // src/env.ts
636
- var rawApiKeyFromEnv = process.env.VITE_OPENAI_API_KEY;
637
- var defaultApiKeyLiteral = "sk-proj-literal-default-for-debug-in-env-ts";
638
- var env = {
639
- MOCK_PLANNER: process.env.VITE_MOCK_PLANNER || "1",
640
- // Simplified MOCK_PLANNER assignment
641
- NODE_ENV: process.env.VITE_NODE_ENV || "development",
642
- // Simplified NODE_ENV assignment
643
- OPENAI_API_KEY: rawApiKeyFromEnv === void 0 ? defaultApiKeyLiteral : rawApiKeyFromEnv
644
- };
497
+ ({
498
+ MOCK_PLANNER: undefined?.VITE_MOCK_PLANNER || "1",
499
+ NODE_ENV: undefined?.MODE || "development"
500
+ // Add other environment variables as needed
501
+ });
645
502
 
646
503
  // src/core/planner.ts
647
- var strictOpenAI = openai.createOpenAI({
648
- compatibility: "strict"
649
- // Required for structured outputs with OpenAI API
650
- });
651
- function buildPrompt(input, customPrompt) {
504
+ function buildPrompt(input, targetNodeId, customPrompt) {
652
505
  const { schema, goal, history, userContext } = input;
653
506
  const schemaInfo = Object.entries(schema).map(([tableName, tableSchema]) => {
654
507
  return `Table: ${tableName}
@@ -661,9 +514,6 @@ Schema: ${JSON.stringify(tableSchema)}`;
661
514
 
662
515
  User Context:
663
516
  ${JSON.stringify(userContext)}` : "";
664
- if (customPrompt) {
665
- return customPrompt;
666
- }
667
517
  return `
668
518
  You are an expert UI generator.
669
519
  Create a user interface that achieves the following goal: "${goal}"
@@ -677,10 +527,10 @@ ${recentEvents}${userContextSection}
677
527
  Generate a complete UI specification in JSON format that matches the following TypeScript type:
678
528
  type UISpecNode = {
679
529
  id: string;
680
- node_type: string;
681
- props?: Record<string, unknown>;
682
- bindings?: Record<string, unknown>;
683
- events?: Record<string, { action: string; target: string; payload?: Record<string, unknown>; }>;
530
+ type: string;
531
+ props?: Record<string, any>;
532
+ bindings?: Record<string, any>;
533
+ events?: Record<string, { action: string; target?: string; payload?: Record<string, any>; }>;
684
534
  children?: UISpecNode[];
685
535
  };
686
536
 
@@ -690,419 +540,211 @@ UI Guidance:
690
540
  3. Include navigation between related views when needed
691
541
  4. Keep the interface simple and intuitive
692
542
  5. Bind to schema data where appropriate
693
- 6. Provide event handlers for user interactions - make sure to always include both action and target properties
543
+ 6. Provide event handlers for user interactions
694
544
 
695
545
  Respond ONLY with the JSON UI specification and no other text.
696
546
  `;
697
547
  }
698
548
  function mockPlanner(input, targetNodeId, customPrompt) {
699
- if (customPrompt) {
700
- console.log("mockPlanner received customPrompt:", customPrompt);
701
- }
702
- const taskSchema = input.schema.tasks;
703
- const taskData = taskSchema?.sampleData || [
704
- {
705
- id: "1",
706
- title: "Example Task 1",
707
- description: "This is a sample task",
708
- status: "pending",
709
- priority: "medium"
710
- },
711
- {
712
- id: "2",
713
- title: "Example Task 2",
714
- description: "Another sample task",
715
- status: "completed",
716
- priority: "high"
717
- }
718
- ];
719
549
  const mockNode = {
720
550
  id: targetNodeId || "root",
721
- node_type: "Container",
722
- props: {
723
- className: "p-4 space-y-6"
724
- },
725
- bindings: null,
726
- events: null,
551
+ type: "Container",
552
+ props: { title: "Mock UI" },
727
553
  children: [
728
554
  {
729
- id: "header-1",
730
- node_type: "Header",
731
- props: {
732
- title: "Task Management Dashboard",
733
- className: "mb-4"
734
- },
735
- bindings: null,
736
- events: null,
737
- children: null
738
- },
739
- {
740
- id: "main-content",
741
- node_type: "Container",
742
- props: {
743
- className: "grid grid-cols-1 gap-6 md:grid-cols-3"
744
- },
745
- bindings: null,
746
- events: null,
747
- children: [
748
- {
749
- id: "tasks-container",
750
- node_type: "Container",
751
- props: {
752
- className: "md:col-span-2"
753
- },
754
- bindings: null,
755
- events: null,
756
- children: [
757
- {
758
- id: "list-heading",
759
- node_type: "Container",
760
- props: {
761
- className: "flex justify-between items-center mb-4"
762
- },
763
- bindings: null,
764
- events: null,
765
- children: [
766
- {
767
- id: "list-title",
768
- node_type: "Header",
769
- props: {
770
- title: "Tasks",
771
- className: "border-none p-0 m-0"
772
- },
773
- bindings: null,
774
- events: null,
775
- children: null
776
- },
777
- {
778
- id: "add-task-button",
779
- node_type: "Button",
780
- props: {
781
- label: "Add Task",
782
- variant: "default"
783
- },
784
- bindings: null,
785
- events: {
786
- onClick: {
787
- action: "ADD_TASK",
788
- target: "tasks-container",
789
- payload: {}
790
- }
791
- },
792
- children: null
793
- }
794
- ]
795
- },
796
- {
797
- id: "task-list",
798
- node_type: "ListView",
799
- props: {
800
- selectable: "true"
801
- },
802
- bindings: {
803
- items: JSON.stringify(taskData),
804
- fields: JSON.stringify([
805
- { key: "id", label: "ID" },
806
- { key: "title", label: "Title" },
807
- { key: "status", label: "Status" },
808
- { key: "priority", label: "Priority" }
809
- ])
810
- },
811
- events: {
812
- onSelect: {
813
- action: "SELECT_TASK",
814
- target: "task-detail",
815
- payload: {
816
- source: "task-list"
817
- }
818
- }
819
- },
820
- children: null
821
- }
822
- ]
823
- },
824
- {
825
- id: "task-detail",
826
- node_type: "Detail",
827
- props: {
828
- title: "Task Details",
829
- visible: "true"
830
- },
831
- bindings: {
832
- data: JSON.stringify(taskData[0]),
833
- fields: JSON.stringify([
834
- { key: "title", label: "Title", type: "heading" },
835
- { key: "description", label: "Description", type: "content" },
836
- { key: "status", label: "Status" },
837
- { key: "priority", label: "Priority" },
838
- { key: "dueDate", label: "Due Date" }
839
- ])
840
- },
841
- events: {
842
- onBack: {
843
- action: "CLOSE_DETAIL",
844
- target: "task-detail",
845
- payload: {}
846
- }
847
- },
848
- children: null
849
- }
850
- ]
555
+ id: "text-1",
556
+ type: "Text",
557
+ props: { text: "This is a mock UI for testing" }
851
558
  }
852
559
  ]
853
560
  };
854
561
  return mockNode;
855
562
  }
856
- async function callPlannerLLM(input, routeResolution) {
857
- await systemEvents.emit(
858
- createSystemEvent("PLAN_START" /* PLAN_START */, { plannerInput: input })
859
- );
860
- if (env.MOCK_PLANNER === "1" || !env.OPENAI_API_KEY) {
861
- console.warn(
862
- "Using mock planner because MOCK_PLANNER is enabled or OPENAI_API_KEY is not available"
863
- );
864
- return mockPlanner(input);
865
- }
866
- const startTime = Date.now();
867
- const prompt = routeResolution?.prompt || buildPrompt(input);
868
- await systemEvents.emit(
869
- createSystemEvent("PLAN_PROMPT_CREATED" /* PLAN_PROMPT_CREATED */, { prompt })
870
- );
871
- try {
872
- const { object: uiSpec } = await ai.generateObject({
873
- model: strictOpenAI("gpt-4o", { structuredOutputs: true }),
874
- schema: openAIUISpec,
875
- messages: [{ role: "user", content: prompt }],
876
- temperature: 0.2,
877
- maxTokens: 4e3
878
- });
879
- await systemEvents.emit(
880
- createSystemEvent("PLAN_COMPLETE" /* PLAN_COMPLETE */, {
881
- layout: uiSpec,
882
- executionTimeMs: Date.now() - startTime
883
- })
884
- );
885
- return uiSpec;
886
- } catch (error) {
887
- console.error("Error calling LLM planner:", error);
888
- await systemEvents.emit(
889
- createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
890
- error: error instanceof Error ? error : new Error(String(error))
891
- })
892
- );
893
- throw error;
894
- }
895
- }
896
- async function processEvent(event, router, schema, layout, dataContext, goal, userContext) {
897
- const routeResolution = await router.resolveRoute(
898
- event,
899
- schema,
900
- layout || null,
901
- dataContext,
902
- goal,
903
- userContext
904
- );
905
- if (!routeResolution) {
906
- throw new Error(
907
- `No route found for event type: ${event.type}, node: ${event.nodeId}`
908
- );
909
- }
910
- if (routeResolution.actionType.toString() === "NoOp") {
911
- if (!layout)
912
- throw new Error("Layout is undefined and action is NoOp");
913
- return layout;
914
- }
915
- const plannerInputForLLM = routeResolution.plannerInput;
916
- const newLayout = await callPlannerLLM(plannerInputForLLM, routeResolution);
917
- return newLayout;
918
- }
919
563
 
920
564
  // src/core/state.ts
565
+ var useChat = (config) => ({
566
+ append: async (message) => {
567
+ },
568
+ data: { content: "{}" },
569
+ isLoading: false,
570
+ error: null,
571
+ stop: () => {
572
+ }
573
+ });
921
574
  function useUIStateEngine({
922
575
  schema,
923
576
  goal,
924
577
  userContext,
925
578
  mockMode = false,
926
- planningConfig,
579
+ planningConfig = {},
927
580
  router = createDefaultRouter(),
928
581
  dataContext = {},
929
582
  enablePartialUpdates = false
930
583
  }) {
931
- if (userContext === null) {
932
- console.warn(
933
- "useUIStateEngine: userContext was explicitly set to null. This is an allowed but discouraged value. Consider using undefined if you intend to omit the user context."
934
- );
935
- }
936
- const [state, dispatch] = React.useReducer(uiReducer, initialState);
937
- const handleEvent = React.useCallback(
938
- async (event) => {
939
- dispatch({ type: "UI_EVENT", event });
940
- dispatch({ type: "LOADING", isLoading: true });
941
- try {
942
- let resolvedNode;
943
- let actionTypeForDispatch = "FULL_REFRESH" /* FULL_REFRESH */;
944
- let targetNodeIdForDispatch = "root";
945
- if (enablePartialUpdates) {
946
- const route = router.resolveRoute(
947
- event,
948
- schema,
949
- state.layout,
950
- dataContext,
951
- goal,
952
- userContext
953
- );
954
- if (route) {
955
- console.log("Resolved route:", route);
956
- actionTypeForDispatch = route.actionType;
957
- targetNodeIdForDispatch = route.targetNodeId;
958
- systemEvents.emit(
959
- createSystemEvent("PLAN_START" /* PLAN_START */, {
960
- plannerInput: route.plannerInput
961
- })
962
- );
963
- if (mockMode) {
964
- resolvedNode = mockPlanner(
965
- route.plannerInput,
966
- route.targetNodeId,
967
- route.prompt
968
- );
969
- } else {
970
- resolvedNode = await callPlannerLLM(route.plannerInput, route);
971
- }
972
- } else {
973
- const input = {
974
- schema,
975
- goal,
976
- history: [...state.history, event],
977
- userContext
978
- };
979
- if (mockMode) {
980
- resolvedNode = mockPlanner(input);
981
- } else {
982
- resolvedNode = await callPlannerLLM(input);
983
- }
984
- }
985
- } else {
986
- const input = {
987
- schema,
988
- goal,
989
- history: [...state.history, event],
990
- // event is already in history from UI_EVENT dispatch
991
- userContext
992
- };
993
- if (mockMode) {
994
- resolvedNode = mockPlanner(input);
995
- } else {
996
- resolvedNode = await callPlannerLLM(input);
997
- }
998
- }
999
- switch (actionTypeForDispatch) {
1000
- case "UPDATE_NODE" /* UPDATE_NODE */:
1001
- case "SHOW_DETAIL" /* SHOW_DETAIL */:
1002
- case "HIDE_DETAIL" /* HIDE_DETAIL */:
1003
- case "TOGGLE_STATE" /* TOGGLE_STATE */:
1004
- case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
1005
- case "UPDATE_FORM" /* UPDATE_FORM */:
1006
- case "NAVIGATE" /* NAVIGATE */:
1007
- dispatch({
1008
- type: "PARTIAL_UPDATE",
1009
- nodeId: targetNodeIdForDispatch,
1010
- node: resolvedNode
1011
- });
1012
- break;
1013
- case "FULL_REFRESH" /* FULL_REFRESH */:
1014
- default:
1015
- dispatch({ type: "AI_RESPONSE", node: resolvedNode });
1016
- break;
1017
- }
1018
- } catch (e) {
1019
- const errorMessage = e instanceof Error ? e.message : String(e);
1020
- dispatch({ type: "ERROR", message: errorMessage });
584
+ const [state, dispatch] = react.useReducer(uiReducer, initialState);
585
+ const { append, data, isLoading, error, stop } = useChat();
586
+ const handleEvent = react.useCallback((event) => {
587
+ dispatch({ type: "UI_EVENT", event });
588
+ if (enablePartialUpdates) {
589
+ const route = router.resolveRoute(
590
+ event,
591
+ schema,
592
+ state.layout,
593
+ dataContext,
594
+ goal,
595
+ userContext
596
+ );
597
+ if (route) {
598
+ console.log("Resolved route:", route);
1021
599
  systemEvents.emit(
1022
- createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
1023
- error: e instanceof Error ? e : new Error(String(e))
600
+ createSystemEvent("PLAN_START" /* PLAN_START */, {
601
+ plannerInput: route.plannerInput
1024
602
  })
1025
603
  );
1026
- } finally {
1027
- dispatch({ type: "LOADING", isLoading: false });
604
+ if (mockMode) {
605
+ const node = mockPlanner(route.plannerInput, route.targetNodeId, route.prompt);
606
+ switch (route.actionType) {
607
+ case "FULL_REFRESH" /* FULL_REFRESH */:
608
+ dispatch({ type: "AI_RESPONSE", node });
609
+ break;
610
+ case "UPDATE_NODE" /* UPDATE_NODE */:
611
+ case "SHOW_DETAIL" /* SHOW_DETAIL */:
612
+ case "HIDE_DETAIL" /* HIDE_DETAIL */:
613
+ case "TOGGLE_STATE" /* TOGGLE_STATE */:
614
+ case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
615
+ case "UPDATE_FORM" /* UPDATE_FORM */:
616
+ case "NAVIGATE" /* NAVIGATE */:
617
+ dispatch({
618
+ type: "PARTIAL_UPDATE",
619
+ nodeId: route.targetNodeId,
620
+ node
621
+ });
622
+ break;
623
+ }
624
+ } else {
625
+ const prompt = route.prompt;
626
+ systemEvents.emit(
627
+ createSystemEvent("PLAN_PROMPT_CREATED" /* PLAN_PROMPT_CREATED */, { prompt })
628
+ );
629
+ append({
630
+ content: prompt,
631
+ role: "user"
632
+ });
633
+ sessionStorage.setItem("currentRoute", JSON.stringify({
634
+ actionType: route.actionType,
635
+ targetNodeId: route.targetNodeId
636
+ }));
637
+ }
638
+ return;
1028
639
  }
1029
- },
1030
- [
1031
- // append, // REMOVE
1032
- goal,
640
+ }
641
+ const input = {
1033
642
  schema,
1034
- state.history,
1035
- // Keep state.history if input preparation needs it
1036
- state.layout,
1037
- // stop, // REMOVE
1038
- userContext,
1039
- router,
1040
- mockMode,
1041
- dataContext,
1042
- enablePartialUpdates,
1043
- dispatch
1044
- // Add dispatch
1045
- ]
1046
- );
1047
- React.useEffect(() => {
1048
- const initialFetch = async () => {
1049
- dispatch({ type: "LOADING", isLoading: true });
643
+ goal,
644
+ history: [...state.history, event],
645
+ userContext
646
+ };
647
+ if (mockMode) {
648
+ const node = mockPlanner();
649
+ dispatch({ type: "AI_RESPONSE", node });
650
+ } else {
651
+ const prompt = buildPrompt(input);
652
+ append({
653
+ content: prompt,
654
+ role: "user"
655
+ });
656
+ }
657
+ }, [append, goal, schema, state.history, state.layout, stop, userContext, router, mockMode, dataContext, enablePartialUpdates]);
658
+ react.useEffect(() => {
659
+ {
1050
660
  try {
1051
- const input = {
1052
- schema,
1053
- goal,
1054
- history: [],
1055
- userContext
1056
- };
1057
- let node;
1058
- if (mockMode) {
1059
- node = mockPlanner(input);
661
+ systemEvents.emit(
662
+ createSystemEvent("PLAN_RESPONSE_CHUNK" /* PLAN_RESPONSE_CHUNK */, {
663
+ chunk: data.content,
664
+ isComplete: true
665
+ })
666
+ );
667
+ const jsonMatch = data.content.match(/```(?:json)?\s*([\s\S]*?)\s*```/) || [null, data.content];
668
+ const jsonStr = jsonMatch[1].trim();
669
+ const parsedJson = JSON.parse(jsonStr);
670
+ const validatedNode = uiSpecNode.parse(parsedJson);
671
+ const routeInfoStr = sessionStorage.getItem("currentRoute");
672
+ if (routeInfoStr && enablePartialUpdates) {
673
+ try {
674
+ const routeInfo = JSON.parse(routeInfoStr);
675
+ switch (routeInfo.actionType) {
676
+ case "FULL_REFRESH" /* FULL_REFRESH */:
677
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
678
+ break;
679
+ case "UPDATE_NODE" /* UPDATE_NODE */:
680
+ case "SHOW_DETAIL" /* SHOW_DETAIL */:
681
+ case "HIDE_DETAIL" /* HIDE_DETAIL */:
682
+ case "TOGGLE_STATE" /* TOGGLE_STATE */:
683
+ case "ADD_DROPDOWN" /* ADD_DROPDOWN */:
684
+ case "UPDATE_FORM" /* UPDATE_FORM */:
685
+ case "NAVIGATE" /* NAVIGATE */:
686
+ dispatch({
687
+ type: "PARTIAL_UPDATE",
688
+ nodeId: routeInfo.targetNodeId,
689
+ node: validatedNode
690
+ });
691
+ break;
692
+ default:
693
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
694
+ }
695
+ sessionStorage.removeItem("currentRoute");
696
+ } catch (e) {
697
+ console.error("Error parsing route info:", e);
698
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
699
+ }
1060
700
  } else {
1061
- node = await callPlannerLLM(input);
701
+ dispatch({ type: "AI_RESPONSE", node: validatedNode });
1062
702
  }
1063
- dispatch({ type: "AI_RESPONSE", node });
1064
- } catch (e) {
1065
- const errorMessage = e instanceof Error ? e.message : String(e);
1066
- dispatch({ type: "ERROR", message: errorMessage });
1067
703
  systemEvents.emit(
1068
- // Also emit system event for initial load error
704
+ createSystemEvent("PLAN_COMPLETE" /* PLAN_COMPLETE */, {
705
+ layout: validatedNode,
706
+ executionTimeMs: 0
707
+ // Not available here
708
+ })
709
+ );
710
+ } catch (parseError) {
711
+ console.error("Failed to parse LLM response:", parseError);
712
+ dispatch({
713
+ type: "ERROR",
714
+ message: "Failed to parse LLM response"
715
+ });
716
+ systemEvents.emit(
1069
717
  createSystemEvent("PLAN_ERROR" /* PLAN_ERROR */, {
1070
- error: e instanceof Error ? e : new Error(String(e))
718
+ error: parseError instanceof Error ? parseError : new Error("Parse error")
1071
719
  })
1072
720
  );
1073
- } finally {
1074
- dispatch({ type: "LOADING", isLoading: false });
1075
721
  }
722
+ }
723
+ }, [data.content, error, isLoading, enablePartialUpdates]);
724
+ react.useEffect(() => {
725
+ const input = {
726
+ schema,
727
+ goal,
728
+ history: [],
729
+ userContext
1076
730
  };
1077
- initialFetch();
1078
- }, [goal, schema, userContext, mockMode, dispatch]);
731
+ if (mockMode) {
732
+ const node = mockPlanner();
733
+ dispatch({ type: "AI_RESPONSE", node });
734
+ } else {
735
+ const prompt = buildPrompt(input);
736
+ append({
737
+ content: prompt,
738
+ role: "user"
739
+ });
740
+ }
741
+ }, [append, goal, schema, userContext, mockMode]);
1079
742
  return {
1080
743
  state,
1081
744
  dispatch,
1082
745
  handleEvent
1083
746
  };
1084
747
  }
1085
- zod.z.enum([
1086
- // Layout components
1087
- "Container",
1088
- "Card",
1089
- "Header",
1090
- // Input components
1091
- "Button",
1092
- "Input",
1093
- "Select",
1094
- "Textarea",
1095
- "Checkbox",
1096
- "RadioGroup",
1097
- // Data display components
1098
- "ListView",
1099
- "Detail",
1100
- "Tabs",
1101
- "Dialog",
1102
- // Typography
1103
- "Heading",
1104
- "Text"
1105
- ]);
1106
748
  var ShimmerBlock = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-8 bg-gray-200 animate-pulse rounded" });
1107
749
  var ShimmerTable = ({ rows = 3 }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-2", children: [
1108
750
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-10 bg-gray-200 animate-pulse rounded" }),
@@ -1116,259 +758,117 @@ var ShimmerCard = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-f
1116
758
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5/6 h-4 bg-gray-200 animate-pulse rounded" })
1117
759
  ] })
1118
760
  ] });
1119
- var Container = (props) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `autoui-mock-container ${props.className || ""}`, children: props.children });
1120
- var Header = ({
1121
- title,
1122
- className
1123
- }) => /* @__PURE__ */ jsxRuntime.jsx(
1124
- "header",
1125
- {
1126
- className: `py-4 px-6 border-b border-gray-300 mb-4 bg-gray-50 dark:bg-gray-800 ${className || ""}`,
1127
- children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-gray-800 dark:text-white", children: title })
1128
- }
1129
- );
761
+ var Container = (props) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full ${props.className || ""}`, style: props.style, children: props.children });
762
+ var Header = ({ title }) => /* @__PURE__ */ jsxRuntime.jsx("header", { className: "py-4 px-6 border-b mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold", children: title }) });
1130
763
  var Button = ({ onClick, children, variant = "default" }) => /* @__PURE__ */ jsxRuntime.jsx(
1131
764
  "button",
1132
765
  {
1133
- className: `px-4 py-2 rounded-md font-medium transition-colors ${variant === "default" ? "bg-blue-600 text-white hover:bg-blue-700" : variant === "outline" ? "border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800" : "bg-red-600 text-white hover:bg-red-700"}`,
766
+ className: `px-4 py-2 rounded font-medium ${variant === "default" ? "bg-blue-600 text-white" : variant === "outline" ? "border border-gray-300 text-gray-700" : "bg-red-600 text-white"}`,
1134
767
  onClick,
1135
768
  children
1136
769
  }
1137
770
  );
1138
- var Table = ({ items = [], fields = [], onSelect, selectable }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full border border-gray-300 dark:border-gray-700 rounded-lg overflow-hidden shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full", children: [
1139
- /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-100 dark:bg-gray-800 border-b border-gray-300 dark:border-gray-700", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1140
- "th",
1141
- {
1142
- className: "px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider",
1143
- children: field.label
1144
- },
1145
- field.key
1146
- )) }) }),
1147
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
771
+ var Table = ({ items = [], fields = [], onSelect, selectable }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full", children: [
772
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider", children: field.label }, field.key)) }) }),
773
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
1148
774
  "tr",
1149
775
  {
1150
776
  onClick: () => selectable && onSelect && onSelect(item),
1151
- className: selectable ? "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800" : "",
1152
- children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx(
1153
- "td",
1154
- {
1155
- className: "px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-gray-300",
1156
- children: item[field.key] ?? ""
1157
- },
1158
- field.key
1159
- ))
777
+ className: selectable ? "cursor-pointer hover:bg-gray-50" : "",
778
+ children: fields.map((field) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-6 py-4 whitespace-nowrap text-sm text-gray-500", children: item[field.key] }, field.key))
1160
779
  },
1161
780
  index
1162
781
  )) })
1163
782
  ] }) });
1164
783
  var Detail = ({ data, fields = [], title, visible = true, onBack }) => {
1165
- if (!visible)
1166
- return null;
1167
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full border border-gray-300 dark:border-gray-700 rounded-lg p-6 space-y-4 bg-white dark:bg-gray-900 shadow-sm", children: [
1168
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center border-b border-gray-200 dark:border-gray-700 pb-3", children: [
1169
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-medium text-gray-800 dark:text-white", children: title }),
784
+ if (!visible) return null;
785
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full border rounded-lg p-6 space-y-4", children: [
786
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
787
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-medium", children: title }),
1170
788
  onBack && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", onClick: onBack, children: "Back" })
1171
789
  ] }),
1172
790
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: fields.map((field) => {
1173
791
  if (field.type === "heading") {
1174
- return /* @__PURE__ */ jsxRuntime.jsx(
1175
- "h3",
1176
- {
1177
- className: "text-xl font-semibold text-gray-800 dark:text-white",
1178
- children: data?.[field.key] ?? ""
1179
- },
1180
- field.key
1181
- );
792
+ return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-semibold", children: data?.[field.key] }, field.key);
1182
793
  }
1183
794
  if (field.type === "content") {
1184
- return /* @__PURE__ */ jsxRuntime.jsx(
1185
- "div",
1186
- {
1187
- className: "text-sm text-gray-700 dark:text-gray-300",
1188
- children: data?.[field.key] ?? ""
1189
- },
1190
- field.key
1191
- );
795
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-gray-700", children: data?.[field.key] }, field.key);
1192
796
  }
1193
- return /* @__PURE__ */ jsxRuntime.jsxs(
1194
- "div",
1195
- {
1196
- className: "flex flex-col border-b border-gray-100 dark:border-gray-800 py-2",
1197
- children: [
1198
- field.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600 dark:text-gray-400 font-medium", children: field.label }),
1199
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-800 dark:text-gray-200", children: data?.[field.key] ?? "" })
1200
- ]
1201
- },
1202
- field.key
1203
- );
797
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
798
+ field.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500", children: field.label }),
799
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: data?.[field.key] })
800
+ ] }, field.key);
1204
801
  }) })
1205
802
  ] });
1206
803
  };
1207
- var getSafeProp = (props, key, validator, defaultValue) => {
1208
- if (props && typeof props === "object" && key in props) {
1209
- const value = props[key];
1210
- if (validator(value)) {
1211
- return value;
1212
- }
1213
- }
1214
- return defaultValue;
1215
- };
1216
- var isObject = (value) => typeof value === "object" && value !== null;
1217
- var isString = (value) => typeof value === "string";
1218
- var isBoolean = (value) => typeof value === "boolean";
1219
- var isCSSProperties = (value) => isObject(value);
1220
- var isButtonVariant = (value) => isString(value) && ["default", "outline", "destructive"].includes(value);
1221
- var getSafeBinding = (bindings, key, validator, defaultValue) => {
1222
- if (bindings && typeof bindings === "object" && key in bindings) {
1223
- const value = bindings[key];
1224
- if (validator(value)) {
1225
- return value;
1226
- }
1227
- }
1228
- return defaultValue;
1229
- };
1230
- var isArrayOf = (itemValidator) => (arr) => Array.isArray(arr) && arr.every(itemValidator);
1231
- var isReactNode = (value) => {
1232
- return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || typeof value === "undefined" || typeof value === "object" && value !== null && "$$typeof" in value;
1233
- };
1234
- var isRecordWithReactNodeValues = (value) => isObject(value) && Object.values(value).every(isReactNode);
1235
- var isFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label);
1236
- var isDetailFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label) && (item.type === void 0 || isString(item.type));
1237
- var createEventHandler = (node, eventName, uiEventType2, processEvent2) => {
1238
- const eventConfig = node.events?.[uiEventType2];
1239
- if (!processEvent2 || !eventConfig)
1240
- return void 0;
1241
- return (eventPayload) => {
1242
- const fullEvent = {
1243
- type: uiEventType2,
1244
- nodeId: node.id,
1245
- timestamp: Date.now(),
1246
- payload: {
1247
- ...eventConfig.payload || {},
1248
- ...eventPayload || {}
1249
- }
1250
- };
1251
- processEvent2(fullEvent);
804
+ var createEventHandler = (node, eventName) => {
805
+ const eventConfig = node.events?.[eventName];
806
+ if (!eventConfig) return void 0;
807
+ return () => {
808
+ console.log(`Event triggered: ${eventName} on node ${node.id}`, {
809
+ action: eventConfig.action,
810
+ target: eventConfig.target,
811
+ payload: eventConfig.payload
812
+ });
1252
813
  };
1253
814
  };
1254
815
  var adapterMap = {
1255
- Container: (node, processEvent2) => /* @__PURE__ */ jsxRuntime.jsx(
1256
- Container,
816
+ Container: (node) => /* @__PURE__ */ jsxRuntime.jsx(Container, { style: node.props?.style, className: node.props?.className, children: node.children?.map((child) => renderNode(child)) }),
817
+ Header: (node) => /* @__PURE__ */ jsxRuntime.jsx(Header, { title: node.props?.title || "Untitled" }),
818
+ Button: (node) => /* @__PURE__ */ jsxRuntime.jsx(
819
+ Button,
1257
820
  {
1258
- style: getSafeProp(node.props, "style", isCSSProperties, {}),
1259
- className: getSafeProp(node.props, "className", isString, ""),
1260
- children: node.children?.map((child) => renderNode(child, processEvent2))
821
+ variant: node.props?.variant,
822
+ onClick: createEventHandler(node, "onClick"),
823
+ children: node.props?.label || "Button"
1261
824
  }
1262
825
  ),
1263
- Header: (node) => /* @__PURE__ */ jsxRuntime.jsx(
1264
- Header,
826
+ ListView: (node) => /* @__PURE__ */ jsxRuntime.jsx(
827
+ Table,
1265
828
  {
1266
- title: getSafeProp(node.props, "title", isString, "Untitled"),
1267
- className: getSafeProp(node.props, "className", isString, "")
829
+ items: node.bindings?.items || [],
830
+ fields: node.bindings?.fields || [],
831
+ selectable: node.props?.selectable,
832
+ onSelect: createEventHandler(node, "onSelect")
1268
833
  }
1269
834
  ),
1270
- Button: (node, processEvent2) => /* @__PURE__ */ jsxRuntime.jsx(
1271
- Button,
835
+ Detail: (node) => /* @__PURE__ */ jsxRuntime.jsx(
836
+ Detail,
1272
837
  {
1273
- variant: getSafeProp(node.props, "variant", isButtonVariant, "default"),
1274
- onClick: createEventHandler(node, "onClick", "CLICK", processEvent2),
1275
- children: getSafeProp(node.props, "label", isString, "Button")
838
+ data: node.bindings?.data,
839
+ fields: node.bindings?.fields || [],
840
+ title: node.props?.title,
841
+ visible: node.props?.visible !== false,
842
+ onBack: createEventHandler(node, "onBack")
1276
843
  }
1277
- ),
1278
- ListView: (node, processEvent2) => {
1279
- const items = getSafeBinding(
1280
- node.bindings,
1281
- "items",
1282
- isArrayOf(isRecordWithReactNodeValues),
1283
- []
1284
- );
1285
- const fields = getSafeBinding(
1286
- node.bindings,
1287
- "fields",
1288
- isArrayOf(isFieldObject),
1289
- []
1290
- );
1291
- const selectable = getSafeProp(node.props, "selectable", isBoolean, false);
1292
- return /* @__PURE__ */ jsxRuntime.jsx(
1293
- Table,
1294
- {
1295
- items,
1296
- fields,
1297
- selectable,
1298
- onSelect: (item) => {
1299
- const handler = createEventHandler(
1300
- node,
1301
- "onSelect",
1302
- "CLICK",
1303
- processEvent2
1304
- );
1305
- if (handler) {
1306
- handler({ selectedItem: item });
1307
- }
1308
- }
1309
- }
1310
- );
1311
- },
1312
- Detail: (node, processEvent2) => {
1313
- const data = getSafeBinding(
1314
- node.bindings,
1315
- "data",
1316
- isRecordWithReactNodeValues,
1317
- {}
1318
- );
1319
- const fields = getSafeBinding(
1320
- node.bindings,
1321
- "fields",
1322
- isArrayOf(isDetailFieldObject),
1323
- []
1324
- );
1325
- const title = getSafeProp(node.props, "title", isString, "");
1326
- const visible = getSafeProp(node.props, "visible", isBoolean, true);
1327
- return /* @__PURE__ */ jsxRuntime.jsx(
1328
- Detail,
1329
- {
1330
- data,
1331
- fields,
1332
- title,
1333
- visible,
1334
- onBack: createEventHandler(node, "onBack", "CLICK", processEvent2)
1335
- }
1336
- );
1337
- }
844
+ )
1338
845
  };
1339
- function renderNode(node, processEvent2) {
1340
- const mappedComponent = adapterMap[node.node_type];
1341
- if (mappedComponent) {
1342
- return mappedComponent(node, processEvent2);
846
+ function renderNode(node) {
847
+ const Component = adapterMap[node.type];
848
+ if (Component) {
849
+ return Component(node);
1343
850
  }
1344
- console.warn(`Unknown node type: ${node.node_type}`);
1345
- return React__default.default.createElement(
1346
- Container,
1347
- {},
1348
- `Unknown node type: ${node.node_type}`
1349
- );
851
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 border border-red-300 rounded", children: [
852
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-red-500", children: [
853
+ "Unsupported component: ",
854
+ node.type
855
+ ] }),
856
+ node.children?.map((child) => renderNode(child))
857
+ ] });
1350
858
  }
1351
- var renderedNodesCache = /* @__PURE__ */ new Map();
1352
- var MAX_CACHE_SIZE = 10;
1353
- var CACHE_TTL = 5e3;
1354
- async function renderNode2(node, adapter = "shadcn", processEvent2) {
859
+ async function renderNode2(node, adapter = "shadcn") {
1355
860
  const startTime = Date.now();
1356
- const nodeId = node.id;
1357
- const cachedItem = renderedNodesCache.get(nodeId);
1358
- if (cachedItem && startTime - cachedItem.timestamp < CACHE_TTL) {
1359
- return cachedItem.element;
1360
- }
1361
861
  await systemEvents.emit(
1362
862
  createSystemEvent("RENDER_START" /* RENDER_START */, { layout: node })
1363
863
  );
1364
864
  let result;
1365
865
  switch (adapter) {
1366
866
  case "shadcn":
1367
- result = renderNode(node, processEvent2);
867
+ result = renderNode(node);
1368
868
  break;
1369
869
  default:
1370
870
  console.warn(`Unsupported adapter: ${adapter}, falling back to shadcn`);
1371
- result = renderNode(node, processEvent2);
871
+ result = renderNode(node);
1372
872
  }
1373
873
  await systemEvents.emit(
1374
874
  createSystemEvent("RENDER_COMPLETE" /* RENDER_COMPLETE */, {
@@ -1376,23 +876,13 @@ async function renderNode2(node, adapter = "shadcn", processEvent2) {
1376
876
  renderTimeMs: Date.now() - startTime
1377
877
  })
1378
878
  );
1379
- renderedNodesCache.set(nodeId, {
1380
- element: result,
1381
- timestamp: startTime
1382
- });
1383
- if (renderedNodesCache.size > MAX_CACHE_SIZE) {
1384
- const oldestKey = [...renderedNodesCache.entries()].sort(
1385
- ([, a], [, b]) => a.timestamp - b.timestamp
1386
- )[0][0];
1387
- renderedNodesCache.delete(oldestKey);
1388
- }
1389
879
  return result;
1390
880
  }
1391
881
  function renderShimmer(node, adapter = "shadcn") {
1392
882
  if (!node) {
1393
883
  return /* @__PURE__ */ jsxRuntime.jsx(ShimmerBlock, {});
1394
884
  }
1395
- switch (node.node_type) {
885
+ switch (node.type) {
1396
886
  case "ListView":
1397
887
  return /* @__PURE__ */ jsxRuntime.jsx(ShimmerTable, { rows: 3 });
1398
888
  case "Detail":
@@ -1405,16 +895,6 @@ function renderShimmer(node, adapter = "shadcn") {
1405
895
  }
1406
896
 
1407
897
  // src/core/bindings.ts
1408
- var bindingsCache = /* @__PURE__ */ new Map();
1409
- var MAX_CACHE_SIZE2 = 50;
1410
- var CACHE_TTL2 = 2e3;
1411
- var nodeCacheTimestamps = /* @__PURE__ */ new Map();
1412
- function hashDataContext(context) {
1413
- return JSON.stringify(context);
1414
- }
1415
- function createCacheKey(nodeId, context) {
1416
- return `${nodeId}:${hashDataContext(context)}`;
1417
- }
1418
898
  function getValueByPath(context, path) {
1419
899
  const parts = path.split(".");
1420
900
  let current = context;
@@ -1432,32 +912,19 @@ function getValueByPath(context, path) {
1432
912
  function setValueByPath(context, path, value) {
1433
913
  const result = { ...context };
1434
914
  const parts = path.split(".");
1435
- if (parts.length === 0)
1436
- return result;
1437
915
  let current = result;
1438
916
  for (let i = 0; i < parts.length - 1; i++) {
1439
917
  const part = parts[i];
1440
- if (typeof current !== "object" || current === null) {
1441
- console.error("setValueByPath: Cannot create path in a non-object.");
1442
- return context;
918
+ if (!(part in current) || current[part] === null || current[part] === void 0) {
919
+ current[part] = {};
1443
920
  }
1444
- const currentAsObject = current;
1445
- if (!(part in currentAsObject) || typeof currentAsObject[part] !== "object" || currentAsObject[part] === null) {
1446
- currentAsObject[part] = {};
921
+ current = current[part];
922
+ if (typeof current !== "object") {
923
+ current = {};
1447
924
  }
1448
- current = currentAsObject[part];
1449
925
  }
1450
926
  const lastPart = parts[parts.length - 1];
1451
- if (typeof current === "object" && current !== null) {
1452
- current[lastPart] = value;
1453
- } else if (parts.length === 1 && typeof result === "object" && result !== null) {
1454
- result[lastPart] = value;
1455
- } else {
1456
- console.warn(
1457
- `setValueByPath: Could not set value for path "${path}". Final segment location is not an object.`
1458
- );
1459
- return context;
1460
- }
927
+ current[lastPart] = value;
1461
928
  return result;
1462
929
  }
1463
930
  function processBinding(binding, context) {
@@ -1477,27 +944,18 @@ function processBinding(binding, context) {
1477
944
  return binding;
1478
945
  }
1479
946
  async function resolveBindings(node, context) {
1480
- const currentTime = Date.now();
1481
- const cacheKey = createCacheKey(node.id, context);
1482
- const cachedNode = bindingsCache.get(cacheKey);
1483
- const cachedTimestamp = nodeCacheTimestamps.get(cacheKey);
1484
- if (cachedNode && cachedTimestamp && currentTime - cachedTimestamp < CACHE_TTL2) {
1485
- return cachedNode;
1486
- }
1487
947
  await systemEvents.emit(
1488
- createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, {
1489
- layout: node
1490
- })
948
+ createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, { layout: node })
1491
949
  );
1492
950
  const result = {
1493
951
  ...node,
1494
- props: node.props ? { ...node.props } : null,
1495
- events: node.events ? { ...node.events } : null
952
+ props: node.props ? { ...node.props } : void 0,
953
+ events: node.events ? { ...node.events } : void 0
1496
954
  };
1497
955
  if (node.bindings) {
1498
956
  for (const [key, binding] of Object.entries(node.bindings)) {
1499
957
  const value = processBinding(binding, context);
1500
- if (value !== void 0 && typeof value === "string") {
958
+ if (value !== void 0) {
1501
959
  if (!result.props) {
1502
960
  result.props = {};
1503
961
  }
@@ -1506,9 +964,7 @@ async function resolveBindings(node, context) {
1506
964
  }
1507
965
  }
1508
966
  if (node.children) {
1509
- result.children = await Promise.all(
1510
- node.children.map((child) => resolveBindings(child, context))
1511
- );
967
+ result.children = await Promise.all(node.children.map((child) => resolveBindings(child, context)));
1512
968
  }
1513
969
  await systemEvents.emit(
1514
970
  createSystemEvent("BINDING_RESOLUTION_COMPLETE" /* BINDING_RESOLUTION_COMPLETE */, {
@@ -1516,17 +972,6 @@ async function resolveBindings(node, context) {
1516
972
  resolvedLayout: result
1517
973
  })
1518
974
  );
1519
- bindingsCache.set(cacheKey, result);
1520
- nodeCacheTimestamps.set(cacheKey, currentTime);
1521
- if (bindingsCache.size > MAX_CACHE_SIZE2) {
1522
- const entries = [...nodeCacheTimestamps.entries()];
1523
- if (entries.length > 0) {
1524
- entries.sort((a, b) => a[1] - b[1]);
1525
- const oldestKey = entries[0][0];
1526
- bindingsCache.delete(oldestKey);
1527
- nodeCacheTimestamps.delete(oldestKey);
1528
- }
1529
- }
1530
975
  return result;
1531
976
  }
1532
977
  function executeAction(action, targetId, payload, context = {}, layoutTree) {
@@ -1549,6 +994,7 @@ function executeAction(action, targetId, payload, context = {}, layoutTree) {
1549
994
  }
1550
995
  break;
1551
996
  }
997
+ // Add more actions as needed
1552
998
  default:
1553
999
  console.warn(`Unknown action: ${action}`);
1554
1000
  }
@@ -1562,7 +1008,7 @@ var EventManager = class {
1562
1008
  }
1563
1009
  /**
1564
1010
  * Register a hook for specific event types
1565
- *
1011
+ *
1566
1012
  * @param eventTypes - Event types to register for, or 'all' for all events
1567
1013
  * @param hook - Hook function to execute
1568
1014
  * @returns Unregister function
@@ -1595,7 +1041,7 @@ var EventManager = class {
1595
1041
  }
1596
1042
  /**
1597
1043
  * Process an event through all registered hooks
1598
- *
1044
+ *
1599
1045
  * @param event - The UI event to process
1600
1046
  * @returns Whether the default action should proceed
1601
1047
  */
@@ -1616,15 +1062,13 @@ var EventManager = class {
1616
1062
  if (this.hooks.all) {
1617
1063
  for (const hook of this.hooks.all) {
1618
1064
  await hook(context);
1619
- if (propagationStopped)
1620
- break;
1065
+ if (propagationStopped) break;
1621
1066
  }
1622
1067
  }
1623
1068
  if (!propagationStopped && this.hooks[event.type]) {
1624
1069
  for (const hook of this.hooks[event.type] || []) {
1625
1070
  await hook(context);
1626
- if (propagationStopped)
1627
- break;
1071
+ if (propagationStopped) break;
1628
1072
  }
1629
1073
  }
1630
1074
  return !defaultPrevented;
@@ -1641,20 +1085,6 @@ function createEventHook(eventTypes, hook, options) {
1641
1085
  }
1642
1086
  };
1643
1087
  }
1644
-
1645
- // src/core/component-detection.ts
1646
- function areShadcnComponentsAvailable() {
1647
- try {
1648
- init_button();
1649
- return true;
1650
- } catch (error) {
1651
- return false;
1652
- }
1653
- }
1654
- function getMissingComponentsMessage() {
1655
- return `Missing required shadcn components. Please run:
1656
- > npm run setup-shadcn`;
1657
- }
1658
1088
  var AutoUI = ({
1659
1089
  schema,
1660
1090
  goal,
@@ -1665,32 +1095,23 @@ var AutoUI = ({
1665
1095
  systemEventHooks,
1666
1096
  debugMode = false,
1667
1097
  mockMode = true,
1098
+ databaseConfig,
1668
1099
  planningConfig,
1669
1100
  integration = {},
1670
1101
  scope = {},
1671
1102
  enablePartialUpdates = false
1672
1103
  }) => {
1673
- const [schemaAdapterInstance] = React.useState(null);
1674
- const [dataContext, setDataContext] = React.useState({});
1675
- const [componentsAvailable, setComponentsAvailable] = React.useState(true);
1104
+ const [schemaAdapterInstance, setSchemaAdapterInstance] = react.useState(null);
1105
+ const [dataContext, setDataContext] = react.useState({});
1676
1106
  const effectiveSchema = schema;
1677
1107
  const scopedGoal = goal;
1678
- React.useEffect(() => {
1679
- if (componentAdapter === "shadcn") {
1680
- setComponentsAvailable(areShadcnComponentsAvailable());
1681
- }
1682
- }, [componentAdapter]);
1683
- React.useEffect(() => {
1108
+ react.useEffect(() => {
1684
1109
  const unregisters = [];
1685
1110
  if (systemEventHooks) {
1686
1111
  Object.entries(systemEventHooks).forEach(([eventType, hooks]) => {
1687
- if (!hooks)
1688
- return;
1112
+ if (!hooks) return;
1689
1113
  hooks.forEach((hook) => {
1690
- const unregister = systemEvents.on(
1691
- eventType,
1692
- hook
1693
- );
1114
+ const unregister = systemEvents.on(eventType, hook);
1694
1115
  unregisters.push(unregister);
1695
1116
  });
1696
1117
  });
@@ -1699,9 +1120,7 @@ var AutoUI = ({
1699
1120
  const debugHook = (event) => {
1700
1121
  console.debug(`[AutoUI Debug] System Event:`, event);
1701
1122
  };
1702
- Object.values(SystemEventType).filter(
1703
- (eventType) => eventType !== "RENDER_START" /* RENDER_START */ && eventType !== "BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */
1704
- ).forEach((eventType) => {
1123
+ Object.values(SystemEventType).forEach((eventType) => {
1705
1124
  const unregister = systemEvents.on(eventType, debugHook);
1706
1125
  unregisters.push(unregister);
1707
1126
  });
@@ -1710,7 +1129,7 @@ var AutoUI = ({
1710
1129
  unregisters.forEach((unregister) => unregister());
1711
1130
  };
1712
1131
  }, [systemEventHooks, debugMode]);
1713
- React.useEffect(() => {
1132
+ react.useEffect(() => {
1714
1133
  const initializeDataContext = async () => {
1715
1134
  let initialData = {};
1716
1135
  if (schemaAdapterInstance) {
@@ -1742,143 +1161,86 @@ var AutoUI = ({
1742
1161
  dataContext,
1743
1162
  enablePartialUpdates
1744
1163
  });
1745
- const eventManagerRef = React.useRef(new EventManager());
1746
- React.useEffect(() => {
1747
- if (!eventHooks)
1748
- return;
1164
+ const eventManagerRef = react.useRef(new EventManager());
1165
+ react.useEffect(() => {
1166
+ if (!eventHooks) return;
1749
1167
  const unregisters = [];
1750
1168
  if (eventHooks.all) {
1751
- const unregister = eventManagerRef.current.register(
1752
- "all",
1753
- async (ctx) => {
1754
- for (const hook of eventHooks.all || []) {
1755
- await hook(ctx);
1756
- if (ctx.isPropagationStopped())
1757
- break;
1758
- }
1169
+ const unregister = eventManagerRef.current.register("all", async (ctx) => {
1170
+ for (const hook of eventHooks.all || []) {
1171
+ await hook(ctx);
1172
+ if (ctx.isPropagationStopped()) break;
1759
1173
  }
1760
- );
1174
+ });
1761
1175
  unregisters.push(unregister);
1762
1176
  }
1763
1177
  Object.entries(eventHooks).forEach(([type, hooks]) => {
1764
- if (type === "all" || !hooks)
1765
- return;
1766
- const unregister = eventManagerRef.current.register(
1767
- [type],
1768
- async (ctx) => {
1769
- for (const hook of hooks) {
1770
- await hook(ctx);
1771
- if (ctx.isPropagationStopped())
1772
- break;
1773
- }
1178
+ if (type === "all" || !hooks) return;
1179
+ const unregister = eventManagerRef.current.register([type], async (ctx) => {
1180
+ for (const hook of hooks) {
1181
+ await hook(ctx);
1182
+ if (ctx.isPropagationStopped()) break;
1774
1183
  }
1775
- );
1184
+ });
1776
1185
  unregisters.push(unregister);
1777
1186
  });
1778
1187
  return () => {
1779
1188
  unregisters.forEach((unregister) => unregister());
1780
1189
  };
1781
1190
  }, [eventHooks]);
1782
- const processEvent2 = React.useCallback(
1783
- async (event) => {
1784
- const shouldProceed = await eventManagerRef.current.processEvent(event);
1785
- if (onEvent) {
1786
- onEvent(event);
1787
- }
1788
- if (!shouldProceed) {
1789
- console.info("Event processing was prevented by hooks", event);
1790
- return;
1791
- }
1792
- const findNodeById2 = (node, id) => {
1793
- if (!node)
1794
- return void 0;
1795
- if (node.id === id)
1796
- return node;
1797
- if (node.children) {
1798
- for (const child of node.children) {
1799
- const found = findNodeById2(child, id);
1800
- if (found)
1801
- return found;
1802
- }
1191
+ react.useCallback(async (event) => {
1192
+ const shouldProceed = await eventManagerRef.current.processEvent(event);
1193
+ if (onEvent) {
1194
+ onEvent(event);
1195
+ }
1196
+ if (!shouldProceed) {
1197
+ console.info("Event processing was prevented by hooks", event);
1198
+ return;
1199
+ }
1200
+ const findNodeById2 = (node, id) => {
1201
+ if (!node) return void 0;
1202
+ if (node.id === id) return node;
1203
+ if (node.children) {
1204
+ for (const child of node.children) {
1205
+ const found = findNodeById2(child, id);
1206
+ if (found) return found;
1803
1207
  }
1804
- return void 0;
1805
- };
1806
- const sourceNode = findNodeById2(state.layout, event.nodeId);
1807
- if (!sourceNode) {
1808
- console.warn(`Node not found for event: ${event.nodeId}`);
1809
- handleEvent(event);
1810
- return;
1811
- }
1812
- const eventConfig = sourceNode.events?.[event.type];
1813
- if (!eventConfig) {
1814
- console.warn(
1815
- `No event config found for ${event.type} on node ${event.nodeId}`
1816
- );
1817
- handleEvent(event);
1818
- return;
1819
1208
  }
1820
- const newContext = executeAction(
1821
- eventConfig.action,
1822
- eventConfig.target || "",
1823
- // Provide empty string as fallback if target is null
1824
- {
1825
- ...eventConfig.payload,
1826
- ...event.payload
1827
- },
1828
- dataContext,
1829
- state.layout || void 0
1830
- );
1831
- setDataContext(newContext);
1209
+ return void 0;
1210
+ };
1211
+ const sourceNode = findNodeById2(state.layout, event.nodeId);
1212
+ if (!sourceNode) {
1213
+ console.warn(`Node not found for event: ${event.nodeId}`);
1832
1214
  handleEvent(event);
1833
- },
1834
- [dataContext, handleEvent, onEvent, state.layout]
1835
- );
1836
- const [resolvedLayout, setResolvedLayout] = React.useState(
1837
- void 0
1838
- );
1839
- const [renderedNode, setRenderedNode] = React.useState(
1840
- null
1841
- );
1842
- const resolveLayoutBindings = React.useCallback(async () => {
1215
+ return;
1216
+ }
1217
+ const eventConfig = sourceNode.events?.[event.type];
1218
+ if (!eventConfig) {
1219
+ console.warn(`No event config found for ${event.type} on node ${event.nodeId}`);
1220
+ handleEvent(event);
1221
+ return;
1222
+ }
1223
+ const newContext = executeAction(
1224
+ eventConfig.action,
1225
+ eventConfig.target,
1226
+ {
1227
+ ...eventConfig.payload,
1228
+ ...event.payload
1229
+ },
1230
+ dataContext,
1231
+ state.layout
1232
+ );
1233
+ setDataContext(newContext);
1234
+ handleEvent(event);
1235
+ }, [dataContext, handleEvent, onEvent, state.layout]);
1236
+ const [resolvedLayout, setResolvedLayout] = react.useState(void 0);
1237
+ react.useEffect(() => {
1843
1238
  if (state.layout) {
1844
- try {
1845
- const resolved = await resolveBindings(state.layout, dataContext);
1846
- setResolvedLayout(resolved);
1847
- } catch (err) {
1848
- console.error("Error resolving bindings:", err);
1849
- }
1239
+ resolveBindings(state.layout, dataContext).then((resolved) => setResolvedLayout(resolved)).catch((err) => console.error("Error resolving bindings:", err));
1850
1240
  } else {
1851
1241
  setResolvedLayout(void 0);
1852
1242
  }
1853
1243
  }, [state.layout, dataContext]);
1854
- React.useEffect(() => {
1855
- resolveLayoutBindings();
1856
- }, [resolveLayoutBindings]);
1857
- const renderResolvedLayout = React.useCallback(async () => {
1858
- if (resolvedLayout) {
1859
- try {
1860
- const rendered = await renderNode2(
1861
- resolvedLayout,
1862
- componentAdapter,
1863
- processEvent2
1864
- );
1865
- setRenderedNode(rendered);
1866
- } catch (err) {
1867
- console.error("Error rendering node:", err);
1868
- }
1869
- } else {
1870
- setRenderedNode(null);
1871
- }
1872
- }, [resolvedLayout, componentAdapter, processEvent2]);
1873
- React.useEffect(() => {
1874
- renderResolvedLayout();
1875
- }, [renderResolvedLayout]);
1876
- if (!componentsAvailable) {
1877
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "autoui-error p-4 border border-red-300 bg-red-50 text-red-700 rounded", children: [
1878
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: "Component Library Not Found" }),
1879
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm whitespace-pre-line", children: getMissingComponentsMessage() })
1880
- ] });
1881
- }
1882
1244
  return /* @__PURE__ */ jsxRuntime.jsxs(
1883
1245
  "div",
1884
1246
  {
@@ -1895,24 +1257,11 @@ var AutoUI = ({
1895
1257
  ] }) })
1896
1258
  ) : (
1897
1259
  // Render the resolved layout
1898
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "autoui-content", children: renderedNode })
1260
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "autoui-content", children: renderNode2(resolvedLayout, componentAdapter) })
1899
1261
  ),
1900
- state.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "autoui-error p-4 border border-red-300 bg-red-50 dark:bg-red-900 dark:border-red-700 rounded-md", children: [
1901
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "autoui-error-title text-lg font-semibold text-red-700 dark:text-red-300 mb-2", children: "Error generating UI" }),
1902
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "autoui-error-message text-sm text-red-600 dark:text-red-300", children: state.error }),
1903
- !mockMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 text-sm text-red-600 dark:text-red-300", children: [
1904
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "This could be because:" }),
1905
- /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "list-disc pl-5 mt-2", children: [
1906
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Your OpenAI API key is missing or invalid" }),
1907
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "The OpenAI service is experiencing issues" }),
1908
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: "Your API rate limit has been exceeded" })
1909
- ] }),
1910
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2", children: [
1911
- "Try setting ",
1912
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "mockMode=true" }),
1913
- " to use sample data instead."
1914
- ] })
1915
- ] })
1262
+ state.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "autoui-error", children: [
1263
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "autoui-error-title", children: "Error generating UI" }),
1264
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "autoui-error-message", children: state.error })
1916
1265
  ] })
1917
1266
  ]
1918
1267
  }
@@ -1965,26 +1314,26 @@ var DrizzleAdapter = class {
1965
1314
  */
1966
1315
  mapDataType(drizzleType) {
1967
1316
  const typeMap = {
1968
- serial: "integer",
1969
- integer: "integer",
1970
- int: "integer",
1971
- bigint: "integer",
1972
- text: "string",
1973
- varchar: "string",
1974
- char: "string",
1975
- boolean: "boolean",
1976
- bool: "boolean",
1977
- timestamp: "datetime",
1978
- timestamptz: "datetime",
1979
- date: "date",
1980
- time: "time",
1981
- json: "object",
1982
- jsonb: "object",
1983
- real: "number",
1984
- float: "number",
1985
- double: "number",
1986
- numeric: "number",
1987
- decimal: "number"
1317
+ "serial": "integer",
1318
+ "integer": "integer",
1319
+ "int": "integer",
1320
+ "bigint": "integer",
1321
+ "text": "string",
1322
+ "varchar": "string",
1323
+ "char": "string",
1324
+ "boolean": "boolean",
1325
+ "bool": "boolean",
1326
+ "timestamp": "datetime",
1327
+ "timestamptz": "datetime",
1328
+ "date": "date",
1329
+ "time": "time",
1330
+ "json": "object",
1331
+ "jsonb": "object",
1332
+ "real": "number",
1333
+ "float": "number",
1334
+ "double": "number",
1335
+ "numeric": "number",
1336
+ "decimal": "number"
1988
1337
  };
1989
1338
  return typeMap[drizzleType.toLowerCase()] || "string";
1990
1339
  }
@@ -2027,92 +1376,10 @@ function createSchemaAdapter(options) {
2027
1376
  case "custom":
2028
1377
  return options.adapter;
2029
1378
  default:
2030
- throw new Error(
2031
- `Unsupported schema adapter type: ${options.type}`
2032
- );
1379
+ throw new Error(`Unsupported schema adapter type: ${options.type}`);
2033
1380
  }
2034
1381
  }
2035
1382
 
2036
- // src/ai-utils.ts
2037
- var generateComponent = async (prompt) => {
2038
- console.warn(
2039
- "generateComponent is a placeholder and will be implemented in a future version"
2040
- );
2041
- return `<div>Generated Component for: ${prompt}</div>`;
2042
- };
2043
- var generateUIDescription = async (prompt) => {
2044
- console.warn(
2045
- "generateUIDescription is a placeholder and will be implemented in a future version"
2046
- );
2047
- return `Description for ${prompt}`;
2048
- };
2049
- var generateUIComponent = async (prompt) => {
2050
- console.warn(
2051
- "generateUIComponent is a placeholder and will be implemented in a future version"
2052
- );
2053
- return `<div>Generated UI Component for: ${prompt}</div>`;
2054
- };
2055
- function usePlanner(options) {
2056
- const { goal, schema, userContext, router: customRouter } = options;
2057
- const [layout, setLayout] = React.useState(void 0);
2058
- const [loading, setLoading] = React.useState(false);
2059
- const [error, setError] = React.useState(null);
2060
- const router = customRouter || createDefaultRouter();
2061
- const dataContext = {};
2062
- const generateInitialLayout = React.useCallback(async () => {
2063
- setLoading(true);
2064
- setError(null);
2065
- try {
2066
- const plannerInput2 = {
2067
- schema,
2068
- goal,
2069
- userContext: userContext || null,
2070
- history: null
2071
- };
2072
- const generatedLayout = await callPlannerLLM(plannerInput2);
2073
- setLayout(generatedLayout);
2074
- } catch (err) {
2075
- setError(err instanceof Error ? err : new Error(String(err)));
2076
- } finally {
2077
- setLoading(false);
2078
- }
2079
- }, [schema, goal, userContext]);
2080
- const handleEvent = React.useCallback(
2081
- async (event) => {
2082
- if (!layout) {
2083
- setError(new Error("Cannot handle event - no layout exists"));
2084
- return;
2085
- }
2086
- setLoading(true);
2087
- setError(null);
2088
- try {
2089
- const updatedLayout = await processEvent(
2090
- event,
2091
- router,
2092
- schema,
2093
- layout,
2094
- dataContext,
2095
- goal,
2096
- userContext
2097
- );
2098
- setLayout(updatedLayout);
2099
- } catch (err) {
2100
- setError(err instanceof Error ? err : new Error(String(err)));
2101
- } finally {
2102
- setLoading(false);
2103
- }
2104
- },
2105
- [layout, router, schema, dataContext, goal, userContext]
2106
- );
2107
- return {
2108
- layout,
2109
- loading,
2110
- error,
2111
- handleEvent,
2112
- generateInitialLayout
2113
- };
2114
- }
2115
-
2116
1383
  exports.ActionRouter = ActionRouter;
2117
1384
  exports.ActionType = ActionType;
2118
1385
  exports.AutoUI = AutoUI;
@@ -2122,13 +1389,9 @@ exports.createDefaultRouter = createDefaultRouter;
2122
1389
  exports.createEventHook = createEventHook;
2123
1390
  exports.createSchemaAdapter = createSchemaAdapter;
2124
1391
  exports.createSystemEvent = createSystemEvent;
2125
- exports.generateComponent = generateComponent;
2126
- exports.generateUIComponent = generateUIComponent;
2127
- exports.generateUIDescription = generateUIDescription;
2128
1392
  exports.systemEvents = systemEvents;
2129
1393
  exports.uiEvent = uiEvent;
2130
1394
  exports.uiEventType = uiEventType;
2131
1395
  exports.uiSpecNode = uiSpecNode;
2132
- exports.usePlanner = usePlanner;
2133
- //# sourceMappingURL=out.js.map
1396
+ //# sourceMappingURL=index.js.map
2134
1397
  //# sourceMappingURL=index.js.map