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,24 @@
/**
* Build the live regions markup.
*
* @param {string} [ariaLive] Value for the 'aria-live' attribute; default: 'polite'.
*
* @return {HTMLDivElement} The ARIA live region HTML element.
*/
export default function addContainer(ariaLive = 'polite') {
const container = document.createElement('div');
container.id = `a11y-speak-${ariaLive}`;
container.className = 'a11y-speak-region';
container.setAttribute('style', 'position: absolute;' + 'margin: -1px;' + 'padding: 0;' + 'height: 1px;' + 'width: 1px;' + 'overflow: hidden;' + 'clip: rect(1px, 1px, 1px, 1px);' + '-webkit-clip-path: inset(50%);' + 'clip-path: inset(50%);' + 'border: 0;' + 'word-wrap: normal !important;');
container.setAttribute('aria-live', ariaLive);
container.setAttribute('aria-relevant', 'additions text');
container.setAttribute('aria-atomic', 'true');
const {
body
} = document;
if (body) {
body.appendChild(container);
}
return container;
}
//# sourceMappingURL=add-container.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["addContainer","ariaLive","container","document","createElement","id","className","setAttribute","body","appendChild"],"sources":["@wordpress/a11y/src/add-container.js"],"sourcesContent":["/**\n * Build the live regions markup.\n *\n * @param {string} [ariaLive] Value for the 'aria-live' attribute; default: 'polite'.\n *\n * @return {HTMLDivElement} The ARIA live region HTML element.\n */\nexport default function addContainer( ariaLive = 'polite' ) {\n\tconst container = document.createElement( 'div' );\n\tcontainer.id = `a11y-speak-${ ariaLive }`;\n\tcontainer.className = 'a11y-speak-region';\n\n\tcontainer.setAttribute(\n\t\t'style',\n\t\t'position: absolute;' +\n\t\t\t'margin: -1px;' +\n\t\t\t'padding: 0;' +\n\t\t\t'height: 1px;' +\n\t\t\t'width: 1px;' +\n\t\t\t'overflow: hidden;' +\n\t\t\t'clip: rect(1px, 1px, 1px, 1px);' +\n\t\t\t'-webkit-clip-path: inset(50%);' +\n\t\t\t'clip-path: inset(50%);' +\n\t\t\t'border: 0;' +\n\t\t\t'word-wrap: normal !important;'\n\t);\n\tcontainer.setAttribute( 'aria-live', ariaLive );\n\tcontainer.setAttribute( 'aria-relevant', 'additions text' );\n\tcontainer.setAttribute( 'aria-atomic', 'true' );\n\n\tconst { body } = document;\n\tif ( body ) {\n\t\tbody.appendChild( container );\n\t}\n\n\treturn container;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASA,YAAYA,CAAEC,QAAQ,GAAG,QAAQ,EAAG;EAC3D,MAAMC,SAAS,GAAGC,QAAQ,CAACC,aAAa,CAAE,KAAM,CAAC;EACjDF,SAAS,CAACG,EAAE,GAAI,cAAcJ,QAAU,EAAC;EACzCC,SAAS,CAACI,SAAS,GAAG,mBAAmB;EAEzCJ,SAAS,CAACK,YAAY,CACrB,OAAO,EACP,qBAAqB,GACpB,eAAe,GACf,aAAa,GACb,cAAc,GACd,aAAa,GACb,mBAAmB,GACnB,iCAAiC,GACjC,gCAAgC,GAChC,wBAAwB,GACxB,YAAY,GACZ,+BACF,CAAC;EACDL,SAAS,CAACK,YAAY,CAAE,WAAW,EAAEN,QAAS,CAAC;EAC/CC,SAAS,CAACK,YAAY,CAAE,eAAe,EAAE,gBAAiB,CAAC;EAC3DL,SAAS,CAACK,YAAY,CAAE,aAAa,EAAE,MAAO,CAAC;EAE/C,MAAM;IAAEC;EAAK,CAAC,GAAGL,QAAQ;EACzB,IAAKK,IAAI,EAAG;IACXA,IAAI,CAACC,WAAW,CAAEP,SAAU,CAAC;EAC9B;EAEA,OAAOA,SAAS;AACjB","ignoreList":[]}

View File

