@gravionlabs/helix-ui 22.2.8 → 22.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import * as i1 from "@angular/cdk/accordion";
2
2
  import { CdkAccordion, CdkAccordionItem } from "@angular/cdk/accordion";
3
3
  import { DOCUMENT, NgComponentOutlet, NgStyle, NgTemplateOutlet, isPlatformBrowser } from "@angular/common";
4
4
  import * as i0 from "@angular/core";
5
- import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injectable, InjectionToken, Injector, PLATFORM_ID, TemplateRef, afterEveryRender, afterNextRender, booleanAttribute, computed, contentChild, contentChildren, effect, forwardRef, inject, input, isDevMode, makeEnvironmentProviders, model, numberAttribute, output, provideEnvironmentInitializer, signal, untracked, viewChild } from "@angular/core";
5
+ import { ChangeDetectionStrategy, Component, DestroyRef, Directive, ElementRef, Injectable, InjectionToken, Injector, PLATFORM_ID, TemplateRef, afterEveryRender, afterNextRender, booleanAttribute, computed, contentChild, contentChildren, effect, forwardRef, inject, input, isDevMode, makeEnvironmentProviders, model, numberAttribute, output, provideEnvironmentInitializer, signal, untracked, viewChild, viewChildren } from "@angular/core";
6
6
  import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
7
7
  import { CdkConnectedOverlay, CdkOverlayOrigin, Overlay } from "@angular/cdk/overlay";
8
8
  import { NG_VALUE_ACCESSOR, NgControl } from "@angular/forms";
@@ -4441,9 +4441,14 @@ i0.ɵɵngDeclareClassMetadata({
4441
4441
  }]
4442
4442
  }
4443
4443
  });
