@elementor/editor-documents 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.5.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-documents@0.4.0...@elementor/editor-documents@0.5.0) (2023-05-30)
7
+
8
+
9
+ ### Features
10
+
11
+ * **editor-documents:** sync document name with V1 [ED-9930] ([#45](https://github.com/elementor/elementor-packages/issues/45)) ([b4d7250](https://github.com/elementor/elementor-packages/commit/b4d7250fb5ed03e21dafcf76a82756cf086ce212))
12
+
13
+
14
+
15
+
16
+
17
+ # [0.4.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-documents@0.3.0...@elementor/editor-documents@0.4.0) (2023-05-21)
18
+
19
+
20
+ ### Features
21
+
22
+ * **editor-site-navigation:** change post without refresh [ED-10713] ([#39](https://github.com/elementor/elementor-packages/issues/39)) ([b72e82f](https://github.com/elementor/elementor-packages/commit/b72e82f9adb9c1237300cbf603f33f268f9f0400))
23
+
24
+
25
+
26
+
27
+
6
28
  # 0.3.0 (2023-05-16)
7
29
 
8
30
 
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ declare function useActiveDocumentActions(): {
8
8
 
9
9
  declare function useHostDocument(): Document | null;
10
10
 
11
+ declare function useNavigateToDocument(): (id: number) => Promise<any>;
12
+
11
13
  type Document = {
12
14
  id: number;
13
15
  title: string;
@@ -74,4 +76,4 @@ type V1Model<T> = {
74
76
  get: <K extends keyof T = keyof T>(key: K) => T[K];
75
77
  };
76
78
 
77
- export { Document, ExtendedWindow, V1Document, useActiveDocument, useActiveDocumentActions, useHostDocument };
79
+ export { Document, ExtendedWindow, V1Document, useActiveDocument, useActiveDocumentActions, useHostDocument, useNavigateToDocument };
package/dist/index.js CHANGED
@@ -22,7 +22,8 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  useActiveDocument: () => useActiveDocument,
24
24
  useActiveDocumentActions: () => useActiveDocumentActions,
25
- useHostDocument: () => useHostDocument
25
+ useHostDocument: () => useHostDocument,
26
+ useNavigateToDocument: () => useNavigateToDocument
26
27
  });
27
28
  module.exports = __toCommonJS(src_exports);
28
29
 
@@ -68,6 +69,7 @@ function syncStore(slice) {
68
69
  syncInitialization(slice);
69
70
  syncActiveDocument(slice);
70
71
  syncOnDocumentSave(slice);
72
+ syncOnTitleChange(slice);
71
73
  syncOnDocumentChange(slice);
72
74
  }
73
75
  function syncInitialization(slice) {
@@ -89,13 +91,16 @@ function syncInitialization(slice) {
89
91
  );
90
92
  }
91
93
  function syncActiveDocument(slice) {
92
- const { activateDocument } = slice.actions;
94
+ const { activateDocument, setAsHost } = slice.actions;
93
95
  (0, import_editor_v1_adapters.listenTo)(
94
96
  (0, import_editor_v1_adapters.commandEndEvent)("editor/documents/open"),
95
97
  () => {
96
98
  const documentsManager = getV1DocumentsManager();
97
99
  const currentDocument = normalizeV1Document(documentsManager.getCurrent());
98
100
  (0, import_store.dispatch)(activateDocument(currentDocument));
101
+ if (documentsManager.getInitialId() === currentDocument.id) {
102
+ (0, import_store.dispatch)(setAsHost(currentDocument.id));
103
+ }
99
104
  }
100
105
  );
101
106
  }
@@ -129,6 +134,22 @@ function syncOnDocumentSave(slice) {
129
134
  }
130
135
  );
131
136
  }
137
+ function syncOnTitleChange(slice) {
138
+ const { updateActiveDocument } = slice.actions;
139
+ const updateTitle = debounce((e) => {
140
+ const event = e;
141
+ if (!("post_title" in event.args?.settings)) {
142
+ return;
143
+ }
144
+ const currentDocument = getV1DocumentsManager().getCurrent();
145
+ const newTitle = currentDocument.container.settings.get("post_title");
146
+ (0, import_store.dispatch)(updateActiveDocument({ title: newTitle }));
147
+ }, 400);
148
+ (0, import_editor_v1_adapters.listenTo)(
149
+ (0, import_editor_v1_adapters.commandEndEvent)("document/elements/settings"),
150
+ updateTitle
151
+ );
152
+ }
132
153
  function syncOnDocumentChange(slice) {
133
154
  const { markAsDirty, markAsPristine } = slice.actions;
134
155
  (0, import_editor_v1_adapters.listenTo)(
@@ -143,6 +164,15 @@ function syncOnDocumentChange(slice) {
143
164
  }
144
165
  );
145
166
  }
167
+ function debounce(fn, timeout) {
168
+ let timer;
169
+ return (...args) => {
170
+ clearTimeout(timer);
171
+ timer = setTimeout(() => {
172
+ fn(...args);
173
+ }, timeout);
174
+ };
175
+ }
146
176
 
147
177
  // src/store/index.ts
148
178
  var import_store2 = require("@elementor/store");
@@ -168,6 +198,17 @@ function createSlice() {
168
198
  state.entities[action.payload.id] = action.payload;
169
199
  state.activeId = action.payload.id;
170
200
  },
201
+ setAsHost(state, action) {
202
+ state.hostId = action.payload;
203
+ },
204
+ updateActiveDocument(state, action) {
205
+ if (hasActiveEntity(state)) {
206
+ state.entities[state.activeId] = {
207
+ ...state.entities[state.activeId],
208
+ ...action.payload
209
+ };
210
+ }
211
+ },
171
212
  startSaving(state) {
172
213
  if (hasActiveEntity(state)) {
173
214
  state.entities[state.activeId].isSaving = true;
@@ -261,12 +302,25 @@ function useHostDocument() {
261
302
  return (0, import_store6.useSelector)(selectHostDocument);
262
303
  }
263
304
 
305
+ // src/hooks/use-navigate-to-document.ts
306
+ var import_react2 = require("react");
307
+ var import_editor_v1_adapters3 = require("@elementor/editor-v1-adapters");
308
+ function useNavigateToDocument() {
309
+ return (0, import_react2.useCallback)((id) => {
310
+ return (0, import_editor_v1_adapters3.runCommand)("editor/documents/switch", {
311
+ id,
312
+ setAsInitial: true
313
+ });
314
+ }, []);
315
+ }
316
+
264
317
  // src/index.ts
265
318
  init();
266
319
  // Annotate the CommonJS export names for ESM import in node:
267
320
  0 && (module.exports = {
268
321
  useActiveDocument,
269
322
  useActiveDocumentActions,
270
- useHostDocument
323
+ useHostDocument,
324
+ useNavigateToDocument
271
325
  });
272
326
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sync/sync-store.ts","../src/sync/utils.ts","../src/store/index.ts","../src/init.ts","../src/hooks/use-active-document.ts","../src/store/selectors.ts","../src/hooks/use-active-document-actions.ts","../src/hooks/use-host-document.ts"],"sourcesContent":["import init from './init';\n\nexport * from './hooks';\nexport * from './types';\n\ninit();\n","import { Slice } from '../store';\nimport { Document } from '../types';\nimport { dispatch } from '@elementor/store';\nimport { normalizeV1Document, getV1DocumentsManager } from './utils';\nimport {\n\tcommandEndEvent,\n\tCommandEvent,\n\tcommandStartEvent,\n\tListenerEvent,\n\tlistenTo,\n\tv1ReadyEvent,\n} from '@elementor/editor-v1-adapters';\n\nexport function syncStore( slice: Slice ) {\n\tsyncInitialization( slice );\n\tsyncActiveDocument( slice );\n\tsyncOnDocumentSave( slice );\n\tsyncOnDocumentChange( slice );\n}\n\nfunction syncInitialization( slice: Slice ) {\n\tconst { init } = slice.actions;\n\n\tlistenTo(\n\t\tv1ReadyEvent(),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\n\t\t\tconst entities = Object.entries( documentsManager.documents )\n\t\t\t\t.reduce( ( acc: Record<string, Document>, [ id, document ] ) => {\n\t\t\t\t\tacc[ id ] = normalizeV1Document( document );\n\n\t\t\t\t\treturn acc;\n\t\t\t\t}, {} );\n\n\t\t\tdispatch( init( {\n\t\t\t\tentities,\n\t\t\t\thostId: documentsManager.getInitialId(),\n\t\t\t\tactiveId: documentsManager.getCurrentId(),\n\t\t\t} ) );\n\t\t}\n\t);\n}\n\nfunction syncActiveDocument( slice: Slice ) {\n\tconst { activateDocument } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'editor/documents/open' ),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\t\t\tconst currentDocument = normalizeV1Document( documentsManager.getCurrent() );\n\n\t\t\tdispatch( activateDocument( currentDocument ) );\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentSave( slice: Slice ) {\n\tconst { startSaving, endSaving, startSavingDraft, endSavingDraft } = slice.actions;\n\n\tconst isDraft = ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ status: string }>;\n\n\t\t/**\n\t\t * @see https://github.com/elementor/elementor/blob/5f815d40a/assets/dev/js/editor/document/save/hooks/ui/save/before.js#L18-L22\n\t\t */\n\t\treturn event.args?.status === 'autosave';\n\t};\n\n\tlistenTo(\n\t\tcommandStartEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( startSavingDraft() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( startSaving() );\n\t\t}\n\t);\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tconst activeDocument = normalizeV1Document(\n\t\t\t\tgetV1DocumentsManager().getCurrent()\n\t\t\t);\n\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( endSavingDraft( activeDocument ) );\n\t\t\t} else {\n\t\t\t\tdispatch( endSaving( activeDocument ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentChange( slice: Slice ) {\n\tconst { markAsDirty, markAsPristine } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/set-is-modified' ),\n\t\t() => {\n\t\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\n\t\t\tif ( currentDocument.editor.isChanged ) {\n\t\t\t\tdispatch( markAsDirty() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( markAsPristine() );\n\t\t}\n\t);\n}\n","import { Document, ExtendedWindow, V1Document } from '../types';\n\nexport function getV1DocumentsManager() {\n\tconst documentsManager = ( window as unknown as ExtendedWindow ).elementor?.documents;\n\n\tif ( ! documentsManager ) {\n\t\tthrow new Error( 'Elementor Editor V1 documents manager not found' );\n\t}\n\n\treturn documentsManager;\n}\n\nexport function normalizeV1Document( documentData: V1Document ): Document {\n\t// Draft or autosave.\n\tconst isUnpublishedRevision = documentData.config.revisions.current_id !== documentData.id;\n\n\treturn {\n\t\tid: documentData.id,\n\t\ttitle: documentData.container.settings.get( 'post_title' ),\n\t\ttype: {\n\t\t\tvalue: documentData.config.type,\n\t\t\tlabel: documentData.config.panel.title,\n\t\t},\n\t\tstatus: {\n\t\t\tvalue: documentData.config.status.value,\n\t\t\tlabel: documentData.config.status.label,\n\t\t},\n\t\tlinks: {\n\t\t\tplatformEdit: documentData.config.urls.exit_to_dashboard,\n\t\t},\n\t\tisDirty: documentData.editor.isChanged || isUnpublishedRevision,\n\t\tisSaving: documentData.editor.isSaving,\n\t\tisSavingDraft: false,\n\t\tuserCan: {\n\t\t\tpublish: documentData.config.user.can_publish,\n\t\t},\n\t};\n}\n","import { Document } from '../types';\nimport { addSlice, PayloadAction } from '@elementor/store';\n\ntype State = {\n\tentities: Record<Document['id'], Document>,\n\tactiveId: Document['id'] | null, // The currently editing document.\n\thostId: Document['id'] | null, // The document that host all the other documents.\n}\n\nexport type Slice = ReturnType<typeof createSlice>;\n\nconst initialState: State = {\n\tentities: {},\n\tactiveId: null,\n\thostId: null,\n};\n\ntype StateWithActiveId = Omit<State, 'activeId'> & { activeId: NonNullable<State['activeId']> };\n\nfunction hasActiveEntity( state: State ): state is StateWithActiveId {\n\treturn !! ( state.activeId && state.entities[ state.activeId ] );\n}\n\nexport function createSlice() {\n\treturn addSlice( {\n\t\tname: 'documents',\n\t\tinitialState,\n\t\treducers: {\n\t\t\tinit( state, { payload } : PayloadAction<State> ) {\n\t\t\t\tstate.entities = payload.entities;\n\t\t\t\tstate.hostId = payload.hostId;\n\t\t\t\tstate.activeId = payload.activeId;\n\t\t\t},\n\n\t\t\tactivateDocument( state, action: PayloadAction<Document> ) {\n\t\t\t\tstate.entities[ action.payload.id ] = action.payload;\n\t\t\t\tstate.activeId = action.payload.id;\n\t\t\t},\n\n\t\t\tstartSaving( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSaving = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSaving( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSaving: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSavingDraft: ( state ) => {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSavingDraft = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSavingDraft( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSavingDraft: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsDirty( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsPristine( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t} );\n}\n","import { syncStore } from './sync';\nimport { createSlice } from './store';\n\nexport default function init() {\n\tinitStore();\n}\n\nfunction initStore() {\n\tconst slice = createSlice();\n\n\tsyncStore( slice );\n}\n","import { useSelector } from '@elementor/store';\nimport { selectActiveDocument } from '../store/selectors';\n\nexport default function useActiveDocument() {\n\treturn useSelector( selectActiveDocument );\n}\n","import type { Slice } from './index';\nimport { createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState<Slice>;\n\nconst selectEntities = ( state: State ) => state.documents.entities;\nconst selectActiveId = ( state: State ) => state.documents.activeId;\nconst selectHostId = ( state: State ) => state.documents.hostId;\n\nexport const selectActiveDocument = createSelector(\n\tselectEntities,\n\tselectActiveId,\n\t( entities, activeId ) => activeId && entities[ activeId ]\n\t\t? entities[ activeId ]\n\t\t: null,\n);\n\nexport const selectHostDocument = createSelector(\n\tselectEntities,\n\tselectHostId,\n\t( entities, hostId ) => hostId && entities[ hostId ]\n\t\t? entities[ hostId ]\n\t\t: null,\n);\n","import { useCallback } from 'react';\nimport { openRoute, runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useActiveDocumentActions() {\n\tconst save = useCallback( () => runCommand( 'document/save/default' ), [] );\n\n\tconst saveDraft = useCallback( () => runCommand( 'document/save/draft' ), [] );\n\n\tconst saveTemplate = useCallback( () => openRoute( 'library/save-template' ), [] );\n\n\treturn {\n\t\tsave,\n\t\tsaveDraft,\n\t\tsaveTemplate,\n\t};\n}\n","import { useSelector } from '@elementor/store';\nimport { selectHostDocument } from '../store/selectors';\n\nexport default function useHostDocument() {\n\treturn useSelector( selectHostDocument );\n}\n"],"mappings":"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","names":["init","import_store","import_store","import_store","import_editor_v1_adapters","import_store"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sync/sync-store.ts","../src/sync/utils.ts","../src/store/index.ts","../src/init.ts","../src/hooks/use-active-document.ts","../src/store/selectors.ts","../src/hooks/use-active-document-actions.ts","../src/hooks/use-host-document.ts","../src/hooks/use-navigate-to-document.ts"],"sourcesContent":["import init from './init';\n\nexport * from './hooks';\nexport * from './types';\n\ninit();\n","import { Slice } from '../store';\nimport { Document } from '../types';\nimport { dispatch } from '@elementor/store';\nimport { normalizeV1Document, getV1DocumentsManager } from './utils';\nimport {\n\tcommandEndEvent,\n\tCommandEvent,\n\tcommandStartEvent,\n\tListenerEvent,\n\tlistenTo,\n\tv1ReadyEvent,\n} from '@elementor/editor-v1-adapters';\n\nexport function syncStore( slice: Slice ) {\n\tsyncInitialization( slice );\n\tsyncActiveDocument( slice );\n\tsyncOnDocumentSave( slice );\n\tsyncOnTitleChange( slice );\n\tsyncOnDocumentChange( slice );\n}\n\nfunction syncInitialization( slice: Slice ) {\n\tconst { init } = slice.actions;\n\n\tlistenTo(\n\t\tv1ReadyEvent(),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\n\t\t\tconst entities = Object.entries( documentsManager.documents )\n\t\t\t\t.reduce( ( acc: Record<string, Document>, [ id, document ] ) => {\n\t\t\t\t\tacc[ id ] = normalizeV1Document( document );\n\n\t\t\t\t\treturn acc;\n\t\t\t\t}, {} );\n\n\t\t\tdispatch( init( {\n\t\t\t\tentities,\n\t\t\t\thostId: documentsManager.getInitialId(),\n\t\t\t\tactiveId: documentsManager.getCurrentId(),\n\t\t\t} ) );\n\t\t}\n\t);\n}\n\nfunction syncActiveDocument( slice: Slice ) {\n\tconst { activateDocument, setAsHost } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'editor/documents/open' ),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\t\t\tconst currentDocument = normalizeV1Document( documentsManager.getCurrent() );\n\n\t\t\tdispatch( activateDocument( currentDocument ) );\n\n\t\t\tif ( documentsManager.getInitialId() === currentDocument.id ) {\n\t\t\t\tdispatch( setAsHost( currentDocument.id ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentSave( slice: Slice ) {\n\tconst { startSaving, endSaving, startSavingDraft, endSavingDraft } = slice.actions;\n\n\tconst isDraft = ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ status: string }>;\n\n\t\t/**\n\t\t * @see https://github.com/elementor/elementor/blob/5f815d40a/assets/dev/js/editor/document/save/hooks/ui/save/before.js#L18-L22\n\t\t */\n\t\treturn event.args?.status === 'autosave';\n\t};\n\n\tlistenTo(\n\t\tcommandStartEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( startSavingDraft() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( startSaving() );\n\t\t}\n\t);\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tconst activeDocument = normalizeV1Document(\n\t\t\t\tgetV1DocumentsManager().getCurrent()\n\t\t\t);\n\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( endSavingDraft( activeDocument ) );\n\t\t\t} else {\n\t\t\t\tdispatch( endSaving( activeDocument ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnTitleChange( slice: Slice ) {\n\tconst { updateActiveDocument } = slice.actions;\n\n\tconst updateTitle = debounce( ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ settings: { post_title?: string } }>;\n\n\t\tif ( ! ( 'post_title' in event.args?.settings ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\t\tconst newTitle = currentDocument.container.settings.get( 'post_title' );\n\n\t\tdispatch( updateActiveDocument( { title: newTitle } ) );\n\t}, 400 );\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/elements/settings' ),\n\t\tupdateTitle\n\t);\n}\n\nfunction syncOnDocumentChange( slice: Slice ) {\n\tconst { markAsDirty, markAsPristine } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/set-is-modified' ),\n\t\t() => {\n\t\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\n\t\t\tif ( currentDocument.editor.isChanged ) {\n\t\t\t\tdispatch( markAsDirty() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( markAsPristine() );\n\t\t}\n\t);\n}\n\nfunction debounce<TArgs extends unknown[]>( fn: ( ...args: TArgs ) => unknown, timeout: number ) {\n\tlet timer: ReturnType<typeof setTimeout>;\n\n\treturn ( ...args: TArgs ) => {\n\t\tclearTimeout( timer );\n\n\t\ttimer = setTimeout( () => {\n\t\t\tfn( ...args );\n\t\t}, timeout );\n\t};\n}\n","import { Document, ExtendedWindow, V1Document } from '../types';\n\nexport function getV1DocumentsManager() {\n\tconst documentsManager = ( window as unknown as ExtendedWindow ).elementor?.documents;\n\n\tif ( ! documentsManager ) {\n\t\tthrow new Error( 'Elementor Editor V1 documents manager not found' );\n\t}\n\n\treturn documentsManager;\n}\n\nexport function normalizeV1Document( documentData: V1Document ): Document {\n\t// Draft or autosave.\n\tconst isUnpublishedRevision = documentData.config.revisions.current_id !== documentData.id;\n\n\treturn {\n\t\tid: documentData.id,\n\t\ttitle: documentData.container.settings.get( 'post_title' ),\n\t\ttype: {\n\t\t\tvalue: documentData.config.type,\n\t\t\tlabel: documentData.config.panel.title,\n\t\t},\n\t\tstatus: {\n\t\t\tvalue: documentData.config.status.value,\n\t\t\tlabel: documentData.config.status.label,\n\t\t},\n\t\tlinks: {\n\t\t\tplatformEdit: documentData.config.urls.exit_to_dashboard,\n\t\t},\n\t\tisDirty: documentData.editor.isChanged || isUnpublishedRevision,\n\t\tisSaving: documentData.editor.isSaving,\n\t\tisSavingDraft: false,\n\t\tuserCan: {\n\t\t\tpublish: documentData.config.user.can_publish,\n\t\t},\n\t};\n}\n","import { Document } from '../types';\nimport { addSlice, PayloadAction } from '@elementor/store';\n\ntype State = {\n\tentities: Record<Document['id'], Document>,\n\tactiveId: Document['id'] | null, // The currently editing document.\n\thostId: Document['id'] | null, // The document that host all the other documents.\n}\n\nexport type Slice = ReturnType<typeof createSlice>;\n\nconst initialState: State = {\n\tentities: {},\n\tactiveId: null,\n\thostId: null,\n};\n\ntype StateWithActiveId = Omit<State, 'activeId'> & { activeId: NonNullable<State['activeId']> };\n\nfunction hasActiveEntity( state: State ): state is StateWithActiveId {\n\treturn !! ( state.activeId && state.entities[ state.activeId ] );\n}\n\nexport function createSlice() {\n\treturn addSlice( {\n\t\tname: 'documents',\n\t\tinitialState,\n\t\treducers: {\n\t\t\tinit( state, { payload } : PayloadAction<State> ) {\n\t\t\t\tstate.entities = payload.entities;\n\t\t\t\tstate.hostId = payload.hostId;\n\t\t\t\tstate.activeId = payload.activeId;\n\t\t\t},\n\n\t\t\tactivateDocument( state, action: PayloadAction<Document> ) {\n\t\t\t\tstate.entities[ action.payload.id ] = action.payload;\n\t\t\t\tstate.activeId = action.payload.id;\n\t\t\t},\n\n\t\t\tsetAsHost( state, action: PayloadAction<Document['id']> ) {\n\t\t\t\tstate.hostId = action.payload;\n\t\t\t},\n\n\t\t\tupdateActiveDocument( state, action: PayloadAction<Partial<Document>> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...state.entities[ state.activeId ],\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSaving( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSaving = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSaving( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSaving: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSavingDraft: ( state ) => {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSavingDraft = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSavingDraft( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSavingDraft: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsDirty( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsPristine( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t} );\n}\n","import { syncStore } from './sync';\nimport { createSlice } from './store';\n\nexport default function init() {\n\tinitStore();\n}\n\nfunction initStore() {\n\tconst slice = createSlice();\n\n\tsyncStore( slice );\n}\n","import { useSelector } from '@elementor/store';\nimport { selectActiveDocument } from '../store/selectors';\n\nexport default function useActiveDocument() {\n\treturn useSelector( selectActiveDocument );\n}\n","import type { Slice } from './index';\nimport { createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState<Slice>;\n\nconst selectEntities = ( state: State ) => state.documents.entities;\nconst selectActiveId = ( state: State ) => state.documents.activeId;\nconst selectHostId = ( state: State ) => state.documents.hostId;\n\nexport const selectActiveDocument = createSelector(\n\tselectEntities,\n\tselectActiveId,\n\t( entities, activeId ) => activeId && entities[ activeId ]\n\t\t? entities[ activeId ]\n\t\t: null,\n);\n\nexport const selectHostDocument = createSelector(\n\tselectEntities,\n\tselectHostId,\n\t( entities, hostId ) => hostId && entities[ hostId ]\n\t\t? entities[ hostId ]\n\t\t: null,\n);\n","import { useCallback } from 'react';\nimport { openRoute, runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useActiveDocumentActions() {\n\tconst save = useCallback( () => runCommand( 'document/save/default' ), [] );\n\n\tconst saveDraft = useCallback( () => runCommand( 'document/save/draft' ), [] );\n\n\tconst saveTemplate = useCallback( () => openRoute( 'library/save-template' ), [] );\n\n\treturn {\n\t\tsave,\n\t\tsaveDraft,\n\t\tsaveTemplate,\n\t};\n}\n","import { useSelector } from '@elementor/store';\nimport { selectHostDocument } from '../store/selectors';\n\nexport default function useHostDocument() {\n\treturn useSelector( selectHostDocument );\n}\n","import { useCallback } from 'react';\nimport { runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useNavigateToDocument() {\n\treturn useCallback( ( id: number ) => {\n\t\treturn runCommand( 'editor/documents/switch', {\n\t\t\tid,\n\t\t\tsetAsInitial: true,\n\t\t} );\n\t}, [] );\n}\n"],"mappings":"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","names":["init","import_store","import_store","import_store","import_editor_v1_adapters","import_store","import_react","import_editor_v1_adapters"]}
package/dist/index.mjs CHANGED
@@ -45,6 +45,7 @@ function syncStore(slice) {
45
45
  syncInitialization(slice);
46
46
  syncActiveDocument(slice);
47
47
  syncOnDocumentSave(slice);
48
+ syncOnTitleChange(slice);
48
49
  syncOnDocumentChange(slice);
49
50
  }
50
51
  function syncInitialization(slice) {
@@ -66,13 +67,16 @@ function syncInitialization(slice) {
66
67
  );
67
68
  }
68
69
  function syncActiveDocument(slice) {
69
- const { activateDocument } = slice.actions;
70
+ const { activateDocument, setAsHost } = slice.actions;
70
71
  listenTo(
71
72
  commandEndEvent("editor/documents/open"),
72
73
  () => {
73
74
  const documentsManager = getV1DocumentsManager();
74
75
  const currentDocument = normalizeV1Document(documentsManager.getCurrent());
75
76
  dispatch(activateDocument(currentDocument));
77
+ if (documentsManager.getInitialId() === currentDocument.id) {
78
+ dispatch(setAsHost(currentDocument.id));
79
+ }
76
80
  }
77
81
  );
78
82
  }
@@ -106,6 +110,22 @@ function syncOnDocumentSave(slice) {
106
110
  }
107
111
  );
108
112
  }
113
+ function syncOnTitleChange(slice) {
114
+ const { updateActiveDocument } = slice.actions;
115
+ const updateTitle = debounce((e) => {
116
+ const event = e;
117
+ if (!("post_title" in event.args?.settings)) {
118
+ return;
119
+ }
120
+ const currentDocument = getV1DocumentsManager().getCurrent();
121
+ const newTitle = currentDocument.container.settings.get("post_title");
122
+ dispatch(updateActiveDocument({ title: newTitle }));
123
+ }, 400);
124
+ listenTo(
125
+ commandEndEvent("document/elements/settings"),
126
+ updateTitle
127
+ );
128
+ }
109
129
  function syncOnDocumentChange(slice) {
110
130
  const { markAsDirty, markAsPristine } = slice.actions;
111
131
  listenTo(
@@ -120,6 +140,15 @@ function syncOnDocumentChange(slice) {
120
140
  }
121
141
  );
122
142
  }
143
+ function debounce(fn, timeout) {
144
+ let timer;
145
+ return (...args) => {
146
+ clearTimeout(timer);
147
+ timer = setTimeout(() => {
148
+ fn(...args);
149
+ }, timeout);
150
+ };
151
+ }
123
152
 
124
153
  // src/store/index.ts
125
154
  import { addSlice } from "@elementor/store";
@@ -145,6 +174,17 @@ function createSlice() {
145
174
  state.entities[action.payload.id] = action.payload;
146
175
  state.activeId = action.payload.id;
147
176
  },
177
+ setAsHost(state, action) {
178
+ state.hostId = action.payload;
179
+ },
180
+ updateActiveDocument(state, action) {
181
+ if (hasActiveEntity(state)) {
182
+ state.entities[state.activeId] = {
183
+ ...state.entities[state.activeId],
184
+ ...action.payload
185
+ };
186
+ }
187
+ },
148
188
  startSaving(state) {
149
189
  if (hasActiveEntity(state)) {
150
190
  state.entities[state.activeId].isSaving = true;
@@ -238,11 +278,24 @@ function useHostDocument() {
238
278
  return useSelector2(selectHostDocument);
239
279
  }
240
280
 
281
+ // src/hooks/use-navigate-to-document.ts
282
+ import { useCallback as useCallback2 } from "react";
283
+ import { runCommand as runCommand2 } from "@elementor/editor-v1-adapters";
284
+ function useNavigateToDocument() {
285
+ return useCallback2((id) => {
286
+ return runCommand2("editor/documents/switch", {
287
+ id,
288
+ setAsInitial: true
289
+ });
290
+ }, []);
291
+ }
292
+
241
293
  // src/index.ts
242
294
  init();
243
295
  export {
244
296
  useActiveDocument,
245
297
  useActiveDocumentActions,
246
- useHostDocument
298
+ useHostDocument,
299
+ useNavigateToDocument
247
300
  };
248
301
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sync/sync-store.ts","../src/sync/utils.ts","../src/store/index.ts","../src/init.ts","../src/hooks/use-active-document.ts","../src/store/selectors.ts","../src/hooks/use-active-document-actions.ts","../src/hooks/use-host-document.ts","../src/index.ts"],"sourcesContent":["import { Slice } from '../store';\nimport { Document } from '../types';\nimport { dispatch } from '@elementor/store';\nimport { normalizeV1Document, getV1DocumentsManager } from './utils';\nimport {\n\tcommandEndEvent,\n\tCommandEvent,\n\tcommandStartEvent,\n\tListenerEvent,\n\tlistenTo,\n\tv1ReadyEvent,\n} from '@elementor/editor-v1-adapters';\n\nexport function syncStore( slice: Slice ) {\n\tsyncInitialization( slice );\n\tsyncActiveDocument( slice );\n\tsyncOnDocumentSave( slice );\n\tsyncOnDocumentChange( slice );\n}\n\nfunction syncInitialization( slice: Slice ) {\n\tconst { init } = slice.actions;\n\n\tlistenTo(\n\t\tv1ReadyEvent(),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\n\t\t\tconst entities = Object.entries( documentsManager.documents )\n\t\t\t\t.reduce( ( acc: Record<string, Document>, [ id, document ] ) => {\n\t\t\t\t\tacc[ id ] = normalizeV1Document( document );\n\n\t\t\t\t\treturn acc;\n\t\t\t\t}, {} );\n\n\t\t\tdispatch( init( {\n\t\t\t\tentities,\n\t\t\t\thostId: documentsManager.getInitialId(),\n\t\t\t\tactiveId: documentsManager.getCurrentId(),\n\t\t\t} ) );\n\t\t}\n\t);\n}\n\nfunction syncActiveDocument( slice: Slice ) {\n\tconst { activateDocument } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'editor/documents/open' ),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\t\t\tconst currentDocument = normalizeV1Document( documentsManager.getCurrent() );\n\n\t\t\tdispatch( activateDocument( currentDocument ) );\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentSave( slice: Slice ) {\n\tconst { startSaving, endSaving, startSavingDraft, endSavingDraft } = slice.actions;\n\n\tconst isDraft = ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ status: string }>;\n\n\t\t/**\n\t\t * @see https://github.com/elementor/elementor/blob/5f815d40a/assets/dev/js/editor/document/save/hooks/ui/save/before.js#L18-L22\n\t\t */\n\t\treturn event.args?.status === 'autosave';\n\t};\n\n\tlistenTo(\n\t\tcommandStartEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( startSavingDraft() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( startSaving() );\n\t\t}\n\t);\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tconst activeDocument = normalizeV1Document(\n\t\t\t\tgetV1DocumentsManager().getCurrent()\n\t\t\t);\n\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( endSavingDraft( activeDocument ) );\n\t\t\t} else {\n\t\t\t\tdispatch( endSaving( activeDocument ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentChange( slice: Slice ) {\n\tconst { markAsDirty, markAsPristine } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/set-is-modified' ),\n\t\t() => {\n\t\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\n\t\t\tif ( currentDocument.editor.isChanged ) {\n\t\t\t\tdispatch( markAsDirty() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( markAsPristine() );\n\t\t}\n\t);\n}\n","import { Document, ExtendedWindow, V1Document } from '../types';\n\nexport function getV1DocumentsManager() {\n\tconst documentsManager = ( window as unknown as ExtendedWindow ).elementor?.documents;\n\n\tif ( ! documentsManager ) {\n\t\tthrow new Error( 'Elementor Editor V1 documents manager not found' );\n\t}\n\n\treturn documentsManager;\n}\n\nexport function normalizeV1Document( documentData: V1Document ): Document {\n\t// Draft or autosave.\n\tconst isUnpublishedRevision = documentData.config.revisions.current_id !== documentData.id;\n\n\treturn {\n\t\tid: documentData.id,\n\t\ttitle: documentData.container.settings.get( 'post_title' ),\n\t\ttype: {\n\t\t\tvalue: documentData.config.type,\n\t\t\tlabel: documentData.config.panel.title,\n\t\t},\n\t\tstatus: {\n\t\t\tvalue: documentData.config.status.value,\n\t\t\tlabel: documentData.config.status.label,\n\t\t},\n\t\tlinks: {\n\t\t\tplatformEdit: documentData.config.urls.exit_to_dashboard,\n\t\t},\n\t\tisDirty: documentData.editor.isChanged || isUnpublishedRevision,\n\t\tisSaving: documentData.editor.isSaving,\n\t\tisSavingDraft: false,\n\t\tuserCan: {\n\t\t\tpublish: documentData.config.user.can_publish,\n\t\t},\n\t};\n}\n","import { Document } from '../types';\nimport { addSlice, PayloadAction } from '@elementor/store';\n\ntype State = {\n\tentities: Record<Document['id'], Document>,\n\tactiveId: Document['id'] | null, // The currently editing document.\n\thostId: Document['id'] | null, // The document that host all the other documents.\n}\n\nexport type Slice = ReturnType<typeof createSlice>;\n\nconst initialState: State = {\n\tentities: {},\n\tactiveId: null,\n\thostId: null,\n};\n\ntype StateWithActiveId = Omit<State, 'activeId'> & { activeId: NonNullable<State['activeId']> };\n\nfunction hasActiveEntity( state: State ): state is StateWithActiveId {\n\treturn !! ( state.activeId && state.entities[ state.activeId ] );\n}\n\nexport function createSlice() {\n\treturn addSlice( {\n\t\tname: 'documents',\n\t\tinitialState,\n\t\treducers: {\n\t\t\tinit( state, { payload } : PayloadAction<State> ) {\n\t\t\t\tstate.entities = payload.entities;\n\t\t\t\tstate.hostId = payload.hostId;\n\t\t\t\tstate.activeId = payload.activeId;\n\t\t\t},\n\n\t\t\tactivateDocument( state, action: PayloadAction<Document> ) {\n\t\t\t\tstate.entities[ action.payload.id ] = action.payload;\n\t\t\t\tstate.activeId = action.payload.id;\n\t\t\t},\n\n\t\t\tstartSaving( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSaving = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSaving( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSaving: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSavingDraft: ( state ) => {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSavingDraft = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSavingDraft( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSavingDraft: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsDirty( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsPristine( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t} );\n}\n","import { syncStore } from './sync';\nimport { createSlice } from './store';\n\nexport default function init() {\n\tinitStore();\n}\n\nfunction initStore() {\n\tconst slice = createSlice();\n\n\tsyncStore( slice );\n}\n","import { useSelector } from '@elementor/store';\nimport { selectActiveDocument } from '../store/selectors';\n\nexport default function useActiveDocument() {\n\treturn useSelector( selectActiveDocument );\n}\n","import type { Slice } from './index';\nimport { createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState<Slice>;\n\nconst selectEntities = ( state: State ) => state.documents.entities;\nconst selectActiveId = ( state: State ) => state.documents.activeId;\nconst selectHostId = ( state: State ) => state.documents.hostId;\n\nexport const selectActiveDocument = createSelector(\n\tselectEntities,\n\tselectActiveId,\n\t( entities, activeId ) => activeId && entities[ activeId ]\n\t\t? entities[ activeId ]\n\t\t: null,\n);\n\nexport const selectHostDocument = createSelector(\n\tselectEntities,\n\tselectHostId,\n\t( entities, hostId ) => hostId && entities[ hostId ]\n\t\t? entities[ hostId ]\n\t\t: null,\n);\n","import { useCallback } from 'react';\nimport { openRoute, runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useActiveDocumentActions() {\n\tconst save = useCallback( () => runCommand( 'document/save/default' ), [] );\n\n\tconst saveDraft = useCallback( () => runCommand( 'document/save/draft' ), [] );\n\n\tconst saveTemplate = useCallback( () => openRoute( 'library/save-template' ), [] );\n\n\treturn {\n\t\tsave,\n\t\tsaveDraft,\n\t\tsaveTemplate,\n\t};\n}\n","import { useSelector } from '@elementor/store';\nimport { selectHostDocument } from '../store/selectors';\n\nexport default function useHostDocument() {\n\treturn useSelector( selectHostDocument );\n}\n","import init from './init';\n\nexport * from './hooks';\nexport * from './types';\n\ninit();\n"],"mappings":"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","names":["init","useSelector","useSelector"]}
1
+ {"version":3,"sources":["../src/sync/sync-store.ts","../src/sync/utils.ts","../src/store/index.ts","../src/init.ts","../src/hooks/use-active-document.ts","../src/store/selectors.ts","../src/hooks/use-active-document-actions.ts","../src/hooks/use-host-document.ts","../src/hooks/use-navigate-to-document.ts","../src/index.ts"],"sourcesContent":["import { Slice } from '../store';\nimport { Document } from '../types';\nimport { dispatch } from '@elementor/store';\nimport { normalizeV1Document, getV1DocumentsManager } from './utils';\nimport {\n\tcommandEndEvent,\n\tCommandEvent,\n\tcommandStartEvent,\n\tListenerEvent,\n\tlistenTo,\n\tv1ReadyEvent,\n} from '@elementor/editor-v1-adapters';\n\nexport function syncStore( slice: Slice ) {\n\tsyncInitialization( slice );\n\tsyncActiveDocument( slice );\n\tsyncOnDocumentSave( slice );\n\tsyncOnTitleChange( slice );\n\tsyncOnDocumentChange( slice );\n}\n\nfunction syncInitialization( slice: Slice ) {\n\tconst { init } = slice.actions;\n\n\tlistenTo(\n\t\tv1ReadyEvent(),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\n\t\t\tconst entities = Object.entries( documentsManager.documents )\n\t\t\t\t.reduce( ( acc: Record<string, Document>, [ id, document ] ) => {\n\t\t\t\t\tacc[ id ] = normalizeV1Document( document );\n\n\t\t\t\t\treturn acc;\n\t\t\t\t}, {} );\n\n\t\t\tdispatch( init( {\n\t\t\t\tentities,\n\t\t\t\thostId: documentsManager.getInitialId(),\n\t\t\t\tactiveId: documentsManager.getCurrentId(),\n\t\t\t} ) );\n\t\t}\n\t);\n}\n\nfunction syncActiveDocument( slice: Slice ) {\n\tconst { activateDocument, setAsHost } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'editor/documents/open' ),\n\t\t() => {\n\t\t\tconst documentsManager = getV1DocumentsManager();\n\t\t\tconst currentDocument = normalizeV1Document( documentsManager.getCurrent() );\n\n\t\t\tdispatch( activateDocument( currentDocument ) );\n\n\t\t\tif ( documentsManager.getInitialId() === currentDocument.id ) {\n\t\t\t\tdispatch( setAsHost( currentDocument.id ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnDocumentSave( slice: Slice ) {\n\tconst { startSaving, endSaving, startSavingDraft, endSavingDraft } = slice.actions;\n\n\tconst isDraft = ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ status: string }>;\n\n\t\t/**\n\t\t * @see https://github.com/elementor/elementor/blob/5f815d40a/assets/dev/js/editor/document/save/hooks/ui/save/before.js#L18-L22\n\t\t */\n\t\treturn event.args?.status === 'autosave';\n\t};\n\n\tlistenTo(\n\t\tcommandStartEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( startSavingDraft() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( startSaving() );\n\t\t}\n\t);\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/save' ),\n\t\t( e ) => {\n\t\t\tconst activeDocument = normalizeV1Document(\n\t\t\t\tgetV1DocumentsManager().getCurrent()\n\t\t\t);\n\n\t\t\tif ( isDraft( e ) ) {\n\t\t\t\tdispatch( endSavingDraft( activeDocument ) );\n\t\t\t} else {\n\t\t\t\tdispatch( endSaving( activeDocument ) );\n\t\t\t}\n\t\t}\n\t);\n}\n\nfunction syncOnTitleChange( slice: Slice ) {\n\tconst { updateActiveDocument } = slice.actions;\n\n\tconst updateTitle = debounce( ( e: ListenerEvent ) => {\n\t\tconst event = e as CommandEvent<{ settings: { post_title?: string } }>;\n\n\t\tif ( ! ( 'post_title' in event.args?.settings ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\t\tconst newTitle = currentDocument.container.settings.get( 'post_title' );\n\n\t\tdispatch( updateActiveDocument( { title: newTitle } ) );\n\t}, 400 );\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/elements/settings' ),\n\t\tupdateTitle\n\t);\n}\n\nfunction syncOnDocumentChange( slice: Slice ) {\n\tconst { markAsDirty, markAsPristine } = slice.actions;\n\n\tlistenTo(\n\t\tcommandEndEvent( 'document/save/set-is-modified' ),\n\t\t() => {\n\t\t\tconst currentDocument = getV1DocumentsManager().getCurrent();\n\n\t\t\tif ( currentDocument.editor.isChanged ) {\n\t\t\t\tdispatch( markAsDirty() );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdispatch( markAsPristine() );\n\t\t}\n\t);\n}\n\nfunction debounce<TArgs extends unknown[]>( fn: ( ...args: TArgs ) => unknown, timeout: number ) {\n\tlet timer: ReturnType<typeof setTimeout>;\n\n\treturn ( ...args: TArgs ) => {\n\t\tclearTimeout( timer );\n\n\t\ttimer = setTimeout( () => {\n\t\t\tfn( ...args );\n\t\t}, timeout );\n\t};\n}\n","import { Document, ExtendedWindow, V1Document } from '../types';\n\nexport function getV1DocumentsManager() {\n\tconst documentsManager = ( window as unknown as ExtendedWindow ).elementor?.documents;\n\n\tif ( ! documentsManager ) {\n\t\tthrow new Error( 'Elementor Editor V1 documents manager not found' );\n\t}\n\n\treturn documentsManager;\n}\n\nexport function normalizeV1Document( documentData: V1Document ): Document {\n\t// Draft or autosave.\n\tconst isUnpublishedRevision = documentData.config.revisions.current_id !== documentData.id;\n\n\treturn {\n\t\tid: documentData.id,\n\t\ttitle: documentData.container.settings.get( 'post_title' ),\n\t\ttype: {\n\t\t\tvalue: documentData.config.type,\n\t\t\tlabel: documentData.config.panel.title,\n\t\t},\n\t\tstatus: {\n\t\t\tvalue: documentData.config.status.value,\n\t\t\tlabel: documentData.config.status.label,\n\t\t},\n\t\tlinks: {\n\t\t\tplatformEdit: documentData.config.urls.exit_to_dashboard,\n\t\t},\n\t\tisDirty: documentData.editor.isChanged || isUnpublishedRevision,\n\t\tisSaving: documentData.editor.isSaving,\n\t\tisSavingDraft: false,\n\t\tuserCan: {\n\t\t\tpublish: documentData.config.user.can_publish,\n\t\t},\n\t};\n}\n","import { Document } from '../types';\nimport { addSlice, PayloadAction } from '@elementor/store';\n\ntype State = {\n\tentities: Record<Document['id'], Document>,\n\tactiveId: Document['id'] | null, // The currently editing document.\n\thostId: Document['id'] | null, // The document that host all the other documents.\n}\n\nexport type Slice = ReturnType<typeof createSlice>;\n\nconst initialState: State = {\n\tentities: {},\n\tactiveId: null,\n\thostId: null,\n};\n\ntype StateWithActiveId = Omit<State, 'activeId'> & { activeId: NonNullable<State['activeId']> };\n\nfunction hasActiveEntity( state: State ): state is StateWithActiveId {\n\treturn !! ( state.activeId && state.entities[ state.activeId ] );\n}\n\nexport function createSlice() {\n\treturn addSlice( {\n\t\tname: 'documents',\n\t\tinitialState,\n\t\treducers: {\n\t\t\tinit( state, { payload } : PayloadAction<State> ) {\n\t\t\t\tstate.entities = payload.entities;\n\t\t\t\tstate.hostId = payload.hostId;\n\t\t\t\tstate.activeId = payload.activeId;\n\t\t\t},\n\n\t\t\tactivateDocument( state, action: PayloadAction<Document> ) {\n\t\t\t\tstate.entities[ action.payload.id ] = action.payload;\n\t\t\t\tstate.activeId = action.payload.id;\n\t\t\t},\n\n\t\t\tsetAsHost( state, action: PayloadAction<Document['id']> ) {\n\t\t\t\tstate.hostId = action.payload;\n\t\t\t},\n\n\t\t\tupdateActiveDocument( state, action: PayloadAction<Partial<Document>> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...state.entities[ state.activeId ],\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSaving( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSaving = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSaving( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSaving: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tstartSavingDraft: ( state ) => {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isSavingDraft = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tendSavingDraft( state, action: PayloadAction<Document> ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ] = {\n\t\t\t\t\t\t...action.payload,\n\t\t\t\t\t\tisSavingDraft: false,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsDirty( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tmarkAsPristine( state ) {\n\t\t\t\tif ( hasActiveEntity( state ) ) {\n\t\t\t\t\tstate.entities[ state.activeId ].isDirty = false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t} );\n}\n","import { syncStore } from './sync';\nimport { createSlice } from './store';\n\nexport default function init() {\n\tinitStore();\n}\n\nfunction initStore() {\n\tconst slice = createSlice();\n\n\tsyncStore( slice );\n}\n","import { useSelector } from '@elementor/store';\nimport { selectActiveDocument } from '../store/selectors';\n\nexport default function useActiveDocument() {\n\treturn useSelector( selectActiveDocument );\n}\n","import type { Slice } from './index';\nimport { createSelector, SliceState } from '@elementor/store';\n\ntype State = SliceState<Slice>;\n\nconst selectEntities = ( state: State ) => state.documents.entities;\nconst selectActiveId = ( state: State ) => state.documents.activeId;\nconst selectHostId = ( state: State ) => state.documents.hostId;\n\nexport const selectActiveDocument = createSelector(\n\tselectEntities,\n\tselectActiveId,\n\t( entities, activeId ) => activeId && entities[ activeId ]\n\t\t? entities[ activeId ]\n\t\t: null,\n);\n\nexport const selectHostDocument = createSelector(\n\tselectEntities,\n\tselectHostId,\n\t( entities, hostId ) => hostId && entities[ hostId ]\n\t\t? entities[ hostId ]\n\t\t: null,\n);\n","import { useCallback } from 'react';\nimport { openRoute, runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useActiveDocumentActions() {\n\tconst save = useCallback( () => runCommand( 'document/save/default' ), [] );\n\n\tconst saveDraft = useCallback( () => runCommand( 'document/save/draft' ), [] );\n\n\tconst saveTemplate = useCallback( () => openRoute( 'library/save-template' ), [] );\n\n\treturn {\n\t\tsave,\n\t\tsaveDraft,\n\t\tsaveTemplate,\n\t};\n}\n","import { useSelector } from '@elementor/store';\nimport { selectHostDocument } from '../store/selectors';\n\nexport default function useHostDocument() {\n\treturn useSelector( selectHostDocument );\n}\n","import { useCallback } from 'react';\nimport { runCommand } from '@elementor/editor-v1-adapters';\n\nexport default function useNavigateToDocument() {\n\treturn useCallback( ( id: number ) => {\n\t\treturn runCommand( 'editor/documents/switch', {\n\t\t\tid,\n\t\t\tsetAsInitial: true,\n\t\t} );\n\t}, [] );\n}\n","import init from './init';\n\nexport * from './hooks';\nexport * from './types';\n\ninit();\n"],"mappings":"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","names":["init","useSelector","useSelector","useCallback","runCommand"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-documents",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -41,5 +41,5 @@
41
41
  "elementor": {
42
42
  "type": "extension"
43
43
  },
44
- "gitHead": "ccd6099031737d52202ba98812e21d16fac4bef2"
44
+ "gitHead": "2299a390624d60ea9d1e35e7d8dcc4208816d555"
45
45
  }
@@ -0,0 +1,24 @@
1
+ import { renderHook } from '@testing-library/react-hooks';
2
+ import { runCommand } from '@elementor/editor-v1-adapters';
3
+ import { useNavigateToDocument } from '@elementor/editor-documents';
4
+
5
+ jest.mock( '@elementor/editor-v1-adapters' );
6
+
7
+ describe( '@elementor/editor-documents - useNavigateToDocument', () => {
8
+ it( 'should navigate to document', () => {
9
+ // Arrange.
10
+ const { result } = renderHook( useNavigateToDocument );
11
+
12
+ const navigateToDocument = result.current;
13
+
14
+ // Act.
15
+ navigateToDocument( 123 );
16
+
17
+ // Assert.
18
+ expect( runCommand ).toHaveBeenCalledTimes( 1 );
19
+ expect( runCommand ).toHaveBeenCalledWith( 'editor/documents/switch', {
20
+ id: 123,
21
+ setAsInitial: true,
22
+ } );
23
+ } );
24
+ } );
@@ -1,3 +1,4 @@
1
1
  export { default as useActiveDocument } from './use-active-document';
2
2
  export { default as useActiveDocumentActions } from './use-active-document-actions';
3
3
  export { default as useHostDocument } from './use-host-document';
4
+ export { default as useNavigateToDocument } from './use-navigate-to-document';
@@ -0,0 +1,11 @@
1
+ import { useCallback } from 'react';
2
+ import { runCommand } from '@elementor/editor-v1-adapters';
3
+
4
+ export default function useNavigateToDocument() {
5
+ return useCallback( ( id: number ) => {
6
+ return runCommand( 'editor/documents/switch', {
7
+ id,
8
+ setAsInitial: true,
9
+ } );
10
+ }, [] );
11
+ }
@@ -37,6 +37,19 @@ export function createSlice() {
37
37
  state.activeId = action.payload.id;
38
38
  },
39
39
 
40
+ setAsHost( state, action: PayloadAction<Document['id']> ) {
41
+ state.hostId = action.payload;
42
+ },
43
+
44
+ updateActiveDocument( state, action: PayloadAction<Partial<Document>> ) {
45
+ if ( hasActiveEntity( state ) ) {
46
+ state.entities[ state.activeId ] = {
47
+ ...state.entities[ state.activeId ],
48
+ ...action.payload,
49
+ };
50
+ }
51
+ },
52
+
40
53
  startSaving( state ) {
41
54
  if ( hasActiveEntity( state ) ) {
42
55
  state.entities[ state.activeId ].isSaving = true;
@@ -20,12 +20,18 @@ describe( '@elementor/editor-documents - Sync Store', () => {
20
20
  let slice: Slice;
21
21
 
22
22
  beforeEach( () => {
23
+ jest.useFakeTimers();
24
+
23
25
  slice = createSlice();
24
26
  store = createStore();
25
27
 
26
28
  syncStore( slice );
27
29
  } );
28
30
 
31
+ afterEach( () => {
32
+ jest.useRealTimers();
33
+ } );
34
+
29
35
  it( 'should sync documents on V1 load', () => {
30
36
  // Arrange.
31
37
  mockV1DocumentsManager( [
@@ -130,6 +136,40 @@ describe( '@elementor/editor-documents - Sync Store', () => {
130
136
  } );
131
137
  } );
132
138
 
139
+ it.each( [
140
+ {
141
+ openAsHost: true,
142
+ expectedHost: 2,
143
+ },
144
+ {
145
+ openAsHost: false,
146
+ expectedHost: 1,
147
+ },
148
+ ] )( 'should sync host document when a new host is opened { openAsHost: $openAsHost }', ( { openAsHost, expectedHost } ) => {
149
+ // Arrange.
150
+ const mockDocument1 = makeMockV1Document( { id: 1 } );
151
+ const mockDocument2 = makeMockV1Document( { id: 2 } );
152
+
153
+ mockV1DocumentsManager( [
154
+ mockDocument1,
155
+ mockDocument2,
156
+ ], 1, 1 );
157
+
158
+ // Populate the documents state.
159
+ dispatchV1ReadyEvent();
160
+
161
+ // Act - Mock a host document change.
162
+ mockV1DocumentsManager( [
163
+ mockDocument1,
164
+ mockDocument2,
165
+ ], 2, openAsHost ? 2 : 1 );
166
+
167
+ dispatchCommandAfter( 'editor/documents/open' );
168
+
169
+ // Assert.
170
+ expect( store.getState().documents.hostId ).toBe( expectedHost );
171
+ } );
172
+
133
173
  it( 'should sync saving state of a document on V1 load', () => {
134
174
  // Arrange.
135
175
  const mockDocument = makeMockV1Document();
@@ -262,6 +302,60 @@ describe( '@elementor/editor-documents - Sync Store', () => {
262
302
  expect( selectActiveDocument( store.getState() )?.isDirty ).toBe( false );
263
303
  } );
264
304
 
305
+ it( 'should sync document title on V1 setting change', () => {
306
+ // Arrange.
307
+ mockV1DocumentsManager( [
308
+ makeMockV1Document( {
309
+ title: 'old title',
310
+ } ),
311
+ ] );
312
+
313
+ // Populate the documents state.
314
+ dispatchV1ReadyEvent();
315
+
316
+ // Act - simulate a change.
317
+ mockV1DocumentsManager( [
318
+ makeMockV1Document( {
319
+ title: 'new title',
320
+ } ),
321
+ ] );
322
+
323
+ dispatchCommandAfter( 'document/elements/settings', {
324
+ settings: {
325
+ post_title: 'new title',
326
+ },
327
+ } );
328
+
329
+ jest.runAllTimers();
330
+
331
+ // Assert.
332
+ expect( selectActiveDocument( store.getState() )?.title ).toBe( 'new title' );
333
+ } );
334
+
335
+ it( 'should not sync document title when a non-related V1 setting has changed', () => {
336
+ // Arrange.
337
+ mockV1DocumentsManager( [
338
+ makeMockV1Document( {
339
+ title: 'old title',
340
+ } ),
341
+ ] );
342
+
343
+ // Populate the documents state.
344
+ dispatchV1ReadyEvent();
345
+
346
+ // Act - simulate a change.
347
+ dispatchCommandAfter( 'document/elements/settings', {
348
+ settings: {
349
+ nonRelated: 'value',
350
+ },
351
+ } );
352
+
353
+ jest.runAllTimers();
354
+
355
+ // Assert.
356
+ expect( selectActiveDocument( store.getState() )?.title ).toBe( 'old title' );
357
+ } );
358
+
265
359
  it( 'should update the document when finish saving', () => {
266
360
  // Arrange.
267
361
  mockV1DocumentsManager( [
@@ -297,8 +391,8 @@ describe( '@elementor/editor-documents - Sync Store', () => {
297
391
  } );
298
392
  } );
299
393
 
300
- function mockV1DocumentsManager( documentsArray: V1Document[], current = 1 ) {
394
+ function mockV1DocumentsManager( documentsArray: V1Document[], current = 1, initial = 1 ) {
301
395
  ( window as unknown as WindowWithOptionalElementor ).elementor = {
302
- documents: makeDocumentsManager( documentsArray, current ),
396
+ documents: makeDocumentsManager( documentsArray, current, initial ),
303
397
  };
304
398
  }
@@ -15,6 +15,7 @@ export function syncStore( slice: Slice ) {
15
15
  syncInitialization( slice );
16
16
  syncActiveDocument( slice );
17
17
  syncOnDocumentSave( slice );
18
+ syncOnTitleChange( slice );
18
19
  syncOnDocumentChange( slice );
19
20
  }
20
21
 
@@ -43,7 +44,7 @@ function syncInitialization( slice: Slice ) {
43
44
  }
44
45
 
45
46
  function syncActiveDocument( slice: Slice ) {
46
- const { activateDocument } = slice.actions;
47
+ const { activateDocument, setAsHost } = slice.actions;
47
48
 
48
49
  listenTo(
49
50
  commandEndEvent( 'editor/documents/open' ),
@@ -52,6 +53,10 @@ function syncActiveDocument( slice: Slice ) {
52
53
  const currentDocument = normalizeV1Document( documentsManager.getCurrent() );
53
54
 
54
55
  dispatch( activateDocument( currentDocument ) );
56
+
57
+ if ( documentsManager.getInitialId() === currentDocument.id ) {
58
+ dispatch( setAsHost( currentDocument.id ) );
59
+ }
55
60
  }
56
61
  );
57
62
  }
@@ -96,6 +101,28 @@ function syncOnDocumentSave( slice: Slice ) {
96
101
  );
97
102
  }
98
103
 
104
+ function syncOnTitleChange( slice: Slice ) {
105
+ const { updateActiveDocument } = slice.actions;
106
+
107
+ const updateTitle = debounce( ( e: ListenerEvent ) => {
108
+ const event = e as CommandEvent<{ settings: { post_title?: string } }>;
109
+
110
+ if ( ! ( 'post_title' in event.args?.settings ) ) {
111
+ return;
112
+ }
113
+
114
+ const currentDocument = getV1DocumentsManager().getCurrent();
115
+ const newTitle = currentDocument.container.settings.get( 'post_title' );
116
+
117
+ dispatch( updateActiveDocument( { title: newTitle } ) );
118
+ }, 400 );
119
+
120
+ listenTo(
121
+ commandEndEvent( 'document/elements/settings' ),
122
+ updateTitle
123
+ );
124
+ }
125
+
99
126
  function syncOnDocumentChange( slice: Slice ) {
100
127
  const { markAsDirty, markAsPristine } = slice.actions;
101
128
 
@@ -113,3 +140,15 @@ function syncOnDocumentChange( slice: Slice ) {
113
140
  }
114
141
  );
115
142
  }
143
+
144
+ function debounce<TArgs extends unknown[]>( fn: ( ...args: TArgs ) => unknown, timeout: number ) {
145
+ let timer: ReturnType<typeof setTimeout>;
146
+
147
+ return ( ...args: TArgs ) => {
148
+ clearTimeout( timer );
149
+
150
+ timer = setTimeout( () => {
151
+ fn( ...args );
152
+ }, timeout );
153
+ };
154
+ }