fix: prevent asset conflicts between React and Grid.js versions

Add coexistence checks to all enqueue methods to prevent loading
both React and Grid.js assets simultaneously.

Changes:
- ReactAdmin.php: Only enqueue React assets when ?react=1
- Init.php: Skip Grid.js when React active on admin pages
- Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0
- Customer.php, Product.php, License.php: Add coexistence checks

Now the toggle between Classic and React versions works correctly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 17:02:14 +07:00
parent bd9cdac02e
commit e8fbfb14c1
74973 changed files with 6658406 additions and 71 deletions

View File

@@ -0,0 +1,64 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useRef, useState, useEffect, createPortal } from '@wordpress/element';
/**
* Internal dependencies
*/
import useSlot from './use-slot';
import StyleProvider from '../../style-provider';
function useForceUpdate() {
const [, setState] = useState({});
const mounted = useRef(true);
useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
}, []);
return () => {
if (mounted.current) {
setState({});
}
};
}
export default function Fill(props) {
var _slot$fillProps;
const {
name,
children
} = props;
const {
registerFill,
unregisterFill,
...slot
} = useSlot(name);
const rerender = useForceUpdate();
const ref = useRef({
rerender
});
useEffect(() => {
// We register fills so we can keep track of their existence.
// Some Slot implementations need to know if there're already fills
// registered so they can choose to render themselves or not.
registerFill(ref);
return () => {
unregisterFill(ref);
};
}, [registerFill, unregisterFill]);
if (!slot.ref || !slot.ref.current) {
return null;
}
// When using a `Fill`, the `children` will be rendered in the document of the
// `Slot`. This means that we need to wrap the `children` in a `StyleProvider`
// to make sure we're referencing the right document/iframe (instead of the
// context of the `Fill`'s parent).
const wrappedChildren = createElement(StyleProvider, {
document: slot.ref.current.ownerDocument
}, typeof children === 'function' ? children((_slot$fillProps = slot.fillProps) !== null && _slot$fillProps !== void 0 ? _slot$fillProps : {}) : children);
return createPortal(wrappedChildren, slot.ref.current);
}
//# sourceMappingURL=fill.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useRef","useState","useEffect","createPortal","useSlot","StyleProvider","useForceUpdate","setState","mounted","current","Fill","props","_slot$fillProps","name","children","registerFill","unregisterFill","slot","rerender","ref","wrappedChildren","createElement","document","ownerDocument","fillProps"],"sources":["@wordpress/components/src/slot-fill/bubbles-virtually/fill.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useRef, useState, useEffect, createPortal } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport useSlot from './use-slot';\nimport StyleProvider from '../../style-provider';\nimport type { FillComponentProps } from '../types';\n\nfunction useForceUpdate() {\n\tconst [ , setState ] = useState( {} );\n\tconst mounted = useRef( true );\n\n\tuseEffect( () => {\n\t\tmounted.current = true;\n\t\treturn () => {\n\t\t\tmounted.current = false;\n\t\t};\n\t}, [] );\n\n\treturn () => {\n\t\tif ( mounted.current ) {\n\t\t\tsetState( {} );\n\t\t}\n\t};\n}\n\nexport default function Fill( props: FillComponentProps ) {\n\tconst { name, children } = props;\n\tconst { registerFill, unregisterFill, ...slot } = useSlot( name );\n\tconst rerender = useForceUpdate();\n\tconst ref = useRef( { rerender } );\n\n\tuseEffect( () => {\n\t\t// We register fills so we can keep track of their existence.\n\t\t// Some Slot implementations need to know if there're already fills\n\t\t// registered so they can choose to render themselves or not.\n\t\tregisterFill( ref );\n\t\treturn () => {\n\t\t\tunregisterFill( ref );\n\t\t};\n\t}, [ registerFill, unregisterFill ] );\n\n\tif ( ! slot.ref || ! slot.ref.current ) {\n\t\treturn null;\n\t}\n\n\t// When using a `Fill`, the `children` will be rendered in the document of the\n\t// `Slot`. This means that we need to wrap the `children` in a `StyleProvider`\n\t// to make sure we're referencing the right document/iframe (instead of the\n\t// context of the `Fill`'s parent).\n\tconst wrappedChildren = (\n\t\t<StyleProvider document={ slot.ref.current.ownerDocument }>\n\t\t\t{ typeof children === 'function'\n\t\t\t\t? children( slot.fillProps ?? {} )\n\t\t\t\t: children }\n\t\t</StyleProvider>\n\t);\n\n\treturn createPortal( wrappedChildren, slot.ref.current );\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,MAAM,EAAEC,QAAQ,EAAEC,SAAS,EAAEC,YAAY,QAAQ,oBAAoB;;AAE9E;AACA;AACA;AACA,OAAOC,OAAO,MAAM,YAAY;AAChC,OAAOC,aAAa,MAAM,sBAAsB;AAGhD,SAASC,cAAcA,CAAA,EAAG;EACzB,MAAM,GAAIC,QAAQ,CAAE,GAAGN,QAAQ,CAAE,CAAC,CAAE,CAAC;EACrC,MAAMO,OAAO,GAAGR,MAAM,CAAE,IAAK,CAAC;EAE9BE,SAAS,CAAE,MAAM;IAChBM,OAAO,CAACC,OAAO,GAAG,IAAI;IACtB,OAAO,MAAM;MACZD,OAAO,CAACC,OAAO,GAAG,KAAK;IACxB,CAAC;EACF,CAAC,EAAE,EAAG,CAAC;EAEP,OAAO,MAAM;IACZ,IAAKD,OAAO,CAACC,OAAO,EAAG;MACtBF,QAAQ,CAAE,CAAC,CAAE,CAAC;IACf;EACD,CAAC;AACF;AAEA,eAAe,SAASG,IAAIA,CAAEC,KAAyB,EAAG;EAAA,IAAAC,eAAA;EACzD,MAAM;IAAEC,IAAI;IAAEC;EAAS,CAAC,GAAGH,KAAK;EAChC,MAAM;IAAEI,YAAY;IAAEC,cAAc;IAAE,GAAGC;EAAK,CAAC,GAAGb,OAAO,CAAES,IAAK,CAAC;EACjE,MAAMK,QAAQ,GAAGZ,cAAc,CAAC,CAAC;EACjC,MAAMa,GAAG,GAAGnB,MAAM,CAAE;IAAEkB;EAAS,CAAE,CAAC;EAElChB,SAAS,CAAE,MAAM;IAChB;IACA;IACA;IACAa,YAAY,CAAEI,GAAI,CAAC;IACnB,OAAO,MAAM;MACZH,cAAc,CAAEG,GAAI,CAAC;IACtB,CAAC;EACF,CAAC,EAAE,CAAEJ,YAAY,EAAEC,cAAc,CAAG,CAAC;EAErC,IAAK,CAAEC,IAAI,CAACE,GAAG,IAAI,CAAEF,IAAI,CAACE,GAAG,CAACV,OAAO,EAAG;IACvC,OAAO,IAAI;EACZ;;EAEA;EACA;EACA;EACA;EACA,MAAMW,eAAe,GACpBC,aAAA,CAAChB,aAAa;IAACiB,QAAQ,EAAGL,IAAI,CAACE,GAAG,CAACV,OAAO,CAACc;EAAe,GACvD,OAAOT,QAAQ,KAAK,UAAU,GAC7BA,QAAQ,EAAAF,eAAA,GAAEK,IAAI,CAACO,SAAS,cAAAZ,eAAA,cAAAA,eAAA,GAAI,CAAC,CAAE,CAAC,GAChCE,QACW,CACf;EAED,OAAOX,YAAY,CAAEiB,eAAe,EAAEH,IAAI,CAACE,GAAG,CAACV,OAAQ,CAAC;AACzD"}

