@brunoalz/smartgesti-site-editor 1.4.0 → 1.4.2

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 (73) hide show
  1. package/dist/editor/BlockSelector.js +4 -2
  2. package/dist/editor/BlockSelector.js.map +1 -1
  3. package/dist/engine/export/exportHtml.d.ts +5 -1
  4. package/dist/engine/export/exportHtml.d.ts.map +1 -1
  5. package/dist/engine/export/exportHtml.js +69 -51
  6. package/dist/engine/export/exportHtml.js.map +1 -1
  7. package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts +2 -0
  8. package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts.map +1 -1
  9. package/dist/engine/export/exporters/sections/BlogPostExporters.js +137 -80
  10. package/dist/engine/export/exporters/sections/BlogPostExporters.js.map +1 -1
  11. package/dist/engine/export/exporters/sections/index.d.ts.map +1 -1
  12. package/dist/engine/export/exporters/sections/index.js +40 -38
  13. package/dist/engine/export/exporters/sections/index.js.map +1 -1
  14. package/dist/engine/index.js +97 -95
  15. package/dist/engine/index.js.map +1 -1
  16. package/dist/engine/plugins/builtin/blog/manifest.d.ts.map +1 -1
  17. package/dist/engine/plugins/builtin/blog/manifest.js +103 -53
  18. package/dist/engine/plugins/builtin/blog/manifest.js.map +1 -1
  19. package/dist/engine/plugins/builtin/blog/mockContentProvider.d.ts.map +1 -1
  20. package/dist/engine/plugins/builtin/blog/mockContentProvider.js +13 -9
  21. package/dist/engine/plugins/builtin/blog/mockContentProvider.js.map +1 -1
  22. package/dist/engine/plugins/contentHydration.d.ts.map +1 -1
  23. package/dist/engine/plugins/contentHydration.js +119 -79
  24. package/dist/engine/plugins/contentHydration.js.map +1 -1
  25. package/dist/engine/plugins/types.d.ts +5 -0
  26. package/dist/engine/plugins/types.d.ts.map +1 -1
  27. package/dist/engine/registry/blocks/sections/blogCategoryFilter.d.ts +3 -0
  28. package/dist/engine/registry/blocks/sections/blogCategoryFilter.d.ts.map +1 -0
  29. package/dist/engine/registry/blocks/sections/blogCategoryFilter.js +53 -0
  30. package/dist/engine/registry/blocks/sections/blogCategoryFilter.js.map +1 -0
  31. package/dist/engine/registry/blocks/sections/blogPostDetail.d.ts.map +1 -1
  32. package/dist/engine/registry/blocks/sections/blogPostDetail.js +4 -1
  33. package/dist/engine/registry/blocks/sections/blogPostDetail.js.map +1 -1
  34. package/dist/engine/registry/blocks/sections/blogPostGrid.js +4 -4
  35. package/dist/engine/registry/blocks/sections/blogPostGrid.js.map +1 -1
  36. package/dist/engine/registry/blocks/sections/blogSearchBar.d.ts +3 -0
  37. package/dist/engine/registry/blocks/sections/blogSearchBar.d.ts.map +1 -0
  38. package/dist/engine/registry/blocks/sections/blogSearchBar.js +56 -0
  39. package/dist/engine/registry/blocks/sections/blogSearchBar.js.map +1 -0
  40. package/dist/engine/registry/blocks/sections/index.d.ts +2 -0
  41. package/dist/engine/registry/blocks/sections/index.d.ts.map +1 -1
  42. package/dist/engine/render/renderers/sections/BlogCategoryFilterRenderer.d.ts +3 -0
  43. package/dist/engine/render/renderers/sections/BlogCategoryFilterRenderer.d.ts.map +1 -0
  44. package/dist/engine/render/renderers/sections/BlogCategoryFilterRenderer.js +213 -0
  45. package/dist/engine/render/renderers/sections/BlogCategoryFilterRenderer.js.map +1 -0
  46. package/dist/engine/render/renderers/sections/BlogSearchBarRenderer.d.ts +3 -0
  47. package/dist/engine/render/renderers/sections/BlogSearchBarRenderer.d.ts.map +1 -0
  48. package/dist/engine/render/renderers/sections/BlogSearchBarRenderer.js +138 -0
  49. package/dist/engine/render/renderers/sections/BlogSearchBarRenderer.js.map +1 -0
  50. package/dist/engine/render/renderers/sections/index.js +28 -24
  51. package/dist/engine/render/renderers/sections/index.js.map +1 -1
  52. package/dist/engine/schema/siteDocument.d.ts +66 -2
  53. package/dist/engine/schema/siteDocument.d.ts.map +1 -1
  54. package/dist/engine/schema/siteDocument.js.map +1 -1
  55. package/dist/hooks/useNavbarAutoSync.d.ts.map +1 -1
  56. package/dist/hooks/useNavbarAutoSync.js +27 -15
  57. package/dist/hooks/useNavbarAutoSync.js.map +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +108 -106
  61. package/dist/index.js.map +1 -1
  62. package/dist/utils/blockIcons.d.ts.map +1 -1
  63. package/dist/utils/blockIcons.js +2 -0
  64. package/dist/utils/blockIcons.js.map +1 -1
  65. package/dist/utils/navbarSync.d.ts +3 -1
  66. package/dist/utils/navbarSync.d.ts.map +1 -1
  67. package/dist/utils/navbarSync.js +3 -3
  68. package/dist/utils/navbarSync.js.map +1 -1
  69. package/dist/viewer/LandingPageViewer.d.ts +7 -2
  70. package/dist/viewer/LandingPageViewer.d.ts.map +1 -1
  71. package/dist/viewer/LandingPageViewer.js +106 -92
  72. package/dist/viewer/LandingPageViewer.js.map +1 -1
  73. package/package.json +1 -1
@@ -1,8 +1,8 @@
1
- import { jsx as a } from "react/jsx-runtime";
2
- import { useState as A, useRef as B, useCallback as F, useEffect as V } from "react";
3
- import { matchDynamicPage as W } from "../engine/plugins/dynamicPageResolver.js";
1
+ import { jsx as i } from "react/jsx-runtime";
2
+ import { useState as A, useRef as z, useCallback as B, useEffect as V } from "react";
3
+ import { matchDynamicPage as N } from "../engine/plugins/dynamicPageResolver.js";
4
4
  import { hydratePageWithContent as G } from "../engine/plugins/contentHydration.js";
5
- import { logger as z } from "../utils/logger.js";
5
+ import { logger as O } from "../utils/logger.js";
6
6
  import { defaultThemeTokens as P } from "../engine/schema/themeTokens.js";
7
7
  import { exportPageToHtml as _ } from "../engine/export/exportHtml.js";
8
8
  import { createEmptySiteDocument as q } from "../engine/schema/siteDocument.js";