@@ -0,0 +1,29 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
/**
* Build the explanatory text to be placed before the aria live regions.
*
* This text is initially hidden from assistive technologies by using a `hidden`
* HTML attribute which is then removed once a message fills the aria-live regions.
*
* @return {HTMLParagraphElement} The explanatory text HTML element.
*/
export default function addIntroText() {
const introText = document.createElement('p');
introText.id = 'a11y-speak-intro-text';
introText.className = 'a11y-speak-intro-text';
introText.textContent = __('Notifications');
introText.setAttribute('style', 'position: absolute;' + 'margin: -1px;' + 'padding: 0;' + 'height: 1px;' + 'width: 1px;' + 'overflow: hidden;' + 'clip: rect(1px, 1px, 1px, 1px);' + '-webkit-clip-path: inset(50%);' + 'clip-path: inset(50%);' + 'border: 0;' + 'word-wrap: normal !important;');
introText.setAttribute('hidden', 'hidden');
const {
body
} = document;
if (body) {
body.appendChild(introText);
}
return introText;
}
//# sourceMappingURL=add-intro-text.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["__","addIntroText","introText","document","createElement","id","className","textContent","setAttribute","body","appendChild"],"sources":["@wordpress/a11y/src/add-intro-text.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\n\n/**\n * Build the explanatory text to be placed before the aria live regions.\n *\n * This text is initially hidden from assistive technologies by using a `hidden`\n * HTML attribute which is then removed once a message fills the aria-live regions.\n *\n * @return {HTMLParagraphElement} The explanatory text HTML element.\n */\nexport default function addIntroText() {\n\tconst introText = document.createElement( 'p' );\n\n\tintroText.id = 'a11y-speak-intro-text';\n\tintroText.className = 'a11y-speak-intro-text';\n\tintroText.textContent = __( 'Notifications' );\n\n\tintroText.setAttribute(\n\t\t'style',\n\t\t'position: absolute;' +\n\t\t\t'margin: -1px;' +\n\t\t\t'padding: 0;' +\n\t\t\t'height: 1px;' +\n\t\t\t'width: 1px;' +\n\t\t\t'overflow: hidden;' +\n\t\t\t'clip: rect(1px, 1px, 1px, 1px);' +\n\t\t\t'-webkit-clip-path: inset(50%);' +\n\t\t\t'clip-path: inset(50%);' +\n\t\t\t'border: 0;' +\n\t\t\t'word-wrap: normal !important;'\n\t);\n\tintroText.setAttribute( 'hidden', 'hidden' );\n\n\tconst { body } = document;\n\tif ( body ) {\n\t\tbody.appendChild( introText );\n\t}\n\n\treturn introText;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,SAASA,EAAE,QAAQ,iBAAiB;;AAEpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,YAAYA,CAAA,EAAG;EACtC,MAAMC,SAAS,GAAGC,QAAQ,CAACC,aAAa,CAAE,GAAI,CAAC;EAE/CF,SAAS,CAACG,EAAE,GAAG,uBAAuB;EACtCH,SAAS,CAACI,SAAS,GAAG,uBAAuB;EAC7CJ,SAAS,CAACK,WAAW,GAAGP,EAAE,CAAE,eAAgB,CAAC;EAE7CE,SAAS,CAACM,YAAY,CACrB,OAAO,EACP,qBAAqB,GACpB,eAAe,GACf,aAAa,GACb,cAAc,GACd,aAAa,GACb,mBAAmB,GACnB,iCAAiC,GACjC,gCAAgC,GAChC,wBAAwB,GACxB,YAAY,GACZ,+BACF,CAAC;EACDN,SAAS,CAACM,YAAY,CAAE,QAAQ,EAAE,QAAS,CAAC;EAE5C,MAAM;IAAEC;EAAK,CAAC,GAAGN,QAAQ;EACzB,IAAKM,IAAI,EAAG;IACXA,IAAI,CAACC,WAAW,CAAER,SAAU,CAAC;EAC9B;EAEA,OAAOA,SAAS;AACjB","ignoreList":[]}

16
node_modules/@wordpress/a11y/build-module/clear.js generated vendored Normal file
View File

