@availity/mui-datepicker 0.6.1 → 1.0.0-alpha.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 +19 -0
- package/DateRangePicker.mdx +8 -0
- package/DateRangePickerDocs.md +294 -0
- package/dist/index.js +7 -6
- package/dist/index.mjs +4 -3
- package/package.json +7 -7
- package/src/lib/Datepicker.stories.tsx +64 -5
- package/src/lib/Datepicker.test.tsx +9 -0
- package/src/lib/Datepicker.tsx +4 -2
- /package/{introduction.stories.mdx → introduction.mdx} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
|
|
4
4
|
|
|
5
|
+
## [1.0.0-alpha.0](https://github.com/Availity/element/compare/@availity/mui-datepicker@0.6.2...@availity/mui-datepicker@1.0.0-alpha.0) (2025-02-24)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
* upgraded to @mui/material v6
|
|
11
|
+
* **element:** upgraded to @mui/material v6
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **element:** upgrade to @mui/material v6 ([cb958bb](https://github.com/Availity/element/commit/cb958bba99a4f1ee6dab323f0ff54b69e6fd3493))
|
|
16
|
+
* upgrade @mui/material ([571453a](https://github.com/Availity/element/commit/571453a34b21c344594ab4c03bc497d19aba942b))
|
|
17
|
+
* upgrade to MUI v6 ([7febd6f](https://github.com/Availity/element/commit/7febd6fd4fd58e87e1c97a832cea3b4595a35d58))
|
|
18
|
+
|
|
19
|
+
## [0.6.2](https://github.com/Availity/element/compare/@availity/mui-datepicker@0.6.1...@availity/mui-datepicker@0.6.2) (2025-02-18)
|
|
20
|
+
|
|
21
|
+
### Dependency Updates
|
|
22
|
+
|
|
23
|
+
* `mui-textfield` updated to version `0.6.1`
|
|
5
24
|
## [0.6.1](https://github.com/Availity/element/compare/@availity/mui-datepicker@0.6.0...@availity/mui-datepicker@0.6.1) (2025-02-05)
|
|
6
25
|
|
|
7
26
|
### Dependency Updates
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Markdown, Source } from '@storybook/blocks';
|
|
2
|
+
import { Meta } from '@storybook/addon-docs';
|
|
3
|
+
|
|
4
|
+
import Docs from './DateRangePickerDocs.md?raw';
|
|
5
|
+
|
|
6
|
+
<Meta title="Form Components/Datepicker/Datepicker/Date Range Picker Docs" />
|
|
7
|
+
|
|
8
|
+
<Markdown>{Docs}</Markdown>
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# DateRangePicker Docs
|
|
2
|
+
|
|
3
|
+
The `element` library has a `Datepicker` component that can be used to create your own `DateRangePicker`. There is not a `DateRangePicker` exported from the library.
|
|
4
|
+
|
|
5
|
+
## Example
|
|
6
|
+
|
|
7
|
+
The following code block shows an example `DateRangePicker` using the `Datepicker` and `Grid` components.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Datepicker, Grid } from '@availity/element';
|
|
11
|
+
import type { Dayjs } from 'dayjs';
|
|
12
|
+
|
|
13
|
+
type DateRangePickerProps = {
|
|
14
|
+
startDate: Dayjs | null;
|
|
15
|
+
endDate: Dayjs | null;
|
|
16
|
+
onStartDateChange: (date: Dayjs | null) => void;
|
|
17
|
+
onEndDateChange: (date: Dayjs | null) => void;
|
|
18
|
+
startFieldProps?: {
|
|
19
|
+
label?: string;
|
|
20
|
+
helperText?: string;
|
|
21
|
+
helpTopicId?: string;
|
|
22
|
+
fullWidth?: boolean;
|
|
23
|
+
};
|
|
24
|
+
endFieldProps?: {
|
|
25
|
+
label?: string;
|
|
26
|
+
helperText?: string;
|
|
27
|
+
helpTopicId?: string;
|
|
28
|
+
fullWidth?: boolean;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DateRangePicker = ({
|
|
33
|
+
startDate,
|
|
34
|
+
endDate,
|
|
35
|
+
onStartDateChange,
|
|
36
|
+
onEndDateChange,
|
|
37
|
+
startFieldProps = {
|
|
38
|
+
label: 'Start Date',
|
|
39
|
+
helperText: 'Select start date',
|
|
40
|
+
},
|
|
41
|
+
endFieldProps = {
|
|
42
|
+
label: 'End Date',
|
|
43
|
+
helperText: 'Select end date',
|
|
44
|
+
},
|
|
45
|
+
}: DateRangePickerProps) => {
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<Grid container spacing={2}>
|
|
49
|
+
<Grid size={{xs: 12, sm: 6}}>
|
|
50
|
+
<Datepicker
|
|
51
|
+
value={startDate}
|
|
52
|
+
onChange={onStartDateChange}
|
|
53
|
+
FieldProps={startFieldProps}
|
|
54
|
+
maxDate={endDate ?? undefined} // Prevent selecting start date after end date
|
|
55
|
+
views={['day', 'month', 'year']}
|
|
56
|
+
/>
|
|
57
|
+
</Grid>
|
|
58
|
+
<Grid size={{xs: 12, sm: 6}}>
|
|
59
|
+
<Datepicker
|
|
60
|
+
value={endDate}
|
|
61
|
+
onChange={onEndDateChange}
|
|
62
|
+
FieldProps={endFieldProps}
|
|
63
|
+
minDate={startDate ?? undefined} // Prevent selecting end date before start date
|
|
64
|
+
views={['day', 'month', 'year']}
|
|
65
|
+
/>
|
|
66
|
+
</Grid>
|
|
67
|
+
</Grid>
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Simple Usage
|
|
74
|
+
|
|
75
|
+
Below is an example of the `DateRangePicker` component we made above.
|
|
76
|
+
|
|
77
|
+
<Source />
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import { useState } from 'react';
|
|
81
|
+
import { Dayjs } from 'dayjs';
|
|
82
|
+
|
|
83
|
+
import { DateRangePicker } from './DateRangePicker';
|
|
84
|
+
|
|
85
|
+
const MyComponent = () => {
|
|
86
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(null);
|
|
87
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(null);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<DateRangePicker
|
|
91
|
+
// Required props
|
|
92
|
+
startDate={startDate}
|
|
93
|
+
endDate={endDate}
|
|
94
|
+
onStartDateChange={setStartDate}
|
|
95
|
+
onEndDateChange={setEndDate}
|
|
96
|
+
// Optional props with default values shown
|
|
97
|
+
startFieldProps={{
|
|
98
|
+
label: 'Start Date',
|
|
99
|
+
helperText: 'Select start date',
|
|
100
|
+
helpTopicId: '1234', // Optional help topic ID
|
|
101
|
+
fullWidth: false, // Optional width control
|
|
102
|
+
}}
|
|
103
|
+
endFieldProps={{
|
|
104
|
+
label: 'End Date',
|
|
105
|
+
helperText: 'Select end date',
|
|
106
|
+
helpTopicId: '1234', // Optional help topic ID
|
|
107
|
+
fullWidth: false, // Optional width control
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Validation
|
|
115
|
+
|
|
116
|
+
The recommended way to validate the `DateRangePicker` is to use `yup`. Below we have an example of validating that the `endDate` is after the `startDate`.
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import * as yup from 'yup';
|
|
120
|
+
import { Dayjs } from 'dayjs';
|
|
121
|
+
|
|
122
|
+
const dateRangeSchema = yup.object().shape({
|
|
123
|
+
startDate: yup.mixed<Dayjs | null>().nullable().required('Start date is required'),
|
|
124
|
+
|
|
125
|
+
endDate: yup
|
|
126
|
+
.mixed<Dayjs | null>()
|
|
127
|
+
.nullable()
|
|
128
|
+
.required('End date is required')
|
|
129
|
+
.test('is-after-start', 'End date must be after start date', function (endDate, context) {
|
|
130
|
+
const { startDate } = context.parent;
|
|
131
|
+
|
|
132
|
+
if (!startDate || !endDate) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return endDate.isAfter(startDate) || endDate.isSame(startDate);
|
|
137
|
+
}),
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
You can then use the created component and validation schema in a form with `react-hook-form`.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
import { useForm, Controller } from 'react-hook-form';
|
|
145
|
+
import { yupResolver } from '@hookform/resolvers/yup';
|
|
146
|
+
import * as yup from 'yup';
|
|
147
|
+
import { Dayjs } from 'dayjs';
|
|
148
|
+
|
|
149
|
+
import { DateRangePicker } from './DateRangePicker';
|
|
150
|
+
|
|
151
|
+
interface DateRangeForm {
|
|
152
|
+
startDate: Dayjs | null;
|
|
153
|
+
endDate: Dayjs | null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const dateRangeSchema = yup.object().shape({
|
|
157
|
+
startDate: yup.mixed<Dayjs | null>().nullable().required('Start date is required'),
|
|
158
|
+
|
|
159
|
+
endDate: yup
|
|
160
|
+
.mixed<Dayjs | null>()
|
|
161
|
+
.nullable()
|
|
162
|
+
.required('End date is required')
|
|
163
|
+
.test('is-after-start', 'End date must be after start date', function (endDate, context) {
|
|
164
|
+
const { startDate } = context.parent;
|
|
165
|
+
|
|
166
|
+
if (!startDate || !endDate) {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return endDate.isAfter(startDate) || endDate.isSame(startDate);
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const DateRangeForm = () => {
|
|
175
|
+
const {
|
|
176
|
+
control,
|
|
177
|
+
handleSubmit,
|
|
178
|
+
formState: { errors },
|
|
179
|
+
} = useForm<DateRangeForm>({
|
|
180
|
+
resolver: yupResolver(dateRangeSchema),
|
|
181
|
+
defaultValues: {
|
|
182
|
+
startDate: null,
|
|
183
|
+
endDate: null,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
const DateRangeForm = () => {
|
|
187
|
+
const {
|
|
188
|
+
control,
|
|
189
|
+
handleSubmit,
|
|
190
|
+
formState: { errors },
|
|
191
|
+
watch,
|
|
192
|
+
} = useForm<DateRangeForm>({
|
|
193
|
+
resolver: yupResolver(dateRangeSchema),
|
|
194
|
+
defaultValues: {
|
|
195
|
+
startDate: null,
|
|
196
|
+
endDate: null,
|
|
197
|
+
},
|
|
198
|
+
mode: 'onChange', // Enable real-time validation
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Watch for changes in dates
|
|
202
|
+
const startDate = watch('startDate');
|
|
203
|
+
const endDate = watch('endDate');
|
|
204
|
+
|
|
205
|
+
// Optional: Add side effects when dates change
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if (startDate && endDate) {
|
|
208
|
+
// Perform any additional validation or business logic
|
|
209
|
+
console.log('Date range changed:', { startDate, endDate });
|
|
210
|
+
}
|
|
211
|
+
}, [startDate, endDate]);
|
|
212
|
+
|
|
213
|
+
const onSubmit = (data: DateRangeForm) => {
|
|
214
|
+
console.log('Form submitted:', data);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
219
|
+
<Controller
|
|
220
|
+
name="startDate"
|
|
221
|
+
control={control}
|
|
222
|
+
render={({ field: { onChange, value } }) => (
|
|
223
|
+
<Controller
|
|
224
|
+
name="endDate"
|
|
225
|
+
control={control}
|
|
226
|
+
render={({ field: { onChange: onEndChange, value: endValue } }) => (
|
|
227
|
+
<DateRangePicker
|
|
228
|
+
startDate={value}
|
|
229
|
+
endDate={endValue}
|
|
230
|
+
onStartDateChange={onChange}
|
|
231
|
+
onEndDateChange={onEndChange}
|
|
232
|
+
startFieldProps={{
|
|
233
|
+
helperText: errors.startDate?.message,
|
|
234
|
+
error: Boolean(errors.startDate),
|
|
235
|
+
label: 'Start Date',
|
|
236
|
+
fullWidth: true,
|
|
237
|
+
}}
|
|
238
|
+
endFieldProps={{
|
|
239
|
+
helperText: errors.endDate?.message,
|
|
240
|
+
error: Boolean(errors.endDate),
|
|
241
|
+
label: 'End Date',
|
|
242
|
+
fullWidth: true,
|
|
243
|
+
}}
|
|
244
|
+
/>
|
|
245
|
+
)}
|
|
246
|
+
/>
|
|
247
|
+
)}
|
|
248
|
+
/>
|
|
249
|
+
<button type="submit" style={{ marginTop: '16px' }}>
|
|
250
|
+
Submit
|
|
251
|
+
</button>
|
|
252
|
+
</form>
|
|
253
|
+
);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const onSubmit = (data: DateRangeForm) => {
|
|
257
|
+
console.log(data);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
262
|
+
<Controller
|
|
263
|
+
name="startDate"
|
|
264
|
+
control={control}
|
|
265
|
+
render={({ field: { onChange, value } }) => (
|
|
266
|
+
<Controller
|
|
267
|
+
name="endDate"
|
|
268
|
+
control={control}
|
|
269
|
+
render={({ field: { onChange: onEndChange, value: endValue } }) => (
|
|
270
|
+
<DateRangePicker
|
|
271
|
+
startDate={value}
|
|
272
|
+
endDate={endValue}
|
|
273
|
+
onStartDateChange={onChange}
|
|
274
|
+
onEndDateChange={onEndChange}
|
|
275
|
+
startFieldProps={{
|
|
276
|
+
helperText: errors.startDate?.message,
|
|
277
|
+
error: Boolean(errors.startDate),
|
|
278
|
+
label: 'Start Date',
|
|
279
|
+
}}
|
|
280
|
+
endFieldProps={{
|
|
281
|
+
helperText: errors.endDate?.message,
|
|
282
|
+
error: Boolean(errors.endDate),
|
|
283
|
+
label: 'End Date',
|
|
284
|
+
}}
|
|
285
|
+
/>
|
|
286
|
+
)}
|
|
287
|
+
/>
|
|
288
|
+
)}
|
|
289
|
+
/>
|
|
290
|
+
<button type="submit">Submit</button>
|
|
291
|
+
</form>
|
|
292
|
+
);
|
|
293
|
+
};
|
|
294
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -47,11 +47,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
47
47
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
48
48
|
|
|
49
49
|
// src/index.ts
|
|
50
|
-
var
|
|
51
|
-
__export(
|
|
50
|
+
var index_exports = {};
|
|
51
|
+
__export(index_exports, {
|
|
52
52
|
Datepicker: () => Datepicker
|
|
53
53
|
});
|
|
54
|
-
module.exports = __toCommonJS(
|
|
54
|
+
module.exports = __toCommonJS(index_exports);
|
|
55
55
|
|
|
56
56
|
// src/lib/Datepicker.tsx
|
|
57
57
|
var import_mui_textfield = require("@availity/mui-textfield");
|
|
@@ -59,6 +59,7 @@ var import_mui_icon = require("@availity/mui-icon");
|
|
|
59
59
|
var import_DatePicker = require("@mui/x-date-pickers/DatePicker");
|
|
60
60
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
61
61
|
var paperProps = { elevation: 8, variant: "elevation", sx: { marginTop: "4px" } };
|
|
62
|
+
var PickerTextField = (params) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_mui_textfield.TextField, __spreadProps(__spreadValues({}, params), { placeholder: "MM/DD/YYYY" }));
|
|
62
63
|
var Datepicker = (_a) => {
|
|
63
64
|
var _b = _a, { FieldProps, placement = "bottom-start" } = _b, props = __objRest(_b, ["FieldProps", "placement"]);
|
|
64
65
|
var _a2, _b2, _c, _d, _e, _f;
|
|
@@ -72,6 +73,7 @@ var Datepicker = (_a) => {
|
|
|
72
73
|
"aria-label": ((_a2 = FieldProps == null ? void 0 : FieldProps.label) == null ? void 0 : _a2.toString()) || ((_b2 = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _b2["aria-label"]) || "Date picker",
|
|
73
74
|
"aria-labelledby": ((_c = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _c["aria-labelledby"]) || void 0
|
|
74
75
|
}),
|
|
76
|
+
textField: FieldProps,
|
|
75
77
|
popper: {
|
|
76
78
|
placement,
|
|
77
79
|
"aria-label": ((_d = FieldProps == null ? void 0 : FieldProps.label) == null ? void 0 : _d.toString()) || ((_e = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _e["aria-label"]) || "Date picker",
|
|
@@ -79,12 +81,11 @@ var Datepicker = (_a) => {
|
|
|
79
81
|
},
|
|
80
82
|
openPickerIcon: {
|
|
81
83
|
fontSize: "xsmall"
|
|
82
|
-
}
|
|
83
|
-
textField: FieldProps
|
|
84
|
+
}
|
|
84
85
|
},
|
|
85
86
|
slots: {
|
|
86
87
|
openPickerIcon: import_mui_icon.CalendarDaysIcon,
|
|
87
|
-
textField:
|
|
88
|
+
textField: PickerTextField
|
|
88
89
|
}
|
|
89
90
|
})
|
|
90
91
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -36,6 +36,7 @@ import { CalendarDaysIcon } from "@availity/mui-icon";
|
|
|
36
36
|
import { DatePicker as MuiDatePicker } from "@mui/x-date-pickers/DatePicker";
|
|
37
37
|
import { jsx } from "react/jsx-runtime";
|
|
38
38
|
var paperProps = { elevation: 8, variant: "elevation", sx: { marginTop: "4px" } };
|
|
39
|
+
var PickerTextField = (params) => /* @__PURE__ */ jsx(TextField, __spreadProps(__spreadValues({}, params), { placeholder: "MM/DD/YYYY" }));
|
|
39
40
|
var Datepicker = (_a) => {
|
|
40
41
|
var _b = _a, { FieldProps, placement = "bottom-start" } = _b, props = __objRest(_b, ["FieldProps", "placement"]);
|
|
41
42
|
var _a2, _b2, _c, _d, _e, _f;
|
|
@@ -49,6 +50,7 @@ var Datepicker = (_a) => {
|
|
|
49
50
|
"aria-label": ((_a2 = FieldProps == null ? void 0 : FieldProps.label) == null ? void 0 : _a2.toString()) || ((_b2 = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _b2["aria-label"]) || "Date picker",
|
|
50
51
|
"aria-labelledby": ((_c = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _c["aria-labelledby"]) || void 0
|
|
51
52
|
}),
|
|
53
|
+
textField: FieldProps,
|
|
52
54
|
popper: {
|
|
53
55
|
placement,
|
|
54
56
|
"aria-label": ((_d = FieldProps == null ? void 0 : FieldProps.label) == null ? void 0 : _d.toString()) || ((_e = FieldProps == null ? void 0 : FieldProps.inputProps) == null ? void 0 : _e["aria-label"]) || "Date picker",
|
|
@@ -56,12 +58,11 @@ var Datepicker = (_a) => {
|
|
|
56
58
|
},
|
|
57
59
|
openPickerIcon: {
|
|
58
60
|
fontSize: "xsmall"
|
|
59
|
-
}
|
|
60
|
-
textField: FieldProps
|
|
61
|
+
}
|
|
61
62
|
},
|
|
62
63
|
slots: {
|
|
63
64
|
openPickerIcon: CalendarDaysIcon,
|
|
64
|
-
textField:
|
|
65
|
+
textField: PickerTextField
|
|
65
66
|
}
|
|
66
67
|
})
|
|
67
68
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@availity/mui-datepicker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
4
|
"description": "Availity MUI Datepicker Component - part of the @availity/element design system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -40,20 +40,20 @@
|
|
|
40
40
|
"publish:canary": "yarn npm publish --access public --tag canary"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@availity/mui-icon": "0.
|
|
44
|
-
"@availity/mui-textfield": "0.
|
|
45
|
-
"@mui/x-date-pickers": "^7.
|
|
43
|
+
"@availity/mui-icon": "1.0.0-alpha.0",
|
|
44
|
+
"@availity/mui-textfield": "1.0.0-alpha.0",
|
|
45
|
+
"@mui/x-date-pickers": "^7.26.0",
|
|
46
46
|
"dayjs": "^1.11.13"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@mui/material": "^
|
|
49
|
+
"@mui/material": "^6.4.5",
|
|
50
50
|
"react": "18.2.0",
|
|
51
51
|
"react-dom": "18.2.0",
|
|
52
|
-
"tsup": "^8.
|
|
52
|
+
"tsup": "^8.3.6",
|
|
53
53
|
"typescript": "^5.4.5"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@mui/material": "^
|
|
56
|
+
"@mui/material": "^6.4.5",
|
|
57
57
|
"react": ">=16.3.0"
|
|
58
58
|
},
|
|
59
59
|
"publishConfig": {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Each exported component in the package should have its own stories file
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
4
|
-
import Grid from '@mui/material/Unstable_Grid2';
|
|
5
|
-
import Paper from '@mui/material/Paper';
|
|
6
4
|
import Typography from '@mui/material/Typography';
|
|
7
5
|
import { MonthCalendar } from '@mui/x-date-pickers/MonthCalendar';
|
|
8
6
|
import { YearCalendar } from '@mui/x-date-pickers/YearCalendar';
|
|
9
7
|
import dayjs, { Dayjs } from 'dayjs';
|
|
8
|
+
import { Box, Grid } from '@availity/mui-layout';
|
|
9
|
+
import { Paper } from '@availity/mui-paper';
|
|
10
10
|
import { Datepicker, DatepickerProps } from './Datepicker';
|
|
11
11
|
import { DateCalendar } from './DateCalendar';
|
|
12
12
|
|
|
@@ -42,6 +42,65 @@ export const _Datepicker: StoryObj<typeof Datepicker> = {
|
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
+
type DateRangePickerProps = {
|
|
46
|
+
startDate: Dayjs | null;
|
|
47
|
+
endDate: Dayjs | null;
|
|
48
|
+
onStartDateChange: (date: Dayjs | null) => void;
|
|
49
|
+
onEndDateChange: (date: Dayjs | null) => void;
|
|
50
|
+
startFieldProps?: {
|
|
51
|
+
label?: string;
|
|
52
|
+
helperText?: string;
|
|
53
|
+
helpTopicId?: string;
|
|
54
|
+
fullWidth?: boolean;
|
|
55
|
+
};
|
|
56
|
+
endFieldProps?: {
|
|
57
|
+
label?: string;
|
|
58
|
+
helperText?: string;
|
|
59
|
+
helpTopicId?: string;
|
|
60
|
+
fullWidth?: boolean;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type DateRangePicker = (props: DateRangePickerProps) => JSX.Element;
|
|
65
|
+
|
|
66
|
+
export const _DateRangePicker: StoryObj<DateRangePicker> = {
|
|
67
|
+
render: () => {
|
|
68
|
+
const [startDate, setStartDate] = useState<Dayjs | null>(null);
|
|
69
|
+
const [endDate, setEndDate] = useState<Dayjs | null>(null);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Box sx={{ backgroundColor: 'background.paper', padding: '1.25rem' }}>
|
|
73
|
+
<Grid container spacing={2}>
|
|
74
|
+
<Grid xs={12} sm={6}>
|
|
75
|
+
<Datepicker
|
|
76
|
+
value={startDate}
|
|
77
|
+
onChange={setStartDate}
|
|
78
|
+
FieldProps={{
|
|
79
|
+
label: 'Start Date',
|
|
80
|
+
helperText: 'Select start date',
|
|
81
|
+
}}
|
|
82
|
+
maxDate={endDate ?? undefined} // Prevent selecting start date after end date
|
|
83
|
+
views={['day', 'month', 'year']}
|
|
84
|
+
/>
|
|
85
|
+
</Grid>
|
|
86
|
+
<Grid xs={12} sm={6}>
|
|
87
|
+
<Datepicker
|
|
88
|
+
value={endDate}
|
|
89
|
+
onChange={setEndDate}
|
|
90
|
+
FieldProps={{
|
|
91
|
+
label: 'End Date',
|
|
92
|
+
helperText: 'Select end date',
|
|
93
|
+
}}
|
|
94
|
+
minDate={startDate ?? undefined} // Prevent selecting end date before start date
|
|
95
|
+
views={['day', 'month', 'year']}
|
|
96
|
+
/>
|
|
97
|
+
</Grid>
|
|
98
|
+
</Grid>
|
|
99
|
+
</Box>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
45
104
|
export const _PickerViews: StoryObj<typeof DateCalendar> = {
|
|
46
105
|
render: () => {
|
|
47
106
|
const minDate = dayjs('2020-01-01T00:00:00.000');
|
|
@@ -50,7 +109,7 @@ export const _PickerViews: StoryObj<typeof DateCalendar> = {
|
|
|
50
109
|
|
|
51
110
|
return (
|
|
52
111
|
<Grid container spacing={3}>
|
|
53
|
-
<Grid xs
|
|
112
|
+
<Grid size={{ xs: 'auto' }}>
|
|
54
113
|
<Typography variant="h3" component="span">
|
|
55
114
|
Default View
|
|
56
115
|
</Typography>
|
|
@@ -58,7 +117,7 @@ export const _PickerViews: StoryObj<typeof DateCalendar> = {
|
|
|
58
117
|
<DateCalendar value={date} onChange={(newDate) => setDate(newDate)} />
|
|
59
118
|
</Paper>
|
|
60
119
|
</Grid>
|
|
61
|
-
<Grid xs
|
|
120
|
+
<Grid size={{ xs: 'auto' }}>
|
|
62
121
|
<Typography variant="h3" component="span">
|
|
63
122
|
Month View
|
|
64
123
|
</Typography>
|
|
@@ -66,7 +125,7 @@ export const _PickerViews: StoryObj<typeof DateCalendar> = {
|
|
|
66
125
|
<MonthCalendar value={date} minDate={minDate} maxDate={maxDate} onChange={(newDate) => setDate(newDate)} />
|
|
67
126
|
</Paper>
|
|
68
127
|
</Grid>
|
|
69
|
-
<Grid xs
|
|
128
|
+
<Grid size={{ xs: 'auto' }}>
|
|
70
129
|
<Typography variant="h3" component="span">
|
|
71
130
|
Year View
|
|
72
131
|
</Typography>
|
|
@@ -11,4 +11,13 @@ describe('Datepicker', () => {
|
|
|
11
11
|
);
|
|
12
12
|
expect(getAllByText('Test')).toBeTruthy();
|
|
13
13
|
});
|
|
14
|
+
|
|
15
|
+
test('should render placeholder successfully', () => {
|
|
16
|
+
const { container } = render(
|
|
17
|
+
<ThemeProvider>
|
|
18
|
+
<Datepicker FieldProps={{ InputProps: { placeholder: 'InputProps' } }} onChange={jest.fn()} value={null} />
|
|
19
|
+
</ThemeProvider>
|
|
20
|
+
);
|
|
21
|
+
expect(container.getElementsByClassName('MuiInputBase-input')[0].getAttribute('placeholder')).toBe('InputProps');
|
|
22
|
+
});
|
|
14
23
|
});
|
package/src/lib/Datepicker.tsx
CHANGED
|
@@ -39,6 +39,8 @@ export type DatepickerProps = {
|
|
|
39
39
|
|
|
40
40
|
const paperProps = { elevation: 8, variant: 'elevation', sx: { marginTop: '4px' } } as const;
|
|
41
41
|
|
|
42
|
+
const PickerTextField = (params: TextFieldProps) => <TextField {...params} placeholder="MM/DD/YYYY" />;
|
|
43
|
+
|
|
42
44
|
export const Datepicker = ({ FieldProps, placement = 'bottom-start', ...props }: DatepickerProps): JSX.Element => {
|
|
43
45
|
return (
|
|
44
46
|
<MuiDatePicker
|
|
@@ -51,6 +53,7 @@ export const Datepicker = ({ FieldProps, placement = 'bottom-start', ...props }:
|
|
|
51
53
|
'aria-label': FieldProps?.label?.toString() || FieldProps?.inputProps?.['aria-label'] || 'Date picker',
|
|
52
54
|
'aria-labelledby': FieldProps?.inputProps?.['aria-labelledby'] || undefined,
|
|
53
55
|
},
|
|
56
|
+
textField: FieldProps,
|
|
54
57
|
popper: {
|
|
55
58
|
placement,
|
|
56
59
|
'aria-label': FieldProps?.label?.toString() || FieldProps?.inputProps?.['aria-label'] || 'Date picker',
|
|
@@ -59,11 +62,10 @@ export const Datepicker = ({ FieldProps, placement = 'bottom-start', ...props }:
|
|
|
59
62
|
openPickerIcon: {
|
|
60
63
|
fontSize: 'xsmall',
|
|
61
64
|
},
|
|
62
|
-
textField: FieldProps,
|
|
63
65
|
}}
|
|
64
66
|
slots={{
|
|
65
67
|
openPickerIcon: CalendarDaysIcon,
|
|
66
|
-
textField:
|
|
68
|
+
textField: PickerTextField,
|
|
67
69
|
}}
|
|
68
70
|
/>
|
|
69
71
|
);
|
|
File without changes
|