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,98 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import ToolbarButton from '../toolbar-button';
import ToolbarGroupContainer from './toolbar-group-container';
import ToolbarGroupCollapsed from './toolbar-group-collapsed';
import ToolbarContext from '../toolbar-context';
function isNestedArray(arr) {
return Array.isArray(arr) && Array.isArray(arr[0]);
}
/**
* Renders a collapsible group of controls
*
* The `controls` prop accepts an array of sets. A set is an array of controls.
* Controls have the following shape:
*
* ```
* {
* icon: string,
* title: string,
* subscript: string,
* onClick: Function,
* isActive: boolean,
* isDisabled: boolean
* }
* ```
*
* For convenience it is also possible to pass only an array of controls. It is
* then assumed this is the only set.
*
* Either `controls` or `children` is required, otherwise this components
* renders nothing.
*
* @param props Component props.
* @param [props.controls] The controls to render in this toolbar.
* @param [props.children] Any other things to render inside the toolbar besides the controls.
* @param [props.className] Class to set on the container div.
* @param [props.isCollapsed] Turns ToolbarGroup into a dropdown menu.
* @param [props.title] ARIA label for dropdown menu if is collapsed.
*/
function ToolbarGroup({
controls = [],
children,
className,
isCollapsed,
title,
...props
}) {
// It'll contain state if `ToolbarGroup` is being used within
// `<Toolbar label="label" />`
const accessibleToolbarState = useContext(ToolbarContext);
if ((!controls || !controls.length) && !children) {
return null;
}
const finalClassName = classnames(
// Unfortunately, there's legacy code referencing to `.components-toolbar`
// So we can't get rid of it
accessibleToolbarState ? 'components-toolbar-group' : 'components-toolbar', className);
// Normalize controls to nested array of objects (sets of controls)
let controlSets;
if (isNestedArray(controls)) {
controlSets = controls;
} else {
controlSets = [controls];
}
if (isCollapsed) {
return createElement(ToolbarGroupCollapsed, {
label: title,
controls: controlSets,
className: finalClassName,
children: children,
...props
});
}
return createElement(ToolbarGroupContainer, {
className: finalClassName,
...props
}, controlSets?.flatMap((controlSet, indexOfSet) => controlSet.map((control, indexOfControl) => createElement(ToolbarButton, {
key: [indexOfSet, indexOfControl].join(),
containerClassName: indexOfSet > 0 && indexOfControl === 0 ? 'has-left-divider' : undefined,
...control
}))), children);
}
export default ToolbarGroup;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useContext } from '@wordpress/element';
/**
* Internal dependencies
*/
import DropdownMenu from '../../dropdown-menu';
import ToolbarContext from '../toolbar-context';
import ToolbarItem from '../toolbar-item';
function ToolbarGroupCollapsed({
controls = [],
toggleProps,
...props
}) {
// It'll contain state if `ToolbarGroup` is being used within
// `<Toolbar label="label" />`
const accessibleToolbarState = useContext(ToolbarContext);
const renderDropdownMenu = internalToggleProps => createElement(DropdownMenu, {
controls: controls,
toggleProps: {
...internalToggleProps,
'data-toolbar-item': true
},
...props
});
if (accessibleToolbarState) {
return createElement(ToolbarItem, {
...toggleProps
}, renderDropdownMenu);
}
return renderDropdownMenu(toggleProps);
}
export default ToolbarGroupCollapsed;
//# sourceMappingURL=toolbar-group-collapsed.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useContext","DropdownMenu","ToolbarContext","ToolbarItem","ToolbarGroupCollapsed","controls","toggleProps","props","accessibleToolbarState","renderDropdownMenu","internalToggleProps","createElement"],"sources":["@wordpress/components/src/toolbar/toolbar-group/toolbar-group-collapsed.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport DropdownMenu from '../../dropdown-menu';\nimport ToolbarContext from '../toolbar-context';\nimport ToolbarItem from '../toolbar-item';\nimport type { ToolbarGroupCollapsedProps } from './types';\nimport type { DropdownMenuProps } from '../../dropdown-menu/types';\n\nfunction ToolbarGroupCollapsed( {\n\tcontrols = [],\n\ttoggleProps,\n\t...props\n}: ToolbarGroupCollapsedProps ) {\n\t// It'll contain state if `ToolbarGroup` is being used within\n\t// `<Toolbar label=\"label\" />`\n\tconst accessibleToolbarState = useContext( ToolbarContext );\n\n\tconst renderDropdownMenu = (\n\t\tinternalToggleProps?: DropdownMenuProps[ 'toggleProps' ]\n\t) => (\n\t\t<DropdownMenu\n\t\t\tcontrols={ controls }\n\t\t\ttoggleProps={ {\n\t\t\t\t...internalToggleProps,\n\t\t\t\t'data-toolbar-item': true,\n\t\t\t} }\n\t\t\t{ ...props }\n\t\t/>\n\t);\n\n\tif ( accessibleToolbarState ) {\n\t\treturn (\n\t\t\t<ToolbarItem { ...toggleProps }>{ renderDropdownMenu }</ToolbarItem>\n\t\t);\n\t}\n\n\treturn renderDropdownMenu( toggleProps );\n}\n\nexport default ToolbarGroupCollapsed;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,UAAU,QAAQ,oBAAoB;;AAE/C;AACA;AACA;AACA,OAAOC,YAAY,MAAM,qBAAqB;AAC9C,OAAOC,cAAc,MAAM,oBAAoB;AAC/C,OAAOC,WAAW,MAAM,iBAAiB;AAIzC,SAASC,qBAAqBA,CAAE;EAC/BC,QAAQ,GAAG,EAAE;EACbC,WAAW;EACX,GAAGC;AACwB,CAAC,EAAG;EAC/B;EACA;EACA,MAAMC,sBAAsB,GAAGR,UAAU,CAAEE,cAAe,CAAC;EAE3D,MAAMO,kBAAkB,GACvBC,mBAAwD,IAExDC,aAAA,CAACV,YAAY;IACZI,QAAQ,EAAGA,QAAU;IACrBC,WAAW,EAAG;MACb,GAAGI,mBAAmB;MACtB,mBAAmB,EAAE;IACtB,CAAG;IAAA,GACEH;EAAK,CACV,CACD;EAED,IAAKC,sBAAsB,EAAG;IAC7B,OACCG,aAAA,CAACR,WAAW;MAAA,GAAMG;IAAW,GAAKG,kBAAiC,CAAC;EAEtE;EAEA,OAAOA,kBAAkB,CAAEH,WAAY,CAAC;AACzC;AAEA,eAAeF,qBAAqB"}

