@nascentdigital/funnel-editor-contentful 4.6.7

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 (44) hide show
  1. package/dist/Editor.d.ts +1 -0
  2. package/dist/Editor.js +10 -0
  3. package/dist/EditorApp.d.ts +1 -0
  4. package/dist/EditorApp.js +30 -0
  5. package/dist/EntryEditor.d.ts +1 -0
  6. package/dist/EntryEditor.js +9 -0
  7. package/dist/EntrySidebar.d.ts +1 -0
  8. package/dist/EntrySidebar.js +7 -0
  9. package/dist/core/api/EditorApiClient.d.ts +7 -0
  10. package/dist/core/api/EditorApiClient.js +29 -0
  11. package/dist/core/api/EditorApiContainer.d.ts +5 -0
  12. package/dist/core/api/EditorApiContainer.js +16 -0
  13. package/dist/core/api/EditorApiContext.d.ts +7 -0
  14. package/dist/core/api/EditorApiContext.js +6 -0
  15. package/dist/core/api/index.d.ts +3 -0
  16. package/dist/core/api/index.js +19 -0
  17. package/dist/core/api/useEditorApi.d.ts +2 -0
  18. package/dist/core/api/useEditorApi.js +12 -0
  19. package/dist/core/domain/Page.d.ts +89 -0
  20. package/dist/core/domain/Page.js +180 -0
  21. package/dist/core/domain/index.d.ts +1 -0
  22. package/dist/core/domain/index.js +17 -0
  23. package/dist/core/index.d.ts +3 -0
  24. package/dist/core/index.js +19 -0
  25. package/dist/core/repository/PageRepository.d.ts +12 -0
  26. package/dist/core/repository/PageRepository.js +23 -0
  27. package/dist/core/repository/PageSerializer.d.ts +9 -0
  28. package/dist/core/repository/PageSerializer.js +44 -0
  29. package/dist/core/repository/index.d.ts +1 -0
  30. package/dist/core/repository/index.js +17 -0
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.js +17 -0
  33. package/dist/page/hooks/PageController.d.ts +31 -0
  34. package/dist/page/hooks/PageController.js +107 -0
  35. package/dist/page/hooks/index.d.ts +1 -0
  36. package/dist/page/hooks/index.js +17 -0
  37. package/dist/page/index.d.ts +1 -0
  38. package/dist/page/index.js +17 -0
  39. package/dist/page/screens/PageEditor.d.ts +1 -0
  40. package/dist/page/screens/PageEditor.js +60 -0
  41. package/dist/page/screens/index.d.ts +1 -0
  42. package/dist/page/screens/index.js +17 -0
  43. package/dist/styles/index.css +2 -0
  44. package/package.json +57 -0
