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,44 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* Internal dependencies
*/
import Button from '../button';
import Dropdown from '../dropdown';
export function DropdownLinkAction({
buttonProps,
className,
dropdownProps,
linkText
}) {
return createElement(Dropdown, {
className: classnames('components-circular-option-picker__dropdown-link-action', className),
renderToggle: ({
isOpen,
onToggle
}) => createElement(Button, {
"aria-expanded": isOpen,
"aria-haspopup": "true",
onClick: onToggle,
variant: "link",
...buttonProps
}, linkText),
...dropdownProps
});
}
export function ButtonAction({
className,
children,
...additionalProps
}) {
return createElement(Button, {
className: classnames('components-circular-option-picker__clear', className),
variant: "tertiary",
...additionalProps
}, children);
}
//# sourceMappingURL=circular-option-picker-actions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["classnames","Button","Dropdown","DropdownLinkAction","buttonProps","className","dropdownProps","linkText","createElement","renderToggle","isOpen","onToggle","onClick","variant","ButtonAction","children","additionalProps"],"sources":["@wordpress/components/src/circular-option-picker/circular-option-picker-actions.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\n\n/**\n * Internal dependencies\n */\nimport Button from '../button';\nimport Dropdown from '../dropdown';\nimport type { DropdownLinkActionProps } from './types';\nimport type { WordPressComponentProps } from '../context';\nimport type { ButtonAsButtonProps } from '../button/types';\n\nexport function DropdownLinkAction( {\n\tbuttonProps,\n\tclassName,\n\tdropdownProps,\n\tlinkText,\n}: DropdownLinkActionProps ) {\n\treturn (\n\t\t<Dropdown\n\t\t\tclassName={ classnames(\n\t\t\t\t'components-circular-option-picker__dropdown-link-action',\n\t\t\t\tclassName\n\t\t\t) }\n\t\t\trenderToggle={ ( { isOpen, onToggle } ) => (\n\t\t\t\t<Button\n\t\t\t\t\taria-expanded={ isOpen }\n\t\t\t\t\taria-haspopup=\"true\"\n\t\t\t\t\tonClick={ onToggle }\n\t\t\t\t\tvariant=\"link\"\n\t\t\t\t\t{ ...buttonProps }\n\t\t\t\t>\n\t\t\t\t\t{ linkText }\n\t\t\t\t</Button>\n\t\t\t) }\n\t\t\t{ ...dropdownProps }\n\t\t/>\n\t);\n}\n\nexport function ButtonAction( {\n\tclassName,\n\tchildren,\n\t...additionalProps\n}: WordPressComponentProps< ButtonAsButtonProps, 'button', false > ) {\n\treturn (\n\t\t<Button\n\t\t\tclassName={ classnames(\n\t\t\t\t'components-circular-option-picker__clear',\n\t\t\t\tclassName\n\t\t\t) }\n\t\t\tvariant=\"tertiary\"\n\t\t\t{ ...additionalProps }\n\t\t>\n\t\t\t{ children }\n\t\t</Button>\n\t);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,UAAU,MAAM,YAAY;;AAEnC;AACA;AACA;AACA,OAAOC,MAAM,MAAM,WAAW;AAC9B,OAAOC,QAAQ,MAAM,aAAa;AAKlC,OAAO,SAASC,kBAAkBA,CAAE;EACnCC,WAAW;EACXC,SAAS;EACTC,aAAa;EACbC;AACwB,CAAC,EAAG;EAC5B,OACCC,aAAA,CAACN,QAAQ;IACRG,SAAS,EAAGL,UAAU,CACrB,yDAAyD,EACzDK,SACD,CAAG;IACHI,YAAY,EAAGA,CAAE;MAAEC,MAAM;MAAEC;IAAS,CAAC,KACpCH,aAAA,CAACP,MAAM;MACN,iBAAgBS,MAAQ;MACxB,iBAAc,MAAM;MACpBE,OAAO,EAAGD,QAAU;MACpBE,OAAO,EAAC,MAAM;MAAA,GACTT;IAAW,GAEdG,QACK,CACN;IAAA,GACED;EAAa,CAClB,CAAC;AAEJ;AAEA,OAAO,SAASQ,YAAYA,CAAE;EAC7BT,SAAS;EACTU,QAAQ;EACR,GAAGC;AAC6D,CAAC,EAAG;EACpE,OACCR,aAAA,CAACP,MAAM;IACNI,SAAS,EAAGL,UAAU,CACrB,0CAA0C,EAC1CK,SACD,CAAG;IACHQ,OAAO,EAAC,UAAU;IAAA,GACbG;EAAe,GAElBD,QACK,CAAC;AAEX"}

View File

