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,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.ToolsPanelItem = void 0;
var _react = require("react");
var _hook = require("./hook");
var _view = require("../../view");
var _context = require("../../context");
/**
* External dependencies
*/
/**
* Internal dependencies
*/
// This wraps controls to be conditionally displayed within a tools panel. It
// prevents props being applied to HTML elements that would make them invalid.
const UnconnectedToolsPanelItem = (props, forwardedRef) => {
const {
children,
isShown,
shouldRenderPlaceholder,
...toolsPanelItemProps
} = (0, _hook.useToolsPanelItem)(props);
if (!isShown) {
return shouldRenderPlaceholder ? (0, _react.createElement)(_view.View, {
...toolsPanelItemProps,
ref: forwardedRef
}) : null;
}
return (0, _react.createElement)(_view.View, {
...toolsPanelItemProps,
ref: forwardedRef
}, children);
};
const ToolsPanelItem = (0, _context.contextConnect)(UnconnectedToolsPanelItem, 'ToolsPanelItem');
exports.ToolsPanelItem = ToolsPanelItem;
var _default = ToolsPanelItem;
exports.default = _default;
//# sourceMappingURL=component.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_hook","require","_view","_context","UnconnectedToolsPanelItem","props","forwardedRef","children","isShown","shouldRenderPlaceholder","toolsPanelItemProps","useToolsPanelItem","_react","createElement","View","ref","ToolsPanelItem","contextConnect","exports","_default","default"],"sources":["@wordpress/components/src/tools-panel/tools-panel-item/component.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { useToolsPanelItem } from './hook';\nimport { View } from '../../view';\nimport type { WordPressComponentProps } from '../../context';\nimport { contextConnect } from '../../context';\nimport type { ToolsPanelItemProps } from '../types';\n\n// This wraps controls to be conditionally displayed within a tools panel. It\n// prevents props being applied to HTML elements that would make them invalid.\nconst UnconnectedToolsPanelItem = (\n\tprops: WordPressComponentProps< ToolsPanelItemProps, 'div' >,\n\tforwardedRef: ForwardedRef< any >\n) => {\n\tconst {\n\t\tchildren,\n\t\tisShown,\n\t\tshouldRenderPlaceholder,\n\t\t...toolsPanelItemProps\n\t} = useToolsPanelItem( props );\n\n\tif ( ! isShown ) {\n\t\treturn shouldRenderPlaceholder ? (\n\t\t\t<View { ...toolsPanelItemProps } ref={ forwardedRef } />\n\t\t) : null;\n\t}\n\n\treturn (\n\t\t<View { ...toolsPanelItemProps } ref={ forwardedRef }>\n\t\t\t{ children }\n\t\t</View>\n\t);\n};\n\nexport const ToolsPanelItem = contextConnect(\n\tUnconnectedToolsPanelItem,\n\t'ToolsPanelItem'\n);\n\nexport default ToolsPanelItem;\n"],"mappings":";;;;;;;AAQA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AAEA,IAAAE,QAAA,GAAAF,OAAA;AAXA;AACA;AACA;;AAGA;AACA;AACA;;AAOA;AACA;AACA,MAAMG,yBAAyB,GAAGA,CACjCC,KAA4D,EAC5DC,YAAiC,KAC7B;EACJ,MAAM;IACLC,QAAQ;IACRC,OAAO;IACPC,uBAAuB;IACvB,GAAGC;EACJ,CAAC,GAAG,IAAAC,uBAAiB,EAAEN,KAAM,CAAC;EAE9B,IAAK,CAAEG,OAAO,EAAG;IAChB,OAAOC,uBAAuB,GAC7B,IAAAG,MAAA,CAAAC,aAAA,EAACX,KAAA,CAAAY,IAAI;MAAA,GAAMJ,mBAAmB;MAAGK,GAAG,EAAGT;IAAc,CAAE,CAAC,GACrD,IAAI;EACT;EAEA,OACC,IAAAM,MAAA,CAAAC,aAAA,EAACX,KAAA,CAAAY,IAAI;IAAA,GAAMJ,mBAAmB;IAAGK,GAAG,EAAGT;EAAc,GAClDC,QACG,CAAC;AAET,CAAC;AAEM,MAAMS,cAAc,GAAG,IAAAC,uBAAc,EAC3Cb,yBAAyB,EACzB,gBACD,CAAC;AAACc,OAAA,CAAAF,cAAA,GAAAA,cAAA;AAAA,IAAAG,QAAA,GAEaH,cAAc;AAAAE,OAAA,CAAAE,OAAA,GAAAD,QAAA"}

View File