View File

@@ -0,0 +1,29 @@
/**
* External dependencies
*/
import { proxyMap } from 'valtio/utils';
/**
* WordPress dependencies
*/
import { createContext } from '@wordpress/element';
import warning from '@wordpress/warning';
/**
* Internal dependencies
*/
const initialContextValue = {
slots: proxyMap(),
fills: proxyMap(),
registerSlot: () => {
typeof SCRIPT_DEBUG !== "undefined" && SCRIPT_DEBUG === true ? warning('Components must be wrapped within `SlotFillProvider`. ' + 'See https://developer.wordpress.org/block-editor/components/slot-fill/') : void 0;
},
updateSlot: () => {},
unregisterSlot: () => {},
registerFill: () => {},
unregisterFill: () => {},
// This helps the provider know if it's using the default context value or not.
isDefault: true
};
const SlotFillContext = createContext(initialContextValue);
export default SlotFillContext;
//# sourceMappingURL=slot-fill-context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["proxyMap","createContext","warning","initialContextValue","slots","fills","registerSlot","SCRIPT_DEBUG","updateSlot","unregisterSlot","registerFill","unregisterFill","isDefault","SlotFillContext"],"sources":["@wordpress/components/src/slot-fill/bubbles-virtually/slot-fill-context.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport { proxyMap } from 'valtio/utils';\n/**\n * WordPress dependencies\n */\nimport { createContext } from '@wordpress/element';\nimport warning from '@wordpress/warning';\n/**\n * Internal dependencies\n */\nimport type { SlotFillBubblesVirtuallyContext } from '../types';\n\nconst initialContextValue: SlotFillBubblesVirtuallyContext = {\n\tslots: proxyMap(),\n\tfills: proxyMap(),\n\tregisterSlot: () => {\n\t\twarning(\n\t\t\t'Components must be wrapped within `SlotFillProvider`. ' +\n\t\t\t\t'See https://developer.wordpress.org/block-editor/components/slot-fill/'\n\t\t);\n\t},\n\tupdateSlot: () => {},\n\tunregisterSlot: () => {},\n\tregisterFill: () => {},\n\tunregisterFill: () => {},\n\n\t// This helps the provider know if it's using the default context value or not.\n\tisDefault: true,\n};\n\nconst SlotFillContext = createContext( initialContextValue );\n\nexport default SlotFillContext;\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,QAAQ,QAAQ,cAAc;AACvC;AACA;AACA;AACA,SAASC,aAAa,QAAQ,oBAAoB;AAClD,OAAOC,OAAO,MAAM,oBAAoB;AACxC;AACA;AACA;;AAGA,MAAMC,mBAAoD,GAAG;EAC5DC,KAAK,EAAEJ,QAAQ,CAAC,CAAC;EACjBK,KAAK,EAAEL,QAAQ,CAAC,CAAC;EACjBM,YAAY,EAAEA,CAAA,KAAM;IACnB,OAAAC,YAAA,oBAAAA,YAAA,YAAAL,OAAO,CACN,wDAAwD,GACvD,wEACF,CAAC;EACF,CAAC;EACDM,UAAU,EAAEA,CAAA,KAAM,CAAC,CAAC;EACpBC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;EACxBC,YAAY,EAAEA,CAAA,KAAM,CAAC,CAAC;EACtBC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;EAExB;EACAC,SAAS,EAAE;AACZ,CAAC;AAED,MAAMC,eAAe,GAAGZ,aAAa,CAAEE,mBAAoB,CAAC;AAE5D,eAAeU,eAAe"}

View File