@@ -0,0 +1,11 @@
/**
* WordPress dependencies
*/
import { createContext } from '@wordpress/element';
/**
* Internal dependencies
*/
export const CircularOptionPickerContext = createContext({});
//# sourceMappingURL=circular-option-picker-context.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["createContext","CircularOptionPickerContext"],"sources":["@wordpress/components/src/circular-option-picker/circular-option-picker-context.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { createContext } from '@wordpress/element';\n\n/**\n * Internal dependencies\n */\nimport type { CircularOptionPickerContextProps } from './types';\n\nexport const CircularOptionPickerContext =\n\tcreateContext< CircularOptionPickerContextProps >( {} );\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,aAAa,QAAQ,oBAAoB;;AAElD;AACA;AACA;;AAGA,OAAO,MAAMC,2BAA2B,GACvCD,aAAa,CAAsC,CAAC,CAAE,CAAC"}

View File

@@ -0,0 +1,23 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* Internal dependencies
*/
export function OptionGroup({
className,
options,
...additionalProps
}) {
const role = 'aria-label' in additionalProps || 'aria-labelledby' in additionalProps ? 'group' : undefined;
return createElement("div", {
...additionalProps,
role: role,
className: classnames('components-circular-option-picker__option-group', 'components-circular-option-picker__swatches', className)
}, options);
}
//# sourceMappingURL=circular-option-picker-option-group.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["classnames","OptionGroup","className","options","additionalProps","role","undefined","createElement"],"sources":["@wordpress/components/src/circular-option-picker/circular-option-picker-option-group.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport classnames from 'classnames';\n\n/**\n * Internal dependencies\n */\nimport type { OptionGroupProps } from './types';\n\nexport function OptionGroup( {\n\tclassName,\n\toptions,\n\t...additionalProps\n}: OptionGroupProps ) {\n\tconst role =\n\t\t'aria-label' in additionalProps || 'aria-labelledby' in additionalProps\n\t\t\t? 'group'\n\t\t\t: undefined;\n\n\treturn (\n\t\t<div\n\t\t\t{ ...additionalProps }\n\t\t\trole={ role }\n\t\t\tclassName={ classnames(\n\t\t\t\t'components-circular-option-picker__option-group',\n\t\t\t\t'components-circular-option-picker__swatches',\n\t\t\t\tclassName\n\t\t\t) }\n\t\t>\n\t\t\t{ options }\n\t\t</div>\n\t);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,OAAOA,UAAU,MAAM,YAAY;;AAEnC;AACA;AACA;;AAGA,OAAO,SAASC,WAAWA,CAAE;EAC5BC,SAAS;EACTC,OAAO;EACP,GAAGC;AACc,CAAC,EAAG;EACrB,MAAMC,IAAI,GACT,YAAY,IAAID,eAAe,IAAI,iBAAiB,IAAIA,eAAe,GACpE,OAAO,GACPE,SAAS;EAEb,OACCC,aAAA;IAAA,GACMH,eAAe;IACpBC,IAAI,EAAGA,IAAM;IACbH,SAAS,EAAGF,UAAU,CACrB,iDAAiD,EACjD,6CAA6C,EAC7CE,SACD;EAAG,GAEDC,OACE,CAAC;AAER"}

View File

