@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,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 { ValidatedSelectControl } from '../select-control';
|
|
15
|
+
import { formDecorator } from './story-utils';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedSelectControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedSelectControl',
|
|
19
|
+
component: ValidatedSelectControl,
|
|
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 ValidatedSelectControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ value, setValue ] = useState( '' );
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ValidatedSelectControl
|
|
35
|
+
{ ...args }
|
|
36
|
+
value={ value }
|
|
37
|
+
onChange={ ( newValue ) => {
|
|
38
|
+
setValue( newValue );
|
|
39
|
+
onChange?.( newValue );
|
|
40
|
+
} }
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
Default.args = {
|
|
46
|
+
required: true,
|
|
47
|
+
label: 'Select',
|
|
48
|
+
help: 'Selecting option 1 will trigger an error.',
|
|
49
|
+
options: [
|
|
50
|
+
{ value: '', label: 'Select an option' },
|
|
51
|
+
{ value: '1', label: 'Option 1 (not allowed)' },
|
|
52
|
+
{ value: '2', label: 'Option 2' },
|
|
53
|
+
],
|
|
54
|
+
customValidator: ( value ) => {
|
|
55
|
+
if ( value === '1' ) {
|
|
56
|
+
return 'Option 1 is not allowed.';
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* External dependencies
|
|
7
|
+
*/
|
|
8
|
+
import type { Meta } from '@storybook/react';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal dependencies
|
|
12
|
+
*/
|
|
13
|
+
import Button from '../../../button';
|
|
14
|
+
|
|
15
|
+
export const formDecorator: Meta[ 'decorators' ] = ( Story ) => (
|
|
16
|
+
<form
|
|
17
|
+
style={ {
|
|
18
|
+
fontFamily: 'sans-serif',
|
|
19
|
+
display: 'flex',
|
|
20
|
+
flexDirection: 'column',
|
|
21
|
+
alignItems: 'flex-start',
|
|
22
|
+
gap: 16,
|
|
23
|
+
} }
|
|
24
|
+
onSubmit={ ( e ) => {
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
// eslint-disable-next-line no-alert
|
|
27
|
+
alert( 'Form submitted!' );
|
|
28
|
+
} }
|
|
29
|
+
>
|
|
30
|
+
<div
|
|
31
|
+
style={ {
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'column',
|
|
34
|
+
gap: 16,
|
|
35
|
+
alignItems: 'stretch',
|
|
36
|
+
width: 300,
|
|
37
|
+
} }
|
|
38
|
+
>
|
|
39
|
+
<Story />
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<Button variant="primary" type="submit" __next40pxDefaultSize>
|
|
43
|
+
Submit
|
|
44
|
+
</Button>
|
|
45
|
+
</form>
|
|
46
|
+
);
|
|
@@ -0,0 +1,55 @@
|
|
|
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 { ValidatedTextControl } from '../text-control';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedTextControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedTextControl',
|
|
19
|
+
component: ValidatedTextControl,
|
|
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 ValidatedTextControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ value, setValue ] = useState( '' );
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ValidatedTextControl
|
|
35
|
+
{ ...args }
|
|
36
|
+
value={ value }
|
|
37
|
+
onChange={ ( newValue ) => {
|
|
38
|
+
setValue( newValue );
|
|
39
|
+
onChange?.( newValue );
|
|
40
|
+
} }
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
Default.args = {
|
|
46
|
+
required: true,
|
|
47
|
+
label: 'Text',
|
|
48
|
+
help: "The word 'error' will trigger an error.",
|
|
49
|
+
customValidator: ( value ) => {
|
|
50
|
+
if ( value?.toString().toLowerCase() === 'error' ) {
|
|
51
|
+
return 'The word "error" is not allowed.';
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
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
|
+
* Internal dependencies
|
|
12
|
+
*/
|
|
13
|
+
import { formDecorator } from './story-utils';
|
|
14
|
+
import { ValidatedTextareaControl } from '../textarea-control';
|
|
15
|
+
|
|
16
|
+
const meta: Meta< typeof ValidatedTextareaControl > = {
|
|
17
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedTextareaControl',
|
|
18
|
+
component: ValidatedTextareaControl,
|
|
19
|
+
tags: [ 'status-private' ],
|
|
20
|
+
decorators: formDecorator,
|
|
21
|
+
args: { onChange: () => {} },
|
|
22
|
+
argTypes: { value: { control: false } },
|
|
23
|
+
};
|
|
24
|
+
export default meta;
|
|
25
|
+
|
|
26
|
+
export const Default: StoryObj< typeof ValidatedTextareaControl > = {
|
|
27
|
+
render: function Template( { onChange, ...args } ) {
|
|
28
|
+
const [ value, setValue ] = useState( '' );
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<ValidatedTextareaControl
|
|
32
|
+
{ ...args }
|
|
33
|
+
onChange={ ( newValue ) => {
|
|
34
|
+
setValue( newValue );
|
|
35
|
+
onChange?.( newValue );
|
|
36
|
+
} }
|
|
37
|
+
value={ value }
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
Default.args = {
|
|
43
|
+
required: true,
|
|
44
|
+
label: 'Textarea',
|
|
45
|
+
help: 'The word "error" will trigger an error.',
|
|
46
|
+
customValidator: ( value ) => {
|
|
47
|
+
if ( value?.toLowerCase() === 'error' ) {
|
|
48
|
+
return 'The word "error" is not allowed.';
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
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 { ValidatedToggleControl } from '../toggle-control';
|
|
16
|
+
|
|
17
|
+
const meta: Meta< typeof ValidatedToggleControl > = {
|
|
18
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedToggleControl',
|
|
19
|
+
component: ValidatedToggleControl,
|
|
20
|
+
tags: [ 'status-private' ],
|
|
21
|
+
decorators: formDecorator,
|
|
22
|
+
args: { onChange: () => {} },
|
|
23
|
+
argTypes: {
|
|
24
|
+
checked: { control: false },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
export const Default: StoryObj< typeof ValidatedToggleControl > = {
|
|
30
|
+
render: function Template( { onChange, ...args } ) {
|
|
31
|
+
const [ checked, setChecked ] = useState( false );
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ValidatedToggleControl
|
|
35
|
+
{ ...args }
|
|
36
|
+
checked={ checked }
|
|
37
|
+
onChange={ ( value ) => {
|
|
38
|
+
setChecked( value );
|
|
39
|
+
onChange?.( value );
|
|
40
|
+
} }
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
Default.args = {
|
|
46
|
+
required: true,
|
|
47
|
+
label: 'Toggle',
|
|
48
|
+
help: 'This toggle may neither be enabled nor disabled.',
|
|
49
|
+
customValidator: ( value ) => {
|
|
50
|
+
if ( value ) {
|
|
51
|
+
return 'This toggle may not be enabled.';
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { ValidatedToggleGroupControl } from '../toggle-group-control';
|
|
16
|
+
import { ToggleGroupControlOption } from '../../../toggle-group-control';
|
|
17
|
+
|
|
18
|
+
const meta: Meta< typeof ValidatedToggleGroupControl > = {
|
|
19
|
+
title: 'Components (Experimental)/Validated Form Controls/ValidatedToggleGroupControl',
|
|
20
|
+
component: ValidatedToggleGroupControl,
|
|
21
|
+
tags: [ 'status-private' ],
|
|
22
|
+
decorators: formDecorator,
|
|
23
|
+
args: { onChange: () => {} },
|
|
24
|
+
argTypes: {
|
|
25
|
+
value: { control: false },
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
export default meta;
|
|
29
|
+
|
|
30
|
+
export const Default: StoryObj< typeof ValidatedToggleGroupControl > = {
|
|
31
|
+
render: function Template( { onChange, ...args } ) {
|
|
32
|
+
const [ value, setValue ] =
|
|
33
|
+
useState<
|
|
34
|
+
React.ComponentProps<
|
|
35
|
+
typeof ValidatedToggleGroupControl
|
|
36
|
+
>[ 'value' ]
|
|
37
|
+
>( '1' );
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<ValidatedToggleGroupControl
|
|
41
|
+
{ ...args }
|
|
42
|
+
value={ value }
|
|
43
|
+
onChange={ ( newValue ) => {
|
|
44
|
+
setValue( newValue );
|
|
45
|
+
onChange?.( newValue );
|
|
46
|
+
} }
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
Default.args = {
|
|
52
|
+
required: true,
|
|
53
|
+
label: 'Toggle Group',
|
|
54
|
+
isBlock: true,
|
|
55
|
+
children: [
|
|
56
|
+
<ToggleGroupControlOption value="1" key="1" label="Option 1" />,
|
|
57
|
+
<ToggleGroupControlOption value="2" key="2" label="Option 2" />,
|
|
58
|
+
],
|
|
59
|
+
help: 'Selecting option 2 will trigger an error.',
|
|
60
|
+
customValidator: ( value ) => {
|
|
61
|
+
if ( value === '2' ) {
|
|
62
|
+
return 'Option 2 is not allowed.';
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useMergeRefs } from '@wordpress/compose';
|
|
5
|
+
import { forwardRef, useRef } from '@wordpress/element';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { ControlWithError } from '../control-with-error';
|
|
11
|
+
import type { ValidatedControlProps } from './types';
|
|
12
|
+
import TextControl from '../../text-control';
|
|
13
|
+
import type { TextControlProps } from '../../text-control/types';
|
|
14
|
+
|
|
15
|
+
type Value = TextControlProps[ 'value' ];
|
|
16
|
+
|
|
17
|
+
const UnforwardedValidatedTextControl = (
|
|
18
|
+
{
|
|
19
|
+
required,
|
|
20
|
+
customValidator,
|
|
21
|
+
onChange,
|
|
22
|
+
markWhenOptional,
|
|
23
|
+
...restProps
|
|
24
|
+
}: Omit<
|
|
25
|
+
React.ComponentProps< typeof TextControl >,
|
|
26
|
+
'__next40pxDefaultSize' | '__nextHasNoMarginBottom'
|
|
27
|
+
> &
|
|
28
|
+
ValidatedControlProps< Value >,
|
|
29
|
+
forwardedRef: React.ForwardedRef< HTMLInputElement >
|
|
30
|
+
) => {
|
|
31
|
+
const validityTargetRef = useRef< HTMLInputElement >( null );
|
|
32
|
+
const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
|
|
33
|
+
const valueRef = useRef< Value >( restProps.value );
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ControlWithError
|
|
37
|
+
required={ required }
|
|
38
|
+
markWhenOptional={ markWhenOptional }
|
|
39
|
+
customValidator={ () => {
|
|
40
|
+
return customValidator?.( valueRef.current );
|
|
41
|
+
} }
|
|
42
|
+
getValidityTarget={ () => validityTargetRef.current }
|
|
43
|
+
>
|
|
44
|
+
<TextControl
|
|
45
|
+
__next40pxDefaultSize
|
|
46
|
+
__nextHasNoMarginBottom
|
|
47
|
+
ref={ mergedRefs }
|
|
48
|
+
onChange={ ( value ) => {
|
|
49
|
+
valueRef.current = value;
|
|
50
|
+
onChange?.( value );
|
|
51
|
+
} }
|
|
52
|
+
{ ...restProps }
|
|
53
|
+
/>
|
|
54
|
+
</ControlWithError>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const ValidatedTextControl = forwardRef(
|
|
59
|
+
UnforwardedValidatedTextControl
|
|
60
|
+
);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { forwardRef, useRef } from '@wordpress/element';
|
|
5
|
+
import { useMergeRefs } from '@wordpress/compose';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { ControlWithError } from '../control-with-error';
|
|
11
|
+
import type { ValidatedControlProps } from './types';
|
|
12
|
+
import TextareaControl from '../../textarea-control';
|
|
13
|
+
import type { TextareaControlProps } from '../../textarea-control/types';
|
|
14
|
+
|
|
15
|
+
type Value = TextareaControlProps[ 'value' ];
|
|
16
|
+
|
|
17
|
+
const UnforwardedValidatedTextareaControl = (
|
|
18
|
+
{
|
|
19
|
+
required,
|
|
20
|
+
customValidator,
|
|
21
|
+
onChange,
|
|
22
|
+
markWhenOptional,
|
|
23
|
+
...restProps
|
|
24
|
+
}: Omit<
|
|
25
|
+
React.ComponentProps< typeof TextareaControl >,
|
|
26
|
+
'__nextHasNoMarginBottom'
|
|
27
|
+
> &
|
|
28
|
+
ValidatedControlProps< Value >,
|
|
29
|
+
forwardedRef: React.ForwardedRef< HTMLTextAreaElement >
|
|
30
|
+
) => {
|
|
31
|
+
const validityTargetRef = useRef< HTMLTextAreaElement >( null );
|
|
32
|
+
const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
|
|
33
|
+
const valueRef = useRef< Value >( restProps.value );
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<ControlWithError
|
|
37
|
+
required={ required }
|
|
38
|
+
markWhenOptional={ markWhenOptional }
|
|
39
|
+
customValidator={ () => {
|
|
40
|
+
return customValidator?.( valueRef.current );
|
|
41
|
+
} }
|
|
42
|
+
getValidityTarget={ () => validityTargetRef.current }
|
|
43
|
+
>
|
|
44
|
+
<TextareaControl
|
|
45
|
+
__nextHasNoMarginBottom
|
|
46
|
+
ref={ mergedRefs }
|
|
47
|
+
onChange={ ( value ) => {
|
|
48
|
+
valueRef.current = value;
|
|
49
|
+
onChange?.( value );
|
|
50
|
+
} }
|
|
51
|
+
{ ...restProps }
|
|
52
|
+
/>
|
|
53
|
+
</ControlWithError>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const ValidatedTextareaControl = forwardRef(
|
|
58
|
+
UnforwardedValidatedTextareaControl
|
|
59
|
+
);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { forwardRef, useRef, useEffect } from '@wordpress/element';
|
|
5
|
+
import { useMergeRefs } from '@wordpress/compose';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Internal dependencies
|
|
9
|
+
*/
|
|
10
|
+
import { ControlWithError } from '../control-with-error';
|
|
11
|
+
import type { ValidatedControlProps } from './types';
|
|
12
|
+
import ToggleControl from '../../toggle-control';
|
|
13
|
+
import type { ToggleControlProps } from '../../toggle-control/types';
|
|
14
|
+
|
|
15
|
+
type Value = ToggleControlProps[ 'checked' ];
|
|
16
|
+
|
|
17
|
+
// TODO: Should we customize the default `missingValue` message? It says to "check this box".
|
|
18
|
+
|
|
19
|
+
const UnforwardedValidatedToggleControl = (
|
|
20
|
+
{
|
|
21
|
+
required,
|
|
22
|
+
customValidator,
|
|
23
|
+
onChange,
|
|
24
|
+
markWhenOptional,
|
|
25
|
+
...restProps
|
|
26
|
+
}: Omit<
|
|
27
|
+
React.ComponentProps< typeof ToggleControl >,
|
|
28
|
+
'__nextHasNoMarginBottom'
|
|
29
|
+
> &
|
|
30
|
+
ValidatedControlProps< Value >,
|
|
31
|
+
forwardedRef: React.ForwardedRef< HTMLInputElement >
|
|
32
|
+
) => {
|
|
33
|
+
const validityTargetRef = useRef< HTMLInputElement >( null );
|
|
34
|
+
const mergedRefs = useMergeRefs( [ forwardedRef, validityTargetRef ] );
|
|
35
|
+
const valueRef = useRef< Value >( restProps.checked );
|
|
36
|
+
|
|
37
|
+
// TODO: Upstream limitation - The `required` attribute is not passed down to the input,
|
|
38
|
+
// so we need to set it manually.
|
|
39
|
+
useEffect( () => {
|
|
40
|
+
if ( validityTargetRef.current ) {
|
|
41
|
+
validityTargetRef.current.required = required ?? false;
|
|
42
|
+
}
|
|
43
|
+
}, [ required ] );
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ControlWithError
|
|
47
|
+
required={ required }
|
|
48
|
+
markWhenOptional={ markWhenOptional }
|
|
49
|
+
customValidator={ () => {
|
|
50
|
+
return customValidator?.( valueRef.current );
|
|
51
|
+
} }
|
|
52
|
+
getValidityTarget={ () => validityTargetRef.current }
|
|
53
|
+
>
|
|
54
|
+
<ToggleControl
|
|
55
|
+
__nextHasNoMarginBottom
|
|
56
|
+
ref={ mergedRefs }
|
|
57
|
+
onChange={ ( value ) => {
|
|
58
|
+
valueRef.current = value;
|
|
59
|
+
onChange?.( value );
|
|
60
|
+
} }
|
|
61
|
+
{ ...restProps }
|
|
62
|
+
/>
|
|
63
|
+
</ControlWithError>
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const ValidatedToggleControl = forwardRef(
|
|
68
|
+
UnforwardedValidatedToggleControl
|
|
69
|
+
);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { forwardRef, useId, 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 { ToggleGroupControl } from '../../toggle-group-control';
|
|
12
|
+
import type { ToggleGroupControlProps } from '../../toggle-group-control/types';
|
|
13
|
+
|
|
14
|
+
type Value = ToggleGroupControlProps[ 'value' ];
|
|
15
|
+
|
|
16
|
+
const UnforwardedValidatedToggleGroupControl = (
|
|
17
|
+
{
|
|
18
|
+
required,
|
|
19
|
+
customValidator,
|
|
20
|
+
onChange,
|
|
21
|
+
markWhenOptional,
|
|
22
|
+
...restProps
|
|
23
|
+
}: Omit<
|
|
24
|
+
React.ComponentProps< typeof ToggleGroupControl >,
|
|
25
|
+
'__next40pxDefaultSize' | '__nextHasNoMarginBottom'
|
|
26
|
+
> &
|
|
27
|
+
ValidatedControlProps< Value >,
|
|
28
|
+
forwardedRef: React.ForwardedRef< HTMLInputElement >
|
|
29
|
+
) => {
|
|
30
|
+
const validityTargetRef = useRef< HTMLInputElement >( null );
|
|
31
|
+
const valueRef = useRef< Value >( restProps.value );
|
|
32
|
+
|
|
33
|
+
const nameAttr = useId();
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="components-validated-control__wrapper-with-error-delegate">
|
|
37
|
+
<ControlWithError
|
|
38
|
+
required={ required }
|
|
39
|
+
markWhenOptional={ markWhenOptional }
|
|
40
|
+
customValidator={ () => {
|
|
41
|
+
return customValidator?.( valueRef.current );
|
|
42
|
+
} }
|
|
43
|
+
getValidityTarget={ () => validityTargetRef.current }
|
|
44
|
+
>
|
|
45
|
+
<ToggleGroupControl
|
|
46
|
+
__nextHasNoMarginBottom
|
|
47
|
+
__next40pxDefaultSize
|
|
48
|
+
ref={ forwardedRef }
|
|
49
|
+
// TODO: Upstream limitation - In uncontrolled mode, starting from an undefined value then
|
|
50
|
+
// setting a value has a visual bug.
|
|
51
|
+
onChange={ ( value ) => {
|
|
52
|
+
valueRef.current = value;
|
|
53
|
+
onChange?.( value );
|
|
54
|
+
} }
|
|
55
|
+
{ ...restProps }
|
|
56
|
+
/>
|
|
57
|
+
</ControlWithError>
|
|
58
|
+
<input
|
|
59
|
+
className="components-validated-control__error-delegate"
|
|
60
|
+
type="radio"
|
|
61
|
+
ref={ validityTargetRef }
|
|
62
|
+
required={ required }
|
|
63
|
+
checked={ restProps.value !== null }
|
|
64
|
+
tabIndex={ -1 }
|
|
65
|
+
// A name attribute is needed for the `required` behavior to work.
|
|
66
|
+
name={ nameAttr }
|
|
67
|
+
onChange={ () => {} }
|
|
68
|
+
onFocus={ ( e ) => {
|
|
69
|
+
e.target.previousElementSibling
|
|
70
|
+
?.querySelector< HTMLButtonElement | HTMLInputElement >(
|
|
71
|
+
'[data-active-item="true"]'
|
|
72
|
+
)
|
|
73
|
+
?.focus();
|
|
74
|
+
} }
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const ValidatedToggleGroupControl = forwardRef(
|
|
81
|
+
UnforwardedValidatedToggleGroupControl
|
|
82
|
+
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type ValidatedControlProps< V > = {
|
|
2
|
+
/**
|
|
3
|
+
* Whether the control is required.
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
required?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Label the control as "optional" when _not_ `required`, instead of the inverse.
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
markWhenOptional?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* A function that returns a custom validity message when applicable. This error message will be applied to the
|
|
14
|
+
* underlying element using the native [`setCustomValidity()` method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity).
|
|
15
|
+
* This means the custom validator will be run _in addition_ to any other HTML attribute-based validation, and
|
|
16
|
+
* will be prioritized over any existing validity messages dictated by the HTML attributes.
|
|
17
|
+
* An empty string or `undefined` return value will clear any existing custom validity message.
|
|
18
|
+
*
|
|
19
|
+
* Make sure you don't programatically pass a value (such as an initial value) to the control component
|
|
20
|
+
* that fails this validator, because the validator will only run for user-initiated changes.
|
|
21
|
+
*
|
|
22
|
+
* Always prefer using standard HTML attributes like `required` and `min`/`max` over custom validators
|
|
23
|
+
* when possible, as they are simpler and have localized error messages built in.
|
|
24
|
+
*/
|
|
25
|
+
// TODO: Technically, we could add an optional `customValidity` string prop so the consumer can set
|
|
26
|
+
// an error message at any point in time. We should wait until we have a use case though.
|
|
27
|
+
customValidator?: ( currentValue: V ) => string | void;
|
|
28
|
+
};
|