@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.
Files changed (29) hide show
  1. package/dist/components.d.ts +2 -1
  2. package/dist/components.js +2 -1
  3. package/dist/core/client/EditorApiClient.js +1 -1
  4. package/dist/core/components/fields/page/PagePicker.js +1 -1
  5. package/dist/core/domain/IPage.d.ts +4 -0
  6. package/dist/core/domain/IPage.js +30 -0
  7. package/dist/core/domain/PageOverview.d.ts +6 -0
  8. package/dist/core/domain/PageOverview.js +17 -0
  9. package/dist/core/domain/PageSummary.d.ts +9 -7
  10. package/dist/core/domain/PageSummary.js +12 -16
  11. package/dist/core/domain/Pages.js +1 -2
  12. package/dist/core/repository/IPageRepository.d.ts +0 -1
  13. package/dist/core/repository/PageRepository.js +1 -1
  14. package/dist/explore/screens/PageExplorer.js +2 -1
  15. package/dist/page/components/BlockEditor.d.ts +3 -1
  16. package/dist/page/components/BlockEditor.js +4 -3
  17. package/dist/page/components/config/BlockConfigurationProvider.d.ts +10 -2
  18. package/dist/page/components/config/BlockConfigurationProvider.js +11 -3
  19. package/dist/page/components/config/BlockPreview.d.ts +4 -2
  20. package/dist/page/components/config/BlockPreview.js +5 -11
  21. package/dist/page/components/config/index.d.ts +1 -0
  22. package/dist/page/components/config/index.js +1 -0
  23. package/dist/page/components/config/useBlockConfiguration$.d.ts +3 -0
  24. package/dist/page/components/config/useBlockConfiguration$.js +22 -0
  25. package/dist/page/components/panels/BlockConfigPanel.js +3 -3
  26. package/dist/page/hooks/PageController.js +2 -1
  27. package/dist/styles/index.css +34 -9
  28. package/dist/styles/tailwind.js +1 -0
  29. package/package.json +3 -3
@@ -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/hooks';
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 };
@@ -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/hooks"), exports);
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);
@@ -33,7 +33,7 @@ class EditorApiClient {
33
33
  });
34
34
  }
35
35
  getPreviewUrl(url) {
36
- return `/api/preview?token=${this._token}&redirect=${url}`;
36
+ return `/api/preview?redirect=${url}`;
37
37
  }
38
38
  async getAssets(data) {
39
39
  return this.sendCommand('getAssets', data);
@@ -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(language: Language, fallback?: Language): IPage.Ref;
18
- isInGroup({ template, region }: PageSummary.IsInGroupArgs): boolean;
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, fallback) {
33
- var _a, _b;
34
- const { template, brand, groupId, region, pages } = this;
35
- const ref = (_b = (_a = pages.find(page => page.language === language)) !== null && _a !== void 0 ? _a : (fallback && pages.find(page => page.language === fallback))) !== null && _b !== void 0 ? _b : pages[0];
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, region }) {
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,
@@ -13,7 +13,6 @@ export declare namespace IPageRepository {
13
13
  namespace Search {
14
14
  type Args = Omit<PageClient.Search.Args, 'version' | 'brand' | 'type' | 'region'> & {
15
15
  template: Schema.Page;
16
- region: string;
17
16
  };
18
17
  type Result = Pagination.Paginated<IPage.Ref>;
19
18
  }
@@ -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({ region: data.group.region }, args), data));
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(site.defaultLanguage) }))
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.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", tabIndex: -1, children: [messageFields.length > 0 &&
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 { Block, PageSettings, Section, SectionBlock } from '../../../core';
3
- export declare function BlockConfigurationProvider({ item, children }: BlockConfigurationProvider.Props): import("react/jsx-runtime").JSX.Element;
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 = 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, configuration }: BlockPreview.Props): import("react/jsx-runtime").JSX.Element;
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
- configuration?: BlockConfiguration;
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, configuration }) {
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 === null || layout === void 0 ? void 0 : layout.tight.mobile
18
- : layout === null || layout === void 0 ? void 0 : layout.tight.desktop;
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: configuration && renderLayout({ configuration }) }));
26
+ }), layoutRoot: true, layout: true, children: renderLayout({ scope, layout }) }));
28
27
  }
29
- function renderLayout({ configuration }) {
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;
@@ -1,3 +1,4 @@
1
1
  export * from './BlockConfigButton';
2
2
  export * from './BlockConfigurationProvider';
3
3
  export * from './BlockPreview';
4
+ export * from './useBlockConfiguration$';
@@ -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,3 @@
1
+ import { Observable } from 'rxjs';
2
+ import { BlockConfiguration } from '../../../core';
3
+ export declare function useBlockConfiguration$(configuration$?: Observable<BlockConfiguration | undefined>): BlockConfiguration | undefined;
@@ -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
- if (!configuration || !configuration.hasPanels) {
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
- const { scope } = configuration;
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
  });
@@ -501,12 +501,12 @@ video {
501
501
  }
502
502
 
503
503
  [popover]{
504
- inset: var(--toolwind-toggle-oQHJpc9jXV, 0px);
505
- background-color: var(--toolwind-toggle-GCBdFMAuDL, canvas);
506
- color: var(--toolwind-toggle-I8FwR2AIO0, canvastext);
507
- margin: var(--toolwind-toggle-irGpFytKLG, auto);
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-oQHJpc9jXV: auto;
6000
- --toolwind-toggle-GCBdFMAuDL: transparent;
6001
- --toolwind-toggle-I8FwR2AIO0: inherit;
6002
- --toolwind-toggle-irGpFytKLG: 0px;
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;
@@ -15,6 +15,7 @@ exports.EditorTailwindConfig = {
15
15
  content: [
16
16
  './src/**/*.{tsx,jsx,ts,js}',
17
17
  '../core/src/**/*.{tsx,jsx,ts,js}',
18
+ '../editor-contentful/src/**/*.{tsx,jsx,ts,js}',
18
19
  '../ui/src/**/*.{tsx,jsx,ts,js}'
19
20
  ],
20
21
  safelist: [
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@nascentdigital/funnel-editor",
3
- "version": "5.0.2",
3
+ "version": "5.0.3",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
- "access": "restricted"
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": "24d9690cf813052f6561c3ccef11c7cf69ad7f7c"
94
+ "gitHead": "0d1cc7d78504e8819998d928ffb342d622f75690"
95
95
  }