@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
724 lines (723 loc) • 33.6 kB
JavaScript
/*! All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://github.com/Esri/calcite-design-system/blob/dev/LICENSE.md for details.
v3.2.1 */
import { c as customElement } from "../../chunks/runtime.js";
import { ref } from "lit-html/directives/ref.js";
import { html } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { n as numberKeys } from "../../chunks/key.js";
import { i as isValidNumber } from "../../chunks/locale.js";
import { f as formatTimePart, p as parseTimeString, i as isValidTime, l as localizeTimeStringToParts, g as getMeridiem, a as getLocalizedTimePartSuffix, b as getLocalizedDecimalSeparator, c as localizeTimePart, d as getLocaleHourFormat, e as getMeridiemOrder, m as maxTenthForMinuteAndSecond } from "../../chunks/time.js";
import { c as componentFocusable, g as getIconScale } from "../../chunks/component.js";
import { g as getDecimals, d as decimalPlaces } from "../../chunks/math.js";
import { g as getElementDir } from "../../chunks/dom.js";
import { u as useT9n } from "../../chunks/useT9n.js";
import { css } from "@lit/reactive-element/css-tag.js";
const CSS = {
button: "button",
buttonBottomLeft: "button--bottom-left",
buttonBottomRight: "button--bottom-right",
buttonFractionalSecondDown: "button--fractionalSecond-down",
buttonFractionalSecondUp: "button--fractionalSecond-up",
buttonHourDown: "button--hour-down",
buttonHourUp: "button--hour-up",
buttonMeridiemDown: "button--meridiem-down",
buttonMeridiemUp: "button--meridiem-up",
buttonMinuteDown: "button--minute-down",
buttonMinuteUp: "button--minute-up",
buttonSecondDown: "button--second-down",
buttonSecondUp: "button--second-up",
buttonTopLeft: "button--top-left",
buttonTopRight: "button--top-right",
column: "column",
decimalSeparator: "decimal-separator",
delimiter: "delimiter",
fractionalSecond: "fractionalSecond",
hour: "hour",
hourSuffix: "hour-suffix",
input: "input",
inputFocus: "inputFocus",
meridiem: "meridiem",
minute: "minute",
minuteSuffix: "minute-suffix",
second: "second",
secondSuffix: "second-suffix",
showMeridiem: "show-meridiem",
showSecond: "show-second",
"scale-s": "scale-s",
"scale-m": "scale-m",
"scale-l": "scale-l",
timePicker: "time-picker",
meridiemStart: "meridiem--start"
};
const styles = css`:host{display:inline-block}.time-picker{display:flex;-webkit-user-select:none;user-select:none;align-items:center;font-weight:var(--calcite-font-weight-medium);--tw-shadow: 0 6px 20px -4px rgba(0, 0, 0, .1), 0 4px 12px -2px rgba(0, 0, 0, .08);--tw-shadow-colored: 0 6px 20px -4px var(--tw-shadow-color), 0 4px 12px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);border-radius:var(--calcite-time-picker-corner-radius, var(--calcite-border-radius-round));color:var(--calcite-time-picker-color, var(--calcite-color-text-1));background-color:var(--calcite-time-picker-background-color, var(--calcite-color-foreground-1))}.time-picker .column{display:flex;flex-direction:column}.time-picker .meridiem--start{order:-1}.time-picker .button{display:inline-flex;cursor:pointer;align-items:center;justify-content:center;background-color:var(--calcite-time-picker-background-color, var(--calcite-color-foreground-1))}.time-picker .button:hover,.time-picker .button:focus{outline:2px solid transparent;outline-offset:2px;z-index:var(--calcite-z-index-header);outline-offset:0;background-color:var(--calcite-time-picker-button-background-color-hover, var(--calcite-color-foreground-2))}.time-picker .button:active{background-color:var(--calcite-time-picker-button-background-color-press, var(--calcite-color-foreground-3))}.time-picker .button.top-left{border-start-start-radius:var(--calcite-time-picker-corner-radius, var(--calcite-border-radius-round))}.time-picker .button.bottom-left{border-end-start-radius:var(--calcite-time-picker-corner-radius, var(--calcite-border-radius-round))}.time-picker .button.top-right{border-start-end-radius:var(--calcite-time-picker-corner-radius, var(--calcite-border-radius-round))}.time-picker .button.bottom-right{border-end-end-radius:var(--calcite-time-picker-corner-radius, var(--calcite-border-radius-round))}.time-picker .button calcite-icon{color:var(--calcite-time-picker-icon-color, var(--calcite-color-text-3))}.time-picker .input{display:inline-flex;cursor:pointer;align-items:center;justify-content:center;font-weight:var(--calcite-font-weight-medium);background-color:var(--calcite-time-picker-background-color, var(--calcite-color-foreground-1))}.time-picker .input:hover{box-shadow:inset 0 0 0 2px var(--calcite-time-picker-input-border-color-hover, var(--calcite-color-foreground-2));z-index:var(--calcite-z-index-header)}.time-picker .input:focus,.time-picker .input:hover:focus{outline:2px solid transparent;outline-offset:2px;outline-offset:0}.time-picker .input.inputFocus,.time-picker .input:hover.inputFocus{box-shadow:inset 0 0 0 2px var(--calcite-time-picker-input-border-color-press, var(--calcite-color-brand));z-index:var(--calcite-z-index-header)}.time-picker.scale-s{font-size:var(--calcite-font-size--1)}.time-picker.scale-s .button,.time-picker.scale-s .input{padding-inline:var(--calcite-spacing-md);padding-block:var(--calcite-spacing-xxs)}.time-picker.scale-s:not(.show-meridiem) .delimiter:last-child{padding-inline-end:var(--calcite-spacing-md)}.time-picker.scale-m{font-size:var(--calcite-font-size-0)}.time-picker.scale-m .button,.time-picker.scale-m .input{padding-inline:var(--calcite-spacing-xl);padding-block:var(--calcite-spacing-sm)}.time-picker.scale-m:not(.show-meridiem) .delimiter:last-child{padding-inline-end:var(--calcite-spacing-xl)}.time-picker.scale-l{font-size:var(--calcite-font-size-1)}.time-picker.scale-l .button,.time-picker.scale-l .input{padding-inline:var(--calcite-spacing-xxl);padding-block:var(--calcite-spacing-md)}.time-picker.scale-l:not(.show-meridiem) .delimiter:last-child{padding-inline-end:var(--calcite-spacing-xxl)}:host([hidden]){display:none}[hidden]{display:none}`;
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
class TimePicker extends LitElement {
constructor() {
super();
this.pointerActivated = false;
this.messages = useT9n();
this.localizedDecimalSeparator = ".";
this.hourFormat = "user";
this.scale = "m";
this.step = 60;
this.value = null;
this.calciteTimePickerChange = createEvent({ cancelable: false });
this.listen("blur", this.blurHandler);
this.listen("keydown", this.keyDownHandler);
this.listen("pointerdown", this.pointerDownHandler);
}
static {
this.properties = { activeEl: [16, {}, { state: true }], effectiveHourFormat: [16, {}, { state: true }], fractionalSecond: [16, {}, { state: true }], hour: [16, {}, { state: true }], localizedDecimalSeparator: [16, {}, { state: true }], localizedFractionalSecond: [16, {}, { state: true }], localizedHour: [16, {}, { state: true }], localizedHourSuffix: [16, {}, { state: true }], localizedMeridiem: [16, {}, { state: true }], localizedMinute: [16, {}, { state: true }], localizedMinuteSuffix: [16, {}, { state: true }], localizedSecond: [16, {}, { state: true }], localizedSecondSuffix: [16, {}, { state: true }], meridiem: [16, {}, { state: true }], minute: [16, {}, { state: true }], second: [16, {}, { state: true }], showFractionalSecond: [16, {}, { state: true }], showSecond: [16, {}, { state: true }], hourFormat: [3, {}, { reflect: true }], messageOverrides: [0, {}, { attribute: false }], numberingSystem: 1, scale: [3, {}, { reflect: true }], step: [11, {}, { reflect: true, type: Number }], value: 1 };
}
static {
this.shadowRootOptions = { mode: "open", delegatesFocus: true };
}
static {
this.styles = styles;
}
async setFocus() {
await componentFocusable(this);
this.el?.focus();
}
connectedCallback() {
super.connectedCallback();
this.updateLocale();
this.toggleSecond();
}
willUpdate(changes) {
if (changes.has("step") && (this.hasUpdated || this.step !== 60)) {
this.toggleSecond();
}
if (changes.has("value") && (this.hasUpdated || this.value !== null)) {
this.setValue(this.value);
}
if (changes.has("hourFormat") || changes.has("messages")) {
this.updateLocale();
}
}
blurHandler() {
this.activeEl = void 0;
this.pointerActivated = false;
}
keyDownHandler(event) {
this.pointerActivated = false;
const { defaultPrevented, key } = event;
if (defaultPrevented) {
return;
}
switch (this.activeEl) {
case this.hourEl:
if (key === "ArrowRight") {
this.focusPart("minute");
event.preventDefault();
}
break;
case this.minuteEl:
switch (key) {
case "ArrowLeft":
this.focusPart("hour");
event.preventDefault();
break;
case "ArrowRight":
if (this.step !== 60) {
this.focusPart("second");
event.preventDefault();
} else if (this.effectiveHourFormat === "12") {
this.focusPart("meridiem");
event.preventDefault();
}
break;
}
break;
case this.secondEl:
switch (key) {
case "ArrowLeft":
this.focusPart("minute");
event.preventDefault();
break;
case "ArrowRight":
if (this.showFractionalSecond) {
this.focusPart("fractionalSecond");
} else if (this.effectiveHourFormat === "12") {
this.focusPart("meridiem");
event.preventDefault();
}
break;
}
break;
case this.fractionalSecondEl:
switch (key) {
case "ArrowLeft":
this.focusPart("second");
event.preventDefault();
break;
case "ArrowRight":
if (this.effectiveHourFormat === "12") {
this.focusPart("meridiem");
event.preventDefault();
}
break;
}
break;
case this.meridiemEl:
switch (key) {
case "ArrowLeft":
if (this.showFractionalSecond) {
this.focusPart("fractionalSecond");
} else if (this.step !== 60) {
this.focusPart("second");
event.preventDefault();
} else {
this.focusPart("minute");
event.preventDefault();
}
break;
}
break;
}
}
pointerDownHandler() {
this.pointerActivated = true;
}
async focusPart(target) {
await componentFocusable(this);
this[`${target || "hour"}El`]?.focus();
}
decrementHour() {
const newHour = !this.hour ? 0 : parseInt(this.hour) === 0 ? 23 : parseInt(this.hour) - 1;
this.setValuePart("hour", newHour);
}
decrementMeridiem() {
const newMeridiem = this.meridiem === "PM" ? "AM" : "PM";
this.setValuePart("meridiem", newMeridiem);
}
decrementMinuteOrSecond(key) {
let newValue;
if (isValidNumber(this[key])) {
const valueAsNumber = parseInt(this[key]);
newValue = valueAsNumber === 0 ? 59 : valueAsNumber - 1;
} else {
newValue = 59;
}
this.setValuePart(key, newValue);
}
decrementMinute() {
this.decrementMinuteOrSecond("minute");
}
decrementSecond() {
this.decrementMinuteOrSecond("second");
}
focusHandler(event) {
if (this.pointerActivated) {
return;
}
this.activeEl = event.currentTarget;
}
fractionalSecondKeyDownHandler(event) {
const { key } = event;
if (numberKeys.includes(key)) {
const { stepPrecision } = this;
const fractionalSecondAsInteger = parseInt(this.fractionalSecond);
const fractionalSecondAsIntegerLength = fractionalSecondAsInteger.toString().length;
let newFractionalSecondAsIntegerString;
if (fractionalSecondAsIntegerLength >= stepPrecision) {
newFractionalSecondAsIntegerString = key.padStart(stepPrecision, "0");
} else if (fractionalSecondAsIntegerLength < stepPrecision) {
newFractionalSecondAsIntegerString = `${fractionalSecondAsInteger}${key}`.padStart(stepPrecision, "0");
}
this.setValuePart("fractionalSecond", parseFloat(`0.${newFractionalSecondAsIntegerString}`));
} else {
switch (key) {
case "Backspace":
case "Delete":
this.setValuePart("fractionalSecond", null);
break;
case "ArrowDown":
event.preventDefault();
this.nudgeFractionalSecond("down");
break;
case "ArrowUp":
event.preventDefault();
this.nudgeFractionalSecond("up");
break;
case " ":
event.preventDefault();
break;
}
}
}
fractionalSecondDownClickHandler() {
this.activeEl = this.fractionalSecondEl;
this.fractionalSecondEl.focus();
this.nudgeFractionalSecond("down");
}
fractionalSecondUpClickHandler() {
this.activeEl = this.fractionalSecondEl;
this.fractionalSecondEl.focus();
this.nudgeFractionalSecond("up");
}
hourDownClickHandler() {
this.activeEl = this.hourEl;
this.hourEl.focus();
this.decrementHour();
}
hourKeyDownHandler(event) {
const { key } = event;
if (numberKeys.includes(key)) {
const keyAsNumber = parseInt(key);
let newHour;
if (isValidNumber(this.hour)) {
switch (this.effectiveHourFormat) {
case "12":
newHour = this.hour === "01" && keyAsNumber >= 0 && keyAsNumber <= 2 ? `1${keyAsNumber}` : keyAsNumber;
break;
case "24":
if (this.hour === "01") {
newHour = `1${keyAsNumber}`;
} else if (this.hour === "02" && keyAsNumber >= 0 && keyAsNumber <= 3) {
newHour = `2${keyAsNumber}`;
} else {
newHour = keyAsNumber;
}
break;
}
} else {
newHour = keyAsNumber;
}
this.setValuePart("hour", newHour);
} else {
switch (key) {
case "Backspace":
case "Delete":
this.setValuePart("hour", null);
break;
case "ArrowDown":
event.preventDefault();
this.decrementHour();
break;
case "ArrowUp":
event.preventDefault();
this.incrementHour();
break;
case " ":
event.preventDefault();
break;
}
}
}
hourUpClickHandler() {
this.activeEl = this.hourEl;
this.hourEl.focus();
this.incrementHour();
}
incrementMeridiem() {
const newMeridiem = this.meridiem === "AM" ? "PM" : "AM";
this.setValuePart("meridiem", newMeridiem);
}
incrementHour() {
const newHour = isValidNumber(this.hour) ? this.hour === "23" ? 0 : parseInt(this.hour) + 1 : 1;
this.setValuePart("hour", newHour);
}
incrementMinuteOrSecond(key) {
const newValue = isValidNumber(this[key]) ? this[key] === "59" ? 0 : parseInt(this[key]) + 1 : 0;
this.setValuePart(key, newValue);
}
incrementMinute() {
this.incrementMinuteOrSecond("minute");
}
incrementSecond() {
this.incrementMinuteOrSecond("second");
}
inputClickHandler(event) {
this.activeEl = event.target;
}
meridiemUpClickHandler() {
this.activeEl = this.meridiemEl;
this.meridiemEl.focus();
this.incrementMeridiem();
}
meridiemKeyDownHandler(event) {
switch (event.key) {
case "a":
this.setValuePart("meridiem", "AM");
break;
case "p":
this.setValuePart("meridiem", "PM");
break;
case "Backspace":
case "Delete":
this.setValuePart("meridiem", null);
break;
case "ArrowUp":
event.preventDefault();
this.incrementMeridiem();
break;
case "ArrowDown":
event.preventDefault();
this.decrementMeridiem();
break;
case " ":
event.preventDefault();
break;
}
}
meridiemDownClickHandler() {
this.activeEl = this.meridiemEl;
this.meridiemEl.focus();
this.decrementMeridiem();
}
minuteDownClickHandler() {
this.activeEl = this.minuteEl;
this.minuteEl.focus();
this.decrementMinute();
}
minuteUpClickHandler() {
this.activeEl = this.minuteEl;
this.minuteEl.focus();
this.incrementMinute();
}
minuteKeyDownHandler(event) {
const { key } = event;
if (numberKeys.includes(key)) {
const keyAsNumber = parseInt(key);
let newMinute;
if (isValidNumber(this.minute) && this.minute.startsWith("0")) {
const minuteAsNumber = parseInt(this.minute);
newMinute = minuteAsNumber > maxTenthForMinuteAndSecond ? keyAsNumber : `${minuteAsNumber}${keyAsNumber}`;
} else {
newMinute = keyAsNumber;
}
this.setValuePart("minute", newMinute);
} else {
switch (key) {
case "Backspace":
case "Delete":
this.setValuePart("minute", null);
break;
case "ArrowDown":
event.preventDefault();
this.decrementMinute();
break;
case "ArrowUp":
event.preventDefault();
this.incrementMinute();
break;
case " ":
event.preventDefault();
break;
}
}
}
nudgeFractionalSecond(direction) {
const stepDecimal = getDecimals(this.step);
const { stepPrecision } = this;
const fractionalSecondAsInteger = parseInt(this.fractionalSecond);
const fractionalSecondAsFloat = parseFloat(`0.${this.fractionalSecond}`);
let nudgedValue;
let nudgedValueRounded;
let nudgedValueRoundedDecimals;
let newFractionalSecond;
if (direction === "up") {
nudgedValue = isNaN(fractionalSecondAsInteger) ? 0 : fractionalSecondAsFloat + stepDecimal;
nudgedValueRounded = parseFloat(nudgedValue.toFixed(stepPrecision));
nudgedValueRoundedDecimals = getDecimals(nudgedValueRounded);
newFractionalSecond = nudgedValueRounded < 1 && decimalPlaces(nudgedValueRoundedDecimals) > 0 ? formatTimePart(nudgedValueRoundedDecimals, stepPrecision) : "".padStart(stepPrecision, "0");
}
if (direction === "down") {
nudgedValue = isNaN(fractionalSecondAsInteger) || fractionalSecondAsInteger === 0 ? 1 - stepDecimal : fractionalSecondAsFloat - stepDecimal;
nudgedValueRounded = parseFloat(nudgedValue.toFixed(stepPrecision));
nudgedValueRoundedDecimals = getDecimals(nudgedValueRounded);
newFractionalSecond = nudgedValueRounded < 1 && decimalPlaces(nudgedValueRoundedDecimals) > 0 && Math.sign(nudgedValueRoundedDecimals) === 1 ? formatTimePart(nudgedValueRoundedDecimals, stepPrecision) : "".padStart(stepPrecision, "0");
}
this.setValuePart("fractionalSecond", newFractionalSecond);
}
sanitizeValue(value) {
const { hour, minute, second, fractionalSecond } = parseTimeString(value);
if (fractionalSecond) {
const sanitizedFractionalSecond = this.sanitizeFractionalSecond(fractionalSecond);
return `${hour}:${minute}:${second}.${sanitizedFractionalSecond}`;
}
return isValidTime(value) && value;
}
sanitizeFractionalSecond(fractionalSecond) {
const { stepPrecision } = this;
return fractionalSecond && stepPrecision !== fractionalSecond.length ? parseFloat(`0.${fractionalSecond}`).toFixed(stepPrecision).replace("0.", "") : fractionalSecond;
}
secondKeyDownHandler(event) {
const { key } = event;
if (numberKeys.includes(key)) {
const keyAsNumber = parseInt(key);
let newSecond;
if (isValidNumber(this.second) && this.second.startsWith("0")) {
const secondAsNumber = parseInt(this.second);
newSecond = secondAsNumber > maxTenthForMinuteAndSecond ? keyAsNumber : `${secondAsNumber}${keyAsNumber}`;
} else {
newSecond = keyAsNumber;
}
this.setValuePart("second", newSecond);
} else {
switch (key) {
case "Backspace":
case "Delete":
this.setValuePart("second", null);
break;
case "ArrowDown":
event.preventDefault();
this.decrementSecond();
break;
case "ArrowUp":
event.preventDefault();
this.incrementSecond();
break;
case " ":
event.preventDefault();
break;
}
}
}
secondDownClickHandler() {
this.activeEl = this.secondEl;
this.secondEl.focus();
this.decrementSecond();
}
secondUpClickHandler() {
this.activeEl = this.secondEl;
this.secondEl.focus();
this.incrementSecond();
}
setHourEl(el) {
this.hourEl = el;
}
setMeridiemEl(el) {
this.meridiemEl = el;
}
setMinuteEl(el) {
this.minuteEl = el;
}
setSecondEl(el) {
this.secondEl = el;
}
setFractionalSecondEl(el) {
this.fractionalSecondEl = el;
}
setValue(value) {
if (isValidTime(value)) {
const { hour, minute, second, fractionalSecond } = parseTimeString(value);
const { effectiveHourFormat, messages: { _lang: locale }, numberingSystem, step } = this;
const { hour: localizedHour, hourSuffix: localizedHourSuffix, minute: localizedMinute, minuteSuffix: localizedMinuteSuffix, second: localizedSecond, secondSuffix: localizedSecondSuffix, decimalSeparator: localizedDecimalSeparator, fractionalSecond: localizedFractionalSecond, meridiem: localizedMeridiem } = localizeTimeStringToParts({
value,
locale,
numberingSystem,
hour12: effectiveHourFormat === "12",
step
});
this.hour = hour;
this.minute = minute;
this.second = second;
this.fractionalSecond = this.sanitizeFractionalSecond(fractionalSecond);
this.localizedHour = localizedHour;
this.localizedHourSuffix = localizedHourSuffix;
this.localizedMinute = localizedMinute;
this.localizedMinuteSuffix = localizedMinuteSuffix;
this.localizedSecond = localizedSecond;
this.localizedDecimalSeparator = localizedDecimalSeparator;
this.localizedFractionalSecond = localizedFractionalSecond;
this.localizedSecondSuffix = localizedSecondSuffix;
if (localizedMeridiem) {
this.localizedMeridiem = localizedMeridiem;
this.meridiem = getMeridiem(this.hour);
}
} else {
this.hour = null;
this.fractionalSecond = null;
this.localizedHour = null;
this.localizedHourSuffix = getLocalizedTimePartSuffix("hour", this.messages._lang, this.numberingSystem);
this.localizedMeridiem = null;
this.localizedMinute = null;
this.localizedMinuteSuffix = getLocalizedTimePartSuffix("minute", this.messages._lang, this.numberingSystem);
this.localizedSecond = null;
this.localizedDecimalSeparator = getLocalizedDecimalSeparator(this.messages._lang, this.numberingSystem);
this.localizedFractionalSecond = null;
this.localizedSecondSuffix = getLocalizedTimePartSuffix("second", this.messages._lang, this.numberingSystem);
this.meridiem = null;
this.minute = null;
this.second = null;
this.value = null;
}
}
setValuePart(key, value) {
const { effectiveHourFormat, messages: { _lang: locale }, numberingSystem, step } = this;
const hour12 = effectiveHourFormat === "12";
if (key === "meridiem") {
this.meridiem = value;
if (isValidNumber(this.hour)) {
const hourAsNumber = parseInt(this.hour);
switch (value) {
case "AM":
if (hourAsNumber >= 12) {
this.hour = formatTimePart(hourAsNumber - 12);
}
break;
case "PM":
if (hourAsNumber < 12) {
this.hour = formatTimePart(hourAsNumber + 12);
}
break;
}
this.localizedHour = localizeTimePart({
value: this.hour,
part: "hour",
locale,
numberingSystem,
hour12
});
}
} else if (key === "fractionalSecond") {
const { stepPrecision } = this;
if (typeof value === "number") {
this.fractionalSecond = value === 0 ? "".padStart(stepPrecision, "0") : formatTimePart(value, stepPrecision);
} else {
this.fractionalSecond = value;
}
this.localizedFractionalSecond = localizeTimePart({
value: this.fractionalSecond,
part: "fractionalSecond",
locale,
numberingSystem,
hour12
});
} else {
this[key] = typeof value === "number" ? formatTimePart(value) : value;
this[`localized${capitalize(key)}`] = localizeTimePart({
value: this[key],
part: key,
locale,
numberingSystem,
hour12
});
}
let emit = false;
let newValue;
if (this.hour && this.minute) {
newValue = `${this.hour}:${this.minute}`;
if (this.showSecond) {
newValue = `${newValue}:${this.second ?? "00"}`;
if (this.showFractionalSecond && this.fractionalSecond) {
newValue = `${newValue}.${this.fractionalSecond}`;
}
}
} else {
newValue = null;
}
if (this.value !== newValue) {
emit = true;
}
this.value = newValue;
this.localizedMeridiem = this.value ? localizeTimeStringToParts({
hour12,
locale,
numberingSystem,
step,
value: this.value
})?.meridiem || null : localizeTimePart({
hour12,
value: this.meridiem,
part: "meridiem",
locale,
numberingSystem
});
if (emit) {
this.calciteTimePickerChange.emit();
}
}
toggleSecond() {
this.showSecond = this.step < 60;
this.stepPrecision = decimalPlaces(this.step);
this.showFractionalSecond = this.stepPrecision > 0;
}
updateLocale() {
this.effectiveHourFormat = this.hourFormat === "user" ? getLocaleHourFormat(this.messages._lang) : this.hourFormat;
this.localizedDecimalSeparator = getLocalizedDecimalSeparator(this.messages._lang, this.numberingSystem);
this.meridiemOrder = getMeridiemOrder(this.messages._lang);
this.setValue(this.sanitizeValue(this.value));
}
render() {
const hourIsNumber = isValidNumber(this.hour);
const iconScale = getIconScale(this.scale);
const minuteIsNumber = isValidNumber(this.minute);
const secondIsNumber = isValidNumber(this.second);
const fractionalSecondIsNumber = isValidNumber(this.fractionalSecond);
const showSecondSuffix = this.messages._lang !== "bg" && this.localizedSecondSuffix;
const showMeridiem = this.effectiveHourFormat === "12";
return html`<div class=${safeClassMap({
[CSS.timePicker]: true,
[CSS.showMeridiem]: showMeridiem,
[CSS.showSecond]: this.showSecond,
[CSS[`scale-${this.scale}`]]: true
})} dir=ltr><div class=${safeClassMap(CSS.column)} role=group><span .ariaLabel=${this.messages.hourUp} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonHourUp]: true,
[CSS.buttonTopLeft]: true
})} =${this.hourUpClickHandler} role=button><calcite-icon icon=chevron-up .scale=${iconScale}></calcite-icon></span><span .ariaLabel=${this.messages.hour} aria-valuemax=23 aria-valuemin=1 .ariaValueNow=${hourIsNumber && parseInt(this.hour) || "0"} .ariaValueText=${this.hour} class=${safeClassMap({
[CSS.input]: true,
[CSS.hour]: true,
[CSS.inputFocus]: this.activeEl && this.activeEl === this.hourEl
})} =${this.inputClickHandler} =${this.focusHandler} =${this.hourKeyDownHandler} role=spinbutton tabindex=0 ${ref(this.setHourEl)}>${this.localizedHour || "--"}</span><span .ariaLabel=${this.messages.hourDown} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonHourDown]: true,
[CSS.buttonBottomLeft]: true
})} =${this.hourDownClickHandler} role=button><calcite-icon icon=chevron-down .scale=${iconScale}></calcite-icon></span></div><span class=${safeClassMap({ [CSS.delimiter]: true, [CSS.hourSuffix]: true })}>${this.localizedHourSuffix}</span><div class=${safeClassMap(CSS.column)} role=group><span .ariaLabel=${this.messages.minuteUp} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonMinuteUp]: true
})} =${this.minuteUpClickHandler} role=button><calcite-icon icon=chevron-up .scale=${iconScale}></calcite-icon></span><span .ariaLabel=${this.messages.minute} aria-valuemax=12 aria-valuemin=1 .ariaValueNow=${minuteIsNumber && parseInt(this.minute) || "0"} .ariaValueText=${this.minute} class=${safeClassMap({
[CSS.input]: true,
[CSS.minute]: true,
[CSS.inputFocus]: this.activeEl && this.activeEl === this.minuteEl
})} =${this.inputClickHandler} =${this.focusHandler} =${this.minuteKeyDownHandler} role=spinbutton tabindex=0 ${ref(this.setMinuteEl)}>${this.localizedMinute || "--"}</span><span .ariaLabel=${this.messages.minuteDown} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonMinuteDown]: true
})} =${this.minuteDownClickHandler} role=button><calcite-icon icon=chevron-down .scale=${iconScale}></calcite-icon></span></div>${this.showSecond && html`<span class=${safeClassMap({ [CSS.delimiter]: true, [CSS.minuteSuffix]: true })}>${this.localizedMinuteSuffix}</span>` || ""}${this.showSecond && html`<div class=${safeClassMap(CSS.column)} role=group><span .ariaLabel=${this.messages.secondUp} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonSecondUp]: true
})} =${this.secondUpClickHandler} role=button><calcite-icon icon=chevron-up .scale=${iconScale}></calcite-icon></span><span .ariaLabel=${this.messages.second} aria-valuemax=59 aria-valuemin=0 .ariaValueNow=${secondIsNumber && parseInt(this.second) || "0"} .ariaValueText=${this.second} class=${safeClassMap({
[CSS.input]: true,
[CSS.second]: true,
[CSS.inputFocus]: this.activeEl && this.activeEl === this.secondEl
})} =${this.inputClickHandler} =${this.focusHandler} =${this.secondKeyDownHandler} role=spinbutton tabindex=0 ${ref(this.setSecondEl)}>${this.localizedSecond || "--"}</span><span .ariaLabel=${this.messages.secondDown} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonSecondDown]: true
})} =${this.secondDownClickHandler} role=button><calcite-icon icon=chevron-down .scale=${iconScale}></calcite-icon></span></div>` || ""}${this.showFractionalSecond && html`<span class=${safeClassMap({ [CSS.delimiter]: true, [CSS.decimalSeparator]: true })}>${this.localizedDecimalSeparator}</span>` || ""}${this.showFractionalSecond && html`<div class=${safeClassMap(CSS.column)} role=group><span .ariaLabel=${this.messages.fractionalSecondUp} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonFractionalSecondUp]: true
})} =${this.fractionalSecondUpClickHandler} role=button><calcite-icon icon=chevron-up .scale=${iconScale}></calcite-icon></span><span .ariaLabel=${this.messages.fractionalSecond} aria-valuemax=999 aria-valuemin=1 .ariaValueNow=${fractionalSecondIsNumber && parseInt(this.fractionalSecond) || "0"} .ariaValueText=${this.localizedFractionalSecond} class=${safeClassMap({
[CSS.input]: true,
[CSS.fractionalSecond]: true,
[CSS.inputFocus]: this.activeEl && this.activeEl === this.fractionalSecondEl
})} =${this.inputClickHandler} =${this.focusHandler} =${this.fractionalSecondKeyDownHandler} role=spinbutton tabindex=0 ${ref(this.setFractionalSecondEl)}>${this.localizedFractionalSecond || "".padStart(this.stepPrecision, "-")}</span><span .ariaLabel=${this.messages.fractionalSecondDown} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonFractionalSecondDown]: true
})} =${this.fractionalSecondDownClickHandler} role=button><calcite-icon icon=chevron-down .scale=${iconScale}></calcite-icon></span></div>` || ""}${showSecondSuffix && html`<span class=${safeClassMap({ [CSS.delimiter]: true, [CSS.secondSuffix]: true })}>${this.localizedSecondSuffix}</span>` || ""}${showMeridiem && html`<div class=${safeClassMap({
[CSS.column]: true,
[CSS.meridiemStart]: this.meridiemOrder === 0 || getElementDir(this.el) === "rtl"
})} role=group><span .ariaLabel=${this.messages.meridiemUp} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonMeridiemUp]: true,
[CSS.buttonTopRight]: true
})} =${this.meridiemUpClickHandler} role=button><calcite-icon icon=chevron-up .scale=${iconScale}></calcite-icon></span><span .ariaLabel=${this.messages.meridiem} aria-valuemax=2 aria-valuemin=1 .ariaValueNow=${this.meridiem === "PM" && "2" || "1"} .ariaValueText=${this.meridiem} class=${safeClassMap({
[CSS.input]: true,
[CSS.meridiem]: true,
[CSS.inputFocus]: this.activeEl && this.activeEl === this.meridiemEl
})} =${this.inputClickHandler} =${this.focusHandler} =${this.meridiemKeyDownHandler} role=spinbutton tabindex=0 ${ref(this.setMeridiemEl)}>${this.localizedMeridiem || "--"}</span><span .ariaLabel=${this.messages.meridiemDown} class=${safeClassMap({
[CSS.button]: true,
[CSS.buttonMeridiemDown]: true,
[CSS.buttonBottomRight]: true
})} =${this.meridiemDownClickHandler} role=button><calcite-icon icon=chevron-down .scale=${iconScale}></calcite-icon></span></div>` || ""}</div>`;
}
}
customElement("calcite-time-picker", TimePicker);
export {
TimePicker
};