@brunoalz/smartgesti-site-editor 1.4.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/editor/BlockSelector.js +4 -2
  2. package/dist/editor/BlockSelector.js.map +1 -1
  3. package/dist/engine/export/exporters/layout/GridExporter.d.ts.map +1 -1
  4. package/dist/engine/export/exporters/layout/GridExporter.js +29 -12
  5. package/dist/engine/export/exporters/layout/GridExporter.js.map +1 -1
  6. package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts +2 -0
  7. package/dist/engine/export/exporters/sections/BlogPostExporters.d.ts.map +1 -1
  8. package/dist/engine/export/exporters/sections/BlogPostExporters.js +183 -119
  9. package/dist/engine/export/exporters/sections/BlogPostExporters.js.map +1 -1
  10. package/dist/engine/export/exporters/sections/index.d.ts.map +1 -1
  11. package/dist/engine/export/exporters/sections/index.js +26 -24
  12. package/dist/engine/export/exporters/sections/index.js.map +1 -1
  13. package/dist/engine/index.js +97 -95
  14. package/dist/engine/index.js.map +1 -1
  15. package/dist/engine/plugins/builtin/blog/manifest.d.ts.map +1 -1
  16. package/dist/engine/plugins/builtin/blog/manifest.js +160 -72
  17. package/dist/engine/plugins/builtin/blog/manifest.js.map +1 -1
  18. package/dist/engine/plugins/contentHydration.js +144 -68
  19. package/dist/engine/plugins/contentHydration.js.map +1 -1
  20. package/dist/engine/registry/blocks/layout/grid.d.ts.map +1 -1
  21. package/dist/engine/registry/blocks/layout/grid.js +10 -4
  22. package/dist/engine/registry/blocks/layout/grid.js.map +1 -1
  23. package/dist/engine/registry/blocks/sections/blogRecentPosts.d.ts +3 -0
  24. package/dist/engine/registry/blocks/sections/blogRecentPosts.d.ts.map +1 -0
  25. package/dist/engine/registry/blocks/sections/blogRecentPosts.js +29 -0
  26. package/dist/engine/registry/blocks/sections/blogRecentPosts.js.map +1 -0
  27. package/dist/engine/registry/blocks/sections/blogTagCloud.d.ts +3 -0
  28. package/dist/engine/registry/blocks/sections/blogTagCloud.d.ts.map +1 -0
  29. package/dist/engine/registry/blocks/sections/blogTagCloud.js +31 -0
  30. package/dist/engine/registry/blocks/sections/blogTagCloud.js.map +1 -0
  31. package/dist/engine/registry/blocks/sections/index.d.ts +2 -0
  32. package/dist/engine/registry/blocks/sections/index.d.ts.map +1 -1
  33. package/dist/engine/render/renderers/layout/GridRenderer.d.ts.map +1 -1
  34. package/dist/engine/render/renderers/layout/GridRenderer.js +21 -18
  35. package/dist/engine/render/renderers/layout/GridRenderer.js.map +1 -1
  36. package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.d.ts.map +1 -1
  37. package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.js +66 -47
  38. package/dist/engine/render/renderers/sections/BlogPostDetailRenderer.js.map +1 -1
  39. package/dist/engine/render/renderers/sections/BlogPostGridRenderer.d.ts.map +1 -1
  40. package/dist/engine/render/renderers/sections/BlogPostGridRenderer.js +175 -32
  41. package/dist/engine/render/renderers/sections/BlogPostGridRenderer.js.map +1 -1
  42. package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.d.ts +3 -0
  43. package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.d.ts.map +1 -0
  44. package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.js +148 -0
  45. package/dist/engine/render/renderers/sections/BlogRecentPostsRenderer.js.map +1 -0
  46. package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.d.ts +3 -0
  47. package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.d.ts.map +1 -0
  48. package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.js +134 -0
  49. package/dist/engine/render/renderers/sections/BlogTagCloudRenderer.js.map +1 -0
  50. package/dist/engine/render/renderers/sections/index.js +20 -16
  51. package/dist/engine/render/renderers/sections/index.js.map +1 -1
  52. package/dist/engine/schema/siteDocument.d.ts +57 -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/index.d.ts +1 -1
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +108 -106
  58. package/dist/index.js.map +1 -1
  59. package/dist/viewer/LandingPageViewer.js +11 -11
  60. package/dist/viewer/LandingPageViewer.js.map +1 -1
  61. package/package.json +1 -1
