UNPKG

@wordpress/interactivity

Version:

Package that provides a standard and simple way to handle the frontend interactivity of Gutenberg blocks.

8 lines (7 loc) 20.9 kB
{ "version": 3, "sources": ["../src/utils.ts"], "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tuseMemo as _useMemo,\n\tuseCallback as _useCallback,\n\tuseEffect as _useEffect,\n\tuseLayoutEffect as _useLayoutEffect,\n\ttype EffectCallback,\n\ttype Inputs,\n} from 'preact/hooks';\nimport { effect, signal } from '@preact/signals';\n\n/**\n * Internal dependencies\n */\nimport { getScope, setScope, resetScope } from './scopes';\nimport { getNamespace, setNamespace, resetNamespace } from './namespaces';\n\ninterface Flusher {\n\treadonly flush: () => void;\n\treadonly dispose: () => void;\n}\n\ndeclare global {\n\tinterface Window {\n\t\tscheduler?: {\n\t\t\treadonly yield?: () => Promise< void >;\n\t\t};\n\t}\n}\n\nexport interface SyncAwareFunction extends Function {\n\tsync?: boolean;\n}\n\n/**\n * Executes a callback function after the next frame is rendered.\n *\n * @param callback The callback function to be executed.\n * @return A promise that resolves after the callback function is executed.\n */\nconst afterNextFrame = ( callback: () => void ) => {\n\treturn new Promise< void >( ( resolve ) => {\n\t\tconst done = () => {\n\t\t\tclearTimeout( timeout );\n\t\t\twindow.cancelAnimationFrame( raf );\n\t\t\tsetTimeout( () => {\n\t\t\t\tcallback();\n\t\t\t\tresolve();\n\t\t\t} );\n\t\t};\n\t\tconst timeout = setTimeout( done, 100 );\n\t\tconst raf = window.requestAnimationFrame( done );\n\t} );\n};\n\n/**\n * Returns a promise that resolves after yielding to main.\n *\n * @return Promise<void>\n */\nexport const splitTask =\n\ttypeof window.scheduler?.yield === 'function'\n\t\t? window.scheduler.yield.bind( window.scheduler )\n\t\t: () => {\n\t\t\t\treturn new Promise( ( resolve ) => {\n\t\t\t\t\tsetTimeout( resolve, 0 );\n\t\t\t\t} );\n\t\t };\n/**\n * Executes the passed callback on `DOMContentLoaded`, or immediately if that\n * event has already been triggered.\n *\n * This function depends on `PerformanceNavigationTiming` (see\n * https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) to\n * detect whether the event has been dispatched.\n *\n * @param callback Function to execute on `DOMContentLoaded`.\n */\nexport const onDOMReady = ( callback: () => void ) => {\n\tconst [ navigation ] = performance.getEntriesByType( 'navigation' );\n\tif (\n\t\t( navigation as PerformanceNavigationTiming )\n\t\t\t.domContentLoadedEventStart > 0\n\t) {\n\t\tcallback();\n\t} else {\n\t\tdocument.addEventListener( 'DOMContentLoaded', callback );\n\t}\n};\n\n/**\n * Creates a Flusher object that can be used to flush computed values and notify listeners.\n *\n * Using the mangled properties:\n * this.c: this._callback\n * this.x: this._compute\n * https://github.com/preactjs/signals/blob/main/mangle.json\n *\n * @param compute The function that computes the value to be flushed.\n * @param notify The function that notifies listeners when the value is flushed.\n * @return The Flusher object with `flush` and `dispose` properties.\n */\nfunction createFlusher( compute: () => void, notify: () => void ): Flusher {\n\tlet flush: () => void = () => undefined;\n\tconst dispose = effect( function ( this: any ): void {\n\t\tflush = this.c.bind( this );\n\t\tthis.x = compute;\n\t\tthis.c = notify;\n\t\treturn compute();\n\t} );\n\treturn { flush, dispose } as const;\n}\n\n/**\n * Custom hook that executes a callback function whenever a signal is triggered.\n * Version of `useSignalEffect` with a `useEffect`-like execution. This hook\n * implementation comes from this PR, but we added short-cirtuiting to avoid\n * infinite loops: https://github.com/preactjs/signals/pull/290\n *\n * @param callback The callback function to be executed.\n */\nexport function useSignalEffect( callback: () => unknown ) {\n\t_useEffect( () => {\n\t\tlet eff: Flusher | null = null;\n\t\tlet isExecuting = false;\n\n\t\tconst notify = async () => {\n\t\t\tif ( eff && ! isExecuting ) {\n\t\t\t\tisExecuting = true;\n\t\t\t\tawait afterNextFrame( eff.flush );\n\t\t\t\tisExecuting = false;\n\t\t\t}\n\t\t};\n\n\t\teff = createFlusher( callback, notify );\n\t\treturn eff.dispose;\n\t}, [] );\n}\n\n/**\n * Returns the passed function wrapped with the current scope so it is\n * accessible whenever the function runs. This is primarily to make the scope\n * available inside hook callbacks.\n *\n * Asynchronous functions should use generators that yield promises instead of awaiting them.\n * See the documentation for details: https://developer.wordpress.org/block-editor/reference-guides/packages/packages-interactivity/packages-interactivity-api-reference/#the-store\n *\n * @param func The passed function.\n * @return The wrapped function.\n */\nexport function withScope<\n\tFunc extends ( ...args: any[] ) => Generator< any, any >,\n>(\n\tfunc: Func\n): (\n\t...args: Parameters< Func >\n) => ReturnType< Func > extends Generator< any, infer Return >\n\t? Promise< Return >\n\t: never;\nexport function withScope< Func extends Function >( func: Func ): Func;\nexport function withScope< Func extends SyncAwareFunction >( func: Func ): Func;\nexport function withScope( func: ( ...args: unknown[] ) => unknown ) {\n\tconst scope = getScope();\n\tconst ns = getNamespace();\n\n\tlet wrapped: Function;\n\tif ( func?.constructor?.name === 'GeneratorFunction' ) {\n\t\twrapped = async ( ...args: Parameters< typeof func > ) => {\n\t\t\tconst gen = func( ...args ) as Generator;\n\t\t\tlet value: any;\n\t\t\tlet it: any;\n\t\t\tlet error: any;\n\t\t\twhile ( true ) {\n\t\t\t\tsetNamespace( ns );\n\t\t\t\tsetScope( scope );\n\t\t\t\ttry {\n\t\t\t\t\tit = error ? gen.throw( error ) : gen.next( value );\n\t\t\t\t\terror = undefined;\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\tthrow e;\n\t\t\t\t} finally {\n\t\t\t\t\tresetScope();\n\t\t\t\t\tresetNamespace();\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tvalue = await it.value;\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\terror = e;\n\t\t\t\t}\n\t\t\t\tif ( it.done ) {\n\t\t\t\t\tif ( error ) {\n\t\t\t\t\t\tthrow error;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn value;\n\t\t};\n\t} else {\n\t\twrapped = ( ...args: Parameters< typeof func > ) => {\n\t\t\tsetNamespace( ns );\n\t\t\tsetScope( scope );\n\t\t\ttry {\n\t\t\t\treturn func( ...args );\n\t\t\t} finally {\n\t\t\t\tresetNamespace();\n\t\t\t\tresetScope();\n\t\t\t}\n\t\t};\n\t}\n\n\t// If function was annotated via `withSyncEvent()`, maintain the annotation.\n\tconst syncAware = func as SyncAwareFunction;\n\tif ( syncAware.sync ) {\n\t\tconst syncAwareWrapped = wrapped as SyncAwareFunction;\n\t\tsyncAwareWrapped.sync = true;\n\t\treturn syncAwareWrapped;\n\t}\n\n\treturn wrapped;\n}\n\n/**\n * Accepts a function that contains imperative code which runs whenever any of\n * the accessed _reactive_ properties (e.g., values from the global state or the\n * context) is modified.\n *\n * This hook makes the element's scope available so functions like\n * `getElement()` and `getContext()` can be used inside the passed callback.\n *\n * @param callback The hook callback.\n */\nexport function useWatch( callback: () => unknown ) {\n\tuseSignalEffect( withScope( callback ) );\n}\n\n/**\n * Accepts a function that contains imperative code which runs only after the\n * element's first render, mainly useful for initialization logic.\n *\n * This hook makes the element's scope available so functions like\n * `getElement()` and `getContext()` can be used inside the passed callback.\n *\n * @param callback The hook callback.\n */\nexport function useInit( callback: EffectCallback ) {\n\t_useEffect( withScope( callback ), [] );\n}\n\n/**\n * Accepts a function that contains imperative, possibly effectful code. The\n * effects run after browser paint, without blocking it.\n *\n * This hook is equivalent to Preact's `useEffect` and makes the element's scope\n * available so functions like `getElement()` and `getContext()` can be used\n * inside the passed callback.\n *\n * @param callback Imperative function that can return a cleanup\n * function.\n * @param inputs If present, effect will only activate if the\n * values in the list change (using `===`).\n */\nexport function useEffect( callback: EffectCallback, inputs: Inputs ) {\n\t_useEffect( withScope( callback ), inputs );\n}\n\n/**\n * Accepts a function that contains imperative, possibly effectful code. Use\n * this to read layout from the DOM and synchronously re-render.\n *\n * This hook is equivalent to Preact's `useLayoutEffect` and makes the element's\n * scope available so functions like `getElement()` and `getContext()` can be\n * used inside the passed callback.\n *\n * @param callback Imperative function that can return a cleanup\n * function.\n * @param inputs If present, effect will only activate if the\n * values in the list change (using `===`).\n */\nexport function useLayoutEffect( callback: EffectCallback, inputs: Inputs ) {\n\t_useLayoutEffect( withScope( callback ), inputs );\n}\n\n/**\n * Returns a memoized version of the callback that only changes if one of the\n * inputs has changed (using `===`).\n *\n * This hook is equivalent to Preact's `useCallback` and makes the element's\n * scope available so functions like `getElement()` and `getContext()` can be\n * used inside the passed callback.\n *\n * @param callback Callback function.\n * @param inputs If present, the callback will only be updated if the\n * values in the list change (using `===`).\n *\n * @return The callback function.\n */\nexport function useCallback< T extends Function >(\n\tcallback: T,\n\tinputs: Inputs\n): T {\n\treturn _useCallback< T >( withScope( callback ), inputs );\n}\n\n/**\n * Returns the memoized output of the passed factory function, allowing access\n * to the current element's scope.\n *\n * This hook is equivalent to Preact's `useMemo` and makes the element's scope\n * available so functions like `getElement()` and `getContext()` can be used\n * inside the passed factory function. Note that `useMemo` will only recompute\n * the memoized value when one of the inputs has changed.\n *\n * @param factory Factory function that returns that value for memoization.\n * @param inputs If present, the factory will only be run to recompute if the\n * values in the list change (using `===`).\n *\n * @return The memoized value.\n */\nexport function useMemo< T >( factory: () => T, inputs: Inputs ): T {\n\treturn _useMemo( withScope( factory ), inputs );\n}\n\n/**\n * Creates a root fragment by replacing a node or an array of nodes in a parent element.\n * For wrapperless hydration.\n * See https://gist.github.com/developit/f4c67a2ede71dc2fab7f357f39cff28c\n *\n * @param parent The parent element where the nodes will be replaced.\n * @param replaceNode The node or array of nodes to replace in the parent element.\n * @return The created root fragment.\n */\nexport const createRootFragment = (\n\tparent: Element,\n\treplaceNode: Node | Node[]\n) => {\n\treplaceNode = ( [] as Node[] ).concat( replaceNode );\n\tconst sibling = replaceNode[ replaceNode.length - 1 ].nextSibling;\n\tfunction insert( child: any, root: any ) {\n\t\tparent.insertBefore( child, root || sibling );\n\t}\n\treturn ( ( parent as any ).__k = {\n\t\tnodeType: 1,\n\t\tparentNode: parent,\n\t\tfirstChild: replaceNode[ 0 ],\n\t\tchildNodes: replaceNode,\n\t\tinsertBefore: insert,\n\t\tappendChild: insert,\n\t\tremoveChild( c: Node ) {\n\t\t\tparent.removeChild( c );\n\t\t},\n\t\tcontains( c: Node ) {\n\t\t\tparent.contains( c );\n\t\t},\n\t} );\n};\n\n/**\n * Transforms a kebab-case string to camelCase.\n *\n * @param str The kebab-case string to transform to camelCase.\n * @return The transformed camelCase string.\n */\nexport function kebabToCamelCase( str: string ): string {\n\treturn str\n\t\t.replace( /^-+|-+$/g, '' )\n\t\t.toLowerCase()\n\t\t.replace( /-([a-z])/g, function ( _match, group1: string ) {\n\t\t\treturn group1.toUpperCase();\n\t\t} );\n}\n\nconst logged: Set< string > = new Set();\n\n/**\n * Shows a warning with `message` if environment is not `production`.\n *\n * Based on the `@wordpress/warning` package.\n *\n * @param message Message to show in the warning.\n */\nexport const warn = ( message: string ): void => {\n\tif ( globalThis.SCRIPT_DEBUG ) {\n\t\tif ( logged.has( message ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn( message );\n\n\t\t// Throwing an error and catching it immediately to improve debugging\n\t\t// A consumer can use 'pause on caught exceptions'\n\t\ttry {\n\t\t\tthrow Error( message );\n\t\t} catch ( e ) {\n\t\t\t// Do nothing.\n\t\t}\n\t\tlogged.add( message );\n\t}\n};\n\n/**\n * Checks if the passed `candidate` is a plain object with just the `Object`\n * prototype.\n *\n * @param candidate The item to check.\n * @return Whether `candidate` is a plain object.\n */\nexport const isPlainObject = (\n\tcandidate: unknown\n): candidate is Record< string, unknown > =>\n\tBoolean(\n\t\tcandidate &&\n\t\t\ttypeof candidate === 'object' &&\n\t\t\tcandidate.constructor === Object\n\t);\n\n/**\n * Indicates that the passed `callback` requires synchronous access to the event object.\n *\n * @param callback The event callback.\n * @return Altered event callback.\n */\nexport function withSyncEvent( callback: Function ): SyncAwareFunction {\n\tconst syncAware = callback as SyncAwareFunction;\n\tsyncAware.sync = true;\n\treturn syncAware;\n}\n\nexport type DeepReadonly< T > = T extends ( ...args: any[] ) => any\n\t? T\n\t: T extends object\n\t? { readonly [ K in keyof T ]: DeepReadonly< T[ K ] > }\n\t: T;\n\n// WeakMap cache to reuse proxies for the same read-only objects.\nconst readOnlyMap = new WeakMap< object, object >();\n\n/**\n * Creates a proxy handler that prevents any modifications to the target object.\n *\n * @param errorMessage Custom error message to display when modification is attempted.\n * @return Proxy handler for read-only behavior.\n */\nconst createDeepReadOnlyHandlers = (\n\terrorMessage: string\n): ProxyHandler< object > => {\n\tconst handleError = () => {\n\t\tif ( globalThis.SCRIPT_DEBUG ) {\n\t\t\twarn( errorMessage );\n\t\t}\n\t\treturn false;\n\t};\n\n\treturn {\n\t\tget( target, prop ) {\n\t\t\tconst value = target[ prop ];\n\t\t\tif ( value && typeof value === 'object' ) {\n\t\t\t\treturn deepReadOnly( value, { errorMessage } );\n\t\t\t}\n\t\t\treturn value;\n\t\t},\n\t\tset: handleError,\n\t\tdeleteProperty: handleError,\n\t\tdefineProperty: handleError,\n\t};\n};\n\n/**\n * Creates a deeply read-only proxy of an object.\n *\n * This function recursively wraps an object and all its nested objects in\n * proxies that prevent any modifications. All mutation operations (`set`,\n * `deleteProperty`, and `defineProperty`) will silently fail in production and\n * emit warnings in development (when `globalThis.SCRIPT_DEBUG` is true).\n *\n * The wrapping is lazy: nested objects are only wrapped when accessed, making\n * this efficient for large or deeply nested structures.\n *\n * Proxies are cached using a WeakMap, so calling this function multiple times\n * with the same object will return the same proxy instance.\n *\n * @param obj The object to make read-only.\n * @param options Optional configuration.\n * @param options.errorMessage Custom error message to display when modification is attempted.\n * @return A read-only proxy of the object.\n */\nexport function deepReadOnly< T extends object >(\n\tobj: T,\n\toptions?: { errorMessage?: string }\n): T {\n\tconst errorMessage =\n\t\toptions?.errorMessage ?? 'Cannot modify read-only object';\n\n\tif ( ! readOnlyMap.has( obj ) ) {\n\t\tconst handlers = createDeepReadOnlyHandlers( errorMessage );\n\t\treadOnlyMap.set( obj, new Proxy( obj, handlers ) );\n\t}\n\n\treturn readOnlyMap.get( obj ) as T;\n}\n\nexport const navigationSignal = signal( 0 );\n\n/**\n * Recursively clones the passed object.\n *\n * @param source Source object.\n * @return Cloned object.\n */\nexport function deepClone< T >( source: T ): T {\n\tif ( isPlainObject( source ) ) {\n\t\treturn Object.fromEntries(\n\t\t\tObject.entries( source as object ).map( ( [ key, value ] ) => [\n\t\t\t\tkey,\n\t\t\t\tdeepClone( value ),\n\t\t\t] )\n\t\t) as T;\n\t}\n\tif ( Array.isArray( source ) ) {\n\t\treturn source.map( ( i ) => deepClone( i ) ) as T;\n\t}\n\treturn source;\n}\n"], "mappings": "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", "names": [] }