@solcre-org/core-ui 2.17.0 → 2.17.1

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.
@@ -578,6 +578,95 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
578
578
  args: [{ selector: 'core-checkbox-field', standalone: true, imports: [CommonModule, FormsModule, ReactiveFormsModule, TranslateModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<!-- Clase para layout inline cuando hay m\u00FAltiples opciones -->\n<div class=\"c-entry-toggle-holder\" [class.hasSeparatedOptions]=\"hasSeparatedOptions()\" [class.multiple-inline]=\"hasMultipleOptions()\">\n\n <span class=\"c-entry-text\"\n *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredIndicator()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n \n @if (hasMultipleOptions()) {\n @for (option of options(); track option.value) {\n\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"cannotDeselect(option)\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (!allowMultiple() && isRequired()) {\n <!-- Cuando allowMultiple: false y required: true, usar radio buttons para todas las opciones -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else if (cannotDeselect(option)) {\n <!-- Usar radio cuando no se puede deseleccionar (modo m\u00FAltiple con una sola opci\u00F3n) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString() + '_' + option.value\"\n [attr.name]=\"allowMultiple() ? field().key.toString() + '[]' : field().key.toString()\"\n [checked]=\"isOptionSelected(option)\"\n (change)=\"handleOptionChange(option, $event)\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n\n <span class=\"c-entry-toggle__text\">\n {{ option.label | translate }}\n @if(option.externalLink) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"option.externalLink\" target=\"_blank\"></a>\n }\n </span>\n @if(option.detail) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ option.detail }}</span>\n }\n </label>\n\n }\n } @else {\n <!-- ! Solcre: Este .c-entry-toggle deber\u00EDa ser un componente en s\u00ED mismo. -->\n <!-- ! Solcre: El cannot-deselect no est\u00E1 over-engineered. Deber\u00EDa ser un Radio. -->\n <label class=\"c-entry-toggle\"\n [class.is-invalid]=\"hasError()\"\n [class.is-disabled]=\"isDisabled()\"\n [class.cannot-deselect]=\"isRequired() && !!formControl().value\">\n\n <!-- onBlurInput() maneja validaciones y marca el campo como touched para mostrar errores -->\n @if (isRequired() && !!formControl().value) {\n <!-- Usar radio cuando es requerido y tiene valor (cannot-deselect) -->\n <input\n type=\"radio\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [checked]=\"!!formControl().value\"\n (change)=\"onRadioChange($event)\"\n (blur)=\"onBlurInput()\"\n />\n } @else {\n <!-- Usar checkbox normal cuando se puede deseleccionar -->\n <input\n type=\"checkbox\"\n [attr.id]=\"field().key.toString()\"\n [attr.name]=\"field().key.toString()\"\n [formControl]=\"formControl()\"\n (blur)=\"onBlurInput()\"\n />\n }\n <span class=\"c-entry-toggle__toggle\"></span>\n <span class=\"c-entry-toggle__text\">\n {{ field().label | translate }}\n @if (hasRequiredIndicator()) {\n <span class=\"c-required\">*</span>\n }\n @if(externalLink()) {\n <!-- Link externo funcional implementado -->\n <a class=\"icon-external-link-thin\" [href]=\"externalLink()\" target=\"_blank\"></a>\n }\n </span>\n @if(detail()) {\n <!-- Texto de detalle funcional implementado -->\n <span class=\"c-form-checkbox__detail\">{{ detail() }}</span>\n }\n </label>\n }\n\n <core-field-errors [errors]=\"errors()\" />\n</div> \n ", styles: [".cannot-deselect{pointer-events:none;cursor:not-allowed}.c-entry-text+.c-entry-toggle-holder.hasSeparatedOptions{margin-top:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--_entry-group-gap) * .8)}.c-entry-toggle-holder.hasSeparatedOptions .c-entry-text{grid-column:span 2;margin-top:1em}\n"] }]
579
579
  }], ctorParameters: () => [] });
580
580
 
