@botlr/react 0.0.0-stage → 0.1.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.
@@ -0,0 +1,67 @@
1
+ import React, { ComponentType } from 'react';
2
+ import { PublisherScope, PageScope, LayoutNode, VisibilityRules } from '@botlr/sdk';
3
+ export { BreadcrumbItem, GridColumn, GridContainerInstance, InlineSectionInstance, LayoutNode, PageScope, PublisherScope, SharedSectionInstance, VisibilityRules } from '@botlr/sdk';
4
+
5
+ /**
6
+ * Props every section component receives from `SectionRenderer`, on top of
7
+ * the section's own props from the page layout.
8
+ */
9
+ interface BaseSectionProps {
10
+ scope?: PublisherScope;
11
+ pageScope?: PageScope;
12
+ [key: string]: any;
13
+ }
14
+ /**
15
+ * A section component is a React component that accepts any props (at least
16
+ * `BaseSectionProps`, usually more).
17
+ */
18
+ type SectionComponent = ComponentType<any>;
19
+ /**
20
+ * Maps section type names (the `sectionType` of an inline layout node) to
21
+ * the React components that render them.
22
+ *
23
+ * ```ts
24
+ * const registry: ComponentRegistry = {
25
+ * hero: Hero,
26
+ * "text-block": TextBlock,
27
+ * };
28
+ * ```
29
+ */
30
+ type ComponentRegistry = Record<string, SectionComponent>;
31
+
32
+ interface SectionRendererProps {
33
+ section: LayoutNode;
34
+ componentRegistry: ComponentRegistry;
35
+ mode?: "draft" | "published";
36
+ onSectionClick?: (sectionId: string, sectionType: string) => void;
37
+ sharedSectionsData?: Map<string, any>;
38
+ scope?: PublisherScope;
39
+ pageScope?: PageScope;
40
+ fromTemplate?: boolean;
41
+ }
42
+ declare function SectionRenderer({ section, componentRegistry, mode, onSectionClick, sharedSectionsData, scope, pageScope, fromTemplate, }: SectionRendererProps): React.JSX.Element | null;
43
+
44
+ /**
45
+ * Visibility evaluation utilities for layout nodes. Framework-agnostic: no
46
+ * React import, so the same logic can back other renderers.
47
+ */
48
+
49
+ interface VisibilityContext {
50
+ pageId?: string;
51
+ currentPath?: string;
52
+ docType?: string;
53
+ locale: string;
54
+ environment?: string;
55
+ userRoles?: string[];
56
+ }
57
+ interface VisibleNode {
58
+ visibility?: VisibilityRules[];
59
+ type?: string;
60
+ columns?: Array<{
61
+ sections: VisibleNode[];
62
+ }>;
63
+ }
64
+ declare function shouldShowNode(node: VisibleNode, context: VisibilityContext): boolean;
65
+ declare function filterVisibleNodesRecursive<T extends VisibleNode>(nodes: T[], context: VisibilityContext): T[];
66
+
67
+ export { type BaseSectionProps, type ComponentRegistry, type SectionComponent, SectionRenderer, type SectionRendererProps, type VisibilityContext, filterVisibleNodesRecursive, shouldShowNode };
@@ -0,0 +1,67 @@
1
+ import React, { ComponentType } from 'react';
2
+ import { PublisherScope, PageScope, LayoutNode, VisibilityRules } from '@botlr/sdk';
3
+ export { BreadcrumbItem, GridColumn, GridContainerInstance, InlineSectionInstance, LayoutNode, PageScope, PublisherScope, SharedSectionInstance, VisibilityRules } from '@botlr/sdk';
4
+
5
+ /**
6
+ * Props every section component receives from `SectionRenderer`, on top of
7
+ * the section's own props from the page layout.
8
+ */
9
+ interface BaseSectionProps {
10
+ scope?: PublisherScope;
11
+ pageScope?: PageScope;
12
+ [key: string]: any;
13
+ }
14
+ /**
15
+ * A section component is a React component that accepts any props (at least
16
+ * `BaseSectionProps`, usually more).
17
+ */
18
+ type SectionComponent = ComponentType<any>;
19
+ /**
20
+ * Maps section type names (the `sectionType` of an inline layout node) to
21
+ * the React components that render them.
22
+ *
23
+ * ```ts
24
+ * const registry: ComponentRegistry = {
25
+ * hero: Hero,
26
+ * "text-block": TextBlock,
27
+ * };
28
+ * ```
29
+ */
30
+ type ComponentRegistry = Record<string, SectionComponent>;
31
+
32
+ interface SectionRendererProps {
33
+ section: LayoutNode;
34
+ componentRegistry: ComponentRegistry;
35
+ mode?: "draft" | "published";
36
+ onSectionClick?: (sectionId: string, sectionType: string) => void;
37
+ sharedSectionsData?: Map<string, any>;
38
+ scope?: PublisherScope;
39
+ pageScope?: PageScope;
40
+ fromTemplate?: boolean;
41
+ }
42
+ declare function SectionRenderer({ section, componentRegistry, mode, onSectionClick, sharedSectionsData, scope, pageScope, fromTemplate, }: SectionRendererProps): React.JSX.Element | null;
43
+
44
+ /**
45
+ * Visibility evaluation utilities for layout nodes. Framework-agnostic: no
46
+ * React import, so the same logic can back other renderers.
47
+ */
48
+
49
+ interface VisibilityContext {
50
+ pageId?: string;
51
+ currentPath?: string;
52
+ docType?: string;
53
+ locale: string;
54
+ environment?: string;
55
+ userRoles?: string[];
56
+ }
57
+ interface VisibleNode {
58
+ visibility?: VisibilityRules[];
59
+ type?: string;
60
+ columns?: Array<{
61
+ sections: VisibleNode[];
62
+ }>;
63
+ }
64
+ declare function shouldShowNode(node: VisibleNode, context: VisibilityContext): boolean;
65
+ declare function filterVisibleNodesRecursive<T extends VisibleNode>(nodes: T[], context: VisibilityContext): T[];
66
+
67
+ export { type BaseSectionProps, type ComponentRegistry, type SectionComponent, SectionRenderer, type SectionRendererProps, type VisibilityContext, filterVisibleNodesRecursive, shouldShowNode };
package/dist/index.js ADDED
@@ -0,0 +1,469 @@
1
+ // src/components/SectionRenderer.tsx
2
+ import "react";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ var colSpanClasses = {
5
+ 1: "col-span-1",
6
+ 2: "col-span-2",
7
+ 3: "col-span-3",
8
+ 4: "col-span-4",
9
+ 5: "col-span-5",
10
+ 6: "col-span-6",
11
+ 7: "col-span-7",
12
+ 8: "col-span-8",
13
+ 9: "col-span-9",
14
+ 10: "col-span-10",
15
+ 11: "col-span-11",
16
+ 12: "col-span-12"
17
+ };
18
+ var mdColSpanClasses = {
19
+ 1: "md:col-span-1",
20
+ 2: "md:col-span-2",
21
+ 3: "md:col-span-3",
22
+ 4: "md:col-span-4",
23
+ 5: "md:col-span-5",
24
+ 6: "md:col-span-6",
25
+ 7: "md:col-span-7",
26
+ 8: "md:col-span-8",
27
+ 9: "md:col-span-9",
28
+ 10: "md:col-span-10",
29
+ 11: "md:col-span-11",
30
+ 12: "md:col-span-12"
31
+ };
32
+ var lgColSpanClasses = {
33
+ 1: "lg:col-span-1",
34
+ 2: "lg:col-span-2",
35
+ 3: "lg:col-span-3",
36
+ 4: "lg:col-span-4",
37
+ 5: "lg:col-span-5",
38
+ 6: "lg:col-span-6",
39
+ 7: "lg:col-span-7",
40
+ 8: "lg:col-span-8",
41
+ 9: "lg:col-span-9",
42
+ 10: "lg:col-span-10",
43
+ 11: "lg:col-span-11",
44
+ 12: "lg:col-span-12"
45
+ };
46
+ var gapClasses = {
47
+ 0: "gap-0",
48
+ 1: "gap-1",
49
+ 2: "gap-2",
50
+ 3: "gap-3",
51
+ 4: "gap-4",
52
+ 5: "gap-5",
53
+ 6: "gap-6",
54
+ 7: "gap-7",
55
+ 8: "gap-8",
56
+ 9: "gap-9",
57
+ 10: "gap-10",
58
+ 11: "gap-11",
59
+ 12: "gap-12"
60
+ };
61
+ var mdGapClasses = {
62
+ 0: "md:gap-0",
63
+ 1: "md:gap-1",
64
+ 2: "md:gap-2",
65
+ 3: "md:gap-3",
66
+ 4: "md:gap-4",
67
+ 5: "md:gap-5",
68
+ 6: "md:gap-6",
69
+ 7: "md:gap-7",
70
+ 8: "md:gap-8",
71
+ 9: "md:gap-9",
72
+ 10: "md:gap-10",
73
+ 11: "md:gap-11",
74
+ 12: "md:gap-12"
75
+ };
76
+ var lgGapClasses = {
77
+ 0: "lg:gap-0",
78
+ 1: "lg:gap-1",
79
+ 2: "lg:gap-2",
80
+ 3: "lg:gap-3",
81
+ 4: "lg:gap-4",
82
+ 5: "lg:gap-5",
83
+ 6: "lg:gap-6",
84
+ 7: "lg:gap-7",
85
+ 8: "lg:gap-8",
86
+ 9: "lg:gap-9",
87
+ 10: "lg:gap-10",
88
+ 11: "lg:gap-11",
89
+ 12: "lg:gap-12"
90
+ };
91
+ function pushClass(classes, value) {
92
+ if (value) classes.push(value);
93
+ }
94
+ function getColumnClasses(span, hideOnMobile, hideOnTablet, hideOnDesktop) {
95
+ const classes = [];
96
+ pushClass(classes, colSpanClasses[span.mobile]);
97
+ if (span.tablet !== void 0) pushClass(classes, mdColSpanClasses[span.tablet]);
98
+ if (span.desktop !== void 0) pushClass(classes, lgColSpanClasses[span.desktop]);
99
+ if (hideOnMobile) {
100
+ classes.push("hidden md:block");
101
+ }
102
+ if (hideOnTablet) {
103
+ classes.push("md:hidden lg:block");
104
+ }
105
+ if (hideOnDesktop) {
106
+ classes.push("lg:hidden");
107
+ }
108
+ return classes.join(" ");
109
+ }
110
+ function getGapClasses(gap) {
111
+ if (!gap) return "gap-6";
112
+ const classes = [];
113
+ if (gap.mobile !== void 0) pushClass(classes, gapClasses[gap.mobile]);
114
+ if (gap.tablet !== void 0) pushClass(classes, mdGapClasses[gap.tablet]);
115
+ if (gap.desktop !== void 0) pushClass(classes, lgGapClasses[gap.desktop]);
116
+ return classes.join(" ") || "gap-6";
117
+ }
118
+ var maxWidthClasses = {
119
+ sm: "max-w-sm",
120
+ md: "max-w-md",
121
+ lg: "max-w-lg",
122
+ xl: "max-w-xl",
123
+ "2xl": "max-w-2xl",
124
+ "3xl": "max-w-3xl",
125
+ "4xl": "max-w-4xl",
126
+ "5xl": "max-w-5xl",
127
+ "6xl": "max-w-6xl",
128
+ "7xl": "max-w-7xl",
129
+ full: "max-w-full",
130
+ none: ""
131
+ };
132
+ var paddingXClasses = {
133
+ none: "px-0",
134
+ xs: "px-2",
135
+ sm: "px-4",
136
+ md: "px-6",
137
+ lg: "px-8",
138
+ xl: "px-10",
139
+ "2xl": "px-12"
140
+ };
141
+ var paddingYClasses = {
142
+ none: "py-0",
143
+ xs: "py-2",
144
+ sm: "py-4",
145
+ md: "py-6",
146
+ lg: "py-8",
147
+ xl: "py-10",
148
+ "2xl": "py-12"
149
+ };
150
+ var marginXClasses = {
151
+ none: "mx-0",
152
+ xs: "mx-2",
153
+ sm: "mx-4",
154
+ md: "mx-6",
155
+ lg: "mx-8",
156
+ xl: "mx-10",
157
+ "2xl": "mx-12",
158
+ auto: "mx-auto"
159
+ };
160
+ var marginYClasses = {
161
+ none: "my-0",
162
+ xs: "my-2",
163
+ sm: "my-4",
164
+ md: "my-6",
165
+ lg: "my-8",
166
+ xl: "my-10",
167
+ "2xl": "my-12"
168
+ };
169
+ var borderRadiusClasses = {
170
+ none: "rounded-none",
171
+ sm: "rounded-sm",
172
+ md: "rounded-md",
173
+ lg: "rounded-lg",
174
+ xl: "rounded-xl",
175
+ "2xl": "rounded-2xl",
176
+ full: "rounded-full"
177
+ };
178
+ var shadowClasses = {
179
+ none: "shadow-none",
180
+ sm: "shadow-sm",
181
+ md: "shadow-md",
182
+ lg: "shadow-lg",
183
+ xl: "shadow-xl",
184
+ "2xl": "shadow-2xl"
185
+ };
186
+ var alignItemsClasses = {
187
+ start: "items-start",
188
+ center: "items-center",
189
+ end: "items-end",
190
+ stretch: "items-stretch"
191
+ };
192
+ var justifyContentClasses = {
193
+ start: "justify-start",
194
+ center: "justify-center",
195
+ end: "justify-end",
196
+ between: "justify-between",
197
+ around: "justify-around",
198
+ evenly: "justify-evenly"
199
+ };
200
+ function SectionRenderer({
201
+ section,
202
+ componentRegistry,
203
+ mode = "published",
204
+ onSectionClick,
205
+ sharedSectionsData,
206
+ scope,
207
+ pageScope,
208
+ fromTemplate = false
209
+ }) {
210
+ if ("type" in section && section.type === "grid-container") {
211
+ const gridSection = section;
212
+ if (mode === "published" && gridSection.status === "draft") {
213
+ return null;
214
+ }
215
+ const gridClasses = [
216
+ "grid",
217
+ "grid-cols-12",
218
+ getGapClasses(gridSection.gap),
219
+ gridSection.alignItems ? alignItemsClasses[gridSection.alignItems] : "",
220
+ gridSection.justifyContent ? justifyContentClasses[gridSection.justifyContent] : ""
221
+ ].filter(Boolean).join(" ");
222
+ if (gridSection.fullWidthBackground && gridSection.background) {
223
+ const outerClasses = [
224
+ "w-full",
225
+ gridSection.background || "",
226
+ gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : "",
227
+ gridSection.marginY ? marginYClasses[gridSection.marginY] : "",
228
+ gridSection.border ? "border-y border-gray-200" : ""
229
+ ].filter(Boolean).join(" ");
230
+ const innerClasses = [
231
+ gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : "",
232
+ gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : "",
233
+ gridSection.marginX ? marginXClasses[gridSection.marginX] : "mx-auto",
234
+ gridSection.borderRadius ? borderRadiusClasses[gridSection.borderRadius] : "",
235
+ gridSection.shadow ? shadowClasses[gridSection.shadow] : ""
236
+ ].filter(Boolean).join(" ");
237
+ return /* @__PURE__ */ jsx("div", { className: outerClasses, "data-grid-id": gridSection._key, children: /* @__PURE__ */ jsx("div", { className: innerClasses, children: /* @__PURE__ */ jsx("div", { className: gridClasses, children: gridSection.columns.map((column, columnIndex) => /* @__PURE__ */ jsx(
238
+ "div",
239
+ {
240
+ className: getColumnClasses(
241
+ column.span,
242
+ column.hideOnMobile,
243
+ column.hideOnTablet,
244
+ column.hideOnDesktop
245
+ ),
246
+ children: column.sections.map((nestedSection) => /* @__PURE__ */ jsx(
247
+ SectionRenderer,
248
+ {
249
+ section: nestedSection,
250
+ componentRegistry,
251
+ mode,
252
+ onSectionClick,
253
+ fromTemplate,
254
+ sharedSectionsData,
255
+ scope,
256
+ pageScope
257
+ },
258
+ nestedSection._key
259
+ ))
260
+ },
261
+ `${gridSection._key}-col-${columnIndex}`
262
+ )) }) }) });
263
+ }
264
+ const containerClasses = [
265
+ gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : "",
266
+ gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : "",
267
+ gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : "",
268
+ gridSection.marginX ? marginXClasses[gridSection.marginX] : "",
269
+ gridSection.marginY ? marginYClasses[gridSection.marginY] : "",
270
+ gridSection.background || "",
271
+ gridSection.border ? "border border-gray-200" : "",
272
+ gridSection.borderRadius ? borderRadiusClasses[gridSection.borderRadius] : "",
273
+ gridSection.shadow ? shadowClasses[gridSection.shadow] : ""
274
+ ].filter(Boolean).join(" ");
275
+ return /* @__PURE__ */ jsx(
276
+ "div",
277
+ {
278
+ className: containerClasses || "w-full",
279
+ "data-grid-id": gridSection._key,
280
+ children: /* @__PURE__ */ jsx("div", { className: gridClasses, children: gridSection.columns.map((column, columnIndex) => /* @__PURE__ */ jsx(
281
+ "div",
282
+ {
283
+ className: getColumnClasses(
284
+ column.span,
285
+ column.hideOnMobile,
286
+ column.hideOnTablet,
287
+ column.hideOnDesktop
288
+ ),
289
+ children: column.sections.map((nestedSection) => /* @__PURE__ */ jsx(
290
+ SectionRenderer,
291
+ {
292
+ section: nestedSection,
293
+ componentRegistry,
294
+ mode,
295
+ onSectionClick,
296
+ fromTemplate,
297
+ sharedSectionsData,
298
+ scope,
299
+ pageScope
300
+ },
301
+ nestedSection._key
302
+ ))
303
+ },
304
+ `${gridSection._key}-col-${columnIndex}`
305
+ )) })
306
+ }
307
+ );
308
+ }
309
+ if ("mode" in section && section.mode === "inline") {
310
+ const inlineSection = section;
311
+ if (mode === "published" && inlineSection.status === "draft") {
312
+ return null;
313
+ }
314
+ const Component = componentRegistry[inlineSection.sectionType];
315
+ if (!Component) {
316
+ return /* @__PURE__ */ jsxs("div", { className: "unknown-section p-8 bg-red-50 border border-red-200 rounded text-center", children: [
317
+ /* @__PURE__ */ jsxs("p", { className: "text-red-600 font-semibold", children: [
318
+ "Unknown section type: ",
319
+ inlineSection.sectionType
320
+ ] }),
321
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-red-500 mt-2", children: "Component not found in registry. Make sure it's registered in your app." })
322
+ ] });
323
+ }
324
+ const handleClick = onSectionClick ? (e) => {
325
+ e.preventDefault();
326
+ e.stopPropagation();
327
+ onSectionClick(inlineSection._key, inlineSection.sectionType);
328
+ } : void 0;
329
+ return /* @__PURE__ */ jsx(
330
+ "div",
331
+ {
332
+ "data-section-id": inlineSection._key,
333
+ "data-section-type": inlineSection.sectionType,
334
+ "data-from-template": fromTemplate || void 0,
335
+ onClick: handleClick,
336
+ className: onSectionClick ? "cursor-pointer hover:ring-2 hover:ring-primary" : void 0,
337
+ children: /* @__PURE__ */ jsx(
338
+ Component,
339
+ {
340
+ ...inlineSection.props || {},
341
+ scope,
342
+ pageScope
343
+ }
344
+ )
345
+ }
346
+ );
347
+ }
348
+ if ("mode" in section && section.mode === "shared") {
349
+ const sharedSection = section;
350
+ const sharedSections = sharedSectionsData?.get(
351
+ sharedSection.sharedSectionId
352
+ );
353
+ if (!sharedSections) {
354
+ return /* @__PURE__ */ jsxs("div", { className: "shared-section-not-found p-8 border-2 border-dashed border-yellow-300 text-center text-yellow-700", children: [
355
+ /* @__PURE__ */ jsx("p", { className: "font-semibold", children: "Shared Section Not Found" }),
356
+ /* @__PURE__ */ jsxs("p", { className: "text-sm mt-2", children: [
357
+ "ID: ",
358
+ sharedSection.sharedSectionId
359
+ ] })
360
+ ] });
361
+ }
362
+ return /* @__PURE__ */ jsx(
363
+ "div",
364
+ {
365
+ "data-section-id": sharedSection._key,
366
+ "data-shared-section-id": sharedSection.sharedSectionId,
367
+ children: Array.isArray(sharedSections) && sharedSections.map((sharedSectionData, index) => {
368
+ let finalSection = sharedSectionData;
369
+ if (index === 0 && "mode" in sharedSectionData && sharedSectionData.mode === "inline" && sharedSection.overrides) {
370
+ finalSection = {
371
+ ...sharedSectionData,
372
+ props: {
373
+ ...sharedSectionData.props,
374
+ ...sharedSection.overrides
375
+ }
376
+ };
377
+ }
378
+ return /* @__PURE__ */ jsx(
379
+ SectionRenderer,
380
+ {
381
+ section: finalSection,
382
+ componentRegistry,
383
+ mode,
384
+ onSectionClick,
385
+ sharedSectionsData,
386
+ scope,
387
+ pageScope,
388
+ fromTemplate
389
+ },
390
+ `${sharedSection.sharedSectionId}-${index}`
391
+ );
392
+ })
393
+ }
394
+ );
395
+ }
396
+ return /* @__PURE__ */ jsxs("div", { className: "invalid-section p-8 bg-yellow-50 border border-yellow-200 rounded text-center", children: [
397
+ /* @__PURE__ */ jsx("p", { className: "text-yellow-700", children: "Invalid section format" }),
398
+ /* @__PURE__ */ jsx("pre", { className: "text-xs mt-2 text-left", children: JSON.stringify(section, null, 2) })
399
+ ] });
400
+ }
401
+
402
+ // src/lib/visibility-evaluator.ts
403
+ function shouldShowNode(node, context) {
404
+ if (!node.visibility || node.visibility.length === 0) return true;
405
+ const rules = node.visibility.find((r) => r.locale === context.locale);
406
+ if (!rules) return true;
407
+ const hasIncludeRules = rules.includePages && rules.includePages.length > 0 || rules.includePatterns && rules.includePatterns.length > 0 || rules.includeDocTypes && rules.includeDocTypes.length > 0 || rules.includeEnvironments && rules.includeEnvironments.length > 0 || rules.requireRoles && rules.requireRoles.length > 0;
408
+ const hasExcludeRules = rules.excludePages && rules.excludePages.length > 0 || rules.excludePatterns && rules.excludePatterns.length > 0 || rules.excludeDocTypes && rules.excludeDocTypes.length > 0 || rules.excludeEnvironments && rules.excludeEnvironments.length > 0 || rules.excludeRoles && rules.excludeRoles.length > 0;
409
+ if (!hasIncludeRules && !hasExcludeRules) return true;
410
+ if (hasExcludeRules) {
411
+ if (context.pageId && rules.excludePages?.includes(context.pageId)) return false;
412
+ if (context.currentPath && rules.excludePatterns) {
413
+ if (matchesAnyPattern(context.currentPath, rules.excludePatterns)) return false;
414
+ }
415
+ if (context.docType && rules.excludeDocTypes?.includes(context.docType)) return false;
416
+ if (context.environment && rules.excludeEnvironments?.includes(context.environment)) return false;
417
+ if (context.userRoles && rules.excludeRoles) {
418
+ if (hasAnyRole(context.userRoles, rules.excludeRoles)) return false;
419
+ }
420
+ }
421
+ if (hasIncludeRules) {
422
+ let matchedInclude = false;
423
+ if (context.pageId && rules.includePages?.includes(context.pageId)) matchedInclude = true;
424
+ if (!matchedInclude && context.currentPath && rules.includePatterns) {
425
+ if (matchesAnyPattern(context.currentPath, rules.includePatterns)) matchedInclude = true;
426
+ }
427
+ if (!matchedInclude && context.docType && rules.includeDocTypes?.includes(context.docType)) matchedInclude = true;
428
+ if (!matchedInclude && context.environment && rules.includeEnvironments?.includes(context.environment)) matchedInclude = true;
429
+ if (!matchedInclude && context.userRoles && rules.requireRoles) {
430
+ if (hasAnyRole(context.userRoles, rules.requireRoles)) matchedInclude = true;
431
+ }
432
+ if (!matchedInclude) return false;
433
+ }
434
+ return true;
435
+ }
436
+ function filterVisibleNodesRecursive(nodes, context) {
437
+ return nodes.filter((node) => shouldShowNode(node, context)).map((node) => {
438
+ if (node.type === "grid-container" && Array.isArray(node.columns)) {
439
+ return {
440
+ ...node,
441
+ columns: node.columns.map((col) => ({
442
+ ...col,
443
+ sections: filterVisibleNodesRecursive(col.sections, context)
444
+ }))
445
+ };
446
+ }
447
+ return node;
448
+ });
449
+ }
450
+ function matchesAnyPattern(path, patterns) {
451
+ return patterns.some((pattern) => matchesPattern(path, pattern));
452
+ }
453
+ function matchesPattern(path, pattern) {
454
+ const normalizedPath = path.replace(/\/$/, "") || "/";
455
+ const normalizedPattern = pattern.replace(/\/$/, "") || "/";
456
+ if (normalizedPath === normalizedPattern) return true;
457
+ let regexPattern = normalizedPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "___DOUBLE_WILDCARD___").replace(/\*/g, "[^/]+").replace(/___DOUBLE_WILDCARD___/g, ".*");
458
+ regexPattern = `^${regexPattern}$`;
459
+ return new RegExp(regexPattern).test(normalizedPath);
460
+ }
461
+ function hasAnyRole(userRoles, requiredRoles) {
462
+ return requiredRoles.some((role) => userRoles.includes(role));
463
+ }
464
+ export {
465
+ SectionRenderer,
466
+ filterVisibleNodesRecursive,
467
+ shouldShowNode
468
+ };
469
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/SectionRenderer.tsx","../src/lib/visibility-evaluator.ts"],"sourcesContent":["import React from \"react\";\nimport type {\n GridContainerInstance,\n InlineSectionInstance,\n LayoutNode,\n PageScope,\n PublisherScope,\n ResponsiveGap,\n ResponsiveSpan,\n SharedSectionInstance,\n} from \"@botlr/sdk\";\nimport type { ComponentRegistry } from \"../types/component-registry\";\n\nexport interface SectionRendererProps {\n section: LayoutNode;\n componentRegistry: ComponentRegistry; // Components provided by the consuming app\n mode?: \"draft\" | \"published\";\n onSectionClick?: (sectionId: string, sectionType: string) => void;\n sharedSectionsData?: Map<string, any>; // Maps shared section ID to complete section data\n scope?: PublisherScope; // Publisher scope for building asset URLs\n pageScope?: PageScope; // Optional page scope for context\n fromTemplate?: boolean; // Whether this section comes from a page template\n}\n\n// Static class mappings for Tailwind JIT compiler\nconst colSpanClasses: Record<number, string> = {\n 1: \"col-span-1\",\n 2: \"col-span-2\",\n 3: \"col-span-3\",\n 4: \"col-span-4\",\n 5: \"col-span-5\",\n 6: \"col-span-6\",\n 7: \"col-span-7\",\n 8: \"col-span-8\",\n 9: \"col-span-9\",\n 10: \"col-span-10\",\n 11: \"col-span-11\",\n 12: \"col-span-12\",\n};\n\nconst mdColSpanClasses: Record<number, string> = {\n 1: \"md:col-span-1\",\n 2: \"md:col-span-2\",\n 3: \"md:col-span-3\",\n 4: \"md:col-span-4\",\n 5: \"md:col-span-5\",\n 6: \"md:col-span-6\",\n 7: \"md:col-span-7\",\n 8: \"md:col-span-8\",\n 9: \"md:col-span-9\",\n 10: \"md:col-span-10\",\n 11: \"md:col-span-11\",\n 12: \"md:col-span-12\",\n};\n\nconst lgColSpanClasses: Record<number, string> = {\n 1: \"lg:col-span-1\",\n 2: \"lg:col-span-2\",\n 3: \"lg:col-span-3\",\n 4: \"lg:col-span-4\",\n 5: \"lg:col-span-5\",\n 6: \"lg:col-span-6\",\n 7: \"lg:col-span-7\",\n 8: \"lg:col-span-8\",\n 9: \"lg:col-span-9\",\n 10: \"lg:col-span-10\",\n 11: \"lg:col-span-11\",\n 12: \"lg:col-span-12\",\n};\n\nconst gapClasses: Record<number, string> = {\n 0: \"gap-0\",\n 1: \"gap-1\",\n 2: \"gap-2\",\n 3: \"gap-3\",\n 4: \"gap-4\",\n 5: \"gap-5\",\n 6: \"gap-6\",\n 7: \"gap-7\",\n 8: \"gap-8\",\n 9: \"gap-9\",\n 10: \"gap-10\",\n 11: \"gap-11\",\n 12: \"gap-12\",\n};\n\nconst mdGapClasses: Record<number, string> = {\n 0: \"md:gap-0\",\n 1: \"md:gap-1\",\n 2: \"md:gap-2\",\n 3: \"md:gap-3\",\n 4: \"md:gap-4\",\n 5: \"md:gap-5\",\n 6: \"md:gap-6\",\n 7: \"md:gap-7\",\n 8: \"md:gap-8\",\n 9: \"md:gap-9\",\n 10: \"md:gap-10\",\n 11: \"md:gap-11\",\n 12: \"md:gap-12\",\n};\n\nconst lgGapClasses: Record<number, string> = {\n 0: \"lg:gap-0\",\n 1: \"lg:gap-1\",\n 2: \"lg:gap-2\",\n 3: \"lg:gap-3\",\n 4: \"lg:gap-4\",\n 5: \"lg:gap-5\",\n 6: \"lg:gap-6\",\n 7: \"lg:gap-7\",\n 8: \"lg:gap-8\",\n 9: \"lg:gap-9\",\n 10: \"lg:gap-10\",\n 11: \"lg:gap-11\",\n 12: \"lg:gap-12\",\n};\n\nfunction pushClass(classes: string[], value: string | undefined): void {\n if (value) classes.push(value);\n}\n\n// Helper function to generate responsive column classes\nfunction getColumnClasses(\n span: ResponsiveSpan,\n hideOnMobile?: boolean,\n hideOnTablet?: boolean,\n hideOnDesktop?: boolean,\n): string {\n const classes: string[] = [];\n\n pushClass(classes, colSpanClasses[span.mobile]);\n if (span.tablet !== undefined) pushClass(classes, mdColSpanClasses[span.tablet]);\n if (span.desktop !== undefined) pushClass(classes, lgColSpanClasses[span.desktop]);\n\n // Responsive visibility\n if (hideOnMobile) {\n classes.push(\"hidden md:block\");\n }\n if (hideOnTablet) {\n classes.push(\"md:hidden lg:block\");\n }\n if (hideOnDesktop) {\n classes.push(\"lg:hidden\");\n }\n\n return classes.join(\" \");\n}\n\n// Helper function to get gap classes\nfunction getGapClasses(gap?: ResponsiveGap): string {\n if (!gap) return \"gap-6\"; // Default gap\n\n const classes: string[] = [];\n if (gap.mobile !== undefined) pushClass(classes, gapClasses[gap.mobile]);\n if (gap.tablet !== undefined) pushClass(classes, mdGapClasses[gap.tablet]);\n if (gap.desktop !== undefined) pushClass(classes, lgGapClasses[gap.desktop]);\n\n return classes.join(\" \") || \"gap-6\";\n}\n\n// Utility class maps for container styling\nconst maxWidthClasses: Record<string, string> = {\n sm: \"max-w-sm\",\n md: \"max-w-md\",\n lg: \"max-w-lg\",\n xl: \"max-w-xl\",\n \"2xl\": \"max-w-2xl\",\n \"3xl\": \"max-w-3xl\",\n \"4xl\": \"max-w-4xl\",\n \"5xl\": \"max-w-5xl\",\n \"6xl\": \"max-w-6xl\",\n \"7xl\": \"max-w-7xl\",\n full: \"max-w-full\",\n none: \"\",\n};\n\nconst paddingXClasses: Record<string, string> = {\n none: \"px-0\",\n xs: \"px-2\",\n sm: \"px-4\",\n md: \"px-6\",\n lg: \"px-8\",\n xl: \"px-10\",\n \"2xl\": \"px-12\",\n};\n\nconst paddingYClasses: Record<string, string> = {\n none: \"py-0\",\n xs: \"py-2\",\n sm: \"py-4\",\n md: \"py-6\",\n lg: \"py-8\",\n xl: \"py-10\",\n \"2xl\": \"py-12\",\n};\n\nconst marginXClasses: Record<string, string> = {\n none: \"mx-0\",\n xs: \"mx-2\",\n sm: \"mx-4\",\n md: \"mx-6\",\n lg: \"mx-8\",\n xl: \"mx-10\",\n \"2xl\": \"mx-12\",\n auto: \"mx-auto\",\n};\n\nconst marginYClasses: Record<string, string> = {\n none: \"my-0\",\n xs: \"my-2\",\n sm: \"my-4\",\n md: \"my-6\",\n lg: \"my-8\",\n xl: \"my-10\",\n \"2xl\": \"my-12\",\n};\n\nconst borderRadiusClasses: Record<string, string> = {\n none: \"rounded-none\",\n sm: \"rounded-sm\",\n md: \"rounded-md\",\n lg: \"rounded-lg\",\n xl: \"rounded-xl\",\n \"2xl\": \"rounded-2xl\",\n full: \"rounded-full\",\n};\n\nconst shadowClasses: Record<string, string> = {\n none: \"shadow-none\",\n sm: \"shadow-sm\",\n md: \"shadow-md\",\n lg: \"shadow-lg\",\n xl: \"shadow-xl\",\n \"2xl\": \"shadow-2xl\",\n};\n\nconst alignItemsClasses: Record<string, string> = {\n start: \"items-start\",\n center: \"items-center\",\n end: \"items-end\",\n stretch: \"items-stretch\",\n};\n\nconst justifyContentClasses: Record<string, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n between: \"justify-between\",\n around: \"justify-around\",\n evenly: \"justify-evenly\",\n};\n\nexport function SectionRenderer({\n section,\n componentRegistry,\n mode = \"published\",\n onSectionClick,\n sharedSectionsData,\n scope,\n pageScope,\n fromTemplate = false,\n}: SectionRendererProps) {\n // Handle grid containers\n if (\"type\" in section && section.type === \"grid-container\") {\n const gridSection = section as GridContainerInstance;\n\n // Check if section should be visible based on mode and status\n if (mode === \"published\" && gridSection.status === \"draft\") {\n return null; // Don't render draft sections in published mode\n }\n\n // Build grid classes\n const gridClasses = [\n \"grid\",\n \"grid-cols-12\",\n getGapClasses(gridSection.gap),\n gridSection.alignItems ? alignItemsClasses[gridSection.alignItems] : \"\",\n gridSection.justifyContent\n ? justifyContentClasses[gridSection.justifyContent]\n : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n // Full-width background rendering\n if (gridSection.fullWidthBackground && gridSection.background) {\n const outerClasses = [\n \"w-full\",\n gridSection.background || \"\",\n gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : \"\",\n gridSection.marginY ? marginYClasses[gridSection.marginY] : \"\",\n gridSection.border ? \"border-y border-gray-200\" : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n const innerClasses = [\n gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : \"\",\n gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : \"\",\n gridSection.marginX ? marginXClasses[gridSection.marginX] : \"mx-auto\",\n gridSection.borderRadius\n ? borderRadiusClasses[gridSection.borderRadius]\n : \"\",\n gridSection.shadow ? shadowClasses[gridSection.shadow] : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div className={outerClasses} data-grid-id={gridSection._key}>\n <div className={innerClasses}>\n <div className={gridClasses}>\n {gridSection.columns.map((column, columnIndex) => (\n <div\n key={`${gridSection._key}-col-${columnIndex}`}\n className={getColumnClasses(\n column.span,\n column.hideOnMobile,\n column.hideOnTablet,\n column.hideOnDesktop,\n )}\n >\n {/* Recursively render sections within the column */}\n {column.sections.map((nestedSection) => (\n <SectionRenderer\n key={nestedSection._key}\n section={nestedSection}\n componentRegistry={componentRegistry}\n mode={mode}\n onSectionClick={onSectionClick}\n fromTemplate={fromTemplate}\n sharedSectionsData={sharedSectionsData}\n scope={scope}\n pageScope={pageScope}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n }\n\n // Standard rendering (no full-width background)\n const containerClasses = [\n gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : \"\",\n gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : \"\",\n gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : \"\",\n gridSection.marginX ? marginXClasses[gridSection.marginX] : \"\",\n gridSection.marginY ? marginYClasses[gridSection.marginY] : \"\",\n gridSection.background || \"\",\n gridSection.border ? \"border border-gray-200\" : \"\",\n gridSection.borderRadius\n ? borderRadiusClasses[gridSection.borderRadius]\n : \"\",\n gridSection.shadow ? shadowClasses[gridSection.shadow] : \"\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <div\n className={containerClasses || \"w-full\"}\n data-grid-id={gridSection._key}\n >\n <div className={gridClasses}>\n {gridSection.columns.map((column, columnIndex) => (\n <div\n key={`${gridSection._key}-col-${columnIndex}`}\n className={getColumnClasses(\n column.span,\n column.hideOnMobile,\n column.hideOnTablet,\n column.hideOnDesktop,\n )}\n >\n {/* Recursively render sections within the column */}\n {column.sections.map((nestedSection) => (\n <SectionRenderer\n key={nestedSection._key}\n section={nestedSection}\n componentRegistry={componentRegistry}\n mode={mode}\n onSectionClick={onSectionClick}\n fromTemplate={fromTemplate}\n sharedSectionsData={sharedSectionsData}\n scope={scope}\n pageScope={pageScope}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Handle inline sections\n if (\"mode\" in section && section.mode === \"inline\") {\n const inlineSection = section as InlineSectionInstance;\n\n // Check if section should be visible\n if (mode === \"published\" && inlineSection.status === \"draft\") {\n return null;\n }\n\n const Component = componentRegistry[inlineSection.sectionType];\n\n if (!Component) {\n return (\n <div className=\"unknown-section p-8 bg-red-50 border border-red-200 rounded text-center\">\n <p className=\"text-red-600 font-semibold\">\n Unknown section type: {inlineSection.sectionType}\n </p>\n <p className=\"text-sm text-red-500 mt-2\">\n Component not found in registry. Make sure it's registered in your\n app.\n </p>\n </div>\n );\n }\n\n const handleClick = onSectionClick\n ? (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onSectionClick(inlineSection._key, inlineSection.sectionType);\n }\n : undefined;\n\n return (\n <div\n data-section-id={inlineSection._key}\n data-section-type={inlineSection.sectionType}\n data-from-template={fromTemplate || undefined}\n onClick={handleClick}\n className={\n onSectionClick\n ? \"cursor-pointer hover:ring-2 hover:ring-primary\"\n : undefined\n }\n >\n <Component\n {...(inlineSection.props || {})}\n scope={scope}\n pageScope={pageScope}\n />\n </div>\n );\n }\n\n // Handle shared sections\n if (\"mode\" in section && section.mode === \"shared\") {\n const sharedSection = section as SharedSectionInstance;\n\n // Get all sections from the shared section (array of sections)\n const sharedSections = sharedSectionsData?.get(\n sharedSection.sharedSectionId,\n );\n\n if (!sharedSections) {\n return (\n <div className=\"shared-section-not-found p-8 border-2 border-dashed border-yellow-300 text-center text-yellow-700\">\n <p className=\"font-semibold\">Shared Section Not Found</p>\n <p className=\"text-sm mt-2\">ID: {sharedSection.sharedSectionId}</p>\n </div>\n );\n }\n\n // Render all sections from the shared section\n return (\n <div\n data-section-id={sharedSection._key}\n data-shared-section-id={sharedSection.sharedSectionId}\n >\n {Array.isArray(sharedSections) &&\n sharedSections.map((sharedSectionData, index) => {\n // Apply overrides to the first section if it's an inline section\n let finalSection = sharedSectionData;\n if (\n index === 0 &&\n \"mode\" in sharedSectionData &&\n sharedSectionData.mode === \"inline\" &&\n sharedSection.overrides\n ) {\n // Merge overrides with inline section props\n finalSection = {\n ...sharedSectionData,\n props: {\n ...sharedSectionData.props,\n ...sharedSection.overrides,\n },\n };\n }\n\n return (\n <SectionRenderer\n key={`${sharedSection.sharedSectionId}-${index}`}\n section={finalSection}\n componentRegistry={componentRegistry}\n mode={mode}\n onSectionClick={onSectionClick}\n sharedSectionsData={sharedSectionsData}\n scope={scope}\n pageScope={pageScope}\n fromTemplate={fromTemplate}\n />\n );\n })}\n </div>\n );\n }\n\n // Unknown section format\n return (\n <div className=\"invalid-section p-8 bg-yellow-50 border border-yellow-200 rounded text-center\">\n <p className=\"text-yellow-700\">Invalid section format</p>\n <pre className=\"text-xs mt-2 text-left\">\n {JSON.stringify(section, null, 2)}\n </pre>\n </div>\n );\n}\n","/**\n * Visibility evaluation utilities for layout nodes. Framework-agnostic: no\n * React import, so the same logic can back other renderers.\n */\n\nimport type { VisibilityRules } from \"@botlr/sdk\";\n\nexport type { VisibilityRules };\n\nexport interface VisibilityContext {\n pageId?: string;\n currentPath?: string;\n docType?: string;\n locale: string;\n environment?: string;\n userRoles?: string[];\n}\n\ninterface VisibleNode {\n visibility?: VisibilityRules[];\n type?: string;\n columns?: Array<{ sections: VisibleNode[] }>;\n}\n\nexport function shouldShowNode(node: VisibleNode, context: VisibilityContext): boolean {\n if (!node.visibility || node.visibility.length === 0) return true;\n\n const rules = node.visibility.find((r) => r.locale === context.locale);\n if (!rules) return true;\n\n const hasIncludeRules =\n (rules.includePages && rules.includePages.length > 0) ||\n (rules.includePatterns && rules.includePatterns.length > 0) ||\n (rules.includeDocTypes && rules.includeDocTypes.length > 0) ||\n (rules.includeEnvironments && rules.includeEnvironments.length > 0) ||\n (rules.requireRoles && rules.requireRoles.length > 0);\n\n const hasExcludeRules =\n (rules.excludePages && rules.excludePages.length > 0) ||\n (rules.excludePatterns && rules.excludePatterns.length > 0) ||\n (rules.excludeDocTypes && rules.excludeDocTypes.length > 0) ||\n (rules.excludeEnvironments && rules.excludeEnvironments.length > 0) ||\n (rules.excludeRoles && rules.excludeRoles.length > 0);\n\n if (!hasIncludeRules && !hasExcludeRules) return true;\n\n if (hasExcludeRules) {\n if (context.pageId && rules.excludePages?.includes(context.pageId)) return false;\n if (context.currentPath && rules.excludePatterns) {\n if (matchesAnyPattern(context.currentPath, rules.excludePatterns)) return false;\n }\n if (context.docType && rules.excludeDocTypes?.includes(context.docType)) return false;\n if (context.environment && rules.excludeEnvironments?.includes(context.environment)) return false;\n if (context.userRoles && rules.excludeRoles) {\n if (hasAnyRole(context.userRoles, rules.excludeRoles)) return false;\n }\n }\n\n if (hasIncludeRules) {\n let matchedInclude = false;\n if (context.pageId && rules.includePages?.includes(context.pageId)) matchedInclude = true;\n if (!matchedInclude && context.currentPath && rules.includePatterns) {\n if (matchesAnyPattern(context.currentPath, rules.includePatterns)) matchedInclude = true;\n }\n if (!matchedInclude && context.docType && rules.includeDocTypes?.includes(context.docType)) matchedInclude = true;\n if (!matchedInclude && context.environment && rules.includeEnvironments?.includes(context.environment)) matchedInclude = true;\n if (!matchedInclude && context.userRoles && rules.requireRoles) {\n if (hasAnyRole(context.userRoles, rules.requireRoles)) matchedInclude = true;\n }\n if (!matchedInclude) return false;\n }\n\n return true;\n}\n\nexport function filterVisibleNodesRecursive<T extends VisibleNode>(\n nodes: T[],\n context: VisibilityContext\n): T[] {\n return nodes\n .filter((node) => shouldShowNode(node, context))\n .map((node) => {\n if (node.type === 'grid-container' && Array.isArray(node.columns)) {\n return {\n ...node,\n columns: node.columns.map((col) => ({\n ...col,\n sections: filterVisibleNodesRecursive(col.sections, context),\n })),\n };\n }\n return node;\n });\n}\n\nfunction matchesAnyPattern(path: string, patterns: string[]): boolean {\n return patterns.some((pattern) => matchesPattern(path, pattern));\n}\n\nfunction matchesPattern(path: string, pattern: string): boolean {\n const normalizedPath = path.replace(/\\/$/, '') || '/';\n const normalizedPattern = pattern.replace(/\\/$/, '') || '/';\n\n if (normalizedPath === normalizedPattern) return true;\n\n let regexPattern = normalizedPattern\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n .replace(/\\*\\*/g, '___DOUBLE_WILDCARD___')\n .replace(/\\*/g, '[^/]+')\n .replace(/___DOUBLE_WILDCARD___/g, '.*');\n\n regexPattern = `^${regexPattern}$`;\n return new RegExp(regexPattern).test(normalizedPath);\n}\n\nfunction hasAnyRole(userRoles: string[], requiredRoles: string[]): boolean {\n return requiredRoles.some((role) => userRoles.includes(role));\n}\n"],"mappings":"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","names":[]}