@availity/mui-controlled-form 2.2.8 → 2.3.1
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/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +74 -4
- package/dist/index.mjs +69 -0
- package/package.json +6 -6
- package/src/index.ts +1 -0
- package/src/lib/Timepicker.stories.tsx +104 -0
- package/src/lib/Timepicker.test.tsx +110 -0
- package/src/lib/Timepicker.tsx +65 -0
- package/src/lib/Types.tsx +51 -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
|
+
## [2.3.1](https://github.com/Availity/element/compare/@availity/mui-controlled-form@2.3.0...@availity/mui-controlled-form@2.3.1) (2026-05-27)
|
|
6
|
+
|
|
7
|
+
### Dependency Updates
|
|
8
|
+
|
|
9
|
+
* `mui-autocomplete` updated to version `2.3.0`
|
|
10
|
+
* `mui-datepicker` updated to version `2.3.0`
|
|
11
|
+
* `mui-form-utils` updated to version `2.3.0`
|
|
12
|
+
* `mui-textfield` updated to version `2.3.0`
|
|
13
|
+
## [2.3.0](https://github.com/Availity/element/compare/@availity/mui-controlled-form@2.2.8...@availity/mui-controlled-form@2.3.0) (2026-05-22)
|
|
14
|
+
|
|
15
|
+
### Dependency Updates
|
|
16
|
+
|
|
17
|
+
* `mui-datepicker` updated to version `2.2.8`
|
|
18
|
+
* `theme-provider` updated to version `2.2.8`
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* **mui-datepicker:** add timepicker and update unfilled pickertextfield placeholder style ([cf95f5f](https://github.com/Availity/element/commit/cf95f5f1fdb1d29f1f66bd0a14f3dede759d834e))
|
|
23
|
+
|
|
5
24
|
## [2.2.8](https://github.com/Availity/element/compare/@availity/mui-controlled-form@2.2.7...@availity/mui-controlled-form@2.2.8) (2026-04-17)
|
|
6
25
|
|
|
7
26
|
### Dependency Updates
|
package/dist/index.d.mts
CHANGED
|
@@ -5,7 +5,7 @@ export { FormProvider, SubmitHandler, UseFormProps, UseFormReturn, useForm, useF
|
|
|
5
5
|
import { ChipTypeMap } from '@mui/material/Chip';
|
|
6
6
|
import { CheckboxProps } from '@availity/mui-checkbox';
|
|
7
7
|
import { ApiConfig } from '@availity/api-axios';
|
|
8
|
-
import { DatepickerProps } from '@availity/mui-datepicker';
|
|
8
|
+
import { DatepickerProps, TimepickerProps } from '@availity/mui-datepicker';
|
|
9
9
|
import { Dayjs } from 'dayjs';
|
|
10
10
|
import { InputProps, RadioGroupProps, FormControlProps, SelectProps } from '@availity/mui-form-utils';
|
|
11
11
|
import { TextFieldProps } from '@availity/mui-textfield';
|
|
@@ -97,4 +97,7 @@ declare const ControlledSelect: <Output = string, Input = unknown>({ name, defau
|
|
|
97
97
|
type ControlledTextFieldProps<Output = string> = Omit<TextFieldProps, 'onBlur' | 'onChange' | 'value' | 'name'> & Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> & ControllerProps & TransformProp<string, Output>;
|
|
98
98
|
declare const ControlledTextField: <Output = string>({ name, defaultValue, disabled, helperText, onBlur, onChange, rules, shouldUnregister, value, transform, ...rest }: ControlledTextFieldProps<Output>) => react_jsx_runtime.JSX.Element;
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
type ControlledTimepickerProps<Output = Dayjs | null> = Omit<TimepickerProps, 'onBlur' | 'onChange' | 'value' | 'name'> & Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> & ControllerProps & TransformProp<Dayjs | null, Output>;
|
|
101
|
+
declare const ControlledTimepicker: <Output = Dayjs | null>({ name, defaultValue, onBlur, onChange, rules, shouldUnregister, value, FieldProps, transform, ...rest }: ControlledTimepickerProps<Output>) => react_jsx_runtime.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { ControlledAsyncAutocomplete, type ControlledAsyncAutocompleteProps, ControlledAutocomplete, type ControlledAutocompleteProps, ControlledCheckbox, type ControlledCheckboxProps, ControlledCodesAutocomplete, type ControlledCodesAutocompleteProps, ControlledDatepicker, type ControlledDatepickerProps, ControlledInput, type ControlledInputProps, type ControlledOrgAutocompleteProps, ControlledOrganizationAutocomplete, ControlledProviderAutocomplete, type ControlledProviderAutocompleteProps, ControlledRadioGroup, type ControlledRadioGroupProps, ControlledSelect, type ControlledSelectProps, ControlledTextField, type ControlledTextFieldProps, ControlledTimepicker, type ControlledTimepickerProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { FormProvider, SubmitHandler, UseFormProps, UseFormReturn, useForm, useF
|
|
|
5
5
|
import { ChipTypeMap } from '@mui/material/Chip';
|
|
6
6
|
import { CheckboxProps } from '@availity/mui-checkbox';
|
|
7
7
|
import { ApiConfig } from '@availity/api-axios';
|
|
8
|
-
import { DatepickerProps } from '@availity/mui-datepicker';
|
|
8
|
+
import { DatepickerProps, TimepickerProps } from '@availity/mui-datepicker';
|
|
9
9
|
import { Dayjs } from 'dayjs';
|
|
10
10
|
import { InputProps, RadioGroupProps, FormControlProps, SelectProps } from '@availity/mui-form-utils';
|
|
11
11
|
import { TextFieldProps } from '@availity/mui-textfield';
|
|
@@ -97,4 +97,7 @@ declare const ControlledSelect: <Output = string, Input = unknown>({ name, defau
|
|
|
97
97
|
type ControlledTextFieldProps<Output = string> = Omit<TextFieldProps, 'onBlur' | 'onChange' | 'value' | 'name'> & Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> & ControllerProps & TransformProp<string, Output>;
|
|
98
98
|
declare const ControlledTextField: <Output = string>({ name, defaultValue, disabled, helperText, onBlur, onChange, rules, shouldUnregister, value, transform, ...rest }: ControlledTextFieldProps<Output>) => react_jsx_runtime.JSX.Element;
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
type ControlledTimepickerProps<Output = Dayjs | null> = Omit<TimepickerProps, 'onBlur' | 'onChange' | 'value' | 'name'> & Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> & ControllerProps & TransformProp<Dayjs | null, Output>;
|
|
101
|
+
declare const ControlledTimepicker: <Output = Dayjs | null>({ name, defaultValue, onBlur, onChange, rules, shouldUnregister, value, FieldProps, transform, ...rest }: ControlledTimepickerProps<Output>) => react_jsx_runtime.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { ControlledAsyncAutocomplete, type ControlledAsyncAutocompleteProps, ControlledAutocomplete, type ControlledAutocompleteProps, ControlledCheckbox, type ControlledCheckboxProps, ControlledCodesAutocomplete, type ControlledCodesAutocompleteProps, ControlledDatepicker, type ControlledDatepickerProps, ControlledInput, type ControlledInputProps, type ControlledOrgAutocompleteProps, ControlledOrganizationAutocomplete, ControlledProviderAutocomplete, type ControlledProviderAutocompleteProps, ControlledRadioGroup, type ControlledRadioGroupProps, ControlledSelect, type ControlledSelectProps, ControlledTextField, type ControlledTextFieldProps, ControlledTimepicker, type ControlledTimepickerProps };
|
package/dist/index.js
CHANGED
|
@@ -80,9 +80,10 @@ __export(index_exports, {
|
|
|
80
80
|
ControlledRadioGroup: () => ControlledRadioGroup,
|
|
81
81
|
ControlledSelect: () => ControlledSelect,
|
|
82
82
|
ControlledTextField: () => ControlledTextField,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
ControlledTimepicker: () => ControlledTimepicker,
|
|
84
|
+
FormProvider: () => import_react_hook_form10.FormProvider,
|
|
85
|
+
useForm: () => import_react_hook_form10.useForm,
|
|
86
|
+
useFormContext: () => import_react_hook_form10.useFormContext
|
|
86
87
|
});
|
|
87
88
|
module.exports = __toCommonJS(index_exports);
|
|
88
89
|
|
|
@@ -720,8 +721,76 @@ var ControlledTextField = (_a) => {
|
|
|
720
721
|
);
|
|
721
722
|
};
|
|
722
723
|
|
|
723
|
-
// src/
|
|
724
|
+
// src/lib/Timepicker.tsx
|
|
725
|
+
var import_mui_datepicker2 = require("@availity/mui-datepicker");
|
|
724
726
|
var import_react_hook_form9 = require("react-hook-form");
|
|
727
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
728
|
+
var ControlledTimepicker = (_a) => {
|
|
729
|
+
var _b = _a, {
|
|
730
|
+
name,
|
|
731
|
+
defaultValue,
|
|
732
|
+
onBlur,
|
|
733
|
+
onChange,
|
|
734
|
+
rules = {},
|
|
735
|
+
shouldUnregister,
|
|
736
|
+
value,
|
|
737
|
+
FieldProps,
|
|
738
|
+
transform
|
|
739
|
+
} = _b, rest = __objRest(_b, [
|
|
740
|
+
"name",
|
|
741
|
+
"defaultValue",
|
|
742
|
+
"onBlur",
|
|
743
|
+
"onChange",
|
|
744
|
+
"rules",
|
|
745
|
+
"shouldUnregister",
|
|
746
|
+
"value",
|
|
747
|
+
"FieldProps",
|
|
748
|
+
"transform"
|
|
749
|
+
]);
|
|
750
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
751
|
+
import_react_hook_form9.Controller,
|
|
752
|
+
{
|
|
753
|
+
name,
|
|
754
|
+
defaultValue,
|
|
755
|
+
rules: __spreadValues({
|
|
756
|
+
onBlur,
|
|
757
|
+
onChange,
|
|
758
|
+
shouldUnregister,
|
|
759
|
+
value
|
|
760
|
+
}, rules),
|
|
761
|
+
shouldUnregister,
|
|
762
|
+
render: ({ field: { onChange: onChange2, value: value2, onBlur: onBlur2, ref }, fieldState: { error } }) => {
|
|
763
|
+
var _a2;
|
|
764
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
765
|
+
import_mui_datepicker2.Timepicker,
|
|
766
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
767
|
+
FieldProps: __spreadProps(__spreadValues({}, FieldProps), {
|
|
768
|
+
required: (typeof rules.required === "object" ? rules.required.value : !!rules.required) || (FieldProps == null ? void 0 : FieldProps.required),
|
|
769
|
+
error: !!error,
|
|
770
|
+
helperText: error ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
771
|
+
error.message,
|
|
772
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("br", {}),
|
|
773
|
+
FieldProps == null ? void 0 : FieldProps.helperText
|
|
774
|
+
] }) : FieldProps == null ? void 0 : FieldProps.helperText,
|
|
775
|
+
inputRef: ref,
|
|
776
|
+
inputProps: {
|
|
777
|
+
onBlur: onBlur2
|
|
778
|
+
}
|
|
779
|
+
}),
|
|
780
|
+
onChange: (e) => {
|
|
781
|
+
var _a3, _b2;
|
|
782
|
+
return onChange2((_b2 = (_a3 = transform == null ? void 0 : transform.output) == null ? void 0 : _a3.call(transform, e)) != null ? _b2 : e);
|
|
783
|
+
},
|
|
784
|
+
value: ((_a2 = transform == null ? void 0 : transform.input) == null ? void 0 : _a2.call(transform, value2)) || value2 || null
|
|
785
|
+
})
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
);
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
// src/index.ts
|
|
793
|
+
var import_react_hook_form10 = require("react-hook-form");
|
|
725
794
|
// Annotate the CommonJS export names for ESM import in node:
|
|
726
795
|
0 && (module.exports = {
|
|
727
796
|
ControlledAsyncAutocomplete,
|
|
@@ -735,6 +804,7 @@ var import_react_hook_form9 = require("react-hook-form");
|
|
|
735
804
|
ControlledRadioGroup,
|
|
736
805
|
ControlledSelect,
|
|
737
806
|
ControlledTextField,
|
|
807
|
+
ControlledTimepicker,
|
|
738
808
|
FormProvider,
|
|
739
809
|
useForm,
|
|
740
810
|
useFormContext
|
package/dist/index.mjs
CHANGED
|
@@ -684,6 +684,74 @@ var ControlledTextField = (_a) => {
|
|
|
684
684
|
);
|
|
685
685
|
};
|
|
686
686
|
|
|
687
|
+
// src/lib/Timepicker.tsx
|
|
688
|
+
import { Timepicker } from "@availity/mui-datepicker";
|
|
689
|
+
import { Controller as Controller9 } from "react-hook-form";
|
|
690
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
691
|
+
var ControlledTimepicker = (_a) => {
|
|
692
|
+
var _b = _a, {
|
|
693
|
+
name,
|
|
694
|
+
defaultValue,
|
|
695
|
+
onBlur,
|
|
696
|
+
onChange,
|
|
697
|
+
rules = {},
|
|
698
|
+
shouldUnregister,
|
|
699
|
+
value,
|
|
700
|
+
FieldProps,
|
|
701
|
+
transform
|
|
702
|
+
} = _b, rest = __objRest(_b, [
|
|
703
|
+
"name",
|
|
704
|
+
"defaultValue",
|
|
705
|
+
"onBlur",
|
|
706
|
+
"onChange",
|
|
707
|
+
"rules",
|
|
708
|
+
"shouldUnregister",
|
|
709
|
+
"value",
|
|
710
|
+
"FieldProps",
|
|
711
|
+
"transform"
|
|
712
|
+
]);
|
|
713
|
+
return /* @__PURE__ */ jsx12(
|
|
714
|
+
Controller9,
|
|
715
|
+
{
|
|
716
|
+
name,
|
|
717
|
+
defaultValue,
|
|
718
|
+
rules: __spreadValues({
|
|
719
|
+
onBlur,
|
|
720
|
+
onChange,
|
|
721
|
+
shouldUnregister,
|
|
722
|
+
value
|
|
723
|
+
}, rules),
|
|
724
|
+
shouldUnregister,
|
|
725
|
+
render: ({ field: { onChange: onChange2, value: value2, onBlur: onBlur2, ref }, fieldState: { error } }) => {
|
|
726
|
+
var _a2;
|
|
727
|
+
return /* @__PURE__ */ jsx12(
|
|
728
|
+
Timepicker,
|
|
729
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
730
|
+
FieldProps: __spreadProps(__spreadValues({}, FieldProps), {
|
|
731
|
+
required: (typeof rules.required === "object" ? rules.required.value : !!rules.required) || (FieldProps == null ? void 0 : FieldProps.required),
|
|
732
|
+
error: !!error,
|
|
733
|
+
helperText: error ? /* @__PURE__ */ jsxs6(Fragment6, { children: [
|
|
734
|
+
error.message,
|
|
735
|
+
/* @__PURE__ */ jsx12("br", {}),
|
|
736
|
+
FieldProps == null ? void 0 : FieldProps.helperText
|
|
737
|
+
] }) : FieldProps == null ? void 0 : FieldProps.helperText,
|
|
738
|
+
inputRef: ref,
|
|
739
|
+
inputProps: {
|
|
740
|
+
onBlur: onBlur2
|
|
741
|
+
}
|
|
742
|
+
}),
|
|
743
|
+
onChange: (e) => {
|
|
744
|
+
var _a3, _b2;
|
|
745
|
+
return onChange2((_b2 = (_a3 = transform == null ? void 0 : transform.output) == null ? void 0 : _a3.call(transform, e)) != null ? _b2 : e);
|
|
746
|
+
},
|
|
747
|
+
value: ((_a2 = transform == null ? void 0 : transform.input) == null ? void 0 : _a2.call(transform, value2)) || value2 || null
|
|
748
|
+
})
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
);
|
|
753
|
+
};
|
|
754
|
+
|
|
687
755
|
// src/index.ts
|
|
688
756
|
import {
|
|
689
757
|
FormProvider,
|
|
@@ -702,6 +770,7 @@ export {
|
|
|
702
770
|
ControlledRadioGroup,
|
|
703
771
|
ControlledSelect,
|
|
704
772
|
ControlledTextField,
|
|
773
|
+
ControlledTimepicker,
|
|
705
774
|
FormProvider,
|
|
706
775
|
useForm,
|
|
707
776
|
useFormContext2 as useFormContext
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@availity/mui-controlled-form",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Availity MUI/react-hook-form controlled form components - part of the @availity/element design system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -40,15 +40,15 @@
|
|
|
40
40
|
"publish:canary": "yarn npm publish --access public --tag canary"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@availity/mui-autocomplete": "^2.2.
|
|
43
|
+
"@availity/mui-autocomplete": "^2.2.7",
|
|
44
44
|
"@availity/mui-checkbox": "^2.0.2",
|
|
45
|
-
"@availity/mui-datepicker": "^2.1
|
|
46
|
-
"@availity/mui-form-utils": "^2.0.
|
|
47
|
-
"@availity/mui-textfield": "^2.0.
|
|
45
|
+
"@availity/mui-datepicker": "^2.2.1",
|
|
46
|
+
"@availity/mui-form-utils": "^2.0.6",
|
|
47
|
+
"@availity/mui-textfield": "^2.0.6",
|
|
48
48
|
"react-hook-form": "^7.55.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@availity/api-axios": "^12.
|
|
51
|
+
"@availity/api-axios": "^12.2.1",
|
|
52
52
|
"@availity/mui-button": "^2.0.2",
|
|
53
53
|
"@availity/mui-layout": "^2.0.1",
|
|
54
54
|
"@availity/mui-menu": "^2.0.2",
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { ControlledTimepicker, ControlledTimepickerProps } from './Timepicker';
|
|
3
|
+
import { Button } from '@availity/mui-button';
|
|
4
|
+
import { Paper } from '@availity/mui-paper';
|
|
5
|
+
import { Typography } from '@availity/mui-typography';
|
|
6
|
+
import { Grid } from '@availity/mui-layout';
|
|
7
|
+
import { AllControllerPropertiesCategorized, TimepickerPropsCategorized } from './Types';
|
|
8
|
+
import { FormProvider, useForm } from '..';
|
|
9
|
+
import dayjs, { Dayjs } from 'dayjs';
|
|
10
|
+
|
|
11
|
+
const meta: Meta<typeof ControlledTimepicker> = {
|
|
12
|
+
title: 'Form Components/Controlled Form/ControlledTimepicker',
|
|
13
|
+
component: ControlledTimepicker,
|
|
14
|
+
tags: ['autodocs'],
|
|
15
|
+
argTypes: { ...AllControllerPropertiesCategorized, ...TimepickerPropsCategorized },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
|
|
20
|
+
export const _ControlledTimePicker: StoryObj<typeof ControlledTimepicker> = {
|
|
21
|
+
render: (args: ControlledTimepickerProps) => {
|
|
22
|
+
const methods = useForm();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<FormProvider {...methods}>
|
|
26
|
+
<form onSubmit={methods.handleSubmit((data) => data)}>
|
|
27
|
+
<ControlledTimepicker {...args} />
|
|
28
|
+
<Grid container direction="row" justifyContent="space-between" marginTop={1}>
|
|
29
|
+
<Button
|
|
30
|
+
disabled={!methods?.formState?.isSubmitSuccessful}
|
|
31
|
+
children="Reset"
|
|
32
|
+
color="secondary"
|
|
33
|
+
onClick={() => methods.reset()}
|
|
34
|
+
/>
|
|
35
|
+
<Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
|
|
36
|
+
</Grid>
|
|
37
|
+
{methods?.formState?.isSubmitSuccessful ? (
|
|
38
|
+
<Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
|
|
39
|
+
<Typography variant="h2">Submitted Values</Typography>
|
|
40
|
+
<pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
|
|
41
|
+
</Paper>
|
|
42
|
+
) : null}
|
|
43
|
+
</form>
|
|
44
|
+
</FormProvider>
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
args: {
|
|
48
|
+
name: 'controlledTimepicker',
|
|
49
|
+
FieldProps: {
|
|
50
|
+
fullWidth: false,
|
|
51
|
+
helperText: 'Help text for the field',
|
|
52
|
+
helpTopicId: '1234',
|
|
53
|
+
label: 'Time',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* In this example, the underlying value is stored as a string in the form values,
|
|
60
|
+
* but the timepicker always receives a Dayjs object. The transform prop is used to
|
|
61
|
+
* convert the value to and from the format you want to store in the underlying
|
|
62
|
+
* form values. You can see the underlying value when submitting the form.
|
|
63
|
+
*/
|
|
64
|
+
export const _Transform: StoryObj<typeof ControlledTimepicker> = {
|
|
65
|
+
render: (args: ControlledTimepickerProps) => {
|
|
66
|
+
const methods = useForm();
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<FormProvider {...methods}>
|
|
70
|
+
<form onSubmit={methods.handleSubmit((data) => data)}>
|
|
71
|
+
<ControlledTimepicker {...args} />
|
|
72
|
+
<Grid container direction="row" justifyContent="space-between" marginTop={1}>
|
|
73
|
+
<Button
|
|
74
|
+
disabled={!methods?.formState?.isSubmitSuccessful}
|
|
75
|
+
children="Reset"
|
|
76
|
+
color="secondary"
|
|
77
|
+
onClick={() => methods.reset()}
|
|
78
|
+
/>
|
|
79
|
+
<Button type="submit" disabled={methods?.formState?.isSubmitSuccessful} children="Submit" />
|
|
80
|
+
</Grid>
|
|
81
|
+
{methods?.formState?.isSubmitSuccessful ? (
|
|
82
|
+
<Paper sx={{ padding: '1.5rem', marginTop: '1.5rem' }}>
|
|
83
|
+
<Typography variant="h2">Submitted Values</Typography>
|
|
84
|
+
<pre data-testid="result">{JSON.stringify(methods.getValues(), null, 2)}</pre>
|
|
85
|
+
</Paper>
|
|
86
|
+
) : null}
|
|
87
|
+
</form>
|
|
88
|
+
</FormProvider>
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
args: {
|
|
92
|
+
transform: {
|
|
93
|
+
output: (value: Dayjs) => value?.format('hh:mm A'),
|
|
94
|
+
input: (value: string) => (value ? dayjs(value, 'hh:mm A') : null),
|
|
95
|
+
},
|
|
96
|
+
name: 'controlledTimepickerTransform',
|
|
97
|
+
FieldProps: {
|
|
98
|
+
fullWidth: false,
|
|
99
|
+
helperText: 'Help text for the field',
|
|
100
|
+
helpTopicId: '1234',
|
|
101
|
+
label: 'Time',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { render, fireEvent, waitFor } from '@testing-library/react';
|
|
2
|
+
import { ThemeProvider } from '@availity/theme-provider';
|
|
3
|
+
import dayjs from 'dayjs';
|
|
4
|
+
import { ControlledTimepicker } from './Timepicker';
|
|
5
|
+
import { TestForm } from './UtilComponents';
|
|
6
|
+
|
|
7
|
+
const onSubmit = jest.fn();
|
|
8
|
+
|
|
9
|
+
describe('ControlledTimepicker', () => {
|
|
10
|
+
test('should render successfully and submit selection', async () => {
|
|
11
|
+
const screen = render(
|
|
12
|
+
<ThemeProvider>
|
|
13
|
+
<TestForm UseFormOptions={{ values: { controlledTimepicker: null } }} onSubmit={onSubmit}>
|
|
14
|
+
<ControlledTimepicker
|
|
15
|
+
name="controlledTimepicker"
|
|
16
|
+
FieldProps={{
|
|
17
|
+
fullWidth: false,
|
|
18
|
+
helperText: 'Help text for the field',
|
|
19
|
+
helpTopicId: '1234',
|
|
20
|
+
label: 'Time',
|
|
21
|
+
}}
|
|
22
|
+
/>
|
|
23
|
+
</TestForm>
|
|
24
|
+
</ThemeProvider>
|
|
25
|
+
);
|
|
26
|
+
expect(screen.getAllByText('Time')).toBeTruthy();
|
|
27
|
+
const input = screen.getByLabelText('Choose time');
|
|
28
|
+
fireEvent.click(input);
|
|
29
|
+
const listboxes = screen.getAllByRole('listbox');
|
|
30
|
+
const hourOption = listboxes[0].querySelectorAll('[role="option"]');
|
|
31
|
+
fireEvent.click(hourOption[2]);
|
|
32
|
+
|
|
33
|
+
fireEvent.click(screen.getByText('OK'));
|
|
34
|
+
fireEvent.click(screen.getByText('Submit'));
|
|
35
|
+
await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1));
|
|
36
|
+
const result = screen.getByTestId('result');
|
|
37
|
+
await waitFor(() => {
|
|
38
|
+
const controlledTimepickerValue = JSON.parse(result.innerHTML).controlledTimepicker;
|
|
39
|
+
expect(controlledTimepickerValue).toBeDefined();
|
|
40
|
+
expect(dayjs(controlledTimepickerValue).isValid()).toBeTruthy();
|
|
41
|
+
});
|
|
42
|
+
}, 10000);
|
|
43
|
+
|
|
44
|
+
describe('when using rules', () => {
|
|
45
|
+
describe('when required', () => {
|
|
46
|
+
test('should indicate it is required when passing a string', async () => {
|
|
47
|
+
const screen = render(
|
|
48
|
+
<ThemeProvider>
|
|
49
|
+
<TestForm UseFormOptions={{ values: { controlledTimepicker: null } }} onSubmit={onSubmit}>
|
|
50
|
+
<ControlledTimepicker
|
|
51
|
+
name="controlledTimepicker"
|
|
52
|
+
FieldProps={{
|
|
53
|
+
fullWidth: false,
|
|
54
|
+
helperText: 'Help text for the field',
|
|
55
|
+
helpTopicId: '1234',
|
|
56
|
+
label: 'Time',
|
|
57
|
+
}}
|
|
58
|
+
rules={{ required: 'This field is required' }}
|
|
59
|
+
/>
|
|
60
|
+
</TestForm>
|
|
61
|
+
</ThemeProvider>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
expect(screen.getAllByText('*')).toBeDefined();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should indicate it is required when passing an object with true', async () => {
|
|
68
|
+
const screen = render(
|
|
69
|
+
<ThemeProvider>
|
|
70
|
+
<TestForm UseFormOptions={{ values: { controlledTimepicker: null } }} onSubmit={onSubmit}>
|
|
71
|
+
<ControlledTimepicker
|
|
72
|
+
name="controlledTimepicker"
|
|
73
|
+
FieldProps={{
|
|
74
|
+
fullWidth: false,
|
|
75
|
+
helperText: 'Help text for the field',
|
|
76
|
+
helpTopicId: '1234',
|
|
77
|
+
label: 'Time',
|
|
78
|
+
}}
|
|
79
|
+
rules={{ required: { value: true, message: 'This field is required' } }}
|
|
80
|
+
/>
|
|
81
|
+
</TestForm>
|
|
82
|
+
</ThemeProvider>
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(screen.getAllByText('*')).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('should not indicate it is required when passing an object with false', async () => {
|
|
89
|
+
const screen = render(
|
|
90
|
+
<ThemeProvider>
|
|
91
|
+
<TestForm UseFormOptions={{ values: { controlledTimepicker: null } }} onSubmit={onSubmit}>
|
|
92
|
+
<ControlledTimepicker
|
|
93
|
+
name="controlledTimepicker"
|
|
94
|
+
FieldProps={{
|
|
95
|
+
fullWidth: false,
|
|
96
|
+
helperText: 'Help text for the field',
|
|
97
|
+
helpTopicId: '1234',
|
|
98
|
+
label: 'Time',
|
|
99
|
+
}}
|
|
100
|
+
rules={{ required: { value: false, message: 'This field is required' } }}
|
|
101
|
+
/>
|
|
102
|
+
</TestForm>
|
|
103
|
+
</ThemeProvider>
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
expect(screen.queryAllByText('*')).toHaveLength(0);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Timepicker, TimepickerProps } from '@availity/mui-datepicker';
|
|
2
|
+
import { RegisterOptions, FieldValues, Controller } from 'react-hook-form';
|
|
3
|
+
import { ControllerProps, TransformProp } from './Types';
|
|
4
|
+
import { Dayjs } from 'dayjs';
|
|
5
|
+
|
|
6
|
+
export type ControlledTimepickerProps<Output = Dayjs | null> = Omit<
|
|
7
|
+
TimepickerProps,
|
|
8
|
+
'onBlur' | 'onChange' | 'value' | 'name'
|
|
9
|
+
> &
|
|
10
|
+
Pick<RegisterOptions<FieldValues, string>, 'onBlur' | 'onChange' | 'value'> &
|
|
11
|
+
ControllerProps &
|
|
12
|
+
TransformProp<Dayjs | null, Output>;
|
|
13
|
+
|
|
14
|
+
export const ControlledTimepicker = <Output = Dayjs | null,>({
|
|
15
|
+
name,
|
|
16
|
+
defaultValue,
|
|
17
|
+
onBlur,
|
|
18
|
+
onChange,
|
|
19
|
+
rules = {},
|
|
20
|
+
shouldUnregister,
|
|
21
|
+
value,
|
|
22
|
+
FieldProps,
|
|
23
|
+
transform,
|
|
24
|
+
...rest
|
|
25
|
+
}: ControlledTimepickerProps<Output>) => {
|
|
26
|
+
return (
|
|
27
|
+
<Controller
|
|
28
|
+
name={name}
|
|
29
|
+
defaultValue={defaultValue}
|
|
30
|
+
rules={{
|
|
31
|
+
onBlur,
|
|
32
|
+
onChange,
|
|
33
|
+
shouldUnregister,
|
|
34
|
+
value,
|
|
35
|
+
...rules,
|
|
36
|
+
}}
|
|
37
|
+
shouldUnregister={shouldUnregister}
|
|
38
|
+
render={({ field: { onChange, value, onBlur, ref }, fieldState: { error } }) => (
|
|
39
|
+
<Timepicker
|
|
40
|
+
{...rest}
|
|
41
|
+
FieldProps={{
|
|
42
|
+
...FieldProps,
|
|
43
|
+
required: (typeof rules.required === 'object' ? rules.required.value : !!rules.required) || FieldProps?.required,
|
|
44
|
+
error: !!error,
|
|
45
|
+
helperText: error ? (
|
|
46
|
+
<>
|
|
47
|
+
{error.message}
|
|
48
|
+
<br />
|
|
49
|
+
{FieldProps?.helperText}
|
|
50
|
+
</>
|
|
51
|
+
) : (
|
|
52
|
+
FieldProps?.helperText
|
|
53
|
+
),
|
|
54
|
+
inputRef: ref,
|
|
55
|
+
inputProps: {
|
|
56
|
+
onBlur: onBlur,
|
|
57
|
+
},
|
|
58
|
+
}}
|
|
59
|
+
onChange={(e) => onChange(transform?.output?.(e) ?? e)}
|
|
60
|
+
value={transform?.input?.(value) || value || null}
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
};
|
package/src/lib/Types.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
ControlledRadioGroupProps,
|
|
12
12
|
ControlledSelectProps,
|
|
13
13
|
ControlledTextFieldProps,
|
|
14
|
+
ControlledTimepickerProps,
|
|
14
15
|
} from '..';
|
|
15
16
|
import { HTMLAttributes } from 'react';
|
|
16
17
|
|
|
@@ -74,6 +75,14 @@ type DatepickerPropsObject = Record<
|
|
|
74
75
|
{ table: { category: 'Input Props' } }
|
|
75
76
|
>;
|
|
76
77
|
|
|
78
|
+
type TimepickerPropsObject = Record<
|
|
79
|
+
keyof Omit<
|
|
80
|
+
ControlledTimepickerProps,
|
|
81
|
+
keyof AllControllerProps | keyof Omit<HTMLAttributes<undefined>, 'autoFocus' | 'className' | 'onError'>
|
|
82
|
+
>,
|
|
83
|
+
{ table: { category: 'Input Props' } }
|
|
84
|
+
>;
|
|
85
|
+
|
|
77
86
|
type ProviderAutocompletePropsObject = Record<
|
|
78
87
|
keyof Omit<
|
|
79
88
|
ControlledProviderAutocompleteProps,
|
|
@@ -429,6 +438,48 @@ export const DatepickerPropsCategorized: DatepickerPropsObject = {
|
|
|
429
438
|
clearable: { table: { category: 'Input Props' } },
|
|
430
439
|
};
|
|
431
440
|
|
|
441
|
+
export const TimepickerPropsCategorized: TimepickerPropsObject = {
|
|
442
|
+
autoFocus: { table: { category: 'Input Props' } },
|
|
443
|
+
className: { table: { category: 'Input Props' } },
|
|
444
|
+
onError: { table: { category: 'Input Props' } },
|
|
445
|
+
sx: { table: { category: 'Input Props' } },
|
|
446
|
+
label: { table: { category: 'Input Props' } },
|
|
447
|
+
view: { table: { category: 'Input Props' } },
|
|
448
|
+
readOnly: { table: { category: 'Input Props' } },
|
|
449
|
+
onClose: { table: { category: 'Input Props' } },
|
|
450
|
+
onOpen: { table: { category: 'Input Props' } },
|
|
451
|
+
open: { table: { category: 'Input Props' } },
|
|
452
|
+
FieldProps: { table: { category: 'Input Props' } },
|
|
453
|
+
disableFuture: { table: { category: 'Input Props' } },
|
|
454
|
+
disablePast: { table: { category: 'Input Props' } },
|
|
455
|
+
views: { table: { category: 'Input Props' } },
|
|
456
|
+
onViewChange: { table: { category: 'Input Props' } },
|
|
457
|
+
localeText: { table: { category: 'Input Props' } },
|
|
458
|
+
onAccept: { table: { category: 'Input Props' } },
|
|
459
|
+
viewRenderers: { table: { category: 'Input Props' } },
|
|
460
|
+
referenceDate: { table: { category: 'Input Props' } },
|
|
461
|
+
timezone: { table: { category: 'Input Props' } },
|
|
462
|
+
formatDensity: { table: { category: 'Input Props' } },
|
|
463
|
+
selectedSections: { table: { category: 'Input Props' } },
|
|
464
|
+
onSelectedSectionsChange: { table: { category: 'Input Props' } },
|
|
465
|
+
closeOnSelect: { table: { category: 'Input Props' } },
|
|
466
|
+
format: { table: { category: 'Input Props' } },
|
|
467
|
+
inputRef: { table: { category: 'Input Props' } },
|
|
468
|
+
placement: { table: { category: 'Input Props' } },
|
|
469
|
+
clearable: { table: { category: 'Input Props' } },
|
|
470
|
+
onClear: { table: { category: 'Input Props' } },
|
|
471
|
+
minutesStep: { table: { category: 'Input Props' } },
|
|
472
|
+
minTime: { table: { category: 'Input Props' } },
|
|
473
|
+
maxTime: { table: { category: 'Input Props' } },
|
|
474
|
+
shouldDisableTime: { table: { category: 'Input Props' } },
|
|
475
|
+
disableIgnoringDatePartForTimeValidation: { table: { category: 'Input Props' } },
|
|
476
|
+
ampm: { table: { category: 'Input Props' } },
|
|
477
|
+
skipDisabled: { table: { category: 'Input Props' } },
|
|
478
|
+
timeSteps: { table: { category: 'Input Props' } },
|
|
479
|
+
ampmInClock: { table: { category: 'Input Props' } },
|
|
480
|
+
thresholdToRenderTimeInASingleColumn: { table: { category: 'Input Props' } }
|
|
481
|
+
};
|
|
482
|
+
|
|
432
483
|
export const CodesAutocompletePropsCategorized: CodesAutocompletePropsObject = {
|
|
433
484
|
classes: { table: { category: 'Input Props' } },
|
|
434
485
|
id: { table: { category: 'Input Props' } },
|