@bravostudioai/react 0.1.30 → 0.1.32

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.
Files changed (72) hide show
  1. package/dist/cli/commands/generate.js +69 -65
  2. package/dist/cli/commands/generate.js.map +1 -1
  3. package/dist/codegen/generator.js.map +1 -1
  4. package/dist/codegen/parser.js +256 -593
  5. package/dist/codegen/parser.js.map +1 -1
  6. package/dist/codegen/propQualification.js +117 -0
  7. package/dist/codegen/propQualification.js.map +1 -0
  8. package/dist/components/DynamicComponent.js.map +1 -1
  9. package/dist/components/EncoreApp.js +142 -275
  10. package/dist/components/EncoreApp.js.map +1 -1
  11. package/dist/components/EncoreContextProviders.js +24 -0
  12. package/dist/components/EncoreContextProviders.js.map +1 -0
  13. package/dist/components.js +179 -174
  14. package/dist/components.js.map +1 -1
  15. package/dist/hooks/useFontLoader.js +41 -0
  16. package/dist/hooks/useFontLoader.js.map +1 -0
  17. package/dist/hooks/usePusherUpdates.js +41 -45
  18. package/dist/hooks/usePusherUpdates.js.map +1 -1
  19. package/dist/hooks/useRepeatingContainers.js +79 -0
  20. package/dist/hooks/useRepeatingContainers.js.map +1 -0
  21. package/dist/index.js +13 -14
  22. package/dist/index.js.map +1 -1
  23. package/dist/lib/dataPatching.js +24 -0
  24. package/dist/lib/dataPatching.js.map +1 -0
  25. package/dist/lib/dynamicModules.js +44 -45
  26. package/dist/lib/dynamicModules.js.map +1 -1
  27. package/dist/lib/fetcher.js +6 -13
  28. package/dist/lib/fetcher.js.map +1 -1
  29. package/dist/lib/logger.js +35 -0
  30. package/dist/lib/logger.js.map +1 -0
  31. package/dist/lib/moduleRegistry.js +9 -8
  32. package/dist/lib/moduleRegistry.js.map +1 -1
  33. package/dist/src/cli/commands/generate.d.ts.map +1 -1
  34. package/dist/src/codegen/generator.d.ts +74 -0
  35. package/dist/src/codegen/generator.d.ts.map +1 -1
  36. package/dist/src/codegen/parser.d.ts +39 -0
  37. package/dist/src/codegen/parser.d.ts.map +1 -1
  38. package/dist/src/codegen/propQualification.d.ts +42 -0
  39. package/dist/src/codegen/propQualification.d.ts.map +1 -0
  40. package/dist/src/components/DynamicComponent.d.ts +1 -1
  41. package/dist/src/components/DynamicComponent.d.ts.map +1 -1
  42. package/dist/src/components/EncoreApp.d.ts +55 -2
  43. package/dist/src/components/EncoreApp.d.ts.map +1 -1
  44. package/dist/src/components/EncoreContextProviders.d.ts +34 -0
  45. package/dist/src/components/EncoreContextProviders.d.ts.map +1 -0
  46. package/dist/src/components.d.ts.map +1 -1
  47. package/dist/src/hooks/useFontLoader.d.ts +17 -0
  48. package/dist/src/hooks/useFontLoader.d.ts.map +1 -0
  49. package/dist/src/hooks/usePusherUpdates.d.ts.map +1 -1
  50. package/dist/src/hooks/useRepeatingContainers.d.ts +31 -0
  51. package/dist/src/hooks/useRepeatingContainers.d.ts.map +1 -0
  52. package/dist/src/index.d.ts +2 -0
  53. package/dist/src/index.d.ts.map +1 -1
  54. package/dist/src/lib/dataPatching.d.ts +18 -0
  55. package/dist/src/lib/dataPatching.d.ts.map +1 -0
  56. package/dist/src/lib/dynamicModules.d.ts.map +1 -1
  57. package/dist/src/lib/fetcher.d.ts.map +1 -1
  58. package/dist/src/lib/logger.d.ts +33 -0
  59. package/dist/src/lib/logger.d.ts.map +1 -0
  60. package/dist/src/lib/moduleRegistry.d.ts.map +1 -1
  61. package/dist/src/stores/useEncoreState.d.ts +43 -1
  62. package/dist/src/stores/useEncoreState.d.ts.map +1 -1
  63. package/dist/src/version.d.ts +1 -1
  64. package/dist/stores/useEncoreState.js.map +1 -1
  65. package/dist/version.js +1 -1
  66. package/dist/version.js.map +1 -1
  67. package/package.json +1 -1
  68. package/src/cli/commands/generate.ts +7 -2
  69. package/src/components/DynamicComponent.tsx +1 -1
  70. package/src/components.tsx +6 -1
  71. package/src/hooks/useRepeatingContainers.ts +1 -1
  72. package/src/version.ts +1 -1
