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,92 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import { decodeEntities } from '@wordpress/html-entities';
/**
* Internal dependencies
*/
import { SelectControl } from '../select-control';
import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props';
function getSelectOptions(tree, level = 0) {
return tree.flatMap(treeNode => [{
value: treeNode.id,
label: '\u00A0'.repeat(level * 3) + decodeEntities(treeNode.name)
}, ...getSelectOptions(treeNode.children || [], level + 1)]);
}
/**
* TreeSelect component is used to generate select input fields.
*
* ```jsx
* import { TreeSelect } from '@wordpress/components';
* import { useState } from '@wordpress/element';
*
* const MyTreeSelect = () => {
* const [ page, setPage ] = useState( 'p21' );
*
* return (
* <TreeSelect
* label="Parent page"
* noOptionLabel="No parent page"
* onChange={ ( newPage ) => setPage( newPage ) }
* selectedId={ page }
* tree={ [
* {
* name: 'Page 1',
* id: 'p1',
* children: [
* { name: 'Descend 1 of page 1', id: 'p11' },
* { name: 'Descend 2 of page 1', id: 'p12' },
* ],
* },
* {
* name: 'Page 2',
* id: 'p2',
* children: [
* {
* name: 'Descend 1 of page 2',
* id: 'p21',
* children: [
* {
* name: 'Descend 1 of Descend 1 of page 2',
* id: 'p211',
* },
* ],
* },
* ],
* },
* ] }
* />
* );
* }
* ```
*/
export function TreeSelect(props) {
const {
label,
noOptionLabel,
onChange,
selectedId,
tree = [],
...restProps
} = useDeprecated36pxDefaultSizeProp(props, 'wp.components.TreeSelect', '6.4');
const options = useMemo(() => {
return [noOptionLabel && {
value: '',
label: noOptionLabel
}, ...getSelectOptions(tree)].filter(option => !!option);
}, [noOptionLabel, tree]);
return createElement(SelectControl, {
label,
options,
onChange,
value: selectedId,
...restProps
});
}
export default TreeSelect;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["useMemo","decodeEntities","SelectControl","useDeprecated36pxDefaultSizeProp","getSelectOptions","tree","level","flatMap","treeNode","value","id","label","repeat","name","children","TreeSelect","props","noOptionLabel","onChange","selectedId","restProps","options","filter","option","createElement"],"sources":["@wordpress/components/src/tree-select/index.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { useMemo } from '@wordpress/element';\nimport { decodeEntities } from '@wordpress/html-entities';\n\n/**\n * Internal dependencies\n */\nimport { SelectControl } from '../select-control';\nimport type { TreeSelectProps, Tree, Truthy } from './types';\nimport { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props';\n\nfunction getSelectOptions(\n\ttree: Tree[],\n\tlevel = 0\n): NonNullable< TreeSelectProps[ 'options' ] > {\n\treturn tree.flatMap( ( treeNode ) => [\n\t\t{\n\t\t\tvalue: treeNode.id,\n\t\t\tlabel:\n\t\t\t\t'\\u00A0'.repeat( level * 3 ) + decodeEntities( treeNode.name ),\n\t\t},\n\t\t...getSelectOptions( treeNode.children || [], level + 1 ),\n\t] );\n}\n\n/**\n * TreeSelect component is used to generate select input fields.\n *\n * ```jsx\n * import { TreeSelect } from '@wordpress/components';\n * import { useState } from '@wordpress/element';\n *\n * const MyTreeSelect = () => {\n * \tconst [ page, setPage ] = useState( 'p21' );\n *\n * \treturn (\n * \t\t<TreeSelect\n * \t\t\tlabel=\"Parent page\"\n * \t\t\tnoOptionLabel=\"No parent page\"\n * \t\t\tonChange={ ( newPage ) => setPage( newPage ) }\n * \t\t\tselectedId={ page }\n * \t\t\ttree={ [\n * \t\t\t\t{\n * \t\t\t\t\tname: 'Page 1',\n * \t\t\t\t\tid: 'p1',\n * \t\t\t\t\tchildren: [\n * \t\t\t\t\t\t{ name: 'Descend 1 of page 1', id: 'p11' },\n * \t\t\t\t\t\t{ name: 'Descend 2 of page 1', id: 'p12' },\n * \t\t\t\t\t],\n * \t\t\t\t},\n * \t\t\t\t{\n * \t\t\t\t\tname: 'Page 2',\n * \t\t\t\t\tid: 'p2',\n * \t\t\t\t\tchildren: [\n * \t\t\t\t\t\t{\n * \t\t\t\t\t\t\tname: 'Descend 1 of page 2',\n * \t\t\t\t\t\t\tid: 'p21',\n * \t\t\t\t\t\t\tchildren: [\n * \t\t\t\t\t\t\t\t{\n * \t\t\t\t\t\t\t\t\tname: 'Descend 1 of Descend 1 of page 2',\n * \t\t\t\t\t\t\t\t\tid: 'p211',\n * \t\t\t\t\t\t\t\t},\n * \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 * \t\t/>\n * \t);\n * }\n * ```\n */\n\nexport function TreeSelect( props: TreeSelectProps ) {\n\tconst {\n\t\tlabel,\n\t\tnoOptionLabel,\n\t\tonChange,\n\t\tselectedId,\n\t\ttree = [],\n\t\t...restProps\n\t} = useDeprecated36pxDefaultSizeProp(\n\t\tprops,\n\t\t'wp.components.TreeSelect',\n\t\t'6.4'\n\t);\n\n\tconst options = useMemo( () => {\n\t\treturn [\n\t\t\tnoOptionLabel && { value: '', label: noOptionLabel },\n\t\t\t...getSelectOptions( tree ),\n\t\t].filter( < T, >( option: T ): option is Truthy< T > => !! option );\n\t}, [ noOptionLabel, tree ] );\n\n\treturn (\n\t\t<SelectControl\n\t\t\t{ ...{ label, options, onChange } }\n\t\t\tvalue={ selectedId }\n\t\t\t{ ...restProps }\n\t\t/>\n\t);\n}\n\nexport default TreeSelect;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,OAAO,QAAQ,oBAAoB;AAC5C,SAASC,cAAc,QAAQ,0BAA0B;;AAEzD;AACA;AACA;AACA,SAASC,aAAa,QAAQ,mBAAmB;AAEjD,SAASC,gCAAgC,QAAQ,+BAA+B;AAEhF,SAASC,gBAAgBA,CACxBC,IAAY,EACZC,KAAK,GAAG,CAAC,EACqC;EAC9C,OAAOD,IAAI,CAACE,OAAO,CAAIC,QAAQ,IAAM,CACpC;IACCC,KAAK,EAAED,QAAQ,CAACE,EAAE;IAClBC,KAAK,EACJ,QAAQ,CAACC,MAAM,CAAEN,KAAK,GAAG,CAAE,CAAC,GAAGL,cAAc,CAAEO,QAAQ,CAACK,IAAK;EAC/D,CAAC,EACD,GAAGT,gBAAgB,CAAEI,QAAQ,CAACM,QAAQ,IAAI,EAAE,EAAER,KAAK,GAAG,CAAE,CAAC,CACxD,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,SAASS,UAAUA,CAAEC,KAAsB,EAAG;EACpD,MAAM;IACLL,KAAK;IACLM,aAAa;IACbC,QAAQ;IACRC,UAAU;IACVd,IAAI,GAAG,EAAE;IACT,GAAGe;EACJ,CAAC,GAAGjB,gCAAgC,CACnCa,KAAK,EACL,0BAA0B,EAC1B,KACD,CAAC;EAED,MAAMK,OAAO,GAAGrB,OAAO,CAAE,MAAM;IAC9B,OAAO,CACNiB,aAAa,IAAI;MAAER,KAAK,EAAE,EAAE;MAAEE,KAAK,EAAEM;IAAc,CAAC,EACpD,GAAGb,gBAAgB,CAAEC,IAAK,CAAC,CAC3B,CAACiB,MAAM,CAAUC,MAAS,IAA6B,CAAC,CAAEA,MAAO,CAAC;EACpE,CAAC,EAAE,CAAEN,aAAa,EAAEZ,IAAI,CAAG,CAAC;EAE5B,OACCmB,aAAA,CAACtB,aAAa;IACNS,KAAK;IAAEU,OAAO;IAAEH,QAAQ;IAC/BT,KAAK,EAAGU,UAAY;IAAA,GACfC;EAAS,CACd,CAAC;AAEJ;AAEA,eAAeL,UAAU"}

View File

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

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/components/src/tree-select/types.ts"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport type { SelectControlSingleSelectionProps } from '../select-control/types';\n\nexport type Truthy< T > = T extends false | '' | 0 | null | undefined\n\t? never\n\t: T;\n\nexport interface Tree {\n\tid: string;\n\tname: string;\n\tchildren?: Tree[];\n}\n\n// `TreeSelect` inherits props from `SelectControl`, but only\n// in single selection mode (ie. when the `multiple` prop is not defined).\nexport interface TreeSelectProps\n\textends Omit< SelectControlSingleSelectionProps, 'value' | 'multiple' > {\n\t/**\n\t * If this property is added, an option will be added with this label to represent empty selection.\n\t */\n\tnoOptionLabel?: string;\n\t/**\n\t * An array containing the tree objects with the possible nodes the user can select.\n\t */\n\ttree?: Tree[];\n\t/**\n\t * The id of the currently selected node.\n\t */\n\tselectedId?: SelectControlSingleSelectionProps[ 'value' ];\n}\n"],"mappings":""}