View File

@@ -0,0 +1,29 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { View } from 'react-native';
/**
* WordPress dependencies
*/
import { withPreferredColorScheme } from '@wordpress/compose';
/**
* Internal dependencies
*/
import DropdownMenu from '../../dropdown-menu';
import styles from './style.scss';
function ToolbarGroupCollapsed({
controls = [],
getStylesFromColorScheme,
passedStyle,
...props
}) {
return createElement(View, {
style: [getStylesFromColorScheme(styles.container, styles.containerDark), passedStyle]
}, createElement(DropdownMenu, {
controls: controls,
...props
}));
}
export default withPreferredColorScheme(ToolbarGroupCollapsed);
//# sourceMappingURL=toolbar-group-collapsed.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["View","withPreferredColorScheme","DropdownMenu","styles","ToolbarGroupCollapsed","controls","getStylesFromColorScheme","passedStyle","props","createElement","style","container","containerDark"],"sources":["@wordpress/components/src/toolbar/toolbar-group/toolbar-group-collapsed.native.js"],"sourcesContent":["/**\n * External dependencies\n */\nimport { View } from 'react-native';\n/**\n * WordPress dependencies\n */\nimport { withPreferredColorScheme } from '@wordpress/compose';\n/**\n * Internal dependencies\n */\nimport DropdownMenu from '../../dropdown-menu';\nimport styles from './style.scss';\n\nfunction ToolbarGroupCollapsed( {\n\tcontrols = [],\n\tgetStylesFromColorScheme,\n\tpassedStyle,\n\t...props\n} ) {\n\treturn (\n\t\t<View\n\t\t\tstyle={ [\n\t\t\t\tgetStylesFromColorScheme(\n\t\t\t\t\tstyles.container,\n\t\t\t\t\tstyles.containerDark\n\t\t\t\t),\n\t\t\t\tpassedStyle,\n\t\t\t] }\n\t\t>\n\t\t\t<DropdownMenu controls={ controls } { ...props } />\n\t\t</View>\n\t);\n}\n\nexport default withPreferredColorScheme( ToolbarGroupCollapsed );\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,IAAI,QAAQ,cAAc;AACnC;AACA;AACA;AACA,SAASC,wBAAwB,QAAQ,oBAAoB;AAC7D;AACA;AACA;AACA,OAAOC,YAAY,MAAM,qBAAqB;AAC9C,OAAOC,MAAM,MAAM,cAAc;AAEjC,SAASC,qBAAqBA,CAAE;EAC/BC,QAAQ,GAAG,EAAE;EACbC,wBAAwB;EACxBC,WAAW;EACX,GAAGC;AACJ,CAAC,EAAG;EACH,OACCC,aAAA,CAACT,IAAI;IACJU,KAAK,EAAG,CACPJ,wBAAwB,CACvBH,MAAM,CAACQ,SAAS,EAChBR,MAAM,CAACS,aACR,CAAC,EACDL,WAAW;EACT,GAEHE,aAAA,CAACP,YAAY;IAACG,QAAQ,EAAGA,QAAU;IAAA,GAAMG;EAAK,CAAI,CAC7C,CAAC;AAET;AAEA,eAAeP,wBAAwB,CAAEG,qBAAsB,CAAC"}

