time input: use internationalized/Date.Time-based value, add onchange

This commit is contained in:
Elijah Duffy
2025-07-21 20:04:42 -07:00
parent 39debb8865
commit 1a111121a1

View File

@@ -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<