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,23 @@
import { createElement } from "react";
/**
* WordPress dependencies
*/
import { memo } from '@wordpress/element';
/**
* Internal dependencies
*/
import { BackdropUI } from './styles/input-control-styles';
function Backdrop({
disabled = false,
isFocused = false
}) {
return createElement(BackdropUI, {
"aria-hidden": "true",
className: "components-input-control__backdrop",
disabled: disabled,
isFocused: isFocused
});
}
const MemoizedBackdrop = memo(Backdrop);
export default MemoizedBackdrop;
//# sourceMappingURL=backdrop.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["memo","BackdropUI","Backdrop","disabled","isFocused","createElement","className","MemoizedBackdrop"],"sources":["@wordpress/components/src/input-control/backdrop.tsx"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { memo } from '@wordpress/element';\n/**\n * Internal dependencies\n */\nimport { BackdropUI } from './styles/input-control-styles';\n\nfunction Backdrop( { disabled = false, isFocused = false } ) {\n\treturn (\n\t\t<BackdropUI\n\t\t\taria-hidden=\"true\"\n\t\t\tclassName=\"components-input-control__backdrop\"\n\t\t\tdisabled={ disabled }\n\t\t\tisFocused={ isFocused }\n\t\t/>\n\t);\n}\n\nconst MemoizedBackdrop = memo( Backdrop );\n\nexport default MemoizedBackdrop;\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,IAAI,QAAQ,oBAAoB;AACzC;AACA;AACA;AACA,SAASC,UAAU,QAAQ,+BAA+B;AAE1D,SAASC,QAAQA,CAAE;EAAEC,QAAQ,GAAG,KAAK;EAAEC,SAAS,GAAG;AAAM,CAAC,EAAG;EAC5D,OACCC,aAAA,CAACJ,UAAU;IACV,eAAY,MAAM;IAClBK,SAAS,EAAC,oCAAoC;IAC9CH,QAAQ,EAAGA,QAAU;IACrBC,SAAS,EAAGA;EAAW,CACvB,CAAC;AAEJ;AAEA,MAAMG,gBAAgB,GAAGP,IAAI,CAAEE,QAAS,CAAC;AAEzC,eAAeK,gBAAgB"}

View File

