@bravostudioai/react 0.1.36 → 0.1.41

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.
@@ -7,7 +7,7 @@ function g(i) {
7
7
  return y === 0 ? e.toLowerCase() + r : e.toUpperCase() + r;
8
8
  }).join("").replace(/^[0-9]/, "_$&") : "item";
9
9
  }
10
- function d(i, o) {
10
+ function W(i, o) {
11
11
  const s = g(i);
12
12
  if (o.length === 0)
13
13
  return s;
@@ -16,7 +16,7 @@ function d(i, o) {
16
16
  (r) => g(r)
17
17
  ).map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join("") + s;
18
18
  }
19
- function F(i, o) {
19
+ function I(i, o) {
20
20
  if (o.length === 0)
21
21
  return [];
22
22
  let s = 0;
@@ -41,20 +41,20 @@ function F(i, o) {
41
41
  s,
42
42
  s + e
43
43
  );
44
- return !v(r, a);
44
+ return !P(r, a);
45
45
  }))
46
46
  return r;
47
47
  }
48
48
  return t;
49
49
  }
50
- function v(i, o) {
50
+ function P(i, o) {
51
51
  return i.length !== o.length ? !1 : i.every((s, y) => s === o[y]);
52
52
  }
53
- function P(i, o) {
54
- return i === "component:image" || i === "component:text" || i?.startsWith("component:input-") || i === "component:webview" || i === "component:video" || i === "component:video" ? "string" : i === "component:embed" ? "React.ReactNode" : "any";
53
+ function C(i, o) {
54
+ return i === "component:image" || i === "component:text" || i?.startsWith("component:input-") || i === "component:webview" || i === "component:web-view" || i === "component:video" || i === "component:video" ? "string" : i === "component:embed" ? "React.ReactNode" : "any";
55
55
  }
56
56
  function S(i) {
57
- return i === "component:image" ? "imageUrl" : i === "component:text" ? "text" : i === "component:webview" ? "url" : i === "component:video" ? "videoUrl" : "value";
57
+ return i === "component:image" ? "imageUrl" : i === "component:text" ? "text" : i === "component:webview" || i === "component:web-view" ? "url" : i === "component:video" ? "videoUrl" : "value";
58
58
  }
59
59
  function j(i) {
60
60
  const o = [];
@@ -79,47 +79,47 @@ function j(i) {
79
79
  if (t.containers && Array.isArray(t.containers) && t.containers.forEach(f), !p && t.components && Array.isArray(t.components) && t.components.forEach(f), p) {
80
80
  const a = p;
81
81
  let u = [];
82
- const c = [], h = (n, b = []) => {
82
+ const c = [], l = (n, b = []) => {
83
83
  if (!n || typeof n != "object") return;
84
84
  if (n.type === "component:image" && c.push(n), Array.isArray(n.tags) && (n.tags.includes("encore:data") || n.tags.includes("bravo:data"))) {
85
- const l = g(n.name || "item"), C = P(n.type, n.name);
85
+ const A = g(n.name || "item"), v = C(n.type, n.name);
86
86
  u.push({
87
87
  id: n.id,
88
88
  name: n.name || "Unnamed",
89
89
  type: n.type,
90
90
  tags: n.tags || [],
91
- propName: l,
91
+ propName: A,
92
92
  // Will be qualified later if needed
93
- propType: C,
93
+ propType: v,
94
94
  // Store parent path for later qualification
95
95
  _parentPath: [...b]
96
96
  });
97
97
  }
98
- const A = [...b];
98
+ const h = [...b];
99
99
  if (n.name && (n.type?.startsWith("container:") || n.type?.startsWith("component:"))) {
100
- const l = n.name.trim(), C = /^frame\s*\d*$/i.test(l) || l.toUpperCase() === "FRAME";
101
- l && !C && A.push(n.name);
100
+ const A = n.name.trim(), v = /^frame\s*\d*$/i.test(A) || A.toUpperCase() === "FRAME";
101
+ A && !v && h.push(n.name);
102
102
  }
103
103
  n.body && Array.isArray(n.body) && n.body.forEach(
104
- (l) => h(l, A)
104
+ (A) => l(A, h)
105
105
  ), n.containers && Array.isArray(n.containers) && n.containers.forEach(
106
- (l) => h(l, A)
106
+ (A) => l(A, h)
107
107
  ), n.components && Array.isArray(n.components) && n.components.forEach(
108
- (l) => h(l, A)
108
+ (A) => l(A, h)
109
109
  );
110
110
  };
111
111
  if (a.components && Array.isArray(a.components) && a.components.forEach(
112
- (n) => h(n, [])
112
+ (n) => l(n, [])
113
113
  ), !u.some(
114
114
  (n) => n.type === "component:image"
115
115
  ) && c.length > 0) {
116
- const n = c[0], A = (n.name || "image").toLowerCase().includes("image") ? "imageUrl" : g(n.name || "image");
116
+ const n = c[0], h = (n.name || "image").toLowerCase().includes("image") ? "imageUrl" : g(n.name || "image");
117
117
  u.push({
118
118
  id: n.id,
119
119
  name: n.name || "Image",
120
120
  type: n.type,
121
121
  tags: n.tags || [],
122
- propName: A,
122
+ propName: h,
123
123
  // Will be qualified later if needed
124
124
  propType: "string",
125
125
  // imageUrl is always string
@@ -128,11 +128,11 @@ function j(i) {
128
128
  }
129
129
  if (E(u), c.length > 0) {
130
130
  const b = (c[0].name || "").toLowerCase();
131
- u = u.filter((A) => {
132
- if (A.type === "component:image") return !0;
133
- if (A.type === "component:color") {
134
- const l = (A.name || "").toLowerCase();
135
- if (b.includes(l) || l.includes("image"))
131
+ u = u.filter((h) => {
132
+ if (h.type === "component:image") return !0;
133
+ if (h.type === "component:color") {
134
+ const A = (h.name || "").toLowerCase();
135
+ if (b.includes(A) || A.includes("image"))
136
136
  return !1;
137
137
  }
138
138
  return !0;
@@ -165,14 +165,14 @@ function x(i) {
165
165
  function t(r, p, f = []) {
166
166
  if (!r || typeof r != "object" || p && s.has(p)) return;
167
167
  const a = Array.isArray(r.tags) && (r.tags.includes("encore:data") || r.tags.includes("bravo:data"));
168
- if (r.type === "component:embed" || a && (r.type === "component:text" || r.type === "component:image" || r.type === "component:webview" || r.type === "component:video")) {
169
- const h = g(r.name || "item"), m = P(r.type, r.name);
168
+ if (r.type === "component:embed" || r.type === "component:webview" || r.type === "component:web-view" || r.type === "component:video" || a && (r.type === "component:text" || r.type === "component:image")) {
169
+ const l = g(r.name || "item"), m = C(r.type, r.name);
170
170
  o.push({
171
171
  id: r.id,
172
172
  name: r.name || "Unnamed",
173
173
  type: r.type,
174
174
  tags: r.tags || [],
175
- propName: h,
175
+ propName: l,
176
176
  // Will be qualified later if needed
177
177
  propType: m,
178
178
  // Store parent path for later qualification
@@ -181,22 +181,22 @@ function x(i) {
181
181
  }
182
182
  const u = [...f];
183
183
  if (r.name && (r.type?.startsWith("container:") || r.type?.startsWith("component:"))) {
184
- const h = r.name.trim(), m = /^frame\s*\d*$/i.test(h) || h.toUpperCase() === "FRAME";
185
- h && !m && u.push(r.name);
184
+ const l = r.name.trim(), m = /^frame\s*\d*$/i.test(l) || l.toUpperCase() === "FRAME";
185
+ l && !m && u.push(r.name);
186
186
  }
187
187
  const c = r.id;
188
188
  r.body && Array.isArray(r.body) && r.body.forEach(
189
- (h) => t(h, c, u)
189
+ (l) => t(l, c, u)
190
190
  ), r.containers && Array.isArray(r.containers) && r.containers.forEach(
191
- (h) => t(h, c, u)
191
+ (l) => t(l, c, u)
192
192
  ), r.components && Array.isArray(r.components) && r.components.forEach(
193
- (h) => t(h, c, u)
193
+ (l) => t(l, c, u)
194
194
  );
195
195
  }
196
196
  const e = i.data?.body || i.body || i.data?.body || [];
197
197
  return Array.isArray(e) && e.length > 0 && (e.forEach(y), e.forEach((r) => t(r))), E(o), o;
198
198
  }
199
- function w(i) {
199
+ function N(i) {
200
200
  const o = /* @__PURE__ */ new Map();
201
201
  function s(t) {
202
202
  if (!(!t || typeof t != "object")) {
@@ -225,7 +225,7 @@ function w(i) {
225
225
  const y = i.data?.body || i.body || i.data?.body || [];
226
226
  return Array.isArray(y) && y.length > 0 && y.forEach((t) => s(t)), Array.from(o.values());
227
227
  }
228
- function N(i) {
228
+ function d(i) {
229
229
  const o = [];
230
230
  function s(t, e) {
231
231
  if (!t || typeof t != "object") return;
@@ -245,15 +245,15 @@ function N(i) {
245
245
  }
246
246
  }
247
247
  if (r && (p || e === void 0) && u(t), r && (f || p)) {
248
- const c = [], h = (m, n = []) => {
248
+ const c = [], l = (m, n = []) => {
249
249
  if (!m || typeof m != "object") return;
250
250
  if (m.type?.startsWith("component:input-") || m.type === "component:input-text" || m.type === "component:input-image" || m.type === "component:input-email" || m.type === "component:input-password" || m.type === "component:input-select") {
251
- const A = g(m.name || "Unnamed input");
251
+ const h = g(m.name || "Unnamed input");
252
252
  c.push({
253
253
  id: m.id,
254
254
  name: m.name || "Unnamed input",
255
255
  type: m.type,
256
- propName: A,
256
+ propName: h,
257
257
  // Will be qualified later if needed
258
258
  _parentPath: [...n]
259
259
  // Store parent path for qualification
@@ -261,14 +261,14 @@ function N(i) {
261
261
  }
262
262
  const b = [...n];
263
263
  if (m.name && (m.type?.startsWith("container:") || m.type?.startsWith("component:"))) {
264
- const A = m.name.trim(), l = /^frame\s*\d*$/i.test(A) || A.toUpperCase() === "FRAME";
265
- A && !l && b.push(m.name);
264
+ const h = m.name.trim(), A = /^frame\s*\d*$/i.test(h) || h.toUpperCase() === "FRAME";
265
+ h && !A && b.push(m.name);
266
266
  }
267
267
  m.components && Array.isArray(m.components) && m.components.forEach(
268
- (A) => h(A, b)
269
- ), m.body && Array.isArray(m.body) && m.body.forEach((A) => h(A, b));
268
+ (h) => l(h, b)
269
+ ), m.body && Array.isArray(m.body) && m.body.forEach((h) => l(h, b));
270
270
  };
271
- h(t, []), c.length > 0 && o.push({
271
+ l(t, []), c.length > 0 && o.push({
272
272
  formId: t.id,
273
273
  formName: t.name || "Form",
274
274
  submitButtonId: a,
@@ -316,25 +316,38 @@ function M(i, o) {
316
316
  );
317
317
  }
318
318
  const e = i.data?.body || i.body || i.data?.body || [];
319
- return Array.isArray(e) && e.length > 0 && e.forEach((r) => t(r)), W(s), s;
319
+ return Array.isArray(e) && e.length > 0 && e.forEach((r) => t(r)), U(s), s;
320
320
  }
321
- function W(i) {
321
+ function U(i) {
322
322
  E(i);
323
323
  }
324
- function L(i) {
324
+ function G(i) {
325
325
  const o = [];
326
+ console.log(
327
+ "[DEBUG] local encore-lib findActionButtons running via alias. Check node.actions support."
328
+ );
326
329
  function s(t, e = []) {
327
330
  if (!t || typeof t != "object") return;
331
+ (t.id === "01KF5PAFFVFSKY6QJZXQTC99P5" || t.tags && t.tags.some((a) => a.includes("action"))) && console.log(`[DEBUG] traverse node ${t.name} (${t.id})`, {
332
+ type: t.type,
333
+ tags: t.tags,
334
+ hasActions: !!t.actions,
335
+ actionsKeys: t.actions ? Object.keys(t.actions) : []
336
+ });
328
337
  const r = Array.isArray(t.tags) && t.tags.some((a) => a.startsWith("action:")), p = t.actions && typeof t.actions == "object";
329
338
  if (r || p) {
330
339
  let a = "tap";
331
340
  if (Array.isArray(t.tags)) {
332
341
  const c = t.tags.find(
333
- (h) => h.startsWith("action:")
342
+ (l) => l.startsWith("action:")
334
343
  );
335
344
  c && (a = c.replace("action:", ""));
336
345
  }
337
- t.actions?.tap?.action && (a = t.actions.tap.action);
346
+ t.actions?.tap?.action && (a = t.actions.tap.action), console.log(`[DEBUG] Found action button: ${t.name} (${t.id})`, {
347
+ actionType: a,
348
+ hasActionTag: r,
349
+ hasActions: p
350
+ });
338
351
  const u = g(t.name || "button");
339
352
  o.push({
340
353
  id: t.id,
@@ -356,29 +369,29 @@ function L(i) {
356
369
  );
357
370
  }
358
371
  const y = i.data?.body || i.body || i.data?.body || [];
359
- return Array.isArray(y) && y.length > 0 && y.forEach((t) => s(t)), I(o), o;
372
+ return Array.isArray(y) && y.length > 0 && y.forEach((t) => s(t)), F(o), o;
360
373
  }
361
- function I(i) {
374
+ function F(i) {
362
375
  E(i);
363
376
  }
364
- function _(i) {
377
+ function $(i) {
365
378
  i.forEach((o) => {
366
379
  E(o.inputs);
367
380
  });
368
381
  }
369
382
  export {
370
- v as arraysEqual,
371
- L as findActionButtons,
372
- N as findForms,
373
- w as findInputGroups,
374
- F as findMinimalDistinguishingPath,
383
+ P as arraysEqual,
384
+ G as findActionButtons,
385
+ d as findForms,
386
+ N as findInputGroups,
387
+ I as findMinimalDistinguishingPath,
375
388
  j as findSlidersAndDataBindings,
376
389
  x as findStandaloneComponents,
377
390
  M as findStandaloneSelectInputs,
378
- d as generateQualifiedPropName,
391
+ W as generateQualifiedPropName,
379
392
  S as getComponentPropName,
380
- P as getComponentPropType,
381
- _ as qualifyFormInputs,
393
+ C as getComponentPropType,
394
+ $ as qualifyFormInputs,
382
395
  g as sanitizePropName
383
396
  };
384
397
  //# sourceMappingURL=parser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.js","sources":["../../src/codegen/parser.ts"],"sourcesContent":["import {\n ComponentInfo,\n SliderInfo,\n InputGroupInfo,\n FormInfo,\n SelectInputInfo,\n ActionButtonInfo,\n} from \"./types\";\nimport { qualifyPropNames } from \"./propQualification\";\n\n/**\n * Sanitizes a component name into a valid camelCase prop name\n *\n * Removes special characters, handles spaces, and converts to camelCase.\n *\n * @param name - Raw component name from Figma/design tool\n * @returns Valid JavaScript property name\n *\n * @example\n * sanitizePropName(\"My Component!\") // \"myComponent\"\n * sanitizePropName(\"user-name\") // \"userName\"\n */\nexport function sanitizePropName(name: string): string {\n // Convert to camelCase and remove invalid characters\n const cleaned = name\n .replace(/[^a-zA-Z0-9\\s]/g, \"\") // Remove special chars\n .trim();\n\n if (!cleaned) return \"item\";\n\n return cleaned\n .split(/\\s+/)\n .map((word, index) => {\n if (!word) return \"\";\n // Handle all-uppercase words (like \"SHOP\", \"NOW\") by lowercasing them first\n const normalizedWord =\n word === word.toUpperCase() && word.length > 1\n ? word.toLowerCase()\n : word;\n const firstChar = normalizedWord.charAt(0);\n const rest = normalizedWord.slice(1);\n if (index === 0) {\n return firstChar.toLowerCase() + rest;\n }\n return firstChar.toUpperCase() + rest;\n })\n .join(\"\")\n .replace(/^[0-9]/, \"_$&\"); // Prefix numbers with underscore\n}\n\nexport function generateQualifiedPropName(\n componentName: string,\n parentPath: string[]\n): string {\n // Start with the component's own name\n const baseName = sanitizePropName(componentName);\n\n // If no parent path, just return the base name\n if (parentPath.length === 0) {\n return baseName;\n }\n\n // Filter out empty parts and reverse so we build from root to leaf\n const validParentParts = parentPath\n .filter((part) => part && part.trim())\n .reverse();\n\n if (validParentParts.length === 0) {\n return baseName;\n }\n\n // Build qualified name: parent1Parent2ComponentName\n // Each parent part is sanitized individually, then combined\n const sanitizedParentParts = validParentParts.map((part) =>\n sanitizePropName(part)\n );\n\n // Join parent parts (all start uppercase) with base name (starts lowercase)\n const parentPrefix = sanitizedParentParts\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n\n return parentPrefix + baseName;\n}\n\n/**\n * Finds the minimal distinguishing path suffix for a component when compared to others.\n * Returns the shortest suffix (from root side, working towards leaf) that makes this path unique.\n *\n * The algorithm finds where paths first diverge from the root, then takes the minimal\n * distinguishing part from that divergence point towards the leaf.\n */\nexport function findMinimalDistinguishingPath(\n thisPath: string[],\n otherPaths: string[][]\n): string[] {\n if (otherPaths.length === 0) {\n // No other paths to compare, return empty (no qualification needed)\n return [];\n }\n\n // Find the longest common prefix (from root side)\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n thisPath.length,\n ...otherPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = thisPath[i];\n // Check if all other paths have the same part at this position\n const allMatch = otherPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // The distinguishing part starts after the common prefix\n const distinguishingSuffix = thisPath.slice(commonPrefixLength);\n\n // Now find the minimal suffix that's unique\n // Try progressively shorter suffixes (from root side) until we find one that's unique\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const thisSuffix = distinguishingSuffix.slice(0, suffixLength);\n\n // Check if this suffix is unique when combined with the common prefix\n const isUnique = otherPaths.every((otherPath) => {\n // If other path is shorter than common prefix + suffix, it can't match\n if (otherPath.length < commonPrefixLength + suffixLength) {\n return true; // Different length means unique\n }\n // Check if the suffix matches at the divergence point\n const otherSuffix = otherPath.slice(\n commonPrefixLength,\n commonPrefixLength + suffixLength\n );\n return !arraysEqual(thisSuffix, otherSuffix);\n });\n\n if (isUnique) {\n // Found minimal distinguishing suffix\n return thisSuffix;\n }\n }\n\n // If we get here, paths are identical (shouldn't happen, but handle it)\n return distinguishingSuffix;\n}\n\n/**\n * Helper to compare two arrays for equality\n */\nexport function arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n}\n\nexport function getComponentPropType(\n componentType: string,\n _componentName: string\n): string {\n if (componentType === \"component:image\") {\n return \"string\"; // imageUrl\n }\n if (componentType === \"component:text\") {\n return \"string\"; // text\n }\n if (componentType?.startsWith(\"component:input-\")) {\n // Input types generally return strings\n if (componentType === \"component:input-image\") {\n return \"string\"; // image URL\n }\n return \"string\"; // text inputs, email, password, etc.\n }\n if (componentType === \"component:webview\") {\n return \"string\"; // url\n }\n if (componentType === \"component:video\") {\n return \"string\"; // videoUrl\n }\n if (componentType === \"component:video\") {\n return \"string\"; // videoUrl\n }\n if (componentType === \"component:embed\") {\n return \"React.ReactNode\";\n }\n // Default to any for unknown types\n return \"any\";\n}\n\nexport function getComponentPropName(componentType: string): string {\n if (componentType === \"component:image\") {\n return \"imageUrl\";\n }\n if (componentType === \"component:text\") {\n return \"text\";\n }\n if (componentType === \"component:webview\") {\n return \"url\";\n }\n if (componentType === \"component:video\") {\n return \"videoUrl\";\n }\n return \"value\";\n}\n\nexport function findSlidersAndDataBindings(pageData: any): SliderInfo[] {\n const sliders: SliderInfo[] = [];\n\n function traverse(node: any, path: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a slider container\n if (node.type === \"container:slider\") {\n const slider: SliderInfo = {\n id: node.id,\n name: node.name || \"Slider\",\n arrayContainer: null,\n };\n\n // Recursively look for containers with encore:data:array tag inside the slider\n let arrayContainer: any = null;\n\n const findArrayContainer = (containerNode: any): void => {\n if (arrayContainer) return; // Already found one\n\n if (!containerNode || typeof containerNode !== \"object\") return;\n\n // Check if this node is the array container\n if (\n Array.isArray(containerNode.tags) &&\n (containerNode.tags.includes(\"encore:data:array\") ||\n containerNode.tags.includes(\"bravo:data:array\"))\n ) {\n arrayContainer = containerNode;\n return;\n }\n\n // Recursively search children\n if (containerNode.body && Array.isArray(containerNode.body)) {\n containerNode.body.forEach(findArrayContainer);\n }\n if (\n containerNode.containers &&\n Array.isArray(containerNode.containers)\n ) {\n containerNode.containers.forEach(findArrayContainer);\n }\n if (\n containerNode.components &&\n Array.isArray(containerNode.components)\n ) {\n containerNode.components.forEach(findArrayContainer);\n }\n };\n\n // Start search from the slider node itself (checking its children)\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(findArrayContainer);\n }\n // Also check components if they exist directly\n if (\n !arrayContainer &&\n node.components &&\n Array.isArray(node.components)\n ) {\n node.components.forEach(findArrayContainer);\n }\n\n if (arrayContainer) {\n const container = arrayContainer;\n let components: ComponentInfo[] = [];\n\n // Find all components with encore:data tag, and also image components\n const imageComponents: any[] = [];\n\n const findDataComponents = (\n comp: any,\n parentPath: string[] = []\n ): void => {\n if (!comp || typeof comp !== \"object\") return;\n\n // Track image components separately (they might not have encore:data tag)\n if (comp.type === \"component:image\") {\n imageComponents.push(comp);\n }\n\n if (\n Array.isArray(comp.tags) &&\n (comp.tags.includes(\"encore:data\") ||\n comp.tags.includes(\"bravo:data\"))\n ) {\n const basePropName = sanitizePropName(comp.name || \"item\");\n const propType = getComponentPropType(comp.type, comp.name);\n // const propKey = getComponentPropName(comp.type);\n\n components.push({\n id: comp.id,\n name: comp.name || \"Unnamed\",\n type: comp.type,\n tags: comp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n comp.name &&\n (comp.type?.startsWith(\"container:\") ||\n comp.type?.startsWith(\"component:\"))\n ) {\n const name = comp.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(comp.name);\n }\n }\n\n // Recursively search children\n if (comp.body && Array.isArray(comp.body)) {\n comp.body.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n if (comp.containers && Array.isArray(comp.containers)) {\n comp.containers.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n if (comp.components && Array.isArray(comp.components)) {\n comp.components.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n };\n\n if (container.components && Array.isArray(container.components)) {\n container.components.forEach((comp: any) =>\n findDataComponents(comp, [])\n );\n }\n\n // After finding all components, if we have image components but no image with encore:data,\n // add the first image component\n const hasImageWithData = components.some(\n (c) => c.type === \"component:image\"\n );\n if (!hasImageWithData && imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n // For image components, use \"imageUrl\" as the prop name\n // Clean the name first, then if it contains \"image\", just use \"imageUrl\"\n const rawName = (imageComp.name || \"image\").toLowerCase();\n const basePropName = rawName.includes(\"image\")\n ? \"imageUrl\"\n : sanitizePropName(imageComp.name || \"image\");\n components.push({\n id: imageComp.id,\n name: imageComp.name || \"Image\",\n type: imageComp.type,\n tags: imageComp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType: \"string\", // imageUrl is always string\n _parentPath: [],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Qualify duplicate prop names using minimal distinguishing paths\n qualifyPropNames(components);\n\n // If we have an image component, remove color components with similar names\n // (they're usually placeholders/backgrounds)\n if (imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n const imageName = (imageComp.name || \"\").toLowerCase();\n components = components.filter((comp) => {\n // Keep image components\n if (comp.type === \"component:image\") return true;\n // Remove color components that seem to be placeholders for images\n if (comp.type === \"component:color\") {\n const compName = (comp.name || \"\").toLowerCase();\n // If color component name is similar to image name, it's likely a placeholder\n if (imageName.includes(compName) || compName.includes(\"image\")) {\n return false;\n }\n }\n return true;\n });\n }\n\n slider.arrayContainer = {\n id: container.id,\n name: container.name || \"Item\",\n propName: sanitizePropName(container.name || \"items\"),\n components,\n };\n }\n\n sliders.push(slider);\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, [...path, \"body\"]));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, [...path, \"containers\"])\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, [...path, \"components\"])\n );\n }\n }\n\n // Start traversal from page data\n // Try multiple possible locations for the body\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return sliders;\n}\n\n/**\n * Finds standalone data-bound components (not in sliders)\n *\n * Locates components tagged with encore:data (but not encore:data:array)\n * for standalone data binding at the page level.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of component metadata\n */\nexport function findStandaloneComponents(pageData: any): ComponentInfo[] {\n const components: ComponentInfo[] = [];\n const sliderIds = new Set<string>();\n\n // First, collect all slider IDs to exclude their children\n function collectSliderIds(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"container:slider\") {\n sliderIds.add(node.id);\n }\n\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(collectSliderIds);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(collectSliderIds);\n }\n }\n\n // Traverse to find standalone components with bravo:data tags\n // Track parent component names for qualification\n function traverse(\n node: any,\n parentId?: string,\n parentPath: string[] = []\n ): void {\n if (!node || typeof node !== \"object\") return;\n\n // Skip if we're inside a slider\n if (parentId && sliderIds.has(parentId)) return;\n\n // Check if this component has bravo:data tag OR is an embed component\n const hasDataTag =\n Array.isArray(node.tags) &&\n (node.tags.includes(\"encore:data\") || node.tags.includes(\"bravo:data\"));\n\n if (\n node.type === \"component:embed\" ||\n (hasDataTag &&\n (node.type === \"component:text\" ||\n node.type === \"component:image\" ||\n node.type === \"component:webview\" ||\n node.type === \"component:video\"))\n ) {\n const basePropName = sanitizePropName(node.name || \"item\");\n const propType = getComponentPropType(node.type, node.name);\n\n components.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n type: node.type,\n tags: node.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n const currentId = node.id;\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach(collectSliderIds);\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names using minimal distinguishing paths\n qualifyPropNames(components);\n\n return components;\n}\n\n/**\n * Finds input groups (radio button-like components) in the page\n *\n * Locates stateful sets tagged with encore:input-group for coordinated\n * selection behavior.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of input group metadata\n */\nexport function findInputGroups(pageData: any): InputGroupInfo[] {\n const groupsMap = new Map<string, InputGroupInfo>();\n\n function traverse(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-stateful-set with input-group tag\n if (\n node.type === \"component:input-stateful-set\" &&\n Array.isArray(node.tags)\n ) {\n const inputGroupTag = node.tags.find((tag: string) =>\n tag.startsWith(\"input-group:\")\n );\n if (inputGroupTag) {\n const parts = inputGroupTag.split(\":\");\n if (parts.length >= 3) {\n const groupType = parts[1];\n const groupName = parts[2];\n\n if (!groupsMap.has(groupName)) {\n groupsMap.set(groupName, {\n groupName,\n groupType,\n elements: [],\n });\n }\n\n const group = groupsMap.get(groupName)!;\n group.elements.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n });\n }\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(traverse);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(traverse);\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach(traverse);\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return Array.from(groupsMap.values());\n}\n\n/**\n * Finds forms and their input fields in the page\n *\n * Locates containers tagged with encore:form and extracts all input\n * components within them for form submission handling.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of form metadata with input fields\n */\nexport function findForms(pageData: any): FormInfo[] {\n const forms: FormInfo[] = [];\n\n function traverse(node: any, parentContainer?: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a container that might be a form\n const isContainer =\n node.type?.startsWith(\"container:\") || node.type === \"container:default\";\n const isNamedForm =\n node.name?.toLowerCase().includes(\"form\") ||\n (Array.isArray(node.tags) && node.tags.includes(\"form\"));\n\n // Check if this container or any child has a submit action\n let hasSubmitAction = false;\n let submitButtonId: string | undefined;\n\n function checkForSubmitAction(n: any): void {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this node has a submit action\n if (\n Array.isArray(n.tags) &&\n (n.tags.includes(\"action:submit\") || n.tags.includes(\"submit\"))\n ) {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Check actions\n if (n.actions?.tap?.action === \"submit\") {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Recursively check children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach(checkForSubmitAction);\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach(checkForSubmitAction);\n }\n }\n\n // If this looks like a form container, check for submit actions\n if (isContainer && (isNamedForm || parentContainer === undefined)) {\n checkForSubmitAction(node);\n }\n\n // If we found a form container (has submit action or is named \"form\")\n if (isContainer && (hasSubmitAction || isNamedForm)) {\n const inputs: FormInfo[\"inputs\"] = [];\n\n // Find all input components within this container\n const findInputs = (n: any, parentPath: string[] = []): void => {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this is an input component\n if (\n n.type?.startsWith(\"component:input-\") ||\n n.type === \"component:input-text\" ||\n n.type === \"component:input-image\" ||\n n.type === \"component:input-email\" ||\n n.type === \"component:input-password\" ||\n n.type === \"component:input-select\"\n ) {\n const basePropName = sanitizePropName(n.name || \"Unnamed input\");\n inputs.push({\n id: n.id,\n name: n.name || \"Unnamed input\",\n type: n.type,\n propName: basePropName, // Will be qualified later if needed\n _parentPath: [...parentPath], // Store parent path for qualification\n });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n n.name &&\n (n.type?.startsWith(\"container:\") || n.type?.startsWith(\"component:\"))\n ) {\n const name = n.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(n.name);\n }\n }\n\n // Recursively search children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach((child: any) =>\n findInputs(child, currentParentPath)\n );\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach((child: any) => findInputs(child, currentParentPath));\n }\n };\n\n findInputs(node, []);\n\n // Only add form if it has inputs\n if (inputs.length > 0) {\n forms.push({\n formId: node.id,\n formName: node.name || \"Form\",\n submitButtonId,\n inputs,\n });\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return forms;\n}\n\n/**\n * Finds standalone select input components (input-select) that are NOT inside forms.\n * These should be exposed as controlled inputs with value and onChange props.\n */\nexport function findStandaloneSelectInputs(\n pageData: any,\n forms: FormInfo[]\n): SelectInputInfo[] {\n const selectInputs: SelectInputInfo[] = [];\n\n // Collect all input IDs that are already in forms\n const formInputIds = new Set<string>();\n forms.forEach((form) => {\n form.inputs.forEach((input) => {\n formInputIds.add(input.id);\n });\n });\n\n // Traverse to find input-select components not in forms\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-select component\n if (node.type === \"component:input-select\" && !formInputIds.has(node.id)) {\n const basePropName = sanitizePropName(node.name || \"selectInput\");\n selectInputs.push({\n id: node.id,\n name: node.name || \"Select Input\",\n propName: basePropName,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifySelectInputs(selectInputs);\n\n return selectInputs;\n}\n\n/**\n * Qualifies select input prop names to ensure uniqueness.\n */\nfunction qualifySelectInputs(selectInputs: SelectInputInfo[]): void {\n qualifyPropNames(selectInputs);\n}\n\n/**\n * Finds action buttons - components that have action tags (action:remote, action:link, etc.)\n * or have actions defined. These should be exposed with onClick handlers.\n */\nexport function findActionButtons(pageData: any): ActionButtonInfo[] {\n const buttons: ActionButtonInfo[] = [];\n\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this component has an action tag or actions defined\n const hasActionTag =\n Array.isArray(node.tags) &&\n node.tags.some((tag: string) => tag.startsWith(\"action:\"));\n const hasActions = node.actions && typeof node.actions === \"object\";\n\n if (hasActionTag || hasActions) {\n // Determine the action type\n let actionType = \"tap\";\n if (Array.isArray(node.tags)) {\n const actionTag = node.tags.find((tag: string) =>\n tag.startsWith(\"action:\")\n );\n if (actionTag) {\n actionType = actionTag.replace(\"action:\", \"\");\n }\n }\n if (node.actions?.tap?.action) {\n actionType = node.actions.tap.action;\n }\n\n const basePropName = sanitizePropName(node.name || \"button\");\n buttons.push({\n id: node.id,\n name: node.name || \"Button\",\n propName: basePropName,\n actionType,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifyActionButtons(buttons);\n\n return buttons;\n}\n\n/**\n * Qualifies action button prop names to ensure uniqueness.\n */\nfunction qualifyActionButtons(buttons: ActionButtonInfo[]): void {\n qualifyPropNames(buttons);\n}\n\n/**\n * Qualifies form input prop names to ensure uniqueness within each form.\n * Only qualifies where necessary, using minimal distinguishing paths.\n */\nexport function qualifyFormInputs(forms: FormInfo[]): void {\n forms.forEach((form) => {\n qualifyPropNames(form.inputs);\n });\n}\n"],"names":["sanitizePropName","name","cleaned","word","index","normalizedWord","firstChar","rest","generateQualifiedPropName","componentName","parentPath","baseName","validParentParts","part","findMinimalDistinguishingPath","thisPath","otherPaths","commonPrefixLength","maxCommonLength","p","i","thisPart","otherPath","distinguishingSuffix","suffixLength","thisSuffix","otherSuffix","arraysEqual","a","b","val","idx","getComponentPropType","componentType","_componentName","getComponentPropName","findSlidersAndDataBindings","pageData","sliders","traverse","node","path","slider","arrayContainer","findArrayContainer","containerNode","container","components","imageComponents","findDataComponents","comp","basePropName","propType","currentParentPath","isGenericFrame","child","c","imageComp","qualifyPropNames","imageName","compName","body","findStandaloneComponents","sliderIds","collectSliderIds","parentId","hasDataTag","currentId","findInputGroups","groupsMap","inputGroupTag","tag","parts","groupType","groupName","findForms","forms","parentContainer","isContainer","isNamedForm","hasSubmitAction","submitButtonId","checkForSubmitAction","n","inputs","findInputs","findStandaloneSelectInputs","selectInputs","formInputIds","form","input","qualifySelectInputs","findActionButtons","buttons","hasActionTag","hasActions","actionType","actionTag","qualifyActionButtons","qualifyFormInputs"],"mappings":"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"}
1
+ {"version":3,"file":"parser.js","sources":["../../src/codegen/parser.ts"],"sourcesContent":["import {\n ComponentInfo,\n SliderInfo,\n InputGroupInfo,\n FormInfo,\n SelectInputInfo,\n ActionButtonInfo,\n} from \"./types\";\nimport { qualifyPropNames } from \"./propQualification\";\n\n/**\n * Sanitizes a component name into a valid camelCase prop name\n *\n * Removes special characters, handles spaces, and converts to camelCase.\n *\n * @param name - Raw component name from Figma/design tool\n * @returns Valid JavaScript property name\n *\n * @example\n * sanitizePropName(\"My Component!\") // \"myComponent\"\n * sanitizePropName(\"user-name\") // \"userName\"\n */\nexport function sanitizePropName(name: string): string {\n // Convert to camelCase and remove invalid characters\n const cleaned = name\n .replace(/[^a-zA-Z0-9\\s]/g, \"\") // Remove special chars\n .trim();\n\n if (!cleaned) return \"item\";\n\n return cleaned\n .split(/\\s+/)\n .map((word, index) => {\n if (!word) return \"\";\n // Handle all-uppercase words (like \"SHOP\", \"NOW\") by lowercasing them first\n const normalizedWord =\n word === word.toUpperCase() && word.length > 1\n ? word.toLowerCase()\n : word;\n const firstChar = normalizedWord.charAt(0);\n const rest = normalizedWord.slice(1);\n if (index === 0) {\n return firstChar.toLowerCase() + rest;\n }\n return firstChar.toUpperCase() + rest;\n })\n .join(\"\")\n .replace(/^[0-9]/, \"_$&\"); // Prefix numbers with underscore\n}\n\nexport function generateQualifiedPropName(\n componentName: string,\n parentPath: string[]\n): string {\n // Start with the component's own name\n const baseName = sanitizePropName(componentName);\n\n // If no parent path, just return the base name\n if (parentPath.length === 0) {\n return baseName;\n }\n\n // Filter out empty parts and reverse so we build from root to leaf\n const validParentParts = parentPath\n .filter((part) => part && part.trim())\n .reverse();\n\n if (validParentParts.length === 0) {\n return baseName;\n }\n\n // Build qualified name: parent1Parent2ComponentName\n // Each parent part is sanitized individually, then combined\n const sanitizedParentParts = validParentParts.map((part) =>\n sanitizePropName(part)\n );\n\n // Join parent parts (all start uppercase) with base name (starts lowercase)\n const parentPrefix = sanitizedParentParts\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n\n return parentPrefix + baseName;\n}\n\n/**\n * Finds the minimal distinguishing path suffix for a component when compared to others.\n * Returns the shortest suffix (from root side, working towards leaf) that makes this path unique.\n *\n * The algorithm finds where paths first diverge from the root, then takes the minimal\n * distinguishing part from that divergence point towards the leaf.\n */\nexport function findMinimalDistinguishingPath(\n thisPath: string[],\n otherPaths: string[][]\n): string[] {\n if (otherPaths.length === 0) {\n // No other paths to compare, return empty (no qualification needed)\n return [];\n }\n\n // Find the longest common prefix (from root side)\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n thisPath.length,\n ...otherPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = thisPath[i];\n // Check if all other paths have the same part at this position\n const allMatch = otherPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // The distinguishing part starts after the common prefix\n const distinguishingSuffix = thisPath.slice(commonPrefixLength);\n\n // Now find the minimal suffix that's unique\n // Try progressively shorter suffixes (from root side) until we find one that's unique\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const thisSuffix = distinguishingSuffix.slice(0, suffixLength);\n\n // Check if this suffix is unique when combined with the common prefix\n const isUnique = otherPaths.every((otherPath) => {\n // If other path is shorter than common prefix + suffix, it can't match\n if (otherPath.length < commonPrefixLength + suffixLength) {\n return true; // Different length means unique\n }\n // Check if the suffix matches at the divergence point\n const otherSuffix = otherPath.slice(\n commonPrefixLength,\n commonPrefixLength + suffixLength\n );\n return !arraysEqual(thisSuffix, otherSuffix);\n });\n\n if (isUnique) {\n // Found minimal distinguishing suffix\n return thisSuffix;\n }\n }\n\n // If we get here, paths are identical (shouldn't happen, but handle it)\n return distinguishingSuffix;\n}\n\n/**\n * Helper to compare two arrays for equality\n */\nexport function arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n}\n\nexport function getComponentPropType(\n componentType: string,\n _componentName: string\n): string {\n if (componentType === \"component:image\") {\n return \"string\"; // imageUrl\n }\n if (componentType === \"component:text\") {\n return \"string\"; // text\n }\n if (componentType?.startsWith(\"component:input-\")) {\n // Input types generally return strings\n if (componentType === \"component:input-image\") {\n return \"string\"; // image URL\n }\n return \"string\"; // text inputs, email, password, etc.\n }\n if (\n componentType === \"component:webview\" ||\n componentType === \"component:web-view\"\n ) {\n return \"string\"; // url\n }\n if (componentType === \"component:video\") {\n return \"string\"; // videoUrl\n }\n if (componentType === \"component:video\") {\n return \"string\"; // videoUrl\n }\n if (componentType === \"component:embed\") {\n return \"React.ReactNode\";\n }\n // Default to any for unknown types\n return \"any\";\n}\n\nexport function getComponentPropName(componentType: string): string {\n if (componentType === \"component:image\") {\n return \"imageUrl\";\n }\n if (componentType === \"component:text\") {\n return \"text\";\n }\n if (\n componentType === \"component:webview\" ||\n componentType === \"component:web-view\"\n ) {\n return \"url\";\n }\n if (componentType === \"component:video\") {\n return \"videoUrl\";\n }\n return \"value\";\n}\n\nexport function findSlidersAndDataBindings(pageData: any): SliderInfo[] {\n const sliders: SliderInfo[] = [];\n\n function traverse(node: any, path: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a slider container\n if (node.type === \"container:slider\") {\n const slider: SliderInfo = {\n id: node.id,\n name: node.name || \"Slider\",\n arrayContainer: null,\n };\n\n // Recursively look for containers with encore:data:array tag inside the slider\n let arrayContainer: any = null;\n\n const findArrayContainer = (containerNode: any): void => {\n if (arrayContainer) return; // Already found one\n\n if (!containerNode || typeof containerNode !== \"object\") return;\n\n // Check if this node is the array container\n if (\n Array.isArray(containerNode.tags) &&\n (containerNode.tags.includes(\"encore:data:array\") ||\n containerNode.tags.includes(\"bravo:data:array\"))\n ) {\n arrayContainer = containerNode;\n return;\n }\n\n // Recursively search children\n if (containerNode.body && Array.isArray(containerNode.body)) {\n containerNode.body.forEach(findArrayContainer);\n }\n if (\n containerNode.containers &&\n Array.isArray(containerNode.containers)\n ) {\n containerNode.containers.forEach(findArrayContainer);\n }\n if (\n containerNode.components &&\n Array.isArray(containerNode.components)\n ) {\n containerNode.components.forEach(findArrayContainer);\n }\n };\n\n // Start search from the slider node itself (checking its children)\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(findArrayContainer);\n }\n // Also check components if they exist directly\n if (\n !arrayContainer &&\n node.components &&\n Array.isArray(node.components)\n ) {\n node.components.forEach(findArrayContainer);\n }\n\n if (arrayContainer) {\n const container = arrayContainer;\n let components: ComponentInfo[] = [];\n\n // Find all components with encore:data tag, and also image components\n const imageComponents: any[] = [];\n\n const findDataComponents = (\n comp: any,\n parentPath: string[] = []\n ): void => {\n if (!comp || typeof comp !== \"object\") return;\n\n // Track image components separately (they might not have encore:data tag)\n if (comp.type === \"component:image\") {\n imageComponents.push(comp);\n }\n\n if (\n Array.isArray(comp.tags) &&\n (comp.tags.includes(\"encore:data\") ||\n comp.tags.includes(\"bravo:data\"))\n ) {\n const basePropName = sanitizePropName(comp.name || \"item\");\n const propType = getComponentPropType(comp.type, comp.name);\n // const propKey = getComponentPropName(comp.type);\n\n components.push({\n id: comp.id,\n name: comp.name || \"Unnamed\",\n type: comp.type,\n tags: comp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n comp.name &&\n (comp.type?.startsWith(\"container:\") ||\n comp.type?.startsWith(\"component:\"))\n ) {\n const name = comp.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(comp.name);\n }\n }\n\n // Recursively search children\n if (comp.body && Array.isArray(comp.body)) {\n comp.body.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n if (comp.containers && Array.isArray(comp.containers)) {\n comp.containers.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n if (comp.components && Array.isArray(comp.components)) {\n comp.components.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n };\n\n if (container.components && Array.isArray(container.components)) {\n container.components.forEach((comp: any) =>\n findDataComponents(comp, [])\n );\n }\n\n // After finding all components, if we have image components but no image with encore:data,\n // add the first image component\n const hasImageWithData = components.some(\n (c) => c.type === \"component:image\"\n );\n if (!hasImageWithData && imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n // For image components, use \"imageUrl\" as the prop name\n // Clean the name first, then if it contains \"image\", just use \"imageUrl\"\n const rawName = (imageComp.name || \"image\").toLowerCase();\n const basePropName = rawName.includes(\"image\")\n ? \"imageUrl\"\n : sanitizePropName(imageComp.name || \"image\");\n components.push({\n id: imageComp.id,\n name: imageComp.name || \"Image\",\n type: imageComp.type,\n tags: imageComp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType: \"string\", // imageUrl is always string\n _parentPath: [],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Qualify duplicate prop names using minimal distinguishing paths\n qualifyPropNames(components);\n\n // If we have an image component, remove color components with similar names\n // (they're usually placeholders/backgrounds)\n if (imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n const imageName = (imageComp.name || \"\").toLowerCase();\n components = components.filter((comp) => {\n // Keep image components\n if (comp.type === \"component:image\") return true;\n // Remove color components that seem to be placeholders for images\n if (comp.type === \"component:color\") {\n const compName = (comp.name || \"\").toLowerCase();\n // If color component name is similar to image name, it's likely a placeholder\n if (imageName.includes(compName) || compName.includes(\"image\")) {\n return false;\n }\n }\n return true;\n });\n }\n\n slider.arrayContainer = {\n id: container.id,\n name: container.name || \"Item\",\n propName: sanitizePropName(container.name || \"items\"),\n components,\n };\n }\n\n sliders.push(slider);\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, [...path, \"body\"]));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, [...path, \"containers\"])\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, [...path, \"components\"])\n );\n }\n }\n\n // Start traversal from page data\n // Try multiple possible locations for the body\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return sliders;\n}\n\n/**\n * Finds standalone data-bound components (not in sliders)\n *\n * Locates components tagged with encore:data (but not encore:data:array)\n * for standalone data binding at the page level.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of component metadata\n */\nexport function findStandaloneComponents(pageData: any): ComponentInfo[] {\n const components: ComponentInfo[] = [];\n const sliderIds = new Set<string>();\n\n // First, collect all slider IDs to exclude their children\n function collectSliderIds(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"container:slider\") {\n sliderIds.add(node.id);\n }\n\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(collectSliderIds);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(collectSliderIds);\n }\n }\n\n // Traverse to find standalone components with bravo:data tags\n // Track parent component names for qualification\n function traverse(\n node: any,\n parentId?: string,\n parentPath: string[] = []\n ): void {\n if (!node || typeof node !== \"object\") return;\n\n // Skip if we're inside a slider\n if (parentId && sliderIds.has(parentId)) return;\n\n // Check if this component has bravo:data tag OR is an embed component\n const hasDataTag =\n Array.isArray(node.tags) &&\n (node.tags.includes(\"encore:data\") || node.tags.includes(\"bravo:data\"));\n\n if (\n node.type === \"component:embed\" ||\n node.type === \"component:webview\" ||\n node.type === \"component:web-view\" ||\n node.type === \"component:video\" ||\n (hasDataTag &&\n (node.type === \"component:text\" || node.type === \"component:image\"))\n ) {\n const basePropName = sanitizePropName(node.name || \"item\");\n const propType = getComponentPropType(node.type, node.name);\n\n components.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n type: node.type,\n tags: node.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n const currentId = node.id;\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach(collectSliderIds);\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names using minimal distinguishing paths\n qualifyPropNames(components);\n\n return components;\n}\n\n/**\n * Finds input groups (radio button-like components) in the page\n *\n * Locates stateful sets tagged with encore:input-group for coordinated\n * selection behavior.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of input group metadata\n */\nexport function findInputGroups(pageData: any): InputGroupInfo[] {\n const groupsMap = new Map<string, InputGroupInfo>();\n\n function traverse(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-stateful-set with input-group tag\n if (\n node.type === \"component:input-stateful-set\" &&\n Array.isArray(node.tags)\n ) {\n const inputGroupTag = node.tags.find((tag: string) =>\n tag.startsWith(\"input-group:\")\n );\n if (inputGroupTag) {\n const parts = inputGroupTag.split(\":\");\n if (parts.length >= 3) {\n const groupType = parts[1];\n const groupName = parts[2];\n\n if (!groupsMap.has(groupName)) {\n groupsMap.set(groupName, {\n groupName,\n groupType,\n elements: [],\n });\n }\n\n const group = groupsMap.get(groupName)!;\n group.elements.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n });\n }\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(traverse);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(traverse);\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach(traverse);\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return Array.from(groupsMap.values());\n}\n\n/**\n * Finds forms and their input fields in the page\n *\n * Locates containers tagged with encore:form and extracts all input\n * components within them for form submission handling.\n *\n * @param pageData - Page definition from Encore service\n * @returns Array of form metadata with input fields\n */\nexport function findForms(pageData: any): FormInfo[] {\n const forms: FormInfo[] = [];\n\n function traverse(node: any, parentContainer?: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a container that might be a form\n const isContainer =\n node.type?.startsWith(\"container:\") || node.type === \"container:default\";\n const isNamedForm =\n node.name?.toLowerCase().includes(\"form\") ||\n (Array.isArray(node.tags) && node.tags.includes(\"form\"));\n\n // Check if this container or any child has a submit action\n let hasSubmitAction = false;\n let submitButtonId: string | undefined;\n\n function checkForSubmitAction(n: any): void {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this node has a submit action\n if (\n Array.isArray(n.tags) &&\n (n.tags.includes(\"action:submit\") || n.tags.includes(\"submit\"))\n ) {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Check actions\n if (n.actions?.tap?.action === \"submit\") {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Recursively check children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach(checkForSubmitAction);\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach(checkForSubmitAction);\n }\n }\n\n // If this looks like a form container, check for submit actions\n if (isContainer && (isNamedForm || parentContainer === undefined)) {\n checkForSubmitAction(node);\n }\n\n // If we found a form container (has submit action or is named \"form\")\n if (isContainer && (hasSubmitAction || isNamedForm)) {\n const inputs: FormInfo[\"inputs\"] = [];\n\n // Find all input components within this container\n const findInputs = (n: any, parentPath: string[] = []): void => {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this is an input component\n if (\n n.type?.startsWith(\"component:input-\") ||\n n.type === \"component:input-text\" ||\n n.type === \"component:input-image\" ||\n n.type === \"component:input-email\" ||\n n.type === \"component:input-password\" ||\n n.type === \"component:input-select\"\n ) {\n const basePropName = sanitizePropName(n.name || \"Unnamed input\");\n inputs.push({\n id: n.id,\n name: n.name || \"Unnamed input\",\n type: n.type,\n propName: basePropName, // Will be qualified later if needed\n _parentPath: [...parentPath], // Store parent path for qualification\n });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n n.name &&\n (n.type?.startsWith(\"container:\") || n.type?.startsWith(\"component:\"))\n ) {\n const name = n.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(n.name);\n }\n }\n\n // Recursively search children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach((child: any) =>\n findInputs(child, currentParentPath)\n );\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach((child: any) => findInputs(child, currentParentPath));\n }\n };\n\n findInputs(node, []);\n\n // Only add form if it has inputs\n if (inputs.length > 0) {\n forms.push({\n formId: node.id,\n formName: node.name || \"Form\",\n submitButtonId,\n inputs,\n });\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return forms;\n}\n\n/**\n * Finds standalone select input components (input-select) that are NOT inside forms.\n * These should be exposed as controlled inputs with value and onChange props.\n */\nexport function findStandaloneSelectInputs(\n pageData: any,\n forms: FormInfo[]\n): SelectInputInfo[] {\n const selectInputs: SelectInputInfo[] = [];\n\n // Collect all input IDs that are already in forms\n const formInputIds = new Set<string>();\n forms.forEach((form) => {\n form.inputs.forEach((input) => {\n formInputIds.add(input.id);\n });\n });\n\n // Traverse to find input-select components not in forms\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-select component\n if (node.type === \"component:input-select\" && !formInputIds.has(node.id)) {\n const basePropName = sanitizePropName(node.name || \"selectInput\");\n selectInputs.push({\n id: node.id,\n name: node.name || \"Select Input\",\n propName: basePropName,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifySelectInputs(selectInputs);\n\n return selectInputs;\n}\n\n/**\n * Qualifies select input prop names to ensure uniqueness.\n */\nfunction qualifySelectInputs(selectInputs: SelectInputInfo[]): void {\n qualifyPropNames(selectInputs);\n}\n\n/**\n * Finds action buttons - components that have action tags (action:remote, action:link, etc.)\n * or have actions defined. These should be exposed with onClick handlers.\n */\nexport function findActionButtons(pageData: any): ActionButtonInfo[] {\n const buttons: ActionButtonInfo[] = [];\n\n console.log(\n \"[DEBUG] local encore-lib findActionButtons running via alias. Check node.actions support.\"\n );\n\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Log nodes with potentially interesting properties for debugging\n if (\n node.id === \"01KF5PAFFVFSKY6QJZXQTC99P5\" ||\n (node.tags && node.tags.some((t: string) => t.includes(\"action\")))\n ) {\n console.log(`[DEBUG] traverse node ${node.name} (${node.id})`, {\n type: node.type,\n tags: node.tags,\n hasActions: !!node.actions,\n actionsKeys: node.actions ? Object.keys(node.actions) : [],\n });\n }\n\n // Check if this component has an action tag or actions defined\n const hasActionTag =\n Array.isArray(node.tags) &&\n node.tags.some((tag: string) => tag.startsWith(\"action:\"));\n const hasActions = node.actions && typeof node.actions === \"object\";\n\n if (hasActionTag || hasActions) {\n // Determine the action type\n let actionType = \"tap\";\n if (Array.isArray(node.tags)) {\n const actionTag = node.tags.find((tag: string) =>\n tag.startsWith(\"action:\")\n );\n if (actionTag) {\n actionType = actionTag.replace(\"action:\", \"\");\n }\n }\n if (node.actions?.tap?.action) {\n actionType = node.actions.tap.action;\n }\n\n console.log(`[DEBUG] Found action button: ${node.name} (${node.id})`, {\n actionType,\n hasActionTag,\n hasActions,\n });\n\n const basePropName = sanitizePropName(node.name || \"button\");\n buttons.push({\n id: node.id,\n name: node.name || \"Button\",\n propName: basePropName,\n actionType,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifyActionButtons(buttons);\n\n return buttons;\n}\n\n/**\n * Qualifies action button prop names to ensure uniqueness.\n */\nfunction qualifyActionButtons(buttons: ActionButtonInfo[]): void {\n qualifyPropNames(buttons);\n}\n\n/**\n * Qualifies form input prop names to ensure uniqueness within each form.\n * Only qualifies where necessary, using minimal distinguishing paths.\n */\nexport function qualifyFormInputs(forms: FormInfo[]): void {\n forms.forEach((form) => {\n qualifyPropNames(form.inputs);\n });\n}\n"],"names":["sanitizePropName","name","cleaned","word","index","normalizedWord","firstChar","rest","generateQualifiedPropName","componentName","parentPath","baseName","validParentParts","part","findMinimalDistinguishingPath","thisPath","otherPaths","commonPrefixLength","maxCommonLength","p","i","thisPart","otherPath","distinguishingSuffix","suffixLength","thisSuffix","otherSuffix","arraysEqual","a","b","val","idx","getComponentPropType","componentType","_componentName","getComponentPropName","findSlidersAndDataBindings","pageData","sliders","traverse","node","path","slider","arrayContainer","findArrayContainer","containerNode","container","components","imageComponents","findDataComponents","comp","basePropName","propType","currentParentPath","isGenericFrame","child","c","imageComp","qualifyPropNames","imageName","compName","body","findStandaloneComponents","sliderIds","collectSliderIds","parentId","hasDataTag","currentId","findInputGroups","groupsMap","inputGroupTag","tag","parts","groupType","groupName","findForms","forms","parentContainer","isContainer","isNamedForm","hasSubmitAction","submitButtonId","checkForSubmitAction","n","inputs","findInputs","findStandaloneSelectInputs","selectInputs","formInputIds","form","input","qualifySelectInputs","findActionButtons","buttons","t","hasActionTag","hasActions","actionType","actionTag","qualifyActionButtons","qualifyFormInputs"],"mappings":"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"}