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,30 @@
/**
* Internal dependencies
*/
import isGenerator from './is-generator';
import createRuntime from './runtime';
/**
* Creates a Redux middleware, given an object of controls where each key is an
* action type for which to act upon, the value a function which returns either
* a promise which is to resolve when evaluation of the action should continue,
* or a value. The value or resolved promise value is assigned on the return
* value of the yield assignment. If the control handler returns undefined, the
* execution is not continued.
*
* @param {Record<string, (value: import('redux').AnyAction) => Promise<boolean> | boolean>} controls Object of control handlers.
*
* @return {import('redux').Middleware} Co-routine runtime
*/
export default function createMiddleware(controls = {}) {
return store => {
const runtime = createRuntime(controls, store.dispatch);
return next => action => {
if (!isGenerator(action)) {
return next(action);
}
return runtime(action);
};
};
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["isGenerator","createRuntime","createMiddleware","controls","store","runtime","dispatch","next","action"],"sources":["@wordpress/redux-routine/src/index.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport isGenerator from './is-generator';\nimport createRuntime from './runtime';\n\n/**\n * Creates a Redux middleware, given an object of controls where each key is an\n * action type for which to act upon, the value a function which returns either\n * a promise which is to resolve when evaluation of the action should continue,\n * or a value. The value or resolved promise value is assigned on the return\n * value of the yield assignment. If the control handler returns undefined, the\n * execution is not continued.\n *\n * @param {Record<string, (value: import('redux').AnyAction) => Promise<boolean> | boolean>} controls Object of control handlers.\n *\n * @return {import('redux').Middleware} Co-routine runtime\n */\nexport default function createMiddleware( controls = {} ) {\n\treturn ( store ) => {\n\t\tconst runtime = createRuntime( controls, store.dispatch );\n\t\treturn ( next ) => ( action ) => {\n\t\t\tif ( ! isGenerator( action ) ) {\n\t\t\t\treturn next( action );\n\t\t\t}\n\n\t\t\treturn runtime( action );\n\t\t};\n\t};\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAOA,WAAW,MAAM,gBAAgB;AACxC,OAAOC,aAAa,MAAM,WAAW;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,gBAAgBA,CAAEC,QAAQ,GAAG,CAAC,CAAC,EAAG;EACzD,OAASC,KAAK,IAAM;IACnB,MAAMC,OAAO,GAAGJ,aAAa,CAAEE,QAAQ,EAAEC,KAAK,CAACE,QAAS,CAAC;IACzD,OAASC,IAAI,IAAQC,MAAM,IAAM;MAChC,IAAK,CAAER,WAAW,CAAEQ,MAAO,CAAC,EAAG;QAC9B,OAAOD,IAAI,CAAEC,MAAO,CAAC;MACtB;MAEA,OAAOH,OAAO,CAAEG,MAAO,CAAC;IACzB,CAAC;EACF,CAAC;AACF","ignoreList":[]}

View File

@@ -0,0 +1,31 @@
/**
* External dependencies
*/
import { isPlainObject } from 'is-plain-object';
/* eslint-disable jsdoc/valid-types */
/**
* Returns true if the given object quacks like an action.
*
* @param {any} object Object to test
*
* @return {object is import('redux').AnyAction} Whether object is an action.
*/
export function isAction(object) {
return isPlainObject(object) && typeof object.type === 'string';
}
/**
* Returns true if the given object quacks like an action and has a specific
* action type
*
* @param {unknown} object Object to test
* @param {string} expectedType The expected type for the action.
*
* @return {object is import('redux').AnyAction} Whether object is an action and is of specific type.
*/
export function isActionOfType(object, expectedType) {
/* eslint-enable jsdoc/valid-types */
return isAction(object) && object.type === expectedType;
}
//# sourceMappingURL=is-action.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["isPlainObject","isAction","object","type","isActionOfType","expectedType"],"sources":["@wordpress/redux-routine/src/is-action.js"],"sourcesContent":["/**\n * External dependencies\n */\nimport { isPlainObject } from 'is-plain-object';\n\n/* eslint-disable jsdoc/valid-types */\n/**\n * Returns true if the given object quacks like an action.\n *\n * @param {any} object Object to test\n *\n * @return {object is import('redux').AnyAction} Whether object is an action.\n */\nexport function isAction( object ) {\n\treturn isPlainObject( object ) && typeof object.type === 'string';\n}\n\n/**\n * Returns true if the given object quacks like an action and has a specific\n * action type\n *\n * @param {unknown} object Object to test\n * @param {string} expectedType The expected type for the action.\n *\n * @return {object is import('redux').AnyAction} Whether object is an action and is of specific type.\n */\nexport function isActionOfType( object, expectedType ) {\n\t/* eslint-enable jsdoc/valid-types */\n\treturn isAction( object ) && object.type === expectedType;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,aAAa,QAAQ,iBAAiB;;AAE/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,QAAQA,CAAEC,MAAM,EAAG;EAClC,OAAOF,aAAa,CAAEE,MAAO,CAAC,IAAI,OAAOA,MAAM,CAACC,IAAI,KAAK,QAAQ;AAClE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAEF,MAAM,EAAEG,YAAY,EAAG;EACtD;EACA,OAAOJ,QAAQ,CAAEC,MAAO,CAAC,IAAIA,MAAM,CAACC,IAAI,KAAKE,YAAY;AAC1D","ignoreList":[]}

View File

@@ -0,0 +1,17 @@
/* eslint-disable jsdoc/valid-types */
/**
* Returns true if the given object is a generator, or false otherwise.
*
* @see https://www.ecma-international.org/ecma-262/6.0/#sec-generator-objects
*
* @param {any} object Object to test.
*
* @return {object is Generator} Whether object is a generator.
*/
export default function isGenerator(object) {
/* eslint-enable jsdoc/valid-types */
// Check that iterator (next) and iterable (Symbol.iterator) interfaces are satisfied.
// These checks seem to be compatible with several generator helpers as well as the native implementation.
return !!object && typeof object[Symbol.iterator] === 'function' && typeof object.next === 'function';
}
//# sourceMappingURL=is-generator.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["isGenerator","object","Symbol","iterator","next"],"sources":["@wordpress/redux-routine/src/is-generator.js"],"sourcesContent":["/* eslint-disable jsdoc/valid-types */\n/**\n * Returns true if the given object is a generator, or false otherwise.\n *\n * @see https://www.ecma-international.org/ecma-262/6.0/#sec-generator-objects\n *\n * @param {any} object Object to test.\n *\n * @return {object is Generator} Whether object is a generator.\n */\nexport default function isGenerator( object ) {\n\t/* eslint-enable jsdoc/valid-types */\n\t// Check that iterator (next) and iterable (Symbol.iterator) interfaces are satisfied.\n\t// These checks seem to be compatible with several generator helpers as well as the native implementation.\n\treturn (\n\t\t!! object &&\n\t\ttypeof object[ Symbol.iterator ] === 'function' &&\n\t\ttypeof object.next === 'function'\n\t);\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASA,WAAWA,CAAEC,MAAM,EAAG;EAC7C;EACA;EACA;EACA,OACC,CAAC,CAAEA,MAAM,IACT,OAAOA,MAAM,CAAEC,MAAM,CAACC,QAAQ,CAAE,KAAK,UAAU,IAC/C,OAAOF,MAAM,CAACG,IAAI,KAAK,UAAU;AAEnC","ignoreList":[]}

View File

@@ -0,0 +1,2 @@
//# sourceMappingURL=rungen.d.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sources":["@wordpress/redux-routine/src/rungen.d.ts"],"sourcesContent":["declare module 'rungen' {\n\ttype Control = (\n\t\tvalue: any,\n\t\tnext: any,\n\t\titerate: any,\n\t\tyieldNext: ( result: boolean ) => void,\n\t\tyieldError: ( err: Error ) => void\n\t) => Promise< boolean > | boolean;\n\n\tfunction create(\n\t\t...args: any[]\n\t): (\n\t\taction: any,\n\t\tsuccessCallback: ( result: any ) => void,\n\t\terrorCallaback: () => void\n\t) => void;\n}\n"],"mappings":"","ignoreList":[]}

View File

@@ -0,0 +1,49 @@
/**
* External dependencies
*/
import { create } from 'rungen';
import isPromise from 'is-promise';
/**
* Internal dependencies
*/
import { isActionOfType, isAction } from './is-action';
/**
* Create a co-routine runtime.
*
* @param controls Object of control handlers.
* @param dispatch Unhandled action dispatch.
*/
export default function createRuntime(controls = {}, dispatch) {
const rungenControls = Object.entries(controls).map(([actionType, control]) => (value, next, iterate, yieldNext, yieldError) => {
if (!isActionOfType(value, actionType)) {
return false;
}
const routine = control(value);
if (isPromise(routine)) {
// Async control routine awaits resolution.
routine.then(yieldNext, yieldError);
} else {
yieldNext(routine);
}
return true;
});
const unhandledActionControl = (value, next) => {
if (!isAction(value)) {
return false;
}
dispatch(value);
next();
return true;
};
rungenControls.push(unhandledActionControl);
const rungenRuntime = create(rungenControls);
return action => new Promise((resolve, reject) => rungenRuntime(action, result => {
if (isAction(result)) {
dispatch(result);
}
resolve(result);
}, reject));
}
//# sourceMappingURL=runtime.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["create","isPromise","isActionOfType","isAction","createRuntime","controls","dispatch","rungenControls","Object","entries","map","actionType","control","value","next","iterate","yieldNext","yieldError","routine","then","unhandledActionControl","push","rungenRuntime","action","Promise","resolve","reject","result"],"sources":["@wordpress/redux-routine/src/runtime.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { Control } from 'rungen';\nimport { create } from 'rungen';\nimport isPromise from 'is-promise';\nimport type { Dispatch, AnyAction } from 'redux';\n\n/**\n * Internal dependencies\n */\nimport { isActionOfType, isAction } from './is-action';\n\n/**\n * Create a co-routine runtime.\n *\n * @param controls Object of control handlers.\n * @param dispatch Unhandled action dispatch.\n */\nexport default function createRuntime(\n\tcontrols: Record<\n\t\tstring,\n\t\t( value: any ) => Promise< boolean > | boolean\n\t> = {},\n\tdispatch: Dispatch\n) {\n\tconst rungenControls = Object.entries( controls ).map(\n\t\t( [ actionType, control ] ): Control =>\n\t\t\t( value, next, iterate, yieldNext, yieldError ) => {\n\t\t\t\tif ( ! isActionOfType( value, actionType ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tconst routine = control( value );\n\t\t\t\tif ( isPromise( routine ) ) {\n\t\t\t\t\t// Async control routine awaits resolution.\n\t\t\t\t\troutine.then( yieldNext, yieldError );\n\t\t\t\t} else {\n\t\t\t\t\tyieldNext( routine );\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t);\n\n\tconst unhandledActionControl = (\n\t\tvalue: AnyAction | unknown,\n\t\tnext: () => void\n\t) => {\n\t\tif ( ! isAction( value ) ) {\n\t\t\treturn false;\n\t\t}\n\t\tdispatch( value );\n\t\tnext();\n\t\treturn true;\n\t};\n\trungenControls.push( unhandledActionControl );\n\n\tconst rungenRuntime = create( rungenControls );\n\n\treturn ( action: AnyAction | Generator ) =>\n\t\tnew Promise( ( resolve, reject ) =>\n\t\t\trungenRuntime(\n\t\t\t\taction,\n\t\t\t\t( result ) => {\n\t\t\t\t\tif ( isAction( result ) ) {\n\t\t\t\t\t\tdispatch( result );\n\t\t\t\t\t}\n\t\t\t\t\tresolve( result );\n\t\t\t\t},\n\t\t\t\treject\n\t\t\t)\n\t\t);\n}\n"],"mappings":"AAAA;AACA;AACA;;AAEA,SAASA,MAAM,QAAQ,QAAQ;AAC/B,OAAOC,SAAS,MAAM,YAAY;AAGlC;AACA;AACA;AACA,SAASC,cAAc,EAAEC,QAAQ,QAAQ,aAAa;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,aAAaA,CACpCC,QAGC,GAAG,CAAC,CAAC,EACNC,QAAkB,EACjB;EACD,MAAMC,cAAc,GAAGC,MAAM,CAACC,OAAO,CAAEJ,QAAS,CAAC,CAACK,GAAG,CACpD,CAAE,CAAEC,UAAU,EAAEC,OAAO,CAAE,KACxB,CAAEC,KAAK,EAAEC,IAAI,EAAEC,OAAO,EAAEC,SAAS,EAAEC,UAAU,KAAM;IAClD,IAAK,CAAEf,cAAc,CAAEW,KAAK,EAAEF,UAAW,CAAC,EAAG;MAC5C,OAAO,KAAK;IACb;IACA,MAAMO,OAAO,GAAGN,OAAO,CAAEC,KAAM,CAAC;IAChC,IAAKZ,SAAS,CAAEiB,OAAQ,CAAC,EAAG;MAC3B;MACAA,OAAO,CAACC,IAAI,CAAEH,SAAS,EAAEC,UAAW,CAAC;IACtC,CAAC,MAAM;MACND,SAAS,CAAEE,OAAQ,CAAC;IACrB;IACA,OAAO,IAAI;EACZ,CACF,CAAC;EAED,MAAME,sBAAsB,GAAGA,CAC9BP,KAA0B,EAC1BC,IAAgB,KACZ;IACJ,IAAK,CAAEX,QAAQ,CAAEU,KAAM,CAAC,EAAG;MAC1B,OAAO,KAAK;IACb;IACAP,QAAQ,CAAEO,KAAM,CAAC;IACjBC,IAAI,CAAC,CAAC;IACN,OAAO,IAAI;EACZ,CAAC;EACDP,cAAc,CAACc,IAAI,CAAED,sBAAuB,CAAC;EAE7C,MAAME,aAAa,GAAGtB,MAAM,CAAEO,cAAe,CAAC;EAE9C,OAASgB,MAA6B,IACrC,IAAIC,OAAO,CAAE,CAAEC,OAAO,EAAEC,MAAM,KAC7BJ,aAAa,CACZC,MAAM,EACJI,MAAM,IAAM;IACb,IAAKxB,QAAQ,CAAEwB,MAAO,CAAC,EAAG;MACzBrB,QAAQ,CAAEqB,MAAO,CAAC;IACnB;IACAF,OAAO,CAAEE,MAAO,CAAC;EAClB,CAAC,EACDD,MACD,CACD,CAAC;AACH","ignoreList":[]}