@alepha/ui 0.10.6 → 0.11.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/dist/AlephaMantineProvider-DDbIijPF.js +96 -0
- package/dist/AlephaMantineProvider-DDbIijPF.js.map +1 -0
- package/dist/AlephaMantineProvider-pOu8hOzK.js +3 -0
- package/dist/index.d.ts +560 -41
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1341 -109
- package/dist/index.js.map +1 -1
- package/package.json +21 -12
- package/src/RootRouter.ts +8 -0
- package/src/components/Action.tsx +296 -135
- package/src/components/AlephaMantineProvider.tsx +34 -31
- package/src/components/Control.tsx +251 -236
- package/src/components/ControlDate.tsx +104 -0
- package/src/components/ControlSelect.tsx +196 -0
- package/src/components/DarkModeButton.tsx +82 -0
- package/src/components/DataTable.css +199 -0
- package/src/components/DataTable.tsx +724 -0
- package/src/components/Omnibar.tsx +77 -0
- package/src/components/Sidebar.css +217 -0
- package/src/components/Sidebar.tsx +255 -0
- package/src/components/TypeForm.tsx +158 -0
- package/src/components/dialogs/AlertDialog.tsx +13 -0
- package/src/components/dialogs/ConfirmDialog.tsx +21 -0
- package/src/components/dialogs/PromptDialog.tsx +52 -0
- package/src/hooks/useDialog.ts +15 -0
- package/src/hooks/useToast.ts +14 -0
- package/src/index.ts +54 -10
- package/src/services/DialogService.tsx +207 -0
- package/src/services/ToastService.tsx +71 -0
- package/src/utils/icons.tsx +121 -0
- package/src/utils/parseInput.ts +125 -0
- package/src/utils/string.ts +21 -0
|
@@ -1,275 +1,290 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type InputField, useFormState } from "@alepha/react-form";
|
|
1
|
+
import { useFormState } from "@alepha/react-form";
|
|
3
2
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
3
|
+
ColorInput,
|
|
4
|
+
type ColorInputProps,
|
|
5
|
+
FileInput,
|
|
6
|
+
type FileInputProps,
|
|
7
|
+
Flex,
|
|
8
|
+
Input,
|
|
9
|
+
NumberInput,
|
|
10
|
+
type NumberInputProps,
|
|
11
|
+
PasswordInput,
|
|
12
|
+
type PasswordInputProps,
|
|
13
|
+
Switch,
|
|
14
|
+
type SwitchProps,
|
|
15
|
+
Textarea,
|
|
16
|
+
type TextareaProps,
|
|
17
|
+
TextInput,
|
|
18
|
+
type TextInputProps,
|
|
20
19
|
} from "@mantine/core";
|
|
21
|
-
import type {
|
|
20
|
+
import type {
|
|
21
|
+
DateInputProps,
|
|
22
|
+
DateTimePickerProps,
|
|
23
|
+
TimeInputProps,
|
|
24
|
+
} from "@mantine/dates";
|
|
25
|
+
import type { ComponentType } from "react";
|
|
26
|
+
import { type GenericControlProps, parseInput } from "../utils/parseInput.ts";
|
|
27
|
+
import ControlDate from "./ControlDate";
|
|
28
|
+
import ControlSelect, { type ControlSelectProps } from "./ControlSelect";
|
|
22
29
|
|
|
23
|
-
export interface ControlProps {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
switch?: boolean | SwitchProps;
|
|
37
|
-
segmented?: boolean | Partial<SegmentedControlProps>;
|
|
38
|
-
|
|
39
|
-
custom?: ComponentType<CustomControlProps>;
|
|
30
|
+
export interface ControlProps extends GenericControlProps {
|
|
31
|
+
text?: TextInputProps;
|
|
32
|
+
area?: boolean | TextareaProps;
|
|
33
|
+
select?: boolean | Partial<ControlSelectProps>;
|
|
34
|
+
password?: boolean | PasswordInputProps;
|
|
35
|
+
switch?: boolean | SwitchProps;
|
|
36
|
+
number?: boolean | NumberInputProps;
|
|
37
|
+
file?: boolean | FileInputProps;
|
|
38
|
+
color?: boolean | ColorInputProps;
|
|
39
|
+
date?: boolean | DateInputProps;
|
|
40
|
+
datetime?: boolean | DateTimePickerProps;
|
|
41
|
+
time?: boolean | TimeInputProps;
|
|
42
|
+
custom?: ComponentType<CustomControlProps>;
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
/**
|
|
43
46
|
* Generic form control that renders the appropriate input based on the schema and props.
|
|
44
47
|
*
|
|
45
48
|
* Supports:
|
|
46
|
-
* - TextInput
|
|
49
|
+
* - TextInput (with format detection: email, url, tel)
|
|
47
50
|
* - Textarea
|
|
51
|
+
* - NumberInput (for number/integer types)
|
|
52
|
+
* - FileInput
|
|
53
|
+
* - ColorInput (for color format)
|
|
48
54
|
* - Select (for enum types)
|
|
49
55
|
* - Autocomplete
|
|
50
56
|
* - PasswordInput
|
|
51
57
|
* - Switch (for boolean types)
|
|
52
58
|
* - SegmentedControl (for enum types)
|
|
59
|
+
* - DateInput (for date format)
|
|
60
|
+
* - DateTimePicker (for date-time format)
|
|
61
|
+
* - TimeInput (for time format)
|
|
53
62
|
* - Custom component
|
|
54
63
|
*
|
|
55
|
-
* Automatically handles labels, descriptions, error messages, and
|
|
64
|
+
* Automatically handles labels, descriptions, error messages, required state, and default icons.
|
|
56
65
|
*/
|
|
57
|
-
const Control = (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// shared props
|
|
66
|
+
const Control = (_props: ControlProps) => {
|
|
67
|
+
const form = useFormState(_props.input, ["error"]);
|
|
68
|
+
const { inputProps, id, icon, format, schema } = parseInput(_props, form);
|
|
69
|
+
if (!_props.input?.props) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
64
72
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
("title" in props.input.schema &&
|
|
70
|
-
typeof props.input.schema.title === "string"
|
|
71
|
-
? props.input.schema.title
|
|
72
|
-
: undefined) ??
|
|
73
|
-
prettyName(props.input.path);
|
|
74
|
-
const description =
|
|
75
|
-
props.description ??
|
|
76
|
-
("description" in props.input.schema &&
|
|
77
|
-
typeof props.input.schema.description === "string"
|
|
78
|
-
? props.input.schema.description
|
|
79
|
-
: undefined);
|
|
80
|
-
const error =
|
|
81
|
-
form.error && form.error instanceof TypeBoxError
|
|
82
|
-
? form.error.value.message
|
|
83
|
-
: undefined;
|
|
84
|
-
const icon = props.icon;
|
|
85
|
-
const required = props.input.required;
|
|
73
|
+
const props = {
|
|
74
|
+
..._props,
|
|
75
|
+
...schema.$control,
|
|
76
|
+
};
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
78
|
+
//region <Custom/>
|
|
79
|
+
if (props.custom) {
|
|
80
|
+
const Custom = props.custom;
|
|
81
|
+
return (
|
|
82
|
+
<Input.Wrapper {...inputProps}>
|
|
83
|
+
<Flex flex={1} mt={"calc(var(--mantine-spacing-xs) / 2)"}>
|
|
84
|
+
<Custom
|
|
85
|
+
defaultValue={props.input.props.defaultValue}
|
|
86
|
+
onChange={(value) => {
|
|
87
|
+
props.input.set(value);
|
|
88
|
+
}}
|
|
89
|
+
/>
|
|
90
|
+
</Flex>
|
|
91
|
+
</Input.Wrapper>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
//endregion
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
//region <NumberInput/>
|
|
97
|
+
if (
|
|
98
|
+
props.number ||
|
|
99
|
+
(props.input.schema &&
|
|
100
|
+
"type" in props.input.schema &&
|
|
101
|
+
(props.input.schema.type === "number" ||
|
|
102
|
+
props.input.schema.type === "integer"))
|
|
103
|
+
) {
|
|
104
|
+
const numberInputProps =
|
|
105
|
+
typeof props.number === "object" ? props.number : {};
|
|
106
|
+
const { type, ...inputPropsWithoutType } = props.input.props;
|
|
107
|
+
return (
|
|
108
|
+
<NumberInput
|
|
109
|
+
{...inputProps}
|
|
110
|
+
id={id}
|
|
111
|
+
leftSection={icon}
|
|
112
|
+
{...inputPropsWithoutType}
|
|
113
|
+
{...numberInputProps}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
//endregion
|
|
96
118
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
//region <FileInput/>
|
|
120
|
+
if (props.file) {
|
|
121
|
+
const fileInputProps = typeof props.file === "object" ? props.file : {};
|
|
122
|
+
return (
|
|
123
|
+
<FileInput
|
|
124
|
+
{...inputProps}
|
|
125
|
+
id={id}
|
|
126
|
+
leftSection={icon}
|
|
127
|
+
onChange={(file) => {
|
|
128
|
+
props.input.set(file);
|
|
129
|
+
}}
|
|
130
|
+
{...fileInputProps}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
//endregion
|
|
112
135
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<Input.Wrapper {...inputProps}>
|
|
129
|
-
<Flex mt={"calc(var(--mantine-spacing-xs) / 2)"}>
|
|
130
|
-
<SegmentedControl
|
|
131
|
-
disabled={disabled}
|
|
132
|
-
defaultValue={String(props.input.props.defaultValue)}
|
|
133
|
-
{...segmentedControlProps}
|
|
134
|
-
onChange={(value) => {
|
|
135
|
-
props.input.set(value);
|
|
136
|
-
}}
|
|
137
|
-
data={data}
|
|
138
|
-
/>
|
|
139
|
-
</Flex>
|
|
140
|
-
</Input.Wrapper>
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
// endregion
|
|
136
|
+
//region <ColorInput/>
|
|
137
|
+
if (props.color || format === "color") {
|
|
138
|
+
const colorInputProps = typeof props.color === "object" ? props.color : {};
|
|
139
|
+
return (
|
|
140
|
+
<ColorInput
|
|
141
|
+
{...inputProps}
|
|
142
|
+
id={id}
|
|
143
|
+
leftSection={icon}
|
|
144
|
+
{...props.input.props}
|
|
145
|
+
{...colorInputProps}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
//endregion
|
|
144
150
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
151
|
+
//region <ControlSelect/>
|
|
152
|
+
// Handle: single enum, array of enum, array of strings, or explicit select/multi/tags props
|
|
153
|
+
const isEnum =
|
|
154
|
+
props.input.schema &&
|
|
155
|
+
"enum" in props.input.schema &&
|
|
156
|
+
props.input.schema.enum;
|
|
157
|
+
const isArray =
|
|
158
|
+
props.input.schema &&
|
|
159
|
+
"type" in props.input.schema &&
|
|
160
|
+
props.input.schema.type === "array";
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
162
|
+
if (isEnum || isArray || props.select) {
|
|
163
|
+
const opts = typeof props.select === "object" ? props.select : {};
|
|
164
|
+
return (
|
|
165
|
+
<ControlSelect
|
|
166
|
+
input={props.input}
|
|
167
|
+
title={props.title}
|
|
168
|
+
description={props.description}
|
|
169
|
+
icon={icon}
|
|
170
|
+
{...opts}
|
|
171
|
+
/>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
//endregion
|
|
161
175
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
props.input.schema &&
|
|
171
|
-
"enum" in props.input.schema &&
|
|
172
|
-
Array.isArray(props.input.schema.enum)
|
|
173
|
-
? props.input.schema.enum?.map((value: string) => ({
|
|
174
|
-
value,
|
|
175
|
-
label: value,
|
|
176
|
-
}))
|
|
177
|
-
: [];
|
|
176
|
+
//region <Switch/>
|
|
177
|
+
if (
|
|
178
|
+
(props.input.schema &&
|
|
179
|
+
"type" in props.input.schema &&
|
|
180
|
+
props.input.schema.type === "boolean") ||
|
|
181
|
+
props.switch
|
|
182
|
+
) {
|
|
183
|
+
const switchProps = typeof props.switch === "object" ? props.switch : {};
|
|
178
184
|
|
|
179
|
-
|
|
185
|
+
return (
|
|
186
|
+
<Switch
|
|
187
|
+
{...inputProps}
|
|
188
|
+
id={id}
|
|
189
|
+
color={"blue"}
|
|
190
|
+
defaultChecked={props.input.props.defaultValue}
|
|
191
|
+
{...props.input.props}
|
|
192
|
+
{...switchProps}
|
|
193
|
+
/>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
//endregion
|
|
180
197
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
//region <PasswordInput/>
|
|
199
|
+
if (props.password || props.input.props.name?.includes("password")) {
|
|
200
|
+
const passwordInputProps =
|
|
201
|
+
typeof props.password === "object" ? props.password : {};
|
|
202
|
+
return (
|
|
203
|
+
<PasswordInput
|
|
204
|
+
{...inputProps}
|
|
205
|
+
id={id}
|
|
206
|
+
leftSection={icon}
|
|
207
|
+
{...props.input.props}
|
|
208
|
+
{...passwordInputProps}
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
//endregion
|
|
193
213
|
|
|
194
|
-
|
|
214
|
+
//region <Textarea/>
|
|
215
|
+
if (props.area) {
|
|
216
|
+
const textAreaProps = typeof props.area === "object" ? props.area : {};
|
|
217
|
+
return (
|
|
218
|
+
<Textarea
|
|
219
|
+
{...inputProps}
|
|
220
|
+
id={id}
|
|
221
|
+
leftSection={icon}
|
|
222
|
+
{...props.input.props}
|
|
223
|
+
{...textAreaProps}
|
|
224
|
+
/>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
//endregion
|
|
195
228
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
229
|
+
//region <ControlDate/>
|
|
230
|
+
// Handle: date, date-time, and time formats
|
|
231
|
+
if (
|
|
232
|
+
props.date ||
|
|
233
|
+
props.datetime ||
|
|
234
|
+
props.time ||
|
|
235
|
+
format === "date" ||
|
|
236
|
+
format === "date-time" ||
|
|
237
|
+
format === "time"
|
|
238
|
+
) {
|
|
239
|
+
return (
|
|
240
|
+
<ControlDate
|
|
241
|
+
input={props.input}
|
|
242
|
+
title={props.title}
|
|
243
|
+
description={props.description}
|
|
244
|
+
icon={icon}
|
|
245
|
+
date={props.date}
|
|
246
|
+
datetime={props.datetime}
|
|
247
|
+
time={props.time}
|
|
248
|
+
/>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
//endregion
|
|
203
252
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
{...inputProps}
|
|
207
|
-
id={id}
|
|
208
|
-
color={"blue"}
|
|
209
|
-
defaultChecked={props.input.props.defaultValue}
|
|
210
|
-
{...props.input.props}
|
|
211
|
-
{...switchProps}
|
|
212
|
-
/>
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
// endregion
|
|
253
|
+
//region <TextInput/> with format detection
|
|
254
|
+
const textInputProps = typeof props.text === "object" ? props.text : {};
|
|
216
255
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
256
|
+
// Detect HTML5 input type from format
|
|
257
|
+
const getInputType = (): string | undefined => {
|
|
258
|
+
switch (format) {
|
|
259
|
+
case "email":
|
|
260
|
+
return "email";
|
|
261
|
+
case "url":
|
|
262
|
+
case "uri":
|
|
263
|
+
return "url";
|
|
264
|
+
case "tel":
|
|
265
|
+
case "phone":
|
|
266
|
+
return "tel";
|
|
267
|
+
default:
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
};
|
|
232
271
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
//endregion
|
|
247
|
-
|
|
248
|
-
// region <TextInput/>
|
|
249
|
-
const textInputProps = typeof props.text === "object" ? props.text : {};
|
|
250
|
-
return (
|
|
251
|
-
<TextInput
|
|
252
|
-
{...inputProps}
|
|
253
|
-
id={id}
|
|
254
|
-
leftSection={icon}
|
|
255
|
-
{...props.input.props}
|
|
256
|
-
{...textInputProps}
|
|
257
|
-
/>
|
|
258
|
-
);
|
|
259
|
-
//endregion
|
|
272
|
+
return (
|
|
273
|
+
<TextInput
|
|
274
|
+
{...inputProps}
|
|
275
|
+
id={id}
|
|
276
|
+
leftSection={icon}
|
|
277
|
+
type={getInputType()}
|
|
278
|
+
{...props.input.props}
|
|
279
|
+
{...textInputProps}
|
|
280
|
+
/>
|
|
281
|
+
);
|
|
282
|
+
//endregion
|
|
260
283
|
};
|
|
261
284
|
|
|
262
285
|
export default Control;
|
|
263
286
|
|
|
264
|
-
const prettyName = (name: string) => {
|
|
265
|
-
return capitalize(name.replaceAll("/", ""));
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const capitalize = (str: string) => {
|
|
269
|
-
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
270
|
-
};
|
|
271
|
-
|
|
272
287
|
export type CustomControlProps = {
|
|
273
|
-
|
|
274
|
-
|
|
288
|
+
defaultValue: any;
|
|
289
|
+
onChange: (value: any) => void;
|
|
275
290
|
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { useFormState } from "@alepha/react-form";
|
|
2
|
+
import {
|
|
3
|
+
DateInput,
|
|
4
|
+
type DateInputProps,
|
|
5
|
+
DateTimePicker,
|
|
6
|
+
type DateTimePickerProps,
|
|
7
|
+
TimeInput,
|
|
8
|
+
type TimeInputProps,
|
|
9
|
+
} from "@mantine/dates";
|
|
10
|
+
import { type GenericControlProps, parseInput } from "../utils/parseInput.ts";
|
|
11
|
+
|
|
12
|
+
export interface ControlDateProps extends GenericControlProps {
|
|
13
|
+
date?: boolean | DateInputProps;
|
|
14
|
+
datetime?: boolean | DateTimePickerProps;
|
|
15
|
+
time?: boolean | TimeInputProps;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* ControlDate component for handling date, datetime, and time inputs.
|
|
20
|
+
*
|
|
21
|
+
* Features:
|
|
22
|
+
* - DateInput for date format
|
|
23
|
+
* - DateTimePicker for date-time format
|
|
24
|
+
* - TimeInput for time format
|
|
25
|
+
*
|
|
26
|
+
* Automatically detects date formats from schema and renders appropriate picker.
|
|
27
|
+
*/
|
|
28
|
+
const ControlDate = (props: ControlDateProps) => {
|
|
29
|
+
const form = useFormState(props.input);
|
|
30
|
+
const { inputProps, id, icon, format } = parseInput(props, form);
|
|
31
|
+
if (!props.input?.props) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// region <DateTimePicker/>
|
|
36
|
+
if (props.datetime || format === "date-time") {
|
|
37
|
+
const dateTimePickerProps =
|
|
38
|
+
typeof props.datetime === "object" ? props.datetime : {};
|
|
39
|
+
return (
|
|
40
|
+
<DateTimePicker
|
|
41
|
+
{...inputProps}
|
|
42
|
+
id={id}
|
|
43
|
+
leftSection={icon}
|
|
44
|
+
defaultValue={
|
|
45
|
+
props.input.props.defaultValue
|
|
46
|
+
? new Date(props.input.props.defaultValue)
|
|
47
|
+
: undefined
|
|
48
|
+
}
|
|
49
|
+
onChange={(value) => {
|
|
50
|
+
props.input.set(value ? new Date(value).toISOString() : undefined);
|
|
51
|
+
}}
|
|
52
|
+
{...dateTimePickerProps}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
//endregion
|
|
57
|
+
|
|
58
|
+
// region <DateInput/>
|
|
59
|
+
if (props.date || format === "date") {
|
|
60
|
+
const dateInputProps = typeof props.date === "object" ? props.date : {};
|
|
61
|
+
return (
|
|
62
|
+
<DateInput
|
|
63
|
+
{...inputProps}
|
|
64
|
+
id={id}
|
|
65
|
+
leftSection={icon}
|
|
66
|
+
defaultValue={
|
|
67
|
+
props.input.props.defaultValue
|
|
68
|
+
? new Date(props.input.props.defaultValue)
|
|
69
|
+
: undefined
|
|
70
|
+
}
|
|
71
|
+
onChange={(value) => {
|
|
72
|
+
props.input.set(
|
|
73
|
+
value ? new Date(value).toISOString().slice(0, 10) : undefined,
|
|
74
|
+
);
|
|
75
|
+
}}
|
|
76
|
+
{...dateInputProps}
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
//endregion
|
|
81
|
+
|
|
82
|
+
// region <TimeInput/>
|
|
83
|
+
if (props.time || format === "time") {
|
|
84
|
+
const timeInputProps = typeof props.time === "object" ? props.time : {};
|
|
85
|
+
return (
|
|
86
|
+
<TimeInput
|
|
87
|
+
{...inputProps}
|
|
88
|
+
id={id}
|
|
89
|
+
leftSection={icon}
|
|
90
|
+
defaultValue={props.input.props.defaultValue}
|
|
91
|
+
onChange={(event) => {
|
|
92
|
+
props.input.set(event.currentTarget.value);
|
|
93
|
+
}}
|
|
94
|
+
{...timeInputProps}
|
|
95
|
+
/>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
//endregion
|
|
99
|
+
|
|
100
|
+
// Fallback - shouldn't happen
|
|
101
|
+
return null;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export default ControlDate;
|