@elementor/editor-embedded-documents-manager 4.2.0-936

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.
@@ -0,0 +1,37 @@
1
+ import { Document } from '@elementor/editor-documents';
2
+
3
+ declare function init(): void;
4
+
5
+ type EmbeddedDocumentLoadCallback = (documentId: number, data: Document) => void;
6
+ declare function setCurrentDocumentId(id: number | null): void;
7
+ /**
8
+ * Adds post IDs to the manager. Any ID not yet loaded will be fetched;
9
+ * already-loaded posts are skipped without notifying listeners.
10
+ *
11
+ * @param {number[]} ids Post IDs to load.
12
+ */
13
+ declare function addDocuments(ids: number[]): void;
14
+ /**
15
+ * Registers a related post that was already fetched.
16
+ *
17
+ * @param {number} documentId The document / post ID.
18
+ * @param {Document} data The document data to deliver.
19
+ */
20
+ declare function setDocument(documentId: number, data: Document): void;
21
+ /**
22
+ * Registers a callback that is invoked whenever a related (non-current) post
23
+ * finishes loading. Already-loaded related posts are delivered to the callback
24
+ * asynchronously on subscribe. Returns an unsubscribe function.
25
+ *
26
+ * @param {EmbeddedDocumentLoadCallback} callback Function called with (documentId, data) on each load.
27
+ */
28
+ declare function onDocumentLoad(callback: EmbeddedDocumentLoadCallback): () => void;
29
+ declare function reset(): void;
30
+ declare const embeddedDocumentsManager: {
31
+ addDocuments: typeof addDocuments;
32
+ setDocument: typeof setDocument;
33
+ onDocumentLoad: typeof onDocumentLoad;
34
+ reset: typeof reset;
35
+ };
36
+
37
+ export { type EmbeddedDocumentLoadCallback, embeddedDocumentsManager, init, setCurrentDocumentId };
@@ -0,0 +1,37 @@
1
+ import { Document } from '@elementor/editor-documents';
2
+
3
+ declare function init(): void;
4
+
5
+ type EmbeddedDocumentLoadCallback = (documentId: number, data: Document) => void;
6
+ declare function setCurrentDocumentId(id: number | null): void;
7
+ /**
8
+ * Adds post IDs to the manager. Any ID not yet loaded will be fetched;
9
+ * already-loaded posts are skipped without notifying listeners.
10
+ *
11
+ * @param {number[]} ids Post IDs to load.
12
+ */
13
+ declare function addDocuments(ids: number[]): void;
14
+ /**
15
+ * Registers a related post that was already fetched.
16
+ *
17
+ * @param {number} documentId The document / post ID.
18
+ * @param {Document} data The document data to deliver.
19
+ */
20
+ declare function setDocument(documentId: number, data: Document): void;
21
+ /**
22
+ * Registers a callback that is invoked whenever a related (non-current) post
23
+ * finishes loading. Already-loaded related posts are delivered to the callback
24
+ * asynchronously on subscribe. Returns an unsubscribe function.
25
+ *
26
+ * @param {EmbeddedDocumentLoadCallback} callback Function called with (documentId, data) on each load.
27
+ */
28
+ declare function onDocumentLoad(callback: EmbeddedDocumentLoadCallback): () => void;
29
+ declare function reset(): void;
30
+ declare const embeddedDocumentsManager: {
31
+ addDocuments: typeof addDocuments;
32
+ setDocument: typeof setDocument;
33
+ onDocumentLoad: typeof onDocumentLoad;
34
+ reset: typeof reset;
35
+ };
36
+
37
+ export { type EmbeddedDocumentLoadCallback, embeddedDocumentsManager, init, setCurrentDocumentId };
package/dist/index.js ADDED
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ embeddedDocumentsManager: () => embeddedDocumentsManager,
24
+ init: () => init,
25
+ setCurrentDocumentId: () => setCurrentDocumentId
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+
29
+ // src/init.ts
30
+ var import_editor_documents = require("@elementor/editor-documents");
31
+ var import_editor_styles_repository2 = require("@elementor/editor-styles-repository");
32
+ var import_editor_v1_adapters2 = require("@elementor/editor-v1-adapters");
33
+
34
+ // src/manager.ts
35
+ var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
36
+
37
+ // src/styles-provider.ts
38
+ var import_editor_styles_repository = require("@elementor/editor-styles-repository");
39
+ var styles = [];
40
+ var documentStyles = /* @__PURE__ */ new Map();
41
+ var styleListeners = /* @__PURE__ */ new Set();
42
+ var embeddedDocumentsStylesProvider = (0, import_editor_styles_repository.createStylesProvider)({
43
+ key: "embedded-documents-styles",
44
+ priority: 75,
45
+ subscribe: (cb) => {
46
+ styleListeners.add(cb);
47
+ return () => {
48
+ styleListeners.delete(cb);
49
+ };
50
+ },
51
+ actions: {
52
+ all: () => styles,
53
+ get: (id) => styles.find((style) => style.id === id) ?? null
54
+ }
55
+ });
56
+ function notifyStyleListeners() {
57
+ styleListeners.forEach((cb) => cb());
58
+ }
59
+ function addEmbeddedDocumentStyles(documentId, document) {
60
+ const extracted = extractStylesFromDocument(document);
61
+ if (!extracted.length) {
62
+ if (!documentStyles.has(documentId)) {
63
+ return;
64
+ }
65
+ documentStyles.delete(documentId);
66
+ } else {
67
+ documentStyles.set(documentId, extracted);
68
+ }
69
+ styles = [...documentStyles.values()].flat();
70
+ notifyStyleListeners();
71
+ }
72
+ function clearEmbeddedDocumentsStyles() {
73
+ documentStyles = /* @__PURE__ */ new Map();
74
+ styles = [];
75
+ notifyStyleListeners();
76
+ }
77
+ function extractStylesFromDocument(document) {
78
+ if (!document.elements?.length) {
79
+ return [];
80
+ }
81
+ return document.elements.flatMap(extractStylesFromElement);
82
+ }
83
+ function extractStylesFromElement(element) {
84
+ return [
85
+ ...Object.values(element.styles ?? {}),
86
+ ...(element.elements ?? []).flatMap(extractStylesFromElement)
87
+ ];
88
+ }
89
+
90
+ // src/manager.ts
91
+ var pendingIds = /* @__PURE__ */ new Set();
92
+ var loadedDocuments = /* @__PURE__ */ new Map();
93
+ var listeners = /* @__PURE__ */ new Set();
94
+ var currentDocumentId = null;
95
+ function setCurrentDocumentId(id) {
96
+ currentDocumentId = id;
97
+ }
98
+ function addDocuments(ids) {
99
+ const newIds = ids.filter(
100
+ (id) => !isCurrentDocument(id) && !pendingIds.has(id) && !loadedDocuments.has(id)
101
+ );
102
+ newIds.forEach((id) => pendingIds.add(id));
103
+ if (!newIds.length) {
104
+ return;
105
+ }
106
+ void fetchAndNotify(newIds);
107
+ }
108
+ function setDocument(documentId, data) {
109
+ if (isCurrentDocument(documentId)) {
110
+ return;
111
+ }
112
+ const isNew = !loadedDocuments.has(documentId);
113
+ loadedDocuments.set(documentId, data);
114
+ if (isNew) {
115
+ notifyListeners(documentId, data);
116
+ } else {
117
+ addEmbeddedDocumentStyles(documentId, data);
118
+ }
119
+ }
120
+ function onDocumentLoad(callback) {
121
+ listeners.add(callback);
122
+ void Promise.resolve().then(() => {
123
+ if (!listeners.has(callback)) {
124
+ return;
125
+ }
126
+ loadedDocuments.forEach((data, documentId) => {
127
+ if (!isCurrentDocument(documentId)) {
128
+ callback(documentId, data);
129
+ }
130
+ });
131
+ });
132
+ return () => {
133
+ listeners.delete(callback);
134
+ };
135
+ }
136
+ function reset() {
137
+ pendingIds.clear();
138
+ loadedDocuments.clear();
139
+ clearEmbeddedDocumentsStyles();
140
+ }
141
+ var embeddedDocumentsManager = {
142
+ addDocuments,
143
+ setDocument,
144
+ onDocumentLoad,
145
+ reset
146
+ };
147
+ function isCurrentDocument(documentId) {
148
+ return currentDocumentId !== null && documentId === currentDocumentId;
149
+ }
150
+ async function fetchAndNotify(ids) {
151
+ const results = await Promise.all(ids.map(fetchDocument));
152
+ results.forEach((result, index) => {
153
+ const id = ids[index];
154
+ if (!pendingIds.has(id)) {
155
+ return;
156
+ }
157
+ pendingIds.delete(id);
158
+ if (!result || isCurrentDocument(id)) {
159
+ return;
160
+ }
161
+ const { data } = result;
162
+ loadedDocuments.set(id, data);
163
+ notifyListeners(id, data);
164
+ });
165
+ }
166
+ async function fetchDocument(id) {
167
+ try {
168
+ const data = await import_editor_v1_adapters.ajax.load({
169
+ data: { id },
170
+ action: "get_document_config",
171
+ unique_id: `embedded-document-${id}`
172
+ });
173
+ return { id, data };
174
+ } catch {
175
+ return null;
176
+ }
177
+ }
178
+ function notifyListeners(documentId, data) {
179
+ if (isCurrentDocument(documentId)) {
180
+ return;
181
+ }
182
+ listeners.forEach((cb) => cb(documentId, data));
183
+ addEmbeddedDocumentStyles(documentId, data);
184
+ }
185
+
186
+ // src/init.ts
187
+ function init() {
188
+ import_editor_styles_repository2.stylesRepository.register(embeddedDocumentsStylesProvider);
189
+ (0, import_editor_v1_adapters2.registerDataHook)("after", "editor/documents/attach-preview", () => {
190
+ const { id } = (0, import_editor_documents.getV1CurrentDocument)() ?? {};
191
+ setCurrentDocumentId(id ?? null);
192
+ embeddedDocumentsManager.reset();
193
+ });
194
+ }
195
+ // Annotate the CommonJS export names for ESM import in node:
196
+ 0 && (module.exports = {
197
+ embeddedDocumentsManager,
198
+ init,
199
+ setCurrentDocumentId
200
+ });
201
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/init.ts","../src/manager.ts","../src/styles-provider.ts"],"sourcesContent":["export { init } from './init';\nexport { embeddedDocumentsManager, setCurrentDocumentId } from './manager';\nexport type { EmbeddedDocumentLoadCallback } from './manager';\n","import { getV1CurrentDocument } from '@elementor/editor-documents';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { registerDataHook } from '@elementor/editor-v1-adapters';\n\nimport { embeddedDocumentsManager, setCurrentDocumentId } from './manager';\nimport { embeddedDocumentsStylesProvider } from './styles-provider';\n\nexport function init() {\n\tstylesRepository.register( embeddedDocumentsStylesProvider );\n\n\tregisterDataHook( 'after', 'editor/documents/attach-preview', () => {\n\t\tconst { id } = getV1CurrentDocument() ?? {};\n\n\t\tsetCurrentDocumentId( id ?? null );\n\t\tembeddedDocumentsManager.reset();\n\t} );\n}\n","import { type Document } from '@elementor/editor-documents';\nimport { ajax } from '@elementor/editor-v1-adapters';\n\nimport { addEmbeddedDocumentStyles, clearEmbeddedDocumentsStyles } from './styles-provider';\n\nexport type EmbeddedDocumentLoadCallback = ( documentId: number, data: Document ) => void;\n\ntype EmbeddedDocumentLoadListener = EmbeddedDocumentLoadCallback;\n\nconst pendingIds = new Set< number >();\nconst loadedDocuments = new Map< number, Document >();\nconst listeners = new Set< EmbeddedDocumentLoadListener >();\nlet currentDocumentId: number | null = null;\n\nexport function setCurrentDocumentId( id: number | null ): void {\n\tcurrentDocumentId = id;\n}\n\n/**\n * Adds post IDs to the manager. Any ID not yet loaded will be fetched;\n * already-loaded posts are skipped without notifying listeners.\n *\n * @param {number[]} ids Post IDs to load.\n */\nfunction addDocuments( ids: number[] ): void {\n\tconst newIds = ids.filter(\n\t\t( id ) => ! isCurrentDocument( id ) && ! pendingIds.has( id ) && ! loadedDocuments.has( id )\n\t);\n\n\tnewIds.forEach( ( id ) => pendingIds.add( id ) );\n\n\tif ( ! newIds.length ) {\n\t\treturn;\n\t}\n\n\tvoid fetchAndNotify( newIds );\n}\n\n/**\n * Registers a related post that was already fetched.\n *\n * @param {number} documentId The document / post ID.\n * @param {Document} data The document data to deliver.\n */\nfunction setDocument( documentId: number, data: Document ): void {\n\tif ( isCurrentDocument( documentId ) ) {\n\t\treturn;\n\t}\n\n\tconst isNew = ! loadedDocuments.has( documentId );\n\n\tloadedDocuments.set( documentId, data );\n\n\tif ( isNew ) {\n\t\tnotifyListeners( documentId, data );\n\t} else {\n\t\taddEmbeddedDocumentStyles( documentId, data );\n\t}\n}\n\n/**\n * Registers a callback that is invoked whenever a related (non-current) post\n * finishes loading. Already-loaded related posts are delivered to the callback\n * asynchronously on subscribe. Returns an unsubscribe function.\n *\n * @param {EmbeddedDocumentLoadCallback} callback Function called with (documentId, data) on each load.\n */\nfunction onDocumentLoad( callback: EmbeddedDocumentLoadCallback ): () => void {\n\tlisteners.add( callback );\n\n\tvoid Promise.resolve().then( () => {\n\t\tif ( ! listeners.has( callback ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tloadedDocuments.forEach( ( data, documentId ) => {\n\t\t\tif ( ! isCurrentDocument( documentId ) ) {\n\t\t\t\tcallback( documentId, data );\n\t\t\t}\n\t\t} );\n\t} );\n\n\treturn () => {\n\t\tlisteners.delete( callback );\n\t};\n}\n\nfunction reset(): void {\n\tpendingIds.clear();\n\tloadedDocuments.clear();\n\tclearEmbeddedDocumentsStyles();\n}\n\nexport const embeddedDocumentsManager = {\n\taddDocuments,\n\tsetDocument,\n\tonDocumentLoad,\n\treset,\n};\n\nfunction isCurrentDocument( documentId: number ): boolean {\n\treturn currentDocumentId !== null && documentId === currentDocumentId;\n}\n\nasync function fetchAndNotify( ids: number[] ): Promise< void > {\n\tconst results = await Promise.all( ids.map( fetchDocument ) );\n\n\tresults.forEach( ( result, index ) => {\n\t\tconst id = ids[ index ];\n\n\t\tif ( ! pendingIds.has( id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tpendingIds.delete( id );\n\n\t\tif ( ! result || isCurrentDocument( id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { data } = result;\n\t\tloadedDocuments.set( id, data );\n\t\tnotifyListeners( id, data );\n\t} );\n}\n\nasync function fetchDocument( id: number ): Promise< {\n\tid: number;\n\tdata: Document;\n} | null > {\n\ttry {\n\t\tconst data = await ajax.load< { id: number }, Document >( {\n\t\t\tdata: { id },\n\t\t\taction: 'get_document_config',\n\t\t\tunique_id: `embedded-document-${ id }`,\n\t\t} );\n\n\t\treturn { id, data };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction notifyListeners( documentId: number, data: Document ): void {\n\tif ( isCurrentDocument( documentId ) ) {\n\t\treturn;\n\t}\n\n\tlisteners.forEach( ( cb ) => cb( documentId, data ) );\n\taddEmbeddedDocumentStyles( documentId, data );\n}\n","import { type Document } from '@elementor/editor-documents';\nimport { type V1ElementData } from '@elementor/editor-elements';\nimport { type StyleDefinition } from '@elementor/editor-styles';\nimport { createStylesProvider } from '@elementor/editor-styles-repository';\n\nlet styles: StyleDefinition[] = [];\nlet documentStyles = new Map< number, StyleDefinition[] >();\nconst styleListeners = new Set< () => void >();\n\nexport const embeddedDocumentsStylesProvider = createStylesProvider( {\n\tkey: 'embedded-documents-styles',\n\tpriority: 75,\n\tsubscribe: ( cb ) => {\n\t\tstyleListeners.add( cb );\n\n\t\treturn () => {\n\t\t\tstyleListeners.delete( cb );\n\t\t};\n\t},\n\tactions: {\n\t\tall: () => styles,\n\t\tget: ( id ) => styles.find( ( style ) => style.id === id ) ?? null,\n\t},\n} );\n\nfunction notifyStyleListeners() {\n\tstyleListeners.forEach( ( cb ) => cb() );\n}\n\nexport function addEmbeddedDocumentStyles( documentId: number, document: Document ) {\n\tconst extracted = extractStylesFromDocument( document );\n\n\tif ( ! extracted.length ) {\n\t\tif ( ! documentStyles.has( documentId ) ) {\n\t\t\treturn;\n\t\t}\n\t\tdocumentStyles.delete( documentId );\n\t} else {\n\t\tdocumentStyles.set( documentId, extracted );\n\t}\n\n\tstyles = [ ...documentStyles.values() ].flat();\n\tnotifyStyleListeners();\n}\n\nexport function clearEmbeddedDocumentsStyles() {\n\tdocumentStyles = new Map();\n\tstyles = [];\n\tnotifyStyleListeners();\n}\n\nfunction extractStylesFromDocument( document: Document ): StyleDefinition[] {\n\tif ( ! document.elements?.length ) {\n\t\treturn [];\n\t}\n\n\treturn document.elements.flatMap( extractStylesFromElement );\n}\n\nfunction extractStylesFromElement( element: V1ElementData ): StyleDefinition[] {\n\treturn [\n\t\t...Object.values( element.styles ?? {} ),\n\t\t...( element.elements ?? [] ).flatMap( extractStylesFromElement ),\n\t];\n}\n"],"mappings":"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","names":["import_editor_styles_repository","import_editor_v1_adapters"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,172 @@
1
+ // src/init.ts
2
+ import { getV1CurrentDocument } from "@elementor/editor-documents";
3
+ import { stylesRepository } from "@elementor/editor-styles-repository";
4
+ import { registerDataHook } from "@elementor/editor-v1-adapters";
5
+
6
+ // src/manager.ts
7
+ import { ajax } from "@elementor/editor-v1-adapters";
8
+
9
+ // src/styles-provider.ts
10
+ import { createStylesProvider } from "@elementor/editor-styles-repository";
11
+ var styles = [];
12
+ var documentStyles = /* @__PURE__ */ new Map();
13
+ var styleListeners = /* @__PURE__ */ new Set();
14
+ var embeddedDocumentsStylesProvider = createStylesProvider({
15
+ key: "embedded-documents-styles",
16
+ priority: 75,
17
+ subscribe: (cb) => {
18
+ styleListeners.add(cb);
19
+ return () => {
20
+ styleListeners.delete(cb);
21
+ };
22
+ },
23
+ actions: {
24
+ all: () => styles,
25
+ get: (id) => styles.find((style) => style.id === id) ?? null
26
+ }
27
+ });
28
+ function notifyStyleListeners() {
29
+ styleListeners.forEach((cb) => cb());
30
+ }
31
+ function addEmbeddedDocumentStyles(documentId, document) {
32
+ const extracted = extractStylesFromDocument(document);
33
+ if (!extracted.length) {
34
+ if (!documentStyles.has(documentId)) {
35
+ return;
36
+ }
37
+ documentStyles.delete(documentId);
38
+ } else {
39
+ documentStyles.set(documentId, extracted);
40
+ }
41
+ styles = [...documentStyles.values()].flat();
42
+ notifyStyleListeners();
43
+ }
44
+ function clearEmbeddedDocumentsStyles() {
45
+ documentStyles = /* @__PURE__ */ new Map();
46
+ styles = [];
47
+ notifyStyleListeners();
48
+ }
49
+ function extractStylesFromDocument(document) {
50
+ if (!document.elements?.length) {
51
+ return [];
52
+ }
53
+ return document.elements.flatMap(extractStylesFromElement);
54
+ }
55
+ function extractStylesFromElement(element) {
56
+ return [
57
+ ...Object.values(element.styles ?? {}),
58
+ ...(element.elements ?? []).flatMap(extractStylesFromElement)
59
+ ];
60
+ }
61
+
62
+ // src/manager.ts
63
+ var pendingIds = /* @__PURE__ */ new Set();
64
+ var loadedDocuments = /* @__PURE__ */ new Map();
65
+ var listeners = /* @__PURE__ */ new Set();
66
+ var currentDocumentId = null;
67
+ function setCurrentDocumentId(id) {
68
+ currentDocumentId = id;
69
+ }
70
+ function addDocuments(ids) {
71
+ const newIds = ids.filter(
72
+ (id) => !isCurrentDocument(id) && !pendingIds.has(id) && !loadedDocuments.has(id)
73
+ );
74
+ newIds.forEach((id) => pendingIds.add(id));
75
+ if (!newIds.length) {
76
+ return;
77
+ }
78
+ void fetchAndNotify(newIds);
79
+ }
80
+ function setDocument(documentId, data) {
81
+ if (isCurrentDocument(documentId)) {
82
+ return;
83
+ }
84
+ const isNew = !loadedDocuments.has(documentId);
85
+ loadedDocuments.set(documentId, data);
86
+ if (isNew) {
87
+ notifyListeners(documentId, data);
88
+ } else {
89
+ addEmbeddedDocumentStyles(documentId, data);
90
+ }
91
+ }
92
+ function onDocumentLoad(callback) {
93
+ listeners.add(callback);
94
+ void Promise.resolve().then(() => {
95
+ if (!listeners.has(callback)) {
96
+ return;
97
+ }
98
+ loadedDocuments.forEach((data, documentId) => {
99
+ if (!isCurrentDocument(documentId)) {
100
+ callback(documentId, data);
101
+ }
102
+ });
103
+ });
104
+ return () => {
105
+ listeners.delete(callback);
106
+ };
107
+ }
108
+ function reset() {
109
+ pendingIds.clear();
110
+ loadedDocuments.clear();
111
+ clearEmbeddedDocumentsStyles();
112
+ }
113
+ var embeddedDocumentsManager = {
114
+ addDocuments,
115
+ setDocument,
116
+ onDocumentLoad,
117
+ reset
118
+ };
119
+ function isCurrentDocument(documentId) {
120
+ return currentDocumentId !== null && documentId === currentDocumentId;
121
+ }
122
+ async function fetchAndNotify(ids) {
123
+ const results = await Promise.all(ids.map(fetchDocument));
124
+ results.forEach((result, index) => {
125
+ const id = ids[index];
126
+ if (!pendingIds.has(id)) {
127
+ return;
128
+ }
129
+ pendingIds.delete(id);
130
+ if (!result || isCurrentDocument(id)) {
131
+ return;
132
+ }
133
+ const { data } = result;
134
+ loadedDocuments.set(id, data);
135
+ notifyListeners(id, data);
136
+ });
137
+ }
138
+ async function fetchDocument(id) {
139
+ try {
140
+ const data = await ajax.load({
141
+ data: { id },
142
+ action: "get_document_config",
143
+ unique_id: `embedded-document-${id}`
144
+ });
145
+ return { id, data };
146
+ } catch {
147
+ return null;
148
+ }
149
+ }
150
+ function notifyListeners(documentId, data) {
151
+ if (isCurrentDocument(documentId)) {
152
+ return;
153
+ }
154
+ listeners.forEach((cb) => cb(documentId, data));
155
+ addEmbeddedDocumentStyles(documentId, data);
156
+ }
157
+
158
+ // src/init.ts
159
+ function init() {
160
+ stylesRepository.register(embeddedDocumentsStylesProvider);
161
+ registerDataHook("after", "editor/documents/attach-preview", () => {
162
+ const { id } = getV1CurrentDocument() ?? {};
163
+ setCurrentDocumentId(id ?? null);
164
+ embeddedDocumentsManager.reset();
165
+ });
166
+ }
167
+ export {
168
+ embeddedDocumentsManager,
169
+ init,
170
+ setCurrentDocumentId
171
+ };
172
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/init.ts","../src/manager.ts","../src/styles-provider.ts"],"sourcesContent":["import { getV1CurrentDocument } from '@elementor/editor-documents';\nimport { stylesRepository } from '@elementor/editor-styles-repository';\nimport { registerDataHook } from '@elementor/editor-v1-adapters';\n\nimport { embeddedDocumentsManager, setCurrentDocumentId } from './manager';\nimport { embeddedDocumentsStylesProvider } from './styles-provider';\n\nexport function init() {\n\tstylesRepository.register( embeddedDocumentsStylesProvider );\n\n\tregisterDataHook( 'after', 'editor/documents/attach-preview', () => {\n\t\tconst { id } = getV1CurrentDocument() ?? {};\n\n\t\tsetCurrentDocumentId( id ?? null );\n\t\tembeddedDocumentsManager.reset();\n\t} );\n}\n","import { type Document } from '@elementor/editor-documents';\nimport { ajax } from '@elementor/editor-v1-adapters';\n\nimport { addEmbeddedDocumentStyles, clearEmbeddedDocumentsStyles } from './styles-provider';\n\nexport type EmbeddedDocumentLoadCallback = ( documentId: number, data: Document ) => void;\n\ntype EmbeddedDocumentLoadListener = EmbeddedDocumentLoadCallback;\n\nconst pendingIds = new Set< number >();\nconst loadedDocuments = new Map< number, Document >();\nconst listeners = new Set< EmbeddedDocumentLoadListener >();\nlet currentDocumentId: number | null = null;\n\nexport function setCurrentDocumentId( id: number | null ): void {\n\tcurrentDocumentId = id;\n}\n\n/**\n * Adds post IDs to the manager. Any ID not yet loaded will be fetched;\n * already-loaded posts are skipped without notifying listeners.\n *\n * @param {number[]} ids Post IDs to load.\n */\nfunction addDocuments( ids: number[] ): void {\n\tconst newIds = ids.filter(\n\t\t( id ) => ! isCurrentDocument( id ) && ! pendingIds.has( id ) && ! loadedDocuments.has( id )\n\t);\n\n\tnewIds.forEach( ( id ) => pendingIds.add( id ) );\n\n\tif ( ! newIds.length ) {\n\t\treturn;\n\t}\n\n\tvoid fetchAndNotify( newIds );\n}\n\n/**\n * Registers a related post that was already fetched.\n *\n * @param {number} documentId The document / post ID.\n * @param {Document} data The document data to deliver.\n */\nfunction setDocument( documentId: number, data: Document ): void {\n\tif ( isCurrentDocument( documentId ) ) {\n\t\treturn;\n\t}\n\n\tconst isNew = ! loadedDocuments.has( documentId );\n\n\tloadedDocuments.set( documentId, data );\n\n\tif ( isNew ) {\n\t\tnotifyListeners( documentId, data );\n\t} else {\n\t\taddEmbeddedDocumentStyles( documentId, data );\n\t}\n}\n\n/**\n * Registers a callback that is invoked whenever a related (non-current) post\n * finishes loading. Already-loaded related posts are delivered to the callback\n * asynchronously on subscribe. Returns an unsubscribe function.\n *\n * @param {EmbeddedDocumentLoadCallback} callback Function called with (documentId, data) on each load.\n */\nfunction onDocumentLoad( callback: EmbeddedDocumentLoadCallback ): () => void {\n\tlisteners.add( callback );\n\n\tvoid Promise.resolve().then( () => {\n\t\tif ( ! listeners.has( callback ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tloadedDocuments.forEach( ( data, documentId ) => {\n\t\t\tif ( ! isCurrentDocument( documentId ) ) {\n\t\t\t\tcallback( documentId, data );\n\t\t\t}\n\t\t} );\n\t} );\n\n\treturn () => {\n\t\tlisteners.delete( callback );\n\t};\n}\n\nfunction reset(): void {\n\tpendingIds.clear();\n\tloadedDocuments.clear();\n\tclearEmbeddedDocumentsStyles();\n}\n\nexport const embeddedDocumentsManager = {\n\taddDocuments,\n\tsetDocument,\n\tonDocumentLoad,\n\treset,\n};\n\nfunction isCurrentDocument( documentId: number ): boolean {\n\treturn currentDocumentId !== null && documentId === currentDocumentId;\n}\n\nasync function fetchAndNotify( ids: number[] ): Promise< void > {\n\tconst results = await Promise.all( ids.map( fetchDocument ) );\n\n\tresults.forEach( ( result, index ) => {\n\t\tconst id = ids[ index ];\n\n\t\tif ( ! pendingIds.has( id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tpendingIds.delete( id );\n\n\t\tif ( ! result || isCurrentDocument( id ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst { data } = result;\n\t\tloadedDocuments.set( id, data );\n\t\tnotifyListeners( id, data );\n\t} );\n}\n\nasync function fetchDocument( id: number ): Promise< {\n\tid: number;\n\tdata: Document;\n} | null > {\n\ttry {\n\t\tconst data = await ajax.load< { id: number }, Document >( {\n\t\t\tdata: { id },\n\t\t\taction: 'get_document_config',\n\t\t\tunique_id: `embedded-document-${ id }`,\n\t\t} );\n\n\t\treturn { id, data };\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction notifyListeners( documentId: number, data: Document ): void {\n\tif ( isCurrentDocument( documentId ) ) {\n\t\treturn;\n\t}\n\n\tlisteners.forEach( ( cb ) => cb( documentId, data ) );\n\taddEmbeddedDocumentStyles( documentId, data );\n}\n","import { type Document } from '@elementor/editor-documents';\nimport { type V1ElementData } from '@elementor/editor-elements';\nimport { type StyleDefinition } from '@elementor/editor-styles';\nimport { createStylesProvider } from '@elementor/editor-styles-repository';\n\nlet styles: StyleDefinition[] = [];\nlet documentStyles = new Map< number, StyleDefinition[] >();\nconst styleListeners = new Set< () => void >();\n\nexport const embeddedDocumentsStylesProvider = createStylesProvider( {\n\tkey: 'embedded-documents-styles',\n\tpriority: 75,\n\tsubscribe: ( cb ) => {\n\t\tstyleListeners.add( cb );\n\n\t\treturn () => {\n\t\t\tstyleListeners.delete( cb );\n\t\t};\n\t},\n\tactions: {\n\t\tall: () => styles,\n\t\tget: ( id ) => styles.find( ( style ) => style.id === id ) ?? null,\n\t},\n} );\n\nfunction notifyStyleListeners() {\n\tstyleListeners.forEach( ( cb ) => cb() );\n}\n\nexport function addEmbeddedDocumentStyles( documentId: number, document: Document ) {\n\tconst extracted = extractStylesFromDocument( document );\n\n\tif ( ! extracted.length ) {\n\t\tif ( ! documentStyles.has( documentId ) ) {\n\t\t\treturn;\n\t\t}\n\t\tdocumentStyles.delete( documentId );\n\t} else {\n\t\tdocumentStyles.set( documentId, extracted );\n\t}\n\n\tstyles = [ ...documentStyles.values() ].flat();\n\tnotifyStyleListeners();\n}\n\nexport function clearEmbeddedDocumentsStyles() {\n\tdocumentStyles = new Map();\n\tstyles = [];\n\tnotifyStyleListeners();\n}\n\nfunction extractStylesFromDocument( document: Document ): StyleDefinition[] {\n\tif ( ! document.elements?.length ) {\n\t\treturn [];\n\t}\n\n\treturn document.elements.flatMap( extractStylesFromElement );\n}\n\nfunction extractStylesFromElement( element: V1ElementData ): StyleDefinition[] {\n\treturn [\n\t\t...Object.values( element.styles ?? {} ),\n\t\t...( element.elements ?? [] ).flatMap( extractStylesFromElement ),\n\t];\n}\n"],"mappings":";AAAA,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AACjC,SAAS,wBAAwB;;;ACDjC,SAAS,YAAY;;;ACErB,SAAS,4BAA4B;AAErC,IAAI,SAA4B,CAAC;AACjC,IAAI,iBAAiB,oBAAI,IAAiC;AAC1D,IAAM,iBAAiB,oBAAI,IAAkB;AAEtC,IAAM,kCAAkC,qBAAsB;AAAA,EACpE,KAAK;AAAA,EACL,UAAU;AAAA,EACV,WAAW,CAAE,OAAQ;AACpB,mBAAe,IAAK,EAAG;AAEvB,WAAO,MAAM;AACZ,qBAAe,OAAQ,EAAG;AAAA,IAC3B;AAAA,EACD;AAAA,EACA,SAAS;AAAA,IACR,KAAK,MAAM;AAAA,IACX,KAAK,CAAE,OAAQ,OAAO,KAAM,CAAE,UAAW,MAAM,OAAO,EAAG,KAAK;AAAA,EAC/D;AACD,CAAE;AAEF,SAAS,uBAAuB;AAC/B,iBAAe,QAAS,CAAE,OAAQ,GAAG,CAAE;AACxC;AAEO,SAAS,0BAA2B,YAAoB,UAAqB;AACnF,QAAM,YAAY,0BAA2B,QAAS;AAEtD,MAAK,CAAE,UAAU,QAAS;AACzB,QAAK,CAAE,eAAe,IAAK,UAAW,GAAI;AACzC;AAAA,IACD;AACA,mBAAe,OAAQ,UAAW;AAAA,EACnC,OAAO;AACN,mBAAe,IAAK,YAAY,SAAU;AAAA,EAC3C;AAEA,WAAS,CAAE,GAAG,eAAe,OAAO,CAAE,EAAE,KAAK;AAC7C,uBAAqB;AACtB;AAEO,SAAS,+BAA+B;AAC9C,mBAAiB,oBAAI,IAAI;AACzB,WAAS,CAAC;AACV,uBAAqB;AACtB;AAEA,SAAS,0BAA2B,UAAwC;AAC3E,MAAK,CAAE,SAAS,UAAU,QAAS;AAClC,WAAO,CAAC;AAAA,EACT;AAEA,SAAO,SAAS,SAAS,QAAS,wBAAyB;AAC5D;AAEA,SAAS,yBAA0B,SAA4C;AAC9E,SAAO;AAAA,IACN,GAAG,OAAO,OAAQ,QAAQ,UAAU,CAAC,CAAE;AAAA,IACvC,IAAK,QAAQ,YAAY,CAAC,GAAI,QAAS,wBAAyB;AAAA,EACjE;AACD;;;ADvDA,IAAM,aAAa,oBAAI,IAAc;AACrC,IAAM,kBAAkB,oBAAI,IAAwB;AACpD,IAAM,YAAY,oBAAI,IAAoC;AAC1D,IAAI,oBAAmC;AAEhC,SAAS,qBAAsB,IAA0B;AAC/D,sBAAoB;AACrB;AAQA,SAAS,aAAc,KAAsB;AAC5C,QAAM,SAAS,IAAI;AAAA,IAClB,CAAE,OAAQ,CAAE,kBAAmB,EAAG,KAAK,CAAE,WAAW,IAAK,EAAG,KAAK,CAAE,gBAAgB,IAAK,EAAG;AAAA,EAC5F;AAEA,SAAO,QAAS,CAAE,OAAQ,WAAW,IAAK,EAAG,CAAE;AAE/C,MAAK,CAAE,OAAO,QAAS;AACtB;AAAA,EACD;AAEA,OAAK,eAAgB,MAAO;AAC7B;AAQA,SAAS,YAAa,YAAoB,MAAuB;AAChE,MAAK,kBAAmB,UAAW,GAAI;AACtC;AAAA,EACD;AAEA,QAAM,QAAQ,CAAE,gBAAgB,IAAK,UAAW;AAEhD,kBAAgB,IAAK,YAAY,IAAK;AAEtC,MAAK,OAAQ;AACZ,oBAAiB,YAAY,IAAK;AAAA,EACnC,OAAO;AACN,8BAA2B,YAAY,IAAK;AAAA,EAC7C;AACD;AASA,SAAS,eAAgB,UAAqD;AAC7E,YAAU,IAAK,QAAS;AAExB,OAAK,QAAQ,QAAQ,EAAE,KAAM,MAAM;AAClC,QAAK,CAAE,UAAU,IAAK,QAAS,GAAI;AAClC;AAAA,IACD;AAEA,oBAAgB,QAAS,CAAE,MAAM,eAAgB;AAChD,UAAK,CAAE,kBAAmB,UAAW,GAAI;AACxC,iBAAU,YAAY,IAAK;AAAA,MAC5B;AAAA,IACD,CAAE;AAAA,EACH,CAAE;AAEF,SAAO,MAAM;AACZ,cAAU,OAAQ,QAAS;AAAA,EAC5B;AACD;AAEA,SAAS,QAAc;AACtB,aAAW,MAAM;AACjB,kBAAgB,MAAM;AACtB,+BAA6B;AAC9B;AAEO,IAAM,2BAA2B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAEA,SAAS,kBAAmB,YAA8B;AACzD,SAAO,sBAAsB,QAAQ,eAAe;AACrD;AAEA,eAAe,eAAgB,KAAiC;AAC/D,QAAM,UAAU,MAAM,QAAQ,IAAK,IAAI,IAAK,aAAc,CAAE;AAE5D,UAAQ,QAAS,CAAE,QAAQ,UAAW;AACrC,UAAM,KAAK,IAAK,KAAM;AAEtB,QAAK,CAAE,WAAW,IAAK,EAAG,GAAI;AAC7B;AAAA,IACD;AAEA,eAAW,OAAQ,EAAG;AAEtB,QAAK,CAAE,UAAU,kBAAmB,EAAG,GAAI;AAC1C;AAAA,IACD;AAEA,UAAM,EAAE,KAAK,IAAI;AACjB,oBAAgB,IAAK,IAAI,IAAK;AAC9B,oBAAiB,IAAI,IAAK;AAAA,EAC3B,CAAE;AACH;AAEA,eAAe,cAAe,IAGnB;AACV,MAAI;AACH,UAAM,OAAO,MAAM,KAAK,KAAkC;AAAA,MACzD,MAAM,EAAE,GAAG;AAAA,MACX,QAAQ;AAAA,MACR,WAAW,qBAAsB,EAAG;AAAA,IACrC,CAAE;AAEF,WAAO,EAAE,IAAI,KAAK;AAAA,EACnB,QAAQ;AACP,WAAO;AAAA,EACR;AACD;AAEA,SAAS,gBAAiB,YAAoB,MAAuB;AACpE,MAAK,kBAAmB,UAAW,GAAI;AACtC;AAAA,EACD;AAEA,YAAU,QAAS,CAAE,OAAQ,GAAI,YAAY,IAAK,CAAE;AACpD,4BAA2B,YAAY,IAAK;AAC7C;;;AD/IO,SAAS,OAAO;AACtB,mBAAiB,SAAU,+BAAgC;AAE3D,mBAAkB,SAAS,mCAAmC,MAAM;AACnE,UAAM,EAAE,GAAG,IAAI,qBAAqB,KAAK,CAAC;AAE1C,yBAAsB,MAAM,IAAK;AACjC,6BAAyB,MAAM;AAAA,EAChC,CAAE;AACH;","names":[]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@elementor/editor-embedded-documents-manager",
3
+ "description": "Shared related-posts registry for the Elementor editor",
4
+ "version": "4.2.0-936",
5
+ "private": false,
6
+ "author": "Elementor Team",
7
+ "homepage": "https://elementor.com/",
8
+ "license": "GPL-3.0-or-later",
9
+ "main": "dist/index.js",
10
+ "module": "dist/index.mjs",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.js"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/elementor/elementor.git",
23
+ "directory": "packages/core/editor-embedded-documents-manager"
24
+ },
25
+ "bugs": {
26
+ "url": "https://github.com/elementor/elementor/issues"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "files": [
32
+ "README.md",
33
+ "CHANGELOG.md",
34
+ "/dist",
35
+ "/src",
36
+ "!**/__tests__"
37
+ ],
38
+ "scripts": {
39
+ "build": "tsup --config=../../tsup.build.ts",
40
+ "dev": "tsup --config=../../tsup.dev.ts"
41
+ },
42
+ "dependencies": {
43
+ "@elementor/editor-documents": "4.2.0-936",
44
+ "@elementor/editor-elements": "4.2.0-936",
45
+ "@elementor/editor-v1-adapters": "4.2.0-936",
46
+ "@elementor/editor-styles": "4.2.0-936",
47
+ "@elementor/editor-styles-repository": "4.2.0-936"
48
+ },
49
+ "devDependencies": {
50
+ "tsup": "^8.3.5"
51
+ }
52
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { init } from './init';
2
+ export { embeddedDocumentsManager, setCurrentDocumentId } from './manager';
3
+ export type { EmbeddedDocumentLoadCallback } from './manager';
package/src/init.ts ADDED
@@ -0,0 +1,17 @@
1
+ import { getV1CurrentDocument } from '@elementor/editor-documents';
2
+ import { stylesRepository } from '@elementor/editor-styles-repository';
3
+ import { registerDataHook } from '@elementor/editor-v1-adapters';
4
+
5
+ import { embeddedDocumentsManager, setCurrentDocumentId } from './manager';
6
+ import { embeddedDocumentsStylesProvider } from './styles-provider';
7
+
8
+ export function init() {
9
+ stylesRepository.register( embeddedDocumentsStylesProvider );
10
+
11
+ registerDataHook( 'after', 'editor/documents/attach-preview', () => {
12
+ const { id } = getV1CurrentDocument() ?? {};
13
+
14
+ setCurrentDocumentId( id ?? null );
15
+ embeddedDocumentsManager.reset();
16
+ } );
17
+ }
package/src/manager.ts ADDED
@@ -0,0 +1,151 @@
1
+ import { type Document } from '@elementor/editor-documents';
2
+ import { ajax } from '@elementor/editor-v1-adapters';
3
+
4
+ import { addEmbeddedDocumentStyles, clearEmbeddedDocumentsStyles } from './styles-provider';
5
+
6
+ export type EmbeddedDocumentLoadCallback = ( documentId: number, data: Document ) => void;
7
+
8
+ type EmbeddedDocumentLoadListener = EmbeddedDocumentLoadCallback;
9
+
10
+ const pendingIds = new Set< number >();
11
+ const loadedDocuments = new Map< number, Document >();
12
+ const listeners = new Set< EmbeddedDocumentLoadListener >();
13
+ let currentDocumentId: number | null = null;
14
+
15
+ export function setCurrentDocumentId( id: number | null ): void {
16
+ currentDocumentId = id;
17
+ }
18
+
19
+ /**
20
+ * Adds post IDs to the manager. Any ID not yet loaded will be fetched;
21
+ * already-loaded posts are skipped without notifying listeners.
22
+ *
23
+ * @param {number[]} ids Post IDs to load.
24
+ */
25
+ function addDocuments( ids: number[] ): void {
26
+ const newIds = ids.filter(
27
+ ( id ) => ! isCurrentDocument( id ) && ! pendingIds.has( id ) && ! loadedDocuments.has( id )
28
+ );
29
+
30
+ newIds.forEach( ( id ) => pendingIds.add( id ) );
31
+
32
+ if ( ! newIds.length ) {
33
+ return;
34
+ }
35
+
36
+ void fetchAndNotify( newIds );
37
+ }
38
+
39
+ /**
40
+ * Registers a related post that was already fetched.
41
+ *
42
+ * @param {number} documentId The document / post ID.
43
+ * @param {Document} data The document data to deliver.
44
+ */
45
+ function setDocument( documentId: number, data: Document ): void {
46
+ if ( isCurrentDocument( documentId ) ) {
47
+ return;
48
+ }
49
+
50
+ const isNew = ! loadedDocuments.has( documentId );
51
+
52
+ loadedDocuments.set( documentId, data );
53
+
54
+ if ( isNew ) {
55
+ notifyListeners( documentId, data );
56
+ } else {
57
+ addEmbeddedDocumentStyles( documentId, data );
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Registers a callback that is invoked whenever a related (non-current) post
63
+ * finishes loading. Already-loaded related posts are delivered to the callback
64
+ * asynchronously on subscribe. Returns an unsubscribe function.
65
+ *
66
+ * @param {EmbeddedDocumentLoadCallback} callback Function called with (documentId, data) on each load.
67
+ */
68
+ function onDocumentLoad( callback: EmbeddedDocumentLoadCallback ): () => void {
69
+ listeners.add( callback );
70
+
71
+ void Promise.resolve().then( () => {
72
+ if ( ! listeners.has( callback ) ) {
73
+ return;
74
+ }
75
+
76
+ loadedDocuments.forEach( ( data, documentId ) => {
77
+ if ( ! isCurrentDocument( documentId ) ) {
78
+ callback( documentId, data );
79
+ }
80
+ } );
81
+ } );
82
+
83
+ return () => {
84
+ listeners.delete( callback );
85
+ };
86
+ }
87
+
88
+ function reset(): void {
89
+ pendingIds.clear();
90
+ loadedDocuments.clear();
91
+ clearEmbeddedDocumentsStyles();
92
+ }
93
+
94
+ export const embeddedDocumentsManager = {
95
+ addDocuments,
96
+ setDocument,
97
+ onDocumentLoad,
98
+ reset,
99
+ };
100
+
101
+ function isCurrentDocument( documentId: number ): boolean {
102
+ return currentDocumentId !== null && documentId === currentDocumentId;
103
+ }
104
+
105
+ async function fetchAndNotify( ids: number[] ): Promise< void > {
106
+ const results = await Promise.all( ids.map( fetchDocument ) );
107
+
108
+ results.forEach( ( result, index ) => {
109
+ const id = ids[ index ];
110
+
111
+ if ( ! pendingIds.has( id ) ) {
112
+ return;
113
+ }
114
+
115
+ pendingIds.delete( id );
116
+
117
+ if ( ! result || isCurrentDocument( id ) ) {
118
+ return;
119
+ }
120
+
121
+ const { data } = result;
122
+ loadedDocuments.set( id, data );
123
+ notifyListeners( id, data );
124
+ } );
125
+ }
126
+
127
+ async function fetchDocument( id: number ): Promise< {
128
+ id: number;
129
+ data: Document;
130
+ } | null > {
131
+ try {
132
+ const data = await ajax.load< { id: number }, Document >( {
133
+ data: { id },
134
+ action: 'get_document_config',
135
+ unique_id: `embedded-document-${ id }`,
136
+ } );
137
+
138
+ return { id, data };
139
+ } catch {
140
+ return null;
141
+ }
142
+ }
143
+
144
+ function notifyListeners( documentId: number, data: Document ): void {
145
+ if ( isCurrentDocument( documentId ) ) {
146
+ return;
147
+ }
148
+
149
+ listeners.forEach( ( cb ) => cb( documentId, data ) );
150
+ addEmbeddedDocumentStyles( documentId, data );
151
+ }
@@ -0,0 +1,65 @@
1
+ import { type Document } from '@elementor/editor-documents';
2
+ import { type V1ElementData } from '@elementor/editor-elements';
3
+ import { type StyleDefinition } from '@elementor/editor-styles';
4
+ import { createStylesProvider } from '@elementor/editor-styles-repository';
5
+
6
+ let styles: StyleDefinition[] = [];
7
+ let documentStyles = new Map< number, StyleDefinition[] >();
8
+ const styleListeners = new Set< () => void >();
9
+
10
+ export const embeddedDocumentsStylesProvider = createStylesProvider( {
11
+ key: 'embedded-documents-styles',
12
+ priority: 75,
13
+ subscribe: ( cb ) => {
14
+ styleListeners.add( cb );
15
+
16
+ return () => {
17
+ styleListeners.delete( cb );
18
+ };
19
+ },
20
+ actions: {
21
+ all: () => styles,
22
+ get: ( id ) => styles.find( ( style ) => style.id === id ) ?? null,
23
+ },
24
+ } );
25
+
26
+ function notifyStyleListeners() {
27
+ styleListeners.forEach( ( cb ) => cb() );
28
+ }
29
+
30
+ export function addEmbeddedDocumentStyles( documentId: number, document: Document ) {
31
+ const extracted = extractStylesFromDocument( document );
32
+
33
+ if ( ! extracted.length ) {
34
+ if ( ! documentStyles.has( documentId ) ) {
35
+ return;
36
+ }
37
+ documentStyles.delete( documentId );
38
+ } else {
39
+ documentStyles.set( documentId, extracted );
40
+ }
41
+
42
+ styles = [ ...documentStyles.values() ].flat();
43
+ notifyStyleListeners();
44
+ }
45
+
46
+ export function clearEmbeddedDocumentsStyles() {
47
+ documentStyles = new Map();
48
+ styles = [];
49
+ notifyStyleListeners();
50
+ }
51
+
52
+ function extractStylesFromDocument( document: Document ): StyleDefinition[] {
53
+ if ( ! document.elements?.length ) {
54
+ return [];
55
+ }
56
+
57
+ return document.elements.flatMap( extractStylesFromElement );
58
+ }
59
+
60
+ function extractStylesFromElement( element: V1ElementData ): StyleDefinition[] {
61
+ return [
62
+ ...Object.values( element.styles ?? {} ),
63
+ ...( element.elements ?? [] ).flatMap( extractStylesFromElement ),
64
+ ];
65
+ }