@@ -0,0 +1,127 @@
import { createElement } from "react";
/**
* External dependencies
*/
import classNames from 'classnames';
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { useState, forwardRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import InputBase from './input-base';
import InputField from './input-field';
import { space } from '../utils/space';
import { useDraft } from './utils';
import BaseControl from '../base-control';
import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props';
const noop = () => {};
function useUniqueId(idProp) {
const instanceId = useInstanceId(InputControl);
const id = `inspector-input-control-${instanceId}`;
return idProp || id;
}
export function UnforwardedInputControl(props, ref) {
const {
__next40pxDefaultSize,
__unstableStateReducer: stateReducer = state => state,
__unstableInputWidth,
className,
disabled = false,
help,
hideLabelFromVision = false,
id: idProp,
isPressEnterToChange = false,
label,
labelPosition = 'top',
onChange = noop,
onValidate = noop,
onKeyDown = noop,
prefix,
size = 'default',
style,
suffix,
value,
...restProps
} = useDeprecated36pxDefaultSizeProp(props, 'wp.components.InputControl', '6.4');
const [isFocused, setIsFocused] = useState(false);
const id = useUniqueId(idProp);
const classes = classNames('components-input-control', className);
const draftHookProps = useDraft({
value,
onBlur: restProps.onBlur,
onChange
});
// ARIA descriptions can only contain plain text, so fall back to aria-details if not.
const helpPropName = typeof help === 'string' ? 'aria-describedby' : 'aria-details';
const helpProp = !!help ? {
[helpPropName]: `${id}__help`
} : {};
return createElement(BaseControl, {
className: classes,
help: help,
id: id,
__nextHasNoMarginBottom: true
}, createElement(InputBase, {
__next40pxDefaultSize: __next40pxDefaultSize,
__unstableInputWidth: __unstableInputWidth,
disabled: disabled,
gap: 3,
hideLabelFromVision: hideLabelFromVision,
id: id,
isFocused: isFocused,
justify: "left",
label: label,
labelPosition: labelPosition,
prefix: prefix,
size: size,
style: style,
suffix: suffix
}, createElement(InputField, {
...restProps,
...helpProp,
__next40pxDefaultSize: __next40pxDefaultSize,
className: "components-input-control__input",
disabled: disabled,
id: id,
isFocused: isFocused,
isPressEnterToChange: isPressEnterToChange,
onKeyDown: onKeyDown,
onValidate: onValidate,
paddingInlineStart: prefix ? space(2) : undefined,
paddingInlineEnd: suffix ? space(2) : undefined,
ref: ref,
setIsFocused: setIsFocused,
size: size,
stateReducer: stateReducer,
...draftHookProps
})));
}
/**
* InputControl components let users enter and edit text. This is an experimental component
* intended to (in time) merge with or replace `TextControl`.
*
* ```jsx
* import { __experimentalInputControl as InputControl } from '@wordpress/components';
* import { useState } from '@wordpress/compose';
*
* const Example = () => {
* const [ value, setValue ] = useState( '' );
*
* return (
* <InputControl
* value={ value }
* onChange={ ( nextValue ) => setValue( nextValue ?? '' ) }
* />
* );
* };
* ```
*/
export const InputControl = forwardRef(UnforwardedInputControl);
export default InputControl;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,116 @@
import { createElement } from "react";
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { forwardRef, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import Backdrop from './backdrop';
import Label from './label';
import { Container, Root, Prefix, Suffix, getSizeConfig } from './styles/input-control-styles';
import { ContextSystemProvider } from '../context';
import { useDeprecated36pxDefaultSizeProp } from '../utils/use-deprecated-props';
function useUniqueId(idProp) {
const instanceId = useInstanceId(InputBase);
const id = `input-base-control-${instanceId}`;
return idProp || id;
}
// Adapter to map props for the new ui/flex component.
function getUIFlexProps(labelPosition) {
const props = {};
switch (labelPosition) {
case 'top':
props.direction = 'column';
props.expanded = false;
props.gap = 0;
break;
case 'bottom':
props.direction = 'column-reverse';
props.expanded = false;
props.gap = 0;
break;
case 'edge':
props.justify = 'space-between';
break;
}
return props;
}
export function InputBase(props, ref) {
const {
__next40pxDefaultSize,
__unstableInputWidth,
children,
className,
disabled = false,
hideLabelFromVision = false,
labelPosition,
id: idProp,
isFocused = false,
label,
prefix,
size = 'default',
suffix,
...restProps
} = useDeprecated36pxDefaultSizeProp(props, 'wp.components.InputBase', '6.4');
const id = useUniqueId(idProp);
const hideLabel = hideLabelFromVision || !label;
const {
paddingLeft,
paddingRight
} = getSizeConfig({
inputSize: size,
__next40pxDefaultSize
});
const prefixSuffixContextValue = useMemo(() => {
return {
InputControlPrefixWrapper: {
paddingLeft
},
InputControlSuffixWrapper: {
paddingRight
}
};
}, [paddingLeft, paddingRight]);
return (
// @ts-expect-error The `direction` prop from Flex (FlexDirection) conflicts with legacy SVGAttributes `direction` (string) that come from React intrinsic prop definitions.
createElement(Root, {
...restProps,
...getUIFlexProps(labelPosition),
className: className,
gap: 2,
isFocused: isFocused,
labelPosition: labelPosition,
ref: ref
}, createElement(Label, {
className: "components-input-control__label",
hideLabelFromVision: hideLabelFromVision,
labelPosition: labelPosition,
htmlFor: id
}, label), createElement(Container, {
__unstableInputWidth: __unstableInputWidth,
className: "components-input-control__container",
disabled: disabled,
hideLabel: hideLabel,
labelPosition: labelPosition
}, createElement(ContextSystemProvider, {
value: prefixSuffixContextValue
}, prefix && createElement(Prefix, {
className: "components-input-control__prefix"
}, prefix), children, suffix && createElement(Suffix, {
className: "components-input-control__suffix"
}, suffix)), createElement(Backdrop, {
disabled: disabled,
isFocused: isFocused
})))
);
}
export default forwardRef(InputBase);
//# sourceMappingURL=input-base.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,206 @@
import { createElement } from "react";
/**
* External dependencies
*/
import { useDrag } from '@use-gesture/react';
/**
* WordPress dependencies
*/
import { forwardRef, useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import { useDragCursor } from './utils';
import { Input } from './styles/input-control-styles';
import { useInputControlStateReducer } from './reducer/reducer';
const noop = () => {};
function InputField({
disabled = false,
dragDirection = 'n',
dragThreshold = 10,
id,
isDragEnabled = false,
isFocused,
isPressEnterToChange = false,
onBlur = noop,
onChange = noop,
onDrag = noop,
onDragEnd = noop,
onDragStart = noop,
onFocus = noop,
onKeyDown = noop,
onValidate = noop,
size = 'default',
setIsFocused,
stateReducer = state => state,
value: valueProp,
type,
...props
}, ref) {
const {
// State.
state,
// Actions.
change,
commit,
drag,
dragEnd,
dragStart,
invalidate,
pressDown,
pressEnter,
pressUp,
reset
} = useInputControlStateReducer(stateReducer, {
isDragEnabled,
value: valueProp,
isPressEnterToChange
}, onChange);
const {
value,
isDragging,
isDirty
} = state;
const wasDirtyOnBlur = useRef(false);
const dragCursor = useDragCursor(isDragging, dragDirection);
const handleOnBlur = event => {
onBlur(event);
setIsFocused?.(false);
/**
* If isPressEnterToChange is set, this commits the value to
* the onChange callback.
*/
if (isDirty || !event.target.validity.valid) {
wasDirtyOnBlur.current = true;
handleOnCommit(event);
}
};
const handleOnFocus = event => {
onFocus(event);
setIsFocused?.(true);
};
const handleOnChange = event => {
const nextValue = event.target.value;
change(nextValue, event);
};
const handleOnCommit = event => {
const nextValue = event.currentTarget.value;
try {
onValidate(nextValue);
commit(nextValue, event);
} catch (err) {
invalidate(err, event);
}
};
const handleOnKeyDown = event => {
const {
key
} = event;
onKeyDown(event);
switch (key) {
case 'ArrowUp':
pressUp(event);
break;
case 'ArrowDown':
pressDown(event);
break;
case 'Enter':
pressEnter(event);
if (isPressEnterToChange) {
event.preventDefault();
handleOnCommit(event);
}
break;
case 'Escape':
if (isPressEnterToChange && isDirty) {
event.preventDefault();
reset(valueProp, event);
}
break;
}
};
const dragGestureProps = useDrag(dragProps => {
const {
distance,
dragging,
event,
target
} = dragProps;
// The `target` prop always references the `input` element while, by
// default, the `dragProps.event.target` property would reference the real
// event target (i.e. any DOM element that the pointer is hovering while
// dragging). Ensuring that the `target` is always the `input` element
// allows consumers of `InputControl` (or any higher-level control) to
// check the input's validity by accessing `event.target.validity.valid`.
dragProps.event = {
...dragProps.event,
target
};
if (!distance) return;
event.stopPropagation();
/**
* Quick return if no longer dragging.
* This prevents unnecessary value calculations.
*/
if (!dragging) {
onDragEnd(dragProps);
dragEnd(dragProps);
return;
}
onDrag(dragProps);
drag(dragProps);
if (!isDragging) {
onDragStart(dragProps);
dragStart(dragProps);
}
}, {
axis: dragDirection === 'e' || dragDirection === 'w' ? 'x' : 'y',
threshold: dragThreshold,
enabled: isDragEnabled,
pointer: {
capture: false
}
});
const dragProps = isDragEnabled ? dragGestureProps() : {};
/*
* Works around the odd UA (e.g. Firefox) that does not focus inputs of
* type=number when their spinner arrows are pressed.
*/
let handleOnMouseDown;
if (type === 'number') {
handleOnMouseDown = event => {
props.onMouseDown?.(event);
if (event.currentTarget !== event.currentTarget.ownerDocument.activeElement) {
event.currentTarget.focus();
}
};
}
return createElement(Input, {
...props,
...dragProps,
className: "components-input-control__input",
disabled: disabled,
dragCursor: dragCursor,
isDragging: isDragging,
id: id,
onBlur: handleOnBlur,
onChange: handleOnChange,
onFocus: handleOnFocus,
onKeyDown: handleOnKeyDown,
onMouseDown: handleOnMouseDown,
ref: ref,
inputSize: size
// Fallback to `''` to avoid "uncontrolled to controlled" warning.
// See https://github.com/WordPress/gutenberg/pull/47250 for details.
,
value: value !== null && value !== void 0 ? value : '',
type: type
});
}
const ForwardedComponent = forwardRef(InputField);
export default ForwardedComponent;
//# sourceMappingURL=input-field.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,37 @@
import { createElement } from "react";
/**
* External dependencies
*/
/**
* Internal dependencies
*/
import { Spacer } from '../spacer';
import { contextConnect, useContextSystem } from '../context';
function UnconnectedInputControlPrefixWrapper(props, forwardedRef) {
const derivedProps = useContextSystem(props, 'InputControlPrefixWrapper');
return createElement(Spacer, {
marginBottom: 0,
...derivedProps,
ref: forwardedRef
});
}
/**
* A convenience wrapper for the `prefix` when you want to apply
* standard padding in accordance with the size variant.
*
* ```jsx
* import {
* __experimentalInputControl as InputControl,
* __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
* } from '@wordpress/components';
*
* <InputControl
* prefix={<InputControlPrefixWrapper>@</InputControlPrefixWrapper>}
* />
* ```
*/
export const InputControlPrefixWrapper = contextConnect(UnconnectedInputControlPrefixWrapper, 'InputControlPrefixWrapper');
export default InputControlPrefixWrapper;
//# sourceMappingURL=input-prefix-wrapper.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["Spacer","contextConnect","useContextSystem","UnconnectedInputControlPrefixWrapper","props","forwardedRef","derivedProps","createElement","marginBottom","ref","InputControlPrefixWrapper"],"sources":["@wordpress/components/src/input-control/input-prefix-wrapper.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { Spacer } from '../spacer';\nimport type { WordPressComponentProps } from '../context';\nimport { contextConnect, useContextSystem } from '../context';\nimport type { InputControlPrefixWrapperProps } from './types';\n\nfunction UnconnectedInputControlPrefixWrapper(\n\tprops: WordPressComponentProps< InputControlPrefixWrapperProps, 'div' >,\n\tforwardedRef: ForwardedRef< any >\n) {\n\tconst derivedProps = useContextSystem( props, 'InputControlPrefixWrapper' );\n\n\treturn (\n\t\t<Spacer marginBottom={ 0 } { ...derivedProps } ref={ forwardedRef } />\n\t);\n}\n\n/**\n * A convenience wrapper for the `prefix` when you want to apply\n * standard padding in accordance with the size variant.\n *\n * ```jsx\n * import {\n * __experimentalInputControl as InputControl,\n * __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,\n * } from '@wordpress/components';\n *\n * <InputControl\n * prefix={<InputControlPrefixWrapper>@</InputControlPrefixWrapper>}\n * />\n * ```\n */\nexport const InputControlPrefixWrapper = contextConnect(\n\tUnconnectedInputControlPrefixWrapper,\n\t'InputControlPrefixWrapper'\n);\n\nexport default InputControlPrefixWrapper;\n"],"mappings":";AAAA;AACA;AACA;;AAGA;AACA;AACA;AACA,SAASA,MAAM,QAAQ,WAAW;AAElC,SAASC,cAAc,EAAEC,gBAAgB,QAAQ,YAAY;AAG7D,SAASC,oCAAoCA,CAC5CC,KAAuE,EACvEC,YAAiC,EAChC;EACD,MAAMC,YAAY,GAAGJ,gBAAgB,CAAEE,KAAK,EAAE,2BAA4B,CAAC;EAE3E,OACCG,aAAA,CAACP,MAAM;IAACQ,YAAY,EAAG,CAAG;IAAA,GAAMF,YAAY;IAAGG,GAAG,EAAGJ;EAAc,CAAE,CAAC;AAExE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMK,yBAAyB,GAAGT,cAAc,CACtDE,oCAAoC,EACpC,2BACD,CAAC;AAED,eAAeO,yBAAyB"}

View File

@@ -0,0 +1,37 @@
import { createElement } from "react";
/**
* External dependencies
*/
/**
* Internal dependencies
*/
import { Spacer } from '../spacer';
import { contextConnect, useContextSystem } from '../context';
function UnconnectedInputControlSuffixWrapper(props, forwardedRef) {
const derivedProps = useContextSystem(props, 'InputControlSuffixWrapper');
return createElement(Spacer, {
marginBottom: 0,
...derivedProps,
ref: forwardedRef
});
}
/**
* A convenience wrapper for the `suffix` when you want to apply
* standard padding in accordance with the size variant.
*
* ```jsx
* import {
* __experimentalInputControl as InputControl,
* __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,
* } from '@wordpress/components';
*
* <InputControl
* suffix={<InputControlSuffixWrapper>%</InputControlSuffixWrapper>}
* />
* ```
*/
export const InputControlSuffixWrapper = contextConnect(UnconnectedInputControlSuffixWrapper, 'InputControlSuffixWrapper');
export default InputControlSuffixWrapper;
//# sourceMappingURL=input-suffix-wrapper.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["Spacer","contextConnect","useContextSystem","UnconnectedInputControlSuffixWrapper","props","forwardedRef","derivedProps","createElement","marginBottom","ref","InputControlSuffixWrapper"],"sources":["@wordpress/components/src/input-control/input-suffix-wrapper.tsx"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { ForwardedRef } from 'react';\n\n/**\n * Internal dependencies\n */\nimport { Spacer } from '../spacer';\nimport type { WordPressComponentProps } from '../context';\nimport { contextConnect, useContextSystem } from '../context';\nimport type { InputControlSuffixWrapperProps } from './types';\n\nfunction UnconnectedInputControlSuffixWrapper(\n\tprops: WordPressComponentProps< InputControlSuffixWrapperProps, 'div' >,\n\tforwardedRef: ForwardedRef< any >\n) {\n\tconst derivedProps = useContextSystem( props, 'InputControlSuffixWrapper' );\n\n\treturn (\n\t\t<Spacer marginBottom={ 0 } { ...derivedProps } ref={ forwardedRef } />\n\t);\n}\n\n/**\n * A convenience wrapper for the `suffix` when you want to apply\n * standard padding in accordance with the size variant.\n *\n * ```jsx\n * import {\n * __experimentalInputControl as InputControl,\n * __experimentalInputControlSuffixWrapper as InputControlSuffixWrapper,\n * } from '@wordpress/components';\n *\n * <InputControl\n * suffix={<InputControlSuffixWrapper>%</InputControlSuffixWrapper>}\n * />\n * ```\n */\nexport const InputControlSuffixWrapper = contextConnect(\n\tUnconnectedInputControlSuffixWrapper,\n\t'InputControlSuffixWrapper'\n);\n\nexport default InputControlSuffixWrapper;\n"],"mappings":";AAAA;AACA;AACA;;AAGA;AACA;AACA;AACA,SAASA,MAAM,QAAQ,WAAW;AAElC,SAASC,cAAc,EAAEC,gBAAgB,QAAQ,YAAY;AAG7D,SAASC,oCAAoCA,CAC5CC,KAAuE,EACvEC,YAAiC,EAChC;EACD,MAAMC,YAAY,GAAGJ,gBAAgB,CAAEE,KAAK,EAAE,2BAA4B,CAAC;EAE3E,OACCG,aAAA,CAACP,MAAM;IAACQ,YAAY,EAAG,CAAG;IAAA,GAAMF,YAAY;IAAGG,GAAG,EAAGJ;EAAc,CAAE,CAAC;AAExE;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMK,yBAAyB,GAAGT,cAAc,CACtDE,oCAAoC,EACpC,2BACD,CAAC;AAED,eAAeO,yBAAyB"}

View File

@@ -0,0 +1,25 @@
import { createElement } from "react";
/**
* Internal dependencies
*/
import { VisuallyHidden } from '../visually-hidden';
import { Label as BaseLabel, LabelWrapper } from './styles/input-control-styles';
export default function Label({
children,
hideLabelFromVision,
htmlFor,
...props
}) {
if (!children) return null;
if (hideLabelFromVision) {
return createElement(VisuallyHidden, {
as: "label",
htmlFor: htmlFor
}, children);
}
return createElement(LabelWrapper, null, createElement(BaseLabel, {
htmlFor: htmlFor,
...props
}, children));
}
//# sourceMappingURL=label.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["VisuallyHidden","Label","BaseLabel","LabelWrapper","children","hideLabelFromVision","htmlFor","props","createElement","as"],"sources":["@wordpress/components/src/input-control/label.tsx"],"sourcesContent":["/**\n * Internal dependencies\n */\nimport { VisuallyHidden } from '../visually-hidden';\nimport {\n\tLabel as BaseLabel,\n\tLabelWrapper,\n} from './styles/input-control-styles';\nimport type { WordPressComponentProps } from '../context';\nimport type { InputControlLabelProps } from './types';\n\nexport default function Label( {\n\tchildren,\n\thideLabelFromVision,\n\thtmlFor,\n\t...props\n}: WordPressComponentProps< InputControlLabelProps, 'label', false > ) {\n\tif ( ! children ) return null;\n\n\tif ( hideLabelFromVision ) {\n\t\treturn (\n\t\t\t<VisuallyHidden as=\"label\" htmlFor={ htmlFor }>\n\t\t\t\t{ children }\n\t\t\t</VisuallyHidden>\n\t\t);\n\t}\n\n\treturn (\n\t\t<LabelWrapper>\n\t\t\t<BaseLabel htmlFor={ htmlFor } { ...props }>\n\t\t\t\t{ children }\n\t\t\t</BaseLabel>\n\t\t</LabelWrapper>\n\t);\n}\n"],"mappings":";AAAA;AACA;AACA;AACA,SAASA,cAAc,QAAQ,oBAAoB;AACnD,SACCC,KAAK,IAAIC,SAAS,EAClBC,YAAY,QACN,+BAA+B;AAItC,eAAe,SAASF,KAAKA,CAAE;EAC9BG,QAAQ;EACRC,mBAAmB;EACnBC,OAAO;EACP,GAAGC;AAC+D,CAAC,EAAG;EACtE,IAAK,CAAEH,QAAQ,EAAG,OAAO,IAAI;EAE7B,IAAKC,mBAAmB,EAAG;IAC1B,OACCG,aAAA,CAACR,cAAc;MAACS,EAAE,EAAC,OAAO;MAACH,OAAO,EAAGA;IAAS,GAC3CF,QACa,CAAC;EAEnB;EAEA,OACCI,aAAA,CAACL,YAAY,QACZK,aAAA,CAACN,SAAS;IAACI,OAAO,EAAGA,OAAS;IAAA,GAAMC;EAAK,GACtCH,QACQ,CACE,CAAC;AAEjB"}

View File

@@ -0,0 +1,20 @@
/**
* External dependencies
*/
/**
* Internal dependencies
*/
export const CHANGE = 'CHANGE';
export const COMMIT = 'COMMIT';
export const CONTROL = 'CONTROL';
export const DRAG_END = 'DRAG_END';
export const DRAG_START = 'DRAG_START';
export const DRAG = 'DRAG';
export const INVALIDATE = 'INVALIDATE';
export const PRESS_DOWN = 'PRESS_DOWN';
export const PRESS_ENTER = 'PRESS_ENTER';
export const PRESS_UP = 'PRESS_UP';
export const RESET = 'RESET';
//# sourceMappingURL=actions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["CHANGE","COMMIT","CONTROL","DRAG_END","DRAG_START","DRAG","INVALIDATE","PRESS_DOWN","PRESS_ENTER","PRESS_UP","RESET"],"sources":["@wordpress/components/src/input-control/reducer/actions.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { SyntheticEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { DragProps } from '../types';\n\nexport const CHANGE = 'CHANGE';\nexport const COMMIT = 'COMMIT';\nexport const CONTROL = 'CONTROL';\nexport const DRAG_END = 'DRAG_END';\nexport const DRAG_START = 'DRAG_START';\nexport const DRAG = 'DRAG';\nexport const INVALIDATE = 'INVALIDATE';\nexport const PRESS_DOWN = 'PRESS_DOWN';\nexport const PRESS_ENTER = 'PRESS_ENTER';\nexport const PRESS_UP = 'PRESS_UP';\nexport const RESET = 'RESET';\n\ninterface EventPayload {\n\tevent?: SyntheticEvent;\n}\n\nexport interface Action< Type = string, ExtraPayload = {} > {\n\ttype: Type;\n\tpayload: EventPayload & ExtraPayload;\n}\n\ninterface ValuePayload {\n\tvalue: string;\n}\n\nexport type ChangeAction = Action< typeof CHANGE, ValuePayload >;\nexport type CommitAction = Action< typeof COMMIT, ValuePayload >;\nexport type ControlAction = Action< typeof CONTROL, ValuePayload >;\nexport type PressUpAction = Action< typeof PRESS_UP >;\nexport type PressDownAction = Action< typeof PRESS_DOWN >;\nexport type PressEnterAction = Action< typeof PRESS_ENTER >;\nexport type DragStartAction = Action< typeof DRAG_START, DragProps >;\nexport type DragEndAction = Action< typeof DRAG_END, DragProps >;\nexport type DragAction = Action< typeof DRAG, DragProps >;\nexport type ResetAction = Action< typeof RESET, Partial< ValuePayload > >;\nexport type InvalidateAction = Action< typeof INVALIDATE, { error: unknown } >;\n\nexport type ChangeEventAction = ChangeAction | ResetAction | CommitAction;\n\nexport type DragEventAction = DragStartAction | DragEndAction | DragAction;\n\nexport type KeyEventAction = PressDownAction | PressUpAction | PressEnterAction;\n\nexport type InputAction =\n\t| ChangeEventAction\n\t| KeyEventAction\n\t| DragEventAction\n\t| InvalidateAction;\n"],"mappings":"AAAA;AACA;AACA;;AAGA;AACA;AACA;;AAGA,OAAO,MAAMA,MAAM,GAAG,QAAQ;AAC9B,OAAO,MAAMC,MAAM,GAAG,QAAQ;AAC9B,OAAO,MAAMC,OAAO,GAAG,SAAS;AAChC,OAAO,MAAMC,QAAQ,GAAG,UAAU;AAClC,OAAO,MAAMC,UAAU,GAAG,YAAY;AACtC,OAAO,MAAMC,IAAI,GAAG,MAAM;AAC1B,OAAO,MAAMC,UAAU,GAAG,YAAY;AACtC,OAAO,MAAMC,UAAU,GAAG,YAAY;AACtC,OAAO,MAAMC,WAAW,GAAG,aAAa;AACxC,OAAO,MAAMC,QAAQ,GAAG,UAAU;AAClC,OAAO,MAAMC,KAAK,GAAG,OAAO"}

View File

@@ -0,0 +1,230 @@
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { useReducer, useLayoutEffect, useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import { initialInputControlState, initialStateReducer } from './state';
import * as actions from './actions';
/**
* Prepares initialState for the reducer.
*
* @param initialState The initial state.
* @return Prepared initialState for the reducer
*/
function mergeInitialState(initialState = initialInputControlState) {
const {
value
} = initialState;
return {
...initialInputControlState,
...initialState,
initialValue: value
};
}
/**
* Creates the base reducer which may be coupled to a specializing reducer.
* As its final step, for all actions other than CONTROL, the base reducer
* passes the state and action on through the specializing reducer. The
* exception for CONTROL actions is because they represent controlled updates
* from props and no case has yet presented for their specialization.
*
* @param composedStateReducers A reducer to specialize state changes.
* @return The reducer.
*/
function inputControlStateReducer(composedStateReducers) {
return (state, action) => {
const nextState = {
...state
};
switch (action.type) {
/*
* Controlled updates
*/
case actions.CONTROL:
nextState.value = action.payload.value;
nextState.isDirty = false;
nextState._event = undefined;
// Returns immediately to avoid invoking additional reducers.
return nextState;
/**
* Keyboard events
*/
case actions.PRESS_UP:
nextState.isDirty = false;
break;
case actions.PRESS_DOWN:
nextState.isDirty = false;
break;
/**
* Drag events
*/
case actions.DRAG_START:
nextState.isDragging = true;
break;
case actions.DRAG_END:
nextState.isDragging = false;
break;
/**
* Input events
*/
case actions.CHANGE:
nextState.error = null;
nextState.value = action.payload.value;
if (state.isPressEnterToChange) {
nextState.isDirty = true;
}
break;
case actions.COMMIT:
nextState.value = action.payload.value;
nextState.isDirty = false;
break;
case actions.RESET:
nextState.error = null;
nextState.isDirty = false;
nextState.value = action.payload.value || state.initialValue;
break;
/**
* Validation
*/
case actions.INVALIDATE:
nextState.error = action.payload.error;
break;
}
nextState._event = action.payload.event;
/**
* Send the nextState + action to the composedReducers via
* this "bridge" mechanism. This allows external stateReducers
* to hook into actions, and modify state if needed.
*/
return composedStateReducers(nextState, action);
};
}
/**
* A custom hook that connects and external stateReducer with an internal
* reducer. This hook manages the internal state of InputControl.
* However, by connecting an external stateReducer function, other
* components can react to actions as well as modify state before it is
* applied.
*
* This technique uses the "stateReducer" design pattern:
* https://kentcdodds.com/blog/the-state-reducer-pattern/
*
* @param stateReducer An external state reducer.
* @param initialState The initial state for the reducer.
* @param onChangeHandler A handler for the onChange event.
* @return State, dispatch, and a collection of actions.
*/
export function useInputControlStateReducer(stateReducer = initialStateReducer, initialState = initialInputControlState, onChangeHandler) {
const [state, dispatch] = useReducer(inputControlStateReducer(stateReducer), mergeInitialState(initialState));
const createChangeEvent = type => (nextValue, event) => {
dispatch({
type,
payload: {
value: nextValue,
event
}
});
};
const createKeyEvent = type => event => {
dispatch({
type,
payload: {
event
}
});
};
const createDragEvent = type => payload => {
dispatch({
type,
payload
});
};
/**
* Actions for the reducer
*/
const change = createChangeEvent(actions.CHANGE);
const invalidate = (error, event) => dispatch({
type: actions.INVALIDATE,
payload: {
error,
event
}
});
const reset = createChangeEvent(actions.RESET);
const commit = createChangeEvent(actions.COMMIT);
const dragStart = createDragEvent(actions.DRAG_START);
const drag = createDragEvent(actions.DRAG);
const dragEnd = createDragEvent(actions.DRAG_END);
const pressUp = createKeyEvent(actions.PRESS_UP);
const pressDown = createKeyEvent(actions.PRESS_DOWN);
const pressEnter = createKeyEvent(actions.PRESS_ENTER);
const currentState = useRef(state);
const refProps = useRef({
value: initialState.value,
onChangeHandler
});
// Freshens refs to props and state so that subsequent effects have access
// to their latest values without their changes causing effect runs.
useLayoutEffect(() => {
currentState.current = state;
refProps.current = {
value: initialState.value,
onChangeHandler
};
});
// Propagates the latest state through onChange.
useLayoutEffect(() => {
if (currentState.current._event !== undefined && state.value !== refProps.current.value && !state.isDirty) {
var _state$value;
refProps.current.onChangeHandler((_state$value = state.value) !== null && _state$value !== void 0 ? _state$value : '', {
event: currentState.current._event
});
}
}, [state.value, state.isDirty]);
// Updates the state from props.
useLayoutEffect(() => {
if (initialState.value !== currentState.current.value && !currentState.current.isDirty) {
var _initialState$value;
dispatch({
type: actions.CONTROL,
payload: {
value: (_initialState$value = initialState.value) !== null && _initialState$value !== void 0 ? _initialState$value : ''
}
});
}
}, [initialState.value]);
return {
change,
commit,
dispatch,
drag,
dragEnd,
dragStart,
invalidate,
pressDown,
pressEnter,
pressUp,
reset,
state
};
}
//# sourceMappingURL=reducer.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,19 @@
/**
* External dependencies
*/
/**
* Internal dependencies
*/
export const initialStateReducer = state => state;
export const initialInputControlState = {
error: null,
initialValue: '',
isDirty: false,
isDragEnabled: false,
isDragging: false,
isPressEnterToChange: false,
value: ''
};
//# sourceMappingURL=state.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["initialStateReducer","state","initialInputControlState","error","initialValue","isDirty","isDragEnabled","isDragging","isPressEnterToChange","value"],"sources":["@wordpress/components/src/input-control/reducer/state.ts"],"sourcesContent":["/**\n * External dependencies\n */\nimport type { Reducer, SyntheticEvent } from 'react';\n\n/**\n * Internal dependencies\n */\nimport type { Action, InputAction } from './actions';\n\nexport interface InputState {\n\t_event?: SyntheticEvent;\n\terror: unknown;\n\tinitialValue?: string;\n\tisDirty: boolean;\n\tisDragEnabled: boolean;\n\tisDragging: boolean;\n\tisPressEnterToChange: boolean;\n\tvalue?: string;\n}\n\nexport type StateReducer< SpecializedAction = {} > = Reducer<\n\tInputState,\n\tSpecializedAction extends Action\n\t\t? InputAction | SpecializedAction\n\t\t: InputAction\n>;\n\nexport const initialStateReducer: StateReducer = ( state: InputState ) => state;\n\nexport const initialInputControlState: InputState = {\n\terror: null,\n\tinitialValue: '',\n\tisDirty: false,\n\tisDragEnabled: false,\n\tisDragging: false,\n\tisPressEnterToChange: false,\n\tvalue: '',\n};\n"],"mappings":"AAAA;AACA;AACA;;AAGA;AACA;AACA;;AAqBA,OAAO,MAAMA,mBAAiC,GAAKC,KAAiB,IAAMA,KAAK;AAE/E,OAAO,MAAMC,wBAAoC,GAAG;EACnDC,KAAK,EAAE,IAAI;EACXC,YAAY,EAAE,EAAE;EAChBC,OAAO,EAAE,KAAK;EACdC,aAAa,EAAE,KAAK;EACpBC,UAAU,EAAE,KAAK;EACjBC,oBAAoB,EAAE,KAAK;EAC3BC,KAAK,EAAE;AACR,CAAC"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,91 @@
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
import { useEffect, useLayoutEffect, useRef, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
/**
* Gets a CSS cursor value based on a drag direction.
*
* @param dragDirection The drag direction.
* @return The CSS cursor value.
*/
export function getDragCursor(dragDirection) {
let dragCursor = 'ns-resize';
switch (dragDirection) {
case 'n':
case 's':
dragCursor = 'ns-resize';
break;
case 'e':
case 'w':
dragCursor = 'ew-resize';
break;
}
return dragCursor;
}
/**
* Custom hook that renders a drag cursor when dragging.
*
* @param {boolean} isDragging The dragging state.
* @param {string} dragDirection The drag direction.
*
* @return {string} The CSS cursor value.
*/
export function useDragCursor(isDragging, dragDirection) {
const dragCursor = getDragCursor(dragDirection);
useEffect(() => {
if (isDragging) {
document.documentElement.style.cursor = dragCursor;
} else {
// @ts-expect-error
document.documentElement.style.cursor = null;
}
}, [isDragging, dragCursor]);
return dragCursor;
}
export function useDraft(props) {
const refPreviousValue = useRef(props.value);
const [draft, setDraft] = useState({});
const value = draft.value !== undefined ? draft.value : props.value;
// Determines when to discard the draft value to restore controlled status.
// To do so, it tracks the previous value and marks the draft value as stale
// after each render.
useLayoutEffect(() => {
const {
current: previousValue
} = refPreviousValue;
refPreviousValue.current = props.value;
if (draft.value !== undefined && !draft.isStale) setDraft({
...draft,
isStale: true
});else if (draft.isStale && props.value !== previousValue) setDraft({});
}, [props.value, draft]);
const onChange = (nextValue, extra) => {
// Mutates the draft value to avoid an extra effect run.
setDraft(current => Object.assign(current, {
value: nextValue,
isStale: false
}));
props.onChange(nextValue, extra);
};
const onBlur = event => {
setDraft({});
props.onBlur?.(event);
};
return {
value,
onBlur,
onChange
};
}
//# sourceMappingURL=utils.js.map

File diff suppressed because one or more lines are too long