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,115 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useState, useRef } from '@wordpress/element';
import { createHigherOrderComponent, useRefEffect, useMergeRefs } from '@wordpress/compose';
import { isKeyboardEvent } from '@wordpress/keycodes';
const defaultShortcuts = {
previous: [{
modifier: 'ctrlShift',
character: '`'
}, {
modifier: 'ctrlShift',
character: '~'
}, {
modifier: 'access',
character: 'p'
}],
next: [{
modifier: 'ctrl',
character: '`'
}, {
modifier: 'access',
character: 'n'
}]
};
export function useNavigateRegions(shortcuts = defaultShortcuts) {
const ref = useRef(null);
const [isFocusingRegions, setIsFocusingRegions] = useState(false);
function focusRegion(offset) {
var _ref$current$querySel;
const regions = Array.from((_ref$current$querySel = ref.current?.querySelectorAll('[role="region"][tabindex="-1"]')) !== null && _ref$current$querySel !== void 0 ? _ref$current$querySel : []);
if (!regions.length) {
return;
}
let nextRegion = regions[0];
// Based off the current element, use closest to determine the wrapping region since this operates up the DOM. Also, match tabindex to avoid edge cases with regions we do not want.
const wrappingRegion = ref.current?.ownerDocument?.activeElement?.closest('[role="region"][tabindex="-1"]');
const selectedIndex = wrappingRegion ? regions.indexOf(wrappingRegion) : -1;
if (selectedIndex !== -1) {
let nextIndex = selectedIndex + offset;
nextIndex = nextIndex === -1 ? regions.length - 1 : nextIndex;
nextIndex = nextIndex === regions.length ? 0 : nextIndex;
nextRegion = regions[nextIndex];
}
nextRegion.focus();
setIsFocusingRegions(true);
}
const clickRef = useRefEffect(element => {
function onClick() {
setIsFocusingRegions(false);
}
element.addEventListener('click', onClick);
return () => {
element.removeEventListener('click', onClick);
};
}, [setIsFocusingRegions]);
return {
ref: useMergeRefs([ref, clickRef]),
className: isFocusingRegions ? 'is-focusing-regions' : '',
onKeyDown(event) {
if (shortcuts.previous.some(({
modifier,
character
}) => {
return isKeyboardEvent[modifier](event, character);
})) {
focusRegion(-1);
} else if (shortcuts.next.some(({
modifier,
character
}) => {
return isKeyboardEvent[modifier](event, character);
})) {
focusRegion(1);
}
}
};
}
/**
* `navigateRegions` is a React [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html)
* adding keyboard navigation to switch between the different DOM elements marked as "regions" (role="region").
* These regions should be focusable (By adding a tabIndex attribute for example). For better accessibility,
* these elements must be properly labelled to briefly describe the purpose of the content in the region.
* For more details, see "Landmark Roles" in the [WAI-ARIA specification](https://www.w3.org/TR/wai-aria/)
* and "Landmark Regions" in the [ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/).
*
* ```jsx
* import { navigateRegions } from '@wordpress/components';
*
* const MyComponentWithNavigateRegions = navigateRegions( () => (
* <div>
* <div role="region" tabIndex="-1" aria-label="Header">
* Header
* </div>
* <div role="region" tabIndex="-1" aria-label="Content">
* Content
* </div>
* <div role="region" tabIndex="-1" aria-label="Sidebar">
* Sidebar
* </div>
* </div>
* ) );
* ```
*/
export default createHigherOrderComponent(Component => ({
shortcuts,
...props
}) => createElement("div", {
...useNavigateRegions(shortcuts)
}, createElement(Component, {
...props
})), 'navigateRegions');
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { createHigherOrderComponent, useConstrainedTabbing } from '@wordpress/compose';
/**
* `withConstrainedTabbing` is a React [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html)
* adding the ability to constrain keyboard navigation with the Tab key within a component.
* For accessibility reasons, some UI components need to constrain Tab navigation, for example
* modal dialogs or similar UI. Use of this component is recommended only in cases where a way to
* navigate away from the wrapped component is implemented by other means, usually by pressing
* the Escape key or using a specific UI control, e.g. a "Close" button.
*/
const withConstrainedTabbing = createHigherOrderComponent(WrappedComponent => function ComponentWithConstrainedTabbing(props) {
const ref = useConstrainedTabbing();
return createElement("div", {
ref: ref,
tabIndex: -1
}, createElement(WrappedComponent, {
...props
}));
}, 'withConstrainedTabbing');
export default withConstrainedTabbing;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["createHigherOrderComponent","useConstrainedTabbing","withConstrainedTabbing","WrappedComponent","ComponentWithConstrainedTabbing","props","ref","createElement","tabIndex"],"sources":["@wordpress/components/src/higher-order/with-constrained-tabbing/index.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport {\n\tcreateHigherOrderComponent,\n\tuseConstrainedTabbing,\n} from '@wordpress/compose';\n\n/**\n * `withConstrainedTabbing` is a React [higher-order component](https://facebook.github.io/react/docs/higher-order-components.html)\n * adding the ability to constrain keyboard navigation with the Tab key within a component.\n * For accessibility reasons, some UI components need to constrain Tab navigation, for example\n * modal dialogs or similar UI. Use of this component is recommended only in cases where a way to\n * navigate away from the wrapped component is implemented by other means, usually by pressing\n * the Escape key or using a specific UI control, e.g. a \"Close\" button.\n */\nconst withConstrainedTabbing = createHigherOrderComponent(\n\t( WrappedComponent ) =>\n\t\tfunction ComponentWithConstrainedTabbing( props ) {\n\t\t\tconst ref = useConstrainedTabbing();\n\t\t\treturn (\n\t\t\t\t<div ref={ ref } tabIndex={ -1 }>\n\t\t\t\t\t<WrappedComponent { ...props } />\n\t\t\t\t</div>\n\t\t\t);\n\t\t},\n\t'withConstrainedTabbing'\n);\n\nexport default withConstrainedTabbing;\n"],"mappings":";AAAA;AACA;AACA;AACA,SACCA,0BAA0B,EAC1BC,qBAAqB,QACf,oBAAoB;;AAE3B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,sBAAsB,GAAGF,0BAA0B,CACtDG,gBAAgB,IACjB,SAASC,+BAA+BA,CAAEC,KAAK,EAAG;EACjD,MAAMC,GAAG,GAAGL,qBAAqB,CAAC,CAAC;EACnC,OACCM,aAAA;IAAKD,GAAG,EAAGA,GAAK;IAACE,QAAQ,EAAG,CAAC;EAAG,GAC/BD,aAAA,CAACJ,gBAAgB;IAAA,GAAME;EAAK,CAAI,CAC5B,CAAC;AAER,CAAC,EACF,wBACD,CAAC;AAED,eAAeH,sBAAsB"}

