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,13 @@
# Block Quotation
A drop-in replacement for the HTML [blockquote](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/blockquote) element that works both on the web and in the mobile apps. It indicates that the enclosed text is an extended quotation.
## Usage
```jsx
import { BlockQuotation } from '@wordpress/components';
const MyBlockQuotation = () => (
<BlockQuotation>...Quote content</BlockQuotation>
);
```

View File

@@ -0,0 +1 @@
export const BlockQuotation = 'blockquote';

View File

@@ -0,0 +1,59 @@
/**
* External dependencies
*/
import { View } from 'react-native';
/**
* WordPress dependencies
*/
import { Children, cloneElement, forwardRef } from '@wordpress/element';
import { usePreferredColorSchemeStyle } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './style.scss';
export const BlockQuotation = forwardRef( ( { ...props }, ref ) => {
const { style } = props;
const blockQuoteStyle = [
usePreferredColorSchemeStyle(
styles.wpBlockQuoteLight,
styles.wpBlockQuoteDark
),
style?.baseColors?.color?.text && {
borderLeftColor: style.baseColors.color.text,
},
style?.color && {
borderLeftColor: style.color,
},
style,
style?.backgroundColor && styles.paddingWithBackground,
];
const colorStyle = style?.color ? { color: style.color } : {};
const newChildren = Children.map( props.children, ( child ) => {
const { identifier, attributeKey } = child?.props || {};
const identifierKey = identifier ?? attributeKey;
if ( identifierKey === 'citation' ) {
return cloneElement( child, {
style: {
...styles.wpBlockQuoteCitation,
...colorStyle,
},
} );
}
if ( child && child.props.identifier === 'value' ) {
return cloneElement( child, {
tagsToEliminate: [ 'div' ],
style: colorStyle,
} );
}
return child;
} );
return (
<View ref={ ref } style={ blockQuoteStyle }>
{ newChildren }
</View>
);
} );

View File

@@ -0,0 +1,25 @@
%wpBlockQuote-shared {
border-left-width: 4px;
border-left-style: solid;
padding-left: $block-edge-to-content;
margin-left: 0;
}
.wpBlockQuoteLight {
@extend %wpBlockQuote-shared;
border-left-color: $black;
}
.wpBlockQuoteDark {
@extend %wpBlockQuote-shared;
border-left-color: $white;
}
.wpBlockQuoteCitation {
margin-top: 16px;
font-size: 14px;
}
.paddingWithBackground {
padding-top: $block-edge-to-content - $block-selected-margin;
}

View File

@@ -0,0 +1,11 @@
# HorizontalRule
A drop-in replacement for the HTML [hr](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/hr) element that works both on the web and in the mobile apps. It represents a thematic break between paragraph-level elements: for example, a change of scene in a story, or a shift of topic within a section.
## Usage
```jsx
import { HorizontalRule } from '@wordpress/components';
const MyHorizontalRule = () => <HorizontalRule />;
```

View File

@@ -0,0 +1 @@
export const HorizontalRule = 'hr';

View File

@@ -0,0 +1,59 @@
/**
* External dependencies
*/
import { Text, View } from 'react-native';
/**
* WordPress dependencies
*/
import { withPreferredColorScheme } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './styles.scss';
const HR = ( {
getStylesFromColorScheme,
lineStyle,
marginLeft,
marginRight,
style,
textStyle,
text,
...props
} ) => {
const renderLine = ( key ) => (
<View
key={ key }
style={ [
getStylesFromColorScheme( styles.line, styles.lineDark ),
lineStyle,
] }
/>
);
const renderText = ( key ) => (
<View key={ key } style={ styles.textContainer }>
<Text style={ [ styles.text, textStyle ] }>{ text }</Text>
</View>
);
const renderInner = () => {
if ( ! text ) {
return renderLine();
}
return [ renderLine( 1 ), renderText( 2 ), renderLine( 3 ) ];
};
return (
<View
style={ [ styles.container, { marginLeft, marginRight }, style ] }
{ ...props }
>
{ renderInner() }
</View>
);
};
export const HorizontalRule = withPreferredColorScheme( HR );

View File

@@ -0,0 +1,26 @@
.container {
align-items: center;
flex-direction: row;
margin-left: 0;
margin-right: 0;
}
.line {
background-color: $gray-lighten-20;
flex: 1 0 10px;
height: 2;
}
.lineDark {
background-color: $gray-50;
}
.textContainer {
flex: 0 1 auto;
margin-left: 15px;
margin-right: 15px;
}
.text {
text-align: center;
}

4
node_modules/@wordpress/primitives/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
export * from './svg';
export * from './horizontal-rule';
export * from './block-quotation';
export * from './view';

20
node_modules/@wordpress/primitives/src/svg/README.md generated vendored Normal file
View File

@@ -0,0 +1,20 @@
# SVG
A drop-in replacement for the svg element that adds the required accessibility attributes for SVG elements across browsers.
## Usage
```jsx
import { G, Path, SVG } from '@wordpress/components';
const MyIcon = () => (
<SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<Path fill="none" d="M0 0h24v24H0V0z" />
<G>
<Path d="M20 4v12H8V4h12m0-2H8L6 4v12l2 2h12l2-2V4l-2-2z" />
<Path d="M12 12l1 2 3-3 3 4H9z" />
<Path d="M2 6v14l2 2h14v-2H4V6H2z" />
</G>
</SVG>
);
```