@@ -0,0 +1,41 @@
1
+ import { useEffect as d } from "react";
2
+ import { logger as n } from "../lib/logger.js";
3
+ function g(s) {
4
+ d(() => {
5
+ const e = s?.app?.fonts ?? [];
6
+ n.debug("Font loading check", { fontCount: e?.length || 0 }), !(!e || e.length === 0) && (typeof window > "u" || !("FontFace" in window) || e.forEach((r) => {
7
+ try {
8
+ const o = r?.fontName?.family, t = r?.url, a = r?.fontName?.postScriptName;
9
+ if (!o || !t) return;
10
+ if (r.broken) {
11
+ n.warn("Skipping broken font", {
12
+ font: a || o,
13
+ url: t
14
+ });
15
+ return;
16
+ }
17
+ const c = a || o;
18
+ new FontFace(c, `url(${t})`, {
19
+ weight: "100 900",
20
+ style: "normal"
21
+ }).load().then((f) => {
22
+ document.fonts.add(f), n.debug("Font loaded", { familyName: c, url: t });
23
+ const i = document.fonts.check(`400 12px "${c}"`);
24
+ n.debug("Font check result", { familyName: c, isCheckPassed: i });
25
+ }).catch((f) => {
26
+ n.warn("Failed to load font", {
27
+ font: a || o,
28
+ url: t,
29
+ error: f.message
30
+ });
31
+ });
32
+ } catch (o) {
33
+ n.warn("Error processing font", o);
34
+ }
35
+ }));
36
+ }, [s]);
37
+ }
38
+ export {
39
+ g as useFontLoader
40
+ };
41
+ //# sourceMappingURL=useFontLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFontLoader.js","sources":["../../src/hooks/useFontLoader.ts"],"sourcesContent":["/**\n * Custom hook for loading fonts from app definition\n *\n * Handles FontFace API loading of custom fonts declared in the app JSON.\n * Skips fonts marked as broken and provides debug logging in development.\n */\n\nimport { useEffect } from \"react\";\nimport logger from \"../lib/logger\";\n\ninterface EncoreFont {\n id?: string;\n url?: string;\n broken?: boolean;\n fontName?: { family?: string; postScriptName?: string };\n}\n\ninterface AppDataWithFonts {\n app?: { fonts?: EncoreFont[] };\n}\n\n/**\n * Loads fonts declared in app definition using the FontFace API\n *\n * @param appData - App definition containing fonts array\n *\n * @example\n * const { data: appData } = useSWR(appUrl, fetcher);\n * useFontLoader(appData);\n */\nexport function useFontLoader(appData: unknown) {\n useEffect(() => {\n const fonts: EncoreFont[] =\n (appData as AppDataWithFonts | undefined)?.app?.fonts ?? [];\n\n logger.debug('Font loading check', { fontCount: fonts?.length || 0 });\n\n if (!fonts || fonts.length === 0) return;\n if (typeof window === \"undefined\" || !(\"FontFace\" in window)) return;\n\n fonts.forEach((f) => {\n try {\n const family = f?.fontName?.family;\n const url = f?.url;\n const postScriptName = f?.fontName?.postScriptName;\n\n if (!family || !url) return;\n\n if (f.broken) {\n logger.warn('Skipping broken font', {\n font: postScriptName || family,\n url\n });\n return;\n }\n\n const familyName = postScriptName || family;\n const fontFace = new FontFace(familyName, `url(${url})`, {\n weight: \"100 900\",\n style: \"normal\",\n });\n\n fontFace\n .load()\n .then((ff) => {\n document.fonts.add(ff);\n logger.debug('Font loaded', { familyName, url });\n\n const isCheckPassed = document.fonts.check(`400 12px \"${familyName}\"`);\n logger.debug('Font check result', { familyName, isCheckPassed });\n })\n .catch((err) => {\n logger.warn('Failed to load font', {\n font: postScriptName || family,\n url,\n error: err.message\n });\n });\n } catch (err) {\n logger.warn('Error processing font', err);\n }\n });\n }, [appData]);\n}\n"],"names":["useFontLoader","appData","useEffect","fonts","logger","f","family","url","postScriptName","familyName","ff","isCheckPassed","err"],"mappings":";;AA8BO,SAASA,EAAcC,GAAkB;AAC9C,EAAAC,EAAU,MAAM;AACd,UAAMC,IACHF,GAA0C,KAAK,SAAS,CAAA;AAI3D,IAFAG,EAAO,MAAM,sBAAsB,EAAE,WAAWD,GAAO,UAAU,GAAG,GAEhE,GAACA,KAASA,EAAM,WAAW,OAC3B,OAAO,SAAW,OAAe,EAAE,cAAc,WAErDA,EAAM,QAAQ,CAACE,MAAM;AACnB,UAAI;AACF,cAAMC,IAASD,GAAG,UAAU,QACtBE,IAAMF,GAAG,KACTG,IAAiBH,GAAG,UAAU;AAEpC,YAAI,CAACC,KAAU,CAACC,EAAK;AAErB,YAAIF,EAAE,QAAQ;AACZ,UAAAD,EAAO,KAAK,wBAAwB;AAAA,YAClC,MAAMI,KAAkBF;AAAA,YACxB,KAAAC;AAAA,UAAA,CACD;AACD;AAAA,QACF;AAEA,cAAME,IAAaD,KAAkBF;AAMrC,QALiB,IAAI,SAASG,GAAY,OAAOF,CAAG,KAAK;AAAA,UACvD,QAAQ;AAAA,UACR,OAAO;AAAA,QAAA,CACR,EAGE,KAAA,EACA,KAAK,CAACG,MAAO;AACZ,mBAAS,MAAM,IAAIA,CAAE,GACrBN,EAAO,MAAM,eAAe,EAAE,YAAAK,GAAY,KAAAF,GAAK;AAE/C,gBAAMI,IAAgB,SAAS,MAAM,MAAM,aAAaF,CAAU,GAAG;AACrE,UAAAL,EAAO,MAAM,qBAAqB,EAAE,YAAAK,GAAY,eAAAE,GAAe;AAAA,QACjE,CAAC,EACA,MAAM,CAACC,MAAQ;AACd,UAAAR,EAAO,KAAK,uBAAuB;AAAA,YACjC,MAAMI,KAAkBF;AAAA,YACxB,KAAAC;AAAA,YACA,OAAOK,EAAI;AAAA,UAAA,CACZ;AAAA,QACH,CAAC;AAAA,MACL,SAASA,GAAK;AACZ,QAAAR,EAAO,KAAK,yBAAyBQ,CAAG;AAAA,MAC1C;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACX,CAAO,CAAC;AACd;"}
@@ -1,62 +1,58 @@
1
- import { useRef as m, useEffect as g } from "react";
2
- import P from "pusher-js";
3
- import { clearModuleCache as v } from "../lib/moduleRegistry.js";
4
- import { j as t } from "../node_modules/swr/dist/_internal/config-context-12s-Dh3trQsc.js";
5
- const y = () => ({
1
+ import { useRef as g, useEffect as $ } from "react";
2
+ import v from "pusher-js";
3
+ import { clearModuleCache as y } from "../lib/moduleRegistry.js";
4
+ import { logger as n } from "../lib/logger.js";
5
+ import { j as o } from "../node_modules/swr/dist/_internal/config-context-12s-Dh3trQsc.js";
6
+ const U = () => ({
6
7
  key: "7b0611d0051677eed996",
7
8
  cluster: "us2",
8
9
  encrypted: !0
9
10
  });
10
- function R({
11
- appId: n,
11
+ function C({
12
+ appId: c,
12
13
  pageId: s,
13
- enabled: h = !0,
14
- onUpdate: f
14
+ enabled: d = !0,
15
+ onUpdate: p
15
16
  }) {
16
- const e = m(null), c = m(null);
17
- return g(() => {
18
- if (!h || !n || !s)
17
+ const e = g(null), u = g(null);
18
+ return $(() => {
19
+ if (!d || !c || !s)
19
20
  return;
20
- const u = y(), p = new P(u.key, {
21
- cluster: u.cluster,
22
- forceTLS: u.encrypted
21
+ const i = U(), b = new v(i.key, {
22
+ cluster: i.cluster,
23
+ forceTLS: i.encrypted
23
24
  });
24
- e.current = p;
25
- const r = `${n}`;
26
- console.log(`[Pusher] Subscribing to channel: ${r}`);
27
- const o = p.subscribe(r);
28
- c.current = o, o.bind("pusher:subscription_succeeded", () => {
29
- console.log(
30
- `[Pusher] Successfully subscribed to channel: ${r}`
31
- );
32
- }), o.bind("pusher:subscription_error", (i) => {
33
- console.error(
34
- `[Pusher] Subscription error for channel ${r}:`,
35
- i
36
- );
25
+ e.current = b;
26
+ const r = `${c}`;
27
+ n.debug("Subscribing to Pusher channel", { channelName: r });
28
+ const t = b.subscribe(r);
29
+ u.current = t, t.bind("pusher:subscription_succeeded", () => {
30
+ n.debug("Pusher subscription succeeded", { channelName: r });
31
+ }), t.bind("pusher:subscription_error", (l) => {
32
+ n.error("Pusher subscription error", { channelName: r, status: l });
37
33
  });
38
- const l = (i) => {
39
- console.log(`[Pusher] Update received for ${r}:`, i);
40
- const $ = `${n}/draft/components/${s}`;
41
- v($);
42
- const d = `/devices/apps/${n}`, b = `/devices/apps/${n}/node/${s}`;
43
- t(d).catch((a) => {
44
- console.error("[Pusher] Error invalidating app cache:", a);
45
- }), t(b).catch((a) => {
46
- console.error("[Pusher] Error invalidating page cache:", a);
47
- }), t(`${d}?useLocal=1`).catch(() => {
48
- }), t(`${b}?useLocal=1`).catch(() => {
49
- }), f?.();
34
+ const a = (l) => {
35
+ n.debug("Pusher update received", { channelName: r, data: l });
36
+ const P = `${c}/draft/components/${s}`;
37
+ y(P);
38
+ const f = `/devices/apps/${c}`, m = `/devices/apps/${c}/node/${s}`;
39
+ o(f).catch((h) => {
40
+ n.error("Error invalidating app cache", h);
41
+ }), o(m).catch((h) => {
42
+ n.error("Error invalidating page cache", h);
43
+ }), o(`${f}?useLocal=1`).catch(() => {
44
+ }), o(`${m}?useLocal=1`).catch(() => {
45
+ }), p?.();
50
46
  };
51
- return o.bind("update", l), o.bind("component-updated", l), o.bind("app-updated", l), () => {
52
- console.log(`[Pusher] Unsubscribing from channel: ${r}`), c.current && c.current.unbind_all(), c.current && e.current && e.current.unsubscribe(r), e.current && (e.current.disconnect(), e.current = null), c.current = null;
47
+ return t.bind("update", a), t.bind("component-updated", a), t.bind("app-updated", a), () => {
48
+ n.debug("Unsubscribing from Pusher channel", { channelName: r }), u.current && u.current.unbind_all(), u.current && e.current && e.current.unsubscribe(r), e.current && (e.current.disconnect(), e.current = null), u.current = null;
53
49
  };
54
- }, [n, s, h, f]), {
55
- channel: c.current,
50
+ }, [c, s, d, p]), {
51
+ channel: u.current,
56
52
  pusher: e.current
57
53
  };
58
54
  }
59
55
  export {
60
- R as usePusherUpdates
56
+ C as usePusherUpdates
61
57
  };
62
58
  //# sourceMappingURL=usePusherUpdates.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usePusherUpdates.js","sources":["../../src/hooks/usePusherUpdates.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useRef } from \"react\";\n\nimport Pusher from \"pusher-js\";\nimport { mutate } from \"swr\";\nimport { clearModuleCache } from \"../lib/moduleRegistry\";\n\ntype PusherConfig = {\n key?: string;\n cluster?: string;\n encrypted?: boolean;\n};\n\ntype UsePusherUpdatesOptions = {\n appId: string;\n pageId?: string;\n enabled?: boolean;\n onUpdate?: () => void;\n};\n\n// Get Pusher config from environment variables\nconst getPusherConfig = (): PusherConfig => {\n return {\n key: \"7b0611d0051677eed996\",\n cluster: \"us2\",\n encrypted: true,\n };\n};\n\n/**\n * Hook to listen for EncoreApp component updates via Pusher\n * Channel name format: `${appId}-${pageId}`\n * When an update event is received, it invalidates SWR cache and triggers a reload\n */\nexport function usePusherUpdates({\n appId,\n pageId,\n enabled = true,\n onUpdate,\n}: UsePusherUpdatesOptions) {\n const pusherRef = useRef<Pusher | null>(null);\n const channelRef = useRef<ReturnType<Pusher[\"subscribe\"]> | null>(null);\n\n useEffect(() => {\n // Only connect if enabled and we have both appId and pageId\n if (!enabled || !appId || !pageId) {\n return;\n }\n\n const config = getPusherConfig();\n\n // Skip if Pusher key is not configured\n if (!config.key) {\n console.warn(\"[Pusher] not configured. Pusher updates disabled.\");\n return;\n }\n\n // Initialize Pusher\n const pusher = new Pusher(config.key, {\n cluster: config.cluster || \"us2\",\n forceTLS: config.encrypted,\n });\n\n pusherRef.current = pusher;\n\n // Channel name format: appId-pageId (e.g., \"01KA23JMNBQ2V9NR7K0VXKT5TF-01KA23JMPBZSG2YRJ6M5X87SKJ\")\n const channelName = `${appId}`;\n console.log(`[Pusher] Subscribing to channel: ${channelName}`);\n\n // Subscribe to the channel\n const channel = pusher.subscribe(channelName);\n channelRef.current = channel;\n\n // Handle subscription success\n channel.bind(\"pusher:subscription_succeeded\", () => {\n console.log(\n `[Pusher] Successfully subscribed to channel: ${channelName}`\n );\n });\n\n // Handle subscription error\n channel.bind(\"pusher:subscription_error\", (status: number) => {\n console.error(\n `[Pusher] Subscription error for channel ${channelName}:`,\n status\n );\n });\n\n // Listen for update events\n // You can customize the event name based on your backend's Pusher event names\n // Common event names: 'update', 'component-updated', 'app-updated', etc.\n const handleUpdate = (data: unknown) => {\n console.log(`[Pusher] Update received for ${channelName}:`, data);\n\n // Clear the module cache for the component to force reload\n const componentName = `${appId}/draft/components/${pageId}`;\n clearModuleCache(componentName);\n\n // Invalidate SWR cache for both app and page data\n const appUrl = `/devices/apps/${appId}`;\n const pageUrl = `/devices/apps/${appId}/node/${pageId}`;\n\n // Mutate both URLs to trigger refetch\n mutate(appUrl).catch((err) => {\n console.error(\"[Pusher] Error invalidating app cache:\", err);\n });\n mutate(pageUrl).catch((err) => {\n console.error(\"[Pusher] Error invalidating page cache:\", err);\n });\n\n // Also invalidate URLs with useLocal query param if they exist\n mutate(`${appUrl}?useLocal=1`).catch(() => {\n // Ignore errors for optional URLs\n });\n mutate(`${pageUrl}?useLocal=1`).catch(() => {\n // Ignore errors for optional URLs\n });\n\n // Call the onUpdate callback if provided\n onUpdate?.();\n };\n\n // Bind to update events\n // Adjust the event name(s) based on what your backend sends\n channel.bind(\"update\", handleUpdate);\n channel.bind(\"component-updated\", handleUpdate);\n channel.bind(\"app-updated\", handleUpdate);\n\n // Cleanup function\n return () => {\n console.log(`[Pusher] Unsubscribing from channel: ${channelName}`);\n\n // Unbind all event handlers\n if (channelRef.current) {\n channelRef.current.unbind_all();\n }\n\n // Unsubscribe from channel\n if (channelRef.current && pusherRef.current) {\n pusherRef.current.unsubscribe(channelName);\n }\n\n // Disconnect Pusher if no other channels are subscribed\n if (pusherRef.current) {\n pusherRef.current.disconnect();\n pusherRef.current = null;\n }\n\n channelRef.current = null;\n };\n }, [appId, pageId, enabled, onUpdate]);\n\n // Return channel ref for advanced usage\n return {\n channel: channelRef.current,\n pusher: pusherRef.current,\n };\n}\n"],"names":["getPusherConfig","usePusherUpdates","appId","pageId","enabled","onUpdate","pusherRef","useRef","channelRef","useEffect","config","pusher","Pusher","channelName","channel","status","handleUpdate","data","componentName","clearModuleCache","appUrl","pageUrl","mutate","err"],"mappings":";;;;AAqBA,MAAMA,IAAkB,OACf;AAAA,EACL,KAAK;AAAA,EACL,SAAS;AAAA,EACT,WAAW;AAAA;AASR,SAASC,EAAiB;AAAA,EAC/B,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,UAAAC;AACF,GAA4B;AAC1B,QAAMC,IAAYC,EAAsB,IAAI,GACtCC,IAAaD,EAA+C,IAAI;AAEtE,SAAAE,EAAU,MAAM;AAEd,QAAI,CAACL,KAAW,CAACF,KAAS,CAACC;AACzB;AAGF,UAAMO,IAASV,EAAA,GASTW,IAAS,IAAIC,EAAOF,EAAO,KAAK;AAAA,MACpC,SAASA,EAAO;AAAA,MAChB,UAAUA,EAAO;AAAA,IAAA,CAClB;AAED,IAAAJ,EAAU,UAAUK;AAGpB,UAAME,IAAc,GAAGX,CAAK;AAC5B,YAAQ,IAAI,oCAAoCW,CAAW,EAAE;AAG7D,UAAMC,IAAUH,EAAO,UAAUE,CAAW;AAC5C,IAAAL,EAAW,UAAUM,GAGrBA,EAAQ,KAAK,iCAAiC,MAAM;AAClD,cAAQ;AAAA,QACN,gDAAgDD,CAAW;AAAA,MAAA;AAAA,IAE/D,CAAC,GAGDC,EAAQ,KAAK,6BAA6B,CAACC,MAAmB;AAC5D,cAAQ;AAAA,QACN,2CAA2CF,CAAW;AAAA,QACtDE;AAAA,MAAA;AAAA,IAEJ,CAAC;AAKD,UAAMC,IAAe,CAACC,MAAkB;AACtC,cAAQ,IAAI,gCAAgCJ,CAAW,KAAKI,CAAI;AAGhE,YAAMC,IAAgB,GAAGhB,CAAK,qBAAqBC,CAAM;AACzD,MAAAgB,EAAiBD,CAAa;AAG9B,YAAME,IAAS,iBAAiBlB,CAAK,IAC/BmB,IAAU,iBAAiBnB,CAAK,SAASC,CAAM;AAGrD,MAAAmB,EAAOF,CAAM,EAAE,MAAM,CAACG,MAAQ;AAC5B,gBAAQ,MAAM,0CAA0CA,CAAG;AAAA,MAC7D,CAAC,GACDD,EAAOD,CAAO,EAAE,MAAM,CAACE,MAAQ;AAC7B,gBAAQ,MAAM,2CAA2CA,CAAG;AAAA,MAC9D,CAAC,GAGDD,EAAO,GAAGF,CAAM,aAAa,EAAE,MAAM,MAAM;AAAA,MAE3C,CAAC,GACDE,EAAO,GAAGD,CAAO,aAAa,EAAE,MAAM,MAAM;AAAA,MAE5C,CAAC,GAGDhB,IAAA;AAAA,IACF;AAIA,WAAAS,EAAQ,KAAK,UAAUE,CAAY,GACnCF,EAAQ,KAAK,qBAAqBE,CAAY,GAC9CF,EAAQ,KAAK,eAAeE,CAAY,GAGjC,MAAM;AACX,cAAQ,IAAI,wCAAwCH,CAAW,EAAE,GAG7DL,EAAW,WACbA,EAAW,QAAQ,WAAA,GAIjBA,EAAW,WAAWF,EAAU,WAClCA,EAAU,QAAQ,YAAYO,CAAW,GAIvCP,EAAU,YACZA,EAAU,QAAQ,WAAA,GAClBA,EAAU,UAAU,OAGtBE,EAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG,CAACN,GAAOC,GAAQC,GAASC,CAAQ,CAAC,GAG9B;AAAA,IACL,SAASG,EAAW;AAAA,IACpB,QAAQF,EAAU;AAAA,EAAA;AAEtB;"}
1
+ {"version":3,"file":"usePusherUpdates.js","sources":["../../src/hooks/usePusherUpdates.ts"],"sourcesContent":["\"use client\";\nimport { useEffect, useRef } from \"react\";\n\nimport Pusher from \"pusher-js\";\nimport { mutate } from \"swr\";\nimport { clearModuleCache } from \"../lib/moduleRegistry\";\nimport logger from \"../lib/logger\";\n\ntype PusherConfig = {\n key?: string;\n cluster?: string;\n encrypted?: boolean;\n};\n\ntype UsePusherUpdatesOptions = {\n appId: string;\n pageId?: string;\n enabled?: boolean;\n onUpdate?: () => void;\n};\n\n// Get Pusher config from environment variables\nconst getPusherConfig = (): PusherConfig => {\n return {\n key: \"7b0611d0051677eed996\",\n cluster: \"us2\",\n encrypted: true,\n };\n};\n\n/**\n * Hook to listen for EncoreApp component updates via Pusher\n * Channel name format: `${appId}-${pageId}`\n * When an update event is received, it invalidates SWR cache and triggers a reload\n */\nexport function usePusherUpdates({\n appId,\n pageId,\n enabled = true,\n onUpdate,\n}: UsePusherUpdatesOptions) {\n const pusherRef = useRef<Pusher | null>(null);\n const channelRef = useRef<ReturnType<Pusher[\"subscribe\"]> | null>(null);\n\n useEffect(() => {\n // Only connect if enabled and we have both appId and pageId\n if (!enabled || !appId || !pageId) {\n return;\n }\n\n const config = getPusherConfig();\n\n // Skip if Pusher key is not configured\n if (!config.key) {\n logger.warn('Pusher not configured - real-time updates disabled');\n return;\n }\n\n // Initialize Pusher\n const pusher = new Pusher(config.key, {\n cluster: config.cluster || \"us2\",\n forceTLS: config.encrypted,\n });\n\n pusherRef.current = pusher;\n\n // Channel name format: appId (e.g., \"01KA23JMNBQ2V9NR7K0VXKT5TF\")\n const channelName = `${appId}`;\n logger.debug('Subscribing to Pusher channel', { channelName });\n\n // Subscribe to the channel\n const channel = pusher.subscribe(channelName);\n channelRef.current = channel;\n\n // Handle subscription success\n channel.bind(\"pusher:subscription_succeeded\", () => {\n logger.debug('Pusher subscription succeeded', { channelName });\n });\n\n // Handle subscription error\n channel.bind(\"pusher:subscription_error\", (status: number) => {\n logger.error('Pusher subscription error', { channelName, status });\n });\n\n // Listen for update events\n // Common event names: 'update', 'component-updated', 'app-updated'\n const handleUpdate = (data: unknown) => {\n logger.debug('Pusher update received', { channelName, data });\n\n // Clear the module cache for the component to force reload\n const componentName = `${appId}/draft/components/${pageId}`;\n clearModuleCache(componentName);\n\n // Invalidate SWR cache for both app and page data\n const appUrl = `/devices/apps/${appId}`;\n const pageUrl = `/devices/apps/${appId}/node/${pageId}`;\n\n // Mutate both URLs to trigger refetch\n mutate(appUrl).catch((err) => {\n logger.error('Error invalidating app cache', err);\n });\n mutate(pageUrl).catch((err) => {\n logger.error('Error invalidating page cache', err);\n });\n\n // Also invalidate URLs with useLocal query param\n mutate(`${appUrl}?useLocal=1`).catch(() => {});\n mutate(`${pageUrl}?useLocal=1`).catch(() => {});\n\n // Call the onUpdate callback if provided\n onUpdate?.();\n };\n\n // Bind to update events\n // Adjust the event name(s) based on what your backend sends\n channel.bind(\"update\", handleUpdate);\n channel.bind(\"component-updated\", handleUpdate);\n channel.bind(\"app-updated\", handleUpdate);\n\n // Cleanup function\n return () => {\n logger.debug('Unsubscribing from Pusher channel', { channelName });\n\n // Unbind all event handlers\n if (channelRef.current) {\n channelRef.current.unbind_all();\n }\n\n // Unsubscribe from channel\n if (channelRef.current && pusherRef.current) {\n pusherRef.current.unsubscribe(channelName);\n }\n\n // Disconnect Pusher if no other channels are subscribed\n if (pusherRef.current) {\n pusherRef.current.disconnect();\n pusherRef.current = null;\n }\n\n channelRef.current = null;\n };\n }, [appId, pageId, enabled, onUpdate]);\n\n // Return channel ref for advanced usage\n return {\n channel: channelRef.current,\n pusher: pusherRef.current,\n };\n}\n"],"names":["getPusherConfig","usePusherUpdates","appId","pageId","enabled","onUpdate","pusherRef","useRef","channelRef","useEffect","config","pusher","Pusher","channelName","logger","channel","status","handleUpdate","data","componentName","clearModuleCache","appUrl","pageUrl","mutate","err"],"mappings":";;;;;AAsBA,MAAMA,IAAkB,OACf;AAAA,EACL,KAAK;AAAA,EACL,SAAS;AAAA,EACT,WAAW;AAAA;AASR,SAASC,EAAiB;AAAA,EAC/B,OAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,UAAAC;AACF,GAA4B;AAC1B,QAAMC,IAAYC,EAAsB,IAAI,GACtCC,IAAaD,EAA+C,IAAI;AAEtE,SAAAE,EAAU,MAAM;AAEd,QAAI,CAACL,KAAW,CAACF,KAAS,CAACC;AACzB;AAGF,UAAMO,IAASV,EAAA,GASTW,IAAS,IAAIC,EAAOF,EAAO,KAAK;AAAA,MACpC,SAASA,EAAO;AAAA,MAChB,UAAUA,EAAO;AAAA,IAAA,CAClB;AAED,IAAAJ,EAAU,UAAUK;AAGpB,UAAME,IAAc,GAAGX,CAAK;AAC5B,IAAAY,EAAO,MAAM,iCAAiC,EAAE,aAAAD,EAAA,CAAa;AAG7D,UAAME,IAAUJ,EAAO,UAAUE,CAAW;AAC5C,IAAAL,EAAW,UAAUO,GAGrBA,EAAQ,KAAK,iCAAiC,MAAM;AAClD,MAAAD,EAAO,MAAM,iCAAiC,EAAE,aAAAD,EAAA,CAAa;AAAA,IAC/D,CAAC,GAGDE,EAAQ,KAAK,6BAA6B,CAACC,MAAmB;AAC5D,MAAAF,EAAO,MAAM,6BAA6B,EAAE,aAAAD,GAAa,QAAAG,GAAQ;AAAA,IACnE,CAAC;AAID,UAAMC,IAAe,CAACC,MAAkB;AACtC,MAAAJ,EAAO,MAAM,0BAA0B,EAAE,aAAAD,GAAa,MAAAK,GAAM;AAG5D,YAAMC,IAAgB,GAAGjB,CAAK,qBAAqBC,CAAM;AACzD,MAAAiB,EAAiBD,CAAa;AAG9B,YAAME,IAAS,iBAAiBnB,CAAK,IAC/BoB,IAAU,iBAAiBpB,CAAK,SAASC,CAAM;AAGrD,MAAAoB,EAAOF,CAAM,EAAE,MAAM,CAACG,MAAQ;AAC5B,QAAAV,EAAO,MAAM,gCAAgCU,CAAG;AAAA,MAClD,CAAC,GACDD,EAAOD,CAAO,EAAE,MAAM,CAACE,MAAQ;AAC7B,QAAAV,EAAO,MAAM,iCAAiCU,CAAG;AAAA,MACnD,CAAC,GAGDD,EAAO,GAAGF,CAAM,aAAa,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC,GAC7CE,EAAO,GAAGD,CAAO,aAAa,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC,GAG9CjB,IAAA;AAAA,IACF;AAIA,WAAAU,EAAQ,KAAK,UAAUE,CAAY,GACnCF,EAAQ,KAAK,qBAAqBE,CAAY,GAC9CF,EAAQ,KAAK,eAAeE,CAAY,GAGjC,MAAM;AACX,MAAAH,EAAO,MAAM,qCAAqC,EAAE,aAAAD,EAAA,CAAa,GAG7DL,EAAW,WACbA,EAAW,QAAQ,WAAA,GAIjBA,EAAW,WAAWF,EAAU,WAClCA,EAAU,QAAQ,YAAYO,CAAW,GAIvCP,EAAU,YACZA,EAAU,QAAQ,WAAA,GAClBA,EAAU,UAAU,OAGtBE,EAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG,CAACN,GAAOC,GAAQC,GAASC,CAAQ,CAAC,GAG9B;AAAA,IACL,SAASG,EAAW;AAAA,IACpB,QAAQF,EAAU;AAAA,EAAA;AAEtB;"}
@@ -0,0 +1,79 @@
1
+ import { useState as b, useEffect as d, useCallback as u, useMemo as x } from "react";
2
+ function k(s) {
3
+ const [i, p] = b(/* @__PURE__ */ new Map()), [a, f] = b(/* @__PURE__ */ new Map());
4
+ d(() => {
5
+ s && f((e) => {
6
+ let t = !1;
7
+ if (e.size !== Object.keys(s).length)
8
+ t = !0;
9
+ else
10
+ for (const [n, r] of Object.entries(s)) {
11
+ const c = e.get(n);
12
+ if (!c) {
13
+ t = !0;
14
+ break;
15
+ }
16
+ if (c.currentIndex !== r.currentIndex || c.onIndexChange !== r.onIndexChange) {
17
+ t = !0;
18
+ break;
19
+ }
20
+ }
21
+ if (!t) return e;
22
+ const o = /* @__PURE__ */ new Map();
23
+ return Object.entries(s).forEach(([n, r]) => {
24
+ o.set(n, r);
25
+ }), o;
26
+ });
27
+ }, [s]);
28
+ const g = u(
29
+ (e, t) => {
30
+ p((o) => {
31
+ const n = new Map(o);
32
+ return n.set(e, t), n;
33
+ });
34
+ },
35
+ []
36
+ ), M = u((e) => {
37
+ p((t) => {
38
+ const o = new Map(t);
39
+ return o.delete(e), o;
40
+ });
41
+ }, []), C = u(
42
+ (e) => i.get(e),
43
+ [i]
44
+ ), l = u(
45
+ (e, t) => {
46
+ f((o) => {
47
+ const n = new Map(o), r = n.get(e) || {}, c = typeof t == "function" ? t(r) : t;
48
+ return n.set(e, c), n;
49
+ });
50
+ },
51
+ []
52
+ ), w = u(
53
+ (e) => a.get(e),
54
+ [a]
55
+ );
56
+ return x(
57
+ () => ({
58
+ registerContainer: g,
59
+ unregisterContainer: M,
60
+ getControl: C,
61
+ setControlProps: l,
62
+ getControlProps: w,
63
+ // Include size to trigger re-renders when it changes
64
+ _propsVersion: a.size
65
+ }),
66
+ [
67
+ g,
68
+ M,
69
+ C,
70
+ l,
71
+ w,
72
+ a.size
73
+ ]
74
+ );
75
+ }
76
+ export {
77
+ k as useRepeatingContainers
78
+ };
79
+ //# sourceMappingURL=useRepeatingContainers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRepeatingContainers.js","sources":["../../src/hooks/useRepeatingContainers.ts"],"sourcesContent":["/**\n * Custom hook for managing repeating container controls\n *\n * Handles slider/list index management and synchronization between\n * parent-provided controls and internal component state.\n */\n\nimport { useState, useCallback, useMemo, useEffect } from \"react\";\n\nimport type { RepeatingContainerControl } from \"../contexts/EncoreRepeatingContainerContext\";\n\ninterface ContainerControlProps {\n currentIndex?: number;\n onIndexChange?: (index: number) => void;\n}\n\n/**\n * Manages repeating container (slider/list) controls\n *\n * @param externalControls - Optional controls passed from parent component\n * @returns Context value for EncoreRepeatingContainerContext\n *\n * @example\n * const containerContextValue = useRepeatingContainers(repeatingContainerControls);\n * <EncoreRepeatingContainerContext.Provider value={containerContextValue}>\n */\nexport function useRepeatingContainers(\n externalControls?: Record<string, ContainerControlProps>\n) {\n const [containerControls, setContainerControls] = useState<\n Map<string, RepeatingContainerControl>\n >(new Map());\n\n const [controlPropsMap, setControlPropsMap] = useState<\n Map<string, ContainerControlProps>\n >(new Map());\n\n // Update control props from external prop\n useEffect(() => {\n if (externalControls) {\n setControlPropsMap((prev) => {\n // Check if content actually changed to avoid unnecessary updates\n let changed = false;\n if (prev.size !== Object.keys(externalControls).length) {\n changed = true;\n } else {\n for (const [id, props] of Object.entries(externalControls)) {\n const prevProps = prev.get(id);\n if (!prevProps) {\n changed = true;\n break;\n }\n if (\n prevProps.currentIndex !== props.currentIndex ||\n prevProps.onIndexChange !== props.onIndexChange\n ) {\n changed = true;\n break;\n }\n }\n }\n\n if (!changed) return prev;\n\n const newMap = new Map();\n Object.entries(externalControls).forEach(([id, props]) => {\n newMap.set(id, props);\n });\n return newMap;\n });\n }\n }, [externalControls]);\n\n const registerContainer = useCallback(\n (id: string, control: RepeatingContainerControl) => {\n setContainerControls((prev) => {\n const next = new Map(prev);\n next.set(id, control);\n return next;\n });\n },\n []\n );\n\n const unregisterContainer = useCallback((id: string) => {\n setContainerControls((prev) => {\n const next = new Map(prev);\n next.delete(id);\n return next;\n });\n }, []);\n\n const getControl = useCallback(\n (id: string) => {\n return containerControls.get(id);\n },\n [containerControls]\n );\n\n const setControlProps = useCallback(\n (\n id: string,\n props:\n | ContainerControlProps\n | ((prev: ContainerControlProps) => ContainerControlProps)\n ) => {\n setControlPropsMap((prev) => {\n const next = new Map(prev);\n const current = next.get(id) || {};\n const newProps = typeof props === \"function\" ? props(current) : props;\n next.set(id, newProps);\n return next;\n });\n },\n []\n );\n\n const getControlProps = useCallback(\n (id: string) => {\n return controlPropsMap.get(id);\n },\n [controlPropsMap]\n );\n\n // Create context value - changes when controlPropsMap changes\n const contextValue = useMemo(\n () => ({\n registerContainer,\n unregisterContainer,\n getControl,\n setControlProps,\n getControlProps,\n // Include size to trigger re-renders when it changes\n _propsVersion: controlPropsMap.size,\n }),\n [\n registerContainer,\n unregisterContainer,\n getControl,\n setControlProps,\n getControlProps,\n controlPropsMap.size,\n ]\n );\n\n return contextValue;\n}\n"],"names":["useRepeatingContainers","externalControls","containerControls","setContainerControls","useState","controlPropsMap","setControlPropsMap","useEffect","prev","changed","id","props","prevProps","newMap","registerContainer","useCallback","control","next","unregisterContainer","getControl","setControlProps","current","newProps","getControlProps","useMemo"],"mappings":";AA0BO,SAASA,EACdC,GACA;AACA,QAAM,CAACC,GAAmBC,CAAoB,IAAIC,EAEhD,oBAAI,KAAK,GAEL,CAACC,GAAiBC,CAAkB,IAAIF,EAE5C,oBAAI,KAAK;AAGX,EAAAG,EAAU,MAAM;AACd,IAAIN,KACFK,EAAmB,CAACE,MAAS;AAE3B,UAAIC,IAAU;AACd,UAAID,EAAK,SAAS,OAAO,KAAKP,CAAgB,EAAE;AAC9C,QAAAQ,IAAU;AAAA;AAEV,mBAAW,CAACC,GAAIC,CAAK,KAAK,OAAO,QAAQV,CAAgB,GAAG;AAC1D,gBAAMW,IAAYJ,EAAK,IAAIE,CAAE;AAC7B,cAAI,CAACE,GAAW;AACd,YAAAH,IAAU;AACV;AAAA,UACF;AACA,cACEG,EAAU,iBAAiBD,EAAM,gBACjCC,EAAU,kBAAkBD,EAAM,eAClC;AACA,YAAAF,IAAU;AACV;AAAA,UACF;AAAA,QACF;AAGF,UAAI,CAACA,EAAS,QAAOD;AAErB,YAAMK,wBAAa,IAAA;AACnB,oBAAO,QAAQZ,CAAgB,EAAE,QAAQ,CAAC,CAACS,GAAIC,CAAK,MAAM;AACxD,QAAAE,EAAO,IAAIH,GAAIC,CAAK;AAAA,MACtB,CAAC,GACME;AAAA,IACT,CAAC;AAAA,EAEL,GAAG,CAACZ,CAAgB,CAAC;AAErB,QAAMa,IAAoBC;AAAA,IACxB,CAACL,GAAYM,MAAuC;AAClD,MAAAb,EAAqB,CAACK,MAAS;AAC7B,cAAMS,IAAO,IAAI,IAAIT,CAAI;AACzB,eAAAS,EAAK,IAAIP,GAAIM,CAAO,GACbC;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAA;AAAA,EAAC,GAGGC,IAAsBH,EAAY,CAACL,MAAe;AACtD,IAAAP,EAAqB,CAACK,MAAS;AAC7B,YAAMS,IAAO,IAAI,IAAIT,CAAI;AACzB,aAAAS,EAAK,OAAOP,CAAE,GACPO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAA,CAAE,GAECE,IAAaJ;AAAA,IACjB,CAACL,MACQR,EAAkB,IAAIQ,CAAE;AAAA,IAEjC,CAACR,CAAiB;AAAA,EAAA,GAGdkB,IAAkBL;AAAA,IACtB,CACEL,GACAC,MAGG;AACH,MAAAL,EAAmB,CAACE,MAAS;AAC3B,cAAMS,IAAO,IAAI,IAAIT,CAAI,GACnBa,IAAUJ,EAAK,IAAIP,CAAE,KAAK,CAAA,GAC1BY,IAAW,OAAOX,KAAU,aAAaA,EAAMU,CAAO,IAAIV;AAChE,eAAAM,EAAK,IAAIP,GAAIY,CAAQ,GACdL;AAAA,MACT,CAAC;AAAA,IACH;AAAA,IACA,CAAA;AAAA,EAAC,GAGGM,IAAkBR;AAAA,IACtB,CAACL,MACQL,EAAgB,IAAIK,CAAE;AAAA,IAE/B,CAACL,CAAe;AAAA,EAAA;AAwBlB,SApBqBmB;AAAA,IACnB,OAAO;AAAA,MACL,mBAAAV;AAAA,MACA,qBAAAI;AAAA,MACA,YAAAC;AAAA,MACA,iBAAAC;AAAA,MACA,iBAAAG;AAAA;AAAA,MAEA,eAAelB,EAAgB;AAAA,IAAA;AAAA,IAEjC;AAAA,MACES;AAAA,MACAI;AAAA,MACAC;AAAA,MACAC;AAAA,MACAG;AAAA,MACAlB,EAAgB;AAAA,IAAA;AAAA,EAClB;AAIJ;"}
package/dist/index.js CHANGED
@@ -1,36 +1,35 @@
1
1
  import { default as n } from "./components/EncoreApp.js";
2
2
  import { default as a } from "./components/EncoreErrorBoundary.js";
3
- import { default as d } from "./components/EncoreLoadingFallback.js";
3
+ import { default as p } from "./components/EncoreLoadingFallback.js";
4
4
  import { default as i } from "./contexts/EncoreAppContext.js";
5
5
  import { default as m } from "./contexts/EncoreBindingContext.js";
6
- import { default as l } from "./stores/useEncoreState.js";
6
+ import { default as u } from "./stores/useEncoreState.js";
7
7
  import { PACKAGE_VERSION as g } from "./version.js";
8
- import { arraysEqual as x, findActionButtons as E, findForms as C, findInputGroups as A, findMinimalDistinguishingPath as P, findSlidersAndDataBindings as S, findStandaloneComponents as y, findStandaloneSelectInputs as B, generateQualifiedPropName as I, getComponentPropName as N, getComponentPropType as F, qualifyFormInputs as L, sanitizePropName as b } from "./codegen/parser.js";
9
- import { generateComponentCode as q, generateComponentMetadata as D, generateReadme as G } from "./codegen/generator.js";
10
- console.log("Encore Lib Loaded");
8
+ import { arraysEqual as E, findActionButtons as c, findForms as C, findInputGroups as A, findMinimalDistinguishingPath as P, findSlidersAndDataBindings as S, findStandaloneComponents as y, findStandaloneSelectInputs as B, generateQualifiedPropName as I, getComponentPropName as N, getComponentPropType as F, qualifyFormInputs as h, sanitizePropName as q } from "./codegen/parser.js";
9
+ import { generateComponentCode as G, generateComponentMetadata as M, generateReadme as R } from "./codegen/generator.js";
11
10
  export {
12
11
  n as EncoreApp,
13
12
  i as EncoreAppContext,
14
13
  m as EncoreBindingContext,
15
14
  a as EncoreErrorBoundary,
16
- d as EncoreLoadingFallback,
15
+ p as EncoreLoadingFallback,
17
16
  g as PACKAGE_VERSION,
18
- x as arraysEqual,
19
- E as findActionButtons,
17
+ E as arraysEqual,
18
+ c as findActionButtons,
20
19
  C as findForms,
21
20
  A as findInputGroups,
22
21
  P as findMinimalDistinguishingPath,
23
22
  S as findSlidersAndDataBindings,
24
23
  y as findStandaloneComponents,
25
24
  B as findStandaloneSelectInputs,
26
- q as generateComponentCode,
27
- D as generateComponentMetadata,
25
+ G as generateComponentCode,
26
+ M as generateComponentMetadata,
28
27
  I as generateQualifiedPropName,
29
- G as generateReadme,
28
+ R as generateReadme,
30
29
  N as getComponentPropName,
31
30
  F as getComponentPropType,
32
- L as qualifyFormInputs,
33
- b as sanitizePropName,
34
- l as useEncoreState
31
+ h as qualifyFormInputs,
32
+ q as sanitizePropName,
33
+ u as useEncoreState
35
34
  };
36
35
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["console.log(\"Encore Lib Loaded\");\nimport EncoreApp from \"./components/EncoreApp\";\nimport EncoreErrorBoundary from \"./components/EncoreErrorBoundary\";\nimport EncoreLoadingFallback from \"./components/EncoreLoadingFallback\";\nimport EncoreAppContext from \"./contexts/EncoreAppContext\";\nimport EncoreBindingContext from \"./contexts/EncoreBindingContext\";\nimport useEncoreState from \"./stores/useEncoreState\";\nimport { PACKAGE_VERSION } from \"./version\";\n\nexport {\n EncoreApp,\n EncoreErrorBoundary,\n EncoreLoadingFallback,\n EncoreAppContext,\n EncoreBindingContext,\n useEncoreState,\n PACKAGE_VERSION,\n};\n\nexport * from \"./codegen\";\n"],"names":[],"mappings":";;;;;;;;;AAAA,QAAQ,IAAI,mBAAmB;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -0,0 +1,24 @@
1
+ import { logger as e } from "./logger.js";
2
+ function f(l) {
3
+ if (!l) return l;
4
+ const r = (t) => {
5
+ if (!(!t || typeof t != "object")) {
6
+ if (t.children && Array.isArray(t.children) && t.children.length > 1) {
7
+ let i = 0, s = 0;
8
+ t.children.forEach((h) => {
9
+ h.style?.width && (i += h.style.width, s++);
10
+ }), (Math.abs(i - 100) < 1 || Math.abs(i - 375) < 5) && s >= 2 && (t.style || (t.style = {}), t.style.layout || (t.style.layout = {}), t.style.layout.mode || (e.debug("Layout patch applied", {
11
+ nodeId: t.id,
12
+ childrenCount: s,
13
+ totalWidth: i
14
+ }), t.style.layout.mode = "HORIZONTAL", t.style.layout.primaryAxisAlignItems = "flex-start", t.style.layout.counterAxisAlignItems = "flex-start"));
15
+ }
16
+ t.children && (Array.isArray(t.children) ? t.children.forEach(r) : r(t.children));
17
+ }
18
+ };
19
+ return r(l), l;
20
+ }
21
+ export {
22
+ f as patchPageData
23
+ };
24
+ //# sourceMappingURL=dataPatching.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataPatching.js","sources":["../../src/lib/dataPatching.ts"],"sourcesContent":["/**\n * Data patching utilities for fixing layout and component issues\n *\n * Applies heuristic-based fixes to page data to correct common layout problems\n * that occur during the Figma-to-Encore conversion process.\n */\n\nimport logger from \"./logger\";\n\n/**\n * Recursively patches page data to fix layout issues\n *\n * Current heuristics:\n * 1. Horizontal layout detection - If children widths sum to ~100% or ~375px,\n * force HORIZONTAL layout mode to prevent vertical stacking\n *\n * @param clientData - The client data object from page definition\n * @returns Patched client data (mutates in place)\n */\nexport function patchPageData(clientData: any): any {\n if (!clientData) return clientData;\n\n const patchNode = (node: any) => {\n if (!node || typeof node !== \"object\") return;\n\n // Heuristic: If children widths sum to ~100% or ~375px, force HORIZONTAL layout\n if (\n node.children &&\n Array.isArray(node.children) &&\n node.children.length > 1\n ) {\n let totalWidth = 0;\n let childrenWithWidth = 0;\n\n node.children.forEach((child: any) => {\n if (child.style?.width) {\n // Width might be percentage (sums to 100) or pixels (sums to 375)\n totalWidth += child.style.width;\n childrenWithWidth++;\n }\n });\n\n // Check if widths sum to full width (100% or 375px)\n const isFullWidthRow =\n (Math.abs(totalWidth - 100) < 1 || Math.abs(totalWidth - 375) < 5) &&\n childrenWithWidth >= 2;\n\n if (isFullWidthRow) {\n if (!node.style) node.style = {};\n if (!node.style.layout) node.style.layout = {};\n\n // Only apply if mode is missing or undefined\n if (!node.style.layout.mode) {\n logger.debug('Layout patch applied', {\n nodeId: node.id,\n childrenCount: childrenWithWidth,\n totalWidth\n });\n node.style.layout.mode = \"HORIZONTAL\";\n node.style.layout.primaryAxisAlignItems = \"flex-start\";\n node.style.layout.counterAxisAlignItems = \"flex-start\";\n }\n }\n }\n\n // Recurse through children\n if (node.children) {\n if (Array.isArray(node.children)) {\n node.children.forEach(patchNode);\n } else {\n patchNode(node.children);\n }\n }\n };\n\n patchNode(clientData);\n return clientData;\n}\n"],"names":["patchPageData","clientData","patchNode","node","totalWidth","childrenWithWidth","child","logger"],"mappings":";AAmBO,SAASA,EAAcC,GAAsB;AAClD,MAAI,CAACA,EAAY,QAAOA;AAExB,QAAMC,IAAY,CAACC,MAAc;AAC/B,QAAI,GAACA,KAAQ,OAAOA,KAAS,WAG7B;AAAA,UACEA,EAAK,YACL,MAAM,QAAQA,EAAK,QAAQ,KAC3BA,EAAK,SAAS,SAAS,GACvB;AACA,YAAIC,IAAa,GACbC,IAAoB;AAExB,QAAAF,EAAK,SAAS,QAAQ,CAACG,MAAe;AACpC,UAAIA,EAAM,OAAO,UAEfF,KAAcE,EAAM,MAAM,OAC1BD;AAAA,QAEJ,CAAC,IAIE,KAAK,IAAID,IAAa,GAAG,IAAI,KAAK,KAAK,IAAIA,IAAa,GAAG,IAAI,MAChEC,KAAqB,MAGhBF,EAAK,UAAOA,EAAK,QAAQ,CAAA,IACzBA,EAAK,MAAM,WAAQA,EAAK,MAAM,SAAS,CAAA,IAGvCA,EAAK,MAAM,OAAO,SACrBI,EAAO,MAAM,wBAAwB;AAAA,UACnC,QAAQJ,EAAK;AAAA,UACb,eAAeE;AAAA,UACf,YAAAD;AAAA,QAAA,CACD,GACDD,EAAK,MAAM,OAAO,OAAO,cACzBA,EAAK,MAAM,OAAO,wBAAwB,cAC1CA,EAAK,MAAM,OAAO,wBAAwB;AAAA,MAGhD;AAGA,MAAIA,EAAK,aACH,MAAM,QAAQA,EAAK,QAAQ,IAC7BA,EAAK,SAAS,QAAQD,CAAS,IAE/BA,EAAUC,EAAK,QAAQ;AAAA;AAAA,EAG7B;AAEA,SAAAD,EAAUD,CAAU,GACbA;AACT;"}
@@ -1,25 +1,26 @@
1
- import f from "./packages.js";
2
- import { isLocalMode as p } from "./localMode.js";
3
- import { CONST_COMPONENTS_CDN_URL as E } from "../packages/encore-lib/constants.js";
4
- import { haveModule as $, getModuleExports as h, registerModule as y } from "./moduleRegistry.js";
5
- import { clearModuleCache as b } from "./moduleRegistry.js";
1
+ import p from "./packages.js";
2
+ import { isLocalMode as h } from "./localMode.js";
3
+ import { CONST_COMPONENTS_CDN_URL as _ } from "../packages/encore-lib/constants.js";
4
+ import { haveModule as $, getModuleExports as g, registerModule as w } from "./moduleRegistry.js";
5
+ import { clearModuleCache as v } from "./moduleRegistry.js";
6
+ import { logger as i } from "./logger.js";
6
7
  const M = {};
7
- Object.keys(f).forEach((t) => {
8
- y(t, f[t]);
8
+ Object.keys(p).forEach((t) => {
9
+ w(t, p[t]);
9
10
  });
10
- function g(t, s) {
11
- return new Promise((i, m) => {
11
+ function y(t, s) {
12
+ return new Promise((m, d) => {
12
13
  const r = (e, a) => {
13
14
  typeof e == "function" && (a = e, e = []), Promise.all(
14
15
  e.map(async (n) => n === "require" ? ((o) => {
15
16
  if (!$(o))
16
17
  throw new Error(`Module ${o} not found`);
17
- return h(o);
18
- }) : n === "exports" ? {} : ($(n) || await L(n), h(n)))
18
+ return g(o);
19
+ }) : n === "exports" ? {} : ($(n) || await x(n), g(n)))
19
20
  ).then((n) => {
20
- const o = {}, l = a.apply(null, n) || o;
21
- i({ default: l });
22
- }).catch(m);
21
+ const o = {}, u = a.apply(null, n) || o;
22
+ m({ default: u });
23
+ }).catch(d);
23
24
  };
24
25
  r.amd = !0;
25
26
  try {
@@ -29,9 +30,9 @@ function g(t, s) {
29
30
  (n, o) => `t.createElement(e.SliderComponent,${o}`
30
31
  ), e = e.replace(
31
32
  /t\.createElement\("undefined",(\{[^}]*nodeData:\{([^}]*type:"([^"]+)")?[^}]*\}[^}]*\})/g,
32
- (n, o, u, l) => {
33
- const c = o.match(/type:"([^"]+)"/), d = c ? c[1] : null;
34
- return `t.createElement(${d ? `(e["${d}"] || e.DefaultLayerComponent)` : "e.DefaultLayerComponent"},${o}`;
33
+ (n, o, l, u) => {
34
+ const c = o.match(/type:"([^"]+)"/), f = c ? c[1] : null;
35
+ return `t.createElement(${f ? `(e["${f}"] || e.DefaultLayerComponent)` : "e.DefaultLayerComponent"},${o}`;
35
36
  }
36
37
  ), e = e.replace(
37
38
  /t\.createElement\("undefined"/g,
@@ -44,7 +45,7 @@ function g(t, s) {
44
45
  ${e}
45
46
  //# sourceURL=dynamic-module://${t}.js
46
47
  } catch (error) {
47
- console.error('[Module Evaluation Error]', {
48
+ console.error('[encore-lib] Module evaluation error', {
48
49
  moduleName: '${t}',
49
50
  error: error.message,
50
51
  stack: error.stack,
@@ -55,68 +56,66 @@ function g(t, s) {
55
56
  }
56
57
  `
57
58
  );
58
- console.debug(`[Module Loading] Attempting to load module: ${t}`), a(r), console.debug(`[Module Loading] Successfully loaded module: ${t}`);
59
+ i.debug("Loading AMD module", { name: t }), a(r), i.debug("Module loaded successfully", { name: t });
59
60
  } catch (e) {
60
- console.error("[Module Loading Failed]", {
61
+ i.error("Module loading failed", {
61
62
  moduleName: t,
62
- error: e,
63
63
  errorType: e.constructor.name,
64
64
  message: e.message,
65
65
  stack: e.stack,
66
- code: s.slice(0, 500) + (s.length > 500 ? "..." : "")
67
- // Show first 500 chars of code
68
- }), m(e);
66
+ codePreview: s.slice(0, 200) + (s.length > 200 ? "..." : "")
67
+ }), d(e);
69
68
  }
70
69
  });
71
70
  }
72
- async function _(t) {
73
- if (console.log(`🔍 fetchDep called for ${t}. isLocalMode: ${p()}`), p()) {
71
+ async function L(t) {
72
+ if (i.debug("Fetching dependency", { name: t, isLocal: h() }), h()) {
74
73
  const r = t.match(/^([^/]+)\/draft\/components\/([^/]+)$/);
75
74
  if (r) {
76
75
  const e = r[1], a = r[2], n = M?.VITE_FLEX_LAYOUT_ABS || null, o = [
77
76
  `/flex-layout/${e}/${a}.js`,
78
77
  n ? `/@fs/${n}/${e}/${a}.js` : null
79
- ].filter(Boolean), u = [];
80
- for (const l of o)
78
+ ].filter(Boolean), l = [];
79
+ for (const u of o)
81
80
  try {
82
- const c = await fetch(l);
81
+ const c = await fetch(u);
83
82
  if (!c.ok) {
84
- u.push(`${l}: ${c.status} ${c.statusText}`);
83
+ l.push(`${u}: ${c.status} ${c.statusText}`);
85
84
  continue;
86
85
  }
87
- const d = await c.text();
88
- return await g(
86
+ const f = await c.text();
87
+ return await y(
89
88
  `${e}/draft/components/${a}`,
90
- d
89
+ f
91
90
  );
92
91
  } catch (c) {
93
- u.push(`${l}: ${c.message || String(c)}`);
92
+ l.push(`${u}: ${c.message || String(c)}`);
94
93
  }
95
94
  throw new Error(
96
95
  `Local component not found for ${t}. Tried: ${o.join(
97
96
  ", "
98
- )}. Errors: ${u.join("; ")}`
97
+ )}. Errors: ${l.join("; ")}`
99
98
  );
100
99
  }
101
100
  }
102
- const s = Math.round(Date.now() / 1e3), i = `${E}/${t}.js?cacheBuster=${s}`;
103
- console.log(`[Module Loading] Fetching remote component from: ${i}`);
104
- const m = await fetch(i).then(async (r) => {
101
+ const s = Math.round(Date.now() / 1e3), m = `${_}/${t}.js?cacheBuster=${s}`;
102
+ i.debug("Fetching remote component", { url: m });
103
+ const d = await fetch(m).then(async (r) => {
105
104
  if (!r.ok)
106
105
  throw r.status === 403 ? new Error(
107
106
  `Error: Could not fetch component '${t}'. Try regenerating components.`
108
107
  ) : new Error(`Network error (${r.status}): ${await r.text()}`);
109
108
  return r.text();
110
109
  });
111
- return await g(t, m);
110
+ return await y(t, d);
112
111
  }
113
- async function L(t) {
114
- const s = await _(t);
115
- y(t, () => ({ exports: s.default }));
112
+ async function x(t) {
113
+ const s = await L(t);
114
+ w(t, () => ({ exports: s.default }));
116
115
  }
117
116
  export {
118
- b as clearModuleCache,
119
- _ as fetchDep,
120
- g as loadAMDModule
117
+ v as clearModuleCache,
118
+ L as fetchDep,
119
+ y as loadAMDModule
121
120
  };
122
121
  //# sourceMappingURL=dynamicModules.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamicModules.js","sources":["../../src/lib/dynamicModules.ts"],"sourcesContent":["import packages from \"./packages\";\nimport { isLocalMode } from \"./localMode\";\nimport { CONST_COMPONENTS_CDN_URL } from \"../../constants\";\nimport { registerModule, getModuleExports, haveModule } from \"./moduleRegistry\";\n\n// Initialize registry with default packages\nObject.keys(packages).forEach((p) => {\n registerModule(p, packages[p]);\n});\n\nexport function loadAMDModule(name: string, code: string) {\n return new Promise<any>((resolve, reject) => {\n const define = (deps: string[], factory: (...va: unknown[]) => unknown) => {\n if (typeof deps === \"function\") {\n factory = deps;\n deps = [];\n }\n\n Promise.all(\n deps.map(async (dep) => {\n if (dep === \"require\") {\n // Return a mock require function for AMD modules\n return ((id: string) => {\n if (!haveModule(id)) {\n throw new Error(`Module ${id} not found`);\n }\n return getModuleExports(id);\n }) as typeof require;\n }\n if (dep === \"exports\") return {};\n if (!haveModule(dep)) await fetchAndRegister(dep);\n return getModuleExports(dep);\n })\n )\n .then((resolvedDeps: unknown[]) => {\n const exports = {};\n const module = factory.apply(null, resolvedDeps);\n const result = module || exports;\n resolve({ default: result });\n })\n .catch(reject);\n };\n\n define.amd = true;\n\n try {\n // Patch code to replace hardcoded \"undefined\" component references\n // This fixes remote component files that were generated before certain components existed\n let patchedCode = code;\n\n // Replace t.createElement(\"undefined\", props) for container:slider with e.SliderComponent\n // Note: Components are passed as the second parameter 'e' in AMD modules: define([\"react\",\"@/bravo/components\"],(function(t,e){...}))\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\",(\\{[^}]*nodeData:\\{[^}]*type:\"container:slider\"[^}]*\\}[^}]*\\})/g,\n (_match, propsStr) => {\n return `t.createElement(e.SliderComponent,${propsStr}`;\n }\n );\n\n // Fallback for any other undefined components - use the type-based lookup\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\",(\\{[^}]*nodeData:\\{([^}]*type:\"([^\"]+)\")?[^}]*\\}[^}]*\\})/g,\n (_match, propsStr, _typeStr, _type) => {\n const typeMatch = propsStr.match(/type:\"([^\"]+)\"/);\n const componentType = typeMatch ? typeMatch[1] : null;\n const componentLookup = componentType\n ? `(e[\"${componentType}\"] || e.DefaultLayerComponent)`\n : \"e.DefaultLayerComponent\";\n return `t.createElement(${componentLookup},${propsStr}`;\n }\n );\n\n // Final fallback for any remaining \"undefined\"\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\"/g,\n \"t.createElement(e.DefaultLayerComponent\"\n );\n\n // Wrap with error boundary\n // Note: Components are already passed as the second parameter 'e' via AMD dependencies,\n // so we don't need to inject them separately\n const wrapper = Function(\n \"define\",\n `\n try {\n ${patchedCode}\\n//# sourceURL=dynamic-module://${name}.js\n } catch (error) {\n console.error('[Module Evaluation Error]', {\n moduleName: '${name}',\n error: error.message,\n stack: error.stack,\n lineNumber: error.lineNumber,\n columnNumber: error.columnNumber\n });\n throw error;\n }\n `\n );\n\n console.debug(`[Module Loading] Attempting to load module: ${name}`);\n wrapper(define);\n console.debug(`[Module Loading] Successfully loaded module: ${name}`);\n } catch (e: any) {\n // Enhanced error logging\n console.error(\"[Module Loading Failed]\", {\n moduleName: name,\n error: e,\n errorType: e.constructor.name,\n message: e.message,\n stack: e.stack,\n code: code.slice(0, 500) + (code.length > 500 ? \"...\" : \"\"), // Show first 500 chars of code\n });\n reject(e);\n }\n });\n}\n\nexport async function fetchDep(name: string) {\n // Local mode: map Encore component name to local JSX/JS under /flex-layout\n console.log(`🔍 fetchDep called for ${name}. isLocalMode: ${isLocalMode()}`);\n if (isLocalMode()) {\n // Expecting `${appId}/draft/components/${pageId}`\n const m = name.match(/^([^/]+)\\/draft\\/components\\/([^/]+)$/);\n if (m) {\n const appId = m[1];\n const pageId = m[2];\n // Load from public as AMD (do not import() public files; Vite forbids importing from /public)\n const absBase = (import.meta as any)?.env?.VITE_FLEX_LAYOUT_ABS || null;\n const candidates = [\n `/flex-layout/${appId}/${pageId}.js`,\n absBase ? `/@fs/${absBase}/${appId}/${pageId}.js` : null,\n ].filter(Boolean) as string[];\n\n // Fetch as text and evaluate via AMD define shim\n const errors: string[] = [];\n for (const url of candidates) {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n errors.push(`${url}: ${response.status} ${response.statusText}`);\n continue;\n }\n const code = await response.text();\n const amd = await loadAMDModule(\n `${appId}/draft/components/${pageId}`,\n code\n );\n return amd;\n } catch (e: any) {\n errors.push(`${url}: ${e.message || String(e)}`);\n }\n }\n throw new Error(\n `Local component not found for ${name}. Tried: ${candidates.join(\n \", \"\n )}. Errors: ${errors.join(\"; \")}`\n );\n }\n }\n // Remote mode: use AMD loader\n const cacheBuster = Math.round(Date.now() / 1000);\n const url = `${CONST_COMPONENTS_CDN_URL}/${name}.js?cacheBuster=${cacheBuster}`;\n console.log(`[Module Loading] Fetching remote component from: ${url}`);\n const text = await fetch(url).then(async (a) => {\n if (!a.ok) {\n if (a.status === 403) {\n throw new Error(\n `Error: Could not fetch component '${name}'. Try regenerating components.`\n );\n } else {\n throw new Error(`Network error (${a.status}): ${await a.text()}`);\n }\n }\n return a.text();\n });\n\n return await loadAMDModule(name, text);\n // } catch (error) {\n // return {\n // default() {\n // console.log(error);\n // throw new Error(\"Failed to render\");\n // },\n // };\n // }\n}\n\nasync function fetchAndRegister(dep: string) {\n const result = await fetchDep(dep);\n registerModule(dep, () => ({ exports: result.default }));\n}\n\nexport { clearModuleCache } from \"./moduleRegistry\";\n"],"names":["packages","p","registerModule","loadAMDModule","name","code","resolve","reject","define","deps","factory","dep","id","haveModule","getModuleExports","fetchAndRegister","resolvedDeps","exports","result","patchedCode","_match","propsStr","_typeStr","_type","typeMatch","componentType","wrapper","fetchDep","isLocalMode","m","appId","pageId","absBase","__vite_import_meta_env__","candidates","errors","url","response","e","cacheBuster","CONST_COMPONENTS_CDN_URL","text","a"],"mappings":"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"}
1
+ {"version":3,"file":"dynamicModules.js","sources":["../../src/lib/dynamicModules.ts"],"sourcesContent":["import packages from \"./packages\";\nimport { isLocalMode } from \"./localMode\";\nimport { CONST_COMPONENTS_CDN_URL } from \"../../constants\";\nimport { registerModule, getModuleExports, haveModule } from \"./moduleRegistry\";\nimport logger from \"./logger\";\n\n// Initialize registry with default packages\nObject.keys(packages).forEach((p) => {\n registerModule(p, packages[p]);\n});\n\nexport function loadAMDModule(name: string, code: string) {\n return new Promise<any>((resolve, reject) => {\n const define = (deps: string[], factory: (...va: unknown[]) => unknown) => {\n if (typeof deps === \"function\") {\n factory = deps;\n deps = [];\n }\n\n Promise.all(\n deps.map(async (dep) => {\n if (dep === \"require\") {\n // Return a mock require function for AMD modules\n return ((id: string) => {\n if (!haveModule(id)) {\n throw new Error(`Module ${id} not found`);\n }\n return getModuleExports(id);\n }) as typeof require;\n }\n if (dep === \"exports\") return {};\n if (!haveModule(dep)) await fetchAndRegister(dep);\n return getModuleExports(dep);\n })\n )\n .then((resolvedDeps: unknown[]) => {\n const exports = {};\n const module = factory.apply(null, resolvedDeps);\n const result = module || exports;\n resolve({ default: result });\n })\n .catch(reject);\n };\n\n define.amd = true;\n\n try {\n // Patch code to replace hardcoded \"undefined\" component references\n // This fixes remote component files that were generated before certain components existed\n let patchedCode = code;\n\n // Replace t.createElement(\"undefined\", props) for container:slider with e.SliderComponent\n // Note: Components are passed as the second parameter 'e' in AMD modules: define([\"react\",\"@/bravo/components\"],(function(t,e){...}))\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\",(\\{[^}]*nodeData:\\{[^}]*type:\"container:slider\"[^}]*\\}[^}]*\\})/g,\n (_match, propsStr) => {\n return `t.createElement(e.SliderComponent,${propsStr}`;\n }\n );\n\n // Fallback for any other undefined components - use the type-based lookup\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\",(\\{[^}]*nodeData:\\{([^}]*type:\"([^\"]+)\")?[^}]*\\}[^}]*\\})/g,\n (_match, propsStr, _typeStr, _type) => {\n const typeMatch = propsStr.match(/type:\"([^\"]+)\"/);\n const componentType = typeMatch ? typeMatch[1] : null;\n const componentLookup = componentType\n ? `(e[\"${componentType}\"] || e.DefaultLayerComponent)`\n : \"e.DefaultLayerComponent\";\n return `t.createElement(${componentLookup},${propsStr}`;\n }\n );\n\n // Final fallback for any remaining \"undefined\"\n patchedCode = patchedCode.replace(\n /t\\.createElement\\(\"undefined\"/g,\n \"t.createElement(e.DefaultLayerComponent\"\n );\n\n // Wrap with error boundary\n // Note: Components are already passed as the second parameter 'e' via AMD dependencies,\n // so we don't need to inject them separately\n const wrapper = Function(\n \"define\",\n `\n try {\n ${patchedCode}\\n//# sourceURL=dynamic-module://${name}.js\n } catch (error) {\n console.error('[encore-lib] Module evaluation error', {\n moduleName: '${name}',\n error: error.message,\n stack: error.stack,\n lineNumber: error.lineNumber,\n columnNumber: error.columnNumber\n });\n throw error;\n }\n `\n );\n\n logger.debug('Loading AMD module', { name });\n wrapper(define);\n logger.debug('Module loaded successfully', { name });\n } catch (e: any) {\n logger.error('Module loading failed', {\n moduleName: name,\n errorType: e.constructor.name,\n message: e.message,\n stack: e.stack,\n codePreview: code.slice(0, 200) + (code.length > 200 ? \"...\" : \"\")\n });\n reject(e);\n }\n });\n}\n\nexport async function fetchDep(name: string) {\n // Local mode: map Encore component name to local JSX/JS under /flex-layout\n logger.debug('Fetching dependency', { name, isLocal: isLocalMode() });\n if (isLocalMode()) {\n // Expecting `${appId}/draft/components/${pageId}`\n const m = name.match(/^([^/]+)\\/draft\\/components\\/([^/]+)$/);\n if (m) {\n const appId = m[1];\n const pageId = m[2];\n // Load from public as AMD (do not import() public files; Vite forbids importing from /public)\n const absBase = (import.meta as any)?.env?.VITE_FLEX_LAYOUT_ABS || null;\n const candidates = [\n `/flex-layout/${appId}/${pageId}.js`,\n absBase ? `/@fs/${absBase}/${appId}/${pageId}.js` : null,\n ].filter(Boolean) as string[];\n\n // Fetch as text and evaluate via AMD define shim\n const errors: string[] = [];\n for (const url of candidates) {\n try {\n const response = await fetch(url);\n if (!response.ok) {\n errors.push(`${url}: ${response.status} ${response.statusText}`);\n continue;\n }\n const code = await response.text();\n const amd = await loadAMDModule(\n `${appId}/draft/components/${pageId}`,\n code\n );\n return amd;\n } catch (e: any) {\n errors.push(`${url}: ${e.message || String(e)}`);\n }\n }\n throw new Error(\n `Local component not found for ${name}. Tried: ${candidates.join(\n \", \"\n )}. Errors: ${errors.join(\"; \")}`\n );\n }\n }\n // Remote mode: use AMD loader\n const cacheBuster = Math.round(Date.now() / 1000);\n const url = `${CONST_COMPONENTS_CDN_URL}/${name}.js?cacheBuster=${cacheBuster}`;\n logger.debug('Fetching remote component', { url });\n const text = await fetch(url).then(async (a) => {\n if (!a.ok) {\n if (a.status === 403) {\n throw new Error(\n `Error: Could not fetch component '${name}'. Try regenerating components.`\n );\n } else {\n throw new Error(`Network error (${a.status}): ${await a.text()}`);\n }\n }\n return a.text();\n });\n\n return await loadAMDModule(name, text);\n // } catch (error) {\n // return {\n // default() {\n // console.log(error);\n // throw new Error(\"Failed to render\");\n // },\n // };\n // }\n}\n\nasync function fetchAndRegister(dep: string) {\n const result = await fetchDep(dep);\n registerModule(dep, () => ({ exports: result.default }));\n}\n\nexport { clearModuleCache } from \"./moduleRegistry\";\n"],"names":["packages","p","registerModule","loadAMDModule","name","code","resolve","reject","define","deps","factory","dep","id","haveModule","getModuleExports","fetchAndRegister","resolvedDeps","exports","result","patchedCode","_match","propsStr","_typeStr","_type","typeMatch","componentType","wrapper","logger","fetchDep","isLocalMode","m","appId","pageId","absBase","__vite_import_meta_env__","candidates","errors","url","response","e","cacheBuster","CONST_COMPONENTS_CDN_URL","text","a"],"mappings":"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"}