@@ -14,24 +14,25 @@ function J(o) {
14
14
  function K(o) {
15
15
  const r = /* @__PURE__ */ new Map();
16
16
  if (o)
17
- for (const h of o)
18
- r.set(h.type, h);
17
+ for (const m of o)
18
+ r.set(m.type, m);
19
19
  return r;
20
20
  }
21
- function re({
21
+ function ne({
22
22
  siteId: o,
23
23
  apiBaseUrl: r,
24
- projectId: h,
24
+ projectId: m,
25
25
  pageSlug: n,
26
- schoolSlug: b,
27
- schoolData: D,
26
+ schoolSlug: w,
27
+ schoolData: k,
28
28
  // reservado para header/navbar dinâmico (logo, nome da escola)
29
- contentProviders: C,
30
- onNavigate: c
29
+ contentProviders: E,
30
+ contentListParams: c,
31
+ onNavigate: C
31
32
  }) {
32
- const [s, E] = A(null), [j, w] = A(null), [p, H] = A(!0), [f, I] = A(null), [M, y] = A(null), k = B(c);
33
- k.current = c;
34
- const L = F((e) => {
33
+ const [s, j] = A(null), [H, u] = A(null), [D, l] = A(!0), [g, I] = A(null), [R, y] = A(null), L = z(C);
34
+ L.current = C;
35
+ const M = B((e) => {
35
36
  const t = `<script>
36
37
  (function() {
37
38
  document.addEventListener('click', function(e) {
@@ -50,105 +51,116 @@ function re({
50
51
  }
51
52
  }
52
53
  }, true);
54
+ document.addEventListener('submit', function(e) {
55
+ var form = e.target;
56
+ if (form && form.tagName === 'FORM') {
57
+ e.preventDefault();
58
+ e.stopPropagation();
59
+ var action = form.getAttribute('action') || '';
60
+ var params = new URLSearchParams(new FormData(form));
61
+ var href = action + (params.toString() ? '?' + params.toString() : '');
62
+ window.parent.postMessage({ type: 'viewer-navigate', href: href }, '*');
63
+ }
64
+ }, true);
53
65
  })();
54
66
  <\/script>`;
55
67
  return e.includes("</body>") ? e.replace("</body>", `${t}</body>`) : e + t;
56
68
  }, []);
57
69
  if (V(() => {
58
70
  const e = (t) => {
59
- t.data?.type === "viewer-navigate" && t.data?.href && k.current && k.current(t.data.href);
71
+ t.data?.type === "viewer-navigate" && t.data?.href && L.current && L.current(t.data.href);
60
72
  };
61
73
  return window.addEventListener("message", e), () => window.removeEventListener("message", e);
62
74
  }, []), V(() => {
63
75
  let e = !1;
64
- return H(!0), I(null), (async () => {
76
+ return l(!0), I(null), (async () => {
65
77
  try {
66
78
  const t = await fetch(
67
- `${r}/sites/${o}?projectId=${h}`
79
+ `${r}/sites/${o}?projectId=${m}`
68
80
  );
69
81
  if (!t.ok)
70
82
  throw new Error("Landing page não encontrada");
71
- const i = await t.json();
83
+ const a = await t.json();
72
84
  if (e) return;
73
- if (i.template) {
74
- const l = i.template.schemaVersion, x = i.template.pages && Array.isArray(i.template.pages);
75
- if (l === 2 || l === "2" || x) {
76
- const u = i.template;
77
- Array.isArray(u.pages) || (u.pages = []), u.schemaVersion !== 2 && u.schemaVersion !== "2" && (u.schemaVersion = 2), E(u);
85
+ if (a.template) {
86
+ const f = a.template.schemaVersion, x = a.template.pages && Array.isArray(a.template.pages);
87
+ if (f === 2 || f === "2" || x) {
88
+ const h = a.template;
89
+ Array.isArray(h.pages) || (h.pages = []), h.schemaVersion !== 2 && h.schemaVersion !== "2" && (h.schemaVersion = 2), j(h);
78
90
  } else
79
91
  throw new Error(
80
92
  "Formato de template legado não suportado. Por favor, recrie o site."
81
93
  );
82
94
  } else
83
- E(null);
84
- if (i.publishedHtml && J(i.publishedHtml) ? w(i.publishedHtml) : w(null), !i.template && !i.publishedHtml)
95
+ j(null);
96
+ if (a.publishedHtml && J(a.publishedHtml) ? u(a.publishedHtml) : u(null), !a.template && !a.publishedHtml)
85
97
  throw new Error("Template não encontrado");
86
98
  } catch (t) {
87
99
  e || I(
88
100
  t instanceof Error ? t.message : "Erro ao carregar landing page"
89
101
  );
90
102
  } finally {
91
- e || H(!1);
103
+ e || l(!1);
92
104
  }
93
105
  })(), () => {
94
106
  e = !0;
95
107
  };
96
- }, [o, r, h]), V(() => {
108
+ }, [o, r, m]), V(() => {
97
109
  if (!s) {
98
110
  y(null);
99
111
  return;
100
112
  }
101
113
  let e = !1;
102
- const t = Array.isArray(s.pages) ? s.pages : [], i = K(C);
103
- if (i.size === 0) {
114
+ const t = Array.isArray(s.pages) ? s.pages : [], a = K(E);
115
+ if (a.size === 0) {
104
116
  y(null);
105
117
  return;
106
118
  }
107
- let l, x = {};
119
+ let f, x = {};
108
120
  if (n) {
109
121
  const d = t.find(
110
- (m) => m.slug === n || m.id === n
122
+ (p) => p.slug === n || p.id === n
111
123
  );
112
124
  if (d)
113
- l = d;
125
+ f = d;
114
126
  else {
115
- const m = W(t, n);
116
- m && (l = m.page, x = m.params);
127
+ const p = N(t, n);
128
+ p && (f = p.page, x = p.params);
117
129
  }
118
130
  } else
119
- l = t.find((d) => d.id === "home") ?? t[0];
120
- if (!l) {
131
+ f = t.find((d) => d.id === "home") ?? t[0];
132
+ if (!f) {
121
133
  y(null);
122
134
  return;
123
135
  }
124
- const T = !!l.dataSource, u = l.structure?.some(
136
+ const T = !!f.dataSource, h = f.structure?.some(
125
137
  (d) => d.type === "blogPostGrid"
126
138
  );
127
- if (!T && !u) {
139
+ if (!T && !h) {
128
140
  y(null);
129
141
  return;
130
142
  }
131
- let R = l;
132
- return !T && u && (R = {
133
- ...l,
143
+ let $ = f;
144
+ return !T && h && ($ = {
145
+ ...f,
134
146
  dataSource: { mode: "list", provider: "blog-posts" }
135
- }), G(R, i, x).then((d) => {
147
+ }), G($, a, x, c).then((d) => {
136
148
  if (e) return;
137
- const m = N(
149
+ const p = W(
138
150
  d,
139
151
  s,
140
- b,
152
+ w,
141
153
  t,
142
154
  !1
143
155
  );
144
- y(m ?? null);
156
+ y(p ?? null);
145
157
  }).catch((d) => {
146
- e || (z.error("Error in content hydration:", d), y(null));
158
+ e || (O.error("Error in content hydration:", d), y(null));
147
159
  }), () => {
148
160
  e = !0;
149
161
  };
150
- }, [s, n, C, b]), p)
151
- return /* @__PURE__ */ a(
162
+ }, [s, n, E, w, c]), D)
163
+ return /* @__PURE__ */ i(
152
164
  "div",
153
165
  {
154
166
  style: {
@@ -157,11 +169,11 @@ function re({
157
169
  justifyContent: "center",
158
170
  minHeight: "100vh"
159
171
  },
160
- children: /* @__PURE__ */ a("div", { children: "Carregando..." })
172
+ children: /* @__PURE__ */ i("div", { children: "Carregando..." })
161
173
  }
162
174
  );
163
- if (f)
164
- return /* @__PURE__ */ a(
175
+ if (g)
176
+ return /* @__PURE__ */ i(
165
177
  "div",
166
178
  {
167
179
  style: {
@@ -170,14 +182,14 @@ function re({
170
182
  justifyContent: "center",
171
183
  minHeight: "100vh"
172
184
  },
173
- children: /* @__PURE__ */ a("div", { children: f || "Landing page não encontrada" })
185
+ children: /* @__PURE__ */ i("div", { children: g || "Landing page não encontrada" })
174
186
  }
175
187
  );
176
- if (j && (!n || n === "home") && !s)
177
- return /* @__PURE__ */ a(
188
+ if (H && (!n || n === "home") && !s)
189
+ return /* @__PURE__ */ i(
178
190
  "iframe",
179
191
  {
180
- srcDoc: L(j),
192
+ srcDoc: M(H),
181
193
  title: "Site publicado",
182
194
  style: {
183
195
  width: "100%",
@@ -189,9 +201,9 @@ function re({
189
201
  );
190
202
  if (!s)
191
203
  return null;
192
- const g = Array.isArray(s.pages) ? s.pages : [];
193
- if (g.length === 0)
194
- return /* @__PURE__ */ a(
204
+ const v = Array.isArray(s.pages) ? s.pages : [];
205
+ if (v.length === 0)
206
+ return /* @__PURE__ */ i(
195
207
  "div",
196
208
  {
197
209
  style: {
@@ -202,14 +214,14 @@ function re({
202
214
  padding: "2rem",
203
215
  textAlign: "center"
204
216
  },
205
- children: /* @__PURE__ */ a("div", { children: "Nenhuma página no site. Adicione páginas no editor." })
217
+ children: /* @__PURE__ */ i("div", { children: "Nenhuma página no site. Adicione páginas no editor." })
206
218
  }
207
219
  );
208
- if (M)
209
- return /* @__PURE__ */ a(
220
+ if (R)
221
+ return /* @__PURE__ */ i(
210
222
  "iframe",
211
223
  {
212
- srcDoc: L(M),
224
+ srcDoc: M(R),
213
225
  title: "Site",
214
226
  style: {
215
227
  width: "100%",
@@ -219,13 +231,13 @@ function re({
219
231
  }
220
232
  }
221
233
  );
222
- let v = (n ? g.find((e) => e.slug === n || e.id === n) : null) ?? null;
223
- if (!v && n) {
224
- const e = W(g, n);
225
- e && (v = e.page);
234
+ let b = (n ? v.find((e) => e.slug === n || e.id === n) : null) ?? null;
235
+ if (!b && n) {
236
+ const e = N(v, n);
237
+ e && (b = e.page);
226
238
  }
227
- if (v || (v = g.find((e) => e.id === "home") ?? g[0]), !v)
228
- return /* @__PURE__ */ a(
239
+ if (b || (b = v.find((e) => e.id === "home") ?? v[0]), !b)
240
+ return /* @__PURE__ */ i(
229
241
  "div",
230
242
  {
231
243
  style: {
@@ -234,14 +246,14 @@ function re({
234
246
  justifyContent: "center",
235
247
  minHeight: "100vh"
236
248
  },
237
- children: /* @__PURE__ */ a("div", { children: "Página não encontrada" })
249
+ children: /* @__PURE__ */ i("div", { children: "Página não encontrada" })
238
250
  }
239
251
  );
240
- const $ = N(v, s, b, g);
241
- return $ ? /* @__PURE__ */ a(
252
+ const F = W(b, s, w, v);
253
+ return F ? /* @__PURE__ */ i(
242
254
  "iframe",
243
255
  {
244
- srcDoc: L($),
256
+ srcDoc: M(F),
245
257
  title: "Site",
246
258
  style: {
247
259
  width: "100%",
@@ -250,7 +262,7 @@ function re({
250
262
  backgroundColor: "#ffffff"
251
263
  }
252
264
  }
253
- ) : /* @__PURE__ */ a(
265
+ ) : /* @__PURE__ */ i(
254
266
  "div",
255
267
  {
256
268
  style: {
@@ -261,41 +273,43 @@ function re({
261
273
  padding: "2rem",
262
274
  textAlign: "center"
263
275
  },
264
- children: /* @__PURE__ */ a("div", { children: "Conteúdo da página vazio. Adicione blocos no editor." })
276
+ children: /* @__PURE__ */ i("div", { children: "Conteúdo da página vazio. Adicione blocos no editor." })
265
277
  }
266
278
  );
267
279
  }
268
- function N(o, r, h, n, b = !0) {
269
- const D = {
280
+ function W(o, r, m, n, w = !0) {
281
+ const k = {
270
282
  ...o,
271
283
  structure: Array.isArray(o.structure) ? o.structure : []
272
- }, C = q(""), c = r.theme && typeof r.theme == "object" ? r.theme : null, s = c ? {
284
+ }, E = q(""), c = r.theme && typeof r.theme == "object" ? r.theme : null, C = c ? {
273
285
  ...P,
274
286
  ...c,
275
287
  colors: c.colors && typeof c.colors == "object" ? { ...P.colors, ...c.colors } : P.colors,
276
288
  typography: c.typography && typeof c.typography == "object" ? { ...P.typography, ...c.typography } : P.typography
277
- } : C.theme, E = {
289
+ } : E.theme, s = {
278
290
  ...r,
279
291
  schemaVersion: 2,
280
- theme: s
281
- }, j = h ? `/site/escola/${h}` : "/site", w = n ?? r.pages, p = w.find((f) => f.id === "home") ?? w[0], H = p && p.id !== D.id ? {
282
- ...p,
283
- structure: Array.isArray(p.structure) ? p.structure : []
292
+ theme: C
293
+ }, j = m ? `/site/escola/${m}` : "/site", H = n ?? r.pages, u = H.find((l) => l.id === "home") ?? H[0], D = u && u.id !== k.id ? {
294
+ ...u,
295
+ structure: Array.isArray(u.structure) ? u.structure : []
284
296
  } : void 0;
285
297
  try {
286
- const f = _(
287
- D,
288
- E,
289
- b,
298
+ const l = {};
299
+ D && (l.layoutFromPage = D), r.metadata && (l.siteMetadata = r.metadata);
300
+ const g = _(
301
+ k,
302
+ s,
303
+ w,
290
304
  j,
291
- H ? { layoutFromPage: H } : void 0
305
+ Object.keys(l).length > 0 ? l : void 0
292
306
  );
293
- return !f || !f.trim() ? null : f;
294
- } catch (f) {
295
- return z.error("Error generating HTML:", f), null;
307
+ return !g || !g.trim() ? null : g;
308
+ } catch (l) {
309
+ return O.error("Error generating HTML:", l), null;
296
310
  }
297
311
  }
298
312
  export {
299
- re as LandingPageViewer
313
+ ne as LandingPageViewer
300
314
  };
301
315
  //# sourceMappingURL=LandingPageViewer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"LandingPageViewer.js","sources":["../../src/viewer/LandingPageViewer.tsx"],"sourcesContent":["/**\n * Landing Page Viewer\n * Visualização pública da landing page.\n * Usa o mesmo mecanismo do Preview (editor): exportPageToHtml + iframe srcdoc.\n *\n * Supports dynamic pages via ContentProvider (Sprint 3):\n * - Optional `contentProviders` prop allows consumer to supply data providers\n * - Dynamic page resolution (e.g., \"blog/:slug\")\n * - Automatic content hydration before rendering\n */\n\nimport { useState, useEffect, useRef, useCallback } from \"react\";\nimport {\n SiteDocument,\n SitePage,\n exportPageToHtml,\n createEmptySiteDocument,\n defaultThemeTokens,\n} from \"../engine\";\nimport type { ContentProvider } from \"../engine/plugins/types\";\nimport { matchDynamicPage } from \"../engine/plugins/dynamicPageResolver\";\nimport {\n hydratePageWithContent,\n type ContentProviderMap,\n} from \"../engine/plugins/contentHydration\";\nimport { logger } from \"../utils/logger\";\n\n/** Verifica se o HTML tem conteúdo real no body (evita usar publishedHtml vazio) */\nfunction hasBodyContent(html: string): boolean {\n if (!html || typeof html !== \"string\") return false;\n const match = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n const bodyInner = match ? match[1].trim() : \"\";\n return bodyInner.length > 50;\n}\n\nexport interface SchoolData {\n id: string;\n name: string;\n slug: string;\n logo_url?: string;\n}\n\ninterface LandingPageViewerProps {\n siteId: string;\n apiBaseUrl: string;\n projectId: string;\n /** Slug da página (ex.: avisos). Se não informado, usa home. */\n pageSlug?: string;\n /** Slug da escola no contexto /site/escola/:schoolSlug */\n schoolSlug?: string;\n /** Dados da escola para header/navbar dinâmico (quando em contexto escola) */\n schoolData?: SchoolData;\n /**\n * Content providers for dynamic pages (e.g., blog posts, products).\n * Supplied by the consumer project to connect plugin data to the viewer.\n */\n contentProviders?: ContentProvider[];\n /**\n * Callback for internal navigation (link clicks inside iframe).\n * Receives the href from clicked links. Consumer should use router navigation.\n */\n onNavigate?: (href: string) => void;\n}\n\n/**\n * Builds a ContentProviderMap from an array of providers.\n */\nfunction buildProviderMap(providers?: ContentProvider[]): ContentProviderMap {\n const map: ContentProviderMap = new Map();\n if (providers) {\n for (const p of providers) {\n map.set(p.type, p);\n }\n }\n return map;\n}\n\nexport function LandingPageViewer({\n siteId,\n apiBaseUrl,\n projectId,\n pageSlug,\n schoolSlug,\n schoolData: _schoolData, // reservado para header/navbar dinâmico (logo, nome da escola)\n contentProviders,\n onNavigate,\n}: LandingPageViewerProps) {\n const [document, setDocument] = useState<SiteDocument | null>(null);\n const [publishedHtml, setPublishedHtml] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [hydratedHtml, setHydratedHtml] = useState<string | null>(null);\n\n const onNavigateRef = useRef(onNavigate);\n onNavigateRef.current = onNavigate;\n\n // Inject click interceptor into iframe HTML so link clicks propagate to parent\n const injectClickInterceptor = useCallback((html: string): string => {\n const script = `<script>\n(function() {\n document.addEventListener('click', function(e) {\n var target = e.target;\n var anchor = target;\n while (anchor && anchor.tagName !== 'A') {\n anchor = anchor.parentElement;\n }\n if (anchor && anchor.tagName === 'A') {\n var href = anchor.getAttribute('href') || '';\n if (href && href !== '#' && !href.startsWith('javascript:')) {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage({ type: 'viewer-navigate', href: href }, '*');\n return;\n }\n }\n }, true);\n})();\n</script>`;\n if (html.includes(\"</body>\")) {\n return html.replace(\"</body>\", `${script}</body>`);\n }\n return html + script;\n }, []);\n\n // Listen for navigation messages from iframe\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === \"viewer-navigate\" && event.data?.href) {\n if (onNavigateRef.current) {\n onNavigateRef.current(event.data.href);\n }\n }\n };\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, []);\n\n // Load site document from API. Uses stale flag to prevent\n // React Strict Mode double-mount from causing duplicate state updates.\n useEffect(() => {\n let stale = false;\n\n setIsLoading(true);\n setError(null);\n\n (async () => {\n try {\n const response = await fetch(\n `${apiBaseUrl}/sites/${siteId}?projectId=${projectId}`,\n );\n if (!response.ok) {\n throw new Error(\"Landing page não encontrada\");\n }\n\n const data = await response.json();\n if (stale) return;\n\n if (data.template) {\n const schemaVersion = data.template.schemaVersion;\n const hasPages =\n data.template.pages && Array.isArray(data.template.pages);\n const isV2 =\n schemaVersion === 2 || schemaVersion === \"2\" || hasPages;\n\n if (isV2) {\n const template = data.template as SiteDocument;\n if (!Array.isArray(template.pages)) {\n template.pages = [];\n }\n if (\n template.schemaVersion !== 2 &&\n template.schemaVersion !== \"2\"\n ) {\n template.schemaVersion = 2;\n }\n setDocument(template);\n } else {\n throw new Error(\n \"Formato de template legado não suportado. Por favor, recrie o site.\",\n );\n }\n } else {\n setDocument(null);\n }\n\n if (data.publishedHtml && hasBodyContent(data.publishedHtml)) {\n setPublishedHtml(data.publishedHtml);\n } else {\n setPublishedHtml(null);\n }\n\n if (!data.template && !data.publishedHtml) {\n throw new Error(\"Template não encontrado\");\n }\n } catch (err) {\n if (!stale) {\n setError(\n err instanceof Error\n ? err.message\n : \"Erro ao carregar landing page\",\n );\n }\n } finally {\n if (!stale) {\n setIsLoading(false);\n }\n }\n })();\n\n return () => {\n stale = true;\n };\n }, [siteId, apiBaseUrl, projectId]);\n\n // Hydrate pages when document + contentProviders are available.\n // Supports both: pages with explicit dataSource AND pages with blogPostGrid blocks.\n // Does NOT reset hydratedHtml at the start to avoid flash of mock data.\n // Only clears it when navigating to a page that doesn't need hydration.\n useEffect(() => {\n if (!document) {\n setHydratedHtml(null);\n return;\n }\n\n let stale = false;\n\n const pages = Array.isArray(document.pages) ? document.pages : [];\n const providerMap = buildProviderMap(contentProviders);\n\n if (providerMap.size === 0) {\n setHydratedHtml(null);\n return;\n }\n\n // Resolve the current page\n let resolvedPage: SitePage | undefined;\n let urlParams: Record<string, string> = {};\n\n if (pageSlug) {\n const exactPage = pages.find(\n (p) => p.slug === pageSlug || p.id === pageSlug,\n );\n if (exactPage) {\n resolvedPage = exactPage;\n } else {\n const match = matchDynamicPage(pages, pageSlug);\n if (match) {\n resolvedPage = match.page;\n urlParams = match.params;\n }\n }\n } else {\n resolvedPage = pages.find((p) => p.id === \"home\") ?? pages[0];\n }\n\n if (!resolvedPage) {\n setHydratedHtml(null);\n return;\n }\n\n // Check if page needs hydration:\n // 1. Has explicit dataSource (blog page, blog-post page)\n // 2. Has blogPostGrid blocks but no dataSource (home page with blog widget)\n const hasDataSource = !!resolvedPage.dataSource;\n const hasBlogBlocks = resolvedPage.structure?.some(\n (b) => b.type === \"blogPostGrid\",\n );\n\n if (!hasDataSource && !hasBlogBlocks) {\n setHydratedHtml(null);\n return;\n }\n\n // For pages without dataSource but with blog blocks, create synthetic dataSource\n let pageToHydrate = resolvedPage;\n if (!hasDataSource && hasBlogBlocks) {\n pageToHydrate = {\n ...resolvedPage,\n dataSource: { mode: \"list\" as const, provider: \"blog-posts\" },\n };\n }\n\n hydratePageWithContent(pageToHydrate, providerMap, urlParams)\n .then((hydratedPage) => {\n if (stale) return;\n\n // useCache: false — hydrated page has different block props than the\n // cached static render. Without this, exportPageToHtml returns the\n // cached static HTML (same page.id + docHash = same cache key).\n const html = renderPageToHtml(\n hydratedPage,\n document,\n schoolSlug,\n pages,\n false,\n );\n\n setHydratedHtml(html ?? null);\n })\n .catch((err) => {\n if (!stale) {\n logger.error(\"Error in content hydration:\", err);\n setHydratedHtml(null);\n }\n });\n\n return () => {\n stale = true;\n };\n }, [document, pageSlug, contentProviders, schoolSlug]);\n\n if (isLoading) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>Carregando...</div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>{error || \"Landing page não encontrada\"}</div>\n </div>\n );\n }\n\n // Preferir renderização via template (client-side) quando disponível.\n // Isso garante que o viewer usa exatamente o mesmo exportPageToHtml() do editor,\n // evitando diferenças de hover effects, CSS, etc. entre editor e site publicado.\n // publishedHtml do servidor é usado apenas como fallback quando não há template.\n const isHomeRoute = !pageSlug || pageSlug === \"home\";\n if (publishedHtml && isHomeRoute && !document) {\n return (\n <iframe\n srcDoc={injectClickInterceptor(publishedHtml)}\n title=\"Site publicado\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n }\n\n // Renderizar documento (template) — mesmo pipeline do editor\n if (!document) {\n return null;\n }\n\n // Garantir que pages seja array (evita crash se API retornar formato inesperado)\n const pages = Array.isArray(document.pages) ? document.pages : [];\n\n if (pages.length === 0) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n padding: \"2rem\",\n textAlign: \"center\",\n }}\n >\n <div>Nenhuma página no site. Adicione páginas no editor.</div>\n </div>\n );\n }\n\n // If we have hydrated HTML from ContentProvider, use it\n if (hydratedHtml) {\n return (\n <iframe\n srcDoc={injectClickInterceptor(hydratedHtml)}\n title=\"Site\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n }\n\n // Resolver página por slug ou id; fallback para home\n // Also try dynamic page resolution\n let page =\n (pageSlug\n ? pages.find((p) => p.slug === pageSlug || p.id === pageSlug)\n : null) ??\n null;\n\n if (!page && pageSlug) {\n const match = matchDynamicPage(pages, pageSlug);\n if (match) {\n page = match.page;\n }\n }\n\n if (!page) {\n page = pages.find((p) => p.id === \"home\") ?? pages[0];\n }\n\n if (!page) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>Página não encontrada</div>\n </div>\n );\n }\n\n const html = renderPageToHtml(page, document, schoolSlug, pages);\n if (!html) {\n return (\n <div\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2rem\",\n textAlign: \"center\",\n }}\n >\n <div>Conteúdo da página vazio. Adicione blocos no editor.</div>\n </div>\n );\n }\n\n // Mesmo mecanismo do Preview (editor): iframe com srcdoc = HTML completo\n return (\n <iframe\n srcDoc={injectClickInterceptor(html)}\n title=\"Site\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n}\n\n/**\n * Generates HTML from a page using the standard export pipeline.\n * Extracted to reuse for both static and hydrated pages.\n *\n * @param useCache - Pass false for hydrated pages to bypass the export cache.\n * The cache key uses page.id + docHash, which is identical for static and\n * hydrated renders of the same page. Hydrated pages have different block\n * props (real data), so they must skip the cache to avoid getting stale HTML.\n */\nfunction renderPageToHtml(\n page: SitePage,\n document: SiteDocument,\n schoolSlug?: string,\n allPages?: SitePage[],\n useCache: boolean = true,\n): string | null {\n // Garantir structure para o export (evita erro se página vier sem structure)\n const pageWithStructure = {\n ...page,\n structure: Array.isArray(page.structure) ? page.structure : [],\n };\n\n // Garantir theme completo para o export (merge com default evita theme parcial quebrar CSS)\n const defaultDoc = createEmptySiteDocument(\"\");\n const rawTheme =\n document.theme && typeof document.theme === \"object\"\n ? document.theme\n : null;\n const theme = rawTheme\n ? {\n ...defaultThemeTokens,\n ...rawTheme,\n colors:\n rawTheme.colors && typeof rawTheme.colors === \"object\"\n ? { ...defaultThemeTokens.colors, ...rawTheme.colors }\n : defaultThemeTokens.colors,\n typography:\n rawTheme.typography && typeof rawTheme.typography === \"object\"\n ? { ...defaultThemeTokens.typography, ...rawTheme.typography }\n : defaultThemeTokens.typography,\n }\n : defaultDoc.theme;\n\n const documentWithTheme: SiteDocument = {\n ...document,\n schemaVersion: 2,\n theme,\n };\n\n // basePath para links (ex.: /site ou /site/escola/:slug)\n const basePath = schoolSlug ? `/site/escola/${schoolSlug}` : \"/site\";\n\n const pages = allPages ?? document.pages;\n const homePage = pages.find((p) => p.id === \"home\") ?? pages[0];\n const layoutFromPage =\n homePage && homePage.id !== pageWithStructure.id\n ? {\n ...homePage,\n structure: Array.isArray(homePage.structure)\n ? homePage.structure\n : [],\n }\n : undefined;\n\n try {\n const html = exportPageToHtml(\n pageWithStructure,\n documentWithTheme,\n useCache,\n basePath,\n layoutFromPage ? { layoutFromPage } : undefined,\n );\n\n if (!html || !html.trim()) {\n return null;\n }\n\n return html;\n } catch (err) {\n logger.error(\"Error generating HTML:\", err);\n return null;\n }\n}\n"],"names":["hasBodyContent","html","match","buildProviderMap","providers","map","p","LandingPageViewer","siteId","apiBaseUrl","projectId","pageSlug","schoolSlug","_schoolData","contentProviders","onNavigate","document","setDocument","useState","publishedHtml","setPublishedHtml","isLoading","setIsLoading","error","setError","hydratedHtml","setHydratedHtml","onNavigateRef","useRef","injectClickInterceptor","useCallback","script","useEffect","handleMessage","event","stale","response","data","schemaVersion","hasPages","template","err","pages","providerMap","resolvedPage","urlParams","exactPage","matchDynamicPage","hasDataSource","hasBlogBlocks","b","pageToHydrate","hydratePageWithContent","hydratedPage","renderPageToHtml","logger","jsx","page","allPages","useCache","pageWithStructure","defaultDoc","createEmptySiteDocument","rawTheme","theme","defaultThemeTokens","documentWithTheme","basePath","homePage","layoutFromPage","exportPageToHtml"],"mappings":"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"}
1
+ {"version":3,"file":"LandingPageViewer.js","sources":["../../src/viewer/LandingPageViewer.tsx"],"sourcesContent":["/**\n * Landing Page Viewer\n * Visualização pública da landing page.\n * Usa o mesmo mecanismo do Preview (editor): exportPageToHtml + iframe srcdoc.\n *\n * Supports dynamic pages via ContentProvider (Sprint 3):\n * - Optional `contentProviders` prop allows consumer to supply data providers\n * - Dynamic page resolution (e.g., \"blog/:slug\")\n * - Automatic content hydration before rendering\n */\n\nimport { useState, useEffect, useRef, useCallback } from \"react\";\nimport {\n SiteDocument,\n SitePage,\n exportPageToHtml,\n createEmptySiteDocument,\n defaultThemeTokens,\n} from \"../engine\";\nimport type { ContentProvider, ContentListParams } from \"../engine/plugins/types\";\nimport { matchDynamicPage } from \"../engine/plugins/dynamicPageResolver\";\nimport {\n hydratePageWithContent,\n type ContentProviderMap,\n} from \"../engine/plugins/contentHydration\";\nimport { logger } from \"../utils/logger\";\n\n/** Verifica se o HTML tem conteúdo real no body (evita usar publishedHtml vazio) */\nfunction hasBodyContent(html: string): boolean {\n if (!html || typeof html !== \"string\") return false;\n const match = html.match(/<body[^>]*>([\\s\\S]*?)<\\/body>/i);\n const bodyInner = match ? match[1].trim() : \"\";\n return bodyInner.length > 50;\n}\n\nexport interface SchoolData {\n id: string;\n name: string;\n slug: string;\n logo_url?: string;\n}\n\ninterface LandingPageViewerProps {\n siteId: string;\n apiBaseUrl: string;\n projectId: string;\n /** Slug da página (ex.: avisos). Se não informado, usa home. */\n pageSlug?: string;\n /** Slug da escola no contexto /site/escola/:schoolSlug */\n schoolSlug?: string;\n /** Dados da escola para header/navbar dinâmico (quando em contexto escola) */\n schoolData?: SchoolData;\n /**\n * Content providers for dynamic pages (e.g., blog posts, products).\n * Supplied by the consumer project to connect plugin data to the viewer.\n */\n contentProviders?: ContentProvider[];\n /**\n * Params for content list filtering (search, category).\n * Consumer extracts these from URL query params (e.g., ?busca=X&categoria=Y).\n */\n contentListParams?: ContentListParams;\n /**\n * Callback for internal navigation (link clicks inside iframe).\n * Receives the href from clicked links. Consumer should use router navigation.\n */\n onNavigate?: (href: string) => void;\n}\n\n/**\n * Builds a ContentProviderMap from an array of providers.\n */\nfunction buildProviderMap(providers?: ContentProvider[]): ContentProviderMap {\n const map: ContentProviderMap = new Map();\n if (providers) {\n for (const p of providers) {\n map.set(p.type, p);\n }\n }\n return map;\n}\n\nexport function LandingPageViewer({\n siteId,\n apiBaseUrl,\n projectId,\n pageSlug,\n schoolSlug,\n schoolData: _schoolData, // reservado para header/navbar dinâmico (logo, nome da escola)\n contentProviders,\n contentListParams,\n onNavigate,\n}: LandingPageViewerProps) {\n const [document, setDocument] = useState<SiteDocument | null>(null);\n const [publishedHtml, setPublishedHtml] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [hydratedHtml, setHydratedHtml] = useState<string | null>(null);\n\n const onNavigateRef = useRef(onNavigate);\n onNavigateRef.current = onNavigate;\n\n // Inject click + form submit interceptor into iframe HTML so interactions propagate to parent\n const injectClickInterceptor = useCallback((html: string): string => {\n const script = `<script>\n(function() {\n document.addEventListener('click', function(e) {\n var target = e.target;\n var anchor = target;\n while (anchor && anchor.tagName !== 'A') {\n anchor = anchor.parentElement;\n }\n if (anchor && anchor.tagName === 'A') {\n var href = anchor.getAttribute('href') || '';\n if (href && href !== '#' && !href.startsWith('javascript:')) {\n e.preventDefault();\n e.stopPropagation();\n window.parent.postMessage({ type: 'viewer-navigate', href: href }, '*');\n return;\n }\n }\n }, true);\n document.addEventListener('submit', function(e) {\n var form = e.target;\n if (form && form.tagName === 'FORM') {\n e.preventDefault();\n e.stopPropagation();\n var action = form.getAttribute('action') || '';\n var params = new URLSearchParams(new FormData(form));\n var href = action + (params.toString() ? '?' + params.toString() : '');\n window.parent.postMessage({ type: 'viewer-navigate', href: href }, '*');\n }\n }, true);\n})();\n</script>`;\n if (html.includes(\"</body>\")) {\n return html.replace(\"</body>\", `${script}</body>`);\n }\n return html + script;\n }, []);\n\n // Listen for navigation messages from iframe\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (event.data?.type === \"viewer-navigate\" && event.data?.href) {\n if (onNavigateRef.current) {\n onNavigateRef.current(event.data.href);\n }\n }\n };\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, []);\n\n // Load site document from API. Uses stale flag to prevent\n // React Strict Mode double-mount from causing duplicate state updates.\n useEffect(() => {\n let stale = false;\n\n setIsLoading(true);\n setError(null);\n\n (async () => {\n try {\n const response = await fetch(\n `${apiBaseUrl}/sites/${siteId}?projectId=${projectId}`,\n );\n if (!response.ok) {\n throw new Error(\"Landing page não encontrada\");\n }\n\n const data = await response.json();\n if (stale) return;\n\n if (data.template) {\n const schemaVersion = data.template.schemaVersion;\n const hasPages =\n data.template.pages && Array.isArray(data.template.pages);\n const isV2 =\n schemaVersion === 2 || schemaVersion === \"2\" || hasPages;\n\n if (isV2) {\n const template = data.template as SiteDocument;\n if (!Array.isArray(template.pages)) {\n template.pages = [];\n }\n if (\n template.schemaVersion !== 2 &&\n template.schemaVersion !== \"2\"\n ) {\n template.schemaVersion = 2;\n }\n setDocument(template);\n } else {\n throw new Error(\n \"Formato de template legado não suportado. Por favor, recrie o site.\",\n );\n }\n } else {\n setDocument(null);\n }\n\n if (data.publishedHtml && hasBodyContent(data.publishedHtml)) {\n setPublishedHtml(data.publishedHtml);\n } else {\n setPublishedHtml(null);\n }\n\n if (!data.template && !data.publishedHtml) {\n throw new Error(\"Template não encontrado\");\n }\n } catch (err) {\n if (!stale) {\n setError(\n err instanceof Error\n ? err.message\n : \"Erro ao carregar landing page\",\n );\n }\n } finally {\n if (!stale) {\n setIsLoading(false);\n }\n }\n })();\n\n return () => {\n stale = true;\n };\n }, [siteId, apiBaseUrl, projectId]);\n\n // Hydrate pages when document + contentProviders are available.\n // Supports both: pages with explicit dataSource AND pages with blogPostGrid blocks.\n // Does NOT reset hydratedHtml at the start to avoid flash of mock data.\n // Only clears it when navigating to a page that doesn't need hydration.\n useEffect(() => {\n if (!document) {\n setHydratedHtml(null);\n return;\n }\n\n let stale = false;\n\n const pages = Array.isArray(document.pages) ? document.pages : [];\n const providerMap = buildProviderMap(contentProviders);\n\n if (providerMap.size === 0) {\n setHydratedHtml(null);\n return;\n }\n\n // Resolve the current page\n let resolvedPage: SitePage | undefined;\n let urlParams: Record<string, string> = {};\n\n if (pageSlug) {\n const exactPage = pages.find(\n (p) => p.slug === pageSlug || p.id === pageSlug,\n );\n if (exactPage) {\n resolvedPage = exactPage;\n } else {\n const match = matchDynamicPage(pages, pageSlug);\n if (match) {\n resolvedPage = match.page;\n urlParams = match.params;\n }\n }\n } else {\n resolvedPage = pages.find((p) => p.id === \"home\") ?? pages[0];\n }\n\n if (!resolvedPage) {\n setHydratedHtml(null);\n return;\n }\n\n // Check if page needs hydration:\n // 1. Has explicit dataSource (blog page, blog-post page)\n // 2. Has blogPostGrid blocks but no dataSource (home page with blog widget)\n const hasDataSource = !!resolvedPage.dataSource;\n const hasBlogBlocks = resolvedPage.structure?.some(\n (b) => b.type === \"blogPostGrid\",\n );\n\n if (!hasDataSource && !hasBlogBlocks) {\n setHydratedHtml(null);\n return;\n }\n\n // For pages without dataSource but with blog blocks, create synthetic dataSource\n let pageToHydrate = resolvedPage;\n if (!hasDataSource && hasBlogBlocks) {\n pageToHydrate = {\n ...resolvedPage,\n dataSource: { mode: \"list\" as const, provider: \"blog-posts\" },\n };\n }\n\n hydratePageWithContent(pageToHydrate, providerMap, urlParams, contentListParams)\n .then((hydratedPage) => {\n if (stale) return;\n\n // useCache: false — hydrated page has different block props than the\n // cached static render. Without this, exportPageToHtml returns the\n // cached static HTML (same page.id + docHash = same cache key).\n const html = renderPageToHtml(\n hydratedPage,\n document,\n schoolSlug,\n pages,\n false,\n );\n\n setHydratedHtml(html ?? null);\n })\n .catch((err) => {\n if (!stale) {\n logger.error(\"Error in content hydration:\", err);\n setHydratedHtml(null);\n }\n });\n\n return () => {\n stale = true;\n };\n }, [document, pageSlug, contentProviders, schoolSlug, contentListParams]);\n\n if (isLoading) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>Carregando...</div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>{error || \"Landing page não encontrada\"}</div>\n </div>\n );\n }\n\n // Preferir renderização via template (client-side) quando disponível.\n // Isso garante que o viewer usa exatamente o mesmo exportPageToHtml() do editor,\n // evitando diferenças de hover effects, CSS, etc. entre editor e site publicado.\n // publishedHtml do servidor é usado apenas como fallback quando não há template.\n const isHomeRoute = !pageSlug || pageSlug === \"home\";\n if (publishedHtml && isHomeRoute && !document) {\n return (\n <iframe\n srcDoc={injectClickInterceptor(publishedHtml)}\n title=\"Site publicado\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n }\n\n // Renderizar documento (template) — mesmo pipeline do editor\n if (!document) {\n return null;\n }\n\n // Garantir que pages seja array (evita crash se API retornar formato inesperado)\n const pages = Array.isArray(document.pages) ? document.pages : [];\n\n if (pages.length === 0) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n padding: \"2rem\",\n textAlign: \"center\",\n }}\n >\n <div>Nenhuma página no site. Adicione páginas no editor.</div>\n </div>\n );\n }\n\n // If we have hydrated HTML from ContentProvider, use it\n if (hydratedHtml) {\n return (\n <iframe\n srcDoc={injectClickInterceptor(hydratedHtml)}\n title=\"Site\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n }\n\n // Resolver página por slug ou id; fallback para home\n // Also try dynamic page resolution\n let page =\n (pageSlug\n ? pages.find((p) => p.slug === pageSlug || p.id === pageSlug)\n : null) ??\n null;\n\n if (!page && pageSlug) {\n const match = matchDynamicPage(pages, pageSlug);\n if (match) {\n page = match.page;\n }\n }\n\n if (!page) {\n page = pages.find((p) => p.id === \"home\") ?? pages[0];\n }\n\n if (!page) {\n return (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"100vh\",\n }}\n >\n <div>Página não encontrada</div>\n </div>\n );\n }\n\n const html = renderPageToHtml(page, document, schoolSlug, pages);\n if (!html) {\n return (\n <div\n style={{\n minHeight: \"100vh\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"2rem\",\n textAlign: \"center\",\n }}\n >\n <div>Conteúdo da página vazio. Adicione blocos no editor.</div>\n </div>\n );\n }\n\n // Mesmo mecanismo do Preview (editor): iframe com srcdoc = HTML completo\n return (\n <iframe\n srcDoc={injectClickInterceptor(html)}\n title=\"Site\"\n style={{\n width: \"100%\",\n minHeight: \"100vh\",\n border: \"none\",\n backgroundColor: \"#ffffff\",\n }}\n />\n );\n}\n\n/**\n * Generates HTML from a page using the standard export pipeline.\n * Extracted to reuse for both static and hydrated pages.\n *\n * @param useCache - Pass false for hydrated pages to bypass the export cache.\n * The cache key uses page.id + docHash, which is identical for static and\n * hydrated renders of the same page. Hydrated pages have different block\n * props (real data), so they must skip the cache to avoid getting stale HTML.\n */\nfunction renderPageToHtml(\n page: SitePage,\n document: SiteDocument,\n schoolSlug?: string,\n allPages?: SitePage[],\n useCache: boolean = true,\n): string | null {\n // Garantir structure para o export (evita erro se página vier sem structure)\n const pageWithStructure = {\n ...page,\n structure: Array.isArray(page.structure) ? page.structure : [],\n };\n\n // Garantir theme completo para o export (merge com default evita theme parcial quebrar CSS)\n const defaultDoc = createEmptySiteDocument(\"\");\n const rawTheme =\n document.theme && typeof document.theme === \"object\"\n ? document.theme\n : null;\n const theme = rawTheme\n ? {\n ...defaultThemeTokens,\n ...rawTheme,\n colors:\n rawTheme.colors && typeof rawTheme.colors === \"object\"\n ? { ...defaultThemeTokens.colors, ...rawTheme.colors }\n : defaultThemeTokens.colors,\n typography:\n rawTheme.typography && typeof rawTheme.typography === \"object\"\n ? { ...defaultThemeTokens.typography, ...rawTheme.typography }\n : defaultThemeTokens.typography,\n }\n : defaultDoc.theme;\n\n const documentWithTheme: SiteDocument = {\n ...document,\n schemaVersion: 2,\n theme,\n };\n\n // basePath para links (ex.: /site ou /site/escola/:slug)\n const basePath = schoolSlug ? `/site/escola/${schoolSlug}` : \"/site\";\n\n const pages = allPages ?? document.pages;\n const homePage = pages.find((p) => p.id === \"home\") ?? pages[0];\n const layoutFromPage =\n homePage && homePage.id !== pageWithStructure.id\n ? {\n ...homePage,\n structure: Array.isArray(homePage.structure)\n ? homePage.structure\n : [],\n }\n : undefined;\n\n try {\n const exportOptions: Record<string, unknown> = {};\n if (layoutFromPage) exportOptions.layoutFromPage = layoutFromPage;\n if (document.metadata) exportOptions.siteMetadata = document.metadata;\n\n const html = exportPageToHtml(\n pageWithStructure,\n documentWithTheme,\n useCache,\n basePath,\n Object.keys(exportOptions).length > 0 ? exportOptions as any : undefined,\n );\n\n if (!html || !html.trim()) {\n return null;\n }\n\n return html;\n } catch (err) {\n logger.error(\"Error generating HTML:\", err);\n return null;\n }\n}\n"],"names":["hasBodyContent","html","match","buildProviderMap","providers","map","p","LandingPageViewer","siteId","apiBaseUrl","projectId","pageSlug","schoolSlug","_schoolData","contentProviders","contentListParams","onNavigate","document","setDocument","useState","publishedHtml","setPublishedHtml","isLoading","setIsLoading","error","setError","hydratedHtml","setHydratedHtml","onNavigateRef","useRef","injectClickInterceptor","useCallback","script","useEffect","handleMessage","event","stale","response","data","schemaVersion","hasPages","template","err","pages","providerMap","resolvedPage","urlParams","exactPage","matchDynamicPage","hasDataSource","hasBlogBlocks","b","pageToHydrate","hydratePageWithContent","hydratedPage","renderPageToHtml","logger","jsx","page","allPages","useCache","pageWithStructure","defaultDoc","createEmptySiteDocument","rawTheme","theme","defaultThemeTokens","documentWithTheme","basePath","homePage","layoutFromPage","exportOptions","exportPageToHtml"],"mappings":";;;;;;;;AA4BA,SAASA,EAAeC,GAAuB;AAC7C,MAAI,CAACA,KAAQ,OAAOA,KAAS,SAAU,QAAO;AAC9C,QAAMC,IAAQD,EAAK,MAAM,gCAAgC;AAEzD,UADkBC,IAAQA,EAAM,CAAC,EAAE,SAAS,IAC3B,SAAS;AAC5B;AAuCA,SAASC,EAAiBC,GAAmD;AAC3E,QAAMC,wBAA8B,IAAA;AACpC,MAAID;AACF,eAAWE,KAAKF;AACd,MAAAC,EAAI,IAAIC,EAAE,MAAMA,CAAC;AAGrB,SAAOD;AACT;AAEO,SAASE,GAAkB;AAAA,EAChC,QAAAC;AAAA,EACA,YAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC;AAAA,EACA,YAAYC;AAAA;AAAA,EACZ,kBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,YAAAC;AACF,GAA2B;AACzB,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAA8B,IAAI,GAC5D,CAACC,GAAeC,CAAgB,IAAIF,EAAwB,IAAI,GAChE,CAACG,GAAWC,CAAY,IAAIJ,EAAS,EAAI,GACzC,CAACK,GAAOC,CAAQ,IAAIN,EAAwB,IAAI,GAChD,CAACO,GAAcC,CAAe,IAAIR,EAAwB,IAAI,GAE9DS,IAAgBC,EAAOb,CAAU;AACvC,EAAAY,EAAc,UAAUZ;AAGxB,QAAMc,IAAyBC,EAAY,CAAC9B,MAAyB;AACnE,UAAM+B,IAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+Bf,WAAI/B,EAAK,SAAS,SAAS,IAClBA,EAAK,QAAQ,WAAW,GAAG+B,CAAM,SAAS,IAE5C/B,IAAO+B;AAAA,EAChB,GAAG,CAAA,CAAE;AA6LL,MA1LAC,EAAU,MAAM;AACd,UAAMC,IAAgB,CAACC,MAAwB;AAC7C,MAAIA,EAAM,MAAM,SAAS,qBAAqBA,EAAM,MAAM,QACpDP,EAAc,WAChBA,EAAc,QAAQO,EAAM,KAAK,IAAI;AAAA,IAG3C;AACA,kBAAO,iBAAiB,WAAWD,CAAa,GACzC,MAAM,OAAO,oBAAoB,WAAWA,CAAa;AAAA,EAClE,GAAG,CAAA,CAAE,GAILD,EAAU,MAAM;AACd,QAAIG,IAAQ;AAEZ,WAAAb,EAAa,EAAI,GACjBE,EAAS,IAAI,IAEZ,YAAY;AACX,UAAI;AACF,cAAMY,IAAW,MAAM;AAAA,UACrB,GAAG5B,CAAU,UAAUD,CAAM,cAAcE,CAAS;AAAA,QAAA;AAEtD,YAAI,CAAC2B,EAAS;AACZ,gBAAM,IAAI,MAAM,6BAA6B;AAG/C,cAAMC,IAAO,MAAMD,EAAS,KAAA;AAC5B,YAAID,EAAO;AAEX,YAAIE,EAAK,UAAU;AACjB,gBAAMC,IAAgBD,EAAK,SAAS,eAC9BE,IACJF,EAAK,SAAS,SAAS,MAAM,QAAQA,EAAK,SAAS,KAAK;AAI1D,cAFEC,MAAkB,KAAKA,MAAkB,OAAOC,GAExC;AACR,kBAAMC,IAAWH,EAAK;AACtB,YAAK,MAAM,QAAQG,EAAS,KAAK,MAC/BA,EAAS,QAAQ,CAAA,IAGjBA,EAAS,kBAAkB,KAC3BA,EAAS,kBAAkB,QAE3BA,EAAS,gBAAgB,IAE3BvB,EAAYuB,CAAQ;AAAA,UACtB;AACE,kBAAM,IAAI;AAAA,cACR;AAAA,YAAA;AAAA,QAGN;AACE,UAAAvB,EAAY,IAAI;AASlB,YANIoB,EAAK,iBAAiBtC,EAAesC,EAAK,aAAa,IACzDjB,EAAiBiB,EAAK,aAAa,IAEnCjB,EAAiB,IAAI,GAGnB,CAACiB,EAAK,YAAY,CAACA,EAAK;AAC1B,gBAAM,IAAI,MAAM,yBAAyB;AAAA,MAE7C,SAASI,GAAK;AACZ,QAAKN,KACHX;AAAA,UACEiB,aAAe,QACXA,EAAI,UACJ;AAAA,QAAA;AAAA,MAGV,UAAA;AACE,QAAKN,KACHb,EAAa,EAAK;AAAA,MAEtB;AAAA,IACF,GAAA,GAEO,MAAM;AACX,MAAAa,IAAQ;AAAA,IACV;AAAA,EACF,GAAG,CAAC5B,GAAQC,GAAYC,CAAS,CAAC,GAMlCuB,EAAU,MAAM;AACd,QAAI,CAAChB,GAAU;AACb,MAAAU,EAAgB,IAAI;AACpB;AAAA,IACF;AAEA,QAAIS,IAAQ;AAEZ,UAAMO,IAAQ,MAAM,QAAQ1B,EAAS,KAAK,IAAIA,EAAS,QAAQ,CAAA,GACzD2B,IAAczC,EAAiBW,CAAgB;AAErD,QAAI8B,EAAY,SAAS,GAAG;AAC1B,MAAAjB,EAAgB,IAAI;AACpB;AAAA,IACF;AAGA,QAAIkB,GACAC,IAAoC,CAAA;AAExC,QAAInC,GAAU;AACZ,YAAMoC,IAAYJ,EAAM;AAAA,QACtB,CAAC,MAAM,EAAE,SAAShC,KAAY,EAAE,OAAOA;AAAA,MAAA;AAEzC,UAAIoC;AACF,QAAAF,IAAeE;AAAA,WACV;AACL,cAAM7C,IAAQ8C,EAAiBL,GAAOhC,CAAQ;AAC9C,QAAIT,MACF2C,IAAe3C,EAAM,MACrB4C,IAAY5C,EAAM;AAAA,MAEtB;AAAA,IACF;AACE,MAAA2C,IAAeF,EAAM,KAAK,CAACrC,MAAMA,EAAE,OAAO,MAAM,KAAKqC,EAAM,CAAC;AAG9D,QAAI,CAACE,GAAc;AACjB,MAAAlB,EAAgB,IAAI;AACpB;AAAA,IACF;AAKA,UAAMsB,IAAgB,CAAC,CAACJ,EAAa,YAC/BK,IAAgBL,EAAa,WAAW;AAAA,MAC5C,CAACM,MAAMA,EAAE,SAAS;AAAA,IAAA;AAGpB,QAAI,CAACF,KAAiB,CAACC,GAAe;AACpC,MAAAvB,EAAgB,IAAI;AACpB;AAAA,IACF;AAGA,QAAIyB,IAAgBP;AACpB,WAAI,CAACI,KAAiBC,MACpBE,IAAgB;AAAA,MACd,GAAGP;AAAA,MACH,YAAY,EAAE,MAAM,QAAiB,UAAU,aAAA;AAAA,IAAa,IAIhEQ,EAAuBD,GAAeR,GAAaE,GAAW/B,CAAiB,EAC5E,KAAK,CAACuC,MAAiB;AACtB,UAAIlB,EAAO;AAKX,YAAMnC,IAAOsD;AAAA,QACXD;AAAA,QACArC;AAAA,QACAL;AAAA,QACA+B;AAAAA,QACA;AAAA,MAAA;AAGF,MAAAhB,EAAgB1B,KAAQ,IAAI;AAAA,IAC9B,CAAC,EACA,MAAM,CAACyC,MAAQ;AACd,MAAKN,MACHoB,EAAO,MAAM,+BAA+Bd,CAAG,GAC/Cf,EAAgB,IAAI;AAAA,IAExB,CAAC,GAEI,MAAM;AACX,MAAAS,IAAQ;AAAA,IACV;AAAA,EACF,GAAG,CAACnB,GAAUN,GAAUG,GAAkBF,GAAYG,CAAiB,CAAC,GAEpEO;AACF,WACE,gBAAAmC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,WAAW;AAAA,QAAA;AAAA,QAGb,UAAA,gBAAAA,EAAC,SAAI,UAAA,gBAAA,CAAa;AAAA,MAAA;AAAA,IAAA;AAKxB,MAAIjC;AACF,WACE,gBAAAiC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,WAAW;AAAA,QAAA;AAAA,QAGb,UAAA,gBAAAA,EAAC,OAAA,EAAK,UAAAjC,KAAS,8BAAA,CAA8B;AAAA,MAAA;AAAA,IAAA;AAUnD,MAAIJ,MADgB,CAACT,KAAYA,MAAa,WACV,CAACM;AACnC,WACE,gBAAAwC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,QAAQ3B,EAAuBV,CAAa;AAAA,QAC5C,OAAM;AAAA,QACN,OAAO;AAAA,UACL,OAAO;AAAA,UACP,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,iBAAiB;AAAA,QAAA;AAAA,MACnB;AAAA,IAAA;AAMN,MAAI,CAACH;AACH,WAAO;AAIT,QAAM0B,IAAQ,MAAM,QAAQ1B,EAAS,KAAK,IAAIA,EAAS,QAAQ,CAAA;AAE/D,MAAI0B,EAAM,WAAW;AACnB,WACE,gBAAAc;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,WAAW;AAAA,UACX,SAAS;AAAA,UACT,WAAW;AAAA,QAAA;AAAA,QAGb,UAAA,gBAAAA,EAAC,SAAI,UAAA,sDAAA,CAAmD;AAAA,MAAA;AAAA,IAAA;AAM9D,MAAI/B;AACF,WACE,gBAAA+B;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,QAAQ3B,EAAuBJ,CAAY;AAAA,QAC3C,OAAM;AAAA,QACN,OAAO;AAAA,UACL,OAAO;AAAA,UACP,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,iBAAiB;AAAA,QAAA;AAAA,MACnB;AAAA,IAAA;AAON,MAAIgC,KACD/C,IACGgC,EAAM,KAAK,CAACrC,MAAMA,EAAE,SAASK,KAAYL,EAAE,OAAOK,CAAQ,IAC1D,SACJ;AAEF,MAAI,CAAC+C,KAAQ/C,GAAU;AACrB,UAAMT,IAAQ8C,EAAiBL,GAAOhC,CAAQ;AAC9C,IAAIT,MACFwD,IAAOxD,EAAM;AAAA,EAEjB;AAMA,MAJKwD,MACHA,IAAOf,EAAM,KAAK,CAACrC,MAAMA,EAAE,OAAO,MAAM,KAAKqC,EAAM,CAAC,IAGlD,CAACe;AACH,WACE,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAO;AAAA,UACL,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,WAAW;AAAA,QAAA;AAAA,QAGb,UAAA,gBAAAA,EAAC,SAAI,UAAA,wBAAA,CAAqB;AAAA,MAAA;AAAA,IAAA;AAKhC,QAAMxD,IAAOsD,EAAiBG,GAAMzC,GAAUL,GAAY+B,CAAK;AAC/D,SAAK1C,IAmBH,gBAAAwD;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,QAAQ3B,EAAuB7B,CAAI;AAAA,MACnC,OAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,iBAAiB;AAAA,MAAA;AAAA,IACnB;AAAA,EAAA,IAzBA,gBAAAwD;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,OAAO;AAAA,QACL,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,gBAAgB;AAAA,QAChB,SAAS;AAAA,QACT,WAAW;AAAA,MAAA;AAAA,MAGb,UAAA,gBAAAA,EAAC,SAAI,UAAA,uDAAA,CAAoD;AAAA,IAAA;AAAA,EAAA;AAkBjE;AAWA,SAASF,EACPG,GACAzC,GACAL,GACA+C,GACAC,IAAoB,IACL;AAEf,QAAMC,IAAoB;AAAA,IACxB,GAAGH;AAAA,IACH,WAAW,MAAM,QAAQA,EAAK,SAAS,IAAIA,EAAK,YAAY,CAAA;AAAA,EAAC,GAIzDI,IAAaC,EAAwB,EAAE,GACvCC,IACJ/C,EAAS,SAAS,OAAOA,EAAS,SAAU,WACxCA,EAAS,QACT,MACAgD,IAAQD,IACV;AAAA,IACE,GAAGE;AAAA,IACH,GAAGF;AAAA,IACH,QACEA,EAAS,UAAU,OAAOA,EAAS,UAAW,WAC1C,EAAE,GAAGE,EAAmB,QAAQ,GAAGF,EAAS,OAAA,IAC5CE,EAAmB;AAAA,IACzB,YACEF,EAAS,cAAc,OAAOA,EAAS,cAAe,WAClD,EAAE,GAAGE,EAAmB,YAAY,GAAGF,EAAS,WAAA,IAChDE,EAAmB;AAAA,EAAA,IAE3BJ,EAAW,OAETK,IAAkC;AAAA,IACtC,GAAGlD;AAAA,IACH,eAAe;AAAA,IACf,OAAAgD;AAAA,EAAA,GAIIG,IAAWxD,IAAa,gBAAgBA,CAAU,KAAK,SAEvD+B,IAAQgB,KAAY1C,EAAS,OAC7BoD,IAAW1B,EAAM,KAAK,CAACrC,MAAMA,EAAE,OAAO,MAAM,KAAKqC,EAAM,CAAC,GACxD2B,IACJD,KAAYA,EAAS,OAAOR,EAAkB,KAC1C;AAAA,IACE,GAAGQ;AAAA,IACH,WAAW,MAAM,QAAQA,EAAS,SAAS,IACvCA,EAAS,YACT,CAAA;AAAA,EAAC,IAEP;AAEN,MAAI;AACF,UAAME,IAAyC,CAAA;AAC/C,IAAID,QAA8B,iBAAiBA,IAC/CrD,EAAS,aAAUsD,EAAc,eAAetD,EAAS;AAE7D,UAAMhB,IAAOuE;AAAA,MACXX;AAAA,MACAM;AAAA,MACAP;AAAA,MACAQ;AAAA,MACA,OAAO,KAAKG,CAAa,EAAE,SAAS,IAAIA,IAAuB;AAAA,IAAA;AAGjE,WAAI,CAACtE,KAAQ,CAACA,EAAK,SACV,OAGFA;AAAA,EACT,SAASyC,GAAK;AACZ,WAAAc,EAAO,MAAM,0BAA0Bd,CAAG,GACnC;AAAA,EACT;AACF;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brunoalz/smartgesti-site-editor",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Site editor component for SmartGesti platform",