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

21
node_modules/use-memo-one/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Alexander Reardon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

121
node_modules/use-memo-one/README.md generated vendored Normal file
View File

@@ -0,0 +1,121 @@
# useMemoOne
[`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) and [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback) with a stable cache (semantic guarantee)
[![Build Status](https://github.com/alexreardon/use-memo-one/actions?query=workflow%3AValidate)](https://github.com/alexreardon/use-memo-one/workflows/Validate/badge.svg)
[![npm](https://img.shields.io/npm/v/use-memo-one.svg)](https://www.npmjs.com/package/use-memo-one)
[![dependencies](https://david-dm.org/alexreardon/use-memo-one.svg)](https://david-dm.org/alexreardon/use-memo-one)
[![min](https://img.shields.io/bundlephobia/min/use-memo-one.svg)](https://bundlephobia.com/result?p=use-memo-one)
[![minzip](https://img.shields.io/bundlephobia/minzip/use-memo-one.svg)](https://bundlephobia.com/result?p=use-memo-one)
## Background
`useMemo` and `useCallback` cache the most recent result. However, this cache can be destroyed by `React` when it wants to:
> You may rely on useMemo as a performance optimization, **not as a semantic guarantee**. In the future, **React may choose to “forget” some previously memoized values** and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo — and then add it to optimize performance. [- React docs](https://reactjs.org/docs/hooks-reference.html#usememo)
`useMemoOne` and `useCallbackOne` are `concurrent mode` safe alternatives to `useMemo` and `useCallback` **that do provide semantic guarantee**. What this means is that you will always get the same reference for a memoized value so long as there is no input change.
Using `useMemoOne` and `useCallbackOne` will consume more memory than `useMemo` and `useCallback` in order to provide a stable cache. `React` can release the cache of `useMemo` and `useCallback`, but `useMemoOne` will not release the cache until it is garbage collected.
## Install
```bash
# npm
npm install use-memo-one --save
# yarn
yarn add use-memo-one
```
## Usage
```js
import { useMemoOne, useCallbackOne } from 'use-memo-one';
function App(props) {
const { name, age } = props;
const value = useMemoOne(() => ({ hello: name }), [name]);
const getAge = useCallbackOne(() => age, [age]);
// ...
}
```
### Aliased imports
You can use this `import` style drop in replacement for `useMemo` and `useCallback`
This style also plays very well with [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks).
```js
import { useMemo, useCallback } from 'use-memo-one';
```
⚠️ The aliased exports `useMemo` and `useCallback` will only work if you use _only_ `use-memo-one` and will clash if you also use `useMemo` or `useCallback` from `react`
```js
import { useMemo, useCallback } from 'react';
// ❌ naming clash
import { useMemo, useCallback } from 'use-memo-one';
```
## API
See [`useMemo`](https://reactjs.org/docs/hooks-reference.html#usememo) and [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback)
## Linting
`useMemo` and `useCallback` have fantastic linting rules with auto fixing in the [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks) package. In order to take advantage of these with `useMemoOne` and `useCallbackOne`, structure your import like this:
```js
import { useMemo, useCallback } from 'use-memo-one';
// Or your can alias it yourself
import {
useMemoOne as useMemo,
useCallbackOne as useCallback,
} from 'use-memo-one';
function App() {
const [isActive] = useState(false);
const onClick = useCallback(() => {
console.log('isActive', isActive);
// the input array will now be correctly checked by eslint-plugin-react-hooks
}, [isActive]);
}
```
## [`eslint`](https://eslint.org/) rules
Here are some `eslint` rules you are welcome to use
```js
module.exports = {
rules: {
// ...other rules
'no-restricted-imports': [
'error',
{
// If you want to force an application to always use useMemoOne
paths: [
{
name: 'react',
importNames: ['useMemo', 'useCallback'],
message:
'`useMemo` and `useCallback` are subject to cache busting. Please use `useMemoOne`',
},
// If you want to force use of the aliased imports from useMemoOne
{
name: 'use-memo-one',
importNames: ['useMemoOne', 'useCallbackOne'],
message:
'use-memo-one exports `useMemo` and `useCallback` which work nicer with `eslint-plugin-react-hooks`',
},
],
},
],
},
};
```

52
node_modules/use-memo-one/dist/use-memo-one.cjs.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var react = require('react');
function areInputsEqual(newInputs, lastInputs) {
if (newInputs.length !== lastInputs.length) {
return false;
}
for (var i = 0; i < newInputs.length; i++) {
if (newInputs[i] !== lastInputs[i]) {
return false;
}
}
return true;
}
function useMemoOne(getResult, inputs) {
var initial = react.useState(function () {
return {
inputs: inputs,
result: getResult()
};
})[0];
var isFirstRun = react.useRef(true);
var committed = react.useRef(initial);
var useCache = isFirstRun.current || Boolean(inputs && committed.current.inputs && areInputsEqual(inputs, committed.current.inputs));
var cache = useCache ? committed.current : {
inputs: inputs,
result: getResult()
};
react.useEffect(function () {
isFirstRun.current = false;
committed.current = cache;
}, [cache]);
return cache.result;
}
function useCallbackOne(callback, inputs) {
return useMemoOne(function () {
return callback;
}, inputs);
}
var useMemo = useMemoOne;
var useCallback = useCallbackOne;
exports.useCallback = useCallback;
exports.useCallbackOne = useCallbackOne;
exports.useMemo = useMemo;
exports.useMemoOne = useMemoOne;

View File

@@ -0,0 +1,3 @@
// @flow
export * from '../src';

45
node_modules/use-memo-one/dist/use-memo-one.esm.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
import { useState, useRef, useEffect } from 'react';
function areInputsEqual(newInputs, lastInputs) {
if (newInputs.length !== lastInputs.length) {
return false;
}
for (var i = 0; i < newInputs.length; i++) {
if (newInputs[i] !== lastInputs[i]) {
return false;
}
}
return true;
}
function useMemoOne(getResult, inputs) {
var initial = useState(function () {
return {
inputs: inputs,
result: getResult()
};
})[0];
var isFirstRun = useRef(true);
var committed = useRef(initial);
var useCache = isFirstRun.current || Boolean(inputs && committed.current.inputs && areInputsEqual(inputs, committed.current.inputs));
var cache = useCache ? committed.current : {
inputs: inputs,
result: getResult()
};
useEffect(function () {
isFirstRun.current = false;
committed.current = cache;
}, [cache]);
return cache.result;
}
function useCallbackOne(callback, inputs) {
return useMemoOne(function () {
return callback;
}, inputs);
}
var useMemo = useMemoOne;
var useCallback = useCallbackOne;
export { useCallback, useCallbackOne, useMemo, useMemoOne };

56
node_modules/use-memo-one/dist/use-memo-one.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react')) :
typeof define === 'function' && define.amd ? define(['exports', 'react'], factory) :
(global = global || self, factory(global.useMemoOne = {}, global.React));
}(this, function (exports, react) { 'use strict';
function areInputsEqual(newInputs, lastInputs) {
if (newInputs.length !== lastInputs.length) {
return false;
}
for (var i = 0; i < newInputs.length; i++) {
if (newInputs[i] !== lastInputs[i]) {
return false;
}
}
return true;
}
function useMemoOne(getResult, inputs) {
var initial = react.useState(function () {
return {
inputs: inputs,
result: getResult()
};
})[0];
var isFirstRun = react.useRef(true);
var committed = react.useRef(initial);
var useCache = isFirstRun.current || Boolean(inputs && committed.current.inputs && areInputsEqual(inputs, committed.current.inputs));
var cache = useCache ? committed.current : {
inputs: inputs,
result: getResult()
};
react.useEffect(function () {
isFirstRun.current = false;
committed.current = cache;
}, [cache]);
return cache.result;
}
function useCallbackOne(callback, inputs) {
return useMemoOne(function () {
return callback;
}, inputs);
}
var useMemo = useMemoOne;
var useCallback = useCallbackOne;
exports.useCallback = useCallback;
exports.useCallbackOne = useCallbackOne;
exports.useMemo = useMemo;
exports.useMemoOne = useMemoOne;
Object.defineProperty(exports, '__esModule', { value: true });
}));

1
node_modules/use-memo-one/dist/use-memo-one.min.js generated vendored Normal file
View File

@@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e=e||self).useMemoOne={},e.React)}(this,function(e,o){"use strict";function n(e,t){var n=o.useState(function(){return{inputs:t,result:e()}})[0],u=o.useRef(!0),r=o.useRef(n),f=u.current||Boolean(t&&r.current.inputs&&function(e,t){if(e.length!==t.length)return!1;for(var n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}(t,r.current.inputs))?r.current:{inputs:t,result:e()};return o.useEffect(function(){u.current=!1,r.current=f},[f]),f.result}function t(e,t){return n(function(){return e},t)}var u=n,r=t;e.useCallback=r,e.useCallbackOne=t,e.useMemo=u,e.useMemoOne=n,Object.defineProperty(e,"__esModule",{value:!0})});

22
node_modules/use-memo-one/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,22 @@
type DependencyList = ReadonlyArray<any>;
declare function useMemoOne<T>(
// getResult changes on every call,
getResult: () => T,
// the inputs array changes on every call
inputs: DependencyList | undefined,
): T;
declare function useCallbackOne<T extends (...args: any[]) => any>(
// getResult changes on every call,
callback: T,
// the inputs array changes on every call
inputs: DependencyList | undefined,
): T;
export {
useMemoOne,
useCallbackOne,
useMemoOne as useMemo,
useCallbackOne as useCallback
};

79
node_modules/use-memo-one/package.json generated vendored Normal file
View File

@@ -0,0 +1,79 @@
{
"name": "use-memo-one",
"version": "1.1.3",
"description": "useMemo and useCallback but with a stable cache",
"keywords": [
"memoization",
"react",
"useMemo",
"useCallback",
"memoize-one"
],
"main": "dist/use-memo-one.cjs.js",
"module": "dist/use-memo-one.esm.js",
"sideEffects": false,
"files": [
"/dist",
"/src",
"index.d.ts"
],
"author": "Alex Reardon <alexreardon@gmail.com>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/alexreardon/use-memo-one.git"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@babel/core": "^7.5.0",
"@babel/preset-env": "^7.5.2",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"babel-core": "^6.26.3",
"babel-eslint": "^10.0.2",
"babel-jest": "^24.8.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"eslint": "^6.0.1",
"eslint-config-airbnb": "^17.1.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-flowtype": "^3.11.1",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-jest": "^22.7.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-react": "^7.14.2",
"eslint-plugin-react-hooks": "^1.6.1",
"flow-bin": "^0.102.0",
"jest": "^24.8.0",
"jest-watch-typeahead": "^0.3.1",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"rimraf": "^2.6.3",
"rollup": "^1.16.7",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-commonjs": "^10.0.1",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-uglify": "^6.0.2"
},
"config": {
"prettier_target": "*.{js,jsx,md,json} src/**/*.{js,jsx,md,json} test/**/*.{js,jsx,md,json}"
},
"scripts": {
"validate": "yarn run lint && yarn run typecheck",
"test": "jest",
"typecheck": "flow check",
"prettier:check": "yarn prettier --debug-check $npm_package_config_prettier_target",
"prettier:write": "yarn prettier --write $npm_package_config_prettier_target",
"lint:eslint": "eslint src test",
"lint": "yarn lint:eslint && yarn prettier:check",
"build": "yarn run build:clean && yarn run build:dist && yarn run build:flow",
"build:clean": "rimraf dist",
"build:dist": "rollup -c",
"build:flow": "echo \"// @flow\n\nexport * from '../src';\" > dist/use-memo-one.cjs.js.flow",
"prepublish": "yarn run build"
}
}

21
node_modules/use-memo-one/src/are-inputs-equal.js generated vendored Normal file
View File

@@ -0,0 +1,21 @@
// @flow
export default function areInputsEqual(
newInputs: mixed[],
lastInputs: mixed[],
) {
// no checks needed if the inputs length has changed
if (newInputs.length !== lastInputs.length) {
return false;
}
// Using for loop for speed. It generally performs better than array.every
// https://github.com/alexreardon/memoize-one/pull/59
for (let i = 0; i < newInputs.length; i++) {
// using shallow equality check
if (newInputs[i] !== lastInputs[i]) {
return false;
}
}
return true;
}

64
node_modules/use-memo-one/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,64 @@
// @flow
import { useRef, useState, useEffect } from 'react';
import areInputsEqual from './are-inputs-equal';
type Cache<T> = {|
inputs: ?(mixed[]),
result: T,
|};
export function useMemoOne<T>(
// getResult changes on every call,
getResult: () => T,
// the inputs array changes on every call
inputs?: mixed[],
): T {
// using useState to generate initial value as it is lazy
const initial: Cache<T> = useState(() => ({
inputs,
result: getResult(),
}))[0];
const isFirstRun = useRef<boolean>(true);
const committed = useRef<Cache<T>>(initial);
// persist any uncommitted changes after they have been committed
const useCache: boolean =
isFirstRun.current ||
Boolean(
inputs &&
committed.current.inputs &&
areInputsEqual(inputs, committed.current.inputs),
);
// create a new cache if required
const cache: Cache<T> = useCache
? committed.current
: {
inputs,
result: getResult(),
};
// commit the cache
useEffect(() => {
isFirstRun.current = false;
committed.current = cache;
}, [cache]);
return cache.result;
}
export function useCallbackOne<T: Function>(
// getResult changes on every call,
callback: T,
// the inputs array changes on every call
inputs?: mixed[],
): T {
return useMemoOne(() => callback, inputs);
}
// Aliased exports
// A drop in replacement for useMemo and useCallback that plays
// very well with eslint-plugin-react-hooks
export const useMemo = useMemoOne;
export const useCallback = useCallbackOne;