-
Notifications
You must be signed in to change notification settings - Fork 2
/
input.tsx
52 lines (46 loc) · 2.33 KB
/
input.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { component$, $, PropsOf, useStyles$ } from "@builder.io/qwik";
import { WithControl, extractControls, useControlProvider } from "../control";
import { mergeProps } from "../../utils/attributes";
import { useFormFieldId } from "../form-field/form-field";
import style from './input.scss?inline';
export type InputValue = string | number | Date;
const fullMonth = (date: Date) => `${date.getMonth() + 1}`.padStart(2, "0");
const fullDay = (date: Date) => `${date.getDate()}`.padStart(2, "0");
const fullHour = (date: Date) => `${date.getHours()}`.padStart(2, "0");
const fullMin = (date: Date) => `${date.getMinutes()}`.padStart(2, "0");
const toHTMLMonthString = (date: Date) => `${date.getFullYear()}-${fullMonth(date)}`;
const toHTMLDateString = (date: Date) => `${date.getFullYear()}-${fullMonth(date)}-${fullDay(date)}`;
const toHTMLTimeString = (date: Date) => `${fullHour(date)}:${fullMin(date)}`;
export function toValueString(type: PropsOf<'input'>['type'], value?: InputValue) {
if (!value) return '';
if (typeof value === 'string') return value;
if (typeof value === 'number') return value.toString();
if (type === 'month') return toHTMLMonthString(value);
if (type === 'date') return toHTMLDateString(value);
if (type === 'time') return toHTMLTimeString(value);
if (type === 'datetime-local') return `${toHTMLDateString(value)}T${toHTMLTimeString(value)}`;
return value.toISOString();
}
export type InputProps = WithControl<InputValue, PropsOf<'input'>>;
export const Input = component$<WithControl<InputValue, PropsOf<'input'>>>((props) => {
useStyles$(style);
const { id, hasFormField } = useFormFieldId(props.id);
const { attr, controls } = extractControls(props);
const { control, change, name } = useControlProvider(controls);
const type = props.type ?? 'text';
const merged = mergeProps<'input'>(attr, {
id,
class: 'he-input',
name: name?.toString(),
value: toValueString(type, control.value),
type,
onInput$: $((e, i) => {
if (type === 'number') change(i.valueAsNumber);
else if (type === 'date' && i.valueAsDate) change(i.valueAsDate);
else if (type === 'datetime-local' && i.value) change(new Date(i.value));
else change(i.value);
}),
'aria-label': hasFormField ? undefined : (props['aria-label'] || props['placeholder']),
});
return <input {...merged} />;
});