@botlr/react 0.0.0-stage → 0.1.1
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.
- package/CHANGELOG.md +18 -0
- package/LICENSE +21 -0
- package/README.md +30 -2
- package/dist/index.cjs +498 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +67 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.js +469 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @botlr/react
|
|
2
|
+
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @botlr/sdk@0.2.0
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
- First release, moved from the `@Djarnis/botlr-renderer` repository (v0.0.10).
|
|
13
|
+
`SectionRenderer`, the visibility helpers and the registry types are
|
|
14
|
+
unchanged in behaviour.
|
|
15
|
+
- Layout node, `PublisherScope`, `PageScope` and `VisibilityRules` types now
|
|
16
|
+
come from `@botlr/sdk` and are re-exported here.
|
|
17
|
+
- The legacy `HeroOld`, `Features`, `CTA` and `GridContainerOld` components
|
|
18
|
+
are gone: no consumer imported them.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Botlr
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @botlr/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Botlr rendering engine for React hosts. It walks a page's layout tree and
|
|
4
|
+
renders each node through a component registry the host app provides. This is
|
|
5
|
+
the successor of the `@Djarnis/botlr-renderer` git dependency.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { SectionRenderer, type ComponentRegistry } from "@botlr/react";
|
|
9
|
+
import { Hero } from "./sections/Hero";
|
|
10
|
+
|
|
11
|
+
const registry: ComponentRegistry = { hero: Hero };
|
|
12
|
+
|
|
13
|
+
export function Page({ page, scope }) {
|
|
14
|
+
return page.layout.main.map((node) => (
|
|
15
|
+
<SectionRenderer key={node._key} section={node} componentRegistry={registry} scope={scope} />
|
|
16
|
+
));
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Exports:
|
|
21
|
+
|
|
22
|
+
- `SectionRenderer` renders inline, shared and grid-container nodes; draft
|
|
23
|
+
nodes are hidden in `published` mode.
|
|
24
|
+
- `filterVisibleNodesRecursive` / `shouldShowNode` apply per-locale
|
|
25
|
+
visibility rules before rendering (also usable without React).
|
|
26
|
+
- `ComponentRegistry`, `SectionComponent`, `BaseSectionProps`, plus the
|
|
27
|
+
`PublisherScope`, `PageScope` and layout node types shared with `@botlr/sdk`.
|
|
28
|
+
|
|
29
|
+
Tailwind classes are emitted as static strings so a host's JIT compiler can
|
|
30
|
+
pick them up. `react` is a peer dependency; the package depends on
|
|
31
|
+
`@botlr/sdk` for types only.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
SectionRenderer: () => SectionRenderer,
|
|
24
|
+
filterVisibleNodesRecursive: () => filterVisibleNodesRecursive,
|
|
25
|
+
shouldShowNode: () => shouldShowNode
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/components/SectionRenderer.tsx
|
|
30
|
+
var import_react = require("react");
|
|
31
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
32
|
+
var colSpanClasses = {
|
|
33
|
+
1: "col-span-1",
|
|
34
|
+
2: "col-span-2",
|
|
35
|
+
3: "col-span-3",
|
|
36
|
+
4: "col-span-4",
|
|
37
|
+
5: "col-span-5",
|
|
38
|
+
6: "col-span-6",
|
|
39
|
+
7: "col-span-7",
|
|
40
|
+
8: "col-span-8",
|
|
41
|
+
9: "col-span-9",
|
|
42
|
+
10: "col-span-10",
|
|
43
|
+
11: "col-span-11",
|
|
44
|
+
12: "col-span-12"
|
|
45
|
+
};
|
|
46
|
+
var mdColSpanClasses = {
|
|
47
|
+
1: "md:col-span-1",
|
|
48
|
+
2: "md:col-span-2",
|
|
49
|
+
3: "md:col-span-3",
|
|
50
|
+
4: "md:col-span-4",
|
|
51
|
+
5: "md:col-span-5",
|
|
52
|
+
6: "md:col-span-6",
|
|
53
|
+
7: "md:col-span-7",
|
|
54
|
+
8: "md:col-span-8",
|
|
55
|
+
9: "md:col-span-9",
|
|
56
|
+
10: "md:col-span-10",
|
|
57
|
+
11: "md:col-span-11",
|
|
58
|
+
12: "md:col-span-12"
|
|
59
|
+
};
|
|
60
|
+
var lgColSpanClasses = {
|
|
61
|
+
1: "lg:col-span-1",
|
|
62
|
+
2: "lg:col-span-2",
|
|
63
|
+
3: "lg:col-span-3",
|
|
64
|
+
4: "lg:col-span-4",
|
|
65
|
+
5: "lg:col-span-5",
|
|
66
|
+
6: "lg:col-span-6",
|
|
67
|
+
7: "lg:col-span-7",
|
|
68
|
+
8: "lg:col-span-8",
|
|
69
|
+
9: "lg:col-span-9",
|
|
70
|
+
10: "lg:col-span-10",
|
|
71
|
+
11: "lg:col-span-11",
|
|
72
|
+
12: "lg:col-span-12"
|
|
73
|
+
};
|
|
74
|
+
var gapClasses = {
|
|
75
|
+
0: "gap-0",
|
|
76
|
+
1: "gap-1",
|
|
77
|
+
2: "gap-2",
|
|
78
|
+
3: "gap-3",
|
|
79
|
+
4: "gap-4",
|
|
80
|
+
5: "gap-5",
|
|
81
|
+
6: "gap-6",
|
|
82
|
+
7: "gap-7",
|
|
83
|
+
8: "gap-8",
|
|
84
|
+
9: "gap-9",
|
|
85
|
+
10: "gap-10",
|
|
86
|
+
11: "gap-11",
|
|
87
|
+
12: "gap-12"
|
|
88
|
+
};
|
|
89
|
+
var mdGapClasses = {
|
|
90
|
+
0: "md:gap-0",
|
|
91
|
+
1: "md:gap-1",
|
|
92
|
+
2: "md:gap-2",
|
|
93
|
+
3: "md:gap-3",
|
|
94
|
+
4: "md:gap-4",
|
|
95
|
+
5: "md:gap-5",
|
|
96
|
+
6: "md:gap-6",
|
|
97
|
+
7: "md:gap-7",
|
|
98
|
+
8: "md:gap-8",
|
|
99
|
+
9: "md:gap-9",
|
|
100
|
+
10: "md:gap-10",
|
|
101
|
+
11: "md:gap-11",
|
|
102
|
+
12: "md:gap-12"
|
|
103
|
+
};
|
|
104
|
+
var lgGapClasses = {
|
|
105
|
+
0: "lg:gap-0",
|
|
106
|
+
1: "lg:gap-1",
|
|
107
|
+
2: "lg:gap-2",
|
|
108
|
+
3: "lg:gap-3",
|
|
109
|
+
4: "lg:gap-4",
|
|
110
|
+
5: "lg:gap-5",
|
|
111
|
+
6: "lg:gap-6",
|
|
112
|
+
7: "lg:gap-7",
|
|
113
|
+
8: "lg:gap-8",
|
|
114
|
+
9: "lg:gap-9",
|
|
115
|
+
10: "lg:gap-10",
|
|
116
|
+
11: "lg:gap-11",
|
|
117
|
+
12: "lg:gap-12"
|
|
118
|
+
};
|
|
119
|
+
function pushClass(classes, value) {
|
|
120
|
+
if (value) classes.push(value);
|
|
121
|
+
}
|
|
122
|
+
function getColumnClasses(span, hideOnMobile, hideOnTablet, hideOnDesktop) {
|
|
123
|
+
const classes = [];
|
|
124
|
+
pushClass(classes, colSpanClasses[span.mobile]);
|
|
125
|
+
if (span.tablet !== void 0) pushClass(classes, mdColSpanClasses[span.tablet]);
|
|
126
|
+
if (span.desktop !== void 0) pushClass(classes, lgColSpanClasses[span.desktop]);
|
|
127
|
+
if (hideOnMobile) {
|
|
128
|
+
classes.push("hidden md:block");
|
|
129
|
+
}
|
|
130
|
+
if (hideOnTablet) {
|
|
131
|
+
classes.push("md:hidden lg:block");
|
|
132
|
+
}
|
|
133
|
+
if (hideOnDesktop) {
|
|
134
|
+
classes.push("lg:hidden");
|
|
135
|
+
}
|
|
136
|
+
return classes.join(" ");
|
|
137
|
+
}
|
|
138
|
+
function getGapClasses(gap) {
|
|
139
|
+
if (!gap) return "gap-6";
|
|
140
|
+
const classes = [];
|
|
141
|
+
if (gap.mobile !== void 0) pushClass(classes, gapClasses[gap.mobile]);
|
|
142
|
+
if (gap.tablet !== void 0) pushClass(classes, mdGapClasses[gap.tablet]);
|
|
143
|
+
if (gap.desktop !== void 0) pushClass(classes, lgGapClasses[gap.desktop]);
|
|
144
|
+
return classes.join(" ") || "gap-6";
|
|
145
|
+
}
|
|
146
|
+
var maxWidthClasses = {
|
|
147
|
+
sm: "max-w-sm",
|
|
148
|
+
md: "max-w-md",
|
|
149
|
+
lg: "max-w-lg",
|
|
150
|
+
xl: "max-w-xl",
|
|
151
|
+
"2xl": "max-w-2xl",
|
|
152
|
+
"3xl": "max-w-3xl",
|
|
153
|
+
"4xl": "max-w-4xl",
|
|
154
|
+
"5xl": "max-w-5xl",
|
|
155
|
+
"6xl": "max-w-6xl",
|
|
156
|
+
"7xl": "max-w-7xl",
|
|
157
|
+
full: "max-w-full",
|
|
158
|
+
none: ""
|
|
159
|
+
};
|
|
160
|
+
var paddingXClasses = {
|
|
161
|
+
none: "px-0",
|
|
162
|
+
xs: "px-2",
|
|
163
|
+
sm: "px-4",
|
|
164
|
+
md: "px-6",
|
|
165
|
+
lg: "px-8",
|
|
166
|
+
xl: "px-10",
|
|
167
|
+
"2xl": "px-12"
|
|
168
|
+
};
|
|
169
|
+
var paddingYClasses = {
|
|
170
|
+
none: "py-0",
|
|
171
|
+
xs: "py-2",
|
|
172
|
+
sm: "py-4",
|
|
173
|
+
md: "py-6",
|
|
174
|
+
lg: "py-8",
|
|
175
|
+
xl: "py-10",
|
|
176
|
+
"2xl": "py-12"
|
|
177
|
+
};
|
|
178
|
+
var marginXClasses = {
|
|
179
|
+
none: "mx-0",
|
|
180
|
+
xs: "mx-2",
|
|
181
|
+
sm: "mx-4",
|
|
182
|
+
md: "mx-6",
|
|
183
|
+
lg: "mx-8",
|
|
184
|
+
xl: "mx-10",
|
|
185
|
+
"2xl": "mx-12",
|
|
186
|
+
auto: "mx-auto"
|
|
187
|
+
};
|
|
188
|
+
var marginYClasses = {
|
|
189
|
+
none: "my-0",
|
|
190
|
+
xs: "my-2",
|
|
191
|
+
sm: "my-4",
|
|
192
|
+
md: "my-6",
|
|
193
|
+
lg: "my-8",
|
|
194
|
+
xl: "my-10",
|
|
195
|
+
"2xl": "my-12"
|
|
196
|
+
};
|
|
197
|
+
var borderRadiusClasses = {
|
|
198
|
+
none: "rounded-none",
|
|
199
|
+
sm: "rounded-sm",
|
|
200
|
+
md: "rounded-md",
|
|
201
|
+
lg: "rounded-lg",
|
|
202
|
+
xl: "rounded-xl",
|
|
203
|
+
"2xl": "rounded-2xl",
|
|
204
|
+
full: "rounded-full"
|
|
205
|
+
};
|
|
206
|
+
var shadowClasses = {
|
|
207
|
+
none: "shadow-none",
|
|
208
|
+
sm: "shadow-sm",
|
|
209
|
+
md: "shadow-md",
|
|
210
|
+
lg: "shadow-lg",
|
|
211
|
+
xl: "shadow-xl",
|
|
212
|
+
"2xl": "shadow-2xl"
|
|
213
|
+
};
|
|
214
|
+
var alignItemsClasses = {
|
|
215
|
+
start: "items-start",
|
|
216
|
+
center: "items-center",
|
|
217
|
+
end: "items-end",
|
|
218
|
+
stretch: "items-stretch"
|
|
219
|
+
};
|
|
220
|
+
var justifyContentClasses = {
|
|
221
|
+
start: "justify-start",
|
|
222
|
+
center: "justify-center",
|
|
223
|
+
end: "justify-end",
|
|
224
|
+
between: "justify-between",
|
|
225
|
+
around: "justify-around",
|
|
226
|
+
evenly: "justify-evenly"
|
|
227
|
+
};
|
|
228
|
+
function SectionRenderer({
|
|
229
|
+
section,
|
|
230
|
+
componentRegistry,
|
|
231
|
+
mode = "published",
|
|
232
|
+
onSectionClick,
|
|
233
|
+
sharedSectionsData,
|
|
234
|
+
scope,
|
|
235
|
+
pageScope,
|
|
236
|
+
fromTemplate = false
|
|
237
|
+
}) {
|
|
238
|
+
if ("type" in section && section.type === "grid-container") {
|
|
239
|
+
const gridSection = section;
|
|
240
|
+
if (mode === "published" && gridSection.status === "draft") {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
const gridClasses = [
|
|
244
|
+
"grid",
|
|
245
|
+
"grid-cols-12",
|
|
246
|
+
getGapClasses(gridSection.gap),
|
|
247
|
+
gridSection.alignItems ? alignItemsClasses[gridSection.alignItems] : "",
|
|
248
|
+
gridSection.justifyContent ? justifyContentClasses[gridSection.justifyContent] : ""
|
|
249
|
+
].filter(Boolean).join(" ");
|
|
250
|
+
if (gridSection.fullWidthBackground && gridSection.background) {
|
|
251
|
+
const outerClasses = [
|
|
252
|
+
"w-full",
|
|
253
|
+
gridSection.background || "",
|
|
254
|
+
gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : "",
|
|
255
|
+
gridSection.marginY ? marginYClasses[gridSection.marginY] : "",
|
|
256
|
+
gridSection.border ? "border-y border-gray-200" : ""
|
|
257
|
+
].filter(Boolean).join(" ");
|
|
258
|
+
const innerClasses = [
|
|
259
|
+
gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : "",
|
|
260
|
+
gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : "",
|
|
261
|
+
gridSection.marginX ? marginXClasses[gridSection.marginX] : "mx-auto",
|
|
262
|
+
gridSection.borderRadius ? borderRadiusClasses[gridSection.borderRadius] : "",
|
|
263
|
+
gridSection.shadow ? shadowClasses[gridSection.shadow] : ""
|
|
264
|
+
].filter(Boolean).join(" ");
|
|
265
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: outerClasses, "data-grid-id": gridSection._key, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: innerClasses, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: gridClasses, children: gridSection.columns.map((column, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
className: getColumnClasses(
|
|
269
|
+
column.span,
|
|
270
|
+
column.hideOnMobile,
|
|
271
|
+
column.hideOnTablet,
|
|
272
|
+
column.hideOnDesktop
|
|
273
|
+
),
|
|
274
|
+
children: column.sections.map((nestedSection) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
275
|
+
SectionRenderer,
|
|
276
|
+
{
|
|
277
|
+
section: nestedSection,
|
|
278
|
+
componentRegistry,
|
|
279
|
+
mode,
|
|
280
|
+
onSectionClick,
|
|
281
|
+
fromTemplate,
|
|
282
|
+
sharedSectionsData,
|
|
283
|
+
scope,
|
|
284
|
+
pageScope
|
|
285
|
+
},
|
|
286
|
+
nestedSection._key
|
|
287
|
+
))
|
|
288
|
+
},
|
|
289
|
+
`${gridSection._key}-col-${columnIndex}`
|
|
290
|
+
)) }) }) });
|
|
291
|
+
}
|
|
292
|
+
const containerClasses = [
|
|
293
|
+
gridSection.maxWidth ? maxWidthClasses[gridSection.maxWidth] : "",
|
|
294
|
+
gridSection.paddingX ? paddingXClasses[gridSection.paddingX] : "",
|
|
295
|
+
gridSection.paddingY ? paddingYClasses[gridSection.paddingY] : "",
|
|
296
|
+
gridSection.marginX ? marginXClasses[gridSection.marginX] : "",
|
|
297
|
+
gridSection.marginY ? marginYClasses[gridSection.marginY] : "",
|
|
298
|
+
gridSection.background || "",
|
|
299
|
+
gridSection.border ? "border border-gray-200" : "",
|
|
300
|
+
gridSection.borderRadius ? borderRadiusClasses[gridSection.borderRadius] : "",
|
|
301
|
+
gridSection.shadow ? shadowClasses[gridSection.shadow] : ""
|
|
302
|
+
].filter(Boolean).join(" ");
|
|
303
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
304
|
+
"div",
|
|
305
|
+
{
|
|
306
|
+
className: containerClasses || "w-full",
|
|
307
|
+
"data-grid-id": gridSection._key,
|
|
308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: gridClasses, children: gridSection.columns.map((column, columnIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
className: getColumnClasses(
|
|
312
|
+
column.span,
|
|
313
|
+
column.hideOnMobile,
|
|
314
|
+
column.hideOnTablet,
|
|
315
|
+
column.hideOnDesktop
|
|
316
|
+
),
|
|
317
|
+
children: column.sections.map((nestedSection) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
318
|
+
SectionRenderer,
|
|
319
|
+
{
|
|
320
|
+
section: nestedSection,
|
|
321
|
+
componentRegistry,
|
|
322
|
+
mode,
|
|
323
|
+
onSectionClick,
|
|
324
|
+
fromTemplate,
|
|
325
|
+
sharedSectionsData,
|
|
326
|
+
scope,
|
|
327
|
+
pageScope
|
|
328
|
+
},
|
|
329
|
+
nestedSection._key
|
|
330
|
+
))
|
|
331
|
+
},
|
|
332
|
+
`${gridSection._key}-col-${columnIndex}`
|
|
333
|
+
)) })
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
if ("mode" in section && section.mode === "inline") {
|
|
338
|
+
const inlineSection = section;
|
|
339
|
+
if (mode === "published" && inlineSection.status === "draft") {
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
const Component = componentRegistry[inlineSection.sectionType];
|
|
343
|
+
if (!Component) {
|
|
344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "unknown-section p-8 bg-red-50 border border-red-200 rounded text-center", children: [
|
|
345
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-red-600 font-semibold", children: [
|
|
346
|
+
"Unknown section type: ",
|
|
347
|
+
inlineSection.sectionType
|
|
348
|
+
] }),
|
|
349
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-red-500 mt-2", children: "Component not found in registry. Make sure it's registered in your app." })
|
|
350
|
+
] });
|
|
351
|
+
}
|
|
352
|
+
const handleClick = onSectionClick ? (e) => {
|
|
353
|
+
e.preventDefault();
|
|
354
|
+
e.stopPropagation();
|
|
355
|
+
onSectionClick(inlineSection._key, inlineSection.sectionType);
|
|
356
|
+
} : void 0;
|
|
357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
358
|
+
"div",
|
|
359
|
+
{
|
|
360
|
+
"data-section-id": inlineSection._key,
|
|
361
|
+
"data-section-type": inlineSection.sectionType,
|
|
362
|
+
"data-from-template": fromTemplate || void 0,
|
|
363
|
+
onClick: handleClick,
|
|
364
|
+
className: onSectionClick ? "cursor-pointer hover:ring-2 hover:ring-primary" : void 0,
|
|
365
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
366
|
+
Component,
|
|
367
|
+
{
|
|
368
|
+
...inlineSection.props || {},
|
|
369
|
+
scope,
|
|
370
|
+
pageScope
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
if ("mode" in section && section.mode === "shared") {
|
|
377
|
+
const sharedSection = section;
|
|
378
|
+
const sharedSections = sharedSectionsData?.get(
|
|
379
|
+
sharedSection.sharedSectionId
|
|
380
|
+
);
|
|
381
|
+
if (!sharedSections) {
|
|
382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "shared-section-not-found p-8 border-2 border-dashed border-yellow-300 text-center text-yellow-700", children: [
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "font-semibold", children: "Shared Section Not Found" }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-sm mt-2", children: [
|
|
385
|
+
"ID: ",
|
|
386
|
+
sharedSection.sharedSectionId
|
|
387
|
+
] })
|
|
388
|
+
] });
|
|
389
|
+
}
|
|
390
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
391
|
+
"div",
|
|
392
|
+
{
|
|
393
|
+
"data-section-id": sharedSection._key,
|
|
394
|
+
"data-shared-section-id": sharedSection.sharedSectionId,
|
|
395
|
+
children: Array.isArray(sharedSections) && sharedSections.map((sharedSectionData, index) => {
|
|
396
|
+
let finalSection = sharedSectionData;
|
|
397
|
+
if (index === 0 && "mode" in sharedSectionData && sharedSectionData.mode === "inline" && sharedSection.overrides) {
|
|
398
|
+
finalSection = {
|
|
399
|
+
...sharedSectionData,
|
|
400
|
+
props: {
|
|
401
|
+
...sharedSectionData.props,
|
|
402
|
+
...sharedSection.overrides
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
407
|
+
SectionRenderer,
|
|
408
|
+
{
|
|
409
|
+
section: finalSection,
|
|
410
|
+
componentRegistry,
|
|
411
|
+
mode,
|
|
412
|
+
onSectionClick,
|
|
413
|
+
sharedSectionsData,
|
|
414
|
+
scope,
|
|
415
|
+
pageScope,
|
|
416
|
+
fromTemplate
|
|
417
|
+
},
|
|
418
|
+
`${sharedSection.sharedSectionId}-${index}`
|
|
419
|
+
);
|
|
420
|
+
})
|
|
421
|
+
}
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "invalid-section p-8 bg-yellow-50 border border-yellow-200 rounded text-center", children: [
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-yellow-700", children: "Invalid section format" }),
|
|
426
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("pre", { className: "text-xs mt-2 text-left", children: JSON.stringify(section, null, 2) })
|
|
427
|
+
] });
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/lib/visibility-evaluator.ts
|
|
431
|
+
function shouldShowNode(node, context) {
|
|
432
|
+
if (!node.visibility || node.visibility.length === 0) return true;
|
|
433
|
+
const rules = node.visibility.find((r) => r.locale === context.locale);
|
|
434
|
+
if (!rules) return true;
|
|
435
|
+
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;
|
|
436
|
+
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;
|
|
437
|
+
if (!hasIncludeRules && !hasExcludeRules) return true;
|
|
438
|
+
if (hasExcludeRules) {
|
|
439
|
+
if (context.pageId && rules.excludePages?.includes(context.pageId)) return false;
|
|
440
|
+
if (context.currentPath && rules.excludePatterns) {
|
|
441
|
+
if (matchesAnyPattern(context.currentPath, rules.excludePatterns)) return false;
|
|
442
|
+
}
|
|
443
|
+
if (context.docType && rules.excludeDocTypes?.includes(context.docType)) return false;
|
|
444
|
+
if (context.environment && rules.excludeEnvironments?.includes(context.environment)) return false;
|
|
445
|
+
if (context.userRoles && rules.excludeRoles) {
|
|
446
|
+
if (hasAnyRole(context.userRoles, rules.excludeRoles)) return false;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (hasIncludeRules) {
|
|
450
|
+
let matchedInclude = false;
|
|
451
|
+
if (context.pageId && rules.includePages?.includes(context.pageId)) matchedInclude = true;
|
|
452
|
+
if (!matchedInclude && context.currentPath && rules.includePatterns) {
|
|
453
|
+
if (matchesAnyPattern(context.currentPath, rules.includePatterns)) matchedInclude = true;
|
|
454
|
+
}
|
|
455
|
+
if (!matchedInclude && context.docType && rules.includeDocTypes?.includes(context.docType)) matchedInclude = true;
|
|
456
|
+
if (!matchedInclude && context.environment && rules.includeEnvironments?.includes(context.environment)) matchedInclude = true;
|
|
457
|
+
if (!matchedInclude && context.userRoles && rules.requireRoles) {
|
|
458
|
+
if (hasAnyRole(context.userRoles, rules.requireRoles)) matchedInclude = true;
|
|
459
|
+
}
|
|
460
|
+
if (!matchedInclude) return false;
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
function filterVisibleNodesRecursive(nodes, context) {
|
|
465
|
+
return nodes.filter((node) => shouldShowNode(node, context)).map((node) => {
|
|
466
|
+
if (node.type === "grid-container" && Array.isArray(node.columns)) {
|
|
467
|
+
return {
|
|
468
|
+
...node,
|
|
469
|
+
columns: node.columns.map((col) => ({
|
|
470
|
+
...col,
|
|
471
|
+
sections: filterVisibleNodesRecursive(col.sections, context)
|
|
472
|
+
}))
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
return node;
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function matchesAnyPattern(path, patterns) {
|
|
479
|
+
return patterns.some((pattern) => matchesPattern(path, pattern));
|
|
480
|
+
}
|
|
481
|
+
function matchesPattern(path, pattern) {
|
|
482
|
+
const normalizedPath = path.replace(/\/$/, "") || "/";
|
|
483
|
+
const normalizedPattern = pattern.replace(/\/$/, "") || "/";
|
|
484
|
+
if (normalizedPath === normalizedPattern) return true;
|
|
485
|
+
let regexPattern = normalizedPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "___DOUBLE_WILDCARD___").replace(/\*/g, "[^/]+").replace(/___DOUBLE_WILDCARD___/g, ".*");
|
|
486
|
+
regexPattern = `^${regexPattern}$`;
|
|
487
|
+
return new RegExp(regexPattern).test(normalizedPath);
|
|
488
|
+
}
|
|
489
|
+
function hasAnyRole(userRoles, requiredRoles) {
|
|
490
|
+
return requiredRoles.some((role) => userRoles.includes(role));
|
|
491
|
+
}
|
|
492
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
493
|
+
0 && (module.exports = {
|
|
494
|
+
SectionRenderer,
|
|
495
|
+
filterVisibleNodesRecursive,
|
|
496
|
+
shouldShowNode
|
|
497
|
+
});
|
|
498
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/SectionRenderer.tsx","../src/lib/visibility-evaluator.ts"],"sourcesContent":["// Rendering\nexport { SectionRenderer, type SectionRendererProps } from \"./components/SectionRenderer\";\n\n// Visibility\nexport {\n filterVisibleNodesRecursive,\n shouldShowNode,\n type VisibilityContext,\n type VisibilityRules,\n} from \"./lib/visibility-evaluator\";\n\n// Registry types\nexport {\n type BaseSectionProps,\n type ComponentRegistry,\n type SectionComponent,\n} from \"./types/component-registry\";\n\n// Scope and layout types, shared with @botlr/sdk\nexport type {\n BreadcrumbItem,\n GridColumn,\n GridContainerInstance,\n InlineSectionInstance,\n LayoutNode,\n PageScope,\n PublisherScope,\n SharedSectionInstance,\n} from \"@botlr/sdk\";\n","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":[]}
|