@@ -1,47 +1,60 @@
1
- import { logger as u } from "../../utils/logger.js";
2
- async function v(t, n, e, r) {
1
+ import { logger as f } from "../../utils/logger.js";
2
+ async function R(t, n, r, e) {
3
3
  if (!t.dataSource)
4
4
  return t;
5
- const { provider: o, mode: i, paramMapping: s } = t.dataSource, a = n.get(o);
6
- if (!a)
7
- return u.warn(
8
- `ContentProvider "${o}" not found for page "${t.id}". Rendering with static props.`
5
+ const { provider: a, mode: s, paramMapping: c } = t.dataSource, d = n.get(a);
6
+ if (!d)
7
+ return f.warn(
8
+ `ContentProvider "${a}" not found for page "${t.id}". Rendering with static props.`
9
9
  ), t;
10
10
  try {
11
- if (i === "list")
12
- return await m(t, a, r);
13
- if (i === "single") {
14
- const c = l(s, e);
15
- return c ? await y(t, a, c) : (u.warn(
11
+ if (s === "list")
12
+ return await C(t, d, e);
13
+ if (s === "single") {
14
+ const p = $(c, r);
15
+ return p ? await I(t, d, p) : (f.warn(
16
16
  `Could not resolve ID/slug for page "${t.id}" from URL params. Using static props.`
17
17
  ), t);
18
18
  }
19
19
  return t;
20
- } catch (c) {
21
- return u.error(`Error hydrating page "${t.id}":`, c), t;
20
+ } catch (p) {
21
+ return f.error(`Error hydrating page "${t.id}":`, p), t;
22
22
  }
23
23
  }
24
- async function m(t, n, e) {
25
- const r = {
24
+ function v(t, n) {
25
+ const e = `/site/p/${t.slug && t.slug !== "home" ? t.slug : "blog"}`, a = new URLSearchParams(), s = n?.filter;
26
+ return s?.search && a.set("busca", s.search), s?.category && a.set("categoria", s.category), a.toString() ? `${e}?${a.toString()}` : e;
27
+ }
28
+ async function C(t, n, r) {
29
+ const e = {
26
30
  limit: 12,
27
31
  ...t.dataSource?.defaultParams,
28
- ...e
29
- }, i = ((await n.fetchList(r)).items || []).map((a) => n.toBlockProps(a)), s = t.structure.map((a) => {
30
- let c = d(a, i);
31
- return c = f(c, i), c;
32
+ ...r
33
+ }, a = await n.fetchList(e), s = (a.items || []).map((i) => n.toBlockProps(i)), c = !!t.dataSource?.defaultParams?._noPagination, d = Math.ceil((a.total || 0) / (a.limit || e.limit || 12)), p = !c && d > 1 ? {
34
+ currentPage: a.page || 1,
35
+ totalPages: d,
36
+ paginationBaseUrl: v(t, r)
37
+ } : void 0, m = t.structure.map((i) => {
38
+ let l = P(i, s, p);
39
+ return l = h(l, s), l;
32
40
  });
33
41
  return {
34
42
  ...t,
35
- structure: s
43
+ structure: m
36
44
  };
37
45
  }
38
- function d(t, n) {
46
+ function P(t, n, r) {
39
47
  if (t.type === "blogPostGrid")
40
48
  return {
41
49
  ...t,
42
50
  props: {
43
51
  ...t.props,
44
- cards: n
52
+ cards: n,
53
+ ...r ? {
54
+ currentPage: r.currentPage,
55
+ totalPages: r.totalPages,
56
+ paginationBaseUrl: r.paginationBaseUrl
57
+ } : {}
45
58
  }
46
59
  };
47
60
  const e = t.props;
@@ -50,25 +63,48 @@ function d(t, n) {
50
63
  props: {
51
64
  ...e,
52
65
  children: e.children.map(
53
- (r) => d(r, n)
66
+ (a) => P(a, n, r)
54
67
  )
55
68
  }
56
69
  } : t;
57
70
  }
58
- async function y(t, n, e) {
59
- const r = await n.fetchById(e);
60
- if (!r)
61
- return u.warn(`Content item "${e}" not found. Using static props.`), t;
62
- const o = n.toBlockProps(r), i = t.structure.map(
63
- (a) => p(a, o, r)
64
- ), s = h(r, o);
71
+ async function I(t, n, r) {
72
+ const e = await n.fetchById(r);
73
+ if (!e)
74
+ return f.warn(`Content item "${r}" not found. Using static props.`), t;
75
+ const a = n.toBlockProps(e);
76
+ let s = [], c = [], d = [];
77
+ try {
78
+ const l = (await n.fetchList({ limit: 10, sort: "published_at" })).items || [];
79
+ d = l.map((o) => n.toBlockProps(o)), s = l.filter((o) => o.slug !== r && o.slug).slice(0, 5).map((o) => {
80
+ const u = o.data;
81
+ return {
82
+ title: u.title ?? "",
83
+ slug: o.slug,
84
+ date: o.metadata?.publishedAt ? new Date(o.metadata.publishedAt).toLocaleDateString("pt-BR", { day: "2-digit", month: "short", year: "numeric" }) : void 0,
85
+ image: u.featuredImage ?? void 0,
86
+ category: u.category ?? void 0
87
+ };
88
+ });
89
+ const g = /* @__PURE__ */ new Map();
90
+ for (const o of l) {
91
+ const u = o.data.tags;
92
+ if (u)
93
+ for (const y of u)
94
+ g.set(y, (g.get(y) ?? 0) + 1);
95
+ }
96
+ c = Array.from(g.entries()).map(([o, u]) => ({ name: o, count: u })).sort((o, u) => u.count - o.count);
97
+ } catch (i) {
98
+ f.warn(`Failed to fetch sidebar data for page "${t.id}":`, i);
99
+ }
100
+ const p = t.structure.map((i) => w(i, a, e)).map((i) => A(i, s)).map((i) => B(i, c)).map((i) => h(i, d)), m = S(e, a);
65
101
  return {
66
102
  ...t,
67
- structure: i,
68
- ...s ? { seo: s } : {}
103
+ structure: p,
104
+ ...m ? { seo: m } : {}
69
105
  };
70
106
  }
71
- function p(t, n, e) {
107
+ function w(t, n, r) {
72
108
  if (t.type === "blogPostDetail")
73
109
  return {
74
110
  ...t,
@@ -76,8 +112,8 @@ function p(t, n, e) {
76
112
  ...t.props,
77
113
  ...n,
78
114
  // Preserve metadata
79
- _contentItemId: e.id,
80
- _contentItemSlug: e.slug
115
+ _contentItemId: r.id,
116
+ _contentItemSlug: r.slug
81
117
  }
82
118
  };
83
119
  if (t.type === "blogPostCard")
@@ -88,74 +124,114 @@ function p(t, n, e) {
88
124
  ...n
89
125
  }
90
126
  };
127
+ const e = t.props;
128
+ return e.children && Array.isArray(e.children) ? {
129
+ ...t,
130
+ props: {
131
+ ...e,
132
+ children: e.children.map(
133
+ (a) => w(a, n, r)
134
+ )
135
+ }
136
+ } : t;
137
+ }
138
+ function S(t, n) {
139
+ const r = t.metadata?.seo, e = r?.metaTitle || n.metaTitle || n.title, a = r?.metaDescription || n.metaDescription || n.excerpt, s = r?.ogImage || n.ogImage || n.featuredImage;
140
+ if (!(!e && !a && !s))
141
+ return {
142
+ metaTitle: e,
143
+ metaDescription: a,
144
+ ogImage: s,
145
+ ogType: "article"
146
+ };
147
+ }
148
+ function A(t, n) {
149
+ if (t.type === "blogRecentPosts")
150
+ return {
151
+ ...t,
152
+ props: {
153
+ ...t.props,
154
+ posts: n
155
+ }
156
+ };
91
157
  const r = t.props;
92
158
  return r.children && Array.isArray(r.children) ? {
93
159
  ...t,
94
160
  props: {
95
161
  ...r,
96
162
  children: r.children.map(
97
- (o) => p(o, n, e)
163
+ (e) => A(e, n)
98
164
  )
99
165
  }
100
166
  } : t;
101
167
  }
102
- function h(t, n) {
103
- const e = t.metadata?.seo, r = e?.metaTitle || n.metaTitle || n.title, o = e?.metaDescription || n.metaDescription || n.excerpt, i = e?.ogImage || n.ogImage || n.featuredImage;
104
- if (!(!r && !o && !i))
168
+ function B(t, n) {
169
+ if (t.type === "blogTagCloud")
105
170
  return {
106
- metaTitle: r,
107
- metaDescription: o,
108
- ogImage: i,
109
- ogType: "article"
171
+ ...t,
172
+ props: {
173
+ ...t.props,
174
+ tags: n
175
+ }
110
176
  };
177
+ const r = t.props;
178
+ return r.children && Array.isArray(r.children) ? {
179
+ ...t,
180
+ props: {
181
+ ...r,
182
+ children: r.children.map(
183
+ (e) => B(e, n)
184
+ )
185
+ }
186
+ } : t;
111
187
  }
112
- function f(t, n) {
188
+ function h(t, n) {
113
189
  if (t.type === "blogCategoryFilter") {
114
- const r = /* @__PURE__ */ new Map();
115
- for (const i of n) {
116
- const s = i.category;
117
- s && r.set(s, (r.get(s) || 0) + 1);
190
+ const e = /* @__PURE__ */ new Map();
191
+ for (const s of n) {
192
+ const c = s.category;
193
+ c && e.set(c, (e.get(c) || 0) + 1);
118
194
  }
119
- const o = Array.from(r.entries()).map(([i, s]) => ({
120
- name: i,
121
- slug: i,
122
- count: s
195
+ const a = Array.from(e.entries()).map(([s, c]) => ({
196
+ name: s,
197
+ slug: s,
198
+ count: c
123
199
  }));
124
200
  return {
125
201
  ...t,
126
202
  props: {
127
203
  ...t.props,
128
- categories: o
204
+ categories: a
129
205
  }
130
206
  };
131
207
  }
132
- const e = t.props;
133
- return e.children && Array.isArray(e.children) ? {
208
+ const r = t.props;
209
+ return r.children && Array.isArray(r.children) ? {
134
210
  ...t,
135
211
  props: {
136
- ...e,
137
- children: e.children.map(
138
- (r) => f(r, n)
212
+ ...r,
213
+ children: r.children.map(
214
+ (e) => h(e, n)
139
215
  )
140
216
  }
141
217
  } : t;
142
218
  }
143
- function l(t, n) {
219
+ function $(t, n) {
144
220
  if (!(!t || !n)) {
145
- for (const e of ["slug", "id"]) {
146
- const r = t[e];
147
- if (r) {
148
- const o = r.startsWith(":") ? r.slice(1) : r, i = n[o];
149
- if (i) return i;
221
+ for (const r of ["slug", "id"]) {
222
+ const e = t[r];
223
+ if (e) {
224
+ const a = e.startsWith(":") ? e.slice(1) : e, s = n[a];
225
+ if (s) return s;
150
226
  }
151
227
  }
152
- for (const e of Object.values(t)) {
153
- const r = e.startsWith(":") ? e.slice(1) : e, o = n[r];
154
- if (o) return o;
228
+ for (const r of Object.values(t)) {
229
+ const e = r.startsWith(":") ? r.slice(1) : r, a = n[e];
230
+ if (a) return a;
155
231
  }
156
232
  }
157
233
  }
158
234
  export {
159
- v as hydratePageWithContent
235
+ R as hydratePageWithContent
160
236
  };
161
237
  //# sourceMappingURL=contentHydration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"contentHydration.js","sources":["../../../src/engine/plugins/contentHydration.ts"],"sourcesContent":["/**\n * Content Hydration\n * Hydrates page blocks with data from ContentProviders before rendering.\n *\n * This works at the data level, before either rendering pipeline\n * (React renderers or HTML exporters) processes the blocks.\n */\n\nimport { logger } from \"../../utils/logger\";\nimport type { SitePage, Block, PageSeoConfig } from \"../schema/siteDocument\";\nimport type { ContentProvider, ContentItem, ContentListParams } from \"./types\";\n\n/**\n * Map of provider type → ContentProvider instance\n */\nexport type ContentProviderMap = Map<string, ContentProvider>;\n\n/**\n * Hydrates a page's blocks with data from ContentProviders.\n *\n * For pages with a dataSource:\n * - mode \"list\": fetches list and populates grid blocks' `cards` prop\n * - mode \"single\": fetches single item and spreads props onto detail blocks\n *\n * Returns a new page with hydrated block props (original page is not mutated).\n */\nexport async function hydratePageWithContent(\n page: SitePage,\n providers: ContentProviderMap,\n urlParams?: Record<string, string>,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n // No dataSource → return page as-is\n if (!page.dataSource) {\n return page;\n }\n\n const { provider: providerType, mode, paramMapping } = page.dataSource;\n const provider = providers.get(providerType);\n\n if (!provider) {\n logger.warn(\n `ContentProvider \"${providerType}\" not found for page \"${page.id}\". Rendering with static props.`,\n );\n return page;\n }\n\n try {\n if (mode === \"list\") {\n return await hydrateListPage(page, provider, fetchParams);\n }\n\n if (mode === \"single\") {\n // Resolve the ID/slug from URL params\n const idOrSlug = resolveIdFromParams(paramMapping, urlParams);\n if (!idOrSlug) {\n logger.warn(\n `Could not resolve ID/slug for page \"${page.id}\" from URL params. Using static props.`,\n );\n return page;\n }\n return await hydrateSinglePage(page, provider, idOrSlug);\n }\n\n return page;\n } catch (error) {\n logger.error(`Error hydrating page \"${page.id}\":`, error);\n return page;\n }\n}\n\n/**\n * Hydrates a list-mode page: fetches items and populates grid blocks.\n */\nasync function hydrateListPage(\n page: SitePage,\n provider: ContentProvider,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n const params: ContentListParams = {\n limit: 12,\n ...page.dataSource?.defaultParams,\n ...fetchParams,\n };\n\n const result = await provider.fetchList(params);\n\n // Convert items to block props (empty array if no results — shows empty state, never mock data)\n const cardProps = (result.items || []).map((item) => provider.toBlockProps(item));\n\n // Hydrate all grid blocks and category filters on the page\n const hydratedStructure = page.structure.map((block) => {\n let hydrated = hydrateGridBlock(block, cardProps);\n hydrated = hydrateCategoryFilterBlock(hydrated, cardProps);\n return hydrated;\n });\n\n return {\n ...page,\n structure: hydratedStructure,\n };\n}\n\n/**\n * Hydrates grid blocks (blogPostGrid, etc.) with card data.\n */\nfunction hydrateGridBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n // Direct match: blogPostGrid gets cards populated\n if (block.type === \"blogPostGrid\") {\n return {\n ...block,\n props: {\n ...block.props,\n cards: cardProps,\n },\n };\n }\n\n // Recurse into children for nested structures\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateGridBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Hydrates a single-mode page: fetches one item and populates detail blocks.\n */\nasync function hydrateSinglePage(\n page: SitePage,\n provider: ContentProvider,\n idOrSlug: string,\n): Promise<SitePage> {\n const item = await provider.fetchById(idOrSlug);\n\n if (!item) {\n logger.warn(`Content item \"${idOrSlug}\" not found. Using static props.`);\n return page;\n }\n\n const blockProps = provider.toBlockProps(item);\n\n // Hydrate all detail blocks on the page\n const hydratedStructure = page.structure.map((block) =>\n hydrateDetailBlock(block, blockProps, item),\n );\n\n // Extract SEO from content item and set on page\n const seo = extractSeoFromContent(item, blockProps);\n\n return {\n ...page,\n structure: hydratedStructure,\n ...(seo ? { seo } : {}),\n };\n}\n\n/**\n * Hydrates detail blocks (blogPostDetail, etc.) with item data.\n */\nfunction hydrateDetailBlock(\n block: Block,\n blockProps: Record<string, unknown>,\n item: ContentItem,\n): Block {\n if (block.type === \"blogPostDetail\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n // Preserve metadata\n _contentItemId: item.id,\n _contentItemSlug: item.slug,\n },\n };\n }\n\n // Also hydrate blogPostCard blocks that reference the same item\n if (block.type === \"blogPostCard\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateDetailBlock(child, blockProps, item),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Extracts SEO configuration from a ContentItem and block props.\n * Priority: item.metadata.seo > blockProps (metaTitle/title, metaDescription/excerpt, ogImage/featuredImage)\n */\nfunction extractSeoFromContent(\n item: ContentItem,\n blockProps: Record<string, unknown>,\n): PageSeoConfig | undefined {\n const seoMeta = item.metadata?.seo;\n\n const metaTitle = seoMeta?.metaTitle || (blockProps.metaTitle as string) || (blockProps.title as string);\n const metaDescription = seoMeta?.metaDescription || (blockProps.metaDescription as string) || (blockProps.excerpt as string);\n const ogImage = seoMeta?.ogImage || (blockProps.ogImage as string) || (blockProps.featuredImage as string);\n\n if (!metaTitle && !metaDescription && !ogImage) {\n return undefined;\n }\n\n return {\n metaTitle,\n metaDescription,\n ogImage,\n ogType: \"article\",\n };\n}\n\n/**\n * Hydrates blogCategoryFilter blocks with category data extracted from posts.\n */\nfunction hydrateCategoryFilterBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n if (block.type === \"blogCategoryFilter\") {\n // Extract unique categories from posts with counts\n const categoryMap = new Map<string, number>();\n for (const card of cardProps) {\n const cat = card.category as string;\n if (cat) {\n categoryMap.set(cat, (categoryMap.get(cat) || 0) + 1);\n }\n }\n\n const categories = Array.from(categoryMap.entries()).map(([name, count]) => ({\n name,\n slug: name,\n count,\n }));\n\n return {\n ...block,\n props: {\n ...block.props,\n categories,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateCategoryFilterBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Resolves the item ID/slug from URL params using paramMapping.\n * e.g., paramMapping: { slug: \":slug\" }, urlParams: { slug: \"my-post\" } → \"my-post\"\n */\nfunction resolveIdFromParams(\n paramMapping?: Record<string, string>,\n urlParams?: Record<string, string>,\n): string | undefined {\n if (!paramMapping || !urlParams) return undefined;\n\n // Try slug first, then id\n for (const key of [\"slug\", \"id\"]) {\n const paramPattern = paramMapping[key];\n if (paramPattern) {\n // Extract param name from pattern (e.g., \":slug\" → \"slug\")\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n }\n\n // Fallback: return first available param value\n for (const paramPattern of Object.values(paramMapping)) {\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n\n return undefined;\n}\n"],"names":["hydratePageWithContent","page","providers","urlParams","fetchParams","providerType","mode","paramMapping","provider","logger","hydrateListPage","idOrSlug","resolveIdFromParams","hydrateSinglePage","error","params","cardProps","item","hydratedStructure","block","hydrated","hydrateGridBlock","hydrateCategoryFilterBlock","props","child","blockProps","hydrateDetailBlock","seo","extractSeoFromContent","seoMeta","metaTitle","metaDescription","ogImage","categoryMap","card","cat","categories","name","count","key","paramPattern","paramName","value"],"mappings":"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"}
1
+ {"version":3,"file":"contentHydration.js","sources":["../../../src/engine/plugins/contentHydration.ts"],"sourcesContent":["/**\n * Content Hydration\n * Hydrates page blocks with data from ContentProviders before rendering.\n *\n * This works at the data level, before either rendering pipeline\n * (React renderers or HTML exporters) processes the blocks.\n */\n\nimport { logger } from \"../../utils/logger\";\nimport type { SitePage, Block, PageSeoConfig } from \"../schema/siteDocument\";\nimport type { ContentProvider, ContentItem, ContentListParams } from \"./types\";\n\n/**\n * Map of provider type → ContentProvider instance\n */\nexport type ContentProviderMap = Map<string, ContentProvider>;\n\n/**\n * Hydrates a page's blocks with data from ContentProviders.\n *\n * For pages with a dataSource:\n * - mode \"list\": fetches list and populates grid blocks' `cards` prop\n * - mode \"single\": fetches single item and spreads props onto detail blocks\n *\n * Returns a new page with hydrated block props (original page is not mutated).\n */\nexport async function hydratePageWithContent(\n page: SitePage,\n providers: ContentProviderMap,\n urlParams?: Record<string, string>,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n // No dataSource → return page as-is\n if (!page.dataSource) {\n return page;\n }\n\n const { provider: providerType, mode, paramMapping } = page.dataSource;\n const provider = providers.get(providerType);\n\n if (!provider) {\n logger.warn(\n `ContentProvider \"${providerType}\" not found for page \"${page.id}\". Rendering with static props.`,\n );\n return page;\n }\n\n try {\n if (mode === \"list\") {\n return await hydrateListPage(page, provider, fetchParams);\n }\n\n if (mode === \"single\") {\n // Resolve the ID/slug from URL params\n const idOrSlug = resolveIdFromParams(paramMapping, urlParams);\n if (!idOrSlug) {\n logger.warn(\n `Could not resolve ID/slug for page \"${page.id}\" from URL params. Using static props.`,\n );\n return page;\n }\n return await hydrateSinglePage(page, provider, idOrSlug);\n }\n\n return page;\n } catch (error) {\n logger.error(`Error hydrating page \"${page.id}\":`, error);\n return page;\n }\n}\n\n/**\n * Pagination metadata passed from hydration to grid blocks.\n */\ninterface PaginationMeta {\n currentPage: number;\n totalPages: number;\n paginationBaseUrl: string;\n}\n\n/**\n * Builds a pagination base URL from the page slug and current filter params.\n * Preserves search/category so pagination links keep the active filters.\n * Uses /site/p/ prefix to match the consumer route pattern (same as viewAllHref, linkHref).\n */\nfunction buildPaginationBaseUrl(\n page: SitePage,\n fetchParams?: ContentListParams,\n): string {\n // Always paginate on the blog listing page — home page widget points to blog page\n const slug = page.slug && page.slug !== \"home\" ? page.slug : \"blog\";\n const basePath = `/site/p/${slug}`;\n\n const params = new URLSearchParams();\n const filter = fetchParams?.filter as Record<string, string> | undefined;\n if (filter?.search) params.set(\"busca\", filter.search);\n if (filter?.category) params.set(\"categoria\", filter.category);\n\n return params.toString() ? `${basePath}?${params.toString()}` : basePath;\n}\n\n/**\n * Hydrates a list-mode page: fetches items and populates grid blocks.\n */\nasync function hydrateListPage(\n page: SitePage,\n provider: ContentProvider,\n fetchParams?: ContentListParams,\n): Promise<SitePage> {\n const params: ContentListParams = {\n limit: 12,\n ...page.dataSource?.defaultParams,\n ...fetchParams,\n };\n\n const result = await provider.fetchList(params);\n\n // Convert items to block props (empty array if no results — shows empty state, never mock data)\n const cardProps = (result.items || []).map((item) => provider.toBlockProps(item));\n\n // Build pagination metadata (only when there are multiple pages)\n // _noPagination flag suppresses pagination for synthetic dataSource (e.g., home page blog widget)\n const noPagination = !!(page.dataSource?.defaultParams as Record<string, unknown> | undefined)?._noPagination;\n const totalPages = Math.ceil((result.total || 0) / (result.limit || params.limit || 12));\n const pagination: PaginationMeta | undefined = !noPagination && totalPages > 1\n ? {\n currentPage: result.page || 1,\n totalPages,\n paginationBaseUrl: buildPaginationBaseUrl(page, fetchParams),\n }\n : undefined;\n\n // Hydrate all grid blocks and category filters on the page\n const hydratedStructure = page.structure.map((block) => {\n let hydrated = hydrateGridBlock(block, cardProps, pagination);\n hydrated = hydrateCategoryFilterBlock(hydrated, cardProps);\n return hydrated;\n });\n\n return {\n ...page,\n structure: hydratedStructure,\n };\n}\n\n/**\n * Hydrates grid blocks (blogPostGrid, etc.) with card data and pagination.\n */\nfunction hydrateGridBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n pagination?: PaginationMeta,\n): Block {\n // Direct match: blogPostGrid gets cards + pagination populated\n if (block.type === \"blogPostGrid\") {\n return {\n ...block,\n props: {\n ...block.props,\n cards: cardProps,\n ...(pagination ? {\n currentPage: pagination.currentPage,\n totalPages: pagination.totalPages,\n paginationBaseUrl: pagination.paginationBaseUrl,\n } : {}),\n },\n };\n }\n\n // Recurse into children for nested structures\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateGridBlock(child, cardProps, pagination),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Hydrates a single-mode page: fetches one item and populates detail blocks.\n * Also fetches sidebar data (recent posts, tags, categories) for widgets.\n */\nasync function hydrateSinglePage(\n page: SitePage,\n provider: ContentProvider,\n idOrSlug: string,\n): Promise<SitePage> {\n const item = await provider.fetchById(idOrSlug);\n\n if (!item) {\n logger.warn(`Content item \"${idOrSlug}\" not found. Using static props.`);\n return page;\n }\n\n const blockProps = provider.toBlockProps(item);\n\n // Fetch recent posts for sidebar widgets\n let recentPosts: Array<{ title: string; slug: string; date?: string; image?: string; category?: string }> = [];\n let tagCloud: Array<{ name: string; count: number }> = [];\n let sidebarCardProps: Record<string, unknown>[] = [];\n\n try {\n const recentResult = await provider.fetchList({ limit: 10, sort: 'published_at' });\n const allItems = recentResult.items || [];\n\n // Map to card props for category filter hydration\n sidebarCardProps = allItems.map((i) => provider.toBlockProps(i));\n\n // Map recent posts (exclude current post)\n recentPosts = allItems\n .filter((i) => i.slug !== idOrSlug && i.slug)\n .slice(0, 5)\n .map((i) => {\n const d = i.data as Record<string, any>;\n return {\n title: (d.title as string) ?? '',\n slug: i.slug as string,\n date: i.metadata?.publishedAt\n ? new Date(i.metadata.publishedAt).toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' })\n : undefined,\n image: (d.featuredImage as string) ?? undefined,\n category: (d.category as string) ?? undefined,\n };\n });\n\n // Extract tags from all posts\n const allTags = new Map<string, number>();\n for (const i of allItems) {\n const tags = (i.data as Record<string, any>).tags as string[] | undefined;\n if (tags) {\n for (const tag of tags) {\n allTags.set(tag, (allTags.get(tag) ?? 0) + 1);\n }\n }\n }\n tagCloud = Array.from(allTags.entries())\n .map(([name, count]) => ({ name, count }))\n .sort((a, b) => b.count - a.count);\n } catch (err) {\n logger.warn(`Failed to fetch sidebar data for page \"${page.id}\":`, err);\n }\n\n // Hydrate all blocks on the page\n const hydratedStructure = page.structure\n .map((block) => hydrateDetailBlock(block, blockProps, item))\n .map((block) => hydrateRecentPostsBlock(block, recentPosts))\n .map((block) => hydrateTagCloudBlock(block, tagCloud))\n .map((block) => hydrateCategoryFilterBlock(block, sidebarCardProps));\n\n // Extract SEO from content item and set on page\n const seo = extractSeoFromContent(item, blockProps);\n\n return {\n ...page,\n structure: hydratedStructure,\n ...(seo ? { seo } : {}),\n };\n}\n\n/**\n * Hydrates detail blocks (blogPostDetail, etc.) with item data.\n */\nfunction hydrateDetailBlock(\n block: Block,\n blockProps: Record<string, unknown>,\n item: ContentItem,\n): Block {\n if (block.type === \"blogPostDetail\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n // Preserve metadata\n _contentItemId: item.id,\n _contentItemSlug: item.slug,\n },\n };\n }\n\n // Also hydrate blogPostCard blocks that reference the same item\n if (block.type === \"blogPostCard\") {\n return {\n ...block,\n props: {\n ...block.props,\n ...blockProps,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateDetailBlock(child, blockProps, item),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Extracts SEO configuration from a ContentItem and block props.\n * Priority: item.metadata.seo > blockProps (metaTitle/title, metaDescription/excerpt, ogImage/featuredImage)\n */\nfunction extractSeoFromContent(\n item: ContentItem,\n blockProps: Record<string, unknown>,\n): PageSeoConfig | undefined {\n const seoMeta = item.metadata?.seo;\n\n const metaTitle = seoMeta?.metaTitle || (blockProps.metaTitle as string) || (blockProps.title as string);\n const metaDescription = seoMeta?.metaDescription || (blockProps.metaDescription as string) || (blockProps.excerpt as string);\n const ogImage = seoMeta?.ogImage || (blockProps.ogImage as string) || (blockProps.featuredImage as string);\n\n if (!metaTitle && !metaDescription && !ogImage) {\n return undefined;\n }\n\n return {\n metaTitle,\n metaDescription,\n ogImage,\n ogType: \"article\",\n };\n}\n\n/**\n * Hydrates blogRecentPosts blocks with recent post data.\n */\nfunction hydrateRecentPostsBlock(\n block: Block,\n recentPosts: Array<{ title: string; slug: string; date?: string; image?: string; category?: string }>,\n): Block {\n if (block.type === \"blogRecentPosts\") {\n return {\n ...block,\n props: {\n ...block.props,\n posts: recentPosts,\n },\n } as Block;\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateRecentPostsBlock(child, recentPosts),\n ),\n },\n } as Block;\n }\n\n return block;\n}\n\n/**\n * Hydrates blogTagCloud blocks with tag data.\n */\nfunction hydrateTagCloudBlock(\n block: Block,\n tags: Array<{ name: string; count: number }>,\n): Block {\n if (block.type === \"blogTagCloud\") {\n return {\n ...block,\n props: {\n ...block.props,\n tags,\n },\n } as Block;\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateTagCloudBlock(child, tags),\n ),\n },\n } as Block;\n }\n\n return block;\n}\n\n/**\n * Hydrates blogCategoryFilter blocks with category data extracted from posts.\n */\nfunction hydrateCategoryFilterBlock(\n block: Block,\n cardProps: Record<string, unknown>[],\n): Block {\n if (block.type === \"blogCategoryFilter\") {\n // Extract unique categories from posts with counts\n const categoryMap = new Map<string, number>();\n for (const card of cardProps) {\n const cat = card.category as string;\n if (cat) {\n categoryMap.set(cat, (categoryMap.get(cat) || 0) + 1);\n }\n }\n\n const categories = Array.from(categoryMap.entries()).map(([name, count]) => ({\n name,\n slug: name,\n count,\n }));\n\n return {\n ...block,\n props: {\n ...block.props,\n categories,\n },\n };\n }\n\n // Recurse into children\n const props = block.props as Record<string, unknown>;\n if (props.children && Array.isArray(props.children)) {\n return {\n ...block,\n props: {\n ...props,\n children: (props.children as Block[]).map((child) =>\n hydrateCategoryFilterBlock(child, cardProps),\n ),\n },\n };\n }\n\n return block;\n}\n\n/**\n * Resolves the item ID/slug from URL params using paramMapping.\n * e.g., paramMapping: { slug: \":slug\" }, urlParams: { slug: \"my-post\" } → \"my-post\"\n */\nfunction resolveIdFromParams(\n paramMapping?: Record<string, string>,\n urlParams?: Record<string, string>,\n): string | undefined {\n if (!paramMapping || !urlParams) return undefined;\n\n // Try slug first, then id\n for (const key of [\"slug\", \"id\"]) {\n const paramPattern = paramMapping[key];\n if (paramPattern) {\n // Extract param name from pattern (e.g., \":slug\" → \"slug\")\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n }\n\n // Fallback: return first available param value\n for (const paramPattern of Object.values(paramMapping)) {\n const paramName = paramPattern.startsWith(\":\")\n ? paramPattern.slice(1)\n : paramPattern;\n const value = urlParams[paramName];\n if (value) return value;\n }\n\n return undefined;\n}\n"],"names":["hydratePageWithContent","page","providers","urlParams","fetchParams","providerType","mode","paramMapping","provider","logger","hydrateListPage","idOrSlug","resolveIdFromParams","hydrateSinglePage","error","buildPaginationBaseUrl","basePath","params","filter","result","cardProps","item","noPagination","totalPages","pagination","hydratedStructure","block","hydrated","hydrateGridBlock","hydrateCategoryFilterBlock","props","child","blockProps","recentPosts","tagCloud","sidebarCardProps","allItems","i","d","allTags","tags","tag","name","count","a","b","err","hydrateDetailBlock","hydrateRecentPostsBlock","hydrateTagCloudBlock","seo","extractSeoFromContent","seoMeta","metaTitle","metaDescription","ogImage","categoryMap","card","cat","categories","key","paramPattern","paramName","value"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,SAAS,EAAE,eAyBvB,CAAC"}
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,SAAS,EAAE,eA+BvB,CAAC"}
@@ -1,5 +1,5 @@
1
- import { componentRegistry as o } from "../../registry.js";
2
- const e = {
1
+ import { componentRegistry as e } from "../../registry.js";
2
+ const o = {
3
3
  type: "grid",
4
4
  name: "Grid",
5
5
  description: "Layout em grid responsivo",
@@ -18,6 +18,12 @@ const e = {
18
18
  max: 12,
19
19
  group: "Layout"
20
20
  },
21
+ colTemplate: {
22
+ label: "Template de Colunas",
23
+ description: "CSS grid-template-columns (ex: '1fr 320px'). Se definido, sobrescreve 'Colunas'.",
24
+ inputType: "text",
25
+ group: "Layout"
26
+ },
21
27
  gap: {
22
28
  label: "Gap",
23
29
  inputType: "text",
@@ -25,8 +31,8 @@ const e = {
25
31
  }
26
32
  }
27
33
  };
28
- o.register(e);
34
+ e.register(o);
29
35
  export {
30
- e as gridBlock
36
+ o as gridBlock
31
37
  };
32
38
  //# sourceMappingURL=grid.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grid.js","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const gridBlock: BlockDefinition = {\n type: \"grid\",\n name: \"Grid\",\n description: \"Layout em grid responsivo\",\n category: \"layout\",\n canHaveChildren: true,\n defaultProps: {\n cols: 3,\n gap: \"1rem\",\n },\n inspectorMeta: {\n cols: {\n label: \"Colunas\",\n description: \"Número de colunas (ou objeto responsivo)\",\n inputType: \"number\",\n min: 1,\n max: 12,\n group: \"Layout\",\n },\n gap: {\n label: \"Gap\",\n inputType: \"text\",\n group: \"Layout\",\n },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(gridBlock);\n"],"names":["gridBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,KAAK;AAAA,EAAA;AAAA,EAEP,eAAe;AAAA,IACb,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,IAAA;AAAA,IAET,KAAK;AAAA,MACH,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAGAC,EAAkB,SAASD,CAAS;"}
1
+ {"version":3,"file":"grid.js","sources":["../../../../../src/engine/registry/blocks/layout/grid.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const gridBlock: BlockDefinition = {\n type: \"grid\",\n name: \"Grid\",\n description: \"Layout em grid responsivo\",\n category: \"layout\",\n canHaveChildren: true,\n defaultProps: {\n cols: 3,\n gap: \"1rem\",\n },\n inspectorMeta: {\n cols: {\n label: \"Colunas\",\n description: \"Número de colunas (ou objeto responsivo)\",\n inputType: \"number\",\n min: 1,\n max: 12,\n group: \"Layout\",\n },\n colTemplate: {\n label: \"Template de Colunas\",\n description: \"CSS grid-template-columns (ex: '1fr 320px'). Se definido, sobrescreve 'Colunas'.\",\n inputType: \"text\",\n group: \"Layout\",\n },\n gap: {\n label: \"Gap\",\n inputType: \"text\",\n group: \"Layout\",\n },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(gridBlock);\n"],"names":["gridBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,KAAK;AAAA,EAAA;AAAA,EAEP,eAAe;AAAA,IACb,MAAM;AAAA,MACJ,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO;AAAA,IAAA;AAAA,IAET,aAAa;AAAA,MACX,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,IAET,KAAK;AAAA,MACH,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IAAA;AAAA,EACT;AAEJ;AAGAC,EAAkB,SAASD,CAAS;"}
@@ -0,0 +1,3 @@
1
+ import { BlockDefinition } from '../../types';
2
+ export declare const blogRecentPostsBlock: BlockDefinition;
3
+ //# sourceMappingURL=blogRecentPosts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blogRecentPosts.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/blogRecentPosts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,oBAAoB,EAAE,eAsBlC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { componentRegistry as e } from "../../registry.js";
2
+ const t = {
3
+ type: "blogRecentPosts",
4
+ name: "Posts Recentes",
5
+ description: "Widget com os posts mais recentes do blog",
6
+ category: "sections",
7
+ pluginId: "blog",
8
+ defaultProps: {
9
+ title: "Posts Recentes",
10
+ count: 5,
11
+ showThumbnail: !0,
12
+ showDate: !0,
13
+ showCategory: !1,
14
+ posts: []
15
+ },
16
+ inspectorMeta: {
17
+ title: { label: "Título", inputType: "text", group: "Conteúdo" },
18
+ count: { label: "Quantidade", inputType: "number", min: 1, max: 10, group: "Conteúdo" },
19
+ showThumbnail: { label: "Mostrar Miniatura", inputType: "checkbox", group: "Exibição" },
20
+ showDate: { label: "Mostrar Data", inputType: "checkbox", group: "Exibição" },
21
+ showCategory: { label: "Mostrar Categoria", inputType: "checkbox", group: "Exibição" },
22
+ posts: { label: "Posts", inputType: "text", readOnly: !0, group: "Dados" }
23
+ }
24
+ };
25
+ e.register(t);
26
+ export {
27
+ t as blogRecentPostsBlock
28
+ };
29
+ //# sourceMappingURL=blogRecentPosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blogRecentPosts.js","sources":["../../../../../src/engine/registry/blocks/sections/blogRecentPosts.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const blogRecentPostsBlock: BlockDefinition = {\n type: \"blogRecentPosts\",\n name: \"Posts Recentes\",\n description: \"Widget com os posts mais recentes do blog\",\n category: \"sections\",\n pluginId: \"blog\",\n defaultProps: {\n title: \"Posts Recentes\",\n count: 5,\n showThumbnail: true,\n showDate: true,\n showCategory: false,\n posts: [],\n },\n inspectorMeta: {\n title: { label: \"Título\", inputType: \"text\", group: \"Conteúdo\" },\n count: { label: \"Quantidade\", inputType: \"number\", min: 1, max: 10, group: \"Conteúdo\" },\n showThumbnail: { label: \"Mostrar Miniatura\", inputType: \"checkbox\", group: \"Exibição\" },\n showDate: { label: \"Mostrar Data\", inputType: \"checkbox\", group: \"Exibição\" },\n showCategory: { label: \"Mostrar Categoria\", inputType: \"checkbox\", group: \"Exibição\" },\n posts: { label: \"Posts\", inputType: \"text\", readOnly: true, group: \"Dados\" },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(blogRecentPostsBlock);\n"],"names":["blogRecentPostsBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAAwC;AAAA,EACnD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,eAAe;AAAA,IACf,UAAU;AAAA,IACV,cAAc;AAAA,IACd,OAAO,CAAA;AAAA,EAAC;AAAA,EAEV,eAAe;AAAA,IACb,OAAO,EAAE,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAA;AAAA,IACpD,OAAO,EAAE,OAAO,cAAc,WAAW,UAAU,KAAK,GAAG,KAAK,IAAI,OAAO,WAAA;AAAA,IAC3E,eAAe,EAAE,OAAO,qBAAqB,WAAW,YAAY,OAAO,WAAA;AAAA,IAC3E,UAAU,EAAE,OAAO,gBAAgB,WAAW,YAAY,OAAO,WAAA;AAAA,IACjE,cAAc,EAAE,OAAO,qBAAqB,WAAW,YAAY,OAAO,WAAA;AAAA,IAC1E,OAAO,EAAE,OAAO,SAAS,WAAW,QAAQ,UAAU,IAAM,OAAO,QAAA;AAAA,EAAQ;AAE/E;AAGAC,EAAkB,SAASD,CAAoB;"}
@@ -0,0 +1,3 @@
1
+ import { BlockDefinition } from '../../types';
2
+ export declare const blogTagCloudBlock: BlockDefinition;
3
+ //# sourceMappingURL=blogTagCloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blogTagCloud.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/blogTagCloud.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,eAAO,MAAM,iBAAiB,EAAE,eAwB/B,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { componentRegistry as t } from "../../registry.js";
2
+ const e = {
3
+ type: "blogTagCloud",
4
+ name: "Nuvem de Tags",
5
+ description: "Widget com tags dos posts do blog",
6
+ category: "sections",
7
+ pluginId: "blog",
8
+ defaultProps: {
9
+ title: "Tags",
10
+ tags: [],
11
+ variant: "badges"
12
+ },
13
+ inspectorMeta: {
14
+ title: { label: "Título", inputType: "text", group: "Conteúdo" },
15
+ variant: {
16
+ label: "Estilo",
17
+ inputType: "select",
18
+ options: [
19
+ { value: "badges", label: "Badges" },
20
+ { value: "list", label: "Lista" }
21
+ ],
22
+ group: "Exibição"
23
+ },
24
+ tags: { label: "Tags", inputType: "text", readOnly: !0, group: "Dados" }
25
+ }
26
+ };
27
+ t.register(e);
28
+ export {
29
+ e as blogTagCloudBlock
30
+ };
31
+ //# sourceMappingURL=blogTagCloud.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blogTagCloud.js","sources":["../../../../../src/engine/registry/blocks/sections/blogTagCloud.ts"],"sourcesContent":["import { BlockDefinition } from \"../../types\";\nimport { componentRegistry } from \"../../registry\";\n\nexport const blogTagCloudBlock: BlockDefinition = {\n type: \"blogTagCloud\",\n name: \"Nuvem de Tags\",\n description: \"Widget com tags dos posts do blog\",\n category: \"sections\",\n pluginId: \"blog\",\n defaultProps: {\n title: \"Tags\",\n tags: [],\n variant: \"badges\",\n },\n inspectorMeta: {\n title: { label: \"Título\", inputType: \"text\", group: \"Conteúdo\" },\n variant: {\n label: \"Estilo\",\n inputType: \"select\",\n options: [\n { value: \"badges\", label: \"Badges\" },\n { value: \"list\", label: \"Lista\" },\n ],\n group: \"Exibição\",\n },\n tags: { label: \"Tags\", inputType: \"text\", readOnly: true, group: \"Dados\" },\n },\n};\n\n// Auto-registro\ncomponentRegistry.register(blogTagCloudBlock);\n"],"names":["blogTagCloudBlock","componentRegistry"],"mappings":";AAGO,MAAMA,IAAqC;AAAA,EAChD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,MAAM,CAAA;AAAA,IACN,SAAS;AAAA,EAAA;AAAA,EAEX,eAAe;AAAA,IACb,OAAO,EAAE,OAAO,UAAU,WAAW,QAAQ,OAAO,WAAA;AAAA,IACpD,SAAS;AAAA,MACP,OAAO;AAAA,MACP,WAAW;AAAA,MACX,SAAS;AAAA,QACP,EAAE,OAAO,UAAU,OAAO,SAAA;AAAA,QAC1B,EAAE,OAAO,QAAQ,OAAO,QAAA;AAAA,MAAQ;AAAA,MAElC,OAAO;AAAA,IAAA;AAAA,IAET,MAAM,EAAE,OAAO,QAAQ,WAAW,QAAQ,UAAU,IAAM,OAAO,QAAA;AAAA,EAAQ;AAE7E;AAGAC,EAAkB,SAASD,CAAiB;"}
@@ -29,4 +29,6 @@ export * from './blogSearchBar';
29
29
  export * from './productShowcase';
30
30
  export * from './aboutSection';
31
31
  export * from './contactSection';
32
+ export * from './blogRecentPosts';
33
+ export * from './blogTagCloud';
32
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/engine/registry/blocks/sections/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,OAAO,CAAC;AACtB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"GridRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,SAAS,CAsBjB"}
1
+ {"version":3,"file":"GridRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAGzD,wBAAgB,UAAU,CACxB,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,MAAM,GACZ,KAAK,CAAC,SAAS,CAgCjB"}
@@ -1,22 +1,25 @@
1
- import { jsx as d } from "react/jsx-runtime";
2
- import p from "react";
3
- import { renderBlockNode as s } from "../../renderNodeImpl.js";
4
- function f(e, i) {
5
- const { cols: r = 3, gap: m = "1rem", children: t = [] } = e.props, n = typeof r == "number" ? r : r.lg || r.md || r.sm || 3;
6
- return /* @__PURE__ */ d(
7
- "div",
8
- {
9
- style: {
10
- display: "grid",
11
- gridTemplateColumns: `repeat(${n}, 1fr)`,
12
- gap: m
13
- },
14
- children: t.map((o) => /* @__PURE__ */ d(p.Fragment, { children: s(o, i + 1) }, o.id))
15
- },
16
- e.id
17
- );
1
+ import { jsxs as c, jsx as i } from "react/jsx-runtime";
2
+ import n from "react";
3
+ import { renderBlockNode as g } from "../../renderNodeImpl.js";
4
+ function x(e, o) {
5
+ const { cols: r = 3, colTemplate: t, gap: s = "1rem", children: p = [] } = e.props, l = typeof r == "number" ? r : r.lg || r.md || r.sm || 3, a = t || `repeat(${l}, 1fr)`, d = t ? `@media (max-width: 767px) { #grid-${e.id} { grid-template-columns: 1fr !important; } }` : "";
6
+ return /* @__PURE__ */ c(n.Fragment, { children: [
7
+ d && /* @__PURE__ */ i("style", { children: d }),
8
+ /* @__PURE__ */ i(
9
+ "div",
10
+ {
11
+ id: `grid-${e.id}`,
12
+ style: {
13
+ display: "grid",
14
+ gridTemplateColumns: a,
15
+ gap: s
16
+ },
17
+ children: p.map((m) => /* @__PURE__ */ i(n.Fragment, { children: g(m, o + 1) }, m.id))
18
+ }
19
+ )
20
+ ] }, e.id);
18
21
  }
19
22
  export {
20
- f as renderGrid
23
+ x as renderGrid
21
24
  };
22
25
  //# sourceMappingURL=GridRenderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GridRenderer.js","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"sourcesContent":["/**\n * Grid Renderer\n * Renderiza bloco de grid com CSS Grid\n */\n\nimport React from \"react\";\nimport { GridBlock } from \"../../../schema/siteDocument\";\nimport { renderBlockNode } from \"../../renderNodeImpl\";\n\nexport function renderGrid(\n block: GridBlock,\n depth: number,\n): React.ReactNode {\n const { cols = 3, gap = \"1rem\", children = [] } = block.props;\n\n const gridCols =\n typeof cols === \"number\" ? cols : cols.lg || cols.md || cols.sm || 3;\n\n return (\n <div\n key={block.id}\n style={{\n display: \"grid\",\n gridTemplateColumns: `repeat(${gridCols}, 1fr)`,\n gap,\n }}\n >\n {children.map((child) => (\n <React.Fragment key={child.id}>\n {renderBlockNode(child, depth + 1)}\n </React.Fragment>\n ))}\n </div>\n );\n}\n"],"names":["renderGrid","block","depth","cols","gap","children","gridCols","jsx","child","React","renderBlockNode"],"mappings":";;;AASO,SAASA,EACdC,GACAC,GACiB;AACjB,QAAM,EAAE,MAAAC,IAAO,GAAG,KAAAC,IAAM,QAAQ,UAAAC,IAAW,CAAA,MAAOJ,EAAM,OAElDK,IACJ,OAAOH,KAAS,WAAWA,IAAOA,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAM;AAErE,SACE,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MAEC,OAAO;AAAA,QACL,SAAS;AAAA,QACT,qBAAqB,UAAUD,CAAQ;AAAA,QACvC,KAAAF;AAAA,MAAA;AAAA,MAGD,UAAAC,EAAS,IAAI,CAACG,wBACZC,EAAM,UAAN,EACE,UAAAC,EAAgBF,GAAON,IAAQ,CAAC,EAAA,GADdM,EAAM,EAE3B,CACD;AAAA,IAAA;AAAA,IAXIP,EAAM;AAAA,EAAA;AAcjB;"}
1
+ {"version":3,"file":"GridRenderer.js","sources":["../../../../../src/engine/render/renderers/layout/GridRenderer.tsx"],"sourcesContent":["/**\n * Grid Renderer\n * Renderiza bloco de grid com CSS Grid\n * Suporte a colTemplate para templates customizados (ex: \"1fr 320px\")\n */\n\nimport React from \"react\";\nimport { GridBlock } from \"../../../schema/siteDocument\";\nimport { renderBlockNode } from \"../../renderNodeImpl\";\n\nexport function renderGrid(\n block: GridBlock,\n depth: number,\n): React.ReactNode {\n const { cols = 3, colTemplate, gap = \"1rem\", children = [] } = block.props;\n\n const gridCols =\n typeof cols === \"number\" ? cols : cols.lg || cols.md || cols.sm || 3;\n\n const gridTemplateColumns = colTemplate || `repeat(${gridCols}, 1fr)`;\n\n // When colTemplate is used, add responsive style to collapse to 1fr on mobile\n const responsiveStyle = colTemplate\n ? `@media (max-width: 767px) { #grid-${block.id} { grid-template-columns: 1fr !important; } }`\n : \"\";\n\n return (\n <React.Fragment key={block.id}>\n {responsiveStyle && <style>{responsiveStyle}</style>}\n <div\n id={`grid-${block.id}`}\n style={{\n display: \"grid\",\n gridTemplateColumns,\n gap,\n }}\n >\n {children.map((child) => (\n <React.Fragment key={child.id}>\n {renderBlockNode(child, depth + 1)}\n </React.Fragment>\n ))}\n </div>\n </React.Fragment>\n );\n}\n"],"names":["renderGrid","block","depth","cols","colTemplate","gap","children","gridCols","gridTemplateColumns","responsiveStyle","jsxs","React","jsx","child","renderBlockNode"],"mappings":";;;AAUO,SAASA,EACdC,GACAC,GACiB;AACjB,QAAM,EAAE,MAAAC,IAAO,GAAG,aAAAC,GAAa,KAAAC,IAAM,QAAQ,UAAAC,IAAW,CAAA,MAAOL,EAAM,OAE/DM,IACJ,OAAOJ,KAAS,WAAWA,IAAOA,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAM,GAE/DK,IAAsBJ,KAAe,UAAUG,CAAQ,UAGvDE,IAAkBL,IACpB,qCAAqCH,EAAM,EAAE,kDAC7C;AAEJ,SACE,gBAAAS,EAACC,EAAM,UAAN,EACE,UAAA;AAAA,IAAAF,KAAmB,gBAAAG,EAAC,WAAO,UAAAH,EAAA,CAAgB;AAAA,IAC5C,gBAAAG;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,IAAI,QAAQX,EAAM,EAAE;AAAA,QACpB,OAAO;AAAA,UACL,SAAS;AAAA,UACT,qBAAAO;AAAA,UACA,KAAAH;AAAA,QAAA;AAAA,QAGD,UAAAC,EAAS,IAAI,CAACO,wBACZF,EAAM,UAAN,EACE,UAAAG,EAAgBD,GAAOX,IAAQ,CAAC,EAAA,GADdW,EAAM,EAE3B,CACD;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,EAAA,GAfmBZ,EAAM,EAgB3B;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"BlogPostDetailRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/sections/BlogPostDetailRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAwB1B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,CAAC,SAAS,CAqQhE"}
1
+ {"version":3,"file":"BlogPostDetailRenderer.d.ts","sourceRoot":"","sources":["../../../../../src/engine/render/renderers/sections/BlogPostDetailRenderer.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAwB1B,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,CAAC,SAAS,CAgShE"}