ngwr 9.0.1 → 10.0.0

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.
Files changed (108) hide show
  1. package/README.md +14 -0
  2. package/badge/styles/_index.scss +16 -6
  3. package/badge/styles/_tag.scss +10 -1
  4. package/button/styles/_index.scss +48 -1
  5. package/date-picker/styles/_index.scss +62 -0
  6. package/dialog/styles/_index.scss +65 -0
  7. package/drawer/styles/_index.scss +83 -0
  8. package/fesm2022/ngwr-action-sheet.mjs +1 -1
  9. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  10. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  11. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  12. package/fesm2022/ngwr-card.mjs +2 -2
  13. package/fesm2022/ngwr-card.mjs.map +1 -1
  14. package/fesm2022/ngwr-cascader.mjs +6 -5
  15. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  16. package/fesm2022/ngwr-color-picker.mjs +6 -5
  17. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  18. package/fesm2022/ngwr-context-menu.mjs +7 -7
  19. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  20. package/fesm2022/ngwr-date-picker.mjs +521 -8
  21. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  22. package/fesm2022/ngwr-density.mjs +10 -2
  23. package/fesm2022/ngwr-density.mjs.map +1 -1
  24. package/fesm2022/ngwr-dialog.mjs +95 -13
  25. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  26. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  27. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  28. package/fesm2022/ngwr-drawer.mjs +377 -22
  29. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  30. package/fesm2022/ngwr-dropdown.mjs +4 -3
  31. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  32. package/fesm2022/ngwr-i18n-en.mjs +21 -0
  33. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  34. package/fesm2022/ngwr-i18n-ru.mjs +22 -0
  35. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  36. package/fesm2022/ngwr-i18n.mjs +74 -1
  37. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  38. package/fesm2022/ngwr-icon.mjs +74 -35
  39. package/fesm2022/ngwr-icon.mjs.map +1 -1
  40. package/fesm2022/ngwr-lightbox.mjs +2 -2
  41. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  42. package/fesm2022/ngwr-list.mjs +2 -2
  43. package/fesm2022/ngwr-list.mjs.map +1 -1
  44. package/fesm2022/ngwr-mention.mjs +166 -10
  45. package/fesm2022/ngwr-mention.mjs.map +1 -1
  46. package/fesm2022/ngwr-overlay.mjs +173 -3
  47. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  48. package/fesm2022/ngwr-pagination.mjs +17 -4
  49. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  50. package/fesm2022/ngwr-popconfirm.mjs +4 -3
  51. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  52. package/fesm2022/ngwr-popover.mjs +10 -3
  53. package/fesm2022/ngwr-popover.mjs.map +1 -1
  54. package/fesm2022/ngwr-select.mjs +233 -43
  55. package/fesm2022/ngwr-select.mjs.map +1 -1
  56. package/fesm2022/ngwr-table.mjs +1 -1
  57. package/fesm2022/ngwr-table.mjs.map +1 -1
  58. package/fesm2022/ngwr-theme.mjs +13 -3
  59. package/fesm2022/ngwr-theme.mjs.map +1 -1
  60. package/fesm2022/ngwr-tree.mjs +4 -3
  61. package/fesm2022/ngwr-tree.mjs.map +1 -1
  62. package/fesm2022/ngwr-version.mjs +1 -1
  63. package/fesm2022/ngwr-version.mjs.map +1 -1
  64. package/fesm2022/ngwr-waves.mjs +25 -3
  65. package/fesm2022/ngwr-waves.mjs.map +1 -1
  66. package/i18n/en.json +165 -0
  67. package/i18n/ru.json +165 -0
  68. package/icon/styles/_index.scss +10 -1
  69. package/input/styles/_index.scss +16 -0
  70. package/input-number/styles/_index.scss +8 -1
  71. package/keyboard/styles/_index.scss +10 -3
  72. package/llms-full.txt +14 -14
  73. package/llms.txt +12 -6
  74. package/mention/styles/_index.scss +23 -0
  75. package/package.json +23 -5
  76. package/pagination/styles/_index.scss +12 -0
  77. package/popover/styles/_index.scss +129 -45
  78. package/schematics/ng-add/index.js +18 -4
  79. package/schematics/package.json +3 -0
  80. package/schematics/use/symbol-map.json +7 -0
  81. package/select/styles/_index.scss +13 -0
  82. package/splitter/styles/_index.scss +7 -1
  83. package/table/styles/_index.scss +28 -10
  84. package/theme/styles/_box-model.scss +29 -0
  85. package/theme/styles/_colors.scss +74 -15
  86. package/theme/styles/_dark.scss +52 -6
  87. package/theme/styles/_index.scss +1 -0
  88. package/types/ngwr-cascader.d.ts +1 -0
  89. package/types/ngwr-color-picker.d.ts +1 -0
  90. package/types/ngwr-context-menu.d.ts +1 -0
  91. package/types/ngwr-date-picker.d.ts +172 -4
  92. package/types/ngwr-density.d.ts +8 -1
  93. package/types/ngwr-dialog.d.ts +80 -8
  94. package/types/ngwr-drawer.d.ts +245 -10
  95. package/types/ngwr-dropdown.d.ts +1 -0
  96. package/types/ngwr-i18n.d.ts +65 -2
  97. package/types/ngwr-icon.d.ts +11 -19
  98. package/types/ngwr-mention.d.ts +45 -1
  99. package/types/ngwr-overlay.d.ts +80 -2
  100. package/types/ngwr-pagination.d.ts +14 -1
  101. package/types/ngwr-popconfirm.d.ts +1 -0
  102. package/types/ngwr-popover.d.ts +1 -0
  103. package/types/ngwr-select.d.ts +121 -9
  104. package/types/ngwr-theme.d.ts +8 -1
  105. package/types/ngwr-tree.d.ts +1 -0
  106. package/types/ngwr-version.d.ts +1 -1
  107. package/types/ngwr-waves.d.ts +10 -0
  108. package/waves/styles/_index.scss +21 -0
