shirkasoft-ui-components 1.3.6 → 1.3.8

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.
@@ -18,6 +18,22 @@ import { TranslocoService } from '@jsverse/transloco';
18
18
  * min/max constraints and locale-aware labels.
19
19
  */
20
20
  class DatePickerComponent {
21
+ /** Localized range label for a week (e.g. '2 — 8 feb'). */
22
+ formatWeekRange(start, end) {
23
+ const loc = this.locale();
24
+ const dayFmt = new Intl.DateTimeFormat(loc, { day: 'numeric' });
25
+ const monthFmt = new Intl.DateTimeFormat(loc, { month: 'short' });
26
+ const startLabel = `${dayFmt.format(start)} ${monthFmt.format(start).replace('.', '')}`;
27
+ if (start.getMonth() !== end.getMonth() || start.getFullYear() !== end.getFullYear()) {
28
+ const year = start.getFullYear() !== end.getFullYear() ? ` ${end.getFullYear()}` : '';
29
+ return `${startLabel} — ${dayFmt.format(end)} ${monthFmt.format(end).replace('.', '')}${year}`;
30
+ }
31
+ return `${startLabel} — ${dayFmt.format(end)}`;
32
+ }
33
+ /** Localized label for a week row ('Semana N' / 'Week N'). */
34
+ weekLabel(index) {
35
+ return this.locale() === 'en' ? `Week ${index}` : `Semana ${index}`;
36
+ }
21
37
  constructor() {
22
38
  this.elementRef = inject(ElementRef);
23
39
  this.cdr = inject(ChangeDetectorRef);
@@ -25,8 +41,10 @@ class DatePickerComponent {
25
41
  this.transloco = inject(TranslocoService);
26
42
  /** HTML id for the input (for label/for pairing). */
27
43
  this.id = input('', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
28
- /** Granularity of the picker ('date' | 'month' | 'year'). */
44
+ /** Granularity of the picker ('date' | 'week' | 'month' | 'year'). */
29
45
  this.view = input('date', ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
46
+ /** First day of the week (0=Sunday ... 6=Saturday), used by week view. */
47
+ this.weekStart = input(0, ...(ngDevMode ? [{ debugName: "weekStart" }] : /* istanbul ignore next */ []));
30
48
  /** Label shown above the input. */
31
49
  this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
32
50
  /** Placeholder of the input. */
@@ -75,10 +93,14 @@ class DatePickerComponent {
75
93
  this.viewMeridiem = signal('AM', ...(ngDevMode ? [{ debugName: "viewMeridiem" }] : /* istanbul ignore next */ []));
76
94
  /** Date part selected but not yet committed until the time is confirmed. */
77
95
  this.pendingDate = signal(null, ...(ngDevMode ? [{ debugName: "pendingDate" }] : /* istanbul ignore next */ []));
96
+ /** Selected year during the selection flow (year -> month -> day). */
97
+ this.selectedYearValue = signal(null, ...(ngDevMode ? [{ debugName: "selectedYearValue" }] : /* istanbul ignore next */ []));
98
+ /** Selected month during the selection flow. */
99
+ this.selectedMonthValue = signal(null, ...(ngDevMode ? [{ debugName: "selectedMonthValue" }] : /* istanbul ignore next */ []));
78
100
  /** Analog clock mode: 'hours' or 'minutes'. */
79
101
  this.clockMode = signal('hours', ...(ngDevMode ? [{ debugName: "clockMode" }] : /* istanbul ignore next */ []));
80
102
  /** Internal view state for drill-down navigation (separates from input `view`). */
81
- this.currentView = signal('date', ...(ngDevMode ? [{ debugName: "currentView" }] : /* istanbul ignore next */ []));
103
+ this.currentView = signal('year', ...(ngDevMode ? [{ debugName: "currentView" }] : /* istanbul ignore next */ []));
82
104
  /** Whether the user is typing in the input field. */
83
105
  this.isTyping = signal(false, ...(ngDevMode ? [{ debugName: "isTyping" }] : /* istanbul ignore next */ []));
84
106
  /** The raw text being typed by the user. */
@@ -184,6 +206,10 @@ class DatePickerComponent {
184
206
  label = fmt.format(new Date(y, m - 1, 1));
185
207
  label = label.charAt(0).toUpperCase() + label.slice(1);
186
208
  }
209
+ else if (v === 'week') {
210
+ const start = new Date(datePart + 'T12:00:00');
211
+ label = this.formatWeekRange(start, new Date(start.getFullYear(), start.getMonth(), start.getDate() + 6));
212
+ }
187
213
  else {
188
214
  const fmt = new Intl.DateTimeFormat(this.locale(), {
189
215
  dateStyle: 'long',
@@ -230,11 +256,31 @@ class DatePickerComponent {
230
256
  days.push(i);
231
257
  return days;
232
258
  }, ...(ngDevMode ? [{ debugName: "calendarDays" }] : /* istanbul ignore next */ []));
259
+ /** Weeks of the viewed month (rows aligned to `weekStart`), for week view. */
260
+ this.monthWeeks = computed(() => {
261
+ const year = this.viewYear();
262
+ const month = this.viewMonth();
263
+ const ws = this.weekStart();
264
+ const first = new Date(year, month, 1);
265
+ const last = new Date(year, month + 1, 0);
266
+ const anchor = new Date(first.getFullYear(), first.getMonth(), first.getDate() - ((first.getDay() - ws + 7) % 7));
267
+ const weeks = [];
268
+ let cursor = anchor;
269
+ let index = 0;
270
+ while (cursor.getTime() <= last.getTime()) {
271
+ index++;
272
+ const start = cursor;
273
+ const end = new Date(start.getFullYear(), start.getMonth(), start.getDate() + 6);
274
+ weeks.push({ index, start, end, range: this.formatWeekRange(start, end) });
275
+ cursor = new Date(start.getFullYear(), start.getMonth(), start.getDate() + 7);
276
+ }
277
+ return weeks;
278
+ }, ...(ngDevMode ? [{ debugName: "monthWeeks" }] : /* istanbul ignore next */ []));
233
279
  /** Whether the prev navigation button is allowed by `minValue`. */
234
280
  this.canGoPrev = computed(() => {
235
- const v = this.view();
281
+ const v = this.currentView();
236
282
  const min = this.minValue();
237
- if (v === 'date') {
283
+ if (v === 'date' || v === 'week') {
238
284
  if (!min)
239
285
  return true;
240
286
  const prev = new Date(this.viewYear(), this.viewMonth() - 1, 1);
@@ -244,14 +290,15 @@ class DatePickerComponent {
244
290
  const minY = min ? Number(min.split('-')[0]) : undefined;
245
291
  return minY === undefined || this.viewYear() > minY;
246
292
  }
247
- const minY = min ? Number(min) : undefined;
293
+ // year view
294
+ const minY = min ? Number(min.split('-')[0]) : undefined;
248
295
  return minY === undefined || this.viewYear() > minY;
249
296
  }, ...(ngDevMode ? [{ debugName: "canGoPrev" }] : /* istanbul ignore next */ []));
250
297
  /** Whether the next navigation button is allowed by `maxValue`. */
251
298
  this.canGoNext = computed(() => {
252
- const v = this.view();
299
+ const v = this.currentView();
253
300
  const max = this.maxValue();
254
- if (v === 'date') {
301
+ if (v === 'date' || v === 'week') {
255
302
  if (!max)
256
303
  return true;
257
304
  const next = new Date(this.viewYear(), this.viewMonth() + 1, 1);
@@ -261,7 +308,8 @@ class DatePickerComponent {
261
308
  const maxY = max ? Number(max.split('-')[0]) : undefined;
262
309
  return maxY === undefined || this.viewYear() < maxY;
263
310
  }
264
- const maxY = max ? Number(max) : undefined;
311
+ // year view
312
+ const maxY = max ? Number(max.split('-')[0]) : undefined;
265
313
  return maxY === undefined || this.viewYear() < maxY;
266
314
  }, ...(ngDevMode ? [{ debugName: "canGoNext" }] : /* istanbul ignore next */ []));
267
315
  /** Year of the displayed date, if any. */
@@ -302,8 +350,6 @@ class DatePickerComponent {
302
350
  const loc = this.locale();
303
351
  return loc === 'en' ? 'MM/DD/YYYY' : 'DD/MM/YYYY';
304
352
  }, ...(ngDevMode ? [{ debugName: "inputFormat" }] : /* istanbul ignore next */ []));
305
- /** Whether the drill-down navigation is active (view differs from input). */
306
- this.isDrilledDown = computed(() => this.currentView() !== this.view(), ...(ngDevMode ? [{ debugName: "isDrilledDown" }] : /* istanbul ignore next */ []));
307
353
  /** (Unused legacy placeholder) plain year list. */
308
354
  this.years = [];
309
355
  // Attach error-state subscriptions to the validated control once found.
@@ -363,7 +409,9 @@ class DatePickerComponent {
363
409
  }
364
410
  else {
365
411
  this.syncViewToValue();
366
- this.currentView.set(this.view());
412
+ this.currentView.set(this.view() === 'week' ? 'week' : 'year');
413
+ this.selectedYearValue.set(null);
414
+ this.selectedMonthValue.set(null);
367
415
  this.clockMode.set('hours');
368
416
  this.isTyping.set(false);
369
417
  this.isOpen.set(true);
@@ -388,10 +436,16 @@ class DatePickerComponent {
388
436
  const timePart = val.includes('T') ? val.split('T')[1] : undefined;
389
437
  if (v === 'year') {
390
438
  this.viewYear.set(Number(datePart));
439
+ this.viewDecade.set(Math.floor(Number(datePart) / 10) * 10);
391
440
  }
392
441
  else if (v === 'month') {
393
442
  this.viewYear.set(Number(datePart.split('-')[0]));
394
443
  }
444
+ else if (v === 'week') {
445
+ const d = new Date(datePart + 'T12:00:00');
446
+ this.viewYear.set(d.getFullYear());
447
+ this.viewMonth.set(d.getMonth());
448
+ }
395
449
  else {
396
450
  const d = new Date(datePart + 'T12:00:00');
397
451
  this.viewYear.set(d.getFullYear());
@@ -424,7 +478,7 @@ class DatePickerComponent {
424
478
  }
425
479
  /** Navigates the calendar to the previous year/month/decade. */
426
480
  prev() {
427
- const v = this.view();
481
+ const v = this.currentView();
428
482
  if (v === 'year') {
429
483
  this.viewDecade.update((d) => d - 12);
430
484
  this.viewYear.update((y) => y - 12);
@@ -444,7 +498,7 @@ class DatePickerComponent {
444
498
  }
445
499
  /** Navigates the calendar to the next year/month/decade. */
446
500
  next() {
447
- const v = this.view();
501
+ const v = this.currentView();
448
502
  if (v === 'year') {
449
503
  this.viewDecade.update((d) => d + 12);
450
504
  this.viewYear.update((y) => y + 12);
@@ -462,37 +516,42 @@ class DatePickerComponent {
462
516
  });
463
517
  }
464
518
  }
465
- /** Selects a day of the month (pending if time is shown). */
466
- selectDay(day) {
467
- const y = this.viewYear();
468
- const m = String(this.viewMonth() + 1).padStart(2, '0');
469
- const d = String(day).padStart(2, '0');
470
- const value = `${y}-${m}-${d}`;
471
- if (this.showTime()) {
472
- this.pendingDate.set(value);
473
- return;
474
- }
475
- this.setValue(value);
519
+ /** Selects a year - stores it and navigates to month selection. */
520
+ selectYear(year) {
521
+ this.selectedYearValue.set(year);
522
+ this.viewYear.set(year);
523
+ this.currentView.set('month');
476
524
  }
477
- /** Selects a month of the year (pending if time is shown). */
525
+ /** Selects a month - stores it and navigates to day selection. */
478
526
  selectMonth(monthIndex) {
479
- const value = `${this.viewYear()}-${String(monthIndex + 1).padStart(2, '0')}`;
527
+ this.selectedMonthValue.set(monthIndex);
528
+ this.viewMonth.set(monthIndex);
529
+ this.currentView.set('date');
530
+ }
531
+ /** Selects a day - completes the date selection. */
532
+ selectDay(day) {
533
+ const year = this.selectedYearValue() ?? this.viewYear();
534
+ const month = this.selectedMonthValue() ?? this.viewMonth();
535
+ const m = String(month + 1).padStart(2, '0');
536
+ const d = String(day).padStart(2, '0');
537
+ const value = `${year}-${m}-${d}`;
480
538
  if (this.showTime()) {
481
539
  this.pendingDate.set(value);
482
540
  return;
483
541
  }
484
542
  this.setValue(value);
485
543
  }
486
- /** Selects a year (pending if time is shown). */
487
- selectYear(year) {
488
- const value = String(year);
544
+ /** Selects a week - emits its start date (YYYY-MM-DD). */
545
+ selectWeek(start) {
546
+ const value = `${start.getFullYear()}-` +
547
+ `${String(start.getMonth() + 1).padStart(2, '0')}-` +
548
+ `${String(start.getDate()).padStart(2, '0')}`;
489
549
  if (this.showTime()) {
490
550
  this.pendingDate.set(value);
491
551
  return;
492
552
  }
493
553
  this.setValue(value);
494
554
  }
495
- /** Commits a value, updates the component, the control and the outputs. */
496
555
  setValue(value, close = true) {
497
556
  this._value.set(value);
498
557
  this.onChange(value);
@@ -721,21 +780,15 @@ class DatePickerComponent {
721
780
  y2: 100 + innerR * Math.sin(angle),
722
781
  };
723
782
  }
724
- /** Switches the drill-down view to months (from date view). */
725
- drillToMonths() {
726
- this.currentView.set('month');
727
- }
728
- /** Switches the drill-down view to years (from month view). */
729
- drillToYears() {
730
- this.currentView.set('year');
731
- }
732
783
  /** Drills down from year view to month view for the selected year. */
733
784
  drillDownToMonth(year) {
785
+ this.selectedYearValue.set(year);
734
786
  this.viewYear.set(year);
735
787
  this.currentView.set('month');
736
788
  }
737
789
  /** Drills down from month view to date view for the selected month. */
738
790
  drillDownToDate(monthIndex) {
791
+ this.selectedMonthValue.set(monthIndex);
739
792
  this.viewMonth.set(monthIndex);
740
793
  this.currentView.set('date');
741
794
  }
@@ -743,15 +796,19 @@ class DatePickerComponent {
743
796
  drillUp() {
744
797
  const v = this.currentView();
745
798
  if (v === 'date') {
799
+ this.selectedMonthValue.set(null);
746
800
  this.currentView.set('month');
747
801
  }
748
802
  else if (v === 'month') {
803
+ this.selectedYearValue.set(null);
749
804
  this.currentView.set('year');
750
805
  }
751
806
  }
752
- /** Returns to the initial view from any drill-down level. */
807
+ /** Returns to the initial view (year selection). */
753
808
  drillToInitial() {
754
- this.currentView.set(this.view());
809
+ this.selectedYearValue.set(null);
810
+ this.selectedMonthValue.set(null);
811
+ this.currentView.set('year');
755
812
  }
756
813
  /** Formats input placeholder based on locale. */
757
814
  inputPlaceholder() {
@@ -761,6 +818,9 @@ class DatePickerComponent {
761
818
  return 'YYYY';
762
819
  if (this.view() === 'month')
763
820
  return 'MM/YYYY';
821
+ if (this.view() === 'week') {
822
+ return this.locale() === 'en' ? 'Week · MM/YYYY' : 'Semana · MM/YYYY';
823
+ }
764
824
  return this.inputFormat();
765
825
  }
766
826
  /** Handles text input in the date field. */
@@ -817,6 +877,8 @@ class DatePickerComponent {
817
877
  if (this.timeOnly()) {
818
878
  return this.parseTimeOnly(clean);
819
879
  }
880
+ if (this.view() === 'week')
881
+ return null;
820
882
  if (this.view() === 'year') {
821
883
  const y = Number(parts[0]);
822
884
  if (parts.length === 1 && y >= 1900 && y <= 2100)
@@ -899,17 +961,35 @@ class DatePickerComponent {
899
961
  this.viewMonth() === now.getMonth() &&
900
962
  day === now.getDate());
901
963
  }
964
+ /** ISO date (YYYY-MM-DD) of the week start containing the given date. */
965
+ weekStartISO(date) {
966
+ const ws = this.weekStart();
967
+ const start = new Date(date.getFullYear(), date.getMonth(), date.getDate() - ((date.getDay() - ws + 7) % 7));
968
+ return (`${start.getFullYear()}-` +
969
+ `${String(start.getMonth() + 1).padStart(2, '0')}-` +
970
+ `${String(start.getDate()).padStart(2, '0')}`);
971
+ }
972
+ /** Whether the given week row contains the displayed/selected date. */
973
+ isSelectedWeek(start) {
974
+ const date = this.displayedDate();
975
+ if (!date)
976
+ return false;
977
+ return this.weekStartISO(new Date(date + 'T12:00:00')) === this.weekStartISO(start);
978
+ }
979
+ /** Whether the given week row contains today's date. */
980
+ isCurrentWeek(start) {
981
+ return this.weekStartISO(new Date()) === this.weekStartISO(start);
982
+ }
902
983
  /** Whether the given month matches the selected month and year. */
903
984
  isSelectedMonth(monthIndex) {
904
- return (this.selectedYear() === this.viewYear() &&
905
- this.selectedMonth() === monthIndex);
985
+ return this.selectedMonthValue() === monthIndex;
906
986
  }
907
987
  isCurrentMonth(monthIndex) {
908
988
  const now = new Date();
909
- return (this.viewYear() === now.getFullYear() && monthIndex === now.getMonth());
989
+ return this.viewYear() === now.getFullYear() && monthIndex === now.getMonth();
910
990
  }
911
991
  isSelectedYear(year) {
912
- return this.selectedYear() === year;
992
+ return this.selectedYearValue() === year;
913
993
  }
914
994
  isCurrentYear(year) {
915
995
  return new Date().getFullYear() === year;
@@ -928,13 +1008,13 @@ class DatePickerComponent {
928
1008
  this.cdr.markForCheck();
929
1009
  }
930
1010
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
931
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: DatePickerComponent, isStandalone: true, selector: "shk-date-picker", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, errorMessages: { classPropertyName: "errorMessages", publicName: "errorMessages", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, timeOnly: { classPropertyName: "timeOnly", publicName: "timeOnly", isSignal: true, isRequired: false, transformFunction: null }, showTime: { classPropertyName: "showTime", publicName: "showTime", isSignal: true, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, providers: [
1011
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: DatePickerComponent, isStandalone: true, selector: "shk-date-picker", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, weekStart: { classPropertyName: "weekStart", publicName: "weekStart", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, errorMessages: { classPropertyName: "errorMessages", publicName: "errorMessages", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, timeOnly: { classPropertyName: "timeOnly", publicName: "timeOnly", isSignal: true, isRequired: false, transformFunction: null }, showTime: { classPropertyName: "showTime", publicName: "showTime", isSignal: true, isRequired: false, transformFunction: null }, hourFormat: { classPropertyName: "hourFormat", publicName: "hourFormat", isSignal: true, isRequired: false, transformFunction: null }, showSeconds: { classPropertyName: "showSeconds", publicName: "showSeconds", isSignal: true, isRequired: false, transformFunction: null }, minuteStep: { classPropertyName: "minuteStep", publicName: "minuteStep", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "onEscape()" } }, providers: [
932
1012
  {
933
1013
  provide: NG_VALUE_ACCESSOR,
934
1014
  useExisting: forwardRef(() => DatePickerComponent),
935
1015
  multi: true,
936
1016
  },
937
- ], ngImport: i0, template: "<div class=\"relative mb-4\">\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n </div>\n }\n\n <div class=\"relative\">\n <div class=\"relative\">\n <input\n [id]=\"id()\"\n type=\"text\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isTyping() ? typedValue() : displayLabel()\"\n (input)=\"onInputText($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown.enter)=\"$any($event.target).blur()\"\n (keydown.escape)=\"cancelTyping()\"\n (click)=\"toggle()\"\n class=\"date-input-field\"\n [ngClass]=\"{\n 'input-error': shouldShowError() || typingValid() === false,\n 'input-valid': wasFixedError() || typingValid() === true,\n }\"\n [attr.aria-invalid]=\"shouldShowError()\"\n [attr.aria-describedby]=\"shouldShowError() ? id() + '-error' : null\"\n />\n <button\n type=\"button\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n class=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 _shk-text-surface-400 dark:[color:var(--shk-surface-400)] hover:[color:var(--shk-surface-600)] dark:hover:[color:var(--shk-surface-300)] transition-colors\"\n >\n <svg\n class=\"w-4 h-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"></rect>\n <path d=\"M16 2v4M8 2v4M3 10h18\"></path>\n </svg>\n </button>\n </div>\n\n @if (isOpen()) {\n <div class=\"fixed inset-0 z-40 bg-black/30\" (click)=\"close()\"></div>\n <div\n class=\"fixed z-50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-72 p-4 bg-white dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-lg shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <!-- DATE VIEW -->\n @if (!timeOnly() && currentView() === 'date') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"drillToMonths()\"\n class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] hover:_shk-text-primary cursor-pointer hover:underline transition-colors\"\n >\n {{ monthNames()[viewMonth()] }} {{ viewYear() }}\n </button>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (name of dayNames(); track $index) {\n <div class=\"text-center text-xs font-medium _shk-text-surface-400 dark:[color:var(--shk-surface-400)] py-1\">\n {{ name }}\n </div>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day !== null) {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"py-1.5 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedDay(day),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isToday(day) && !isSelectedDay(day),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedDay(day) && !isToday(day),\n }\"\n >\n {{ day }}\n </button>\n } @else {\n <div></div>\n }\n }\n </div>\n }\n\n <!-- MONTH VIEW -->\n @if (!timeOnly() && currentView() === 'month') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"drillToYears()\"\n class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] hover:_shk-text-primary cursor-pointer hover:underline transition-colors\"\n >\n {{ viewYear() }}\n </button>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (name of monthNames(); track $index) {\n <button\n type=\"button\"\n (click)=\"drillDownToDate($index)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedMonth($index),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentMonth($index) && !isSelectedMonth($index),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedMonth($index) && !isCurrentMonth($index),\n }\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- YEAR VIEW -->\n @if (!timeOnly() && currentView() === 'year') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ viewDecade() }} - {{ viewDecade() + 11 }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (year of decadeYears(); track year) {\n <button\n type=\"button\"\n (click)=\"drillDownToMonth(year)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedYear(year),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentYear(year) && !isSelectedYear(year),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedYear(year) && !isCurrentYear(year),\n }\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n\n <!-- ANALOG CLOCK TIME PICKER -->\n @if (timeOnly() || showTime()) {\n <div class=\"mt-3 pt-3 _shk-border dark:[border-color:var(--shk-surface-200)]\">\n <!-- Clock display time -->\n <div class=\"text-center mb-2\">\n <span class=\"text-lg font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ clockDisplayTime() }}\n </span>\n </div>\n\n <!-- Analog clock face -->\n <div class=\"clock-container\">\n <svg\n viewBox=\"0 0 200 200\"\n class=\"w-full h-full cursor-pointer\"\n (click)=\"onClockClick($event, clockMode())\"\n >\n <!-- Clock face background -->\n <circle cx=\"100\" cy=\"100\" r=\"96\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\"\n class=\"_shk-text-surface-200 dark:[color:var(--shk-surface-200)]\" />\n\n <!-- Minute markers -->\n @if (clockMode() === 'minutes') {\n @for (i of [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]; track i) {\n <line\n [attr.x1]=\"clockMinuteMarker(i).x1\"\n [attr.y1]=\"clockMinuteMarker(i).y1\"\n [attr.x2]=\"clockMinuteMarker(i).x2\"\n [attr.y2]=\"clockMinuteMarker(i).y2\"\n [attr.stroke-width]=\"i % 5 === 0 ? 2 : 1\"\n [class]=\"i % 5 === 0 ? '_shk-text-surface-500 dark:[color:var(--shk-surface-500)]' : '_shk-text-surface-300 dark:[color:var(--shk-surface-400)]'\"\n stroke=\"currentColor\"\n />\n }\n <!-- Minute numbers (00, 05, 10, ...) -->\n @for (m of [0,5,10,15,20,25,30,35,40,45,50,55]; track m) {\n <text\n [attr.x]=\"clockMinutePos(m).x\"\n [attr.y]=\"clockMinutePos(m).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-[9px] _shk-text-surface-500 dark:[color:var(--shk-surface-400)]\"\n [class._shk-text-primary]=\"viewMinute() === m\"\n >\n {{ m.toString().padStart(2, '0') }}\n </text>\n }\n }\n\n <!-- Hour numbers -->\n @if (clockMode() === 'hours') {\n @for (h of clockHours(); track h) {\n <text\n [attr.x]=\"clockNumberPos(h).x\"\n [attr.y]=\"clockNumberPos(h).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-sm font-medium\"\n [class._shk-text-primary]=\"isClockHourSelected(h)\"\n [class._shk-text-surface-700]=\"!isClockHourSelected(h)\"\n >\n {{ h }}\n </text>\n }\n }\n\n <!-- Clock hand -->\n <line\n x1=\"100\" y1=\"100\"\n [attr.x2]=\"clockHandLine(60).x2\"\n [attr.y2]=\"clockHandLine(60).y2\"\n class=\"_shk-text-primary\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n\n <!-- Center dot -->\n <circle cx=\"100\" cy=\"100\" r=\"4\" class=\"fill-current _shk-text-primary\" />\n </svg>\n </div>\n\n <!-- Mode toggle: Hours / Minutes -->\n <div class=\"clock-mode-toggle\">\n <button\n type=\"button\"\n (click)=\"clockMode.set('hours')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'hours'\"\n >\n {{ 'Horas' }}\n </button>\n <button\n type=\"button\"\n (click)=\"clockMode.set('minutes')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'minutes'\"\n >\n {{ 'Minutos' }}\n </button>\n </div>\n\n <!-- AM/PM toggle for 12h format -->\n @if (hourFormat() === '12') {\n <div class=\"flex items-center justify-center gap-2 mt-2\">\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('AM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'AM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'AM'\n }\"\n >\n AM\n </button>\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('PM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'PM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'PM'\n }\"\n >\n PM\n </button>\n </div>\n }\n\n <!-- Seconds selector (if enabled) -->\n @if (showSeconds()) {\n <div class=\"flex items-center justify-center gap-1 mt-2\">\n <span class=\"text-xs _shk-text-surface-400\">Seg:</span>\n <select\n class=\"px-2 py-1 text-xs _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-md\"\n [value]=\"viewSecond()\"\n (change)=\"onSecondChange($event)\"\n aria-label=\"Segundos\"\n >\n @for (seconds of secondsRange(); track seconds) {\n <option [value]=\"seconds\">{{ minutesLabel(seconds) }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Confirm button -->\n <button\n type=\"button\"\n (click)=\"confirmTime()\"\n class=\"mt-3 w-full py-2 text-sm _shk-bg-primary _shk-text-white rounded-lg hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n {{ timeOnly() ? 'Confirmar' : 'Introducir hora' }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n @if (shouldShowError()) {\n <div [id]=\"id() + '-error'\" class=\"mt-1 text-xs text-red-500 max-h-20 overflow-y-auto _shk-scrollbar\">\n <ul class=\"list-disc pl-4 space-y-1\">\n @for (error of getErrorMessages(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </div>\n }\n</div>\n", styles: [".clock-container{position:relative;width:200px;height:200px;margin:0 auto}.clock-face{width:100%;height:100%;border-radius:50%;border:2px solid var(--shk-surface-200);position:relative;background-color:var(--shk-surface-50)}.dark .clock-face{border-color:var(--shk-surface-200);background-color:var(--shk-surface-100)}.clock-number{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:background-color .15s,color .15s;-webkit-user-select:none;user-select:none;color:var(--shk-surface-700)}.dark .clock-number{color:var(--shk-surface-700)}.clock-number:hover{background-color:var(--shk-surface-100)}.dark .clock-number:hover{background-color:var(--shk-surface-200)}.clock-number.selected{background-color:var(--shk-primary-500);color:#fff}.clock-number.current{font-weight:700}.clock-hand{position:absolute;bottom:50%;left:50%;width:2px;background-color:var(--shk-primary-500);transform-origin:bottom center;border-radius:1px;pointer-events:none;transition:transform .2s ease-out}.clock-center{position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;background-color:var(--shk-primary-500);transform:translate(-50%,-50%);pointer-events:none;z-index:2}.clock-minute-marker{position:absolute;width:1px;height:8px;background-color:var(--shk-surface-300);top:6px;left:50%;transform-origin:center 94px}.dark .clock-minute-marker{background-color:var(--shk-surface-400)}.clock-minute-marker.major{width:2px;height:12px;background-color:var(--shk-surface-400)}.dark .clock-minute-marker.major{background-color:var(--shk-surface-500)}.clock-mode-toggle{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.75rem}.clock-mode-btn{padding:.25rem .75rem;font-size:.75rem;font-weight:500;border-radius:9999px;cursor:pointer;transition:background-color .15s,color .15s;border:none;background:transparent;color:var(--shk-surface-500)}.dark .clock-mode-btn{color:var(--shk-surface-400)}.clock-mode-btn.active{background-color:var(--shk-primary-500);color:#fff}.clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-100)}.dark .clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-200)}.date-input-field{width:100%;padding:.5rem 2.5rem .5rem .75rem;font-size:.875rem;border-radius:.5rem;outline:none;transition:border-color .15s,box-shadow .15s;background-color:var(--shk-surface-50);color:var(--shk-surface-700);border:1px solid var(--shk-surface-200)}.dark .date-input-field{background-color:var(--shk-surface-100);color:var(--shk-surface-700);border-color:var(--shk-surface-200)}.date-input-field::placeholder{color:var(--shk-surface-400)}.dark .date-input-field::placeholder{color:var(--shk-surface-400)}.date-input-field:focus{border-color:var(--shk-primary-500);box-shadow:0 0 0 1px var(--shk-primary-500)}.date-input-field:disabled{opacity:.5;cursor:not-allowed}.date-input-field.input-error{border-color:#ef4444}.date-input-field.input-error:focus{border-color:#ef4444;box-shadow:0 0 0 1px #ef4444}.date-input-field.input-valid{border-color:#22c55e}.date-input-field.input-valid:focus{border-color:#22c55e;box-shadow:0 0 0 1px #22c55e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1017
+ ], ngImport: i0, template: "<div class=\"relative mb-4\">\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n </div>\n }\n\n <div class=\"relative\">\n <div class=\"relative\">\n <input\n [id]=\"id()\"\n type=\"text\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isTyping() ? typedValue() : displayLabel()\"\n (input)=\"onInputText($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown.enter)=\"$any($event.target).blur()\"\n (keydown.escape)=\"cancelTyping()\"\n (click)=\"toggle()\"\n class=\"date-input-field\"\n [ngClass]=\"{\n 'input-error': shouldShowError() || typingValid() === false,\n 'input-valid': wasFixedError() || typingValid() === true,\n }\"\n [attr.aria-invalid]=\"shouldShowError()\"\n [attr.aria-describedby]=\"shouldShowError() ? id() + '-error' : null\"\n />\n <button\n type=\"button\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n class=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 _shk-text-surface-400 dark:[color:var(--shk-surface-400)] hover:[color:var(--shk-surface-600)] dark:hover:[color:var(--shk-surface-300)] transition-colors\"\n >\n <svg\n class=\"w-4 h-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"></rect>\n <path d=\"M16 2v4M8 2v4M3 10h18\"></path>\n </svg>\n </button>\n </div>\n\n @if (isOpen()) {\n <div class=\"fixed inset-0 z-40 bg-black/30\" (click)=\"close()\"></div>\n <div\n class=\"fixed z-50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-72 p-4 bg-white dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-lg shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <!-- DATE VIEW -->\n @if (!timeOnly() && currentView() === 'date') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"drillUp()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ monthNames()[viewMonth()] }} {{ selectedYearValue() ?? viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"drillToInitial()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (name of dayNames(); track $index) {\n <div class=\"text-center text-xs font-medium _shk-text-surface-400 dark:[color:var(--shk-surface-400)] py-1\">\n {{ name }}\n </div>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day !== null) {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"py-1.5 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedDay(day),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isToday(day) && !isSelectedDay(day),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedDay(day) && !isToday(day),\n }\"\n >\n {{ day }}\n </button>\n } @else {\n <div></div>\n }\n }\n </div>\n }\n\n <!-- WEEK VIEW -->\n @if (!timeOnly() && currentView() === 'week') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ monthNames()[viewMonth()] }} {{ viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"space-y-1\">\n @for (week of monthWeeks(); track week.index) {\n <button\n type=\"button\"\n (click)=\"selectWeek(week.start)\"\n class=\"w-full flex items-center justify-between py-1.5 px-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedWeek(week.start),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentWeek(week.start) && !isSelectedWeek(week.start),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedWeek(week.start) && !isCurrentWeek(week.start),\n }\"\n >\n <span class=\"font-medium\">{{ weekLabel(week.index) }}</span>\n <span class=\"text-xs opacity-80\">{{ week.range }}</span>\n </button>\n }\n </div>\n }\n\n <!-- MONTH VIEW -->\n @if (!timeOnly() && currentView() === 'month') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"drillUp()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ selectedYearValue() ?? viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"drillToInitial()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (name of monthNames(); track $index) {\n <button\n type=\"button\"\n (click)=\"selectMonth($index)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': selectedMonthValue() === $index,\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentMonth($index) && selectedMonthValue() !== $index,\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': selectedMonthValue() !== $index && !isCurrentMonth($index),\n }\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- YEAR VIEW -->\n @if (!timeOnly() && currentView() === 'year') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ viewDecade() }} - {{ viewDecade() + 11 }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (year of decadeYears(); track year) {\n <button\n type=\"button\"\n (click)=\"selectYear(year)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': selectedYearValue() === year,\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentYear(year) && selectedYearValue() !== year,\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': selectedYearValue() !== year && !isCurrentYear(year),\n }\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n\n <!-- ANALOG CLOCK TIME PICKER -->\n @if (timeOnly() || showTime()) {\n <div class=\"mt-3 pt-3 _shk-border dark:[border-color:var(--shk-surface-200)]\">\n <!-- Clock display time -->\n <div class=\"text-center mb-2\">\n <span class=\"text-lg font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ clockDisplayTime() }}\n </span>\n </div>\n\n <!-- Analog clock face -->\n <div class=\"clock-container\">\n <svg\n viewBox=\"0 0 200 200\"\n class=\"w-full h-full cursor-pointer\"\n (click)=\"onClockClick($event, clockMode())\"\n >\n <!-- Clock face background -->\n <circle cx=\"100\" cy=\"100\" r=\"96\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\"\n class=\"_shk-text-surface-200 dark:[color:var(--shk-surface-200)]\" />\n\n <!-- Minute markers -->\n @if (clockMode() === 'minutes') {\n @for (i of [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]; track i) {\n <line\n [attr.x1]=\"clockMinuteMarker(i).x1\"\n [attr.y1]=\"clockMinuteMarker(i).y1\"\n [attr.x2]=\"clockMinuteMarker(i).x2\"\n [attr.y2]=\"clockMinuteMarker(i).y2\"\n [attr.stroke-width]=\"i % 5 === 0 ? 2 : 1\"\n [class]=\"i % 5 === 0 ? '_shk-text-surface-500 dark:[color:var(--shk-surface-500)]' : '_shk-text-surface-300 dark:[color:var(--shk-surface-400)]'\"\n stroke=\"currentColor\"\n />\n }\n <!-- Minute numbers (00, 05, 10, ...) -->\n @for (m of [0,5,10,15,20,25,30,35,40,45,50,55]; track m) {\n <text\n [attr.x]=\"clockMinutePos(m).x\"\n [attr.y]=\"clockMinutePos(m).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-[9px] _shk-text-surface-500 dark:[color:var(--shk-surface-400)]\"\n [class._shk-text-primary]=\"viewMinute() === m\"\n >\n {{ m.toString().padStart(2, '0') }}\n </text>\n }\n }\n\n <!-- Hour numbers -->\n @if (clockMode() === 'hours') {\n @for (h of clockHours(); track h) {\n <text\n [attr.x]=\"clockNumberPos(h).x\"\n [attr.y]=\"clockNumberPos(h).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-sm font-medium\"\n [class._shk-text-primary]=\"isClockHourSelected(h)\"\n [class._shk-text-surface-700]=\"!isClockHourSelected(h)\"\n >\n {{ h }}\n </text>\n }\n }\n\n <!-- Clock hand -->\n <line\n x1=\"100\" y1=\"100\"\n [attr.x2]=\"clockHandLine(60).x2\"\n [attr.y2]=\"clockHandLine(60).y2\"\n class=\"_shk-text-primary\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n\n <!-- Center dot -->\n <circle cx=\"100\" cy=\"100\" r=\"4\" class=\"fill-current _shk-text-primary\" />\n </svg>\n </div>\n\n <!-- Mode toggle: Hours / Minutes -->\n <div class=\"clock-mode-toggle\">\n <button\n type=\"button\"\n (click)=\"clockMode.set('hours')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'hours'\"\n >\n {{ 'Horas' }}\n </button>\n <button\n type=\"button\"\n (click)=\"clockMode.set('minutes')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'minutes'\"\n >\n {{ 'Minutos' }}\n </button>\n </div>\n\n <!-- AM/PM toggle for 12h format -->\n @if (hourFormat() === '12') {\n <div class=\"flex items-center justify-center gap-2 mt-2\">\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('AM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'AM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'AM'\n }\"\n >\n AM\n </button>\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('PM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'PM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'PM'\n }\"\n >\n PM\n </button>\n </div>\n }\n\n <!-- Seconds selector (if enabled) -->\n @if (showSeconds()) {\n <div class=\"flex items-center justify-center gap-1 mt-2\">\n <span class=\"text-xs _shk-text-surface-400\">Seg:</span>\n <select\n class=\"px-2 py-1 text-xs _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-md\"\n [value]=\"viewSecond()\"\n (change)=\"onSecondChange($event)\"\n aria-label=\"Segundos\"\n >\n @for (seconds of secondsRange(); track seconds) {\n <option [value]=\"seconds\">{{ minutesLabel(seconds) }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Confirm button -->\n <button\n type=\"button\"\n (click)=\"confirmTime()\"\n class=\"mt-3 w-full py-2 text-sm _shk-bg-primary _shk-text-white rounded-lg hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n {{ timeOnly() ? 'Confirmar' : 'Introducir hora' }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n @if (shouldShowError()) {\n <div [id]=\"id() + '-error'\" class=\"mt-1 text-xs text-red-500 max-h-20 overflow-y-auto _shk-scrollbar\">\n <ul class=\"list-disc pl-4 space-y-1\">\n @for (error of getErrorMessages(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </div>\n }\n</div>\n", styles: [".clock-container{position:relative;width:200px;height:200px;margin:0 auto}.clock-face{width:100%;height:100%;border-radius:50%;border:2px solid var(--shk-surface-200);position:relative;background-color:var(--shk-surface-50)}.dark .clock-face{border-color:var(--shk-surface-200);background-color:var(--shk-surface-100)}.clock-number{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:background-color .15s,color .15s;-webkit-user-select:none;user-select:none;color:var(--shk-surface-700)}.dark .clock-number{color:var(--shk-surface-700)}.clock-number:hover{background-color:var(--shk-surface-100)}.dark .clock-number:hover{background-color:var(--shk-surface-200)}.clock-number.selected{background-color:var(--shk-primary-500);color:#fff}.clock-number.current{font-weight:700}.clock-hand{position:absolute;bottom:50%;left:50%;width:2px;background-color:var(--shk-primary-500);transform-origin:bottom center;border-radius:1px;pointer-events:none;transition:transform .2s ease-out}.clock-center{position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;background-color:var(--shk-primary-500);transform:translate(-50%,-50%);pointer-events:none;z-index:2}.clock-minute-marker{position:absolute;width:1px;height:8px;background-color:var(--shk-surface-300);top:6px;left:50%;transform-origin:center 94px}.dark .clock-minute-marker{background-color:var(--shk-surface-400)}.clock-minute-marker.major{width:2px;height:12px;background-color:var(--shk-surface-400)}.dark .clock-minute-marker.major{background-color:var(--shk-surface-500)}.clock-mode-toggle{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.75rem}.clock-mode-btn{padding:.25rem .75rem;font-size:.75rem;font-weight:500;border-radius:9999px;cursor:pointer;transition:background-color .15s,color .15s;border:none;background:transparent;color:var(--shk-surface-500)}.dark .clock-mode-btn{color:var(--shk-surface-400)}.clock-mode-btn.active{background-color:var(--shk-primary-500);color:#fff}.clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-100)}.dark .clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-200)}.date-input-field{width:100%;padding:.5rem 2.5rem .5rem .75rem;font-size:.875rem;border-radius:.5rem;outline:none;transition:border-color .15s,box-shadow .15s;background-color:var(--shk-surface-50);color:var(--shk-surface-700);border:1px solid var(--shk-surface-200)}.dark .date-input-field{background-color:var(--shk-surface-100);color:var(--shk-surface-700);border-color:var(--shk-surface-200)}.date-input-field::placeholder{color:var(--shk-surface-400)}.dark .date-input-field::placeholder{color:var(--shk-surface-400)}.date-input-field:focus{border-color:var(--shk-primary-500);box-shadow:0 0 0 1px var(--shk-primary-500)}.date-input-field:disabled{opacity:.5;cursor:not-allowed}.date-input-field.input-error{border-color:#ef4444}.date-input-field.input-error:focus{border-color:#ef4444;box-shadow:0 0 0 1px #ef4444}.date-input-field.input-valid{border-color:#22c55e}.date-input-field.input-valid:focus{border-color:#22c55e;box-shadow:0 0 0 1px #22c55e}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
938
1018
  }
939
1019
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DatePickerComponent, decorators: [{
940
1020
  type: Component,
@@ -944,8 +1024,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImpo
944
1024
  useExisting: forwardRef(() => DatePickerComponent),
945
1025
  multi: true,
946
1026
  },
947
- ], template: "<div class=\"relative mb-4\">\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n </div>\n }\n\n <div class=\"relative\">\n <div class=\"relative\">\n <input\n [id]=\"id()\"\n type=\"text\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isTyping() ? typedValue() : displayLabel()\"\n (input)=\"onInputText($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown.enter)=\"$any($event.target).blur()\"\n (keydown.escape)=\"cancelTyping()\"\n (click)=\"toggle()\"\n class=\"date-input-field\"\n [ngClass]=\"{\n 'input-error': shouldShowError() || typingValid() === false,\n 'input-valid': wasFixedError() || typingValid() === true,\n }\"\n [attr.aria-invalid]=\"shouldShowError()\"\n [attr.aria-describedby]=\"shouldShowError() ? id() + '-error' : null\"\n />\n <button\n type=\"button\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n class=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 _shk-text-surface-400 dark:[color:var(--shk-surface-400)] hover:[color:var(--shk-surface-600)] dark:hover:[color:var(--shk-surface-300)] transition-colors\"\n >\n <svg\n class=\"w-4 h-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"></rect>\n <path d=\"M16 2v4M8 2v4M3 10h18\"></path>\n </svg>\n </button>\n </div>\n\n @if (isOpen()) {\n <div class=\"fixed inset-0 z-40 bg-black/30\" (click)=\"close()\"></div>\n <div\n class=\"fixed z-50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-72 p-4 bg-white dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-lg shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <!-- DATE VIEW -->\n @if (!timeOnly() && currentView() === 'date') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"drillToMonths()\"\n class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] hover:_shk-text-primary cursor-pointer hover:underline transition-colors\"\n >\n {{ monthNames()[viewMonth()] }} {{ viewYear() }}\n </button>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (name of dayNames(); track $index) {\n <div class=\"text-center text-xs font-medium _shk-text-surface-400 dark:[color:var(--shk-surface-400)] py-1\">\n {{ name }}\n </div>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day !== null) {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"py-1.5 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedDay(day),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isToday(day) && !isSelectedDay(day),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedDay(day) && !isToday(day),\n }\"\n >\n {{ day }}\n </button>\n } @else {\n <div></div>\n }\n }\n </div>\n }\n\n <!-- MONTH VIEW -->\n @if (!timeOnly() && currentView() === 'month') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <button\n type=\"button\"\n (click)=\"drillToYears()\"\n class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] hover:_shk-text-primary cursor-pointer hover:underline transition-colors\"\n >\n {{ viewYear() }}\n </button>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (name of monthNames(); track $index) {\n <button\n type=\"button\"\n (click)=\"drillDownToDate($index)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedMonth($index),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentMonth($index) && !isSelectedMonth($index),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedMonth($index) && !isCurrentMonth($index),\n }\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- YEAR VIEW -->\n @if (!timeOnly() && currentView() === 'year') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ viewDecade() }} - {{ viewDecade() + 11 }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (year of decadeYears(); track year) {\n <button\n type=\"button\"\n (click)=\"drillDownToMonth(year)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedYear(year),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentYear(year) && !isSelectedYear(year),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedYear(year) && !isCurrentYear(year),\n }\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n\n <!-- ANALOG CLOCK TIME PICKER -->\n @if (timeOnly() || showTime()) {\n <div class=\"mt-3 pt-3 _shk-border dark:[border-color:var(--shk-surface-200)]\">\n <!-- Clock display time -->\n <div class=\"text-center mb-2\">\n <span class=\"text-lg font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ clockDisplayTime() }}\n </span>\n </div>\n\n <!-- Analog clock face -->\n <div class=\"clock-container\">\n <svg\n viewBox=\"0 0 200 200\"\n class=\"w-full h-full cursor-pointer\"\n (click)=\"onClockClick($event, clockMode())\"\n >\n <!-- Clock face background -->\n <circle cx=\"100\" cy=\"100\" r=\"96\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\"\n class=\"_shk-text-surface-200 dark:[color:var(--shk-surface-200)]\" />\n\n <!-- Minute markers -->\n @if (clockMode() === 'minutes') {\n @for (i of [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]; track i) {\n <line\n [attr.x1]=\"clockMinuteMarker(i).x1\"\n [attr.y1]=\"clockMinuteMarker(i).y1\"\n [attr.x2]=\"clockMinuteMarker(i).x2\"\n [attr.y2]=\"clockMinuteMarker(i).y2\"\n [attr.stroke-width]=\"i % 5 === 0 ? 2 : 1\"\n [class]=\"i % 5 === 0 ? '_shk-text-surface-500 dark:[color:var(--shk-surface-500)]' : '_shk-text-surface-300 dark:[color:var(--shk-surface-400)]'\"\n stroke=\"currentColor\"\n />\n }\n <!-- Minute numbers (00, 05, 10, ...) -->\n @for (m of [0,5,10,15,20,25,30,35,40,45,50,55]; track m) {\n <text\n [attr.x]=\"clockMinutePos(m).x\"\n [attr.y]=\"clockMinutePos(m).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-[9px] _shk-text-surface-500 dark:[color:var(--shk-surface-400)]\"\n [class._shk-text-primary]=\"viewMinute() === m\"\n >\n {{ m.toString().padStart(2, '0') }}\n </text>\n }\n }\n\n <!-- Hour numbers -->\n @if (clockMode() === 'hours') {\n @for (h of clockHours(); track h) {\n <text\n [attr.x]=\"clockNumberPos(h).x\"\n [attr.y]=\"clockNumberPos(h).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-sm font-medium\"\n [class._shk-text-primary]=\"isClockHourSelected(h)\"\n [class._shk-text-surface-700]=\"!isClockHourSelected(h)\"\n >\n {{ h }}\n </text>\n }\n }\n\n <!-- Clock hand -->\n <line\n x1=\"100\" y1=\"100\"\n [attr.x2]=\"clockHandLine(60).x2\"\n [attr.y2]=\"clockHandLine(60).y2\"\n class=\"_shk-text-primary\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n\n <!-- Center dot -->\n <circle cx=\"100\" cy=\"100\" r=\"4\" class=\"fill-current _shk-text-primary\" />\n </svg>\n </div>\n\n <!-- Mode toggle: Hours / Minutes -->\n <div class=\"clock-mode-toggle\">\n <button\n type=\"button\"\n (click)=\"clockMode.set('hours')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'hours'\"\n >\n {{ 'Horas' }}\n </button>\n <button\n type=\"button\"\n (click)=\"clockMode.set('minutes')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'minutes'\"\n >\n {{ 'Minutos' }}\n </button>\n </div>\n\n <!-- AM/PM toggle for 12h format -->\n @if (hourFormat() === '12') {\n <div class=\"flex items-center justify-center gap-2 mt-2\">\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('AM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'AM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'AM'\n }\"\n >\n AM\n </button>\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('PM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'PM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'PM'\n }\"\n >\n PM\n </button>\n </div>\n }\n\n <!-- Seconds selector (if enabled) -->\n @if (showSeconds()) {\n <div class=\"flex items-center justify-center gap-1 mt-2\">\n <span class=\"text-xs _shk-text-surface-400\">Seg:</span>\n <select\n class=\"px-2 py-1 text-xs _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-md\"\n [value]=\"viewSecond()\"\n (change)=\"onSecondChange($event)\"\n aria-label=\"Segundos\"\n >\n @for (seconds of secondsRange(); track seconds) {\n <option [value]=\"seconds\">{{ minutesLabel(seconds) }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Confirm button -->\n <button\n type=\"button\"\n (click)=\"confirmTime()\"\n class=\"mt-3 w-full py-2 text-sm _shk-bg-primary _shk-text-white rounded-lg hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n {{ timeOnly() ? 'Confirmar' : 'Introducir hora' }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n @if (shouldShowError()) {\n <div [id]=\"id() + '-error'\" class=\"mt-1 text-xs text-red-500 max-h-20 overflow-y-auto _shk-scrollbar\">\n <ul class=\"list-disc pl-4 space-y-1\">\n @for (error of getErrorMessages(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </div>\n }\n</div>\n", styles: [".clock-container{position:relative;width:200px;height:200px;margin:0 auto}.clock-face{width:100%;height:100%;border-radius:50%;border:2px solid var(--shk-surface-200);position:relative;background-color:var(--shk-surface-50)}.dark .clock-face{border-color:var(--shk-surface-200);background-color:var(--shk-surface-100)}.clock-number{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:background-color .15s,color .15s;-webkit-user-select:none;user-select:none;color:var(--shk-surface-700)}.dark .clock-number{color:var(--shk-surface-700)}.clock-number:hover{background-color:var(--shk-surface-100)}.dark .clock-number:hover{background-color:var(--shk-surface-200)}.clock-number.selected{background-color:var(--shk-primary-500);color:#fff}.clock-number.current{font-weight:700}.clock-hand{position:absolute;bottom:50%;left:50%;width:2px;background-color:var(--shk-primary-500);transform-origin:bottom center;border-radius:1px;pointer-events:none;transition:transform .2s ease-out}.clock-center{position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;background-color:var(--shk-primary-500);transform:translate(-50%,-50%);pointer-events:none;z-index:2}.clock-minute-marker{position:absolute;width:1px;height:8px;background-color:var(--shk-surface-300);top:6px;left:50%;transform-origin:center 94px}.dark .clock-minute-marker{background-color:var(--shk-surface-400)}.clock-minute-marker.major{width:2px;height:12px;background-color:var(--shk-surface-400)}.dark .clock-minute-marker.major{background-color:var(--shk-surface-500)}.clock-mode-toggle{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.75rem}.clock-mode-btn{padding:.25rem .75rem;font-size:.75rem;font-weight:500;border-radius:9999px;cursor:pointer;transition:background-color .15s,color .15s;border:none;background:transparent;color:var(--shk-surface-500)}.dark .clock-mode-btn{color:var(--shk-surface-400)}.clock-mode-btn.active{background-color:var(--shk-primary-500);color:#fff}.clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-100)}.dark .clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-200)}.date-input-field{width:100%;padding:.5rem 2.5rem .5rem .75rem;font-size:.875rem;border-radius:.5rem;outline:none;transition:border-color .15s,box-shadow .15s;background-color:var(--shk-surface-50);color:var(--shk-surface-700);border:1px solid var(--shk-surface-200)}.dark .date-input-field{background-color:var(--shk-surface-100);color:var(--shk-surface-700);border-color:var(--shk-surface-200)}.date-input-field::placeholder{color:var(--shk-surface-400)}.dark .date-input-field::placeholder{color:var(--shk-surface-400)}.date-input-field:focus{border-color:var(--shk-primary-500);box-shadow:0 0 0 1px var(--shk-primary-500)}.date-input-field:disabled{opacity:.5;cursor:not-allowed}.date-input-field.input-error{border-color:#ef4444}.date-input-field.input-error:focus{border-color:#ef4444;box-shadow:0 0 0 1px #ef4444}.date-input-field.input-valid{border-color:#22c55e}.date-input-field.input-valid:focus{border-color:#22c55e;box-shadow:0 0 0 1px #22c55e}\n"] }]
948
- }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], timeOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeOnly", required: false }] }], showTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTime", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], onDocumentClick: [{
1027
+ ], template: "<div class=\"relative mb-4\">\n @if (label()) {\n <div class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)] mb-1\">\n {{ label() }}\n </div>\n }\n\n <div class=\"relative\">\n <div class=\"relative\">\n <input\n [id]=\"id()\"\n type=\"text\"\n [disabled]=\"isDisabled()\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isTyping() ? typedValue() : displayLabel()\"\n (input)=\"onInputText($event)\"\n (focus)=\"onInputFocus()\"\n (blur)=\"onInputBlur()\"\n (keydown.enter)=\"$any($event.target).blur()\"\n (keydown.escape)=\"cancelTyping()\"\n (click)=\"toggle()\"\n class=\"date-input-field\"\n [ngClass]=\"{\n 'input-error': shouldShowError() || typingValid() === false,\n 'input-valid': wasFixedError() || typingValid() === true,\n }\"\n [attr.aria-invalid]=\"shouldShowError()\"\n [attr.aria-describedby]=\"shouldShowError() ? id() + '-error' : null\"\n />\n <button\n type=\"button\"\n [disabled]=\"isDisabled()\"\n (click)=\"toggle()\"\n class=\"absolute right-2 top-1/2 -translate-y-1/2 p-1 _shk-text-surface-400 dark:[color:var(--shk-surface-400)] hover:[color:var(--shk-surface-600)] dark:hover:[color:var(--shk-surface-300)] transition-colors\"\n >\n <svg\n class=\"w-4 h-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\"></rect>\n <path d=\"M16 2v4M8 2v4M3 10h18\"></path>\n </svg>\n </button>\n </div>\n\n @if (isOpen()) {\n <div class=\"fixed inset-0 z-40 bg-black/30\" (click)=\"close()\"></div>\n <div\n class=\"fixed z-50 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-72 p-4 bg-white dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-lg shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <!-- DATE VIEW -->\n @if (!timeOnly() && currentView() === 'date') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"drillUp()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ monthNames()[viewMonth()] }} {{ selectedYearValue() ?? viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"drillToInitial()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-7 gap-0 mb-1\">\n @for (name of dayNames(); track $index) {\n <div class=\"text-center text-xs font-medium _shk-text-surface-400 dark:[color:var(--shk-surface-400)] py-1\">\n {{ name }}\n </div>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-0\">\n @for (day of calendarDays(); track $index) {\n @if (day !== null) {\n <button\n type=\"button\"\n (click)=\"selectDay(day)\"\n class=\"py-1.5 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedDay(day),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isToday(day) && !isSelectedDay(day),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedDay(day) && !isToday(day),\n }\"\n >\n {{ day }}\n </button>\n } @else {\n <div></div>\n }\n }\n </div>\n }\n\n <!-- WEEK VIEW -->\n @if (!timeOnly() && currentView() === 'week') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ monthNames()[viewMonth()] }} {{ viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"space-y-1\">\n @for (week of monthWeeks(); track week.index) {\n <button\n type=\"button\"\n (click)=\"selectWeek(week.start)\"\n class=\"w-full flex items-center justify-between py-1.5 px-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': isSelectedWeek(week.start),\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentWeek(week.start) && !isSelectedWeek(week.start),\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': !isSelectedWeek(week.start) && !isCurrentWeek(week.start),\n }\"\n >\n <span class=\"font-medium\">{{ weekLabel(week.index) }}</span>\n <span class=\"text-xs opacity-80\">{{ week.range }}</span>\n </button>\n }\n </div>\n }\n\n <!-- MONTH VIEW -->\n @if (!timeOnly() && currentView() === 'month') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"drillUp()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ selectedYearValue() ?? viewYear() }}\n </span>\n <button\n type=\"button\"\n (click)=\"drillToInitial()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (name of monthNames(); track $index) {\n <button\n type=\"button\"\n (click)=\"selectMonth($index)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': selectedMonthValue() === $index,\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentMonth($index) && selectedMonthValue() !== $index,\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': selectedMonthValue() !== $index && !isCurrentMonth($index),\n }\"\n >\n {{ name }}\n </button>\n }\n </div>\n }\n\n <!-- YEAR VIEW -->\n @if (!timeOnly() && currentView() === 'year') {\n <div class=\"flex items-center justify-between mb-3\">\n <button\n type=\"button\"\n (click)=\"prev()\"\n [disabled]=\"!canGoPrev()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M15 18l-6-6 6-6\"></path>\n </svg>\n </button>\n <span class=\"text-sm font-medium _shk-text-surface-700 dark:[color:var(--shk-surface-600)]\">\n {{ viewDecade() }} - {{ viewDecade() + 11 }}\n </span>\n <button\n type=\"button\"\n (click)=\"next()\"\n [disabled]=\"!canGoNext()\"\n class=\"p-1 rounded hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)] disabled:opacity-30 disabled:cursor-not-allowed\"\n >\n <svg class=\"w-4 h-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M9 18l6-6-6-6\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"grid grid-cols-3 gap-1\">\n @for (year of decadeYears(); track year) {\n <button\n type=\"button\"\n (click)=\"selectYear(year)\"\n class=\"py-2 text-sm rounded transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white hover:[background-color:var(--shk-primary-700)]': selectedYearValue() === year,\n 'ring-1 [--tw-ring-color:var(--shk-primary-500)] _shk-text-surface-700 dark:[color:var(--shk-surface-700)]': isCurrentYear(year) && selectedYearValue() !== year,\n '_shk-text-surface-700 dark:[color:var(--shk-surface-700)] hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': selectedYearValue() !== year && !isCurrentYear(year),\n }\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n\n <!-- ANALOG CLOCK TIME PICKER -->\n @if (timeOnly() || showTime()) {\n <div class=\"mt-3 pt-3 _shk-border dark:[border-color:var(--shk-surface-200)]\">\n <!-- Clock display time -->\n <div class=\"text-center mb-2\">\n <span class=\"text-lg font-semibold _shk-text-surface-700 dark:[color:var(--shk-surface-700)]\">\n {{ clockDisplayTime() }}\n </span>\n </div>\n\n <!-- Analog clock face -->\n <div class=\"clock-container\">\n <svg\n viewBox=\"0 0 200 200\"\n class=\"w-full h-full cursor-pointer\"\n (click)=\"onClockClick($event, clockMode())\"\n >\n <!-- Clock face background -->\n <circle cx=\"100\" cy=\"100\" r=\"96\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1\"\n class=\"_shk-text-surface-200 dark:[color:var(--shk-surface-200)]\" />\n\n <!-- Minute markers -->\n @if (clockMode() === 'minutes') {\n @for (i of [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59]; track i) {\n <line\n [attr.x1]=\"clockMinuteMarker(i).x1\"\n [attr.y1]=\"clockMinuteMarker(i).y1\"\n [attr.x2]=\"clockMinuteMarker(i).x2\"\n [attr.y2]=\"clockMinuteMarker(i).y2\"\n [attr.stroke-width]=\"i % 5 === 0 ? 2 : 1\"\n [class]=\"i % 5 === 0 ? '_shk-text-surface-500 dark:[color:var(--shk-surface-500)]' : '_shk-text-surface-300 dark:[color:var(--shk-surface-400)]'\"\n stroke=\"currentColor\"\n />\n }\n <!-- Minute numbers (00, 05, 10, ...) -->\n @for (m of [0,5,10,15,20,25,30,35,40,45,50,55]; track m) {\n <text\n [attr.x]=\"clockMinutePos(m).x\"\n [attr.y]=\"clockMinutePos(m).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-[9px] _shk-text-surface-500 dark:[color:var(--shk-surface-400)]\"\n [class._shk-text-primary]=\"viewMinute() === m\"\n >\n {{ m.toString().padStart(2, '0') }}\n </text>\n }\n }\n\n <!-- Hour numbers -->\n @if (clockMode() === 'hours') {\n @for (h of clockHours(); track h) {\n <text\n [attr.x]=\"clockNumberPos(h).x\"\n [attr.y]=\"clockNumberPos(h).y\"\n text-anchor=\"middle\"\n dominant-baseline=\"central\"\n class=\"text-sm font-medium\"\n [class._shk-text-primary]=\"isClockHourSelected(h)\"\n [class._shk-text-surface-700]=\"!isClockHourSelected(h)\"\n >\n {{ h }}\n </text>\n }\n }\n\n <!-- Clock hand -->\n <line\n x1=\"100\" y1=\"100\"\n [attr.x2]=\"clockHandLine(60).x2\"\n [attr.y2]=\"clockHandLine(60).y2\"\n class=\"_shk-text-primary\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n />\n\n <!-- Center dot -->\n <circle cx=\"100\" cy=\"100\" r=\"4\" class=\"fill-current _shk-text-primary\" />\n </svg>\n </div>\n\n <!-- Mode toggle: Hours / Minutes -->\n <div class=\"clock-mode-toggle\">\n <button\n type=\"button\"\n (click)=\"clockMode.set('hours')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'hours'\"\n >\n {{ 'Horas' }}\n </button>\n <button\n type=\"button\"\n (click)=\"clockMode.set('minutes')\"\n class=\"clock-mode-btn\"\n [class.active]=\"clockMode() === 'minutes'\"\n >\n {{ 'Minutos' }}\n </button>\n </div>\n\n <!-- AM/PM toggle for 12h format -->\n @if (hourFormat() === '12') {\n <div class=\"flex items-center justify-center gap-2 mt-2\">\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('AM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'AM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'AM'\n }\"\n >\n AM\n </button>\n <button\n type=\"button\"\n (click)=\"viewMeridiem.set('PM')\"\n class=\"px-3 py-1 text-xs font-medium rounded-full transition-colors\"\n [ngClass]=\"{\n '_shk-bg-primary _shk-text-white': viewMeridiem() === 'PM',\n '_shk-text-surface-500 hover:[background-color:var(--shk-surface-100)] dark:hover:[background-color:var(--shk-surface-200)]': viewMeridiem() !== 'PM'\n }\"\n >\n PM\n </button>\n </div>\n }\n\n <!-- Seconds selector (if enabled) -->\n @if (showSeconds()) {\n <div class=\"flex items-center justify-center gap-1 mt-2\">\n <span class=\"text-xs _shk-text-surface-400\">Seg:</span>\n <select\n class=\"px-2 py-1 text-xs _shk-bg-surface-50 dark:[background-color:var(--shk-surface-100)] _shk-border dark:[border-color:var(--shk-surface-200)] rounded-md\"\n [value]=\"viewSecond()\"\n (change)=\"onSecondChange($event)\"\n aria-label=\"Segundos\"\n >\n @for (seconds of secondsRange(); track seconds) {\n <option [value]=\"seconds\">{{ minutesLabel(seconds) }}</option>\n }\n </select>\n </div>\n }\n\n <!-- Confirm button -->\n <button\n type=\"button\"\n (click)=\"confirmTime()\"\n class=\"mt-3 w-full py-2 text-sm _shk-bg-primary _shk-text-white rounded-lg hover:[background-color:var(--shk-primary-700)] transition-colors\"\n >\n {{ timeOnly() ? 'Confirmar' : 'Introducir hora' }}\n </button>\n </div>\n }\n </div>\n }\n </div>\n\n @if (shouldShowError()) {\n <div [id]=\"id() + '-error'\" class=\"mt-1 text-xs text-red-500 max-h-20 overflow-y-auto _shk-scrollbar\">\n <ul class=\"list-disc pl-4 space-y-1\">\n @for (error of getErrorMessages(); track error) {\n <li>{{ error }}</li>\n }\n </ul>\n </div>\n }\n</div>\n", styles: [".clock-container{position:relative;width:200px;height:200px;margin:0 auto}.clock-face{width:100%;height:100%;border-radius:50%;border:2px solid var(--shk-surface-200);position:relative;background-color:var(--shk-surface-50)}.dark .clock-face{border-color:var(--shk-surface-200);background-color:var(--shk-surface-100)}.clock-number{position:absolute;width:32px;height:32px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;border-radius:50%;transform:translate(-50%,-50%);cursor:pointer;transition:background-color .15s,color .15s;-webkit-user-select:none;user-select:none;color:var(--shk-surface-700)}.dark .clock-number{color:var(--shk-surface-700)}.clock-number:hover{background-color:var(--shk-surface-100)}.dark .clock-number:hover{background-color:var(--shk-surface-200)}.clock-number.selected{background-color:var(--shk-primary-500);color:#fff}.clock-number.current{font-weight:700}.clock-hand{position:absolute;bottom:50%;left:50%;width:2px;background-color:var(--shk-primary-500);transform-origin:bottom center;border-radius:1px;pointer-events:none;transition:transform .2s ease-out}.clock-center{position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;background-color:var(--shk-primary-500);transform:translate(-50%,-50%);pointer-events:none;z-index:2}.clock-minute-marker{position:absolute;width:1px;height:8px;background-color:var(--shk-surface-300);top:6px;left:50%;transform-origin:center 94px}.dark .clock-minute-marker{background-color:var(--shk-surface-400)}.clock-minute-marker.major{width:2px;height:12px;background-color:var(--shk-surface-400)}.dark .clock-minute-marker.major{background-color:var(--shk-surface-500)}.clock-mode-toggle{display:flex;align-items:center;justify-content:center;gap:.5rem;margin-top:.75rem}.clock-mode-btn{padding:.25rem .75rem;font-size:.75rem;font-weight:500;border-radius:9999px;cursor:pointer;transition:background-color .15s,color .15s;border:none;background:transparent;color:var(--shk-surface-500)}.dark .clock-mode-btn{color:var(--shk-surface-400)}.clock-mode-btn.active{background-color:var(--shk-primary-500);color:#fff}.clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-100)}.dark .clock-mode-btn:hover:not(.active){background-color:var(--shk-surface-200)}.date-input-field{width:100%;padding:.5rem 2.5rem .5rem .75rem;font-size:.875rem;border-radius:.5rem;outline:none;transition:border-color .15s,box-shadow .15s;background-color:var(--shk-surface-50);color:var(--shk-surface-700);border:1px solid var(--shk-surface-200)}.dark .date-input-field{background-color:var(--shk-surface-100);color:var(--shk-surface-700);border-color:var(--shk-surface-200)}.date-input-field::placeholder{color:var(--shk-surface-400)}.dark .date-input-field::placeholder{color:var(--shk-surface-400)}.date-input-field:focus{border-color:var(--shk-primary-500);box-shadow:0 0 0 1px var(--shk-primary-500)}.date-input-field:disabled{opacity:.5;cursor:not-allowed}.date-input-field.input-error{border-color:#ef4444}.date-input-field.input-error:focus{border-color:#ef4444;box-shadow:0 0 0 1px #ef4444}.date-input-field.input-valid{border-color:#22c55e}.date-input-field.input-valid:focus{border-color:#22c55e;box-shadow:0 0 0 1px #22c55e}\n"] }]
1028
+ }], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }], weekStart: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekStart", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], errorMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessages", required: false }] }], minValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "minValue", required: false }] }], maxValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxValue", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], timeOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeOnly", required: false }] }], showTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTime", required: false }] }], hourFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourFormat", required: false }] }], showSeconds: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSeconds", required: false }] }], minuteStep: [{ type: i0.Input, args: [{ isSignal: true, alias: "minuteStep", required: false }] }], onDocumentClick: [{
949
1029
  type: HostListener,
950
1030
  args: ['document:click', ['$event']]
951
1031
  }], onEscape: [{