@wordpress/components 29.13.1-next.719a03cbe.0 → 30.1.1-next.46f643fa0.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.
- package/CHANGELOG.md +34 -3
- package/build/autocomplete/index.js +4 -0
- package/build/autocomplete/index.js.map +1 -1
- package/build/calendar/date-calendar/index.js +13 -4
- package/build/calendar/date-calendar/index.js.map +1 -1
- package/build/calendar/date-range-calendar/index.js +8 -4
- package/build/calendar/date-range-calendar/index.js.map +1 -1
- package/build/calendar/types.js.map +1 -1
- package/build/color-picker/styles.js +7 -7
- package/build/color-picker/styles.js.map +1 -1
- package/build/icon/index.js +2 -0
- package/build/icon/index.js.map +1 -1
- package/build/index.js +0 -19
- package/build/index.js.map +1 -1
- package/build/palette-edit/index.js +1 -1
- package/build/palette-edit/index.js.map +1 -1
- package/build/private-apis.js +9 -1
- package/build/private-apis.js.map +1 -1
- package/build/range-control/index.js +1 -1
- package/build/range-control/index.js.map +1 -1
- package/build/range-control/styles/range-control-styles.js +35 -35
- package/build/range-control/styles/range-control-styles.js.map +1 -1
- package/build/range-control/tooltip.js +15 -15
- package/build/range-control/tooltip.js.map +1 -1
- package/build/range-control/types.js.map +1 -1
- package/build/select-control/index.js +1 -1
- package/build/select-control/index.js.map +1 -1
- package/build/textarea-control/index.js +7 -1
- package/build/textarea-control/index.js.map +1 -1
- package/build/toggle-group-control/toggle-group-control/as-button-group.js.map +1 -1
- package/build/utils/hooks/use-controlled-value.js +8 -4
- package/build/utils/hooks/use-controlled-value.js.map +1 -1
- package/build/validated-form-controls/components/checkbox-control.js +52 -0
- package/build/validated-form-controls/components/checkbox-control.js.map +1 -0
- package/build/validated-form-controls/components/combobox-control.js +64 -0
- package/build/validated-form-controls/components/combobox-control.js.map +1 -0
- package/build/validated-form-controls/components/custom-select-control.js +71 -0
- package/build/validated-form-controls/components/custom-select-control.js.map +1 -0
- package/build/validated-form-controls/components/index.js +138 -0
- package/build/validated-form-controls/components/index.js.map +1 -0
- package/build/validated-form-controls/components/input-control.js +50 -0
- package/build/validated-form-controls/components/input-control.js.map +1 -0
- package/build/validated-form-controls/components/number-control.js +53 -0
- package/build/validated-form-controls/components/number-control.js.map +1 -0
- package/build/validated-form-controls/components/radio-control.js +51 -0
- package/build/validated-form-controls/components/radio-control.js.map +1 -0
- package/build/validated-form-controls/components/range-control.js +51 -0
- package/build/validated-form-controls/components/range-control.js.map +1 -0
- package/build/validated-form-controls/components/select-control.js +53 -0
- package/build/validated-form-controls/components/select-control.js.map +1 -0
- package/build/validated-form-controls/components/text-control.js +51 -0
- package/build/validated-form-controls/components/text-control.js.map +1 -0
- package/build/validated-form-controls/components/textarea-control.js +50 -0
- package/build/validated-form-controls/components/textarea-control.js.map +1 -0
- package/build/validated-form-controls/components/toggle-control.js +60 -0
- package/build/validated-form-controls/components/toggle-control.js.map +1 -0
- package/build/validated-form-controls/components/toggle-group-control.js +69 -0
- package/build/validated-form-controls/components/toggle-group-control.js.map +1 -0
- package/build/validated-form-controls/components/types.js +6 -0
- package/build/validated-form-controls/components/types.js.map +1 -0
- package/build/validated-form-controls/control-with-error.js +137 -0
- package/build/validated-form-controls/control-with-error.js.map +1 -0
- package/build/validated-form-controls/index.js +28 -0
- package/build/validated-form-controls/index.js.map +1 -0
- package/build-module/autocomplete/index.js +4 -0
- package/build-module/autocomplete/index.js.map +1 -1
- package/build-module/calendar/date-calendar/index.js +11 -3
- package/build-module/calendar/date-calendar/index.js.map +1 -1
- package/build-module/calendar/date-range-calendar/index.js +8 -4
- package/build-module/calendar/date-range-calendar/index.js.map +1 -1
- package/build-module/calendar/types.js.map +1 -1
- package/build-module/color-picker/styles.js +7 -7
- package/build-module/color-picker/styles.js.map +1 -1
- package/build-module/icon/index.js +2 -0
- package/build-module/icon/index.js.map +1 -1
- package/build-module/index.js +0 -1
- package/build-module/index.js.map +1 -1
- package/build-module/palette-edit/index.js +2 -2
- package/build-module/palette-edit/index.js.map +1 -1
- package/build-module/private-apis.js +9 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/range-control/index.js +1 -1
- package/build-module/range-control/index.js.map +1 -1
- package/build-module/range-control/styles/range-control-styles.js +35 -35
- package/build-module/range-control/styles/range-control-styles.js.map +1 -1
- package/build-module/range-control/tooltip.js +15 -15
- package/build-module/range-control/tooltip.js.map +1 -1
- package/build-module/range-control/types.js.map +1 -1
- package/build-module/select-control/index.js +1 -1
- package/build-module/select-control/index.js.map +1 -1
- package/build-module/textarea-control/index.js +7 -1
- package/build-module/textarea-control/index.js.map +1 -1
- package/build-module/toggle-group-control/toggle-group-control/as-button-group.js.map +1 -1
- package/build-module/utils/hooks/use-controlled-value.js +9 -5
- package/build-module/utils/hooks/use-controlled-value.js.map +1 -1
- package/build-module/validated-form-controls/components/checkbox-control.js +44 -0
- package/build-module/validated-form-controls/components/checkbox-control.js.map +1 -0
- package/build-module/validated-form-controls/components/combobox-control.js +56 -0
- package/build-module/validated-form-controls/components/combobox-control.js.map +1 -0
- package/build-module/validated-form-controls/components/custom-select-control.js +63 -0
- package/build-module/validated-form-controls/components/custom-select-control.js.map +1 -0
- package/build-module/validated-form-controls/components/index.js +13 -0
- package/build-module/validated-form-controls/components/index.js.map +1 -0
- package/build-module/validated-form-controls/components/input-control.js +42 -0
- package/build-module/validated-form-controls/components/input-control.js.map +1 -0
- package/build-module/validated-form-controls/components/number-control.js +45 -0
- package/build-module/validated-form-controls/components/number-control.js.map +1 -0
- package/build-module/validated-form-controls/components/radio-control.js +43 -0
- package/build-module/validated-form-controls/components/radio-control.js.map +1 -0
- package/build-module/validated-form-controls/components/range-control.js +43 -0
- package/build-module/validated-form-controls/components/range-control.js.map +1 -0
- package/build-module/validated-form-controls/components/select-control.js +45 -0
- package/build-module/validated-form-controls/components/select-control.js.map +1 -0
- package/build-module/validated-form-controls/components/text-control.js +43 -0
- package/build-module/validated-form-controls/components/text-control.js.map +1 -0
- package/build-module/validated-form-controls/components/textarea-control.js +42 -0
- package/build-module/validated-form-controls/components/textarea-control.js.map +1 -0
- package/build-module/validated-form-controls/components/toggle-control.js +52 -0
- package/build-module/validated-form-controls/components/toggle-control.js.map +1 -0
- package/build-module/validated-form-controls/components/toggle-group-control.js +62 -0
- package/build-module/validated-form-controls/components/toggle-group-control.js.map +1 -0
- package/build-module/validated-form-controls/components/types.js +2 -0
- package/build-module/validated-form-controls/components/types.js.map +1 -0
- package/build-module/validated-form-controls/control-with-error.js +129 -0
- package/build-module/validated-form-controls/control-with-error.js.map +1 -0
- package/build-module/validated-form-controls/index.js +3 -0
- package/build-module/validated-form-controls/index.js.map +1 -0
- package/build-style/style-rtl.css +79 -67
- package/build-style/style.css +79 -67
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/box-control/utils.d.ts +7 -7
- package/build-types/calendar/date-calendar/index.d.ts.map +1 -1
- package/build-types/calendar/date-range-calendar/index.d.ts.map +1 -1
- package/build-types/calendar/types.d.ts +2 -2
- package/build-types/calendar/types.d.ts.map +1 -1
- package/build-types/calendar/utils/use-localization-props.d.ts +3 -3
- package/build-types/color-picker/styles.d.ts.map +1 -1
- package/build-types/custom-gradient-picker/constants.d.ts +2 -2
- package/build-types/dimension-control/sizes.d.ts +5 -5
- package/build-types/font-size-picker/constants.d.ts +2 -2
- package/build-types/font-size-picker/constants.d.ts.map +1 -1
- package/build-types/icon/index.d.ts.map +1 -1
- package/build-types/index.d.ts +0 -1
- package/build-types/index.d.ts.map +1 -1
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/range-control/types.d.ts +2 -2
- package/build-types/range-control/types.d.ts.map +1 -1
- package/build-types/select-control/stories/index.story.d.ts.map +1 -1
- package/build-types/text-control/stories/index.story.d.ts.map +1 -1
- package/build-types/textarea-control/index.d.ts.map +1 -1
- package/build-types/toggle-group-control/toggle-group-control/as-button-group.d.ts.map +1 -1
- package/build-types/utils/hooks/use-controlled-value.d.ts +2 -2
- package/build-types/utils/hooks/use-controlled-value.d.ts.map +1 -1
- package/build-types/validated-form-controls/components/checkbox-control.d.ts +9 -0
- package/build-types/validated-form-controls/components/checkbox-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/combobox-control.d.ts +21 -0
- package/build-types/validated-form-controls/components/combobox-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/custom-select-control.d.ts +4 -0
- package/build-types/validated-form-controls/components/custom-select-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/index.d.ts +13 -0
- package/build-types/validated-form-controls/components/index.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/input-control.d.ts +4 -0
- package/build-types/validated-form-controls/components/input-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/number-control.d.ts +17 -0
- package/build-types/validated-form-controls/components/number-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/radio-control.d.ts +11 -0
- package/build-types/validated-form-controls/components/radio-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/range-control.d.ts +36 -0
- package/build-types/validated-form-controls/components/range-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/select-control.d.ts +9 -0
- package/build-types/validated-form-controls/components/select-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/checkbox-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/checkbox-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/combobox-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/combobox-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/custom-select-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/custom-select-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/input-control.story.d.ts +18 -0
- package/build-types/validated-form-controls/components/stories/input-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/number-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/number-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/overview.story.d.ts +19 -0
- package/build-types/validated-form-controls/components/stories/overview.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/radio-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/radio-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/range-control.story.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/range-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/select-control.story.d.ts +12 -0
- package/build-types/validated-form-controls/components/stories/select-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/story-utils.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/story-utils.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/text-control.story.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/text-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/textarea-control.story.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/textarea-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/toggle-control.story.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/toggle-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/stories/toggle-group-control.story.d.ts +9 -0
- package/build-types/validated-form-controls/components/stories/toggle-group-control.story.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/text-control.d.ts +8 -0
- package/build-types/validated-form-controls/components/text-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/textarea-control.d.ts +7 -0
- package/build-types/validated-form-controls/components/textarea-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/toggle-control.d.ts +7 -0
- package/build-types/validated-form-controls/components/toggle-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/toggle-group-control.d.ts +15 -0
- package/build-types/validated-form-controls/components/toggle-group-control.d.ts.map +1 -0
- package/build-types/validated-form-controls/components/types.d.ts +27 -0
- package/build-types/validated-form-controls/components/types.d.ts.map +1 -0
- package/build-types/validated-form-controls/control-with-error.d.ts +36 -0
- package/build-types/validated-form-controls/control-with-error.d.ts.map +1 -0
- package/build-types/validated-form-controls/index.d.ts +3 -0
- package/build-types/validated-form-controls/index.d.ts.map +1 -0
- package/package.json +19 -19
- package/src/autocomplete/index.tsx +4 -0
- package/src/calendar/date-calendar/README.md +57 -46
- package/src/calendar/date-calendar/index.tsx +22 -8
- package/src/calendar/date-range-calendar/README.md +63 -52
- package/src/calendar/date-range-calendar/index.tsx +23 -11
- package/src/calendar/types.ts +2 -2
- package/src/color-picker/styles.ts +10 -0
- package/src/dimension-control/test/__snapshots__/index.test.js.snap +8 -8
- package/src/icon/index.tsx +2 -0
- package/src/index.ts +0 -1
- package/src/modal/style.scss +2 -2
- package/src/palette-edit/index.tsx +3 -3
- package/src/private-apis.ts +13 -0
- package/src/range-control/index.tsx +1 -1
- package/src/range-control/styles/range-control-styles.ts +3 -3
- package/src/range-control/tooltip.tsx +13 -13
- package/src/range-control/types.ts +2 -2
- package/src/select-control/index.tsx +1 -1
- package/src/style.scss +2 -2
- package/src/text-control/stories/index.story.tsx +1 -0
- package/src/text-control/style.scss +6 -1
- package/src/textarea-control/index.tsx +8 -1
- package/src/toggle-group-control/toggle-group-control/as-button-group.tsx +3 -1
- package/src/utils/hooks/use-controlled-value.ts +16 -8
- package/src/utils/theme-variables.scss +3 -0
- package/src/validated-form-controls/components/checkbox-control.tsx +64 -0
- package/src/validated-form-controls/components/combobox-control.tsx +77 -0
- package/src/validated-form-controls/components/custom-select-control.tsx +86 -0
- package/src/validated-form-controls/components/index.ts +12 -0
- package/src/validated-form-controls/components/input-control.tsx +59 -0
- package/src/validated-form-controls/components/number-control.tsx +61 -0
- package/src/validated-form-controls/components/radio-control.tsx +60 -0
- package/src/validated-form-controls/components/range-control.tsx +60 -0
- package/src/validated-form-controls/components/select-control.tsx +75 -0
- package/src/validated-form-controls/components/stories/checkbox-control.story.tsx +57 -0
- package/src/validated-form-controls/components/stories/combobox-control.story.tsx +64 -0
- package/src/validated-form-controls/components/stories/custom-select-control.story.tsx +64 -0
- package/src/validated-form-controls/components/stories/input-control.story.tsx +132 -0
- package/src/validated-form-controls/components/stories/number-control.story.tsx +62 -0
- package/src/validated-form-controls/components/stories/overview.mdx +52 -0
- package/src/validated-form-controls/components/stories/overview.story.tsx +100 -0
- package/src/validated-form-controls/components/stories/radio-control.story.tsx +64 -0
- package/src/validated-form-controls/components/stories/range-control.story.tsx +60 -0
- package/src/validated-form-controls/components/stories/select-control.story.tsx +60 -0
- package/src/validated-form-controls/components/stories/story-utils.tsx +46 -0
- package/src/validated-form-controls/components/stories/text-control.story.tsx +55 -0
- package/src/validated-form-controls/components/stories/textarea-control.story.tsx +52 -0
- package/src/validated-form-controls/components/stories/toggle-control.story.tsx +55 -0
- package/src/validated-form-controls/components/stories/toggle-group-control.story.tsx +66 -0
- package/src/validated-form-controls/components/text-control.tsx +60 -0
- package/src/validated-form-controls/components/textarea-control.tsx +59 -0
- package/src/validated-form-controls/components/toggle-control.tsx +69 -0
- package/src/validated-form-controls/components/toggle-group-control.tsx +82 -0
- package/src/validated-form-controls/components/types.ts +28 -0
- package/src/validated-form-controls/control-with-error.tsx +198 -0
- package/src/validated-form-controls/index.ts +2 -0
- package/src/validated-form-controls/style.scss +75 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/build/calendar/utils/use-controlled-value.js +0 -58
- package/build/calendar/utils/use-controlled-value.js.map +0 -1
- package/build-module/calendar/utils/use-controlled-value.js +0 -51
- package/build-module/calendar/utils/use-controlled-value.js.map +0 -1
- package/build-types/calendar/utils/use-controlled-value.d.ts +0 -27
- package/build-types/calendar/utils/use-controlled-value.d.ts.map +0 -1
- package/src/calendar/utils/use-controlled-value.ts +0 -61
- package/src/dimension-control/style.scss +0 -22
|
@@ -0,0 +1,57 @@
|
|
|
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 { ValidatedCheckboxControl } from '../checkbox-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedCheckboxControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedCheckboxControl',
|
|
19
|
+
component: ValidatedCheckboxControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
checked: { control: false },
|
|
25
|
+
// TODO: Figure out why this deprecated prop is still showing up here and not in the WP Storybook.
|
|
26
|
+
heading: { table: { disable: true } },
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
export default meta;
|
|
30
|
+
|
|
31
|
+
export const Default: StoryObj< typeof ValidatedCheckboxControl > = {
|
|
32
|
+
render: function Template( { onChange, ...args } ) {
|
|
33
|
+
const [ checked, setChecked ] = useState( false );
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ValidatedCheckboxControl
|
|
37
|
+
{ ...args }
|
|
38
|
+
checked={ checked }
|
|
39
|
+
onChange={ ( value ) => {
|
|
40
|
+
setChecked( value );
|
|
41
|
+
onChange?.( value );
|
|
42
|
+
} }
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
Default.args = {
|
|
48
|
+
required: true,
|
|
49
|
+
label: 'Checkbox',
|
|
50
|
+
help: 'This checkbox may neither be checked nor unchecked.',
|
|
51
|
+
customValidator: ( value ) => {
|
|
52
|
+
if ( value ) {
|
|
53
|
+
return 'This checkbox may not be checked.';
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
},
|
|
57
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
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 { ValidatedComboboxControl } from '../combobox-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedComboboxControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedComboboxControl',
|
|
19
|
+
component: ValidatedComboboxControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
value: { control: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
export const Default: StoryObj< typeof ValidatedComboboxControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ value, setValue ] =
|
|
32
|
+
useState<
|
|
33
|
+
React.ComponentProps<
|
|
34
|
+
typeof ValidatedComboboxControl
|
|
35
|
+
>[ 'value' ]
|
|
36
|
+
>();
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ValidatedComboboxControl
|
|
40
|
+
{ ...args }
|
|
41
|
+
value={ value }
|
|
42
|
+
onChange={ ( newValue ) => {
|
|
43
|
+
setValue( newValue );
|
|
44
|
+
onChange?.( newValue );
|
|
45
|
+
} }
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
Default.args = {
|
|
51
|
+
required: true,
|
|
52
|
+
label: 'Combobox',
|
|
53
|
+
help: 'Option A is not allowed.',
|
|
54
|
+
options: [
|
|
55
|
+
{ value: 'a', label: 'Option A (not allowed)' },
|
|
56
|
+
{ value: 'b', label: 'Option B' },
|
|
57
|
+
],
|
|
58
|
+
customValidator: ( value ) => {
|
|
59
|
+
if ( value === 'a' ) {
|
|
60
|
+
return 'Option A is not allowed.';
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
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 { ValidatedCustomSelectControl } from '../custom-select-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedCustomSelectControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedCustomSelectControl',
|
|
19
|
+
component: ValidatedCustomSelectControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
value: { control: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
export const Default: StoryObj< typeof ValidatedCustomSelectControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ value, setValue ] =
|
|
32
|
+
useState<
|
|
33
|
+
React.ComponentProps<
|
|
34
|
+
typeof ValidatedCustomSelectControl
|
|
35
|
+
>[ 'value' ]
|
|
36
|
+
>();
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ValidatedCustomSelectControl
|
|
40
|
+
{ ...args }
|
|
41
|
+
value={ value }
|
|
42
|
+
onChange={ ( newValue ) => {
|
|
43
|
+
setValue( newValue.selectedItem );
|
|
44
|
+
onChange?.( newValue );
|
|
45
|
+
} }
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
Default.args = {
|
|
51
|
+
required: true,
|
|
52
|
+
label: 'Custom Select',
|
|
53
|
+
options: [
|
|
54
|
+
{ key: '', name: 'Select an option' },
|
|
55
|
+
{ key: 'a', name: 'Option A (not allowed)' },
|
|
56
|
+
{ key: 'b', name: 'Option B' },
|
|
57
|
+
],
|
|
58
|
+
customValidator: ( value ) => {
|
|
59
|
+
if ( value?.key === 'a' ) {
|
|
60
|
+
return 'Option A is not allowed.';
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
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
|
+
* WordPress dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { seen, unseen } from '@wordpress/icons';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Internal dependencies
|
|
18
|
+
*/
|
|
19
|
+
import { ValidatedInputControl } from '../input-control';
|
|
20
|
+
import { formDecorator } from './story-utils';
|
|
21
|
+
import InputControlSuffixWrapper from '../../../input-control/input-suffix-wrapper';
|
|
22
|
+
import { Button } from '../../../button';
|
|
23
|
+
|
|
24
|
+
const meta: Meta< typeof ValidatedInputControl > = {
|
|
25
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedInputControl',
|
|
26
|
+
component: ValidatedInputControl,
|
|
27
|
+
tags: [ 'status-private' ],
|
|
28
|
+
decorators: formDecorator,
|
|
29
|
+
args: { onChange: () => {} },
|
|
30
|
+
argTypes: {
|
|
31
|
+
__unstableInputWidth: { control: { type: 'text' } },
|
|
32
|
+
__unstableStateReducer: { control: false },
|
|
33
|
+
onChange: { control: false },
|
|
34
|
+
prefix: { control: false },
|
|
35
|
+
suffix: { control: false },
|
|
36
|
+
type: { control: { type: 'text' } },
|
|
37
|
+
value: { control: false },
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export default meta;
|
|
41
|
+
|
|
42
|
+
export const Default: StoryObj< typeof ValidatedInputControl > = {
|
|
43
|
+
render: function Template( { onChange, ...args } ) {
|
|
44
|
+
const [ value, setValue ] =
|
|
45
|
+
useState<
|
|
46
|
+
React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
|
|
47
|
+
>( '' );
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<ValidatedInputControl
|
|
51
|
+
{ ...args }
|
|
52
|
+
value={ value }
|
|
53
|
+
onChange={ ( newValue, ...rest ) => {
|
|
54
|
+
setValue( newValue );
|
|
55
|
+
onChange?.( newValue, ...rest );
|
|
56
|
+
} }
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
Default.args = {
|
|
62
|
+
required: true,
|
|
63
|
+
label: 'Input',
|
|
64
|
+
help: 'The word "error" will trigger an error.',
|
|
65
|
+
customValidator: ( value ) => {
|
|
66
|
+
if ( value?.toLowerCase() === 'error' ) {
|
|
67
|
+
return 'The word "error" is not allowed.';
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* This demonstrates how password validation would work with the standard implementation.
|
|
75
|
+
*
|
|
76
|
+
* We are planning to move to a custom implementation more tailored to the password use case.
|
|
77
|
+
*/
|
|
78
|
+
export const Password: StoryObj< typeof ValidatedInputControl > = {
|
|
79
|
+
render: function Template( { onChange, ...args } ) {
|
|
80
|
+
const [ value, setValue ] =
|
|
81
|
+
useState<
|
|
82
|
+
React.ComponentProps< typeof ValidatedInputControl >[ 'value' ]
|
|
83
|
+
>( '' );
|
|
84
|
+
const [ visible, setVisible ] = useState( false );
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<ValidatedInputControl
|
|
88
|
+
{ ...args }
|
|
89
|
+
type={ visible ? 'text' : 'password' }
|
|
90
|
+
suffix={
|
|
91
|
+
<InputControlSuffixWrapper variant="control">
|
|
92
|
+
<Button
|
|
93
|
+
size="small"
|
|
94
|
+
icon={ visible ? unseen : seen }
|
|
95
|
+
onClick={ () => setVisible( ( v ) => ! v ) }
|
|
96
|
+
label={
|
|
97
|
+
visible ? 'Hide password' : 'Show password'
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
</InputControlSuffixWrapper>
|
|
101
|
+
}
|
|
102
|
+
value={ value }
|
|
103
|
+
onChange={ ( newValue, ...rest ) => {
|
|
104
|
+
setValue( newValue );
|
|
105
|
+
onChange?.( newValue, ...rest );
|
|
106
|
+
} }
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
Password.args = {
|
|
112
|
+
required: true,
|
|
113
|
+
label: 'Password',
|
|
114
|
+
help: 'Minimum 8 characters, include a number, capital letter, and symbol (!@£$%^&*#).',
|
|
115
|
+
minLength: 8,
|
|
116
|
+
customValidator: ( value ) => {
|
|
117
|
+
if ( ! /\d/.test( value ?? '' ) ) {
|
|
118
|
+
return 'Password must include at least one number.';
|
|
119
|
+
}
|
|
120
|
+
if ( ! /[A-Z]/.test( value ?? '' ) ) {
|
|
121
|
+
return 'Password must include at least one capital letter.';
|
|
122
|
+
}
|
|
123
|
+
if ( ! /[!@£$%^&*#]/.test( value ?? '' ) ) {
|
|
124
|
+
return 'Password must include at least one symbol.';
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
Password.argTypes = {
|
|
130
|
+
suffix: { control: false },
|
|
131
|
+
type: { control: false },
|
|
132
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
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 { ValidatedNumberControl } from '../number-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedNumberControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedNumberControl',
|
|
19
|
+
component: ValidatedNumberControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
prefix: { control: { type: 'text' } },
|
|
25
|
+
step: { control: { type: 'text' } },
|
|
26
|
+
suffix: { control: { type: 'text' } },
|
|
27
|
+
type: { control: { type: 'text' } },
|
|
28
|
+
value: { control: false },
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
export default meta;
|
|
32
|
+
|
|
33
|
+
export const Default: StoryObj< typeof ValidatedNumberControl > = {
|
|
34
|
+
render: function Template( { onChange, ...args } ) {
|
|
35
|
+
const [ value, setValue ] =
|
|
36
|
+
useState<
|
|
37
|
+
React.ComponentProps< typeof ValidatedNumberControl >[ 'value' ]
|
|
38
|
+
>();
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<ValidatedNumberControl
|
|
42
|
+
{ ...args }
|
|
43
|
+
value={ value }
|
|
44
|
+
onChange={ ( newValue, ...rest ) => {
|
|
45
|
+
setValue( newValue );
|
|
46
|
+
onChange?.( newValue, ...rest );
|
|
47
|
+
} }
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
Default.args = {
|
|
53
|
+
required: true,
|
|
54
|
+
label: 'Number',
|
|
55
|
+
help: 'Odd numbers are not allowed.',
|
|
56
|
+
customValidator: ( value ) => {
|
|
57
|
+
if ( value && parseInt( value.toString(), 10 ) % 2 !== 0 ) {
|
|
58
|
+
return 'Choose an even number.';
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ArgTypes, Meta, Stories } from '@storybook/blocks';
|
|
2
|
+
import * as OverviewStories from './overview.story';
|
|
3
|
+
import { ValidatedInputControl } from '..';
|
|
4
|
+
|
|
5
|
+
<Meta of={ OverviewStories } title="Components (Private)/Validated Form Controls/Overview" />
|
|
6
|
+
|
|
7
|
+
# Validated Form Controls
|
|
8
|
+
|
|
9
|
+
This section contains form control components that extend [WordPress components](https://wordpress.github.io/gutenberg/) with additional validation capabilities.
|
|
10
|
+
|
|
11
|
+
## Status: Beta
|
|
12
|
+
|
|
13
|
+
We are still gathering feedback and iterating. Please get in touch with `@WordPress/gutenberg-components` if you are interested in trying them out in the Gutenberg app.
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
Component APIs are the same as the underlying WordPress components, with the addition of some optional props:
|
|
18
|
+
|
|
19
|
+
<ArgTypes of={ ValidatedInputControl } include={ [ 'required', 'markWhenOptional', 'customValidator' ] } />
|
|
20
|
+
|
|
21
|
+
## Implementation
|
|
22
|
+
|
|
23
|
+
These components are designed to work with the native HTML5 [Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/API/Constraint_validation). Using this browser API as the "source of truth" for form element errors has these benefits:
|
|
24
|
+
|
|
25
|
+
- Ability to use CSS selectors like `:invalid`, `:user-invalid`, `:required`, and `:optional`.
|
|
26
|
+
- Ability to use simple HTML attribute-based constraints (e.g. `min`, `max`, `required`, `pattern`, `type`) together with fully custom validation logic (with the `setCustomValidity()` method).
|
|
27
|
+
- Attribute-based constraints will already have localized, user-facing error messages built in.
|
|
28
|
+
- When a user clicks the form submit button, the browser will automatically check the validity states of all enclosed form elements and block the submit when there are errors. It will also automatically scroll and focus to the first erroring element and show a prominent error popover.
|
|
29
|
+
- While not _all_ aspects of the Constraint Validation API are well-supported in all screen readers yet, many aspects are, and will continue to improve. We can supplement any accessibility shortcomings with things like `aria-live` announcements of error messages.
|
|
30
|
+
|
|
31
|
+
## Current limitations
|
|
32
|
+
|
|
33
|
+
### No easy access to underlying validation APIs
|
|
34
|
+
|
|
35
|
+
- The consumer does not have a simple way to trigger their custom validators at an arbitrary point in time. Currently, the validation timings for custom validators are handled by the component — first on `blur`, and then on every `change` after the field is considered "touched". Note that this limitation only applies to **custom** validators, not the standard attribute-based validators like `required` or `pattern`, which can be triggered at any time using the `reportValidity()` method on either the underlying control element or the wrapping `<form>` element.
|
|
36
|
+
- The consumer does not have direct access to the [`validity` object](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState) of the underlying element.
|
|
37
|
+
|
|
38
|
+
We don't foresee these being needed much, but it is technically possible by the consumer accessing the target element's validation APIs via `ref`. Better docs or ergonomics can be added when we have actual use cases.
|
|
39
|
+
|
|
40
|
+
### Delegate elements
|
|
41
|
+
|
|
42
|
+
The implementations for `ToggleGroupControl` and `CustomSelectControl` use a "delegate" element for validation, due to upstream limitations that prevent us from using the actual underlying elements for constraint validation. A delegate element in this context is a visually hidden form element that we "delegate" the Constraint Validation API concerns to.
|
|
43
|
+
|
|
44
|
+
This is not ideal, but lets us maintain a consistent mechanism to scroll to the invalid field when attempting to submit, and block the form from submitting. It is hopefully fine as a stopgap, given the low amount of actual validation that will need happen on these two specific components.
|
|
45
|
+
|
|
46
|
+
### Controlled mode only
|
|
47
|
+
|
|
48
|
+
Some of the underlying WordPress components currently do not fully support uncontrolled mode. For now, we recommend sticking to controlled mode to avoid any issues.
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
<Stories />
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useState } from '@wordpress/element';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* External dependencies
|
|
8
|
+
*/
|
|
9
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Internal dependencies
|
|
13
|
+
*/
|
|
14
|
+
import { ValidatedInputControl } from '..';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
import type { ControlWithError } from '../../control-with-error';
|
|
17
|
+
|
|
18
|
+
const meta: Meta< typeof ControlWithError > = {
|
|
19
|
+
title: 'Components (Experimental)/Validated Form Controls/Overview',
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
};
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
type Story = StoryObj< typeof ControlWithError >;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* When there are multiple controls with errors, attempting to submit will
|
|
29
|
+
* move focus to the first control with an error.
|
|
30
|
+
*/
|
|
31
|
+
export const WithMultipleControls: Story = {
|
|
32
|
+
render: function Template() {
|
|
33
|
+
const [ text, setText ] = useState( '' );
|
|
34
|
+
const [ text2, setText2 ] = useState( '' );
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
<ValidatedInputControl
|
|
39
|
+
label="Text"
|
|
40
|
+
required
|
|
41
|
+
value={ text }
|
|
42
|
+
help="The word 'error' will trigger an error."
|
|
43
|
+
customValidator={ ( value ) => {
|
|
44
|
+
if ( value?.toLowerCase() === 'error' ) {
|
|
45
|
+
return 'The word "error" is not allowed.';
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
} }
|
|
49
|
+
onChange={ ( value ) => setText( value ?? '' ) }
|
|
50
|
+
/>
|
|
51
|
+
<ValidatedInputControl
|
|
52
|
+
label="Text"
|
|
53
|
+
required
|
|
54
|
+
value={ text2 }
|
|
55
|
+
help="The word 'error' will trigger an error."
|
|
56
|
+
customValidator={ ( value ) => {
|
|
57
|
+
if ( value?.toLowerCase() === 'error' ) {
|
|
58
|
+
return 'The word "error" is not allowed.';
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
} }
|
|
62
|
+
onChange={ ( value ) => setText2( value ?? '' ) }
|
|
63
|
+
/>
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Help text can be configured to be hidden when a custom error is reported. Whether to opt for this approach
|
|
71
|
+
* will depend on context.
|
|
72
|
+
*/
|
|
73
|
+
export const WithHelpTextReplacement: Story = {
|
|
74
|
+
render: function Template() {
|
|
75
|
+
const [ text, setText ] = useState( '' );
|
|
76
|
+
const [ hasCustomError, setHasCustomError ] = useState( false );
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<ValidatedInputControl
|
|
80
|
+
label="Text"
|
|
81
|
+
required
|
|
82
|
+
value={ text }
|
|
83
|
+
help={
|
|
84
|
+
hasCustomError
|
|
85
|
+
? undefined
|
|
86
|
+
: 'The word "error" is not allowed.'
|
|
87
|
+
}
|
|
88
|
+
customValidator={ ( value ) => {
|
|
89
|
+
if ( value?.toLowerCase() === 'error' ) {
|
|
90
|
+
setHasCustomError( true );
|
|
91
|
+
return 'The word "error" is not allowed.';
|
|
92
|
+
}
|
|
93
|
+
setHasCustomError( false );
|
|
94
|
+
return undefined;
|
|
95
|
+
} }
|
|
96
|
+
onChange={ ( value ) => setText( value ?? '' ) }
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
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 { ValidatedRadioControl } from '../radio-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedRadioControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedRadioControl',
|
|
19
|
+
component: ValidatedRadioControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
selected: { control: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
export const Default: StoryObj< typeof ValidatedRadioControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ selected, setSelected ] =
|
|
32
|
+
useState<
|
|
33
|
+
React.ComponentProps<
|
|
34
|
+
typeof ValidatedRadioControl
|
|
35
|
+
>[ 'selected' ]
|
|
36
|
+
>();
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ValidatedRadioControl
|
|
40
|
+
{ ...args }
|
|
41
|
+
selected={ selected }
|
|
42
|
+
onChange={ ( value ) => {
|
|
43
|
+
setSelected( value );
|
|
44
|
+
onChange?.( value );
|
|
45
|
+
} }
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
Default.args = {
|
|
51
|
+
required: true,
|
|
52
|
+
label: 'Radio',
|
|
53
|
+
help: 'Option B is not allowed.',
|
|
54
|
+
options: [
|
|
55
|
+
{ label: 'Option A', value: 'a' },
|
|
56
|
+
{ label: 'Option B (not allowed)', value: 'b' },
|
|
57
|
+
],
|
|
58
|
+
customValidator: ( value ) => {
|
|
59
|
+
if ( value === 'b' ) {
|
|
60
|
+
return 'Option B is not allowed.';
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
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 { formDecorator } from './story-utils';
|
|
15
|
+
import { ValidatedRangeControl } from '../range-control';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedRangeControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedRangeControl',
|
|
19
|
+
component: ValidatedRangeControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
value: { control: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
export const Default: StoryObj< typeof ValidatedRangeControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ value, setValue ] =
|
|
32
|
+
useState<
|
|
33
|
+
React.ComponentProps< typeof ValidatedRangeControl >[ 'value' ]
|
|
34
|
+
>();
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<ValidatedRangeControl
|
|
38
|
+
{ ...args }
|
|
39
|
+
value={ value }
|
|
40
|
+
onChange={ ( newValue ) => {
|
|
41
|
+
setValue( newValue );
|
|
42
|
+
onChange?.( newValue );
|
|
43
|
+
} }
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
Default.args = {
|
|
49
|
+
required: true,
|
|
50
|
+
label: 'Range',
|
|
51
|
+
help: 'Odd numbers are not allowed.',
|
|
52
|
+
min: 0,
|
|
53
|
+
max: 20,
|
|
54
|
+
customValidator: ( value ) => {
|
|
55
|
+
if ( value && value % 2 !== 0 ) {
|
|
56
|
+
return 'Choose an even number.';
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
},
|
|
60
|
+
};
|