UNPKG

@wordpress/interactivity

Version:

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

8 lines (7 loc) 6.79 kB
{ "version": 3, "sources": ["../../src/proxies/signals.ts"], "sourcesContent": ["/**\n * External dependencies\n */\nimport {\n\tcomputed,\n\tsignal,\n\tbatch,\n\ttype Signal,\n\ttype ReadonlySignal,\n} from '@preact/signals';\n\n/**\n * Internal dependencies\n */\nimport { getNamespaceFromProxy } from './registry';\nimport { getScope } from '../scopes';\nimport { setNamespace, resetNamespace } from '../namespaces';\nimport { withScope } from '../utils';\n\n/**\n * Identifier for property computeds not associated to any scope.\n */\nconst NO_SCOPE = {};\n\n/**\n * Structure that manages reactivity for a property in a state object. It uses\n * signals to keep track of property value or getter modifications.\n */\nexport class PropSignal {\n\t/**\n\t * Proxy that holds the property this PropSignal is associated with.\n\t */\n\tprivate owner: object;\n\n\t/**\n\t * Relation of computeds by scope. These computeds are read-only signals\n\t * that depend on whether the property is a value or a getter and,\n\t * therefore, can return different values depending on the scope in which\n\t * the getter is accessed.\n\t */\n\tprivate computedsByScope: WeakMap< WeakKey, ReadonlySignal >;\n\n\t/**\n\t * Signal with the value assigned to the related property.\n\t */\n\tprivate valueSignal?: Signal;\n\n\t/**\n\t * Signal with the getter assigned to the related property.\n\t */\n\tprivate getterSignal?: Signal< ( () => any ) | undefined >;\n\n\t/**\n\t * Pending getter to be consolidated.\n\t */\n\tprivate pendingGetter?: () => any;\n\n\t/**\n\t * Structure that manages reactivity for a property in a state object, using\n\t * signals to keep track of property value or getter modifications.\n\t *\n\t * @param owner Proxy that holds the property this instance is associated\n\t * with.\n\t */\n\tconstructor( owner: object ) {\n\t\tthis.owner = owner;\n\t\tthis.computedsByScope = new WeakMap();\n\t}\n\n\t/**\n\t * Changes the internal value. If a getter was set before, it is set to\n\t * `undefined`.\n\t *\n\t * @param value New value.\n\t */\n\tpublic setValue( value: unknown ) {\n\t\tthis.update( { value } );\n\t}\n\n\t/**\n\t * Changes the internal getter. If a value was set before, it is set to\n\t * `undefined`.\n\t *\n\t * @param getter New getter.\n\t */\n\tpublic setGetter( getter: () => any ) {\n\t\tthis.update( { get: getter } );\n\t}\n\n\t/**\n\t * Changes the internal getter asynchronously.\n\t *\n\t * The update is made in a microtask, which prevents issues with getters\n\t * accessing the state, and ensures the update occurs before any render.\n\t *\n\t * @param getter New getter.\n\t */\n\tpublic setPendingGetter( getter: () => any ) {\n\t\tthis.pendingGetter = getter;\n\t\tqueueMicrotask( () => this.consolidateGetter() );\n\t}\n\n\t/**\n\t * Consolidate the pending value of the getter.\n\t */\n\tprivate consolidateGetter() {\n\t\tconst getter = this.pendingGetter;\n\t\tif ( getter ) {\n\t\t\tthis.pendingGetter = undefined;\n\t\t\tthis.update( { get: getter } );\n\t\t}\n\t}\n\n\t/**\n\t * Returns the computed that holds the result of evaluating the prop in the\n\t * current scope.\n\t *\n\t * These computeds are read-only signals that depend on whether the property\n\t * is a value or a getter and, therefore, can return different values\n\t * depending on the scope in which the getter is accessed.\n\t *\n\t * @return Computed that depends on the scope.\n\t */\n\tpublic getComputed(): ReadonlySignal {\n\t\tconst scope = getScope() || NO_SCOPE;\n\n\t\tif ( ! this.valueSignal && ! this.getterSignal ) {\n\t\t\tthis.update( {} );\n\t\t}\n\n\t\t/*\n\t\t * If there is any pending getter, consolidate it first. This\n\t\t * could happen if a getter is accessed synchronously after\n\t\t * being set with `store()`.\n\t\t */\n\t\tif ( this.pendingGetter ) {\n\t\t\tthis.consolidateGetter();\n\t\t}\n\n\t\tif ( ! this.computedsByScope.has( scope ) ) {\n\t\t\tconst callback = () => {\n\t\t\t\tconst getter = this.getterSignal?.value;\n\t\t\t\treturn getter\n\t\t\t\t\t? getter.call( this.owner )\n\t\t\t\t\t: this.valueSignal?.value;\n\t\t\t};\n\n\t\t\tsetNamespace( getNamespaceFromProxy( this.owner ) );\n\t\t\tthis.computedsByScope.set(\n\t\t\t\tscope,\n\t\t\t\tcomputed( withScope( callback ) )\n\t\t\t);\n\t\t\tresetNamespace();\n\t\t}\n\n\t\treturn this.computedsByScope.get( scope )!;\n\t}\n\n\t/**\n\t * Updates the internal signals for the value and the getter of the\n\t * corresponding prop.\n\t *\n\t * @param param0\n\t * @param param0.get New getter.\n\t * @param param0.value New value.\n\t */\n\tprivate update( { get, value }: { get?: () => any; value?: unknown } ) {\n\t\tif ( ! this.valueSignal ) {\n\t\t\tthis.valueSignal = signal( value );\n\t\t\tthis.getterSignal = signal( get );\n\t\t} else if (\n\t\t\tvalue !== this.valueSignal.peek() ||\n\t\t\tget !== this.getterSignal!.peek()\n\t\t) {\n\t\t\tbatch( () => {\n\t\t\t\tthis.valueSignal!.value = value;\n\t\t\t\tthis.getterSignal!.value = get;\n\t\t\t} );\n\t\t}\n\t}\n}\n"], "mappings": ";AAGA;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,OAGM;AAKP,SAAS,6BAA6B;AACtC,SAAS,gBAAgB;AACzB,SAAS,cAAc,sBAAsB;AAC7C,SAAS,iBAAiB;AAK1B,IAAM,WAAW,CAAC;AAMX,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA,EAIf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YAAa,OAAgB;AAC5B,SAAK,QAAQ;AACb,SAAK,mBAAmB,oBAAI,QAAQ;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,SAAU,OAAiB;AACjC,SAAK,OAAQ,EAAE,MAAM,CAAE;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,UAAW,QAAoB;AACrC,SAAK,OAAQ,EAAE,KAAK,OAAO,CAAE;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUO,iBAAkB,QAAoB;AAC5C,SAAK,gBAAgB;AACrB,mBAAgB,MAAM,KAAK,kBAAkB,CAAE;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB;AAC3B,UAAM,SAAS,KAAK;AACpB,QAAK,QAAS;AACb,WAAK,gBAAgB;AACrB,WAAK,OAAQ,EAAE,KAAK,OAAO,CAAE;AAAA,IAC9B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,cAA8B;AACpC,UAAM,QAAQ,SAAS,KAAK;AAE5B,QAAK,CAAE,KAAK,eAAe,CAAE,KAAK,cAAe;AAChD,WAAK,OAAQ,CAAC,CAAE;AAAA,IACjB;AAOA,QAAK,KAAK,eAAgB;AACzB,WAAK,kBAAkB;AAAA,IACxB;AAEA,QAAK,CAAE,KAAK,iBAAiB,IAAK,KAAM,GAAI;AAC3C,YAAM,WAAW,MAAM;AACtB,cAAM,SAAS,KAAK,cAAc;AAClC,eAAO,SACJ,OAAO,KAAM,KAAK,KAAM,IACxB,KAAK,aAAa;AAAA,MACtB;AAEA,mBAAc,sBAAuB,KAAK,KAAM,CAAE;AAClD,WAAK,iBAAiB;AAAA,QACrB;AAAA,QACA,SAAU,UAAW,QAAS,CAAE;AAAA,MACjC;AACA,qBAAe;AAAA,IAChB;AAEA,WAAO,KAAK,iBAAiB,IAAK,KAAM;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,OAAQ,EAAE,KAAK,MAAM,GAA0C;AACtE,QAAK,CAAE,KAAK,aAAc;AACzB,WAAK,cAAc,OAAQ,KAAM;AACjC,WAAK,eAAe,OAAQ,GAAI;AAAA,IACjC,WACC,UAAU,KAAK,YAAY,KAAK,KAChC,QAAQ,KAAK,aAAc,KAAK,GAC/B;AACD,YAAO,MAAM;AACZ,aAAK,YAAa,QAAQ;AAC1B,aAAK,aAAc,QAAQ;AAAA,MAC5B,CAAE;AAAA,IACH;AAAA,EACD;AACD;", "names": [] }