@@ -0,0 +1 @@
1
+ export declare function Editor(): import("react/jsx-runtime").JSX.Element;
package/dist/Editor.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Editor = Editor;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_apps_toolkit_1 = require("@contentful/react-apps-toolkit");
6
+ const EditorApp_1 = require("./EditorApp");
7
+ // wrapper around editor app to provide Contentful SDK
8
+ function Editor() {
9
+ return ((0, jsx_runtime_1.jsx)(react_apps_toolkit_1.SDKProvider, { children: (0, jsx_runtime_1.jsx)(EditorApp_1.EditorApp, {}) }));
10
+ }
@@ -0,0 +1 @@
1
+ export declare function EditorApp(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorApp = EditorApp;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const app_sdk_1 = require("@contentful/app-sdk");
6
+ const react_apps_toolkit_1 = require("@contentful/react-apps-toolkit");
7
+ const components_1 = require("@nascentdigital/funnel-editor/components");
8
+ const core_1 = require("./core");
9
+ const EntryEditor_1 = require("./EntryEditor");
10
+ const EntrySidebar_1 = require("./EntrySidebar");
11
+ // editor
12
+ function EditorApp() {
13
+ // hooks
14
+ const sdk = (0, react_apps_toolkit_1.useSDK)();
15
+ // entry editor
16
+ let content;
17
+ if (sdk.location.is(app_sdk_1.locations.LOCATION_ENTRY_EDITOR)) {
18
+ content = (0, jsx_runtime_1.jsx)(EntryEditor_1.EntryEditor, {});
19
+ }
20
+ // entry sidebar
21
+ else if (sdk.location.is(app_sdk_1.locations.LOCATION_ENTRY_SIDEBAR)) {
22
+ content = (0, jsx_runtime_1.jsx)(EntrySidebar_1.EntrySidebar, {});
23
+ }
24
+ // fallback
25
+ else {
26
+ content = (0, jsx_runtime_1.jsx)("div", { children: "Unsupported location" });
27
+ }
28
+ // render
29
+ return ((0, jsx_runtime_1.jsx)(core_1.EditorApiContainer, { children: (0, jsx_runtime_1.jsx)(components_1.DialogContainer, { children: content }) }));
30
+ }
@@ -0,0 +1 @@
1
+ export declare function EntryEditor(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntryEditor = EntryEditor;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const page_1 = require("./page");
6
+ // entry editor
7
+ function EntryEditor() {
8
+ return ((0, jsx_runtime_1.jsx)(page_1.PageEditor, {}));
9
+ }
@@ -0,0 +1 @@
1
+ export declare function EntrySidebar(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EntrySidebar = EntrySidebar;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function EntrySidebar() {
6
+ return ((0, jsx_runtime_1.jsx)("div", { children: "Entry sidebar" }));
7
+ }
@@ -0,0 +1,7 @@
1
+ import { EditorAppSDK } from '@contentful/app-sdk';
2
+ import { PageClient } from '@nascentdigital/funnel-cms';
3
+ export declare class EditorApiClient {
4
+ readonly sdk: EditorAppSDK;
5
+ constructor(sdk: EditorAppSDK);
6
+ currentPageGroup(): Promise<PageClient.GetGroup.Result>;
7
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorApiClient = void 0;
4
+ // class
5
+ class EditorApiClient {
6
+ constructor(sdk) {
7
+ this.sdk = sdk;
8
+ }
9
+ async currentPageGroup() {
10
+ const entry = this.sdk.entry;
11
+ const { type, content } = entry.fields;
12
+ return {
13
+ group: {},
14
+ page: {
15
+ data: {
16
+ id: entry.getSys().id,
17
+ type: 'home', // type.getValue(),
18
+ region: 'ca',
19
+ language: 'en',
20
+ content: content.getValue(),
21
+ },
22
+ files: {},
23
+ pages: {},
24
+ collections: {},
25
+ },
26
+ };
27
+ }
28
+ }
29
+ exports.EditorApiClient = EditorApiClient;
@@ -0,0 +1,5 @@
1
+ import { PropsWithChildren } from 'react';
2
+ export declare function EditorApiContainer({ children }: EditorApiContainer.Props): import("react/jsx-runtime").JSX.Element;
3
+ export declare namespace EditorApiContainer {
4
+ type Props = PropsWithChildren;
5
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorApiContainer = EditorApiContainer;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_apps_toolkit_1 = require("@contentful/react-apps-toolkit");
6
+ const react_1 = require("react");
7
+ const EditorApiClient_1 = require("./EditorApiClient");
8
+ const EditorApiContext_1 = require("./EditorApiContext");
9
+ // container
10
+ function EditorApiContainer({ children }) {
11
+ // bind context
12
+ const sdk = (0, react_apps_toolkit_1.useSDK)();
13
+ const context = (0, react_1.useMemo)(() => ({ client: new EditorApiClient_1.EditorApiClient(sdk) }), [sdk]);
14
+ // render
15
+ return ((0, jsx_runtime_1.jsx)(EditorApiContext_1.EditorApiContext.Provider, { value: context, children: children }));
16
+ }
@@ -0,0 +1,7 @@
1
+ import { EditorApiClient } from './EditorApiClient';
2
+ export declare const EditorApiContext: import("react").Context<EditorApiContext.Type>;
3
+ export declare namespace EditorApiContext {
4
+ type Type = {
5
+ client: EditorApiClient;
6
+ };
7
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EditorApiContext = void 0;
4
+ const react_1 = require("react");
5
+ // context
6
+ exports.EditorApiContext = (0, react_1.createContext)({});
@@ -0,0 +1,3 @@
1
+ export * from './EditorApiClient';
2
+ export * from './EditorApiContainer';
3
+ export * from './useEditorApi';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./EditorApiClient"), exports);
18
+ __exportStar(require("./EditorApiContainer"), exports);
19
+ __exportStar(require("./useEditorApi"), exports);
@@ -0,0 +1,2 @@
1
+ import { EditorApiClient } from './EditorApiClient';
2
+ export declare function useEditorApi(): EditorApiClient;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useEditorApi = useEditorApi;
4
+ const react_1 = require("react");
5
+ const EditorApiContext_1 = require("./EditorApiContext");
6
+ // hook
7
+ function useEditorApi() {
8
+ // bind context
9
+ const { client } = (0, react_1.useContext)(EditorApiContext_1.EditorApiContext);
10
+ // return client
11
+ return client;
12
+ }
@@ -0,0 +1,89 @@
1
+ import { AssetClient } from '@nascentdigital/funnel-cms';
2
+ import { EventBus, Language, Schema } from '@nascentdigital/funnel-core';
3
+ import { Asset, Block, IPage, PageSettings, Section, SectionBlock } from '@nascentdigital/funnel-editor/components';
4
+ import { Observable } from 'rxjs';
5
+ export declare class Page implements IPage {
6
+ readonly id: Schema.Page.Id;
7
+ readonly template: Schema.Page;
8
+ readonly eventBus: EventBus;
9
+ readonly groupId: Schema.Page.GroupId;
10
+ readonly brand: string;
11
+ readonly language: Language;
12
+ readonly region: string;
13
+ readonly url: string;
14
+ readonly publishedOn?: number;
15
+ readonly createdOn: number;
16
+ readonly updatedOn: number;
17
+ private readonly _content;
18
+ private readonly _assets;
19
+ private readonly _pages;
20
+ private readonly _collections;
21
+ private readonly _tags;
22
+ private _initialTags;
23
+ private _initialSlug;
24
+ private _slug;
25
+ private _syncing;
26
+ private _modifiedOn?;
27
+ constructor(args: Page.ConstructorArgs);
28
+ settings: PageSettings;
29
+ publication: number | undefined;
30
+ get events$(): Observable<IPage.Events>;
31
+ get stable$(): Observable<boolean>;
32
+ get modified(): boolean;
33
+ get published(): boolean;
34
+ get syncing(): boolean;
35
+ get hasSlug(): boolean;
36
+ get slug(): string | undefined;
37
+ get discover(): ReadonlyArray<Block>;
38
+ get content(): ReadonlyArray<Section | Block>;
39
+ get blocks(): (Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>>)[];
40
+ get firstBlock(): Block<Schema.Block<string, any, any>> | SectionBlock<Schema.Block<string, any, any>> | undefined;
41
+ get firstItem(): Block<Schema.Block<string, any, any>> | Section;
42
+ get items(): Array<Block | Section>;
43
+ get assets(): Asset[];
44
+ get collections(): ReadonlyArray<Schema.Collection.Data.AsLink>;
45
+ get initialTags(): ReadonlySet<Schema.Tag<string, string>>;
46
+ get tagGroups(): ReadonlyArray<Schema.TagGroup>;
47
+ get tags(): ReadonlySet<Schema.Tag>;
48
+ getItem(identifier: string | undefined): Block | SectionBlock | Section | PageSettings | undefined;
49
+ coerceItem(identifier: string | undefined): Block | SectionBlock | Section | PageSettings;
50
+ deleteBlock(area: IPage.Area, key: string): void;
51
+ getAsset(assetId: Asset.Id): Asset | undefined;
52
+ getAssetScope(range: Schema.AssetScope.Range): Schema.AssetScope;
53
+ getSearchScope(): AssetClient.GetAssets.Scope;
54
+ addAsset(asset: Asset): void;
55
+ removeAsset(assetId: Asset.Id): boolean;
56
+ getCollection(collectionId: Schema.Collection.Id): Schema.Collection.Data.AsLink | undefined;
57
+ addCollection(collection: Schema.Collection.Data.AsLink): void;
58
+ removeCollection(collectionId: Schema.Collection.Id): boolean;
59
+ getPageRef(pageId: Schema.Page.Id | undefined): IPage.Ref | undefined;
60
+ addPageRef(ref: IPage.Ref): void;
61
+ removePageRef(pageId: Schema.Page.Id): boolean;
62
+ addTag(tag: Schema.Tag): void;
63
+ removeTag(tag: Schema.Tag): void;
64
+ }
65
+ export declare namespace Page {
66
+ type ConstructorArgs = {
67
+ template: Schema.Page;
68
+ eventBus: EventBus;
69
+ id: Schema.Page.Id;
70
+ groupId: Schema.Page.GroupId;
71
+ brand: string;
72
+ language: Language;
73
+ region: string;
74
+ url: string;
75
+ slug?: string;
76
+ name: string;
77
+ tags: Schema.Tag[];
78
+ content: Content;
79
+ files?: Asset[];
80
+ pages?: IPage.Ref[];
81
+ collections?: Schema.Collection.Data.AsLink[];
82
+ state: Schema.Page.State;
83
+ createdOn: number;
84
+ updatedOn: number;
85
+ publishedOn?: number;
86
+ publication?: number;
87
+ };
88
+ type Content = Array<Block | Section>;
89
+ }
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Page = void 0;
4
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
5
+ const components_1 = require("@nascentdigital/funnel-editor/components");
6
+ const rxjs_1 = require("rxjs");
7
+ // class
8
+ class Page {
9
+ constructor(args) {
10
+ var _a, _b, _c;
11
+ // initialize instance variables
12
+ this.id = args.id;
13
+ this.template = args.template;
14
+ this.eventBus = args.eventBus;
15
+ this.groupId = args.groupId;
16
+ this.brand = args.brand;
17
+ this.language = args.language;
18
+ this.region = args.region;
19
+ this.url = args.url;
20
+ this.publishedOn = args.publishedOn;
21
+ this.createdOn = args.createdOn;
22
+ this.updatedOn = args.updatedOn;
23
+ this.settings = new components_1.PageSettings(this);
24
+ this._content = args.content;
25
+ this._initialSlug = this._slug = args.slug;
26
+ this._assets = (_a = args.files) !== null && _a !== void 0 ? _a : [];
27
+ this._pages = (_b = args.pages) !== null && _b !== void 0 ? _b : [];
28
+ this._collections = (_c = args.collections) !== null && _c !== void 0 ? _c : [];
29
+ this._initialTags = new Set(args.tags);
30
+ this._tags = new Set(args.tags);
31
+ this._syncing = false;
32
+ // bind content
33
+ this._content.forEach((item) => item.bind({ parent: this, area: 'content' }));
34
+ }
35
+ get events$() {
36
+ return this.eventBus.events$;
37
+ }
38
+ get stable$() {
39
+ return this.eventBus.events$.pipe((0, rxjs_1.map)(() => !this._syncing && !this.modified), (0, rxjs_1.distinctUntilChanged)());
40
+ }
41
+ get modified() {
42
+ return false;
43
+ }
44
+ get published() {
45
+ return this.publishedOn !== undefined;
46
+ }
47
+ get syncing() {
48
+ return this._syncing;
49
+ }
50
+ get hasSlug() {
51
+ return this.template.variant === 'dynamic';
52
+ }
53
+ get slug() {
54
+ return this._slug;
55
+ }
56
+ get discover() {
57
+ return [];
58
+ }
59
+ get content() {
60
+ return this._content;
61
+ }
62
+ get blocks() {
63
+ return this.content
64
+ .flatMap((item) => item instanceof components_1.Section ? item.blocks : item);
65
+ }
66
+ get firstBlock() {
67
+ // find first block
68
+ for (const item of this.content) {
69
+ // return item if it matches
70
+ if (item instanceof components_1.Block) {
71
+ return item;
72
+ }
73
+ // search deeply into sections
74
+ else {
75
+ const { blocks } = item;
76
+ if (blocks.length > 0) {
77
+ return blocks[0];
78
+ }
79
+ }
80
+ }
81
+ // or return undefined
82
+ return undefined;
83
+ }
84
+ get firstItem() {
85
+ return this.content[0];
86
+ }
87
+ get items() {
88
+ return [...this._content];
89
+ }
90
+ get assets() {
91
+ return this._assets;
92
+ }
93
+ get collections() {
94
+ return this._collections;
95
+ }
96
+ get initialTags() {
97
+ return this._initialTags;
98
+ }
99
+ get tagGroups() {
100
+ return this.template.tags;
101
+ }
102
+ get tags() {
103
+ return this._tags;
104
+ }
105
+ getItem(identifier) {
106
+ // skip if there's no identifier
107
+ if (!identifier) {
108
+ return undefined;
109
+ }
110
+ // or return settings
111
+ else if (identifier === components_1.PageSettings.id) {
112
+ return this.settings;
113
+ }
114
+ // search content for item
115
+ for (const item of this.items) {
116
+ // return item if it matches
117
+ if (item.identifier === identifier) {
118
+ return item;
119
+ }
120
+ // search deeply into sections
121
+ if (item instanceof components_1.Section) {
122
+ for (const block of item.blocks) {
123
+ // return block if it matches
124
+ if (block.identifier === identifier) {
125
+ return block;
126
+ }
127
+ }
128
+ }
129
+ }
130
+ // or return undefined
131
+ return undefined;
132
+ }
133
+ coerceItem(identifier) {
134
+ var _a, _b;
135
+ return (_b = (_a = this.getItem(identifier)) !== null && _a !== void 0 ? _a : this.firstBlock) !== null && _b !== void 0 ? _b : this.firstItem;
136
+ }
137
+ deleteBlock(area, key) {
138
+ throw new Error('Method not implemented.');
139
+ }
140
+ getAsset(assetId) {
141
+ return this._assets.find((asset) => asset.value.id === assetId);
142
+ }
143
+ getAssetScope(range) {
144
+ throw new Error('Method not implemented.');
145
+ }
146
+ getSearchScope() {
147
+ throw new Error('Method not implemented.');
148
+ }
149
+ addAsset(asset) {
150
+ throw new Error('Method not implemented.');
151
+ }
152
+ removeAsset(assetId) {
153
+ throw new Error('Method not implemented.');
154
+ }
155
+ getCollection(collectionId) {
156
+ throw new Error('Method not implemented.');
157
+ }
158
+ addCollection(collection) {
159
+ throw new Error('Method not implemented.');
160
+ }
161
+ removeCollection(collectionId) {
162
+ throw new Error('Method not implemented.');
163
+ }
164
+ getPageRef(pageId) {
165
+ return pageId && pageId !== funnel_core_1.Schema.Page.Id.draft ? this._pages.find((ref) => ref.id === pageId) : undefined;
166
+ }
167
+ addPageRef(ref) {
168
+ throw new Error('Method not implemented.');
169
+ }
170
+ removePageRef(pageId) {
171
+ throw new Error('Method not implemented.');
172
+ }
173
+ addTag(tag) {
174
+ throw new Error('Method not implemented.');
175
+ }
176
+ removeTag(tag) {
177
+ throw new Error('Method not implemented.');
178
+ }
179
+ }
180
+ exports.Page = Page;
@@ -0,0 +1 @@
1
+ export * from './Page';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Page"), exports);
@@ -0,0 +1,3 @@
1
+ export * from './api';
2
+ export * from './domain';
3
+ export * from './repository';
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./api"), exports);
18
+ __exportStar(require("./domain"), exports);
19
+ __exportStar(require("./repository"), exports);
@@ -0,0 +1,12 @@
1
+ import { EventBus } from '@nascentdigital/funnel-core';
2
+ import { EditorApiClient } from '../api';
3
+ export declare class PageRepository {
4
+ readonly editorApi: EditorApiClient;
5
+ constructor(editorApi: EditorApiClient);
6
+ load({ eventBus }: PageRepository.LoadArgs): Promise<import("..").Page | undefined>;
7
+ }
8
+ export declare namespace PageRepository {
9
+ type LoadArgs = {
10
+ eventBus: EventBus;
11
+ };
12
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageRepository = void 0;
4
+ const PageSerializer_1 = require("./PageSerializer");
5
+ // class
6
+ class PageRepository {
7
+ constructor(editorApi) {
8
+ this.editorApi = editorApi;
9
+ }
10
+ async load({ eventBus }) {
11
+ // fetch current page
12
+ const { page: flattenedPage } = await this.editorApi.currentPageGroup();
13
+ if (!flattenedPage) {
14
+ return undefined;
15
+ }
16
+ // deserialize page
17
+ return PageSerializer_1.PageSerializer.deserializePage({
18
+ eventBus,
19
+ flattenedPage
20
+ });
21
+ }
22
+ }
23
+ exports.PageRepository = PageRepository;
@@ -0,0 +1,9 @@
1
+ import { EventBus, Schema } from '@nascentdigital/funnel-core';
2
+ import { Page } from '../domain';
3
+ export declare namespace PageSerializer {
4
+ type DeserializePageArgs = {
5
+ flattenedPage: Schema.Page.FlattenedData;
6
+ eventBus: EventBus;
7
+ };
8
+ function deserializePage({ flattenedPage, eventBus }: DeserializePageArgs): Page;
9
+ }
@@ -0,0 +1,44 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.PageSerializer = void 0;
15
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
16
+ const components_1 = require("@nascentdigital/funnel-editor/components");
17
+ const domain_1 = require("../domain");
18
+ // namespace
19
+ var PageSerializer;
20
+ (function (PageSerializer) {
21
+ function deserializePage({ flattenedPage, eventBus }) {
22
+ // destructure
23
+ const { data } = flattenedPage;
24
+ const { snapshot, content } = data, dataRest = __rest(data
25
+ // determine latest snapshot (if any)
26
+ , ["snapshot", "content"]);
27
+ // determine latest snapshot (if any)
28
+ const { content: contentSnapshot = {} } = snapshot !== null && snapshot !== void 0 ? snapshot : {};
29
+ // create new page using shared bus
30
+ const pageSchemas = funnel_core_1.Schema.Site.current().regions[data.region];
31
+ const template = pageSchemas[data.type];
32
+ // create new page
33
+ const page = new domain_1.Page(Object.assign(Object.assign({}, dataRest), { template, content: Object.entries(template.content).map(([key, schema]) => components_1.PageSerializer.deserializeContent({
34
+ key,
35
+ schema: schema.unwrap(),
36
+ eventBus,
37
+ content: content[key],
38
+ snapshot: contentSnapshot[key],
39
+ })), eventBus }));
40
+ // return
41
+ return page;
42
+ }
43
+ PageSerializer.deserializePage = deserializePage;
44
+ })(PageSerializer || (exports.PageSerializer = PageSerializer = {}));
@@ -0,0 +1 @@
1
+ export * from './PageRepository';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./PageRepository"), exports);
@@ -0,0 +1 @@
1
+ export * from './Editor';
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Editor"), exports);
@@ -0,0 +1,31 @@
1
+ import { Language } from '@nascentdigital/funnel-core';
2
+ import { IPage, IPageController, PageSummary } from '@nascentdigital/funnel-editor/components';
3
+ import { EditorApiClient, Page, PageRepository } from '../../core';
4
+ export declare class PageController implements IPageController {
5
+ private readonly _eventBus;
6
+ private _state;
7
+ private _pageSummary?;
8
+ private _page?;
9
+ readonly repository: PageRepository;
10
+ constructor({ editorApi }: PageController.ConstructorArgs);
11
+ get events$(): import("rxjs").Observable<IPage.Event | IPageController.Event>;
12
+ get saved$(): import("rxjs").Observable<[IPageController.StateChangedEvent, IPageController.StateChangedEvent]>;
13
+ get state(): IPageController.State;
14
+ private set state(value);
15
+ get ready(): boolean;
16
+ get languages(): ReadonlyArray<Language>;
17
+ get pageSummary(): PageSummary | undefined;
18
+ private set pageSummary(value);
19
+ get page(): Page | undefined;
20
+ private set page(value);
21
+ load(): Promise<void>;
22
+ create(target: IPageController.Target): Promise<void>;
23
+ reload(): Promise<void>;
24
+ unpublish(): Promise<void>;
25
+ private raiseEvent;
26
+ }
27
+ export declare namespace PageController {
28
+ type ConstructorArgs = {
29
+ editorApi: EditorApiClient;
30
+ };
31
+ }
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageController = void 0;
4
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
5
+ const components_1 = require("@nascentdigital/funnel-editor/components");
6
+ const rxjs_1 = require("rxjs");
7
+ const core_1 = require("../../core");
8
+ // class
9
+ class PageController {
10
+ constructor({ editorApi }) {
11
+ // initialize instance variables
12
+ this._eventBus = new funnel_core_1.EventBus();
13
+ this._state = 'uninitialized';
14
+ this.repository = new core_1.PageRepository(editorApi);
15
+ }
16
+ get events$() {
17
+ return this._eventBus.events$.pipe((0, rxjs_1.filter)((e) => components_1.IPageController.Event.filter(e) || components_1.IPage.Event.filter(e)));
18
+ }
19
+ get saved$() {
20
+ return this._eventBus.events$.pipe((0, rxjs_1.filter)(components_1.IPageController.StateChangedEvent.filter), (0, rxjs_1.pairwise)(), (0, rxjs_1.filter)(([previous, current]) => previous.state === 'saving' && current.state === 'ready'));
21
+ }
22
+ get state() {
23
+ return this._state;
24
+ }
25
+ set state(value) {
26
+ // skip if unchanged
27
+ if (this._state === value) {
28
+ return;
29
+ }
30
+ // or update
31
+ this._state = value;
32
+ // raise event
33
+ this._eventBus.publish(components_1.IPageController.StateChangedEvent.create({
34
+ state: value,
35
+ controller: this
36
+ }));
37
+ }
38
+ get ready() {
39
+ const { _state } = this;
40
+ return _state !== 'uninitialized' && _state !== 'initializing';
41
+ }
42
+ get languages() {
43
+ return [];
44
+ }
45
+ get pageSummary() {
46
+ return this._pageSummary;
47
+ }
48
+ set pageSummary(pageSummary) {
49
+ // skip if summary is the same
50
+ if (this._pageSummary === pageSummary) {
51
+ return;
52
+ }
53
+ // update summary
54
+ this._pageSummary = pageSummary;
55
+ // raise event
56
+ this.raiseEvent('pageSummary.changed');
57
+ }
58
+ get page() {
59
+ return this._page;
60
+ }
61
+ set page(page) {
62
+ // skip if page is the same
63
+ if (this._page === page) {
64
+ return;
65
+ }
66
+ // update page
67
+ this._page = page;
68
+ // raise state change
69
+ this.raiseEvent('page.changed');
70
+ }
71
+ async load() {
72
+ // mark as loading (or initialing if loading for first time)
73
+ this.state = this._state === 'uninitialized'
74
+ ? 'initializing'
75
+ : 'loading';
76
+ // try to load page
77
+ try {
78
+ // load page
79
+ const page = await this.repository.load({ eventBus: this._eventBus });
80
+ // set page
81
+ // TODO: create real page summary
82
+ this.pageSummary = new components_1.PageSummary({ pages: [{ state: 'draft' }] });
83
+ this.page = page;
84
+ // update state
85
+ this.state = 'ready';
86
+ }
87
+ // handle error
88
+ catch (e) {
89
+ console.error('[PageController] failed to load page', e);
90
+ // set error state
91
+ this.state = 'error';
92
+ }
93
+ }
94
+ async create(target) {
95
+ throw new funnel_core_1.NotImplementedError();
96
+ }
97
+ async reload() {
98
+ throw new funnel_core_1.NotImplementedError();
99
+ }
100
+ async unpublish() {
101
+ throw new funnel_core_1.NotImplementedError();
102
+ }
103
+ raiseEvent(type) {
104
+ this._eventBus.publish(components_1.IPageController.Event.create({ type, controller: this }));
105
+ }
106
+ }
107
+ exports.PageController = PageController;
@@ -0,0 +1 @@
1
+ export * from './PageController';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./PageController"), exports);
@@ -0,0 +1 @@
1
+ export * from './screens';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./screens"), exports);
@@ -0,0 +1 @@
1
+ export declare function PageEditor(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PageEditor = PageEditor;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const components_1 = require("@nascentdigital/funnel-editor/components");
6
+ const react_1 = require("react");
7
+ const core_1 = require("../../core");
8
+ const hooks_1 = require("../hooks");
9
+ // component
10
+ function PageEditor() {
11
+ // hooks
12
+ const editorApi = (0, core_1.useEditorApi)();
13
+ const { controller, controllerContext } = (0, react_1.useMemo)(() => {
14
+ const controller = new hooks_1.PageController({ editorApi });
15
+ return {
16
+ controller,
17
+ controllerContext: { controller }
18
+ };
19
+ }, [editorApi]);
20
+ const { page } = controller;
21
+ const pageContext = (0, react_1.useMemo)(() => ({ page }), [page]);
22
+ const [itemId, setItemId] = (0, react_1.useState)();
23
+ const selectedItem = (0, react_1.useMemo)(() => page === null || page === void 0 ? void 0 : page.coerceItem(itemId), [page, itemId]);
24
+ // sync with controller
25
+ (0, components_1.usePageController)(controller);
26
+ // load
27
+ (0, react_1.useEffect)(() => {
28
+ controller.load().catch(console.error);
29
+ }, [controller]);
30
+ const onSelectItem = (item) => setItemId(item.identifier);
31
+ // render
32
+ return ((0, jsx_runtime_1.jsx)(components_1.PageControllerContext.Provider, { value: controllerContext, children: (0, jsx_runtime_1.jsx)(components_1.PageContext.Provider, { value: pageContext, children: (0, jsx_runtime_1.jsx)(components_1.AssetStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)(components_1.CollectionStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)(components_1.PageRefStoreContext.Provider, { value: page, children: (0, jsx_runtime_1.jsx)("div", { className: "bg-background flex h-dvh w-dvw flex-col", children: (0, jsx_runtime_1.jsx)("div", { className: "relative flex-1", children: (0, jsx_runtime_1.jsxs)("div", { className: "absolute inset-0 flex", children: [(0, jsx_runtime_1.jsx)("section", { className: "scrollbar-thin w-[220px] shrink-0 overflow-y-scroll lg:w-[240px] xl:w-[280px]", children: (0, jsx_runtime_1.jsx)(components_1.PageNav, { selectedItem: selectedItem, onSelectItem: onSelectItem }) }), (0, jsx_runtime_1.jsx)("section", { className: "mx-auto h-full max-h-full max-w-[1000px] flex-1", children: renderContent({ controller, page, selectedItem, onSelectItem }) })] }) }) }) }) }) }) }) }));
33
+ }
34
+ function renderContent({ controller, page, selectedItem, onSelectItem }) {
35
+ // show loader if not ready
36
+ const { pageSummary } = controller;
37
+ if (!controller.ready) {
38
+ return (0, jsx_runtime_1.jsx)(components_1.Loader, {});
39
+ }
40
+ // show not found if there's no group
41
+ else if (!pageSummary || (!pageSummary.hasPages && pageSummary.variant !== 'static')) {
42
+ return ((0, jsx_runtime_1.jsx)(components_1.EmptyState, { variant: "missing", size: "md", children: "Oops! This page doesn't seem to exist..." }));
43
+ }
44
+ // or handle case where page doesn't exist
45
+ else if (!page) {
46
+ return null;
47
+ }
48
+ // or render loader if we don't have an item selected
49
+ else if (!selectedItem || selectedItem instanceof components_1.Section) {
50
+ return null;
51
+ }
52
+ // or settings editor
53
+ else if (selectedItem instanceof components_1.PageSettings) {
54
+ return ((0, jsx_runtime_1.jsx)(components_1.SettingsEditor, { className: "h-full max-h-full" }));
55
+ }
56
+ // or render block editor
57
+ else {
58
+ return ((0, jsx_runtime_1.jsx)(components_1.BlockEditor, { className: "h-full max-h-full", block: selectedItem, onSelectItem: onSelectItem }));
59
+ }
60
+ }
@@ -0,0 +1 @@
1
+ export * from './PageEditor';
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./PageEditor"), exports);
@@ -0,0 +1,2 @@
1
+ @import "@nascentdigital/funnel-editor/dist/styles/index.css";
2
+ /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdHlsZXMvaW5kZXguY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6ImluZGV4LmNzcyIsInNvdXJjZXNDb250ZW50IjpbIkBpbXBvcnQgXCJAbmFzY2VudGRpZ2l0YWwvZnVubmVsLWVkaXRvci9kaXN0L3N0eWxlcy9pbmRleC5jc3NcIjsiXX0= */
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@nascentdigital/funnel-editor-contentful",
3
+ "version": "4.6.7",
4
+ "publishConfig": {
5
+ "registry": "https://registry.npmjs.org/",
6
+ "access": "restricted"
7
+ },
8
+ "repository": {
9
+ "url": "git+https://github.com/nascentdigital/funnel.git",
10
+ "directory": "libs/editor-contentful"
11
+ },
12
+ "main": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "exports": {
15
+ ".": "./dist/index.js",
16
+ "./styles.css": "./dist/styles/index.css"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "engines": {
22
+ "node": ">=22.0.0"
23
+ },
24
+ "scripts": {
25
+ "build": "npm-run-all -s build:*",
26
+ "build:compile": "tsc -P tsconfig.build.json",
27
+ "build:css": "postcss ./src/styles/index.css -o ./dist/styles/index.css --verbose",
28
+ "clean": "rimraf -I dist",
29
+ "test": "jest"
30
+ },
31
+ "peerDependencies": {
32
+ "@nascentdigital/funnel-cms": "*",
33
+ "@nascentdigital/funnel-core": "*",
34
+ "@nascentdigital/funnel-ui": "*",
35
+ "next": "^15",
36
+ "react": "^19",
37
+ "react-dom": "^19"
38
+ },
39
+ "dependencies": {
40
+ "@contentful/app-sdk": "^4.69.0",
41
+ "@contentful/react-apps-toolkit": "^2.0.1",
42
+ "@nascentdigital/funnel-editor": "^4.6.7"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^22",
46
+ "autoprefixer": "^10",
47
+ "jest": "^29",
48
+ "npm-run-all": "^4",
49
+ "postcss": "^8",
50
+ "postcss-cli": "^11",
51
+ "postcss-import": "^16",
52
+ "tailwindcss": "^3",
53
+ "ts-jest": "^29",
54
+ "type-fest": "^4"
55
+ },
56
+ "gitHead": "b17e33b4400391b3984e61225c572f097c4c26c9"
57
+ }