@wordpress/components 30.3.0 → 30.3.2-next.6f42e1382.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +12 -4
  2. package/build/private-apis.js +5 -0
  3. package/build/private-apis.js.map +1 -1
  4. package/build/validated-form-controls/components/form-token-field.js +64 -0
  5. package/build/validated-form-controls/components/form-token-field.js.map +1 -0
  6. package/build/validated-form-controls/components/index.js +11 -0
  7. package/build/validated-form-controls/components/index.js.map +1 -1
  8. package/build/validated-form-controls/control-with-error.js.map +1 -1
  9. package/build-module/private-apis.js +6 -1
  10. package/build-module/private-apis.js.map +1 -1
  11. package/build-module/validated-form-controls/components/form-token-field.js +57 -0
  12. package/build-module/validated-form-controls/components/form-token-field.js.map +1 -0
  13. package/build-module/validated-form-controls/components/index.js +1 -0
  14. package/build-module/validated-form-controls/components/index.js.map +1 -1
  15. package/build-module/validated-form-controls/control-with-error.js.map +1 -1
  16. package/build-style/style-rtl.css +15 -5
  17. package/build-style/style.css +15 -5
  18. package/build-types/private-apis.d.ts.map +1 -1
  19. package/build-types/validated-form-controls/components/form-token-field.d.ts +4 -0
  20. package/build-types/validated-form-controls/components/form-token-field.d.ts.map +1 -0
  21. package/build-types/validated-form-controls/components/index.d.ts +1 -0
  22. package/build-types/validated-form-controls/components/index.d.ts.map +1 -1
  23. package/build-types/validated-form-controls/components/stories/form-token-field.story.d.ts +15 -0
  24. package/build-types/validated-form-controls/components/stories/form-token-field.story.d.ts.map +1 -0
  25. package/build-types/validated-form-controls/control-with-error.d.ts +5 -0
  26. package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -1
  27. package/package.json +19 -19
  28. package/src/modal/style.scss +8 -0
  29. package/src/private-apis.ts +8 -0
  30. package/src/validated-form-controls/components/form-token-field.tsx +84 -0
  31. package/src/validated-form-controls/components/index.ts +1 -0
  32. package/src/validated-form-controls/components/stories/form-token-field.story.tsx +83 -0
  33. package/src/validated-form-controls/control-with-error.tsx +5 -0
  34. package/src/validated-form-controls/style.scss +11 -5
  35. package/tsconfig.tsbuildinfo +1 -1
@@ -28,6 +28,11 @@ export declare const ControlWithError: import("react").ForwardRefExoticComponent
28
28
  getValidityTarget: () => ValidityTarget | null | undefined;
29
29
  /**
30
30
  * The control component to apply validation to.
31
+ *
32
+ * As `children` will be cloned with additional props,
33
+ * the component at the root of `children` should accept
34
+ * `label`, `onChange`, and `required` props, and process them
35
+ * appropriately.
31
36
  */
32
37
  children: import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
33
38
  } & import("react").RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"control-with-error.d.ts","sourceRoot":"","sources":["../../src/validated-form-controls/control-with-error.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAyBhE;;;;;;;GAOG;AACH,KAAK,cAAc,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,CAAC;AAoMvB,eAAO,MAAM,gBAAgB;IAzL3B;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,OAAO;IAC1B;;OAEG;iBACU,MAAM,IAAI;qBACN,qBAAqB,CAAE,OAAO,CAAE,CAAE,gBAAgB,CAAE;IACrE;;OAEG;uBACgB,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS;IAC1D;;OAEG;;kDAsKoE,CAAC"}