View File

@@ -0,0 +1,61 @@
import { createElement } from "react";
/**
* External dependencies
*/
import fastDeepEqual from 'fast-deep-equal/es6';
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';
export default (mapNodeToProps => createHigherOrderComponent(WrappedComponent => {
return class extends Component {
constructor(props) {
super(props);
this.nodeRef = this.props.node;
this.state = {
fallbackStyles: undefined,
grabStylesCompleted: false
};
this.bindRef = this.bindRef.bind(this);
}
bindRef(node) {
if (!node) {
return;
}
this.nodeRef = node;
}
componentDidMount() {
this.grabFallbackStyles();
}
componentDidUpdate() {
this.grabFallbackStyles();
}
grabFallbackStyles() {
const {
grabStylesCompleted,
fallbackStyles
} = this.state;
if (this.nodeRef && !grabStylesCompleted) {
const newFallbackStyles = mapNodeToProps(this.nodeRef, this.props);
if (!fastDeepEqual(newFallbackStyles, fallbackStyles)) {
this.setState({
fallbackStyles: newFallbackStyles,
grabStylesCompleted: Object.values(newFallbackStyles).every(Boolean)
});
}
}
}
render() {
const wrappedComponent = createElement(WrappedComponent, {
...this.props,
...this.state.fallbackStyles
});
return this.props.node ? wrappedComponent : createElement("div", {
ref: this.bindRef
}, " ", wrappedComponent, " ");
}
};
}, 'withFallbackStyles'));
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["fastDeepEqual","Component","createHigherOrderComponent","mapNodeToProps","WrappedComponent","constructor","props","nodeRef","node","state","fallbackStyles","undefined","grabStylesCompleted","bindRef","bind","componentDidMount","grabFallbackStyles","componentDidUpdate","newFallbackStyles","setState","Object","values","every","Boolean","render","wrappedComponent","createElement","ref"],"sources":["@wordpress/components/src/higher-order/with-fallback-styles/index.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport fastDeepEqual from 'fast-deep-equal/es6';\n\n/**\n * WordPress dependencies\n */\nimport { Component } from '@wordpress/element';\nimport { createHigherOrderComponent } from '@wordpress/compose';\n\ntype Props = {\n\tnode?: HTMLElement;\n\t[ key: string ]: any;\n};\n\ntype State = {\n\tfallbackStyles?: { [ key: string ]: any };\n\tgrabStylesCompleted: boolean;\n};\n\nexport default (\n\tmapNodeToProps: (\n\t\tnode: HTMLElement,\n\t\tprops: Props\n\t) => { [ key: string ]: any }\n) =>\n\tcreateHigherOrderComponent( ( WrappedComponent ) => {\n\t\treturn class extends Component< Props, State > {\n\t\t\tnodeRef?: HTMLElement;\n\n\t\t\tconstructor( props: Props ) {\n\t\t\t\tsuper( props );\n\t\t\t\tthis.nodeRef = this.props.node;\n\t\t\t\tthis.state = {\n\t\t\t\t\tfallbackStyles: undefined,\n\t\t\t\t\tgrabStylesCompleted: false,\n\t\t\t\t};\n\n\t\t\t\tthis.bindRef = this.bindRef.bind( this );\n\t\t\t}\n\n\t\t\tbindRef( node: HTMLDivElement ) {\n\t\t\t\tif ( ! node ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis.nodeRef = node;\n\t\t\t}\n\n\t\t\tcomponentDidMount() {\n\t\t\t\tthis.grabFallbackStyles();\n\t\t\t}\n\n\t\t\tcomponentDidUpdate() {\n\t\t\t\tthis.grabFallbackStyles();\n\t\t\t}\n\n\t\t\tgrabFallbackStyles() {\n\t\t\t\tconst { grabStylesCompleted, fallbackStyles } = this.state;\n\t\t\t\tif ( this.nodeRef && ! grabStylesCompleted ) {\n\t\t\t\t\tconst newFallbackStyles = mapNodeToProps(\n\t\t\t\t\t\tthis.nodeRef,\n\t\t\t\t\t\tthis.props\n\t\t\t\t\t);\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t! fastDeepEqual( newFallbackStyles, fallbackStyles )\n\t\t\t\t\t) {\n\t\t\t\t\t\tthis.setState( {\n\t\t\t\t\t\t\tfallbackStyles: newFallbackStyles,\n\t\t\t\t\t\t\tgrabStylesCompleted:\n\t\t\t\t\t\t\t\tObject.values( newFallbackStyles ).every(\n\t\t\t\t\t\t\t\t\tBoolean\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\trender() {\n\t\t\t\tconst wrappedComponent = (\n\t\t\t\t\t<WrappedComponent\n\t\t\t\t\t\t{ ...this.props }\n\t\t\t\t\t\t{ ...this.state.fallbackStyles }\n\t\t\t\t\t/>\n\t\t\t\t);\n\t\t\t\treturn this.props.node ? (\n\t\t\t\t\twrappedComponent\n\t\t\t\t) : (\n\t\t\t\t\t<div ref={ this.bindRef }> { wrappedComponent } </div>\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}, 'withFallbackStyles' );\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,aAAa,MAAM,qBAAqB;;AAE/C;AACA;AACA;AACA,SAASC,SAAS,QAAQ,oBAAoB;AAC9C,SAASC,0BAA0B,QAAQ,oBAAoB;AAY/D,gBACCC,cAG6B,IAE7BD,0BAA0B,CAAIE,gBAAgB,IAAM;EACnD,OAAO,cAAcH,SAAS,CAAiB;IAG9CI,WAAWA,CAAEC,KAAY,EAAG;MAC3B,KAAK,CAAEA,KAAM,CAAC;MACd,IAAI,CAACC,OAAO,GAAG,IAAI,CAACD,KAAK,CAACE,IAAI;MAC9B,IAAI,CAACC,KAAK,GAAG;QACZC,cAAc,EAAEC,SAAS;QACzBC,mBAAmB,EAAE;MACtB,CAAC;MAED,IAAI,CAACC,OAAO,GAAG,IAAI,CAACA,OAAO,CAACC,IAAI,CAAE,IAAK,CAAC;IACzC;IAEAD,OAAOA,CAAEL,IAAoB,EAAG;MAC/B,IAAK,CAAEA,IAAI,EAAG;QACb;MACD;MACA,IAAI,CAACD,OAAO,GAAGC,IAAI;IACpB;IAEAO,iBAAiBA,CAAA,EAAG;MACnB,IAAI,CAACC,kBAAkB,CAAC,CAAC;IAC1B;IAEAC,kBAAkBA,CAAA,EAAG;MACpB,IAAI,CAACD,kBAAkB,CAAC,CAAC;IAC1B;IAEAA,kBAAkBA,CAAA,EAAG;MACpB,MAAM;QAAEJ,mBAAmB;QAAEF;MAAe,CAAC,GAAG,IAAI,CAACD,KAAK;MAC1D,IAAK,IAAI,CAACF,OAAO,IAAI,CAAEK,mBAAmB,EAAG;QAC5C,MAAMM,iBAAiB,GAAGf,cAAc,CACvC,IAAI,CAACI,OAAO,EACZ,IAAI,CAACD,KACN,CAAC;QAED,IACC,CAAEN,aAAa,CAAEkB,iBAAiB,EAAER,cAAe,CAAC,EACnD;UACD,IAAI,CAACS,QAAQ,CAAE;YACdT,cAAc,EAAEQ,iBAAiB;YACjCN,mBAAmB,EAClBQ,MAAM,CAACC,MAAM,CAAEH,iBAAkB,CAAC,CAACI,KAAK,CACvCC,OACD;UACF,CAAE,CAAC;QACJ;MACD;IACD;IAEAC,MAAMA,CAAA,EAAG;MACR,MAAMC,gBAAgB,GACrBC,aAAA,CAACtB,gBAAgB;QAAA,GACX,IAAI,CAACE,KAAK;QAAA,GACV,IAAI,CAACG,KAAK,CAACC;MAAc,CAC9B,CACD;MACD,OAAO,IAAI,CAACJ,KAAK,CAACE,IAAI,GACrBiB,gBAAgB,GAEhBC,aAAA;QAAKC,GAAG,EAAG,IAAI,CAACd;MAAS,GAAC,GAAC,EAAEY,gBAAgB,EAAE,GAAM,CACrD;IACF;EACD,CAAC;AACF,CAAC,EAAE,oBAAqB,CAAC"}

