autoui-react 0.0.4-alpha → 0.0.5-alpha

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.mjs CHANGED
@@ -7,6 +7,13 @@ import React, { useState, useEffect, useRef, useCallback, useReducer } from 'rea
7
7
  import { createOpenAI } from '@ai-sdk/openai';
8
8
  import { generateObject } from 'ai';
9
9
  import { z } from 'zod';
10
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
11
+ import { XIcon, ChevronDownIcon, CheckIcon, ChevronUpIcon, CircleIcon } from 'lucide-react';
12
+ import * as SelectPrimitive from '@radix-ui/react-select';
13
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
14
+ import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
15
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
16
+ import * as LabelPrimitive from '@radix-ui/react-label';
10
17
 
11
18
  var __defProp = Object.defineProperty;
12
19
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -293,6 +300,72 @@ var initialState = {
293
300
  };
294
301
 
295
302
  // src/core/action-router.ts
303
+ var UI_GUIDANCE_BASE = `
304
+ UI Guidance:
305
+ 1. Create a focused interface that directly addresses the goal
306
+ 2. Use appropriate UI patterns (lists, forms, details, etc.)
307
+ 3. Include navigation between related views when needed
308
+ 4. Keep the interface simple and intuitive
309
+ 5. Bind to schema data where appropriate
310
+ 6. Provide event handlers for user interactions - make sure to always include both action and target properties`;
311
+ var LIST_BINDING_GUIDANCE = `7. **CRITICAL:** For \`ListView\` or \`Table\` nodes, the \`data\` binding key **MUST** point to the *exact path* of the data *array* within the context.`;
312
+ var LIST_BINDING_EXAMPLE = `Example: If the context has \`{ tasks: { data: [...] } }\`, the binding **MUST** be \`{ "bindings": { "data": "tasks.data" } }\`. If the context has \`{ userList: [...] }\`, the binding **MUST** be \`{ "bindings": { "data": "userList" } }\`. **NEVER** bind to the parent object containing the array (e.g., DO NOT USE \`{ "bindings": { "data": "tasks" } }\`).`;
313
+ var COMMON_UI_GUIDANCE = UI_GUIDANCE_BASE + "\n" + // Add a newline separator
314
+ LIST_BINDING_GUIDANCE + // Add the specific list binding rule
315
+ "\n" + // Add a newline separator
316
+ LIST_BINDING_EXAMPLE;
317
+ function processTemplate(template, values) {
318
+ return template.replace(/\${(.*?)}/g, (match, key) => {
319
+ const trimmedKey = key.trim();
320
+ return trimmedKey in values ? String(values[trimmedKey]) : match;
321
+ });
322
+ }
323
+ function buildPrompt(input, promptTemplate, templateValues) {
324
+ const { schema, goal, history, userContext } = input;
325
+ const schemaInfo = Object.entries(schema).map(([tableName, tableSchema]) => {
326
+ const schemaString = typeof tableSchema === "object" && tableSchema !== null ? JSON.stringify(tableSchema) : String(tableSchema);
327
+ return `Table: ${tableName}
328
+ Schema: ${schemaString}`;
329
+ }).join("\n\n");
330
+ const recentEvents = history && history.length > 0 ? history.slice(-5).map(
331
+ (event) => `Event: ${event.type} on node ${event.nodeId}${event.payload ? ` with payload ${JSON.stringify(event.payload)}` : ""}`
332
+ ).join("\n") : "No recent events";
333
+ const userContextSection = userContext ? `
334
+
335
+ User Context:
336
+ ${JSON.stringify(userContext)}` : "";
337
+ if (promptTemplate && templateValues) {
338
+ const fullTemplateValues = {
339
+ ...templateValues,
340
+ schemaInfo,
341
+ recentEvents,
342
+ userContextString: userContextSection.trim(),
343
+ // Use trimmed version
344
+ commonUIGuidance: COMMON_UI_GUIDANCE,
345
+ goal
346
+ // Ensure goal is always available to templates
347
+ };
348
+ return processTemplate(promptTemplate, fullTemplateValues);
349
+ }
350
+ const interactionDescription = history && history.length > 0 ? `The user's last action was: ${history[history.length - 1].type} on node ${history[history.length - 1].nodeId}` : "The user initiated the session for the goal";
351
+ return `
352
+ You are an expert UI generator.
353
+ Create a user interface that achieves the following goal: "${goal}".
354
+ ${interactionDescription}.
355
+
356
+ Available data schema:
357
+ ${schemaInfo}
358
+
359
+ Recent user interactions:
360
+ ${recentEvents}${userContextSection}
361
+
362
+ Generate a complete UI specification in JSON format that matches the following TypeScript type:
363
+ type UISpecNode = { id: string; node_type: string; props?: Record<string, unknown>; bindings?: Record<string, unknown>; events?: Record<string, { action: string; target: string; payload?: Record<string, unknown>; }>; children?: UISpecNode[]; };
364
+ ${COMMON_UI_GUIDANCE}
365
+
366
+ Respond ONLY with the JSON UI specification and no other text.
367
+ `;
368
+ }
296
369
  var ActionType = /* @__PURE__ */ ((ActionType2) => {
297
370
  ActionType2["FULL_REFRESH"] = "FULL_REFRESH";
298
371
  ActionType2["UPDATE_NODE"] = "UPDATE_NODE";
@@ -327,19 +400,39 @@ var ActionRouter = class {
327
400
  * @returns Route resolution or null if no match
328
401
  */
329
402
  resolveRoute(event, schema, layout, dataContext, goal, userContext) {
403
+ console.log(
404
+ `[ActionRouter Debug] resolveRoute called for event type: ${event.type}`
405
+ );
330
406
  const routes = this.routes[event.type] || [];
407
+ console.log(
408
+ `[ActionRouter Debug] Found ${routes.length} routes for ${event.type}`
409
+ );
331
410
  if (routes.length === 0) {
332
- return {
411
+ console.log(
412
+ `[ActionRouter Debug] No specific route found for ${event.type}, using default FULL_REFRESH.`
413
+ );
414
+ const defaultPlannerInput = {
415
+ schema,
416
+ goal,
417
+ history: [event],
418
+ userContext: userContext || null
419
+ };
420
+ const defaultPrompt = buildPrompt(
421
+ defaultPlannerInput,
422
+ void 0,
423
+ void 0
424
+ );
425
+ const defaultResolution = {
333
426
  actionType: "FULL_REFRESH" /* FULL_REFRESH */,
334
427
  targetNodeId: layout?.id || "root",
335
- plannerInput: {
336
- schema,
337
- goal,
338
- history: [event],
339
- userContext: userContext || null
340
- },
341
- prompt: `Generate a new UI for the goal: "${goal}". The user just triggered: ${event.type} on node ${event.nodeId}`
428
+ plannerInput: defaultPlannerInput,
429
+ prompt: defaultPrompt
342
430
  };
431
+ console.log(
432
+ "[ActionRouter Debug] Default Resolution:",
433
+ defaultResolution
434
+ );
435
+ return defaultResolution;
343
436
  }
344
437
  const sourceNode = layout ? findNodeById(layout, event.nodeId) : void 0;
345
438
  const nodeConfig = sourceNode?.events?.[event.type];
@@ -352,6 +445,7 @@ var ActionRouter = class {
352
445
  if (!matchingRoute) {
353
446
  matchingRoute = routes[0];
354
447
  }
448
+ console.log("[ActionRouter Debug] Matching Route Config:", matchingRoute);
355
449
  const targetNodeId = nodeConfig?.target || matchingRoute.targetNodeId || event.nodeId;
356
450
  const additionalContext = {};
357
451
  if (matchingRoute.contextKeys) {
@@ -396,16 +490,24 @@ var ActionRouter = class {
396
490
  ...additionalContext
397
491
  // Spread additionalContext afterwards (can override userContext keys)
398
492
  };
399
- const prompt = this.processTemplate(
493
+ console.log("[ActionRouter Debug] Template Values:", templateValues);
494
+ const finalPrompt = buildPrompt(
495
+ plannerInput2,
400
496
  matchingRoute.promptTemplate,
497
+ // Pass template if it exists (can be undefined)
401
498
  templateValues
499
+ // Pass templateValues (used only if promptTemplate exists)
402
500
  );
403
- return {
501
+ console.log("[ActionRouter Debug] Generated Prompt:", finalPrompt);
502
+ const finalResolution = {
404
503
  actionType: matchingRoute.actionType,
405
504
  targetNodeId,
406
505
  plannerInput: plannerInput2,
407
- prompt
506
+ prompt: finalPrompt
507
+ // Use the generated prompt
408
508
  };
509
+ console.log("[ActionRouter Debug] Final Resolution:", finalResolution);
510
+ return finalResolution;
409
511
  }
410
512
  /**
411
513
  * Process a prompt template with variables
@@ -423,8 +525,11 @@ function createDefaultRouter() {
423
525
  const router = new ActionRouter();
424
526
  router.registerRoute("CLICK", {
425
527
  actionType: "FULL_REFRESH" /* FULL_REFRESH */,
426
- targetNodeId: "root",
427
- promptTemplate: 'Generate a new UI for the goal: "${goal}". The user just clicked on node ${nodeId}'
528
+ targetNodeId: "root"
529
+ });
530
+ router.registerRoute("INIT", {
531
+ actionType: "FULL_REFRESH" /* FULL_REFRESH */,
532
+ targetNodeId: "root"
428
533
  });
429
534
  router.registerRoute("CLICK", {
430
535
  actionType: "SHOW_DETAIL" /* SHOW_DETAIL */,
@@ -454,7 +559,31 @@ function createDefaultRouter() {
454
559
  });
455
560
  return router;
456
561
  }
562
+ var componentType = z.enum([
563
+ // Layout components
564
+ "Container",
565
+ "Card",
566
+ "Header",
567
+ // Input components
568
+ "Button",
569
+ "Input",
570
+ "Select",
571
+ "Textarea",
572
+ "Checkbox",
573
+ "RadioGroup",
574
+ // Data display components
575
+ "ListView",
576
+ "Detail",
577
+ "Tabs",
578
+ "Dialog",
579
+ // Typography
580
+ "Heading",
581
+ "Text"
582
+ ]);
583
+
584
+ // src/schema/ui.ts
457
585
  var uiEventType = z.enum([
586
+ "INIT",
458
587
  "CLICK",
459
588
  "CHANGE",
460
589
  "SUBMIT",
@@ -475,12 +604,16 @@ var openAISimplifiedValue = z.string().nullable();
475
604
  var openAIRecordSimplifiedNullable = z.record(openAISimplifiedValue).nullable();
476
605
  var openAIEventPayloadSimplifiedNullable = z.record(openAISimplifiedValue).nullable();
477
606
  var openAIBaseNode = z.object({
478
- id: z.string(),
479
- node_type: z.string(),
480
- props: openAIRecordSimplifiedNullable,
481
- // Nullable record
482
- bindings: openAIRecordSimplifiedNullable,
483
- // Nullable record
607
+ id: z.string().describe("Unique identifier for the UI node."),
608
+ node_type: componentType.describe(
609
+ "The type of UI component (e.g., Container, Text, Button, ListView)."
610
+ ),
611
+ props: openAIRecordSimplifiedNullable.describe(
612
+ 'Component-specific properties (attributes). Values should be strings or null. E.g., for Header use { "title": "My Title" }; for Text use { "text": "My Text" }.'
613
+ ),
614
+ bindings: openAIRecordSimplifiedNullable.describe(
615
+ 'Data bindings map context paths to component props. Values are paths (e.g., "user.name") or templates (e.g., "{{item.title}}"). **CRITICAL for ListView/Table:** the `data` key MUST point to the *exact array path* (e.g., { "data": "tasks.data" } or { "data": "userList" }), NOT the parent object.'
616
+ ),
484
617
  events: z.record(
485
618
  z.string(),
486
619
  z.object({
@@ -628,67 +761,22 @@ function createSystemEvent(type, data) {
628
761
 
629
762
  // src/env.ts
630
763
  var rawApiKeyFromEnv = process.env.VITE_OPENAI_API_KEY;
631
- var defaultApiKeyLiteral = "sk-proj-literal-default-for-debug-in-env-ts";
632
764
  var env = {
633
- MOCK_PLANNER: process.env.VITE_MOCK_PLANNER || "1",
765
+ MOCK_PLANNER: process.env.VITE_MOCK_PLANNER || "0",
634
766
  // Simplified MOCK_PLANNER assignment
635
- NODE_ENV: process.env.VITE_NODE_ENV || "development",
767
+ NODE_ENV: process.env.VITE_NODE_ENV || "production",
636
768
  // Simplified NODE_ENV assignment
637
- OPENAI_API_KEY: rawApiKeyFromEnv === void 0 ? defaultApiKeyLiteral : rawApiKeyFromEnv
769
+ OPENAI_API_KEY: rawApiKeyFromEnv || ""
638
770
  };
639
771
 
640
772
  // src/core/planner.ts
641
- var strictOpenAI = createOpenAI({
642
- compatibility: "strict"
643
- // Required for structured outputs with OpenAI API
644
- });
645
- function buildPrompt(input, customPrompt) {
646
- const { schema, goal, history, userContext } = input;
647
- const schemaInfo = Object.entries(schema).map(([tableName, tableSchema]) => {
648
- return `Table: ${tableName}
649
- Schema: ${JSON.stringify(tableSchema)}`;
650
- }).join("\n\n");
651
- const recentEvents = history?.slice(-5).map(
652
- (event) => `Event: ${event.type} on node ${event.nodeId}${event.payload ? ` with payload ${JSON.stringify(event.payload)}` : ""}`
653
- ).join("\n") || "No recent events";
654
- const userContextSection = userContext ? `
655
-
656
- User Context:
657
- ${JSON.stringify(userContext)}` : "";
658
- if (customPrompt) {
659
- return customPrompt;
660
- }
661
- return `
662
- You are an expert UI generator.
663
- Create a user interface that achieves the following goal: "${goal}"
664
-
665
- Available data schema:
666
- ${schemaInfo}
667
-
668
- Recent user interactions:
669
- ${recentEvents}${userContextSection}
670
-
671
- Generate a complete UI specification in JSON format that matches the following TypeScript type:
672
- type UISpecNode = {
673
- id: string;
674
- node_type: string;
675
- props?: Record<string, unknown>;
676
- bindings?: Record<string, unknown>;
677
- events?: Record<string, { action: string; target: string; payload?: Record<string, unknown>; }>;
678
- children?: UISpecNode[];
773
+ var getOpenAIClient = (apiKey) => {
774
+ return createOpenAI({
775
+ apiKey,
776
+ // Use the provided key directly
777
+ compatibility: "strict"
778
+ });
679
779
  };
680
-
681
- UI Guidance:
682
- 1. Create a focused interface that directly addresses the goal
683
- 2. Use appropriate UI patterns (lists, forms, details, etc.)
684
- 3. Include navigation between related views when needed
685
- 4. Keep the interface simple and intuitive
686
- 5. Bind to schema data where appropriate
687
- 6. Provide event handlers for user interactions - make sure to always include both action and target properties
688
-
689
- Respond ONLY with the JSON UI specification and no other text.
690
- `;
691
- }
692
780
  function mockPlanner(input, targetNodeId, customPrompt) {
693
781
  if (customPrompt) {
694
782
  console.log("mockPlanner received customPrompt:", customPrompt);
@@ -794,7 +882,7 @@ function mockPlanner(input, targetNodeId, customPrompt) {
794
882
  selectable: "true"
795
883
  },
796
884
  bindings: {
797
- items: JSON.stringify(taskData),
885
+ data: "tasks.data",
798
886
  fields: JSON.stringify([
799
887
  { key: "id", label: "ID" },
800
888
  { key: "title", label: "Title" },
@@ -847,24 +935,35 @@ function mockPlanner(input, targetNodeId, customPrompt) {
847
935
  };
848
936
  return mockNode;
849
937
  }
850
- async function callPlannerLLM(input, routeResolution) {
938
+ async function callPlannerLLM(input, openaiApiKey, routeResolution) {
851
939
  await systemEvents.emit(
852
940
  createSystemEvent("PLAN_START" /* PLAN_START */, { plannerInput: input })
853
941
  );
854
- if (env.MOCK_PLANNER === "1" || !env.OPENAI_API_KEY) {
942
+ if (env.MOCK_PLANNER === "1") {
855
943
  console.warn(
856
- "Using mock planner because MOCK_PLANNER is enabled or OPENAI_API_KEY is not available"
944
+ `Using mock planner because MOCK_PLANNER environment variable is set to "1".`
945
+ );
946
+ return mockPlanner(input);
947
+ }
948
+ if (!openaiApiKey) {
949
+ console.warn(
950
+ `OpenAI API key was not provided to callPlannerLLM. Falling back to mock planner.`
857
951
  );
858
952
  return mockPlanner(input);
859
953
  }
860
954
  const startTime = Date.now();
861
- const prompt = routeResolution?.prompt || buildPrompt(input);
955
+ const prompt = routeResolution?.prompt;
956
+ if (!prompt) {
957
+ throw new Error("ActionRouter did not provide a prompt to callPlannerLLM.");
958
+ }
862
959
  await systemEvents.emit(
863
960
  createSystemEvent("PLAN_PROMPT_CREATED" /* PLAN_PROMPT_CREATED */, { prompt })
864
961
  );
865
962
  try {
866
963
  const { object: uiSpec } = await generateObject({
867
- model: strictOpenAI("gpt-4o", { structuredOutputs: true }),
964
+ model: getOpenAIClient(openaiApiKey)("gpt-4o", {
965
+ structuredOutputs: true
966
+ }),
868
967
  schema: openAIUISpec,
869
968
  messages: [{ role: "user", content: prompt }],
870
969
  temperature: 0.2,
@@ -887,7 +986,7 @@ async function callPlannerLLM(input, routeResolution) {
887
986
  throw error;
888
987
  }
889
988
  }
890
- async function processEvent(event, router, schema, layout, dataContext, goal, userContext) {
989
+ async function processEvent(event, router, schema, layout, dataContext, goal, userContext, openaiApiKey) {
891
990
  const routeResolution = await router.resolveRoute(
892
991
  event,
893
992
  schema,
@@ -907,7 +1006,11 @@ async function processEvent(event, router, schema, layout, dataContext, goal, us
907
1006
  return layout;
908
1007
  }
909
1008
  const plannerInputForLLM = routeResolution.plannerInput;
910
- const newLayout = await callPlannerLLM(plannerInputForLLM, routeResolution);
1009
+ const newLayout = await callPlannerLLM(
1010
+ plannerInputForLLM,
1011
+ openaiApiKey || "",
1012
+ routeResolution
1013
+ );
911
1014
  return newLayout;
912
1015
  }
913
1016
 
@@ -915,6 +1018,7 @@ async function processEvent(event, router, schema, layout, dataContext, goal, us
915
1018
  function useUIStateEngine({
916
1019
  schema,
917
1020
  goal,
1021
+ openaiApiKey,
918
1022
  userContext,
919
1023
  mockMode = false,
920
1024
  planningConfig,
@@ -961,7 +1065,11 @@ function useUIStateEngine({
961
1065
  route.prompt
962
1066
  );
963
1067
  } else {
964
- resolvedNode = await callPlannerLLM(route.plannerInput, route);
1068
+ resolvedNode = await callPlannerLLM(
1069
+ route.plannerInput,
1070
+ openaiApiKey || "",
1071
+ route
1072
+ );
965
1073
  }
966
1074
  } else {
967
1075
  const input = {
@@ -973,7 +1081,11 @@ function useUIStateEngine({
973
1081
  if (mockMode) {
974
1082
  resolvedNode = mockPlanner(input);
975
1083
  } else {
976
- resolvedNode = await callPlannerLLM(input);
1084
+ resolvedNode = await callPlannerLLM(
1085
+ input,
1086
+ openaiApiKey || "",
1087
+ void 0
1088
+ );
977
1089
  }
978
1090
  }
979
1091
  } else {
@@ -987,7 +1099,11 @@ function useUIStateEngine({
987
1099
  if (mockMode) {
988
1100
  resolvedNode = mockPlanner(input);
989
1101
  } else {
990
- resolvedNode = await callPlannerLLM(input);
1102
+ resolvedNode = await callPlannerLLM(
1103
+ input,
1104
+ openaiApiKey || "",
1105
+ void 0
1106
+ );
991
1107
  }
992
1108
  }
993
1109
  switch (actionTypeForDispatch) {
@@ -1033,6 +1149,7 @@ function useUIStateEngine({
1033
1149
  router,
1034
1150
  mockMode,
1035
1151
  dataContext,
1152
+ openaiApiKey,
1036
1153
  enablePartialUpdates,
1037
1154
  dispatch
1038
1155
  // Add dispatch
@@ -1046,13 +1163,48 @@ function useUIStateEngine({
1046
1163
  schema,
1047
1164
  goal,
1048
1165
  history: [],
1166
+ // Initial history is empty
1049
1167
  userContext
1050
1168
  };
1051
1169
  let node;
1052
1170
  if (mockMode) {
1053
1171
  node = mockPlanner(input);
1054
1172
  } else {
1055
- node = await callPlannerLLM(input);
1173
+ const initEvent = {
1174
+ type: "INIT",
1175
+ // Assuming "INIT" is your initial event type
1176
+ nodeId: "system",
1177
+ // Or some other appropriate initial nodeId
1178
+ timestamp: Date.now(),
1179
+ payload: null
1180
+ };
1181
+ const route = router.resolveRoute(
1182
+ initEvent,
1183
+ schema,
1184
+ null,
1185
+ // No existing layout on initial fetch
1186
+ dataContext,
1187
+ goal,
1188
+ userContext
1189
+ );
1190
+ if (!route || !route.prompt) {
1191
+ console.error(
1192
+ "[UIStateEngine] Initial fetch: Failed to resolve route or get prompt for INIT event."
1193
+ );
1194
+ throw new Error("Failed to initialize UI due to routing error.");
1195
+ }
1196
+ systemEvents.emit(
1197
+ createSystemEvent("PLAN_START" /* PLAN_START */, {
1198
+ plannerInput: route.plannerInput
1199
+ })
1200
+ );
1201
+ node = await callPlannerLLM(
1202
+ route.plannerInput,
1203
+ // Use plannerInput from the resolved route
1204
+ openaiApiKey || "",
1205
+ route
1206
+ // Pass the entire route object
1207
+ );
1056
1208
  }
1057
1209
  dispatch({ type: "AI_RESPONSE", node });
1058
1210
  } catch (e) {
@@ -1069,34 +1221,456 @@ function useUIStateEngine({
1069
1221
  }
1070
1222
  };
1071
1223
  initialFetch();
1072
- }, [goal, schema, userContext, mockMode, dispatch]);
1224
+ }, [goal, schema, userContext, mockMode, dispatch, openaiApiKey]);
1073
1225
  return {
1074
1226
  state,
1075
1227
  dispatch,
1076
1228
  handleEvent
1077
1229
  };
1078
1230
  }
1079
- z.enum([
1080
- // Layout components
1081
- "Container",
1082
- "Card",
1083
- "Header",
1084
- // Input components
1085
- "Button",
1086
- "Input",
1087
- "Select",
1088
- "Textarea",
1089
- "Checkbox",
1090
- "RadioGroup",
1091
- // Data display components
1092
- "ListView",
1093
- "Detail",
1094
- "Tabs",
1095
- "Dialog",
1096
- // Typography
1097
- "Heading",
1098
- "Text"
1099
- ]);
1231
+
1232
+ // src/adapters/shadcn.tsx
1233
+ init_utils();
1234
+
1235
+ // components/ui/dialog.tsx
1236
+ init_utils();
1237
+ function Dialog({
1238
+ ...props
1239
+ }) {
1240
+ return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
1241
+ }
1242
+ function DialogPortal({
1243
+ ...props
1244
+ }) {
1245
+ return /* @__PURE__ */ jsx(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
1246
+ }
1247
+ function DialogOverlay({
1248
+ className,
1249
+ ...props
1250
+ }) {
1251
+ return /* @__PURE__ */ jsx(
1252
+ DialogPrimitive.Overlay,
1253
+ {
1254
+ "data-slot": "dialog-overlay",
1255
+ className: cn(
1256
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
1257
+ className
1258
+ ),
1259
+ ...props
1260
+ }
1261
+ );
1262
+ }
1263
+ function DialogContent({
1264
+ className,
1265
+ children,
1266
+ ...props
1267
+ }) {
1268
+ return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
1269
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
1270
+ /* @__PURE__ */ jsxs(
1271
+ DialogPrimitive.Content,
1272
+ {
1273
+ "data-slot": "dialog-content",
1274
+ className: cn(
1275
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
1276
+ className
1277
+ ),
1278
+ ...props,
1279
+ children: [
1280
+ children,
1281
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", children: [
1282
+ /* @__PURE__ */ jsx(XIcon, {}),
1283
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
1284
+ ] })
1285
+ ]
1286
+ }
1287
+ )
1288
+ ] });
1289
+ }
1290
+ function DialogHeader({ className, ...props }) {
1291
+ return /* @__PURE__ */ jsx(
1292
+ "div",
1293
+ {
1294
+ "data-slot": "dialog-header",
1295
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
1296
+ ...props
1297
+ }
1298
+ );
1299
+ }
1300
+ function DialogTitle({
1301
+ className,
1302
+ ...props
1303
+ }) {
1304
+ return /* @__PURE__ */ jsx(
1305
+ DialogPrimitive.Title,
1306
+ {
1307
+ "data-slot": "dialog-title",
1308
+ className: cn("text-lg leading-none font-semibold", className),
1309
+ ...props
1310
+ }
1311
+ );
1312
+ }
1313
+ function DialogDescription({
1314
+ className,
1315
+ ...props
1316
+ }) {
1317
+ return /* @__PURE__ */ jsx(
1318
+ DialogPrimitive.Description,
1319
+ {
1320
+ "data-slot": "dialog-description",
1321
+ className: cn("text-muted-foreground text-sm", className),
1322
+ ...props
1323
+ }
1324
+ );
1325
+ }
1326
+
1327
+ // components/ui/card.tsx
1328
+ init_utils();
1329
+ function Card({ className, ...props }) {
1330
+ return /* @__PURE__ */ jsx(
1331
+ "div",
1332
+ {
1333
+ "data-slot": "card",
1334
+ className: cn(
1335
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
1336
+ className
1337
+ ),
1338
+ ...props
1339
+ }
1340
+ );
1341
+ }
1342
+ function CardContent({ className, ...props }) {
1343
+ return /* @__PURE__ */ jsx(
1344
+ "div",
1345
+ {
1346
+ "data-slot": "card-content",
1347
+ className: cn("px-6", className),
1348
+ ...props
1349
+ }
1350
+ );
1351
+ }
1352
+
1353
+ // components/ui/input.tsx
1354
+ init_utils();
1355
+ function Input({ className, type, ...props }) {
1356
+ return /* @__PURE__ */ jsx(
1357
+ "input",
1358
+ {
1359
+ type,
1360
+ "data-slot": "input",
1361
+ className: cn(
1362
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1363
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1364
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1365
+ className
1366
+ ),
1367
+ ...props
1368
+ }
1369
+ );
1370
+ }
1371
+
1372
+ // components/ui/textarea.tsx
1373
+ init_utils();
1374
+ function Textarea({ className, ...props }) {
1375
+ return /* @__PURE__ */ jsx(
1376
+ "textarea",
1377
+ {
1378
+ "data-slot": "textarea",
1379
+ className: cn(
1380
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1381
+ className
1382
+ ),
1383
+ ...props
1384
+ }
1385
+ );
1386
+ }
1387
+
1388
+ // components/ui/select.tsx
1389
+ init_utils();
1390
+ function Select({
1391
+ ...props
1392
+ }) {
1393
+ return /* @__PURE__ */ jsx(SelectPrimitive.Root, { "data-slot": "select", ...props });
1394
+ }
1395
+ function SelectValue({
1396
+ ...props
1397
+ }) {
1398
+ return /* @__PURE__ */ jsx(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
1399
+ }
1400
+ function SelectTrigger({
1401
+ className,
1402
+ size = "default",
1403
+ children,
1404
+ ...props
1405
+ }) {
1406
+ return /* @__PURE__ */ jsxs(
1407
+ SelectPrimitive.Trigger,
1408
+ {
1409
+ "data-slot": "select-trigger",
1410
+ "data-size": size,
1411
+ className: cn(
1412
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1413
+ className
1414
+ ),
1415
+ ...props,
1416
+ children: [
1417
+ children,
1418
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4 opacity-50" }) })
1419
+ ]
1420
+ }
1421
+ );
1422
+ }
1423
+ function SelectContent({
1424
+ className,
1425
+ children,
1426
+ position = "popper",
1427
+ ...props
1428
+ }) {
1429
+ return /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
1430
+ SelectPrimitive.Content,
1431
+ {
1432
+ "data-slot": "select-content",
1433
+ className: cn(
1434
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
1435
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1436
+ className
1437
+ ),
1438
+ position,
1439
+ ...props,
1440
+ children: [
1441
+ /* @__PURE__ */ jsx(SelectScrollUpButton, {}),
1442
+ /* @__PURE__ */ jsx(
1443
+ SelectPrimitive.Viewport,
1444
+ {
1445
+ className: cn(
1446
+ "p-1",
1447
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
1448
+ ),
1449
+ children
1450
+ }
1451
+ ),
1452
+ /* @__PURE__ */ jsx(SelectScrollDownButton, {})
1453
+ ]
1454
+ }
1455
+ ) });
1456
+ }
1457
+ function SelectItem({
1458
+ className,
1459
+ children,
1460
+ ...props
1461
+ }) {
1462
+ return /* @__PURE__ */ jsxs(
1463
+ SelectPrimitive.Item,
1464
+ {
1465
+ "data-slot": "select-item",
1466
+ className: cn(
1467
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
1468
+ className
1469
+ ),
1470
+ ...props,
1471
+ children: [
1472
+ /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }) }) }),
1473
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
1474
+ ]
1475
+ }
1476
+ );
1477
+ }
1478
+ function SelectScrollUpButton({
1479
+ className,
1480
+ ...props
1481
+ }) {
1482
+ return /* @__PURE__ */ jsx(
1483
+ SelectPrimitive.ScrollUpButton,
1484
+ {
1485
+ "data-slot": "select-scroll-up-button",
1486
+ className: cn(
1487
+ "flex cursor-default items-center justify-center py-1",
1488
+ className
1489
+ ),
1490
+ ...props,
1491
+ children: /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-4" })
1492
+ }
1493
+ );
1494
+ }
1495
+ function SelectScrollDownButton({
1496
+ className,
1497
+ ...props
1498
+ }) {
1499
+ return /* @__PURE__ */ jsx(
1500
+ SelectPrimitive.ScrollDownButton,
1501
+ {
1502
+ "data-slot": "select-scroll-down-button",
1503
+ className: cn(
1504
+ "flex cursor-default items-center justify-center py-1",
1505
+ className
1506
+ ),
1507
+ ...props,
1508
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-4" })
1509
+ }
1510
+ );
1511
+ }
1512
+
1513
+ // components/ui/checkbox.tsx
1514
+ init_utils();
1515
+ function Checkbox({
1516
+ className,
1517
+ ...props
1518
+ }) {
1519
+ return /* @__PURE__ */ jsx(
1520
+ CheckboxPrimitive.Root,
1521
+ {
1522
+ "data-slot": "checkbox",
1523
+ className: cn(
1524
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1525
+ className
1526
+ ),
1527
+ ...props,
1528
+ children: /* @__PURE__ */ jsx(
1529
+ CheckboxPrimitive.Indicator,
1530
+ {
1531
+ "data-slot": "checkbox-indicator",
1532
+ className: "flex items-center justify-center text-current transition-none",
1533
+ children: /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5" })
1534
+ }
1535
+ )
1536
+ }
1537
+ );
1538
+ }
1539
+
1540
+ // components/ui/radio-group.tsx
1541
+ init_utils();
1542
+ function RadioGroup({
1543
+ className,
1544
+ ...props
1545
+ }) {
1546
+ return /* @__PURE__ */ jsx(
1547
+ RadioGroupPrimitive.Root,
1548
+ {
1549
+ "data-slot": "radio-group",
1550
+ className: cn("grid gap-3", className),
1551
+ ...props
1552
+ }
1553
+ );
1554
+ }
1555
+ function RadioGroupItem({
1556
+ className,
1557
+ ...props
1558
+ }) {
1559
+ return /* @__PURE__ */ jsx(
1560
+ RadioGroupPrimitive.Item,
1561
+ {
1562
+ "data-slot": "radio-group-item",
1563
+ className: cn(
1564
+ "border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
1565
+ className
1566
+ ),
1567
+ ...props,
1568
+ children: /* @__PURE__ */ jsx(
1569
+ RadioGroupPrimitive.Indicator,
1570
+ {
1571
+ "data-slot": "radio-group-indicator",
1572
+ className: "relative flex items-center justify-center",
1573
+ children: /* @__PURE__ */ jsx(CircleIcon, { className: "fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" })
1574
+ }
1575
+ )
1576
+ }
1577
+ );
1578
+ }
1579
+
1580
+ // components/ui/tabs.tsx
1581
+ init_utils();
1582
+ function Tabs({
1583
+ className,
1584
+ ...props
1585
+ }) {
1586
+ return /* @__PURE__ */ jsx(
1587
+ TabsPrimitive.Root,
1588
+ {
1589
+ "data-slot": "tabs",
1590
+ className: cn("flex flex-col gap-2", className),
1591
+ ...props
1592
+ }
1593
+ );
1594
+ }
1595
+ function TabsList({
1596
+ className,
1597
+ ...props
1598
+ }) {
1599
+ return /* @__PURE__ */ jsx(
1600
+ TabsPrimitive.List,
1601
+ {
1602
+ "data-slot": "tabs-list",
1603
+ className: cn(
1604
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
1605
+ className
1606
+ ),
1607
+ ...props
1608
+ }
1609
+ );
1610
+ }
1611
+ function TabsTrigger({
1612
+ className,
1613
+ ...props
1614
+ }) {
1615
+ return /* @__PURE__ */ jsx(
1616
+ TabsPrimitive.Trigger,
1617
+ {
1618
+ "data-slot": "tabs-trigger",
1619
+ className: cn(
1620
+ "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1621
+ className
1622
+ ),
1623
+ ...props
1624
+ }
1625
+ );
1626
+ }
1627
+ function TabsContent({
1628
+ className,
1629
+ ...props
1630
+ }) {
1631
+ return /* @__PURE__ */ jsx(
1632
+ TabsPrimitive.Content,
1633
+ {
1634
+ "data-slot": "tabs-content",
1635
+ className: cn("flex-1 outline-none", className),
1636
+ ...props
1637
+ }
1638
+ );
1639
+ }
1640
+
1641
+ // components/ui/label.tsx
1642
+ init_utils();
1643
+ function Label2({
1644
+ className,
1645
+ ...props
1646
+ }) {
1647
+ return /* @__PURE__ */ jsx(
1648
+ LabelPrimitive.Root,
1649
+ {
1650
+ "data-slot": "label",
1651
+ className: cn(
1652
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
1653
+ className
1654
+ ),
1655
+ ...props
1656
+ }
1657
+ );
1658
+ }
1659
+ var parseStyleString = (styleString) => {
1660
+ if (typeof styleString !== "string") {
1661
+ return typeof styleString === "object" ? styleString : {};
1662
+ }
1663
+ const style = {};
1664
+ styleString.split(";").forEach((declaration) => {
1665
+ const [property, value] = declaration.split(":");
1666
+ if (property && value) {
1667
+ const camelCasedProperty = property.trim().replace(/-([a-z])/g, (g) => g[1].toUpperCase());
1668
+ style[camelCasedProperty] = value.trim();
1669
+ }
1670
+ });
1671
+ return style;
1672
+ };
1673
+ var isArrayOf = (guard) => (arr) => Array.isArray(arr) && arr.every(guard);
1100
1674
  var ShimmerBlock = () => /* @__PURE__ */ jsx("div", { className: "w-full h-8 bg-gray-200 animate-pulse rounded" });
1101
1675
  var ShimmerTable = ({ rows = 3 }) => /* @__PURE__ */ jsxs("div", { className: "w-full space-y-2", children: [
1102
1676
  /* @__PURE__ */ jsx("div", { className: "w-full h-10 bg-gray-200 animate-pulse rounded" }),
@@ -1125,36 +1699,10 @@ var Button = ({ onClick, children, variant = "default" }) => /* @__PURE__ */ jsx
1125
1699
  "button",
1126
1700
  {
1127
1701
  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"}`,
1128
- onClick,
1702
+ onClick: () => onClick?.(),
1129
1703
  children
1130
1704
  }
1131
1705
  );
1132
- var Table = ({ items = [], fields = [], onSelect, selectable }) => /* @__PURE__ */ jsx("div", { className: "w-full border border-gray-300 dark:border-gray-700 rounded-lg overflow-hidden shadow-sm", children: /* @__PURE__ */ jsxs("table", { className: "w-full", children: [
1133
- /* @__PURE__ */ jsx("thead", { className: "bg-gray-100 dark:bg-gray-800 border-b border-gray-300 dark:border-gray-700", children: /* @__PURE__ */ jsx("tr", { children: fields.map((field) => /* @__PURE__ */ jsx(
1134
- "th",
1135
- {
1136
- className: "px-6 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider",
1137
- children: field.label
1138
- },
1139
- field.key
1140
- )) }) }),
1141
- /* @__PURE__ */ jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: items.map((item, index) => /* @__PURE__ */ jsx(
1142
- "tr",
1143
- {
1144
- onClick: () => selectable && onSelect && onSelect(item),
1145
- className: selectable ? "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800" : "",
1146
- children: fields.map((field) => /* @__PURE__ */ jsx(
1147
- "td",
1148
- {
1149
- className: "px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-gray-300",
1150
- children: item[field.key] ?? ""
1151
- },
1152
- field.key
1153
- ))
1154
- },
1155
- index
1156
- )) })
1157
- ] }) });
1158
1706
  var Detail = ({ data, fields = [], title, visible = true, onBack }) => {
1159
1707
  if (!visible)
1160
1708
  return null;
@@ -1210,7 +1758,6 @@ var getSafeProp = (props, key, validator, defaultValue) => {
1210
1758
  var isObject = (value) => typeof value === "object" && value !== null;
1211
1759
  var isString = (value) => typeof value === "string";
1212
1760
  var isBoolean = (value) => typeof value === "boolean";
1213
- var isCSSProperties = (value) => isObject(value);
1214
1761
  var isButtonVariant = (value) => isString(value) && ["default", "outline", "destructive"].includes(value);
1215
1762
  var getSafeBinding = (bindings, key, validator, defaultValue) => {
1216
1763
  if (bindings && typeof bindings === "object" && key in bindings) {
@@ -1221,12 +1768,20 @@ var getSafeBinding = (bindings, key, validator, defaultValue) => {
1221
1768
  }
1222
1769
  return defaultValue;
1223
1770
  };
1224
- var isArrayOf = (itemValidator) => (arr) => Array.isArray(arr) && arr.every(itemValidator);
1225
1771
  var isReactNode = (value) => {
1226
1772
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || typeof value === "undefined" || typeof value === "object" && value !== null && "$$typeof" in value;
1227
1773
  };
1228
1774
  var isRecordWithReactNodeValues = (value) => isObject(value) && Object.values(value).every(isReactNode);
1229
- var isFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label);
1775
+ var isSelectOptionObject = (item) => isObject(item) && isString(item.value) && isString(item.label);
1776
+ var isTabObject = (item) => (
1777
+ // Allow content to be optional initially
1778
+ isObject(item) && isString(item.value) && isString(item.label) && (item.content === void 0 || isUISpecNode(item.content))
1779
+ );
1780
+ var isUISpecNode = (value) => {
1781
+ if (!isObject(value))
1782
+ return false;
1783
+ return isString(value.id) && isString(value.node_type);
1784
+ };
1230
1785
  var isDetailFieldObject = (item) => isObject(item) && isString(item.key) && isString(item.label) && (item.type === void 0 || isString(item.type));
1231
1786
  var createEventHandler = (node, eventName, uiEventType2, processEvent2) => {
1232
1787
  const eventConfig = node.events?.[uiEventType2];
@@ -1246,14 +1801,36 @@ var createEventHandler = (node, eventName, uiEventType2, processEvent2) => {
1246
1801
  };
1247
1802
  };
1248
1803
  var adapterMap = {
1249
- Container: (node, processEvent2) => /* @__PURE__ */ jsx(
1250
- Container,
1251
- {
1252
- style: getSafeProp(node.props, "style", isCSSProperties, {}),
1253
- className: getSafeProp(node.props, "className", isString, ""),
1254
- children: node.children?.map((child) => renderNode(child, processEvent2))
1255
- }
1256
- ),
1804
+ Container: (node, processEvent2) => {
1805
+ const { className, style: styleProp, key, ...restProps } = node.props || {};
1806
+ const children = node.children?.map(
1807
+ (child) => (
1808
+ // Use React.cloneElement to add the key prop to the element returned by renderNode
1809
+ React.cloneElement(renderNode(child, processEvent2), { key: child.id })
1810
+ )
1811
+ );
1812
+ const style = typeof styleProp === "string" ? parseStyleString(styleProp) : styleProp;
1813
+ return /* @__PURE__ */ jsxs(
1814
+ "div",
1815
+ {
1816
+ className: cn("autoui-container", className),
1817
+ style,
1818
+ ...restProps,
1819
+ "data-id": node.id,
1820
+ children: [
1821
+ (() => {
1822
+ console.log(
1823
+ `[Adapter Debug] Rendering Container: id=${node.id}, props=`,
1824
+ node.props
1825
+ );
1826
+ return null;
1827
+ })(),
1828
+ children
1829
+ ]
1830
+ },
1831
+ key
1832
+ );
1833
+ },
1257
1834
  Header: (node) => /* @__PURE__ */ jsx(
1258
1835
  Header,
1259
1836
  {
@@ -1270,37 +1847,28 @@ var adapterMap = {
1270
1847
  }
1271
1848
  ),
1272
1849
  ListView: (node, processEvent2) => {
1273
- const items = getSafeBinding(
1274
- node.bindings,
1275
- "items",
1276
- isArrayOf(isRecordWithReactNodeValues),
1277
- []
1850
+ const { className, style: styleProp, key, ...restProps } = node.props || {};
1851
+ const style = typeof styleProp === "string" ? parseStyleString(styleProp) : styleProp;
1852
+ console.log(
1853
+ `[Adapter Debug] Rendering ListView: id=${node.id}, props=`,
1854
+ node.props
1278
1855
  );
1279
- const fields = getSafeBinding(
1280
- node.bindings,
1281
- "fields",
1282
- isArrayOf(isFieldObject),
1283
- []
1856
+ const children = node.children?.map(
1857
+ (child) => React.cloneElement(renderNode(child, processEvent2), { key: child.id })
1284
1858
  );
1285
- const selectable = getSafeProp(node.props, "selectable", isBoolean, false);
1286
1859
  return /* @__PURE__ */ jsx(
1287
- Table,
1860
+ "div",
1288
1861
  {
1289
- items,
1290
- fields,
1291
- selectable,
1292
- onSelect: (item) => {
1293
- const handler = createEventHandler(
1294
- node,
1295
- "onSelect",
1296
- "CLICK",
1297
- processEvent2
1298
- );
1299
- if (handler) {
1300
- handler({ selectedItem: item });
1301
- }
1302
- }
1303
- }
1862
+ className: cn(
1863
+ "autoui-listview-container space-y-2",
1864
+ className
1865
+ ),
1866
+ style,
1867
+ ...restProps,
1868
+ "data-id": node.id,
1869
+ children
1870
+ },
1871
+ key
1304
1872
  );
1305
1873
  },
1306
1874
  Detail: (node, processEvent2) => {
@@ -1328,6 +1896,449 @@ var adapterMap = {
1328
1896
  onBack: createEventHandler(node, "onBack", "CLICK", processEvent2)
1329
1897
  }
1330
1898
  );
1899
+ },
1900
+ Card: (node, processEvent2) => {
1901
+ const { className, style: styleProp, key, ...restProps } = node.props || {};
1902
+ const children = node.children?.map(
1903
+ (child) => React.cloneElement(renderNode(child, processEvent2), { key: child.id })
1904
+ );
1905
+ const style = typeof styleProp === "string" ? parseStyleString(styleProp) : styleProp;
1906
+ return /* @__PURE__ */ jsx(
1907
+ Card,
1908
+ {
1909
+ className: cn("autoui-card", className),
1910
+ style,
1911
+ ...restProps,
1912
+ "data-id": node.id,
1913
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "p-0", children: [
1914
+ " ",
1915
+ children
1916
+ ] })
1917
+ },
1918
+ key
1919
+ );
1920
+ },
1921
+ Input: (node, processEvent2) => {
1922
+ const name = getSafeProp(node.props, "name", isString, "inputName");
1923
+ const label = getSafeProp(node.props, "label", isString, "");
1924
+ const value = getSafeBinding(node.bindings, "value", isString, "");
1925
+ const placeholder = getSafeProp(node.props, "placeholder", isString, "");
1926
+ const disabled = getSafeProp(node.props, "disabled", isBoolean, false);
1927
+ const className = getSafeProp(node.props, "className", isString, "");
1928
+ const handleChange = (e) => {
1929
+ const handler = createEventHandler(
1930
+ node,
1931
+ "onChange",
1932
+ "CHANGE",
1933
+ processEvent2
1934
+ );
1935
+ if (handler)
1936
+ handler({ value: e.target.value });
1937
+ };
1938
+ const handleFocus = () => {
1939
+ const handler = createEventHandler(
1940
+ node,
1941
+ "onFocus",
1942
+ "FOCUS",
1943
+ processEvent2
1944
+ );
1945
+ if (handler)
1946
+ handler({});
1947
+ };
1948
+ const handleBlur = () => {
1949
+ const handler = createEventHandler(node, "onBlur", "BLUR", processEvent2);
1950
+ if (handler)
1951
+ handler({});
1952
+ };
1953
+ return /* @__PURE__ */ jsxs("div", { className: "grid w-full max-w-sm items-center gap-1.5", children: [
1954
+ label && /* @__PURE__ */ jsx(Label2, { htmlFor: name, children: label }),
1955
+ /* @__PURE__ */ jsx(
1956
+ Input,
1957
+ {
1958
+ id: name,
1959
+ name,
1960
+ placeholder,
1961
+ disabled,
1962
+ value,
1963
+ onChange: handleChange,
1964
+ onFocus: handleFocus,
1965
+ onBlur: handleBlur,
1966
+ className
1967
+ }
1968
+ )
1969
+ ] });
1970
+ },
1971
+ Select: (node, processEvent2) => {
1972
+ const name = getSafeProp(node.props, "name", isString, "selectName");
1973
+ const label = getSafeProp(node.props, "label", isString, "");
1974
+ const placeholder = getSafeProp(
1975
+ node.props,
1976
+ "placeholder",
1977
+ isString,
1978
+ "Select..."
1979
+ );
1980
+ const disabled = getSafeProp(node.props, "disabled", isBoolean, false);
1981
+ const value = getSafeBinding(node.bindings, "value", isString, "");
1982
+ const options = getSafeBinding(
1983
+ node.bindings,
1984
+ "options",
1985
+ isArrayOf(isSelectOptionObject),
1986
+ []
1987
+ );
1988
+ const className = getSafeProp(node.props, "className", isString, "");
1989
+ const handleValueChange = (selectedValue) => {
1990
+ const handler = createEventHandler(
1991
+ node,
1992
+ "onValueChange",
1993
+ "CHANGE",
1994
+ processEvent2
1995
+ );
1996
+ if (handler)
1997
+ handler({ value: selectedValue });
1998
+ };
1999
+ return /* @__PURE__ */ jsxs(
2000
+ "div",
2001
+ {
2002
+ className: cn("grid w-full max-w-sm items-center gap-1.5", className),
2003
+ children: [
2004
+ label && /* @__PURE__ */ jsx(Label2, { htmlFor: name, children: label }),
2005
+ /* @__PURE__ */ jsxs(
2006
+ Select,
2007
+ {
2008
+ name,
2009
+ value,
2010
+ onValueChange: handleValueChange,
2011
+ disabled,
2012
+ children: [
2013
+ /* @__PURE__ */ jsx(SelectTrigger, { id: name, children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
2014
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
2015
+ ]
2016
+ }
2017
+ )
2018
+ ]
2019
+ }
2020
+ );
2021
+ },
2022
+ Textarea: (node, processEvent2) => {
2023
+ const { key, ...propsWithoutKey } = node.props || {};
2024
+ const name = getSafeProp(propsWithoutKey, "name", isString, "textareaName");
2025
+ const label = getSafeProp(propsWithoutKey, "label", isString, "");
2026
+ const placeholder = getSafeProp(
2027
+ propsWithoutKey,
2028
+ "placeholder",
2029
+ isString,
2030
+ ""
2031
+ );
2032
+ const disabled = getSafeProp(propsWithoutKey, "disabled", isBoolean, false);
2033
+ const rows = getSafeProp(
2034
+ propsWithoutKey,
2035
+ "rows",
2036
+ (v) => typeof v === "number",
2037
+ 3
2038
+ );
2039
+ const value = getSafeBinding(node.bindings, "value", isString, "");
2040
+ const className = getSafeProp(propsWithoutKey, "className", isString, "");
2041
+ const handleChange = (e) => {
2042
+ const handler = createEventHandler(
2043
+ node,
2044
+ "onChange",
2045
+ "CHANGE",
2046
+ processEvent2
2047
+ );
2048
+ if (handler)
2049
+ handler({ value: e.target.value });
2050
+ };
2051
+ const handleFocus = () => {
2052
+ const handler = createEventHandler(
2053
+ node,
2054
+ "onFocus",
2055
+ "FOCUS",
2056
+ processEvent2
2057
+ );
2058
+ if (handler)
2059
+ handler({});
2060
+ };
2061
+ const handleBlur = () => {
2062
+ const handler = createEventHandler(node, "onBlur", "BLUR", processEvent2);
2063
+ if (handler)
2064
+ handler({});
2065
+ };
2066
+ return /* @__PURE__ */ jsxs("div", { className: "grid w-full gap-1.5", children: [
2067
+ label && /* @__PURE__ */ jsx(Label2, { htmlFor: name, children: label }),
2068
+ /* @__PURE__ */ jsx(
2069
+ Textarea,
2070
+ {
2071
+ id: name,
2072
+ name,
2073
+ placeholder,
2074
+ disabled,
2075
+ rows,
2076
+ value,
2077
+ onChange: handleChange,
2078
+ onFocus: handleFocus,
2079
+ onBlur: handleBlur,
2080
+ className
2081
+ }
2082
+ )
2083
+ ] }, key);
2084
+ },
2085
+ Checkbox: (node, processEvent2) => {
2086
+ const { key, ...propsWithoutKey } = node.props || {};
2087
+ const name = getSafeProp(propsWithoutKey, "name", isString, "checkboxName");
2088
+ const label = getSafeProp(propsWithoutKey, "label", isString, "");
2089
+ const checked = getSafeBinding(node.bindings, "checked", isBoolean, false);
2090
+ const disabled = getSafeProp(propsWithoutKey, "disabled", isBoolean, false);
2091
+ const className = getSafeProp(propsWithoutKey, "className", isString, "");
2092
+ const handleCheckedChange = (isChecked) => {
2093
+ if (typeof isChecked === "boolean") {
2094
+ const handler = createEventHandler(
2095
+ node,
2096
+ "onCheckedChange",
2097
+ "CHANGE",
2098
+ processEvent2
2099
+ );
2100
+ if (handler)
2101
+ handler({ checked: isChecked });
2102
+ }
2103
+ };
2104
+ return /* @__PURE__ */ jsxs(
2105
+ "div",
2106
+ {
2107
+ className: cn("flex items-center space-x-2", className),
2108
+ children: [
2109
+ /* @__PURE__ */ jsx(
2110
+ Checkbox,
2111
+ {
2112
+ id: name,
2113
+ name,
2114
+ checked,
2115
+ disabled,
2116
+ onCheckedChange: handleCheckedChange
2117
+ }
2118
+ ),
2119
+ label && /* @__PURE__ */ jsx(Label2, { htmlFor: name, className: "cursor-pointer", children: label })
2120
+ ]
2121
+ },
2122
+ key
2123
+ );
2124
+ },
2125
+ RadioGroup: (node, processEvent2) => {
2126
+ const { key, ...propsWithoutKey } = node.props || {};
2127
+ const name = getSafeProp(
2128
+ propsWithoutKey,
2129
+ "name",
2130
+ isString,
2131
+ "radioGroupName"
2132
+ );
2133
+ const label = getSafeProp(propsWithoutKey, "label", isString, "");
2134
+ const value = getSafeBinding(node.bindings, "value", isString, "");
2135
+ const options = getSafeBinding(
2136
+ node.bindings,
2137
+ "options",
2138
+ isArrayOf(isSelectOptionObject),
2139
+ []
2140
+ );
2141
+ const disabled = getSafeProp(propsWithoutKey, "disabled", isBoolean, false);
2142
+ const className = getSafeProp(propsWithoutKey, "className", isString, "");
2143
+ const handleValueChange = (selectedValue) => {
2144
+ const handler = createEventHandler(
2145
+ node,
2146
+ "onValueChange",
2147
+ "CHANGE",
2148
+ processEvent2
2149
+ );
2150
+ if (handler)
2151
+ handler({ value: selectedValue });
2152
+ };
2153
+ return /* @__PURE__ */ jsxs(
2154
+ "div",
2155
+ {
2156
+ className: cn("grid gap-1.5", className),
2157
+ children: [
2158
+ label && /* @__PURE__ */ jsx(Label2, { className: "mb-1", children: label }),
2159
+ /* @__PURE__ */ jsx(
2160
+ RadioGroup,
2161
+ {
2162
+ name,
2163
+ value,
2164
+ onValueChange: handleValueChange,
2165
+ disabled,
2166
+ className: "flex flex-col space-y-1",
2167
+ children: options.map((option) => /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
2168
+ /* @__PURE__ */ jsx(
2169
+ RadioGroupItem,
2170
+ {
2171
+ value: option.value,
2172
+ id: `${name}-${option.value}`
2173
+ }
2174
+ ),
2175
+ /* @__PURE__ */ jsx(
2176
+ Label2,
2177
+ {
2178
+ htmlFor: `${name}-${option.value}`,
2179
+ className: "cursor-pointer",
2180
+ children: option.label
2181
+ }
2182
+ )
2183
+ ] }, option.value))
2184
+ }
2185
+ )
2186
+ ]
2187
+ },
2188
+ key
2189
+ );
2190
+ },
2191
+ Tabs: (node, processEvent2) => {
2192
+ const { key, ...propsWithoutKey } = node.props || {};
2193
+ const rawTabs = getSafeBinding(
2194
+ node.bindings,
2195
+ "tabs",
2196
+ isArrayOf(isTabObject),
2197
+ []
2198
+ );
2199
+ const defaultValue = getSafeProp(
2200
+ propsWithoutKey,
2201
+ "defaultValue",
2202
+ isString,
2203
+ rawTabs[0]?.value || ""
2204
+ );
2205
+ const className = getSafeProp(propsWithoutKey, "className", isString, "");
2206
+ const handleValueChange = (value) => {
2207
+ const handler = createEventHandler(
2208
+ node,
2209
+ "onValueChange",
2210
+ "CHANGE",
2211
+ processEvent2
2212
+ );
2213
+ if (handler)
2214
+ handler({ value });
2215
+ };
2216
+ return /* @__PURE__ */ jsxs(
2217
+ Tabs,
2218
+ {
2219
+ defaultValue,
2220
+ onValueChange: handleValueChange,
2221
+ className: cn("autoui-tabs w-full", className),
2222
+ "data-id": node.id,
2223
+ children: [
2224
+ /* @__PURE__ */ jsx(TabsList, { children: rawTabs.map((tab) => /* @__PURE__ */ jsx(TabsTrigger, { value: tab.value, children: tab.label }, tab.value)) }),
2225
+ rawTabs.map((tab) => /* @__PURE__ */ jsx(TabsContent, { value: tab.value, children: tab.content ? renderNode(tab.content, processEvent2) : null }, tab.value))
2226
+ ]
2227
+ },
2228
+ key
2229
+ );
2230
+ },
2231
+ Dialog: (node, processEvent2) => {
2232
+ const isOpen = getSafeBinding(
2233
+ node.bindings,
2234
+ "open",
2235
+ isBoolean,
2236
+ getSafeProp(node.props, "open", isBoolean, false)
2237
+ );
2238
+ const {
2239
+ title,
2240
+ description,
2241
+ className,
2242
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2243
+ style: _styleProp,
2244
+ key,
2245
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2246
+ open: _openProp,
2247
+ ...restProps
2248
+ } = node.props || {};
2249
+ const children = node.children?.map(
2250
+ (child) => React.cloneElement(renderNode(child, processEvent2), { key: child.id })
2251
+ );
2252
+ const handleOpenChange = (open) => {
2253
+ if (!open) {
2254
+ const handler = createEventHandler(
2255
+ node,
2256
+ "onClose",
2257
+ // Assumed event name in UISpec
2258
+ "CLICK",
2259
+ // Use CLICK as the event type for closing dialogs
2260
+ processEvent2
2261
+ );
2262
+ if (handler) {
2263
+ handler({});
2264
+ }
2265
+ }
2266
+ };
2267
+ console.log(
2268
+ `[Adapter Debug] Rendering Dialog: id=${node.id}, props=`,
2269
+ node.props,
2270
+ `isOpen=${isOpen}`
2271
+ );
2272
+ return /* @__PURE__ */ jsx(
2273
+ Dialog,
2274
+ {
2275
+ open: isOpen,
2276
+ onOpenChange: handleOpenChange,
2277
+ children: /* @__PURE__ */ jsxs(
2278
+ DialogContent,
2279
+ {
2280
+ className: cn("autoui-dialog-content", className),
2281
+ ...restProps,
2282
+ "data-id": node.id,
2283
+ children: [
2284
+ (title || description) && /* @__PURE__ */ jsxs(DialogHeader, { children: [
2285
+ title && /* @__PURE__ */ jsx(DialogTitle, { children: title }),
2286
+ description && /* @__PURE__ */ jsx(DialogDescription, { children: description })
2287
+ ] }),
2288
+ children
2289
+ ]
2290
+ }
2291
+ )
2292
+ },
2293
+ key
2294
+ );
2295
+ },
2296
+ Heading: (node) => {
2297
+ const { className, style: styleProp, key, ...restProps } = node.props || {};
2298
+ const text = getSafeProp(node.props, "text", isString, "Heading");
2299
+ let level = getSafeProp(
2300
+ node.props,
2301
+ "level",
2302
+ (v) => typeof v === "number" && v >= 1 && v <= 6,
2303
+ 2
2304
+ );
2305
+ if (typeof level !== "number" || level < 1 || level > 6) {
2306
+ level = 2;
2307
+ }
2308
+ const Tag = `h${level}`;
2309
+ const style = typeof styleProp === "string" ? parseStyleString(styleProp) : styleProp;
2310
+ const headingStyles = {
2311
+ 1: "scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl",
2312
+ 2: "scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0",
2313
+ 3: "scroll-m-20 text-2xl font-semibold tracking-tight",
2314
+ 4: "scroll-m-20 text-xl font-semibold tracking-tight"
2315
+ // Add styles for h5, h6 if needed, using text-lg, text-base etc.
2316
+ }[level] || "text-lg font-semibold";
2317
+ return /* @__PURE__ */ jsx(
2318
+ Tag,
2319
+ {
2320
+ className: cn(headingStyles, className),
2321
+ style,
2322
+ ...restProps,
2323
+ children: text
2324
+ },
2325
+ key
2326
+ );
2327
+ },
2328
+ Text: (node) => {
2329
+ const { className, style: styleProp, key, ...restProps } = node.props || {};
2330
+ const text = getSafeProp(node.props, "text", isString, "Some text");
2331
+ const style = typeof styleProp === "string" ? parseStyleString(styleProp) : styleProp;
2332
+ return /* @__PURE__ */ jsx(
2333
+ "p",
2334
+ {
2335
+ className: cn("leading-7", className),
2336
+ style,
2337
+ ...restProps,
2338
+ children: text
2339
+ },
2340
+ key
2341
+ );
1331
2342
  }
1332
2343
  };
1333
2344
  function renderNode(node, processEvent2) {
@@ -1424,99 +2435,261 @@ function getValueByPath(context, path) {
1424
2435
  return current;
1425
2436
  }
1426
2437
  function setValueByPath(context, path, value) {
2438
+ if (!path) {
2439
+ return context;
2440
+ }
1427
2441
  const result = { ...context };
1428
2442
  const parts = path.split(".");
1429
- if (parts.length === 0)
1430
- return result;
1431
2443
  let current = result;
1432
2444
  for (let i = 0; i < parts.length - 1; i++) {
1433
2445
  const part = parts[i];
1434
2446
  if (typeof current !== "object" || current === null) {
1435
- console.error("setValueByPath: Cannot create path in a non-object.");
2447
+ console.warn(
2448
+ `setValueByPath: Cannot traverse path "${path}". Parent segment "${parts[i - 1] || "(root)"}" is not an object.`
2449
+ );
1436
2450
  return context;
1437
2451
  }
1438
2452
  const currentAsObject = current;
1439
- if (!(part in currentAsObject) || typeof currentAsObject[part] !== "object" || currentAsObject[part] === null) {
2453
+ const nextPartValue = currentAsObject[part];
2454
+ if (nextPartValue === void 0 || nextPartValue === null) {
1440
2455
  currentAsObject[part] = {};
2456
+ } else if (typeof nextPartValue !== "object") {
2457
+ console.warn(
2458
+ `setValueByPath: Cannot create nested path "${path}". Segment "${part}" is not an object.`
2459
+ );
2460
+ return context;
2461
+ } else {
2462
+ currentAsObject[part] = { ...nextPartValue };
1441
2463
  }
1442
2464
  current = currentAsObject[part];
1443
2465
  }
1444
2466
  const lastPart = parts[parts.length - 1];
1445
2467
  if (typeof current === "object" && current !== null) {
1446
2468
  current[lastPart] = value;
1447
- } else if (parts.length === 1 && typeof result === "object" && result !== null) {
1448
- result[lastPart] = value;
1449
2469
  } else {
1450
2470
  console.warn(
1451
- `setValueByPath: Could not set value for path "${path}". Final segment location is not an object.`
2471
+ `setValueByPath: Could not set value for path "${path}". Final segment parent is not an object.`
1452
2472
  );
1453
2473
  return context;
1454
2474
  }
1455
2475
  return result;
1456
2476
  }
1457
- function processBinding(binding, context) {
2477
+ function processBinding(binding, context, itemData) {
1458
2478
  if (typeof binding === "string") {
1459
- return getValueByPath(context, binding);
2479
+ const exactMatchArr = binding.match(/^{{(.*)}}$/);
2480
+ const pathInsideExact = exactMatchArr ? exactMatchArr[1].trim() : null;
2481
+ if (pathInsideExact !== null && !pathInsideExact.includes("{{") && !pathInsideExact.includes("}}")) {
2482
+ const pathToResolve = pathInsideExact;
2483
+ let resolvedValue = void 0;
2484
+ console.log(
2485
+ `[processBinding Debug] Processing EXACT template: "${binding}", Path: "${pathToResolve}", Has itemData: ${!!itemData}`
2486
+ );
2487
+ if (itemData) {
2488
+ try {
2489
+ console.log(
2490
+ `[processBinding Debug] itemData content (EXACT):`,
2491
+ JSON.parse(JSON.stringify(itemData))
2492
+ );
2493
+ } catch {
2494
+ }
2495
+ }
2496
+ if ((pathToResolve.startsWith("item.") || pathToResolve.startsWith("row.")) && itemData) {
2497
+ if (pathToResolve.startsWith("item.")) {
2498
+ resolvedValue = getValueByPath(itemData, pathToResolve.substring(5));
2499
+ } else {
2500
+ resolvedValue = getValueByPath(itemData, pathToResolve.substring(4));
2501
+ }
2502
+ } else if (itemData && pathToResolve in itemData) {
2503
+ resolvedValue = getValueByPath(itemData, pathToResolve);
2504
+ }
2505
+ if (resolvedValue === void 0) {
2506
+ resolvedValue = getValueByPath(context, pathToResolve);
2507
+ }
2508
+ return resolvedValue;
2509
+ } else if (binding.includes("{{") && binding.includes("}}")) {
2510
+ console.log(
2511
+ `[processBinding Debug] Processing EMBEDDED templates: "${binding}", Has itemData: ${!!itemData}`
2512
+ );
2513
+ if (itemData) {
2514
+ try {
2515
+ console.log(
2516
+ `[processBinding Debug] itemData content (EMBEDDED):`,
2517
+ JSON.parse(JSON.stringify(itemData))
2518
+ );
2519
+ } catch {
2520
+ }
2521
+ }
2522
+ const resolvedString = binding.replaceAll(
2523
+ /{{(.*?)}}/g,
2524
+ // Non-greedy match inside braces
2525
+ (match, path) => {
2526
+ const trimmedPath = path.trim();
2527
+ let resolvedValue = void 0;
2528
+ if ((trimmedPath.startsWith("item.") || trimmedPath.startsWith("row.")) && itemData) {
2529
+ if (trimmedPath.startsWith("item.")) {
2530
+ resolvedValue = getValueByPath(
2531
+ itemData,
2532
+ trimmedPath.substring(5)
2533
+ );
2534
+ } else {
2535
+ resolvedValue = getValueByPath(
2536
+ itemData,
2537
+ trimmedPath.substring(4)
2538
+ );
2539
+ }
2540
+ } else if (itemData && trimmedPath in itemData) {
2541
+ resolvedValue = getValueByPath(itemData, trimmedPath);
2542
+ }
2543
+ if (resolvedValue === void 0) {
2544
+ resolvedValue = getValueByPath(context, trimmedPath);
2545
+ }
2546
+ return resolvedValue === null || resolvedValue === void 0 ? "" : String(resolvedValue);
2547
+ }
2548
+ );
2549
+ return resolvedString;
2550
+ } else {
2551
+ const pathToResolve = binding;
2552
+ let resolvedValue = void 0;
2553
+ console.log(
2554
+ `[processBinding Debug] Processing PATH string: "${pathToResolve}", Has itemData: ${!!itemData}`
2555
+ );
2556
+ if (itemData && !pathToResolve.includes(".") && pathToResolve in itemData) {
2557
+ resolvedValue = getValueByPath(itemData, pathToResolve);
2558
+ }
2559
+ if (resolvedValue === void 0) {
2560
+ resolvedValue = getValueByPath(context, pathToResolve);
2561
+ }
2562
+ return resolvedValue;
2563
+ }
1460
2564
  }
1461
2565
  if (Array.isArray(binding)) {
1462
- return binding.map((item) => processBinding(item, context));
2566
+ return binding.map((item) => processBinding(item, context, itemData));
1463
2567
  }
1464
2568
  if (binding !== null && typeof binding === "object") {
1465
2569
  const result = {};
1466
2570
  for (const [key, value] of Object.entries(binding)) {
1467
- result[key] = processBinding(value, context);
2571
+ result[key] = processBinding(value, context, itemData);
1468
2572
  }
1469
2573
  return result;
1470
2574
  }
1471
2575
  return binding;
1472
2576
  }
1473
- async function resolveBindings(node, context) {
2577
+ async function resolveBindings(node, context, itemData) {
2578
+ const effectiveContext = itemData ? { ...context, item: itemData } : context;
1474
2579
  const currentTime = Date.now();
1475
- const cacheKey = createCacheKey(node.id, context);
2580
+ const cacheKey = createCacheKey(node.id, effectiveContext);
1476
2581
  const cachedNode = bindingsCache.get(cacheKey);
1477
2582
  const cachedTimestamp = nodeCacheTimestamps.get(cacheKey);
1478
2583
  if (cachedNode && cachedTimestamp && currentTime - cachedTimestamp < CACHE_TTL2) {
1479
2584
  return cachedNode;
1480
2585
  }
1481
- await systemEvents.emit(
1482
- createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, {
1483
- layout: node
1484
- })
1485
- );
2586
+ if (!itemData) {
2587
+ await systemEvents.emit(
2588
+ createSystemEvent("BINDING_RESOLUTION_START" /* BINDING_RESOLUTION_START */, {
2589
+ layout: node
2590
+ })
2591
+ );
2592
+ }
1486
2593
  const result = {
1487
2594
  ...node,
1488
- props: node.props ? { ...node.props } : null,
1489
- events: node.events ? { ...node.events } : null
2595
+ props: node.props ? JSON.parse(JSON.stringify(node.props)) : null,
2596
+ events: node.events ? JSON.parse(JSON.stringify(node.events)) : null,
2597
+ bindings: node.bindings ? JSON.parse(JSON.stringify(node.bindings)) : null,
2598
+ children: null
2599
+ // Initialize children to null
1490
2600
  };
2601
+ const resolvedBindings = {};
1491
2602
  if (node.bindings) {
1492
- for (const [key, binding] of Object.entries(node.bindings)) {
1493
- const value = processBinding(binding, context);
1494
- if (value !== void 0 && typeof value === "string") {
1495
- if (!result.props) {
2603
+ for (const [key, bindingValue] of Object.entries(node.bindings)) {
2604
+ const resolvedValue = processBinding(bindingValue, context, itemData);
2605
+ resolvedBindings[key] = resolvedValue;
2606
+ if (resolvedValue !== void 0) {
2607
+ if (!result.props)
1496
2608
  result.props = {};
1497
- }
1498
- result.props[key] = value;
2609
+ result.props[key] = resolvedValue;
1499
2610
  }
1500
2611
  }
1501
2612
  }
1502
- if (node.children) {
2613
+ result.bindings = null;
2614
+ if (node.events) {
2615
+ result.events = processBinding(
2616
+ node.events,
2617
+ context,
2618
+ itemData
2619
+ );
2620
+ } else {
2621
+ result.events = null;
2622
+ }
2623
+ const dataBindingValue = resolvedBindings["data"] ?? resolvedBindings["items"];
2624
+ if ((node.node_type === "ListView" || node.node_type === "Table") && Array.isArray(dataBindingValue) && node.children && node.children.length > 0) {
2625
+ const templateChild = node.children[0];
2626
+ const mappedChildren = await Promise.all(
2627
+ dataBindingValue.map(async (currentItemData, index) => {
2628
+ try {
2629
+ if (typeof currentItemData !== "object" || currentItemData === null) {
2630
+ console.warn(
2631
+ `List item at index ${index} for node ${node.id} is not an object:`,
2632
+ currentItemData
2633
+ );
2634
+ return null;
2635
+ }
2636
+ const currentItemAsRecord = currentItemData;
2637
+ const itemId = currentItemAsRecord.id;
2638
+ const instanceId = `${templateChild.id}-${itemId || index}`;
2639
+ const childNodeInstance = JSON.parse(
2640
+ JSON.stringify(templateChild)
2641
+ );
2642
+ childNodeInstance.id = instanceId;
2643
+ const resolvedChild = await resolveBindings(
2644
+ childNodeInstance,
2645
+ context,
2646
+ currentItemAsRecord
2647
+ );
2648
+ if (!resolvedChild.props)
2649
+ resolvedChild.props = {};
2650
+ resolvedChild.props.key = itemId || `${node.id}-item-${index}`;
2651
+ return resolvedChild;
2652
+ } catch (error) {
2653
+ console.error(
2654
+ `[resolveBindings Error] Error processing item at index ${index} for node ${node.id}:`,
2655
+ error,
2656
+ "Item Data:",
2657
+ currentItemData
2658
+ );
2659
+ return null;
2660
+ }
2661
+ })
2662
+ );
2663
+ result.children = mappedChildren.filter(
2664
+ (child) => child !== null
2665
+ );
2666
+ } else if (node.children && node.children.length > 0) {
1503
2667
  result.children = await Promise.all(
1504
- node.children.map((child) => resolveBindings(child, context))
2668
+ node.children.map((child) => resolveBindings(child, context, itemData))
2669
+ );
2670
+ } else {
2671
+ result.children = [];
2672
+ }
2673
+ if (!itemData) {
2674
+ await systemEvents.emit(
2675
+ createSystemEvent("BINDING_RESOLUTION_COMPLETE" /* BINDING_RESOLUTION_COMPLETE */, {
2676
+ originalLayout: node,
2677
+ resolvedLayout: result
2678
+ })
1505
2679
  );
1506
2680
  }
1507
- await systemEvents.emit(
1508
- createSystemEvent("BINDING_RESOLUTION_COMPLETE" /* BINDING_RESOLUTION_COMPLETE */, {
1509
- originalLayout: node,
1510
- resolvedLayout: result
1511
- })
1512
- );
1513
2681
  bindingsCache.set(cacheKey, result);
1514
2682
  nodeCacheTimestamps.set(cacheKey, currentTime);
1515
2683
  if (bindingsCache.size > MAX_CACHE_SIZE2) {
1516
- const entries = [...nodeCacheTimestamps.entries()];
1517
- if (entries.length > 0) {
1518
- entries.sort((a, b) => a[1] - b[1]);
1519
- const oldestKey = entries[0][0];
2684
+ let oldestKey = null;
2685
+ let oldestTimestamp = currentTime;
2686
+ for (const [key, timestamp] of nodeCacheTimestamps.entries()) {
2687
+ if (timestamp < oldestTimestamp) {
2688
+ oldestTimestamp = timestamp;
2689
+ oldestKey = key;
2690
+ }
2691
+ }
2692
+ if (oldestKey) {
1520
2693
  bindingsCache.delete(oldestKey);
1521
2694
  nodeCacheTimestamps.delete(oldestKey);
1522
2695
  }
@@ -1649,6 +2822,31 @@ function getMissingComponentsMessage() {
1649
2822
  return `Missing required shadcn components. Please run:
1650
2823
  > npm run setup-shadcn`;
1651
2824
  }
2825
+ function correctListBindingsRecursive(node, dataContext) {
2826
+ const correctedNode = JSON.parse(JSON.stringify(node));
2827
+ if ((correctedNode.node_type === "ListView" || correctedNode.node_type === "Table") && correctedNode.bindings?.data) {
2828
+ const bindingPath = correctedNode.bindings.data;
2829
+ if (typeof bindingPath === "string") {
2830
+ const pathSegments = bindingPath.split(".");
2831
+ const mainKey = pathSegments[0];
2832
+ if (pathSegments.length === 1) {
2833
+ const potentialDataContextEntry = dataContext[mainKey];
2834
+ if (potentialDataContextEntry && typeof potentialDataContextEntry === "object" && potentialDataContextEntry !== null && "data" in potentialDataContextEntry && Array.isArray(potentialDataContextEntry.data)) {
2835
+ correctedNode.bindings.data = `${mainKey}.data`;
2836
+ console.log(
2837
+ `[AutoUI Debug] Corrected list binding for node '${correctedNode.id}': from '${mainKey}' to '${mainKey}.data'`
2838
+ );
2839
+ }
2840
+ }
2841
+ }
2842
+ }
2843
+ if (correctedNode.children) {
2844
+ correctedNode.children = correctedNode.children.map(
2845
+ (child) => correctListBindingsRecursive(child, dataContext)
2846
+ );
2847
+ }
2848
+ return correctedNode;
2849
+ }
1652
2850
  var AutoUI = ({
1653
2851
  schema,
1654
2852
  goal,
@@ -1658,11 +2856,12 @@ var AutoUI = ({
1658
2856
  eventHooks,
1659
2857
  systemEventHooks,
1660
2858
  debugMode = false,
1661
- mockMode = true,
2859
+ mockMode = false,
1662
2860
  planningConfig,
1663
2861
  integration = {},
1664
2862
  scope = {},
1665
- enablePartialUpdates = false
2863
+ enablePartialUpdates = false,
2864
+ openaiApiKey
1666
2865
  }) => {
1667
2866
  const [schemaAdapterInstance] = useState(null);
1668
2867
  const [dataContext, setDataContext] = useState({});
@@ -1734,7 +2933,8 @@ var AutoUI = ({
1734
2933
  planningConfig,
1735
2934
  router: void 0,
1736
2935
  dataContext,
1737
- enablePartialUpdates
2936
+ enablePartialUpdates,
2937
+ openaiApiKey
1738
2938
  });
1739
2939
  const eventManagerRef = useRef(new EventManager());
1740
2940
  useEffect(() => {
@@ -1834,13 +3034,29 @@ var AutoUI = ({
1834
3034
  null
1835
3035
  );
1836
3036
  const resolveLayoutBindings = useCallback(async () => {
1837
- if (state.layout) {
1838
- try {
1839
- const resolved = await resolveBindings(state.layout, dataContext);
1840
- setResolvedLayout(resolved);
1841
- } catch (err) {
1842
- console.error("Error resolving bindings:", err);
1843
- }
3037
+ if (state.layout && dataContext) {
3038
+ console.log(
3039
+ "[AutoUI Debug] DataContext before resolving bindings:",
3040
+ JSON.stringify(dataContext, null, 2)
3041
+ );
3042
+ console.log(
3043
+ "[AutoUI Debug] Raw layout before resolving (from planner):",
3044
+ JSON.stringify(state.layout, null, 2)
3045
+ );
3046
+ const correctedLayout = correctListBindingsRecursive(
3047
+ state.layout,
3048
+ dataContext
3049
+ );
3050
+ console.log(
3051
+ "[AutoUI Debug] Layout after binding correction (before resolving):",
3052
+ JSON.stringify(correctedLayout, null, 2)
3053
+ );
3054
+ const resolved = await resolveBindings(correctedLayout, dataContext);
3055
+ setResolvedLayout(resolved);
3056
+ console.log(
3057
+ "[AutoUI Debug] Resolved layout after bindings:",
3058
+ JSON.stringify(resolved, null, 2)
3059
+ );
1844
3060
  } else {
1845
3061
  setResolvedLayout(void 0);
1846
3062
  }
@@ -2047,12 +3263,23 @@ var generateUIComponent = async (prompt) => {
2047
3263
  return `<div>Generated UI Component for: ${prompt}</div>`;
2048
3264
  };
2049
3265
  function usePlanner(options) {
2050
- const { goal, schema, userContext, router: customRouter } = options;
2051
- const [layout, setLayout] = useState(void 0);
3266
+ const {
3267
+ schema,
3268
+ goal,
3269
+ openaiApiKey,
3270
+ userContext,
3271
+ initialLayout,
3272
+ mockMode: optionsMockMode
3273
+ } = options;
3274
+ const [layout, setLayout] = useState(
3275
+ initialLayout || void 0
3276
+ );
2052
3277
  const [loading, setLoading] = useState(false);
2053
3278
  const [error, setError] = useState(null);
2054
- const router = customRouter || createDefaultRouter();
3279
+ const router = options.router || createDefaultRouter();
2055
3280
  const dataContext = {};
3281
+ const initialFetchAttempted = useRef(false);
3282
+ const mockMode = optionsMockMode || !openaiApiKey;
2056
3283
  const generateInitialLayout = useCallback(async () => {
2057
3284
  setLoading(true);
2058
3285
  setError(null);
@@ -2063,14 +3290,26 @@ function usePlanner(options) {
2063
3290
  userContext: userContext || null,
2064
3291
  history: null
2065
3292
  };
2066
- const generatedLayout = await callPlannerLLM(plannerInput2);
3293
+ let generatedLayout;
3294
+ if (mockMode) {
3295
+ console.warn(
3296
+ "Using mock planner in usePlanner hook (mockMode enabled or API key missing)."
3297
+ );
3298
+ generatedLayout = mockPlanner(plannerInput2);
3299
+ } else {
3300
+ generatedLayout = await callPlannerLLM(
3301
+ plannerInput2,
3302
+ openaiApiKey,
3303
+ void 0
3304
+ );
3305
+ }
2067
3306
  setLayout(generatedLayout);
2068
3307
  } catch (err) {
2069
3308
  setError(err instanceof Error ? err : new Error(String(err)));
2070
3309
  } finally {
2071
3310
  setLoading(false);
2072
3311
  }
2073
- }, [schema, goal, userContext]);
3312
+ }, [schema, goal, userContext, openaiApiKey, mockMode]);
2074
3313
  const handleEvent = useCallback(
2075
3314
  async (event) => {
2076
3315
  if (!layout) {
@@ -2087,7 +3326,8 @@ function usePlanner(options) {
2087
3326
  layout,
2088
3327
  dataContext,
2089
3328
  goal,
2090
- userContext
3329
+ userContext,
3330
+ openaiApiKey
2091
3331
  );
2092
3332
  setLayout(updatedLayout);
2093
3333
  } catch (err) {
@@ -2096,8 +3336,14 @@ function usePlanner(options) {
2096
3336
  setLoading(false);
2097
3337
  }
2098
3338
  },
2099
- [layout, router, schema, dataContext, goal, userContext]
3339
+ [layout, router, schema, dataContext, goal, userContext, openaiApiKey]
2100
3340
  );
3341
+ useEffect(() => {
3342
+ if (options.initialLayout === void 0 && layout === void 0 && !initialFetchAttempted.current) {
3343
+ initialFetchAttempted.current = true;
3344
+ generateInitialLayout();
3345
+ }
3346
+ }, [options.initialLayout, layout, generateInitialLayout]);
2101
3347
  return {
2102
3348
  layout,
2103
3349
  loading,