107
node_modules/@wordpress/primitives/src/svg/index.js generated vendored Normal file
View File

@@ -0,0 +1,107 @@
/**
* External dependencies
*/
import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { createElement, forwardRef } from '@wordpress/element';
/** @typedef {{isPressed?: boolean} & import('react').ComponentPropsWithoutRef<'svg'>} SVGProps */
/**
* @param {import('react').ComponentPropsWithoutRef<'circle'>} props
*
* @return {JSX.Element} Circle component
*/
export const Circle = ( props ) => createElement( 'circle', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'g'>} props
*
* @return {JSX.Element} G component
*/
export const G = ( props ) => createElement( 'g', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'line'>} props
*
* @return {JSX.Element} Path component
*/
export const Line = ( props ) => createElement( 'line', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'path'>} props
*
* @return {JSX.Element} Path component
*/
export const Path = ( props ) => createElement( 'path', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'polygon'>} props
*
* @return {JSX.Element} Polygon component
*/
export const Polygon = ( props ) => createElement( 'polygon', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'rect'>} props
*
* @return {JSX.Element} Rect component
*/
export const Rect = ( props ) => createElement( 'rect', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'defs'>} props
*
* @return {JSX.Element} Defs component
*/
export const Defs = ( props ) => createElement( 'defs', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'radialGradient'>} props
*
* @return {JSX.Element} RadialGradient component
*/
export const RadialGradient = ( props ) =>
createElement( 'radialGradient', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'linearGradient'>} props
*
* @return {JSX.Element} LinearGradient component
*/
export const LinearGradient = ( props ) =>
createElement( 'linearGradient', props );
/**
* @param {import('react').ComponentPropsWithoutRef<'stop'>} props
*
* @return {JSX.Element} Stop component
*/
export const Stop = ( props ) => createElement( 'stop', props );
export const SVG = forwardRef(
/**
* @param {SVGProps} props isPressed indicates whether the SVG should appear as pressed.
* Other props will be passed through to svg component.
* @param {import('react').ForwardedRef<SVGSVGElement>} ref The forwarded ref to the SVG element.
*
* @return {JSX.Element} Stop component
*/
( { className, isPressed, ...props }, ref ) => {
const appliedProps = {
...props,
className:
clsx( className, { 'is-pressed': isPressed } ) || undefined,
'aria-hidden': true,
focusable: false,
};
// Disable reason: We need to have a way to render HTML tag for web.
// eslint-disable-next-line react/forbid-elements
return <svg { ...appliedProps } ref={ ref } />;
}
);
SVG.displayName = 'SVG';

View File

@@ -0,0 +1,75 @@
/**
* External dependencies
*/
import { Svg } from 'react-native-svg';
import { Animated } from 'react-native';
/**
* WordPress dependencies
*/
import { forwardRef } from '@wordpress/element';
import { usePreferredColorScheme } from '@wordpress/compose';
/**
* Internal dependencies
*/
import styles from './style.scss';
export {
Circle,
G,
Path,
Polygon,
Rect,
Defs,
RadialGradient,
LinearGradient,
Stop,
Line,
SvgXml,
} from 'react-native-svg';
const AnimatedSvg = Animated.createAnimatedComponent(
forwardRef( ( props, ref ) => <Svg ref={ ref } { ...props } /> )
);
export const SVG = ( {
className = '',
isPressed,
animated = false,
...props
} ) => {
const colorScheme = usePreferredColorScheme();
const stylesFromClasses = className
.split( ' ' )
.map( ( element ) => styles[ element ] )
.filter( Boolean );
const defaultStyle = isPressed
? styles[ `is-pressed--${ colorScheme }` ]
: styles[ 'components-toolbar__control-' + colorScheme ];
const propStyle = Array.isArray( props.style )
? props.style.reduce( ( acc, el ) => {
return { ...acc, ...el };
}, {} )
: props.style;
const styleValues = Object.assign(
{},
defaultStyle,
propStyle,
...stylesFromClasses
);
const appliedProps = { ...props, style: styleValues };
const SvgWrapper = animated ? AnimatedSvg : Svg;
return (
<SvgWrapper
// We want to re-render when style color is changed.
key={ appliedProps.style.color }
height="100%"
width="100%"
{ ...appliedProps }
/>
);
};

View File

@@ -0,0 +1,51 @@
.dashicon-light,
.components-toolbar__control-light {
color: $light-primary;
fill: currentColor;
}
.dashicon-dark,
.components-toolbar__control-dark {
color: $dark-primary;
fill: currentColor;
}
.dashicon-active {
color: #fff;
fill: currentColor;
}
.is-pressed--light {
color: $light-primary;
fill: currentColor;
}
.is-pressed--dark {
color: $dark-primary;
fill: currentColor;
}
.dashicons-insert {
color: #87a6bc;
fill: currentColor;
}
.unsupported-icon-light {
color: $gray-dark;
fill: currentColor;
}
.unsupported-icon-dark {
color: $white;
fill: currentColor;
}
.warning-icon-light {
color: $gray-dark;
fill: currentColor;
}
.warning-icon-dark {
color: $white;
fill: currentColor;
}

View File

@@ -0,0 +1,3 @@
# View
A drop-in replacement for the div element that works across devices.

1
node_modules/@wordpress/primitives/src/view/index.js generated vendored Normal file
View File

@@ -0,0 +1 @@
export const View = 'div';

View File

@@ -0,0 +1,4 @@
/**
* External dependencies
*/
export { View } from 'react-native';