@@ -0,0 +1,148 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useToolsPanelItem = useToolsPanelItem;
var _compose = require("@wordpress/compose");
var _element = require("@wordpress/element");
var styles = _interopRequireWildcard(require("../styles"));
var _context = require("../context");
var _context2 = require("../../context");
var _useCx = require("../../utils/hooks/use-cx");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
const noop = () => {};
function useToolsPanelItem(props) {
const {
className,
hasValue,
isShownByDefault = false,
label,
panelId,
resetAllFilter = noop,
onDeselect,
onSelect,
...otherProps
} = (0, _context2.useContextSystem)(props, 'ToolsPanelItem');
const {
panelId: currentPanelId,
menuItems,
registerResetAllFilter,
deregisterResetAllFilter,
registerPanelItem,
deregisterPanelItem,
flagItemCustomization,
isResetting,
shouldRenderPlaceholderItems: shouldRenderPlaceholder,
firstDisplayedItem,
lastDisplayedItem,
__experimentalFirstVisibleItemClass,
__experimentalLastVisibleItemClass
} = (0, _context.useToolsPanelContext)();
// hasValue is a new function on every render, so do not add it as a
// dependency to the useCallback hook! If needed, we should use a ref.
// eslint-disable-next-line react-hooks/exhaustive-deps
const hasValueCallback = (0, _element.useCallback)(hasValue, [panelId]);
// resetAllFilter is a new function on every render, so do not add it as a
// dependency to the useCallback hook! If needed, we should use a ref.
// eslint-disable-next-line react-hooks/exhaustive-deps
const resetAllFilterCallback = (0, _element.useCallback)(resetAllFilter, [panelId]);
const previousPanelId = (0, _compose.usePrevious)(currentPanelId);
const hasMatchingPanel = currentPanelId === panelId || currentPanelId === null;
// Registering the panel item allows the panel to include it in its
// automatically generated menu and determine its initial checked status.
//
// This is performed in a layout effect to ensure that the panel item
// is registered before it is rendered preventing a rendering glitch.
// See: https://github.com/WordPress/gutenberg/issues/56470
(0, _element.useLayoutEffect)(() => {
if (hasMatchingPanel && previousPanelId !== null) {
registerPanelItem({
hasValue: hasValueCallback,
isShownByDefault,
label,
panelId
});
}
return () => {
if (previousPanelId === null && !!currentPanelId || currentPanelId === panelId) {
deregisterPanelItem(label);
}
};
}, [currentPanelId, hasMatchingPanel, isShownByDefault, label, hasValueCallback, panelId, previousPanelId, registerPanelItem, deregisterPanelItem]);
(0, _element.useEffect)(() => {
if (hasMatchingPanel) {
registerResetAllFilter(resetAllFilterCallback);
}
return () => {
if (hasMatchingPanel) {
deregisterResetAllFilter(resetAllFilterCallback);
}
};
}, [registerResetAllFilter, deregisterResetAllFilter, resetAllFilterCallback, hasMatchingPanel]);
// Note: `label` is used as a key when building menu item state in
// `ToolsPanel`.
const menuGroup = isShownByDefault ? 'default' : 'optional';
const isMenuItemChecked = menuItems?.[menuGroup]?.[label];
const wasMenuItemChecked = (0, _compose.usePrevious)(isMenuItemChecked);
const isRegistered = menuItems?.[menuGroup]?.[label] !== undefined;
const isValueSet = hasValue();
const wasValueSet = (0, _compose.usePrevious)(isValueSet);
const newValueSet = isValueSet && !wasValueSet;
// Notify the panel when an item's value has been set.
(0, _element.useEffect)(() => {
if (!newValueSet) {
return;
}
flagItemCustomization(label, menuGroup);
}, [newValueSet, menuGroup, label, flagItemCustomization]);
// Determine if the panel item's corresponding menu is being toggled and
// trigger appropriate callback if it is.
(0, _element.useEffect)(() => {
// We check whether this item is currently registered as items rendered
// via fills can persist through the parent panel being remounted.
// See: https://github.com/WordPress/gutenberg/pull/45673
if (!isRegistered || isResetting || !hasMatchingPanel) {
return;
}
if (isMenuItemChecked && !isValueSet && !wasMenuItemChecked) {
onSelect?.();
}
if (!isMenuItemChecked && wasMenuItemChecked) {
onDeselect?.();
}
}, [hasMatchingPanel, isMenuItemChecked, isRegistered, isResetting, isValueSet, wasMenuItemChecked, onSelect, onDeselect]);
// The item is shown if it is a default control regardless of whether it
// has a value. Optional items are shown when they are checked or have
// a value.
const isShown = isShownByDefault ? menuItems?.[menuGroup]?.[label] !== undefined : isMenuItemChecked;
const cx = (0, _useCx.useCx)();
const classes = (0, _element.useMemo)(() => {
const shouldApplyPlaceholderStyles = shouldRenderPlaceholder && !isShown;
const firstItemStyle = firstDisplayedItem === label && __experimentalFirstVisibleItemClass;
const lastItemStyle = lastDisplayedItem === label && __experimentalLastVisibleItemClass;
return cx(styles.ToolsPanelItem, shouldApplyPlaceholderStyles && styles.ToolsPanelItemPlaceholder, !shouldApplyPlaceholderStyles && className, firstItemStyle, lastItemStyle);
}, [isShown, shouldRenderPlaceholder, className, cx, firstDisplayedItem, lastDisplayedItem, __experimentalFirstVisibleItemClass, __experimentalLastVisibleItemClass, label]);
return {
...otherProps,
isShown,
shouldRenderPlaceholder,
className: classes
};
}
//# sourceMappingURL=hook.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function () {
return _component.default;
}
});
Object.defineProperty(exports, "useToolsPanelItem", {
enumerable: true,
get: function () {
return _hook.useToolsPanelItem;
}
});
var _component = _interopRequireDefault(require("./component"));
var _hook = require("./hook");
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["_component","_interopRequireDefault","require","_hook"],"sources":["@wordpress/components/src/tools-panel/tools-panel-item/index.ts"],"sourcesContent":["export { default } from './component';\nexport { useToolsPanelItem } from './hook';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA"}