@nascentdigital/funnel-editor 4.5.6 → 4.6.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.
- package/dist/collection/hooks/CollectionController.d.ts +1 -1
- package/dist/core/components/ColorModeToggle.js +6 -4
- package/dist/core/components/Header.js +3 -2
- package/dist/core/components/UserEditor.d.ts +2 -2
- package/dist/core/components/feedback/Badge.d.ts +2 -1
- package/dist/core/components/feedback/Badge.js +4 -3
- package/dist/core/components/fields/DynamicPagesEditor.js +7 -6
- package/dist/core/components/fields/EmptyFieldCard.js +4 -4
- package/dist/core/components/fields/FieldCardLayout.js +5 -5
- package/dist/core/components/fields/FieldHeader.js +3 -2
- package/dist/core/components/fields/FieldsPanel.js +4 -4
- package/dist/core/components/fields/FormEditor.js +5 -4
- package/dist/core/components/fields/asset/AssetEditor.d.ts +3 -2
- package/dist/core/components/fields/asset/AssetEditor.js +1 -1
- package/dist/core/components/fields/asset/AssetUploader.d.ts +3 -2
- package/dist/core/components/fields/asset/AssetUploader.js +1 -1
- package/dist/core/components/fields/collection/CollectionCard.js +1 -11
- package/dist/core/components/fields/collection/CollectionPicker.js +3 -2
- package/dist/core/components/fields/collection/previews/index.d.ts +0 -1
- package/dist/core/components/fields/collection/previews/index.js +0 -1
- package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
- package/dist/core/components/fields/factories/AssetFactory.d.ts +1 -1
- package/dist/core/components/fields/factories/CollectionFactory.d.ts +1 -1
- package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +2 -2
- package/dist/core/components/fields/factories/FieldValueFactory.d.ts +1 -1
- package/dist/core/components/fields/factories/FieldValueFactory.js +1 -1
- package/dist/core/components/fields/factories/LinkFactory.d.ts +2 -2
- package/dist/core/components/fields/factories/TextFactory.d.ts +2 -2
- package/dist/core/components/fields/form/FormFieldEditor.d.ts +3 -2
- package/dist/core/components/fields/index.d.ts +1 -0
- package/dist/core/components/fields/index.js +1 -0
- package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
- package/dist/core/components/fields/link/LinkEditor.js +4 -0
- package/dist/core/components/fields/list/CreateFieldButton.d.ts +1 -1
- package/dist/core/components/fields/list/CreateFieldButton.js +4 -5
- package/dist/core/components/fields/list/CreateFieldCard.js +4 -4
- package/dist/core/components/fields/page/PagePicker.js +4 -2
- package/dist/core/components/fields/richtext/FloatingToolbarPlugin.js +3 -2
- package/dist/core/components/fields/richtext/LinkEditor.js +17 -4
- package/dist/core/components/fields/richtext/LinkPopup.js +11 -7
- package/dist/core/components/interaction/AvatarButton.d.ts +2 -1
- package/dist/core/components/interaction/AvatarButton.js +3 -2
- package/dist/core/components/interaction/Button.d.ts +2 -0
- package/dist/core/components/interaction/Button.js +3 -2
- package/dist/core/components/interaction/Combobox.js +2 -2
- package/dist/core/components/interaction/IconButton.d.ts +2 -0
- package/dist/core/components/interaction/IconButton.js +3 -2
- package/dist/core/components/interaction/IconLink.d.ts +1 -1
- package/dist/core/components/interaction/MiniEditor.d.ts +3 -2
- package/dist/core/components/interaction/MiniEditor.js +7 -5
- package/dist/core/components/interaction/Popup.d.ts +20 -15
- package/dist/core/components/interaction/Popup.js +63 -66
- package/dist/core/components/interaction/QuickInput.js +2 -0
- package/dist/core/components/interaction/QuickPicker.d.ts +1 -0
- package/dist/core/components/interaction/QuickPicker.js +5 -5
- package/dist/core/components/interaction/Tabs.d.ts +5 -1
- package/dist/core/components/interaction/Tabs.js +18 -8
- package/dist/core/components/interaction/menu/useMenuController.d.ts +2 -2
- package/dist/core/components/interaction/table/TableItem.d.ts +2 -1
- package/dist/core/components/interaction/table/TableItem.js +5 -3
- package/dist/core/components/layout/InfoPanel.js +4 -2
- package/dist/core/components/visuals/Icon.d.ts +1 -1
- package/dist/core/components/visuals/Icon.js +6 -0
- package/dist/core/components/visuals/index.d.ts +0 -1
- package/dist/core/components/visuals/index.js +0 -1
- package/dist/core/domain/Block.d.ts +4 -0
- package/dist/core/domain/Block.js +7 -0
- package/dist/core/domain/BlockConfiguration.d.ts +11 -3
- package/dist/core/domain/BlockConfiguration.js +77 -14
- package/dist/core/domain/CollectionBrowser.d.ts +2 -2
- package/dist/core/domain/CollectionFieldProxy.d.ts +7 -2
- package/dist/core/domain/CollectionFieldProxy.js +55 -66
- package/dist/core/domain/SectionBlock.d.ts +5 -0
- package/dist/core/domain/SectionBlock.js +15 -0
- package/dist/core/hooks/useBlockConfiguration.d.ts +7 -1
- package/dist/core/hooks/useBlockConfiguration.js +8 -1
- package/dist/core/hooks/usePage.d.ts +2 -2
- package/dist/core/hooks/usePage.js +5 -4
- package/dist/core/repository/CollectionRepository.js +1 -1
- package/dist/core/repository/CollectionSerializer.d.ts +3 -2
- package/dist/core/repository/CollectionSerializer.js +12 -7
- package/dist/core/repository/PageRepository.js +2 -2
- package/dist/core/repository/PageSerializer.d.ts +5 -3
- package/dist/core/repository/PageSerializer.js +10 -11
- package/dist/explore/components/CreateCollectionDialog.d.ts +2 -3
- package/dist/explore/components/CreateCollectionDialog.js +1 -1
- package/dist/explore/components/CreatePageDialog.d.ts +3 -3
- package/dist/explore/components/CreatePageDialog.js +2 -2
- package/dist/explore/screens/CollectionExplorer.js +4 -4
- package/dist/explore/screens/PageExplorer.js +4 -4
- package/dist/page/components/BlockEditor.js +10 -2
- package/dist/page/components/config/BlockConfigButton.d.ts +8 -0
- package/dist/page/components/config/BlockConfigButton.js +320 -0
- package/dist/page/components/config/BlockConfigurationProvider.d.ts +8 -0
- package/dist/page/components/config/BlockConfigurationProvider.js +17 -0
- package/dist/page/components/config/LegacyBlockPreview.d.ts +8 -0
- package/dist/page/components/config/{BlockPreview.js → LegacyBlockPreview.js} +30 -40
- package/dist/page/components/config/index.d.ts +3 -1
- package/dist/page/components/config/index.js +3 -1
- package/dist/page/components/index.d.ts +1 -1
- package/dist/page/components/index.js +1 -1
- package/dist/page/components/nav/NavSection.js +4 -3
- package/dist/page/components/panels/BlockConfigPanel.d.ts +1 -0
- package/dist/page/components/panels/BlockConfigPanel.js +25 -0
- package/dist/page/components/{PageStatus.d.ts → panels/PageStatus.d.ts} +3 -3
- package/dist/page/components/{PageStatus.js → panels/PageStatus.js} +10 -14
- package/dist/page/components/panels/index.d.ts +2 -0
- package/dist/page/components/{status → panels}/index.js +2 -1
- package/dist/page/hooks/PageController.d.ts +2 -2
- package/dist/page/screens/PageEditor.js +8 -1
- package/dist/styles/index.css +174 -56
- package/dist/styles/tailwind.js +7 -3
- package/dist/users/screens/UserExplorer.js +7 -6
- package/package.json +3 -2
- package/dist/core/components/fields/collection/previews/ClientPreview.d.ts +0 -10
- package/dist/core/components/fields/collection/previews/ClientPreview.js +0 -29
- package/dist/core/components/visuals/SkeletonLayout.d.ts +0 -9
- package/dist/core/components/visuals/SkeletonLayout.js +0 -429
- package/dist/page/components/config/BlockConfig.d.ts +0 -8
- package/dist/page/components/config/BlockConfig.js +0 -28
- package/dist/page/components/config/BlockConfigEditor.d.ts +0 -9
- package/dist/page/components/config/BlockConfigEditor.js +0 -114
- package/dist/page/components/config/BlockPreview.d.ts +0 -10
- package/dist/page/components/config/BlockView.d.ts +0 -4
- package/dist/page/components/config/BlockView.js +0 -9
- package/dist/page/components/config/LegacyBlockConfigEditor.d.ts +0 -9
- package/dist/page/components/config/LegacyBlockConfigEditor.js +0 -27
- package/dist/page/components/config/ListPanelEditor.d.ts +0 -8
- package/dist/page/components/config/ListPanelEditor.js +0 -89
- package/dist/page/components/config/MessagePanelEditor.d.ts +0 -8
- package/dist/page/components/config/MessagePanelEditor.js +0 -17
- package/dist/page/components/config/VisualPanelEditor.d.ts +0 -8
- package/dist/page/components/config/VisualPanelEditor.js +0 -76
- package/dist/page/components/status/index.d.ts +0 -1
- /package/dist/page/components/{status → panels}/AutoSave.d.ts +0 -0
- /package/dist/page/components/{status → panels}/AutoSave.js +0 -0
|
@@ -73,8 +73,8 @@ class PageRepository {
|
|
|
73
73
|
// return new page if it was updated
|
|
74
74
|
if (pageData) {
|
|
75
75
|
console.debug('[PageRepository/save] received new page');
|
|
76
|
-
const { eventBus, template, region } = page;
|
|
77
|
-
return PageSerializer_1.PageSerializer.deserializePage(
|
|
76
|
+
const { eventBus, template, region, language } = page;
|
|
77
|
+
return PageSerializer_1.PageSerializer.deserializePage({ flattenedPage: pageData, eventBus, target: { template, region, language } });
|
|
78
78
|
}
|
|
79
79
|
// or simply update the page updated stamp
|
|
80
80
|
else {
|
|
@@ -5,9 +5,11 @@ export declare namespace PageSerializer {
|
|
|
5
5
|
type DeserializePageWithSummaryArgs = Schema.Page.Data.AsGroup & PageTarget & {
|
|
6
6
|
eventBus: EventBus;
|
|
7
7
|
};
|
|
8
|
-
function deserializePageWithSummary({ eventBus, group: groupData, page:
|
|
9
|
-
type DeserializePageArgs =
|
|
8
|
+
function deserializePageWithSummary({ eventBus, group: groupData, page: flattenedPage, ...target }: DeserializePageWithSummaryArgs): Page.WithSummary;
|
|
9
|
+
type DeserializePageArgs = {
|
|
10
|
+
flattenedPage: Schema.Page.FlattenedData;
|
|
11
|
+
target: PageTarget;
|
|
10
12
|
eventBus: EventBus;
|
|
11
13
|
};
|
|
12
|
-
function deserializePage({
|
|
14
|
+
function deserializePage({ flattenedPage, target, eventBus }: DeserializePageArgs): Page;
|
|
13
15
|
}
|
|
@@ -20,30 +20,30 @@ const TagSerializer_1 = require("./TagSerializer");
|
|
|
20
20
|
var PageSerializer;
|
|
21
21
|
(function (PageSerializer) {
|
|
22
22
|
function deserializePageWithSummary(_a) {
|
|
23
|
-
var { eventBus, group: groupData, page:
|
|
23
|
+
var { eventBus, group: groupData, page: flattenedPage } = _a, target = __rest(_a, ["eventBus", "group", "page"]);
|
|
24
24
|
// deserialize page (if any)
|
|
25
|
-
const {
|
|
26
|
-
const page = pageData && deserializePage(Object.assign(Object.assign({}, pageData), { template, region, eventBus }));
|
|
25
|
+
const page = flattenedPage && deserializePage({ flattenedPage, target, eventBus });
|
|
27
26
|
// deserialize summary
|
|
28
27
|
const { brand, groupId, instances } = groupData;
|
|
29
|
-
const summary = new domain_1.PageSummary(Object.assign(Object.assign({},
|
|
28
|
+
const summary = new domain_1.PageSummary(Object.assign(Object.assign({}, target), { brand,
|
|
30
29
|
groupId, pages: instances }));
|
|
31
30
|
// return result
|
|
32
31
|
return { summary, page };
|
|
33
32
|
}
|
|
34
33
|
PageSerializer.deserializePageWithSummary = deserializePageWithSummary;
|
|
35
|
-
function deserializePage(
|
|
36
|
-
|
|
34
|
+
function deserializePage({ flattenedPage, target, eventBus }) {
|
|
35
|
+
const { data, files, pages, collections } = flattenedPage;
|
|
36
|
+
const { snapshot, discover, content, tags } = data, dataRest = __rest(data, ["snapshot", "discover", "content", "tags"]);
|
|
37
|
+
const { template, region } = target;
|
|
37
38
|
// determine latest snapshot (if any)
|
|
38
39
|
const { discover: discoverSnapshot = {}, preview: previewSnapshot = {}, content: contentSnapshot = {} } = snapshot !== null && snapshot !== void 0 ? snapshot : {};
|
|
39
40
|
// create new page using shared bus
|
|
40
|
-
const region = data.region;
|
|
41
41
|
const pageSchemas = funnel_core_1.Schema.Site.current().regions[region];
|
|
42
42
|
const page = new domain_1.Page(Object.assign(Object.assign({ eventBus,
|
|
43
43
|
template, tags: TagSerializer_1.TagSerializer.deserializeTags({
|
|
44
44
|
groups: template.tags,
|
|
45
45
|
tagsData: tags
|
|
46
|
-
}) },
|
|
46
|
+
}) }, dataRest), { discover: [
|
|
47
47
|
deserializeBlock({ schema: funnel_core_1.Schema.Seo, eventBus, key: 'seo', content: discover['seo'], snapshot: discoverSnapshot['seo'] })
|
|
48
48
|
], content: Object.entries(template.content).map(([key, schema]) => deserializeContent({
|
|
49
49
|
key,
|
|
@@ -51,11 +51,10 @@ var PageSerializer;
|
|
|
51
51
|
eventBus,
|
|
52
52
|
content: content[key],
|
|
53
53
|
snapshot: contentSnapshot[key]
|
|
54
|
-
})), files, pages: pages.map((_a) => {
|
|
54
|
+
})), files: Object.values(files), pages: Object.values(pages).map((_a) => {
|
|
55
55
|
var { type, tags } = _a, ref = __rest(_a, ["type", "tags"]);
|
|
56
56
|
return (Object.assign(Object.assign({}, ref), { template: pageSchemas[type], tags: template.tags.flatMap(tagGroup => tagGroup.parse(tags)) }));
|
|
57
|
-
}), collections,
|
|
58
|
-
snapshot }));
|
|
57
|
+
}), collections: Object.values(collections), snapshot }));
|
|
59
58
|
// repair any issues on the page
|
|
60
59
|
page.repair();
|
|
61
60
|
// return page
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Collection, CollectionBrowser } from '../../core';
|
|
1
|
+
import { Collection, CollectionBrowser, Popup } from '../../core';
|
|
3
2
|
export declare const CreateCollectionDialog: import("react").ForwardRefExoticComponent<import("react").RefAttributes<CreateCollectionDialog.Ref>>;
|
|
4
3
|
export declare namespace CreateCollectionDialog {
|
|
5
4
|
type Props = {};
|
|
@@ -8,6 +7,6 @@ export declare namespace CreateCollectionDialog {
|
|
|
8
7
|
}
|
|
9
8
|
type Options = {
|
|
10
9
|
collectionBrowser: CollectionBrowser;
|
|
11
|
-
anchor:
|
|
10
|
+
anchor: Popup.Anchor;
|
|
12
11
|
};
|
|
13
12
|
}
|
|
@@ -110,7 +110,7 @@ exports.CreateCollectionDialog = (0, react_1.forwardRef)(function CreateCollecti
|
|
|
110
110
|
deferral.resolve(result !== null && result !== void 0 ? result : undefined);
|
|
111
111
|
};
|
|
112
112
|
// skip if we don't have any params
|
|
113
|
-
if (!deferral || !collectionBrowser) {
|
|
113
|
+
if (!deferral || !collectionBrowser || !anchor) {
|
|
114
114
|
return null;
|
|
115
115
|
}
|
|
116
116
|
// render
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Page, Pages, Site } from '../../core';
|
|
1
|
+
import { Schema } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { Page, Pages, Popup, Site } from '../../core';
|
|
3
3
|
export declare const CreatePageDialog: import("react").ForwardRefExoticComponent<import("react").RefAttributes<CreatePageDialog.Ref>>;
|
|
4
4
|
export declare namespace CreatePageDialog {
|
|
5
5
|
type Props = {};
|
|
@@ -10,6 +10,6 @@ export declare namespace CreatePageDialog {
|
|
|
10
10
|
site: Site;
|
|
11
11
|
template: Schema.Page;
|
|
12
12
|
collection: Pages;
|
|
13
|
-
anchor:
|
|
13
|
+
anchor: Popup.Anchor;
|
|
14
14
|
};
|
|
15
15
|
}
|
|
@@ -159,11 +159,11 @@ exports.CreatePageDialog = (0, react_1.forwardRef)(function CreatePageDialog(_,
|
|
|
159
159
|
deferral.resolve(result !== null && result !== void 0 ? result : undefined);
|
|
160
160
|
};
|
|
161
161
|
// skip if we don't have any params
|
|
162
|
-
if (!deferral || !site || !template) {
|
|
162
|
+
if (!deferral || !site || !template || !anchor) {
|
|
163
163
|
return null;
|
|
164
164
|
}
|
|
165
165
|
// render
|
|
166
|
-
return ((0, jsx_runtime_1.jsxs)(core_1.MiniEditor, { className: "flex flex-col gap-l8", title: `Create new ${(_d = template.name) !== null && _d !== void 0 ? _d : 'page'}`, open: result === undefined, anchor: anchor, anchorOffset: 4, placement: "
|
|
166
|
+
return ((0, jsx_runtime_1.jsxs)(core_1.MiniEditor, { className: "flex flex-col gap-l8", title: `Create new ${(_d = template.name) !== null && _d !== void 0 ? _d : 'page'}`, open: result === undefined, anchor: anchor, anchorOffset: 4, placement: "left", renderSaveLabel: state => state === 'saving' ? 'Creating...' : 'Create', canSave: onValidate, onSave: onCreate, onClose: onCancel, onClosed: onClosed, children: [(0, jsx_runtime_1.jsx)(core_1.ErrorMessage, { error: error }), (0, jsx_runtime_1.jsxs)(core_1.FieldErrorController, { errorLevel: errorLevel, children: [(0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: nameField, autoFocus: true }), (0, jsx_runtime_1.jsx)(core_1.TextField, { ref: slugFieldRef, field: slugField, onKeyDown: onSlugKeyDown }), multiLanguage &&
|
|
167
167
|
(0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: languageField })] })] }));
|
|
168
168
|
});
|
|
169
169
|
function getLanguageOptions(site) {
|
|
@@ -25,7 +25,7 @@ function CollectionExplorer({ type }) {
|
|
|
25
25
|
}
|
|
26
26
|
}, [splash, groupedCollections]);
|
|
27
27
|
// helpers
|
|
28
|
-
const onCreateCollection = async (e) => {
|
|
28
|
+
const onCreateCollection = async (e, anchorId) => {
|
|
29
29
|
var _a;
|
|
30
30
|
// ignore if template isn't bound
|
|
31
31
|
if (!collectionBrowser) {
|
|
@@ -34,7 +34,7 @@ function CollectionExplorer({ type }) {
|
|
|
34
34
|
// open dialog (skip if the page creation was cancelled)
|
|
35
35
|
const collection = await ((_a = createDialogRef.current) === null || _a === void 0 ? void 0 : _a.createCollection({
|
|
36
36
|
collectionBrowser,
|
|
37
|
-
anchor:
|
|
37
|
+
anchor: anchorId
|
|
38
38
|
}));
|
|
39
39
|
if (!collection) {
|
|
40
40
|
return;
|
|
@@ -56,10 +56,10 @@ function renderCollections({ template, groupedCollections, onOpenLink, onCreateC
|
|
|
56
56
|
// or render
|
|
57
57
|
const { inProgress, live } = groupedCollections;
|
|
58
58
|
if (inProgress.length === 0 && live.length === 0) {
|
|
59
|
-
return ((0, jsx_runtime_1.jsxs)(core_1.EmptyState, { variant: "missing", children: [(0, jsx_runtime_1.jsxs)("div", { className: "max-w-sm flex flex-col items-center gap-l4 text-center text-pretty whitespace-pre", children: [(0, jsx_runtime_1.jsx)("p", { children: "It doesn't look like you've created anything yet." }), (0, jsx_runtime_1.jsx)("p", { children: "Get started by creating your first item. It's pretty simple and shouldn't take too long!" })] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { variant: "primary", onClick: onCreateCollection, children: ["Create a ", template.name] })] }, "empty"));
|
|
59
|
+
return ((0, jsx_runtime_1.jsxs)(core_1.EmptyState, { variant: "missing", children: [(0, jsx_runtime_1.jsxs)("div", { className: "max-w-sm flex flex-col items-center gap-l4 text-center text-pretty whitespace-pre", children: [(0, jsx_runtime_1.jsx)("p", { children: "It doesn't look like you've created anything yet." }), (0, jsx_runtime_1.jsx)("p", { children: "Get started by creating your first item. It's pretty simple and shouldn't take too long!" })] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { anchorId: "collection.create", variant: "primary", onClick: e => onCreateCollection(e, 'collection.create'), children: ["Create a ", template.name] })] }, "empty"));
|
|
60
60
|
}
|
|
61
61
|
// render pages
|
|
62
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-l8 justify-between items-center", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "heading-lg text-content-primary", children: [template.name, " data"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { variant: "primary", iconLeft: "Plus", onClick: onCreateCollection, children: ["Create a new ", template.name] })] }), inProgress.length > 0 &&
|
|
62
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-l8 justify-between items-center", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "heading-lg text-content-primary", children: [template.name, " data"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { className: "collection.createNew", variant: "primary", iconLeft: "Plus", onClick: e => onCreateCollection(e, 'collection.createNew'), children: ["Create a new ", template.name] })] }), inProgress.length > 0 &&
|
|
63
63
|
(0, jsx_runtime_1.jsx)(core_1.Table, { className: "flex-1", title: "Work in progress", children: inProgress.map(({ status, link }) => (0, jsx_runtime_1.jsx)(core_1.TableItem, { details: status === 'ready'
|
|
64
64
|
? (0, jsx_runtime_1.jsx)(core_1.StatusBadge, { variant: "success", label: "Ready to go" })
|
|
65
65
|
: status === 'changed'
|
|
@@ -25,7 +25,7 @@ function PageExplorer({ region, page: pageType }) {
|
|
|
25
25
|
}
|
|
26
26
|
}, [splash, ready]);
|
|
27
27
|
// helpers
|
|
28
|
-
const onCreatePage = async (e) => {
|
|
28
|
+
const onCreatePage = async (e, anchorId) => {
|
|
29
29
|
var _a;
|
|
30
30
|
// skip if there are no collections (should never happen)
|
|
31
31
|
if (!collection) {
|
|
@@ -36,7 +36,7 @@ function PageExplorer({ region, page: pageType }) {
|
|
|
36
36
|
site,
|
|
37
37
|
template,
|
|
38
38
|
collection,
|
|
39
|
-
anchor:
|
|
39
|
+
anchor: anchorId
|
|
40
40
|
}));
|
|
41
41
|
if (!page) {
|
|
42
42
|
return;
|
|
@@ -58,10 +58,10 @@ function renderPages({ template, groupedPages, onCreatePage, onOpenPage }) {
|
|
|
58
58
|
// or show empty state if there are no pages
|
|
59
59
|
const { inProgress, live, unpublished } = groupedPages;
|
|
60
60
|
if (inProgress.length === 0 && live.length === 0 && unpublished.length === 0) {
|
|
61
|
-
return ((0, jsx_runtime_1.jsxs)(core_1.EmptyState, { variant: "missing", children: [(0, jsx_runtime_1.jsxs)("h3", { className: "heading-md text-content-primary", children: ["There are no ", template.name, " pages created yet!"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { variant: "primary", iconLeft: "Plus", onClick: onCreatePage, children: ["Create a ", template.name] })] }, "empty"));
|
|
61
|
+
return ((0, jsx_runtime_1.jsxs)(core_1.EmptyState, { variant: "missing", children: [(0, jsx_runtime_1.jsxs)("h3", { className: "heading-md text-content-primary", children: ["There are no ", template.name, " pages created yet!"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { anchorId: "page-create", variant: "primary", iconLeft: "Plus", onClick: e => onCreatePage(e, 'page-create'), children: ["Create a ", template.name] })] }, "empty"));
|
|
62
62
|
}
|
|
63
63
|
// render pages
|
|
64
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-l8 justify-between items-center", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "heading-lg text-content-primary", children: [template.name, " pages"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { variant: "primary", iconLeft: "Plus", onClick: onCreatePage, children: ["Create a new ", template.name] })] }), inProgress.length > 0 &&
|
|
64
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap gap-l8 justify-between items-center", children: [(0, jsx_runtime_1.jsxs)("h2", { className: "heading-lg text-content-primary", children: [template.name, " pages"] }), (0, jsx_runtime_1.jsxs)(core_1.Button, { anchorId: "page-create", variant: "primary", iconLeft: "Plus", onClick: e => onCreatePage(e, 'page-create'), children: ["Create a new ", template.name] })] }), inProgress.length > 0 &&
|
|
65
65
|
(0, jsx_runtime_1.jsx)(core_1.Table, { className: "flex-1", title: "Work in progress", children: inProgress.map(({ summary: { status }, link }) => (0, jsx_runtime_1.jsx)(core_1.TableItem, { details: status === 'ready'
|
|
66
66
|
? (0, jsx_runtime_1.jsx)(core_1.StatusBadge, { variant: "success", label: "Ready to publish" })
|
|
67
67
|
: status === 'changed'
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.BlockEditor = BlockEditor;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
const react_1 = require("react");
|
|
9
10
|
const core_1 = require("../../core");
|
|
10
11
|
const config_1 = require("./config");
|
|
11
12
|
// component
|
|
@@ -13,6 +14,8 @@ function BlockEditor({ className, block, onSelectItem }) {
|
|
|
13
14
|
// bind props + hooks
|
|
14
15
|
const dialog = (0, core_1.useDialog)();
|
|
15
16
|
const menu = (0, core_1.useMenuController)(blockMenu);
|
|
17
|
+
const anchorId = (0, react_1.useId)();
|
|
18
|
+
// sync block
|
|
16
19
|
(0, core_1.useBlock)(block);
|
|
17
20
|
// render empty state if block isn't selected
|
|
18
21
|
if (!block) {
|
|
@@ -54,8 +57,13 @@ function BlockEditor({ className, block, onSelectItem }) {
|
|
|
54
57
|
}
|
|
55
58
|
};
|
|
56
59
|
// render editor
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
const { messageFields, visualFields, listsFields, extendedFields } = block;
|
|
61
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(className, 'max-h-full h-full flex flex-col'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center px-l6 pt-l10 pb-l4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "heading-lg flex-1", children: block.name }), (0, jsx_runtime_1.jsx)("div", { className: "shrink-0 flex items-center gap-l5", children: block.canDelete &&
|
|
62
|
+
(0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(core_1.IconButton, { anchorId: anchorId, className: "DeleteAction text-content-primary hover:text-destructive shrink-0", variant: "util", icon: "EllipsisVertical", onClick: e => menu.open(anchorId) }), (0, jsx_runtime_1.jsx)(core_1.Menu, { controller: menu, onItemClick: onMenuClick })] }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex flex-col gap-l8 px-l6 pb-l10 overflow-y-scroll scrollbar-thin scroller-fade-top bg-background", children: [messageFields.length > 0 &&
|
|
63
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "Messaging", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "message" }), fields: messageFields }), visualFields.length > 0 &&
|
|
64
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "Visual", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "visual" }), fields: visualFields }), listsFields.length > 0 &&
|
|
65
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { title: "List", actions: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { target: "list" }), fields: listsFields }), extendedFields.length > 0 &&
|
|
66
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldsPanel, { fields: extendedFields })] })] }));
|
|
59
67
|
}
|
|
60
68
|
const blockMenu = [
|
|
61
69
|
{
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
export declare function BlockConfigButton({ target, children }: BlockConfigButton.Props): import("react/jsx-runtime").JSX.Element | null;
|
|
3
|
+
export declare namespace BlockConfigButton {
|
|
4
|
+
type Target = 'block' | 'message' | 'visual' | 'list';
|
|
5
|
+
type Props = PropsWithChildren & {
|
|
6
|
+
target: Target;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
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.BlockConfigButton = BlockConfigButton;
|
|
18
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
|
+
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
20
|
+
const funnel_ui_1 = require("@nascentdigital/funnel-ui");
|
|
21
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
22
|
+
const react_1 = require("motion/react");
|
|
23
|
+
const react_2 = require("react");
|
|
24
|
+
const rxjs_1 = require("rxjs");
|
|
25
|
+
const core_1 = require("../../../core");
|
|
26
|
+
const hooks_1 = require("../../hooks");
|
|
27
|
+
// component
|
|
28
|
+
function BlockConfigButton({ target, children = 'Configure' }) {
|
|
29
|
+
var _a;
|
|
30
|
+
// bind state + hooks
|
|
31
|
+
const [open, setOpen] = (0, react_2.useState)(false);
|
|
32
|
+
const anchorId = (0, react_2.useId)();
|
|
33
|
+
const panelLayoutPickerRef = (0, react_2.useRef)(null);
|
|
34
|
+
const listLayoutPickerRef = (0, react_2.useRef)(null);
|
|
35
|
+
const configuration = (0, core_1.useBlockConfiguration)();
|
|
36
|
+
const pageController = (0, hooks_1.usePageController)();
|
|
37
|
+
// skip if there's no config
|
|
38
|
+
if (!configuration) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
// determine popup
|
|
42
|
+
let size;
|
|
43
|
+
let placement;
|
|
44
|
+
let title;
|
|
45
|
+
let tip = undefined;
|
|
46
|
+
let content;
|
|
47
|
+
switch (target) {
|
|
48
|
+
case 'block': {
|
|
49
|
+
// helper
|
|
50
|
+
const onChangePanelLayout = async (e) => {
|
|
51
|
+
var _a;
|
|
52
|
+
// skip if there's no layout field (shouldn't happen)
|
|
53
|
+
if (!layoutField) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
// pick new layout
|
|
57
|
+
const { schema: layoutSchema, value: layoutData } = layoutField;
|
|
58
|
+
const selectedLayout = await ((_a = panelLayoutPickerRef.current) === null || _a === void 0 ? void 0 : _a.open({
|
|
59
|
+
anchor: anchorId,
|
|
60
|
+
anchorOffset: 4,
|
|
61
|
+
placement: 'top',
|
|
62
|
+
items: Object.entries(layoutSchema.options).map(([layout, option]) => ({
|
|
63
|
+
id: layout,
|
|
64
|
+
label: option.name
|
|
65
|
+
})),
|
|
66
|
+
selectedItem: layoutData === null || layoutData === void 0 ? void 0 : layoutData.value
|
|
67
|
+
}));
|
|
68
|
+
// update if something was picked
|
|
69
|
+
if (selectedLayout) {
|
|
70
|
+
layoutField.value = funnel_core_1.Schema.EnumField.Value.toData(selectedLayout);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
// set variables
|
|
74
|
+
size = 'sm';
|
|
75
|
+
placement = 'left';
|
|
76
|
+
title = 'Block Configuration';
|
|
77
|
+
// render content
|
|
78
|
+
const { scope, layoutField, blocksFields = [], desktopFields = [], mobileFields = [] } = configuration;
|
|
79
|
+
const settingsFields = scope === 'desktop'
|
|
80
|
+
? desktopFields
|
|
81
|
+
: mobileFields;
|
|
82
|
+
const { options: slotOptions = [], currentIndex: slotIndex = 0 } = configuration.slotState;
|
|
83
|
+
content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("section", { className: "grid grid-cols-2 gap-x-l5 gap-y-l4", children: [blocksFields.length > 0 &&
|
|
84
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldErrorController, { children: blocksFields.map(field => (0, jsx_runtime_1.jsx)(core_1.FieldEditor, { className: "col-span-full", field: field, size: "xs" }, field.id)) }), layoutField && layoutField.schema.enum.length > 1 &&
|
|
85
|
+
(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l2", children: [(0, jsx_runtime_1.jsx)(core_1.FieldHeader, { label: "Layout", size: "xs" }), (0, jsx_runtime_1.jsx)(core_1.Button, { anchorId: anchorId, variant: "secondary", size: "xs", iconLeft: "LayoutTemplate", onClick: onChangePanelLayout, children: "Change" })] }), slotOptions.length > 1 &&
|
|
86
|
+
(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l2", children: [(0, jsx_runtime_1.jsx)(core_1.FieldHeader, { label: "Arrangement", size: "xs" }), slotOptions.length === 2
|
|
87
|
+
?
|
|
88
|
+
(0, jsx_runtime_1.jsx)(core_1.Button, { variant: "secondary", size: "xs", iconLeft: "ArrowLeftRight", onClick: () => configuration === null || configuration === void 0 ? void 0 : configuration.gotToNextSlot(), children: "Swap" })
|
|
89
|
+
:
|
|
90
|
+
(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-l4", children: [(0, jsx_runtime_1.jsx)(core_1.Button, { variant: "secondary", size: "xs", onClick: () => configuration === null || configuration === void 0 ? void 0 : configuration.gotToPreviousSlot(), children: (0, jsx_runtime_1.jsx)(core_1.Icon, { variant: "ArrowLeft", size: { size: 16, strokeWidth: 1, absoluteStrokeWidth: true } }) }), (0, jsx_runtime_1.jsxs)("span", { className: "label-xs", children: [slotIndex + 1, " of ", slotOptions.length] }), (0, jsx_runtime_1.jsx)(core_1.Button, { variant: "secondary", size: "xs", onClick: () => configuration === null || configuration === void 0 ? void 0 : configuration.gotToNextSlot(), children: (0, jsx_runtime_1.jsx)(core_1.Icon, { variant: "ArrowRight", size: { size: 16, strokeWidth: 1, absoluteStrokeWidth: true } }) })] })] }), settingsFields.map(field => (0, jsx_runtime_1.jsx)(core_1.FieldEditor, { className: "col-span-full", field: field, size: "xs" }, field.id))] }), (0, jsx_runtime_1.jsx)(core_1.QuickPicker, { ref: panelLayoutPickerRef, variant: "card", title: "Pick Block Layout", description: "Select an available layout for this block.", renderItem: (item) => renderPanelLayoutItem(item) })] }));
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case 'message':
|
|
94
|
+
size = 'xs';
|
|
95
|
+
placement = 'bottom-end';
|
|
96
|
+
title = 'Message Configuration';
|
|
97
|
+
tip = 'Medium and Large are relative to this block\'s text area, not the page width.';
|
|
98
|
+
content = Object.values(configuration.messageFields)
|
|
99
|
+
.filter(funnel_core_1.Value.isDefined)
|
|
100
|
+
.map(field => (0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: field, size: "xs" }, field.id));
|
|
101
|
+
break;
|
|
102
|
+
case 'list': {
|
|
103
|
+
// pull out layout from listFields
|
|
104
|
+
const _b = configuration.listFields, { layout: layoutField } = _b, listFields = __rest(_b, ["layout"]);
|
|
105
|
+
// helpers
|
|
106
|
+
const onChangeLayout = async (e) => {
|
|
107
|
+
var _a;
|
|
108
|
+
// skip if there's no layout field (shouldn't happen)
|
|
109
|
+
const layoutSchema = layoutField === null || layoutField === void 0 ? void 0 : layoutField.schema;
|
|
110
|
+
if (!layoutField || !layoutSchema) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// pick new layout
|
|
114
|
+
const { value: layoutData } = layoutField;
|
|
115
|
+
const selectedLayout = await ((_a = listLayoutPickerRef.current) === null || _a === void 0 ? void 0 : _a.open({
|
|
116
|
+
anchor: anchorId,
|
|
117
|
+
anchorOffset: 4,
|
|
118
|
+
placement: 'top',
|
|
119
|
+
items: Object.entries(layoutSchema.options).map(([layout, option]) => ({
|
|
120
|
+
id: layout,
|
|
121
|
+
label: option.name
|
|
122
|
+
})),
|
|
123
|
+
selectedItem: layoutData === null || layoutData === void 0 ? void 0 : layoutData.value
|
|
124
|
+
}));
|
|
125
|
+
// update if something was picked
|
|
126
|
+
if (selectedLayout) {
|
|
127
|
+
layoutField.value = funnel_core_1.Schema.EnumField.Value.toData(selectedLayout);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
// set variables
|
|
131
|
+
size = 'xs';
|
|
132
|
+
placement = 'bottom-end';
|
|
133
|
+
title = 'List Configuration';
|
|
134
|
+
// render content
|
|
135
|
+
content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l4", children: [(0, jsx_runtime_1.jsx)(core_1.Button, { anchorId: anchorId, variant: "secondary", size: "xs", iconLeft: "LayoutTemplate", onClick: onChangeLayout, children: "Change" }), Object.values(listFields)
|
|
136
|
+
.filter(funnel_core_1.Value.isDefined)
|
|
137
|
+
.map(field => (0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: field, size: "xs" }, field.id))] }), (0, jsx_runtime_1.jsx)(core_1.QuickPicker, { ref: listLayoutPickerRef, variant: "card", title: "Pick List Layout", description: "Select an available layout for this list.", renderItem: (item) => renderListLayoutItem(item) })] }));
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case 'visual': {
|
|
141
|
+
// set variables
|
|
142
|
+
size = 'xs';
|
|
143
|
+
placement = 'bottom-end';
|
|
144
|
+
title = 'Visual Configuration';
|
|
145
|
+
tip = 'Cropping changes how the image appears on your site, not your original file.';
|
|
146
|
+
// get fields
|
|
147
|
+
const { aspect: aspectField, anchor: anchorField, width: widthField, horizontalAlign: horizontalAlignField } = configuration.visualFields;
|
|
148
|
+
const { value } = (_a = configuration.getFieldData('visual')) !== null && _a !== void 0 ? _a : {};
|
|
149
|
+
const visual = funnel_core_1.Schema.AssetField.LinkedValue.Visual.filter(value)
|
|
150
|
+
? value
|
|
151
|
+
: undefined;
|
|
152
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l9", children: [(0, jsx_runtime_1.jsxs)("section", { className: "flex flex-col gap-l4", children: [aspectField &&
|
|
153
|
+
(0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: aspectField, size: "xs" }), anchorField
|
|
154
|
+
? (0, jsx_runtime_1.jsx)(core_1.FieldEditor, { field: anchorField, size: "xs" })
|
|
155
|
+
:
|
|
156
|
+
(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(core_1.FieldHeader, { label: "Anchor", size: "xs" }), (0, jsx_runtime_1.jsx)("p", { className: "label-xs text-content-secondary text-pretty", children: "Your current image size and aspect ratio don't require and anchor (there's no cropping)." })] })] }), visual && renderVisual({
|
|
157
|
+
configuration,
|
|
158
|
+
visual,
|
|
159
|
+
aspectField: aspectField,
|
|
160
|
+
anchorField: anchorField
|
|
161
|
+
})] }));
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
throw new funnel_core_1.NotImplementedError();
|
|
166
|
+
}
|
|
167
|
+
// helpers
|
|
168
|
+
const onSave = async () => {
|
|
169
|
+
// try to save
|
|
170
|
+
configuration.save();
|
|
171
|
+
// wait for page to save
|
|
172
|
+
await (0, rxjs_1.firstValueFrom)(pageController.saved$);
|
|
173
|
+
// re-sync config
|
|
174
|
+
configuration.reset();
|
|
175
|
+
// close
|
|
176
|
+
setOpen(false);
|
|
177
|
+
};
|
|
178
|
+
const onClosed = () => {
|
|
179
|
+
// reset configuration (drops changes)
|
|
180
|
+
configuration.reset();
|
|
181
|
+
};
|
|
182
|
+
// render
|
|
183
|
+
return ((0, jsx_runtime_1.jsx)(core_1.MiniEditor, { title: title, size: size, anchor: (0, jsx_runtime_1.jsx)(core_1.Button, { variant: "secondary", size: "xs", onClick: () => setOpen(true), children: children }), anchorOffset: 4, placement: placement, open: open, onSave: onSave, disableSave: !configuration.modified, onClose: () => setOpen(false), onClosed: onClosed, customActions: (0, jsx_runtime_1.jsx)(core_1.Button, { variant: "secondary", size: "xs", iconLeft: configuration.scope === 'mobile'
|
|
184
|
+
? 'Smartphone'
|
|
185
|
+
: 'Monitor', onClick: () => configuration.scope = configuration.scope === 'desktop' ? 'mobile' : 'desktop', children: configuration.scope === 'mobile' ? 'Mobile' : 'Desktop' }), children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l4", children: [tip &&
|
|
186
|
+
(0, jsx_runtime_1.jsx)(core_1.Note, { variant: "tip", size: size, children: (0, jsx_runtime_1.jsx)(funnel_ui_1.Markup, { markdown: `**Tip:** ${tip}` }) }), content] }) }));
|
|
187
|
+
}
|
|
188
|
+
function renderPanelLayoutItem(item) {
|
|
189
|
+
const panel = (className = 'flex-1') => ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('bg-surface-placeholder rounded-[2px]', className) }));
|
|
190
|
+
const panelPaddedX = 'px-l4';
|
|
191
|
+
const panelPaddedY = 'py-l4';
|
|
192
|
+
const panelPadded = (0, classnames_1.default)(panelPaddedX, panelPaddedY);
|
|
193
|
+
const panelGap = 'gap-l1';
|
|
194
|
+
const nestedPanel = (config = {}) => {
|
|
195
|
+
// unpack config
|
|
196
|
+
const { panelClassName, nestedPanelClassName, multipleItems = false } = config;
|
|
197
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex h-full bg-surface-placeholder rounded-[2px]', panelClassName, panelGap, { 'p-l2': multipleItems }), children: [(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('flex-1 bg-surface-placeholder-raised rounded-[2px]', nestedPanelClassName, { 'm-l2': !multipleItems }) }), multipleItems &&
|
|
198
|
+
(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('flex-1 bg-surface-placeholder-raised rounded-[2px]', nestedPanelClassName) })] }));
|
|
199
|
+
};
|
|
200
|
+
switch (item.id) {
|
|
201
|
+
case 'solo':
|
|
202
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('size-full', panelPadded), children: panel('size-full') }));
|
|
203
|
+
case 'stack.v':
|
|
204
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex flex-col h-full", panelPadded, panelGap), children: [panel(), panel()] }));
|
|
205
|
+
case 'stack.h':
|
|
206
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex h-full", panelPadded, panelGap), children: [panel(), panel()] }));
|
|
207
|
+
case 'brick.v':
|
|
208
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex flex-col h-full", panelPadded, panelGap), children: [panel(), panel(), panel()] }));
|
|
209
|
+
case 'brick.t':
|
|
210
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex flex-col h-full", panelPadded, panelGap), children: [panel('flex-1 w-full h-[20px]'), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex flex-1', panelGap), children: [panel(), panel()] })] }));
|
|
211
|
+
case 'brick.r':
|
|
212
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex h-full', panelPadded, panelGap), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex h-full flex-1 flex-col', panelGap), children: [panel(), panel()] }), panel('h-full w-[30px]')] }));
|
|
213
|
+
case 'brick.b':
|
|
214
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex flex-col h-full", panelPadded, panelGap), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex flex-1', panelGap), children: [panel(), panel()] }), panel('flex-1 w-full h-[20px]')] }));
|
|
215
|
+
case 'brick.l':
|
|
216
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex h-full', panelPadded, panelGap), children: [panel('h-full w-[30px]'), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('flex h-full flex-1 flex-col', panelGap), children: [panel(), panel()] })] }));
|
|
217
|
+
case 'nested':
|
|
218
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('size-full', panelPadded), children: nestedPanel() }));
|
|
219
|
+
case 'nested.v':
|
|
220
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('size-full', panelPadded), children: nestedPanel({ panelClassName: 'flex-col', multipleItems: true }) }));
|
|
221
|
+
case 'nested.h':
|
|
222
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('size-full', panelPadded), children: nestedPanel({ multipleItems: true }) }));
|
|
223
|
+
case 'nested.t':
|
|
224
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex h-full flex-col", panelPadded, panelGap), children: [nestedPanel({ panelClassName: 'flex-1' }), panel()] }));
|
|
225
|
+
case 'nested.r':
|
|
226
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex h-full", panelPadded, panelGap), children: [panel(), nestedPanel({ panelClassName: 'flex-1' })] }));
|
|
227
|
+
case 'nested.b':
|
|
228
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex h-full flex-col", panelPadded, panelGap), children: [panel(), nestedPanel({ panelClassName: 'flex-1' })] }));
|
|
229
|
+
case 'nested.l':
|
|
230
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)("flex h-full", panelPadded, panelGap), children: [nestedPanel({ panelClassName: 'flex-1' }), panel()] }));
|
|
231
|
+
default:
|
|
232
|
+
return ((0, jsx_runtime_1.jsx)("div", { children: item.id }));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function renderListLayoutItem(item) {
|
|
236
|
+
// panel
|
|
237
|
+
const panel = (className = 'w-full') => ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('bg-surface-placeholder-raised rounded-[2px]', className) }));
|
|
238
|
+
// get content
|
|
239
|
+
const panelClassName = 'w-full h-full';
|
|
240
|
+
const panelPaddedX = 'px-10';
|
|
241
|
+
const panelPaddedY = 'py-10';
|
|
242
|
+
const panelPadded = (0, classnames_1.default)(panelPaddedX, panelPaddedY);
|
|
243
|
+
let content;
|
|
244
|
+
switch (item.id) {
|
|
245
|
+
case 'card':
|
|
246
|
+
case 'grid':
|
|
247
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPadded, 'grid grid-cols-3 auto-cols-fr gap-x-l3 gap-y-l2 '), children: [panel(), panel(), panel(), panel(), panel()] }));
|
|
248
|
+
break;
|
|
249
|
+
case 'flexWrap':
|
|
250
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPadded, 'flex flex-wrap justify-center items-center gap-l3'), children: [panel('w-12 h-12'), panel('w-12 h-12'), panel('w-12 h-12'), panel('w-12 h-12'), panel('w-12 h-12')] }));
|
|
251
|
+
break;
|
|
252
|
+
case 'verticalStack':
|
|
253
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPadded, 'grid grid-cols-1 auto-rows-fr gap-y-l2 '), children: [panel(), panel(), panel()] }));
|
|
254
|
+
break;
|
|
255
|
+
case 'horizontalStack':
|
|
256
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPadded, 'grid grid-rows-1 auto-cols-fr grid-flow-col gap-x-l3 '), children: [panel(), panel(), panel()] }));
|
|
257
|
+
break;
|
|
258
|
+
case 'masonry':
|
|
259
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPaddedX, 'grid grid-cols-3 grid-flow-col gap-x-l3 pt-10'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l2", children: [panel('h-l5'), panel('h-l6'), panel('h-l5')] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l2", children: [panel('h-22'), panel('h-l6')] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-l2", children: [panel('h-l4'), panel('h-l7'), panel('h-l5')] })] }));
|
|
260
|
+
break;
|
|
261
|
+
case 'bento':
|
|
262
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPadded, 'grid auto-rows-auto auto-cols-auto gap-l3'), children: [panel('w-20 row-start-1 row-span-2 col-start-1'), panel('w-28 row-start-1 col-start-2'), panel('w-18 row-start-2 col-start-2')] }));
|
|
263
|
+
break;
|
|
264
|
+
case 'brick':
|
|
265
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPaddedX, 'grid grid-cols-2 gap-l3 pt-10'), children: [panel('h-12 row-start-1 col-span-full'), panel('h-12 row-start-2 col-start-1'), panel('h-12 row-start-2 col-start-2'), panel('h-12 row-start-3 col-span-full')] }));
|
|
266
|
+
break;
|
|
267
|
+
case 'brickFlipped':
|
|
268
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, panelPaddedX, 'grid grid-cols-2 gap-l3 pt-10'), children: [panel('h-12 row-start-1 col-start-1'), panel('h-12 row-start-1 col-start-2'), panel('h-12 row-start-2 col-span-full'), panel('h-12 row-start-3 col-start-1'), panel('h-12 row-start-3 col-start-2')] }));
|
|
269
|
+
break;
|
|
270
|
+
case 'carousel':
|
|
271
|
+
content = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(panelClassName, 'flex flex-col gap-l2 pt-10 pb-l3'), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex-1 flex items-stretch gap-l3", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-8 bg-surface-placeholder rounded-r-[2px]" }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1 bg-surface-placeholder-raised rounded-[2px]" }), (0, jsx_runtime_1.jsx)("div", { className: "w-8 bg-surface-placeholder rounded-l-[2px]" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center items-center gap-l1", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-4 h-4 bg-surface-placeholder-raised rounded-full" }), (0, jsx_runtime_1.jsx)("div", { className: "w-4 h-4 bg-surface-placeholder-raised rounded-full" }), (0, jsx_runtime_1.jsx)("div", { className: "w-4 h-4 bg-surface-placeholder-raised rounded-full" })] })] }));
|
|
272
|
+
break;
|
|
273
|
+
default:
|
|
274
|
+
content = ((0, jsx_runtime_1.jsx)("div", { children: item.id }));
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
// render item in frame
|
|
278
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('w-full h-full flex justify-center items-center'), children: content }));
|
|
279
|
+
}
|
|
280
|
+
function renderVisual({ configuration, visual, aspectField, anchorField }) {
|
|
281
|
+
var _a, _b, _c;
|
|
282
|
+
// determine layout info
|
|
283
|
+
const { metadata, name, description } = visual;
|
|
284
|
+
const { dimensions: { width, height } } = metadata;
|
|
285
|
+
const isPortrait = width < height;
|
|
286
|
+
const aspect = (_b = (_a = aspectField === null || aspectField === void 0 ? void 0 : aspectField.value) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : 'auto';
|
|
287
|
+
const anchor = (_c = anchorField === null || anchorField === void 0 ? void 0 : anchorField.value) === null || _c === void 0 ? void 0 : _c.value;
|
|
288
|
+
const anchorDirection = anchorField
|
|
289
|
+
? anchorField.schema.isValidOption('left')
|
|
290
|
+
? 'x'
|
|
291
|
+
: 'y'
|
|
292
|
+
: undefined;
|
|
293
|
+
// render
|
|
294
|
+
return ((0, jsx_runtime_1.jsx)("section", { className: (0, classnames_1.default)('w-full h-[210px]', 'flex flex-col justify-center items-center', 'bg-background rounded-xs'), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)('relative bg-destructive', {
|
|
295
|
+
'h-full max-h-full w-auto': isPortrait,
|
|
296
|
+
'w-full': !isPortrait
|
|
297
|
+
}), children: [funnel_core_1.Schema.AssetField.LinkedValue.Image.filter(visual)
|
|
298
|
+
? renderImage({ configuration, visual })
|
|
299
|
+
: renderVideo({ configuration, visual }), aspect !== 'auto' && anchor && anchorDirection &&
|
|
300
|
+
(0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)('absolute inset-0 z-supersurface flex', {
|
|
301
|
+
'flex-col': anchorDirection === 'y'
|
|
302
|
+
}), children: (0, jsx_runtime_1.jsxs)(react_1.AnimatePresence, { mode: "popLayout", children: [anchor !== 'left' && anchor !== 'top' &&
|
|
303
|
+
(0, jsx_runtime_1.jsx)(react_1.motion.div, { className: "flex-1 bg-content-button-contrast/backdrop", layout: true, variants: core_1.Animate.Variants.fade, initial: "initial", animate: "animate", exit: "exit" }, "crop.start"), (0, jsx_runtime_1.jsx)(react_1.motion.div, { className: (0, classnames_1.default)('shrink-0 outline outline-1 outline-ix-primary', {
|
|
304
|
+
'h-full w-auto': anchorDirection === 'x',
|
|
305
|
+
'w-full h-auto': anchorDirection === 'y',
|
|
306
|
+
'aspect-square': aspect === 'square',
|
|
307
|
+
'aspect-phone': aspect === 'phone',
|
|
308
|
+
'aspect-tv': aspect === 'tv',
|
|
309
|
+
'aspect-widescreen': aspect === 'widescreen',
|
|
310
|
+
'aspect-cinema': aspect === 'cinema'
|
|
311
|
+
}), layout: true }, "visible"), anchor !== 'right' && anchor !== 'bottom' &&
|
|
312
|
+
(0, jsx_runtime_1.jsx)(react_1.motion.div, { className: "flex-1 bg-content-button-contrast/backdrop", layout: true, variants: core_1.Animate.Variants.fade, initial: "initial", animate: "animate", exit: "exit" }, "crop.end")] }) })] }) }));
|
|
313
|
+
}
|
|
314
|
+
function renderImage({ visual }) {
|
|
315
|
+
var _a;
|
|
316
|
+
return ((0, jsx_runtime_1.jsx)("img", { className: "max-w-full max-h-full", src: visual.url, alt: (_a = visual.description) !== null && _a !== void 0 ? _a : visual.name }));
|
|
317
|
+
}
|
|
318
|
+
function renderVideo({ visual }) {
|
|
319
|
+
return ((0, jsx_runtime_1.jsx)("video", { className: "max-w-full max-h-full", src: visual.url, autoPlay: true, muted: true, loop: true, playsInline: true }));
|
|
320
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { PropsWithChildren } from 'react';
|
|
2
|
+
import { Block, PageSettings, Section, SectionBlock } from '../../../core';
|
|
3
|
+
export declare function BlockConfigurationProvider({ item, children }: BlockConfigurationProvider.Props): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare namespace BlockConfigurationProvider {
|
|
5
|
+
type Props = PropsWithChildren & {
|
|
6
|
+
item?: Block | SectionBlock | Section | PageSettings;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BlockConfigurationProvider = BlockConfigurationProvider;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const core_1 = require("../../../core");
|
|
7
|
+
// provider
|
|
8
|
+
function BlockConfigurationProvider({ item, children }) {
|
|
9
|
+
// bind context
|
|
10
|
+
const context = (0, react_1.useMemo)(() => ({
|
|
11
|
+
configuration: item instanceof core_1.Block || item instanceof core_1.SectionBlock
|
|
12
|
+
? item.getConfiguration()
|
|
13
|
+
: undefined
|
|
14
|
+
}), [item]);
|
|
15
|
+
// render
|
|
16
|
+
return ((0, jsx_runtime_1.jsx)(core_1.BlockConfigurationContext.Provider, { value: context, children: children }));
|
|
17
|
+
}
|