@elementor/editor-v1-adapters 0.6.2 → 0.7.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,17 @@
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.7.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-v1-adapters@0.6.2...@elementor/editor-v1-adapters@0.7.0) (2024-07-08)
7
+
8
+
9
+ ### Features
10
+
11
+ * **editor-editing-panel:** create editor panel package [EDS-226] ([#188](https://github.com/elementor/elementor-packages/issues/188)) ([e361aed](https://github.com/elementor/elementor-packages/commit/e361aed023c3a5d4dd329b354f1403de238da20e))
12
+
13
+
14
+
15
+
16
+
6
17
  ## [0.6.2](https://github.com/elementor/elementor-packages/compare/@elementor/editor-v1-adapters@0.6.1...@elementor/editor-v1-adapters@0.6.2) (2024-07-03)
7
18
 
8
19
  **Note:** Version bump only for package @elementor/editor-v1-adapters
package/dist/index.d.mts CHANGED
@@ -1,6 +1,11 @@
1
1
  declare function runCommand(command: string, args?: object): Promise<any>;
2
2
  declare function openRoute(route: string): Promise<unknown>;
3
3
  declare function registerRoute(route: string): Promise<unknown>;
4
+ type UnknownArgs = Record<string, unknown>;
5
+ declare function blockDataCommand({ command, condition, }: {
6
+ command: string;
7
+ condition: (args: UnknownArgs) => boolean;
8
+ }): Promise<void>;
4
9
 
5
10
  declare function useIsPreviewMode(): boolean;
6
11
 
@@ -79,4 +84,4 @@ type EditMode = 'edit' | 'preview' | 'picker';
79
84
  declare function isRouteActive(route: string): boolean;
80
85
  declare function getCurrentEditMode(): EditMode;
81
86
 
82
- export { CommandEvent, CommandEventDescriptor, EventDescriptor, ExtendedWindow, ListenerCallback, ListenerEvent, RouteEvent, RouteEventDescriptor, WindowEvent, WindowEventDescriptor, dispatchReadyEvent as __privateDispatchReadyEvent, flushListeners as __privateFlushListeners, getCurrentEditMode as __privateGetCurrentEditMode, isRouteActive as __privateIsRouteActive, listenTo as __privateListenTo, openRoute as __privateOpenRoute, registerRoute as __privateRegisterRoute, runCommand as __privateRunCommand, setReady as __privateSetReady, useIsPreviewMode as __privateUseIsPreviewMode, useIsRouteActive as __privateUseIsRouteActive, useListenTo as __privateUseListenTo, useRouteStatus as __privateUseRouteStatus, commandEndEvent, commandStartEvent, dispatchReadyEvent, editModeChangeEvent, flushListeners, isReady, listenTo, routeCloseEvent, routeOpenEvent, setReady, v1ReadyEvent, windowEvent };
87
+ export { CommandEvent, CommandEventDescriptor, EventDescriptor, ExtendedWindow, ListenerCallback, ListenerEvent, RouteEvent, RouteEventDescriptor, WindowEvent, WindowEventDescriptor, blockDataCommand as __privateBlockDataCommand, dispatchReadyEvent as __privateDispatchReadyEvent, flushListeners as __privateFlushListeners, getCurrentEditMode as __privateGetCurrentEditMode, isRouteActive as __privateIsRouteActive, listenTo as __privateListenTo, openRoute as __privateOpenRoute, registerRoute as __privateRegisterRoute, runCommand as __privateRunCommand, setReady as __privateSetReady, useIsPreviewMode as __privateUseIsPreviewMode, useIsRouteActive as __privateUseIsRouteActive, useListenTo as __privateUseListenTo, useRouteStatus as __privateUseRouteStatus, commandEndEvent, commandStartEvent, dispatchReadyEvent, editModeChangeEvent, flushListeners, isReady, listenTo, routeCloseEvent, routeOpenEvent, setReady, v1ReadyEvent, windowEvent };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  declare function runCommand(command: string, args?: object): Promise<any>;
2
2
  declare function openRoute(route: string): Promise<unknown>;
3
3
  declare function registerRoute(route: string): Promise<unknown>;
4
+ type UnknownArgs = Record<string, unknown>;
5
+ declare function blockDataCommand({ command, condition, }: {
6
+ command: string;
7
+ condition: (args: UnknownArgs) => boolean;
8
+ }): Promise<void>;
4
9
 
5
10
  declare function useIsPreviewMode(): boolean;
6
11
 
@@ -79,4 +84,4 @@ type EditMode = 'edit' | 'preview' | 'picker';
79
84
  declare function isRouteActive(route: string): boolean;
80
85
  declare function getCurrentEditMode(): EditMode;
81
86
 
82
- export { CommandEvent, CommandEventDescriptor, EventDescriptor, ExtendedWindow, ListenerCallback, ListenerEvent, RouteEvent, RouteEventDescriptor, WindowEvent, WindowEventDescriptor, dispatchReadyEvent as __privateDispatchReadyEvent, flushListeners as __privateFlushListeners, getCurrentEditMode as __privateGetCurrentEditMode, isRouteActive as __privateIsRouteActive, listenTo as __privateListenTo, openRoute as __privateOpenRoute, registerRoute as __privateRegisterRoute, runCommand as __privateRunCommand, setReady as __privateSetReady, useIsPreviewMode as __privateUseIsPreviewMode, useIsRouteActive as __privateUseIsRouteActive, useListenTo as __privateUseListenTo, useRouteStatus as __privateUseRouteStatus, commandEndEvent, commandStartEvent, dispatchReadyEvent, editModeChangeEvent, flushListeners, isReady, listenTo, routeCloseEvent, routeOpenEvent, setReady, v1ReadyEvent, windowEvent };
87
+ export { CommandEvent, CommandEventDescriptor, EventDescriptor, ExtendedWindow, ListenerCallback, ListenerEvent, RouteEvent, RouteEventDescriptor, WindowEvent, WindowEventDescriptor, blockDataCommand as __privateBlockDataCommand, dispatchReadyEvent as __privateDispatchReadyEvent, flushListeners as __privateFlushListeners, getCurrentEditMode as __privateGetCurrentEditMode, isRouteActive as __privateIsRouteActive, listenTo as __privateListenTo, openRoute as __privateOpenRoute, registerRoute as __privateRegisterRoute, runCommand as __privateRunCommand, setReady as __privateSetReady, useIsPreviewMode as __privateUseIsPreviewMode, useIsRouteActive as __privateUseIsRouteActive, useListenTo as __privateUseListenTo, useRouteStatus as __privateUseRouteStatus, commandEndEvent, commandStartEvent, dispatchReadyEvent, editModeChangeEvent, flushListeners, isReady, listenTo, routeCloseEvent, routeOpenEvent, setReady, v1ReadyEvent, windowEvent };
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
+ __privateBlockDataCommand: () => blockDataCommand,
23
24
  __privateDispatchReadyEvent: () => dispatchReadyEvent,
24
25
  __privateFlushListeners: () => flushListeners,
25
26
  __privateGetCurrentEditMode: () => getCurrentEditMode,
@@ -100,6 +101,35 @@ function registerRoute(route) {
100
101
  return Promise.reject(e);
101
102
  }
102
103
  }
104
+ var hookId = 0;
105
+ function blockDataCommand({
106
+ command,
107
+ condition
108
+ }) {
109
+ const extendedWindow = window;
110
+ const DependencyHook = extendedWindow.$e?.modules?.hookData?.Dependency;
111
+ if (!DependencyHook) {
112
+ return Promise.reject("`$e.modules.hookData.Dependency` is not available");
113
+ }
114
+ const __hookId = ++hookId;
115
+ const dependencyHook = new class extends DependencyHook {
116
+ getCommand() {
117
+ return command;
118
+ }
119
+ getId() {
120
+ return `${command}--block--${__hookId}`;
121
+ }
122
+ apply(args) {
123
+ const shouldStopOriginalAction = condition(args);
124
+ return !shouldStopOriginalAction;
125
+ }
126
+ }();
127
+ try {
128
+ return Promise.resolve(dependencyHook.register());
129
+ } catch (e) {
130
+ return Promise.reject(e);
131
+ }
132
+ }
103
133
 
104
134
  // src/hooks/use-listen-to.ts
105
135
  var import_react = require("react");
@@ -329,6 +359,7 @@ function useRouteStatus(route, {
329
359
  }
330
360
  // Annotate the CommonJS export names for ESM import in node:
331
361
  0 && (module.exports = {
362
+ __privateBlockDataCommand,
332
363
  __privateDispatchReadyEvent,
333
364
  __privateFlushListeners,
334
365
  __privateGetCurrentEditMode,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/dispatchers/utils.ts","../src/dispatchers/dispatchers.ts","../src/hooks/use-listen-to.ts","../src/listeners/event-creators.ts","../src/listeners/is-ready.ts","../src/listeners/utils.ts","../src/listeners/listeners.ts","../src/readers/index.ts","../src/hooks/use-is-preview-mode.ts","../src/hooks/use-is-route-active.ts","../src/hooks/use-route-status.ts"],"sourcesContent":["export {\n\trunCommand as __privateRunCommand,\n\topenRoute as __privateOpenRoute,\n\tregisterRoute as __privateRegisterRoute,\n} from './dispatchers';\n\nexport {\n\tuseIsPreviewMode as __privateUseIsPreviewMode,\n\tuseIsRouteActive as __privateUseIsRouteActive,\n\tuseListenTo as __privateUseListenTo,\n\tuseRouteStatus as __privateUseRouteStatus,\n} from './hooks';\n\nexport {\n\tsetReady as __privateSetReady,\n\tlistenTo as __privateListenTo,\n\tflushListeners as __privateFlushListeners,\n\tdispatchReadyEvent as __privateDispatchReadyEvent,\n\twindowEvent,\n\tv1ReadyEvent,\n\tcommandStartEvent,\n\tcommandEndEvent,\n\trouteOpenEvent,\n\trouteCloseEvent,\n\teditModeChangeEvent,\n} from './listeners';\n\nexport type * from './listeners';\n\nexport {\n\tisRouteActive as __privateIsRouteActive,\n\tgetCurrentEditMode as __privateGetCurrentEditMode,\n} from './readers';\n","import { jQueryDeferred } from './types';\n\nexport function isJQueryDeferred<T>( value: unknown ): value is jQueryDeferred<T> {\n\t// TODO: Copied from:\n\t// https://github.com/elementor/elementor/blob/6a74fc9/modules/web-cli/assets/js/core/commands.js#L410\n\n\treturn ( !! value ) &&\n\t\t'object' === typeof value &&\n\t\tObject.hasOwn( value, 'promise' ) &&\n\t\tObject.hasOwn( value, 'then' ) &&\n\t\tObject.hasOwn( value, 'fail' );\n}\n\nexport function promisifyJQueryDeferred<T>( deferred: jQueryDeferred<T> ): Promise<T> {\n\treturn new Promise( ( resolve, reject ) => {\n\t\tdeferred.then( resolve, reject );\n\t} );\n}\n","import { ExtendedWindow } from './types';\nimport { isJQueryDeferred, promisifyJQueryDeferred } from './utils';\n\nexport function runCommand( command: string, args?: object ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.run ) {\n\t\treturn Promise.reject( '`$e.run()` is not available' );\n\t}\n\n\tconst result = extendedWindow.$e.run( command, args );\n\n\tif ( result instanceof Promise ) {\n\t\treturn result;\n\t}\n\n\tif ( isJQueryDeferred( result ) ) {\n\t\treturn promisifyJQueryDeferred( result );\n\t}\n\n\treturn Promise.resolve( result );\n}\n\nexport function openRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.route ) {\n\t\treturn Promise.reject( '`$e.route()` is not available' );\n\t}\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.route( route )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\nexport function registerRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.routes?.register ) {\n\t\treturn Promise.reject( '`$e.routes.register()` is not available' );\n\t}\n\n\tconst routeParts = route.split( '/' );\n\n\tif ( routeParts.length < 2 ) {\n\t\treturn Promise.reject( `\\`${ route }\\` is an invalid route` );\n\t}\n\n\tconst componentRoute = routeParts.pop() as string; // routeParts.length must be >= 2\n\tconst component = routeParts.join( '/' );\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.routes.register( component, componentRoute, () => null )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n","import { useEffect, useState } from 'react';\nimport { EventDescriptor, listenTo } from '../listeners';\n\nexport default function useListenTo<T>(\n\tevent: EventDescriptor | EventDescriptor[],\n\tgetSnapshot: () => T,\n\tdeps: unknown[] = []\n) {\n\tconst [ snapshot, setSnapshot ] = useState( () => getSnapshot() );\n\n\tuseEffect( () => {\n\t\tconst updateState = () => setSnapshot( getSnapshot() );\n\n\t\t// Ensure the state is re-calculated when the dependencies have been changed.\n\t\tupdateState();\n\n\t\treturn listenTo( event, updateState );\n\t}, deps ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn snapshot;\n}\n","import { CommandEventDescriptor, RouteEventDescriptor, WindowEventDescriptor } from './types';\n\nexport const commandStartEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'before',\n\t};\n};\n\nexport const commandEndEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'after',\n\t};\n};\n\nexport const routeOpenEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'open',\n\t};\n};\n\nexport const routeCloseEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'close',\n\t};\n};\n\nexport const windowEvent = ( event: WindowEventDescriptor['name'] ): WindowEventDescriptor => {\n\treturn {\n\t\ttype: 'window-event',\n\t\tname: event,\n\t};\n};\n\nexport const v1ReadyEvent = () => {\n\treturn windowEvent( 'elementor/initialized' );\n};\n\nexport const editModeChangeEvent = () => {\n\treturn windowEvent( 'elementor/edit-mode/change' );\n};\n","/**\n * This file is used to store the state of the isReady variable, which is used to determine\n * if the adapter is ready to receive events (editor v1 and v2 are loaded).\n */\n\nlet ready = false;\n\nexport function isReady() {\n\treturn ready;\n}\n\nexport function setReady( value: boolean ) {\n\tready = value;\n}\n","import { ExtendedWindow, ListenerEvent } from './types';\nimport { setReady } from './is-ready';\n\nexport function dispatchReadyEvent() {\n\treturn getV1LoadingPromise().then( () => {\n\t\tsetReady( true );\n\t\twindow.dispatchEvent( new CustomEvent( 'elementor/initialized' ) );\n\t} );\n}\n\nfunction getV1LoadingPromise() {\n\tconst v1LoadingPromise = ( window as unknown as ExtendedWindow ).__elementorEditorV1LoadingPromise;\n\n\tif ( ! v1LoadingPromise ) {\n\t\treturn Promise.reject( 'Elementor Editor V1 is not loaded' );\n\t}\n\n\treturn v1LoadingPromise;\n}\n\nexport function normalizeEvent( e: ListenerEvent['originalEvent'] ): ListenerEvent {\n\tif ( e instanceof CustomEvent && e.detail?.command ) {\n\t\treturn {\n\t\t\ttype: 'command',\n\t\t\tcommand: e.detail.command,\n\t\t\targs: e.detail.args,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\tif ( e instanceof CustomEvent && e.detail?.route ) {\n\t\treturn {\n\t\t\ttype: 'route',\n\t\t\troute: e.detail.route,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: 'window-event',\n\t\tevent: e.type,\n\t\toriginalEvent: e,\n\t};\n}\n","import { normalizeEvent } from './utils';\nimport {\n\tCommandEventDescriptor,\n\tEventDescriptor,\n\tListenerCallback,\n\tRouteEventDescriptor,\n\tWindowEventDescriptor,\n} from './types';\nimport { isReady, setReady } from './is-ready';\n\nconst callbacksByEvent = new Map<EventDescriptor['name'], ListenerCallback[]>();\nlet abortController = new AbortController();\n\nexport function listenTo(\n\teventDescriptors: EventDescriptor | EventDescriptor[],\n\tcallback: ListenerCallback\n) {\n\tif ( ! Array.isArray( eventDescriptors ) ) {\n\t\teventDescriptors = [ eventDescriptors ];\n\t}\n\n\t// @see https://github.com/typescript-eslint/typescript-eslint/issues/2841\n\t// eslint-disable-next-line array-callback-return -- Clashes with typescript.\n\tconst cleanups = eventDescriptors.map( ( event ) => {\n\t\tconst { type, name } = event;\n\n\t\tswitch ( type ) {\n\t\t\tcase 'command':\n\t\t\t\treturn registerCommandListener( name, event.state, callback );\n\n\t\t\tcase 'route':\n\t\t\t\treturn registerRouteListener( name, event.state, callback );\n\n\t\t\tcase 'window-event':\n\t\t\t\treturn registerWindowEventListener( name, callback );\n\t\t}\n\t} );\n\n\treturn () => {\n\t\tcleanups.forEach( ( cleanup ) => cleanup() );\n\t};\n}\n\nexport function flushListeners() {\n\tabortController.abort();\n\tcallbacksByEvent.clear();\n\tsetReady( false );\n\n\tabortController = new AbortController();\n}\n\nfunction registerCommandListener(\n\tcommand: CommandEventDescriptor['name'],\n\tstate: CommandEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/commands/run/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'command' && e.command === command;\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerRouteListener(\n\troute: RouteEventDescriptor['name'],\n\tstate: RouteEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/routes/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'route' && e.route.startsWith( route );\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerWindowEventListener( event: WindowEventDescriptor['name'], callback: ListenerCallback ) {\n\tconst isFirstListener = ! callbacksByEvent.has( event );\n\n\tif ( isFirstListener ) {\n\t\tcallbacksByEvent.set( event, [] );\n\n\t\taddListener( event );\n\t}\n\n\tcallbacksByEvent.get( event )?.push( callback );\n\n\treturn () => {\n\t\tconst callbacks = callbacksByEvent.get( event );\n\n\t\tif ( ! callbacks?.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst filtered = callbacks.filter( ( cb ) => cb !== callback );\n\n\t\tcallbacksByEvent.set( event, filtered );\n\t};\n}\n\nfunction addListener( event: EventDescriptor['name'] ) {\n\twindow.addEventListener(\n\t\tevent,\n\t\tmakeEventHandler( event ),\n\t\t{ signal: abortController.signal }\n\t);\n}\n\nfunction makeEventHandler( event: EventDescriptor['name'] ): EventListener {\n\treturn ( e ) => {\n\t\tif ( ! isReady() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedEvent = normalizeEvent( e );\n\n\t\tcallbacksByEvent.get( event )?.forEach( ( callback ) => {\n\t\t\tcallback( normalizedEvent );\n\t\t} );\n\t};\n}\n","import { ExtendedWindow } from './types';\n\nexport function isRouteActive( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn !! extendedWindow.$e?.routes?.isPartOf( route );\n}\n\nexport function getCurrentEditMode() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.dataEditMode?.request?.( 'activeMode' );\n}\n","import useListenTo from './use-listen-to';\nimport { getCurrentEditMode } from '../readers';\nimport { editModeChangeEvent } from '../listeners';\n\nexport default function useIsPreviewMode() {\n\treturn useListenTo(\n\t\teditModeChangeEvent(),\n\t\t() => getCurrentEditMode() === 'preview'\n\t);\n}\n","import useListenTo from './use-listen-to';\nimport { isRouteActive } from '../readers';\nimport { routeCloseEvent, routeOpenEvent, RouteEventDescriptor } from '../listeners';\n\nexport default function useIsRouteActive( route: RouteEventDescriptor['name'] ) {\n\treturn useListenTo(\n\t\t[\n\t\t\trouteOpenEvent( route ),\n\t\t\trouteCloseEvent( route ),\n\t\t],\n\t\t() => isRouteActive( route ),\n\t\t[ route ]\n\t);\n}\n","import useIsPreviewMode from './use-is-preview-mode';\nimport useIsRouteActive from './use-is-route-active';\nimport { RouteEventDescriptor } from '../listeners';\n\ntype Options = {\n\tblockOnKitRoutes?: boolean,\n\tblockOnPreviewMode?: boolean,\n}\n\nexport default function useRouteStatus(\n\troute: RouteEventDescriptor['name'],\n\t{\n\t\tblockOnKitRoutes = true,\n\t\tblockOnPreviewMode = true,\n\t}: Options = {}\n) {\n\tconst isRouteActive = useIsRouteActive( route );\n\tconst isKitRouteActive = useIsRouteActive( 'panel/global' );\n\tconst isPreviewMode = useIsPreviewMode();\n\n\tconst isActive = isRouteActive && ! ( blockOnPreviewMode && isPreviewMode );\n\n\tconst isBlocked = (\n\t\t( blockOnPreviewMode && isPreviewMode ) ||\n\t\t( blockOnKitRoutes && isKitRouteActive )\n\t);\n\n\treturn {\n\t\tisActive,\n\t\tisBlocked,\n\t};\n}\n"],"mappings":"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","names":["isRouteActive"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/dispatchers/utils.ts","../src/dispatchers/dispatchers.ts","../src/hooks/use-listen-to.ts","../src/listeners/event-creators.ts","../src/listeners/is-ready.ts","../src/listeners/utils.ts","../src/listeners/listeners.ts","../src/readers/index.ts","../src/hooks/use-is-preview-mode.ts","../src/hooks/use-is-route-active.ts","../src/hooks/use-route-status.ts"],"sourcesContent":["export {\n\trunCommand as __privateRunCommand,\n\topenRoute as __privateOpenRoute,\n\tregisterRoute as __privateRegisterRoute,\n\tblockDataCommand as __privateBlockDataCommand,\n} from './dispatchers';\n\nexport {\n\tuseIsPreviewMode as __privateUseIsPreviewMode,\n\tuseIsRouteActive as __privateUseIsRouteActive,\n\tuseListenTo as __privateUseListenTo,\n\tuseRouteStatus as __privateUseRouteStatus,\n} from './hooks';\n\nexport {\n\tsetReady as __privateSetReady,\n\tlistenTo as __privateListenTo,\n\tflushListeners as __privateFlushListeners,\n\tdispatchReadyEvent as __privateDispatchReadyEvent,\n\twindowEvent,\n\tv1ReadyEvent,\n\tcommandStartEvent,\n\tcommandEndEvent,\n\trouteOpenEvent,\n\trouteCloseEvent,\n\teditModeChangeEvent,\n} from './listeners';\n\nexport type * from './listeners';\n\nexport {\n\tisRouteActive as __privateIsRouteActive,\n\tgetCurrentEditMode as __privateGetCurrentEditMode,\n} from './readers';\n","import { jQueryDeferred } from './types';\n\nexport function isJQueryDeferred<T>( value: unknown ): value is jQueryDeferred<T> {\n\t// TODO: Copied from:\n\t// https://github.com/elementor/elementor/blob/6a74fc9/modules/web-cli/assets/js/core/commands.js#L410\n\n\treturn ( !! value ) &&\n\t\t'object' === typeof value &&\n\t\tObject.hasOwn( value, 'promise' ) &&\n\t\tObject.hasOwn( value, 'then' ) &&\n\t\tObject.hasOwn( value, 'fail' );\n}\n\nexport function promisifyJQueryDeferred<T>( deferred: jQueryDeferred<T> ): Promise<T> {\n\treturn new Promise( ( resolve, reject ) => {\n\t\tdeferred.then( resolve, reject );\n\t} );\n}\n","import { ExtendedWindow } from './types';\nimport { isJQueryDeferred, promisifyJQueryDeferred } from './utils';\n\nexport function runCommand( command: string, args?: object ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.run ) {\n\t\treturn Promise.reject( '`$e.run()` is not available' );\n\t}\n\n\tconst result = extendedWindow.$e.run( command, args );\n\n\tif ( result instanceof Promise ) {\n\t\treturn result;\n\t}\n\n\tif ( isJQueryDeferred( result ) ) {\n\t\treturn promisifyJQueryDeferred( result );\n\t}\n\n\treturn Promise.resolve( result );\n}\n\nexport function openRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.route ) {\n\t\treturn Promise.reject( '`$e.route()` is not available' );\n\t}\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.route( route )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\nexport function registerRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.routes?.register ) {\n\t\treturn Promise.reject( '`$e.routes.register()` is not available' );\n\t}\n\n\tconst routeParts = route.split( '/' );\n\n\tif ( routeParts.length < 2 ) {\n\t\treturn Promise.reject( `\\`${ route }\\` is an invalid route` );\n\t}\n\n\tconst componentRoute = routeParts.pop() as string; // routeParts.length must be >= 2\n\tconst component = routeParts.join( '/' );\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.routes.register( component, componentRoute, () => null )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\ntype UnknownArgs = Record<string, unknown>;\n\nlet hookId = 0;\n\nexport function blockDataCommand( {\n\tcommand,\n\tcondition,\n}: {\n\tcommand: string,\n\tcondition: ( args: UnknownArgs ) => boolean,\n} ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\tconst DependencyHook = extendedWindow.$e?.modules?.hookData?.Dependency;\n\n\tif ( ! DependencyHook ) {\n\t\treturn Promise.reject( '`$e.modules.hookData.Dependency` is not available' );\n\t}\n\n\tconst __hookId = ++hookId;\n\n\tconst dependencyHook = new class extends DependencyHook {\n\t\tgetCommand() {\n\t\t\treturn command;\n\t\t}\n\n\t\tgetId() {\n\t\t\treturn `${ command }--block--${ __hookId }`;\n\t\t}\n\n\t\tapply( args: UnknownArgs ) {\n\t\t\t// If the condition is met, we will stop the original command from running.\n\t\t\tconst shouldStopOriginalAction = condition( args );\n\n\t\t\t// We will return `false` if we want to stop the original action from running.\n\t\t\treturn ! shouldStopOriginalAction;\n\t\t}\n\t};\n\n\ttry {\n\t\treturn Promise.resolve( dependencyHook.register() );\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n","import { useEffect, useState } from 'react';\nimport { EventDescriptor, listenTo } from '../listeners';\n\nexport default function useListenTo<T>(\n\tevent: EventDescriptor | EventDescriptor[],\n\tgetSnapshot: () => T,\n\tdeps: unknown[] = []\n) {\n\tconst [ snapshot, setSnapshot ] = useState( () => getSnapshot() );\n\n\tuseEffect( () => {\n\t\tconst updateState = () => setSnapshot( getSnapshot() );\n\n\t\t// Ensure the state is re-calculated when the dependencies have been changed.\n\t\tupdateState();\n\n\t\treturn listenTo( event, updateState );\n\t}, deps ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn snapshot;\n}\n","import { CommandEventDescriptor, RouteEventDescriptor, WindowEventDescriptor } from './types';\n\nexport const commandStartEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'before',\n\t};\n};\n\nexport const commandEndEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'after',\n\t};\n};\n\nexport const routeOpenEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'open',\n\t};\n};\n\nexport const routeCloseEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'close',\n\t};\n};\n\nexport const windowEvent = ( event: WindowEventDescriptor['name'] ): WindowEventDescriptor => {\n\treturn {\n\t\ttype: 'window-event',\n\t\tname: event,\n\t};\n};\n\nexport const v1ReadyEvent = () => {\n\treturn windowEvent( 'elementor/initialized' );\n};\n\nexport const editModeChangeEvent = () => {\n\treturn windowEvent( 'elementor/edit-mode/change' );\n};\n","/**\n * This file is used to store the state of the isReady variable, which is used to determine\n * if the adapter is ready to receive events (editor v1 and v2 are loaded).\n */\n\nlet ready = false;\n\nexport function isReady() {\n\treturn ready;\n}\n\nexport function setReady( value: boolean ) {\n\tready = value;\n}\n","import { ExtendedWindow, ListenerEvent } from './types';\nimport { setReady } from './is-ready';\n\nexport function dispatchReadyEvent() {\n\treturn getV1LoadingPromise().then( () => {\n\t\tsetReady( true );\n\t\twindow.dispatchEvent( new CustomEvent( 'elementor/initialized' ) );\n\t} );\n}\n\nfunction getV1LoadingPromise() {\n\tconst v1LoadingPromise = ( window as unknown as ExtendedWindow ).__elementorEditorV1LoadingPromise;\n\n\tif ( ! v1LoadingPromise ) {\n\t\treturn Promise.reject( 'Elementor Editor V1 is not loaded' );\n\t}\n\n\treturn v1LoadingPromise;\n}\n\nexport function normalizeEvent( e: ListenerEvent['originalEvent'] ): ListenerEvent {\n\tif ( e instanceof CustomEvent && e.detail?.command ) {\n\t\treturn {\n\t\t\ttype: 'command',\n\t\t\tcommand: e.detail.command,\n\t\t\targs: e.detail.args,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\tif ( e instanceof CustomEvent && e.detail?.route ) {\n\t\treturn {\n\t\t\ttype: 'route',\n\t\t\troute: e.detail.route,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: 'window-event',\n\t\tevent: e.type,\n\t\toriginalEvent: e,\n\t};\n}\n","import { normalizeEvent } from './utils';\nimport {\n\tCommandEventDescriptor,\n\tEventDescriptor,\n\tListenerCallback,\n\tRouteEventDescriptor,\n\tWindowEventDescriptor,\n} from './types';\nimport { isReady, setReady } from './is-ready';\n\nconst callbacksByEvent = new Map<EventDescriptor['name'], ListenerCallback[]>();\nlet abortController = new AbortController();\n\nexport function listenTo(\n\teventDescriptors: EventDescriptor | EventDescriptor[],\n\tcallback: ListenerCallback\n) {\n\tif ( ! Array.isArray( eventDescriptors ) ) {\n\t\teventDescriptors = [ eventDescriptors ];\n\t}\n\n\t// @see https://github.com/typescript-eslint/typescript-eslint/issues/2841\n\t// eslint-disable-next-line array-callback-return -- Clashes with typescript.\n\tconst cleanups = eventDescriptors.map( ( event ) => {\n\t\tconst { type, name } = event;\n\n\t\tswitch ( type ) {\n\t\t\tcase 'command':\n\t\t\t\treturn registerCommandListener( name, event.state, callback );\n\n\t\t\tcase 'route':\n\t\t\t\treturn registerRouteListener( name, event.state, callback );\n\n\t\t\tcase 'window-event':\n\t\t\t\treturn registerWindowEventListener( name, callback );\n\t\t}\n\t} );\n\n\treturn () => {\n\t\tcleanups.forEach( ( cleanup ) => cleanup() );\n\t};\n}\n\nexport function flushListeners() {\n\tabortController.abort();\n\tcallbacksByEvent.clear();\n\tsetReady( false );\n\n\tabortController = new AbortController();\n}\n\nfunction registerCommandListener(\n\tcommand: CommandEventDescriptor['name'],\n\tstate: CommandEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/commands/run/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'command' && e.command === command;\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerRouteListener(\n\troute: RouteEventDescriptor['name'],\n\tstate: RouteEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/routes/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'route' && e.route.startsWith( route );\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerWindowEventListener( event: WindowEventDescriptor['name'], callback: ListenerCallback ) {\n\tconst isFirstListener = ! callbacksByEvent.has( event );\n\n\tif ( isFirstListener ) {\n\t\tcallbacksByEvent.set( event, [] );\n\n\t\taddListener( event );\n\t}\n\n\tcallbacksByEvent.get( event )?.push( callback );\n\n\treturn () => {\n\t\tconst callbacks = callbacksByEvent.get( event );\n\n\t\tif ( ! callbacks?.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst filtered = callbacks.filter( ( cb ) => cb !== callback );\n\n\t\tcallbacksByEvent.set( event, filtered );\n\t};\n}\n\nfunction addListener( event: EventDescriptor['name'] ) {\n\twindow.addEventListener(\n\t\tevent,\n\t\tmakeEventHandler( event ),\n\t\t{ signal: abortController.signal }\n\t);\n}\n\nfunction makeEventHandler( event: EventDescriptor['name'] ): EventListener {\n\treturn ( e ) => {\n\t\tif ( ! isReady() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedEvent = normalizeEvent( e );\n\n\t\tcallbacksByEvent.get( event )?.forEach( ( callback ) => {\n\t\t\tcallback( normalizedEvent );\n\t\t} );\n\t};\n}\n","import { ExtendedWindow } from './types';\n\nexport function isRouteActive( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn !! extendedWindow.$e?.routes?.isPartOf( route );\n}\n\nexport function getCurrentEditMode() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.dataEditMode?.request?.( 'activeMode' );\n}\n","import useListenTo from './use-listen-to';\nimport { getCurrentEditMode } from '../readers';\nimport { editModeChangeEvent } from '../listeners';\n\nexport default function useIsPreviewMode() {\n\treturn useListenTo(\n\t\teditModeChangeEvent(),\n\t\t() => getCurrentEditMode() === 'preview'\n\t);\n}\n","import useListenTo from './use-listen-to';\nimport { isRouteActive } from '../readers';\nimport { routeCloseEvent, routeOpenEvent, RouteEventDescriptor } from '../listeners';\n\nexport default function useIsRouteActive( route: RouteEventDescriptor['name'] ) {\n\treturn useListenTo(\n\t\t[\n\t\t\trouteOpenEvent( route ),\n\t\t\trouteCloseEvent( route ),\n\t\t],\n\t\t() => isRouteActive( route ),\n\t\t[ route ]\n\t);\n}\n","import useIsPreviewMode from './use-is-preview-mode';\nimport useIsRouteActive from './use-is-route-active';\nimport { RouteEventDescriptor } from '../listeners';\n\ntype Options = {\n\tblockOnKitRoutes?: boolean,\n\tblockOnPreviewMode?: boolean,\n}\n\nexport default function useRouteStatus(\n\troute: RouteEventDescriptor['name'],\n\t{\n\t\tblockOnKitRoutes = true,\n\t\tblockOnPreviewMode = true,\n\t}: Options = {}\n) {\n\tconst isRouteActive = useIsRouteActive( route );\n\tconst isKitRouteActive = useIsRouteActive( 'panel/global' );\n\tconst isPreviewMode = useIsPreviewMode();\n\n\tconst isActive = isRouteActive && ! ( blockOnPreviewMode && isPreviewMode );\n\n\tconst isBlocked = (\n\t\t( blockOnPreviewMode && isPreviewMode ) ||\n\t\t( blockOnKitRoutes && isKitRouteActive )\n\t);\n\n\treturn {\n\t\tisActive,\n\t\tisBlocked,\n\t};\n}\n"],"mappings":"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","names":["isRouteActive"]}
package/dist/index.mjs CHANGED
@@ -55,6 +55,35 @@ function registerRoute(route) {
55
55
  return Promise.reject(e);
56
56
  }
57
57
  }
58
+ var hookId = 0;
59
+ function blockDataCommand({
60
+ command,
61
+ condition
62
+ }) {
63
+ const extendedWindow = window;
64
+ const DependencyHook = extendedWindow.$e?.modules?.hookData?.Dependency;
65
+ if (!DependencyHook) {
66
+ return Promise.reject("`$e.modules.hookData.Dependency` is not available");
67
+ }
68
+ const __hookId = ++hookId;
69
+ const dependencyHook = new class extends DependencyHook {
70
+ getCommand() {
71
+ return command;
72
+ }
73
+ getId() {
74
+ return `${command}--block--${__hookId}`;
75
+ }
76
+ apply(args) {
77
+ const shouldStopOriginalAction = condition(args);
78
+ return !shouldStopOriginalAction;
79
+ }
80
+ }();
81
+ try {
82
+ return Promise.resolve(dependencyHook.register());
83
+ } catch (e) {
84
+ return Promise.reject(e);
85
+ }
86
+ }
58
87
 
59
88
  // src/hooks/use-listen-to.ts
60
89
  import { useEffect, useState } from "react";
@@ -283,6 +312,7 @@ function useRouteStatus(route, {
283
312
  };
284
313
  }
285
314
  export {
315
+ blockDataCommand as __privateBlockDataCommand,
286
316
  dispatchReadyEvent as __privateDispatchReadyEvent,
287
317
  flushListeners as __privateFlushListeners,
288
318
  getCurrentEditMode as __privateGetCurrentEditMode,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dispatchers/utils.ts","../src/dispatchers/dispatchers.ts","../src/hooks/use-listen-to.ts","../src/listeners/event-creators.ts","../src/listeners/is-ready.ts","../src/listeners/utils.ts","../src/listeners/listeners.ts","../src/readers/index.ts","../src/hooks/use-is-preview-mode.ts","../src/hooks/use-is-route-active.ts","../src/hooks/use-route-status.ts"],"sourcesContent":["import { jQueryDeferred } from './types';\n\nexport function isJQueryDeferred<T>( value: unknown ): value is jQueryDeferred<T> {\n\t// TODO: Copied from:\n\t// https://github.com/elementor/elementor/blob/6a74fc9/modules/web-cli/assets/js/core/commands.js#L410\n\n\treturn ( !! value ) &&\n\t\t'object' === typeof value &&\n\t\tObject.hasOwn( value, 'promise' ) &&\n\t\tObject.hasOwn( value, 'then' ) &&\n\t\tObject.hasOwn( value, 'fail' );\n}\n\nexport function promisifyJQueryDeferred<T>( deferred: jQueryDeferred<T> ): Promise<T> {\n\treturn new Promise( ( resolve, reject ) => {\n\t\tdeferred.then( resolve, reject );\n\t} );\n}\n","import { ExtendedWindow } from './types';\nimport { isJQueryDeferred, promisifyJQueryDeferred } from './utils';\n\nexport function runCommand( command: string, args?: object ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.run ) {\n\t\treturn Promise.reject( '`$e.run()` is not available' );\n\t}\n\n\tconst result = extendedWindow.$e.run( command, args );\n\n\tif ( result instanceof Promise ) {\n\t\treturn result;\n\t}\n\n\tif ( isJQueryDeferred( result ) ) {\n\t\treturn promisifyJQueryDeferred( result );\n\t}\n\n\treturn Promise.resolve( result );\n}\n\nexport function openRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.route ) {\n\t\treturn Promise.reject( '`$e.route()` is not available' );\n\t}\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.route( route )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\nexport function registerRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.routes?.register ) {\n\t\treturn Promise.reject( '`$e.routes.register()` is not available' );\n\t}\n\n\tconst routeParts = route.split( '/' );\n\n\tif ( routeParts.length < 2 ) {\n\t\treturn Promise.reject( `\\`${ route }\\` is an invalid route` );\n\t}\n\n\tconst componentRoute = routeParts.pop() as string; // routeParts.length must be >= 2\n\tconst component = routeParts.join( '/' );\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.routes.register( component, componentRoute, () => null )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n","import { useEffect, useState } from 'react';\nimport { EventDescriptor, listenTo } from '../listeners';\n\nexport default function useListenTo<T>(\n\tevent: EventDescriptor | EventDescriptor[],\n\tgetSnapshot: () => T,\n\tdeps: unknown[] = []\n) {\n\tconst [ snapshot, setSnapshot ] = useState( () => getSnapshot() );\n\n\tuseEffect( () => {\n\t\tconst updateState = () => setSnapshot( getSnapshot() );\n\n\t\t// Ensure the state is re-calculated when the dependencies have been changed.\n\t\tupdateState();\n\n\t\treturn listenTo( event, updateState );\n\t}, deps ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn snapshot;\n}\n","import { CommandEventDescriptor, RouteEventDescriptor, WindowEventDescriptor } from './types';\n\nexport const commandStartEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'before',\n\t};\n};\n\nexport const commandEndEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'after',\n\t};\n};\n\nexport const routeOpenEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'open',\n\t};\n};\n\nexport const routeCloseEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'close',\n\t};\n};\n\nexport const windowEvent = ( event: WindowEventDescriptor['name'] ): WindowEventDescriptor => {\n\treturn {\n\t\ttype: 'window-event',\n\t\tname: event,\n\t};\n};\n\nexport const v1ReadyEvent = () => {\n\treturn windowEvent( 'elementor/initialized' );\n};\n\nexport const editModeChangeEvent = () => {\n\treturn windowEvent( 'elementor/edit-mode/change' );\n};\n","/**\n * This file is used to store the state of the isReady variable, which is used to determine\n * if the adapter is ready to receive events (editor v1 and v2 are loaded).\n */\n\nlet ready = false;\n\nexport function isReady() {\n\treturn ready;\n}\n\nexport function setReady( value: boolean ) {\n\tready = value;\n}\n","import { ExtendedWindow, ListenerEvent } from './types';\nimport { setReady } from './is-ready';\n\nexport function dispatchReadyEvent() {\n\treturn getV1LoadingPromise().then( () => {\n\t\tsetReady( true );\n\t\twindow.dispatchEvent( new CustomEvent( 'elementor/initialized' ) );\n\t} );\n}\n\nfunction getV1LoadingPromise() {\n\tconst v1LoadingPromise = ( window as unknown as ExtendedWindow ).__elementorEditorV1LoadingPromise;\n\n\tif ( ! v1LoadingPromise ) {\n\t\treturn Promise.reject( 'Elementor Editor V1 is not loaded' );\n\t}\n\n\treturn v1LoadingPromise;\n}\n\nexport function normalizeEvent( e: ListenerEvent['originalEvent'] ): ListenerEvent {\n\tif ( e instanceof CustomEvent && e.detail?.command ) {\n\t\treturn {\n\t\t\ttype: 'command',\n\t\t\tcommand: e.detail.command,\n\t\t\targs: e.detail.args,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\tif ( e instanceof CustomEvent && e.detail?.route ) {\n\t\treturn {\n\t\t\ttype: 'route',\n\t\t\troute: e.detail.route,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: 'window-event',\n\t\tevent: e.type,\n\t\toriginalEvent: e,\n\t};\n}\n","import { normalizeEvent } from './utils';\nimport {\n\tCommandEventDescriptor,\n\tEventDescriptor,\n\tListenerCallback,\n\tRouteEventDescriptor,\n\tWindowEventDescriptor,\n} from './types';\nimport { isReady, setReady } from './is-ready';\n\nconst callbacksByEvent = new Map<EventDescriptor['name'], ListenerCallback[]>();\nlet abortController = new AbortController();\n\nexport function listenTo(\n\teventDescriptors: EventDescriptor | EventDescriptor[],\n\tcallback: ListenerCallback\n) {\n\tif ( ! Array.isArray( eventDescriptors ) ) {\n\t\teventDescriptors = [ eventDescriptors ];\n\t}\n\n\t// @see https://github.com/typescript-eslint/typescript-eslint/issues/2841\n\t// eslint-disable-next-line array-callback-return -- Clashes with typescript.\n\tconst cleanups = eventDescriptors.map( ( event ) => {\n\t\tconst { type, name } = event;\n\n\t\tswitch ( type ) {\n\t\t\tcase 'command':\n\t\t\t\treturn registerCommandListener( name, event.state, callback );\n\n\t\t\tcase 'route':\n\t\t\t\treturn registerRouteListener( name, event.state, callback );\n\n\t\t\tcase 'window-event':\n\t\t\t\treturn registerWindowEventListener( name, callback );\n\t\t}\n\t} );\n\n\treturn () => {\n\t\tcleanups.forEach( ( cleanup ) => cleanup() );\n\t};\n}\n\nexport function flushListeners() {\n\tabortController.abort();\n\tcallbacksByEvent.clear();\n\tsetReady( false );\n\n\tabortController = new AbortController();\n}\n\nfunction registerCommandListener(\n\tcommand: CommandEventDescriptor['name'],\n\tstate: CommandEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/commands/run/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'command' && e.command === command;\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerRouteListener(\n\troute: RouteEventDescriptor['name'],\n\tstate: RouteEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/routes/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'route' && e.route.startsWith( route );\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerWindowEventListener( event: WindowEventDescriptor['name'], callback: ListenerCallback ) {\n\tconst isFirstListener = ! callbacksByEvent.has( event );\n\n\tif ( isFirstListener ) {\n\t\tcallbacksByEvent.set( event, [] );\n\n\t\taddListener( event );\n\t}\n\n\tcallbacksByEvent.get( event )?.push( callback );\n\n\treturn () => {\n\t\tconst callbacks = callbacksByEvent.get( event );\n\n\t\tif ( ! callbacks?.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst filtered = callbacks.filter( ( cb ) => cb !== callback );\n\n\t\tcallbacksByEvent.set( event, filtered );\n\t};\n}\n\nfunction addListener( event: EventDescriptor['name'] ) {\n\twindow.addEventListener(\n\t\tevent,\n\t\tmakeEventHandler( event ),\n\t\t{ signal: abortController.signal }\n\t);\n}\n\nfunction makeEventHandler( event: EventDescriptor['name'] ): EventListener {\n\treturn ( e ) => {\n\t\tif ( ! isReady() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedEvent = normalizeEvent( e );\n\n\t\tcallbacksByEvent.get( event )?.forEach( ( callback ) => {\n\t\t\tcallback( normalizedEvent );\n\t\t} );\n\t};\n}\n","import { ExtendedWindow } from './types';\n\nexport function isRouteActive( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn !! extendedWindow.$e?.routes?.isPartOf( route );\n}\n\nexport function getCurrentEditMode() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.dataEditMode?.request?.( 'activeMode' );\n}\n","import useListenTo from './use-listen-to';\nimport { getCurrentEditMode } from '../readers';\nimport { editModeChangeEvent } from '../listeners';\n\nexport default function useIsPreviewMode() {\n\treturn useListenTo(\n\t\teditModeChangeEvent(),\n\t\t() => getCurrentEditMode() === 'preview'\n\t);\n}\n","import useListenTo from './use-listen-to';\nimport { isRouteActive } from '../readers';\nimport { routeCloseEvent, routeOpenEvent, RouteEventDescriptor } from '../listeners';\n\nexport default function useIsRouteActive( route: RouteEventDescriptor['name'] ) {\n\treturn useListenTo(\n\t\t[\n\t\t\trouteOpenEvent( route ),\n\t\t\trouteCloseEvent( route ),\n\t\t],\n\t\t() => isRouteActive( route ),\n\t\t[ route ]\n\t);\n}\n","import useIsPreviewMode from './use-is-preview-mode';\nimport useIsRouteActive from './use-is-route-active';\nimport { RouteEventDescriptor } from '../listeners';\n\ntype Options = {\n\tblockOnKitRoutes?: boolean,\n\tblockOnPreviewMode?: boolean,\n}\n\nexport default function useRouteStatus(\n\troute: RouteEventDescriptor['name'],\n\t{\n\t\tblockOnKitRoutes = true,\n\t\tblockOnPreviewMode = true,\n\t}: Options = {}\n) {\n\tconst isRouteActive = useIsRouteActive( route );\n\tconst isKitRouteActive = useIsRouteActive( 'panel/global' );\n\tconst isPreviewMode = useIsPreviewMode();\n\n\tconst isActive = isRouteActive && ! ( blockOnPreviewMode && isPreviewMode );\n\n\tconst isBlocked = (\n\t\t( blockOnPreviewMode && isPreviewMode ) ||\n\t\t( blockOnKitRoutes && isKitRouteActive )\n\t);\n\n\treturn {\n\t\tisActive,\n\t\tisBlocked,\n\t};\n}\n"],"mappings":"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","names":["isRouteActive"]}
1
+ {"version":3,"sources":["../src/dispatchers/utils.ts","../src/dispatchers/dispatchers.ts","../src/hooks/use-listen-to.ts","../src/listeners/event-creators.ts","../src/listeners/is-ready.ts","../src/listeners/utils.ts","../src/listeners/listeners.ts","../src/readers/index.ts","../src/hooks/use-is-preview-mode.ts","../src/hooks/use-is-route-active.ts","../src/hooks/use-route-status.ts"],"sourcesContent":["import { jQueryDeferred } from './types';\n\nexport function isJQueryDeferred<T>( value: unknown ): value is jQueryDeferred<T> {\n\t// TODO: Copied from:\n\t// https://github.com/elementor/elementor/blob/6a74fc9/modules/web-cli/assets/js/core/commands.js#L410\n\n\treturn ( !! value ) &&\n\t\t'object' === typeof value &&\n\t\tObject.hasOwn( value, 'promise' ) &&\n\t\tObject.hasOwn( value, 'then' ) &&\n\t\tObject.hasOwn( value, 'fail' );\n}\n\nexport function promisifyJQueryDeferred<T>( deferred: jQueryDeferred<T> ): Promise<T> {\n\treturn new Promise( ( resolve, reject ) => {\n\t\tdeferred.then( resolve, reject );\n\t} );\n}\n","import { ExtendedWindow } from './types';\nimport { isJQueryDeferred, promisifyJQueryDeferred } from './utils';\n\nexport function runCommand( command: string, args?: object ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.run ) {\n\t\treturn Promise.reject( '`$e.run()` is not available' );\n\t}\n\n\tconst result = extendedWindow.$e.run( command, args );\n\n\tif ( result instanceof Promise ) {\n\t\treturn result;\n\t}\n\n\tif ( isJQueryDeferred( result ) ) {\n\t\treturn promisifyJQueryDeferred( result );\n\t}\n\n\treturn Promise.resolve( result );\n}\n\nexport function openRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.route ) {\n\t\treturn Promise.reject( '`$e.route()` is not available' );\n\t}\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.route( route )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\nexport function registerRoute( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\tif ( ! extendedWindow.$e?.routes?.register ) {\n\t\treturn Promise.reject( '`$e.routes.register()` is not available' );\n\t}\n\n\tconst routeParts = route.split( '/' );\n\n\tif ( routeParts.length < 2 ) {\n\t\treturn Promise.reject( `\\`${ route }\\` is an invalid route` );\n\t}\n\n\tconst componentRoute = routeParts.pop() as string; // routeParts.length must be >= 2\n\tconst component = routeParts.join( '/' );\n\n\ttry {\n\t\treturn Promise.resolve(\n\t\t\textendedWindow.$e.routes.register( component, componentRoute, () => null )\n\t\t);\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n\ntype UnknownArgs = Record<string, unknown>;\n\nlet hookId = 0;\n\nexport function blockDataCommand( {\n\tcommand,\n\tcondition,\n}: {\n\tcommand: string,\n\tcondition: ( args: UnknownArgs ) => boolean,\n} ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\tconst DependencyHook = extendedWindow.$e?.modules?.hookData?.Dependency;\n\n\tif ( ! DependencyHook ) {\n\t\treturn Promise.reject( '`$e.modules.hookData.Dependency` is not available' );\n\t}\n\n\tconst __hookId = ++hookId;\n\n\tconst dependencyHook = new class extends DependencyHook {\n\t\tgetCommand() {\n\t\t\treturn command;\n\t\t}\n\n\t\tgetId() {\n\t\t\treturn `${ command }--block--${ __hookId }`;\n\t\t}\n\n\t\tapply( args: UnknownArgs ) {\n\t\t\t// If the condition is met, we will stop the original command from running.\n\t\t\tconst shouldStopOriginalAction = condition( args );\n\n\t\t\t// We will return `false` if we want to stop the original action from running.\n\t\t\treturn ! shouldStopOriginalAction;\n\t\t}\n\t};\n\n\ttry {\n\t\treturn Promise.resolve( dependencyHook.register() );\n\t} catch ( e ) {\n\t\treturn Promise.reject( e );\n\t}\n}\n","import { useEffect, useState } from 'react';\nimport { EventDescriptor, listenTo } from '../listeners';\n\nexport default function useListenTo<T>(\n\tevent: EventDescriptor | EventDescriptor[],\n\tgetSnapshot: () => T,\n\tdeps: unknown[] = []\n) {\n\tconst [ snapshot, setSnapshot ] = useState( () => getSnapshot() );\n\n\tuseEffect( () => {\n\t\tconst updateState = () => setSnapshot( getSnapshot() );\n\n\t\t// Ensure the state is re-calculated when the dependencies have been changed.\n\t\tupdateState();\n\n\t\treturn listenTo( event, updateState );\n\t}, deps ); // eslint-disable-line react-hooks/exhaustive-deps\n\n\treturn snapshot;\n}\n","import { CommandEventDescriptor, RouteEventDescriptor, WindowEventDescriptor } from './types';\n\nexport const commandStartEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'before',\n\t};\n};\n\nexport const commandEndEvent = ( command: CommandEventDescriptor['name'] ): CommandEventDescriptor => {\n\treturn {\n\t\ttype: 'command',\n\t\tname: command,\n\t\tstate: 'after',\n\t};\n};\n\nexport const routeOpenEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'open',\n\t};\n};\n\nexport const routeCloseEvent = ( route: RouteEventDescriptor['name'] ): RouteEventDescriptor => {\n\treturn {\n\t\ttype: 'route',\n\t\tname: route,\n\t\tstate: 'close',\n\t};\n};\n\nexport const windowEvent = ( event: WindowEventDescriptor['name'] ): WindowEventDescriptor => {\n\treturn {\n\t\ttype: 'window-event',\n\t\tname: event,\n\t};\n};\n\nexport const v1ReadyEvent = () => {\n\treturn windowEvent( 'elementor/initialized' );\n};\n\nexport const editModeChangeEvent = () => {\n\treturn windowEvent( 'elementor/edit-mode/change' );\n};\n","/**\n * This file is used to store the state of the isReady variable, which is used to determine\n * if the adapter is ready to receive events (editor v1 and v2 are loaded).\n */\n\nlet ready = false;\n\nexport function isReady() {\n\treturn ready;\n}\n\nexport function setReady( value: boolean ) {\n\tready = value;\n}\n","import { ExtendedWindow, ListenerEvent } from './types';\nimport { setReady } from './is-ready';\n\nexport function dispatchReadyEvent() {\n\treturn getV1LoadingPromise().then( () => {\n\t\tsetReady( true );\n\t\twindow.dispatchEvent( new CustomEvent( 'elementor/initialized' ) );\n\t} );\n}\n\nfunction getV1LoadingPromise() {\n\tconst v1LoadingPromise = ( window as unknown as ExtendedWindow ).__elementorEditorV1LoadingPromise;\n\n\tif ( ! v1LoadingPromise ) {\n\t\treturn Promise.reject( 'Elementor Editor V1 is not loaded' );\n\t}\n\n\treturn v1LoadingPromise;\n}\n\nexport function normalizeEvent( e: ListenerEvent['originalEvent'] ): ListenerEvent {\n\tif ( e instanceof CustomEvent && e.detail?.command ) {\n\t\treturn {\n\t\t\ttype: 'command',\n\t\t\tcommand: e.detail.command,\n\t\t\targs: e.detail.args,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\tif ( e instanceof CustomEvent && e.detail?.route ) {\n\t\treturn {\n\t\t\ttype: 'route',\n\t\t\troute: e.detail.route,\n\t\t\toriginalEvent: e,\n\t\t};\n\t}\n\n\treturn {\n\t\ttype: 'window-event',\n\t\tevent: e.type,\n\t\toriginalEvent: e,\n\t};\n}\n","import { normalizeEvent } from './utils';\nimport {\n\tCommandEventDescriptor,\n\tEventDescriptor,\n\tListenerCallback,\n\tRouteEventDescriptor,\n\tWindowEventDescriptor,\n} from './types';\nimport { isReady, setReady } from './is-ready';\n\nconst callbacksByEvent = new Map<EventDescriptor['name'], ListenerCallback[]>();\nlet abortController = new AbortController();\n\nexport function listenTo(\n\teventDescriptors: EventDescriptor | EventDescriptor[],\n\tcallback: ListenerCallback\n) {\n\tif ( ! Array.isArray( eventDescriptors ) ) {\n\t\teventDescriptors = [ eventDescriptors ];\n\t}\n\n\t// @see https://github.com/typescript-eslint/typescript-eslint/issues/2841\n\t// eslint-disable-next-line array-callback-return -- Clashes with typescript.\n\tconst cleanups = eventDescriptors.map( ( event ) => {\n\t\tconst { type, name } = event;\n\n\t\tswitch ( type ) {\n\t\t\tcase 'command':\n\t\t\t\treturn registerCommandListener( name, event.state, callback );\n\n\t\t\tcase 'route':\n\t\t\t\treturn registerRouteListener( name, event.state, callback );\n\n\t\t\tcase 'window-event':\n\t\t\t\treturn registerWindowEventListener( name, callback );\n\t\t}\n\t} );\n\n\treturn () => {\n\t\tcleanups.forEach( ( cleanup ) => cleanup() );\n\t};\n}\n\nexport function flushListeners() {\n\tabortController.abort();\n\tcallbacksByEvent.clear();\n\tsetReady( false );\n\n\tabortController = new AbortController();\n}\n\nfunction registerCommandListener(\n\tcommand: CommandEventDescriptor['name'],\n\tstate: CommandEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/commands/run/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'command' && e.command === command;\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerRouteListener(\n\troute: RouteEventDescriptor['name'],\n\tstate: RouteEventDescriptor['state'],\n\tcallback: ListenerCallback\n) {\n\treturn registerWindowEventListener( `elementor/routes/${ state }`, ( e ) => {\n\t\tconst shouldRunCallback = e.type === 'route' && e.route.startsWith( route );\n\n\t\tif ( shouldRunCallback ) {\n\t\t\tcallback( e );\n\t\t}\n\t} );\n}\n\nfunction registerWindowEventListener( event: WindowEventDescriptor['name'], callback: ListenerCallback ) {\n\tconst isFirstListener = ! callbacksByEvent.has( event );\n\n\tif ( isFirstListener ) {\n\t\tcallbacksByEvent.set( event, [] );\n\n\t\taddListener( event );\n\t}\n\n\tcallbacksByEvent.get( event )?.push( callback );\n\n\treturn () => {\n\t\tconst callbacks = callbacksByEvent.get( event );\n\n\t\tif ( ! callbacks?.length ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst filtered = callbacks.filter( ( cb ) => cb !== callback );\n\n\t\tcallbacksByEvent.set( event, filtered );\n\t};\n}\n\nfunction addListener( event: EventDescriptor['name'] ) {\n\twindow.addEventListener(\n\t\tevent,\n\t\tmakeEventHandler( event ),\n\t\t{ signal: abortController.signal }\n\t);\n}\n\nfunction makeEventHandler( event: EventDescriptor['name'] ): EventListener {\n\treturn ( e ) => {\n\t\tif ( ! isReady() ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedEvent = normalizeEvent( e );\n\n\t\tcallbacksByEvent.get( event )?.forEach( ( callback ) => {\n\t\t\tcallback( normalizedEvent );\n\t\t} );\n\t};\n}\n","import { ExtendedWindow } from './types';\n\nexport function isRouteActive( route: string ) {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn !! extendedWindow.$e?.routes?.isPartOf( route );\n}\n\nexport function getCurrentEditMode() {\n\tconst extendedWindow = window as unknown as ExtendedWindow;\n\n\treturn extendedWindow.elementor?.channels?.dataEditMode?.request?.( 'activeMode' );\n}\n","import useListenTo from './use-listen-to';\nimport { getCurrentEditMode } from '../readers';\nimport { editModeChangeEvent } from '../listeners';\n\nexport default function useIsPreviewMode() {\n\treturn useListenTo(\n\t\teditModeChangeEvent(),\n\t\t() => getCurrentEditMode() === 'preview'\n\t);\n}\n","import useListenTo from './use-listen-to';\nimport { isRouteActive } from '../readers';\nimport { routeCloseEvent, routeOpenEvent, RouteEventDescriptor } from '../listeners';\n\nexport default function useIsRouteActive( route: RouteEventDescriptor['name'] ) {\n\treturn useListenTo(\n\t\t[\n\t\t\trouteOpenEvent( route ),\n\t\t\trouteCloseEvent( route ),\n\t\t],\n\t\t() => isRouteActive( route ),\n\t\t[ route ]\n\t);\n}\n","import useIsPreviewMode from './use-is-preview-mode';\nimport useIsRouteActive from './use-is-route-active';\nimport { RouteEventDescriptor } from '../listeners';\n\ntype Options = {\n\tblockOnKitRoutes?: boolean,\n\tblockOnPreviewMode?: boolean,\n}\n\nexport default function useRouteStatus(\n\troute: RouteEventDescriptor['name'],\n\t{\n\t\tblockOnKitRoutes = true,\n\t\tblockOnPreviewMode = true,\n\t}: Options = {}\n) {\n\tconst isRouteActive = useIsRouteActive( route );\n\tconst isKitRouteActive = useIsRouteActive( 'panel/global' );\n\tconst isPreviewMode = useIsPreviewMode();\n\n\tconst isActive = isRouteActive && ! ( blockOnPreviewMode && isPreviewMode );\n\n\tconst isBlocked = (\n\t\t( blockOnPreviewMode && isPreviewMode ) ||\n\t\t( blockOnKitRoutes && isKitRouteActive )\n\t);\n\n\treturn {\n\t\tisActive,\n\t\tisBlocked,\n\t};\n}\n"],"mappings":"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","names":["isRouteActive"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-v1-adapters",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -34,5 +34,5 @@
34
34
  "peerDependencies": {
35
35
  "react": "^18.3.1"
36
36
  },
37
- "gitHead": "8fee803f32268363169a260a99c2eb7c2d548b39"
37
+ "gitHead": "33d28e27101a9bf272b11d19d7092830e8cb69d0"
38
38
  }
@@ -1,12 +1,16 @@
1
- import { openRoute, registerRoute, runCommand } from '../index';
2
- import { ExtendedWindow } from '../types';
1
+ import { openRoute, blockDataCommand, registerRoute, runCommand } from '../index';
2
+ import { DependencyHook, ExtendedWindow } from '../types';
3
3
 
4
4
  describe( '@elementor/editor-v1-adapters/dispatchers', () => {
5
5
  let eRun: jest.Mock,
6
6
  eRoute: jest.Mock,
7
- eRegisterRoute: jest.Mock;
7
+ eRegisterRoute: jest.Mock,
8
+ eDependencyRegisterSpy: jest.SpyInstance;
9
+
10
+ let hooks: DependencyHook[] = [];
8
11
 
9
12
  beforeEach( () => {
13
+ hooks = [];
10
14
  const extendedWindow = window as unknown as ExtendedWindow;
11
15
 
12
16
  extendedWindow.$e = {
@@ -15,11 +19,21 @@ describe( '@elementor/editor-v1-adapters/dispatchers', () => {
15
19
  routes: {
16
20
  register: jest.fn(),
17
21
  },
22
+ modules: {
23
+ hookData: {
24
+ Dependency: class {
25
+ register() {
26
+ hooks.push( this as never );
27
+ }
28
+ } as typeof DependencyHook,
29
+ },
30
+ },
18
31
  };
19
32
 
20
33
  eRun = jest.mocked( extendedWindow.$e.run );
21
34
  eRoute = jest.mocked( extendedWindow.$e.route );
22
35
  eRegisterRoute = jest.mocked( extendedWindow.$e?.routes?.register || jest.fn() );
36
+ eDependencyRegisterSpy = jest.spyOn( extendedWindow.$e?.modules?.hookData?.Dependency?.prototype as DependencyHook, 'register' );
23
37
  } );
24
38
 
25
39
  it( 'should run a V1 command that returns Promise', () => {
@@ -115,6 +129,10 @@ describe( '@elementor/editor-v1-adapters/dispatchers', () => {
115
129
  [ '$e.route()', () => openRoute( 'test/route' ) ],
116
130
  [ '$e.run()', () => runCommand( 'editor/documents/open' ) ],
117
131
  [ '$e.routes.register()', () => registerRoute( 'test/route' ) ],
132
+ [ '$e.modules.hookData.Dependency', () => blockDataCommand( {
133
+ command: '',
134
+ condition: () => true,
135
+ } ) ],
118
136
  ] )( 'should reject when trying to use V1 and `%s` is unavailable', ( v1Method, action ) => {
119
137
  // Arrange.
120
138
  delete ( window as { $e?: unknown } ).$e;
@@ -124,6 +142,71 @@ describe( '@elementor/editor-v1-adapters/dispatchers', () => {
124
142
  .rejects
125
143
  .toEqual( `\`${ v1Method }\` is not available` );
126
144
  } );
145
+
146
+ it( 'should register a V1 dependency hook that blocks a V1 command', () => {
147
+ // Act.
148
+ const result = blockDataCommand( {
149
+ command: '',
150
+ condition: () => true,
151
+ } );
152
+
153
+ // Assert.
154
+ expect( eDependencyRegisterSpy ).toHaveBeenCalled();
155
+ expect( result ).toEqual( Promise.resolve() );
156
+ } );
157
+
158
+ it( 'should reject when failing to register a V1 dependency hook that blocks a V1 command', () => {
159
+ // Arrange.
160
+ eDependencyRegisterSpy.mockImplementation( () => {
161
+ throw 'Error';
162
+ } );
163
+
164
+ // Act & Assert.
165
+ expect( () => blockDataCommand( {
166
+ command: '',
167
+ condition: () => true,
168
+ } ) )
169
+ .rejects
170
+ .toEqual( 'Error' );
171
+ } );
172
+
173
+ it( 'should get the right command name, id and condition when blocking a v1 command', () => {
174
+ // Arrange.
175
+ blockDataCommand( {
176
+ command: 'editor/documents/open',
177
+ condition: ( args ) => 'key' in args,
178
+ } );
179
+
180
+ blockDataCommand( {
181
+ command: 'editor/documents/open',
182
+ condition: () => false,
183
+ } );
184
+
185
+ blockDataCommand( {
186
+ command: 'editor/documents/close',
187
+ condition: () => false,
188
+ } );
189
+
190
+ // Act & Assert.
191
+ expect( hooks ).toHaveLength( 3 );
192
+
193
+ expect( hooks[ 0 ].getCommand() ).toEqual( 'editor/documents/open' );
194
+ expect( hooks[ 1 ].getCommand() ).toEqual( 'editor/documents/open' );
195
+ expect( hooks[ 2 ].getCommand() ).toEqual( 'editor/documents/close' );
196
+
197
+ const hookId1 = hooks[ 0 ].getId();
198
+ const hookId2 = hooks[ 1 ].getId();
199
+ const hookId3 = hooks[ 2 ].getId();
200
+
201
+ expect( hookId1 ).not.toEqual( hookId2 );
202
+
203
+ expect( hookId1 ).toMatch( /^editor\/documents\/open--block--\d+$/ );
204
+ expect( hookId2 ).toMatch( /^editor\/documents\/open--block--\d+$/ );
205
+ expect( hookId3 ).toMatch( /^editor\/documents\/close--block--\d+$/ );
206
+
207
+ expect( hooks[ 0 ].apply( { key: 'value' } ) ).toBe( false );
208
+ expect( hooks[ 0 ].apply( { value: 'value' } ) ).toBe( true );
209
+ } );
127
210
  } );
128
211
 
129
212
  function makeJQueryDeferred( value: unknown ) {
@@ -61,3 +61,48 @@ export function registerRoute( route: string ) {
61
61
  return Promise.reject( e );
62
62
  }
63
63
  }
64
+
65
+ type UnknownArgs = Record<string, unknown>;
66
+
67
+ let hookId = 0;
68
+
69
+ export function blockDataCommand( {
70
+ command,
71
+ condition,
72
+ }: {
73
+ command: string,
74
+ condition: ( args: UnknownArgs ) => boolean,
75
+ } ) {
76
+ const extendedWindow = window as unknown as ExtendedWindow;
77
+ const DependencyHook = extendedWindow.$e?.modules?.hookData?.Dependency;
78
+
79
+ if ( ! DependencyHook ) {
80
+ return Promise.reject( '`$e.modules.hookData.Dependency` is not available' );
81
+ }
82
+
83
+ const __hookId = ++hookId;
84
+
85
+ const dependencyHook = new class extends DependencyHook {
86
+ getCommand() {
87
+ return command;
88
+ }
89
+
90
+ getId() {
91
+ return `${ command }--block--${ __hookId }`;
92
+ }
93
+
94
+ apply( args: UnknownArgs ) {
95
+ // If the condition is met, we will stop the original command from running.
96
+ const shouldStopOriginalAction = condition( args );
97
+
98
+ // We will return `false` if we want to stop the original action from running.
99
+ return ! shouldStopOriginalAction;
100
+ }
101
+ };
102
+
103
+ try {
104
+ return Promise.resolve( dependencyHook.register() );
105
+ } catch ( e ) {
106
+ return Promise.reject( e );
107
+ }
108
+ }
@@ -12,6 +12,18 @@ export type ExtendedWindow = Window & {
12
12
  route: string,
13
13
  callback: () => unknown
14
14
  ) => unknown;
15
+ },
16
+ modules?: {
17
+ hookData?: {
18
+ Dependency: typeof DependencyHook,
19
+ }
15
20
  }
16
21
  },
17
22
  }
23
+
24
+ export declare class DependencyHook {
25
+ getCommand(): string;
26
+ getId(): string;
27
+ apply( args: Record<string, unknown> ): boolean;
28
+ register(): void;
29
+ }
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ export {
2
2
  runCommand as __privateRunCommand,
3
3
  openRoute as __privateOpenRoute,
4
4
  registerRoute as __privateRegisterRoute,
5
+ blockDataCommand as __privateBlockDataCommand,
5
6
  } from './dispatchers';
6
7
 
7
8
  export {