@@ -0,0 +1,79 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { ref as valRef } from 'valtio';
import { proxyMap } from 'valtio/utils';
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import isShallowEqual from '@wordpress/is-shallow-equal';
/**
* Internal dependencies
*/
import SlotFillContext from './slot-fill-context';
function createSlotRegistry() {
const slots = proxyMap();
const fills = proxyMap();
const registerSlot = (name, ref, fillProps) => {
const slot = slots.get(name);
slots.set(name, valRef({
...slot,
ref: ref || slot?.ref,
fillProps: fillProps || slot?.fillProps || {}
}));
};
const unregisterSlot = (name, ref) => {
// Make sure we're not unregistering a slot registered by another element
// See https://github.com/WordPress/gutenberg/pull/19242#issuecomment-590295412
if (slots.get(name)?.ref === ref) {
slots.delete(name);
}
};
const updateSlot = (name, fillProps) => {
const slot = slots.get(name);
if (!slot) {
return;
}
if (isShallowEqual(slot.fillProps, fillProps)) {
return;
}
slot.fillProps = fillProps;
const slotFills = fills.get(name);
if (slotFills) {
// Force update fills.
slotFills.forEach(fill => fill.current.rerender());
}
};
const registerFill = (name, ref) => {
fills.set(name, valRef([...(fills.get(name) || []), ref]));
};
const unregisterFill = (name, ref) => {
const fillsForName = fills.get(name);
if (!fillsForName) {
return;
}
fills.set(name, valRef(fillsForName.filter(fillRef => fillRef !== ref)));
};
return {
slots,
fills,
registerSlot,
updateSlot,
unregisterSlot,
registerFill,
unregisterFill
};
}
export default function SlotFillProvider({
children
}) {
const registry = useMemo(createSlotRegistry, []);
return createElement(SlotFillContext.Provider, {
value: registry
}, children);
}
//# sourceMappingURL=slot-fill-provider.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,57 @@
import { createElement } from "react";
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { useRef, useLayoutEffect, useContext, forwardRef } from '@wordpress/element';
import { useMergeRefs } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { View } from '../../view';
import SlotFillContext from './slot-fill-context';
function Slot(props, forwardedRef) {
const {
name,
fillProps = {},
as,
// `children` is not allowed. However, if it is passed,
// it will be displayed as is, so remove `children`.
// @ts-ignore
children,
...restProps
} = props;
const {
registerSlot,
unregisterSlot,
...registry
} = useContext(SlotFillContext);
const ref = useRef(null);
useLayoutEffect(() => {
registerSlot(name, ref, fillProps);
return () => {
unregisterSlot(name, ref);
};
// Ignore reason: We don't want to unregister and register the slot whenever
// `fillProps` change, which would cause the fill to be re-mounted. Instead,
// we can just update the slot (see hook below).
// For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [registerSlot, unregisterSlot, name]);
// fillProps may be an update that interacts with the layout, so we
// useLayoutEffect.
useLayoutEffect(() => {
registry.updateSlot(name, fillProps);
});
return createElement(View, {
as: as,
ref: useMergeRefs([forwardedRef, ref]),
...restProps
});
}
export default forwardRef(Slot);
//# sourceMappingURL=slot.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useRef","useLayoutEffect","useContext","forwardRef","useMergeRefs","View","SlotFillContext","Slot","props","forwardedRef","name","fillProps","as","children","restProps","registerSlot","unregisterSlot","registry","ref","updateSlot","createElement"],"sources":["@wordpress/components/src/slot-fill/bubbles-virtually/slot.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport {\n\tuseRef,\n\tuseLayoutEffect,\n\tuseContext,\n\tforwardRef,\n} from '@wordpress/element';\nimport { useMergeRefs } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport { View } from '../../view';\nimport SlotFillContext from './slot-fill-context';\nimport type { WordPressComponentProps } from '../../context';\nimport type { SlotComponentProps } from '../types';\n\nfunction Slot(\n\tprops: WordPressComponentProps<\n\t\tOmit< SlotComponentProps, 'bubblesVirtually' >,\n\t\t'div'\n\t>,\n\tforwardedRef: ForwardedRef< any >\n) {\n\tconst {\n\t\tname,\n\t\tfillProps = {},\n\t\tas,\n\t\t// `children` is not allowed. However, if it is passed,\n\t\t// it will be displayed as is, so remove `children`.\n\t\t// @ts-ignore\n\t\tchildren,\n\t\t...restProps\n\t} = props;\n\n\tconst { registerSlot, unregisterSlot, ...registry } =\n\t\tuseContext( SlotFillContext );\n\tconst ref = useRef< HTMLElement >( null );\n\n\tuseLayoutEffect( () => {\n\t\tregisterSlot( name, ref, fillProps );\n\t\treturn () => {\n\t\t\tunregisterSlot( name, ref );\n\t\t};\n\t\t// Ignore reason: We don't want to unregister and register the slot whenever\n\t\t// `fillProps` change, which would cause the fill to be re-mounted. Instead,\n\t\t// we can just update the slot (see hook below).\n\t\t// For more context, see https://github.com/WordPress/gutenberg/pull/44403#discussion_r994415973\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ registerSlot, unregisterSlot, name ] );\n\t// fillProps may be an update that interacts with the layout, so we\n\t// useLayoutEffect.\n\tuseLayoutEffect( () => {\n\t\tregistry.updateSlot( name, fillProps );\n\t} );\n\n\treturn (\n\t\t<View\n\t\t\tas={ as }\n\t\t\tref={ useMergeRefs( [ forwardedRef, ref ] ) }\n\t\t\t{ ...restProps }\n\t\t/>\n\t);\n}\n\nexport default forwardRef( Slot );\n"],"mappings":";AAAA;AACA;AACA;;AAGA;AACA;AACA;AACA,SACCA,MAAM,EACNC,eAAe,EACfC,UAAU,EACVC,UAAU,QACJ,oBAAoB;AAC3B,SAASC,YAAY,QAAQ,oBAAoB;;AAEjD;AACA;AACA;AACA,SAASC,IAAI,QAAQ,YAAY;AACjC,OAAOC,eAAe,MAAM,qBAAqB;AAIjD,SAASC,IAAIA,CACZC,KAGC,EACDC,YAAiC,EAChC;EACD,MAAM;IACLC,IAAI;IACJC,SAAS,GAAG,CAAC,CAAC;IACdC,EAAE;IACF;IACA;IACA;IACAC,QAAQ;IACR,GAAGC;EACJ,CAAC,GAAGN,KAAK;EAET,MAAM;IAAEO,YAAY;IAAEC,cAAc;IAAE,GAAGC;EAAS,CAAC,GAClDf,UAAU,CAAEI,eAAgB,CAAC;EAC9B,MAAMY,GAAG,GAAGlB,MAAM,CAAiB,IAAK,CAAC;EAEzCC,eAAe,CAAE,MAAM;IACtBc,YAAY,CAAEL,IAAI,EAAEQ,GAAG,EAAEP,SAAU,CAAC;IACpC,OAAO,MAAM;MACZK,cAAc,CAAEN,IAAI,EAAEQ,GAAI,CAAC;IAC5B,CAAC;IACD;IACA;IACA;IACA;IACA;EACD,CAAC,EAAE,CAAEH,YAAY,EAAEC,cAAc,EAAEN,IAAI,CAAG,CAAC;EAC3C;EACA;EACAT,eAAe,CAAE,MAAM;IACtBgB,QAAQ,CAACE,UAAU,CAAET,IAAI,EAAEC,SAAU,CAAC;EACvC,CAAE,CAAC;EAEH,OACCS,aAAA,CAACf,IAAI;IACJO,EAAE,EAAGA,EAAI;IACTM,GAAG,EAAGd,YAAY,CAAE,CAAEK,YAAY,EAAES,GAAG,CAAG,CAAG;IAAA,GACxCJ;EAAS,CACd,CAAC;AAEJ;AAEA,eAAeX,UAAU,CAAEI,IAAK,CAAC"}

View File

@@ -0,0 +1,25 @@
/**
* External dependencies
*/
import { useSnapshot } from 'valtio';
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './slot-fill-context';
export default function useSlotFills(name) {
const registry = useContext(SlotFillContext);
const fills = useSnapshot(registry.fills, {
sync: true
});
// The important bit here is that this call ensures that the hook
// only causes a re-render if the "fills" of a given slot name
// change, not any fills.
return fills.get(name);
}
//# sourceMappingURL=use-slot-fills.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useSnapshot","useContext","SlotFillContext","useSlotFills","name","registry","fills","sync","get"],"sources":["@wordpress/components/src/slot-fill/bubbles-virtually/use-slot-fills.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport { useSnapshot } from 'valtio';\n\n/**\n * WordPress dependencies\n */\nimport { useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport SlotFillContext from './slot-fill-context';\nimport type { SlotKey } from '../types';\n\nexport default function useSlotFills( name: SlotKey ) {\n\tconst registry = useContext( SlotFillContext );\n\tconst fills = useSnapshot( registry.fills, { sync: true } );\n\t// The important bit here is that this call ensures that the hook\n\t// only causes a re-render if the \"fills\" of a given slot name\n\t// change, not any fills.\n\treturn fills.get( name );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,WAAW,QAAQ,QAAQ;;AAEpC;AACA;AACA;AACA,SAASC,UAAU,QAAQ,oBAAoB;;AAE/C;AACA;AACA;AACA,OAAOC,eAAe,MAAM,qBAAqB;AAGjD,eAAe,SAASC,YAAYA,CAAEC,IAAa,EAAG;EACrD,MAAMC,QAAQ,GAAGJ,UAAU,CAAEC,eAAgB,CAAC;EAC9C,MAAMI,KAAK,GAAGN,WAAW,CAAEK,QAAQ,CAACC,KAAK,EAAE;IAAEC,IAAI,EAAE;EAAK,CAAE,CAAC;EAC3D;EACA;EACA;EACA,OAAOD,KAAK,CAACE,GAAG,CAAEJ,IAAK,CAAC;AACzB"}

View File

@@ -0,0 +1,35 @@
/**
* External dependencies
*/
import { useSnapshot } from 'valtio';
/**
* WordPress dependencies
*/
import { useMemo, useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './slot-fill-context';
export default function useSlot(name) {
const registry = useContext(SlotFillContext);
const slots = useSnapshot(registry.slots, {
sync: true
});
// The important bit here is that the `useSnapshot` call ensures that the
// hook only causes a re-render if the slot with the given name changes,
// not any other slot.
const slot = slots.get(name);
const api = useMemo(() => ({
updateSlot: fillProps => registry.updateSlot(name, fillProps),
unregisterSlot: ref => registry.unregisterSlot(name, ref),
registerFill: ref => registry.registerFill(name, ref),
unregisterFill: ref => registry.unregisterFill(name, ref)
}), [name, registry]);
return {
...slot,
...api
};
}
//# sourceMappingURL=use-slot.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useSnapshot","useMemo","useContext","SlotFillContext","useSlot","name","registry","slots","sync","slot","get","api","updateSlot","fillProps","unregisterSlot","ref","registerFill","unregisterFill"],"sources":["@wordpress/components/src/slot-fill/bubbles-virtually/use-slot.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport { useSnapshot } from 'valtio';\n\n/**\n * WordPress dependencies\n */\nimport { useMemo, useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport SlotFillContext from './slot-fill-context';\nimport type {\n\tSlotFillBubblesVirtuallyFillRef,\n\tSlotFillBubblesVirtuallySlotRef,\n\tFillProps,\n\tSlotKey,\n} from '../types';\n\nexport default function useSlot( name: SlotKey ) {\n\tconst registry = useContext( SlotFillContext );\n\tconst slots = useSnapshot( registry.slots, { sync: true } );\n\t// The important bit here is that the `useSnapshot` call ensures that the\n\t// hook only causes a re-render if the slot with the given name changes,\n\t// not any other slot.\n\tconst slot = slots.get( name );\n\n\tconst api = useMemo(\n\t\t() => ( {\n\t\t\tupdateSlot: ( fillProps: FillProps ) =>\n\t\t\t\tregistry.updateSlot( name, fillProps ),\n\t\t\tunregisterSlot: ( ref: SlotFillBubblesVirtuallySlotRef ) =>\n\t\t\t\tregistry.unregisterSlot( name, ref ),\n\t\t\tregisterFill: ( ref: SlotFillBubblesVirtuallyFillRef ) =>\n\t\t\t\tregistry.registerFill( name, ref ),\n\t\t\tunregisterFill: ( ref: SlotFillBubblesVirtuallyFillRef ) =>\n\t\t\t\tregistry.unregisterFill( name, ref ),\n\t\t} ),\n\t\t[ name, registry ]\n\t);\n\n\treturn {\n\t\t...slot,\n\t\t...api,\n\t};\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,WAAW,QAAQ,QAAQ;;AAEpC;AACA;AACA;AACA,SAASC,OAAO,EAAEC,UAAU,QAAQ,oBAAoB;;AAExD;AACA;AACA;AACA,OAAOC,eAAe,MAAM,qBAAqB;AAQjD,eAAe,SAASC,OAAOA,CAAEC,IAAa,EAAG;EAChD,MAAMC,QAAQ,GAAGJ,UAAU,CAAEC,eAAgB,CAAC;EAC9C,MAAMI,KAAK,GAAGP,WAAW,CAAEM,QAAQ,CAACC,KAAK,EAAE;IAAEC,IAAI,EAAE;EAAK,CAAE,CAAC;EAC3D;EACA;EACA;EACA,MAAMC,IAAI,GAAGF,KAAK,CAACG,GAAG,CAAEL,IAAK,CAAC;EAE9B,MAAMM,GAAG,GAAGV,OAAO,CAClB,OAAQ;IACPW,UAAU,EAAIC,SAAoB,IACjCP,QAAQ,CAACM,UAAU,CAAEP,IAAI,EAAEQ,SAAU,CAAC;IACvCC,cAAc,EAAIC,GAAoC,IACrDT,QAAQ,CAACQ,cAAc,CAAET,IAAI,EAAEU,GAAI,CAAC;IACrCC,YAAY,EAAID,GAAoC,IACnDT,QAAQ,CAACU,YAAY,CAAEX,IAAI,EAAEU,GAAI,CAAC;IACnCE,cAAc,EAAIF,GAAoC,IACrDT,QAAQ,CAACW,cAAc,CAAEZ,IAAI,EAAEU,GAAI;EACrC,CAAC,CAAE,EACH,CAAEV,IAAI,EAAEC,QAAQ,CACjB,CAAC;EAED,OAAO;IACN,GAAGG,IAAI;IACP,GAAGE;EACJ,CAAC;AACF"}

View File

@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { createContext } from '@wordpress/element';
/**
* Internal dependencies
*/
const initialValue = {
registerSlot: () => {},
unregisterSlot: () => {},
registerFill: () => {},
unregisterFill: () => {},
getSlot: () => undefined,
getFills: () => [],
subscribe: () => () => {}
};
export const SlotFillContext = createContext(initialValue);
export default SlotFillContext;
//# sourceMappingURL=context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["createContext","initialValue","registerSlot","unregisterSlot","registerFill","unregisterFill","getSlot","undefined","getFills","subscribe","SlotFillContext"],"sources":["@wordpress/components/src/slot-fill/context.ts"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createContext } from '@wordpress/element';\n/**\n * Internal dependencies\n */\nimport type { BaseSlotFillContext } from './types';\n\nconst initialValue: BaseSlotFillContext = {\n\tregisterSlot: () => {},\n\tunregisterSlot: () => {},\n\tregisterFill: () => {},\n\tunregisterFill: () => {},\n\tgetSlot: () => undefined,\n\tgetFills: () => [],\n\tsubscribe: () => () => {},\n};\nexport const SlotFillContext = createContext( initialValue );\n\nexport default SlotFillContext;\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,aAAa,QAAQ,oBAAoB;AAClD;AACA;AACA;;AAGA,MAAMC,YAAiC,GAAG;EACzCC,YAAY,EAAEA,CAAA,KAAM,CAAC,CAAC;EACtBC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;EACxBC,YAAY,EAAEA,CAAA,KAAM,CAAC,CAAC;EACtBC,cAAc,EAAEA,CAAA,KAAM,CAAC,CAAC;EACxBC,OAAO,EAAEA,CAAA,KAAMC,SAAS;EACxBC,QAAQ,EAAEA,CAAA,KAAM,EAAE;EAClBC,SAAS,EAAEA,CAAA,KAAM,MAAM,CAAC;AACzB,CAAC;AACD,OAAO,MAAMC,eAAe,GAAGV,aAAa,CAAEC,YAAa,CAAC;AAE5D,eAAeS,eAAe"}

View File

@@ -0,0 +1,55 @@
/**
* WordPress dependencies
*/
import { useContext, useLayoutEffect, useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './context';
import useSlot from './use-slot';
export default function Fill({
name,
children
}) {
const {
registerFill,
unregisterFill
} = useContext(SlotFillContext);
const slot = useSlot(name);
const ref = useRef({
name,
children
});
useLayoutEffect(() => {
const refValue = ref.current;
registerFill(name, refValue);
return () => unregisterFill(name, refValue);
// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.
// We'll leave them as-is until a more detailed investigation/refactor can be performed.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useLayoutEffect(() => {
ref.current.children = children;
if (slot) {
slot.forceUpdate();
}
// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.
// We'll leave them as-is until a more detailed investigation/refactor can be performed.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [children]);
useLayoutEffect(() => {
if (name === ref.current.name) {
// Ignore initial effect.
return;
}
unregisterFill(ref.current.name, ref.current);
ref.current.name = name;
registerFill(name, ref.current);
// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.
// We'll leave them as-is until a more detailed investigation/refactor can be performed.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [name]);
return null;
}
//# sourceMappingURL=fill.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useContext","useLayoutEffect","useRef","SlotFillContext","useSlot","Fill","name","children","registerFill","unregisterFill","slot","ref","refValue","current","forceUpdate"],"sources":["@wordpress/components/src/slot-fill/fill.ts"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useContext, useLayoutEffect, useRef } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport SlotFillContext from './context';\nimport useSlot from './use-slot';\nimport type { FillComponentProps } from './types';\n\nexport default function Fill( { name, children }: FillComponentProps ) {\n\tconst { registerFill, unregisterFill } = useContext( SlotFillContext );\n\tconst slot = useSlot( name );\n\n\tconst ref = useRef( {\n\t\tname,\n\t\tchildren,\n\t} );\n\n\tuseLayoutEffect( () => {\n\t\tconst refValue = ref.current;\n\t\tregisterFill( name, refValue );\n\t\treturn () => unregisterFill( name, refValue );\n\t\t// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.\n\t\t// We'll leave them as-is until a more detailed investigation/refactor can be performed.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [] );\n\n\tuseLayoutEffect( () => {\n\t\tref.current.children = children;\n\t\tif ( slot ) {\n\t\t\tslot.forceUpdate();\n\t\t}\n\t\t// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.\n\t\t// We'll leave them as-is until a more detailed investigation/refactor can be performed.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ children ] );\n\n\tuseLayoutEffect( () => {\n\t\tif ( name === ref.current.name ) {\n\t\t\t// Ignore initial effect.\n\t\t\treturn;\n\t\t}\n\t\tunregisterFill( ref.current.name, ref.current );\n\t\tref.current.name = name;\n\t\tregisterFill( name, ref.current );\n\t\t// Ignore reason: the useLayoutEffects here are written to fire at specific times, and introducing new dependencies could cause unexpected changes in behavior.\n\t\t// We'll leave them as-is until a more detailed investigation/refactor can be performed.\n\t\t// eslint-disable-next-line react-hooks/exhaustive-deps\n\t}, [ name ] );\n\n\treturn null;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,UAAU,EAAEC,eAAe,EAAEC,MAAM,QAAQ,oBAAoB;;AAExE;AACA;AACA;AACA,OAAOC,eAAe,MAAM,WAAW;AACvC,OAAOC,OAAO,MAAM,YAAY;AAGhC,eAAe,SAASC,IAAIA,CAAE;EAAEC,IAAI;EAAEC;AAA6B,CAAC,EAAG;EACtE,MAAM;IAAEC,YAAY;IAAEC;EAAe,CAAC,GAAGT,UAAU,CAAEG,eAAgB,CAAC;EACtE,MAAMO,IAAI,GAAGN,OAAO,CAAEE,IAAK,CAAC;EAE5B,MAAMK,GAAG,GAAGT,MAAM,CAAE;IACnBI,IAAI;IACJC;EACD,CAAE,CAAC;EAEHN,eAAe,CAAE,MAAM;IACtB,MAAMW,QAAQ,GAAGD,GAAG,CAACE,OAAO;IAC5BL,YAAY,CAAEF,IAAI,EAAEM,QAAS,CAAC;IAC9B,OAAO,MAAMH,cAAc,CAAEH,IAAI,EAAEM,QAAS,CAAC;IAC7C;IACA;IACA;EACD,CAAC,EAAE,EAAG,CAAC;EAEPX,eAAe,CAAE,MAAM;IACtBU,GAAG,CAACE,OAAO,CAACN,QAAQ,GAAGA,QAAQ;IAC/B,IAAKG,IAAI,EAAG;MACXA,IAAI,CAACI,WAAW,CAAC,CAAC;IACnB;IACA;IACA;IACA;EACD,CAAC,EAAE,CAAEP,QAAQ,CAAG,CAAC;EAEjBN,eAAe,CAAE,MAAM;IACtB,IAAKK,IAAI,KAAKK,GAAG,CAACE,OAAO,CAACP,IAAI,EAAG;MAChC;MACA;IACD;IACAG,cAAc,CAAEE,GAAG,CAACE,OAAO,CAACP,IAAI,EAAEK,GAAG,CAACE,OAAQ,CAAC;IAC/CF,GAAG,CAACE,OAAO,CAACP,IAAI,GAAGA,IAAI;IACvBE,YAAY,CAAEF,IAAI,EAAEK,GAAG,CAACE,OAAQ,CAAC;IACjC;IACA;IACA;EACD,CAAC,EAAE,CAAEP,IAAI,CAAG,CAAC;EAEb,OAAO,IAAI;AACZ"}

View File

@@ -0,0 +1,85 @@
import { createElement, Fragment } from "react";
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { forwardRef, useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import BaseFill from './fill';
import BaseSlot from './slot';
import BubblesVirtuallyFill from './bubbles-virtually/fill';
import BubblesVirtuallySlot from './bubbles-virtually/slot';
import BubblesVirtuallySlotFillProvider from './bubbles-virtually/slot-fill-provider';
import SlotFillProvider from './provider';
import SlotFillContext from './bubbles-virtually/slot-fill-context';
export { default as useSlot } from './bubbles-virtually/use-slot';
export { default as useSlotFills } from './bubbles-virtually/use-slot-fills';
export function Fill(props) {
// We're adding both Fills here so they can register themselves before
// their respective slot has been registered. Only the Fill that has a slot
// will render. The other one will return null.
return createElement(Fragment, null, createElement(BaseFill, {
...props
}), createElement(BubblesVirtuallyFill, {
...props
}));
}
export function UnforwardedSlot(props, ref) {
const {
bubblesVirtually,
...restProps
} = props;
if (bubblesVirtually) {
return createElement(BubblesVirtuallySlot, {
...restProps,
ref: ref
});
}
return createElement(BaseSlot, {
...restProps
});
}
export const Slot = forwardRef(UnforwardedSlot);
export function Provider({
children,
passthrough = false
}) {
const parent = useContext(SlotFillContext);
if (!parent.isDefault && passthrough) {
return createElement(Fragment, null, children);
}
return createElement(SlotFillProvider, null, createElement(BubblesVirtuallySlotFillProvider, null, children));
}
export function createSlotFill(key) {
const baseName = typeof key === 'symbol' ? key.description : key;
const FillComponent = props => createElement(Fill, {
name: key,
...props
});
FillComponent.displayName = `${baseName}Fill`;
const SlotComponent = props => createElement(Slot, {
name: key,
...props
});
SlotComponent.displayName = `${baseName}Slot`;
SlotComponent.__unstableName = key;
return {
Fill: FillComponent,
Slot: SlotComponent
};
}
export const createPrivateSlotFill = name => {
const privateKey = Symbol(name);
const privateSlotFill = createSlotFill(privateKey);
return {
privateKey,
...privateSlotFill
};
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import { createElement } from "react";
/**
* Internal dependencies
*/
import BaseSlot from './slot';
import Fill from './fill';
import Provider from './provider';
export { Fill, Provider };
export function Slot({
bubblesVirtually,
...restProps
}) {
return createElement(BaseSlot, {
...restProps
});
}
export function createSlotFill(name) {
const FillComponent = props => createElement(Fill, {
name: name,
...props
});
FillComponent.displayName = name + 'Fill';
const SlotComponent = props => createElement(Slot, {
name: name,
...props
});
SlotComponent.displayName = name + 'Slot';
return {
Fill: FillComponent,
Slot: SlotComponent
};
}
//# sourceMappingURL=index.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["BaseSlot","Fill","Provider","Slot","bubblesVirtually","restProps","createElement","createSlotFill","name","FillComponent","props","displayName","SlotComponent"],"sources":["@wordpress/components/src/slot-fill/index.native.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport BaseSlot from './slot';\nimport Fill from './fill';\nimport Provider from './provider';\n\nexport { Fill, Provider };\n\nexport function Slot( { bubblesVirtually, ...restProps } ) {\n\treturn <BaseSlot { ...restProps } />;\n}\n\nexport function createSlotFill( name ) {\n\tconst FillComponent = ( props ) => <Fill name={ name } { ...props } />;\n\tFillComponent.displayName = name + 'Fill';\n\n\tconst SlotComponent = ( props ) => <Slot name={ name } { ...props } />;\n\tSlotComponent.displayName = name + 'Slot';\n\n\treturn {\n\t\tFill: FillComponent,\n\t\tSlot: SlotComponent,\n\t};\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,QAAQ,MAAM,QAAQ;AAC7B,OAAOC,IAAI,MAAM,QAAQ;AACzB,OAAOC,QAAQ,MAAM,YAAY;AAEjC,SAASD,IAAI,EAAEC,QAAQ;AAEvB,OAAO,SAASC,IAAIA,CAAE;EAAEC,gBAAgB;EAAE,GAAGC;AAAU,CAAC,EAAG;EAC1D,OAAOC,aAAA,CAACN,QAAQ;IAAA,GAAMK;EAAS,CAAI,CAAC;AACrC;AAEA,OAAO,SAASE,cAAcA,CAAEC,IAAI,EAAG;EACtC,MAAMC,aAAa,GAAKC,KAAK,IAAMJ,aAAA,CAACL,IAAI;IAACO,IAAI,EAAGA,IAAM;IAAA,GAAME;EAAK,CAAI,CAAC;EACtED,aAAa,CAACE,WAAW,GAAGH,IAAI,GAAG,MAAM;EAEzC,MAAMI,aAAa,GAAKF,KAAK,IAAMJ,aAAA,CAACH,IAAI;IAACK,IAAI,EAAGA,IAAM;IAAA,GAAME;EAAK,CAAI,CAAC;EACtEE,aAAa,CAACD,WAAW,GAAGH,IAAI,GAAG,MAAM;EAEzC,OAAO;IACNP,IAAI,EAAEQ,aAAa;IACnBN,IAAI,EAAES;EACP,CAAC;AACF"}

View File

@@ -0,0 +1,97 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './context';
function createSlotRegistry() {
const slots = {};
const fills = {};
let listeners = [];
function registerSlot(name, slot) {
const previousSlot = slots[name];
slots[name] = slot;
triggerListeners();
// Sometimes the fills are registered after the initial render of slot
// But before the registerSlot call, we need to rerender the slot.
forceUpdateSlot(name);
// If a new instance of a slot is being mounted while another with the
// same name exists, force its update _after_ the new slot has been
// assigned into the instance, such that its own rendering of children
// will be empty (the new Slot will subsume all fills for this name).
if (previousSlot) {
previousSlot.forceUpdate();
}
}
function registerFill(name, instance) {
fills[name] = [...(fills[name] || []), instance];
forceUpdateSlot(name);
}
function unregisterSlot(name, instance) {
// If a previous instance of a Slot by this name unmounts, do nothing,
// as the slot and its fills should only be removed for the current
// known instance.
if (slots[name] !== instance) {
return;
}
delete slots[name];
triggerListeners();
}
function unregisterFill(name, instance) {
var _fills$name$filter;
fills[name] = (_fills$name$filter = fills[name]?.filter(fill => fill !== instance)) !== null && _fills$name$filter !== void 0 ? _fills$name$filter : [];
forceUpdateSlot(name);
}
function getSlot(name) {
return slots[name];
}
function getFills(name, slotInstance) {
// Fills should only be returned for the current instance of the slot
// in which they occupy.
if (slots[name] !== slotInstance) {
return [];
}
return fills[name];
}
function forceUpdateSlot(name) {
const slot = getSlot(name);
if (slot) {
slot.forceUpdate();
}
}
function triggerListeners() {
listeners.forEach(listener => listener());
}
function subscribe(listener) {
listeners.push(listener);
return () => {
listeners = listeners.filter(l => l !== listener);
};
}
return {
registerSlot,
unregisterSlot,
registerFill,
unregisterFill,
getSlot,
getFills,
subscribe
};
}
export function SlotFillProvider({
children
}) {
const contextValue = useMemo(createSlotRegistry, []);
return createElement(SlotFillContext.Provider, {
value: contextValue
}, children);
}
export default SlotFillProvider;
//# sourceMappingURL=provider.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,101 @@
import { createElement, Fragment } from "react";
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { Children, Component, cloneElement, isEmptyElement } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './context';
/**
* Whether the argument is a function.
*
* @param maybeFunc The argument to check.
* @return True if the argument is a function, false otherwise.
*/
function isFunction(maybeFunc) {
return typeof maybeFunc === 'function';
}
class SlotComponent extends Component {
constructor(props) {
super(props);
this.isUnmounted = false;
}
componentDidMount() {
const {
registerSlot
} = this.props;
this.isUnmounted = false;
registerSlot(this.props.name, this);
}
componentWillUnmount() {
const {
unregisterSlot
} = this.props;
this.isUnmounted = true;
unregisterSlot(this.props.name, this);
}
componentDidUpdate(prevProps) {
const {
name,
unregisterSlot,
registerSlot
} = this.props;
if (prevProps.name !== name) {
unregisterSlot(prevProps.name, this);
registerSlot(name, this);
}
}
forceUpdate() {
if (this.isUnmounted) {
return;
}
super.forceUpdate();
}
render() {
var _getFills;
const {
children,
name,
fillProps = {},
getFills
} = this.props;
const fills = ((_getFills = getFills(name, this)) !== null && _getFills !== void 0 ? _getFills : []).map(fill => {
const fillChildren = isFunction(fill.children) ? fill.children(fillProps) : fill.children;
return Children.map(fillChildren, (child, childIndex) => {
if (!child || typeof child === 'string') {
return child;
}
let childKey = childIndex;
if (typeof child === 'object' && 'key' in child && child?.key) {
childKey = child.key;
}
return cloneElement(child, {
key: childKey
});
});
}).filter(
// In some cases fills are rendered only when some conditions apply.
// This ensures that we only use non-empty fills when rendering, i.e.,
// it allows us to render wrappers only when the fills are actually present.
element => !isEmptyElement(element));
return createElement(Fragment, null, isFunction(children) ? children(fills) : fills);
}
}
const Slot = props => createElement(SlotFillContext.Consumer, null, ({
registerSlot,
unregisterSlot,
getFills
}) => createElement(SlotComponent, {
...props,
registerSlot: registerSlot,
unregisterSlot: unregisterSlot,
getFills: getFills
}));
export default Slot;
//# sourceMappingURL=slot.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/components/src/slot-fill/types.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { Component, MutableRefObject, ReactNode, RefObject } from 'react';\n\nexport type DistributiveOmit< T, K extends keyof any > = T extends any\n\t? Omit< T, K >\n\t: never;\n\nexport type SlotKey = string | symbol;\n\nexport type FillProps = Record< string, any >;\n\ntype SlotPropBase = {\n\t/**\n\t * Slot name.\n\t */\n\tname: SlotKey;\n\n\t/**\n\t * props to pass from `Slot` to `Fill`.\n\t *\n\t * @default {}\n\t */\n\tfillProps?: FillProps;\n};\n\nexport type SlotComponentProps =\n\t| ( SlotPropBase & {\n\t\t\t/**\n\t\t\t * By default, events will bubble to their parents on the DOM hierarchy (native event bubbling).\n\t\t\t * If set to true, events will bubble to their virtual parent in the React elements hierarchy instead,\n\t\t\t * also accept an optional `className`, `id`, etc. to add to the slot container.\n\t\t\t */\n\t\t\tbubblesVirtually: true;\n\n\t\t\t/**\n\t\t\t * A function that returns nodes to be rendered.\n\t\t\t * Supported only when `bubblesVirtually` is `false`.\n\t\t\t */\n\t\t\tchildren?: never;\n\n\t\t\t/**\n\t\t\t * Additional className for the `Slot` component.\n\t\t\t * Supported only when `bubblesVirtually` is `true`.\n\t\t\t */\n\t\t\tclassName?: string;\n\n\t\t\t/**\n\t\t\t * Additional styles for the `Slot` component.\n\t\t\t * Supported only when `bubblesVirtually` is `true`.\n\t\t\t */\n\t\t\tstyle?: React.CSSProperties;\n\t } )\n\t| ( SlotPropBase & {\n\t\t\t/**\n\t\t\t * By default, events will bubble to their parents on the DOM hierarchy (native event bubbling).\n\t\t\t * If set to true, events will bubble to their virtual parent in the React elements hierarchy instead,\n\t\t\t * also accept an optional `className`, `id`, etc. to add to the slot container.\n\t\t\t */\n\t\t\tbubblesVirtually?: false;\n\n\t\t\t/**\n\t\t\t * A function that returns nodes to be rendered.\n\t\t\t * Supported only when `bubblesVirtually` is `false`.\n\t\t\t */\n\t\t\tchildren?: ( fills: ReactNode ) => ReactNode;\n\n\t\t\t/**\n\t\t\t * Additional className for the `Slot` component.\n\t\t\t * Supported only when `bubblesVirtually` is `true`.\n\t\t\t */\n\t\t\tclassName?: never;\n\n\t\t\t/**\n\t\t\t * Additional styles for the `Slot` component.\n\t\t\t * Supported only when `bubblesVirtually` is `true`.\n\t\t\t */\n\t\t\tstyle?: never;\n\t } );\n\nexport type FillComponentProps = {\n\t/**\n\t * The name of the slot to fill into.\n\t */\n\tname: SlotKey;\n\n\t/**\n\t * Children elements or render function.\n\t */\n\tchildren?: ReactNode | ( ( fillProps: FillProps ) => ReactNode );\n};\n\nexport type SlotFillProviderProps = {\n\t/**\n\t * The children elements.\n\t */\n\tchildren: ReactNode;\n\n\t/**\n\t * Whether to pass slots to the parent provider if existent.\n\t */\n\tpassthrough?: boolean;\n};\n\nexport type SlotFillBubblesVirtuallySlotRef = RefObject< HTMLElement >;\nexport type SlotFillBubblesVirtuallyFillRef = MutableRefObject< {\n\trerender: () => void;\n} >;\n\nexport type SlotFillBubblesVirtuallyContext = {\n\tslots: Map<\n\t\tSlotKey,\n\t\t{\n\t\t\tref: SlotFillBubblesVirtuallySlotRef;\n\t\t\tfillProps: FillProps;\n\t\t}\n\t>;\n\tfills: Map< SlotKey, SlotFillBubblesVirtuallyFillRef[] >;\n\tregisterSlot: (\n\t\tname: SlotKey,\n\t\tref: SlotFillBubblesVirtuallySlotRef,\n\t\tfillProps: FillProps\n\t) => void;\n\tunregisterSlot: (\n\t\tname: SlotKey,\n\t\tref: SlotFillBubblesVirtuallySlotRef\n\t) => void;\n\tupdateSlot: ( name: SlotKey, fillProps: FillProps ) => void;\n\tregisterFill: (\n\t\tname: SlotKey,\n\t\tref: SlotFillBubblesVirtuallyFillRef\n\t) => void;\n\tunregisterFill: (\n\t\tname: SlotKey,\n\t\tref: SlotFillBubblesVirtuallyFillRef\n\t) => void;\n\n\t/**\n\t * This helps the provider know if it's using the default context value or not.\n\t */\n\tisDefault?: boolean;\n};\n\nexport type BaseSlotFillContext = {\n\tregisterSlot: (\n\t\tname: SlotKey,\n\t\tslot: Component< BaseSlotComponentProps >\n\t) => void;\n\tunregisterSlot: (\n\t\tname: SlotKey,\n\t\tslot: Component< BaseSlotComponentProps >\n\t) => void;\n\tregisterFill: ( name: SlotKey, instance: FillComponentProps ) => void;\n\tunregisterFill: ( name: SlotKey, instance: FillComponentProps ) => void;\n\tgetSlot: (\n\t\tname: SlotKey\n\t) => Component< BaseSlotComponentProps > | undefined;\n\tgetFills: (\n\t\tname: SlotKey,\n\t\tslotInstance: Component< BaseSlotComponentProps >\n\t) => FillComponentProps[];\n\tsubscribe: ( listener: () => void ) => () => void;\n};\n\nexport type BaseSlotComponentProps = Pick<\n\tBaseSlotFillContext,\n\t'registerSlot' | 'unregisterSlot' | 'getFills'\n> &\n\tOmit< SlotComponentProps, 'bubblesVirtually' > & {\n\t\tchildren?: ( fills: ReactNode ) => ReactNode;\n\t};\n"],"mappings":""}

View File

@@ -0,0 +1,24 @@
/**
* WordPress dependencies
*/
import { useContext, useSyncExternalStore } from '@wordpress/element';
/**
* Internal dependencies
*/
import SlotFillContext from './context';
/**
* React hook returning the active slot given a name.
*
* @param name Slot name.
* @return Slot object.
*/
const useSlot = name => {
const {
getSlot,
subscribe
} = useContext(SlotFillContext);
return useSyncExternalStore(subscribe, () => getSlot(name), () => getSlot(name));
};
export default useSlot;
//# sourceMappingURL=use-slot.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useContext","useSyncExternalStore","SlotFillContext","useSlot","name","getSlot","subscribe"],"sources":["@wordpress/components/src/slot-fill/use-slot.ts"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useContext, useSyncExternalStore } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport SlotFillContext from './context';\nimport type { SlotKey } from './types';\n\n/**\n * React hook returning the active slot given a name.\n *\n * @param name Slot name.\n * @return Slot object.\n */\nconst useSlot = ( name: SlotKey ) => {\n\tconst { getSlot, subscribe } = useContext( SlotFillContext );\n\treturn useSyncExternalStore(\n\t\tsubscribe,\n\t\t() => getSlot( name ),\n\t\t() => getSlot( name )\n\t);\n};\n\nexport default useSlot;\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,UAAU,EAAEC,oBAAoB,QAAQ,oBAAoB;;AAErE;AACA;AACA;AACA,OAAOC,eAAe,MAAM,WAAW;AAGvC;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,OAAO,GAAKC,IAAa,IAAM;EACpC,MAAM;IAAEC,OAAO;IAAEC;EAAU,CAAC,GAAGN,UAAU,CAAEE,eAAgB,CAAC;EAC5D,OAAOD,oBAAoB,CAC1BK,SAAS,EACT,MAAMD,OAAO,CAAED,IAAK,CAAC,EACrB,MAAMC,OAAO,CAAED,IAAK,CACrB,CAAC;AACF,CAAC;AAED,eAAeD,OAAO"}