@@ -8,7 +8,7 @@ import { WrCalendar } from 'ngwr/calendar';
8
8
  import { WrDateAdapter, WR_DATE_LOCALE } from 'ngwr/date-adapter';
9
9
  import { readI18nText } from 'ngwr/i18n';
10
10
  import { WrInput, WrInputGroup, WrInputSuffix } from 'ngwr/input';
11
- import { WR_OVERLAY } from 'ngwr/overlay';
11
+ import { WR_OVERLAY, WrOutsideClick } from 'ngwr/overlay';
12
12
  import * as i1 from '@angular/forms';
13
13
  import { FormsModule } from '@angular/forms';
14
14
  import { clamp } from 'ngwr/utils';
@@ -301,7 +301,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
301
301
  * accepts both named keys (`'shortDate'`, `'mediumDateTime'`, …) and raw
302
302
  * token strings (`'dd.MM.yyyy'`, `'HH:mm'`). When `format` is left at the
303
303
  * default (`null`), the picker derives the right named key from `mode`:
304
- * `'date'` → `'shortDate'`, `'time'` → `'shortTime'`, `'datetime'` →
304
+ * `'date'` gives `'shortDate'`, `'time'` gives `'time'`, `'datetime'` gives
305
305
  * `'shortDateTime'`.
306
306
  *
307
307
  * @example
