codexly-ui 0.4.1 → 0.4.3

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.
@@ -1156,6 +1156,7 @@ class ClxTagComponent {
1156
1156
  <ng-content />
1157
1157
  <button
1158
1158
  clx-button
1159
+ type="button"
1159
1160
  variant="ghost"
1160
1161
  [color]="_closeBtnColor()"
1161
1162
  shape="circle"
@@ -1177,6 +1178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
1177
1178
  <ng-content />
1178
1179
  <button
1179
1180
  clx-button
1181
+ type="button"
1180
1182
  variant="ghost"
1181
1183
  [color]="_closeBtnColor()"
1182
1184
  shape="circle"
@@ -2727,6 +2729,7 @@ class ClxInputComponent {
2727
2729
  @if (type() === 'password') {
2728
2730
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
2729
2731
  <button clx-button
2732
+ type="button"
2730
2733
  variant="ghost"
2731
2734
  [color]="_color()"
2732
2735
  shape="circle"
@@ -2821,6 +2824,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
2821
2824
  @if (type() === 'password') {
2822
2825
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
2823
2826
  <button clx-button
2827
+ type="button"
2824
2828
  variant="ghost"
2825
2829
  [color]="_color()"
2826
2830
  shape="circle"
@@ -3344,6 +3348,7 @@ class ClxNumberComponent {
3344
3348
  <!-- − + buttons -->
3345
3349
  <div class="flex items-center self-center pr-1 gap-0">
3346
3350
  <button clx-button
3351
+ type="button"
3347
3352
  variant="ghost"
3348
3353
  [color]="_color()"
3349
3354
  shape="circle"
@@ -3354,6 +3359,7 @@ class ClxNumberComponent {
3354
3359
  (mousedown)="$event.preventDefault()"
3355
3360
  (click)="_decrement()"></button>
3356
3361
  <button clx-button
3362
+ type="button"
3357
3363
  variant="ghost"
3358
3364
  [color]="_color()"
3359
3365
  shape="circle"
@@ -3373,6 +3379,7 @@ class ClxNumberComponent {
3373
3379
 
3374
3380
  <!-- Decrement -->
3375
3381
  <button clx-button
3382
+ type="button"
3376
3383
  variant="ghost"
3377
3384
  [color]="_color()"
3378
3385
  shape="circle"
@@ -3388,6 +3395,7 @@ class ClxNumberComponent {
3388
3395
 
3389
3396
  <!-- Increment -->
3390
3397
  <button clx-button
3398
+ type="button"
3391
3399
  variant="ghost"
3392
3400
  [color]="_color()"
3393
3401
  shape="circle"
@@ -3457,6 +3465,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3457
3465
  <!-- − + buttons -->
3458
3466
  <div class="flex items-center self-center pr-1 gap-0">
3459
3467
  <button clx-button
3468
+ type="button"
3460
3469
  variant="ghost"
3461
3470
  [color]="_color()"
3462
3471
  shape="circle"
@@ -3467,6 +3476,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3467
3476
  (mousedown)="$event.preventDefault()"
3468
3477
  (click)="_decrement()"></button>
3469
3478
  <button clx-button
3479
+ type="button"
3470
3480
  variant="ghost"
3471
3481
  [color]="_color()"
3472
3482
  shape="circle"
@@ -3486,6 +3496,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3486
3496
 
3487
3497
  <!-- Decrement -->
3488
3498
  <button clx-button
3499
+ type="button"
3489
3500
  variant="ghost"
3490
3501
  [color]="_color()"
3491
3502
  shape="circle"
@@ -3501,6 +3512,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3501
3512
 
3502
3513
  <!-- Increment -->
3503
3514
  <button clx-button
3515
+ type="button"
3504
3516
  variant="ghost"
3505
3517
  [color]="_color()"
3506
3518
  shape="circle"
@@ -3821,6 +3833,7 @@ class ClxSelectComponent {
3821
3833
  @if (_hasValue() && !_disabled() && multiple()) {
3822
3834
  <button
3823
3835
  clx-button
3836
+ type="button"
3824
3837
  variant="ghost"
3825
3838
  [color]="_activeColor()"
3826
3839
  shape="circle"
@@ -3833,6 +3846,7 @@ class ClxSelectComponent {
3833
3846
  }
3834
3847
  <button
3835
3848
  clx-button
3849
+ type="button"
3836
3850
  variant="ghost"
3837
3851
  [color]="_activeColor()"
3838
3852
  shape="circle"
@@ -3968,6 +3982,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3968
3982
  @if (_hasValue() && !_disabled() && multiple()) {
3969
3983
  <button
3970
3984
  clx-button
3985
+ type="button"
3971
3986
  variant="ghost"
3972
3987
  [color]="_activeColor()"
3973
3988
  shape="circle"
@@ -3980,6 +3995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
3980
3995
  }
3981
3996
  <button
3982
3997
  clx-button
3998
+ type="button"
3983
3999
  variant="ghost"
3984
4000
  [color]="_activeColor()"
3985
4001
  shape="circle"
@@ -4938,7 +4954,8 @@ class ClxUploadComponent {
4938
4954
  const existing = this.existingFiles().map(f => ({
4939
4955
  kind: 'existing',
4940
4956
  key: `existing:${f.id}`,
4941
- name: f.name ?? '',
4957
+ name: f.name ?? this._nameFromUrl(f.url),
4958
+ size: f.size,
4942
4959
  isImage: true,
4943
4960
  thumbUrl: f.url,
4944
4961
  fileIcon: '',
@@ -5169,6 +5186,14 @@ class ClxUploadComponent {
5169
5186
  : (files[0] ?? null);
5170
5187
  this._onChange(value);
5171
5188
  }
5189
+ _nameFromUrl(url) {
5190
+ try {
5191
+ return decodeURIComponent(url.split('/').pop() ?? url);
5192
+ }
5193
+ catch {
5194
+ return url;
5195
+ }
5196
+ }
5172
5197
  _formatSize(bytes) {
5173
5198
  if (bytes === 0)
5174
5199
  return '0 B';
@@ -5781,6 +5806,7 @@ class ClxColorPickerComponent {
5781
5806
  @if (_hasValue() && !_disabled()) {
5782
5807
  <button
5783
5808
  clx-button
5809
+ type="button"
5784
5810
  variant="ghost"
5785
5811
  [color]="_activeColor()"
5786
5812
  shape="circle"
@@ -5793,6 +5819,7 @@ class ClxColorPickerComponent {
5793
5819
  }
5794
5820
  <button
5795
5821
  clx-button
5822
+ type="button"
5796
5823
  variant="ghost"
5797
5824
  [color]="_activeColor()"
5798
5825
  shape="circle"
@@ -5948,6 +5975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5948
5975
  @if (_hasValue() && !_disabled()) {
5949
5976
  <button
5950
5977
  clx-button
5978
+ type="button"
5951
5979
  variant="ghost"
5952
5980
  [color]="_activeColor()"
5953
5981
  shape="circle"
@@ -5960,6 +5988,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
5960
5988
  }
5961
5989
  <button
5962
5990
  clx-button
5991
+ type="button"
5963
5992
  variant="ghost"
5964
5993
  [color]="_activeColor()"
5965
5994
  shape="circle"
@@ -6335,7 +6364,7 @@ class ClxDatepickerComponent {
6335
6364
 
6336
6365
  @if (_value() && !_disabled()) {
6337
6366
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
6338
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6367
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6339
6368
  icon="close" [iconOnly]="true"
6340
6369
  (mousedown)="$event.preventDefault()"
6341
6370
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -6357,12 +6386,12 @@ class ClxDatepickerComponent {
6357
6386
  <div [class]="_panelClass()" role="dialog" aria-label="Calendario">
6358
6387
 
6359
6388
  <div class="flex items-center justify-between px-4 py-3 border-b border-clx-border-soft">
6360
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6389
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6361
6390
  icon="chevron_left" [iconOnly]="true" (click)="_prevMonth()"></button>
6362
6391
  <button type="button" [class]="_headerLabelCls()" (click)="_toggleYearView()">
6363
6392
  {{ _headerLabel() }}
6364
6393
  </button>
6365
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6394
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6366
6395
  icon="chevron_right" [iconOnly]="true" (click)="_nextMonth()"></button>
6367
6396
  </div>
6368
6397
 
@@ -6389,8 +6418,8 @@ class ClxDatepickerComponent {
6389
6418
  }
6390
6419
 
6391
6420
  <div class="flex items-center justify-between px-4 py-2 border-t border-clx-border-soft">
6392
- <button clx-button variant="ghost" [color]="_color()" size="sm" (click)="_selectToday()">Hoy</button>
6393
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6421
+ <button clx-button type="button" variant="ghost" [color]="_color()" size="sm" (click)="_selectToday()">Hoy</button>
6422
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6394
6423
  </div>
6395
6424
 
6396
6425
  </div>
@@ -6435,7 +6464,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6435
6464
 
6436
6465
  @if (_value() && !_disabled()) {
6437
6466
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
6438
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6467
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6439
6468
  icon="close" [iconOnly]="true"
6440
6469
  (mousedown)="$event.preventDefault()"
6441
6470
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -6457,12 +6486,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6457
6486
  <div [class]="_panelClass()" role="dialog" aria-label="Calendario">
6458
6487
 
6459
6488
  <div class="flex items-center justify-between px-4 py-3 border-b border-clx-border-soft">
6460
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6489
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6461
6490
  icon="chevron_left" [iconOnly]="true" (click)="_prevMonth()"></button>
6462
6491
  <button type="button" [class]="_headerLabelCls()" (click)="_toggleYearView()">
6463
6492
  {{ _headerLabel() }}
6464
6493
  </button>
6465
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6494
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6466
6495
  icon="chevron_right" [iconOnly]="true" (click)="_nextMonth()"></button>
6467
6496
  </div>
6468
6497
 
@@ -6489,8 +6518,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6489
6518
  }
6490
6519
 
6491
6520
  <div class="flex items-center justify-between px-4 py-2 border-t border-clx-border-soft">
6492
- <button clx-button variant="ghost" [color]="_color()" size="sm" (click)="_selectToday()">Hoy</button>
6493
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6521
+ <button clx-button type="button" variant="ghost" [color]="_color()" size="sm" (click)="_selectToday()">Hoy</button>
6522
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6494
6523
  </div>
6495
6524
 
6496
6525
  </div>
@@ -6663,7 +6692,7 @@ class ClxTimepickerComponent {
6663
6692
 
6664
6693
  @if (_value() && !_disabled()) {
6665
6694
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
6666
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6695
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6667
6696
  icon="close" [iconOnly]="true"
6668
6697
  (mousedown)="$event.preventDefault()"
6669
6698
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -6704,8 +6733,8 @@ class ClxTimepickerComponent {
6704
6733
  </div>
6705
6734
 
6706
6735
  <div class="flex items-center justify-between px-4 py-2 border-t border-clx-border-soft">
6707
- <button clx-button variant="ghost" [color]="_color()" size="sm" (click)="_selectNow()">Ahora</button>
6708
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6736
+ <button clx-button type="button" variant="ghost" [color]="_color()" size="sm" (click)="_selectNow()">Ahora</button>
6737
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6709
6738
  </div>
6710
6739
 
6711
6740
  </div>
@@ -6750,7 +6779,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6750
6779
 
6751
6780
  @if (_value() && !_disabled()) {
6752
6781
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
6753
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
6782
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
6754
6783
  icon="close" [iconOnly]="true"
6755
6784
  (mousedown)="$event.preventDefault()"
6756
6785
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -6791,8 +6820,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
6791
6820
  </div>
6792
6821
 
6793
6822
  <div class="flex items-center justify-between px-4 py-2 border-t border-clx-border-soft">
6794
- <button clx-button variant="ghost" [color]="_color()" size="sm" (click)="_selectNow()">Ahora</button>
6795
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6823
+ <button clx-button type="button" variant="ghost" [color]="_color()" size="sm" (click)="_selectNow()">Ahora</button>
6824
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_closePanel()">Cerrar</button>
6796
6825
  </div>
6797
6826
 
6798
6827
  </div>
@@ -7151,7 +7180,7 @@ class ClxDateRangePickerComponent {
7151
7180
 
7152
7181
  @if (_hasValue() && !_disabled()) {
7153
7182
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
7154
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7183
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7155
7184
  icon="close" [iconOnly]="true"
7156
7185
  (mousedown)="$event.preventDefault()"
7157
7186
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -7191,7 +7220,7 @@ class ClxDateRangePickerComponent {
7191
7220
  <!-- Left calendar (cursor month) -->
7192
7221
  <div class="p-4">
7193
7222
  <div class="flex items-center justify-between mb-3">
7194
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7223
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7195
7224
  icon="chevron_left" [iconOnly]="true" (click)="_prevMonth()"></button>
7196
7225
  <span class="text-sm font-semibold text-clx-text-label">{{ _leftLabel() }}</span>
7197
7226
  <div class="w-9"></div>
@@ -7219,7 +7248,7 @@ class ClxDateRangePickerComponent {
7219
7248
  <div class="flex items-center justify-between mb-3">
7220
7249
  <div class="w-9"></div>
7221
7250
  <span class="text-sm font-semibold text-clx-text-label">{{ _rightLabel() }}</span>
7222
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7251
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7223
7252
  icon="chevron_right" [iconOnly]="true" (click)="_nextMonth()"></button>
7224
7253
  </div>
7225
7254
  <div class="grid grid-cols-7 mb-1">
@@ -7254,8 +7283,8 @@ class ClxDateRangePickerComponent {
7254
7283
  }
7255
7284
  </span>
7256
7285
  <div class="flex items-center gap-2">
7257
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_cancel()">Cancelar</button>
7258
- <button clx-button variant="solid" [color]="_color()" size="sm"
7286
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_cancel()">Cancelar</button>
7287
+ <button clx-button type="button" variant="solid" [color]="_color()" size="sm"
7259
7288
  [disabled]="!_canApply()"
7260
7289
  (click)="_apply()">
7261
7290
  Aplicar
@@ -7308,7 +7337,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7308
7337
 
7309
7338
  @if (_hasValue() && !_disabled()) {
7310
7339
  <div class="absolute right-0 top-0 h-full flex items-center pr-1">
7311
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7340
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7312
7341
  icon="close" [iconOnly]="true"
7313
7342
  (mousedown)="$event.preventDefault()"
7314
7343
  (click)="$event.stopPropagation(); _clear()"></button>
@@ -7348,7 +7377,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7348
7377
  <!-- Left calendar (cursor month) -->
7349
7378
  <div class="p-4">
7350
7379
  <div class="flex items-center justify-between mb-3">
7351
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7380
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7352
7381
  icon="chevron_left" [iconOnly]="true" (click)="_prevMonth()"></button>
7353
7382
  <span class="text-sm font-semibold text-clx-text-label">{{ _leftLabel() }}</span>
7354
7383
  <div class="w-9"></div>
@@ -7376,7 +7405,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7376
7405
  <div class="flex items-center justify-between mb-3">
7377
7406
  <div class="w-9"></div>
7378
7407
  <span class="text-sm font-semibold text-clx-text-label">{{ _rightLabel() }}</span>
7379
- <button clx-button variant="ghost" [color]="_color()" shape="circle" size="sm"
7408
+ <button clx-button type="button" variant="ghost" [color]="_color()" shape="circle" size="sm"
7380
7409
  icon="chevron_right" [iconOnly]="true" (click)="_nextMonth()"></button>
7381
7410
  </div>
7382
7411
  <div class="grid grid-cols-7 mb-1">
@@ -7411,8 +7440,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7411
7440
  }
7412
7441
  </span>
7413
7442
  <div class="flex items-center gap-2">
7414
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_cancel()">Cancelar</button>
7415
- <button clx-button variant="solid" [color]="_color()" size="sm"
7443
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_cancel()">Cancelar</button>
7444
+ <button clx-button type="button" variant="solid" [color]="_color()" size="sm"
7416
7445
  [disabled]="!_canApply()"
7417
7446
  (click)="_apply()">
7418
7447
  Aplicar
@@ -7493,6 +7522,7 @@ class ClxModalComponent {
7493
7522
  @if (showClose()) {
7494
7523
  <button
7495
7524
  clx-button
7525
+ type="button"
7496
7526
  variant="ghost"
7497
7527
  color="zinc"
7498
7528
  shape="circle"
@@ -7516,6 +7546,7 @@ class ClxModalComponent {
7516
7546
  @if (showCancelButton()) {
7517
7547
  <button
7518
7548
  clx-button
7549
+ type="button"
7519
7550
  [color]="_cancelColor()"
7520
7551
  [variant]="_cancelVariant()"
7521
7552
  size="md"
@@ -7525,6 +7556,7 @@ class ClxModalComponent {
7525
7556
  }
7526
7557
  <button
7527
7558
  clx-button
7559
+ type="button"
7528
7560
  [color]="_confirmColor()"
7529
7561
  [variant]="_confirmVariant()"
7530
7562
  size="md"
@@ -7552,6 +7584,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7552
7584
  @if (showClose()) {
7553
7585
  <button
7554
7586
  clx-button
7587
+ type="button"
7555
7588
  variant="ghost"
7556
7589
  color="zinc"
7557
7590
  shape="circle"
@@ -7575,6 +7608,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7575
7608
  @if (showCancelButton()) {
7576
7609
  <button
7577
7610
  clx-button
7611
+ type="button"
7578
7612
  [color]="_cancelColor()"
7579
7613
  [variant]="_cancelVariant()"
7580
7614
  size="md"
@@ -7584,6 +7618,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
7584
7618
  }
7585
7619
  <button
7586
7620
  clx-button
7621
+ type="button"
7587
7622
  [color]="_confirmColor()"
7588
7623
  [variant]="_confirmVariant()"
7589
7624
  size="md"
@@ -8288,6 +8323,7 @@ class ClxEditorComponent {
8288
8323
  @for (btn of group; track btn.cmd) {
8289
8324
  <button
8290
8325
  clx-button
8326
+ type="button"
8291
8327
  [variant]="_btnVariant(btn.mark)"
8292
8328
  [color]="_color()"
8293
8329
  size="xs"
@@ -8309,6 +8345,7 @@ class ClxEditorComponent {
8309
8345
  <!-- Text color -->
8310
8346
  <button
8311
8347
  clx-button
8348
+ type="button"
8312
8349
  variant="ghost"
8313
8350
  [color]="_color()"
8314
8351
  size="xs"
@@ -8324,6 +8361,7 @@ class ClxEditorComponent {
8324
8361
  <!-- Highlight -->
8325
8362
  <button
8326
8363
  clx-button
8364
+ type="button"
8327
8365
  variant="ghost"
8328
8366
  [color]="_color()"
8329
8367
  size="xs"
@@ -8342,6 +8380,7 @@ class ClxEditorComponent {
8342
8380
  <!-- HTML source toggle -->
8343
8381
  <button
8344
8382
  clx-button
8383
+ type="button"
8345
8384
  [variant]="_sourceMode() ? 'light' : 'ghost'"
8346
8385
  [color]="_color()"
8347
8386
  size="xs"
@@ -8356,6 +8395,7 @@ class ClxEditorComponent {
8356
8395
  <!-- Copy HTML -->
8357
8396
  <button
8358
8397
  clx-button
8398
+ type="button"
8359
8399
  variant="ghost"
8360
8400
  [color]="_color()"
8361
8401
  size="xs"
@@ -8470,6 +8510,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8470
8510
  @for (btn of group; track btn.cmd) {
8471
8511
  <button
8472
8512
  clx-button
8513
+ type="button"
8473
8514
  [variant]="_btnVariant(btn.mark)"
8474
8515
  [color]="_color()"
8475
8516
  size="xs"
@@ -8491,6 +8532,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8491
8532
  <!-- Text color -->
8492
8533
  <button
8493
8534
  clx-button
8535
+ type="button"
8494
8536
  variant="ghost"
8495
8537
  [color]="_color()"
8496
8538
  size="xs"
@@ -8506,6 +8548,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8506
8548
  <!-- Highlight -->
8507
8549
  <button
8508
8550
  clx-button
8551
+ type="button"
8509
8552
  variant="ghost"
8510
8553
  [color]="_color()"
8511
8554
  size="xs"
@@ -8524,6 +8567,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8524
8567
  <!-- HTML source toggle -->
8525
8568
  <button
8526
8569
  clx-button
8570
+ type="button"
8527
8571
  [variant]="_sourceMode() ? 'light' : 'ghost'"
8528
8572
  [color]="_color()"
8529
8573
  size="xs"
@@ -8538,6 +8582,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8538
8582
  <!-- Copy HTML -->
8539
8583
  <button
8540
8584
  clx-button
8585
+ type="button"
8541
8586
  variant="ghost"
8542
8587
  [color]="_color()"
8543
8588
  size="xs"
@@ -8658,6 +8703,7 @@ class ClxTabsComponent {
8658
8703
  @for (tab of tabs(); track tab.id) {
8659
8704
  <div class="flex relative">
8660
8705
  <button clx-button
8706
+ type="button"
8661
8707
  role="tab"
8662
8708
  variant="ghost"
8663
8709
  [color]="activeTab() === tab.id ? _clxColor() : 'slate'"
@@ -8698,6 +8744,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
8698
8744
  @for (tab of tabs(); track tab.id) {
8699
8745
  <div class="flex relative">
8700
8746
  <button clx-button
8747
+ type="button"
8701
8748
  role="tab"
8702
8749
  variant="ghost"
8703
8750
  [color]="activeTab() === tab.id ? _clxColor() : 'slate'"
@@ -8916,6 +8963,7 @@ class ClxWizardComponent {
8916
8963
  @if (_currentIndex() > 0) {
8917
8964
  <button
8918
8965
  clx-button
8966
+ type="button"
8919
8967
  [color]="_color()"
8920
8968
  variant="ghost"
8921
8969
  size="sm"
@@ -8927,6 +8975,7 @@ class ClxWizardComponent {
8927
8975
  @if (_currentIndex() < _lastIndex()) {
8928
8976
  <button
8929
8977
  clx-button
8978
+ type="button"
8930
8979
  [color]="_color()"
8931
8980
  variant="solid"
8932
8981
  size="sm"
@@ -8938,6 +8987,7 @@ class ClxWizardComponent {
8938
8987
  } @else {
8939
8988
  <button
8940
8989
  clx-button
8990
+ type="button"
8941
8991
  color="green"
8942
8992
  variant="solid"
8943
8993
  size="sm"
@@ -9021,6 +9071,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9021
9071
  @if (_currentIndex() > 0) {
9022
9072
  <button
9023
9073
  clx-button
9074
+ type="button"
9024
9075
  [color]="_color()"
9025
9076
  variant="ghost"
9026
9077
  size="sm"
@@ -9032,6 +9083,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9032
9083
  @if (_currentIndex() < _lastIndex()) {
9033
9084
  <button
9034
9085
  clx-button
9086
+ type="button"
9035
9087
  [color]="_color()"
9036
9088
  variant="solid"
9037
9089
  size="sm"
@@ -9043,6 +9095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9043
9095
  } @else {
9044
9096
  <button
9045
9097
  clx-button
9098
+ type="button"
9046
9099
  color="green"
9047
9100
  variant="solid"
9048
9101
  size="sm"
@@ -9755,7 +9808,7 @@ class ClxProfileComponent {
9755
9808
  @if (menuItems().length) {
9756
9809
  <div class="p-1.5">
9757
9810
  @for (item of menuItems(); track item.action) {
9758
- <button clx-button variant="ghost" [color]="_color()" [block]="true" [icon]="item.icon"
9811
+ <button clx-button type="button" variant="ghost" [color]="_color()" [block]="true" [icon]="item.icon"
9759
9812
  class="justify-start rounded-xl!"
9760
9813
  (click)="_onAction(item.action)">
9761
9814
  {{ item.label }}
@@ -9767,7 +9820,7 @@ class ClxProfileComponent {
9767
9820
 
9768
9821
  <!-- Sign out -->
9769
9822
  <div class="p-1.5">
9770
- <button clx-button variant="ghost" color="red" [block]="true" icon="logout"
9823
+ <button clx-button type="button" variant="ghost" color="red" [block]="true" icon="logout"
9771
9824
  class="justify-start rounded-xl!"
9772
9825
  (click)="_onSignOut()">
9773
9826
  {{ signOutLabel() }}
@@ -9836,7 +9889,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9836
9889
  @if (menuItems().length) {
9837
9890
  <div class="p-1.5">
9838
9891
  @for (item of menuItems(); track item.action) {
9839
- <button clx-button variant="ghost" [color]="_color()" [block]="true" [icon]="item.icon"
9892
+ <button clx-button type="button" variant="ghost" [color]="_color()" [block]="true" [icon]="item.icon"
9840
9893
  class="justify-start rounded-xl!"
9841
9894
  (click)="_onAction(item.action)">
9842
9895
  {{ item.label }}
@@ -9848,7 +9901,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9848
9901
 
9849
9902
  <!-- Sign out -->
9850
9903
  <div class="p-1.5">
9851
- <button clx-button variant="ghost" color="red" [block]="true" icon="logout"
9904
+ <button clx-button type="button" variant="ghost" color="red" [block]="true" icon="logout"
9852
9905
  class="justify-start rounded-xl!"
9853
9906
  (click)="_onSignOut()">
9854
9907
  {{ signOutLabel() }}
@@ -9910,6 +9963,7 @@ class ClxDrawerComponent {
9910
9963
  @if (showClose()) {
9911
9964
  <button
9912
9965
  clx-button
9966
+ type="button"
9913
9967
  variant="ghost"
9914
9968
  color="zinc"
9915
9969
  shape="circle"
@@ -9933,6 +9987,7 @@ class ClxDrawerComponent {
9933
9987
  @if (showCancelButton()) {
9934
9988
  <button
9935
9989
  clx-button
9990
+ type="button"
9936
9991
  [color]="_cancelColor()"
9937
9992
  [variant]="_cancelVariant()"
9938
9993
  size="md"
@@ -9942,6 +9997,7 @@ class ClxDrawerComponent {
9942
9997
  }
9943
9998
  <button
9944
9999
  clx-button
10000
+ type="button"
9945
10001
  [color]="_confirmColor()"
9946
10002
  [variant]="_confirmVariant()"
9947
10003
  size="md"
@@ -9969,6 +10025,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9969
10025
  @if (showClose()) {
9970
10026
  <button
9971
10027
  clx-button
10028
+ type="button"
9972
10029
  variant="ghost"
9973
10030
  color="zinc"
9974
10031
  shape="circle"
@@ -9992,6 +10049,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
9992
10049
  @if (showCancelButton()) {
9993
10050
  <button
9994
10051
  clx-button
10052
+ type="button"
9995
10053
  [color]="_cancelColor()"
9996
10054
  [variant]="_cancelVariant()"
9997
10055
  size="md"
@@ -10001,6 +10059,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
10001
10059
  }
10002
10060
  <button
10003
10061
  clx-button
10062
+ type="button"
10004
10063
  [color]="_confirmColor()"
10005
10064
  [variant]="_confirmVariant()"
10006
10065
  size="md"
@@ -10213,6 +10272,7 @@ class ClxAlertComponent {
10213
10272
  @if (_showCancel()) {
10214
10273
  <button
10215
10274
  clx-button
10275
+ type="button"
10216
10276
  [color]="_cancelColor()"
10217
10277
  [variant]="_cancelVariant()"
10218
10278
  size="md"
@@ -10224,6 +10284,7 @@ class ClxAlertComponent {
10224
10284
 
10225
10285
  <button
10226
10286
  clx-button
10287
+ type="button"
10227
10288
  [color]="_confirmColor()"
10228
10289
  variant="solid"
10229
10290
  size="md"
@@ -10283,6 +10344,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
10283
10344
  @if (_showCancel()) {
10284
10345
  <button
10285
10346
  clx-button
10347
+ type="button"
10286
10348
  [color]="_cancelColor()"
10287
10349
  [variant]="_cancelVariant()"
10288
10350
  size="md"
@@ -10294,6 +10356,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
10294
10356
 
10295
10357
  <button
10296
10358
  clx-button
10359
+ type="button"
10297
10360
  [color]="_confirmColor()"
10298
10361
  variant="solid"
10299
10362
  size="md"
@@ -10580,6 +10643,7 @@ class ClxToastComponent {
10580
10643
  @if (entry().action) {
10581
10644
  <button
10582
10645
  clx-button
10646
+ type="button"
10583
10647
  variant="link"
10584
10648
  [color]="_buttonColor()"
10585
10649
  size="xs"
@@ -10594,6 +10658,7 @@ class ClxToastComponent {
10594
10658
  <!-- Close button -->
10595
10659
  <button
10596
10660
  clx-button
10661
+ type="button"
10597
10662
  variant="ghost"
10598
10663
  [color]="_buttonColor()"
10599
10664
  size="xxs"
@@ -10649,6 +10714,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
10649
10714
  @if (entry().action) {
10650
10715
  <button
10651
10716
  clx-button
10717
+ type="button"
10652
10718
  variant="link"
10653
10719
  [color]="_buttonColor()"
10654
10720
  size="xs"
@@ -10663,6 +10729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
10663
10729
  <!-- Close button -->
10664
10730
  <button
10665
10731
  clx-button
10732
+ type="button"
10666
10733
  variant="ghost"
10667
10734
  [color]="_buttonColor()"
10668
10735
  size="xxs"
@@ -11132,6 +11199,7 @@ class ClxPaginationComponent {
11132
11199
  <!-- |<< Primera página -->
11133
11200
  <button
11134
11201
  clx-button
11202
+ type="button"
11135
11203
  variant="ghost"
11136
11204
  color="slate"
11137
11205
  [size]="_cfg().btnSize"
@@ -11145,6 +11213,7 @@ class ClxPaginationComponent {
11145
11213
  <!-- < Anterior -->
11146
11214
  <button
11147
11215
  clx-button
11216
+ type="button"
11148
11217
  variant="ghost"
11149
11218
  color="slate"
11150
11219
  [size]="_cfg().btnSize"
@@ -11160,6 +11229,7 @@ class ClxPaginationComponent {
11160
11229
  @if (item.type === 'page') {
11161
11230
  <button
11162
11231
  clx-button
11232
+ type="button"
11163
11233
  [variant]="currentPage() === item.page ? 'solid' : 'ghost'"
11164
11234
  [color]="currentPage() === item.page ? _color() : 'slate'"
11165
11235
  [size]="_cfg().btnSize"
@@ -11177,6 +11247,7 @@ class ClxPaginationComponent {
11177
11247
  <!-- > Siguiente -->
11178
11248
  <button
11179
11249
  clx-button
11250
+ type="button"
11180
11251
  variant="ghost"
11181
11252
  color="slate"
11182
11253
  [size]="_cfg().btnSize"
@@ -11190,6 +11261,7 @@ class ClxPaginationComponent {
11190
11261
  <!-- >>| Última página -->
11191
11262
  <button
11192
11263
  clx-button
11264
+ type="button"
11193
11265
  variant="ghost"
11194
11266
  color="slate"
11195
11267
  [size]="_cfg().btnSize"
@@ -11238,6 +11310,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11238
11310
  <!-- |<< Primera página -->
11239
11311
  <button
11240
11312
  clx-button
11313
+ type="button"
11241
11314
  variant="ghost"
11242
11315
  color="slate"
11243
11316
  [size]="_cfg().btnSize"
@@ -11251,6 +11324,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11251
11324
  <!-- < Anterior -->
11252
11325
  <button
11253
11326
  clx-button
11327
+ type="button"
11254
11328
  variant="ghost"
11255
11329
  color="slate"
11256
11330
  [size]="_cfg().btnSize"
@@ -11266,6 +11340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11266
11340
  @if (item.type === 'page') {
11267
11341
  <button
11268
11342
  clx-button
11343
+ type="button"
11269
11344
  [variant]="currentPage() === item.page ? 'solid' : 'ghost'"
11270
11345
  [color]="currentPage() === item.page ? _color() : 'slate'"
11271
11346
  [size]="_cfg().btnSize"
@@ -11283,6 +11358,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11283
11358
  <!-- > Siguiente -->
11284
11359
  <button
11285
11360
  clx-button
11361
+ type="button"
11286
11362
  variant="ghost"
11287
11363
  color="slate"
11288
11364
  [size]="_cfg().btnSize"
@@ -11296,6 +11372,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11296
11372
  <!-- >>| Última página -->
11297
11373
  <button
11298
11374
  clx-button
11375
+ type="button"
11299
11376
  variant="ghost"
11300
11377
  color="slate"
11301
11378
  [size]="_cfg().btnSize"
@@ -11432,7 +11509,7 @@ class ClxFilterPanelComponent {
11432
11509
  }
11433
11510
  </div>
11434
11511
  @if (_activeCount() > 0) {
11435
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_reset()">
11512
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_reset()">
11436
11513
  Limpiar
11437
11514
  </button>
11438
11515
  }
@@ -11542,7 +11619,7 @@ class ClxFilterPanelComponent {
11542
11619
  <!-- Apply footer -->
11543
11620
  @if (showApply()) {
11544
11621
  <div class="px-4 py-3 border-t border-clx-border-soft flex gap-2">
11545
- <button clx-button variant="solid" [color]="_color()" size="sm" class="flex-1" (click)="_apply()">
11622
+ <button clx-button type="button" variant="solid" [color]="_color()" size="sm" class="flex-1" (click)="_apply()">
11546
11623
  Aplicar filtros
11547
11624
  </button>
11548
11625
  </div>
@@ -11566,7 +11643,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11566
11643
  }
11567
11644
  </div>
11568
11645
  @if (_activeCount() > 0) {
11569
- <button clx-button variant="ghost" color="slate" size="sm" (click)="_reset()">
11646
+ <button clx-button type="button" variant="ghost" color="slate" size="sm" (click)="_reset()">
11570
11647
  Limpiar
11571
11648
  </button>
11572
11649
  }
@@ -11676,7 +11753,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11676
11753
  <!-- Apply footer -->
11677
11754
  @if (showApply()) {
11678
11755
  <div class="px-4 py-3 border-t border-clx-border-soft flex gap-2">
11679
- <button clx-button variant="solid" [color]="_color()" size="sm" class="flex-1" (click)="_apply()">
11756
+ <button clx-button type="button" variant="solid" [color]="_color()" size="sm" class="flex-1" (click)="_apply()">
11680
11757
  Aplicar filtros
11681
11758
  </button>
11682
11759
  </div>
@@ -11839,6 +11916,7 @@ class ClxCarouselComponent {
11839
11916
  @if (_slides().length > 1) {
11840
11917
  <div class="absolute left-3 top-1/2 -translate-y-1/2 z-10">
11841
11918
  <button clx-button
11919
+ type="button"
11842
11920
  variant="solid"
11843
11921
  color="white"
11844
11922
  shape="circle"
@@ -11853,6 +11931,7 @@ class ClxCarouselComponent {
11853
11931
  <!-- Arrow: Next -->
11854
11932
  <div class="absolute right-3 top-1/2 -translate-y-1/2 z-10">
11855
11933
  <button clx-button
11934
+ type="button"
11856
11935
  variant="solid"
11857
11936
  color="white"
11858
11937
  shape="circle"
@@ -11905,6 +11984,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11905
11984
  @if (_slides().length > 1) {
11906
11985
  <div class="absolute left-3 top-1/2 -translate-y-1/2 z-10">
11907
11986
  <button clx-button
11987
+ type="button"
11908
11988
  variant="solid"
11909
11989
  color="white"
11910
11990
  shape="circle"
@@ -11919,6 +11999,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
11919
11999
  <!-- Arrow: Next -->
11920
12000
  <div class="absolute right-3 top-1/2 -translate-y-1/2 z-10">
11921
12001
  <button clx-button
12002
+ type="button"
11922
12003
  variant="solid"
11923
12004
  color="white"
11924
12005
  shape="circle"
@@ -12072,6 +12153,7 @@ class ClxPageEmptyComponent {
12072
12153
  @if (ctaLabel()) {
12073
12154
  <button
12074
12155
  clx-button
12156
+ type="button"
12075
12157
  [color]="_ctaColor()"
12076
12158
  variant="solid"
12077
12159
  [icon]="ctaIcon()"
@@ -12105,6 +12187,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12105
12187
  @if (ctaLabel()) {
12106
12188
  <button
12107
12189
  clx-button
12190
+ type="button"
12108
12191
  [color]="_ctaColor()"
12109
12192
  variant="solid"
12110
12193
  [icon]="ctaIcon()"
@@ -12589,6 +12672,7 @@ class ClxPageNotFoundComponent {
12589
12672
  @if (backLabel()) {
12590
12673
  <button
12591
12674
  clx-button
12675
+ type="button"
12592
12676
  color="indigo"
12593
12677
  variant="solid"
12594
12678
  icon="arrow_back"
@@ -12619,6 +12703,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12619
12703
  @if (backLabel()) {
12620
12704
  <button
12621
12705
  clx-button
12706
+ type="button"
12622
12707
  color="indigo"
12623
12708
  variant="solid"
12624
12709
  icon="arrow_back"
@@ -12652,6 +12737,7 @@ class ClxPageUnauthorizedComponent {
12652
12737
  @if (loginLabel()) {
12653
12738
  <button
12654
12739
  clx-button
12740
+ type="button"
12655
12741
  color="indigo"
12656
12742
  variant="solid"
12657
12743
  icon="login"
@@ -12662,6 +12748,7 @@ class ClxPageUnauthorizedComponent {
12662
12748
  @if (backLabel()) {
12663
12749
  <button
12664
12750
  clx-button
12751
+ type="button"
12665
12752
  color="slate"
12666
12753
  variant="ghost"
12667
12754
  icon="arrow_back"
@@ -12694,6 +12781,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12694
12781
  @if (loginLabel()) {
12695
12782
  <button
12696
12783
  clx-button
12784
+ type="button"
12697
12785
  color="indigo"
12698
12786
  variant="solid"
12699
12787
  icon="login"
@@ -12704,6 +12792,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12704
12792
  @if (backLabel()) {
12705
12793
  <button
12706
12794
  clx-button
12795
+ type="button"
12707
12796
  color="slate"
12708
12797
  variant="ghost"
12709
12798
  icon="arrow_back"
@@ -12742,6 +12831,7 @@ class ClxPageServerErrorComponent {
12742
12831
  @if (retryLabel()) {
12743
12832
  <button
12744
12833
  clx-button
12834
+ type="button"
12745
12835
  color="red"
12746
12836
  variant="solid"
12747
12837
  icon="refresh"
@@ -12752,6 +12842,7 @@ class ClxPageServerErrorComponent {
12752
12842
  @if (backLabel()) {
12753
12843
  <button
12754
12844
  clx-button
12845
+ type="button"
12755
12846
  color="slate"
12756
12847
  variant="ghost"
12757
12848
  icon="arrow_back"
@@ -12788,6 +12879,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12788
12879
  @if (retryLabel()) {
12789
12880
  <button
12790
12881
  clx-button
12882
+ type="button"
12791
12883
  color="red"
12792
12884
  variant="solid"
12793
12885
  icon="refresh"
@@ -12798,6 +12890,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
12798
12890
  @if (backLabel()) {
12799
12891
  <button
12800
12892
  clx-button
12893
+ type="button"
12801
12894
  color="slate"
12802
12895
  variant="ghost"
12803
12896
  icon="arrow_back"
@@ -13233,6 +13326,7 @@ class ClxProductComponent {
13233
13326
  <div class="absolute bottom-3 right-3">
13234
13327
  <button
13235
13328
  clx-button
13329
+ type="button"
13236
13330
  [color]="clxColor()"
13237
13331
  variant="solid"
13238
13332
  [size]="_buttonSize()"
@@ -13276,6 +13370,7 @@ class ClxProductComponent {
13276
13370
  <div [class]="_actionsClass()">
13277
13371
  <button
13278
13372
  clx-button
13373
+ type="button"
13279
13374
  [color]="clxColor()"
13280
13375
  variant="solid"
13281
13376
  [size]="_buttonSize()"
@@ -13366,6 +13461,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13366
13461
  <div class="absolute bottom-3 right-3">
13367
13462
  <button
13368
13463
  clx-button
13464
+ type="button"
13369
13465
  [color]="clxColor()"
13370
13466
  variant="solid"
13371
13467
  [size]="_buttonSize()"
@@ -13409,6 +13505,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13409
13505
  <div [class]="_actionsClass()">
13410
13506
  <button
13411
13507
  clx-button
13508
+ type="button"
13412
13509
  [color]="clxColor()"
13413
13510
  variant="solid"
13414
13511
  [size]="_buttonSize()"
@@ -13504,7 +13601,7 @@ class ClxProductDetailComponent {
13504
13601
  specsLeft(specs) { return specs.slice(0, Math.ceil(specs.length / 2)); }
13505
13602
  specsRight(specs) { return specs.slice(Math.ceil(specs.length / 2)); }
13506
13603
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13507
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProductDetailComponent, isStandalone: true, selector: "clx-product-detail", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, clxColor: { classPropertyName: "clxColor", publicName: "clxColor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_carousel", first: true, predicate: ClxCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxButtonGroupComponent, selector: "clx-button-group", inputs: ["label", "shape", "attached", "orientation"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxRatingComponent, selector: "clx-rating", inputs: ["value", "max", "color"] }, { kind: "component", type: ClxCarouselComponent, selector: "clx-carousel", inputs: ["clxColor", "autoPlay", "interval", "loop", "aspectRatio", "transparent"] }, { kind: "directive", type: ClxCarouselDirective, selector: "[clxSlide]" }, { kind: "component", type: ClxTabsComponent, selector: "clx-tabs", inputs: ["tabs", "clxColor", "activeTab"], outputs: ["activeTabChange"] }, { kind: "directive", type: ClxTabDirective, selector: "[clxTabPanel]", inputs: ["clxTabPanel"] }, { kind: "component", type: ClxNumberComponent, selector: "clx-number", inputs: ["variant", "size", "color", "label", "placeholder", "hint", "prefixIcon", "min", "max", "step", "value", "disabled"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }, { kind: "component", type: ClxListComponent, selector: "clx-list", inputs: ["color", "variant", "size", "numbered"] }, { kind: "component", type: ClxListItemComponent, selector: "clx-list-item", inputs: ["label", "sublabel", "icon", "meta", "metaColor", "disabled"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13604
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProductDetailComponent, isStandalone: true, selector: "clx-product-detail", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, clxColor: { classPropertyName: "clxColor", publicName: "clxColor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_carousel", first: true, predicate: ClxCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button type=\"button\" variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button type=\"button\" variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxButtonGroupComponent, selector: "clx-button-group", inputs: ["label", "shape", "attached", "orientation"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxRatingComponent, selector: "clx-rating", inputs: ["value", "max", "color"] }, { kind: "component", type: ClxCarouselComponent, selector: "clx-carousel", inputs: ["clxColor", "autoPlay", "interval", "loop", "aspectRatio", "transparent"] }, { kind: "directive", type: ClxCarouselDirective, selector: "[clxSlide]" }, { kind: "component", type: ClxTabsComponent, selector: "clx-tabs", inputs: ["tabs", "clxColor", "activeTab"], outputs: ["activeTabChange"] }, { kind: "directive", type: ClxTabDirective, selector: "[clxTabPanel]", inputs: ["clxTabPanel"] }, { kind: "component", type: ClxNumberComponent, selector: "clx-number", inputs: ["variant", "size", "color", "label", "placeholder", "hint", "prefixIcon", "min", "max", "step", "value", "disabled"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }, { kind: "component", type: ClxListComponent, selector: "clx-list", inputs: ["color", "variant", "size", "numbered"] }, { kind: "component", type: ClxListItemComponent, selector: "clx-list-item", inputs: ["label", "sublabel", "icon", "meta", "metaColor", "disabled"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
13508
13605
  }
13509
13606
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, decorators: [{
13510
13607
  type: Component,
@@ -13526,7 +13623,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13526
13623
  ClxTooltipDirective,
13527
13624
  ClxListComponent,
13528
13625
  ClxListItemComponent,
13529
- ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n" }]
13626
+ ], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button type=\"button\" variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button type=\"button\" variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button type=\"button\" variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n" }]
13530
13627
  }], ctorParameters: () => [], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }], clxColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "clxColor", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], _carousel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClxCarouselComponent), { isSignal: true }] }] } });
13531
13628
 
13532
13629
  const WISHLIST_PAGE_SIZE_DEFAULT = 6;
@@ -13664,6 +13761,7 @@ class ClxWishlistComponent {
13664
13761
  </div>
13665
13762
  <button
13666
13763
  clx-button
13764
+ type="button"
13667
13765
  variant="light"
13668
13766
  [color]="color()"
13669
13767
  size="sm"
@@ -13756,6 +13854,7 @@ class ClxWishlistComponent {
13756
13854
  <div class="absolute top-3 right-3 z-10">
13757
13855
  <button
13758
13856
  clx-button
13857
+ type="button"
13759
13858
  variant="ghost"
13760
13859
  color="red"
13761
13860
  size="md"
@@ -13773,6 +13872,7 @@ class ClxWishlistComponent {
13773
13872
  <div [class]="_actionsClass">
13774
13873
  <button
13775
13874
  clx-button
13875
+ type="button"
13776
13876
  [color]="color()"
13777
13877
  variant="solid"
13778
13878
  size="md"
@@ -13863,6 +13963,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13863
13963
  </div>
13864
13964
  <button
13865
13965
  clx-button
13966
+ type="button"
13866
13967
  variant="light"
13867
13968
  [color]="color()"
13868
13969
  size="sm"
@@ -13955,6 +14056,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13955
14056
  <div class="absolute top-3 right-3 z-10">
13956
14057
  <button
13957
14058
  clx-button
14059
+ type="button"
13958
14060
  variant="ghost"
13959
14061
  color="red"
13960
14062
  size="md"
@@ -13972,6 +14074,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
13972
14074
  <div [class]="_actionsClass">
13973
14075
  <button
13974
14076
  clx-button
14077
+ type="button"
13975
14078
  [color]="color()"
13976
14079
  variant="solid"
13977
14080
  size="md"
@@ -14101,7 +14204,7 @@ class ClxCartComponent {
14101
14204
  <span clx-badge variant="light" [color]="color()" size="sm">{{ _totalUnits() }}</span>
14102
14205
  </div>
14103
14206
  <button
14104
- clx-button variant="ghost" color="red" size="sm" icon="delete_sweep"
14207
+ clx-button type="button" variant="ghost" color="red" size="sm" icon="delete_sweep"
14105
14208
  (click)="onClearCart.emit()">
14106
14209
  Vaciar
14107
14210
  </button>
@@ -14141,7 +14244,7 @@ class ClxCartComponent {
14141
14244
  <!-- Remove -->
14142
14245
  <div class="absolute top-2 right-2 z-10">
14143
14246
  <button
14144
- clx-button variant="ghost" color="red" size="sm"
14247
+ clx-button type="button" variant="ghost" color="red" size="sm"
14145
14248
  icon="close" [iconOnly]="true" shape="circle"
14146
14249
  (click)="onRemove.emit(item)">
14147
14250
  </button>
@@ -14181,7 +14284,7 @@ class ClxCartComponent {
14181
14284
  <!-- Quantity control -->
14182
14285
  <div class="flex items-center border border-clx-border rounded-xl overflow-hidden">
14183
14286
  <button
14184
- clx-button variant="ghost" color="slate" size="sm"
14287
+ clx-button type="button" variant="ghost" color="slate" size="sm"
14185
14288
  icon="remove" [iconOnly]="true"
14186
14289
  [disabled]="item.quantity <= 1"
14187
14290
  (click)="onQuantityChange.emit({ item, quantity: item.quantity - 1 })">
@@ -14190,7 +14293,7 @@ class ClxCartComponent {
14190
14293
  {{ item.quantity }}
14191
14294
  </span>
14192
14295
  <button
14193
- clx-button variant="ghost" [color]="color()" size="sm"
14296
+ clx-button type="button" variant="ghost" [color]="color()" size="sm"
14194
14297
  icon="add" [iconOnly]="true"
14195
14298
  [disabled]="!item.in_stock || (!!item.max_quantity && item.quantity >= item.max_quantity)"
14196
14299
  (click)="onQuantityChange.emit({ item, quantity: item.quantity + 1 })">
@@ -14231,13 +14334,13 @@ class ClxCartComponent {
14231
14334
  </div>
14232
14335
  @if (coupon()?.valid) {
14233
14336
  <button
14234
- clx-button variant="ghost" color="red" size="sm"
14337
+ clx-button type="button" variant="ghost" color="red" size="sm"
14235
14338
  icon="close" [iconOnly]="true" shape="circle"
14236
14339
  (click)="removeCoupon()">
14237
14340
  </button>
14238
14341
  } @else {
14239
14342
  <button
14240
- clx-button [color]="color()" variant="solid" size="sm" shape="pill"
14343
+ clx-button type="button" [color]="color()" variant="solid" size="sm" shape="pill"
14241
14344
  [disabled]="!_couponCode.trim()"
14242
14345
  (click)="applyCoupon()">
14243
14346
  Aplicar
@@ -14289,7 +14392,7 @@ class ClxCartComponent {
14289
14392
 
14290
14393
  <!-- Checkout -->
14291
14394
  <button
14292
- clx-button [color]="color()" variant="solid" size="lg"
14395
+ clx-button type="button" [color]="color()" variant="solid" size="lg"
14293
14396
  icon="arrow_forward" iconPosition="right" [block]="true"
14294
14397
  (click)="onCheckout.emit()">
14295
14398
  Proceder al pago
@@ -14379,7 +14482,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14379
14482
  <span clx-badge variant="light" [color]="color()" size="sm">{{ _totalUnits() }}</span>
14380
14483
  </div>
14381
14484
  <button
14382
- clx-button variant="ghost" color="red" size="sm" icon="delete_sweep"
14485
+ clx-button type="button" variant="ghost" color="red" size="sm" icon="delete_sweep"
14383
14486
  (click)="onClearCart.emit()">
14384
14487
  Vaciar
14385
14488
  </button>
@@ -14419,7 +14522,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14419
14522
  <!-- Remove -->
14420
14523
  <div class="absolute top-2 right-2 z-10">
14421
14524
  <button
14422
- clx-button variant="ghost" color="red" size="sm"
14525
+ clx-button type="button" variant="ghost" color="red" size="sm"
14423
14526
  icon="close" [iconOnly]="true" shape="circle"
14424
14527
  (click)="onRemove.emit(item)">
14425
14528
  </button>
@@ -14459,7 +14562,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14459
14562
  <!-- Quantity control -->
14460
14563
  <div class="flex items-center border border-clx-border rounded-xl overflow-hidden">
14461
14564
  <button
14462
- clx-button variant="ghost" color="slate" size="sm"
14565
+ clx-button type="button" variant="ghost" color="slate" size="sm"
14463
14566
  icon="remove" [iconOnly]="true"
14464
14567
  [disabled]="item.quantity <= 1"
14465
14568
  (click)="onQuantityChange.emit({ item, quantity: item.quantity - 1 })">
@@ -14468,7 +14571,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14468
14571
  {{ item.quantity }}
14469
14572
  </span>
14470
14573
  <button
14471
- clx-button variant="ghost" [color]="color()" size="sm"
14574
+ clx-button type="button" variant="ghost" [color]="color()" size="sm"
14472
14575
  icon="add" [iconOnly]="true"
14473
14576
  [disabled]="!item.in_stock || (!!item.max_quantity && item.quantity >= item.max_quantity)"
14474
14577
  (click)="onQuantityChange.emit({ item, quantity: item.quantity + 1 })">
@@ -14509,13 +14612,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14509
14612
  </div>
14510
14613
  @if (coupon()?.valid) {
14511
14614
  <button
14512
- clx-button variant="ghost" color="red" size="sm"
14615
+ clx-button type="button" variant="ghost" color="red" size="sm"
14513
14616
  icon="close" [iconOnly]="true" shape="circle"
14514
14617
  (click)="removeCoupon()">
14515
14618
  </button>
14516
14619
  } @else {
14517
14620
  <button
14518
- clx-button [color]="color()" variant="solid" size="sm" shape="pill"
14621
+ clx-button type="button" [color]="color()" variant="solid" size="sm" shape="pill"
14519
14622
  [disabled]="!_couponCode.trim()"
14520
14623
  (click)="applyCoupon()">
14521
14624
  Aplicar
@@ -14567,7 +14670,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
14567
14670
 
14568
14671
  <!-- Checkout -->
14569
14672
  <button
14570
- clx-button [color]="color()" variant="solid" size="lg"
14673
+ clx-button type="button" [color]="color()" variant="solid" size="lg"
14571
14674
  icon="arrow_forward" iconPosition="right" [block]="true"
14572
14675
  (click)="onCheckout.emit()">
14573
14676
  Proceder al pago