@elementor/locations
Advanced tools
+40
-10
@@ -78,7 +78,27 @@ "use strict"; | ||
| } | ||
| function createSubscription() { | ||
| const listeners = /* @__PURE__ */ new Set(); | ||
| return { | ||
| subscribe: (listener) => { | ||
| listeners.add(listener); | ||
| return () => listeners.delete(listener); | ||
| }, | ||
| notify: () => listeners.forEach((listener) => listener()) | ||
| }; | ||
| } | ||
| function createGetInjections(injections) { | ||
| return () => [...injections.values()].sort((a, b) => a.priority - b.priority); | ||
| } | ||
| function createUseInjections(getInjections) { | ||
| return () => (0, import_react3.useMemo)(() => getInjections(), []); | ||
| function createUseInjections(getInjections, subscribe) { | ||
| let snapshot = null; | ||
| subscribe(() => { | ||
| snapshot = null; | ||
| }); | ||
| const getSnapshot = () => { | ||
| if (!snapshot) { | ||
| snapshot = getInjections(); | ||
| } | ||
| return snapshot; | ||
| }; | ||
| return () => (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot); | ||
| } | ||
@@ -92,7 +112,11 @@ function wrapInjectedComponent(Component2) { | ||
| const injections = /* @__PURE__ */ new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections(injections); | ||
| const useInjections = createUseInjections(getInjections); | ||
| const useInjections = createUseInjections(getInjections, subscribe); | ||
| const Slot = createSlot(useInjections); | ||
| const inject = createInject(injections); | ||
| flushInjectionsFns.push(() => injections.clear()); | ||
| const inject = createInject(injections, notify); | ||
| flushInjectionsFns.push(() => { | ||
| injections.clear(); | ||
| notify(); | ||
| }); | ||
| return { | ||
@@ -111,3 +135,3 @@ inject, | ||
| } | ||
| function createInject(injections) { | ||
| function createInject(injections, notify) { | ||
| return ({ component, id, options = {} }) => { | ||
@@ -125,2 +149,3 @@ if (injections.has(id) && !options?.overwrite) { | ||
| }); | ||
| notify(); | ||
| }; | ||
@@ -133,7 +158,11 @@ } | ||
| const injections = /* @__PURE__ */ new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections(injections); | ||
| const useInjections = createUseInjections(getInjections); | ||
| const useInjections = createUseInjections(getInjections, subscribe); | ||
| const Slot = createReplaceable(useInjections); | ||
| const inject = createRegister(injections); | ||
| flushInjectionsFns.push(() => injections.clear()); | ||
| const inject = createRegister(injections, notify); | ||
| flushInjectionsFns.push(() => { | ||
| injections.clear(); | ||
| notify(); | ||
| }); | ||
| return { | ||
@@ -156,3 +185,3 @@ getInjections, | ||
| } | ||
| function createRegister(injections) { | ||
| function createRegister(injections, notify) { | ||
| return ({ component, id, condition = () => true, options = {} }) => { | ||
@@ -165,2 +194,3 @@ injections.set(id, { | ||
| }); | ||
| notify(); | ||
| }; | ||
@@ -167,0 +197,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts","../src/create-location.tsx","../src/injections.tsx","../src/components/injected-component-wrapper.tsx","../src/components/error-boundary.tsx","../src/create-replaceable-location.tsx"],"sourcesContent":["export * from './types';\n\nexport { createLocation } from './create-location';\nexport { createReplaceableLocation } from './create-replaceable-location';\nexport { flushAllInjections as __flushAllInjections } from './injections';\n","import * as React from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport { type AnyProps, type Id, type InjectArgs, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport function createLocation< TProps extends object = AnyProps >(): Location< TProps > {\n\tconst injections: InjectionsMap< TProps > = new Map();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections );\n\tconst Slot = createSlot( useInjections );\n\tconst inject = createInject( injections );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\tflushInjectionsFns.push( () => injections.clear() );\n\n\treturn {\n\t\tinject,\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tSlot,\n\t};\n}\n\nfunction createSlot< TProps extends object = AnyProps >( useInjections: Location< TProps >[ 'useInjections' ] ) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ injections.map( ( { id, component: Component } ) => (\n\t\t\t\t\t<Component { ...props } key={ id } />\n\t\t\t\t) ) }\n\t\t\t</>\n\t\t);\n\t};\n}\n\nfunction createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn ( { component, id, options = {} }: InjectArgs< TProps > ) => {\n\t\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`An injection with the id \"${ id }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\t};\n}\n","import * as React from 'react';\nimport { useMemo } from 'react';\n\nimport InjectedComponentWrapper from './components/injected-component-wrapper';\nimport { type AnyProps, type Id, type InjectedComponent, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport const DEFAULT_PRIORITY = 10;\n\n// Allow flushing all injections at once, for testing purposes.\nexport const flushInjectionsFns: ( () => void )[] = [];\n\nexport function flushAllInjections() {\n\tflushInjectionsFns.forEach( ( flush ) => flush() );\n}\n\nexport function createGetInjections< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn () => [ ...injections.values() ].sort( ( a, b ) => a.priority - b.priority );\n}\n\nexport function createUseInjections< TProps extends object = AnyProps >(\n\tgetInjections: Location< TProps >[ 'getInjections' ]\n) {\n\treturn () => useMemo( () => getInjections(), [] );\n}\n\nexport function wrapInjectedComponent< TProps extends object = AnyProps >( Component: InjectedComponent< TProps > ) {\n\treturn ( props: TProps ) => (\n\t\t<InjectedComponentWrapper>\n\t\t\t<Component { ...props } />\n\t\t</InjectedComponentWrapper>\n\t);\n}\n","import * as React from 'react';\nimport { type ReactNode, Suspense } from 'react';\n\nimport ErrorBoundary from './error-boundary';\n\nexport default function InjectedComponentWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>{ children }</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, type ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component< Props, State > {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import * as React from 'react';\nimport { type PropsWithChildren } from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport {\n\ttype AnyProps,\n\ttype Id,\n\ttype ReplaceableInjectArgs,\n\ttype ReplaceableInjection,\n\ttype ReplaceableLocation,\n} from './types';\n\ntype ReplaceableInjectionsMap< TProps extends object = AnyProps > = Map< Id, ReplaceableInjection< TProps > >;\n\nexport function createReplaceableLocation< TProps extends object = AnyProps >(): ReplaceableLocation< TProps > {\n\tconst injections: ReplaceableInjectionsMap< TProps > = new Map();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections );\n\tconst Slot = createReplaceable( useInjections );\n\tconst inject = createRegister( injections );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\tflushInjectionsFns.push( () => injections.clear() );\n\n\treturn {\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tinject,\n\t\tSlot,\n\t};\n}\n\nfunction createReplaceable< TProps extends PropsWithChildren< object > = AnyProps >(\n\tuseInjections: ReplaceableLocation< TProps >[ 'useInjections' ]\n) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\tconst { component: Component } = injections.find( ( { condition } ) => condition?.( props ) ) ?? {};\n\n\t\tif ( ! Component ) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\treturn <Component { ...props } />;\n\t};\n}\n\nfunction createRegister< TProps extends object = AnyProps >( injections: ReplaceableInjectionsMap< TProps > ) {\n\treturn ( { component, id, condition = () => true, options = {} }: ReplaceableInjectArgs< TProps > ) => {\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tcondition,\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\t};\n}\n"],"mappings":"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","names":["React","React","import_react","import_react","Component","Component","React","Component"]} | ||
| {"version":3,"sources":["../src/index.ts","../src/create-location.tsx","../src/injections.tsx","../src/components/injected-component-wrapper.tsx","../src/components/error-boundary.tsx","../src/create-replaceable-location.tsx"],"sourcesContent":["export * from './types';\n\nexport { createLocation } from './create-location';\nexport { createReplaceableLocation } from './create-replaceable-location';\nexport { flushAllInjections as __flushAllInjections } from './injections';\n","import * as React from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateSubscription,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport { type AnyProps, type Id, type InjectArgs, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport function createLocation< TProps extends object = AnyProps >(): Location< TProps > {\n\tconst injections: InjectionsMap< TProps > = new Map();\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections, subscribe );\n\tconst Slot = createSlot( useInjections );\n\tconst inject = createInject( injections, notify );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\t// `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush,\n\t// which matters for test isolation between test cases.\n\tflushInjectionsFns.push( () => {\n\t\tinjections.clear();\n\t\tnotify();\n\t} );\n\n\treturn {\n\t\tinject,\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tSlot,\n\t};\n}\n\nfunction createSlot< TProps extends object = AnyProps >( useInjections: Location< TProps >[ 'useInjections' ] ) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ injections.map( ( { id, component: Component } ) => (\n\t\t\t\t\t<Component { ...props } key={ id } />\n\t\t\t\t) ) }\n\t\t\t</>\n\t\t);\n\t};\n}\n\nfunction createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps >, notify: () => void ) {\n\treturn ( { component, id, options = {} }: InjectArgs< TProps > ) => {\n\t\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`An injection with the id \"${ id }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n","import * as React from 'react';\nimport { useSyncExternalStore } from 'react';\n\nimport InjectedComponentWrapper from './components/injected-component-wrapper';\nimport { type AnyProps, type Id, type InjectedComponent, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport const DEFAULT_PRIORITY = 10;\n\n// Allow flushing all injections at once, for testing purposes.\nexport const flushInjectionsFns: ( () => void )[] = [];\n\nexport function flushAllInjections() {\n\tflushInjectionsFns.forEach( ( flush ) => flush() );\n}\n\nexport type Subscribe = ( listener: () => void ) => () => void;\n\nexport function createSubscription() {\n\tconst listeners = new Set< () => void >();\n\n\treturn {\n\t\tsubscribe: ( listener: () => void ) => {\n\t\t\tlisteners.add( listener );\n\n\t\t\treturn () => listeners.delete( listener );\n\t\t},\n\t\tnotify: () => listeners.forEach( ( listener ) => listener() ),\n\t};\n}\n\nexport function createGetInjections< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn () => [ ...injections.values() ].sort( ( a, b ) => a.priority - b.priority );\n}\n\n// Injections registered after the `Slot` has already mounted (e.g. by an external plugin's\n// script that loads after the editor has rendered) must still be reflected in the UI, so the\n// snapshot is invalidated and re-read whenever `notify()` is called.\nexport function createUseInjections< TProps extends object = AnyProps >(\n\tgetInjections: Location< TProps >[ 'getInjections' ],\n\tsubscribe: Subscribe\n) {\n\tlet snapshot: ReturnType< Location< TProps >[ 'getInjections' ] > | null = null;\n\n\tsubscribe( () => {\n\t\tsnapshot = null;\n\t} );\n\n\tconst getSnapshot = () => {\n\t\tif ( ! snapshot ) {\n\t\t\tsnapshot = getInjections();\n\t\t}\n\n\t\treturn snapshot;\n\t};\n\n\treturn () => useSyncExternalStore( subscribe, getSnapshot );\n}\n\nexport function wrapInjectedComponent< TProps extends object = AnyProps >( Component: InjectedComponent< TProps > ) {\n\treturn ( props: TProps ) => (\n\t\t<InjectedComponentWrapper>\n\t\t\t<Component { ...props } />\n\t\t</InjectedComponentWrapper>\n\t);\n}\n","import * as React from 'react';\nimport { type ReactNode, Suspense } from 'react';\n\nimport ErrorBoundary from './error-boundary';\n\nexport default function InjectedComponentWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>{ children }</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, type ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component< Props, State > {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import * as React from 'react';\nimport { type PropsWithChildren } from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateSubscription,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport {\n\ttype AnyProps,\n\ttype Id,\n\ttype ReplaceableInjectArgs,\n\ttype ReplaceableInjection,\n\ttype ReplaceableLocation,\n} from './types';\n\ntype ReplaceableInjectionsMap< TProps extends object = AnyProps > = Map< Id, ReplaceableInjection< TProps > >;\n\nexport function createReplaceableLocation< TProps extends object = AnyProps >(): ReplaceableLocation< TProps > {\n\tconst injections: ReplaceableInjectionsMap< TProps > = new Map();\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections, subscribe );\n\tconst Slot = createReplaceable( useInjections );\n\tconst inject = createRegister( injections, notify );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\t// `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush,\n\t// which matters for test isolation between test cases.\n\tflushInjectionsFns.push( () => {\n\t\tinjections.clear();\n\t\tnotify();\n\t} );\n\n\treturn {\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tinject,\n\t\tSlot,\n\t};\n}\n\nfunction createReplaceable< TProps extends PropsWithChildren< object > = AnyProps >(\n\tuseInjections: ReplaceableLocation< TProps >[ 'useInjections' ]\n) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\tconst { component: Component } = injections.find( ( { condition } ) => condition?.( props ) ) ?? {};\n\n\t\tif ( ! Component ) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\treturn <Component { ...props } />;\n\t};\n}\n\nfunction createRegister< TProps extends object = AnyProps >(\n\tinjections: ReplaceableInjectionsMap< TProps >,\n\tnotify: () => void\n) {\n\treturn ( { component, id, condition = () => true, options = {} }: ReplaceableInjectArgs< TProps > ) => {\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tcondition,\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n"],"mappings":"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","names":["React","React","import_react","import_react","Component","Component","React","Component"]} |
+41
-11
@@ -6,3 +6,3 @@ // src/create-location.tsx | ||
| import * as React2 from "react"; | ||
| import { useMemo } from "react"; | ||
| import { useSyncExternalStore } from "react"; | ||
@@ -41,7 +41,27 @@ // src/components/injected-component-wrapper.tsx | ||
| } | ||
| function createSubscription() { | ||
| const listeners = /* @__PURE__ */ new Set(); | ||
| return { | ||
| subscribe: (listener) => { | ||
| listeners.add(listener); | ||
| return () => listeners.delete(listener); | ||
| }, | ||
| notify: () => listeners.forEach((listener) => listener()) | ||
| }; | ||
| } | ||
| function createGetInjections(injections) { | ||
| return () => [...injections.values()].sort((a, b) => a.priority - b.priority); | ||
| } | ||
| function createUseInjections(getInjections) { | ||
| return () => useMemo(() => getInjections(), []); | ||
| function createUseInjections(getInjections, subscribe) { | ||
| let snapshot = null; | ||
| subscribe(() => { | ||
| snapshot = null; | ||
| }); | ||
| const getSnapshot = () => { | ||
| if (!snapshot) { | ||
| snapshot = getInjections(); | ||
| } | ||
| return snapshot; | ||
| }; | ||
| return () => useSyncExternalStore(subscribe, getSnapshot); | ||
| } | ||
@@ -55,7 +75,11 @@ function wrapInjectedComponent(Component2) { | ||
| const injections = /* @__PURE__ */ new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections(injections); | ||
| const useInjections = createUseInjections(getInjections); | ||
| const useInjections = createUseInjections(getInjections, subscribe); | ||
| const Slot = createSlot(useInjections); | ||
| const inject = createInject(injections); | ||
| flushInjectionsFns.push(() => injections.clear()); | ||
| const inject = createInject(injections, notify); | ||
| flushInjectionsFns.push(() => { | ||
| injections.clear(); | ||
| notify(); | ||
| }); | ||
| return { | ||
@@ -74,3 +98,3 @@ inject, | ||
| } | ||
| function createInject(injections) { | ||
| function createInject(injections, notify) { | ||
| return ({ component, id, options = {} }) => { | ||
@@ -88,2 +112,3 @@ if (injections.has(id) && !options?.overwrite) { | ||
| }); | ||
| notify(); | ||
| }; | ||
@@ -96,7 +121,11 @@ } | ||
| const injections = /* @__PURE__ */ new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections(injections); | ||
| const useInjections = createUseInjections(getInjections); | ||
| const useInjections = createUseInjections(getInjections, subscribe); | ||
| const Slot = createReplaceable(useInjections); | ||
| const inject = createRegister(injections); | ||
| flushInjectionsFns.push(() => injections.clear()); | ||
| const inject = createRegister(injections, notify); | ||
| flushInjectionsFns.push(() => { | ||
| injections.clear(); | ||
| notify(); | ||
| }); | ||
| return { | ||
@@ -119,3 +148,3 @@ getInjections, | ||
| } | ||
| function createRegister(injections) { | ||
| function createRegister(injections, notify) { | ||
| return ({ component, id, condition = () => true, options = {} }) => { | ||
@@ -128,2 +157,3 @@ injections.set(id, { | ||
| }); | ||
| notify(); | ||
| }; | ||
@@ -130,0 +160,0 @@ } |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/create-location.tsx","../src/injections.tsx","../src/components/injected-component-wrapper.tsx","../src/components/error-boundary.tsx","../src/create-replaceable-location.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport { type AnyProps, type Id, type InjectArgs, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport function createLocation< TProps extends object = AnyProps >(): Location< TProps > {\n\tconst injections: InjectionsMap< TProps > = new Map();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections );\n\tconst Slot = createSlot( useInjections );\n\tconst inject = createInject( injections );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\tflushInjectionsFns.push( () => injections.clear() );\n\n\treturn {\n\t\tinject,\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tSlot,\n\t};\n}\n\nfunction createSlot< TProps extends object = AnyProps >( useInjections: Location< TProps >[ 'useInjections' ] ) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ injections.map( ( { id, component: Component } ) => (\n\t\t\t\t\t<Component { ...props } key={ id } />\n\t\t\t\t) ) }\n\t\t\t</>\n\t\t);\n\t};\n}\n\nfunction createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn ( { component, id, options = {} }: InjectArgs< TProps > ) => {\n\t\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`An injection with the id \"${ id }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\t};\n}\n","import * as React from 'react';\nimport { useMemo } from 'react';\n\nimport InjectedComponentWrapper from './components/injected-component-wrapper';\nimport { type AnyProps, type Id, type InjectedComponent, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport const DEFAULT_PRIORITY = 10;\n\n// Allow flushing all injections at once, for testing purposes.\nexport const flushInjectionsFns: ( () => void )[] = [];\n\nexport function flushAllInjections() {\n\tflushInjectionsFns.forEach( ( flush ) => flush() );\n}\n\nexport function createGetInjections< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn () => [ ...injections.values() ].sort( ( a, b ) => a.priority - b.priority );\n}\n\nexport function createUseInjections< TProps extends object = AnyProps >(\n\tgetInjections: Location< TProps >[ 'getInjections' ]\n) {\n\treturn () => useMemo( () => getInjections(), [] );\n}\n\nexport function wrapInjectedComponent< TProps extends object = AnyProps >( Component: InjectedComponent< TProps > ) {\n\treturn ( props: TProps ) => (\n\t\t<InjectedComponentWrapper>\n\t\t\t<Component { ...props } />\n\t\t</InjectedComponentWrapper>\n\t);\n}\n","import * as React from 'react';\nimport { type ReactNode, Suspense } from 'react';\n\nimport ErrorBoundary from './error-boundary';\n\nexport default function InjectedComponentWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>{ children }</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, type ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component< Props, State > {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import * as React from 'react';\nimport { type PropsWithChildren } from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport {\n\ttype AnyProps,\n\ttype Id,\n\ttype ReplaceableInjectArgs,\n\ttype ReplaceableInjection,\n\ttype ReplaceableLocation,\n} from './types';\n\ntype ReplaceableInjectionsMap< TProps extends object = AnyProps > = Map< Id, ReplaceableInjection< TProps > >;\n\nexport function createReplaceableLocation< TProps extends object = AnyProps >(): ReplaceableLocation< TProps > {\n\tconst injections: ReplaceableInjectionsMap< TProps > = new Map();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections );\n\tconst Slot = createReplaceable( useInjections );\n\tconst inject = createRegister( injections );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\tflushInjectionsFns.push( () => injections.clear() );\n\n\treturn {\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tinject,\n\t\tSlot,\n\t};\n}\n\nfunction createReplaceable< TProps extends PropsWithChildren< object > = AnyProps >(\n\tuseInjections: ReplaceableLocation< TProps >[ 'useInjections' ]\n) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\tconst { component: Component } = injections.find( ( { condition } ) => condition?.( props ) ) ?? {};\n\n\t\tif ( ! Component ) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\treturn <Component { ...props } />;\n\t};\n}\n\nfunction createRegister< TProps extends object = AnyProps >( injections: ReplaceableInjectionsMap< TProps > ) {\n\treturn ( { component, id, condition = () => true, options = {} }: ReplaceableInjectArgs< TProps > ) => {\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tcondition,\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\t};\n}\n"],"mappings":"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","names":["React","React","Component","Component","React","Component"]} | ||
| {"version":3,"sources":["../src/create-location.tsx","../src/injections.tsx","../src/components/injected-component-wrapper.tsx","../src/components/error-boundary.tsx","../src/create-replaceable-location.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateSubscription,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport { type AnyProps, type Id, type InjectArgs, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport function createLocation< TProps extends object = AnyProps >(): Location< TProps > {\n\tconst injections: InjectionsMap< TProps > = new Map();\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections, subscribe );\n\tconst Slot = createSlot( useInjections );\n\tconst inject = createInject( injections, notify );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\t// `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush,\n\t// which matters for test isolation between test cases.\n\tflushInjectionsFns.push( () => {\n\t\tinjections.clear();\n\t\tnotify();\n\t} );\n\n\treturn {\n\t\tinject,\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tSlot,\n\t};\n}\n\nfunction createSlot< TProps extends object = AnyProps >( useInjections: Location< TProps >[ 'useInjections' ] ) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ injections.map( ( { id, component: Component } ) => (\n\t\t\t\t\t<Component { ...props } key={ id } />\n\t\t\t\t) ) }\n\t\t\t</>\n\t\t);\n\t};\n}\n\nfunction createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps >, notify: () => void ) {\n\treturn ( { component, id, options = {} }: InjectArgs< TProps > ) => {\n\t\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`An injection with the id \"${ id }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t\t);\n\n\t\t\treturn;\n\t\t}\n\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n","import * as React from 'react';\nimport { useSyncExternalStore } from 'react';\n\nimport InjectedComponentWrapper from './components/injected-component-wrapper';\nimport { type AnyProps, type Id, type InjectedComponent, type Injection, type Location } from './types';\n\ntype InjectionsMap< TProps extends object = AnyProps > = Map< Id, Injection< TProps > >;\n\nexport const DEFAULT_PRIORITY = 10;\n\n// Allow flushing all injections at once, for testing purposes.\nexport const flushInjectionsFns: ( () => void )[] = [];\n\nexport function flushAllInjections() {\n\tflushInjectionsFns.forEach( ( flush ) => flush() );\n}\n\nexport type Subscribe = ( listener: () => void ) => () => void;\n\nexport function createSubscription() {\n\tconst listeners = new Set< () => void >();\n\n\treturn {\n\t\tsubscribe: ( listener: () => void ) => {\n\t\t\tlisteners.add( listener );\n\n\t\t\treturn () => listeners.delete( listener );\n\t\t},\n\t\tnotify: () => listeners.forEach( ( listener ) => listener() ),\n\t};\n}\n\nexport function createGetInjections< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) {\n\treturn () => [ ...injections.values() ].sort( ( a, b ) => a.priority - b.priority );\n}\n\n// Injections registered after the `Slot` has already mounted (e.g. by an external plugin's\n// script that loads after the editor has rendered) must still be reflected in the UI, so the\n// snapshot is invalidated and re-read whenever `notify()` is called.\nexport function createUseInjections< TProps extends object = AnyProps >(\n\tgetInjections: Location< TProps >[ 'getInjections' ],\n\tsubscribe: Subscribe\n) {\n\tlet snapshot: ReturnType< Location< TProps >[ 'getInjections' ] > | null = null;\n\n\tsubscribe( () => {\n\t\tsnapshot = null;\n\t} );\n\n\tconst getSnapshot = () => {\n\t\tif ( ! snapshot ) {\n\t\t\tsnapshot = getInjections();\n\t\t}\n\n\t\treturn snapshot;\n\t};\n\n\treturn () => useSyncExternalStore( subscribe, getSnapshot );\n}\n\nexport function wrapInjectedComponent< TProps extends object = AnyProps >( Component: InjectedComponent< TProps > ) {\n\treturn ( props: TProps ) => (\n\t\t<InjectedComponentWrapper>\n\t\t\t<Component { ...props } />\n\t\t</InjectedComponentWrapper>\n\t);\n}\n","import * as React from 'react';\nimport { type ReactNode, Suspense } from 'react';\n\nimport ErrorBoundary from './error-boundary';\n\nexport default function InjectedComponentWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>{ children }</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, type ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component< Props, State > {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import * as React from 'react';\nimport { type PropsWithChildren } from 'react';\n\nimport {\n\tcreateGetInjections,\n\tcreateSubscription,\n\tcreateUseInjections,\n\tDEFAULT_PRIORITY,\n\tflushInjectionsFns,\n\twrapInjectedComponent,\n} from './injections';\nimport {\n\ttype AnyProps,\n\ttype Id,\n\ttype ReplaceableInjectArgs,\n\ttype ReplaceableInjection,\n\ttype ReplaceableLocation,\n} from './types';\n\ntype ReplaceableInjectionsMap< TProps extends object = AnyProps > = Map< Id, ReplaceableInjection< TProps > >;\n\nexport function createReplaceableLocation< TProps extends object = AnyProps >(): ReplaceableLocation< TProps > {\n\tconst injections: ReplaceableInjectionsMap< TProps > = new Map();\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst getInjections = createGetInjections( injections );\n\tconst useInjections = createUseInjections( getInjections, subscribe );\n\tconst Slot = createReplaceable( useInjections );\n\tconst inject = createRegister( injections, notify );\n\n\t// Push the clear function to the flushInjectionsFns array, so we can flush all injections at once.\n\t// `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush,\n\t// which matters for test isolation between test cases.\n\tflushInjectionsFns.push( () => {\n\t\tinjections.clear();\n\t\tnotify();\n\t} );\n\n\treturn {\n\t\tgetInjections,\n\t\tuseInjections,\n\t\tinject,\n\t\tSlot,\n\t};\n}\n\nfunction createReplaceable< TProps extends PropsWithChildren< object > = AnyProps >(\n\tuseInjections: ReplaceableLocation< TProps >[ 'useInjections' ]\n) {\n\treturn ( props: TProps ) => {\n\t\tconst injections = useInjections();\n\n\t\tconst { component: Component } = injections.find( ( { condition } ) => condition?.( props ) ) ?? {};\n\n\t\tif ( ! Component ) {\n\t\t\treturn props.children;\n\t\t}\n\n\t\treturn <Component { ...props } />;\n\t};\n}\n\nfunction createRegister< TProps extends object = AnyProps >(\n\tinjections: ReplaceableInjectionsMap< TProps >,\n\tnotify: () => void\n) {\n\treturn ( { component, id, condition = () => true, options = {} }: ReplaceableInjectArgs< TProps > ) => {\n\t\tinjections.set( id, {\n\t\t\tid,\n\t\t\tcomponent: wrapInjectedComponent( component ),\n\t\t\tcondition,\n\t\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n"],"mappings":";AAAA,YAAYA,YAAW;;;ACAvB,YAAYC,YAAW;AACvB,SAAS,4BAA4B;;;ACDrC,YAAY,WAAW;AACvB,SAAyB,gBAAgB;;;ACDzC,SAAS,iBAAiC;AAW1C,IAAqB,gBAArB,cAA2C,UAA0B;AAAA,EAC7D,QAAe;AAAA,IACrB,UAAU;AAAA,EACX;AAAA,EAEA,OAAc,2BAAkC;AAE/C,WAAO,EAAE,UAAU,KAAK;AAAA,EACzB;AAAA,EAEO,SAAS;AACf,QAAK,KAAK,MAAM,UAAW;AAC1B,aAAO,KAAK,MAAM;AAAA,IACnB;AAEA,WAAO,KAAK,MAAM;AAAA,EACnB;AACD;;;ADvBe,SAAR,yBAA2C,EAAE,SAAS,GAA6B;AACzF,SACC,oCAAC,iBAAc,UAAW,QACzB,oCAAC,YAAS,UAAW,QAAS,QAAU,CACzC;AAEF;;;ADHO,IAAM,mBAAmB;AAGzB,IAAM,qBAAuC,CAAC;AAE9C,SAAS,qBAAqB;AACpC,qBAAmB,QAAS,CAAE,UAAW,MAAM,CAAE;AAClD;AAIO,SAAS,qBAAqB;AACpC,QAAM,YAAY,oBAAI,IAAkB;AAExC,SAAO;AAAA,IACN,WAAW,CAAE,aAA0B;AACtC,gBAAU,IAAK,QAAS;AAExB,aAAO,MAAM,UAAU,OAAQ,QAAS;AAAA,IACzC;AAAA,IACA,QAAQ,MAAM,UAAU,QAAS,CAAE,aAAc,SAAS,CAAE;AAAA,EAC7D;AACD;AAEO,SAAS,oBAAyD,YAAsC;AAC9G,SAAO,MAAM,CAAE,GAAG,WAAW,OAAO,CAAE,EAAE,KAAM,CAAE,GAAG,MAAO,EAAE,WAAW,EAAE,QAAS;AACnF;AAKO,SAAS,oBACf,eACA,WACC;AACD,MAAI,WAAuE;AAE3E,YAAW,MAAM;AAChB,eAAW;AAAA,EACZ,CAAE;AAEF,QAAM,cAAc,MAAM;AACzB,QAAK,CAAE,UAAW;AACjB,iBAAW,cAAc;AAAA,IAC1B;AAEA,WAAO;AAAA,EACR;AAEA,SAAO,MAAM,qBAAsB,WAAW,WAAY;AAC3D;AAEO,SAAS,sBAA2DC,YAAyC;AACnH,SAAO,CAAE,UACR,qCAAC,gCACA,qCAACA,YAAA,EAAY,GAAG,OAAQ,CACzB;AAEF;;;ADpDO,SAAS,iBAAyE;AACxF,QAAM,aAAsC,oBAAI,IAAI;AACpD,QAAM,EAAE,WAAW,OAAO,IAAI,mBAAmB;AAEjD,QAAM,gBAAgB,oBAAqB,UAAW;AACtD,QAAM,gBAAgB,oBAAqB,eAAe,SAAU;AACpE,QAAM,OAAO,WAAY,aAAc;AACvC,QAAM,SAAS,aAAc,YAAY,MAAO;AAKhD,qBAAmB,KAAM,MAAM;AAC9B,eAAW,MAAM;AACjB,WAAO;AAAA,EACR,CAAE;AAEF,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEA,SAAS,WAAgD,eAAuD;AAC/G,SAAO,CAAE,UAAmB;AAC3B,UAAM,aAAa,cAAc;AAEjC,WACC,4DACG,WAAW,IAAK,CAAE,EAAE,IAAI,WAAWC,WAAU,MAC9C,qCAACA,YAAA,EAAY,GAAG,OAAQ,KAAM,IAAK,CAClC,CACH;AAAA,EAEF;AACD;AAEA,SAAS,aAAkD,YAAqC,QAAqB;AACpH,SAAO,CAAE,EAAE,WAAW,IAAI,UAAU,CAAC,EAAE,MAA6B;AACnE,QAAK,WAAW,IAAK,EAAG,KAAK,CAAE,SAAS,WAAY;AAEnD,cAAQ;AAAA,QACP,6BAA8B,EAAG;AAAA,MAClC;AAEA;AAAA,IACD;AAEA,eAAW,IAAK,IAAI;AAAA,MACnB;AAAA,MACA,WAAW,sBAAuB,SAAU;AAAA,MAC5C,UAAU,QAAQ,YAAY;AAAA,IAC/B,CAAE;AAEF,WAAO;AAAA,EACR;AACD;;;AIxEA,YAAYC,YAAW;AAqBhB,SAAS,4BAA+F;AAC9G,QAAM,aAAiD,oBAAI,IAAI;AAC/D,QAAM,EAAE,WAAW,OAAO,IAAI,mBAAmB;AAEjD,QAAM,gBAAgB,oBAAqB,UAAW;AACtD,QAAM,gBAAgB,oBAAqB,eAAe,SAAU;AACpE,QAAM,OAAO,kBAAmB,aAAc;AAC9C,QAAM,SAAS,eAAgB,YAAY,MAAO;AAKlD,qBAAmB,KAAM,MAAM;AAC9B,eAAW,MAAM;AACjB,WAAO;AAAA,EACR,CAAE;AAEF,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEA,SAAS,kBACR,eACC;AACD,SAAO,CAAE,UAAmB;AAC3B,UAAM,aAAa,cAAc;AAEjC,UAAM,EAAE,WAAWC,WAAU,IAAI,WAAW,KAAM,CAAE,EAAE,UAAU,MAAO,YAAa,KAAM,CAAE,KAAK,CAAC;AAElG,QAAK,CAAEA,YAAY;AAClB,aAAO,MAAM;AAAA,IACd;AAEA,WAAO,qCAACA,YAAA,EAAY,GAAG,OAAQ;AAAA,EAChC;AACD;AAEA,SAAS,eACR,YACA,QACC;AACD,SAAO,CAAE,EAAE,WAAW,IAAI,YAAY,MAAM,MAAM,UAAU,CAAC,EAAE,MAAwC;AACtG,eAAW,IAAK,IAAI;AAAA,MACnB;AAAA,MACA,WAAW,sBAAuB,SAAU;AAAA,MAC5C;AAAA,MACA,UAAU,QAAQ,YAAY;AAAA,IAC/B,CAAE;AAEF,WAAO;AAAA,EACR;AACD;","names":["React","React","Component","Component","React","Component"]} |
+1
-1
| { | ||
| "name": "@elementor/locations", | ||
| "description": "Create & manage pluggable React applications", | ||
| "version": "4.3.0-986", | ||
| "version": "4.3.0-987", | ||
| "private": false, | ||
@@ -6,0 +6,0 @@ "author": "Elementor Team", |
@@ -5,2 +5,3 @@ import * as React from 'react'; | ||
| createGetInjections, | ||
| createSubscription, | ||
| createUseInjections, | ||
@@ -17,10 +18,16 @@ DEFAULT_PRIORITY, | ||
| const injections: InjectionsMap< TProps > = new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections( injections ); | ||
| const useInjections = createUseInjections( getInjections ); | ||
| const useInjections = createUseInjections( getInjections, subscribe ); | ||
| const Slot = createSlot( useInjections ); | ||
| const inject = createInject( injections ); | ||
| const inject = createInject( injections, notify ); | ||
| // Push the clear function to the flushInjectionsFns array, so we can flush all injections at once. | ||
| flushInjectionsFns.push( () => injections.clear() ); | ||
| // `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush, | ||
| // which matters for test isolation between test cases. | ||
| flushInjectionsFns.push( () => { | ||
| injections.clear(); | ||
| notify(); | ||
| } ); | ||
@@ -49,3 +56,3 @@ return { | ||
| function createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) { | ||
| function createInject< TProps extends object = AnyProps >( injections: InjectionsMap< TProps >, notify: () => void ) { | ||
| return ( { component, id, options = {} }: InjectArgs< TProps > ) => { | ||
@@ -66,3 +73,5 @@ if ( injections.has( id ) && ! options?.overwrite ) { | ||
| } ); | ||
| notify(); | ||
| }; | ||
| } |
@@ -6,2 +6,3 @@ import * as React from 'react'; | ||
| createGetInjections, | ||
| createSubscription, | ||
| createUseInjections, | ||
@@ -24,10 +25,16 @@ DEFAULT_PRIORITY, | ||
| const injections: ReplaceableInjectionsMap< TProps > = new Map(); | ||
| const { subscribe, notify } = createSubscription(); | ||
| const getInjections = createGetInjections( injections ); | ||
| const useInjections = createUseInjections( getInjections ); | ||
| const useInjections = createUseInjections( getInjections, subscribe ); | ||
| const Slot = createReplaceable( useInjections ); | ||
| const inject = createRegister( injections ); | ||
| const inject = createRegister( injections, notify ); | ||
| // Push the clear function to the flushInjectionsFns array, so we can flush all injections at once. | ||
| flushInjectionsFns.push( () => injections.clear() ); | ||
| // `notify()` is called too, so any mounted `Slot` (and its cached snapshot) reflects the flush, | ||
| // which matters for test isolation between test cases. | ||
| flushInjectionsFns.push( () => { | ||
| injections.clear(); | ||
| notify(); | ||
| } ); | ||
@@ -58,3 +65,6 @@ return { | ||
| function createRegister< TProps extends object = AnyProps >( injections: ReplaceableInjectionsMap< TProps > ) { | ||
| function createRegister< TProps extends object = AnyProps >( | ||
| injections: ReplaceableInjectionsMap< TProps >, | ||
| notify: () => void | ||
| ) { | ||
| return ( { component, id, condition = () => true, options = {} }: ReplaceableInjectArgs< TProps > ) => { | ||
@@ -67,3 +77,5 @@ injections.set( id, { | ||
| } ); | ||
| notify(); | ||
| }; | ||
| } |
+36
-3
| import * as React from 'react'; | ||
| import { useMemo } from 'react'; | ||
| import { useSyncExternalStore } from 'react'; | ||
@@ -18,2 +18,17 @@ import InjectedComponentWrapper from './components/injected-component-wrapper'; | ||
| export type Subscribe = ( listener: () => void ) => () => void; | ||
| export function createSubscription() { | ||
| const listeners = new Set< () => void >(); | ||
| return { | ||
| subscribe: ( listener: () => void ) => { | ||
| listeners.add( listener ); | ||
| return () => listeners.delete( listener ); | ||
| }, | ||
| notify: () => listeners.forEach( ( listener ) => listener() ), | ||
| }; | ||
| } | ||
| export function createGetInjections< TProps extends object = AnyProps >( injections: InjectionsMap< TProps > ) { | ||
@@ -23,6 +38,24 @@ return () => [ ...injections.values() ].sort( ( a, b ) => a.priority - b.priority ); | ||
| // Injections registered after the `Slot` has already mounted (e.g. by an external plugin's | ||
| // script that loads after the editor has rendered) must still be reflected in the UI, so the | ||
| // snapshot is invalidated and re-read whenever `notify()` is called. | ||
| export function createUseInjections< TProps extends object = AnyProps >( | ||
| getInjections: Location< TProps >[ 'getInjections' ] | ||
| getInjections: Location< TProps >[ 'getInjections' ], | ||
| subscribe: Subscribe | ||
| ) { | ||
| return () => useMemo( () => getInjections(), [] ); | ||
| let snapshot: ReturnType< Location< TProps >[ 'getInjections' ] > | null = null; | ||
| subscribe( () => { | ||
| snapshot = null; | ||
| } ); | ||
| const getSnapshot = () => { | ||
| if ( ! snapshot ) { | ||
| snapshot = getInjections(); | ||
| } | ||
| return snapshot; | ||
| }; | ||
| return () => useSyncExternalStore( subscribe, getSnapshot ); | ||
| } | ||
@@ -29,0 +62,0 @@ |
55750
14.92%726
16.72%