@@ -0,0 +1,16 @@
/**
* Clears the a11y-speak-region elements and hides the explanatory text.
*/
export default function clear() {
const regions = document.getElementsByClassName('a11y-speak-region');
const introText = document.getElementById('a11y-speak-intro-text');
for (let i = 0; i < regions.length; i++) {
regions[i].textContent = '';
}
// Make sure the explanatory text is hidden from assistive technologies.
if (introText) {
introText.setAttribute('hidden', 'hidden');
}
}
//# sourceMappingURL=clear.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["clear","regions","document","getElementsByClassName","introText","getElementById","i","length","textContent","setAttribute"],"sources":["@wordpress/a11y/src/clear.js"],"sourcesContent":["/**\n * Clears the a11y-speak-region elements and hides the explanatory text.\n */\nexport default function clear() {\n\tconst regions = document.getElementsByClassName( 'a11y-speak-region' );\n\tconst introText = document.getElementById( 'a11y-speak-intro-text' );\n\n\tfor ( let i = 0; i < regions.length; i++ ) {\n\t\tregions[ i ].textContent = '';\n\t}\n\n\t// Make sure the explanatory text is hidden from assistive technologies.\n\tif ( introText ) {\n\t\tintroText.setAttribute( 'hidden', 'hidden' );\n\t}\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,eAAe,SAASA,KAAKA,CAAA,EAAG;EAC/B,MAAMC,OAAO,GAAGC,QAAQ,CAACC,sBAAsB,CAAE,mBAAoB,CAAC;EACtE,MAAMC,SAAS,GAAGF,QAAQ,CAACG,cAAc,CAAE,uBAAwB,CAAC;EAEpE,KAAM,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGL,OAAO,CAACM,MAAM,EAAED,CAAC,EAAE,EAAG;IAC1CL,OAAO,CAAEK,CAAC,CAAE,CAACE,WAAW,GAAG,EAAE;EAC9B;;EAEA;EACA,IAAKJ,SAAS,EAAG;IAChBA,SAAS,CAACK,YAAY,CAAE,QAAQ,EAAE,QAAS,CAAC;EAC7C;AACD","ignoreList":[]}

View File

@@ -0,0 +1,30 @@
let previousMessage = '';
/**
* Filter the message to be announced to the screenreader.
*
* @param {string} message The message to be announced.
*
* @return {string} The filtered message.
*/
export default function filterMessage(message) {
/*
* Strip HTML tags (if any) from the message string. Ideally, messages should
* be simple strings, carefully crafted for specific use with A11ySpeak.
* When re-using already existing strings this will ensure simple HTML to be
* stripped out and replaced with a space. Browsers will collapse multiple
* spaces natively.
*/
message = message.replace(/<[^<>]+>/g, ' ');
/*
* Safari + VoiceOver don't announce repeated, identical strings. We use
* a `no-break space` to force them to think identical strings are different.
*/
if (previousMessage === message) {
message += '\u00A0';
}
previousMessage = message;
return message;
}
//# sourceMappingURL=filter-message.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["previousMessage","filterMessage","message","replace"],"sources":["@wordpress/a11y/src/filter-message.js"],"sourcesContent":["let previousMessage = '';\n\n/**\n * Filter the message to be announced to the screenreader.\n *\n * @param {string} message The message to be announced.\n *\n * @return {string} The filtered message.\n */\nexport default function filterMessage( message ) {\n\t/*\n\t * Strip HTML tags (if any) from the message string. Ideally, messages should\n\t * be simple strings, carefully crafted for specific use with A11ySpeak.\n\t * When re-using already existing strings this will ensure simple HTML to be\n\t * stripped out and replaced with a space. Browsers will collapse multiple\n\t * spaces natively.\n\t */\n\tmessage = message.replace( /<[^<>]+>/g, ' ' );\n\n\t/*\n\t * Safari + VoiceOver don't announce repeated, identical strings. We use\n\t * a `no-break space` to force them to think identical strings are different.\n\t */\n\tif ( previousMessage === message ) {\n\t\tmessage += '\\u00A0';\n\t}\n\n\tpreviousMessage = message;\n\n\treturn message;\n}\n"],"mappings":"AAAA,IAAIA,eAAe,GAAG,EAAE;;AAExB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,SAASC,aAAaA,CAAEC,OAAO,EAAG;EAChD;AACD;AACA;AACA;AACA;AACA;AACA;EACCA,OAAO,GAAGA,OAAO,CAACC,OAAO,CAAE,WAAW,EAAE,GAAI,CAAC;;EAE7C;AACD;AACA;AACA;EACC,IAAKH,eAAe,KAAKE,OAAO,EAAG;IAClCA,OAAO,IAAI,QAAQ;EACpB;EAEAF,eAAe,GAAGE,OAAO;EAEzB,OAAOA,OAAO;AACf","ignoreList":[]}