View File

@@ -0,0 +1,15 @@
import { createElement } from "react";
/**
* Internal dependencies
*/
const ToolbarGroupContainer = ({
className,
children,
...props
}) => createElement("div", {
className: className,
...props
}, children);
export default ToolbarGroupContainer;
//# sourceMappingURL=toolbar-group-container.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["ToolbarGroupContainer","className","children","props","createElement"],"sources":["@wordpress/components/src/toolbar/toolbar-group/toolbar-group-container.tsx"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport type { WordPressComponentProps } from '../../context';\nimport type { ToolbarGroupContainerProps } from './types';\n\nconst ToolbarGroupContainer = ( {\n\tclassName,\n\tchildren,\n\t...props\n}: WordPressComponentProps< ToolbarGroupContainerProps, 'div', false > ) => (\n\t<div className={ className } { ...props }>\n\t\t{ children }\n\t</div>\n);\nexport default ToolbarGroupContainer;\n"],"mappings":";AAAA;AACA;AACA;;AAIA,MAAMA,qBAAqB,GAAGA,CAAE;EAC/BC,SAAS;EACTC,QAAQ;EACR,GAAGC;AACiE,CAAC,KACrEC,aAAA;EAAKH,SAAS,EAAGA,SAAW;EAAA,GAAME;AAAK,GACpCD,QACE,CACL;AACD,eAAeF,qBAAqB"}

View File

