@gloww/gloww 20.0.0-beta.31 → 20.0.0-beta.33

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.
@@ -3626,6 +3626,9 @@ class DatetimeComponent {
3626
3626
  'YYYY-MM-DDTHH:mm:ss',
3627
3627
  'YYYY-MM-DDTHH:mm'
3628
3628
  ]; }
3629
+ static { this.CLOCK_CENTER = 50; }
3630
+ static { this.CLOCK_OUTER_RADIUS = 40; }
3631
+ static { this.CLOCK_INNER_RADIUS = 27; }
3629
3632
  constructor(locale) {
3630
3633
  this.locale = locale;
3631
3634
  this._value = null;
@@ -3637,10 +3640,12 @@ class DatetimeComponent {
3637
3640
  this.hourControl = new FormControl('00', { nonNullable: true });
3638
3641
  this.minuteControl = new FormControl('00', { nonNullable: true });
3639
3642
  this.secondControl = new FormControl('00', { nonNullable: true });
3643
+ this.hourMarkers = this.buildHourMarkers();
3644
+ this.minuteMarkers = this.buildUnitMarkers();
3645
+ this.secondMarkers = this.buildUnitMarkers();
3640
3646
  this.isDisabled = false;
3641
- this.hours = Array.from({ length: 24 }, (_, value) => value.toString().padStart(2, '0'));
3642
- this.minutes = Array.from({ length: 60 }, (_, value) => value.toString().padStart(2, '0'));
3643
- this.seconds = Array.from({ length: 60 }, (_, value) => value.toString().padStart(2, '0'));
3647
+ this.isClockOpen = false;
3648
+ this.clockStep = 'hour';
3644
3649
  this.onChange = () => { };
3645
3650
  this.onTouched = () => { };
3646
3651
  this.dateControl.valueChanges.subscribe(() => this.emitCurrentValue());
@@ -3676,6 +3681,7 @@ class DatetimeComponent {
3676
3681
  }
3677
3682
  clear() {
3678
3683
  this._value = null;
3684
+ this.isClockOpen = false;
3679
3685
  this.dateControl.setValue(null, { emitEvent: false });
3680
3686
  this.hourControl.setValue('00', { emitEvent: false });
3681
3687
  this.minuteControl.setValue('00', { emitEvent: false });
@@ -3686,6 +3692,81 @@ class DatetimeComponent {
3686
3692
  markTouched() {
3687
3693
  this.onTouched();
3688
3694
  }
3695
+ get timeSummary() {
3696
+ return this.showSeconds
3697
+ ? `${this.normalizeTimePartValue(this.hourControl.value, 23, true)}:${this.normalizeTimePartValue(this.minuteControl.value, 59, true)}:${this.normalizeTimePartValue(this.secondControl.value, 59, true)}`
3698
+ : `${this.normalizeTimePartValue(this.hourControl.value, 23, true)}:${this.normalizeTimePartValue(this.minuteControl.value, 59, true)}`;
3699
+ }
3700
+ get clockTitle() {
3701
+ switch (this.clockStep) {
3702
+ case 'hour':
3703
+ return 'Hours';
3704
+ case 'minute':
3705
+ return 'Minutes';
3706
+ default:
3707
+ return 'Seconds';
3708
+ }
3709
+ }
3710
+ openClock() {
3711
+ if (this.isDisabled) {
3712
+ return;
3713
+ }
3714
+ this.isClockOpen = true;
3715
+ this.clockStep = 'hour';
3716
+ this.onTouched();
3717
+ }
3718
+ closeClock() {
3719
+ this.isClockOpen = false;
3720
+ this.onTouched();
3721
+ }
3722
+ onTimePartInput(part) {
3723
+ const control = this.getTimeControl(part);
3724
+ const max = this.getTimePartMax(part);
3725
+ control.setValue(this.normalizeTimePartValue(control.value, max, false), { emitEvent: false });
3726
+ this.emitCurrentValue();
3727
+ }
3728
+ onTimePartBlur(part) {
3729
+ const control = this.getTimeControl(part);
3730
+ const max = this.getTimePartMax(part);
3731
+ control.setValue(this.normalizeTimePartValue(control.value, max, true), { emitEvent: false });
3732
+ this.emitCurrentValue();
3733
+ this.onTouched();
3734
+ }
3735
+ selectClockHour(value) {
3736
+ this.hourControl.setValue(value.toString().padStart(2, '0'), { emitEvent: false });
3737
+ this.emitCurrentValue();
3738
+ this.clockStep = 'minute';
3739
+ this.onTouched();
3740
+ }
3741
+ selectClockMinute(value) {
3742
+ this.minuteControl.setValue(value.toString().padStart(2, '0'), { emitEvent: false });
3743
+ this.emitCurrentValue();
3744
+ if (this.showSeconds) {
3745
+ this.clockStep = 'second';
3746
+ }
3747
+ else {
3748
+ this.closeClock();
3749
+ }
3750
+ this.onTouched();
3751
+ }
3752
+ selectClockSecond(value) {
3753
+ this.secondControl.setValue(value.toString().padStart(2, '0'), { emitEvent: false });
3754
+ this.emitCurrentValue();
3755
+ this.closeClock();
3756
+ this.onTouched();
3757
+ }
3758
+ goToClockStep(step) {
3759
+ this.clockStep = step;
3760
+ }
3761
+ isHourSelected(value) {
3762
+ return this.toNumber(this.hourControl.value) === value;
3763
+ }
3764
+ isMinuteSelected(value) {
3765
+ return this.toNumber(this.minuteControl.value) === value;
3766
+ }
3767
+ isSecondSelected(value) {
3768
+ return this.toNumber(this.secondControl.value) === value;
3769
+ }
3689
3770
  setValueFromOutside(value, emit) {
3690
3771
  const normalized = this.normalizeDateValue(value);
3691
3772
  this._value = normalized;
@@ -3714,6 +3795,28 @@ class DatetimeComponent {
3714
3795
  const parsed = Number.parseInt(value ?? '0', 10);
3715
3796
  return Number.isNaN(parsed) ? 0 : parsed;
3716
3797
  }
3798
+ getTimeControl(part) {
3799
+ switch (part) {
3800
+ case 'hour':
3801
+ return this.hourControl;
3802
+ case 'minute':
3803
+ return this.minuteControl;
3804
+ default:
3805
+ return this.secondControl;
3806
+ }
3807
+ }
3808
+ getTimePartMax(part) {
3809
+ return part === 'hour' ? 23 : 59;
3810
+ }
3811
+ normalizeTimePartValue(value, max, pad) {
3812
+ const digits = `${value ?? ''}`.replace(/\D/g, '').slice(-2);
3813
+ if (!digits) {
3814
+ return pad ? '00' : '';
3815
+ }
3816
+ const parsed = Number.parseInt(digits, 10);
3817
+ const clamped = Number.isNaN(parsed) ? 0 : Math.min(max, Math.max(0, parsed));
3818
+ return pad || digits.length > 1 ? clamped.toString().padStart(2, '0') : clamped.toString();
3819
+ }
3717
3820
  normalizeDateValue(value) {
3718
3821
  if (value === undefined || value === null || value === '') {
3719
3822
  return null;
@@ -3739,6 +3842,23 @@ class DatetimeComponent {
3739
3842
  }
3740
3843
  return null;
3741
3844
  }
3845
+ buildHourMarkers() {
3846
+ return Array.from({ length: 24 }, (_, index) => this.buildClockMarker(index, index < 12 ? DatetimeComponent.CLOCK_OUTER_RADIUS : DatetimeComponent.CLOCK_INNER_RADIUS, index.toString().padStart(2, '0')));
3847
+ }
3848
+ buildUnitMarkers() {
3849
+ return Array.from({ length: 60 }, (_, index) => this.buildClockMarker(index, DatetimeComponent.CLOCK_OUTER_RADIUS, index % 5 === 0 ? index.toString().padStart(2, '0') : ''));
3850
+ }
3851
+ buildClockMarker(index, radius, label) {
3852
+ const angle = ((index % 12) / 12) * (Math.PI * 2) - (Math.PI / 2);
3853
+ const x = DatetimeComponent.CLOCK_CENTER + Math.cos(angle) * radius;
3854
+ const y = DatetimeComponent.CLOCK_CENTER + Math.sin(angle) * radius;
3855
+ return {
3856
+ value: index,
3857
+ label,
3858
+ left: `${x}%`,
3859
+ top: `${y}%`
3860
+ };
3861
+ }
3742
3862
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatetimeComponent, deps: [{ token: MAT_DATE_LOCALE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
3743
3863
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: DatetimeComponent, isStandalone: true, selector: "gloww-datetime", inputs: { _value: ["value", "_value"], display: "display", placeHolder: "placeHolder", mode: "mode", showSeconds: "showSeconds" }, providers: [
3744
3864
  {
@@ -3746,7 +3866,7 @@ class DatetimeComponent {
3746
3866
  multi: true,
3747
3867
  useExisting: forwardRef(() => DatetimeComponent)
3748
3868
  }
3749
- ], ngImport: i0, template: "<div class=\"datetime-wrapper\" [class.datetime-mode]=\"isDateTime\" [class.has-seconds]=\"showSeconds\">\n <mat-form-field class=\"date-field\">\n @if (display) {\n <mat-label>{{ display }}</mat-label>\n }\n <input\n matInput\n [matDatepicker]=\"picker\"\n [placeholder]=\"placeHolder\"\n [formControl]=\"dateControl\"\n [disabled]=\"isDisabled\"\n (dateChange)=\"markTouched()\"\n (blur)=\"markTouched()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n\n @if (isDateTime) {\n <div class=\"time-row\">\n <mat-form-field class=\"time-field\">\n <mat-label>HH</mat-label>\n <mat-select [formControl]=\"hourControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (hour of hours; track hour) {\n <mat-option [value]=\"hour\">{{ hour }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"time-field\">\n <mat-label>MM</mat-label>\n <mat-select [formControl]=\"minuteControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (minute of minutes; track minute) {\n <mat-option [value]=\"minute\">{{ minute }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @if (showSeconds) {\n <mat-form-field class=\"time-field\">\n <mat-label>SS</mat-label>\n <mat-select [formControl]=\"secondControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (second of seconds; track second) {\n <mat-option [value]=\"second\">{{ second }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n }\n\n <div class=\"actions-row\">\n <button mat-button type=\"button\" (click)=\"clear()\" [disabled]=\"isDisabled\">Clear</button>\n </div>\n</div>\n", styles: [".datetime-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.date-field,.time-field{width:100%}.time-row{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}.actions-row{display:flex;justify-content:flex-end}@media(min-width:720px){.time-row{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:960px){.datetime-wrapper.datetime-mode{display:grid;align-items:start;gap:8px;grid-template-columns:minmax(240px,2fr) repeat(2,minmax(84px,96px)) auto}.datetime-wrapper.datetime-mode.has-seconds{grid-template-columns:minmax(240px,2fr) repeat(3,minmax(84px,96px)) auto}.datetime-wrapper.datetime-mode .date-field{margin-bottom:0}.datetime-wrapper.datetime-mode .time-row{display:contents}.datetime-wrapper.datetime-mode .actions-row{align-self:start;justify-content:flex-start;padding-top:4px}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: MatFormField$1, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel$1, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] }); }
3869
+ ], ngImport: i0, template: "<div class=\"datetime-wrapper\" [class.datetime-mode]=\"isDateTime\" [class.has-seconds]=\"showSeconds\">\n <mat-form-field class=\"date-field\">\n @if (display) {\n <mat-label>{{ display }}</mat-label>\n }\n <input\n matInput\n [matDatepicker]=\"picker\"\n [placeholder]=\"placeHolder\"\n [formControl]=\"dateControl\"\n [disabled]=\"isDisabled\"\n (dateChange)=\"markTouched()\"\n (blur)=\"markTouched()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n\n @if (isDateTime) {\n <div class=\"middle-actions\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"icon-action\"\n [disabled]=\"isDisabled\"\n title=\"Clear date and time\"\n aria-label=\"Clear date and time\"\n (click)=\"clear()\">\n <i class=\"fal fa-eraser\"></i>\n </button>\n\n <button\n mat-icon-button\n type=\"button\"\n class=\"icon-action\"\n [disabled]=\"isDisabled\"\n title=\"Open time clock\"\n aria-label=\"Open time clock\"\n (click)=\"openClock()\">\n <i class=\"fal fa-clock\"></i>\n </button>\n </div>\n\n <div class=\"time-row\">\n <mat-form-field class=\"time-field\">\n <mat-label>HH</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"23\"\n inputmode=\"numeric\"\n [formControl]=\"hourControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('hour')\"\n (blur)=\"onTimePartBlur('hour')\">\n </mat-form-field>\n\n <mat-form-field class=\"time-field\">\n <mat-label>MM</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"59\"\n inputmode=\"numeric\"\n [formControl]=\"minuteControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('minute')\"\n (blur)=\"onTimePartBlur('minute')\">\n </mat-form-field>\n\n @if (showSeconds) {\n <mat-form-field class=\"time-field\">\n <mat-label>SS</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"59\"\n inputmode=\"numeric\"\n [formControl]=\"secondControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('second')\"\n (blur)=\"onTimePartBlur('second')\">\n </mat-form-field>\n }\n </div>\n\n @if (isClockOpen) {\n <div class=\"clock-panel\">\n <div class=\"clock-panel-header\">\n <div class=\"clock-panel-title\">{{ clockTitle }}</div>\n <button\n mat-button\n type=\"button\"\n class=\"clock-close\"\n [disabled]=\"isDisabled\"\n (click)=\"closeClock()\">\n Close\n </button>\n </div>\n\n <div class=\"clock-summary\">\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'hour'\" (click)=\"goToClockStep('hour')\">\n {{ hourControl.value || '00' }}\n </button>\n <span>:</span>\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'minute'\" (click)=\"goToClockStep('minute')\">\n {{ minuteControl.value || '00' }}\n </button>\n @if (showSeconds) {\n <span>:</span>\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'second'\" (click)=\"goToClockStep('second')\">\n {{ secondControl.value || '00' }}\n </button>\n }\n </div>\n\n <div class=\"clock-face\">\n @if (clockStep === 'hour') {\n @for (marker of hourMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker\"\n [class.selected]=\"isHourSelected(marker.value)\"\n [class.inner-ring]=\"marker.value >= 12\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockHour(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n @if (clockStep === 'minute') {\n @for (marker of minuteMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker clock-unit-marker\"\n [class.selected]=\"isMinuteSelected(marker.value)\"\n [class.major]=\"!!marker.label\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockMinute(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n @if (clockStep === 'second') {\n @for (marker of secondMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker clock-unit-marker\"\n [class.selected]=\"isSecondSelected(marker.value)\"\n [class.major]=\"!!marker.label\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockSecond(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n <div class=\"clock-center-dot\"></div>\n </div>\n\n <div class=\"clock-help\">\n @if (clockStep === 'hour') {\n <span>Outer ring 00-11, inner ring 12-23.</span>\n }\n @if (clockStep === 'minute') {\n <span>Choose the minute.</span>\n }\n @if (clockStep === 'second') {\n <span>Choose the second.</span>\n }\n </div>\n\n <div class=\"clock-footer\">\n <span>{{ timeSummary }}</span>\n </div>\n </div>\n }\n }\n</div>\n", styles: [".datetime-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.date-field,.time-field{width:100%}.middle-actions{display:flex;align-items:center;gap:4px;justify-content:flex-start}.icon-action{flex:0 0 auto}.icon-action i{font-size:1rem;line-height:1}.time-row{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}.clock-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid rgba(0,0,0,.12);border-radius:16px;background:#fff}.clock-panel-header,.clock-summary,.clock-footer{display:flex;align-items:center;justify-content:space-between;gap:8px}.clock-panel-title{font-size:.95rem;font-weight:600}.clock-summary{justify-content:center;font-size:1.1rem}.clock-step{min-width:52px;font-weight:600}.clock-step.active{background:#1976d21f}.clock-face{position:relative;align-self:center;width:min(100%,280px);aspect-ratio:1;border-radius:50%;background:radial-gradient(circle at center,rgba(25,118,210,.08) 0 16%,transparent 16% 100%),radial-gradient(circle at center,transparent 0 61%,rgba(25,118,210,.08) 61% 62%,transparent 62% 100%),radial-gradient(circle at center,#0000000a 0 100%)}.clock-marker{position:absolute;transform:translate(-50%,-50%);width:38px;height:38px;min-width:38px;padding:0;border-radius:50%;font-size:.72rem;line-height:1}.clock-marker.inner-ring{width:34px;height:34px;min-width:34px;font-size:.68rem}.clock-unit-marker{width:24px;height:24px;min-width:24px;font-size:.58rem;color:transparent}.clock-unit-marker.major{width:34px;height:34px;min-width:34px;font-size:.68rem;color:inherit}.clock-marker.selected{background:#1976d2;color:#fff}.clock-center-dot{position:absolute;top:50%;left:50%;width:12px;height:12px;border-radius:50%;transform:translate(-50%,-50%);background:#1976d2}.clock-help,.clock-footer{font-size:.78rem;color:#000000ad}@media(min-width:720px){.time-row{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:960px){.datetime-wrapper.datetime-mode{display:grid;align-items:start;gap:8px;grid-template-columns:minmax(240px,2fr) auto repeat(2,minmax(84px,96px))}.datetime-wrapper.datetime-mode.has-seconds{grid-template-columns:minmax(240px,2fr) auto repeat(3,minmax(84px,96px))}.datetime-wrapper.datetime-mode .date-field{margin-bottom:0}.datetime-wrapper.datetime-mode .middle-actions{align-self:start;padding-top:4px}.datetime-wrapper.datetime-mode .time-row{display:contents}.datetime-wrapper.datetime-mode .clock-panel{grid-column:1/-1}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: MatFormField$1, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel$1, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "directive", type: MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "component", type: MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }] }); }
3750
3870
  }
3751
3871
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DatetimeComponent, decorators: [{
3752
3872
  type: Component,
@@ -3756,7 +3876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
3756
3876
  multi: true,
3757
3877
  useExisting: forwardRef(() => DatetimeComponent)
3758
3878
  }
3759
- ], imports: [ReactiveFormsModule, MatFormField$1, MatLabel$1, MatInput, MatDatepickerInput, MatDatepickerToggle, MatDatepicker, MatSuffix, MatSelect, MatOption, MatButton], template: "<div class=\"datetime-wrapper\" [class.datetime-mode]=\"isDateTime\" [class.has-seconds]=\"showSeconds\">\n <mat-form-field class=\"date-field\">\n @if (display) {\n <mat-label>{{ display }}</mat-label>\n }\n <input\n matInput\n [matDatepicker]=\"picker\"\n [placeholder]=\"placeHolder\"\n [formControl]=\"dateControl\"\n [disabled]=\"isDisabled\"\n (dateChange)=\"markTouched()\"\n (blur)=\"markTouched()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n\n @if (isDateTime) {\n <div class=\"time-row\">\n <mat-form-field class=\"time-field\">\n <mat-label>HH</mat-label>\n <mat-select [formControl]=\"hourControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (hour of hours; track hour) {\n <mat-option [value]=\"hour\">{{ hour }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field class=\"time-field\">\n <mat-label>MM</mat-label>\n <mat-select [formControl]=\"minuteControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (minute of minutes; track minute) {\n <mat-option [value]=\"minute\">{{ minute }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @if (showSeconds) {\n <mat-form-field class=\"time-field\">\n <mat-label>SS</mat-label>\n <mat-select [formControl]=\"secondControl\" [disabled]=\"isDisabled\" (selectionChange)=\"markTouched()\">\n @for (second of seconds; track second) {\n <mat-option [value]=\"second\">{{ second }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n </div>\n }\n\n <div class=\"actions-row\">\n <button mat-button type=\"button\" (click)=\"clear()\" [disabled]=\"isDisabled\">Clear</button>\n </div>\n</div>\n", styles: [".datetime-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.date-field,.time-field{width:100%}.time-row{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}.actions-row{display:flex;justify-content:flex-end}@media(min-width:720px){.time-row{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:960px){.datetime-wrapper.datetime-mode{display:grid;align-items:start;gap:8px;grid-template-columns:minmax(240px,2fr) repeat(2,minmax(84px,96px)) auto}.datetime-wrapper.datetime-mode.has-seconds{grid-template-columns:minmax(240px,2fr) repeat(3,minmax(84px,96px)) auto}.datetime-wrapper.datetime-mode .date-field{margin-bottom:0}.datetime-wrapper.datetime-mode .time-row{display:contents}.datetime-wrapper.datetime-mode .actions-row{align-self:start;justify-content:flex-start;padding-top:4px}}\n"] }]
3879
+ ], imports: [ReactiveFormsModule, MatFormField$1, MatLabel$1, MatInput, MatDatepickerInput, MatDatepickerToggle, MatDatepicker, MatSuffix, MatButton], template: "<div class=\"datetime-wrapper\" [class.datetime-mode]=\"isDateTime\" [class.has-seconds]=\"showSeconds\">\n <mat-form-field class=\"date-field\">\n @if (display) {\n <mat-label>{{ display }}</mat-label>\n }\n <input\n matInput\n [matDatepicker]=\"picker\"\n [placeholder]=\"placeHolder\"\n [formControl]=\"dateControl\"\n [disabled]=\"isDisabled\"\n (dateChange)=\"markTouched()\"\n (blur)=\"markTouched()\">\n <mat-datepicker-toggle matSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n\n @if (isDateTime) {\n <div class=\"middle-actions\">\n <button\n mat-icon-button\n type=\"button\"\n class=\"icon-action\"\n [disabled]=\"isDisabled\"\n title=\"Clear date and time\"\n aria-label=\"Clear date and time\"\n (click)=\"clear()\">\n <i class=\"fal fa-eraser\"></i>\n </button>\n\n <button\n mat-icon-button\n type=\"button\"\n class=\"icon-action\"\n [disabled]=\"isDisabled\"\n title=\"Open time clock\"\n aria-label=\"Open time clock\"\n (click)=\"openClock()\">\n <i class=\"fal fa-clock\"></i>\n </button>\n </div>\n\n <div class=\"time-row\">\n <mat-form-field class=\"time-field\">\n <mat-label>HH</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"23\"\n inputmode=\"numeric\"\n [formControl]=\"hourControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('hour')\"\n (blur)=\"onTimePartBlur('hour')\">\n </mat-form-field>\n\n <mat-form-field class=\"time-field\">\n <mat-label>MM</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"59\"\n inputmode=\"numeric\"\n [formControl]=\"minuteControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('minute')\"\n (blur)=\"onTimePartBlur('minute')\">\n </mat-form-field>\n\n @if (showSeconds) {\n <mat-form-field class=\"time-field\">\n <mat-label>SS</mat-label>\n <input\n matInput\n type=\"number\"\n min=\"0\"\n max=\"59\"\n inputmode=\"numeric\"\n [formControl]=\"secondControl\"\n [disabled]=\"isDisabled\"\n (input)=\"onTimePartInput('second')\"\n (blur)=\"onTimePartBlur('second')\">\n </mat-form-field>\n }\n </div>\n\n @if (isClockOpen) {\n <div class=\"clock-panel\">\n <div class=\"clock-panel-header\">\n <div class=\"clock-panel-title\">{{ clockTitle }}</div>\n <button\n mat-button\n type=\"button\"\n class=\"clock-close\"\n [disabled]=\"isDisabled\"\n (click)=\"closeClock()\">\n Close\n </button>\n </div>\n\n <div class=\"clock-summary\">\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'hour'\" (click)=\"goToClockStep('hour')\">\n {{ hourControl.value || '00' }}\n </button>\n <span>:</span>\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'minute'\" (click)=\"goToClockStep('minute')\">\n {{ minuteControl.value || '00' }}\n </button>\n @if (showSeconds) {\n <span>:</span>\n <button mat-button type=\"button\" class=\"clock-step\" [class.active]=\"clockStep === 'second'\" (click)=\"goToClockStep('second')\">\n {{ secondControl.value || '00' }}\n </button>\n }\n </div>\n\n <div class=\"clock-face\">\n @if (clockStep === 'hour') {\n @for (marker of hourMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker\"\n [class.selected]=\"isHourSelected(marker.value)\"\n [class.inner-ring]=\"marker.value >= 12\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockHour(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n @if (clockStep === 'minute') {\n @for (marker of minuteMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker clock-unit-marker\"\n [class.selected]=\"isMinuteSelected(marker.value)\"\n [class.major]=\"!!marker.label\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockMinute(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n @if (clockStep === 'second') {\n @for (marker of secondMarkers; track marker.value) {\n <button\n mat-icon-button\n type=\"button\"\n class=\"clock-marker clock-unit-marker\"\n [class.selected]=\"isSecondSelected(marker.value)\"\n [class.major]=\"!!marker.label\"\n [style.left]=\"marker.left\"\n [style.top]=\"marker.top\"\n (click)=\"selectClockSecond(marker.value)\">\n {{ marker.label }}\n </button>\n }\n }\n\n <div class=\"clock-center-dot\"></div>\n </div>\n\n <div class=\"clock-help\">\n @if (clockStep === 'hour') {\n <span>Outer ring 00-11, inner ring 12-23.</span>\n }\n @if (clockStep === 'minute') {\n <span>Choose the minute.</span>\n }\n @if (clockStep === 'second') {\n <span>Choose the second.</span>\n }\n </div>\n\n <div class=\"clock-footer\">\n <span>{{ timeSummary }}</span>\n </div>\n </div>\n }\n }\n</div>\n", styles: [".datetime-wrapper{display:flex;flex-direction:column;gap:8px;width:100%}.date-field,.time-field{width:100%}.middle-actions{display:flex;align-items:center;gap:4px;justify-content:flex-start}.icon-action{flex:0 0 auto}.icon-action i{font-size:1rem;line-height:1}.time-row{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr))}.clock-panel{display:flex;flex-direction:column;gap:10px;padding:12px;border:1px solid rgba(0,0,0,.12);border-radius:16px;background:#fff}.clock-panel-header,.clock-summary,.clock-footer{display:flex;align-items:center;justify-content:space-between;gap:8px}.clock-panel-title{font-size:.95rem;font-weight:600}.clock-summary{justify-content:center;font-size:1.1rem}.clock-step{min-width:52px;font-weight:600}.clock-step.active{background:#1976d21f}.clock-face{position:relative;align-self:center;width:min(100%,280px);aspect-ratio:1;border-radius:50%;background:radial-gradient(circle at center,rgba(25,118,210,.08) 0 16%,transparent 16% 100%),radial-gradient(circle at center,transparent 0 61%,rgba(25,118,210,.08) 61% 62%,transparent 62% 100%),radial-gradient(circle at center,#0000000a 0 100%)}.clock-marker{position:absolute;transform:translate(-50%,-50%);width:38px;height:38px;min-width:38px;padding:0;border-radius:50%;font-size:.72rem;line-height:1}.clock-marker.inner-ring{width:34px;height:34px;min-width:34px;font-size:.68rem}.clock-unit-marker{width:24px;height:24px;min-width:24px;font-size:.58rem;color:transparent}.clock-unit-marker.major{width:34px;height:34px;min-width:34px;font-size:.68rem;color:inherit}.clock-marker.selected{background:#1976d2;color:#fff}.clock-center-dot{position:absolute;top:50%;left:50%;width:12px;height:12px;border-radius:50%;transform:translate(-50%,-50%);background:#1976d2}.clock-help,.clock-footer{font-size:.78rem;color:#000000ad}@media(min-width:720px){.time-row{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:960px){.datetime-wrapper.datetime-mode{display:grid;align-items:start;gap:8px;grid-template-columns:minmax(240px,2fr) auto repeat(2,minmax(84px,96px))}.datetime-wrapper.datetime-mode.has-seconds{grid-template-columns:minmax(240px,2fr) auto repeat(3,minmax(84px,96px))}.datetime-wrapper.datetime-mode .date-field{margin-bottom:0}.datetime-wrapper.datetime-mode .middle-actions{align-self:start;padding-top:4px}.datetime-wrapper.datetime-mode .time-row{display:contents}.datetime-wrapper.datetime-mode .clock-panel{grid-column:1/-1}}\n"] }]
3760
3880
  }], ctorParameters: () => [{ type: undefined, decorators: [{
3761
3881
  type: Optional
3762
3882
  }, {