@@ -0,0 +1,89 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { forwardRef, useContext } from '@wordpress/element';
import { Icon, check } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { CircularOptionPickerContext } from './circular-option-picker-context';
import Button from '../button';
import { CompositeItem } from '../composite/v2';
import Tooltip from '../tooltip';
function UnforwardedOptionAsButton(props, forwardedRef) {
const {
isPressed,
...additionalProps
} = props;
return createElement(Button, {
...additionalProps,
"aria-pressed": isPressed,
ref: forwardedRef
});
}
const OptionAsButton = forwardRef(UnforwardedOptionAsButton);
function UnforwardedOptionAsOption(props, forwardedRef) {
const {
id,
isSelected,
compositeStore,
...additionalProps
} = props;
const activeId = compositeStore.useState('activeId');
if (isSelected && !activeId) {
compositeStore.setActiveId(id);
}
return createElement(CompositeItem, {
render: createElement(Button, {
...additionalProps,
role: "option",
"aria-selected": !!isSelected,
ref: forwardedRef
}),
store: compositeStore,
id: id
});
}
const OptionAsOption = forwardRef(UnforwardedOptionAsOption);
export function Option({
className,
isSelected,
selectedIconProps = {},
tooltipText,
...additionalProps
}) {
const {
baseId,
compositeStore
} = useContext(CircularOptionPickerContext);
const id = useInstanceId(Option, baseId || 'components-circular-option-picker__option');
const commonProps = {
id,
className: 'components-circular-option-picker__option',
...additionalProps
};
const optionControl = compositeStore ? createElement(OptionAsOption, {
...commonProps,
compositeStore: compositeStore,
isSelected: isSelected
}) : createElement(OptionAsButton, {
...commonProps,
isPressed: isSelected
});
return createElement("div", {
className: classnames(className, 'components-circular-option-picker__option-wrapper')
}, tooltipText ? createElement(Tooltip, {
text: tooltipText
}, optionControl) : optionControl, isSelected && createElement(Icon, {
icon: check,
...selectedIconProps
}));
}
//# sourceMappingURL=circular-option-picker-option.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,144 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classnames from 'classnames';
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { isRTL } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { CircularOptionPickerContext } from './circular-option-picker-context';
import { Composite, useCompositeStore } from '../composite/v2';
import { Option } from './circular-option-picker-option';
import { OptionGroup } from './circular-option-picker-option-group';
import { ButtonAction, DropdownLinkAction } from './circular-option-picker-actions';
/**
*`CircularOptionPicker` is a component that displays a set of options as circular buttons.
*
* ```jsx
* import { CircularOptionPicker } from '../circular-option-picker';
* import { useState } from '@wordpress/element';
*
* const Example = () => {
* const [ currentColor, setCurrentColor ] = useState();
* const colors = [
* { color: '#f00', name: 'Red' },
* { color: '#0f0', name: 'Green' },
* { color: '#00f', name: 'Blue' },
* ];
* const colorOptions = (
* <>
* { colors.map( ( { color, name }, index ) => {
* return (
* <CircularOptionPicker.Option
* key={ `${ color }-${ index }` }
* tooltipText={ name }
* style={ { backgroundColor: color, color } }
* isSelected={ index === currentColor }
* onClick={ () => setCurrentColor( index ) }
* aria-label={ name }
* />
* );
* } ) }
* </>
* );
* return (
* <CircularOptionPicker
* options={ colorOptions }
* actions={
* <CircularOptionPicker.ButtonAction
* onClick={ () => setCurrentColor( undefined ) }
* >
* { 'Clear' }
* </CircularOptionPicker.ButtonAction>
* }
* />
* );
* };
* ```
*/
function ListboxCircularOptionPicker(props) {
const {
actions,
options,
baseId,
className,
loop = true,
children,
...additionalProps
} = props;
const compositeStore = useCompositeStore({
focusLoop: loop,
rtl: isRTL()
});
const compositeContext = {
baseId,
compositeStore
};
return createElement("div", {
className: className
}, createElement(CircularOptionPickerContext.Provider, {
value: compositeContext
}, createElement(Composite, {
...additionalProps,
id: baseId,
store: compositeStore,
role: 'listbox'
}, options), children, actions));
}
function ButtonsCircularOptionPicker(props) {
const {
actions,
options,
children,
baseId,
...additionalProps
} = props;
return createElement("div", {
...additionalProps,
id: baseId
}, createElement(CircularOptionPickerContext.Provider, {
value: {
baseId
}
}, options, children, actions));
}
function CircularOptionPicker(props) {
const {
asButtons,
actions: actionsProp,
options: optionsProp,
children,
className,
...additionalProps
} = props;
const baseId = useInstanceId(CircularOptionPicker, 'components-circular-option-picker', additionalProps.id);
const OptionPickerImplementation = asButtons ? ButtonsCircularOptionPicker : ListboxCircularOptionPicker;
const actions = actionsProp ? createElement("div", {
className: "components-circular-option-picker__custom-clear-wrapper"
}, actionsProp) : undefined;
const options = createElement("div", {
className: 'components-circular-option-picker__swatches'
}, optionsProp);
return createElement(OptionPickerImplementation, {
...additionalProps,
baseId: baseId,
className: classnames('components-circular-option-picker', className),
actions: actions,
options: options
}, children);
}
CircularOptionPicker.Option = Option;
CircularOptionPicker.OptionGroup = OptionGroup;
CircularOptionPicker.ButtonAction = ButtonAction;
CircularOptionPicker.DropdownLinkAction = DropdownLinkAction;
export default CircularOptionPicker;
//# sourceMappingURL=circular-option-picker.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
/**
* Internal dependencies
*/
import CircularOptionPicker from './circular-option-picker';
export { Option } from './circular-option-picker-option';
export { OptionGroup } from './circular-option-picker-option-group';
export { ButtonAction, DropdownLinkAction } from './circular-option-picker-actions';
export default CircularOptionPicker;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["CircularOptionPicker","Option","OptionGroup","ButtonAction","DropdownLinkAction"],"sources":["@wordpress/components/src/circular-option-picker/index.tsx"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport CircularOptionPicker from './circular-option-picker';\n\nexport { Option } from './circular-option-picker-option';\nexport { OptionGroup } from './circular-option-picker-option-group';\nexport {\n\tButtonAction,\n\tDropdownLinkAction,\n} from './circular-option-picker-actions';\n\nexport default CircularOptionPicker;\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAOA,oBAAoB,MAAM,0BAA0B;AAE3D,SAASC,MAAM,QAAQ,iCAAiC;AACxD,SAASC,WAAW,QAAQ,uCAAuC;AACnE,SACCC,YAAY,EACZC,kBAAkB,QACZ,kCAAkC;AAEzC,eAAeJ,oBAAoB"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/components/src/circular-option-picker/types.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ReactNode } from 'react';\n\n/**\n * WordPress dependencies\n */\nimport type { Icon } from '@wordpress/icons';\n\n/**\n * Internal dependencies\n */\nimport type { ButtonAsButtonProps } from '../button/types';\nimport type { DropdownProps } from '../dropdown/types';\nimport type { WordPressComponentProps } from '../context';\nimport type { CompositeStore } from '../composite/v2';\n\ntype CommonCircularOptionPickerProps = {\n\t/**\n\t * An ID to apply to the component.\n\t */\n\tid?: string;\n\t/**\n\t * A CSS class to apply to the wrapper element.\n\t */\n\tclassName?: string;\n\t/**\n\t * The action(s) to be rendered after the options,\n\t * such as a 'clear' button as seen in `ColorPalette`.\n\t * Usually a `CircularOptionPicker.ButtonAction` or\n\t * `CircularOptionPicker.DropdownLinkAction` component.\n\t */\n\tactions?: ReactNode;\n\t/**\n\t * The options to be rendered, such as color swatches.\n\t * Usually a `CircularOptionPicker.Option` component.\n\t */\n\toptions: ReactNode;\n\t/**\n\t * The child elements.\n\t */\n\tchildren?: ReactNode;\n};\n\ntype WithBaseId = {\n\tbaseId: string;\n};\n\ntype FullListboxCircularOptionPickerProps = CommonCircularOptionPickerProps & {\n\t/**\n\t * Whether the control should present as a set of buttons,\n\t * each with its own tab stop.\n\t */\n\tasButtons?: false;\n\t/**\n\t * Prevents keyboard interaction from wrapping around.\n\t * Only used when `asButtons` is not true.\n\t *\n\t * @default true\n\t */\n\tloop?: boolean;\n} & (\n\t\t| {\n\t\t\t\t'aria-label': string;\n\t\t\t\t'aria-labelledby'?: never;\n\t\t }\n\t\t| {\n\t\t\t\t'aria-label'?: never;\n\t\t\t\t'aria-labelledby': string;\n\t\t }\n\t);\n\nexport type ListboxCircularOptionPickerProps = WithBaseId &\n\tOmit< FullListboxCircularOptionPickerProps, 'asButtons' >;\n\ntype FullButtonsCircularOptionPickerProps = CommonCircularOptionPickerProps & {\n\t/**\n\t * Whether the control should present as a set of buttons,\n\t * each with its own tab stop.\n\t *\n\t * @default false\n\t */\n\tasButtons: true;\n};\n\nexport type ButtonsCircularOptionPickerProps = WithBaseId &\n\tOmit< FullButtonsCircularOptionPickerProps, 'asButtons' >;\n\nexport type CircularOptionPickerProps =\n\t| FullListboxCircularOptionPickerProps\n\t| FullButtonsCircularOptionPickerProps;\n\nexport type DropdownLinkActionProps = {\n\tbuttonProps?: Omit<\n\t\tWordPressComponentProps< ButtonAsButtonProps, 'button', false >,\n\t\t'children'\n\t>;\n\tlinkText: string;\n\tdropdownProps: Omit< DropdownProps, 'className' | 'renderToggle' >;\n\tclassName?: string;\n};\n\nexport type OptionGroupProps = {\n\tclassName?: string;\n\toptions: ReactNode;\n};\n\nexport type OptionProps = Omit<\n\tWordPressComponentProps< ButtonAsButtonProps, 'button', false >,\n\t'isPressed' | 'className'\n> & {\n\tclassName?: string;\n\ttooltipText?: string;\n\tisSelected?: boolean;\n\t// `icon` is explicitly defined as 'check' by CircleOptionPicker.Option\n\t// and is not intended to be overridden.\n\t// `size` relies on the `Icon` component's default size of `24` to fit\n\t// `CircularOptionPicker`'s design, and should not be explicitly set.\n\tselectedIconProps?: Omit<\n\t\tReact.ComponentProps< typeof Icon >,\n\t\t'icon' | 'size'\n\t>;\n};\n\nexport type CircularOptionPickerCompositeStore = CompositeStore;\nexport type CircularOptionPickerContextProps = {\n\tbaseId?: string;\n\tcompositeStore?: CircularOptionPickerCompositeStore;\n};\n"],"mappings":""}