time input: use internationalized/Date.Time-based value, add onchange
This commit is contained in:
@@ -6,29 +6,32 @@
|
|||||||
import type { ClassValue } from 'svelte/elements';
|
import type { ClassValue } from 'svelte/elements';
|
||||||
import { generateIdentifier, targetMust } from './util';
|
import { generateIdentifier, targetMust } from './util';
|
||||||
import { FocusManager } from './focus';
|
import { FocusManager } from './focus';
|
||||||
|
import { Time } from '@internationalized/date';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
name?: string;
|
name?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
value?: string;
|
value?: Time | null;
|
||||||
formattedValue?: string;
|
formattedValue?: string;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
invalidMessage?: string;
|
invalidMessage?: string;
|
||||||
showConfirm?: boolean;
|
showConfirm?: boolean;
|
||||||
compact?: boolean;
|
compact?: boolean;
|
||||||
class?: ClassValue | null | undefined;
|
class?: ClassValue | null | undefined;
|
||||||
|
onchange?: (details: { time: Time | null; formattedTime: string }) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
name,
|
name,
|
||||||
label,
|
label,
|
||||||
value = $bindable(''),
|
value = $bindable(null),
|
||||||
formattedValue = $bindable(''),
|
formattedValue = $bindable(''),
|
||||||
required,
|
required,
|
||||||
invalidMessage = 'Please select a time',
|
invalidMessage = 'Please select a time',
|
||||||
showConfirm = false,
|
showConfirm = false,
|
||||||
compact = false,
|
compact = false,
|
||||||
class: classValue
|
class: classValue,
|
||||||
|
onchange
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
type ampmKey = 'AM' | 'PM';
|
type ampmKey = 'AM' | 'PM';
|
||||||
@@ -121,17 +124,6 @@
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* prefixZero adds a leading zero to the string if it is less than 10
|
|
||||||
* @param str The string to prefix
|
|
||||||
*/
|
|
||||||
const prefixZero = (str: string) => {
|
|
||||||
if (str.length === 1) {
|
|
||||||
return '0' + str;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* updateValue updates `value` with the current time in 24-hour format.
|
* updateValue updates `value` with the current time in 24-hour format.
|
||||||
* If any component is invalid or blank, it sets `value` to an empty string.
|
* If any component is invalid or blank, it sets `value` to an empty string.
|
||||||
@@ -142,7 +134,7 @@
|
|||||||
let minuteValue = parseInt(values.minute);
|
let minuteValue = parseInt(values.minute);
|
||||||
|
|
||||||
if (isNaN(hourValue)) {
|
if (isNaN(hourValue)) {
|
||||||
value = '';
|
value = null;
|
||||||
formattedValue = '';
|
formattedValue = '';
|
||||||
updateHiddenInput();
|
updateHiddenInput();
|
||||||
return;
|
return;
|
||||||
@@ -157,7 +149,7 @@
|
|||||||
minuteValue = 0;
|
minuteValue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = `${prefixZero((hourValue + (ampmLocal === 'PM' ? 12 : 0)).toString())}:${prefixZero(minuteValue.toString())}`;
|
value = new Time(hourValue + (ampmLocal === 'PM' ? 12 : 0), minuteValue, 0);
|
||||||
updateHiddenInput();
|
updateHiddenInput();
|
||||||
|
|
||||||
// update formatted value
|
// update formatted value
|
||||||
@@ -170,8 +162,9 @@
|
|||||||
* a keyup event to allow validation to detect the change.
|
* a keyup event to allow validation to detect the change.
|
||||||
*/
|
*/
|
||||||
const updateHiddenInput = () => {
|
const updateHiddenInput = () => {
|
||||||
hiddenInput.value = value;
|
hiddenInput.value = value?.toString() ?? '';
|
||||||
hiddenInput.dispatchEvent(new KeyboardEvent('keyup'));
|
hiddenInput.dispatchEvent(new KeyboardEvent('keyup'));
|
||||||
|
onchange?.({ time: value, formattedTime: formattedValue });
|
||||||
};
|
};
|
||||||
|
|
||||||
const components: Record<
|
const components: Record<
|
||||||
|
|||||||
Reference in New Issue
Block a user