581
+ const DEFAULT_COLORS = [
582
+ '#4285f4', '#ea4335', '#34a853', '#fbbc04',
583
+ '#9c27b0', '#00bcd4', '#ff5722', '#795548',
584
+ '#607d8b', '#e91e63', '#3f51b5', '#009688',
585
+ '#ff9800', '#673ab7', '#2196f3', '#4caf50'
586
+ ];
587
+ class ColorPickerFieldComponent extends BaseFieldComponent {
588
+ isPickerOpen = signal(false);
589
+ presetColors = signal(DEFAULT_COLORS);
590
+ constructor() {
591
+ super();
592
+ effect(() => {
593
+ const shouldDisable = this.mode() === ModalMode.VIEW || this.evaluateReadonly();
594
+ const control = this.formControl();
595
+ if (shouldDisable && control.enabled) {
596
+ control.disable();
597
+ }
598
+ else if (!shouldDisable && control.disabled) {
599
+ control.enable();
600
+ }
601
+ });
602
+ effect(() => {
603
+ const fieldConfig = this.field();
604
+ if (fieldConfig.presetColors && Array.isArray(fieldConfig.presetColors)) {
605
+ this.presetColors.set(fieldConfig.presetColors);
606
+ }
607
+ });
608
+ }
609
+ isDisabled() {
610
+ return this.mode() === ModalMode.VIEW || this.evaluateReadonly();
611
+ }
612
+ togglePicker() {
613
+ if (!this.isDisabled()) {
614
+ this.isPickerOpen.update(open => !open);
615
+ }
616
+ }
617
+ closePicker() {
618
+ this.isPickerOpen.set(false);
619
+ }
620
+ selectColor(color) {
621
+ if (!this.isDisabled()) {
622
+ this.formControl().setValue(color);
623
+ this.valueChange.emit(color);
624
+ this.closePicker();
625
+ }
626
+ }
627
+ onColorInputChange(event) {
628
+ const input = event.target;
629
+ const color = input.value;
630
+ this.formControl().setValue(color);
631
+ this.valueChange.emit(color);
632
+ }
633
+ onTextInputChange(event) {
634
+ const input = event.target;
635
+ let color = input.value;
636
+ if (color && !color.startsWith('#')) {
637
+ color = '#' + color;
638
+ }
639
+ if (this.isValidHexColor(color)) {
640
+ this.formControl().setValue(color);
641
+ this.valueChange.emit(color);
642
+ }
643
+ }
644
+ isValidHexColor(color) {
645
+ return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
646
+ }
647
+ getCurrentColor() {
648
+ const value = this.formControl().value;
649
+ return value && this.isValidHexColor(value) ? value : '#4783E1';
650
+ }
651
+ onBlurInput(event) {
652
+ setTimeout(() => {
653
+ if (!this.isPickerOpen()) {
654
+ this.onBlur(event);
655
+ }
656
+ }, 200);
657
+ }
658
+ handleEnterKey(event) {
659
+ const keyboardEvent = event;
660
+ this.onEnterInput(keyboardEvent);
661
+ }
662
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ColorPickerFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
663
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: ColorPickerFieldComponent, isStandalone: true, selector: "core-color-picker-field", usesInheritance: true, hostDirectives: [{ directive: CoreHostDirective }], ngImport: i0, template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n <span class=\"c-entry-text\" *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n\n <div class=\"c-entry-input c-entry-input--color\"\n [class.is-readonly]=\"isReadonly()\"\n [class.is-disabled]=\"isDisabled()\">\n <div class=\"c-color-picker\">\n <div class=\"c-color-picker__preview-wrapper\">\n <div \n class=\"c-color-picker__preview\"\n [style.background-color]=\"getCurrentColor()\"\n (click)=\"togglePicker()\"\n [class.c-color-picker__preview--disabled]=\"isDisabled()\">\n </div>\n \n <input\n type=\"text\"\n class=\"c-color-picker__text-input\"\n [id]=\"field().key\"\n [formControl]=\"formControl()\"\n [placeholder]=\"(field().placeholder ?? '#4783E1') | translate\"\n [class.c-color-picker__text-input--disabled]=\"isDisabled()\"\n [class.c-color-picker__text-input--error]=\"hasError()\"\n (input)=\"onTextInputChange($event)\"\n (blur)=\"onBlurInput($event)\"\n (keydown.enter)=\"handleEnterKey($event)\"\n maxlength=\"7\"\n />\n \n <input\n type=\"color\"\n class=\"c-color-picker__native-input\"\n [value]=\"getCurrentColor()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onColorInputChange($event)\"\n />\n </div>\n\n @if (isPickerOpen()) {\n <div class=\"c-color-picker__dropdown\">\n <div class=\"c-color-picker__preset-colors\">\n @for (color of presetColors(); track color) {\n <button\n type=\"button\"\n class=\"c-color-picker__preset-color\"\n [style.background-color]=\"color\"\n [class.c-color-picker__preset-color--selected]=\"getCurrentColor() === color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n</label>\n", styles: [".c-color-picker{position:relative;width:100%}.c-color-picker__preview-wrapper{display:flex;align-items:center;gap:8px}.c-color-picker__preview{width:36px;height:36px;border-radius:6px;border:2px solid var(--color-border, #e0e0e0);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease;flex-shrink:0}.c-color-picker__preview:hover:not(.c-color-picker__preview--disabled){border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__preview--disabled{cursor:not-allowed;opacity:.6}.c-color-picker__text-input{flex:1;height:36px;padding:0 12px;font-size:14px;font-family:monospace;text-transform:uppercase;border:1px solid var(--color-border, #e0e0e0);border-radius:6px;background-color:var(--color-background, #fff);transition:border-color .2s ease,box-shadow .2s ease}.c-color-picker__text-input:focus{outline:none;border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__text-input--disabled{background-color:var(--color-disabled-bg, #f5f5f5);cursor:not-allowed;opacity:.6}.c-color-picker__text-input--error{border-color:var(--color-danger, #dc3545)}.c-color-picker__text-input--error:focus{box-shadow:0 0 0 2px #dc354533}.c-color-picker__native-input{width:36px;height:36px;padding:0;border:none;border-radius:6px;cursor:pointer;flex-shrink:0}.c-color-picker__native-input::-webkit-color-swatch-wrapper{padding:0}.c-color-picker__native-input::-webkit-color-swatch{border:2px solid var(--color-border, #e0e0e0);border-radius:6px}.c-color-picker__native-input:disabled{cursor:not-allowed;opacity:.6}.c-color-picker__dropdown{position:absolute;top:calc(100% + 8px);left:0;z-index:1000;background-color:var(--color-background, #fff);border:1px solid var(--color-border, #e0e0e0);border-radius:8px;box-shadow:0 4px 12px #00000026;padding:12px;min-width:200px}.c-color-picker__preset-colors{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.c-color-picker__preset-color{width:32px;height:32px;border:2px solid transparent;border-radius:6px;cursor:pointer;padding:0;transition:transform .15s ease,border-color .15s ease}.c-color-picker__preset-color:hover{transform:scale(1.1)}.c-color-picker__preset-color--selected{border-color:var(--color-text, #333);box-shadow:0 0 0 2px var(--color-background, #fff),0 0 0 4px var(--color-primary, #4783E1)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: FieldErrorsComponent, selector: "core-field-errors", inputs: ["errors"] }] });
664
+ }
665
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: ColorPickerFieldComponent, decorators: [{
666
+ type: Component,
667
+ args: [{ selector: 'core-color-picker-field', standalone: true, imports: [CommonModule, FormsModule, TranslateModule, ReactiveFormsModule, FieldErrorsComponent], hostDirectives: [CoreHostDirective], template: "<label class=\"c-entry-item\" [class.c-entry-item--inline]=\"field().inline\">\n <span class=\"c-entry-text\" *ngIf=\"field().label\">\n {{ field().label | translate }}\n @if (hasRequiredValidators()) {\n <span class=\"c-required\">*</span>\n }\n </span>\n\n <div class=\"c-entry-input c-entry-input--color\"\n [class.is-readonly]=\"isReadonly()\"\n [class.is-disabled]=\"isDisabled()\">\n <div class=\"c-color-picker\">\n <div class=\"c-color-picker__preview-wrapper\">\n <div \n class=\"c-color-picker__preview\"\n [style.background-color]=\"getCurrentColor()\"\n (click)=\"togglePicker()\"\n [class.c-color-picker__preview--disabled]=\"isDisabled()\">\n </div>\n \n <input\n type=\"text\"\n class=\"c-color-picker__text-input\"\n [id]=\"field().key\"\n [formControl]=\"formControl()\"\n [placeholder]=\"(field().placeholder ?? '#4783E1') | translate\"\n [class.c-color-picker__text-input--disabled]=\"isDisabled()\"\n [class.c-color-picker__text-input--error]=\"hasError()\"\n (input)=\"onTextInputChange($event)\"\n (blur)=\"onBlurInput($event)\"\n (keydown.enter)=\"handleEnterKey($event)\"\n maxlength=\"7\"\n />\n \n <input\n type=\"color\"\n class=\"c-color-picker__native-input\"\n [value]=\"getCurrentColor()\"\n [disabled]=\"isDisabled()\"\n (input)=\"onColorInputChange($event)\"\n />\n </div>\n\n @if (isPickerOpen()) {\n <div class=\"c-color-picker__dropdown\">\n <div class=\"c-color-picker__preset-colors\">\n @for (color of presetColors(); track color) {\n <button\n type=\"button\"\n class=\"c-color-picker__preset-color\"\n [style.background-color]=\"color\"\n [class.c-color-picker__preset-color--selected]=\"getCurrentColor() === color\"\n (click)=\"selectColor(color)\"\n [title]=\"color\">\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <core-field-errors [errors]=\"errors()\"></core-field-errors>\n</label>\n", styles: [".c-color-picker{position:relative;width:100%}.c-color-picker__preview-wrapper{display:flex;align-items:center;gap:8px}.c-color-picker__preview{width:36px;height:36px;border-radius:6px;border:2px solid var(--color-border, #e0e0e0);cursor:pointer;transition:border-color .2s ease,box-shadow .2s ease;flex-shrink:0}.c-color-picker__preview:hover:not(.c-color-picker__preview--disabled){border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__preview--disabled{cursor:not-allowed;opacity:.6}.c-color-picker__text-input{flex:1;height:36px;padding:0 12px;font-size:14px;font-family:monospace;text-transform:uppercase;border:1px solid var(--color-border, #e0e0e0);border-radius:6px;background-color:var(--color-background, #fff);transition:border-color .2s ease,box-shadow .2s ease}.c-color-picker__text-input:focus{outline:none;border-color:var(--color-primary, #4783E1);box-shadow:0 0 0 2px #4783e133}.c-color-picker__text-input--disabled{background-color:var(--color-disabled-bg, #f5f5f5);cursor:not-allowed;opacity:.6}.c-color-picker__text-input--error{border-color:var(--color-danger, #dc3545)}.c-color-picker__text-input--error:focus{box-shadow:0 0 0 2px #dc354533}.c-color-picker__native-input{width:36px;height:36px;padding:0;border:none;border-radius:6px;cursor:pointer;flex-shrink:0}.c-color-picker__native-input::-webkit-color-swatch-wrapper{padding:0}.c-color-picker__native-input::-webkit-color-swatch{border:2px solid var(--color-border, #e0e0e0);border-radius:6px}.c-color-picker__native-input:disabled{cursor:not-allowed;opacity:.6}.c-color-picker__dropdown{position:absolute;top:calc(100% + 8px);left:0;z-index:1000;background-color:var(--color-background, #fff);border:1px solid var(--color-border, #e0e0e0);border-radius:8px;box-shadow:0 4px 12px #00000026;padding:12px;min-width:200px}.c-color-picker__preset-colors{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}.c-color-picker__preset-color{width:32px;height:32px;border:2px solid transparent;border-radius:6px;cursor:pointer;padding:0;transition:transform .15s ease,border-color .15s ease}.c-color-picker__preset-color:hover{transform:scale(1.1)}.c-color-picker__preset-color--selected{border-color:var(--color-text, #333);box-shadow:0 0 0 2px var(--color-background, #fff),0 0 0 4px var(--color-primary, #4783E1)}\n"] }]
668
+ }], ctorParameters: () => [] });
669
+
581
670
  class DateFieldComponent extends BaseFieldComponent {
582
671
  elementRef;
583
672
  isPickerOpen = false;
@@ -2409,6 +2498,7 @@ var FieldType;
2409
2498
  FieldType["FILE"] = "file";
2410
2499
  FieldType["PHONE"] = "phone";
2411
2500
  FieldType["DOCUMENT"] = "document";
2501
+ FieldType["COLOR"] = "color";
2412
2502
  })(FieldType || (FieldType = {}));