79
node_modules/@wordpress/a11y/build-module/index.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
/**
* WordPress dependencies
*/
import domReady from '@wordpress/dom-ready';
/**
* Internal dependencies
*/
import addIntroText from './add-intro-text';
import addContainer from './add-container';
import clear from './clear';
import filterMessage from './filter-message';
/**
* Create the live regions.
*/
export function setup() {
const introText = document.getElementById('a11y-speak-intro-text');
const containerAssertive = document.getElementById('a11y-speak-assertive');
const containerPolite = document.getElementById('a11y-speak-polite');
if (introText === null) {
addIntroText();
}
if (containerAssertive === null) {
addContainer('assertive');
}
if (containerPolite === null) {
addContainer('polite');
}
}
/**
* Run setup on domReady.
*/
domReady(setup);
/**
* Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions.
* This module is inspired by the `speak` function in `wp-a11y.js`.
*
* @param {string} message The message to be announced by assistive technologies.
* @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'.
*
* @example
* ```js
* import { speak } from '@wordpress/a11y';
*
* // For polite messages that shouldn't interrupt what screen readers are currently announcing.
* speak( 'The message you want to send to the ARIA live region' );
*
* // For assertive messages that should interrupt what screen readers are currently announcing.
* speak( 'The message you want to send to the ARIA live region', 'assertive' );
* ```
*/
export function speak(message, ariaLive) {
/*
* Clear previous messages to allow repeated strings being read out and hide
* the explanatory text from assistive technologies.
*/
clear();
message = filterMessage(message);
const introText = document.getElementById('a11y-speak-intro-text');
const containerAssertive = document.getElementById('a11y-speak-assertive');
const containerPolite = document.getElementById('a11y-speak-polite');
if (containerAssertive && ariaLive === 'assertive') {
containerAssertive.textContent = message;
} else if (containerPolite) {
containerPolite.textContent = message;
}
/*
* Make the explanatory text available to assistive technologies by removing
* the 'hidden' HTML attribute.
*/
if (introText) {
introText.removeAttribute('hidden');
}
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["domReady","addIntroText","addContainer","clear","filterMessage","setup","introText","document","getElementById","containerAssertive","containerPolite","speak","message","ariaLive","textContent","removeAttribute"],"sources":["@wordpress/a11y/src/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport domReady from '@wordpress/dom-ready';\n\n/**\n * Internal dependencies\n */\nimport addIntroText from './add-intro-text';\nimport addContainer from './add-container';\nimport clear from './clear';\nimport filterMessage from './filter-message';\n\n/**\n * Create the live regions.\n */\nexport function setup() {\n\tconst introText = document.getElementById( 'a11y-speak-intro-text' );\n\tconst containerAssertive = document.getElementById(\n\t\t'a11y-speak-assertive'\n\t);\n\tconst containerPolite = document.getElementById( 'a11y-speak-polite' );\n\n\tif ( introText === null ) {\n\t\taddIntroText();\n\t}\n\n\tif ( containerAssertive === null ) {\n\t\taddContainer( 'assertive' );\n\t}\n\n\tif ( containerPolite === null ) {\n\t\taddContainer( 'polite' );\n\t}\n}\n\n/**\n * Run setup on domReady.\n */\ndomReady( setup );\n\n/**\n * Allows you to easily announce dynamic interface updates to screen readers using ARIA live regions.\n * This module is inspired by the `speak` function in `wp-a11y.js`.\n *\n * @param {string} message The message to be announced by assistive technologies.\n * @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'.\n *\n * @example\n * ```js\n * import { speak } from '@wordpress/a11y';\n *\n * // For polite messages that shouldn't interrupt what screen readers are currently announcing.\n * speak( 'The message you want to send to the ARIA live region' );\n *\n * // For assertive messages that should interrupt what screen readers are currently announcing.\n * speak( 'The message you want to send to the ARIA live region', 'assertive' );\n * ```\n */\nexport function speak( message, ariaLive ) {\n\t/*\n\t * Clear previous messages to allow repeated strings being read out and hide\n\t * the explanatory text from assistive technologies.\n\t */\n\tclear();\n\n\tmessage = filterMessage( message );\n\n\tconst introText = document.getElementById( 'a11y-speak-intro-text' );\n\tconst containerAssertive = document.getElementById(\n\t\t'a11y-speak-assertive'\n\t);\n\tconst containerPolite = document.getElementById( 'a11y-speak-polite' );\n\n\tif ( containerAssertive && ariaLive === 'assertive' ) {\n\t\tcontainerAssertive.textContent = message;\n\t} else if ( containerPolite ) {\n\t\tcontainerPolite.textContent = message;\n\t}\n\n\t/*\n\t * Make the explanatory text available to assistive technologies by removing\n\t * the 'hidden' HTML attribute.\n\t */\n\tif ( introText ) {\n\t\tintroText.removeAttribute( 'hidden' );\n\t}\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAOA,QAAQ,MAAM,sBAAsB;;AAE3C;AACA;AACA;AACA,OAAOC,YAAY,MAAM,kBAAkB;AAC3C,OAAOC,YAAY,MAAM,iBAAiB;AAC1C,OAAOC,KAAK,MAAM,SAAS;AAC3B,OAAOC,aAAa,MAAM,kBAAkB;;AAE5C;AACA;AACA;AACA,OAAO,SAASC,KAAKA,CAAA,EAAG;EACvB,MAAMC,SAAS,GAAGC,QAAQ,CAACC,cAAc,CAAE,uBAAwB,CAAC;EACpE,MAAMC,kBAAkB,GAAGF,QAAQ,CAACC,cAAc,CACjD,sBACD,CAAC;EACD,MAAME,eAAe,GAAGH,QAAQ,CAACC,cAAc,CAAE,mBAAoB,CAAC;EAEtE,IAAKF,SAAS,KAAK,IAAI,EAAG;IACzBL,YAAY,CAAC,CAAC;EACf;EAEA,IAAKQ,kBAAkB,KAAK,IAAI,EAAG;IAClCP,YAAY,CAAE,WAAY,CAAC;EAC5B;EAEA,IAAKQ,eAAe,KAAK,IAAI,EAAG;IAC/BR,YAAY,CAAE,QAAS,CAAC;EACzB;AACD;;AAEA;AACA;AACA;AACAF,QAAQ,CAAEK,KAAM,CAAC;;AAEjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,KAAKA,CAAEC,OAAO,EAAEC,QAAQ,EAAG;EAC1C;AACD;AACA;AACA;EACCV,KAAK,CAAC,CAAC;EAEPS,OAAO,GAAGR,aAAa,CAAEQ,OAAQ,CAAC;EAElC,MAAMN,SAAS,GAAGC,QAAQ,CAACC,cAAc,CAAE,uBAAwB,CAAC;EACpE,MAAMC,kBAAkB,GAAGF,QAAQ,CAACC,cAAc,CACjD,sBACD,CAAC;EACD,MAAME,eAAe,GAAGH,QAAQ,CAACC,cAAc,CAAE,mBAAoB,CAAC;EAEtE,IAAKC,kBAAkB,IAAII,QAAQ,KAAK,WAAW,EAAG;IACrDJ,kBAAkB,CAACK,WAAW,GAAGF,OAAO;EACzC,CAAC,MAAM,IAAKF,eAAe,EAAG;IAC7BA,eAAe,CAACI,WAAW,GAAGF,OAAO;EACtC;;EAEA;AACD;AACA;AACA;EACC,IAAKN,SAAS,EAAG;IAChBA,SAAS,CAACS,eAAe,CAAE,QAAS,CAAC;EACtC;AACD","ignoreList":[]}

View File

@@ -0,0 +1,17 @@
/**
* Internal dependencies
*/
import filterMessage from './filter-message';
/**
* Update the ARIA live notification area text node.
*
* @param {string} message The message to be announced by Assistive Technologies.
* @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'.
*/
export function speak(message, ariaLive) {
message = filterMessage(message);
// TODO: Use native module to speak message.
if (ariaLive === 'assertive') {} else {}
}
//# sourceMappingURL=index.native.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["filterMessage","speak","message","ariaLive"],"sources":["@wordpress/a11y/src/index.native.js"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport filterMessage from './filter-message';\n\n/**\n * Update the ARIA live notification area text node.\n *\n * @param {string} message The message to be announced by Assistive Technologies.\n * @param {string} [ariaLive] The politeness level for aria-live; default: 'polite'.\n */\nexport function speak( message, ariaLive ) {\n\tmessage = filterMessage( message );\n\t// TODO: Use native module to speak message.\n\tif ( ariaLive === 'assertive' ) {\n\t} else {\n\t}\n}\n"],"mappings":"AAAA;AACA;AACA;AACA,OAAOA,aAAa,MAAM,kBAAkB;;AAE5C;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,KAAKA,CAAEC,OAAO,EAAEC,QAAQ,EAAG;EAC1CD,OAAO,GAAGF,aAAa,CAAEE,OAAQ,CAAC;EAClC;EACA,IAAKC,QAAQ,KAAK,WAAW,EAAG,CAChC,CAAC,MAAM,CACP;AACD","ignoreList":[]}