@simplybusiness/mobius-datepicker 4.3.32 → 4.3.33
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 +9 -0
- package/dist/cjs/components/DatePicker/DatePicker.js +37 -20
- package/dist/cjs/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/esm/components/DatePicker/DatePicker.js +38 -21
- package/dist/esm/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/types/components/DatePicker/DatePicker.d.ts +6 -2
- package/package.json +2 -2
- package/src/components/DatePicker/DatePicker.stories.tsx +3 -11
- package/src/components/DatePicker/DatePicker.test.tsx +2 -2
- package/src/components/DatePicker/DatePicker.tsx +51 -21
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.3.33
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2392b6b: Fix handling of `isInvalid` prop; remove internal use of `validationState`
|
|
8
|
+
- Updated dependencies [2392b6b]
|
|
9
|
+
- Updated dependencies [09bc11f]
|
|
10
|
+
- @simplybusiness/mobius@4.8.8
|
|
11
|
+
|
|
3
12
|
## 4.3.32
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -11,6 +11,7 @@ Object.defineProperty(exports, "DatePicker", {
|
|
|
11
11
|
});
|
|
12
12
|
const _jsxruntime = require("react/jsx-runtime");
|
|
13
13
|
const _mobius = require("@simplybusiness/mobius");
|
|
14
|
+
const _icons = require("@simplybusiness/icons");
|
|
14
15
|
const _dedupe = /*#__PURE__*/ _interop_require_default(require("classnames/dedupe"));
|
|
15
16
|
const _react = require("react");
|
|
16
17
|
const _isTouchDevice = require("../../utils/isTouchDevice");
|
|
@@ -62,29 +63,39 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
62
63
|
return newObj;
|
|
63
64
|
}
|
|
64
65
|
const DatePickerModal = /*#__PURE__*/ (0, _react.lazy)(()=>Promise.resolve().then(()=>/*#__PURE__*/ _interop_require_wildcard(require("./DatePickerModal"))));
|
|
66
|
+
const getValidationState = (props)=>{
|
|
67
|
+
const { validationState, isInvalid } = props;
|
|
68
|
+
if (isInvalid || validationState === "invalid") {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (isInvalid === false || validationState === "valid") {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
};
|
|
65
76
|
const DatePicker = (props)=>{
|
|
66
|
-
const { onChange, defaultValue = "", isDisabled, validationState, errorMessage = "", ...otherProps } = props;
|
|
77
|
+
const { onChange, defaultValue = "", isDisabled, validationState, isInvalid, errorMessage = "", ...otherProps } = props;
|
|
67
78
|
const containerRef = (0, _react.useRef)(null);
|
|
68
79
|
const [top, setTop] = (0, _react.useState)(0);
|
|
69
80
|
const inputRef = (0, _react.useRef)(null);
|
|
70
81
|
const [isOpen, setIsOpen] = (0, _react.useState)(false);
|
|
71
82
|
const [textFieldVal, setTextFieldVal] = (0, _react.useState)((0, _utils.validateDateFormat)(defaultValue));
|
|
72
|
-
const [isValid, setIsValid] = (0, _react.useState)(
|
|
73
|
-
const
|
|
74
|
-
|
|
83
|
+
const [isValid, setIsValid] = (0, _react.useState)(undefined);
|
|
84
|
+
const isInvalidProp = getValidationState({
|
|
85
|
+
validationState,
|
|
86
|
+
isInvalid: isValid === false || isInvalid
|
|
87
|
+
});
|
|
88
|
+
const errorMessageText = isInvalidProp ? (0, _utils.formatErrorMessageText)(textFieldVal, props.min, props.max) : errorMessage;
|
|
75
89
|
const touchDevice = (0, _isTouchDevice.isTouchDevice)();
|
|
76
|
-
const validationClasses = {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
90
|
+
const validationClasses = (0, _mobius.useValidationClasses)({
|
|
91
|
+
validationState,
|
|
92
|
+
isInvalid: isInvalidProp
|
|
93
|
+
});
|
|
80
94
|
const containerClasses = (0, _dedupe.default)("mobius/DatePickerContainer", {
|
|
81
95
|
"--is-disabled": isDisabled,
|
|
82
|
-
"--is-touch-device": touchDevice
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const popoverToggleClasses = (0, _dedupe.default)("mobius/DateFieldButton", {
|
|
86
|
-
...validationClasses
|
|
87
|
-
});
|
|
96
|
+
"--is-touch-device": touchDevice
|
|
97
|
+
}, validationClasses);
|
|
98
|
+
const popoverToggleClasses = (0, _dedupe.default)("mobius/DateFieldButton", validationClasses);
|
|
88
99
|
const togglePopoverVisibility = ()=>{
|
|
89
100
|
setIsValid(true);
|
|
90
101
|
setIsOpen(!isOpen);
|
|
@@ -148,7 +159,7 @@ const DatePicker = (props)=>{
|
|
|
148
159
|
onChange: handleTextFieldChange,
|
|
149
160
|
value: textFieldVal,
|
|
150
161
|
isDisabled: isDisabled,
|
|
151
|
-
|
|
162
|
+
isInvalid: isInvalidProp,
|
|
152
163
|
...otherProps,
|
|
153
164
|
errorMessage: errorMessageText
|
|
154
165
|
})
|
|
@@ -167,16 +178,22 @@ const DatePicker = (props)=>{
|
|
|
167
178
|
onChange: handleTextFieldChange,
|
|
168
179
|
value: textFieldVal,
|
|
169
180
|
isDisabled: isDisabled,
|
|
170
|
-
|
|
181
|
+
isInvalid: isInvalidProp,
|
|
171
182
|
...otherProps,
|
|
172
183
|
errorMessage: errorMessageText,
|
|
173
|
-
suffixOutside: /*#__PURE__*/ (0, _jsxruntime.
|
|
184
|
+
suffixOutside: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_mobius.Button, {
|
|
174
185
|
className: popoverToggleClasses,
|
|
175
186
|
onClick: togglePopoverVisibility,
|
|
176
187
|
isDisabled: isDisabled,
|
|
177
|
-
children:
|
|
178
|
-
|
|
179
|
-
|
|
188
|
+
children: [
|
|
189
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_mobius.Icon, {
|
|
190
|
+
size: "sm",
|
|
191
|
+
icon: _icons.calendarDay
|
|
192
|
+
}),
|
|
193
|
+
/*#__PURE__*/ (0, _jsxruntime.jsx)(_mobius.VisuallyHidden, {
|
|
194
|
+
children: "Pick date"
|
|
195
|
+
})
|
|
196
|
+
]
|
|
180
197
|
})
|
|
181
198
|
}),
|
|
182
199
|
isOpen && /*#__PURE__*/ (0, _jsxruntime.jsx)(_react.Suspense, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Button,\n TextField,\n TextFieldElementType,\n TextFieldProps,\n VisuallyHidden,\n} from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport {\n ChangeEvent,\n FocusEvent,\n Suspense,\n lazy,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nexport interface DatePickerProps\n extends Omit<\n TextFieldProps,\n \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"\n > {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n validationState,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean>(true);\n const errorMessageText = !isValid\n ? // eslint-disable-next-line react/destructuring-assignment\n formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const inputValidationState = !isValid ? \"invalid\" : validationState;\n const touchDevice = isTouchDevice();\n\n const validationClasses = {\n \"--is-valid\": validationState === \"valid\",\n \"--is-invalid\": validationState === \"invalid\" || !isValid,\n };\n\n const containerClasses = classNames(\"mobius/DatePickerContainer\", {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n ...validationClasses,\n });\n\n const popoverToggleClasses = classNames(\"mobius/DateFieldButton\", {\n ...validationClasses,\n });\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const validate = () => {\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent<TextFieldElementType>) => {\n validate();\n\n // User hasn't entered a date OR\n // entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(event.target.value);\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n validationState={inputValidationState}\n {...otherProps}\n errorMessage={errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n validationState={inputValidationState}\n {...otherProps}\n errorMessage={errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n >\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n // eslint-disable-next-line react/destructuring-assignment\n min={props.min}\n // eslint-disable-next-line react/destructuring-assignment\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n"],"names":["DatePicker","DatePickerModal","lazy","props","onChange","defaultValue","isDisabled","validationState","errorMessage","otherProps","containerRef","useRef","top","setTop","useState","inputRef","isOpen","setIsOpen","textFieldVal","setTextFieldVal","validateDateFormat","isValid","setIsValid","errorMessageText","formatErrorMessageText","min","max","inputValidationState","touchDevice","isTouchDevice","validationClasses","containerClasses","classNames","popoverToggleClasses","togglePopoverVisibility","handleTextFieldChange","event","target","value","validate","isValidInput","current","checkValidity","onDateSelected","selectedDate","handleBlur","useEffect","getBoundingClientRect","height","div","className","TextField","ref","type","onBlur","suffixOutside","Button","onClick","VisuallyHidden","Suspense","date","onSelected"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Button,\n TextField,\n TextFieldElementType,\n TextFieldProps,\n VisuallyHidden,\n Validation,\n useValidationClasses,\n Icon,\n} from \"@simplybusiness/mobius\";\nimport { calendarDay } from \"@simplybusiness/icons\";\nimport classNames from \"classnames/dedupe\";\nimport {\n ChangeEvent,\n FocusEvent,\n Suspense,\n lazy,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nexport interface GetValidationStateProps {\n validationState?: Validation[\"validationState\"];\n isInvalid?: Validation[\"isInvalid\"];\n}\n\nconst getValidationState = (props: GetValidationStateProps) => {\n const { validationState, isInvalid } = props;\n\n if (isInvalid || validationState === \"invalid\") {\n return true;\n }\n\n if (isInvalid === false || validationState === \"valid\") {\n return false;\n }\n\n return undefined;\n};\n\nexport interface DatePickerProps\n extends Validation,\n Omit<TextFieldProps, \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"> {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n validationState,\n isInvalid,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean | undefined>(undefined);\n const isInvalidProp = getValidationState({\n validationState,\n isInvalid: isValid === false || isInvalid,\n });\n const errorMessageText = isInvalidProp\n ? // eslint-disable-next-line react/destructuring-assignment\n formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const touchDevice = isTouchDevice();\n\n const validationClasses = useValidationClasses({\n validationState,\n isInvalid: isInvalidProp,\n });\n\n const containerClasses = classNames(\n \"mobius/DatePickerContainer\",\n {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n },\n validationClasses,\n );\n\n const popoverToggleClasses = classNames(\n \"mobius/DateFieldButton\",\n validationClasses,\n );\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const validate = () => {\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent<TextFieldElementType>) => {\n validate();\n\n // User hasn't entered a date OR\n // entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(event.target.value);\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n >\n <Icon size=\"sm\" icon={calendarDay} />\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n // eslint-disable-next-line react/destructuring-assignment\n min={props.min}\n // eslint-disable-next-line react/destructuring-assignment\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n"],"names":["DatePicker","DatePickerModal","lazy","getValidationState","props","validationState","isInvalid","undefined","onChange","defaultValue","isDisabled","errorMessage","otherProps","containerRef","useRef","top","setTop","useState","inputRef","isOpen","setIsOpen","textFieldVal","setTextFieldVal","validateDateFormat","isValid","setIsValid","isInvalidProp","errorMessageText","formatErrorMessageText","min","max","touchDevice","isTouchDevice","validationClasses","useValidationClasses","containerClasses","classNames","popoverToggleClasses","togglePopoverVisibility","handleTextFieldChange","event","target","value","validate","isValidInput","current","checkValidity","onDateSelected","selectedDate","handleBlur","useEffect","getBoundingClientRect","height","div","className","TextField","ref","type","onBlur","suffixOutside","Button","onClick","Icon","size","icon","calendarDay","VisuallyHidden","Suspense","date","onSelected"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -1,34 +1,45 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Button, TextField, VisuallyHidden } from "@simplybusiness/mobius";
|
|
3
|
+
import { Button, TextField, VisuallyHidden, useValidationClasses, Icon } from "@simplybusiness/mobius";
|
|
4
|
+
import { calendarDay } from "@simplybusiness/icons";
|
|
4
5
|
import classNames from "classnames/dedupe";
|
|
5
6
|
import { Suspense, lazy, useEffect, useRef, useState } from "react";
|
|
6
7
|
import { isTouchDevice } from "../../utils/isTouchDevice";
|
|
7
8
|
import { formatErrorMessageText, validateDateFormat } from "./utils";
|
|
8
9
|
const DatePickerModal = /*#__PURE__*/ lazy(()=>import("./DatePickerModal"));
|
|
10
|
+
const getValidationState = (props)=>{
|
|
11
|
+
const { validationState, isInvalid } = props;
|
|
12
|
+
if (isInvalid || validationState === "invalid") {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (isInvalid === false || validationState === "valid") {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
};
|
|
9
20
|
export const DatePicker = (props)=>{
|
|
10
|
-
const { onChange, defaultValue = "", isDisabled, validationState, errorMessage = "", ...otherProps } = props;
|
|
21
|
+
const { onChange, defaultValue = "", isDisabled, validationState, isInvalid, errorMessage = "", ...otherProps } = props;
|
|
11
22
|
const containerRef = useRef(null);
|
|
12
23
|
const [top, setTop] = useState(0);
|
|
13
24
|
const inputRef = useRef(null);
|
|
14
25
|
const [isOpen, setIsOpen] = useState(false);
|
|
15
26
|
const [textFieldVal, setTextFieldVal] = useState(validateDateFormat(defaultValue));
|
|
16
|
-
const [isValid, setIsValid] = useState(
|
|
17
|
-
const
|
|
18
|
-
|
|
27
|
+
const [isValid, setIsValid] = useState(undefined);
|
|
28
|
+
const isInvalidProp = getValidationState({
|
|
29
|
+
validationState,
|
|
30
|
+
isInvalid: isValid === false || isInvalid
|
|
31
|
+
});
|
|
32
|
+
const errorMessageText = isInvalidProp ? formatErrorMessageText(textFieldVal, props.min, props.max) : errorMessage;
|
|
19
33
|
const touchDevice = isTouchDevice();
|
|
20
|
-
const validationClasses = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
};
|
|
34
|
+
const validationClasses = useValidationClasses({
|
|
35
|
+
validationState,
|
|
36
|
+
isInvalid: isInvalidProp
|
|
37
|
+
});
|
|
24
38
|
const containerClasses = classNames("mobius/DatePickerContainer", {
|
|
25
39
|
"--is-disabled": isDisabled,
|
|
26
|
-
"--is-touch-device": touchDevice
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const popoverToggleClasses = classNames("mobius/DateFieldButton", {
|
|
30
|
-
...validationClasses
|
|
31
|
-
});
|
|
40
|
+
"--is-touch-device": touchDevice
|
|
41
|
+
}, validationClasses);
|
|
42
|
+
const popoverToggleClasses = classNames("mobius/DateFieldButton", validationClasses);
|
|
32
43
|
const togglePopoverVisibility = ()=>{
|
|
33
44
|
setIsValid(true);
|
|
34
45
|
setIsOpen(!isOpen);
|
|
@@ -92,7 +103,7 @@ export const DatePicker = (props)=>{
|
|
|
92
103
|
onChange: handleTextFieldChange,
|
|
93
104
|
value: textFieldVal,
|
|
94
105
|
isDisabled: isDisabled,
|
|
95
|
-
|
|
106
|
+
isInvalid: isInvalidProp,
|
|
96
107
|
...otherProps,
|
|
97
108
|
errorMessage: errorMessageText
|
|
98
109
|
})
|
|
@@ -111,16 +122,22 @@ export const DatePicker = (props)=>{
|
|
|
111
122
|
onChange: handleTextFieldChange,
|
|
112
123
|
value: textFieldVal,
|
|
113
124
|
isDisabled: isDisabled,
|
|
114
|
-
|
|
125
|
+
isInvalid: isInvalidProp,
|
|
115
126
|
...otherProps,
|
|
116
127
|
errorMessage: errorMessageText,
|
|
117
|
-
suffixOutside: /*#__PURE__*/
|
|
128
|
+
suffixOutside: /*#__PURE__*/ _jsxs(Button, {
|
|
118
129
|
className: popoverToggleClasses,
|
|
119
130
|
onClick: togglePopoverVisibility,
|
|
120
131
|
isDisabled: isDisabled,
|
|
121
|
-
children:
|
|
122
|
-
|
|
123
|
-
|
|
132
|
+
children: [
|
|
133
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
134
|
+
size: "sm",
|
|
135
|
+
icon: calendarDay
|
|
136
|
+
}),
|
|
137
|
+
/*#__PURE__*/ _jsx(VisuallyHidden, {
|
|
138
|
+
children: "Pick date"
|
|
139
|
+
})
|
|
140
|
+
]
|
|
124
141
|
})
|
|
125
142
|
}),
|
|
126
143
|
isOpen && /*#__PURE__*/ _jsx(Suspense, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Button,\n TextField,\n TextFieldElementType,\n TextFieldProps,\n VisuallyHidden,\n} from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport {\n ChangeEvent,\n FocusEvent,\n Suspense,\n lazy,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nexport interface DatePickerProps\n extends Omit<\n TextFieldProps,\n \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"\n > {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n validationState,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean>(true);\n const errorMessageText = !isValid\n ? // eslint-disable-next-line react/destructuring-assignment\n formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const inputValidationState = !isValid ? \"invalid\" : validationState;\n const touchDevice = isTouchDevice();\n\n const validationClasses = {\n \"--is-valid\": validationState === \"valid\",\n \"--is-invalid\": validationState === \"invalid\" || !isValid,\n };\n\n const containerClasses = classNames(\"mobius/DatePickerContainer\", {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n ...validationClasses,\n });\n\n const popoverToggleClasses = classNames(\"mobius/DateFieldButton\", {\n ...validationClasses,\n });\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const validate = () => {\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent<TextFieldElementType>) => {\n validate();\n\n // User hasn't entered a date OR\n // entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(event.target.value);\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n validationState={inputValidationState}\n {...otherProps}\n errorMessage={errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n validationState={inputValidationState}\n {...otherProps}\n errorMessage={errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n >\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n // eslint-disable-next-line react/destructuring-assignment\n min={props.min}\n // eslint-disable-next-line react/destructuring-assignment\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n"],"names":["Button","TextField","VisuallyHidden","classNames","Suspense","lazy","useEffect","useRef","useState","isTouchDevice","formatErrorMessageText","validateDateFormat","DatePickerModal","DatePicker","props","onChange","defaultValue","isDisabled","validationState","errorMessage","otherProps","containerRef","top","setTop","inputRef","isOpen","setIsOpen","textFieldVal","setTextFieldVal","isValid","setIsValid","errorMessageText","min","max","inputValidationState","touchDevice","validationClasses","containerClasses","popoverToggleClasses","togglePopoverVisibility","handleTextFieldChange","event","target","value","validate","isValidInput","current","checkValidity","onDateSelected","selectedDate","handleBlur","getBoundingClientRect","height","div","className","ref","type","onBlur","suffixOutside","onClick","date","onSelected"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n Button,\n TextField,\n TextFieldElementType,\n TextFieldProps,\n VisuallyHidden,\n Validation,\n useValidationClasses,\n Icon,\n} from \"@simplybusiness/mobius\";\nimport { calendarDay } from \"@simplybusiness/icons\";\nimport classNames from \"classnames/dedupe\";\nimport {\n ChangeEvent,\n FocusEvent,\n Suspense,\n lazy,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nexport interface GetValidationStateProps {\n validationState?: Validation[\"validationState\"];\n isInvalid?: Validation[\"isInvalid\"];\n}\n\nconst getValidationState = (props: GetValidationStateProps) => {\n const { validationState, isInvalid } = props;\n\n if (isInvalid || validationState === \"invalid\") {\n return true;\n }\n\n if (isInvalid === false || validationState === \"valid\") {\n return false;\n }\n\n return undefined;\n};\n\nexport interface DatePickerProps\n extends Validation,\n Omit<TextFieldProps, \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"> {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n validationState,\n isInvalid,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean | undefined>(undefined);\n const isInvalidProp = getValidationState({\n validationState,\n isInvalid: isValid === false || isInvalid,\n });\n const errorMessageText = isInvalidProp\n ? // eslint-disable-next-line react/destructuring-assignment\n formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const touchDevice = isTouchDevice();\n\n const validationClasses = useValidationClasses({\n validationState,\n isInvalid: isInvalidProp,\n });\n\n const containerClasses = classNames(\n \"mobius/DatePickerContainer\",\n {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n },\n validationClasses,\n );\n\n const popoverToggleClasses = classNames(\n \"mobius/DateFieldButton\",\n validationClasses,\n );\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const validate = () => {\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent<TextFieldElementType>) => {\n validate();\n\n // User hasn't entered a date OR\n // entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(event.target.value);\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius/DatePicker\"\n // @ts-expect-error event type\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n >\n <Icon size=\"sm\" icon={calendarDay} />\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n // eslint-disable-next-line react/destructuring-assignment\n min={props.min}\n // eslint-disable-next-line react/destructuring-assignment\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n"],"names":["Button","TextField","VisuallyHidden","useValidationClasses","Icon","calendarDay","classNames","Suspense","lazy","useEffect","useRef","useState","isTouchDevice","formatErrorMessageText","validateDateFormat","DatePickerModal","getValidationState","props","validationState","isInvalid","undefined","DatePicker","onChange","defaultValue","isDisabled","errorMessage","otherProps","containerRef","top","setTop","inputRef","isOpen","setIsOpen","textFieldVal","setTextFieldVal","isValid","setIsValid","isInvalidProp","errorMessageText","min","max","touchDevice","validationClasses","containerClasses","popoverToggleClasses","togglePopoverVisibility","handleTextFieldChange","event","target","value","validate","isValidInput","current","checkValidity","onDateSelected","selectedDate","handleBlur","getBoundingClientRect","height","div","className","ref","type","onBlur","suffixOutside","onClick","size","icon","date","onSelected"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { TextFieldProps } from "@simplybusiness/mobius";
|
|
2
|
-
export interface
|
|
1
|
+
import { TextFieldProps, Validation } from "@simplybusiness/mobius";
|
|
2
|
+
export interface GetValidationStateProps {
|
|
3
|
+
validationState?: Validation["validationState"];
|
|
4
|
+
isInvalid?: Validation["isInvalid"];
|
|
5
|
+
}
|
|
6
|
+
export interface DatePickerProps extends Validation, Omit<TextFieldProps, "defaultValue" | "onChange" | "onBlur" | "onFocus"> {
|
|
3
7
|
onChange?: (date: string | undefined) => void;
|
|
4
8
|
defaultValue?: string;
|
|
5
9
|
min?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplybusiness/mobius-datepicker",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
|
-
"version": "4.3.
|
|
4
|
+
"version": "4.3.33",
|
|
5
5
|
"description": "Mobius date picker component",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"@simplybusiness/icons": "^4.7.1",
|
|
76
|
-
"@simplybusiness/mobius": "^4.8.
|
|
76
|
+
"@simplybusiness/mobius": "^4.8.8",
|
|
77
77
|
"classnames": "^2.5.1",
|
|
78
78
|
"date-fns": "^3.6.0",
|
|
79
79
|
"react-day-picker": "^8.10.1"
|
|
@@ -10,21 +10,13 @@ const meta: Meta<typeof DatePicker> = {
|
|
|
10
10
|
title: "Forms/DatePicker",
|
|
11
11
|
component: DatePicker,
|
|
12
12
|
argTypes: {
|
|
13
|
-
validationState: {
|
|
14
|
-
options: ["valid", "invalid", "neither"],
|
|
15
|
-
control: { type: "radio" },
|
|
16
|
-
mapping: {
|
|
17
|
-
valid: "valid",
|
|
18
|
-
invalid: "invalid",
|
|
19
|
-
neither: "",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
13
|
...excludeControls(
|
|
23
14
|
"description",
|
|
24
15
|
"type",
|
|
25
16
|
"labelElementType",
|
|
26
17
|
"inputElementType",
|
|
27
18
|
"isReadOnly",
|
|
19
|
+
"validationState",
|
|
28
20
|
),
|
|
29
21
|
},
|
|
30
22
|
args: {
|
|
@@ -84,7 +76,7 @@ export const Valid: StoryType = {
|
|
|
84
76
|
render: (args: DatePickerProps) => <DatePicker {...args} />,
|
|
85
77
|
args: {
|
|
86
78
|
label: "Start date",
|
|
87
|
-
|
|
79
|
+
isInvalid: false,
|
|
88
80
|
},
|
|
89
81
|
};
|
|
90
82
|
|
|
@@ -92,7 +84,7 @@ export const Invalid: StoryType = {
|
|
|
92
84
|
render: (args: DatePickerProps) => <DatePicker {...args} />,
|
|
93
85
|
args: {
|
|
94
86
|
label: "Start date",
|
|
95
|
-
|
|
87
|
+
isInvalid: true,
|
|
96
88
|
errorMessage: "This is an error message",
|
|
97
89
|
},
|
|
98
90
|
};
|
|
@@ -79,7 +79,7 @@ describe("DatePicker", () => {
|
|
|
79
79
|
<DatePicker
|
|
80
80
|
defaultValue={exampleDate}
|
|
81
81
|
label={labelText}
|
|
82
|
-
|
|
82
|
+
isInvalid={false}
|
|
83
83
|
/>,
|
|
84
84
|
);
|
|
85
85
|
|
|
@@ -96,7 +96,7 @@ describe("DatePicker", () => {
|
|
|
96
96
|
<DatePicker
|
|
97
97
|
defaultValue={exampleDate}
|
|
98
98
|
label={labelText}
|
|
99
|
-
|
|
99
|
+
isInvalid
|
|
100
100
|
/>,
|
|
101
101
|
);
|
|
102
102
|
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
TextFieldElementType,
|
|
7
7
|
TextFieldProps,
|
|
8
8
|
VisuallyHidden,
|
|
9
|
+
Validation,
|
|
10
|
+
useValidationClasses,
|
|
11
|
+
Icon,
|
|
9
12
|
} from "@simplybusiness/mobius";
|
|
13
|
+
import { calendarDay } from "@simplybusiness/icons";
|
|
10
14
|
import classNames from "classnames/dedupe";
|
|
11
15
|
import {
|
|
12
16
|
ChangeEvent,
|
|
@@ -22,11 +26,28 @@ import { formatErrorMessageText, validateDateFormat } from "./utils";
|
|
|
22
26
|
|
|
23
27
|
const DatePickerModal = lazy(() => import("./DatePickerModal"));
|
|
24
28
|
|
|
29
|
+
export interface GetValidationStateProps {
|
|
30
|
+
validationState?: Validation["validationState"];
|
|
31
|
+
isInvalid?: Validation["isInvalid"];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const getValidationState = (props: GetValidationStateProps) => {
|
|
35
|
+
const { validationState, isInvalid } = props;
|
|
36
|
+
|
|
37
|
+
if (isInvalid || validationState === "invalid") {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isInvalid === false || validationState === "valid") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return undefined;
|
|
46
|
+
};
|
|
47
|
+
|
|
25
48
|
export interface DatePickerProps
|
|
26
|
-
extends
|
|
27
|
-
TextFieldProps,
|
|
28
|
-
"defaultValue" | "onChange" | "onBlur" | "onFocus"
|
|
29
|
-
> {
|
|
49
|
+
extends Validation,
|
|
50
|
+
Omit<TextFieldProps, "defaultValue" | "onChange" | "onBlur" | "onFocus"> {
|
|
30
51
|
onChange?: (date: string | undefined) => void;
|
|
31
52
|
defaultValue?: string;
|
|
32
53
|
min?: string;
|
|
@@ -40,6 +61,7 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
40
61
|
defaultValue = "",
|
|
41
62
|
isDisabled,
|
|
42
63
|
validationState,
|
|
64
|
+
isInvalid,
|
|
43
65
|
errorMessage = "",
|
|
44
66
|
...otherProps
|
|
45
67
|
} = props;
|
|
@@ -50,28 +72,35 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
50
72
|
const [textFieldVal, setTextFieldVal] = useState<string>(
|
|
51
73
|
validateDateFormat(defaultValue),
|
|
52
74
|
);
|
|
53
|
-
const [isValid, setIsValid] = useState<boolean>(
|
|
54
|
-
const
|
|
75
|
+
const [isValid, setIsValid] = useState<boolean | undefined>(undefined);
|
|
76
|
+
const isInvalidProp = getValidationState({
|
|
77
|
+
validationState,
|
|
78
|
+
isInvalid: isValid === false || isInvalid,
|
|
79
|
+
});
|
|
80
|
+
const errorMessageText = isInvalidProp
|
|
55
81
|
? // eslint-disable-next-line react/destructuring-assignment
|
|
56
82
|
formatErrorMessageText(textFieldVal, props.min, props.max)
|
|
57
83
|
: errorMessage;
|
|
58
|
-
const inputValidationState = !isValid ? "invalid" : validationState;
|
|
59
84
|
const touchDevice = isTouchDevice();
|
|
60
85
|
|
|
61
|
-
const validationClasses = {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const containerClasses = classNames("mobius/DatePickerContainer", {
|
|
67
|
-
"--is-disabled": isDisabled,
|
|
68
|
-
"--is-touch-device": touchDevice,
|
|
69
|
-
...validationClasses,
|
|
86
|
+
const validationClasses = useValidationClasses({
|
|
87
|
+
validationState,
|
|
88
|
+
isInvalid: isInvalidProp,
|
|
70
89
|
});
|
|
71
90
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
91
|
+
const containerClasses = classNames(
|
|
92
|
+
"mobius/DatePickerContainer",
|
|
93
|
+
{
|
|
94
|
+
"--is-disabled": isDisabled,
|
|
95
|
+
"--is-touch-device": touchDevice,
|
|
96
|
+
},
|
|
97
|
+
validationClasses,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const popoverToggleClasses = classNames(
|
|
101
|
+
"mobius/DateFieldButton",
|
|
102
|
+
validationClasses,
|
|
103
|
+
);
|
|
75
104
|
|
|
76
105
|
const togglePopoverVisibility = () => {
|
|
77
106
|
setIsValid(true);
|
|
@@ -143,7 +172,7 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
143
172
|
onChange={handleTextFieldChange}
|
|
144
173
|
value={textFieldVal}
|
|
145
174
|
isDisabled={isDisabled}
|
|
146
|
-
|
|
175
|
+
isInvalid={isInvalidProp}
|
|
147
176
|
{...otherProps}
|
|
148
177
|
errorMessage={errorMessageText}
|
|
149
178
|
/>
|
|
@@ -162,7 +191,7 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
162
191
|
onChange={handleTextFieldChange}
|
|
163
192
|
value={textFieldVal}
|
|
164
193
|
isDisabled={isDisabled}
|
|
165
|
-
|
|
194
|
+
isInvalid={isInvalidProp}
|
|
166
195
|
{...otherProps}
|
|
167
196
|
errorMessage={errorMessageText}
|
|
168
197
|
suffixOutside={
|
|
@@ -171,6 +200,7 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
171
200
|
onClick={togglePopoverVisibility}
|
|
172
201
|
isDisabled={isDisabled}
|
|
173
202
|
>
|
|
203
|
+
<Icon size="sm" icon={calendarDay} />
|
|
174
204
|
<VisuallyHidden>Pick date</VisuallyHidden>
|
|
175
205
|
</Button>
|
|
176
206
|
}
|