4444
+ const HX_SELECT_OVERLAY_CLASS = "hx-select-overlay";
4445
+ function isInSelectOverlay(target) {
4446
+ return target instanceof Element && target.closest(`.hx-select-overlay`) !== null;
4447
+ }
4444
4448
  var HxSelect = class HxSelect {
4445
4449
  #host = inject(ElementRef);
4446
4450
  #injector = inject(Injector);
4451
+ overlayClass = HX_SELECT_OVERLAY_CLASS;
4447
4452
  options = input([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
4448
4453
  optionLabel = input("label", ...ngDevMode ? [{ debugName: "optionLabel" }] : /* istanbul ignore next */ []);
4449
4454
  optionValue = input("value", ...ngDevMode ? [{ debugName: "optionValue" }] : /* istanbul ignore next */ []);
@@ -4470,6 +4475,7 @@ var HxSelect = class HxSelect {
4470
4475
  inputId = input(...ngDevMode ? [void 0, { debugName: "inputId" }] : /* istanbul ignore next */ []);
4471
4476
  ariaLabel = input(...ngDevMode ? [void 0, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
4472
4477
  ariaLabelledby = input(...ngDevMode ? [void 0, { debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
4478
+ ariaDescribedby = input(...ngDevMode ? [void 0, { debugName: "ariaDescribedby" }] : /* istanbul ignore next */ []);
4473
4479
  compareWith = input(compareValues$1, ...ngDevMode ? [{ debugName: "compareWith" }] : /* istanbul ignore next */ []);
4474
4480
  value = model(null, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
4475
4481
  disabled = input(false, {
@@ -4750,6 +4756,13 @@ var HxSelect = class HxSelect {
4750
4756
  isRequired: false,
4751
4757
  transformFunction: null
4752
4758
  },
4759
+ ariaDescribedby: {
4760
+ classPropertyName: "ariaDescribedby",
4761
+ publicName: "ariaDescribedby",
4762
+ isSignal: true,
4763
+ isRequired: false,
4764
+ transformFunction: null
4765
+ },
4753
4766
  compareWith: {
4754
4767
  classPropertyName: "compareWith",
4755
4768
  publicName: "compareWith",
@@ -4827,7 +4840,7 @@ var HxSelect = class HxSelect {
4827
4840
  }
4828
4841
  ],
4829
4842
  ngImport: i0,
4830
- template: "<button\n #trigger\n type=\"button\"\n class=\"hx-select-trigger\"\n role=\"combobox\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"inputId() ?? null\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n <span class=\"hx-select-label\" [class.hx-select-placeholder]=\"!selected()\">{{\n selected()?.label ?? placeholder()\n }}</span>\n <span class=\"hx-select-chevron\" aria-hidden=\"true\"></span>\n</button>\n@if (canClear()) {\n <button type=\"button\" class=\"hx-select-clear\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\n <span class=\"hx-select-clear-icon\" aria-hidden=\"true\"></span>\n </button>\n}\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-select-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n>\n <div class=\"hx-select-panel\">\n @if (filter()) {\n <div class=\"hx-select-header\">\n <input\n #filterField\n type=\"text\"\n class=\"hx-select-filter\"\n autocomplete=\"off\"\n [attr.aria-label]=\"filterPlaceholder()\"\n [attr.aria-controls]=\"panelId\"\n [placeholder]=\"filterPlaceholder()\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n }\n <div\n cdkListbox\n class=\"hx-select-list\"\n [id]=\"panelId\"\n [cdkListboxValue]=\"selectedValues()\"\n [cdkListboxUseActiveDescendant]=\"true\"\n [cdkListboxCompareWith]=\"compareWith()\"\n [attr.aria-label]=\"ariaLabel() ?? placeholder() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (cdkListboxValueChange)=\"onSelect($event)\"\n >\n @for (item of visibleItems(); track item) {\n <div\n class=\"hx-select-option\"\n [cdkOption]=\"item.value\"\n [cdkOptionDisabled]=\"item.disabled\"\n [cdkOptionTypeaheadLabel]=\"item.label\"\n >\n <span class=\"hx-select-check\" aria-hidden=\"true\"></span>\n <span>{{ item.label }}</span>\n </div>\n } @empty {\n <div class=\"hx-select-empty\">{{ query().trim() ? emptyFilterMessage() : emptyMessage() }}</div>\n }\n </div>\n @if (filter()) {\n <span class=\"hx-select-sr-only\" aria-live=\"polite\">{{ resultsLabel() }}</span>\n }\n </div>\n</ng-template>\n",
4843
+ template: "<button\n #trigger\n type=\"button\"\n class=\"hx-select-trigger\"\n role=\"combobox\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"inputId() ?? null\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-describedby]=\"ariaDescribedby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n <span class=\"hx-select-label\" [class.hx-select-placeholder]=\"!selected()\">{{\n selected()?.label ?? placeholder()\n }}</span>\n <span class=\"hx-select-chevron\" aria-hidden=\"true\"></span>\n</button>\n@if (canClear()) {\n <button type=\"button\" class=\"hx-select-clear\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\n <span class=\"hx-select-clear-icon\" aria-hidden=\"true\"></span>\n </button>\n}\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayPanelClass]=\"overlayClass\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n>\n <div class=\"hx-select-panel\">\n @if (filter()) {\n <div class=\"hx-select-header\">\n <input\n #filterField\n type=\"text\"\n class=\"hx-select-filter\"\n autocomplete=\"off\"\n [attr.aria-label]=\"filterPlaceholder()\"\n [attr.aria-controls]=\"panelId\"\n [placeholder]=\"filterPlaceholder()\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n }\n <div\n cdkListbox\n class=\"hx-select-list\"\n [id]=\"panelId\"\n [cdkListboxValue]=\"selectedValues()\"\n [cdkListboxUseActiveDescendant]=\"true\"\n [cdkListboxCompareWith]=\"compareWith()\"\n [attr.aria-label]=\"ariaLabel() ?? placeholder() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (cdkListboxValueChange)=\"onSelect($event)\"\n >\n @for (item of visibleItems(); track item) {\n <div\n class=\"hx-select-option\"\n [cdkOption]=\"item.value\"\n [cdkOptionDisabled]=\"item.disabled\"\n [cdkOptionTypeaheadLabel]=\"item.label\"\n >\n <span class=\"hx-select-check\" aria-hidden=\"true\"></span>\n <span>{{ item.label }}</span>\n </div>\n } @empty {\n <div class=\"hx-select-empty\">{{ query().trim() ? emptyFilterMessage() : emptyMessage() }}</div>\n }\n </div>\n @if (filter()) {\n <span class=\"hx-select-sr-only\" aria-live=\"polite\">{{ resultsLabel() }}</span>\n }\n </div>\n</ng-template>\n",
4831
4844
  dependencies: [
4832
4845
  {
4833
4846
  kind: "directive",
@@ -4946,7 +4959,7 @@ i0.ɵɵngDeclareClassMetadata({
4946
4959
  "[class.hx-filled]": "!!selected()",
4947
4960
  "(focusout)": "onFocusOut($event)"
4948
4961
  },
4949
- template: "<button\n #trigger\n type=\"button\"\n class=\"hx-select-trigger\"\n role=\"combobox\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"inputId() ?? null\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n <span class=\"hx-select-label\" [class.hx-select-placeholder]=\"!selected()\">{{\n selected()?.label ?? placeholder()\n }}</span>\n <span class=\"hx-select-chevron\" aria-hidden=\"true\"></span>\n</button>\n@if (canClear()) {\n <button type=\"button\" class=\"hx-select-clear\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\n <span class=\"hx-select-clear-icon\" aria-hidden=\"true\"></span>\n </button>\n}\n\n<ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-select-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n>\n <div class=\"hx-select-panel\">\n @if (filter()) {\n <div class=\"hx-select-header\">\n <input\n #filterField\n type=\"text\"\n class=\"hx-select-filter\"\n autocomplete=\"off\"\n [attr.aria-label]=\"filterPlaceholder()\"\n [attr.aria-controls]=\"panelId\"\n [placeholder]=\"filterPlaceholder()\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n }\n <div\n cdkListbox\n class=\"hx-select-list\"\n [id]=\"panelId\"\n [cdkListboxValue]=\"selectedValues()\"\n [cdkListboxUseActiveDescendant]=\"true\"\n [cdkListboxCompareWith]=\"compareWith()\"\n [attr.aria-label]=\"ariaLabel() ?? placeholder() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (cdkListboxValueChange)=\"onSelect($event)\"\n >\n @for (item of visibleItems(); track item) {\n <div\n class=\"hx-select-option\"\n [cdkOption]=\"item.value\"\n [cdkOptionDisabled]=\"item.disabled\"\n [cdkOptionTypeaheadLabel]=\"item.label\"\n >\n <span class=\"hx-select-check\" aria-hidden=\"true\"></span>\n <span>{{ item.label }}</span>\n </div>\n } @empty {\n <div class=\"hx-select-empty\">{{ query().trim() ? emptyFilterMessage() : emptyMessage() }}</div>\n }\n </div>\n @if (filter()) {\n <span class=\"hx-select-sr-only\" aria-live=\"polite\">{{ resultsLabel() }}</span>\n }\n </div>\n</ng-template>\n"
4962
+ template: "<button\n #trigger\n type=\"button\"\n class=\"hx-select-trigger\"\n role=\"combobox\"\n cdkOverlayOrigin\n #origin=\"cdkOverlayOrigin\"\n aria-haspopup=\"listbox\"\n [attr.id]=\"inputId() ?? null\"\n [disabled]=\"isDisabled()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? panelId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-describedby]=\"ariaDescribedby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"toggle()\"\n (keydown)=\"onTriggerKeydown($event)\"\n>\n <span class=\"hx-select-label\" [class.hx-select-placeholder]=\"!selected()\">{{\n selected()?.label ?? placeholder()\n }}</span>\n <span class=\"hx-select-chevron\" aria-hidden=\"true\"></span>\n</button>\n@if (canClear()) {\n <button type=\"button\" class=\"hx-select-clear\" aria-label=\"Clear selection\" (click)=\"clear($event)\">\n <span class=\"hx-select-clear-icon\" aria-hidden=\"true\"></span>\n </button>\n}\n\n<ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayPanelClass]=\"overlayClass\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayMinWidth]=\"panelWidth()\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n>\n <div class=\"hx-select-panel\">\n @if (filter()) {\n <div class=\"hx-select-header\">\n <input\n #filterField\n type=\"text\"\n class=\"hx-select-filter\"\n autocomplete=\"off\"\n [attr.aria-label]=\"filterPlaceholder()\"\n [attr.aria-controls]=\"panelId\"\n [placeholder]=\"filterPlaceholder()\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n (keydown)=\"onFilterKeydown($event)\"\n />\n </div>\n }\n <div\n cdkListbox\n class=\"hx-select-list\"\n [id]=\"panelId\"\n [cdkListboxValue]=\"selectedValues()\"\n [cdkListboxUseActiveDescendant]=\"true\"\n [cdkListboxCompareWith]=\"compareWith()\"\n [attr.aria-label]=\"ariaLabel() ?? placeholder() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (cdkListboxValueChange)=\"onSelect($event)\"\n >\n @for (item of visibleItems(); track item) {\n <div\n class=\"hx-select-option\"\n [cdkOption]=\"item.value\"\n [cdkOptionDisabled]=\"item.disabled\"\n [cdkOptionTypeaheadLabel]=\"item.label\"\n >\n <span class=\"hx-select-check\" aria-hidden=\"true\"></span>\n <span>{{ item.label }}</span>\n </div>\n } @empty {\n <div class=\"hx-select-empty\">{{ query().trim() ? emptyFilterMessage() : emptyMessage() }}</div>\n }\n </div>\n @if (filter()) {\n <span class=\"hx-select-sr-only\" aria-live=\"polite\">{{ resultsLabel() }}</span>\n }\n </div>\n</ng-template>\n"
4950
4963
  }]
4951
4964
  }],
4952
4965
  propDecorators: {
@@ -5086,6 +5099,14 @@ i0.ɵɵngDeclareClassMetadata({
5086
5099
  required: false
5087
5100
  }]
5088
5101
  }],
5102
+ ariaDescribedby: [{
5103
+ type: i0.Input,
5104
+ args: [{
5105
+ isSignal: true,
5106
+ alias: "ariaDescribedby",
5107
+ required: false
5108
+ }]
5109
+ }],
5089
5110
  compareWith: [{
5090
5111
  type: i0.Input,
5091
5112
  args: [{
@@ -5393,6 +5414,7 @@ var HxPaginator = class HxPaginator {
5393
5414
  "inputId",
5394
5415
  "ariaLabel",
5395
5416
  "ariaLabelledby",
5417
+ "ariaDescribedby",
5396
5418
  "compareWith",
5397
5419
  "value",
5398
5420
  "disabled",
@@ -7413,6 +7435,90 @@ function monthCells(year, month, firstDayOfWeek) {
7413
7435
  for (let i = 0; i < cells.length; i += 7) rows.push(cells.slice(i, i + 7));
7414
7436
  return rows;
7415
7437
  }
7438
+ function hxResolvePreset(preset, context, fit) {
7439
+ const from = fit(preset.from(context), "from");
7440
+ const to = fit(preset.to(context), "to");
7441
+ if (from === void 0 || to === void 0) return void 0;
7442
+ return from && to && to < from ? {
7443
+ from: to,
7444
+ to: from
7445
+ } : {
7446
+ from,
7447
+ to
7448
+ };
7449
+ }
7450
+ const ENGLISH = {
7451
+ last15Minutes: "Last 15 minutes",
7452
+ last1Hour: "Last 1 hour",
7453
+ last6Hours: "Last 6 hours",
7454
+ last24Hours: "Last 24 hours",
7455
+ last7Days: "Last 7 days",
7456
+ last30Days: "Last 30 days",
7457
+ today: "Today",
7458
+ yesterday: "Yesterday",
7459
+ thisWeek: "This week",
7460
+ thisMonth: "This month"
7461
+ };
7462
+ const minutesAgo = (minutes) => () => /* @__PURE__ */ new Date(Date.now() - minutes * 6e4);
7463
+ const now = () => /* @__PURE__ */ new Date();
7464
+ const endOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999);
7465
+ const startOfWeek = (date, firstDayOfWeek = 0) => addDays(startOfDay(date), -((date.getDay() - firstDayOfWeek + 7) % 7));
7466
+ const RANGES = {
7467
+ last15Minutes: {
7468
+ from: minutesAgo(15),
7469
+ to: now
7470
+ },
7471
+ last1Hour: {
7472
+ from: minutesAgo(60),
7473
+ to: now
7474
+ },
7475
+ last6Hours: {
7476
+ from: minutesAgo(360),
7477
+ to: now
7478
+ },
7479
+ last24Hours: {
7480
+ from: minutesAgo(1440),
7481
+ to: now
7482
+ },
7483
+ last7Days: {
7484
+ from: () => addDays(startOfDay(/* @__PURE__ */ new Date()), -6),
7485
+ to: now
7486
+ },
7487
+ last30Days: {
7488
+ from: () => addDays(startOfDay(/* @__PURE__ */ new Date()), -29),
7489
+ to: now
7490
+ },
7491
+ today: {
7492
+ from: () => startOfDay(/* @__PURE__ */ new Date()),
7493
+ to: now
7494
+ },
7495
+ yesterday: {
7496
+ from: () => addDays(startOfDay(/* @__PURE__ */ new Date()), -1),
7497
+ to: () => endOfDay(addDays(/* @__PURE__ */ new Date(), -1))
7498
+ },
7499
+ thisWeek: {
7500
+ from: (c) => startOfWeek(/* @__PURE__ */ new Date(), c?.firstDayOfWeek),
7501
+ to: (c) => endOfDay(addDays(startOfWeek(/* @__PURE__ */ new Date(), c?.firstDayOfWeek), 6))
7502
+ },
7503
+ thisMonth: {
7504
+ from: () => new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth(), 1),
7505
+ to: () => endOfDay(new Date((/* @__PURE__ */ new Date()).getFullYear(), (/* @__PURE__ */ new Date()).getMonth() + 1, 0))
7506
+ }
7507
+ };
7508
+ const DAY_IDS = [
7509
+ "today",
7510
+ "last7Days",
7511
+ "thisMonth"
7512
+ ];
7513
+ const build = (ids, labels) => ids.map((id) => ({
7514
+ label: labels[id] ?? ENGLISH[id],
7515
+ ...RANGES[id]
7516
+ }));
7517
+ function hxDateRangePresets(labels = {}) {
7518
+ return build(Object.keys(RANGES), labels);
7519
+ }
7520
+ const HX_DATE_RANGE_PRESETS = hxDateRangePresets();
7521
+ const HX_DATE_RANGE_DAY_PRESETS = build(DAY_IDS, {});
7416
7522
  function dateKey(date) {
7417
7523
  return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
7418
7524
  }
@@ -7818,6 +7924,275 @@ function parseDateTimeText(text, options) {
7818
7924
  const day = options.timeOnly && rest === "" ? startOfDay(options.fallbackDay) : parseDateText(rest, options.locale);
7819
7925
  return day && withTime(day, hours, minutes, seconds);
7820
7926
  }
7927
+ var HxRangePresets = class HxRangePresets {
7928
+ presets = input.required(...ngDevMode ? [{ debugName: "presets" }] : /* istanbul ignore next */ []);
7929
+ display = input("buttons", ...ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []);
7930
+ label = input("Presets", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
7931
+ disabled = input(false, {
7932
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
7933
+ transform: booleanAttribute
7934
+ });
7935
+ selected = input(null, ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
7936
+ describedBy = input(null, ...ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []);
7937
+ chosen = output();
7938
+ select = viewChild(HxSelect, ...ngDevMode ? [{ debugName: "select" }] : /* istanbul ignore next */ []);
7939
+ presetValue = (preset) => preset;
7940
+ #restoring = false;
7941
+ chooseInSelect(preset) {
7942
+ if (!preset || this.#restoring) return;
7943
+ this.chosen.emit(preset);
7944
+ this.#restoring = true;
7945
+ try {
7946
+ this.select()?.value.set(this.selected());
7947
+ } finally {
7948
+ this.#restoring = false;
7949
+ }
7950
+ }
7951
+ static ɵfac = i0.ɵɵngDeclareFactory({
7952
+ minVersion: "12.0.0",
7953
+ version: "22.2.1",
7954
+ ngImport: i0,
7955
+ type: HxRangePresets,
7956
+ deps: [],
7957
+ target: i0.ɵɵFactoryTarget.Component
7958
+ });
7959
+ static ɵcmp = i0.ɵɵngDeclareComponent({
7960
+ minVersion: "17.0.0",
7961
+ version: "22.2.1",
7962
+ type: HxRangePresets,
7963
+ isStandalone: true,
7964
+ selector: "hx-range-presets",
7965
+ inputs: {
7966
+ presets: {
7967
+ classPropertyName: "presets",
7968
+ publicName: "presets",
7969
+ isSignal: true,
7970
+ isRequired: true,
7971
+ transformFunction: null
7972
+ },
7973
+ display: {
7974
+ classPropertyName: "display",
7975
+ publicName: "display",
7976
+ isSignal: true,
7977
+ isRequired: false,
7978
+ transformFunction: null
7979
+ },
7980
+ label: {
7981
+ classPropertyName: "label",
7982
+ publicName: "label",
7983
+ isSignal: true,
7984
+ isRequired: false,
7985
+ transformFunction: null
7986
+ },
7987
+ disabled: {
7988
+ classPropertyName: "disabled",
7989
+ publicName: "disabled",
7990
+ isSignal: true,
7991
+ isRequired: false,
7992
+ transformFunction: null
7993
+ },
7994
+ selected: {
7995
+ classPropertyName: "selected",
7996
+ publicName: "selected",
7997
+ isSignal: true,
7998
+ isRequired: false,
7999
+ transformFunction: null
8000
+ },
8001
+ describedBy: {
8002
+ classPropertyName: "describedBy",
8003
+ publicName: "describedBy",
8004
+ isSignal: true,
8005
+ isRequired: false,
8006
+ transformFunction: null
8007
+ }
8008
+ },
8009
+ outputs: { chosen: "chosen" },
8010
+ host: {
8011
+ properties: {
8012
+ "class.hx-range-presets-select": "display() === 'select'",
8013
+ "attr.role": "display() === 'select' ? null : 'group'",
8014
+ "attr.aria-label": "display() === 'select' ? null : label()"
8015
+ },
8016
+ classAttribute: "hx-range-presets"
8017
+ },
8018
+ viewQueries: [{
8019
+ propertyName: "select",
8020
+ first: true,
8021
+ predicate: HxSelect,
8022
+ descendants: true,
8023
+ isSignal: true
8024
+ }],
8025
+ ngImport: i0,
8026
+ template: `
8027
+ @if (display() === 'select') {
8028
+ <hx-select
8029
+ class="hx-range-preset-select"
8030
+ fluid
8031
+ [options]="presets()"
8032
+ optionLabel="label"
8033
+ [optionValue]="presetValue"
8034
+ [placeholder]="label()"
8035
+ [ariaLabel]="label()"
8036
+ [ariaDescribedby]="describedBy()"
8037
+ [disabled]="disabled()"
8038
+ [value]="selected()"
8039
+ (valueChange)="chooseInSelect($event)"
8040
+ />
8041
+ } @else {
8042
+ @for (preset of presets(); track $index) {
8043
+ <button
8044
+ type="button"
8045
+ class="hx-date-picker-button hx-range-preset"
8046
+ [disabled]="disabled()"
8047
+ [attr.aria-describedby]="describedBy()"
8048
+ (click)="chosen.emit(preset)"
8049
+ >
8050
+ {{ preset.label }}
8051
+ </button>
8052
+ }
8053
+ }
8054
+ `,
8055
+ isInline: true,
8056
+ dependencies: [{
8057
+ kind: "component",
8058
+ type: HxSelect,
8059
+ selector: "hx-select",
8060
+ inputs: [
8061
+ "options",
8062
+ "optionLabel",
8063
+ "optionValue",
8064
+ "optionDisabled",
8065
+ "placeholder",
8066
+ "emptyMessage",
8067
+ "filter",
8068
+ "filterPlaceholder",
8069
+ "filterBy",
8070
+ "emptyFilterMessage",
8071
+ "size",
8072
+ "variant",
8073
+ "fluid",
8074
+ "showClear",
8075
+ "inputId",
8076
+ "ariaLabel",
8077
+ "ariaLabelledby",
8078
+ "ariaDescribedby",
8079
+ "compareWith",
8080
+ "value",
8081
+ "disabled",
8082
+ "invalid"
8083
+ ],
8084
+ outputs: ["valueChange", "touch"]
8085
+ }],
8086
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
8087
+ });
8088
+ };
8089
+ i0.ɵɵngDeclareClassMetadata({
8090
+ minVersion: "12.0.0",
8091
+ version: "22.2.1",
8092
+ ngImport: i0,
8093
+ type: HxRangePresets,
8094
+ decorators: [{
8095
+ type: Component,
8096
+ args: [{
8097
+ selector: "hx-range-presets",
8098
+ imports: [HxSelect],
8099
+ template: `
8100
+ @if (display() === 'select') {
8101
+ <hx-select
8102
+ class="hx-range-preset-select"
8103
+ fluid
8104
+ [options]="presets()"
8105
+ optionLabel="label"
8106
+ [optionValue]="presetValue"
8107
+ [placeholder]="label()"
8108
+ [ariaLabel]="label()"
8109
+ [ariaDescribedby]="describedBy()"
8110
+ [disabled]="disabled()"
8111
+ [value]="selected()"
8112
+ (valueChange)="chooseInSelect($event)"
8113
+ />
8114
+ } @else {
8115
+ @for (preset of presets(); track $index) {
8116
+ <button
8117
+ type="button"
8118
+ class="hx-date-picker-button hx-range-preset"
8119
+ [disabled]="disabled()"
8120
+ [attr.aria-describedby]="describedBy()"
8121
+ (click)="chosen.emit(preset)"
8122
+ >
8123
+ {{ preset.label }}
8124
+ </button>
8125
+ }
8126
+ }
8127
+ `,
8128
+ changeDetection: ChangeDetectionStrategy.OnPush,
8129
+ host: {
8130
+ class: "hx-range-presets",
8131
+ "[class.hx-range-presets-select]": "display() === 'select'",
8132
+ "[attr.role]": "display() === 'select' ? null : 'group'",
8133
+ "[attr.aria-label]": "display() === 'select' ? null : label()"
8134
+ }
8135
+ }]
8136
+ }],
8137
+ propDecorators: {
8138
+ presets: [{
8139
+ type: i0.Input,
8140
+ args: [{
8141
+ isSignal: true,
8142
+ alias: "presets",
8143
+ required: true
8144
+ }]
8145
+ }],
8146
+ display: [{
8147
+ type: i0.Input,
8148
+ args: [{
8149
+ isSignal: true,
8150
+ alias: "display",
8151
+ required: false
8152
+ }]
8153
+ }],
8154
+ label: [{
8155
+ type: i0.Input,
8156
+ args: [{
8157
+ isSignal: true,
8158
+ alias: "label",
8159
+ required: false
8160
+ }]
8161
+ }],
8162
+ disabled: [{
8163
+ type: i0.Input,
8164
+ args: [{
8165
+ isSignal: true,
8166
+ alias: "disabled",
8167
+ required: false
8168
+ }]
8169
+ }],
8170
+ selected: [{
8171
+ type: i0.Input,
8172
+ args: [{
8173
+ isSignal: true,
8174
+ alias: "selected",
8175
+ required: false
8176
+ }]
8177
+ }],
8178
+ describedBy: [{
8179
+ type: i0.Input,
8180
+ args: [{
8181
+ isSignal: true,
8182
+ alias: "describedBy",
8183
+ required: false
8184
+ }]
8185
+ }],
8186
+ chosen: [{
8187
+ type: i0.Output,
8188
+ args: ["chosen"]
8189
+ }],
8190
+ select: [{
8191
+ type: i0.ViewChild,
8192
+ args: [i0.forwardRef(() => HxSelect), { isSignal: true }]
8193
+ }]
8194
+ }
8195
+ });
7821
8196
  const startOfDayOrNull$1 = (date) => isValidDate(date) ? startOfDay(date) : null;
7822
8197
  var HxDatePicker = class HxDatePicker {
7823
8198
  #host = inject(ElementRef);
@@ -7851,6 +8226,10 @@ var HxDatePicker = class HxDatePicker {
7851
8226
  locale = input(...ngDevMode ? [void 0, { debugName: "locale" }] : /* istanbul ignore next */ []);
7852
8227
  ariaLabel = input(...ngDevMode ? [void 0, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
7853
8228
  ariaLabelledby = input(...ngDevMode ? [void 0, { debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
8229
+ presets = input([], ...ngDevMode ? [{ debugName: "presets" }] : /* istanbul ignore next */ []);
8230
+ presetDisplay = input("buttons", ...ngDevMode ? [{ debugName: "presetDisplay" }] : /* istanbul ignore next */ []);
8231
+ presetsLabel = input("Presets", ...ngDevMode ? [{ debugName: "presetsLabel" }] : /* istanbul ignore next */ []);
8232
+ presetRefusedLabel = input("This range cannot be chosen.", ...ngDevMode ? [{ debugName: "presetRefusedLabel" }] : /* istanbul ignore next */ []);
7854
8233
  value = model(null, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
7855
8234
  disabled = input(false, {
7856
8235
  ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
@@ -7879,6 +8258,18 @@ var HxDatePicker = class HxDatePicker {
7879
8258
  }];
7880
8259
  field = viewChild("field", ...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
7881
8260
  calendar = viewChild(HxCalendar, ...ngDevMode ? [{ debugName: "calendar" }] : /* istanbul ignore next */ []);
8261
+ shownPresets = computed(() => this.selectionMode() === "range" ? this.presets() : [], ...ngDevMode ? [{ debugName: "shownPresets" }] : /* istanbul ignore next */ []);
8262
+ #chosen = signal(null, ...ngDevMode ? [{ debugName: "#chosen" }] : /* istanbul ignore next */ []);
8263
+ selectedPreset = computed(() => {
8264
+ const chosen = this.#chosen();
8265
+ if (!chosen) return null;
8266
+ const days = this.selectedDates();
8267
+ if (!(days.length === 2 && isSameDay(days[0], chosen.from) && isSameDay(days[1], chosen.to))) return null;
8268
+ const list = this.shownPresets();
8269
+ return list.find((p) => p === chosen.preset) ?? list.find((p) => p.label === chosen.preset.label) ?? null;
8270
+ }, ...ngDevMode ? [{ debugName: "selectedPreset" }] : /* istanbul ignore next */ []);
8271
+ presetError = signal(false, ...ngDevMode ? [{ debugName: "presetError" }] : /* istanbul ignore next */ []);
8272
+ presetErrorId = nextId("hx-date-picker-preset-error");
7882
8273
  #typed = signal(null, ...ngDevMode ? [{ debugName: "#typed" }] : /* istanbul ignore next */ []);
7883
8274
  view = signal("day", ...ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []);
7884
8275
  #cvaDisabled = signal(false, ...ngDevMode ? [{ debugName: "#cvaDisabled" }] : /* istanbul ignore next */ []);
@@ -7914,6 +8305,7 @@ var HxDatePicker = class HxDatePicker {
7914
8305
  #onTouched = () => {};
7915
8306
  writeValue(value) {
7916
8307
  this.#typed.set(null);
8308
+ this.presetError.set(false);
7917
8309
  this.value.set(value ?? null);
7918
8310
  }
7919
8311
  registerOnChange(fn) {
@@ -7963,7 +8355,41 @@ var HxDatePicker = class HxDatePicker {
7963
8355
  if (mode === "single" || mode === "range" && Array.isArray(next) && next.length === 2) this.close(true);
7964
8356
  }
7965
8357
  }
8358
+ applyPreset(preset) {
8359
+ if (this.isDisabled()) return;
8360
+ const range = hxResolvePreset(preset, { firstDayOfWeek: this.firstDayOfWeek() }, (date) => this.#presetDay(date));
8361
+ const [min, max] = [this.minDate(), this.maxDate()];
8362
+ const outside = !range?.from || !range.to || isValidDate(min) && compareDays(range.to, min) < 0 || isValidDate(max) && compareDays(range.from, max) > 0;
8363
+ const from = range?.from && this.#inLimits(range.from);
8364
+ const to = range?.to && this.#inLimits(range.to);
8365
+ if (outside || !from || !to || this.isDateDisabled(from) || this.isDateDisabled(to)) {
8366
+ this.presetError.set(true);
8367
+ return;
8368
+ }
8369
+ const next = [from, to];
8370
+ this.#typed.set(null);
8371
+ this.focusedDate.set(from);
8372
+ this.#commit(next);
8373
+ this.#chosen.set({
8374
+ preset,
8375
+ from,
8376
+ to
8377
+ });
8378
+ if (this.inline() || !this.open()) return;
8379
+ this.close();
8380
+ afterNextRender(() => this.field()?.nativeElement.focus(), { injector: this.#injector });
8381
+ }
8382
+ #presetDay(date) {
8383
+ if (!isValidDate(date)) return null;
8384
+ const day = startOfDay(date);
8385
+ return this.disabledDates().some((d) => isSameDay(d, day)) ? void 0 : day;
8386
+ }
8387
+ #inLimits(day) {
8388
+ const max = this.maxDate();
8389
+ return clampTime(day, startOfDayOrNull$1(this.minDate()), isValidDate(max) ? startOfDay(max) : null);
8390
+ }
7966
8391
  #commit(next) {
8392
+ this.presetError.set(false);
7967
8393
  this.value.set(next);
7968
8394
  this.#onChange(next);
7969
8395
  }
@@ -7974,6 +8400,7 @@ var HxDatePicker = class HxDatePicker {
7974
8400
  }
7975
8401
  show() {
7976
8402
  if (this.isDisabled() || this.inline() || this.open()) return;
8403
+ this.presetError.set(false);
7977
8404
  this.open.set(true);
7978
8405
  }
7979
8406
  toggle() {
@@ -7998,6 +8425,7 @@ var HxDatePicker = class HxDatePicker {
7998
8425
  }
7999
8426
  }
8000
8427
  onOutsideClick(event) {
8428
+ if (isInSelectOverlay(event.target)) return;
8001
8429
  if (!this.#host.nativeElement.contains(event.target)) this.close();
8002
8430
  }
8003
8431
  onFieldKeydown(event) {
@@ -8053,7 +8481,9 @@ var HxDatePicker = class HxDatePicker {
8053
8481
  }
8054
8482
  onFocusOut(event) {
8055
8483
  if (!this.inline()) return;
8056
- if (this.#host.nativeElement.contains(event.relatedTarget)) return;
8484
+ const host = this.#host.nativeElement;
8485
+ const next = event.relatedTarget;
8486
+ if (host.contains(next) || isInSelectOverlay(next)) return;
8057
8487
  this.#onTouched();
8058
8488
  this.touch.emit();
8059
8489
  }
@@ -8191,6 +8621,34 @@ var HxDatePicker = class HxDatePicker {
8191
8621
  isRequired: false,
8192
8622
  transformFunction: null
8193
8623
  },
8624
+ presets: {
8625
+ classPropertyName: "presets",
8626
+ publicName: "presets",
8627
+ isSignal: true,
8628
+ isRequired: false,
8629
+ transformFunction: null
8630
+ },
8631
+ presetDisplay: {
8632
+ classPropertyName: "presetDisplay",
8633
+ publicName: "presetDisplay",
8634
+ isSignal: true,
8635
+ isRequired: false,
8636
+ transformFunction: null
8637
+ },
8638
+ presetsLabel: {
8639
+ classPropertyName: "presetsLabel",
8640
+ publicName: "presetsLabel",
8641
+ isSignal: true,
8642
+ isRequired: false,
8643
+ transformFunction: null
8644
+ },
8645
+ presetRefusedLabel: {
8646
+ classPropertyName: "presetRefusedLabel",
8647
+ publicName: "presetRefusedLabel",
8648
+ isSignal: true,
8649
+ isRequired: false,
8650
+ transformFunction: null
8651
+ },
8194
8652
  value: {
8195
8653
  classPropertyName: "value",
8196
8654
  publicName: "value",
@@ -8248,7 +8706,7 @@ var HxDatePicker = class HxDatePicker {
8248
8706
  isSignal: true
8249
8707
  }],
8250
8708
  ngImport: i0,
8251
- template: "@if (inline()) {\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n} @else {\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n @if (showIcon()) {\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? 'Choose date'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n >\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n @if (showButtonBar()) {\n <div class=\"hx-date-picker-buttonbar\">\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"selectToday()\">{{ todayLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n </div>\n }\n </div>\n </ng-template>\n}\n\n<ng-template #calendar>\n<div\n class=\"hx-date-picker-panel\"\n role=\"group\"\n [attr.aria-label]=\"ariaLabel() ?? 'Calendar'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onFocusOut($event)\"\n>\n <hx-calendar\n [(focusedDate)]=\"focusedDate\"\n [(view)]=\"view\"\n [selectedDates]=\"selectedDates()\"\n [selectionMode]=\"selectionMode()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"titleId\"\n [today]=\"today\"\n (picked)=\"pick($event)\"\n />\n</div>\n</ng-template>\n",
8709
+ template: "@if (inline()) {\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n} @else {\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n @if (showIcon()) {\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? 'Choose date'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n >\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n @if (showButtonBar()) {\n <div class=\"hx-date-picker-buttonbar\">\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"selectToday()\">{{ todayLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n </div>\n }\n </div>\n </ng-template>\n}\n\n<ng-template #calendar>\n<div\n class=\"hx-date-picker-panel\"\n role=\"group\"\n [attr.aria-label]=\"ariaLabel() ?? 'Calendar'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onFocusOut($event)\"\n>\n @if (shownPresets().length > 0) {\n <hx-range-presets\n [presets]=\"shownPresets()\"\n [display]=\"presetDisplay()\"\n [label]=\"presetsLabel()\"\n [disabled]=\"isDisabled()\"\n [selected]=\"selectedPreset()\"\n [describedBy]=\"presetError() ? presetErrorId : null\"\n (chosen)=\"applyPreset($event)\"\n />\n @if (presetError()) {\n <p class=\"hx-date-picker-error\" role=\"alert\" [id]=\"presetErrorId\">{{ presetRefusedLabel() }}</p>\n }\n }\n <hx-calendar\n [(focusedDate)]=\"focusedDate\"\n [(view)]=\"view\"\n [selectedDates]=\"selectedDates()\"\n [selectionMode]=\"selectionMode()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"titleId\"\n [today]=\"today\"\n (picked)=\"pick($event)\"\n />\n</div>\n</ng-template>\n",
8252
8710
  dependencies: [
8253
8711
  {
8254
8712
  kind: "directive",
@@ -8330,164 +8788,1621 @@ var HxDatePicker = class HxDatePicker {
8330
8788
  "viewChange",
8331
8789
  "picked"
8332
8790
  ]
8333
- }
8334
- ],
8335
- changeDetection: i0.ChangeDetectionStrategy.OnPush
8336
- });
8791
+ },
8792
+ {
8793
+ kind: "component",
8794
+ type: HxRangePresets,
8795
+ selector: "hx-range-presets",
8796
+ inputs: [
8797
+ "presets",
8798
+ "display",
8799
+ "label",
8800
+ "disabled",
8801
+ "selected",
8802
+ "describedBy"
8803
+ ],
8804
+ outputs: ["chosen"]
8805
+ }
8806
+ ],
8807
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
8808
+ });
8809
+ };
8810
+ i0.ɵɵngDeclareClassMetadata({
8811
+ minVersion: "12.0.0",
8812
+ version: "22.2.1",
8813
+ ngImport: i0,
8814
+ type: HxDatePicker,
8815
+ decorators: [{
8816
+ type: Component,
8817
+ args: [{
8818
+ selector: "hx-date-picker",
8819
+ imports: [
8820
+ CdkConnectedOverlay,
8821
+ CdkOverlayOrigin,
8822
+ NgTemplateOutlet,
8823
+ HxCalendar,
8824
+ HxRangePresets
8825
+ ],
8826
+ changeDetection: ChangeDetectionStrategy.OnPush,
8827
+ providers: [{
8828
+ provide: NG_VALUE_ACCESSOR,
8829
+ useExisting: forwardRef(() => HxDatePicker),
8830
+ multi: true
8831
+ }],
8832
+ host: {
8833
+ class: "hx-date-picker",
8834
+ "[class.hx-date-picker-inline]": "inline()",
8835
+ "[class.hx-date-picker-disabled]": "isDisabled()",
8836
+ "[class.hx-date-picker-invalid]": "invalid()",
8837
+ "[class.hx-date-picker-open]": "open()",
8838
+ "[class.hx-date-picker-has-icon]": "showIcon() && !inline()",
8839
+ "[class.hx-filled]": "!inline() && text() !== \"\"",
8840
+ "(focusout)": "onHostFocusOut($event)"
8841
+ },
8842
+ template: "@if (inline()) {\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n} @else {\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n @if (showIcon()) {\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? 'Choose date'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n >\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n @if (showButtonBar()) {\n <div class=\"hx-date-picker-buttonbar\">\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"selectToday()\">{{ todayLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n </div>\n }\n </div>\n </ng-template>\n}\n\n<ng-template #calendar>\n<div\n class=\"hx-date-picker-panel\"\n role=\"group\"\n [attr.aria-label]=\"ariaLabel() ?? 'Calendar'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onFocusOut($event)\"\n>\n @if (shownPresets().length > 0) {\n <hx-range-presets\n [presets]=\"shownPresets()\"\n [display]=\"presetDisplay()\"\n [label]=\"presetsLabel()\"\n [disabled]=\"isDisabled()\"\n [selected]=\"selectedPreset()\"\n [describedBy]=\"presetError() ? presetErrorId : null\"\n (chosen)=\"applyPreset($event)\"\n />\n @if (presetError()) {\n <p class=\"hx-date-picker-error\" role=\"alert\" [id]=\"presetErrorId\">{{ presetRefusedLabel() }}</p>\n }\n }\n <hx-calendar\n [(focusedDate)]=\"focusedDate\"\n [(view)]=\"view\"\n [selectedDates]=\"selectedDates()\"\n [selectionMode]=\"selectionMode()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"titleId\"\n [today]=\"today\"\n (picked)=\"pick($event)\"\n />\n</div>\n</ng-template>\n"
8843
+ }]
8844
+ }],
8845
+ ctorParameters: () => [],
8846
+ propDecorators: {
8847
+ placeholder: [{
8848
+ type: i0.Input,
8849
+ args: [{
8850
+ isSignal: true,
8851
+ alias: "placeholder",
8852
+ required: false
8853
+ }]
8854
+ }],
8855
+ showIcon: [{
8856
+ type: i0.Input,
8857
+ args: [{
8858
+ isSignal: true,
8859
+ alias: "showIcon",
8860
+ required: false
8861
+ }]
8862
+ }],
8863
+ showButtonBar: [{
8864
+ type: i0.Input,
8865
+ args: [{
8866
+ isSignal: true,
8867
+ alias: "showButtonBar",
8868
+ required: false
8869
+ }]
8870
+ }],
8871
+ dateFormat: [{
8872
+ type: i0.Input,
8873
+ args: [{
8874
+ isSignal: true,
8875
+ alias: "dateFormat",
8876
+ required: false
8877
+ }]
8878
+ }],
8879
+ todayLabel: [{
8880
+ type: i0.Input,
8881
+ args: [{
8882
+ isSignal: true,
8883
+ alias: "todayLabel",
8884
+ required: false
8885
+ }]
8886
+ }],
8887
+ clearLabel: [{
8888
+ type: i0.Input,
8889
+ args: [{
8890
+ isSignal: true,
8891
+ alias: "clearLabel",
8892
+ required: false
8893
+ }]
8894
+ }],
8895
+ chooseLabel: [{
8896
+ type: i0.Input,
8897
+ args: [{
8898
+ isSignal: true,
8899
+ alias: "chooseLabel",
8900
+ required: false
8901
+ }]
8902
+ }],
8903
+ inputId: [{
8904
+ type: i0.Input,
8905
+ args: [{
8906
+ isSignal: true,
8907
+ alias: "inputId",
8908
+ required: false
8909
+ }]
8910
+ }],
8911
+ inline: [{
8912
+ type: i0.Input,
8913
+ args: [{
8914
+ isSignal: true,
8915
+ alias: "inline",
8916
+ required: false
8917
+ }]
8918
+ }],
8919
+ selectionMode: [{
8920
+ type: i0.Input,
8921
+ args: [{
8922
+ isSignal: true,
8923
+ alias: "selectionMode",
8924
+ required: false
8925
+ }]
8926
+ }],
8927
+ minDate: [{
8928
+ type: i0.Input,
8929
+ args: [{
8930
+ isSignal: true,
8931
+ alias: "minDate",
8932
+ required: false
8933
+ }]
8934
+ }],
8935
+ maxDate: [{
8936
+ type: i0.Input,
8937
+ args: [{
8938
+ isSignal: true,
8939
+ alias: "maxDate",
8940
+ required: false
8941
+ }]
8942
+ }],
8943
+ disabledDates: [{
8944
+ type: i0.Input,
8945
+ args: [{
8946
+ isSignal: true,
8947
+ alias: "disabledDates",
8948
+ required: false
8949
+ }]
8950
+ }],
8951
+ firstDayOfWeek: [{
8952
+ type: i0.Input,
8953
+ args: [{
8954
+ isSignal: true,
8955
+ alias: "firstDayOfWeek",
8956
+ required: false
8957
+ }]
8958
+ }],
8959
+ locale: [{
8960
+ type: i0.Input,
8961
+ args: [{
8962
+ isSignal: true,
8963
+ alias: "locale",
8964
+ required: false
8965
+ }]
8966
+ }],
8967
+ ariaLabel: [{
8968
+ type: i0.Input,
8969
+ args: [{
8970
+ isSignal: true,
8971
+ alias: "ariaLabel",
8972
+ required: false
8973
+ }]
8974
+ }],
8975
+ ariaLabelledby: [{
8976
+ type: i0.Input,
8977
+ args: [{
8978
+ isSignal: true,
8979
+ alias: "ariaLabelledby",
8980
+ required: false
8981
+ }]
8982
+ }],
8983
+ presets: [{
8984
+ type: i0.Input,
8985
+ args: [{
8986
+ isSignal: true,
8987
+ alias: "presets",
8988
+ required: false
8989
+ }]
8990
+ }],
8991
+ presetDisplay: [{
8992
+ type: i0.Input,
8993
+ args: [{
8994
+ isSignal: true,
8995
+ alias: "presetDisplay",
8996
+ required: false
8997
+ }]
8998
+ }],
8999
+ presetsLabel: [{
9000
+ type: i0.Input,
9001
+ args: [{
9002
+ isSignal: true,
9003
+ alias: "presetsLabel",
9004
+ required: false
9005
+ }]
9006
+ }],
9007
+ presetRefusedLabel: [{
9008
+ type: i0.Input,
9009
+ args: [{
9010
+ isSignal: true,
9011
+ alias: "presetRefusedLabel",
9012
+ required: false
9013
+ }]
9014
+ }],
9015
+ value: [{
9016
+ type: i0.Input,
9017
+ args: [{
9018
+ isSignal: true,
9019
+ alias: "value",
9020
+ required: false
9021
+ }]
9022
+ }, {
9023
+ type: i0.Output,
9024
+ args: ["valueChange"]
9025
+ }],
9026
+ disabled: [{
9027
+ type: i0.Input,
9028
+ args: [{
9029
+ isSignal: true,
9030
+ alias: "disabled",
9031
+ required: false
9032
+ }]
9033
+ }],
9034
+ invalid: [{
9035
+ type: i0.Input,
9036
+ args: [{
9037
+ isSignal: true,
9038
+ alias: "invalid",
9039
+ required: false
9040
+ }]
9041
+ }],
9042
+ touch: [{
9043
+ type: i0.Output,
9044
+ args: ["touch"]
9045
+ }],
9046
+ field: [{
9047
+ type: i0.ViewChild,
9048
+ args: ["field", { isSignal: true }]
9049
+ }],
9050
+ calendar: [{
9051
+ type: i0.ViewChild,
9052
+ args: [i0.forwardRef(() => HxCalendar), { isSignal: true }]
9053
+ }]
9054
+ }
9055
+ });
9056
+ const EXPRESSION = /^now((?:[+-]\d+[smhdwMy]|\/[smhdwMy])*)$/;
9057
+ const TOKEN = /([+-])(\d+)([smhdwMy])|\/([smhdwMy])/g;
9058
+ const MS = {
9059
+ s: 1e3,
9060
+ m: 6e4,
9061
+ h: 36e5
9062
+ };
9063
+ function add(date, amount, unit) {
9064
+ switch (unit) {
9065
+ case "s":
9066
+ case "m":
9067
+ case "h": return new Date(date.getTime() + amount * MS[unit]);
9068
+ case "d":
9069
+ case "w": {
9070
+ const result = new Date(date);
9071
+ result.setDate(result.getDate() + amount * (unit === "w" ? 7 : 1));
9072
+ return result;
9073
+ }
9074
+ case "M": return addMonthsKeepingTime(date, amount);
9075
+ case "y": return addMonthsKeepingTime(date, amount * 12);
9076
+ }
9077
+ }
9078
+ function addMonthsKeepingTime(date, months) {
9079
+ const day = addMonths(date, months);
9080
+ day.setHours(date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
9081
+ return day;
9082
+ }
9083
+ function startOf(date, unit, firstDayOfWeek) {
9084
+ const [y, mo, d, h, mi, s] = [
9085
+ date.getFullYear(),
9086
+ date.getMonth(),
9087
+ date.getDate(),
9088
+ date.getHours(),
9089
+ date.getMinutes(),
9090
+ date.getSeconds()
9091
+ ];
9092
+ switch (unit) {
9093
+ case "s": return new Date(y, mo, d, h, mi, s);
9094
+ case "m": return new Date(y, mo, d, h, mi);
9095
+ case "h": return new Date(y, mo, d, h);
9096
+ case "d": return new Date(y, mo, d);
9097
+ case "w": return new Date(y, mo, d - (date.getDay() - firstDayOfWeek + 7) % 7);
9098
+ case "M": return new Date(y, mo, 1);
9099
+ case "y": return new Date(y, 0, 1);
9100
+ }
9101
+ }
9102
+ function round(date, unit, options) {
9103
+ const start = startOf(date, unit, options.firstDayOfWeek ?? 0);
9104
+ if (!options.roundUp) return start;
9105
+ return /* @__PURE__ */ new Date(add(start, 1, unit).getTime() - 1);
9106
+ }
9107
+ function hxParseDateMath(expression, options = {}) {
9108
+ const match = typeof expression === "string" ? EXPRESSION.exec(expression.trim()) : null;
9109
+ const now = options.now ?? /* @__PURE__ */ new Date();
9110
+ if (!match || Number.isNaN(now.getTime())) return null;
9111
+ let result = new Date(now);
9112
+ for (const token of match[1].matchAll(TOKEN)) {
9113
+ const [, sign, amount, shiftUnit, roundUnit] = token;
9114
+ result = roundUnit ? round(result, roundUnit, options) : add(result, (sign === "-" ? -1 : 1) * Number(amount), shiftUnit);
9115
+ if (Number.isNaN(result.getTime())) return null;
9116
+ }
9117
+ return result;
9118
+ }
9119
+ function hxRelativeRangeExpressions(direction, amount, unit) {
9120
+ if (!Number.isSafeInteger(amount) || amount < 1) return null;
9121
+ return direction === "last" ? {
9122
+ from: `now-${amount}${unit}`,
9123
+ to: "now"
9124
+ } : {
9125
+ from: "now",
9126
+ to: `now+${amount}${unit}`
9127
+ };
9128
+ }
9129
+ const QUICK_SELECT_UNITS = [
9130
+ "s",
9131
+ "m",
9132
+ "h",
9133
+ "d",
9134
+ "w",
9135
+ "M",
9136
+ "y"
9137
+ ];
9138
+ const HX_QUICK_SELECT_LABELS = {
9139
+ quickSelect: "Quick select",
9140
+ last: "Last",
9141
+ next: "Next",
9142
+ amount: "Amount",
9143
+ unit: "Unit",
9144
+ direction: "Direction",
9145
+ apply: "Apply",
9146
+ commonlyUsed: "Commonly used",
9147
+ recentlyUsed: "Recently used",
9148
+ start: "Start",
9149
+ end: "End",
9150
+ absolute: "Absolute",
9151
+ relative: "Relative",
9152
+ now: "Now",
9153
+ nowHint: "Set to the current time when the range is applied.",
9154
+ incompleteRange: "Choose a start and an end that can be applied.",
9155
+ date: "Date",
9156
+ roundTo: "Round to the {unit}",
9157
+ lastRange: "Last {n} {unit}",
9158
+ nextRange: "Next {n} {unit}",
9159
+ range: "Start and end",
9160
+ nowSummary: "now",
9161
+ agoSummary: "~ {n} {unit} ago",
9162
+ fromNowSummary: "~ {n} {unit} from now",
9163
+ roundedSummary: "rounded to the {unit}",
9164
+ emptySide: "Not set",
9165
+ resolvesTo: "Resolves to {date}",
9166
+ units: {
9167
+ s: "seconds",
9168
+ m: "minutes",
9169
+ h: "hours",
9170
+ d: "days",
9171
+ w: "weeks",
9172
+ M: "months",
9173
+ y: "years"
9174
+ },
9175
+ unitsOne: {
9176
+ s: "second",
9177
+ m: "minute",
9178
+ h: "hour",
9179
+ d: "day",
9180
+ w: "week",
9181
+ M: "month",
9182
+ y: "year"
9183
+ },
9184
+ unitsAgo: {
9185
+ s: "Seconds ago",
9186
+ m: "Minutes ago",
9187
+ h: "Hours ago",
9188
+ d: "Days ago",
9189
+ w: "Weeks ago",
9190
+ M: "Months ago",
9191
+ y: "Years ago"
9192
+ },
9193
+ unitsFromNow: {
9194
+ s: "Seconds from now",
9195
+ m: "Minutes from now",
9196
+ h: "Hours from now",
9197
+ d: "Days from now",
9198
+ w: "Weeks from now",
9199
+ M: "Months from now",
9200
+ y: "Years from now"
9201
+ }
9202
+ };
9203
+ const HX_QUICK_SELECT_COMMONLY_USED = [
9204
+ {
9205
+ label: "Today",
9206
+ from: "now/d",
9207
+ to: "now/d"
9208
+ },
9209
+ {
9210
+ label: "This week",
9211
+ from: "now/w",
9212
+ to: "now/w"
9213
+ },
9214
+ {
9215
+ label: "Last 15 minutes",
9216
+ from: "now-15m",
9217
+ to: "now"
9218
+ },
9219
+ {
9220
+ label: "Last 30 minutes",
9221
+ from: "now-30m",
9222
+ to: "now"
9223
+ },
9224
+ {
9225
+ label: "Last 1 hour",
9226
+ from: "now-1h",
9227
+ to: "now"
9228
+ },
9229
+ {
9230
+ label: "Last 24 hours",
9231
+ from: "now-24h",
9232
+ to: "now"
9233
+ },
9234
+ {
9235
+ label: "Last 7 days",
9236
+ from: "now-7d",
9237
+ to: "now"
9238
+ },
9239
+ {
9240
+ label: "Last 30 days",
9241
+ from: "now-30d",
9242
+ to: "now"
9243
+ },
9244
+ {
9245
+ label: "Last 90 days",
9246
+ from: "now-90d",
9247
+ to: "now"
9248
+ },
9249
+ {
9250
+ label: "Last 1 year",
9251
+ from: "now-1y",
9252
+ to: "now"
9253
+ }
9254
+ ];
9255
+ const DEFAULT_SIDE = {
9256
+ mode: "absolute",
9257
+ amount: 15,
9258
+ unit: "m",
9259
+ direction: "ago",
9260
+ round: false,
9261
+ raw: null
9262
+ };
9263
+ const SIDE_MODES = [
9264
+ "absolute",
9265
+ "relative",
9266
+ "now"
9267
+ ];
9268
+ const ABSOLUTE_SIDES = {
9269
+ from: DEFAULT_SIDE,
9270
+ to: DEFAULT_SIDE
9271
+ };
9272
+ const SIMPLE = /^now(?:([+-])(\d+)([smhdwMy]))?(?:\/([smhdwMy]))?$/;
9273
+ function sideFromExpression(expression) {
9274
+ const text = expression.trim();
9275
+ if (text === "now") return {
9276
+ ...DEFAULT_SIDE,
9277
+ mode: "now"
9278
+ };
9279
+ const match = SIMPLE.exec(text);
9280
+ if (match) {
9281
+ const [, sign, amount, shiftUnit, roundUnit] = match;
9282
+ if (!shiftUnit || !roundUnit || shiftUnit === roundUnit) return {
9283
+ mode: "relative",
9284
+ amount: amount ? Number(amount) : 0,
9285
+ unit: shiftUnit ?? roundUnit,
9286
+ direction: sign === "+" ? "fromNow" : "ago",
9287
+ round: !!roundUnit,
9288
+ raw: null
9289
+ };
9290
+ }
9291
+ if (hxParseDateMath(text)) return {
9292
+ ...DEFAULT_SIDE,
9293
+ mode: "relative",
9294
+ raw: text
9295
+ };
9296
+ return { ...DEFAULT_SIDE };
9297
+ }
9298
+ function sideExpression(side) {
9299
+ if (side.mode === "now") return "now";
9300
+ if (side.mode === "absolute") return null;
9301
+ if (side.raw) return side.raw;
9302
+ if (side.amount === null || !Number.isFinite(side.amount) || side.amount < 0) return null;
9303
+ const amount = Math.floor(side.amount);
9304
+ return `now${amount > 0 ? `${side.direction === "ago" ? "-" : "+"}${amount}${side.unit}` : ""}${side.round ? `/${side.unit}` : ""}`;
9305
+ }
9306
+ const DATE_ONLY = /^(\d{4})-(\d{2})-(\d{2})$/;
9307
+ function hxResolveRangeSide(expression, options = {}) {
9308
+ const math = hxParseDateMath(expression, options);
9309
+ if (math) return math;
9310
+ const text = typeof expression === "string" ? expression.trim() : "";
9311
+ const day = DATE_ONLY.exec(text);
9312
+ if (day) {
9313
+ const [y, m, d] = [
9314
+ Number(day[1]),
9315
+ Number(day[2]) - 1,
9316
+ Number(day[3])
9317
+ ];
9318
+ const date = new Date(y, m, d);
9319
+ return date.getFullYear() === y && date.getMonth() === m && date.getDate() === d ? date : null;
9320
+ }
9321
+ if (!/^\d{4}-\d{2}-\d{2}T/.test(text)) return null;
9322
+ const date = new Date(text);
9323
+ return Number.isNaN(date.getTime()) ? null : date;
9324
+ }
9325
+ function hxResolveRangeExpression(range, options = {}) {
9326
+ return {
9327
+ from: hxResolveRangeSide(range.from, {
9328
+ ...options,
9329
+ roundUp: false
9330
+ }),
9331
+ to: hxResolveRangeSide(range.to, {
9332
+ ...options,
9333
+ roundUp: true
9334
+ })
9335
+ };
9336
+ }
9337
+ const fill = (template, n, unit) => template.replace("{n}", String(n)).replace("{unit}", unit);
9338
+ function describeSide(side, labels) {
9339
+ if (side.mode === "absolute") return null;
9340
+ if (side.mode === "now") return labels.nowSummary;
9341
+ if (side.raw) return side.raw;
9342
+ if (sideExpression(side) === null) return labels.emptySide;
9343
+ const n = Math.floor(side.amount ?? 0);
9344
+ const unit = n === 1 ? labels.unitsOne[side.unit] : labels.units[side.unit];
9345
+ const text = n === 0 ? labels.nowSummary : fill(side.direction === "ago" ? labels.agoSummary : labels.fromNowSummary, n, unit);
9346
+ return side.round ? `${text}, ${fill(labels.roundedSummary, n, labels.unitsOne[side.unit])}` : text;
9347
+ }
9348
+ function describeRange(range, labels, common, formatDate, separator = "-") {
9349
+ const known = common.find((c) => c.from === range.from && c.to === range.to);
9350
+ if (known) return known.label;
9351
+ const last = /^now-(\d+)([smhdwMy])$/.exec(range.from);
9352
+ const next = /^now\+(\d+)([smhdwMy])$/.exec(range.to);
9353
+ const unitName = (n, unit) => n === 1 ? labels.unitsOne[unit] : labels.units[unit];
9354
+ if (last && range.to === "now") {
9355
+ const n = Number(last[1]);
9356
+ return fill(labels.lastRange, n, unitName(n, last[2]));
9357
+ }
9358
+ if (next && range.from === "now") {
9359
+ const n = Number(next[1]);
9360
+ return fill(labels.nextRange, n, unitName(n, next[2]));
9361
+ }
9362
+ const side = (text) => {
9363
+ if (hxParseDateMath(text)) return text;
9364
+ const date = hxResolveRangeSide(text);
9365
+ return date ? formatDate(date) : text;
9366
+ };
9367
+ return `${side(range.from)} ${separator} ${side(range.to)}`;
9368
+ }
9369
+ const RECENT_SIDE_MAX = 64;
9370
+ const isRangeSide = (value) => typeof value === "string" && value.length <= RECENT_SIDE_MAX && hxResolveRangeSide(value) !== null;
9371
+ const isRange = (value) => !!value && isRangeSide(value.from) && isRangeSide(value.to);
9372
+ function storage() {
9373
+ try {
9374
+ return globalThis.localStorage ?? null;
9375
+ } catch {
9376
+ return null;
9377
+ }
9378
+ }
9379
+ function readRecentRanges(key) {
9380
+ if (!key) return null;
9381
+ let text;
9382
+ try {
9383
+ const store = storage();
9384
+ if (!store) return null;
9385
+ text = store.getItem(key);
9386
+ } catch {
9387
+ return null;
9388
+ }
9389
+ try {
9390
+ const parsed = JSON.parse(text ?? "[]");
9391
+ if (!Array.isArray(parsed)) return [];
9392
+ return parsed.filter(isRange).reduce((list, { from, to }) => list.some((r) => r.from === from && r.to === to) ? list : [...list, {
9393
+ from,
9394
+ to
9395
+ }], []).slice(0, 5);
9396
+ } catch {
9397
+ return [];
9398
+ }
9399
+ }
9400
+ function writeRecentRanges(key, ranges) {
9401
+ if (!key) return;
9402
+ try {
9403
+ storage()?.setItem(key, JSON.stringify(ranges));
9404
+ } catch {}
9405
+ }
9406
+ function addRecentRange(ranges, range, max = 5) {
9407
+ const rest = ranges.filter((r) => r.from !== range.from || r.to !== range.to);
9408
+ return [{
9409
+ from: range.from,
9410
+ to: range.to
9411
+ }, ...rest].slice(0, max);
9412
+ }
9413
+ const EMPTY$1 = {
9414
+ from: null,
9415
+ to: null
9416
+ };
9417
+ const RESOLVE_TOLERANCE_MS = 1e3;
9418
+ const sameTime$1 = (a, b, tolerance = 0) => a === null || b === null ? a === b : Math.abs(a.getTime() - b.getTime()) <= tolerance;
9419
+ const sameRange$1 = (a, b) => b !== null && sameTime$1(a.from, b.from) && sameTime$1(a.to, b.to);
9420
+ const SIDE_KEYS = ["from", "to"];
9421
+ const sidesFrom = (expression) => expression ? {
9422
+ from: sideFromExpression(expression.from),
9423
+ to: sideFromExpression(expression.to)
9424
+ } : ABSOLUTE_SIDES;
9425
+ var HxDateRangeQuickSelect = class HxDateRangeQuickSelect {
9426
+ labels = input({}, ...ngDevMode ? [{ debugName: "labels" }] : /* istanbul ignore next */ []);
9427
+ commonlyUsed = input(HX_QUICK_SELECT_COMMONLY_USED, ...ngDevMode ? [{ debugName: "commonlyUsed" }] : /* istanbul ignore next */ []);
9428
+ recentStorageKey = input("hx-date-range-recent", ...ngDevMode ? [{ debugName: "recentStorageKey" }] : /* istanbul ignore next */ []);
9429
+ expression = model(null, ...ngDevMode ? [{ debugName: "expression" }] : /* istanbul ignore next */ []);
9430
+ minDate = input(null, ...ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []);
9431
+ maxDate = input(null, ...ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []);
9432
+ firstDayOfWeek = input(0, {
9433
+ ...ngDevMode ? { debugName: "firstDayOfWeek" } : /* istanbul ignore next */ {},
9434
+ transform: numberAttribute
9435
+ });
9436
+ locale = input(...ngDevMode ? [void 0, { debugName: "locale" }] : /* istanbul ignore next */ []);
9437
+ dateFormat = input(...ngDevMode ? [void 0, { debugName: "dateFormat" }] : /* istanbul ignore next */ []);
9438
+ separator = input("-", ...ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []);
9439
+ placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
9440
+ chooseLabel = input("Choose date range", ...ngDevMode ? [{ debugName: "chooseLabel" }] : /* istanbul ignore next */ []);
9441
+ inputId = input(...ngDevMode ? [void 0, { debugName: "inputId" }] : /* istanbul ignore next */ []);
9442
+ ariaLabel = input(...ngDevMode ? [void 0, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
9443
+ ariaLabelledby = input(...ngDevMode ? [void 0, { debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
9444
+ value = model(EMPTY$1, ...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
9445
+ disabled = input(false, {
9446
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
9447
+ transform: booleanAttribute
9448
+ });
9449
+ invalid = input(false, {
9450
+ ...ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {},
9451
+ transform: booleanAttribute
9452
+ });
9453
+ touch = output();
9454
+ #host = inject(ElementRef);
9455
+ #injector = inject(Injector);
9456
+ open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
9457
+ popupId = nextId("hx-date-range-quick-select-popup");
9458
+ positions = [{
9459
+ originX: "start",
9460
+ originY: "bottom",
9461
+ overlayX: "start",
9462
+ overlayY: "top",
9463
+ offsetY: 2
9464
+ }, {
9465
+ originX: "start",
9466
+ originY: "top",
9467
+ overlayX: "start",
9468
+ overlayY: "bottom",
9469
+ offsetY: -2
9470
+ }];
9471
+ quickDirection = signal("last", ...ngDevMode ? [{ debugName: "quickDirection" }] : /* istanbul ignore next */ []);
9472
+ quickAmount = signal("15", ...ngDevMode ? [{ debugName: "quickAmount" }] : /* istanbul ignore next */ []);
9473
+ quickUnit = signal("m", ...ngDevMode ? [{ debugName: "quickUnit" }] : /* istanbul ignore next */ []);
9474
+ recent = signal([], ...ngDevMode ? [{ debugName: "recent" }] : /* istanbul ignore next */ []);
9475
+ quickError = signal(false, ...ngDevMode ? [{ debugName: "quickError" }] : /* istanbul ignore next */ []);
9476
+ quickErrorId = `${this.popupId}-error`;
9477
+ sideKeys = SIDE_KEYS;
9478
+ sideModes = SIDE_MODES;
9479
+ openSide = signal(null, ...ngDevMode ? [{ debugName: "openSide" }] : /* istanbul ignore next */ []);
9480
+ sides = signal(ABSOLUTE_SIDES, ...ngDevMode ? [{ debugName: "sides" }] : /* istanbul ignore next */ []);
9481
+ #appliedSides = signal(ABSOLUTE_SIDES, ...ngDevMode ? [{ debugName: "#appliedSides" }] : /* istanbul ignore next */ []);
9482
+ sideError = signal(false, ...ngDevMode ? [{ debugName: "sideError" }] : /* istanbul ignore next */ []);
9483
+ calendarFocus = signal(startOfDay(/* @__PURE__ */ new Date()), ...ngDevMode ? [{ debugName: "calendarFocus" }] : /* istanbul ignore next */ []);
9484
+ calendarView = signal("day", ...ngDevMode ? [{ debugName: "calendarView" }] : /* istanbul ignore next */ []);
9485
+ today = signal(startOfDay(/* @__PURE__ */ new Date()), ...ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []);
9486
+ calendarTitleId = `${this.popupId}-calendar-title`;
9487
+ texts = computed(() => ({
9488
+ ...HX_QUICK_SELECT_LABELS,
9489
+ ...this.labels()
9490
+ }), ...ngDevMode ? [{ debugName: "texts" }] : /* istanbul ignore next */ []);
9491
+ directionOptions = computed(() => [{
9492
+ label: this.texts().last,
9493
+ value: "last"
9494
+ }, {
9495
+ label: this.texts().next,
9496
+ value: "next"
9497
+ }], ...ngDevMode ? [{ debugName: "directionOptions" }] : /* istanbul ignore next */ []);
9498
+ unitOptions = computed(() => QUICK_SELECT_UNITS.map((unit) => ({
9499
+ label: this.texts().units[unit],
9500
+ value: unit
9501
+ })), ...ngDevMode ? [{ debugName: "unitOptions" }] : /* istanbul ignore next */ []);
9502
+ relativeOptions = computed(() => {
9503
+ const l = this.texts();
9504
+ return [...QUICK_SELECT_UNITS.map((unit) => ({
9505
+ label: l.unitsAgo[unit],
9506
+ value: `${unit}-ago`
9507
+ })), ...QUICK_SELECT_UNITS.map((unit) => ({
9508
+ label: l.unitsFromNow[unit],
9509
+ value: `${unit}-fromNow`
9510
+ }))];
9511
+ }, ...ngDevMode ? [{ debugName: "relativeOptions" }] : /* istanbul ignore next */ []);
9512
+ recentItems = computed(() => this.recent().map((range) => ({
9513
+ range,
9514
+ label: this.#describe(range)
9515
+ })), ...ngDevMode ? [{ debugName: "recentItems" }] : /* istanbul ignore next */ []);
9516
+ isDisabled = computed(() => this.disabled() || this.#cvaDisabled(), ...ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []);
9517
+ text = computed(() => {
9518
+ const expression = this.expression();
9519
+ if (expression) return this.#describe(expression);
9520
+ const { from, to } = this.value();
9521
+ if (!from && !to) return "";
9522
+ const one = (d) => d ? this.#formatDate(d) : "";
9523
+ return `${one(from)} ${this.separator()} ${one(to)}`.trim();
9524
+ }, ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
9525
+ field = viewChild("field", ...ngDevMode ? [{ debugName: "field" }] : /* istanbul ignore next */ []);
9526
+ quickFirst = viewChild("quickFirst", {
9527
+ ...ngDevMode ? { debugName: "quickFirst" } : /* istanbul ignore next */ {},
9528
+ read: HxSelect
9529
+ });
9530
+ sideButtons = viewChildren("sideButton", ...ngDevMode ? [{ debugName: "sideButtons" }] : /* istanbul ignore next */ []);
9531
+ sideTabs = viewChildren("sideTab", ...ngDevMode ? [{ debugName: "sideTabs" }] : /* istanbul ignore next */ []);
9532
+ #cvaDisabled = signal(false, ...ngDevMode ? [{ debugName: "#cvaDisabled" }] : /* istanbul ignore next */ []);
9533
+ #format = computed(() => new Intl.DateTimeFormat(this.locale(), this.dateFormat() ?? {
9534
+ day: "numeric",
9535
+ month: "numeric",
9536
+ year: "numeric",
9537
+ hour: "numeric",
9538
+ minute: "2-digit",
9539
+ hourCycle: "h23"
9540
+ }), ...ngDevMode ? [{ debugName: "#format" }] : /* istanbul ignore next */ []);
9541
+ #onChange = () => {};
9542
+ #onTouched = () => {};
9543
+ #seenExpression = null;
9544
+ #expressionValue = null;
9545
+ #editedValue = null;
9546
+ #editedExpression = null;
9547
+ #editedRange = null;
9548
+ constructor() {
9549
+ effect(() => {
9550
+ if (this.isDisabled()) untracked(() => this.close());
9551
+ });
9552
+ effect(() => {
9553
+ const value = this.value();
9554
+ const expression = this.expression();
9555
+ untracked(() => {
9556
+ if (expression !== this.#seenExpression) {
9557
+ this.#seenExpression = expression;
9558
+ this.#expressionValue = value;
9559
+ } else if (expression !== null && value !== this.#expressionValue) if (sameRange$1(value, this.#expressionValue) || this.#resolvesTo(expression, value)) this.#expressionValue = value;
9560
+ else this.expression.set(null);
9561
+ if (value !== this.#editedValue || this.expression() !== this.#editedExpression) {
9562
+ this.#editedValue = null;
9563
+ this.#editedExpression = null;
9564
+ this.#editedRange = null;
9565
+ this.sideError.set(false);
9566
+ const sides = sidesFrom(this.expression());
9567
+ this.sides.set(sides);
9568
+ this.#appliedSides.set(sides);
9569
+ }
9570
+ });
9571
+ });
9572
+ }
9573
+ writeValue(value) {
9574
+ this.value.set({
9575
+ from: value?.from ?? null,
9576
+ to: value?.to ?? null
9577
+ });
9578
+ }
9579
+ registerOnChange(fn) {
9580
+ this.#onChange = fn;
9581
+ }
9582
+ registerOnTouched(fn) {
9583
+ this.#onTouched = fn;
9584
+ }
9585
+ setDisabledState(disabled) {
9586
+ this.#cvaDisabled.set(disabled);
9587
+ }
9588
+ focus() {
9589
+ this.field()?.nativeElement.focus();
9590
+ }
9591
+ show() {
9592
+ if (this.isDisabled() || this.open()) return;
9593
+ const stored = readRecentRanges(this.recentStorageKey());
9594
+ if (stored) this.recent.set(stored);
9595
+ this.quickError.set(false);
9596
+ this.#dropRefusedEdit();
9597
+ this.openSide.set(null);
9598
+ this.open.set(true);
9599
+ }
9600
+ toggle() {
9601
+ if (this.open()) this.close(true);
9602
+ else this.show();
9603
+ }
9604
+ close(refocus = false) {
9605
+ if (!this.open()) return;
9606
+ this.#dropRefusedEdit();
9607
+ this.openSide.set(null);
9608
+ if (this.#editedRange) this.#remember(this.#editedRange);
9609
+ this.#editedRange = null;
9610
+ this.open.set(false);
9611
+ if (refocus) this.field()?.nativeElement.focus();
9612
+ }
9613
+ onAttach() {
9614
+ afterNextRender(() => this.quickFirst()?.focus(), { injector: this.#injector });
9615
+ }
9616
+ onFieldKeydown(event) {
9617
+ if (event.key === "ArrowDown" || event.altKey && event.key === "ArrowUp" || event.key === "Enter" || event.key === " ") {
9618
+ event.preventDefault();
9619
+ this.show();
9620
+ }
9621
+ }
9622
+ onOverlayKeydown(event) {
9623
+ if (event.key !== "Escape") return;
9624
+ event.preventDefault();
9625
+ if (this.openSide()) this.closeSide();
9626
+ else this.close(true);
9627
+ }
9628
+ onOutsideClick(event) {
9629
+ if (isInSelectOverlay(event.target)) return;
9630
+ if (!this.#host.nativeElement.contains(event.target)) this.close();
9631
+ }
9632
+ setQuickDirection(direction) {
9633
+ if (direction === "last" || direction === "next") this.quickDirection.set(direction);
9634
+ }
9635
+ setQuickAmount(event) {
9636
+ this.quickError.set(false);
9637
+ this.quickAmount.set(event.target.value);
9638
+ }
9639
+ setQuickUnit(unit) {
9640
+ if (QUICK_SELECT_UNITS.includes(unit)) this.quickUnit.set(unit);
9641
+ }
9642
+ applyQuick() {
9643
+ const text = this.quickAmount().trim();
9644
+ const range = hxRelativeRangeExpressions(this.quickDirection(), text === "" ? NaN : Number(text), this.quickUnit());
9645
+ if (!range || !this.#applyRange(range)) this.quickError.set(true);
9646
+ }
9647
+ applyRange(range) {
9648
+ if (!this.#applyRange(range)) this.quickError.set(true);
9649
+ }
9650
+ sideSummary(side) {
9651
+ const relative = describeSide(this.#appliedSides()[side], this.texts());
9652
+ if (relative !== null) return relative;
9653
+ const date = this.value()[side];
9654
+ return date ? this.#formatDate(date) : this.texts().emptySide;
9655
+ }
9656
+ sideButtonId(side) {
9657
+ return `${this.popupId}-${side}-button`;
9658
+ }
9659
+ editorId(side) {
9660
+ return `${this.popupId}-${side}-editor`;
9661
+ }
9662
+ tabId(side, mode) {
9663
+ return `${this.popupId}-${side}-${mode}`;
9664
+ }
9665
+ panelId(side) {
9666
+ return `${this.popupId}-${side}-panel`;
9667
+ }
9668
+ toggleSide(side) {
9669
+ if (this.openSide() === side) {
9670
+ this.closeSide();
9671
+ return;
9672
+ }
9673
+ this.#dropRefusedEdit();
9674
+ this.openSide.set(side);
9675
+ this.#showDay(side);
9676
+ afterNextRender(() => this.#focusById(this.sideTabs(), this.tabId(side, this.sides()[side].mode)), { injector: this.#injector });
9677
+ }
9678
+ closeSide() {
9679
+ const side = this.openSide();
9680
+ if (!side) return;
9681
+ this.#dropRefusedEdit();
9682
+ this.openSide.set(null);
9683
+ this.#focusById(this.sideButtons(), this.sideButtonId(side));
9684
+ }
9685
+ setSideMode(side, mode) {
9686
+ const sides = this.sides();
9687
+ if (sides[side].mode === mode) return;
9688
+ this.#editSides({
9689
+ ...sides,
9690
+ [side]: {
9691
+ ...sides[side],
9692
+ mode
9693
+ }
9694
+ });
9695
+ if (mode === "absolute") this.#showDay(side);
9696
+ }
9697
+ onTabKeydown(side, event) {
9698
+ const index = SIDE_MODES.indexOf(this.sides()[side].mode);
9699
+ const last = SIDE_MODES.length - 1;
9700
+ const next = event.key === "ArrowRight" ? (index + 1) % SIDE_MODES.length : event.key === "ArrowLeft" ? (index + last) % SIDE_MODES.length : event.key === "Home" ? 0 : event.key === "End" ? last : -1;
9701
+ if (next < 0) return;
9702
+ event.preventDefault();
9703
+ this.setSideMode(side, SIDE_MODES[next]);
9704
+ event.currentTarget.querySelectorAll("[role=tab]")[next]?.focus();
9705
+ }
9706
+ setSideAmount(side, event) {
9707
+ const text = event.target.value.trim();
9708
+ this.#patchSide(side, { amount: text === "" ? null : Number(text) });
9709
+ }
9710
+ setSideUnit(side, value) {
9711
+ const [unit, direction] = String(value).split("-");
9712
+ if (!QUICK_SELECT_UNITS.includes(unit)) return;
9713
+ this.#patchSide(side, {
9714
+ unit,
9715
+ direction: direction === "fromNow" ? "fromNow" : "ago"
9716
+ });
9717
+ }
9718
+ setSideRound(side, event) {
9719
+ this.#patchSide(side, { round: event.target.checked });
9720
+ }
9721
+ sideUnitValue(side) {
9722
+ const state = this.sides()[side];
9723
+ return `${state.unit}-${state.direction}`;
9724
+ }
9725
+ sideRoundLabel(side) {
9726
+ return this.texts().roundTo.replace("{unit}", this.texts().unitsOne[this.sides()[side].unit]);
9727
+ }
9728
+ sideExpressionText(side) {
9729
+ return sideExpression(this.sides()[side]) ?? "";
9730
+ }
9731
+ sideResolvedText(side) {
9732
+ const state = this.sides()[side];
9733
+ const expression = sideExpression(state);
9734
+ const resolved = state.mode === "absolute" ? this.value()[side] : expression ? hxResolveRangeSide(expression, {
9735
+ firstDayOfWeek: this.firstDayOfWeek(),
9736
+ roundUp: side === "to"
9737
+ }) : null;
9738
+ if (!isValidDate(resolved)) return "";
9739
+ const date = clampTime(resolved, this.minDate(), this.maxDate());
9740
+ return this.texts().resolvesTo.replace("{date}", this.#formatDate(date));
9741
+ }
9742
+ sideText(side) {
9743
+ const date = this.value()[side];
9744
+ return date ? this.#formatDate(date) : "";
9745
+ }
9746
+ sideDays(side) {
9747
+ const date = this.value()[side];
9748
+ return date ? [date] : [];
9749
+ }
9750
+ setAbsoluteSide(side, event) {
9751
+ const field = event.target;
9752
+ const text = field.value.trim();
9753
+ if (text === this.sideText(side)) {
9754
+ this.#dropRefusedEdit();
9755
+ return;
9756
+ }
9757
+ let date = null;
9758
+ if (text !== "") {
9759
+ date = parseDateTimeText(text, {
9760
+ locale: this.locale(),
9761
+ showMinutes: true,
9762
+ timeOnly: false,
9763
+ fallbackDay: this.value()[side] ?? /* @__PURE__ */ new Date()
9764
+ }) ?? parseDateText(text, this.locale());
9765
+ const [min, max] = [this.minDate(), this.maxDate()];
9766
+ if (!date || min && date < min || max && date > max) {
9767
+ this.sideError.set(true);
9768
+ return;
9769
+ }
9770
+ }
9771
+ if (!this.#editSides(this.sides(), { [side]: date })) return;
9772
+ if (date) this.calendarFocus.set(startOfDay(date));
9773
+ field.value = this.sideText(this.openSide() ?? side);
9774
+ }
9775
+ pickDay(side, day) {
9776
+ const [min, max] = [this.minDate(), this.maxDate()];
9777
+ if (this.isDisabled() || isDateDisabled(day, {
9778
+ min,
9779
+ max
9780
+ })) return;
9781
+ const old = this.value()[side];
9782
+ const date = startOfDay(day);
9783
+ if (old) date.setHours(old.getHours(), old.getMinutes(), old.getSeconds(), old.getMilliseconds());
9784
+ else if (side === "to") date.setHours(23, 59, 59, 999);
9785
+ this.calendarFocus.set(startOfDay(day));
9786
+ this.#editSides(this.sides(), { [side]: clampTime(date, min, max) });
9787
+ }
9788
+ #patchSide(side, patch) {
9789
+ const sides = this.sides();
9790
+ this.#editSides({
9791
+ ...sides,
9792
+ [side]: {
9793
+ ...sides[side],
9794
+ ...patch,
9795
+ raw: null
9796
+ }
9797
+ });
9798
+ }
9799
+ #editSides(sides, dates = {}) {
9800
+ this.sides.set(sides);
9801
+ const applied = this.#applySides(sides, dates);
9802
+ this.sideError.set(!applied);
9803
+ return applied;
9804
+ }
9805
+ #applySides(edited, dates) {
9806
+ let sides = edited;
9807
+ const options = {
9808
+ now: /* @__PURE__ */ new Date(),
9809
+ firstDayOfWeek: this.firstDayOfWeek()
9810
+ };
9811
+ const resolved = {
9812
+ from: null,
9813
+ to: null
9814
+ };
9815
+ const texts = {
9816
+ from: null,
9817
+ to: null
9818
+ };
9819
+ for (const side of SIDE_KEYS) {
9820
+ const state = sides[side];
9821
+ if (state.mode === "absolute") {
9822
+ const date = side in dates ? dates[side] ?? null : this.value()[side];
9823
+ resolved[side] = date;
9824
+ texts[side] = date?.toISOString() ?? null;
9825
+ continue;
9826
+ }
9827
+ const expression = sideExpression(state);
9828
+ const date = expression ? hxResolveRangeSide(expression, {
9829
+ ...options,
9830
+ roundUp: side === "to"
9831
+ }) : null;
9832
+ if (!expression || !isValidDate(date)) return false;
9833
+ resolved[side] = date;
9834
+ texts[side] = expression;
9835
+ }
9836
+ if (resolved.from && resolved.to && resolved.from > resolved.to) {
9837
+ [resolved.from, resolved.to] = [resolved.to, resolved.from];
9838
+ [texts.from, texts.to] = [texts.to, texts.from];
9839
+ sides = {
9840
+ from: sides.to,
9841
+ to: sides.from
9842
+ };
9843
+ this.sides.set(sides);
9844
+ const open = this.openSide();
9845
+ if (open) this.openSide.set(open === "from" ? "to" : "from");
9846
+ }
9847
+ const inside = (d) => d && clampTime(d, this.minDate(), this.maxDate());
9848
+ const next = {
9849
+ from: inside(resolved.from),
9850
+ to: inside(resolved.to)
9851
+ };
9852
+ const range = texts.from !== null && texts.to !== null ? {
9853
+ from: texts.from,
9854
+ to: texts.to
9855
+ } : null;
9856
+ const expression = sides.from.mode !== "absolute" || sides.to.mode !== "absolute" ? range : null;
9857
+ this.#editedValue = next;
9858
+ this.#editedExpression = expression;
9859
+ this.#editedRange = range;
9860
+ this.#appliedSides.set(sides);
9861
+ this.#commit(next);
9862
+ this.expression.set(expression);
9863
+ return true;
9864
+ }
9865
+ #focusById(elements, id) {
9866
+ elements.find((e) => e.nativeElement.id === id)?.nativeElement.focus();
9867
+ }
9868
+ #dropRefusedEdit() {
9869
+ if (!this.sideError()) return;
9870
+ this.sideError.set(false);
9871
+ this.sides.set(this.#appliedSides());
9872
+ }
9873
+ #showDay(side) {
9874
+ const today = startOfDay(/* @__PURE__ */ new Date());
9875
+ this.today.set(today);
9876
+ const min = this.minDate();
9877
+ const date = this.value()[side] ?? clampTime(today, min && startOfDay(min), this.maxDate());
9878
+ this.calendarFocus.set(startOfDay(date));
9879
+ this.calendarView.set("day");
9880
+ }
9881
+ #applyRange(range) {
9882
+ const options = {
9883
+ now: /* @__PURE__ */ new Date(),
9884
+ firstDayOfWeek: this.firstDayOfWeek()
9885
+ };
9886
+ const from = hxResolveRangeSide(range.from, {
9887
+ ...options,
9888
+ roundUp: false
9889
+ });
9890
+ const to = hxResolveRangeSide(range.to, {
9891
+ ...options,
9892
+ roundUp: true
9893
+ });
9894
+ if (!isValidDate(from) || !isValidDate(to)) return false;
9895
+ const swapped = to < from;
9896
+ const stored = swapped ? {
9897
+ from: range.to,
9898
+ to: range.from
9899
+ } : {
9900
+ from: range.from,
9901
+ to: range.to
9902
+ };
9903
+ const inside = (d) => clampTime(d, this.minDate(), this.maxDate());
9904
+ const next = swapped ? {
9905
+ from: inside(to),
9906
+ to: inside(from)
9907
+ } : {
9908
+ from: inside(from),
9909
+ to: inside(to)
9910
+ };
9911
+ const relative = hxParseDateMath(range.from) !== null || hxParseDateMath(range.to) !== null;
9912
+ this.#editedRange = null;
9913
+ this.#remember(stored);
9914
+ this.#commit(next);
9915
+ this.expression.set(relative ? stored : null);
9916
+ this.close(true);
9917
+ return true;
9918
+ }
9919
+ #resolvesTo(expression, value) {
9920
+ const { from, to } = hxResolveRangeExpression(expression, { firstDayOfWeek: this.firstDayOfWeek() });
9921
+ const inside = (d) => isValidDate(d) ? clampTime(d, this.minDate(), this.maxDate()) : null;
9922
+ const near = (a, b) => sameTime$1(a, b, RESOLVE_TOLERANCE_MS);
9923
+ const matches = (start, end) => near(value.from, start) && near(value.to, end) || near(value.from, inside(start)) && near(value.to, inside(end));
9924
+ return matches(from, to) || matches(to, from);
9925
+ }
9926
+ #remember(range) {
9927
+ const next = addRecentRange(this.recent(), range);
9928
+ this.recent.set(next);
9929
+ writeRecentRanges(this.recentStorageKey(), next);
9930
+ }
9931
+ #describe(range) {
9932
+ return describeRange(range, this.texts(), this.commonlyUsed(), (d) => this.#formatDate(d), this.separator());
9933
+ }
9934
+ #formatDate(date) {
9935
+ return this.#format().format(date).replace(/,\s*/, " ");
9936
+ }
9937
+ onHostFocusOut(event) {
9938
+ const next = event.relatedTarget;
9939
+ if (isInSelectOverlay(next) || next?.closest(".hx-date-range-quick-select-popup") || this.#host.nativeElement.contains(next)) return;
9940
+ if (this.open() && !next) return;
9941
+ this.close();
9942
+ this.markTouched();
9943
+ }
9944
+ onPopupFocusOut(event) {
9945
+ const next = event.relatedTarget;
9946
+ if (!next || isInSelectOverlay(next) || next.closest(".hx-date-range-quick-select-popup") || this.#host.nativeElement.contains(next)) return;
9947
+ this.close();
9948
+ this.markTouched();
9949
+ }
9950
+ markTouched() {
9951
+ this.#onTouched();
9952
+ this.touch.emit();
9953
+ }
9954
+ #commit(next) {
9955
+ this.value.set(next);
9956
+ this.#onChange(next);
9957
+ }
9958
+ static ɵfac = i0.ɵɵngDeclareFactory({
9959
+ minVersion: "12.0.0",
9960
+ version: "22.2.1",
9961
+ ngImport: i0,
9962
+ type: HxDateRangeQuickSelect,
9963
+ deps: [],
9964
+ target: i0.ɵɵFactoryTarget.Component
9965
+ });
9966
+ static ɵcmp = i0.ɵɵngDeclareComponent({
9967
+ minVersion: "17.0.0",
9968
+ version: "22.2.1",
9969
+ type: HxDateRangeQuickSelect,
9970
+ isStandalone: true,
9971
+ selector: "hx-date-range-quick-select",
9972
+ inputs: {
9973
+ labels: {
9974
+ classPropertyName: "labels",
9975
+ publicName: "labels",
9976
+ isSignal: true,
9977
+ isRequired: false,
9978
+ transformFunction: null
9979
+ },
9980
+ commonlyUsed: {
9981
+ classPropertyName: "commonlyUsed",
9982
+ publicName: "commonlyUsed",
9983
+ isSignal: true,
9984
+ isRequired: false,
9985
+ transformFunction: null
9986
+ },
9987
+ recentStorageKey: {
9988
+ classPropertyName: "recentStorageKey",
9989
+ publicName: "recentStorageKey",
9990
+ isSignal: true,
9991
+ isRequired: false,
9992
+ transformFunction: null
9993
+ },
9994
+ expression: {
9995
+ classPropertyName: "expression",
9996
+ publicName: "expression",
9997
+ isSignal: true,
9998
+ isRequired: false,
9999
+ transformFunction: null
10000
+ },
10001
+ minDate: {
10002
+ classPropertyName: "minDate",
10003
+ publicName: "minDate",
10004
+ isSignal: true,
10005
+ isRequired: false,
10006
+ transformFunction: null
10007
+ },
10008
+ maxDate: {
10009
+ classPropertyName: "maxDate",
10010
+ publicName: "maxDate",
10011
+ isSignal: true,
10012
+ isRequired: false,
10013
+ transformFunction: null
10014
+ },
10015
+ firstDayOfWeek: {
10016
+ classPropertyName: "firstDayOfWeek",
10017
+ publicName: "firstDayOfWeek",
10018
+ isSignal: true,
10019
+ isRequired: false,
10020
+ transformFunction: null
10021
+ },
10022
+ locale: {
10023
+ classPropertyName: "locale",
10024
+ publicName: "locale",
10025
+ isSignal: true,
10026
+ isRequired: false,
10027
+ transformFunction: null
10028
+ },
10029
+ dateFormat: {
10030
+ classPropertyName: "dateFormat",
10031
+ publicName: "dateFormat",
10032
+ isSignal: true,
10033
+ isRequired: false,
10034
+ transformFunction: null
10035
+ },
10036
+ separator: {
10037
+ classPropertyName: "separator",
10038
+ publicName: "separator",
10039
+ isSignal: true,
10040
+ isRequired: false,
10041
+ transformFunction: null
10042
+ },
10043
+ placeholder: {
10044
+ classPropertyName: "placeholder",
10045
+ publicName: "placeholder",
10046
+ isSignal: true,
10047
+ isRequired: false,
10048
+ transformFunction: null
10049
+ },
10050
+ chooseLabel: {
10051
+ classPropertyName: "chooseLabel",
10052
+ publicName: "chooseLabel",
10053
+ isSignal: true,
10054
+ isRequired: false,
10055
+ transformFunction: null
10056
+ },
10057
+ inputId: {
10058
+ classPropertyName: "inputId",
10059
+ publicName: "inputId",
10060
+ isSignal: true,
10061
+ isRequired: false,
10062
+ transformFunction: null
10063
+ },
10064
+ ariaLabel: {
10065
+ classPropertyName: "ariaLabel",
10066
+ publicName: "ariaLabel",
10067
+ isSignal: true,
10068
+ isRequired: false,
10069
+ transformFunction: null
10070
+ },
10071
+ ariaLabelledby: {
10072
+ classPropertyName: "ariaLabelledby",
10073
+ publicName: "ariaLabelledby",
10074
+ isSignal: true,
10075
+ isRequired: false,
10076
+ transformFunction: null
10077
+ },
10078
+ value: {
10079
+ classPropertyName: "value",
10080
+ publicName: "value",
10081
+ isSignal: true,
10082
+ isRequired: false,
10083
+ transformFunction: null
10084
+ },
10085
+ disabled: {
10086
+ classPropertyName: "disabled",
10087
+ publicName: "disabled",
10088
+ isSignal: true,
10089
+ isRequired: false,
10090
+ transformFunction: null
10091
+ },
10092
+ invalid: {
10093
+ classPropertyName: "invalid",
10094
+ publicName: "invalid",
10095
+ isSignal: true,
10096
+ isRequired: false,
10097
+ transformFunction: null
10098
+ }
10099
+ },
10100
+ outputs: {
10101
+ expression: "expressionChange",
10102
+ value: "valueChange",
10103
+ touch: "touch"
10104
+ },
10105
+ host: {
10106
+ listeners: { "focusout": "onHostFocusOut($event)" },
10107
+ classAttribute: "hx-date-range-quick-select"
10108
+ },
10109
+ providers: [{
10110
+ provide: NG_VALUE_ACCESSOR,
10111
+ useExisting: forwardRef(() => HxDateRangeQuickSelect),
10112
+ multi: true
10113
+ }],
10114
+ viewQueries: [
10115
+ {
10116
+ propertyName: "field",
10117
+ first: true,
10118
+ predicate: ["field"],
10119
+ descendants: true,
10120
+ isSignal: true
10121
+ },
10122
+ {
10123
+ propertyName: "quickFirst",
10124
+ first: true,
10125
+ predicate: ["quickFirst"],
10126
+ descendants: true,
10127
+ read: HxSelect,
10128
+ isSignal: true
10129
+ },
10130
+ {
10131
+ propertyName: "sideButtons",
10132
+ predicate: ["sideButton"],
10133
+ descendants: true,
10134
+ isSignal: true
10135
+ },
10136
+ {
10137
+ propertyName: "sideTabs",
10138
+ predicate: ["sideTab"],
10139
+ descendants: true,
10140
+ isSignal: true
10141
+ }
10142
+ ],
10143
+ ngImport: i0,
10144
+ template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-range-quick-select-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n readonly\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n >\n @let l = texts();\n <div\n class=\"hx-date-picker-popup hx-date-range-quick-select-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-quick'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-quick'\">{{ l.quickSelect }}</span>\n <div class=\"hx-date-range-quick-select-row\">\n <hx-select\n #quickFirst\n class=\"hx-date-range-quick-select-direction\"\n [options]=\"directionOptions()\"\n [ariaLabel]=\"l.direction\"\n [value]=\"quickDirection()\"\n (valueChange)=\"setQuickDirection($event)\"\n />\n <input\n hx-input\n type=\"number\"\n min=\"1\"\n step=\"1\"\n class=\"hx-date-range-quick-select-amount\"\n [attr.aria-label]=\"l.amount\"\n [attr.aria-invalid]=\"quickError() ? 'true' : null\"\n [attr.aria-describedby]=\"quickError() ? quickErrorId : null\"\n [value]=\"quickAmount()\"\n (input)=\"setQuickAmount($event)\"\n (keydown.enter)=\"$event.preventDefault(); applyQuick()\"\n />\n <hx-select\n class=\"hx-date-range-quick-select-unit\"\n [options]=\"unitOptions()\"\n [ariaLabel]=\"l.unit\"\n [value]=\"quickUnit()\"\n (valueChange)=\"setQuickUnit($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-button hx-date-range-quick-select-apply\"\n [attr.aria-describedby]=\"quickError() ? quickErrorId : null\"\n (click)=\"applyQuick()\"\n >\n {{ l.apply }}\n </button>\n </div>\n </section>\n @if (commonlyUsed().length > 0) {\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-common'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-common'\">{{ l.commonlyUsed }}</span>\n <ul class=\"hx-date-range-quick-select-ranges hx-date-range-quick-select-common\">\n @for (range of commonlyUsed(); track $index) {\n <li>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"applyRange(range)\">{{ range.label }}</button>\n </li>\n }\n </ul>\n </section>\n }\n @if (recentItems().length > 0) {\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-recent'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-recent'\">{{ l.recentlyUsed }}</span>\n <ul class=\"hx-date-range-quick-select-ranges hx-date-range-quick-select-recent\">\n @for (item of recentItems(); track item.range.from + ' ' + item.range.to) {\n <li>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"applyRange(item.range)\">{{ item.label }}</button>\n </li>\n }\n </ul>\n </section>\n }\n <!-- one line per side; a click opens the editor of that side (Absolute / Relative / Now) below -->\n <div class=\"hx-date-range-quick-select-summary\" role=\"group\" [attr.aria-label]=\"l.range\">\n @for (s of sideKeys; track s) {\n <button\n #sideButton\n type=\"button\"\n class=\"hx-date-range-quick-select-side-line\"\n [class]=\"'hx-date-range-quick-select-side-line-' + s\"\n [id]=\"sideButtonId(s)\"\n [attr.aria-expanded]=\"openSide() === s\"\n [attr.aria-controls]=\"openSide() === s ? editorId(s) : null\"\n (click)=\"toggleSide(s)\"\n >\n <span class=\"hx-date-range-quick-select-side-name\">{{ s === 'from' ? l.start : l.end }}</span>&ngsp;\n <span class=\"hx-date-range-quick-select-side-value\">{{ sideSummary(s) }}</span>\n </button>\n }\n </div>\n @if (openSide(); as s) {\n @let state = sides()[s];\n @let sideName = s === 'from' ? l.start : l.end;\n <section\n class=\"hx-date-range-quick-select-editor\"\n [class]=\"'hx-date-range-quick-select-editor-' + s\"\n [id]=\"editorId(s)\"\n [attr.aria-labelledby]=\"sideButtonId(s)\"\n >\n <div\n class=\"hx-date-range-quick-select-tabs\"\n role=\"tablist\"\n [attr.aria-labelledby]=\"sideButtonId(s)\"\n (keydown)=\"onTabKeydown(s, $event)\"\n >\n @for (mode of sideModes; track mode) {\n <button\n #sideTab\n type=\"button\"\n role=\"tab\"\n class=\"hx-date-range-quick-select-tab\"\n [id]=\"tabId(s, mode)\"\n [attr.aria-selected]=\"state.mode === mode\"\n [attr.aria-controls]=\"panelId(s)\"\n [attr.tabindex]=\"state.mode === mode ? 0 : -1\"\n (click)=\"setSideMode(s, mode)\"\n >\n {{ mode === 'absolute' ? l.absolute : mode === 'relative' ? l.relative : l.now }}\n </button>\n }\n </div>\n <div\n class=\"hx-date-range-quick-select-tabpanel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n [id]=\"panelId(s)\"\n [attr.aria-labelledby]=\"tabId(s, state.mode)\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n >\n @switch (state.mode) {\n @case ('absolute') {\n <input\n hx-input\n fluid\n type=\"text\"\n autocomplete=\"off\"\n class=\"hx-date-range-quick-select-side-date\"\n [attr.aria-label]=\"sideName + ' ' + l.date\"\n [attr.aria-invalid]=\"sideError() ? 'true' : null\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n [value]=\"sideText(s)\"\n (change)=\"setAbsoluteSide(s, $event)\"\n (keydown.enter)=\"$event.preventDefault(); setAbsoluteSide(s, $event)\"\n />\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n <div class=\"hx-date-range-quick-select-calendar\" role=\"group\" [attr.aria-label]=\"sideName + ' ' + l.date\">\n <hx-calendar\n [(focusedDate)]=\"calendarFocus\"\n [(view)]=\"calendarView\"\n [selectedDates]=\"sideDays(s)\"\n selectionMode=\"single\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"calendarTitleId\"\n [today]=\"today()\"\n (picked)=\"pickDay(s, $event)\"\n />\n </div>\n }\n @case ('relative') {\n <div class=\"hx-date-range-quick-select-row\">\n <input\n hx-input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n class=\"hx-date-range-quick-select-side-amount\"\n [attr.aria-label]=\"l.amount\"\n [attr.aria-invalid]=\"sideError() ? 'true' : null\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n [value]=\"state.amount ?? ''\"\n (input)=\"setSideAmount(s, $event)\"\n />\n <hx-select\n class=\"hx-date-range-quick-select-side-unit\"\n [options]=\"relativeOptions()\"\n [ariaLabel]=\"l.unit\"\n [value]=\"sideUnitValue(s)\"\n (valueChange)=\"setSideUnit(s, $event)\"\n />\n </div>\n <label class=\"hx-date-range-quick-select-side-round\">\n <input type=\"checkbox\" hx-checkbox [checked]=\"state.round\" (change)=\"setSideRound(s, $event)\" />\n {{ sideRoundLabel(s) }}\n </label>\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <code class=\"hx-date-range-quick-select-expression\">{{ sideExpressionText(s) }}</code>&ngsp;\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n }\n @case ('now') {\n <p class=\"hx-date-range-quick-select-now-hint\">{{ l.nowHint }}</p>\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n }\n }\n </div>\n </section>\n }\n @if (quickError() || sideError()) {\n <p class=\"hx-date-range-quick-select-error\" role=\"alert\" [id]=\"quickErrorId\">{{ l.incompleteRange }}</p>\n }\n </div>\n </ng-template>\n</div>\n",
10145
+ dependencies: [
10146
+ {
10147
+ kind: "directive",
10148
+ type: CdkConnectedOverlay,
10149
+ selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]",
10150
+ inputs: [
10151
+ "cdkConnectedOverlayOrigin",
10152
+ "cdkConnectedOverlayPositions",
10153
+ "cdkConnectedOverlayPositionStrategy",
10154
+ "cdkConnectedOverlayOffsetX",
10155
+ "cdkConnectedOverlayOffsetY",
10156
+ "cdkConnectedOverlayWidth",
10157
+ "cdkConnectedOverlayHeight",
10158
+ "cdkConnectedOverlayMinWidth",
10159
+ "cdkConnectedOverlayMinHeight",
10160
+ "cdkConnectedOverlayBackdropClass",
10161
+ "cdkConnectedOverlayPanelClass",
10162
+ "cdkConnectedOverlayViewportMargin",
10163
+ "cdkConnectedOverlayScrollStrategy",
10164
+ "cdkConnectedOverlayOpen",
10165
+ "cdkConnectedOverlayDisableClose",
10166
+ "cdkConnectedOverlayTransformOriginOn",
10167
+ "cdkConnectedOverlayHasBackdrop",
10168
+ "cdkConnectedOverlayLockPosition",
10169
+ "cdkConnectedOverlayFlexibleDimensions",
10170
+ "cdkConnectedOverlayGrowAfterOpen",
10171
+ "cdkConnectedOverlayPush",
10172
+ "cdkConnectedOverlayDisposeOnNavigation",
10173
+ "cdkConnectedOverlayUsePopover",
10174
+ "cdkConnectedOverlayMatchWidth",
10175
+ "cdkConnectedOverlay"
10176
+ ],
10177
+ outputs: [
10178
+ "backdropClick",
10179
+ "positionChange",
10180
+ "attach",
10181
+ "detach",
10182
+ "overlayKeydown",
10183
+ "overlayOutsideClick"
10184
+ ],
10185
+ exportAs: ["cdkConnectedOverlay"]
10186
+ },
10187
+ {
10188
+ kind: "directive",
10189
+ type: CdkOverlayOrigin,
10190
+ selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]",
10191
+ exportAs: ["cdkOverlayOrigin"]
10192
+ },
10193
+ {
10194
+ kind: "component",
10195
+ type: HxCalendar,
10196
+ selector: "hx-calendar",
10197
+ inputs: [
10198
+ "focusedDate",
10199
+ "view",
10200
+ "selectedDates",
10201
+ "selectionMode",
10202
+ "minDate",
10203
+ "maxDate",
10204
+ "disabledDates",
10205
+ "firstDayOfWeek",
10206
+ "locale",
10207
+ "disabled",
10208
+ "titleId",
10209
+ "today"
10210
+ ],
10211
+ outputs: [
10212
+ "focusedDateChange",
10213
+ "viewChange",
10214
+ "picked"
10215
+ ]
10216
+ },
10217
+ {
10218
+ kind: "directive",
10219
+ type: HxCheckbox,
10220
+ selector: "input[hx-checkbox]",
10221
+ inputs: ["size"],
10222
+ exportAs: ["hx-checkbox"]
10223
+ },
10224
+ {
10225
+ kind: "directive",
10226
+ type: HxInput,
10227
+ selector: "input[hx-input], textarea[hx-input]",
10228
+ inputs: [
10229
+ "variant",
10230
+ "size",
10231
+ "fluid",
10232
+ "autoResize"
10233
+ ],
10234
+ exportAs: ["hx-input"]
10235
+ },
10236
+ {
10237
+ kind: "component",
10238
+ type: HxSelect,
10239
+ selector: "hx-select",
10240
+ inputs: [
10241
+ "options",
10242
+ "optionLabel",
10243
+ "optionValue",
10244
+ "optionDisabled",
10245
+ "placeholder",
10246
+ "emptyMessage",
10247
+ "filter",
10248
+ "filterPlaceholder",
10249
+ "filterBy",
10250
+ "emptyFilterMessage",
10251
+ "size",
10252
+ "variant",
10253
+ "fluid",
10254
+ "showClear",
10255
+ "inputId",
10256
+ "ariaLabel",
10257
+ "ariaLabelledby",
10258
+ "ariaDescribedby",
10259
+ "compareWith",
10260
+ "value",
10261
+ "disabled",
10262
+ "invalid"
10263
+ ],
10264
+ outputs: ["valueChange", "touch"]
10265
+ }
10266
+ ],
10267
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
10268
+ });
8337
10269
  };
8338
10270
  i0.ɵɵngDeclareClassMetadata({
8339
10271
  minVersion: "12.0.0",
8340
10272
  version: "22.2.1",
8341
10273
  ngImport: i0,
8342
- type: HxDatePicker,
10274
+ type: HxDateRangeQuickSelect,
8343
10275
  decorators: [{
8344
10276
  type: Component,
8345
10277
  args: [{
8346
- selector: "hx-date-picker",
10278
+ selector: "hx-date-range-quick-select",
8347
10279
  imports: [
8348
10280
  CdkConnectedOverlay,
8349
10281
  CdkOverlayOrigin,
8350
- NgTemplateOutlet,
8351
- HxCalendar
10282
+ HxCalendar,
10283
+ HxCheckbox,
10284
+ HxInput,
10285
+ HxSelect
8352
10286
  ],
8353
10287
  changeDetection: ChangeDetectionStrategy.OnPush,
8354
10288
  providers: [{
8355
10289
  provide: NG_VALUE_ACCESSOR,
8356
- useExisting: forwardRef(() => HxDatePicker),
10290
+ useExisting: forwardRef(() => HxDateRangeQuickSelect),
8357
10291
  multi: true
8358
10292
  }],
8359
10293
  host: {
8360
- class: "hx-date-picker",
8361
- "[class.hx-date-picker-inline]": "inline()",
8362
- "[class.hx-date-picker-disabled]": "isDisabled()",
8363
- "[class.hx-date-picker-invalid]": "invalid()",
8364
- "[class.hx-date-picker-open]": "open()",
8365
- "[class.hx-date-picker-has-icon]": "showIcon() && !inline()",
8366
- "[class.hx-filled]": "!inline() && text() !== \"\"",
10294
+ class: "hx-date-range-quick-select",
8367
10295
  "(focusout)": "onHostFocusOut($event)"
8368
10296
  },
8369
- template: "@if (inline()) {\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n} @else {\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n @if (showIcon()) {\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n }\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? 'Choose date'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n >\n <ng-container [ngTemplateOutlet]=\"calendar\" />\n @if (showButtonBar()) {\n <div class=\"hx-date-picker-buttonbar\">\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"selectToday()\">{{ todayLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n </div>\n }\n </div>\n </ng-template>\n}\n\n<ng-template #calendar>\n<div\n class=\"hx-date-picker-panel\"\n role=\"group\"\n [attr.aria-label]=\"ariaLabel() ?? 'Calendar'\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onFocusOut($event)\"\n>\n <hx-calendar\n [(focusedDate)]=\"focusedDate\"\n [(view)]=\"view\"\n [selectedDates]=\"selectedDates()\"\n [selectionMode]=\"selectionMode()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [disabledDates]=\"disabledDates()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"titleId\"\n [today]=\"today\"\n (picked)=\"pick($event)\"\n />\n</div>\n</ng-template>\n"
10297
+ template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-range-quick-select-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n readonly\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (click)=\"show()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"close()\"\n >\n @let l = texts();\n <div\n class=\"hx-date-picker-popup hx-date-range-quick-select-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-quick'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-quick'\">{{ l.quickSelect }}</span>\n <div class=\"hx-date-range-quick-select-row\">\n <hx-select\n #quickFirst\n class=\"hx-date-range-quick-select-direction\"\n [options]=\"directionOptions()\"\n [ariaLabel]=\"l.direction\"\n [value]=\"quickDirection()\"\n (valueChange)=\"setQuickDirection($event)\"\n />\n <input\n hx-input\n type=\"number\"\n min=\"1\"\n step=\"1\"\n class=\"hx-date-range-quick-select-amount\"\n [attr.aria-label]=\"l.amount\"\n [attr.aria-invalid]=\"quickError() ? 'true' : null\"\n [attr.aria-describedby]=\"quickError() ? quickErrorId : null\"\n [value]=\"quickAmount()\"\n (input)=\"setQuickAmount($event)\"\n (keydown.enter)=\"$event.preventDefault(); applyQuick()\"\n />\n <hx-select\n class=\"hx-date-range-quick-select-unit\"\n [options]=\"unitOptions()\"\n [ariaLabel]=\"l.unit\"\n [value]=\"quickUnit()\"\n (valueChange)=\"setQuickUnit($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-button hx-date-range-quick-select-apply\"\n [attr.aria-describedby]=\"quickError() ? quickErrorId : null\"\n (click)=\"applyQuick()\"\n >\n {{ l.apply }}\n </button>\n </div>\n </section>\n @if (commonlyUsed().length > 0) {\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-common'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-common'\">{{ l.commonlyUsed }}</span>\n <ul class=\"hx-date-range-quick-select-ranges hx-date-range-quick-select-common\">\n @for (range of commonlyUsed(); track $index) {\n <li>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"applyRange(range)\">{{ range.label }}</button>\n </li>\n }\n </ul>\n </section>\n }\n @if (recentItems().length > 0) {\n <section class=\"hx-date-range-quick-select-section\" [attr.aria-labelledby]=\"popupId + '-recent'\">\n <span class=\"hx-date-range-quick-select-caption\" [id]=\"popupId + '-recent'\">{{ l.recentlyUsed }}</span>\n <ul class=\"hx-date-range-quick-select-ranges hx-date-range-quick-select-recent\">\n @for (item of recentItems(); track item.range.from + ' ' + item.range.to) {\n <li>\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"applyRange(item.range)\">{{ item.label }}</button>\n </li>\n }\n </ul>\n </section>\n }\n <!-- one line per side; a click opens the editor of that side (Absolute / Relative / Now) below -->\n <div class=\"hx-date-range-quick-select-summary\" role=\"group\" [attr.aria-label]=\"l.range\">\n @for (s of sideKeys; track s) {\n <button\n #sideButton\n type=\"button\"\n class=\"hx-date-range-quick-select-side-line\"\n [class]=\"'hx-date-range-quick-select-side-line-' + s\"\n [id]=\"sideButtonId(s)\"\n [attr.aria-expanded]=\"openSide() === s\"\n [attr.aria-controls]=\"openSide() === s ? editorId(s) : null\"\n (click)=\"toggleSide(s)\"\n >\n <span class=\"hx-date-range-quick-select-side-name\">{{ s === 'from' ? l.start : l.end }}</span>&ngsp;\n <span class=\"hx-date-range-quick-select-side-value\">{{ sideSummary(s) }}</span>\n </button>\n }\n </div>\n @if (openSide(); as s) {\n @let state = sides()[s];\n @let sideName = s === 'from' ? l.start : l.end;\n <section\n class=\"hx-date-range-quick-select-editor\"\n [class]=\"'hx-date-range-quick-select-editor-' + s\"\n [id]=\"editorId(s)\"\n [attr.aria-labelledby]=\"sideButtonId(s)\"\n >\n <div\n class=\"hx-date-range-quick-select-tabs\"\n role=\"tablist\"\n [attr.aria-labelledby]=\"sideButtonId(s)\"\n (keydown)=\"onTabKeydown(s, $event)\"\n >\n @for (mode of sideModes; track mode) {\n <button\n #sideTab\n type=\"button\"\n role=\"tab\"\n class=\"hx-date-range-quick-select-tab\"\n [id]=\"tabId(s, mode)\"\n [attr.aria-selected]=\"state.mode === mode\"\n [attr.aria-controls]=\"panelId(s)\"\n [attr.tabindex]=\"state.mode === mode ? 0 : -1\"\n (click)=\"setSideMode(s, mode)\"\n >\n {{ mode === 'absolute' ? l.absolute : mode === 'relative' ? l.relative : l.now }}\n </button>\n }\n </div>\n <div\n class=\"hx-date-range-quick-select-tabpanel\"\n role=\"tabpanel\"\n tabindex=\"0\"\n [id]=\"panelId(s)\"\n [attr.aria-labelledby]=\"tabId(s, state.mode)\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n >\n @switch (state.mode) {\n @case ('absolute') {\n <input\n hx-input\n fluid\n type=\"text\"\n autocomplete=\"off\"\n class=\"hx-date-range-quick-select-side-date\"\n [attr.aria-label]=\"sideName + ' ' + l.date\"\n [attr.aria-invalid]=\"sideError() ? 'true' : null\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n [value]=\"sideText(s)\"\n (change)=\"setAbsoluteSide(s, $event)\"\n (keydown.enter)=\"$event.preventDefault(); setAbsoluteSide(s, $event)\"\n />\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n <div class=\"hx-date-range-quick-select-calendar\" role=\"group\" [attr.aria-label]=\"sideName + ' ' + l.date\">\n <hx-calendar\n [(focusedDate)]=\"calendarFocus\"\n [(view)]=\"calendarView\"\n [selectedDates]=\"sideDays(s)\"\n selectionMode=\"single\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n [titleId]=\"calendarTitleId\"\n [today]=\"today()\"\n (picked)=\"pickDay(s, $event)\"\n />\n </div>\n }\n @case ('relative') {\n <div class=\"hx-date-range-quick-select-row\">\n <input\n hx-input\n type=\"number\"\n min=\"0\"\n step=\"1\"\n class=\"hx-date-range-quick-select-side-amount\"\n [attr.aria-label]=\"l.amount\"\n [attr.aria-invalid]=\"sideError() ? 'true' : null\"\n [attr.aria-describedby]=\"sideError() ? quickErrorId : null\"\n [value]=\"state.amount ?? ''\"\n (input)=\"setSideAmount(s, $event)\"\n />\n <hx-select\n class=\"hx-date-range-quick-select-side-unit\"\n [options]=\"relativeOptions()\"\n [ariaLabel]=\"l.unit\"\n [value]=\"sideUnitValue(s)\"\n (valueChange)=\"setSideUnit(s, $event)\"\n />\n </div>\n <label class=\"hx-date-range-quick-select-side-round\">\n <input type=\"checkbox\" hx-checkbox [checked]=\"state.round\" (change)=\"setSideRound(s, $event)\" />\n {{ sideRoundLabel(s) }}\n </label>\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <code class=\"hx-date-range-quick-select-expression\">{{ sideExpressionText(s) }}</code>&ngsp;\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n }\n @case ('now') {\n <p class=\"hx-date-range-quick-select-now-hint\">{{ l.nowHint }}</p>\n <p class=\"hx-date-range-quick-select-side-resolved\">\n <span class=\"hx-date-range-quick-select-resolved-date\">{{ sideResolvedText(s) }}</span>\n </p>\n }\n }\n </div>\n </section>\n }\n @if (quickError() || sideError()) {\n <p class=\"hx-date-range-quick-select-error\" role=\"alert\" [id]=\"quickErrorId\">{{ l.incompleteRange }}</p>\n }\n </div>\n </ng-template>\n</div>\n"
8370
10298
  }]
8371
10299
  }],
8372
10300
  ctorParameters: () => [],
8373
10301
  propDecorators: {
8374
- placeholder: [{
8375
- type: i0.Input,
8376
- args: [{
8377
- isSignal: true,
8378
- alias: "placeholder",
8379
- required: false
8380
- }]
8381
- }],
8382
- showIcon: [{
8383
- type: i0.Input,
8384
- args: [{
8385
- isSignal: true,
8386
- alias: "showIcon",
8387
- required: false
8388
- }]
8389
- }],
8390
- showButtonBar: [{
10302
+ labels: [{
8391
10303
  type: i0.Input,
8392
10304
  args: [{
8393
10305
  isSignal: true,
8394
- alias: "showButtonBar",
10306
+ alias: "labels",
8395
10307
  required: false
8396
10308
  }]
8397
10309
  }],
8398
- dateFormat: [{
10310
+ commonlyUsed: [{
8399
10311
  type: i0.Input,
8400
10312
  args: [{
8401
10313
  isSignal: true,
8402
- alias: "dateFormat",
10314
+ alias: "commonlyUsed",
8403
10315
  required: false
8404
10316
  }]
8405
10317
  }],
8406
- todayLabel: [{
10318
+ recentStorageKey: [{
8407
10319
  type: i0.Input,
8408
10320
  args: [{
8409
10321
  isSignal: true,
8410
- alias: "todayLabel",
10322
+ alias: "recentStorageKey",
8411
10323
  required: false
8412
10324
  }]
8413
10325
  }],
8414
- clearLabel: [{
10326
+ expression: [{
8415
10327
  type: i0.Input,
8416
10328
  args: [{
8417
10329
  isSignal: true,
8418
- alias: "clearLabel",
10330
+ alias: "expression",
8419
10331
  required: false
8420
10332
  }]
10333
+ }, {
10334
+ type: i0.Output,
10335
+ args: ["expressionChange"]
8421
10336
  }],
8422
- chooseLabel: [{
10337
+ minDate: [{
8423
10338
  type: i0.Input,
8424
10339
  args: [{
8425
10340
  isSignal: true,
8426
- alias: "chooseLabel",
10341
+ alias: "minDate",
8427
10342
  required: false
8428
10343
  }]
8429
10344
  }],
8430
- inputId: [{
10345
+ maxDate: [{
8431
10346
  type: i0.Input,
8432
10347
  args: [{
8433
10348
  isSignal: true,
8434
- alias: "inputId",
10349
+ alias: "maxDate",
8435
10350
  required: false
8436
10351
  }]
8437
10352
  }],
8438
- inline: [{
10353
+ firstDayOfWeek: [{
8439
10354
  type: i0.Input,
8440
10355
  args: [{
8441
10356
  isSignal: true,
8442
- alias: "inline",
10357
+ alias: "firstDayOfWeek",
8443
10358
  required: false
8444
10359
  }]
8445
10360
  }],
8446
- selectionMode: [{
10361
+ locale: [{
8447
10362
  type: i0.Input,
8448
10363
  args: [{
8449
10364
  isSignal: true,
8450
- alias: "selectionMode",
10365
+ alias: "locale",
8451
10366
  required: false
8452
10367
  }]
8453
10368
  }],
8454
- minDate: [{
10369
+ dateFormat: [{
8455
10370
  type: i0.Input,
8456
10371
  args: [{
8457
10372
  isSignal: true,
8458
- alias: "minDate",
10373
+ alias: "dateFormat",
8459
10374
  required: false
8460
10375
  }]
8461
10376
  }],
8462
- maxDate: [{
10377
+ separator: [{
8463
10378
  type: i0.Input,
8464
10379
  args: [{
8465
10380
  isSignal: true,
8466
- alias: "maxDate",
10381
+ alias: "separator",
8467
10382
  required: false
8468
10383
  }]
8469
10384
  }],
8470
- disabledDates: [{
10385
+ placeholder: [{
8471
10386
  type: i0.Input,
8472
10387
  args: [{
8473
10388
  isSignal: true,
8474
- alias: "disabledDates",
10389
+ alias: "placeholder",
8475
10390
  required: false
8476
10391
  }]
8477
10392
  }],
8478
- firstDayOfWeek: [{
10393
+ chooseLabel: [{
8479
10394
  type: i0.Input,
8480
10395
  args: [{
8481
10396
  isSignal: true,
8482
- alias: "firstDayOfWeek",
10397
+ alias: "chooseLabel",
8483
10398
  required: false
8484
10399
  }]
8485
10400
  }],
8486
- locale: [{
10401
+ inputId: [{
8487
10402
  type: i0.Input,
8488
10403
  args: [{
8489
10404
  isSignal: true,
8490
- alias: "locale",
10405
+ alias: "inputId",
8491
10406
  required: false
8492
10407
  }]
8493
10408
  }],
@@ -8542,9 +10457,20 @@ i0.ɵɵngDeclareClassMetadata({
8542
10457
  type: i0.ViewChild,
8543
10458
  args: ["field", { isSignal: true }]
8544
10459
  }],
8545
- calendar: [{
10460
+ quickFirst: [{
8546
10461
  type: i0.ViewChild,
8547
- args: [i0.forwardRef(() => HxCalendar), { isSignal: true }]
10462
+ args: ["quickFirst", {
10463
+ read: HxSelect,
10464
+ isSignal: true
10465
+ }]
10466
+ }],
10467
+ sideButtons: [{
10468
+ type: i0.ViewChildren,
10469
+ args: ["sideButton", { isSignal: true }]
10470
+ }],
10471
+ sideTabs: [{
10472
+ type: i0.ViewChildren,
10473
+ args: ["sideTab", { isSignal: true }]
8548
10474
  }]
8549
10475
  }
8550
10476
  });
@@ -10766,6 +12692,7 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
10766
12692
  placeholder = input("", ...ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []);
10767
12693
  presetsLabel = input("Presets", ...ngDevMode ? [{ debugName: "presetsLabel" }] : /* istanbul ignore next */ []);
10768
12694
  presets = input([], ...ngDevMode ? [{ debugName: "presets" }] : /* istanbul ignore next */ []);
12695
+ presetDisplay = input("buttons", ...ngDevMode ? [{ debugName: "presetDisplay" }] : /* istanbul ignore next */ []);
10769
12696
  clearLabel = input("Clear", ...ngDevMode ? [{ debugName: "clearLabel" }] : /* istanbul ignore next */ []);
10770
12697
  cancelLabel = input("Cancel", ...ngDevMode ? [{ debugName: "cancelLabel" }] : /* istanbul ignore next */ []);
10771
12698
  submitLabel = input("Submit", ...ngDevMode ? [{ debugName: "submitLabel" }] : /* istanbul ignore next */ []);
@@ -10833,6 +12760,7 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
10833
12760
  #injector = inject(Injector);
10834
12761
  open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
10835
12762
  draft = signal(EMPTY, ...ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []);
12763
+ selectedPreset = signal(null, ...ngDevMode ? [{ debugName: "selectedPreset" }] : /* istanbul ignore next */ []);
10836
12764
  popupId = nextId("hx-date-time-range-picker-popup");
10837
12765
  positions = [{
10838
12766
  originX: "start",
@@ -10875,8 +12803,7 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
10875
12803
  if (typed !== null) return typed;
10876
12804
  const { from, to } = this.value();
10877
12805
  if (!from && !to) return "";
10878
- const fmt = this.#format();
10879
- const one = (d) => d ? fmt.format(d).replace(/,\s*/, " ") : "";
12806
+ const one = (d) => d ? this.#formatDate(d) : "";
10880
12807
  return `${one(from)} ${this.separator()} ${one(to)}`.trim();
10881
12808
  }, ...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
10882
12809
  isDisabled = computed(() => this.disabled() || this.#cvaDisabled(), ...ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []);
@@ -10914,6 +12841,7 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
10914
12841
  show() {
10915
12842
  if (this.isDisabled() || this.open()) return;
10916
12843
  this.#stage(this.value());
12844
+ this.selectedPreset.set(null);
10917
12845
  this.open.set(true);
10918
12846
  }
10919
12847
  toggle() {
@@ -11005,23 +12933,24 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11005
12933
  }
11006
12934
  }
11007
12935
  onOutsideClick(event) {
12936
+ if (this.#inSelectList(event.target)) return;
11008
12937
  if (!this.#host.nativeElement.contains(event.target)) this.close();
11009
12938
  }
11010
12939
  clear() {
11011
12940
  this.#stage(EMPTY);
11012
12941
  }
12942
+ selectPreset(preset) {
12943
+ if (this.applyPreset(preset)) this.selectedPreset.set(preset);
12944
+ }
12945
+ #inSelectList(target) {
12946
+ return isInSelectOverlay(target);
12947
+ }
11013
12948
  applyPreset(preset) {
11014
12949
  const { from: oldFrom, to: oldTo } = this.draft();
11015
- const from = this.#fitPreset(preset.from(), oldFrom);
11016
- const to = this.#fitPreset(preset.to(), oldTo ?? oldFrom);
11017
- if (from === void 0 || to === void 0) return;
11018
- this.#stage(from && to && to < from ? {
11019
- from: to,
11020
- to: from
11021
- } : {
11022
- from,
11023
- to
11024
- });
12950
+ const range = hxResolvePreset(preset, { firstDayOfWeek: this.firstDayOfWeek() }, (date, side) => this.#fitPreset(date, side === "from" ? oldFrom : oldTo ?? oldFrom));
12951
+ if (!range) return false;
12952
+ this.#stage(range);
12953
+ return true;
11025
12954
  }
11026
12955
  #fitPreset(date, old) {
11027
12956
  if (!isValidDate(date)) return null;
@@ -11035,16 +12964,19 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11035
12964
  this.#commit(this.draft());
11036
12965
  this.close(true);
11037
12966
  }
12967
+ #formatDate(date) {
12968
+ return this.#format().format(date).replace(/,\s*/, " ");
12969
+ }
11038
12970
  onHostFocusOut(event) {
11039
12971
  const next = event.relatedTarget;
11040
- if (next?.closest(".hx-date-time-range-picker-popup") || this.#host.nativeElement.contains(next)) return;
12972
+ if (this.#inSelectList(next) || next?.closest(".hx-date-time-range-picker-popup") || this.#host.nativeElement.contains(next)) return;
11041
12973
  if (this.open() && !next) return;
11042
12974
  this.close();
11043
12975
  this.markTouched();
11044
12976
  }
11045
12977
  onPopupFocusOut(event) {
11046
12978
  const next = event.relatedTarget;
11047
- if (!next || next.closest(".hx-date-time-range-picker-popup") || this.#host.nativeElement.contains(next)) return;
12979
+ if (!next || this.#inSelectList(next) || next.closest(".hx-date-time-range-picker-popup") || this.#host.nativeElement.contains(next)) return;
11048
12980
  this.close();
11049
12981
  this.markTouched();
11050
12982
  }
@@ -11116,14 +13048,18 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11116
13048
  this.touch.emit();
11117
13049
  }
11118
13050
  #stage(next) {
13051
+ const clean = this.#inside(next);
13052
+ this.selectedPreset.set(null);
13053
+ if (clean.from) this.#lastFrom = clean.from;
13054
+ if (clean.to) this.#lastTo = clean.to;
13055
+ this.draft.set(clean);
13056
+ }
13057
+ #inside(next) {
11119
13058
  const inside = (d) => isValidDate(d) ? clampTime(d, this.minDate(), this.maxDate()) : null;
11120
- const clean = {
13059
+ return {
11121
13060
  from: inside(next.from),
11122
13061
  to: inside(next.to)
11123
13062
  };
11124
- if (clean.from) this.#lastFrom = clean.from;
11125
- if (clean.to) this.#lastTo = clean.to;
11126
- this.draft.set(clean);
11127
13063
  }
11128
13064
  #commit(next) {
11129
13065
  this.value.set(next);
@@ -11186,6 +13122,13 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11186
13122
  isRequired: false,
11187
13123
  transformFunction: null
11188
13124
  },
13125
+ presetDisplay: {
13126
+ classPropertyName: "presetDisplay",
13127
+ publicName: "presetDisplay",
13128
+ isSignal: true,
13129
+ isRequired: false,
13130
+ transformFunction: null
13131
+ },
11189
13132
  clearLabel: {
11190
13133
  classPropertyName: "clearLabel",
11191
13134
  publicName: "clearLabel",
@@ -11406,7 +13349,7 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11406
13349
  }
11407
13350
  ],
11408
13351
  ngImport: i0,
11409
- template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-time-range-picker-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n [readOnly]=\"!typeable()\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"onFieldClick()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup hx-date-time-range-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n @if (presets().length > 0) {\n <div class=\"hx-date-time-range-picker-presets\" role=\"group\" [attr.aria-label]=\"presetsLabel()\">\n @for (preset of presets(); track $index) {\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-preset\" (click)=\"applyPreset(preset)\">{{ preset.label }}</button>\n }\n </div>\n }\n <div class=\"hx-date-time-range-picker-body\">\n @if (!timeOnly()) {\n <hx-date-picker\n class=\"hx-date-time-range-picker-days\"\n inline\n selectionMode=\"range\"\n [ariaLabel]=\"chooseLabel()\"\n [value]=\"days()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [locale]=\"locale()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [disabledDates]=\"disabledDates()\"\n (valueChange)=\"setDays($event)\"\n />\n }\n @if (showTime() || timeOnly()) {\n <div class=\"hx-date-time-range-picker-times\">\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ fromLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-from\"\n [ariaLabel]=\"fromLabel()\"\n [value]=\"fromValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setFromTime($event)\"\n />\n </div>\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ toLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-to\"\n [ariaLabel]=\"toLabel()\"\n [value]=\"toValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setToTime($event)\"\n />\n </div>\n </div>\n }\n </div>\n <div class=\"hx-date-picker-buttonbar hx-date-time-range-picker-footer\">\n @if (showButtonBar()) {\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n }\n <span class=\"hx-date-time-range-picker-spacer\"></span>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-cancel\" (click)=\"close(true)\">{{ cancelLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-submit\" (click)=\"submit()\">{{ submitLabel() }}</button>\n </div>\n </div>\n </ng-template>\n</div>\n",
13352
+ template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-time-range-picker-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n [readOnly]=\"!typeable()\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"onFieldClick()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup hx-date-time-range-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n @if (presets().length > 0) {\n <hx-range-presets\n [presets]=\"presets()\"\n [display]=\"presetDisplay()\"\n [label]=\"presetsLabel()\"\n [disabled]=\"isDisabled()\"\n [selected]=\"selectedPreset()\"\n (chosen)=\"selectPreset($event)\"\n />\n }\n <div class=\"hx-date-time-range-picker-body\">\n @if (!timeOnly()) {\n <hx-date-picker\n class=\"hx-date-time-range-picker-days\"\n inline\n selectionMode=\"range\"\n [ariaLabel]=\"chooseLabel()\"\n [value]=\"days()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [locale]=\"locale()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [disabledDates]=\"disabledDates()\"\n (valueChange)=\"setDays($event)\"\n />\n }\n @if (showTime() || timeOnly()) {\n <div class=\"hx-date-time-range-picker-times\">\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ fromLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-from\"\n [ariaLabel]=\"fromLabel()\"\n [value]=\"fromValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setFromTime($event)\"\n />\n </div>\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ toLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-to\"\n [ariaLabel]=\"toLabel()\"\n [value]=\"toValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setToTime($event)\"\n />\n </div>\n </div>\n }\n </div>\n <div class=\"hx-date-picker-buttonbar hx-date-time-range-picker-footer\">\n @if (showButtonBar()) {\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n }\n <span class=\"hx-date-time-range-picker-spacer\"></span>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-cancel\" (click)=\"close(true)\">{{ cancelLabel() }}</button>\n <button\n type=\"button\"\n class=\"hx-date-picker-button hx-date-time-range-picker-submit\"\n (click)=\"submit()\"\n >{{ submitLabel() }}</button>\n </div>\n </div>\n </ng-template>\n</div>\n",
11410
13353
  dependencies: [
11411
13354
  {
11412
13355
  kind: "directive",
@@ -11477,12 +13420,30 @@ var HxDateTimeRangePicker = class HxDateTimeRangePicker {
11477
13420
  "locale",
11478
13421
  "ariaLabel",
11479
13422
  "ariaLabelledby",
13423
+ "presets",
13424
+ "presetDisplay",
13425
+ "presetsLabel",
13426
+ "presetRefusedLabel",
11480
13427
  "value",
11481
13428
  "disabled",
11482
13429
  "invalid"
11483
13430
  ],
11484
13431
  outputs: ["valueChange", "touch"]
11485
13432
  },
13433
+ {
13434
+ kind: "component",
13435
+ type: HxRangePresets,
13436
+ selector: "hx-range-presets",
13437
+ inputs: [
13438
+ "presets",
13439
+ "display",
13440
+ "label",
13441
+ "disabled",
13442
+ "selected",
13443
+ "describedBy"
13444
+ ],
13445
+ outputs: ["chosen"]
13446
+ },
11486
13447
  {
11487
13448
  kind: "component",
11488
13449
  type: HxTimePicker,
@@ -11536,6 +13497,7 @@ i0.ɵɵngDeclareClassMetadata({
11536
13497
  CdkConnectedOverlay,
11537
13498
  CdkOverlayOrigin,
11538
13499
  HxDatePicker,
13500
+ HxRangePresets,
11539
13501
  HxTimePicker
11540
13502
  ],
11541
13503
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -11548,7 +13510,7 @@ i0.ɵɵngDeclareClassMetadata({
11548
13510
  class: "hx-date-time-range-picker",
11549
13511
  "(focusout)": "onHostFocusOut($event)"
11550
13512
  },
11551
- template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-time-range-picker-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n [readOnly]=\"!typeable()\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"onFieldClick()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup hx-date-time-range-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n @if (presets().length > 0) {\n <div class=\"hx-date-time-range-picker-presets\" role=\"group\" [attr.aria-label]=\"presetsLabel()\">\n @for (preset of presets(); track $index) {\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-preset\" (click)=\"applyPreset(preset)\">{{ preset.label }}</button>\n }\n </div>\n }\n <div class=\"hx-date-time-range-picker-body\">\n @if (!timeOnly()) {\n <hx-date-picker\n class=\"hx-date-time-range-picker-days\"\n inline\n selectionMode=\"range\"\n [ariaLabel]=\"chooseLabel()\"\n [value]=\"days()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [locale]=\"locale()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [disabledDates]=\"disabledDates()\"\n (valueChange)=\"setDays($event)\"\n />\n }\n @if (showTime() || timeOnly()) {\n <div class=\"hx-date-time-range-picker-times\">\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ fromLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-from\"\n [ariaLabel]=\"fromLabel()\"\n [value]=\"fromValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setFromTime($event)\"\n />\n </div>\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ toLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-to\"\n [ariaLabel]=\"toLabel()\"\n [value]=\"toValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setToTime($event)\"\n />\n </div>\n </div>\n }\n </div>\n <div class=\"hx-date-picker-buttonbar hx-date-time-range-picker-footer\">\n @if (showButtonBar()) {\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n }\n <span class=\"hx-date-time-range-picker-spacer\"></span>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-cancel\" (click)=\"close(true)\">{{ cancelLabel() }}</button>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-submit\" (click)=\"submit()\">{{ submitLabel() }}</button>\n </div>\n </div>\n </ng-template>\n</div>\n"
13513
+ template: "<div\n class=\"hx-date-picker hx-date-picker-has-icon hx-date-time-range-picker-control\"\n [class.hx-date-picker-open]=\"open()\"\n [class.hx-date-picker-disabled]=\"isDisabled()\"\n [class.hx-date-picker-invalid]=\"invalid()\"\n>\n <div class=\"hx-date-picker-field\" cdkOverlayOrigin #origin=\"cdkOverlayOrigin\">\n <input\n #field\n type=\"text\"\n [readOnly]=\"!typeable()\"\n class=\"hx-date-picker-input\"\n autocomplete=\"off\"\n aria-haspopup=\"dialog\"\n [attr.id]=\"inputId() ?? null\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [value]=\"text()\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"open() ? popupId : null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n [attr.aria-invalid]=\"invalid() ? 'true' : null\"\n (input)=\"onTyping($event)\"\n (change)=\"commitTyping()\"\n (click)=\"onFieldClick()\"\n (keydown)=\"onFieldKeydown($event)\"\n />\n <button\n type=\"button\"\n class=\"hx-date-picker-trigger\"\n aria-haspopup=\"dialog\"\n [attr.aria-label]=\"chooseLabel()\"\n [attr.aria-expanded]=\"open()\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n >\n <span class=\"hx-date-picker-trigger-icon\" aria-hidden=\"true\"></span>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n cdkConnectedOverlayPanelClass=\"hx-date-picker-overlay\"\n [cdkConnectedOverlayOrigin]=\"origin\"\n [cdkConnectedOverlayOpen]=\"open()\"\n [cdkConnectedOverlayPositions]=\"positions\"\n [cdkConnectedOverlayPush]=\"true\"\n (overlayOutsideClick)=\"onOutsideClick($event)\"\n (overlayKeydown)=\"onOverlayKeydown($event)\"\n (attach)=\"onAttach()\"\n (detach)=\"open.set(false)\"\n >\n <div\n class=\"hx-date-picker-popup hx-date-time-range-picker-popup\"\n role=\"dialog\"\n aria-modal=\"false\"\n [id]=\"popupId\"\n [attr.aria-label]=\"ariaLabel() ?? chooseLabel()\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (focusout)=\"onPopupFocusOut($event)\"\n >\n @if (presets().length > 0) {\n <hx-range-presets\n [presets]=\"presets()\"\n [display]=\"presetDisplay()\"\n [label]=\"presetsLabel()\"\n [disabled]=\"isDisabled()\"\n [selected]=\"selectedPreset()\"\n (chosen)=\"selectPreset($event)\"\n />\n }\n <div class=\"hx-date-time-range-picker-body\">\n @if (!timeOnly()) {\n <hx-date-picker\n class=\"hx-date-time-range-picker-days\"\n inline\n selectionMode=\"range\"\n [ariaLabel]=\"chooseLabel()\"\n [value]=\"days()\"\n [minDate]=\"minDate()\"\n [maxDate]=\"maxDate()\"\n [locale]=\"locale()\"\n [firstDayOfWeek]=\"firstDayOfWeek()\"\n [disabledDates]=\"disabledDates()\"\n (valueChange)=\"setDays($event)\"\n />\n }\n @if (showTime() || timeOnly()) {\n <div class=\"hx-date-time-range-picker-times\">\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ fromLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-from\"\n [ariaLabel]=\"fromLabel()\"\n [value]=\"fromValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setFromTime($event)\"\n />\n </div>\n <div class=\"hx-date-time-range-picker-time\">\n <span class=\"hx-date-time-range-picker-caption\" aria-hidden=\"true\">{{ toLabel() }}</span>\n <hx-time-picker\n inline\n class=\"hx-date-time-range-picker-to\"\n [ariaLabel]=\"toLabel()\"\n [value]=\"toValue()\"\n [hourFormat]=\"hourFormat()\"\n [showMinutes]=\"showMinutes()\"\n [showSeconds]=\"showSeconds()\"\n [stepHour]=\"stepHour()\"\n [stepMinute]=\"stepMinute()\"\n [stepSecond]=\"stepSecond()\"\n [locale]=\"locale()\"\n [disabled]=\"isDisabled()\"\n (valueChange)=\"setToTime($event)\"\n />\n </div>\n </div>\n }\n </div>\n <div class=\"hx-date-picker-buttonbar hx-date-time-range-picker-footer\">\n @if (showButtonBar()) {\n <button type=\"button\" class=\"hx-date-picker-button\" (click)=\"clear()\">{{ clearLabel() }}</button>\n }\n <span class=\"hx-date-time-range-picker-spacer\"></span>\n <button type=\"button\" class=\"hx-date-picker-button hx-date-time-range-picker-cancel\" (click)=\"close(true)\">{{ cancelLabel() }}</button>\n <button\n type=\"button\"\n class=\"hx-date-picker-button hx-date-time-range-picker-submit\"\n (click)=\"submit()\"\n >{{ submitLabel() }}</button>\n </div>\n </div>\n </ng-template>\n</div>\n"
11552
13514
  }]
11553
13515
  }],
11554
13516
  ctorParameters: () => [],
@@ -11601,6 +13563,14 @@ i0.ɵɵngDeclareClassMetadata({
11601
13563
  required: false
11602
13564
  }]
11603
13565
  }],
13566
+ presetDisplay: [{
13567
+ type: i0.Input,
13568
+ args: [{
13569
+ isSignal: true,
13570
+ alias: "presetDisplay",
13571
+ required: false
13572
+ }]
13573
+ }],
11604
13574
  clearLabel: [{
11605
13575
  type: i0.Input,
11606
13576
  args: [{
@@ -23846,6 +25816,6 @@ i0.ɵɵngDeclareClassMetadata({
23846
25816
  }]
23847
25817
  }
23848
25818
  });
23849
- export { HX_DIALOG_DATA, HX_PRIMARY_COLORS, HX_SURFACES, HX_SURFACE_NAMES, HX_THEME_OPTIONS, HxAccordion, HxAccordionContent, HxAccordionHeader, HxAccordionPanel, HxAutoComplete, HxAvatar, HxAvatarGroup, HxBadge, HxBreadcrumb, HxButton, HxButtonGroup, HxCard, HxCarousel, HxCarouselItem, HxCell, HxCheckbox, HxChip, HxColumnHeader, HxConfirmDialog, HxConfirmPopup, HxConfirmationService, HxDataTable, HxDatePicker, HxDateTimePicker, HxDateTimeRangePicker, HxDialog, HxDialogRef, HxDialogService, HxDivider, HxDrawer, HxFieldset, HxFileUpload, HxFloatLabel, HxGalleria, HxGalleriaCaption, HxGalleriaItemTemplate, HxGalleriaThumbnail, HxIconField, HxImage, HxImageIndicator, HxInput, HxInputGroup, HxInputGroupAddon, HxInputIcon, HxInputNumber, HxListbox, HxMenu, HxMenubar, HxMessage, HxMessageService, HxMultiSelect, HxOverlayBadge, HxPaginator, HxPanel, HxPassword, HxPopover, HxProgressBar, HxProgressSpinner, HxRadio, HxRating, HxRowExpansion, HxSelect, HxSelectButton, HxSkeleton, HxSlider, HxSplitButton, HxStep, HxStepContent, HxStepList, HxStepPanel, HxStepPanels, HxStepper, HxSwitch, HxTab, HxTabContent, HxTabList, HxTabPanel, HxTabPanels, HxTable, HxTableBody, HxTableCaption, HxTableEmpty, HxTableFooter, HxTableHeader, HxTabs, HxTag, HxTheme, HxTimePicker, HxTimeline, HxTimelineContent, HxTimelineMarker, HxTimelineOpposite, HxToast, HxToastItem, HxToggleButton, HxToolbar, HxTooltip, HxTree, HxTreeNodeTemplate, compareValues, formatFileSize, matchesAccept, provideHxTheme, resolveField };
25819
+ export { HX_DATE_RANGE_DAY_PRESETS, HX_DATE_RANGE_PRESETS, HX_DIALOG_DATA, HX_PRIMARY_COLORS, HX_QUICK_SELECT_COMMONLY_USED, HX_QUICK_SELECT_LABELS, HX_SURFACES, HX_SURFACE_NAMES, HX_THEME_OPTIONS, HxAccordion, HxAccordionContent, HxAccordionHeader, HxAccordionPanel, HxAutoComplete, HxAvatar, HxAvatarGroup, HxBadge, HxBreadcrumb, HxButton, HxButtonGroup, HxCard, HxCarousel, HxCarouselItem, HxCell, HxCheckbox, HxChip, HxColumnHeader, HxConfirmDialog, HxConfirmPopup, HxConfirmationService, HxDataTable, HxDatePicker, HxDateRangeQuickSelect, HxDateTimePicker, HxDateTimeRangePicker, HxDialog, HxDialogRef, HxDialogService, HxDivider, HxDrawer, HxFieldset, HxFileUpload, HxFloatLabel, HxGalleria, HxGalleriaCaption, HxGalleriaItemTemplate, HxGalleriaThumbnail, HxIconField, HxImage, HxImageIndicator, HxInput, HxInputGroup, HxInputGroupAddon, HxInputIcon, HxInputNumber, HxListbox, HxMenu, HxMenubar, HxMessage, HxMessageService, HxMultiSelect, HxOverlayBadge, HxPaginator, HxPanel, HxPassword, HxPopover, HxProgressBar, HxProgressSpinner, HxRadio, HxRating, HxRowExpansion, HxSelect, HxSelectButton, HxSkeleton, HxSlider, HxSplitButton, HxStep, HxStepContent, HxStepList, HxStepPanel, HxStepPanels, HxStepper, HxSwitch, HxTab, HxTabContent, HxTabList, HxTabPanel, HxTabPanels, HxTable, HxTableBody, HxTableCaption, HxTableEmpty, HxTableFooter, HxTableHeader, HxTabs, HxTag, HxTheme, HxTimePicker, HxTimeline, HxTimelineContent, HxTimelineMarker, HxTimelineOpposite, HxToast, HxToastItem, HxToggleButton, HxToolbar, HxTooltip, HxTree, HxTreeNodeTemplate, compareValues, formatFileSize, hxDateRangePresets, hxParseDateMath, hxRelativeRangeExpressions, hxResolveRangeExpression, hxResolveRangeSide, matchesAccept, provideHxTheme, resolveField };
23850
25820
 
23851
25821
  //# sourceMappingURL=gravionlabs-helix-ui.mjs.map