calcite-input-time-picker_2.entry.js 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.97
  5. */
  6. import { r as registerInstance, c as createEvent, h, H as Host, g as getElement } from './index-1f9b54dc.js';
  7. import { g as guid } from './guid-9f15e57a.js';
  8. import { i as isValidNumber, g as getSupportedLocale, b as getSupportedNumberingSystem, n as numberStringFormatter, u as updateEffectiveLocale, c as connectLocalized, d as disconnectLocalized } from './locale-35f81208.js';
  9. import { c as connectLabel, d as disconnectLabel, g as getLabelText } from './label-333c4a4c.js';
  10. import { s as submitForm, c as connectForm, d as disconnectForm, H as HiddenFormInputSlot } from './form-80dbd90e.js';
  11. import { u as updateHostInteraction } from './interactive-5db230e8.js';
  12. import { n as numberKeys, i as isActivationKey } from './key-acc755b7.js';
  13. import './observers-9f44e9b3.js';
  14. import './dom-8f0a9ff2.js';
  15. import './resources-9c476cb6.js';
  16. const maxTenthForMinuteAndSecond = 5;
  17. function createLocaleDateTimeFormatter(locale, numberingSystem, includeSeconds = true) {
  18. try {
  19. const options = {
  20. hour: "2-digit",
  21. minute: "2-digit",
  22. timeZone: "UTC",
  23. numberingSystem: getSupportedNumberingSystem(numberingSystem)
  24. };
  25. if (includeSeconds) {
  26. options.second = "2-digit";
  27. }
  28. return new Intl.DateTimeFormat(getSupportedLocale(locale), options);
  29. }
  30. catch (error) {
  31. throw new Error(`Invalid locale supplied while attempting to create a DateTime formatter: ${locale}`);
  32. }
  33. }
  34. function formatTimePart(number) {
  35. const numberAsString = number.toString();
  36. return number >= 0 && number <= 9 ? numberAsString.padStart(2, "0") : numberAsString;
  37. }
  38. function formatTimeString(value) {
  39. if (!isValidTime(value)) {
  40. return null;
  41. }
  42. const [hourString, minuteString, secondString] = value.split(":");
  43. const hour = formatTimePart(parseInt(hourString));
  44. const minute = formatTimePart(parseInt(minuteString));
  45. if (secondString) {
  46. const second = formatTimePart(parseInt(secondString));
  47. return `${hour}:${minute}:${second}`;
  48. }
  49. return `${hour}:${minute}`;
  50. }
  51. function getLocaleHourCycle(locale, numberingSystem) {
  52. const formatter = createLocaleDateTimeFormatter(locale, numberingSystem);
  53. const parts = formatter.formatToParts(new Date(Date.UTC(0, 0, 0, 0, 0, 0)));
  54. return getLocalizedTimePart("meridiem", parts) ? "12" : "24";
  55. }
  56. function getLocalizedTimePart(part, parts) {
  57. var _a, _b, _c, _d;
  58. if (!part || !parts) {
  59. return null;
  60. }
  61. if (part === "hourSuffix") {
  62. const hourIndex = parts.indexOf(parts.find(({ type }) => type === "hour"));
  63. const minuteIndex = parts.indexOf(parts.find(({ type }) => type === "minute"));
  64. const hourSuffix = parts[hourIndex + 1];
  65. return hourSuffix && hourSuffix.type === "literal" && minuteIndex - hourIndex === 2
  66. ? ((_a = hourSuffix.value) === null || _a === void 0 ? void 0 : _a.trim()) || null
  67. : null;
  68. }
  69. if (part === "minuteSuffix") {
  70. const minuteIndex = parts.indexOf(parts.find(({ type }) => type === "minute"));
  71. const secondIndex = parts.indexOf(parts.find(({ type }) => type === "second"));
  72. const minuteSuffix = parts[minuteIndex + 1];
  73. return minuteSuffix && minuteSuffix.type === "literal" && secondIndex - minuteIndex === 2
  74. ? ((_b = minuteSuffix.value) === null || _b === void 0 ? void 0 : _b.trim()) || null
  75. : null;
  76. }
  77. if (part === "secondSuffix") {
  78. const secondIndex = parts.indexOf(parts.find(({ type }) => type === "second"));
  79. const secondSuffix = parts[secondIndex + 1];
  80. return secondSuffix && secondSuffix.type === "literal" ? ((_c = secondSuffix.value) === null || _c === void 0 ? void 0 : _c.trim()) || null : null;
  81. }
  82. return ((_d = parts.find(({ type }) => (part == "meridiem" ? type === "dayPeriod" : type === part))) === null || _d === void 0 ? void 0 : _d.value) || null;
  83. }
  84. function getMeridiem(hour) {
  85. if (!isValidNumber(hour)) {
  86. return null;
  87. }
  88. const hourAsNumber = parseInt(hour);
  89. return hourAsNumber >= 0 && hourAsNumber <= 11 ? "AM" : "PM";
  90. }
  91. function isValidTime(value) {
  92. if (!value || value.startsWith(":") || value.endsWith(":")) {
  93. return false;
  94. }
  95. const splitValue = value.split(":");
  96. const validLength = splitValue.length > 1 && splitValue.length < 4;
  97. if (!validLength) {
  98. return false;
  99. }
  100. const [hour, minute, second] = splitValue;
  101. const hourAsNumber = parseInt(splitValue[0]);
  102. const minuteAsNumber = parseInt(splitValue[1]);
  103. const secondAsNumber = parseInt(splitValue[2]);
  104. const hourValid = isValidNumber(hour) && hourAsNumber >= 0 && hourAsNumber < 24;
  105. const minuteValid = isValidNumber(minute) && minuteAsNumber >= 0 && minuteAsNumber < 60;
  106. const secondValid = isValidNumber(second) && secondAsNumber >= 0 && secondAsNumber < 60;
  107. if ((hourValid && minuteValid && !second) || (hourValid && minuteValid && secondValid)) {
  108. return true;
  109. }
  110. }
  111. function isValidTimePart(value, part) {
  112. if (part === "meridiem") {
  113. return value === "AM" || value === "PM";
  114. }
  115. if (!isValidNumber(value)) {
  116. return false;
  117. }
  118. const valueAsNumber = Number(value);
  119. return part === "hour" ? valueAsNumber >= 0 && valueAsNumber < 24 : valueAsNumber >= 0 && valueAsNumber < 60;
  120. }
  121. function localizeTimePart({ value, part, locale, numberingSystem }) {
  122. if (!isValidTimePart(value, part)) {
  123. return;
  124. }
  125. const valueAsNumber = parseInt(value);
  126. const date = new Date(Date.UTC(0, 0, 0, part === "hour" ? valueAsNumber : part === "meridiem" ? (value === "AM" ? 0 : 12) : 0, part === "minute" ? valueAsNumber : 0, part === "second" ? valueAsNumber : 0));
  127. if (!date) {
  128. return;
  129. }
  130. const formatter = createLocaleDateTimeFormatter(locale, numberingSystem);
  131. const parts = formatter.formatToParts(date);
  132. return getLocalizedTimePart(part, parts);
  133. }
  134. function localizeTimeString({ value, locale, numberingSystem, includeSeconds = true }) {
  135. if (!isValidTime(value)) {
  136. return null;
  137. }
  138. const { hour, minute, second = "0" } = parseTimeString(value);
  139. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  140. const formatter = createLocaleDateTimeFormatter(locale, numberingSystem, includeSeconds);
  141. return (formatter === null || formatter === void 0 ? void 0 : formatter.format(dateFromTimeString)) || null;
  142. }
  143. function localizeTimeStringToParts({ value, locale, numberingSystem }) {
  144. if (!isValidTime(value)) {
  145. return null;
  146. }
  147. const { hour, minute, second = "0" } = parseTimeString(value);
  148. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  149. if (dateFromTimeString) {
  150. const formatter = createLocaleDateTimeFormatter(locale, numberingSystem);
  151. const parts = formatter.formatToParts(dateFromTimeString);
  152. return {
  153. localizedHour: getLocalizedTimePart("hour", parts),
  154. localizedHourSuffix: getLocalizedTimePart("hourSuffix", parts),
  155. localizedMinute: getLocalizedTimePart("minute", parts),
  156. localizedMinuteSuffix: getLocalizedTimePart("minuteSuffix", parts),
  157. localizedSecond: getLocalizedTimePart("second", parts),
  158. localizedSecondSuffix: getLocalizedTimePart("secondSuffix", parts),
  159. localizedMeridiem: getLocalizedTimePart("meridiem", parts)
  160. };
  161. }
  162. return null;
  163. }
  164. function getTimeParts({ value, locale, numberingSystem }) {
  165. if (!isValidTime(value)) {
  166. return null;
  167. }
  168. const { hour, minute, second = "0" } = parseTimeString(value);
  169. const dateFromTimeString = new Date(Date.UTC(0, 0, 0, parseInt(hour), parseInt(minute), parseInt(second)));
  170. if (dateFromTimeString) {
  171. const formatter = createLocaleDateTimeFormatter(locale, numberingSystem);
  172. const parts = formatter.formatToParts(dateFromTimeString);
  173. return parts;
  174. }
  175. return null;
  176. }
  177. function parseTimeString(value) {
  178. if (isValidTime(value)) {
  179. const [hour, minute, second] = value.split(":");
  180. return {
  181. hour,
  182. minute,
  183. second
  184. };
  185. }
  186. return {
  187. hour: null,
  188. minute: null,
  189. second: null
  190. };
  191. }
  192. const inputTimePickerCss = "@keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in-down{0%{opacity:0;transform:translate3D(0, -5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;transform:translate3D(0, 5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-scale{0%{opacity:0;transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;animation-fill-mode:both;animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{animation-name:in}.calcite-animate__in-down{animation-name:in-down}.calcite-animate__in-up{animation-name:in-up}.calcite-animate__in-scale{animation-name:in-scale}@media (prefers-reduced-motion: reduce){:root{--calcite-internal-duration-factor:0.01}}:root{--calcite-floating-ui-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}:host([disabled]){pointer-events:none;cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-ui-opacity-disabled)}:host{display:inline-block;-webkit-user-select:none;user-select:none}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}::slotted(input[slot=hidden-form-input]){margin:0 !important;opacity:0 !important;outline:none !important;padding:0 !important;position:absolute !important;inset:0 !important;transform:none !important;-webkit-appearance:none !important;z-index:-1 !important}";
  193. const InputTimePicker = class {
  194. constructor(hostRef) {
  195. registerInstance(this, hostRef);
  196. this.calciteInputTimePickerChange = createEvent(this, "calciteInputTimePickerChange", 7);
  197. //--------------------------------------------------------------------------
  198. //
  199. // Properties
  200. //
  201. //--------------------------------------------------------------------------
  202. /**
  203. * When `true`, the component is active.
  204. *
  205. * @deprecated Use `open` instead.
  206. */
  207. this.active = false;
  208. /** When `true`, displays the `calcite-time-picker` component. */
  209. this.open = false;
  210. /** When `true`, interaction is prevented and the component is displayed with lower opacity. */
  211. this.disabled = false;
  212. /**
  213. * When `true`, the component's value can be read, but controls are not accessible and the value cannot be modified.
  214. *
  215. * @mdn [readOnly](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly)
  216. */
  217. this.readOnly = false;
  218. /**
  219. * When `true`, the component must have a value in order for the form to submit.
  220. *
  221. * @internal
  222. */
  223. this.required = false;
  224. /** Specifies the size of the component. */
  225. this.scale = "m";
  226. /**
  227. * Determines the type of positioning to use for the overlaid content.
  228. *
  229. * Using `"absolute"` will work for most cases. The component will be positioned inside of overflowing parent containers and will affect the container's layout.
  230. *
  231. * `"fixed"` should be used to escape an overflowing parent container, or when the reference element's `position` CSS property is `"fixed"`.
  232. *
  233. */
  234. this.overlayPositioning = "absolute";
  235. /**
  236. * Determines where the popover will be positioned relative to the input.
  237. *
  238. * @see [LogicalPlacement](https://github.com/Esri/calcite-components/blob/master/src/utils/floating-ui.ts#L25)
  239. */
  240. this.placement = "auto";
  241. /** Specifies the granularity the component's `value` must adhere to (in seconds). */
  242. this.step = 60;
  243. /** The component's value in UTC (always 24-hour format). */
  244. this.value = null;
  245. /** whether the value of the input was changed as a result of user typing or not */
  246. this.internalValueChange = false;
  247. this.previousValidValue = null;
  248. this.referenceElementId = `input-time-picker-${guid()}`;
  249. //--------------------------------------------------------------------------
  250. //
  251. // State
  252. //
  253. //--------------------------------------------------------------------------
  254. this.effectiveLocale = "";
  255. //--------------------------------------------------------------------------
  256. //
  257. // Event Listeners
  258. //
  259. //--------------------------------------------------------------------------
  260. this.calciteInternalInputBlurHandler = () => {
  261. this.open = false;
  262. const shouldIncludeSeconds = this.shouldIncludeSeconds();
  263. const { effectiveLocale: locale, numberingSystem, value, calciteInputEl } = this;
  264. numberStringFormatter.numberFormatOptions = {
  265. locale,
  266. numberingSystem,
  267. useGrouping: false
  268. };
  269. const delocalizedValue = numberStringFormatter.delocalize(calciteInputEl.value);
  270. const localizedInputValue = localizeTimeString({
  271. value: delocalizedValue,
  272. includeSeconds: shouldIncludeSeconds,
  273. locale,
  274. numberingSystem
  275. });
  276. this.setInputValue(localizedInputValue ||
  277. localizeTimeString({ value, locale, numberingSystem, includeSeconds: shouldIncludeSeconds }));
  278. };
  279. this.calciteInternalInputFocusHandler = (event) => {
  280. if (!this.readOnly) {
  281. this.open = true;
  282. event.stopPropagation();
  283. }
  284. };
  285. this.calciteInputInputHandler = (event) => {
  286. const target = event.target;
  287. numberStringFormatter.numberFormatOptions = {
  288. locale: this.effectiveLocale,
  289. numberingSystem: this.numberingSystem,
  290. useGrouping: false
  291. };
  292. const delocalizedValue = numberStringFormatter.delocalize(target.value);
  293. this.setValue({ value: delocalizedValue });
  294. // only translate the numerals until blur
  295. const localizedValue = delocalizedValue
  296. .split("")
  297. .map((char) => numberKeys.includes(char)
  298. ? numberStringFormatter.numberFormatter.format(Number(char))
  299. : char)
  300. .join("");
  301. this.setInputValue(localizedValue);
  302. };
  303. this.timePickerChangeHandler = (event) => {
  304. event.stopPropagation();
  305. const target = event.target;
  306. const value = target.value;
  307. this.setValue({ value, origin: "time-picker" });
  308. };
  309. // --------------------------------------------------------------------------
  310. //
  311. // Private Methods
  312. //
  313. // --------------------------------------------------------------------------
  314. this.keyDownHandler = (event) => {
  315. const { defaultPrevented, key } = event;
  316. if (defaultPrevented) {
  317. return;
  318. }
  319. if (key === "Enter") {
  320. if (submitForm(this)) {
  321. event.preventDefault();
  322. }
  323. }
  324. if (key === "Escape" && this.open) {
  325. this.open = false;
  326. event.preventDefault();
  327. }
  328. };
  329. this.setCalcitePopoverEl = (el) => {
  330. this.popoverEl = el;
  331. };
  332. this.setCalciteInputEl = (el) => {
  333. this.calciteInputEl = el;
  334. };
  335. this.setCalciteTimePickerEl = (el) => {
  336. this.calciteTimePickerEl = el;
  337. };
  338. this.setInputValue = (newInputValue) => {
  339. if (!this.calciteInputEl) {
  340. return;
  341. }
  342. this.calciteInputEl.value = newInputValue;
  343. };
  344. this.setValue = ({ value, origin = "input" }) => {
  345. const previousValue = this.value;
  346. const newValue = formatTimeString(value);
  347. const newLocalizedValue = localizeTimeString({
  348. value: newValue,
  349. locale: this.effectiveLocale,
  350. numberingSystem: this.numberingSystem,
  351. includeSeconds: this.shouldIncludeSeconds()
  352. });
  353. this.internalValueChange = origin !== "external" && origin !== "loading";
  354. const shouldEmit = origin !== "loading" &&
  355. origin !== "external" &&
  356. ((value !== this.previousValidValue && !value) ||
  357. !!(!this.previousValidValue && newValue) ||
  358. (newValue !== this.previousValidValue && newValue));
  359. if (value) {
  360. if (shouldEmit) {
  361. this.previousValidValue = newValue;
  362. }
  363. if (newValue && newValue !== this.value) {
  364. this.value = newValue;
  365. }
  366. this.localizedValue = newLocalizedValue;
  367. }
  368. else {
  369. this.value = value;
  370. this.localizedValue = null;
  371. }
  372. if (origin === "time-picker" || origin === "external") {
  373. this.setInputValue(newLocalizedValue);
  374. }
  375. if (shouldEmit) {
  376. const changeEvent = this.calciteInputTimePickerChange.emit();
  377. if (changeEvent.defaultPrevented) {
  378. this.internalValueChange = false;
  379. this.value = previousValue;
  380. this.setInputValue(previousValue);
  381. this.previousValidValue = previousValue;
  382. }
  383. else {
  384. this.previousValidValue = newValue;
  385. }
  386. }
  387. };
  388. }
  389. activeHandler(value) {
  390. this.open = value;
  391. }
  392. openHandler(value) {
  393. this.active = value;
  394. if (this.disabled || this.readOnly) {
  395. this.open = false;
  396. return;
  397. }
  398. if (value) {
  399. this.reposition(true);
  400. }
  401. }
  402. handleDisabledAndReadOnlyChange(value) {
  403. if (!value) {
  404. this.open = false;
  405. }
  406. }
  407. localeChanged() {
  408. updateEffectiveLocale(this);
  409. }
  410. valueWatcher(newValue) {
  411. if (!this.internalValueChange) {
  412. this.setValue({ value: newValue, origin: "external" });
  413. }
  414. this.internalValueChange = false;
  415. }
  416. effectiveLocaleWatcher() {
  417. this.setInputValue(localizeTimeString({
  418. value: this.value,
  419. locale: this.effectiveLocale,
  420. numberingSystem: this.numberingSystem,
  421. includeSeconds: this.shouldIncludeSeconds()
  422. }));
  423. }
  424. clickHandler(event) {
  425. if (event.composedPath().includes(this.calciteTimePickerEl)) {
  426. return;
  427. }
  428. this.setFocus();
  429. }
  430. timePickerBlurHandler(event) {
  431. event.preventDefault();
  432. event.stopPropagation();
  433. this.open = false;
  434. }
  435. timePickerFocusHandler(event) {
  436. event.preventDefault();
  437. event.stopPropagation();
  438. if (!this.readOnly) {
  439. this.open = true;
  440. }
  441. }
  442. // --------------------------------------------------------------------------
  443. //
  444. // Public Methods
  445. //
  446. // --------------------------------------------------------------------------
  447. /** Sets focus on the component. */
  448. async setFocus() {
  449. var _a;
  450. (_a = this.calciteInputEl) === null || _a === void 0 ? void 0 : _a.setFocus();
  451. }
  452. /**
  453. * Updates the position of the component.
  454. *
  455. * @param delayed
  456. */
  457. async reposition(delayed = false) {
  458. var _a;
  459. (_a = this.popoverEl) === null || _a === void 0 ? void 0 : _a.reposition(delayed);
  460. }
  461. onLabelClick() {
  462. this.setFocus();
  463. }
  464. shouldIncludeSeconds() {
  465. return this.step < 60;
  466. }
  467. //--------------------------------------------------------------------------
  468. //
  469. // Lifecycle
  470. //
  471. //--------------------------------------------------------------------------
  472. connectedCallback() {
  473. connectLocalized(this);
  474. const { active, open } = this;
  475. if (this.value) {
  476. this.setValue({ value: isValidTime(this.value) ? this.value : undefined, origin: "loading" });
  477. }
  478. connectLabel(this);
  479. connectForm(this);
  480. if (open) {
  481. this.active = open;
  482. }
  483. else if (active) {
  484. this.open = active;
  485. }
  486. }
  487. componentDidLoad() {
  488. this.setInputValue(this.localizedValue);
  489. }
  490. disconnectedCallback() {
  491. disconnectLabel(this);
  492. disconnectForm(this);
  493. disconnectLocalized(this);
  494. }
  495. componentDidRender() {
  496. updateHostInteraction(this);
  497. }
  498. // --------------------------------------------------------------------------
  499. //
  500. // Render Methods
  501. //
  502. // --------------------------------------------------------------------------
  503. render() {
  504. const popoverId = `${this.referenceElementId}-popover`;
  505. return (h(Host, { onKeyDown: this.keyDownHandler }, h("div", { "aria-controls": popoverId, "aria-haspopup": "dialog", "aria-label": this.name, "aria-owns": popoverId, id: this.referenceElementId, role: "combobox" }, h("calcite-input", { disabled: this.disabled, icon: "clock", label: getLabelText(this), onCalciteInputInput: this.calciteInputInputHandler, onCalciteInternalInputBlur: this.calciteInternalInputBlurHandler, onCalciteInternalInputFocus: this.calciteInternalInputFocusHandler, readOnly: this.readOnly, ref: this.setCalciteInputEl, scale: this.scale, step: this.step })), h("calcite-popover", { id: popoverId, label: "Time Picker", open: this.open, overlayPositioning: this.overlayPositioning, placement: this.placement, ref: this.setCalcitePopoverEl, referenceElement: this.referenceElementId, triggerDisabled: true }, h("calcite-time-picker", { intlHour: this.intlHour, intlHourDown: this.intlHourDown, intlHourUp: this.intlHourUp, intlMeridiem: this.intlMeridiem, intlMeridiemDown: this.intlMeridiemDown, intlMeridiemUp: this.intlMeridiemUp, intlMinute: this.intlMinute, intlMinuteDown: this.intlMinuteDown, intlMinuteUp: this.intlMinuteUp, intlSecond: this.intlSecond, intlSecondDown: this.intlSecondDown, intlSecondUp: this.intlSecondUp, lang: this.effectiveLocale, numberingSystem: this.numberingSystem, onCalciteInternalTimePickerChange: this.timePickerChangeHandler, ref: this.setCalciteTimePickerEl, scale: this.scale, step: this.step, value: this.value })), h(HiddenFormInputSlot, { component: this })));
  506. }
  507. get el() { return getElement(this); }
  508. static get watchers() { return {
  509. "active": ["activeHandler"],
  510. "open": ["openHandler"],
  511. "disabled": ["handleDisabledAndReadOnlyChange"],
  512. "readOnly": ["handleDisabledAndReadOnlyChange"],
  513. "locale": ["localeChanged"],
  514. "value": ["valueWatcher"],
  515. "effectiveLocale": ["effectiveLocaleWatcher"]
  516. }; }
  517. };
  518. InputTimePicker.style = inputTimePickerCss;
  519. const CSS = {
  520. button: "button",
  521. buttonBottomLeft: "button--bottom-left",
  522. buttonBottomRight: "button--bottom-right",
  523. buttonHourDown: "button--hour-down",
  524. buttonHourUp: "button--hour-up",
  525. buttonMeridiemDown: "button--meridiem-down",
  526. buttonMeridiemUp: "button--meridiem-up",
  527. buttonMinuteDown: "button--minute-down",
  528. buttonMinuteUp: "button--minute-up",
  529. buttonSecondDown: "button--second-down",
  530. buttonSecondUp: "button--second-up",
  531. buttonTopLeft: "button--top-left",
  532. buttonTopRight: "button--top-right",
  533. column: "column",
  534. delimiter: "delimiter",
  535. hour: "hour",
  536. input: "input",
  537. meridiem: "meridiem",
  538. minute: "minute",
  539. second: "second",
  540. showMeridiem: "show-meridiem",
  541. showSecond: "show-second",
  542. "scale-s": "scale-s",
  543. "scale-m": "scale-m",
  544. "scale-l": "scale-l",
  545. timePicker: "time-picker",
  546. meridiemStart: "meridiem--start"
  547. };
  548. const TEXT = {
  549. hour: "Hour",
  550. hourDown: "Decrease hour",
  551. hourUp: "Increase hour",
  552. meridiem: "AM/PM",
  553. meridiemDown: "Decrease AM/PM",
  554. meridiemUp: "Increase AM/PM",
  555. minute: "Minute",
  556. minuteDown: "Decrease minute",
  557. minuteUp: "Increase minute",
  558. second: "Second",
  559. secondDown: "Decrease second",
  560. secondUp: "Increase second"
  561. };
  562. const timePickerCss = "@keyframes in{0%{opacity:0}100%{opacity:1}}@keyframes in-down{0%{opacity:0;transform:translate3D(0, -5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-up{0%{opacity:0;transform:translate3D(0, 5px, 0)}100%{opacity:1;transform:translate3D(0, 0, 0)}}@keyframes in-scale{0%{opacity:0;transform:scale3D(0.95, 0.95, 1)}100%{opacity:1;transform:scale3D(1, 1, 1)}}:root{--calcite-animation-timing:calc(150ms * var(--calcite-internal-duration-factor));--calcite-internal-duration-factor:var(--calcite-duration-factor, 1);--calcite-internal-animation-timing-fast:calc(100ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-medium:calc(200ms * var(--calcite-internal-duration-factor));--calcite-internal-animation-timing-slow:calc(300ms * var(--calcite-internal-duration-factor))}.calcite-animate{opacity:0;animation-fill-mode:both;animation-duration:var(--calcite-animation-timing)}.calcite-animate__in{animation-name:in}.calcite-animate__in-down{animation-name:in-down}.calcite-animate__in-up{animation-name:in-up}.calcite-animate__in-scale{animation-name:in-scale}@media (prefers-reduced-motion: reduce){:root{--calcite-internal-duration-factor:0.01}}:root{--calcite-floating-ui-transition:var(--calcite-animation-timing)}:host([hidden]){display:none}:host{display:inline-block}.time-picker{display:flex;-webkit-user-select:none;user-select:none;align-items:center;background-color:var(--calcite-ui-foreground-1);font-weight:var(--calcite-font-weight-medium);color:var(--calcite-ui-text-1);--tw-shadow:0 6px 20px -4px rgba(0, 0, 0, 0.1), 0 4px 12px -2px rgba(0, 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-border-radius)}.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-ui-foreground-1)}.time-picker .button:hover,.time-picker .button:focus{background-color:var(--calcite-ui-foreground-2);outline:2px solid transparent;outline-offset:2px}.time-picker .button:active{background-color:var(--calcite-ui-foreground-3)}.time-picker .button.top-left{border-start-start-radius:var(--calcite-border-radius)}.time-picker .button.bottom-left{border-end-start-radius:var(--calcite-border-radius)}.time-picker .button.top-right{border-start-end-radius:var(--calcite-border-radius)}.time-picker .button.bottom-right{border-end-end-radius:var(--calcite-border-radius)}.time-picker .button calcite-icon{color:var(--calcite-ui-text-3)}.time-picker .input{display:inline-flex;cursor:pointer;align-items:center;justify-content:center;background-color:var(--calcite-ui-foreground-1);font-weight:var(--calcite-font-weight-medium)}.time-picker .input:hover{box-shadow:inset 0 0 0 2px var(--calcite-ui-foreground-2)}.time-picker .input:focus,.time-picker .input:hover:focus{outline:2px solid transparent;outline-offset:2px;box-shadow:inset 0 0 0 2px var(--calcite-ui-brand)}.time-picker.scale-s{font-size:var(--calcite-font-size--1)}.time-picker.scale-s .button,.time-picker.scale-s .input{padding-inline:0.75rem;padding-block:0.25rem}.time-picker.scale-s:not(.show-meridiem) .delimiter:last-child{padding-inline-end:0.75rem}.time-picker.scale-m{font-size:var(--calcite-font-size-0)}.time-picker.scale-m .button,.time-picker.scale-m .input{padding-inline:1rem;padding-block:0.5rem}.time-picker.scale-m:not(.show-meridiem) .delimiter:last-child{padding-inline-end:1rem}.time-picker.scale-l{font-size:var(--calcite-font-size-1)}.time-picker.scale-l .button,.time-picker.scale-l .input{padding-inline:1.25rem;padding-block:0.75rem}.time-picker.scale-l:not(.show-meridiem) .delimiter:last-child{padding-inline-end:1.25rem}";
  563. function capitalize(str) {
  564. return str.charAt(0).toUpperCase() + str.slice(1);
  565. }
  566. const TimePicker = class {
  567. constructor(hostRef) {
  568. registerInstance(this, hostRef);
  569. this.calciteInternalTimePickerBlur = createEvent(this, "calciteInternalTimePickerBlur", 6);
  570. this.calciteInternalTimePickerChange = createEvent(this, "calciteInternalTimePickerChange", 6);
  571. this.calciteInternalTimePickerFocus = createEvent(this, "calciteInternalTimePickerFocus", 6);
  572. //--------------------------------------------------------------------------
  573. //
  574. // Properties
  575. //
  576. //--------------------------------------------------------------------------
  577. /**
  578. * Accessible name for the component's hour input.
  579. *
  580. * @default "Hour"
  581. */
  582. this.intlHour = TEXT.hour;
  583. /**
  584. * Accessible name for the component's hour down button.
  585. *
  586. * @default "Decrease hour"
  587. */
  588. this.intlHourDown = TEXT.hourDown;
  589. /**
  590. * Accessible name for the component's hour up button.
  591. *
  592. * @default "Increase hour"
  593. */
  594. this.intlHourUp = TEXT.hourUp;
  595. /**
  596. * Accessible name for the component's meridiem (AM/PM) input.
  597. *
  598. * @default "AM/PM"
  599. */
  600. this.intlMeridiem = TEXT.meridiem;
  601. /**
  602. * Accessible name for the component's meridiem (AM/PM) down button.
  603. *
  604. * @default "Decrease AM/PM"
  605. */
  606. this.intlMeridiemDown = TEXT.meridiemDown;
  607. /**
  608. * Accessible name for the component's meridiem (AM/PM) up button.
  609. *
  610. * @default "Increase AM/PM"
  611. */
  612. this.intlMeridiemUp = TEXT.meridiemUp;
  613. /**
  614. * Accessible name for the component's minute input.
  615. *
  616. * @default "Minute"
  617. */
  618. this.intlMinute = TEXT.minute;
  619. /**
  620. * Accessible name for the component's minute down button.
  621. *
  622. * @default "Decrease minute"
  623. */
  624. this.intlMinuteDown = TEXT.minuteDown;
  625. /**
  626. * Accessible name for the component's minute up button.
  627. *
  628. * @default "Increase minute"
  629. */
  630. this.intlMinuteUp = TEXT.minuteUp;
  631. /**
  632. * Accessible name for the component's second input.
  633. *
  634. * @default "Second"
  635. */
  636. this.intlSecond = TEXT.second;
  637. /**
  638. * Accessible name for the component's second down button.
  639. *
  640. * @default "Decrease second"
  641. */
  642. this.intlSecondDown = TEXT.secondDown;
  643. /**
  644. * Accessible name for the component's second up button.
  645. *
  646. * @default "Increase second"
  647. */
  648. this.intlSecondUp = TEXT.secondUp;
  649. /** Specifies the size of the component. */
  650. this.scale = "m";
  651. /** Specifies the granularity the `value` must adhere to (in seconds). */
  652. this.step = 60;
  653. /** The component's value in UTC (always 24-hour format). */
  654. this.value = null;
  655. // --------------------------------------------------------------------------
  656. //
  657. // State
  658. //
  659. // --------------------------------------------------------------------------
  660. this.effectiveLocale = "";
  661. this.showSecond = this.step < 60;
  662. this.decrementHour = () => {
  663. const newHour = !this.hour ? 0 : this.hour === "00" ? 23 : parseInt(this.hour) - 1;
  664. this.setValuePart("hour", newHour);
  665. };
  666. this.decrementMeridiem = () => {
  667. const newMeridiem = this.meridiem === "PM" ? "AM" : "PM";
  668. this.setValuePart("meridiem", newMeridiem);
  669. };
  670. this.decrementMinuteOrSecond = (key) => {
  671. let newValue;
  672. if (isValidNumber(this[key])) {
  673. const valueAsNumber = parseInt(this[key]);
  674. newValue = valueAsNumber === 0 ? 59 : valueAsNumber - 1;
  675. }
  676. else {
  677. newValue = 59;
  678. }
  679. this.setValuePart(key, newValue);
  680. };
  681. this.decrementMinute = () => {
  682. this.decrementMinuteOrSecond("minute");
  683. };
  684. this.decrementSecond = () => {
  685. this.decrementMinuteOrSecond("second");
  686. };
  687. this.focusHandler = (event) => {
  688. this.activeEl = event.currentTarget;
  689. };
  690. this.hourDownButtonKeyDownHandler = (event) => {
  691. if (this.buttonActivated(event)) {
  692. this.decrementHour();
  693. }
  694. };
  695. this.hourKeyDownHandler = (event) => {
  696. const { key } = event;
  697. if (numberKeys.includes(key)) {
  698. const keyAsNumber = parseInt(key);
  699. let newHour;
  700. if (isValidNumber(this.hour)) {
  701. switch (this.hourCycle) {
  702. case "12":
  703. newHour =
  704. this.hour === "01" && keyAsNumber >= 0 && keyAsNumber <= 2
  705. ? `1${keyAsNumber}`
  706. : keyAsNumber;
  707. break;
  708. case "24":
  709. if (this.hour === "01") {
  710. newHour = `1${keyAsNumber}`;
  711. }
  712. else if (this.hour === "02" && keyAsNumber >= 0 && keyAsNumber <= 3) {
  713. newHour = `2${keyAsNumber}`;
  714. }
  715. else {
  716. newHour = keyAsNumber;
  717. }
  718. break;
  719. }
  720. }
  721. else {
  722. newHour = keyAsNumber;
  723. }
  724. this.setValuePart("hour", newHour);
  725. }
  726. else {
  727. switch (key) {
  728. case "Backspace":
  729. case "Delete":
  730. this.setValuePart("hour", null);
  731. break;
  732. case "ArrowDown":
  733. event.preventDefault();
  734. this.decrementHour();
  735. break;
  736. case "ArrowUp":
  737. event.preventDefault();
  738. this.incrementHour();
  739. break;
  740. case " ":
  741. event.preventDefault();
  742. break;
  743. }
  744. }
  745. };
  746. this.hourUpButtonKeyDownHandler = (event) => {
  747. if (this.buttonActivated(event)) {
  748. this.incrementHour();
  749. }
  750. };
  751. this.incrementMeridiem = () => {
  752. const newMeridiem = this.meridiem === "AM" ? "PM" : "AM";
  753. this.setValuePart("meridiem", newMeridiem);
  754. };
  755. this.incrementHour = () => {
  756. const newHour = isValidNumber(this.hour)
  757. ? this.hour === "23"
  758. ? 0
  759. : parseInt(this.hour) + 1
  760. : 1;
  761. this.setValuePart("hour", newHour);
  762. };
  763. this.incrementMinuteOrSecond = (key) => {
  764. const newValue = isValidNumber(this[key])
  765. ? this[key] === "59"
  766. ? 0
  767. : parseInt(this[key]) + 1
  768. : 0;
  769. this.setValuePart(key, newValue);
  770. };
  771. this.incrementMinute = () => {
  772. this.incrementMinuteOrSecond("minute");
  773. };
  774. this.incrementSecond = () => {
  775. this.incrementMinuteOrSecond("second");
  776. };
  777. this.meridiemDownButtonKeyDownHandler = (event) => {
  778. if (this.buttonActivated(event)) {
  779. this.decrementMeridiem();
  780. }
  781. };
  782. this.meridiemKeyDownHandler = (event) => {
  783. switch (event.key) {
  784. case "a":
  785. this.setValuePart("meridiem", "AM");
  786. break;
  787. case "p":
  788. this.setValuePart("meridiem", "PM");
  789. break;
  790. case "Backspace":
  791. case "Delete":
  792. this.setValuePart("meridiem", null);
  793. break;
  794. case "ArrowUp":
  795. event.preventDefault();
  796. this.incrementMeridiem();
  797. break;
  798. case "ArrowDown":
  799. event.preventDefault();
  800. this.decrementMeridiem();
  801. break;
  802. case " ":
  803. event.preventDefault();
  804. break;
  805. }
  806. };
  807. this.meridiemUpButtonKeyDownHandler = (event) => {
  808. if (this.buttonActivated(event)) {
  809. this.incrementMeridiem();
  810. }
  811. };
  812. this.minuteDownButtonKeyDownHandler = (event) => {
  813. if (this.buttonActivated(event)) {
  814. this.decrementMinute();
  815. }
  816. };
  817. this.minuteKeyDownHandler = (event) => {
  818. const { key } = event;
  819. if (numberKeys.includes(key)) {
  820. const keyAsNumber = parseInt(key);
  821. let newMinute;
  822. if (isValidNumber(this.minute) && this.minute.startsWith("0")) {
  823. const minuteAsNumber = parseInt(this.minute);
  824. newMinute =
  825. minuteAsNumber > maxTenthForMinuteAndSecond
  826. ? keyAsNumber
  827. : `${minuteAsNumber}${keyAsNumber}`;
  828. }
  829. else {
  830. newMinute = keyAsNumber;
  831. }
  832. this.setValuePart("minute", newMinute);
  833. }
  834. else {
  835. switch (key) {
  836. case "Backspace":
  837. case "Delete":
  838. this.setValuePart("minute", null);
  839. break;
  840. case "ArrowDown":
  841. event.preventDefault();
  842. this.decrementMinute();
  843. break;
  844. case "ArrowUp":
  845. event.preventDefault();
  846. this.incrementMinute();
  847. break;
  848. case " ":
  849. event.preventDefault();
  850. break;
  851. }
  852. }
  853. };
  854. this.minuteUpButtonKeyDownHandler = (event) => {
  855. if (this.buttonActivated(event)) {
  856. this.incrementMinute();
  857. }
  858. };
  859. this.secondDownButtonKeyDownHandler = (event) => {
  860. if (this.buttonActivated(event)) {
  861. this.decrementSecond();
  862. }
  863. };
  864. this.secondKeyDownHandler = (event) => {
  865. const { key } = event;
  866. if (numberKeys.includes(key)) {
  867. const keyAsNumber = parseInt(key);
  868. let newSecond;
  869. if (isValidNumber(this.second) && this.second.startsWith("0")) {
  870. const secondAsNumber = parseInt(this.second);
  871. newSecond =
  872. secondAsNumber > maxTenthForMinuteAndSecond
  873. ? keyAsNumber
  874. : `${secondAsNumber}${keyAsNumber}`;
  875. }
  876. else {
  877. newSecond = keyAsNumber;
  878. }
  879. this.setValuePart("second", newSecond);
  880. }
  881. else {
  882. switch (key) {
  883. case "Backspace":
  884. case "Delete":
  885. this.setValuePart("second", null);
  886. break;
  887. case "ArrowDown":
  888. event.preventDefault();
  889. this.decrementSecond();
  890. break;
  891. case "ArrowUp":
  892. event.preventDefault();
  893. this.incrementSecond();
  894. break;
  895. case " ":
  896. event.preventDefault();
  897. break;
  898. }
  899. }
  900. };
  901. this.secondUpButtonKeyDownHandler = (event) => {
  902. if (this.buttonActivated(event)) {
  903. this.incrementSecond();
  904. }
  905. };
  906. this.setHourEl = (el) => (this.hourEl = el);
  907. this.setMeridiemEl = (el) => (this.meridiemEl = el);
  908. this.setMinuteEl = (el) => (this.minuteEl = el);
  909. this.setSecondEl = (el) => (this.secondEl = el);
  910. this.setValue = (value, emit = true) => {
  911. if (isValidTime(value)) {
  912. const { hour, minute, second } = parseTimeString(value);
  913. const { effectiveLocale: locale, numberingSystem } = this;
  914. const { localizedHour, localizedHourSuffix, localizedMinute, localizedMinuteSuffix, localizedSecond, localizedSecondSuffix, localizedMeridiem } = localizeTimeStringToParts({ value, locale, numberingSystem });
  915. this.localizedHour = localizedHour;
  916. this.localizedHourSuffix = localizedHourSuffix;
  917. this.localizedMinute = localizedMinute;
  918. this.localizedMinuteSuffix = localizedMinuteSuffix;
  919. this.localizedSecond = localizedSecond;
  920. this.localizedSecondSuffix = localizedSecondSuffix;
  921. this.hour = hour;
  922. this.minute = minute;
  923. this.second = second;
  924. if (localizedMeridiem) {
  925. this.localizedMeridiem = localizedMeridiem;
  926. this.meridiem = getMeridiem(this.hour);
  927. const formatParts = getTimeParts({ value, locale, numberingSystem });
  928. this.meridiemOrder = this.getMeridiemOrder(formatParts);
  929. }
  930. }
  931. else {
  932. this.hour = null;
  933. this.localizedHour = null;
  934. this.localizedHourSuffix = null;
  935. this.localizedMeridiem = null;
  936. this.localizedMinute = null;
  937. this.localizedMinuteSuffix = null;
  938. this.localizedSecond = null;
  939. this.localizedSecondSuffix = null;
  940. this.meridiem = null;
  941. this.minute = null;
  942. this.second = null;
  943. this.value = null;
  944. }
  945. if (emit) {
  946. this.calciteInternalTimePickerChange.emit();
  947. }
  948. };
  949. this.setValuePart = (key, value, emit = true) => {
  950. var _a;
  951. const { effectiveLocale: locale, numberingSystem } = this;
  952. if (key === "meridiem") {
  953. this.meridiem = value;
  954. if (isValidNumber(this.hour)) {
  955. const hourAsNumber = parseInt(this.hour);
  956. switch (value) {
  957. case "AM":
  958. if (hourAsNumber >= 12) {
  959. this.hour = formatTimePart(hourAsNumber - 12);
  960. }
  961. break;
  962. case "PM":
  963. if (hourAsNumber < 12) {
  964. this.hour = formatTimePart(hourAsNumber + 12);
  965. }
  966. break;
  967. }
  968. this.localizedHour = localizeTimePart({
  969. value: this.hour,
  970. part: "hour",
  971. locale,
  972. numberingSystem
  973. });
  974. }
  975. }
  976. else {
  977. this[key] = typeof value === "number" ? formatTimePart(value) : value;
  978. this[`localized${capitalize(key)}`] = localizeTimePart({
  979. value: this[key],
  980. part: key,
  981. locale,
  982. numberingSystem
  983. });
  984. }
  985. if (this.hour && this.minute) {
  986. const showSeconds = this.second && this.showSecond;
  987. this.value = `${this.hour}:${this.minute}:${showSeconds ? this.second : "00"}`;
  988. }
  989. else {
  990. this.value = null;
  991. }
  992. this.localizedMeridiem = this.value
  993. ? ((_a = localizeTimeStringToParts({ value: this.value, locale, numberingSystem })) === null || _a === void 0 ? void 0 : _a.localizedMeridiem) || null
  994. : localizeTimePart({ value: this.meridiem, part: "meridiem", locale, numberingSystem });
  995. if (emit) {
  996. this.calciteInternalTimePickerChange.emit();
  997. }
  998. };
  999. }
  1000. localeChanged() {
  1001. updateEffectiveLocale(this);
  1002. }
  1003. valueWatcher(newValue) {
  1004. this.setValue(newValue, false);
  1005. }
  1006. effectiveLocaleWatcher() {
  1007. this.updateLocale();
  1008. }
  1009. //--------------------------------------------------------------------------
  1010. //
  1011. // Event Listeners
  1012. //
  1013. //--------------------------------------------------------------------------
  1014. hostBlurHandler() {
  1015. this.calciteInternalTimePickerBlur.emit();
  1016. }
  1017. hostFocusHandler() {
  1018. this.calciteInternalTimePickerFocus.emit();
  1019. }
  1020. keyDownHandler(event) {
  1021. const { defaultPrevented, key } = event;
  1022. if (defaultPrevented) {
  1023. return;
  1024. }
  1025. switch (this.activeEl) {
  1026. case this.hourEl:
  1027. if (key === "ArrowRight") {
  1028. this.setFocus("minute");
  1029. event.preventDefault();
  1030. }
  1031. break;
  1032. case this.minuteEl:
  1033. switch (key) {
  1034. case "ArrowLeft":
  1035. this.setFocus("hour");
  1036. event.preventDefault();
  1037. break;
  1038. case "ArrowRight":
  1039. if (this.step !== 60) {
  1040. this.setFocus("second");
  1041. event.preventDefault();
  1042. }
  1043. else if (this.hourCycle === "12") {
  1044. this.setFocus("meridiem");
  1045. event.preventDefault();
  1046. }
  1047. break;
  1048. }
  1049. break;
  1050. case this.secondEl:
  1051. switch (key) {
  1052. case "ArrowLeft":
  1053. this.setFocus("minute");
  1054. event.preventDefault();
  1055. break;
  1056. case "ArrowRight":
  1057. if (this.hourCycle === "12") {
  1058. this.setFocus("meridiem");
  1059. event.preventDefault();
  1060. }
  1061. break;
  1062. }
  1063. break;
  1064. case this.meridiemEl:
  1065. switch (key) {
  1066. case "ArrowLeft":
  1067. if (this.step !== 60) {
  1068. this.setFocus("second");
  1069. event.preventDefault();
  1070. }
  1071. else {
  1072. this.setFocus("minute");
  1073. event.preventDefault();
  1074. }
  1075. break;
  1076. }
  1077. break;
  1078. }
  1079. }
  1080. //--------------------------------------------------------------------------
  1081. //
  1082. // Public Methods
  1083. //
  1084. //--------------------------------------------------------------------------
  1085. /**
  1086. * Sets focus on the component.
  1087. *
  1088. * @param target
  1089. */
  1090. async setFocus(target) {
  1091. var _a;
  1092. (_a = this[`${target || "hour"}El`]) === null || _a === void 0 ? void 0 : _a.focus();
  1093. }
  1094. // --------------------------------------------------------------------------
  1095. //
  1096. // Private Methods
  1097. //
  1098. // --------------------------------------------------------------------------
  1099. buttonActivated(event) {
  1100. const { key } = event;
  1101. if (key === " ") {
  1102. event.preventDefault();
  1103. }
  1104. return isActivationKey(key);
  1105. }
  1106. getMeridiemOrder(formatParts) {
  1107. const locale = this.effectiveLocale;
  1108. const isRTLKind = locale === "ar" || locale === "he";
  1109. if (formatParts && !isRTLKind) {
  1110. const index = formatParts.findIndex((parts) => {
  1111. return parts.value === this.localizedMeridiem;
  1112. });
  1113. return index;
  1114. }
  1115. return 0;
  1116. }
  1117. updateLocale() {
  1118. this.hourCycle = getLocaleHourCycle(this.effectiveLocale, this.numberingSystem);
  1119. this.setValue(this.value, false);
  1120. }
  1121. // --------------------------------------------------------------------------
  1122. //
  1123. // Lifecycle
  1124. //
  1125. // --------------------------------------------------------------------------
  1126. connectedCallback() {
  1127. connectLocalized(this);
  1128. this.updateLocale();
  1129. this.meridiemOrder = this.getMeridiemOrder(getTimeParts({
  1130. value: "0:00:00",
  1131. locale: this.effectiveLocale,
  1132. numberingSystem: this.numberingSystem
  1133. }));
  1134. }
  1135. disconnectedCallback() {
  1136. disconnectLocalized(this);
  1137. }
  1138. // --------------------------------------------------------------------------
  1139. //
  1140. // Render Methods
  1141. //
  1142. // --------------------------------------------------------------------------
  1143. render() {
  1144. const hourIsNumber = isValidNumber(this.hour);
  1145. const iconScale = this.scale === "s" || this.scale === "m" ? "s" : "m";
  1146. const minuteIsNumber = isValidNumber(this.minute);
  1147. const secondIsNumber = isValidNumber(this.second);
  1148. const showMeridiem = this.hourCycle === "12";
  1149. return (h("div", { class: {
  1150. [CSS.timePicker]: true,
  1151. [CSS.showMeridiem]: showMeridiem,
  1152. [CSS.showSecond]: this.showSecond,
  1153. [CSS[`scale-${this.scale}`]]: true
  1154. }, dir: "ltr" }, h("div", { class: CSS.column, role: "group" }, h("span", { "aria-label": this.intlHourUp, class: {
  1155. [CSS.button]: true,
  1156. [CSS.buttonHourUp]: true,
  1157. [CSS.buttonTopLeft]: true
  1158. }, onClick: this.incrementHour, onKeyDown: this.hourUpButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-up", scale: iconScale })), h("span", { "aria-label": this.intlHour, "aria-valuemax": "23", "aria-valuemin": "1", "aria-valuenow": (hourIsNumber && parseInt(this.hour)) || "0", "aria-valuetext": this.hour, class: {
  1159. [CSS.input]: true,
  1160. [CSS.hour]: true
  1161. }, onFocus: this.focusHandler, onKeyDown: this.hourKeyDownHandler, ref: this.setHourEl, role: "spinbutton", tabIndex: 0 }, this.localizedHour || "--"), h("span", { "aria-label": this.intlHourDown, class: {
  1162. [CSS.button]: true,
  1163. [CSS.buttonHourDown]: true,
  1164. [CSS.buttonBottomLeft]: true
  1165. }, onClick: this.decrementHour, onKeyDown: this.hourDownButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-down", scale: iconScale }))), h("span", { class: CSS.delimiter }, this.localizedHourSuffix), h("div", { class: CSS.column, role: "group" }, h("span", { "aria-label": this.intlMinuteUp, class: {
  1166. [CSS.button]: true,
  1167. [CSS.buttonMinuteUp]: true
  1168. }, onClick: this.incrementMinute, onKeyDown: this.minuteUpButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-up", scale: iconScale })), h("span", { "aria-label": this.intlMinute, "aria-valuemax": "12", "aria-valuemin": "1", "aria-valuenow": (minuteIsNumber && parseInt(this.minute)) || "0", "aria-valuetext": this.minute, class: {
  1169. [CSS.input]: true,
  1170. [CSS.minute]: true
  1171. }, onFocus: this.focusHandler, onKeyDown: this.minuteKeyDownHandler, ref: this.setMinuteEl, role: "spinbutton", tabIndex: 0 }, this.localizedMinute || "--"), h("span", { "aria-label": this.intlMinuteDown, class: {
  1172. [CSS.button]: true,
  1173. [CSS.buttonMinuteDown]: true
  1174. }, onClick: this.decrementMinute, onKeyDown: this.minuteDownButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-down", scale: iconScale }))), this.showSecond && h("span", { class: CSS.delimiter }, this.localizedMinuteSuffix), this.showSecond && (h("div", { class: CSS.column, role: "group" }, h("span", { "aria-label": this.intlSecondUp, class: {
  1175. [CSS.button]: true,
  1176. [CSS.buttonSecondUp]: true
  1177. }, onClick: this.incrementSecond, onKeyDown: this.secondUpButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-up", scale: iconScale })), h("span", { "aria-label": this.intlSecond, "aria-valuemax": "59", "aria-valuemin": "0", "aria-valuenow": (secondIsNumber && parseInt(this.second)) || "0", "aria-valuetext": this.second, class: {
  1178. [CSS.input]: true,
  1179. [CSS.second]: true
  1180. }, onFocus: this.focusHandler, onKeyDown: this.secondKeyDownHandler, ref: this.setSecondEl, role: "spinbutton", tabIndex: 0 }, this.localizedSecond || "--"), h("span", { "aria-label": this.intlSecondDown, class: {
  1181. [CSS.button]: true,
  1182. [CSS.buttonSecondDown]: true
  1183. }, onClick: this.decrementSecond, onKeyDown: this.secondDownButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-down", scale: iconScale })))), this.localizedSecondSuffix && (h("span", { class: CSS.delimiter }, this.localizedSecondSuffix)), showMeridiem && (h("div", { class: {
  1184. [CSS.column]: true,
  1185. [CSS.meridiemStart]: this.meridiemOrder === 0
  1186. }, role: "group" }, h("span", { "aria-label": this.intlMeridiemUp, class: {
  1187. [CSS.button]: true,
  1188. [CSS.buttonMeridiemUp]: true,
  1189. [CSS.buttonTopRight]: true
  1190. }, onClick: this.incrementMeridiem, onKeyDown: this.meridiemUpButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-up", scale: iconScale })), h("span", { "aria-label": this.intlMeridiem, "aria-valuemax": "2", "aria-valuemin": "1", "aria-valuenow": (this.meridiem === "PM" && "2") || "1", "aria-valuetext": this.meridiem, class: {
  1191. [CSS.input]: true,
  1192. [CSS.meridiem]: true
  1193. }, onFocus: this.focusHandler, onKeyDown: this.meridiemKeyDownHandler, ref: this.setMeridiemEl, role: "spinbutton", tabIndex: 0 }, this.localizedMeridiem || "--"), h("span", { "aria-label": this.intlMeridiemDown, class: {
  1194. [CSS.button]: true,
  1195. [CSS.buttonMeridiemDown]: true,
  1196. [CSS.buttonBottomRight]: true
  1197. }, onClick: this.decrementMeridiem, onKeyDown: this.meridiemDownButtonKeyDownHandler, role: "button", tabIndex: -1 }, h("calcite-icon", { icon: "chevron-down", scale: iconScale }))))));
  1198. }
  1199. get el() { return getElement(this); }
  1200. static get watchers() { return {
  1201. "locale": ["localeChanged"],
  1202. "value": ["valueWatcher"],
  1203. "effectiveLocale": ["effectiveLocaleWatcher"]
  1204. }; }
  1205. };
  1206. TimePicker.style = timePickerCss;
  1207. export { InputTimePicker as calcite_input_time_picker, TimePicker as calcite_time_picker };