@nascentdigital/funnel-editor 4.4.21 → 4.5.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/dist/core/components/interaction/Animate.d.ts +2 -2
- package/dist/core/components/interaction/Animate.js +12 -10
- package/dist/core/components/interaction/QuickPicker.d.ts +27 -0
- package/dist/core/components/interaction/QuickPicker.js +108 -0
- package/dist/core/components/interaction/Tabs.d.ts +16 -0
- package/dist/core/components/interaction/Tabs.js +24 -0
- package/dist/core/components/interaction/index.d.ts +2 -0
- package/dist/core/components/interaction/index.js +2 -0
- package/dist/core/components/visuals/Icon.d.ts +1 -1
- package/dist/core/components/visuals/Icon.js +3 -0
- package/dist/core/components/visuals/SkeletonLayout.js +226 -33
- package/dist/core/domain/BlockConfiguration.d.ts +9 -1
- package/dist/core/domain/BlockConfiguration.js +50 -20
- package/dist/core/domain/Section.js +1 -1
- package/dist/page/components/BlockEditor.js +3 -3
- package/dist/page/components/{BlockConfig.d.ts → config/BlockConfig.d.ts} +1 -1
- package/dist/page/components/config/BlockConfig.js +43 -0
- package/dist/page/components/config/BlockConfigEditor.d.ts +13 -0
- package/dist/page/components/config/BlockConfigEditor.js +110 -0
- package/dist/page/components/config/BlockPreview.d.ts +10 -0
- package/dist/page/components/config/BlockPreview.js +456 -0
- package/dist/page/components/config/BlockView.d.ts +4 -0
- package/dist/page/components/config/BlockView.js +9 -0
- package/dist/page/components/config/LegacyBlockConfigEditor.d.ts +13 -0
- package/dist/page/components/{BlockConfig.js → config/LegacyBlockConfigEditor.js} +4 -29
- package/dist/page/components/config/ListLayoutPicker.d.ts +6 -0
- package/dist/page/components/config/ListLayoutPicker.js +13 -0
- package/dist/page/components/config/ListPanelEditor.d.ts +6 -0
- package/dist/page/components/config/ListPanelEditor.js +13 -0
- package/dist/page/components/config/MessagePanelEditor.d.ts +6 -0
- package/dist/page/components/config/MessagePanelEditor.js +13 -0
- package/dist/page/components/config/VisualPanelEditor.d.ts +6 -0
- package/dist/page/components/config/VisualPanelEditor.js +13 -0
- package/dist/page/components/config/index.d.ts +1 -0
- package/dist/page/components/config/index.js +17 -0
- package/dist/page/hooks/PageController.js +1 -1
- package/dist/styles/index.css +108 -3
- package/package.json +2 -2
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.BlockPreview = BlockPreview;
|
|
18
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
20
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
21
|
+
const react_1 = require("react");
|
|
22
|
+
const core_1 = require("../../../core");
|
|
23
|
+
// component
|
|
24
|
+
function BlockPreview({ className, variant, configuration }) {
|
|
25
|
+
// determine active panels
|
|
26
|
+
const { layout } = configuration;
|
|
27
|
+
// sync configuration
|
|
28
|
+
(0, core_1.useBlockConfiguration)(configuration);
|
|
29
|
+
// helpers
|
|
30
|
+
const onPanelClick = (panel) => {
|
|
31
|
+
console.debug('[BlockPreview] opening panel editor', panel);
|
|
32
|
+
};
|
|
33
|
+
// render
|
|
34
|
+
const tight = variant === 'mobile'
|
|
35
|
+
? layout === null || layout === void 0 ? void 0 : layout.tight.mobile
|
|
36
|
+
: layout === null || layout === void 0 ? void 0 : layout.tight.desktop;
|
|
37
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'w-full flex justify-center'), children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('bg-surface2 rounded-xs', {
|
|
38
|
+
'min-h-[100px]': !layout,
|
|
39
|
+
'w-[120px]': variant === 'desktop',
|
|
40
|
+
'w-[64px]': variant === 'mobile',
|
|
41
|
+
'pb-l4': tight === 'above',
|
|
42
|
+
'pt-l4': tight === 'below',
|
|
43
|
+
'py-l4': tight === 'none'
|
|
44
|
+
}), children: renderLayout({ variant, layout, onPanelClick }) }) }));
|
|
45
|
+
}
|
|
46
|
+
// helpers
|
|
47
|
+
var Skeleton;
|
|
48
|
+
(function (Skeleton) {
|
|
49
|
+
function HeadlinePart({ className, size }) {
|
|
50
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'bg-ix-primary rounded-xxs overflow-hidden', {
|
|
51
|
+
'h-6 ': size === 'sm',
|
|
52
|
+
'h-8': size === 'md'
|
|
53
|
+
}) }));
|
|
54
|
+
}
|
|
55
|
+
Skeleton.HeadlinePart = HeadlinePart;
|
|
56
|
+
function CaptionPart({ className, size }) {
|
|
57
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'h-4 bg-draft/tint3 rounded-px overflow-hidden', {
|
|
58
|
+
'': size === 'sm'
|
|
59
|
+
}) }));
|
|
60
|
+
}
|
|
61
|
+
Skeleton.CaptionPart = CaptionPart;
|
|
62
|
+
function MediaPart({ className, aspect }) {
|
|
63
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'flex justify-center items-center bg-draft/tint3 rounded-xxs overflow-hidden', {
|
|
64
|
+
'aspect-square': aspect === 'square' || aspect === 'auto',
|
|
65
|
+
'aspect-phone': aspect === 'phone',
|
|
66
|
+
'aspect-tv': aspect === 'tv',
|
|
67
|
+
'aspect-widescreen': aspect === 'widescreen',
|
|
68
|
+
'aspect-cinema': aspect === 'cinema'
|
|
69
|
+
}), children: (0, jsx_runtime_1.jsx)(core_1.Icon, { className: "text-content-tertiary", variant: "Image", size: {
|
|
70
|
+
size: 20,
|
|
71
|
+
strokeWidth: 1.5,
|
|
72
|
+
absoluteStrokeWidth: false
|
|
73
|
+
} }) }));
|
|
74
|
+
}
|
|
75
|
+
Skeleton.MediaPart = MediaPart;
|
|
76
|
+
function IconPart({ className, size }) {
|
|
77
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'bg-draft/tint3 rounded-full overflow-hidden', {
|
|
78
|
+
'w-10 h-10': size === 'sm',
|
|
79
|
+
'w-14 h-14': size === 'md'
|
|
80
|
+
}) }));
|
|
81
|
+
}
|
|
82
|
+
Skeleton.IconPart = IconPart;
|
|
83
|
+
function LogoPart({ className, size }) {
|
|
84
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, 'bg-draft/tint3 rounded-px overflow-hidden', {
|
|
85
|
+
'w-14 h-6': size === 'sm',
|
|
86
|
+
'w-20 h-9': size === 'md'
|
|
87
|
+
}) }));
|
|
88
|
+
}
|
|
89
|
+
Skeleton.LogoPart = LogoPart;
|
|
90
|
+
})(Skeleton || (Skeleton = {}));
|
|
91
|
+
function renderLayout({ className, variant, layout, onPanelClick }) {
|
|
92
|
+
// TODO: render empty state if there's no layout
|
|
93
|
+
if (!layout) {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
// render root layout
|
|
97
|
+
const { type, items } = layout.root;
|
|
98
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: getContainerClasses({ className, variant, siblingCount: 1, item: layout.root }), children: items.map((item, parentOffset) => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderItem({
|
|
99
|
+
className: (0, classnames_1.default)({
|
|
100
|
+
'flex-1': type === 'row' && variant !== 'mobile'
|
|
101
|
+
}),
|
|
102
|
+
variant,
|
|
103
|
+
parent: type,
|
|
104
|
+
parentNested: false,
|
|
105
|
+
siblingCount: items.length,
|
|
106
|
+
item,
|
|
107
|
+
itemPosition: new ItemPosition({
|
|
108
|
+
parent: type,
|
|
109
|
+
parentOffset,
|
|
110
|
+
parentSize: items.length
|
|
111
|
+
}),
|
|
112
|
+
onPanelClick
|
|
113
|
+
}) }, `${item.type}.${parentOffset}`)) }));
|
|
114
|
+
}
|
|
115
|
+
function renderItem({ className, parent, parentNested, siblingCount, variant, item, itemPosition, onPanelClick }) {
|
|
116
|
+
// render item
|
|
117
|
+
const { type: itemType } = item;
|
|
118
|
+
switch (itemType) {
|
|
119
|
+
case 'row':
|
|
120
|
+
case 'column':
|
|
121
|
+
case 'stack':
|
|
122
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: getContainerClasses({ className, parent, siblingCount, variant, item }), children: item.items.map((item, parentOffset, items) => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderItem({
|
|
123
|
+
className: (0, classnames_1.default)({
|
|
124
|
+
'flex-1': itemType === 'row'
|
|
125
|
+
}),
|
|
126
|
+
variant,
|
|
127
|
+
parent: itemType,
|
|
128
|
+
parentNested: true,
|
|
129
|
+
siblingCount: items.length,
|
|
130
|
+
item: item,
|
|
131
|
+
itemPosition: new ItemPosition({
|
|
132
|
+
parent: itemType,
|
|
133
|
+
parentOffset,
|
|
134
|
+
parentSize: items.length
|
|
135
|
+
}),
|
|
136
|
+
onPanelClick
|
|
137
|
+
}) }, `${item.type}.${parentOffset}`)) }));
|
|
138
|
+
case 'message':
|
|
139
|
+
return renderMessage({ className, parent, parentNested, siblingCount, variant, item, itemPosition, onPanelClick });
|
|
140
|
+
case 'visual':
|
|
141
|
+
return renderVisual({ className, parent, parentNested, siblingCount, variant, item, itemPosition, onPanelClick });
|
|
142
|
+
case 'list':
|
|
143
|
+
return renderList({ className, parent, parentNested, siblingCount, variant, item, itemPosition, onPanelClick });
|
|
144
|
+
default:
|
|
145
|
+
console.error('[SkeletonLayout] no support for BlockLayout item', item);
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function getContainerClasses({ className, variant, parent, item }) {
|
|
150
|
+
const { type, alignY } = item;
|
|
151
|
+
// row style
|
|
152
|
+
if (type === 'row' && variant !== 'mobile') {
|
|
153
|
+
return (0, classnames_1.default)(className, 'grid gap-l3 px-l4', {
|
|
154
|
+
'items-start': alignY === 'start',
|
|
155
|
+
'items-center': alignY === 'center',
|
|
156
|
+
'items-end': alignY === 'end',
|
|
157
|
+
'grid-cols-[1fr,1fr]': item.ratio.desktop === '1/1',
|
|
158
|
+
'grid-cols-[1fr,2fr]': item.ratio.desktop === '1/2',
|
|
159
|
+
'grid-cols-[1fr,3fr]': item.ratio.desktop === '1/3',
|
|
160
|
+
'grid-cols-[2fr,1fr]': item.ratio.desktop === '2/1',
|
|
161
|
+
'grid-cols-[2fr,3fr]': item.ratio.desktop === '2/3',
|
|
162
|
+
'grid-cols-[3fr,1fr]': item.ratio.desktop === '3/1',
|
|
163
|
+
'grid-cols-[3fr,2fr]': item.ratio.desktop === '3/2'
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
// or stack
|
|
167
|
+
else if (type === 'stack') {
|
|
168
|
+
return (0, classnames_1.default)(className, 'stacked-stretch');
|
|
169
|
+
}
|
|
170
|
+
// or column
|
|
171
|
+
else {
|
|
172
|
+
return (0, classnames_1.default)(className, 'flex flex-col gap-l4');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function renderMessage(args) {
|
|
176
|
+
// resolve props
|
|
177
|
+
const { variant, item: { textAlign } } = args;
|
|
178
|
+
const messageClasses = variant === 'mobile'
|
|
179
|
+
? (0, classnames_1.default)({
|
|
180
|
+
'items-start': textAlign.mobile === 'left',
|
|
181
|
+
'items-center': textAlign.mobile === 'center',
|
|
182
|
+
'items-end': textAlign.mobile === 'right'
|
|
183
|
+
})
|
|
184
|
+
: (0, classnames_1.default)({
|
|
185
|
+
'items-start': textAlign.desktop === 'left',
|
|
186
|
+
'items-center': textAlign.desktop === 'center',
|
|
187
|
+
'items-end': textAlign.desktop === 'right'
|
|
188
|
+
});
|
|
189
|
+
// render
|
|
190
|
+
return ((0, jsx_runtime_1.jsxs)(EditablePanel, Object.assign({}, args, { panelClassName: (0, classnames_1.default)(messageClasses, getPanelClasses(Object.assign(Object.assign({}, args), { className: 'flex flex-col' }))), children: [(0, jsx_runtime_1.jsx)(Skeleton.HeadlinePart, { className: "w-full mb-l2", size: "md" }), (0, jsx_runtime_1.jsx)(Skeleton.CaptionPart, { className: "w-full mb-px", size: "md" }), (0, jsx_runtime_1.jsx)(Skeleton.CaptionPart, { className: "w-full mb-px", size: "md" }), (0, jsx_runtime_1.jsx)(Skeleton.CaptionPart, { className: "w-20", size: "md" })] })));
|
|
191
|
+
}
|
|
192
|
+
function renderVisual(args) {
|
|
193
|
+
// resolve props
|
|
194
|
+
const { variant, item: { aspectRatio }, parent } = args;
|
|
195
|
+
const aspect = variant === 'mobile' ? aspectRatio.mobile : aspectRatio.desktop;
|
|
196
|
+
// render
|
|
197
|
+
return ((0, jsx_runtime_1.jsx)(EditablePanel, Object.assign({}, args, { panelClassName: (0, classnames_1.default)(getPanelClasses(Object.assign(Object.assign({}, args), { className: '' }))), children: (0, jsx_runtime_1.jsx)(Skeleton.MediaPart, { className: "w-full", aspect: aspect }) })));
|
|
198
|
+
}
|
|
199
|
+
function renderList(args) {
|
|
200
|
+
// resolve props
|
|
201
|
+
const { variant, parent, parentNested, item: { layout: layoutRaw, itemType, itemCount: itemCountRaw } } = args;
|
|
202
|
+
const layout = variant === 'mobile'
|
|
203
|
+
? layoutRaw.mobile
|
|
204
|
+
: layoutRaw.desktop;
|
|
205
|
+
// render a grid
|
|
206
|
+
if (layout === 'grid') {
|
|
207
|
+
return renderGrid(args);
|
|
208
|
+
}
|
|
209
|
+
// or render row/column
|
|
210
|
+
const itemCount = variant === 'mobile'
|
|
211
|
+
? itemCountRaw.mobile
|
|
212
|
+
: itemCountRaw.desktop;
|
|
213
|
+
return ((0, jsx_runtime_1.jsx)(EditablePanel, Object.assign({}, args, { panelClassName: getListPanelClasses(args), children: funnel_core_1.ArrayUtils.series(itemCount, 1).map(row => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderListItem({ variant, parent, parentNested, layout, itemType, index: row, count: itemCount }) }, `list.${row}`)) })));
|
|
214
|
+
}
|
|
215
|
+
function getListPanelClasses(args) {
|
|
216
|
+
// resolve props
|
|
217
|
+
const { variant, item: { layout: layoutRaw } } = args;
|
|
218
|
+
const layout = variant === 'mobile'
|
|
219
|
+
? layoutRaw.mobile
|
|
220
|
+
: layoutRaw.desktop;
|
|
221
|
+
// determine list classes
|
|
222
|
+
let listClasses = '';
|
|
223
|
+
switch (layout) {
|
|
224
|
+
case 'row':
|
|
225
|
+
listClasses = 'grid grid-rows-1 auto-cols-auto grid-flow-col gap-l2';
|
|
226
|
+
break;
|
|
227
|
+
case 'column':
|
|
228
|
+
listClasses = 'flex flex-col gap-l2';
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
// return completed classes
|
|
232
|
+
return getPanelClasses(Object.assign(Object.assign({}, args), { className: listClasses }));
|
|
233
|
+
}
|
|
234
|
+
function renderListItem({ className, variant, parent, parentNested, layout, itemType, index, count }) {
|
|
235
|
+
let itemClassName = '';
|
|
236
|
+
switch (itemType) {
|
|
237
|
+
case 'message':
|
|
238
|
+
case 'message+visual':
|
|
239
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'flex flex-row p-3 bg-background rounded-xxs'), children: [itemType === 'message+visual' &&
|
|
240
|
+
(0, jsx_runtime_1.jsx)("div", { className: "flex justify-center items-center", children: (0, jsx_runtime_1.jsx)("div", { className: "bg-content-tertiary rounded-full w-4 h-4" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col", children: [(0, jsx_runtime_1.jsx)(Skeleton.HeadlinePart, { className: "w-11/12 mb-l1", size: "sm" }), (0, jsx_runtime_1.jsx)(Skeleton.CaptionPart, { className: "w-full mb-px", size: "sm" }), (0, jsx_runtime_1.jsx)(Skeleton.CaptionPart, { className: "w-8/12", size: "sm" })] })] }));
|
|
241
|
+
case 'visual': {
|
|
242
|
+
// determine aspect
|
|
243
|
+
let aspect;
|
|
244
|
+
switch (layout) {
|
|
245
|
+
case 'column':
|
|
246
|
+
aspect = parent === 'row' || parentNested
|
|
247
|
+
? 'widescreen'
|
|
248
|
+
: variant === 'mobile'
|
|
249
|
+
? 'widescreen'
|
|
250
|
+
: 'cinema';
|
|
251
|
+
break;
|
|
252
|
+
case 'row':
|
|
253
|
+
aspect = parent === 'row' || parentNested
|
|
254
|
+
? 'square'
|
|
255
|
+
: 'widescreen';
|
|
256
|
+
break;
|
|
257
|
+
case 'grid': {
|
|
258
|
+
// aspect for mobile/nested
|
|
259
|
+
if (variant === 'mobile' || parent === 'row' || parentNested) {
|
|
260
|
+
itemClassName = 'w-full';
|
|
261
|
+
aspect = count === 1
|
|
262
|
+
? 'square'
|
|
263
|
+
: count <= 3
|
|
264
|
+
? 'tv'
|
|
265
|
+
: 'widescreen';
|
|
266
|
+
}
|
|
267
|
+
// adjust aspect based on layout (if it's a grid)
|
|
268
|
+
else if (layout === 'grid') {
|
|
269
|
+
// set base class
|
|
270
|
+
itemClassName = 'min-w-[50px]';
|
|
271
|
+
// override base + pick aspect
|
|
272
|
+
switch (count) {
|
|
273
|
+
case 1:
|
|
274
|
+
aspect = 'widescreen';
|
|
275
|
+
break;
|
|
276
|
+
case 2:
|
|
277
|
+
aspect = 'widescreen';
|
|
278
|
+
break;
|
|
279
|
+
case 3:
|
|
280
|
+
itemClassName = index === 1
|
|
281
|
+
? 'min-w-full'
|
|
282
|
+
: 'min-w-[50px]';
|
|
283
|
+
aspect = index === 1
|
|
284
|
+
? 'cinema'
|
|
285
|
+
: 'tv';
|
|
286
|
+
break;
|
|
287
|
+
case 4:
|
|
288
|
+
aspect = 'tv';
|
|
289
|
+
break;
|
|
290
|
+
case 5:
|
|
291
|
+
itemClassName = index === 3
|
|
292
|
+
? 'min-w-full'
|
|
293
|
+
: 'min-w-[50px]';
|
|
294
|
+
aspect = index === 3
|
|
295
|
+
? 'cinema'
|
|
296
|
+
: 'tv';
|
|
297
|
+
break;
|
|
298
|
+
default:
|
|
299
|
+
aspect = 'widescreen';
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// otherwise standard
|
|
304
|
+
else {
|
|
305
|
+
aspect = 'widescreen';
|
|
306
|
+
}
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// create visual
|
|
311
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className, itemClassName), children: (0, jsx_runtime_1.jsx)(Skeleton.MediaPart, { aspect: aspect }) }));
|
|
312
|
+
}
|
|
313
|
+
case 'icon':
|
|
314
|
+
return ((0, jsx_runtime_1.jsx)(Skeleton.IconPart, { className: (0, classnames_1.default)(className, itemClassName), size: variant === 'mobile' ? 'md' : 'sm' }));
|
|
315
|
+
case 'logo':
|
|
316
|
+
return ((0, jsx_runtime_1.jsx)(Skeleton.LogoPart, { className: (0, classnames_1.default)(className, itemClassName), size: variant === 'mobile' ? 'md' : 'sm' }));
|
|
317
|
+
default:
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function renderGrid(args) {
|
|
322
|
+
// determine props
|
|
323
|
+
const { variant, parent, parentNested, item: { itemType, itemCount: itemCountRaw } } = args;
|
|
324
|
+
const itemCount = variant === 'mobile'
|
|
325
|
+
? itemCountRaw.mobile
|
|
326
|
+
: itemCountRaw.desktop;
|
|
327
|
+
const { panelClassName, panelItemClassName } = getGridPanelClasses(args);
|
|
328
|
+
// render grid (really a flexbox layout with controlled item widths)
|
|
329
|
+
return ((0, jsx_runtime_1.jsx)(EditablePanel, Object.assign({}, args, { panelClassName: panelClassName, children: funnel_core_1.ArrayUtils.series(itemCount, 1).map(row => (0, jsx_runtime_1.jsx)(react_1.Fragment, { children: renderListItem({
|
|
330
|
+
className: panelItemClassName,
|
|
331
|
+
variant,
|
|
332
|
+
parent,
|
|
333
|
+
parentNested,
|
|
334
|
+
layout: 'grid',
|
|
335
|
+
itemType, index: row,
|
|
336
|
+
count: itemCount
|
|
337
|
+
}) }, `list.${row}`)) })));
|
|
338
|
+
}
|
|
339
|
+
function getGridPanelClasses(args) {
|
|
340
|
+
// resolve props
|
|
341
|
+
const { variant, parent, parentNested, item: { itemType, itemCount: itemCountRaw, itemAlign: itemAlignRaw } } = args;
|
|
342
|
+
const itemAlign = variant === 'mobile'
|
|
343
|
+
? itemAlignRaw.mobile
|
|
344
|
+
: itemAlignRaw.desktop;
|
|
345
|
+
// determine list classes
|
|
346
|
+
const panelClasses = (0, classnames_1.default)('flex flex-wrap gap-l2', {
|
|
347
|
+
'justify-center': itemAlign === 'center',
|
|
348
|
+
'justify-end': itemAlign === 'end'
|
|
349
|
+
});
|
|
350
|
+
let panelItemClasses = '';
|
|
351
|
+
switch (itemType) {
|
|
352
|
+
case 'message':
|
|
353
|
+
case 'message+visual':
|
|
354
|
+
panelItemClasses = (0, classnames_1.default)({
|
|
355
|
+
'w-full': variant === 'mobile' || (variant === 'desktop' && (parent === 'row' || parentNested)),
|
|
356
|
+
'w-[50px]': variant === 'desktop' && parent !== 'row' && !parentNested
|
|
357
|
+
});
|
|
358
|
+
break;
|
|
359
|
+
case 'visual':
|
|
360
|
+
panelItemClasses = (0, classnames_1.default)({
|
|
361
|
+
'': variant === 'mobile' || (variant === 'desktop' && (parent === 'row' || parentNested)),
|
|
362
|
+
'flex-1': variant === 'desktop' && parent !== 'row' && !parentNested
|
|
363
|
+
});
|
|
364
|
+
break;
|
|
365
|
+
case 'icon':
|
|
366
|
+
panelItemClasses = (0, classnames_1.default)({});
|
|
367
|
+
break;
|
|
368
|
+
case 'logo':
|
|
369
|
+
panelItemClasses = (0, classnames_1.default)({
|
|
370
|
+
'': variant === 'desktop',
|
|
371
|
+
'': variant === 'mobile'
|
|
372
|
+
});
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
// return completed classes
|
|
376
|
+
return {
|
|
377
|
+
panelClassName: getPanelClasses(Object.assign(Object.assign({}, args), { className: panelClasses })),
|
|
378
|
+
panelItemClassName: panelItemClasses
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function getPanelWrapClasses({ className, variant, parent, parentNested, item: { mobileOrder, alignY, fullBleed }, itemPosition }) {
|
|
382
|
+
return variant === 'mobile'
|
|
383
|
+
? (0, classnames_1.default)(className, 'relative w-full flex flex-col', {
|
|
384
|
+
'justify-start': alignY === 'start',
|
|
385
|
+
'justify-center': alignY === 'center',
|
|
386
|
+
'justify-end': alignY === 'end',
|
|
387
|
+
'order-first': mobileOrder === 'first',
|
|
388
|
+
'order-last': mobileOrder === 'last',
|
|
389
|
+
'px-l4': !fullBleed.mobile
|
|
390
|
+
})
|
|
391
|
+
: (0, classnames_1.default)(className, 'relative grid grid-cols-12', {
|
|
392
|
+
'items-start': alignY === 'start',
|
|
393
|
+
'items-center': alignY === 'center',
|
|
394
|
+
'items-end': alignY === 'end',
|
|
395
|
+
'px-l4': parent !== 'row' && !fullBleed.desktop && !parentNested,
|
|
396
|
+
'-ml-l4': itemPosition.left && fullBleed.desktop,
|
|
397
|
+
'-mr-l4': itemPosition.right && fullBleed.desktop
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function getPanelClasses({ className, variant, parent, parentNested, item: { alignX, size } }) {
|
|
401
|
+
// force full width for mobile
|
|
402
|
+
if (variant === 'mobile') {
|
|
403
|
+
return (0, classnames_1.default)(className);
|
|
404
|
+
}
|
|
405
|
+
// or size for desktop
|
|
406
|
+
switch (parent === 'row' || parentNested ? 'full' : size) {
|
|
407
|
+
case 'xs':
|
|
408
|
+
return (0, classnames_1.default)(className, 'col-span-4', {
|
|
409
|
+
'col-start-1': alignX === 'start',
|
|
410
|
+
'col-start-5': alignX === 'center',
|
|
411
|
+
'col-end-13': alignX === 'end'
|
|
412
|
+
});
|
|
413
|
+
case 'sm':
|
|
414
|
+
return (0, classnames_1.default)(className, 'col-span-6', {
|
|
415
|
+
'col-start-1': alignX === 'start',
|
|
416
|
+
'col-start-4': alignX === 'center',
|
|
417
|
+
'col-end-13': alignX === 'end'
|
|
418
|
+
});
|
|
419
|
+
case 'md':
|
|
420
|
+
return (0, classnames_1.default)(className, 'col-span-8', {
|
|
421
|
+
'col-start-1': alignX === 'start',
|
|
422
|
+
'col-start-3': alignX === 'center',
|
|
423
|
+
'col-end-13': alignX === 'end'
|
|
424
|
+
});
|
|
425
|
+
case 'lg':
|
|
426
|
+
return (0, classnames_1.default)(className, 'col-span-10', {
|
|
427
|
+
'col-start-1': alignX === 'start',
|
|
428
|
+
'col-start-2': alignX === 'center',
|
|
429
|
+
'col-end-13': alignX === 'end'
|
|
430
|
+
});
|
|
431
|
+
case 'full':
|
|
432
|
+
return (0, classnames_1.default)(className, 'col-span-full');
|
|
433
|
+
default:
|
|
434
|
+
return className;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function EditablePanel(_a) {
|
|
438
|
+
var { panelClassName, children } = _a, args = __rest(_a, ["panelClassName", "children"]);
|
|
439
|
+
// render
|
|
440
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: getPanelWrapClasses(args), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, 'relative'), children: [children, (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('group absolute inset-0 z-overlay cursor-pointer interpolate', 'bg-surface1 border border-solid, border-ix-primary rounded-xxs overflow-hidden', 'opacity-none hover:opacity-full'), onClick: () => args.onPanelClick(args.item), children: (0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('w-full h-full interpolate', 'flex flex-col justify-center items-center gap-l6', 'text-ix-primary group-hover:bg-ix-primary/tint1 group-active:bg-ix-primary/tint3'), children: (0, jsx_runtime_1.jsx)("span", { className: "label-xs label-strong", children: "Edit" }) }) })] }) }));
|
|
441
|
+
}
|
|
442
|
+
// TODO: scrap this
|
|
443
|
+
class ItemPosition {
|
|
444
|
+
constructor(args) {
|
|
445
|
+
// initialize instance variables
|
|
446
|
+
this.parent = args.parent;
|
|
447
|
+
this.parentOffset = args.parentOffset;
|
|
448
|
+
this.parentSize = args.parentSize;
|
|
449
|
+
}
|
|
450
|
+
get left() {
|
|
451
|
+
return this.parent === 'row' && this.parentOffset === 0;
|
|
452
|
+
}
|
|
453
|
+
get right() {
|
|
454
|
+
return this.parent === 'row' && this.parentOffset === 1;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlockView = void 0;
|
|
4
|
+
// extension
|
|
5
|
+
var BlockView;
|
|
6
|
+
(function (BlockView) {
|
|
7
|
+
// values
|
|
8
|
+
BlockView.values = ['desktop', 'mobile'];
|
|
9
|
+
})(BlockView || (exports.BlockView = BlockView = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Rect } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { Block, SectionBlock } from '../../../core';
|
|
3
|
+
export declare const LegacyBlockConfigEditor: import("react").ForwardRefExoticComponent<import("react").RefAttributes<LegacyBlockConfigEditor.Ref>>;
|
|
4
|
+
export declare namespace LegacyBlockConfigEditor {
|
|
5
|
+
type Props = {};
|
|
6
|
+
interface Ref {
|
|
7
|
+
edit(options: Options): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
type Options = {
|
|
10
|
+
block: Block | SectionBlock;
|
|
11
|
+
anchor: HTMLElement | Rect;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
@@ -1,40 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.LegacyBlockConfigEditor = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
6
6
|
const client_1 = require("@nascentdigital/funnel-ui/client");
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const rxjs_1 = require("rxjs");
|
|
9
|
-
const core_1 = require("
|
|
10
|
-
const hooks_1 = require("
|
|
11
|
-
// component
|
|
12
|
-
function BlockConfig({ className, block: blockOrSectionBlock }) {
|
|
13
|
-
// bind ref
|
|
14
|
-
const editorRef = (0, react_1.useRef)(null);
|
|
15
|
-
// skip if there's no config
|
|
16
|
-
const block = blockOrSectionBlock instanceof core_1.SectionBlock
|
|
17
|
-
? blockOrSectionBlock.block
|
|
18
|
-
: blockOrSectionBlock;
|
|
19
|
-
const { config } = block;
|
|
20
|
-
if (config.length === 0) {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
// helpers
|
|
24
|
-
const onEdit = async (event) => {
|
|
25
|
-
var _a;
|
|
26
|
-
// edit configuration
|
|
27
|
-
await ((_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.edit({
|
|
28
|
-
block: blockOrSectionBlock,
|
|
29
|
-
anchor: event.currentTarget
|
|
30
|
-
}));
|
|
31
|
-
};
|
|
32
|
-
// render
|
|
33
|
-
const valid = config.every(field => field.valid);
|
|
34
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.StatusChip, { className: className, variant: valid ? 'success' : 'error', onClick: onEdit, children: "Configure" }), (0, jsx_runtime_1.jsx)(BlockConfigEditor, { ref: editorRef })] }));
|
|
35
|
-
}
|
|
9
|
+
const core_1 = require("../../../core");
|
|
10
|
+
const hooks_1 = require("../../hooks");
|
|
36
11
|
// editor
|
|
37
|
-
|
|
12
|
+
exports.LegacyBlockConfigEditor = (0, react_1.forwardRef)(function LegacyBlockConfigEditor(_, ref) {
|
|
38
13
|
// bind state + hooks
|
|
39
14
|
const [deferral, setDeferral] = (0, react_1.useState)(undefined);
|
|
40
15
|
const [configuration, setConfiguration] = (0, react_1.useState)();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ListLayoutPicker = ListLayoutPicker;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
// component
|
|
10
|
+
function ListLayoutPicker({ className }) {
|
|
11
|
+
// render
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className), children: "ListLayoutPicker" }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ListPanelEditor = ListPanelEditor;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
// component
|
|
10
|
+
function ListPanelEditor({ className }) {
|
|
11
|
+
// render
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className), children: "ListPanelEditor" }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MessagePanelEditor = MessagePanelEditor;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
// component
|
|
10
|
+
function MessagePanelEditor({ className }) {
|
|
11
|
+
// render
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className), children: "MessagePanelEditor" }));
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.VisualPanelEditor = VisualPanelEditor;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
// component
|
|
10
|
+
function VisualPanelEditor({ className }) {
|
|
11
|
+
// render
|
|
12
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(className), children: "MessagePanelEditor" }));
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BlockConfig';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./BlockConfig"), exports);
|
|
@@ -146,7 +146,7 @@ class PageController {
|
|
|
146
146
|
});
|
|
147
147
|
// save page immediately if modified (this is a re-entrant call, so we can't await it - trust me)
|
|
148
148
|
if (page.modified) {
|
|
149
|
-
console.
|
|
149
|
+
console.debug('[PageController/setPage] save triggered by page modification', page);
|
|
150
150
|
this.save().catch(console.error);
|
|
151
151
|
}
|
|
152
152
|
}
|