@nascentdigital/funnel-editor 5.0.2 → 5.0.3
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/components.d.ts +2 -1
- package/dist/components.js +2 -1
- package/dist/core/client/EditorApiClient.js +1 -1
- package/dist/core/components/fields/page/PagePicker.js +1 -1
- package/dist/core/domain/IPage.d.ts +4 -0
- package/dist/core/domain/IPage.js +30 -0
- package/dist/core/domain/PageOverview.d.ts +6 -0
- package/dist/core/domain/PageOverview.js +17 -0
- package/dist/core/domain/PageSummary.d.ts +9 -7
- package/dist/core/domain/PageSummary.js +12 -16
- package/dist/core/domain/Pages.js +1 -2
- package/dist/core/repository/IPageRepository.d.ts +0 -1
- package/dist/core/repository/PageRepository.js +1 -1
- package/dist/explore/screens/PageExplorer.js +2 -1
- package/dist/page/components/BlockEditor.d.ts +3 -1
- package/dist/page/components/BlockEditor.js +4 -3
- package/dist/page/components/config/BlockConfigurationProvider.d.ts +10 -2
- package/dist/page/components/config/BlockConfigurationProvider.js +11 -3
- package/dist/page/components/config/BlockPreview.d.ts +4 -2
- package/dist/page/components/config/BlockPreview.js +5 -11
- package/dist/page/components/config/index.d.ts +1 -0
- package/dist/page/components/config/index.js +1 -0
- package/dist/page/components/config/useBlockConfiguration$.d.ts +3 -0
- package/dist/page/components/config/useBlockConfiguration$.js +22 -0
- package/dist/page/components/panels/BlockConfigPanel.js +3 -3
- package/dist/page/hooks/PageController.js +2 -1
- package/dist/styles/index.css +34 -9
- package/dist/styles/tailwind.js +1 -0
- package/package.json +3 -3
package/dist/components.d.ts
CHANGED
|
@@ -15,7 +15,8 @@ export * from './core/repository/SerializeCollectionUpdate';
|
|
|
15
15
|
export * from './core/repository/SerializePageUpdate';
|
|
16
16
|
export * from './core/repository/TagSerializer';
|
|
17
17
|
export * from './core/splash';
|
|
18
|
-
export * from './page/
|
|
18
|
+
export * from './page/components/config';
|
|
19
19
|
export * from './page/components/SettingsEditor';
|
|
20
|
+
export * from './page/hooks';
|
|
20
21
|
export * from './collection/hooks';
|
|
21
22
|
export { PageNav, BlockEditor };
|
package/dist/components.js
CHANGED
|
@@ -36,7 +36,8 @@ __exportStar(require("./core/repository/SerializePageUpdate"), exports);
|
|
|
36
36
|
__exportStar(require("./core/repository/TagSerializer"), exports);
|
|
37
37
|
__exportStar(require("./core/splash"), exports);
|
|
38
38
|
// page
|
|
39
|
-
__exportStar(require("./page/
|
|
39
|
+
__exportStar(require("./page/components/config"), exports);
|
|
40
40
|
__exportStar(require("./page/components/SettingsEditor"), exports);
|
|
41
|
+
__exportStar(require("./page/hooks"), exports);
|
|
41
42
|
// collection
|
|
42
43
|
__exportStar(require("./collection/hooks"), exports);
|
|
@@ -138,7 +138,7 @@ exports.PagePicker = (0, react_1.forwardRef)(function PagePicker({ language }, r
|
|
|
138
138
|
pages.sync()
|
|
139
139
|
.then(() => {
|
|
140
140
|
setPagesSchema(pages.template);
|
|
141
|
-
setPages(pages.items.map(page => page.getClosestPageRef(language, site.defaultLanguage)));
|
|
141
|
+
setPages(pages.items.map(page => page.getClosestPageRef({ region: site.region.id, language, fallbackLanguage: site.defaultLanguage })));
|
|
142
142
|
})
|
|
143
143
|
.catch(e => setError(feedback_1.ErrorMessage.coerce(e)));
|
|
144
144
|
}
|
|
@@ -52,6 +52,9 @@ export declare namespace IPage {
|
|
|
52
52
|
updatedOn: number;
|
|
53
53
|
publishedOn?: number;
|
|
54
54
|
};
|
|
55
|
+
namespace Ref {
|
|
56
|
+
function fromData({ tags, ...data }: Schema.Page.Data.AsLink): Ref;
|
|
57
|
+
}
|
|
55
58
|
type References = {
|
|
56
59
|
pages: Ref[];
|
|
57
60
|
collections: Schema.Collection.Data.AsLink[];
|
|
@@ -70,4 +73,5 @@ export declare namespace IPage {
|
|
|
70
73
|
function filter(event: EventBus.Event): event is Event;
|
|
71
74
|
function create(event: EventBus.Args<Event>): Event;
|
|
72
75
|
}
|
|
76
|
+
function getPreviewUrl(path: string): URL;
|
|
73
77
|
}
|
|
@@ -1,10 +1,30 @@
|
|
|
1
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
|
+
};
|
|
2
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
14
|
exports.IPage = void 0;
|
|
4
15
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
16
|
// extension
|
|
6
17
|
var IPage;
|
|
7
18
|
(function (IPage) {
|
|
19
|
+
let Ref;
|
|
20
|
+
(function (Ref) {
|
|
21
|
+
function fromData(_a) {
|
|
22
|
+
var { tags } = _a, data = __rest(_a, ["tags"]);
|
|
23
|
+
const template = funnel_core_1.Schema.Site.getPage(data.type, data.region);
|
|
24
|
+
return Object.assign({ template, tags: template.parseTags(tags !== null && tags !== void 0 ? tags : []) }, data);
|
|
25
|
+
}
|
|
26
|
+
Ref.fromData = fromData;
|
|
27
|
+
})(Ref = IPage.Ref || (IPage.Ref = {}));
|
|
8
28
|
let Event;
|
|
9
29
|
(function (Event) {
|
|
10
30
|
// methods
|
|
@@ -17,4 +37,14 @@ var IPage;
|
|
|
17
37
|
}
|
|
18
38
|
Event.create = create;
|
|
19
39
|
})(Event = IPage.Event || (IPage.Event = {}));
|
|
40
|
+
// helpers
|
|
41
|
+
function getPreviewUrl(path) {
|
|
42
|
+
// get base url
|
|
43
|
+
const url = new URL('/api/preview', window.location.href);
|
|
44
|
+
// apply args
|
|
45
|
+
url.searchParams.set('redirect', path);
|
|
46
|
+
// return url
|
|
47
|
+
return url;
|
|
48
|
+
}
|
|
49
|
+
IPage.getPreviewUrl = getPreviewUrl;
|
|
20
50
|
})(IPage || (exports.IPage = IPage = {}));
|
|
@@ -17,14 +17,20 @@ export declare class StaticPageOverview extends PageOverviewBase {
|
|
|
17
17
|
readonly refs: Readonly<Record<Language, Schema.Page.Data.AsLink>>;
|
|
18
18
|
readonly languages: ReadonlyArray<Language>;
|
|
19
19
|
constructor({ refs, ...args }: StaticPageOverview.ConstructorArgs);
|
|
20
|
+
get pages(): Schema.Page.Data.AsLink<Schema.Page<Schema.Page.Content, string>, string>[];
|
|
20
21
|
get isEmpty(): boolean;
|
|
21
22
|
hasLanguage(language: Language): boolean;
|
|
23
|
+
findPage({ region, language }: StaticPageOverview.FindPageArgs): Schema.Page.Data.AsLink | undefined;
|
|
22
24
|
getClosestPageRef(language: Language, fallback?: Language): IPage.Ref | undefined;
|
|
23
25
|
}
|
|
24
26
|
export declare namespace StaticPageOverview {
|
|
25
27
|
type ConstructorArgs = Omit<PageOverviewBase.ConstructorArgs, 'variant'> & {
|
|
26
28
|
refs: Record<Language, Schema.Page.Data.AsLink>;
|
|
27
29
|
};
|
|
30
|
+
type FindPageArgs = {
|
|
31
|
+
region: string;
|
|
32
|
+
language?: Language;
|
|
33
|
+
};
|
|
28
34
|
}
|
|
29
35
|
export declare class DynamicPageOverview extends PageOverviewBase {
|
|
30
36
|
readonly count: number;
|
|
@@ -32,12 +32,29 @@ class StaticPageOverview extends PageOverviewBase {
|
|
|
32
32
|
this.refs = refs;
|
|
33
33
|
this.languages = Object.keys(refs).map(funnel_core_1.Language.parse);
|
|
34
34
|
}
|
|
35
|
+
get pages() {
|
|
36
|
+
return Object.values(this.refs);
|
|
37
|
+
}
|
|
35
38
|
get isEmpty() {
|
|
36
39
|
return this.languages.length === 0;
|
|
37
40
|
}
|
|
38
41
|
hasLanguage(language) {
|
|
39
42
|
return this.languages.includes(language);
|
|
40
43
|
}
|
|
44
|
+
findPage({ region, language }) {
|
|
45
|
+
var _a;
|
|
46
|
+
// narrow down to region
|
|
47
|
+
const pages = this.pages.filter(page => page.region === region);
|
|
48
|
+
// return exact match (if any) if a language is provided
|
|
49
|
+
if (language) {
|
|
50
|
+
return pages.find(page => page.language === language);
|
|
51
|
+
}
|
|
52
|
+
// or pick the best match
|
|
53
|
+
else {
|
|
54
|
+
const { defaultLanguage } = funnel_core_1.AppConfig.brandConfig().regionalization.regions[region];
|
|
55
|
+
return (_a = pages.find(page => page.language === defaultLanguage)) !== null && _a !== void 0 ? _a : pages[0];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
41
58
|
getClosestPageRef(language, fallback) {
|
|
42
59
|
var _a, _b;
|
|
43
60
|
const { template, languages, refs } = this;
|
|
@@ -4,7 +4,6 @@ export declare class PageSummary {
|
|
|
4
4
|
readonly template: Schema.Page;
|
|
5
5
|
readonly brand: string;
|
|
6
6
|
readonly groupId: Schema.Page.GroupId;
|
|
7
|
-
readonly region: string;
|
|
8
7
|
readonly slug?: string;
|
|
9
8
|
readonly pages: ReadonlyArray<PageSummary.PageRef>;
|
|
10
9
|
readonly status: PageSummary.Status;
|
|
@@ -12,10 +11,10 @@ export declare class PageSummary {
|
|
|
12
11
|
get type(): Schema.Page.Type;
|
|
13
12
|
get variant(): Schema.Page.Variant;
|
|
14
13
|
get hasPages(): boolean;
|
|
15
|
-
hasLanguage(language: Language): boolean;
|
|
16
|
-
getPage(language: Language): PageSummary.PageRef | undefined;
|
|
17
|
-
getClosestPageRef(
|
|
18
|
-
isInGroup({ template
|
|
14
|
+
hasLanguage(region: string, language: Language): boolean;
|
|
15
|
+
getPage(region: string, language: Language): PageSummary.PageRef | undefined;
|
|
16
|
+
getClosestPageRef({ region, language, fallbackLanguage }: PageSummary.GetClosestPageRefArgs): IPage.Ref;
|
|
17
|
+
isInGroup({ template }: PageSummary.IsInGroupArgs): boolean;
|
|
19
18
|
}
|
|
20
19
|
export declare namespace PageSummary {
|
|
21
20
|
type Status = 'draft' | 'ready' | 'live' | 'unpublished' | 'changed' | 'empty';
|
|
@@ -23,13 +22,16 @@ export declare namespace PageSummary {
|
|
|
23
22
|
template: Schema.Page;
|
|
24
23
|
brand: string;
|
|
25
24
|
groupId: Schema.Page.GroupId;
|
|
26
|
-
region: string;
|
|
27
25
|
slug?: string;
|
|
28
26
|
pages: PageSummary.PageRef[];
|
|
29
27
|
};
|
|
30
28
|
type PageRef = Schema.Page.Data.AsGroup.Instance & Pick<Schema.Page.Data.AsLink, 'state' | 'errors' | 'createdOn' | 'updatedOn' | 'publishedOn'>;
|
|
29
|
+
type GetClosestPageRefArgs = {
|
|
30
|
+
region: string;
|
|
31
|
+
language: Language;
|
|
32
|
+
fallbackLanguage?: Language;
|
|
33
|
+
};
|
|
31
34
|
type IsInGroupArgs = {
|
|
32
35
|
template: Schema.Page;
|
|
33
|
-
region: string;
|
|
34
36
|
};
|
|
35
37
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PageSummary = void 0;
|
|
4
4
|
const funnel_core_1 = require("@nascentdigital/funnel-core");
|
|
5
|
+
const IPage_1 = require("./IPage");
|
|
5
6
|
// class
|
|
6
7
|
class PageSummary {
|
|
7
8
|
constructor(args) {
|
|
@@ -9,7 +10,6 @@ class PageSummary {
|
|
|
9
10
|
this.template = args.template;
|
|
10
11
|
this.brand = args.brand;
|
|
11
12
|
this.groupId = args.groupId;
|
|
12
|
-
this.region = args.region;
|
|
13
13
|
this.slug = args.slug;
|
|
14
14
|
this.pages = args.pages;
|
|
15
15
|
this.status = getStatus(args.pages);
|
|
@@ -23,24 +23,20 @@ class PageSummary {
|
|
|
23
23
|
get hasPages() {
|
|
24
24
|
return this.groupId !== funnel_core_1.Schema.Page.GroupId.empty;
|
|
25
25
|
}
|
|
26
|
-
hasLanguage(language) {
|
|
27
|
-
return this.pages.some(page => page.language === language);
|
|
26
|
+
hasLanguage(region, language) {
|
|
27
|
+
return this.pages.some(page => page.region === region && page.language === language);
|
|
28
28
|
}
|
|
29
|
-
getPage(language) {
|
|
30
|
-
return this.pages.find(page => page.language === language);
|
|
29
|
+
getPage(region, language) {
|
|
30
|
+
return this.pages.find(page => page.region === region && page.language === language);
|
|
31
31
|
}
|
|
32
|
-
getClosestPageRef(language,
|
|
33
|
-
var _a, _b;
|
|
34
|
-
const { template, brand, groupId,
|
|
35
|
-
const ref = (_b = (_a = pages.find(page => page.language === language)) !== null && _a !== void 0 ? _a : (
|
|
36
|
-
return Object.assign(Object.assign({}, ref), { template,
|
|
37
|
-
brand,
|
|
38
|
-
groupId,
|
|
39
|
-
region, tags: template.tags.flatMap(tagGroup => tagGroup.parse(ref.tags)) });
|
|
32
|
+
getClosestPageRef({ region, language, fallbackLanguage }) {
|
|
33
|
+
var _a, _b, _c, _d;
|
|
34
|
+
const { template, brand, groupId, pages } = this;
|
|
35
|
+
const ref = (_d = (_c = (_b = (_a = pages.find(page => page.region === region && page.language === language)) !== null && _a !== void 0 ? _a : (fallbackLanguage && pages.find(page => page.region === region && page.language === fallbackLanguage))) !== null && _b !== void 0 ? _b : pages.find(page => page.language === language)) !== null && _c !== void 0 ? _c : (fallbackLanguage && pages.find(page => page.language === fallbackLanguage))) !== null && _d !== void 0 ? _d : pages[0];
|
|
36
|
+
return IPage_1.IPage.Ref.fromData(Object.assign(Object.assign({}, ref), { groupId, type: template.type, brand }));
|
|
40
37
|
}
|
|
41
|
-
isInGroup({ template
|
|
42
|
-
return this.template.type === template.type
|
|
43
|
-
&& this.region === region;
|
|
38
|
+
isInGroup({ template }) {
|
|
39
|
+
return this.template.type === template.type;
|
|
44
40
|
}
|
|
45
41
|
}
|
|
46
42
|
exports.PageSummary = PageSummary;
|
|
@@ -60,7 +60,6 @@ class Pages {
|
|
|
60
60
|
const { region } = site;
|
|
61
61
|
const { items: pages } = await site.repository.search({
|
|
62
62
|
template,
|
|
63
|
-
region: region.id,
|
|
64
63
|
tags: tags.map(tag => tag.data),
|
|
65
64
|
pagination: 'all'
|
|
66
65
|
});
|
|
@@ -77,7 +76,6 @@ class Pages {
|
|
|
77
76
|
template,
|
|
78
77
|
brand: page.brand,
|
|
79
78
|
groupId: page.groupId,
|
|
80
|
-
region: region.id,
|
|
81
79
|
slug: page.slug,
|
|
82
80
|
pages: []
|
|
83
81
|
};
|
|
@@ -88,6 +86,7 @@ class Pages {
|
|
|
88
86
|
// add page to args
|
|
89
87
|
args.pages.push({
|
|
90
88
|
id: page.id,
|
|
89
|
+
region: page.region,
|
|
91
90
|
language: page.language,
|
|
92
91
|
slug: page.slug,
|
|
93
92
|
name: page.name,
|
|
@@ -57,7 +57,7 @@ class PageRepository {
|
|
|
57
57
|
const { eventBus, template } = args, query = __rest(args, ["eventBus", "template"]);
|
|
58
58
|
const data = await this.editorApi.createPage(Object.assign(Object.assign({}, query), { type: template.type }));
|
|
59
59
|
// return page
|
|
60
|
-
return PageSerializer_1.PageSerializer.deserializePageWithSummary(Object.assign(Object.assign({
|
|
60
|
+
return PageSerializer_1.PageSerializer.deserializePageWithSummary(Object.assign(Object.assign({}, args), data));
|
|
61
61
|
}
|
|
62
62
|
async save(page) {
|
|
63
63
|
// get page update
|
|
@@ -72,9 +72,10 @@ function renderPages({ template, groupedPages, onCreatePage, onOpenPage }) {
|
|
|
72
72
|
}
|
|
73
73
|
function groupPages(site, summaries) {
|
|
74
74
|
// group pages
|
|
75
|
+
const { region: { id: region }, defaultLanguage: language } = site;
|
|
75
76
|
const groupedPages = summaries
|
|
76
77
|
// enrich summaries with links
|
|
77
|
-
.map(summary => ({ summary, link: summary.getClosestPageRef(
|
|
78
|
+
.map(summary => ({ summary, link: summary.getClosestPageRef({ region, language }) }))
|
|
78
79
|
// group summaries based on status
|
|
79
80
|
.reduce((groupedPages, linkedSummary) => {
|
|
80
81
|
// bind page to group (drop empty pages groups, which shouldn't occur)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Callback } from '@nascentdigital/funnel-core';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { Block, PageSettings, Section, SectionBlock } from '../../core';
|
|
3
|
-
export declare function BlockEditor({ className, block, onSelectItem }: BlockEditor.Props): import("react/jsx-runtime").JSX.Element | null;
|
|
4
|
+
export declare function BlockEditor({ className, block, headerActions, onSelectItem }: BlockEditor.Props): import("react/jsx-runtime").JSX.Element | null;
|
|
4
5
|
export declare namespace BlockEditor {
|
|
5
6
|
type Props = {
|
|
6
7
|
className?: string;
|
|
7
8
|
block: Block | SectionBlock;
|
|
9
|
+
headerActions?: ReactNode;
|
|
8
10
|
onSelectItem: Callback<Block | SectionBlock | Section | PageSettings>;
|
|
9
11
|
};
|
|
10
12
|
}
|
|
@@ -10,8 +10,9 @@ const react_1 = require("react");
|
|
|
10
10
|
const core_1 = require("../../core");
|
|
11
11
|
const config_1 = require("./config");
|
|
12
12
|
// component
|
|
13
|
-
function BlockEditor({ className, block, onSelectItem }) {
|
|
13
|
+
function BlockEditor({ className, block, headerActions, onSelectItem }) {
|
|
14
14
|
// bind props + hooks
|
|
15
|
+
const page = (0, core_1.usePage)();
|
|
15
16
|
const dialog = (0, core_1.useDialog)();
|
|
16
17
|
const menu = (0, core_1.useMenuController)(blockMenu);
|
|
17
18
|
const anchorId = (0, react_1.useId)();
|
|
@@ -58,8 +59,8 @@ function BlockEditor({ className, block, onSelectItem }) {
|
|
|
58
59
|
};
|
|
59
60
|
// render editor
|
|
60
61
|
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.
|
|
62
|
-
|
|
62
|
+
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: (0, jsx_runtime_1.jsx)("a", { href: core_1.IPage.getPreviewUrl(page.url).href, target: `${page.brand}.preview`, children: block.name }) }), (0, jsx_runtime_1.jsxs)("div", { className: "shrink-0 flex items-center gap-l5", children: [headerActions, block.canDelete &&
|
|
63
|
+
(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", tabIndex: -1, children: [messageFields.length > 0 &&
|
|
63
64
|
(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
65
|
(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
66
|
(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 &&
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { PropsWithChildren } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { Block, BlockConfiguration, PageSettings, Section, SectionBlock } from '../../../core';
|
|
4
|
+
export declare const BlockConfigurationProvider: import("react").ForwardRefExoticComponent<{
|
|
5
|
+
children?: import("react").ReactNode | undefined;
|
|
6
|
+
} & {
|
|
7
|
+
item?: Block | SectionBlock | Section | PageSettings;
|
|
8
|
+
} & import("react").RefAttributes<BlockConfigurationProvider.Ref>>;
|
|
4
9
|
export declare namespace BlockConfigurationProvider {
|
|
5
10
|
type Props = PropsWithChildren & {
|
|
6
11
|
item?: Block | SectionBlock | Section | PageSettings;
|
|
7
12
|
};
|
|
13
|
+
interface Ref {
|
|
14
|
+
readonly configuration$: Observable<BlockConfiguration | undefined>;
|
|
15
|
+
}
|
|
8
16
|
}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BlockConfigurationProvider =
|
|
3
|
+
exports.BlockConfigurationProvider = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
6
7
|
const core_1 = require("../../../core");
|
|
7
8
|
// provider
|
|
8
|
-
function BlockConfigurationProvider({ item, children }) {
|
|
9
|
+
exports.BlockConfigurationProvider = (0, react_1.forwardRef)(function BlockConfigurationProvider({ item, children }, ref) {
|
|
9
10
|
// bind context
|
|
10
11
|
const context = (0, react_1.useMemo)(() => ({
|
|
11
12
|
configuration: item instanceof core_1.Block || item instanceof core_1.SectionBlock
|
|
12
13
|
? item.getConfiguration()
|
|
13
14
|
: undefined
|
|
14
15
|
}), [item]);
|
|
16
|
+
const configuration$ = (0, react_1.useMemo)(() => new rxjs_1.BehaviorSubject(undefined), []);
|
|
17
|
+
// bind interface
|
|
18
|
+
(0, react_1.useImperativeHandle)(ref, () => ({ configuration$ }), [configuration$]);
|
|
19
|
+
// sync configuration when context updates
|
|
20
|
+
(0, react_1.useEffect)(() => {
|
|
21
|
+
configuration$.next(context.configuration);
|
|
22
|
+
}, [configuration$, context]);
|
|
15
23
|
// render
|
|
16
24
|
return ((0, jsx_runtime_1.jsx)(core_1.BlockConfigurationContext.Provider, { value: context, children: children }));
|
|
17
|
-
}
|
|
25
|
+
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { BlockLayout } from '@nascentdigital/funnel-core';
|
|
1
2
|
import { BlockConfiguration } from '../../../core';
|
|
2
|
-
export declare function BlockPreview({ className,
|
|
3
|
+
export declare function BlockPreview({ className, scope, layout }: BlockPreview.Props): import("react/jsx-runtime").JSX.Element;
|
|
3
4
|
export declare namespace BlockPreview {
|
|
4
5
|
type Props = {
|
|
5
6
|
className?: string;
|
|
6
|
-
|
|
7
|
+
scope: BlockConfiguration.Scope;
|
|
8
|
+
layout: BlockLayout;
|
|
7
9
|
};
|
|
8
10
|
}
|
|
@@ -10,12 +10,11 @@ const classnames_1 = __importDefault(require("classnames"));
|
|
|
10
10
|
const react_1 = require("motion/react");
|
|
11
11
|
const preview_1 = require("./preview");
|
|
12
12
|
// components
|
|
13
|
-
function BlockPreview({ className,
|
|
13
|
+
function BlockPreview({ className, scope, layout }) {
|
|
14
14
|
// bind props
|
|
15
|
-
const { scope = 'desktop', layout } = configuration !== null && configuration !== void 0 ? configuration : {};
|
|
16
15
|
const tight = scope === 'mobile'
|
|
17
|
-
? layout
|
|
18
|
-
: layout
|
|
16
|
+
? layout.tight.mobile
|
|
17
|
+
: layout.tight.desktop;
|
|
19
18
|
// render
|
|
20
19
|
return ((0, jsx_runtime_1.jsx)(react_1.motion.section, { className: (0, classnames_1.default)(className, 'bg-surface2 rounded-xs interpolate-all', {
|
|
21
20
|
'min-h-[100px]': !layout,
|
|
@@ -24,14 +23,9 @@ function BlockPreview({ className, configuration }) {
|
|
|
24
23
|
'pb-l4': tight === 'above',
|
|
25
24
|
'pt-l4': tight === 'below',
|
|
26
25
|
'py-l4': tight === 'none'
|
|
27
|
-
}), layoutRoot: true, layout: true, children:
|
|
26
|
+
}), layoutRoot: true, layout: true, children: renderLayout({ scope, layout }) }));
|
|
28
27
|
}
|
|
29
|
-
function renderLayout({
|
|
30
|
-
// skip if there's no layout
|
|
31
|
-
const { scope, layout } = configuration;
|
|
32
|
-
if (!layout) {
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
28
|
+
function renderLayout({ scope, layout }) {
|
|
35
29
|
// render layout based on root type
|
|
36
30
|
const mobile = scope === 'mobile';
|
|
37
31
|
const { root } = layout;
|
|
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./BlockConfigButton"), exports);
|
|
18
18
|
__exportStar(require("./BlockConfigurationProvider"), exports);
|
|
19
19
|
__exportStar(require("./BlockPreview"), exports);
|
|
20
|
+
__exportStar(require("./useBlockConfiguration$"), exports);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useBlockConfiguration$ = useBlockConfiguration$;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function useBlockConfiguration$(configuration$) {
|
|
6
|
+
// bind hooks
|
|
7
|
+
const [configuration, setConfiguration] = (0, react_1.useState)();
|
|
8
|
+
// sync configuration
|
|
9
|
+
(0, react_1.useEffect)(() => {
|
|
10
|
+
// skip if there's no stream
|
|
11
|
+
if (!configuration$) {
|
|
12
|
+
setConfiguration(undefined);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
// watch stream and sync
|
|
16
|
+
const subscription = configuration$.subscribe(setConfiguration);
|
|
17
|
+
// stop on unmount
|
|
18
|
+
return () => subscription.unsubscribe();
|
|
19
|
+
}, [configuration$]);
|
|
20
|
+
// return configuration
|
|
21
|
+
return configuration;
|
|
22
|
+
}
|
|
@@ -11,12 +11,12 @@ function BlockConfigPanel() {
|
|
|
11
11
|
const id = (0, react_1.useId)();
|
|
12
12
|
const configuration = (0, core_1.useBlockConfiguration)();
|
|
13
13
|
// skip if there's no config (shouldn't happen)
|
|
14
|
-
|
|
14
|
+
const { scope = 'desktop', layout } = configuration !== null && configuration !== void 0 ? configuration : {};
|
|
15
|
+
if (!configuration || !configuration.hasPanels || !layout) {
|
|
15
16
|
return null;
|
|
16
17
|
}
|
|
17
18
|
// render
|
|
18
|
-
|
|
19
|
-
return ((0, jsx_runtime_1.jsx)(core_1.FadeIn, { children: (0, jsx_runtime_1.jsxs)(core_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "h-full flex flex-col gap-l6 py-l7 bg-surface1 rounded-xxl interpolate-all", children: [(0, jsx_runtime_1.jsx)(core_1.Tabs, { className: "mx-l7", variant: "highlighted", size: "sm", items: blockScopes, selectedItem: scope, onSelect: scope => configuration.scope = scope }), (0, jsx_runtime_1.jsx)(config_1.BlockPreview, { className: "self-center", configuration: configuration }), (0, jsx_runtime_1.jsx)("div", { className: "px-l7", children: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { anchorId: id, target: "block" }) })] }) }, "block.config"));
|
|
19
|
+
return ((0, jsx_runtime_1.jsx)(core_1.FadeIn, { children: (0, jsx_runtime_1.jsxs)(core_1.Popup.AnchorElement, { tag: "div", anchorId: id, className: "h-full flex flex-col gap-l6 py-l7 bg-surface1 rounded-xxl interpolate-all", children: [(0, jsx_runtime_1.jsx)(core_1.Tabs, { className: "mx-l7", variant: "highlighted", size: "sm", items: blockScopes, selectedItem: scope, onSelect: scope => configuration.scope = scope }), (0, jsx_runtime_1.jsx)(config_1.BlockPreview, { className: "self-center", scope: scope, layout: layout }), (0, jsx_runtime_1.jsx)("div", { className: "px-l7", children: (0, jsx_runtime_1.jsx)(config_1.BlockConfigButton, { anchorId: id, target: "block" }) })] }) }, "block.config"));
|
|
20
20
|
}
|
|
21
21
|
// helpers
|
|
22
22
|
const blockScopes = [
|
|
@@ -206,11 +206,12 @@ class PageController {
|
|
|
206
206
|
if (existingSummary
|
|
207
207
|
&& existingSummary.isInGroup(target)
|
|
208
208
|
&& existingSummary.groupId !== funnel_core_1.Schema.Page.GroupId.empty) {
|
|
209
|
-
const { template, slug, language } = target;
|
|
209
|
+
const { template, slug, region, language } = target;
|
|
210
210
|
result = await this.repository.createLanguage({
|
|
211
211
|
template,
|
|
212
212
|
groupId: existingSummary.groupId,
|
|
213
213
|
slug,
|
|
214
|
+
region,
|
|
214
215
|
language,
|
|
215
216
|
eventBus
|
|
216
217
|
});
|
package/dist/styles/index.css
CHANGED
|
@@ -501,12 +501,12 @@ video {
|
|
|
501
501
|
}
|
|
502
502
|
|
|
503
503
|
[popover]{
|
|
504
|
-
inset: var(--toolwind-toggle-
|
|
505
|
-
background-color: var(--toolwind-toggle-
|
|
506
|
-
color: var(--toolwind-toggle-
|
|
507
|
-
margin: var(--toolwind-toggle-
|
|
504
|
+
inset: var(--toolwind-toggle-JZbcB7Gi7r, 0px);
|
|
505
|
+
background-color: var(--toolwind-toggle-BCaXoftPtT, canvas);
|
|
506
|
+
color: var(--toolwind-toggle-JbSxTBifE3, canvastext);
|
|
507
|
+
margin: var(--toolwind-toggle-j7HGGXmZWl, auto);
|
|
508
508
|
}
|
|
509
|
-
html, body, #__next, .Editor-wrap{
|
|
509
|
+
html, body, #__next, #root, .Editor-wrap{
|
|
510
510
|
position: relative;
|
|
511
511
|
height: 100lvh;
|
|
512
512
|
max-height: 100lvh;
|
|
@@ -549,6 +549,31 @@ video {
|
|
|
549
549
|
overflow: scroll;
|
|
550
550
|
}
|
|
551
551
|
|
|
552
|
+
|
|
553
|
+
html.Editor-widget{
|
|
554
|
+
height: -moz-max-content;
|
|
555
|
+
height: max-content;
|
|
556
|
+
max-height: -moz-max-content;
|
|
557
|
+
max-height: max-content;
|
|
558
|
+
min-height: -moz-max-content;
|
|
559
|
+
min-height: max-content;
|
|
560
|
+
background-color: transparent;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
html.Editor-widget body, html.Editor-widget #__next, html.Editor-widget #root, html.Editor-widget .Editor-wrap{
|
|
564
|
+
height: -moz-max-content;
|
|
565
|
+
height: max-content;
|
|
566
|
+
max-height: -moz-max-content;
|
|
567
|
+
max-height: max-content;
|
|
568
|
+
min-height: -moz-max-content;
|
|
569
|
+
min-height: max-content;
|
|
570
|
+
background-color: transparent;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
html.Editor-widget nextjs-portal {
|
|
574
|
+
display: none !important;
|
|
575
|
+
}
|
|
576
|
+
|
|
552
577
|
/* colors: light mode */
|
|
553
578
|
html, *.light-mode {
|
|
554
579
|
--color-background: 247 250 252;
|
|
@@ -5996,10 +6021,10 @@ img.nd-Visual-image {
|
|
|
5996
6021
|
.anchored\/\[--nd-popup-anchor\]:where(.anchored\/\[--nd-popup-anchor\]){
|
|
5997
6022
|
position: absolute;
|
|
5998
6023
|
view-transition-name: --tw-anchor-view-transition-2j1919322s193433343934192p322r2w33362l;
|
|
5999
|
-
--toolwind-toggle-
|
|
6000
|
-
--toolwind-toggle-
|
|
6001
|
-
--toolwind-toggle-
|
|
6002
|
-
--toolwind-toggle-
|
|
6024
|
+
--toolwind-toggle-JZbcB7Gi7r: auto;
|
|
6025
|
+
--toolwind-toggle-BCaXoftPtT: transparent;
|
|
6026
|
+
--toolwind-toggle-JbSxTBifE3: inherit;
|
|
6027
|
+
--toolwind-toggle-j7HGGXmZWl: 0px;
|
|
6003
6028
|
}
|
|
6004
6029
|
.counter-l1{
|
|
6005
6030
|
counter-reset: l1;
|
package/dist/styles/tailwind.js
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nascentdigital/funnel-editor",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
|
-
"access": "
|
|
6
|
+
"access": "public"
|
|
7
7
|
},
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "git+https://github.com/nascentdigital/funnel.git",
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"ts-jest": "^29",
|
|
92
92
|
"type-fest": "^4"
|
|
93
93
|
},
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "0d1cc7d78504e8819998d928ffb342d622f75690"
|
|
95
95
|
}
|