1
+ {"version":3,"file":"control-with-error.d.ts","sourceRoot":"","sources":["../../src/validated-form-controls/control-with-error.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAyBhE;;;;;;;GAOG;AACH,KAAK,cAAc,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,GACjB,mBAAmB,CAAC;AAyMvB,eAAO,MAAM,gBAAgB;IA9L3B;;OAEG;eACQ,OAAO;IAClB;;OAEG;uBACgB,OAAO;IAC1B;;OAEG;iBACU,MAAM,IAAI;qBACN,qBAAqB,CAAE,OAAO,CAAE,CAAE,gBAAgB,CAAE;IACrE;;OAEG;uBACgB,MAAM,cAAc,GAAG,IAAI,GAAG,SAAS;IAC1D;;;;;;;OAOG;;kDAsKoE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/components",
3
- "version": "30.3.0",
3
+ "version": "30.3.2-next.6f42e1382.0",
4
4
  "description": "UI components for WordPress.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -44,23 +44,23 @@
44
44
  "@types/gradient-parser": "1.1.0",
45
45
  "@types/highlight-words-core": "1.2.1",
46
46
  "@use-gesture/react": "^10.3.1",
47
- "@wordpress/a11y": "^4.30.0",
48
- "@wordpress/compose": "^7.30.0",
49
- "@wordpress/date": "^5.30.0",
50
- "@wordpress/deprecated": "^4.30.0",
51
- "@wordpress/dom": "^4.30.0",
52
- "@wordpress/element": "^6.30.0",
53
- "@wordpress/escape-html": "^3.30.0",
54
- "@wordpress/hooks": "^4.30.0",
55
- "@wordpress/html-entities": "^4.30.0",
56
- "@wordpress/i18n": "^6.3.0",
57
- "@wordpress/icons": "^10.30.0",
58
- "@wordpress/is-shallow-equal": "^5.30.0",
59
- "@wordpress/keycodes": "^4.30.0",
60
- "@wordpress/primitives": "^4.30.0",
61
- "@wordpress/private-apis": "^1.30.0",
62
- "@wordpress/rich-text": "^7.30.0",
63
- "@wordpress/warning": "^3.30.0",
47
+ "@wordpress/a11y": "^4.30.1-next.6f42e1382.0",
48
+ "@wordpress/compose": "^7.30.1-next.6f42e1382.0",
49
+ "@wordpress/date": "^5.30.1-next.6f42e1382.0",
50
+ "@wordpress/deprecated": "^4.30.1-next.6f42e1382.0",
51
+ "@wordpress/dom": "^4.30.1-next.6f42e1382.0",
52
+ "@wordpress/element": "^6.30.1-next.6f42e1382.0",
53
+ "@wordpress/escape-html": "^3.30.1-next.6f42e1382.0",
54
+ "@wordpress/hooks": "^4.30.1-next.6f42e1382.0",
55
+ "@wordpress/html-entities": "^4.30.1-next.6f42e1382.0",
56
+ "@wordpress/i18n": "^6.3.1-next.6f42e1382.0",
57
+ "@wordpress/icons": "^10.30.1-next.6f42e1382.0",
58
+ "@wordpress/is-shallow-equal": "^5.30.1-next.6f42e1382.0",
59
+ "@wordpress/keycodes": "^4.30.1-next.6f42e1382.0",
60
+ "@wordpress/primitives": "^4.30.1-next.6f42e1382.0",
61
+ "@wordpress/private-apis": "^1.30.1-next.6f42e1382.0",
62
+ "@wordpress/rich-text": "^7.30.1-next.6f42e1382.0",
63
+ "@wordpress/warning": "^3.30.1-next.6f42e1382.0",
64
64
  "change-case": "^4.1.2",
65
65
  "clsx": "^2.1.1",
66
66
  "colord": "^2.7.0",
@@ -86,5 +86,5 @@
86
86
  "publishConfig": {
87
87
  "access": "public"
88
88
  },
89
- "gitHead": "c66cb089eed19d4f4956962fa7b4c81abe6dd513"
89
+ "gitHead": "8806899f598577a3c90a55d9aa79fbc372fe1e75"
90
90
  }
@@ -31,11 +31,19 @@
31
31
  overflow: hidden;
32
32
  // Have the content element fill the vertical space yet not overflow.
33
33
  display: flex;
34
+ color: $gray-900;
34
35
  // Animate the modal frame/contents appearing on the page.
35
36
  animation-name: components-modal__appear-animation;
36
37
  animation-fill-mode: forwards;
37
38
  animation-timing-function: cubic-bezier(0.29, 0, 0, 1);
38
39
 
40
+ // Ensure all headings use the proper editor text color, overriding wp-admin common.css
41
+ h1,
42
+ h2,
43
+ h3 {
44
+ color: $gray-900;
45
+ }
46
+
39
47
  @media not (prefers-reduced-motion) {
40
48
  animation-duration: var(--modal-frame-animation-duration);
41
49
  }
@@ -13,10 +13,14 @@ import Badge from './badge';
13
13
 
14
14
  import { DateCalendar, DateRangeCalendar, TZDate } from './calendar';
15
15
  import {
16
+ ValidatedCheckboxControl,
17
+ ValidatedInputControl,
16
18
  ValidatedNumberControl,
17
19
  ValidatedTextControl,
20
+ ValidatedTextareaControl,
18
21
  ValidatedToggleControl,
19
22
  } from './validated-form-controls';
23
+ import { Picker } from './color-picker/picker';
20
24
 
21
25
  export const privateApis = {};
22
26
  lock( privateApis, {
@@ -32,7 +36,11 @@ lock( privateApis, {
32
36
  DateCalendar,
33
37
  DateRangeCalendar,
34
38
  TZDate,
39
+ Picker,
40
+ ValidatedInputControl,
41
+ ValidatedCheckboxControl,
35
42
  ValidatedNumberControl,
36
43
  ValidatedTextControl,
44
+ ValidatedTextareaControl,
37
45
  ValidatedToggleControl,
38
46
  } );
@@ -0,0 +1,84 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { forwardRef, useRef } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { ControlWithError } from '../control-with-error';
10
+ import type { ValidatedControlProps } from './types';
11
+ import { FormTokenField } from '../../form-token-field';
12
+ import type { FormTokenFieldProps } from '../../form-token-field/types';
13
+
14
+ type Value = FormTokenFieldProps[ 'value' ];
15
+
16
+ const UnforwardedValidatedFormTokenField = (
17
+ {
18
+ required,
19
+ onValidate,
20
+ customValidity,
21
+ onChange,
22
+ markWhenOptional,
23
+ ...restProps
24
+ }: Omit<
25
+ React.ComponentProps< typeof FormTokenField >,
26
+ '__next40pxDefaultSize' | '__nextHasNoMarginBottom'
27
+ > &
28
+ ValidatedControlProps< FormTokenFieldProps[ 'value' ] >,
29
+ forwardedRef: React.ForwardedRef< HTMLDivElement >
30
+ ) => {
31
+ const validityTargetRef = useRef< HTMLInputElement >( null );
32
+ const valueRef = useRef< Value >( restProps.value );
33
+
34
+ return (
35
+ <div
36
+ className="components-validated-control__wrapper-with-error-delegate"
37
+ ref={ forwardedRef }
38
+ >
39
+ <ControlWithError
40
+ required={ required }
41
+ markWhenOptional={ markWhenOptional }
42
+ onValidate={ () => {
43
+ return onValidate?.( valueRef.current );
44
+ } }
45
+ customValidity={ customValidity }
46
+ getValidityTarget={ () => validityTargetRef.current }
47
+ >
48
+ <FormTokenField
49
+ __next40pxDefaultSize
50
+ __nextHasNoMarginBottom
51
+ { ...restProps }
52
+ onChange={ ( value, ...args ) => {
53
+ valueRef.current = value;
54
+ onChange?.( value, ...args );
55
+ } }
56
+ />
57
+ </ControlWithError>
58
+ <input
59
+ className="components-validated-control__error-delegate"
60
+ type="text"
61
+ ref={ validityTargetRef }
62
+ required={ required }
63
+ value={
64
+ valueRef.current && valueRef.current.length > 0
65
+ ? 'hasvalue'
66
+ : ''
67
+ }
68
+ tabIndex={ -1 }
69
+ onChange={ () => {} }
70
+ onFocus={ ( e ) => {
71
+ e.target.previousElementSibling
72
+ ?.querySelector< HTMLInputElement >(
73
+ 'input[type="text"]'
74
+ )
75
+ ?.focus();
76
+ } }
77
+ />
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export const ValidatedFormTokenField = forwardRef(
83
+ UnforwardedValidatedFormTokenField
84
+ );
@@ -1,6 +1,7 @@
1
1
  export * from './checkbox-control';
2
2
  export * from './combobox-control';
3
3
  export * from './custom-select-control';
4
+ export * from './form-token-field';
4
5
  export * from './input-control';
5
6
  export * from './number-control';
6
7
  export * from './radio-control';
@@ -0,0 +1,83 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+
6
+ /**
7
+ * External dependencies
8
+ */
9
+ import type { StoryObj, Meta } from '@storybook/react';
10
+
11
+ /**
12
+ * Internal dependencies
13
+ */
14
+ import { ValidatedFormTokenField } from '../form-token-field';
15
+ import { formDecorator } from './story-utils';
16
+ import type { TokenItem } from '../../../form-token-field/types';
17
+
18
+ const meta: Meta< typeof ValidatedFormTokenField > = {
19
+ title: 'Components/Selection & Input/Validated Form Controls/ValidatedFormTokenField',
20
+ id: 'components-validatedformtokenfield',
21
+ component: ValidatedFormTokenField,
22
+ tags: [ 'status-private' ],
23
+ decorators: formDecorator,
24
+ args: { onChange: () => {} },
25
+ argTypes: {
26
+ onChange: { control: false },
27
+ value: { control: false },
28
+ customValidity: { control: false },
29
+ },
30
+ };
31
+ export default meta;
32
+
33
+ /**
34
+ * This demonstrates how array validation would work with the ValidatedFormTokenField component.
35
+ */
36
+ export const Default: StoryObj< typeof ValidatedFormTokenField > = {
37
+ render: function Template( { onChange, ...args } ) {
38
+ const [ value, setValue ] = useState< ( string | TokenItem )[] >( [] );
39
+ const [ customValidity, setCustomValidity ] =
40
+ useState<
41
+ React.ComponentProps<
42
+ typeof ValidatedFormTokenField
43
+ >[ 'customValidity' ]
44
+ >( undefined );
45
+
46
+ return (
47
+ <ValidatedFormTokenField
48
+ { ...args }
49
+ value={ value }
50
+ onChange={ ( newValue, ...rest ) => {
51
+ setValue( newValue );
52
+ onChange?.( newValue, ...rest );
53
+ } }
54
+ onValidate={ ( v ) => {
55
+ if (
56
+ v?.some( ( token ) => {
57
+ const tokenValue =
58
+ typeof token === 'string' ? token : token.value;
59
+ return tokenValue.toLowerCase() === 'error';
60
+ } )
61
+ ) {
62
+ setCustomValidity( {
63
+ type: 'invalid',
64
+ message: 'The tag "error" is not allowed.',
65
+ } );
66
+ return;
67
+ }
68
+
69
+ setCustomValidity( undefined );
70
+ } }
71
+ customValidity={ customValidity }
72
+ />
73
+ );
74
+ },
75
+ };
76
+
77
+ Default.args = {
78
+ required: true,
79
+ label: 'Tags',
80
+ placeholder: 'Add tags...',
81
+ suggestions: [ 'Posts', 'Pages', 'Media', 'Error' ],
82
+ __experimentalExpandOnFocus: true,
83
+ };
@@ -81,6 +81,11 @@ function UnforwardedControlWithError< C extends React.ReactElement >(
81
81
  getValidityTarget: () => ValidityTarget | null | undefined;
82
82
  /**
83
83
  * The control component to apply validation to.
84
+ *
85
+ * As `children` will be cloned with additional props,
86
+ * the component at the root of `children` should accept
87
+ * `label`, `onChange`, and `required` props, and process them
88
+ * appropriately.
84
89
  */
85
90
  children: C;
86
91
  },
@@ -2,14 +2,14 @@
2
2
  // For components based on InputBase
3
3
  &:has(:is(input, select):user-invalid)
4
4
  .components-input-control__backdrop {
5
- --wp-components-color-accent: $alert-red;
5
+ --wp-components-color-accent: #{$alert-red};
6
6
  border-color: $alert-red;
7
7
  }
8
8
 
9
9
  // For TextControl, TextareaControl
10
10
  :is(textarea, input[type="text"]):user-invalid {
11
- --wp-admin-theme-color: $alert-red;
12
- --wp-components-color-accent: $alert-red;
11
+ --wp-admin-theme-color: #{$alert-red};
12
+ --wp-components-color-accent: #{$alert-red};
13
13
  border-color: $alert-red;
14
14
  }
15
15
 
@@ -26,13 +26,19 @@
26
26
 
27
27
  // For CustomSelectControl
28
28
  &:has(select:user-invalid) .components-input-control__backdrop {
29
- --wp-components-color-accent: $alert-red;
29
+ --wp-components-color-accent: #{$alert-red};
30
30
  border-color: $alert-red;
31
31
  }
32
32
 
33
33
  // For ToggleGroupControl
34
34
  &:has(input[type="radio"]:invalid) {
35
- --wp-components-color-accent: $alert-red;
35
+ --wp-components-color-accent: #{$alert-red};
36
+ }
37
+
38
+ // For FormTokenField
39
+ &:has(input:user-invalid) .components-form-token-field__input-container:not(:has([aria-expanded="true"])) {
40
+ --wp-components-color-accent: #{$alert-red};
41
+ border-color: $alert-red;
36
42
  }
37
43
  }
38
44