@@ -0,0 +1,28 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { StyleSheet, View } from 'react-native';
/**
* WordPress dependencies
*/
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './style.scss';
const ToolbarGroupContainer = ({
passedStyle,
children
}) => {
const groupStyles = [usePreferredColorSchemeStyle(styles.container, styles.containerDark), {
borderLeftWidth: StyleSheet.hairlineWidth
}, passedStyle];
return createElement(View, {
style: groupStyles
}, children);
};
export default ToolbarGroupContainer;
//# sourceMappingURL=toolbar-group-container.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["StyleSheet","View","usePreferredColorSchemeStyle","styles","ToolbarGroupContainer","passedStyle","children","groupStyles","container","containerDark","borderLeftWidth","hairlineWidth","createElement","style"],"sources":["@wordpress/components/src/toolbar/toolbar-group/toolbar-group-container.native.js"],"sourcesContent":["/**\n * External dependencies\n */\nimport { StyleSheet, View } from 'react-native';\n\n/**\n * WordPress dependencies\n */\nimport { usePreferredColorSchemeStyle } from '@wordpress/compose';\n\n/**\n * Internal dependencies\n */\nimport styles from './style.scss';\n\nconst ToolbarGroupContainer = ( { passedStyle, children } ) => {\n\tconst groupStyles = [\n\t\tusePreferredColorSchemeStyle( styles.container, styles.containerDark ),\n\t\t{ borderLeftWidth: StyleSheet.hairlineWidth },\n\t\tpassedStyle,\n\t];\n\n\treturn <View style={ groupStyles }>{ children }</View>;\n};\n\nexport default ToolbarGroupContainer;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,UAAU,EAAEC,IAAI,QAAQ,cAAc;;AAE/C;AACA;AACA;AACA,SAASC,4BAA4B,QAAQ,oBAAoB;;AAEjE;AACA;AACA;AACA,OAAOC,MAAM,MAAM,cAAc;AAEjC,MAAMC,qBAAqB,GAAGA,CAAE;EAAEC,WAAW;EAAEC;AAAS,CAAC,KAAM;EAC9D,MAAMC,WAAW,GAAG,CACnBL,4BAA4B,CAAEC,MAAM,CAACK,SAAS,EAAEL,MAAM,CAACM,aAAc,CAAC,EACtE;IAAEC,eAAe,EAAEV,UAAU,CAACW;EAAc,CAAC,EAC7CN,WAAW,CACX;EAED,OAAOO,aAAA,CAACX,IAAI;IAACY,KAAK,EAAGN;EAAa,GAAGD,QAAgB,CAAC;AACvD,CAAC;AAED,eAAeF,qBAAqB"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/components/src/toolbar/toolbar-group/types.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type {\n\tDropdownMenuProps,\n\tDropdownOption,\n} from '../../dropdown-menu/types';\n\n/**\n * WordPress dependencies\n */\nimport type { Props as IconProps } from '../../icon';\n\nexport type ToolbarGroupControls = DropdownOption & {\n\t/**\n\t * An optional subscript associated to the control.\n\t */\n\tsubscript?: string;\n};\n\ntype ToolbarGroupPropsBase = {\n\t/**\n\t * The controls to render in this toolbar.\n\t */\n\tcontrols?: ToolbarGroupControls[] | ToolbarGroupControls[][];\n\n\t/**\n\t * Class to set on the container div.\n\t */\n\tclassName?: string;\n\n\t/**\n\t * Any other things to render inside the toolbar besides the controls.\n\t */\n\tchildren?: ReactNode;\n\n\t/**\n\t * The Dashicon icon slug to be shown for the option.\n\t */\n\ticon?: IconProps[ 'icon' ];\n};\n\nexport type ToolbarGroupProps = ToolbarGroupPropsBase &\n\t(\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * When true, turns `ToolbarGroup` into a dropdown menu.\n\t\t\t\t */\n\t\t\t\tisCollapsed?: false;\n\t\t\t\t/**\n\t\t\t\t * Any other things to render inside the toolbar besides the controls.\n\t\t\t\t */\n\t\t\t\tchildren?: ReactNode;\n\t\t\t\ttitle?: never;\n\t\t }\n\t\t| {\n\t\t\t\t/**\n\t\t\t\t * When true, turns `ToolbarGroup` into a dropdown menu.\n\t\t\t\t */\n\t\t\t\tisCollapsed: true;\n\t\t\t\t/**\n\t\t\t\t * Any other things to render inside the toolbar besides the controls.\n\t\t\t\t */\n\t\t\t\tchildren?: ToolbarGroupCollapsedProps[ 'children' ];\n\t\t\t\t/**\n\t\t\t\t * ARIA label for dropdown menu if is collapsed.\n\t\t\t\t */\n\t\t\t\ttitle: string;\n\t\t }\n\t);\n\nexport type ToolbarGroupCollapsedProps = DropdownMenuProps;\n\nexport type ToolbarGroupContainerProps = {\n\t/**\n\t * Children to be rendered inside the toolbar.\n\t */\n\tchildren?: ReactNode;\n\t/**\n\t * Class to set on the container div.\n\t */\n\tclassName?: string;\n\t/**\n\t * Props to be passed.\n\t */\n\tprops?: any;\n};\n"],"mappings":""}