@@ -327,8 +327,8 @@ class WrDatePicker {
327
327
  ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
328
328
  /**
329
329
  * Format used for both display and parsing. When `null` (default), the
330
- * format is derived from `mode` (`shortDate` / `shortTime` /
331
- * `shortDateTime`). Pass a named key or raw token string to override.
330
+ * format is derived from `mode` (`shortDate` / `time` / `shortDateTime`).
331
+ * Pass a named key or raw token string to override.
332
332
  */
333
333
  format = input(null, /* @ts-ignore */
334
334
  ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
@@ -366,6 +366,7 @@ class WrDatePicker {
366
366
  readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
367
367
  adapter = inject(WrDateAdapter);
368
368
  overlay = inject(WR_OVERLAY);
369
+ outsideClick = inject(WrOutsideClick);
369
370
  scrollStrategies = inject(ScrollStrategyOptions);
370
371
  host = inject(ElementRef);
371
372
  destroyRef = inject(DestroyRef);
@@ -390,8 +391,11 @@ class WrDatePicker {
390
391
  const m = this.mode();
391
392
  if (m === 'datetime')
392
393
  return 'shortDateTime';
394
+ // `time`, not `shortTime` — the latter is not a member of WrDateFormat, so
395
+ // adapters fell through to treating it as a raw token pattern. date-fns then
396
+ // threw on the unescaped letters; the native adapter degraded silently.
393
397
  if (m === 'time')
394
- return 'shortTime';
398
+ return 'time';
395
399
  return 'shortDate';
396
400
  }, /* @ts-ignore */
397
401
  ...(ngDevMode ? [{ debugName: "resolvedFormat" }] : /* istanbul ignore next */ []));
@@ -522,8 +526,8 @@ class WrDatePicker {
522
526
  this.attachDateTime();
523
527
  else
524
528
  this.attachDate();
525
- this.overlayRef
526
- .outsidePointerEvents()
529
+ this.outsideClick
530
+ .outsidePointerEvents(this.overlayRef)
527
531
  .pipe(takeUntilDestroyed(this.destroyRef))
528
532
  .subscribe(event => {
529
533
  if (this.host.nativeElement.contains(event.target))
@@ -635,9 +639,518 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImpor
635
639
  args: [{ selector: 'wr-date-picker', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [WrInput, WrInputGroup, WrInputSuffix], template: "<wr-input-group>\n <input\n #input\n wrInput\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"overlayOpen()\"\n [value]=\"text()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (click)=\"openOnInput()\"\n (input)=\"onInput($event)\"\n (blur)=\"onBlur()\"\n />\n <button\n type=\"button\"\n wrInputSuffix\n class=\"wr-date-picker__trigger\"\n [attr.aria-label]=\"triggerLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"toggleOverlay()\"\n >\n @if (isTime()) {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <circle cx=\"7\" cy=\"7\" r=\"5.75\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"7\" y1=\"7\" x2=\"7\" y2=\"3.75\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n <line x1=\"7\" y1=\"7\" x2=\"9.5\" y2=\"7\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n </svg>\n } @else {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"11\" height=\"10\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"1.5\" y1=\"5.5\" x2=\"12.5\" y2=\"5.5\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"4\" y1=\"1\" x2=\"4\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n <line x1=\"10\" y1=\"1\" x2=\"10\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n @if (isDateTime()) {\n <circle cx=\"7\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" />\n }\n </svg>\n }\n </button>\n</wr-input-group>\n" }]
636
640
  }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], inputEl: [{ type: i0.ViewChild, args: ['input', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }] } });
637
641
 
642
+ /**
643
+ * @license
644
+ *
645
+ * Use of this source code is governed by an MIT-style license that can be
646
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
647
+ */
648
+ /**
649
+ * Internal panel behind `<wr-date-range-picker>`: a range-mode
650
+ * `<wr-calendar>`, plus one `<wr-time-picker>` per end when `withTime` is on.
651
+ * Not part of the public API.
652
+ *
653
+ * The calendar owns range picking (including the start/end swap and the hover
654
+ * preview); this panel only re-attaches the times so a datetime range keeps the
655
+ * hours the user set while the dates move around.
656
+ *
657
+ * @internal
658
+ */
659
+ class WrDateRangePanel {
660
+ value = input([null, null], /* @ts-ignore */
661
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
662
+ min = input(null, /* @ts-ignore */
663
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
664
+ max = input(null, /* @ts-ignore */
665
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
666
+ dateFilter = input(null, /* @ts-ignore */
667
+ ...(ngDevMode ? [{ debugName: "dateFilter" }] : /* istanbul ignore next */ []));
668
+ withTime = input(false, /* @ts-ignore */
669
+ ...(ngDevMode ? [{ debugName: "withTime" }] : /* istanbul ignore next */ []));
670
+ timeFormat = input('auto', /* @ts-ignore */
671
+ ...(ngDevMode ? [{ debugName: "timeFormat" }] : /* istanbul ignore next */ []));
672
+ showSeconds = input(false, /* @ts-ignore */
673
+ ...(ngDevMode ? [{ debugName: "showSeconds" }] : /* istanbul ignore next */ []));
674
+ step = input(1, /* @ts-ignore */
675
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
676
+ changed = output();
677
+ adapter = inject(WrDateAdapter);
678
+ startTimeLabel = readI18nText('datePicker.startTime', 'Start time');
679
+ endTimeLabel = readI18nText('datePicker.endTime', 'End time');
680
+ /**
681
+ * A time set before its end has a date. The stepper is always live, so the
682
+ * hours are parked here until a date arrives to carry them — otherwise the
683
+ * edit would be silently dropped and the pick would land on midnight.
684
+ */
685
+ pendingStartTime = signal(null, /* @ts-ignore */
686
+ ...(ngDevMode ? [{ debugName: "pendingStartTime" }] : /* istanbul ignore next */ []));
687
+ pendingEndTime = signal(null, /* @ts-ignore */
688
+ ...(ngDevMode ? [{ debugName: "pendingEndTime" }] : /* istanbul ignore next */ []));
689
+ /** The calendar's own range model shape — same tuple, narrower name. */
690
+ calendarRange = computed(() => this.value(), /* @ts-ignore */
691
+ ...(ngDevMode ? [{ debugName: "calendarRange" }] : /* istanbul ignore next */ []));
692
+ /**
693
+ * Midnight today. The steppers need a concrete date to render, but the
694
+ * fallback must NOT be the current wall clock: picking a date carries no time
695
+ * across until a stepper is touched, so a `14:37` default would display a time
696
+ * the commit never actually stores.
697
+ */
698
+ dayStart = computed(() => {
699
+ const t = this.adapter.today();
700
+ return this.adapter.createDate(this.adapter.getYear(t), this.adapter.getMonth(t), this.adapter.getDate(t));
701
+ }, /* @ts-ignore */
702
+ ...(ngDevMode ? [{ debugName: "dayStart" }] : /* istanbul ignore next */ []));
703
+ /** Time steppers need a concrete date; fall back to a parked time, then midnight. */
704
+ startTime = computed(() => this.value()[0] ?? this.pendingStartTime() ?? this.dayStart(), /* @ts-ignore */
705
+ ...(ngDevMode ? [{ debugName: "startTime" }] : /* istanbul ignore next */ []));
706
+ endTime = computed(() => this.value()[1] ?? this.pendingEndTime() ?? this.dayStart(), /* @ts-ignore */
707
+ ...(ngDevMode ? [{ debugName: "endTime" }] : /* istanbul ignore next */ []));
708
+ onRangeChange(range) {
709
+ const [start, end] = range;
710
+ const [prevStart, prevEnd] = this.value();
711
+ // `WrCalendar.pickRange` restarts the range whenever it has no start, so a
712
+ // range that was end-only (typed into the end input alone) would lose that
713
+ // end on the next click. Read the click as filling in the missing start
714
+ // instead; the picker orders the pair afterwards.
715
+ const keptEnd = !prevStart && prevEnd && start && !end ? prevEnd : end;
716
+ // The calendar only moves dates, so carry each end's existing time across —
717
+ // or the time parked by a stepper that ran before this date existed.
718
+ this.changed.emit([
719
+ this.withTimeOf(start, prevStart ?? this.pendingStartTime()),
720
+ this.withTimeOf(keptEnd, prevEnd ?? this.pendingEndTime()),
721
+ ]);
722
+ }
723
+ onStartTimeChange(time) {
724
+ if (!time)
725
+ return;
726
+ const [start, end] = this.value();
727
+ if (!start) {
728
+ this.pendingStartTime.set(time);
729
+ return;
730
+ }
731
+ this.changed.emit([this.withTimeOf(start, time), end]);
732
+ }
733
+ onEndTimeChange(time) {
734
+ if (!time)
735
+ return;
736
+ const [start, end] = this.value();
737
+ if (!end) {
738
+ this.pendingEndTime.set(time);
739
+ return;
740
+ }
741
+ this.changed.emit([start, this.withTimeOf(end, time)]);
742
+ }
743
+ /** `date`'s calendar day carrying `time`'s clock. Null date stays null. */
744
+ withTimeOf(date, time) {
745
+ if (!date)
746
+ return null;
747
+ if (!this.withTime() || !time)
748
+ return date;
749
+ return this.adapter.setTime(this.adapter.createDate(this.adapter.getYear(date), this.adapter.getMonth(date), this.adapter.getDate(date)), this.adapter.getHours(time), this.adapter.getMinutes(time), this.adapter.getSeconds(time));
750
+ }
751
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDateRangePanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
752
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrDateRangePanel, isStandalone: true, selector: "wr-date-range-panel", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, withTime: { classPropertyName: "withTime", publicName: "withTime", isSignal: true, isRequired: false, transformFunction: null }, timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { classAttribute: "wr-date-range-panel" }, ngImport: i0, template: "<wr-calendar\n mode=\"range\"\n [range]=\"calendarRange()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [dateFilter]=\"dateFilter()\"\n (rangeChange)=\"onRangeChange($event)\"\n/>\n\n@if (withTime()) {\n <div class=\"wr-date-range-panel__times\">\n <!-- A time picker is several inputs, not one control, so each end is a\n labelled group rather than a <label>. -->\n <div class=\"wr-date-range-panel__time\" role=\"group\" [attr.aria-label]=\"startTimeLabel\">\n <span class=\"wr-date-range-panel__time-label\" aria-hidden=\"true\">{{ startTimeLabel }}</span>\n <wr-time-picker\n [ngModel]=\"startTime()\"\n [format]=\"timeFormat()\"\n [showSeconds]=\"showSeconds()\"\n [step]=\"step()\"\n (ngModelChange)=\"onStartTimeChange($event)\"\n />\n </div>\n <div class=\"wr-date-range-panel__time\" role=\"group\" [attr.aria-label]=\"endTimeLabel\">\n <span class=\"wr-date-range-panel__time-label\" aria-hidden=\"true\">{{ endTimeLabel }}</span>\n <wr-time-picker\n [ngModel]=\"endTime()\"\n [format]=\"timeFormat()\"\n [showSeconds]=\"showSeconds()\"\n [step]=\"step()\"\n (ngModelChange)=\"onEndTimeChange($event)\"\n />\n </div>\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: WrCalendar, selector: "wr-calendar", inputs: ["mode", "date", "range", "min", "max", "dateFilter", "disabled"], outputs: ["dateChange", "rangeChange"] }, { kind: "component", type: WrTimePanel, selector: "wr-time-picker", inputs: ["format", "showSeconds", "step", "disabled", "readonly", "value"], outputs: ["valueChange", "touch"] }], encapsulation: i0.ViewEncapsulation.None });
753
+ }
754
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDateRangePanel, decorators: [{
755
+ type: Component,
756
+ args: [{ selector: 'wr-date-range-panel', encapsulation: ViewEncapsulation.None, host: { class: 'wr-date-range-panel' }, imports: [FormsModule, WrCalendar, WrTimePanel], template: "<wr-calendar\n mode=\"range\"\n [range]=\"calendarRange()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [dateFilter]=\"dateFilter()\"\n (rangeChange)=\"onRangeChange($event)\"\n/>\n\n@if (withTime()) {\n <div class=\"wr-date-range-panel__times\">\n <!-- A time picker is several inputs, not one control, so each end is a\n labelled group rather than a <label>. -->\n <div class=\"wr-date-range-panel__time\" role=\"group\" [attr.aria-label]=\"startTimeLabel\">\n <span class=\"wr-date-range-panel__time-label\" aria-hidden=\"true\">{{ startTimeLabel }}</span>\n <wr-time-picker\n [ngModel]=\"startTime()\"\n [format]=\"timeFormat()\"\n [showSeconds]=\"showSeconds()\"\n [step]=\"step()\"\n (ngModelChange)=\"onStartTimeChange($event)\"\n />\n </div>\n <div class=\"wr-date-range-panel__time\" role=\"group\" [attr.aria-label]=\"endTimeLabel\">\n <span class=\"wr-date-range-panel__time-label\" aria-hidden=\"true\">{{ endTimeLabel }}</span>\n <wr-time-picker\n [ngModel]=\"endTime()\"\n [format]=\"timeFormat()\"\n [showSeconds]=\"showSeconds()\"\n [step]=\"step()\"\n (ngModelChange)=\"onEndTimeChange($event)\"\n />\n </div>\n </div>\n}\n" }]
757
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], withTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "withTime", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
758
+
759
+ /**
760
+ * @license
761
+ *
762
+ * Use of this source code is governed by an MIT-style license that can be
763
+ * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
764
+ */
765
+ /**
766
+ * Date-range picker — two text inputs sharing one range calendar.
767
+ *
768
+ * Separate from `<wr-date-picker>` because the value is a different type: a
769
+ * range is `[start, end]`, and folding that into the single picker's
770
+ * `Date | null` would break `[formField]` inference for every existing usage.
771
+ * Everything else matches — same input skeleton, same overlay, same
772
+ * {@link WrDateAdapter} formats.
773
+ *
774
+ * - `'date'` (default) — popover renders a range calendar. Picking the second
775
+ * date closes the overlay.
776
+ * - `'datetime'` — popover adds a time stepper per end. Picking dates does NOT
777
+ * close, since the user typically sets the times next.
778
+ *
779
+ * A signal-forms native control: it implements
780
+ * `FormValueControl<WrDateRange | null>`, so `[formField]` binds straight to
781
+ * its `value` model. `[(value)]` works standalone, and classic `[(ngModel)]` /
782
+ * reactive forms keep working through Angular's bridge.
783
+ *
784
+ * Either end may be `null` while the range is half-picked. Out-of-order ends
785
+ * are swapped on commit, matching the calendar's own behaviour.
786
+ *
787
+ * @example
788
+ * ```html
789
+ * <!-- signal forms -->
790
+ * <wr-date-range-picker [formField]="form.period" format="dd.MM.yyyy" />
791
+ *
792
+ * <!-- standalone two-way binding -->
793
+ * <wr-date-range-picker [(value)]="period" [minDate]="minDate" />
794
+ *
795
+ * <!-- date + time on both ends -->
796
+ * <wr-date-range-picker mode="datetime" [(value)]="window" timeFormat="24h" />
797
+ * ```
798
+ *
799
+ * @see https://ngwr.dev/reference/components/date-picker
800
+ */
801
+ class WrDateRangePicker {
802
+ /** Picker behavior — see class doc. @default 'date' */
803
+ mode = input('date', /* @ts-ignore */
804
+ ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
805
+ /**
806
+ * Format used for both display and parsing, on both ends. When `null`
807
+ * (default), it is derived from `mode` (`shortDate` / `shortDateTime`). Pass
808
+ * a named key or raw token string to override.
809
+ */
810
+ format = input(null, /* @ts-ignore */
811
+ ...(ngDevMode ? [{ debugName: "format" }] : /* istanbul ignore next */ []));
812
+ /** Placeholder for the start input. */
813
+ startPlaceholder = input('', /* @ts-ignore */
814
+ ...(ngDevMode ? [{ debugName: "startPlaceholder" }] : /* istanbul ignore next */ []));
815
+ /** Placeholder for the end input. */
816
+ endPlaceholder = input('', /* @ts-ignore */
817
+ ...(ngDevMode ? [{ debugName: "endPlaceholder" }] : /* istanbul ignore next */ []));
818
+ /** Glyph rendered between the two inputs. @default '–' */
819
+ separator = input('–', /* @ts-ignore */
820
+ ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
821
+ // Named `minDate` / `maxDate`, not `min` / `max`: `FormUiControl` reserves
822
+ // those slots for the control's own value type, which here is a range — a
823
+ // `min` typed as a range makes no sense. Matches `WrValidators.minDate`.
824
+ /** Min selectable date, applied to both ends. */
825
+ minDate = input(null, /* @ts-ignore */
826
+ ...(ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []));
827
+ /** Max selectable date, applied to both ends. */
828
+ maxDate = input(null, /* @ts-ignore */
829
+ ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
830
+ /** Predicate to disable specific dates (forwarded to the calendar). */
831
+ dateFilter = input(null, /* @ts-ignore */
832
+ ...(ngDevMode ? [{ debugName: "dateFilter" }] : /* istanbul ignore next */ []));
833
+ /** Time-panel 12 / 24-hour format. Applies in `datetime` mode. @default 'auto' */
834
+ timeFormat = input('auto', /* @ts-ignore */
835
+ ...(ngDevMode ? [{ debugName: "timeFormat" }] : /* istanbul ignore next */ []));
836
+ /** Render the seconds column. Applies in `datetime` mode. @default false */
837
+ showSeconds = input(false, { ...(ngDevMode ? { debugName: "showSeconds" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
838
+ /** Minute / second step for the time panels. @default 1 */
839
+ step = input(1, { ...(ngDevMode ? { debugName: "step" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(1, coerceNumberProperty(v, 1)) });
840
+ /**
841
+ * Disable interaction. Bound automatically from the field's disabled state
842
+ * when used with `[formField]`.
843
+ *
844
+ * @default false
845
+ */
846
+ disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
847
+ /** Read-only — inputs not typeable, but the trigger icon still opens the overlay. @default false */
848
+ readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
849
+ adapter = inject(WrDateAdapter);
850
+ overlay = inject(WR_OVERLAY);
851
+ outsideClick = inject(WrOutsideClick);
852
+ scrollStrategies = inject(ScrollStrategyOptions);
853
+ host = inject(ElementRef);
854
+ destroyRef = inject(DestroyRef);
855
+ startEl = viewChild.required('startInput', /* @ts-ignore */
856
+ ...(ngDevMode ? [{ debugName: "startEl" }] : /* istanbul ignore next */ []));
857
+ /** The picked range. Bound by `[formField]`, or two-way via `[(value)]`. */
858
+ value = model(null, /* @ts-ignore */
859
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
860
+ /** Emitted on blur so a bound field can mark itself touched. */
861
+ touch = output();
862
+ /** Text currently in each input (may be partial / invalid mid-type). */
863
+ startText = signal('', /* @ts-ignore */
864
+ ...(ngDevMode ? [{ debugName: "startText" }] : /* istanbul ignore next */ []));
865
+ endText = signal('', /* @ts-ignore */
866
+ ...(ngDevMode ? [{ debugName: "endText" }] : /* istanbul ignore next */ []));
867
+ /** Whether the popover is currently open. */
868
+ overlayOpen = signal(false, /* @ts-ignore */
869
+ ...(ngDevMode ? [{ debugName: "overlayOpen" }] : /* istanbul ignore next */ []));
870
+ /** Resolved format — falls back to a mode-appropriate default. */
871
+ resolvedFormat = computed(() => this.format() ? String(this.format()) : this.mode() === 'datetime' ? 'shortDateTime' : 'shortDate', /* @ts-ignore */
872
+ ...(ngDevMode ? [{ debugName: "resolvedFormat" }] : /* istanbul ignore next */ []));
873
+ isDateTime = computed(() => this.mode() === 'datetime', /* @ts-ignore */
874
+ ...(ngDevMode ? [{ debugName: "isDateTime" }] : /* istanbul ignore next */ []));
875
+ triggerLabel = readI18nText('datePicker.openRange', 'Open range calendar');
876
+ startLabel = readI18nText('datePicker.rangeStart', 'Range start');
877
+ endLabel = readI18nText('datePicker.rangeEnd', 'Range end');
878
+ classes = computed(() => {
879
+ const parts = ['wr-date-range-picker', `wr-date-range-picker--${this.mode()}`];
880
+ if (this.disabled())
881
+ parts.push('wr-date-range-picker--disabled');
882
+ return parts.join(' ');
883
+ }, /* @ts-ignore */
884
+ ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
885
+ overlayRef = null;
886
+ /** Live panel ref while the popover is open — lets typed edits move the
887
+ * displayed month in real time (not just on reopen). */
888
+ panelRef = signal(null, /* @ts-ignore */
889
+ ...(ngDevMode ? [{ debugName: "panelRef" }] : /* istanbul ignore next */ []));
890
+ /** Last range we pushed into the model ourselves, so the sync effect can skip
891
+ * the echo of our own edits and never reformat text mid-type. */
892
+ lastValue = null;
893
+ constructor() {
894
+ this.destroyRef.onDestroy(() => this.dispose());
895
+ // Mirror external writes to `value` into the two display texts.
896
+ effect(() => {
897
+ const v = this.value();
898
+ untracked(() => {
899
+ if (this.sameRange(v, this.lastValue))
900
+ return;
901
+ this.lastValue = v;
902
+ this.startText.set(this.display(v?.[0] ?? null));
903
+ this.endText.set(this.display(v?.[1] ?? null));
904
+ });
905
+ });
906
+ // Keep the open panel in step with the model.
907
+ effect(() => {
908
+ const ref = this.panelRef();
909
+ if (ref)
910
+ ref.setInput('value', this.value() ?? [null, null]);
911
+ });
912
+ // …and with every other input. Pushing these only at attach time meant a
913
+ // `[minDate]` (or filter, or time format) that changed while the popover was
914
+ // open silently kept the stale constraint until the next reopen.
915
+ effect(() => {
916
+ const ref = this.panelRef();
917
+ if (!ref)
918
+ return;
919
+ ref.setInput('min', this.minDate());
920
+ ref.setInput('max', this.maxDate());
921
+ ref.setInput('dateFilter', this.dateFilter());
922
+ ref.setInput('withTime', this.isDateTime());
923
+ ref.setInput('timeFormat', this.timeFormat());
924
+ ref.setInput('showSeconds', this.showSeconds());
925
+ ref.setInput('step', this.step());
926
+ });
927
+ }
928
+ // Template handlers
929
+ onStartInput(event) {
930
+ this.onRangeInput(event, 0);
931
+ }
932
+ onEndInput(event) {
933
+ this.onRangeInput(event, 1);
934
+ }
935
+ onBlur(event) {
936
+ // Moving between the two ends is still one interaction — only report the
937
+ // control as touched once focus actually leaves it, or tabbing from start to
938
+ // end would mark a bound field touched mid-entry.
939
+ const next = event.relatedTarget;
940
+ if (!next || !this.host.nativeElement.contains(next))
941
+ this.touch.emit();
942
+ // Typing leaves the ends in whatever order they were entered; settle it
943
+ // here, once the user has stopped.
944
+ const [start, end] = this.commitRange(this.current(), { normalise: true });
945
+ // Reformat to canonical on blur (cleans up `1/5/25` → `1/5/2025`).
946
+ this.startText.set(this.display(start));
947
+ this.endText.set(this.display(end));
948
+ }
949
+ /** Called by an input's click — opens the overlay if it isn't open already. */
950
+ openOnInput() {
951
+ if (this.disabled() || this.readonly() || this.overlayRef)
952
+ return;
953
+ this.openOverlay();
954
+ }
955
+ toggleOverlay() {
956
+ // `readonly` blocks the calendar too — otherwise the inputs refuse typing
957
+ // while the popover happily edits the same value.
958
+ if (this.disabled() || this.readonly())
959
+ return;
960
+ if (this.overlayRef)
961
+ this.closeOverlay();
962
+ else
963
+ this.openOverlay();
964
+ }
965
+ // Input parsing
966
+ onRangeInput(event, end) {
967
+ const raw = event.target.value;
968
+ (end === 0 ? this.startText : this.endText).set(raw);
969
+ const [start, finish] = this.current();
970
+ if (!raw) {
971
+ this.commitRange(end === 0 ? [null, finish] : [start, null], { normalise: false });
972
+ return;
973
+ }
974
+ const parsed = this.adapter.parse(raw, this.resolvedFormat());
975
+ if (!parsed || !this.adapter.isValid(parsed) || this.isOutOfBounds(parsed))
976
+ return;
977
+ // Never reorder mid-keystroke: a half-typed date can parse to an
978
+ // out-of-order value, and swapping there would yank the text the user is
979
+ // still typing over to the other input. Ordering is settled on blur.
980
+ this.commitRange(end === 0 ? [parsed, finish] : [start, parsed], { normalise: false });
981
+ }
982
+ // Overlay
983
+ openOverlay() {
984
+ if (this.overlayRef)
985
+ return;
986
+ const positionStrategy = this.overlay
987
+ .position()
988
+ .flexibleConnectedTo(this.host)
989
+ .withPositions([
990
+ { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top', offsetY: 4 },
991
+ { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom', offsetY: -4 },
992
+ { originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
993
+ { originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -4 },
994
+ ])
995
+ .withPush(true);
996
+ this.overlayRef = this.overlay.create({
997
+ positionStrategy,
998
+ scrollStrategy: this.scrollStrategies.reposition(),
999
+ panelClass: 'wr-date-picker-overlay',
1000
+ });
1001
+ this.overlayOpen.set(true);
1002
+ const ref = this.overlayRef.attach(new ComponentPortal(WrDateRangePanel));
1003
+ ref.setInput('value', this.value() ?? [null, null]);
1004
+ this.panelRef.set(ref);
1005
+ ref.instance.changed.subscribe(next => {
1006
+ const committed = this.commitRange(next, { normalise: true });
1007
+ // A complete date-only range is the end of the interaction; a datetime
1008
+ // range still needs its hours, so the panel stays put.
1009
+ if (!this.isDateTime() && committed[0] && committed[1])
1010
+ this.closeOverlay();
1011
+ });
1012
+ this.outsideClick
1013
+ .outsidePointerEvents(this.overlayRef)
1014
+ .pipe(takeUntilDestroyed(this.destroyRef))
1015
+ .subscribe(event => {
1016
+ if (this.host.nativeElement.contains(event.target))
1017
+ return;
1018
+ this.closeOverlay();
1019
+ });
1020
+ this.overlayRef
1021
+ .keydownEvents()
1022
+ .pipe(takeUntilDestroyed(this.destroyRef))
1023
+ .subscribe(event => {
1024
+ if (event.key === 'Escape') {
1025
+ event.preventDefault();
1026
+ this.closeOverlay();
1027
+ this.startEl().nativeElement.focus();
1028
+ }
1029
+ });
1030
+ }
1031
+ /**
1032
+ * Close the popover. `restoreFocus` returns focus to the start input — needed
1033
+ * when the overlay is dismissed while focus lives inside it (picking the
1034
+ * second date), because disposing then leaves focus on a removed element and
1035
+ * the browser falls back to `<body>`.
1036
+ */
1037
+ closeOverlay(restoreFocus = false) {
1038
+ const inside = this.overlayRef?.overlayElement.contains(this.host.nativeElement.ownerDocument.activeElement);
1039
+ this.dispose();
1040
+ if (restoreFocus || inside)
1041
+ this.startEl().nativeElement.focus();
1042
+ }
1043
+ dispose() {
1044
+ if (this.overlayRef) {
1045
+ this.overlayRef.dispose();
1046
+ this.overlayRef = null;
1047
+ }
1048
+ this.panelRef.set(null);
1049
+ this.overlayOpen.set(false);
1050
+ }
1051
+ // Commit
1052
+ /**
1053
+ * Push to the model and refresh the text of whichever ends changed. Returns
1054
+ * what was actually committed.
1055
+ *
1056
+ * `normalise` swaps out-of-order ends. The calendar and blur ask for it; a
1057
+ * keystroke does not, because reordering while the user is still typing would
1058
+ * move their in-progress text into the other input.
1059
+ */
1060
+ commitRange(next, options) {
1061
+ const normalised = options.normalise ? this.normalise(next) : next;
1062
+ // Only write when a date actually moved. `normalise()` allocates a fresh
1063
+ // tuple on every call and `model()` compares by reference, so an
1064
+ // unconditional write would emit on every blur — enough to mark a bound
1065
+ // `[formField]` dirty just by tabbing through the two inputs.
1066
+ if (!this.sameRange(normalised, this.value())) {
1067
+ this.lastValue = normalised;
1068
+ this.value.set(normalised);
1069
+ }
1070
+ // Only rewrite the text of an end whose date moved out from under it —
1071
+ // otherwise a half-typed date would be reformatted on every keystroke.
1072
+ if (!this.sameDate(normalised[0], this.parseText(this.startText()))) {
1073
+ this.startText.set(this.display(normalised[0]));
1074
+ }
1075
+ if (!this.sameDate(normalised[1], this.parseText(this.endText()))) {
1076
+ this.endText.set(this.display(normalised[1]));
1077
+ }
1078
+ return normalised;
1079
+ }
1080
+ // Helpers
1081
+ current() {
1082
+ return this.value() ?? [null, null];
1083
+ }
1084
+ display(date) {
1085
+ return date && this.adapter.isValid(date) ? this.adapter.format(date, this.resolvedFormat()) : '';
1086
+ }
1087
+ parseText(raw) {
1088
+ if (!raw)
1089
+ return null;
1090
+ const parsed = this.adapter.parse(raw, this.resolvedFormat());
1091
+ return parsed && this.adapter.isValid(parsed) ? parsed : null;
1092
+ }
1093
+ /** Keep `[start, end]` in chronological order once both ends exist. */
1094
+ normalise(range) {
1095
+ const [start, end] = range;
1096
+ if (start && end && this.compareEnds(start, end) > 0)
1097
+ return [end, start];
1098
+ return [start, end];
1099
+ }
1100
+ /**
1101
+ * Chronological comparison at the precision the mode needs. The adapter's
1102
+ * `compareDate` is day-precision by contract, which would leave an inverted
1103
+ * same-day `datetime` range (18:00 → 09:00) unswapped.
1104
+ */
1105
+ compareEnds(a, b) {
1106
+ const byDay = this.adapter.compareDate(a, b);
1107
+ if (byDay !== 0 || !this.isDateTime())
1108
+ return byDay;
1109
+ const clock = (d) => this.adapter.getHours(d) * 3600 + this.adapter.getMinutes(d) * 60 + this.adapter.getSeconds(d);
1110
+ return clock(a) - clock(b);
1111
+ }
1112
+ /**
1113
+ * Whether a typed date must be rejected. Covers `dateFilter` as well as the
1114
+ * bounds — the calendar disables filtered days, so accepting them from the
1115
+ * keyboard would make the two entry paths disagree.
1116
+ */
1117
+ isOutOfBounds(date) {
1118
+ const min = this.minDate();
1119
+ if (min && this.adapter.compareDate(date, min) < 0)
1120
+ return true;
1121
+ const max = this.maxDate();
1122
+ if (max && this.adapter.compareDate(date, max) > 0)
1123
+ return true;
1124
+ const filter = this.dateFilter();
1125
+ if (filter && !filter(date))
1126
+ return true;
1127
+ return false;
1128
+ }
1129
+ sameDate(a, b) {
1130
+ if (a === b)
1131
+ return true;
1132
+ if (!a || !b)
1133
+ return false;
1134
+ return a.getTime() === b.getTime();
1135
+ }
1136
+ sameRange(a, b) {
1137
+ if (a === b)
1138
+ return true;
1139
+ if (!a || !b)
1140
+ return false;
1141
+ return this.sameDate(a[0], b[0]) && this.sameDate(a[1], b[1]);
1142
+ }
1143
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDateRangePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
1144
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrDateRangePicker, isStandalone: true, selector: "wr-date-range-picker", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, startPlaceholder: { classPropertyName: "startPlaceholder", publicName: "startPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, endPlaceholder: { classPropertyName: "endPlaceholder", publicName: "endPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, dateFilter: { classPropertyName: "dateFilter", publicName: "dateFilter", isSignal: true, isRequired: false, transformFunction: null }, timeFormat: { classPropertyName: "timeFormat", publicName: "timeFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()" } }, viewQueries: [{ propertyName: "startEl", first: true, predicate: ["startInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<wr-input-group>\n <input\n #startInput\n wrInput\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n class=\"wr-date-range-picker__input\"\n [attr.aria-label]=\"startLabel\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"overlayOpen()\"\n [value]=\"startText()\"\n [placeholder]=\"startPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (click)=\"openOnInput()\"\n (input)=\"onStartInput($event)\"\n (blur)=\"onBlur($event)\"\n />\n <span class=\"wr-date-range-picker__separator\" aria-hidden=\"true\">{{ separator() }}</span>\n <input\n wrInput\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n class=\"wr-date-range-picker__input\"\n [attr.aria-label]=\"endLabel\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"overlayOpen()\"\n [value]=\"endText()\"\n [placeholder]=\"endPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (click)=\"openOnInput()\"\n (input)=\"onEndInput($event)\"\n (blur)=\"onBlur($event)\"\n />\n <button\n type=\"button\"\n wrInputSuffix\n class=\"wr-date-picker__trigger\"\n [attr.aria-label]=\"triggerLabel\"\n [disabled]=\"disabled()\"\n (click)=\"toggleOverlay()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"11\" height=\"10\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"1.5\" y1=\"5.5\" x2=\"12.5\" y2=\"5.5\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"4\" y1=\"1\" x2=\"4\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n <line x1=\"10\" y1=\"1\" x2=\"10\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n @if (isDateTime()) {\n <circle cx=\"7\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" />\n }\n </svg>\n </button>\n</wr-input-group>\n", dependencies: [{ kind: "directive", type: WrInput, selector: "input[wrInput], textarea[wrInput]", inputs: ["wrSize", "rounded"] }, { kind: "component", type: WrInputGroup, selector: "wr-input-group", inputs: ["rounded"] }, { kind: "directive", type: WrInputSuffix, selector: "[wrInputSuffix]" }], encapsulation: i0.ViewEncapsulation.None });
1145
+ }
1146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrDateRangePicker, decorators: [{
1147
+ type: Component,
1148
+ args: [{ selector: 'wr-date-range-picker', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [WrInput, WrInputGroup, WrInputSuffix], template: "<wr-input-group>\n <input\n #startInput\n wrInput\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n class=\"wr-date-range-picker__input\"\n [attr.aria-label]=\"startLabel\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"overlayOpen()\"\n [value]=\"startText()\"\n [placeholder]=\"startPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (click)=\"openOnInput()\"\n (input)=\"onStartInput($event)\"\n (blur)=\"onBlur($event)\"\n />\n <span class=\"wr-date-range-picker__separator\" aria-hidden=\"true\">{{ separator() }}</span>\n <input\n wrInput\n type=\"text\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n class=\"wr-date-range-picker__input\"\n [attr.aria-label]=\"endLabel\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-expanded]=\"overlayOpen()\"\n [value]=\"endText()\"\n [placeholder]=\"endPlaceholder()\"\n [disabled]=\"disabled()\"\n [readonly]=\"readonly()\"\n (click)=\"openOnInput()\"\n (input)=\"onEndInput($event)\"\n (blur)=\"onBlur($event)\"\n />\n <button\n type=\"button\"\n wrInputSuffix\n class=\"wr-date-picker__trigger\"\n [attr.aria-label]=\"triggerLabel\"\n [disabled]=\"disabled()\"\n (click)=\"toggleOverlay()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" aria-hidden=\"true\">\n <rect x=\"1.5\" y=\"2.5\" width=\"11\" height=\"10\" rx=\"1.5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"1.5\" y1=\"5.5\" x2=\"12.5\" y2=\"5.5\" stroke=\"currentColor\" stroke-width=\"1.2\" />\n <line x1=\"4\" y1=\"1\" x2=\"4\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n <line x1=\"10\" y1=\"1\" x2=\"10\" y2=\"4\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\" />\n @if (isDateTime()) {\n <circle cx=\"7\" cy=\"9\" r=\"1.5\" fill=\"currentColor\" />\n }\n </svg>\n </button>\n</wr-input-group>\n" }]
1149
+ }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], startPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "startPlaceholder", required: false }] }], endPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPlaceholder", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], dateFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFilter", required: false }] }], timeFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], startEl: [{ type: i0.ViewChild, args: ['startInput', { isSignal: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }] } });
1150
+
638
1151
  /**
639
1152
  * Generated bundle index. Do not edit.
640
1153
  */
641
1154
 
642
- export { WrDatePicker };
1155
+ export { WrDatePicker, WrDateRangePicker };
643
1156
  //# sourceMappingURL=ngwr-date-picker.mjs.map