View File

@@ -0,0 +1,129 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { addAction, applyFilters, removeAction } from '@wordpress/hooks';
import { createHigherOrderComponent, debounce } from '@wordpress/compose';
const ANIMATION_FRAME_PERIOD = 16;
/**
* Creates a higher-order component which adds filtering capability to the
* wrapped component. Filters get applied when the original component is about
* to be mounted. When a filter is added or removed that matches the hook name,
* the wrapped component re-renders.
*
* @param hookName Hook name exposed to be used by filters.
*
* @return Higher-order component factory.
*
* ```jsx
* import { withFilters } from '@wordpress/components';
* import { addFilter } from '@wordpress/hooks';
*
* const MyComponent = ( { title } ) => <h1>{ title }</h1>;
*
* const ComponentToAppend = () => <div>Appended component</div>;
*
* function withComponentAppended( FilteredComponent ) {
* return ( props ) => (
* <>
* <FilteredComponent { ...props } />
* <ComponentToAppend />
* </>
* );
* }
*
* addFilter(
* 'MyHookName',
* 'my-plugin/with-component-appended',
* withComponentAppended
* );
*
* const MyComponentWithFilters = withFilters( 'MyHookName' )( MyComponent );
* ```
*/
export default function withFilters(hookName) {
return createHigherOrderComponent(OriginalComponent => {
const namespace = 'core/with-filters/' + hookName;
/**
* The component definition with current filters applied. Each instance
* reuse this shared reference as an optimization to avoid excessive
* calls to `applyFilters` when many instances exist.
*/
let FilteredComponent;
/**
* Initializes the FilteredComponent variable once, if not already
* assigned. Subsequent calls are effectively a noop.
*/
function ensureFilteredComponent() {
if (FilteredComponent === undefined) {
FilteredComponent = applyFilters(hookName, OriginalComponent);
}
}
class FilteredComponentRenderer extends Component {
constructor(props) {
super(props);
ensureFilteredComponent();
}
componentDidMount() {
FilteredComponentRenderer.instances.push(this);
// If there were previously no mounted instances for components
// filtered on this hook, add the hook handler.
if (FilteredComponentRenderer.instances.length === 1) {
addAction('hookRemoved', namespace, onHooksUpdated);
addAction('hookAdded', namespace, onHooksUpdated);
}
}
componentWillUnmount() {
FilteredComponentRenderer.instances = FilteredComponentRenderer.instances.filter(instance => instance !== this);
// If this was the last of the mounted components filtered on
// this hook, remove the hook handler.
if (FilteredComponentRenderer.instances.length === 0) {
removeAction('hookRemoved', namespace);
removeAction('hookAdded', namespace);
}
}
render() {
return createElement(FilteredComponent, {
...this.props
});
}
}
FilteredComponentRenderer.instances = [];
/**
* Updates the FilteredComponent definition, forcing a render for each
* mounted instance. This occurs a maximum of once per animation frame.
*/
const throttledForceUpdate = debounce(() => {
// Recreate the filtered component, only after delay so that it's
// computed once, even if many filters added.
FilteredComponent = applyFilters(hookName, OriginalComponent);
// Force each instance to render.
FilteredComponentRenderer.instances.forEach(instance => {
instance.forceUpdate();
});
}, ANIMATION_FRAME_PERIOD);
/**
* When a filter is added or removed for the matching hook name, each
* mounted instance should re-render with the new filters having been
* applied to the original component.
*
* @param updatedHookName Name of the hook that was updated.
*/
function onHooksUpdated(updatedHookName) {
if (updatedHookName === hookName) {
throttledForceUpdate();
}
}
return FilteredComponentRenderer;
}, 'withFilters');
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useCallback, useState } from '@wordpress/element';
import { createHigherOrderComponent, __experimentalUseFocusOutside as useFocusOutside } from '@wordpress/compose';
export default createHigherOrderComponent(WrappedComponent => props => {
const [handleFocusOutside, setHandleFocusOutside] = useState(undefined);
const bindFocusOutsideHandler = useCallback(node => setHandleFocusOutside(() => node?.handleFocusOutside ? node.handleFocusOutside.bind(node) : undefined), []);
return createElement("div", {
...useFocusOutside(handleFocusOutside)
}, createElement(WrappedComponent, {
ref: bindFocusOutsideHandler,
...props
}));
}, 'withFocusOutside');
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useCallback","useState","createHigherOrderComponent","__experimentalUseFocusOutside","useFocusOutside","WrappedComponent","props","handleFocusOutside","setHandleFocusOutside","undefined","bindFocusOutsideHandler","node","bind","createElement","ref"],"sources":["@wordpress/components/src/higher-order/with-focus-outside/index.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useCallback, useState } from '@wordpress/element';\nimport {\n\tcreateHigherOrderComponent,\n\t__experimentalUseFocusOutside as useFocusOutside,\n} from '@wordpress/compose';\n\nexport default createHigherOrderComponent(\n\t( WrappedComponent ) => ( props ) => {\n\t\tconst [ handleFocusOutside, setHandleFocusOutside ] = useState<\n\t\t\tundefined | ( ( event: React.FocusEvent ) => void )\n\t\t>( undefined );\n\n\t\tconst bindFocusOutsideHandler = useCallback<\n\t\t\t( node: React.FocusEvent ) => void\n\t\t>(\n\t\t\t( node: any ) =>\n\t\t\t\tsetHandleFocusOutside( () =>\n\t\t\t\t\tnode?.handleFocusOutside\n\t\t\t\t\t\t? node.handleFocusOutside.bind( node )\n\t\t\t\t\t\t: undefined\n\t\t\t\t),\n\t\t\t[]\n\t\t);\n\n\t\treturn (\n\t\t\t<div { ...useFocusOutside( handleFocusOutside ) }>\n\t\t\t\t<WrappedComponent\n\t\t\t\t\tref={ bindFocusOutsideHandler }\n\t\t\t\t\t{ ...props }\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t},\n\t'withFocusOutside'\n);\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,WAAW,EAAEC,QAAQ,QAAQ,oBAAoB;AAC1D,SACCC,0BAA0B,EAC1BC,6BAA6B,IAAIC,eAAe,QAC1C,oBAAoB;AAE3B,eAAeF,0BAA0B,CACtCG,gBAAgB,IAAQC,KAAK,IAAM;EACpC,MAAM,CAAEC,kBAAkB,EAAEC,qBAAqB,CAAE,GAAGP,QAAQ,CAE3DQ,SAAU,CAAC;EAEd,MAAMC,uBAAuB,GAAGV,WAAW,CAGxCW,IAAS,IACVH,qBAAqB,CAAE,MACtBG,IAAI,EAAEJ,kBAAkB,GACrBI,IAAI,CAACJ,kBAAkB,CAACK,IAAI,CAAED,IAAK,CAAC,GACpCF,SACJ,CAAC,EACF,EACD,CAAC;EAED,OACCI,aAAA;IAAA,GAAUT,eAAe,CAAEG,kBAAmB;EAAC,GAC9CM,aAAA,CAACR,gBAAgB;IAChBS,GAAG,EAAGJ,uBAAyB;IAAA,GAC1BJ;EAAK,CACV,CACG,CAAC;AAER,CAAC,EACD,kBACD,CAAC"}

View File

@@ -0,0 +1,21 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { View } from 'react-native';
/**
* WordPress dependencies
*/
import { useCallback, useState } from '@wordpress/element';
import { createHigherOrderComponent, __experimentalUseFocusOutside as useFocusOutside } from '@wordpress/compose';
export default createHigherOrderComponent(WrappedComponent => props => {
const [handleFocusOutside, setHandleFocusOutside] = useState();
const bindFocusOutsideHandler = useCallback(node => setHandleFocusOutside(() => node?.handleFocusOutside ? node.handleFocusOutside.bind(node) : undefined), []);
return createElement(View, {
...useFocusOutside(handleFocusOutside)
}, createElement(WrappedComponent, {
ref: bindFocusOutsideHandler,
...props
}));
}, 'withFocusOutside');
//# sourceMappingURL=index.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["View","useCallback","useState","createHigherOrderComponent","__experimentalUseFocusOutside","useFocusOutside","WrappedComponent","props","handleFocusOutside","setHandleFocusOutside","bindFocusOutsideHandler","node","bind","undefined","createElement","ref"],"sources":["@wordpress/components/src/higher-order/with-focus-outside/index.native.js"],"sourcesContent":["/**\n * External dependencies\n */\nimport { View } from 'react-native';\n/**\n * WordPress dependencies\n */\nimport { useCallback, useState } from '@wordpress/element';\nimport {\n\tcreateHigherOrderComponent,\n\t__experimentalUseFocusOutside as useFocusOutside,\n} from '@wordpress/compose';\n\nexport default createHigherOrderComponent(\n\t( WrappedComponent ) => ( props ) => {\n\t\tconst [ handleFocusOutside, setHandleFocusOutside ] = useState();\n\t\tconst bindFocusOutsideHandler = useCallback(\n\t\t\t( node ) =>\n\t\t\t\tsetHandleFocusOutside( () =>\n\t\t\t\t\tnode?.handleFocusOutside\n\t\t\t\t\t\t? node.handleFocusOutside.bind( node )\n\t\t\t\t\t\t: undefined\n\t\t\t\t),\n\t\t\t[]\n\t\t);\n\n\t\treturn (\n\t\t\t<View { ...useFocusOutside( handleFocusOutside ) }>\n\t\t\t\t<WrappedComponent\n\t\t\t\t\tref={ bindFocusOutsideHandler }\n\t\t\t\t\t{ ...props }\n\t\t\t\t/>\n\t\t\t</View>\n\t\t);\n\t},\n\t'withFocusOutside'\n);\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,IAAI,QAAQ,cAAc;AACnC;AACA;AACA;AACA,SAASC,WAAW,EAAEC,QAAQ,QAAQ,oBAAoB;AAC1D,SACCC,0BAA0B,EAC1BC,6BAA6B,IAAIC,eAAe,QAC1C,oBAAoB;AAE3B,eAAeF,0BAA0B,CACtCG,gBAAgB,IAAQC,KAAK,IAAM;EACpC,MAAM,CAAEC,kBAAkB,EAAEC,qBAAqB,CAAE,GAAGP,QAAQ,CAAC,CAAC;EAChE,MAAMQ,uBAAuB,GAAGT,WAAW,CACxCU,IAAI,IACLF,qBAAqB,CAAE,MACtBE,IAAI,EAAEH,kBAAkB,GACrBG,IAAI,CAACH,kBAAkB,CAACI,IAAI,CAAED,IAAK,CAAC,GACpCE,SACJ,CAAC,EACF,EACD,CAAC;EAED,OACCC,aAAA,CAACd,IAAI;IAAA,GAAMK,eAAe,CAAEG,kBAAmB;EAAC,GAC/CM,aAAA,CAACR,gBAAgB;IAChBS,GAAG,EAAGL,uBAAyB;IAAA,GAC1BH;EAAK,CACV,CACI,CAAC;AAET,CAAC,EACD,kBACD,CAAC"}

View File

@@ -0,0 +1,64 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';
import { createHigherOrderComponent, useFocusReturn } from '@wordpress/compose';
import deprecated from '@wordpress/deprecated';
/**
* Returns true if the given object is component-like. An object is component-
* like if it is an instance of wp.element.Component, or is a function.
*
* @param object Object to test.
*
* @return Whether object is component-like.
*/
function isComponentLike(object) {
return object instanceof Component || typeof object === 'function';
}
/**
* Higher Order Component used to be used to wrap disposable elements like
* sidebars, modals, dropdowns. When mounting the wrapped component, we track a
* reference to the current active element so we know where to restore focus
* when the component is unmounted.
*
* @param options The component to be enhanced with
* focus return behavior, or an object
* describing the component and the
* focus return characteristics.
*
* @return Higher Order Component with the focus restauration behaviour.
*/
export default createHigherOrderComponent(
// @ts-expect-error TODO: Reconcile with intended `createHigherOrderComponent` types
options => {
const HoC = ({
onFocusReturn
} = {}) => WrappedComponent => {
const WithFocusReturn = props => {
const ref = useFocusReturn(onFocusReturn);
return createElement("div", {
ref: ref
}, createElement(WrappedComponent, {
...props
}));
};
return WithFocusReturn;
};
if (isComponentLike(options)) {
const WrappedComponent = options;
return HoC()(WrappedComponent);
}
return HoC(options);
}, 'withFocusReturn');
export const Provider = ({
children
}) => {
deprecated('wp.components.FocusReturnProvider component', {
since: '5.7',
hint: 'This provider is not used anymore. You can just remove it from your codebase'
});
return children;
};
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["Component","createHigherOrderComponent","useFocusReturn","deprecated","isComponentLike","object","options","HoC","onFocusReturn","WrappedComponent","WithFocusReturn","props","ref","createElement","Provider","children","since","hint"],"sources":["@wordpress/components/src/higher-order/with-focus-return/index.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { Component } from '@wordpress/element';\nimport { createHigherOrderComponent, useFocusReturn } from '@wordpress/compose';\nimport deprecated from '@wordpress/deprecated';\n\n/**\n * Returns true if the given object is component-like. An object is component-\n * like if it is an instance of wp.element.Component, or is a function.\n *\n * @param object Object to test.\n *\n * @return Whether object is component-like.\n */\nfunction isComponentLike( object: any ): object is React.ComponentType {\n\treturn object instanceof Component || typeof object === 'function';\n}\n\ntype Props = {\n\tonFocusReturn?: () => void;\n};\n\n/**\n * Higher Order Component used to be used to wrap disposable elements like\n * sidebars, modals, dropdowns. When mounting the wrapped component, we track a\n * reference to the current active element so we know where to restore focus\n * when the component is unmounted.\n *\n * @param options The component to be enhanced with\n * focus return behavior, or an object\n * describing the component and the\n * focus return characteristics.\n *\n * @return Higher Order Component with the focus restauration behaviour.\n */\nexport default createHigherOrderComponent(\n\t// @ts-expect-error TODO: Reconcile with intended `createHigherOrderComponent` types\n\t( options: React.ComponentType | Record< string, unknown > ) => {\n\t\tconst HoC =\n\t\t\t( { onFocusReturn }: Props = {} ) =>\n\t\t\t( WrappedComponent: React.ComponentType ) => {\n\t\t\t\tconst WithFocusReturn = (\n\t\t\t\t\tprops: Record< string, unknown >\n\t\t\t\t) => {\n\t\t\t\t\tconst ref = useFocusReturn( onFocusReturn );\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<div ref={ ref }>\n\t\t\t\t\t\t\t<WrappedComponent { ...props } />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\treturn WithFocusReturn;\n\t\t\t};\n\n\t\tif ( isComponentLike( options ) ) {\n\t\t\tconst WrappedComponent = options;\n\t\t\treturn HoC()( WrappedComponent );\n\t\t}\n\n\t\treturn HoC( options );\n\t},\n\t'withFocusReturn'\n);\n\nexport const Provider = ( { children }: { children: React.ReactNode } ) => {\n\tdeprecated( 'wp.components.FocusReturnProvider component', {\n\t\tsince: '5.7',\n\t\thint: 'This provider is not used anymore. You can just remove it from your codebase',\n\t} );\n\n\treturn children;\n};\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,SAAS,QAAQ,oBAAoB;AAC9C,SAASC,0BAA0B,EAAEC,cAAc,QAAQ,oBAAoB;AAC/E,OAAOC,UAAU,MAAM,uBAAuB;;AAE9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASC,eAAeA,CAAEC,MAAW,EAAkC;EACtE,OAAOA,MAAM,YAAYL,SAAS,IAAI,OAAOK,MAAM,KAAK,UAAU;AACnE;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeJ,0BAA0B;AACxC;AACEK,OAAwD,IAAM;EAC/D,MAAMC,GAAG,GACRA,CAAE;IAAEC;EAAqB,CAAC,GAAG,CAAC,CAAC,KAC7BC,gBAAqC,IAAM;IAC5C,MAAMC,eAAe,GACpBC,KAAgC,IAC5B;MACJ,MAAMC,GAAG,GAAGV,cAAc,CAAEM,aAAc,CAAC;MAC3C,OACCK,aAAA;QAAKD,GAAG,EAAGA;MAAK,GACfC,aAAA,CAACJ,gBAAgB;QAAA,GAAME;MAAK,CAAI,CAC5B,CAAC;IAER,CAAC;IAED,OAAOD,eAAe;EACvB,CAAC;EAEF,IAAKN,eAAe,CAAEE,OAAQ,CAAC,EAAG;IACjC,MAAMG,gBAAgB,GAAGH,OAAO;IAChC,OAAOC,GAAG,CAAC,CAAC,CAAEE,gBAAiB,CAAC;EACjC;EAEA,OAAOF,GAAG,CAAED,OAAQ,CAAC;AACtB,CAAC,EACD,iBACD,CAAC;AAED,OAAO,MAAMQ,QAAQ,GAAGA,CAAE;EAAEC;AAAwC,CAAC,KAAM;EAC1EZ,UAAU,CAAE,6CAA6C,EAAE;IAC1Da,KAAK,EAAE,KAAK;IACZC,IAAI,EAAE;EACP,CAAE,CAAC;EAEH,OAAOF,QAAQ;AAChB,CAAC"}

View File

@@ -0,0 +1,103 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { v4 as uuid } from 'uuid';
/**
* WordPress dependencies
*/
import { forwardRef, useState, useMemo } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';
/**
* Internal dependencies
*/
import NoticeList from '../../notice/list';
/**
* Override the default edit UI to include notices if supported.
*
* Wrapping the original component with `withNotices` encapsulates the component
* with the additional props `noticeOperations` and `noticeUI`.
*
* ```jsx
* import { withNotices, Button } from '@wordpress/components';
*
* const MyComponentWithNotices = withNotices(
* ( { noticeOperations, noticeUI } ) => {
* const addError = () =>
* noticeOperations.createErrorNotice( 'Error message' );
* return (
* <div>
* { noticeUI }
* <Button variant="secondary" onClick={ addError }>
* Add error
* </Button>
* </div>
* );
* }
* );
* ```
*
* @param OriginalComponent Original component.
*
* @return Wrapped component.
*/
export default createHigherOrderComponent(OriginalComponent => {
function Component(props, ref) {
const [noticeList, setNoticeList] = useState([]);
const noticeOperations = useMemo(() => {
const createNotice = notice => {
const noticeToAdd = notice.id ? notice : {
...notice,
id: uuid()
};
setNoticeList(current => [...current, noticeToAdd]);
};
return {
createNotice,
createErrorNotice: msg => {
// @ts-expect-error TODO: Missing `id`, potentially a bug
createNotice({
status: 'error',
content: msg
});
},
removeNotice: id => {
setNoticeList(current => current.filter(notice => notice.id !== id));
},
removeAllNotices: () => {
setNoticeList([]);
}
};
}, []);
const propsOut = {
...props,
noticeList,
noticeOperations,
noticeUI: noticeList.length > 0 && createElement(NoticeList, {
className: "components-with-notices-ui",
notices: noticeList,
onRemove: noticeOperations.removeNotice
})
};
return isForwardRef ? createElement(OriginalComponent, {
...propsOut,
ref: ref
}) : createElement(OriginalComponent, {
...propsOut
});
}
let isForwardRef;
// @ts-expect-error - `render` will only be present when OriginalComponent was wrapped with forwardRef().
const {
render
} = OriginalComponent;
// Returns a forwardRef if OriginalComponent appears to be a forwardRef.
if (typeof render === 'function') {
isForwardRef = true;
return forwardRef(Component);
}
return Component;
}, 'withNotices');
//# sourceMappingURL=index.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/higher-order/with-notices/types.ts"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport type { NoticeListProps } from '../../notice/types';\n\nexport type WithNoticeProps = {\n\tnoticeList: NoticeListProps[ 'notices' ];\n\tnoticeOperations: {\n\t\t/**\n\t\t * Function passed down as a prop that adds a new notice.\n\t\t *\n\t\t * @param notice Notice to add.\n\t\t */\n\t\tcreateNotice: (\n\t\t\tnotice: NoticeListProps[ 'notices' ][ number ]\n\t\t) => void;\n\t\t/**\n\t\t * Function passed as a prop that adds a new error notice.\n\t\t *\n\t\t * @param msg Error message of the notice.\n\t\t */\n\t\tcreateErrorNotice: ( msg: string ) => void;\n\t\t/**\n\t\t * Removes a notice by id.\n\t\t *\n\t\t * @param id Id of the notice to remove.\n\t\t */\n\t\tremoveNotice: ( id: string ) => void;\n\t\t/**\n\t\t * Removes all notices\n\t\t */\n\t\tremoveAllNotices: () => void;\n\t};\n\tnoticeUI: false | JSX.Element;\n};\n"],"mappings":""}

View File

@@ -0,0 +1,25 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { createHigherOrderComponent, useDebounce } from '@wordpress/compose';
import { speak } from '@wordpress/a11y';
/** @typedef {import('react').ComponentType} ComponentType */
/**
* A Higher Order Component used to be provide speak and debounced speak
* functions.
*
* @see https://developer.wordpress.org/block-editor/packages/packages-a11y/#speak
*
* @param {ComponentType} Component The component to be wrapped.
*
* @return {ComponentType} The wrapped component.
*/
export default createHigherOrderComponent(Component => props => createElement(Component, {
...props,
speak: speak,
debouncedSpeak: useDebounce(speak, 500)
}), 'withSpokenMessages');
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["createHigherOrderComponent","useDebounce","speak","Component","props","createElement","debouncedSpeak"],"sources":["@wordpress/components/src/higher-order/with-spoken-messages/index.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createHigherOrderComponent, useDebounce } from '@wordpress/compose';\nimport { speak } from '@wordpress/a11y';\n\n/** @typedef {import('react').ComponentType} ComponentType */\n\n/**\n * A Higher Order Component used to be provide speak and debounced speak\n * functions.\n *\n * @see https://developer.wordpress.org/block-editor/packages/packages-a11y/#speak\n *\n * @param {ComponentType} Component The component to be wrapped.\n *\n * @return {ComponentType} The wrapped component.\n */\nexport default createHigherOrderComponent(\n\t( Component ) => ( props ) => (\n\t\t<Component\n\t\t\t{ ...props }\n\t\t\tspeak={ speak }\n\t\t\tdebouncedSpeak={ useDebounce( speak, 500 ) }\n\t\t/>\n\t),\n\t'withSpokenMessages'\n);\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,0BAA0B,EAAEC,WAAW,QAAQ,oBAAoB;AAC5E,SAASC,KAAK,QAAQ,iBAAiB;;AAEvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeF,0BAA0B,CACtCG,SAAS,IAAQC,KAAK,IACvBC,aAAA,CAACF,SAAS;EAAA,GACJC,KAAK;EACVF,KAAK,EAAGA,KAAO;EACfI,cAAc,EAAGL,WAAW,CAAEC,KAAK,EAAE,GAAI;AAAG,CAC5C,CACD,EACD,oBACD,CAAC"}