2413
2503
  var NumberFieldType;
2414
2504
  (function (NumberFieldType) {
@@ -4969,6 +5059,7 @@ class DynamicFieldDirective {
4969
5059
  document: DocumentFieldComponent,
4970
5060
  file: FileFieldComponent,
4971
5061
  phone: PhoneFieldComponent,
5062
+ color: ColorPickerFieldComponent,
4972
5063
  };
4973
5064
  ngOnChanges(changes) {
4974
5065
  if (changes['field']?.firstChange || this.shouldReloadComponent(changes)) {
@@ -16556,12 +16647,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
16556
16647
  // Este archivo es generado automáticamente por scripts/update-version.js
16557
16648
  // No edites manualmente este archivo
16558
16649
  const VERSION = {
16559
- full: '2.17.0',
16650
+ full: '2.17.1',
16560
16651
  major: 2,
16561
16652
  minor: 17,
16562
- patch: 0,
16563
- timestamp: '2025-12-11T18:35:18.659Z',
16564
- buildDate: '11/12/2025'
16653
+ patch: 1,
16654
+ timestamp: '2025-12-16T13:58:16.774Z',
16655
+ buildDate: '16/12/2025'
16565
16656
  };
16566
16657
 
16567
16658
  class MainNavComponent {
@@ -21156,7 +21247,8 @@ const DEFAULT_SCHEDULER_CONFIG = {
21156
21247
  slotDuration: 30,
21157
21248
  rowHeightRem: 4,
21158
21249
  showCurrentTimeLine: true,
21159
- locale: 'es-ES'
21250
+ locale: 'es-ES',
21251
+ viewMode: 'day'
21160
21252
  };
21161
21253
 
21162
21254
  class GenericSchedulerComponent {
@@ -21171,6 +21263,10 @@ class GenericSchedulerComponent {
21171
21263
  disabledSlotLabel = input('No disponible');
21172
21264
  todayLabel = input('Hoy');
21173
21265
  locale = input('es-ES');
21266
+ weekLabel = input('Semana');
21267
+ dayLabel = input('Día');
21268
+ monthLabel = input('Mes');
21269
+ disabledDates = input([]);
21174
21270
  slotClick = output();
21175
21271
  eventClick = output();
21176
21272
  eventHover = output();
@@ -21178,10 +21274,70 @@ class GenericSchedulerComponent {
21178
21274
  todayClick = output();
21179
21275
  previousDay = output();
21180
21276
  nextDay = output();
21277
+ previousWeek = output();
21278
+ nextWeek = output();
21279
+ previousMonth = output();
21280
+ nextMonth = output();
21281
+ viewModeChange = output();
21181
21282
  timeSlots = signal([]);
21182
21283
  currentTime = signal(new Date());
21284
+ expandedDay = signal(null);
21183
21285
  timeUpdateInterval = null;
21184
21286
  mergedConfig = computed(() => ({ ...DEFAULT_SCHEDULER_CONFIG, ...this.config() }));
21287
+ viewMode = computed(() => this.mergedConfig().viewMode || 'day');
21288
+ weekDays = computed(() => {
21289
+ if (this.viewMode() !== 'week')
21290
+ return [];
21291
+ const selected = this.selectedDate();
21292
+ const localeValue = this.locale();
21293
+ const today = new Date();
21294
+ const dayOfWeek = selected.getUTCDay();
21295
+ const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
21296
+ const monday = new Date(Date.UTC(selected.getUTCFullYear(), selected.getUTCMonth(), selected.getUTCDate() + mondayOffset));
21297
+ const days = [];
21298
+ for (let i = 0; i < 7; i++) {
21299
+ const date = new Date(Date.UTC(monday.getUTCFullYear(), monday.getUTCMonth(), monday.getUTCDate() + i));
21300
+ const isToday = date.getUTCFullYear() === today.getUTCFullYear() &&
21301
+ date.getUTCMonth() === today.getUTCMonth() &&
21302
+ date.getUTCDate() === today.getUTCDate();
21303
+ days.push({
21304
+ date,
21305
+ dayNumber: date.getUTCDate(),
21306
+ dayName: date.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }),
21307
+ isToday,
21308
+ isWeekend: i >= 5
21309
+ });
21310
+ }
21311
+ return days;
21312
+ });
21313
+ monthDays = computed(() => {
21314
+ if (this.viewMode() !== 'month')
21315
+ return [];
21316
+ const selected = this.selectedDate();
21317
+ const localeValue = this.locale();
21318
+ const today = new Date();
21319
+ const year = selected.getUTCFullYear();
21320
+ const month = selected.getUTCMonth();
21321
+ const firstDayOfMonth = new Date(Date.UTC(year, month, 1));
21322
+ const dayOfWeek = firstDayOfMonth.getUTCDay();
21323
+ const mondayOffset = dayOfWeek === 0 ? -6 : 1 - dayOfWeek;
21324
+ const startDate = new Date(Date.UTC(year, month, 1 + mondayOffset));
21325
+ const days = [];
21326
+ for (let i = 0; i < 42; i++) {
21327
+ const date = new Date(Date.UTC(startDate.getUTCFullYear(), startDate.getUTCMonth(), startDate.getUTCDate() + i));
21328
+ const isToday = date.getUTCFullYear() === today.getUTCFullYear() &&
21329
+ date.getUTCMonth() === today.getUTCMonth() &&
21330
+ date.getUTCDate() === today.getUTCDate();
21331
+ days.push({
21332
+ date,
21333
+ dayNumber: date.getUTCDate(),
21334
+ dayName: date.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }),
21335
+ isToday,
21336
+ isWeekend: [0, 6].includes(date.getUTCDay())
21337
+ });
21338
+ }
21339
+ return days;
21340
+ });
21185
21341
  isToday = computed(() => {
21186
21342
  const selected = this.selectedDate();
21187
21343
  const today = new Date();
@@ -21192,6 +21348,32 @@ class GenericSchedulerComponent {
21192
21348
  formattedDate = computed(() => {
21193
21349
  const date = this.selectedDate();
21194
21350
  const localeValue = this.locale();
21351
+ if (this.viewMode() === 'week') {
21352
+ const days = this.weekDays();
21353
+ if (days.length > 0) {
21354
+ const firstDay = days[0].date;
21355
+ const lastDay = days[6].date;
21356
+ const firstFormatted = firstDay.toLocaleDateString(localeValue, {
21357
+ day: 'numeric',
21358
+ month: 'short',
21359
+ timeZone: 'UTC'
21360
+ });
21361
+ const lastFormatted = lastDay.toLocaleDateString(localeValue, {
21362
+ day: 'numeric',
21363
+ month: 'short',
21364
+ year: 'numeric',
21365
+ timeZone: 'UTC'
21366
+ });
21367
+ return `${firstFormatted} - ${lastFormatted}`;
21368
+ }
21369
+ }
21370
+ if (this.viewMode() === 'month') {
21371
+ return date.toLocaleDateString(localeValue, {
21372
+ month: 'long',
21373
+ year: 'numeric',
21374
+ timeZone: 'UTC'
21375
+ });
21376
+ }
21195
21377
  return date.toLocaleDateString(localeValue, {
21196
21378
  weekday: 'long',
21197
21379
  year: 'numeric',
@@ -21201,8 +21383,17 @@ class GenericSchedulerComponent {
21201
21383
  });
21202
21384
  });
21203
21385
  currentTimePosition = computed(() => {
21204
- if (!this.isToday() || !this.mergedConfig().showCurrentTimeLine)
21386
+ if (!this.mergedConfig().showCurrentTimeLine)
21387
+ return null;
21388
+ if (this.viewMode() === 'week') {
21389
+ const days = this.weekDays();
21390
+ const todayIndex = days.findIndex(d => d.isToday);
21391
+ if (todayIndex === -1)
21392
+ return null;
21393
+ }
21394
+ else if (!this.isToday()) {
21205
21395
  return null;
21396
+ }
21206
21397
  const now = this.currentTime();
21207
21398
  const hours = now.getUTCHours();
21208
21399
  const minutes = now.getUTCMinutes();
@@ -21215,6 +21406,12 @@ class GenericSchedulerComponent {
21215
21406
  const positionInRem = slotsFromStart * cfg.rowHeightRem;
21216
21407
  return positionInRem;
21217
21408
  });
21409
+ currentTimeDayIndex = computed(() => {
21410
+ if (this.viewMode() !== 'week')
21411
+ return -1;
21412
+ const days = this.weekDays();
21413
+ return days.findIndex(d => d.isToday);
21414
+ });
21218
21415
  eventMap = computed(() => {
21219
21416
  const map = new Map();
21220
21417
  const evts = this.events();
@@ -21295,6 +21492,10 @@ class GenericSchedulerComponent {
21295
21492
  isSlotDisabled(columnId, slot) {
21296
21493
  const now = new Date();
21297
21494
  const selected = this.selectedDate();
21495
+ const dateStr = selected.toISOString().split('T')[0];
21496
+ if (this.disabledDates().includes(dateStr)) {
21497
+ return true;
21498
+ }
21298
21499
  const todayUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
21299
21500
  const selectedUTC = Date.UTC(selected.getUTCFullYear(), selected.getUTCMonth(), selected.getUTCDate());
21300
21501
  if (selectedUTC < todayUTC) {
@@ -21350,15 +21551,170 @@ class GenericSchedulerComponent {
21350
21551
  const nextDayDate = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() + 1));
21351
21552
  this.nextDay.emit(nextDayDate);
21352
21553
  }
21554
+ onPreviousWeek() {
21555
+ const current = this.selectedDate();
21556
+ const prevWeek = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() - 7));
21557
+ this.previousWeek.emit(prevWeek);
21558
+ }
21559
+ onNextWeek() {
21560
+ const current = this.selectedDate();
21561
+ const nextWeekDate = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth(), current.getUTCDate() + 7));
21562
+ this.nextWeek.emit(nextWeekDate);
21563
+ }
21564
+ onPreviousMonth() {
21565
+ const current = this.selectedDate();
21566
+ const prevMonth = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth() - 1, 1));
21567
+ this.previousMonth.emit(prevMonth);
21568
+ }
21569
+ onNextMonth() {
21570
+ const current = this.selectedDate();
21571
+ const nextMonth = new Date(Date.UTC(current.getUTCFullYear(), current.getUTCMonth() + 1, 1));
21572
+ this.nextMonth.emit(nextMonth);
21573
+ }
21574
+ onPrevious() {
21575
+ if (this.viewMode() === 'week') {
21576
+ this.onPreviousWeek();
21577
+ }
21578
+ else if (this.viewMode() === 'month') {
21579
+ this.onPreviousMonth();
21580
+ }
21581
+ else {
21582
+ this.onPreviousDay();
21583
+ }
21584
+ }
21585
+ onNext() {
21586
+ if (this.viewMode() === 'week') {
21587
+ this.onNextWeek();
21588
+ }
21589
+ else if (this.viewMode() === 'month') {
21590
+ this.onNextMonth();
21591
+ }
21592
+ else {
21593
+ this.onNextDay();
21594
+ }
21595
+ }
21596
+ toggleViewMode() {
21597
+ const newMode = this.viewMode() === 'day' ? 'week' : 'day';
21598
+ this.viewModeChange.emit(newMode);
21599
+ }
21600
+ setViewMode(mode) {
21601
+ this.viewModeChange.emit(mode);
21602
+ }
21603
+ getEventsForDay(dayDate) {
21604
+ const evts = this.events();
21605
+ return evts.filter(event => {
21606
+ if (!event.date)
21607
+ return false;
21608
+ const eventDate = new Date(event.date);
21609
+ return eventDate.getUTCFullYear() === dayDate.getUTCFullYear() &&
21610
+ eventDate.getUTCMonth() === dayDate.getUTCMonth() &&
21611
+ eventDate.getUTCDate() === dayDate.getUTCDate();
21612
+ });
21613
+ }
21614
+ isSlotOccupiedForDay(dayDate, slot) {
21615
+ const evts = this.getEventsForDay(dayDate);
21616
+ return evts.some(event => this.isTimeInEvent(slot.time, event));
21617
+ }
21618
+ shouldShowEventForDay(dayDate, slot) {
21619
+ const evts = this.getEventsForDay(dayDate);
21620
+ return evts.some(event => event.startTime === slot.time);
21621
+ }
21622
+ getEventForDaySlot(dayDate, slot) {
21623
+ const evts = this.getEventsForDay(dayDate);
21624
+ return evts.find(event => event.startTime === slot.time);
21625
+ }
21626
+ isDayDisabled(dayDate) {
21627
+ const dateStr = dayDate.toISOString().split('T')[0];
21628
+ return this.disabledDates().includes(dateStr);
21629
+ }
21630
+ isSlotDisabledForDay(dayDate, slot) {
21631
+ if (this.isDayDisabled(dayDate)) {
21632
+ return true;
21633
+ }
21634
+ const now = new Date();
21635
+ const todayUTC = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
21636
+ const dayUTC = Date.UTC(dayDate.getUTCFullYear(), dayDate.getUTCMonth(), dayDate.getUTCDate());
21637
+ if (dayUTC < todayUTC) {
21638
+ return true;
21639
+ }
21640
+ if (dayUTC === todayUTC) {
21641
+ const [slotHour, slotMin] = slot.time.split(':').map(Number);
21642
+ const slotMinutes = slotHour * 60 + slotMin;
21643
+ const currentMinutes = now.getUTCHours() * 60 + now.getUTCMinutes();
21644
+ return slotMinutes < currentMinutes;
21645
+ }
21646
+ return false;
21647
+ }
21648
+ onWeekSlotClick(dayDate, slot) {
21649
+ if (this.isSlotOccupiedForDay(dayDate, slot) || this.isSlotDisabledForDay(dayDate, slot)) {
21650
+ return;
21651
+ }
21652
+ this.slotClick.emit({
21653
+ columnId: dayDate.toISOString(),
21654
+ slot,
21655
+ date: dayDate
21656
+ });
21657
+ }
21658
+ onWeekEventClick(event, dayDate) {
21659
+ const pseudoColumn = {
21660
+ id: dayDate.toISOString(),
21661
+ name: dayDate.toLocaleDateString(this.locale(), { weekday: 'long', timeZone: 'UTC' })
21662
+ };
21663
+ this.eventClick.emit({ event, column: pseudoColumn });
21664
+ }
21665
+ onMonthDayClick(dayDate) {
21666
+ const dummySlot = {
21667
+ time: '00:00',
21668
+ hour: 0,
21669
+ minutes: 0,
21670
+ isHalfHour: false,
21671
+ displayTime: false
21672
+ };
21673
+ this.slotClick.emit({
21674
+ columnId: dayDate.toISOString(),
21675
+ slot: dummySlot,
21676
+ date: dayDate
21677
+ });
21678
+ }
21679
+ onMonthEventClick(event, dayDate) {
21680
+ const pseudoColumn = {
21681
+ id: dayDate.toISOString(),
21682
+ name: dayDate.toLocaleDateString(this.locale(), { weekday: 'long', timeZone: 'UTC' })
21683
+ };
21684
+ this.eventClick.emit({ event, column: pseudoColumn });
21685
+ }
21686
+ openDayPopover(dayDate, event) {
21687
+ event.stopPropagation();
21688
+ this.expandedDay.set(dayDate);
21689
+ }
21690
+ closeDayPopover() {
21691
+ this.expandedDay.set(null);
21692
+ }
21693
+ getExpandedDayEvents() {
21694
+ const day = this.expandedDay();
21695
+ if (!day)
21696
+ return [];
21697
+ return this.getEventsForDay(day);
21698
+ }
21699
+ getExpandedDayLabel() {
21700
+ const day = this.expandedDay();
21701
+ if (!day)
21702
+ return '';
21703
+ const localeValue = this.locale();
21704
+ const weekday = day.toLocaleDateString(localeValue, { weekday: 'short', timeZone: 'UTC' }).toUpperCase();
21705
+ const dayNum = day.getUTCDate();
21706
+ return `${weekday}\n${dayNum}`;
21707
+ }
21353
21708
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSchedulerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
21354
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericSchedulerComponent, isStandalone: true, selector: "core-generic-scheduler", inputs: { selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showTimeColumn: { classPropertyName: "showTimeColumn", publicName: "showTimeColumn", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, timeColumnLabel: { classPropertyName: "timeColumnLabel", publicName: "timeColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, emptySlotLabel: { classPropertyName: "emptySlotLabel", publicName: "emptySlotLabel", isSignal: true, isRequired: false, transformFunction: null }, disabledSlotLabel: { classPropertyName: "disabledSlotLabel", publicName: "disabledSlotLabel", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventHover: "eventHover", eventLeave: "eventLeave", todayClick: "todayClick", previousDay: "previousDay", nextDay: "nextDay" }, host: { properties: { "style.--cols": "columns().length" }, classAttribute: "c-bookings-grid c-bookings-card" }, ngImport: i0, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"D\u00EDa anterior\"\n (click)=\"onPreviousDay()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"D\u00EDa siguiente\"\n (click)=\"onNextDay()\"\n ></button>\n </div>\n</div>\n}\n\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;overflow:visible}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
21709
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.6", type: GenericSchedulerComponent, isStandalone: true, selector: "core-generic-scheduler", inputs: { selectedDate: { classPropertyName: "selectedDate", publicName: "selectedDate", isSignal: true, isRequired: false, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, showTimeColumn: { classPropertyName: "showTimeColumn", publicName: "showTimeColumn", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, timeColumnLabel: { classPropertyName: "timeColumnLabel", publicName: "timeColumnLabel", isSignal: true, isRequired: false, transformFunction: null }, emptySlotLabel: { classPropertyName: "emptySlotLabel", publicName: "emptySlotLabel", isSignal: true, isRequired: false, transformFunction: null }, disabledSlotLabel: { classPropertyName: "disabledSlotLabel", publicName: "disabledSlotLabel", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, weekLabel: { classPropertyName: "weekLabel", publicName: "weekLabel", isSignal: true, isRequired: false, transformFunction: null }, dayLabel: { classPropertyName: "dayLabel", publicName: "dayLabel", isSignal: true, isRequired: false, transformFunction: null }, monthLabel: { classPropertyName: "monthLabel", publicName: "monthLabel", isSignal: true, isRequired: false, transformFunction: null }, disabledDates: { classPropertyName: "disabledDates", publicName: "disabledDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventHover: "eventHover", eventLeave: "eventLeave", todayClick: "todayClick", previousDay: "previousDay", nextDay: "nextDay", previousWeek: "previousWeek", nextWeek: "nextWeek", previousMonth: "previousMonth", nextMonth: "nextMonth", viewModeChange: "viewModeChange" }, host: { properties: { "class.c-bookings-grid--weekly": "viewMode() === \"week\"", "style.--cols": "columns().length" }, classAttribute: "c-bookings-grid c-bookings-card" }, ngImport: i0, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n [title]=\"viewMode() === 'week' ? 'Semana anterior' : 'D\u00EDa anterior'\"\n (click)=\"onPrevious()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n [title]=\"viewMode() === 'week' ? 'Semana siguiente' : 'D\u00EDa siguiente'\"\n (click)=\"onNext()\"\n ></button>\n </div>\n\n <div class=\"c-bookings-header__view-toggle\">\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'day'\"\n (click)=\"setViewMode('day')\"\n >\n {{ dayLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'week'\"\n (click)=\"setViewMode('week')\"\n >\n {{ weekLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'month'\"\n (click)=\"setViewMode('month')\"\n >\n {{ monthLabel() }}\n </button>\n </div>\n</div>\n} @if (viewMode() === 'day') {\n<!-- DAILY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'week') {\n<!-- WEEKLY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--weekly\"\n [style.--cols]=\"7\"\n style=\"position: relative\"\n>\n @if (currentTimePosition() !== null && currentTimeDayIndex() >= 0) {\n <div\n class=\"c-bookings-grid__current-time-line c-bookings-grid__current-time-line--weekly\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n [style.--day-index]=\"currentTimeDayIndex()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (day of weekDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__col\"\n [class.c-bookings-grid__col--weekend]=\"day.isWeekend\"\n >\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__day-header\" [class.is-today]=\"day.isToday\">\n <span class=\"c-bookings-grid__day-name\">{{ day.dayName }}</span>\n <span\n class=\"c-bookings-grid__day-number\"\n [class.is-today]=\"day.isToday\"\n >{{ day.dayNumber }}</span\n >\n </div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupiedForDay(day.date, slot)) { @if\n (isSlotDisabledForDay(day.date, slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n ></button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onWeekSlotClick(day.date, slot)\"\n ></button>\n } } @if (shouldShowEventForDay(day.date, slot)) { @let event =\n getEventForDaySlot(day.date, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onWeekEventClick(event, day.date)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'month') {\n<!-- MONTHLY VIEW -->\n<div class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--monthly\">\n <!-- Header Row -->\n <div class=\"c-bookings-grid__header-row\">\n @for (day of monthDays().slice(0, 7); track day.dayName) {\n <div class=\"c-bookings-grid__header-cell\">\n {{ day.dayName }}\n </div>\n }\n </div>\n\n <!-- Days Grid -->\n <div class=\"c-bookings-grid__month-grid\">\n @for (day of monthDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__month-cell\"\n [class.is-today]=\"day.isToday\"\n [class.is-weekend]=\"day.isWeekend\"\n [class.is-other-month]=\"\n day.date.getUTCMonth() !== selectedDate().getUTCMonth()\n \"\n [class.is-disabled]=\"isDayDisabled(day.date)\"\n (click)=\"!isDayDisabled(day.date) && onMonthDayClick(day.date)\"\n >\n <div class=\"c-bookings-grid__month-day-number\">\n {{ day.dayNumber }}\n </div>\n\n <div class=\"c-bookings-grid__month-events\">\n @let dayEvents = getEventsForDay(day.date); @for (event of\n dayEvents.slice(0, 3); track event.id) {\n <div\n class=\"c-bookings-grid__month-event\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"$event.stopPropagation(); onMonthEventClick(event, day.date)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n } @if (dayEvents.length > 3) {\n <div\n class=\"c-bookings-grid__more-events\"\n (click)=\"openDayPopover(day.date, $event)\"\n >\n {{ dayEvents.length - 3 }} m\u00E1s\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n @if (expandedDay()) {\n <div class=\"c-bookings-grid__popover-overlay\" (click)=\"closeDayPopover()\">\n <div class=\"c-bookings-grid__popover\" (click)=\"$event.stopPropagation()\">\n <div class=\"c-bookings-grid__popover-header\">\n <div class=\"c-bookings-grid__popover-date\">\n <span class=\"c-bookings-grid__popover-weekday\">{{\n expandedDay() | date : \"EEE\" : \"UTC\" : locale() | uppercase\n }}</span>\n <span class=\"c-bookings-grid__popover-daynum\">{{\n expandedDay() | date : \"d\" : \"UTC\"\n }}</span>\n </div>\n <button\n class=\"c-bookings-grid__popover-close\"\n (click)=\"closeDayPopover()\"\n >\n <span class=\"icon-cross\"></span>\n </button>\n </div>\n <div class=\"c-bookings-grid__popover-content\">\n @for (event of getExpandedDayEvents(); track event.id) {\n <div\n class=\"c-bookings-grid__month-event c-bookings-grid__month-event--popover\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"onMonthEventClick(event, expandedDay()!)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</div>\n}\n", styles: [":host{display:block;width:100%;overflow:visible}.c-bookings-grid__month-cell.is-disabled{background-color:#f3f4f6;cursor:not-allowed;opacity:.7}.c-bookings-grid__month-cell.is-disabled:hover{background-color:#f3f4f6}.c-bookings-grid__month-cell.is-disabled .c-bookings-grid__month-day-number{color:#9ca3af}.c-bookings-grid__slot--disabled{background-color:#f3f4f6;cursor:not-allowed}.c-bookings-grid__slot--disabled:hover{background-color:#f3f4f6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
21355
21710
  }
21356
21711
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImport: i0, type: GenericSchedulerComponent, decorators: [{
21357
21712
  type: Component,
21358
21713
  args: [{ selector: 'core-generic-scheduler', standalone: true, imports: [CommonModule], host: {
21359
21714
  'class': 'c-bookings-grid c-bookings-card',
21715
+ '[class.c-bookings-grid--weekly]': 'viewMode() === "week"',
21360
21716
  '[style.--cols]': 'columns().length'
21361
- }, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n title=\"D\u00EDa anterior\"\n (click)=\"onPreviousDay()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n title=\"D\u00EDa siguiente\"\n (click)=\"onNextDay()\"\n ></button>\n </div>\n</div>\n}\n\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;overflow:visible}\n"] }]
21717
+ }, template: "@if (showHeader()) {\n<div class=\"c-bookings-header\">\n <button class=\"c-bookings-header__today\" (click)=\"onTodayClick()\">\n {{ todayLabel() }}\n </button>\n\n <div class=\"c-bookings-header__date\">\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-left\"\n [title]=\"viewMode() === 'week' ? 'Semana anterior' : 'D\u00EDa anterior'\"\n (click)=\"onPrevious()\"\n ></button>\n <span>{{ formattedDate() }}</span>\n <button\n class=\"c-bookings-header__date-arrow icon-arrow-right\"\n [title]=\"viewMode() === 'week' ? 'Semana siguiente' : 'D\u00EDa siguiente'\"\n (click)=\"onNext()\"\n ></button>\n </div>\n\n <div class=\"c-bookings-header__view-toggle\">\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'day'\"\n (click)=\"setViewMode('day')\"\n >\n {{ dayLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'week'\"\n (click)=\"setViewMode('week')\"\n >\n {{ weekLabel() }}\n </button>\n <button\n class=\"c-bookings-header__view-btn\"\n [class.is-active]=\"viewMode() === 'month'\"\n (click)=\"setViewMode('month')\"\n >\n {{ monthLabel() }}\n </button>\n </div>\n</div>\n} @if (viewMode() === 'day') {\n<!-- DAILY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper\"\n [style.--cols]=\"columns().length\"\n style=\"position: relative\"\n>\n @if (isToday() && currentTimePosition() !== null) {\n <div\n class=\"c-bookings-grid__current-time-line\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (column of columns(); track column.id) {\n <div class=\"c-bookings-grid__col\">\n <div class=\"c-bookings-grid__top\">\n <p class=\"c-bookings-grid__title\">{{ column.name }}</p>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupied(column.id, slot)) { @if (isSlotDisabled(column.id,\n slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n >\n {{ disabledSlotLabel() }}\n </button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onSlotClick(column.id, slot)\"\n >\n {{ emptySlotLabel() }}\n </button>\n } } @if (shouldShowEvent(column.id, slot)) { @let event =\n getEventForSlot(column.id, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onEventClick(event, column)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n\n @if (event.canCancel) {\n <button\n class=\"c-bookings-grid__link c-link--underlined\"\n (click)=\"$event.stopPropagation()\"\n >\n <span class=\"icon-cross-thin\"></span>\n Cancelar\n </button>\n } @if ((event.canApprove || event.canReject) && event.duration >= 91) {\n <div class=\"c-bookings-grid__quick-actions\">\n @if (event.canApprove) {\n <button\n class=\"c-icon-btn--fill context:success icon-check\"\n title=\"Aprobar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n } @if (event.canReject) {\n <button\n class=\"c-icon-btn--fill context:error icon-cross\"\n title=\"Rechazar\"\n (click)=\"$event.stopPropagation()\"\n ></button>\n }\n </div>\n }\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'week') {\n<!-- WEEKLY VIEW -->\n<div\n class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--weekly\"\n [style.--cols]=\"7\"\n style=\"position: relative\"\n>\n @if (currentTimePosition() !== null && currentTimeDayIndex() >= 0) {\n <div\n class=\"c-bookings-grid__current-time-line c-bookings-grid__current-time-line--weekly\"\n [style.--time-position-rem]=\"currentTimePosition()\"\n [style.--day-index]=\"currentTimeDayIndex()\"\n ></div>\n } @if (showTimeColumn()) {\n <div class=\"c-bookings-grid__times\">\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__title\">{{ timeColumnLabel() }}</div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (slot.displayTime) {\n <span class=\"c-bookings-grid__time\">{{ slot.time }}</span>\n }\n </div>\n }\n </div>\n } @for (day of weekDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__col\"\n [class.c-bookings-grid__col--weekend]=\"day.isWeekend\"\n >\n <div class=\"c-bookings-grid__top c-bookings-grid__top--weekly\">\n <div class=\"c-bookings-grid__day-header\" [class.is-today]=\"day.isToday\">\n <span class=\"c-bookings-grid__day-name\">{{ day.dayName }}</span>\n <span\n class=\"c-bookings-grid__day-number\"\n [class.is-today]=\"day.isToday\"\n >{{ day.dayNumber }}</span\n >\n </div>\n </div>\n\n @for (slot of timeSlots(); track slot.time) {\n <div class=\"c-bookings-grid__row\">\n @if (!isSlotOccupiedForDay(day.date, slot)) { @if\n (isSlotDisabledForDay(day.date, slot)) {\n <button\n class=\"c-bookings-grid__slot c-bookings-grid__slot--disabled\"\n disabled\n [title]=\"disabledSlotLabel()\"\n ></button>\n } @else {\n <button\n class=\"c-bookings-grid__slot\"\n [title]=\"emptySlotLabel()\"\n (click)=\"onWeekSlotClick(day.date, slot)\"\n ></button>\n } } @if (shouldShowEventForDay(day.date, slot)) { @let event =\n getEventForDaySlot(day.date, slot); @if (event) {\n <div\n [class]=\"getEventClasses(event)\"\n [attr.data-type]=\"event.type\"\n [attr.data-status]=\"event.status\"\n [style.--rows]=\"getEventRowSpan(event)\"\n (mouseenter)=\"onEventHover($event, event)\"\n (mouseleave)=\"onEventLeave()\"\n (click)=\"onWeekEventClick(event, day.date)\"\n >\n <p class=\"c-bookings-grid__title\">\n {{ event.subtitle || event.title }}\n </p>\n <p class=\"c-bookings-grid__text\">\n {{ event.startTime }} - {{ event.endTime }}\n </p>\n </div>\n } }\n </div>\n }\n </div>\n }\n</div>\n} @else if (viewMode() === 'month') {\n<!-- MONTHLY VIEW -->\n<div class=\"c-bookings-grid__wrapper c-bookings-grid__wrapper--monthly\">\n <!-- Header Row -->\n <div class=\"c-bookings-grid__header-row\">\n @for (day of monthDays().slice(0, 7); track day.dayName) {\n <div class=\"c-bookings-grid__header-cell\">\n {{ day.dayName }}\n </div>\n }\n </div>\n\n <!-- Days Grid -->\n <div class=\"c-bookings-grid__month-grid\">\n @for (day of monthDays(); track day.date.getTime()) {\n <div\n class=\"c-bookings-grid__month-cell\"\n [class.is-today]=\"day.isToday\"\n [class.is-weekend]=\"day.isWeekend\"\n [class.is-other-month]=\"\n day.date.getUTCMonth() !== selectedDate().getUTCMonth()\n \"\n [class.is-disabled]=\"isDayDisabled(day.date)\"\n (click)=\"!isDayDisabled(day.date) && onMonthDayClick(day.date)\"\n >\n <div class=\"c-bookings-grid__month-day-number\">\n {{ day.dayNumber }}\n </div>\n\n <div class=\"c-bookings-grid__month-events\">\n @let dayEvents = getEventsForDay(day.date); @for (event of\n dayEvents.slice(0, 3); track event.id) {\n <div\n class=\"c-bookings-grid__month-event\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"$event.stopPropagation(); onMonthEventClick(event, day.date)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n } @if (dayEvents.length > 3) {\n <div\n class=\"c-bookings-grid__more-events\"\n (click)=\"openDayPopover(day.date, $event)\"\n >\n {{ dayEvents.length - 3 }} m\u00E1s\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n @if (expandedDay()) {\n <div class=\"c-bookings-grid__popover-overlay\" (click)=\"closeDayPopover()\">\n <div class=\"c-bookings-grid__popover\" (click)=\"$event.stopPropagation()\">\n <div class=\"c-bookings-grid__popover-header\">\n <div class=\"c-bookings-grid__popover-date\">\n <span class=\"c-bookings-grid__popover-weekday\">{{\n expandedDay() | date : \"EEE\" : \"UTC\" : locale() | uppercase\n }}</span>\n <span class=\"c-bookings-grid__popover-daynum\">{{\n expandedDay() | date : \"d\" : \"UTC\"\n }}</span>\n </div>\n <button\n class=\"c-bookings-grid__popover-close\"\n (click)=\"closeDayPopover()\"\n >\n <span class=\"icon-cross\"></span>\n </button>\n </div>\n <div class=\"c-bookings-grid__popover-content\">\n @for (event of getExpandedDayEvents(); track event.id) {\n <div\n class=\"c-bookings-grid__month-event c-bookings-grid__month-event--popover\"\n [attr.data-type]=\"event.type\"\n [style.background-color]=\"event.metadata?.['color']\"\n [style.border-left]=\"event.metadata?.['color'] ? '3px solid ' + event.metadata?.['color'] : ''\"\n (click)=\"onMonthEventClick(event, expandedDay()!)\"\n >\n <span class=\"c-bookings-grid__month-event-title\">{{\n event.title\n }}</span>\n </div>\n }\n </div>\n </div>\n </div>\n }\n</div>\n}\n", styles: [":host{display:block;width:100%;overflow:visible}.c-bookings-grid__month-cell.is-disabled{background-color:#f3f4f6;cursor:not-allowed;opacity:.7}.c-bookings-grid__month-cell.is-disabled:hover{background-color:#f3f4f6}.c-bookings-grid__month-cell.is-disabled .c-bookings-grid__month-day-number{color:#9ca3af}.c-bookings-grid__slot--disabled{background-color:#f3f4f6;cursor:not-allowed}.c-bookings-grid__slot--disabled:hover{background-color:#f3f4f6}\n"] }]
21362
21718
  }] });
21363
21719
 
21364
21720
  class CacheBustingInterceptor {
@@ -21642,5 +21998,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.6", ngImpor
21642
21998
  * Generated bundle index. Do not edit.
21643
21999
  */
21644
22000
 
21645
- export { AD_AUTH_CONFIG, AD_AUTH_INTERCEPTOR_CONFIG, ALL_COUNTRY_CODES, ActiveFiltersComponent, AdAuthService, AdInteractionType, AdLoginButtonComponent, AgeValidationHelper, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, COMMON_COUNTRIES, CacheBustingInterceptor, CalendarEventType, CardComponent, CarouselComponent, ChatMessagePosition, ChatMessageType, CheckboxFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreManualRefreshComponent, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, CountryCode, CustomClassService, DEFAULT_AD_AUTH_INTERCEPTOR_CONFIG, DEFAULT_COUNTRIES, DEFAULT_SCHEDULER_CONFIG, DataListComponent, DataListItemComponent, DataStoreService, DateFieldComponent, DateUtility, DatetimeFieldComponent, DayState, DayType, DialogActions, DocumentAction, DocumentDisplayMode, DocumentFieldComponent, DocumentFieldValidators, DocumentPayloadMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FilePreviewActionType, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, FixedActionPosition, FixedActionsMobileModalComponent, FixedActionsMobileModalService, GalleryAnimationType, GalleryLayoutType, GalleryModalComponent, GalleryModalGlobalService, GenericButtonComponent, GenericCalendarComponent, GenericChatComponent, GenericChatService, GenericDocumentationComponent, GenericFixedActionsComponent, GenericGalleryComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSchedulerComponent, GenericSidebarComponent, GenericSkeletonComponent, GenericStepsComponent, GenericSwitchComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LATIN_AMERICA_COUNTRIES, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MODEL_REFERENCE_SORT_KEY, MainNavComponent, MainNavService, ManualRefreshService, MobileHeaderComponent, MobileResolutionService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsCustomActions, PermissionsInterceptor, PermissionsResources, PhoneFieldComponent, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, RedirectUrlService, ResetPasswordModel, RoleModel, SOUTH_AMERICA_COUNTRIES, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SkeletonAnimation, SkeletonService, SkeletonSize, SkeletonType, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableFixedActionsService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UruguayanDocumentValidationHelper, UsersModel, VERSION, WeekDay, adAuthGuard, adAuthInterceptor, adGuestGuard, adRoleGuard, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideAdAuth, provideAdAuthInterceptor, provideAdAuthWithInterceptor, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
22001
+ export { AD_AUTH_CONFIG, AD_AUTH_INTERCEPTOR_CONFIG, ALL_COUNTRY_CODES, ActiveFiltersComponent, AdAuthService, AdInteractionType, AdLoginButtonComponent, AgeValidationHelper, AlertComponent, AlertContainerComponent, AlertService, AlertType, ApiConfigurationProvider, BaseFieldComponent, ButtonContext, ButtonSize, ButtonType, COMMON_COUNTRIES, CacheBustingInterceptor, CalendarEventType, CardComponent, CarouselComponent, ChatMessagePosition, ChatMessageType, CheckboxFieldComponent, ColorPickerFieldComponent, ConfigurationModel, ConfirmationDialogComponent, ConfirmationDialogService, CoreHostDirective, CoreManualRefreshComponent, CoreUiHttpLoaderFactory, CoreUiTranslateLoader, CoreUiTranslateService, CountryCode, CustomClassService, DEFAULT_AD_AUTH_INTERCEPTOR_CONFIG, DEFAULT_COUNTRIES, DEFAULT_SCHEDULER_CONFIG, DataListComponent, DataListItemComponent, DataStoreService, DateFieldComponent, DateUtility, DatetimeFieldComponent, DayState, DayType, DialogActions, DocumentAction, DocumentDisplayMode, DocumentFieldComponent, DocumentFieldValidators, DocumentPayloadMode, DropdownComponent, DropdownDirection, DropdownService, DynamicFieldDirective, DynamicFieldsHelper, FieldErrorsComponent, FieldType, FileFieldComponent, FileModel, FilePreviewActionType, FileTemplateModel, FileTemplateType, FileType, FileTypeModel, FileUploadService, FilterModalComponent, FilterService, FilterType, FixedActionPosition, FixedActionsMobileModalComponent, FixedActionsMobileModalService, GalleryAnimationType, GalleryLayoutType, GalleryModalComponent, GalleryModalGlobalService, GenericButtonComponent, GenericCalendarComponent, GenericChatComponent, GenericChatService, GenericDocumentationComponent, GenericFixedActionsComponent, GenericGalleryComponent, GenericModalComponent, GenericPaginationComponent, GenericRatingComponent, GenericSchedulerComponent, GenericSidebarComponent, GenericSkeletonComponent, GenericStepsComponent, GenericSwitchComponent, GenericTableComponent, GenericTabsComponent, GenericTimelineComponent, GlobalApiConfigService, HeaderComponent, HeaderConfigurationService, HeaderElementType, HeaderService, HttpLoaderFactory, ImageModalComponent, ImageModalService, ImagePreviewComponent, LATIN_AMERICA_COUNTRIES, LayoutAuth, LayoutBreakpoint, LayoutComponent, LayoutService, LayoutStateService, LayoutType, LoaderComponent, LoaderService, MODEL_REFERENCE_SORT_KEY, MainNavComponent, MainNavService, ManualRefreshService, MobileHeaderComponent, MobileResolutionService, ModalMode, ModelApiService, MultiEntryFieldComponent, MultiEntryOutputFormat, NumberFieldComponent, NumberFieldConfigType, NumberFieldType, NumberRange, PERMISSION_ACTIONS_PROVIDER, PERMISSION_PROVIDER, PERMISSION_RESOURCES_PROVIDER, PaginationService, PasswordFieldComponent, PermissionEnumsService, PermissionModel, PermissionService, PermissionWrapperService, PermissionsActions, PermissionsCustomActions, PermissionsInterceptor, PermissionsResources, PhoneFieldComponent, ProgressBarComponent, ProgressBarSize, RatingService, RatingSize, RatingType, RedirectUrlService, ResetPasswordModel, RoleModel, SOUTH_AMERICA_COUNTRIES, SelectFieldComponent, ServerSelectFieldComponent, ServerSelectService, SidebarCustomModalComponent, SidebarCustomModalService, SidebarHeight, SidebarMobileModalService, SidebarMobileType, SidebarPosition, SidebarService, SidebarState, SidebarTemplateRegistryService, SidebarVisibility, SidebarWidth, SkeletonAnimation, SkeletonService, SkeletonSize, SkeletonType, SmartFieldComponent, SortDirection, SortMode, StepSize, StepStatus, StepType, StepsService, SwitchFieldComponent, TableAction, TableActionService, TableDataService, TableFixedActionsService, TableSortService, TextAreaFieldComponent, TextFieldComponent, TimeFieldComponent, TimeInterval, TimelineService, TimelineStatus, TimelineType, TranslationMergeService, UruguayanDocumentValidationHelper, UsersModel, VERSION, WeekDay, adAuthGuard, adAuthInterceptor, adGuestGuard, adRoleGuard, ageValidator, calculateAge, equalToValidator, generateRandomUruguayanDocument, getCountryCodeStrings, getLatestBirthDateForAge, getRandomCi, getUruguayanDocumentValidationDigit, getValidationDigit, isSameDate, isValidCountryCode, provideAdAuth, provideAdAuthInterceptor, provideAdAuthWithInterceptor, provideCoreUiTranslateLoader, providePermissionActions, providePermissionEnums, providePermissionResources, providePermissionService, providePermissionServiceFactory, provideTranslateLoader, random, transform, transformUruguayanDocument, uruguayanDocumentValidator, validate, validateAge, validateCi, validateUruguayanDocument, validationDigit };
21646
22002
  //# sourceMappingURL=solcre-org-core-ui.mjs.map