codexly-ui 0.10.57 → 0.10.59
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.
- package/fesm2022/codexly-ui.mjs +185 -206
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +28 -10
package/fesm2022/codexly-ui.mjs
CHANGED
|
@@ -13034,43 +13034,18 @@ class ClxPageEmptyComponent {
|
|
|
13034
13034
|
ctaLabel = input('', ...(ngDevMode ? [{ debugName: "ctaLabel" }] : /* istanbul ignore next */ []));
|
|
13035
13035
|
ctaIcon = input('add', ...(ngDevMode ? [{ debugName: "ctaIcon" }] : /* istanbul ignore next */ []));
|
|
13036
13036
|
ctaColor = input(undefined, ...(ngDevMode ? [{ debugName: "ctaColor" }] : /* istanbul ignore next */ []));
|
|
13037
|
-
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
13038
13037
|
_ctaColor = computed(() => this.ctaColor() ?? this._themeSvc.config().primaryColor, ...(ngDevMode ? [{ debugName: "_ctaColor" }] : /* istanbul ignore next */ []));
|
|
13039
13038
|
cta = output();
|
|
13040
|
-
_iconWrap() {
|
|
13041
|
-
const s = this.size();
|
|
13042
|
-
const sz = s === 'sm' ? 'w-12 h-12' : s === 'lg' ? 'w-20 h-20' : 'w-16 h-16';
|
|
13043
|
-
return `${sz} rounded-2xl bg-clx-surface-2 flex items-center justify-center mb-4`;
|
|
13044
|
-
}
|
|
13045
|
-
_iconSize() {
|
|
13046
|
-
const s = this.size();
|
|
13047
|
-
return s === 'sm' ? 'md' : s === 'lg' ? 'xl' : 'lg';
|
|
13048
|
-
}
|
|
13049
|
-
_titleCls() {
|
|
13050
|
-
const s = this.size();
|
|
13051
|
-
return s === 'sm'
|
|
13052
|
-
? 'text-sm font-semibold text-clx-text-label mb-1'
|
|
13053
|
-
: s === 'lg'
|
|
13054
|
-
? 'text-xl font-semibold text-clx-text-label mb-2'
|
|
13055
|
-
: 'text-base font-semibold text-clx-text-label mb-1';
|
|
13056
|
-
}
|
|
13057
|
-
_descCls() {
|
|
13058
|
-
const s = this.size();
|
|
13059
|
-
return `${s === 'lg' ? 'text-sm' : 'text-xs'} text-clx-text-subtle max-w-xs mb-5`;
|
|
13060
|
-
}
|
|
13061
|
-
_ctaCls() {
|
|
13062
|
-
return this.size() === 'sm' ? 'mt-3' : 'mt-5';
|
|
13063
|
-
}
|
|
13064
13039
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxPageEmptyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13065
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageEmptyComponent, isStandalone: true, selector: "clx-page-empty", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, ctaLabel: { classPropertyName: "ctaLabel", publicName: "ctaLabel", isSignal: true, isRequired: false, transformFunction: null }, ctaIcon: { classPropertyName: "ctaIcon", publicName: "ctaIcon", isSignal: true, isRequired: false, transformFunction: null }, ctaColor: { classPropertyName: "ctaColor", publicName: "ctaColor", isSignal: true, isRequired: false, transformFunction: null }
|
|
13066
|
-
<div
|
|
13067
|
-
<span clx-icon [name]="icon()"
|
|
13040
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageEmptyComponent, isStandalone: true, selector: "clx-page-empty", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, ctaLabel: { classPropertyName: "ctaLabel", publicName: "ctaLabel", isSignal: true, isRequired: false, transformFunction: null }, ctaIcon: { classPropertyName: "ctaIcon", publicName: "ctaIcon", isSignal: true, isRequired: false, transformFunction: null }, ctaColor: { classPropertyName: "ctaColor", publicName: "ctaColor", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cta: "cta" }, host: { classAttribute: "flex flex-col items-center justify-center w-full px-6 text-center text-sm" }, ngImport: i0, template: `
|
|
13041
|
+
<div class="w-20 h-20 rounded-2xl bg-clx-surface-2 flex items-center justify-center mb-6">
|
|
13042
|
+
<span clx-icon [name]="icon()" size="xl" class="text-clx-text-faint"></span>
|
|
13068
13043
|
</div>
|
|
13069
13044
|
|
|
13070
|
-
<
|
|
13045
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13071
13046
|
|
|
13072
13047
|
@if (description()) {
|
|
13073
|
-
<p
|
|
13048
|
+
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13074
13049
|
}
|
|
13075
13050
|
|
|
13076
13051
|
@if (ctaLabel()) {
|
|
@@ -13080,7 +13055,6 @@ class ClxPageEmptyComponent {
|
|
|
13080
13055
|
[color]="_ctaColor()"
|
|
13081
13056
|
variant="solid"
|
|
13082
13057
|
[icon]="ctaIcon()"
|
|
13083
|
-
[class]="_ctaCls()"
|
|
13084
13058
|
(click)="cta.emit()">
|
|
13085
13059
|
{{ ctaLabel() }}
|
|
13086
13060
|
</button>
|
|
@@ -13095,16 +13069,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13095
13069
|
imports: [ClxButtonComponent, ClxIconComponent],
|
|
13096
13070
|
encapsulation: ViewEncapsulation.None,
|
|
13097
13071
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13098
|
-
host: { class: 'flex flex-col items-center justify-center w-full px-6 text-center' },
|
|
13072
|
+
host: { class: 'flex flex-col items-center justify-center w-full px-6 text-center text-sm' },
|
|
13099
13073
|
template: `
|
|
13100
|
-
<div
|
|
13101
|
-
<span clx-icon [name]="icon()"
|
|
13074
|
+
<div class="w-20 h-20 rounded-2xl bg-clx-surface-2 flex items-center justify-center mb-6">
|
|
13075
|
+
<span clx-icon [name]="icon()" size="xl" class="text-clx-text-faint"></span>
|
|
13102
13076
|
</div>
|
|
13103
13077
|
|
|
13104
|
-
<
|
|
13078
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13105
13079
|
|
|
13106
13080
|
@if (description()) {
|
|
13107
|
-
<p
|
|
13081
|
+
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13108
13082
|
}
|
|
13109
13083
|
|
|
13110
13084
|
@if (ctaLabel()) {
|
|
@@ -13114,14 +13088,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13114
13088
|
[color]="_ctaColor()"
|
|
13115
13089
|
variant="solid"
|
|
13116
13090
|
[icon]="ctaIcon()"
|
|
13117
|
-
[class]="_ctaCls()"
|
|
13118
13091
|
(click)="cta.emit()">
|
|
13119
13092
|
{{ ctaLabel() }}
|
|
13120
13093
|
</button>
|
|
13121
13094
|
}
|
|
13122
13095
|
`,
|
|
13123
13096
|
}]
|
|
13124
|
-
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], ctaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaLabel", required: false }] }], ctaIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaIcon", required: false }] }], ctaColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaColor", required: false }] }],
|
|
13097
|
+
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], ctaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaLabel", required: false }] }], ctaIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaIcon", required: false }] }], ctaColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "ctaColor", required: false }] }], cta: [{ type: i0.Output, args: ["cta"] }] } });
|
|
13125
13098
|
|
|
13126
13099
|
class ClxTableComponent {
|
|
13127
13100
|
_themeSvc = inject(ClxThemeService);
|
|
@@ -13416,7 +13389,7 @@ class ClxTableComponent {
|
|
|
13416
13389
|
</div>
|
|
13417
13390
|
}
|
|
13418
13391
|
}
|
|
13419
|
-
`, isInline: true, 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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ClxCheckboxComponent, selector: "clx-checkbox", inputs: ["color", "variant", "size", "label", "value", "disabled"] }, { kind: "component", type: ClxInputComponent, selector: "clx-input", inputs: ["label", "placeholder", "type", "color", "hint", "prefixIcon", "suffixIcon", "prefixText", "suffixText", "status", "statusMessage", "size", "value", "disabled", "autocomplete"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxPaginationComponent, selector: "clx-pagination", inputs: ["totalItems", "color", "size", "showPageSize", "pageSizeOptions", "currentPage", "pageSize"], outputs: ["currentPageChange", "pageSizeChange", "pageChange", "sizeChange"] }, { kind: "component", type: ClxPageEmptyComponent, selector: "clx-page-empty", inputs: ["icon", "title", "description", "ctaLabel", "ctaIcon", "ctaColor"
|
|
13392
|
+
`, isInline: true, 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: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ClxCheckboxComponent, selector: "clx-checkbox", inputs: ["color", "variant", "size", "label", "value", "disabled"] }, { kind: "component", type: ClxInputComponent, selector: "clx-input", inputs: ["label", "placeholder", "type", "color", "hint", "prefixIcon", "suffixIcon", "prefixText", "suffixText", "status", "statusMessage", "size", "value", "disabled", "autocomplete"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxPaginationComponent, selector: "clx-pagination", inputs: ["totalItems", "color", "size", "showPageSize", "pageSizeOptions", "currentPage", "pageSize"], outputs: ["currentPageChange", "pageSizeChange", "pageChange", "sizeChange"] }, { kind: "component", type: ClxPageEmptyComponent, selector: "clx-page-empty", inputs: ["icon", "title", "description", "ctaLabel", "ctaIcon", "ctaColor"], outputs: ["cta"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
13420
13393
|
}
|
|
13421
13394
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxTableComponent, decorators: [{
|
|
13422
13395
|
type: Component,
|
|
@@ -13576,13 +13549,13 @@ class ClxPageNotFoundComponent {
|
|
|
13576
13549
|
backLabel = input('Volver al inicio', ...(ngDevMode ? [{ debugName: "backLabel" }] : /* istanbul ignore next */ []));
|
|
13577
13550
|
back = output();
|
|
13578
13551
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxPageNotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13579
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageNotFoundComponent, isStandalone: true, selector: "clx-page-not-found", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center" }, ngImport: i0, template: `
|
|
13552
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageNotFoundComponent, isStandalone: true, selector: "clx-page-not-found", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm" }, ngImport: i0, template: `
|
|
13580
13553
|
<div class="w-20 h-20 rounded-2xl bg-indigo-50 flex items-center justify-center mb-6">
|
|
13581
13554
|
<span clx-icon name="search_off" size="xl" class="text-indigo-400"></span>
|
|
13582
13555
|
</div>
|
|
13583
13556
|
|
|
13584
|
-
<p class="text-
|
|
13585
|
-
<h1 class="text-
|
|
13557
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">404</p>
|
|
13558
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13586
13559
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13587
13560
|
|
|
13588
13561
|
@if (backLabel()) {
|
|
@@ -13606,14 +13579,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13606
13579
|
imports: [ClxButtonComponent, ClxIconComponent],
|
|
13607
13580
|
encapsulation: ViewEncapsulation.None,
|
|
13608
13581
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13609
|
-
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center' },
|
|
13582
|
+
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm' },
|
|
13610
13583
|
template: `
|
|
13611
13584
|
<div class="w-20 h-20 rounded-2xl bg-indigo-50 flex items-center justify-center mb-6">
|
|
13612
13585
|
<span clx-icon name="search_off" size="xl" class="text-indigo-400"></span>
|
|
13613
13586
|
</div>
|
|
13614
13587
|
|
|
13615
|
-
<p class="text-
|
|
13616
|
-
<h1 class="text-
|
|
13588
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">404</p>
|
|
13589
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13617
13590
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13618
13591
|
|
|
13619
13592
|
@if (backLabel()) {
|
|
@@ -13640,13 +13613,13 @@ class ClxPageUnauthorizedComponent {
|
|
|
13640
13613
|
login = output();
|
|
13641
13614
|
back = output();
|
|
13642
13615
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxPageUnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13643
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageUnauthorizedComponent, isStandalone: true, selector: "clx-page-unauthorized", inputs: { code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, loginLabel: { classPropertyName: "loginLabel", publicName: "loginLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { login: "login", back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center" }, ngImport: i0, template: `
|
|
13616
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageUnauthorizedComponent, isStandalone: true, selector: "clx-page-unauthorized", inputs: { code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, loginLabel: { classPropertyName: "loginLabel", publicName: "loginLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { login: "login", back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm" }, ngImport: i0, template: `
|
|
13644
13617
|
<div class="w-20 h-20 rounded-2xl bg-amber-50 flex items-center justify-center mb-6">
|
|
13645
13618
|
<span clx-icon name="lock" size="xl" class="text-amber-400"></span>
|
|
13646
13619
|
</div>
|
|
13647
13620
|
|
|
13648
|
-
<p class="text-
|
|
13649
|
-
<h1 class="text-
|
|
13621
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">{{ code() }}</p>
|
|
13622
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13650
13623
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13651
13624
|
|
|
13652
13625
|
<div class="flex items-center gap-3">
|
|
@@ -13683,14 +13656,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13683
13656
|
imports: [ClxButtonComponent, ClxIconComponent],
|
|
13684
13657
|
encapsulation: ViewEncapsulation.None,
|
|
13685
13658
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13686
|
-
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center' },
|
|
13659
|
+
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm' },
|
|
13687
13660
|
template: `
|
|
13688
13661
|
<div class="w-20 h-20 rounded-2xl bg-amber-50 flex items-center justify-center mb-6">
|
|
13689
13662
|
<span clx-icon name="lock" size="xl" class="text-amber-400"></span>
|
|
13690
13663
|
</div>
|
|
13691
13664
|
|
|
13692
|
-
<p class="text-
|
|
13693
|
-
<h1 class="text-
|
|
13665
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">{{ code() }}</p>
|
|
13666
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13694
13667
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13695
13668
|
|
|
13696
13669
|
<div class="flex items-center gap-3">
|
|
@@ -13730,13 +13703,13 @@ class ClxPageServerErrorComponent {
|
|
|
13730
13703
|
retry = output();
|
|
13731
13704
|
back = output();
|
|
13732
13705
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxPageServerErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13733
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageServerErrorComponent, isStandalone: true, selector: "clx-page-server-error", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, retryLabel: { classPropertyName: "retryLabel", publicName: "retryLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, errorId: { classPropertyName: "errorId", publicName: "errorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { retry: "retry", back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center" }, ngImport: i0, template: `
|
|
13706
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxPageServerErrorComponent, isStandalone: true, selector: "clx-page-server-error", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, retryLabel: { classPropertyName: "retryLabel", publicName: "retryLabel", isSignal: true, isRequired: false, transformFunction: null }, backLabel: { classPropertyName: "backLabel", publicName: "backLabel", isSignal: true, isRequired: false, transformFunction: null }, errorId: { classPropertyName: "errorId", publicName: "errorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { retry: "retry", back: "back" }, host: { classAttribute: "flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm" }, ngImport: i0, template: `
|
|
13734
13707
|
<div class="w-20 h-20 rounded-2xl bg-red-50 flex items-center justify-center mb-6">
|
|
13735
13708
|
<span clx-icon name="error_outline" size="xl" class="text-red-400"></span>
|
|
13736
13709
|
</div>
|
|
13737
13710
|
|
|
13738
|
-
<p class="text-
|
|
13739
|
-
<h1 class="text-
|
|
13711
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">500</p>
|
|
13712
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13740
13713
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13741
13714
|
|
|
13742
13715
|
@if (errorId()) {
|
|
@@ -13777,14 +13750,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
13777
13750
|
imports: [ClxButtonComponent, ClxIconComponent],
|
|
13778
13751
|
encapsulation: ViewEncapsulation.None,
|
|
13779
13752
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13780
|
-
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center' },
|
|
13753
|
+
host: { class: 'flex flex-col items-center justify-center min-h-[60vh] px-6 text-center text-sm' },
|
|
13781
13754
|
template: `
|
|
13782
13755
|
<div class="w-20 h-20 rounded-2xl bg-red-50 flex items-center justify-center mb-6">
|
|
13783
13756
|
<span clx-icon name="error_outline" size="xl" class="text-red-400"></span>
|
|
13784
13757
|
</div>
|
|
13785
13758
|
|
|
13786
|
-
<p class="text-
|
|
13787
|
-
<h1 class="text-
|
|
13759
|
+
<p class="text-[50px] font-black text-clx-text-faint leading-none select-none mb-2">500</p>
|
|
13760
|
+
<h1 class="text-base font-semibold text-clx-text-label mb-2">{{ title() }}</h1>
|
|
13788
13761
|
<p class="text-clx-text-subtle max-w-sm mb-8">{{ description() }}</p>
|
|
13789
13762
|
|
|
13790
13763
|
@if (errorId()) {
|
|
@@ -14271,7 +14244,7 @@ class ClxProductComponent {
|
|
|
14271
14244
|
clxTooltip="Añadir a favoritos"
|
|
14272
14245
|
clxTooltipPosition="left"
|
|
14273
14246
|
[clxTooltipColor]="clxColor()"
|
|
14274
|
-
(click)="addToWishlist.emit(product()!)"
|
|
14247
|
+
(click)="$event.stopPropagation(); addToWishlist.emit(product()!)"
|
|
14275
14248
|
></button>
|
|
14276
14249
|
</div>
|
|
14277
14250
|
|
|
@@ -14292,10 +14265,10 @@ class ClxProductComponent {
|
|
|
14292
14265
|
|
|
14293
14266
|
<!-- Price -->
|
|
14294
14267
|
<div class="flex items-baseline gap-2 mt-2">
|
|
14295
|
-
<span [class]="_priceClass()">{{ _price() | currency:'COP':'
|
|
14268
|
+
<span [class]="_priceClass()">{{ _price() | currency:'COP':'$':'1.0-0' }}</span>
|
|
14296
14269
|
@if (product()?.has_discount && product()?.discount_price) {
|
|
14297
14270
|
<span class="text-sm text-clx-text-subtle line-through">
|
|
14298
|
-
{{ product()?.discount_price | currency:'COP':'
|
|
14271
|
+
{{ product()?.discount_price | currency:'COP':'$':'1.0-0' }}
|
|
14299
14272
|
</span>
|
|
14300
14273
|
}
|
|
14301
14274
|
</div>
|
|
@@ -14313,7 +14286,7 @@ class ClxProductComponent {
|
|
|
14313
14286
|
iconPosition="left"
|
|
14314
14287
|
[disabled]="_disabled()"
|
|
14315
14288
|
[block]="true"
|
|
14316
|
-
(click)="_hasMultipleOptions() ? viewOptions.emit(product()!) : addToCart.emit(product()!)"
|
|
14289
|
+
(click)="$event.stopPropagation(); _hasMultipleOptions() ? viewOptions.emit(product()!) : addToCart.emit(product()!)"
|
|
14317
14290
|
>
|
|
14318
14291
|
{{ _hasMultipleOptions() ? 'Ver opciones' : 'Añadir al carrito' }}
|
|
14319
14292
|
</button>
|
|
@@ -14406,7 +14379,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14406
14379
|
clxTooltip="Añadir a favoritos"
|
|
14407
14380
|
clxTooltipPosition="left"
|
|
14408
14381
|
[clxTooltipColor]="clxColor()"
|
|
14409
|
-
(click)="addToWishlist.emit(product()!)"
|
|
14382
|
+
(click)="$event.stopPropagation(); addToWishlist.emit(product()!)"
|
|
14410
14383
|
></button>
|
|
14411
14384
|
</div>
|
|
14412
14385
|
|
|
@@ -14427,10 +14400,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14427
14400
|
|
|
14428
14401
|
<!-- Price -->
|
|
14429
14402
|
<div class="flex items-baseline gap-2 mt-2">
|
|
14430
|
-
<span [class]="_priceClass()">{{ _price() | currency:'COP':'
|
|
14403
|
+
<span [class]="_priceClass()">{{ _price() | currency:'COP':'$':'1.0-0' }}</span>
|
|
14431
14404
|
@if (product()?.has_discount && product()?.discount_price) {
|
|
14432
14405
|
<span class="text-sm text-clx-text-subtle line-through">
|
|
14433
|
-
{{ product()?.discount_price | currency:'COP':'
|
|
14406
|
+
{{ product()?.discount_price | currency:'COP':'$':'1.0-0' }}
|
|
14434
14407
|
</span>
|
|
14435
14408
|
}
|
|
14436
14409
|
</div>
|
|
@@ -14448,7 +14421,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14448
14421
|
iconPosition="left"
|
|
14449
14422
|
[disabled]="_disabled()"
|
|
14450
14423
|
[block]="true"
|
|
14451
|
-
(click)="_hasMultipleOptions() ? viewOptions.emit(product()!) : addToCart.emit(product()!)"
|
|
14424
|
+
(click)="$event.stopPropagation(); _hasMultipleOptions() ? viewOptions.emit(product()!) : addToCart.emit(product()!)"
|
|
14452
14425
|
>
|
|
14453
14426
|
{{ _hasMultipleOptions() ? 'Ver opciones' : 'Añadir al carrito' }}
|
|
14454
14427
|
</button>
|
|
@@ -14468,6 +14441,9 @@ class ClxProductDetailComponent {
|
|
|
14468
14441
|
clxColor = input('indigo', ...(ngDevMode ? [{ debugName: "clxColor" }] : /* istanbul ignore next */ []));
|
|
14469
14442
|
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
14470
14443
|
currency = input('COP', ...(ngDevMode ? [{ debugName: "currency" }] : /* istanbul ignore next */ []));
|
|
14444
|
+
/** Hides the tabs (Características/Especificaciones/Descripción) and the Reviews section —
|
|
14445
|
+
* for contexts like a quick-view modal where only the gallery + spec selector + CTA matter. */
|
|
14446
|
+
compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : /* istanbul ignore next */ []));
|
|
14471
14447
|
addToCart = output();
|
|
14472
14448
|
buyNow = output();
|
|
14473
14449
|
wishlist = output();
|
|
@@ -14556,7 +14532,7 @@ class ClxProductDetailComponent {
|
|
|
14556
14532
|
specsLeft(specs) { return specs.slice(0, Math.ceil(specs.length / 2)); }
|
|
14557
14533
|
specsRight(specs) { return specs.slice(Math.ceil(specs.length / 2)); }
|
|
14558
14534
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14559
|
-
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 }, initialVariationId: { classPropertyName: "initialVariationId", publicName: "initialVariationId", 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 } }, outputs: { addToCart: "addToCart", buyNow: "buyNow", wishlist: "wishlist", variationChange: "variationChange" }, 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 md: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 md:grid-cols-2 gap-8 md:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2014 each column sizes to its own content (no forced equal\n height, no position:sticky). A `sticky` gallery reads great in isolation, but a host app\n that already has its own `position: sticky` header (a full-width top bar, as opposed to\n this library's own `clx-app-layout` sidebar, which is `fixed` and never competes) forces\n the browser to keep recomputing both stickies' viewport-relative offsets together on every\n resize \u2014 confirmed as the source of a persistent resize-lag bug in codexly-store's product\n page. Not worth reintroducing until sticky positioning is made robust to an arbitrary host\n header. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"flex flex-col gap-3\">\n <div class=\"relative aspect-4/3\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track i; let i = $index) {\n <ng-template clxSlide>\n <div class=\"w-full h-full p-5 sm:p-12.5 md:p-5 lg:p-12.5\">\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-contain\"\n [loading]=\"i === 0 ? 'eager' : 'lazy'\"\n [attr.fetchpriority]=\"i === 0 ? 'high' : null\" />\n </div>\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=\"Agregar a favoritos\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\"\n (click)=\"wishlist.emit()\">\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 i; 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-2.5\">\n\n <!-- Stock status -->\n @if (v) {\n <span clx-badge [variant]=\"v.in_stock ? 'light' : 'solid'\" [color]=\"v.in_stock ? clxColor() : 'green'\" size=\"sm\" shape=\"pill\">\n @if (v.in_stock) {\n @if (v.stock_quantity != null) {\n {{ v.stock_quantity }} en stock\n } @else {\n En stock\n }\n } @else {\n Sin stock\n }\n </span>\n }\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-1\">\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-sm 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\">{{ v?.name || p.product_name }}</h1>\n @if (p.product_detail) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ p.product_detail }}</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>\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-2xl 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-base 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 </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) \u2014 opciones no disponibles\n para la combinaci\u00F3n actual (ej. Talla S con Color Rojo) se ocultan por completo en vez\n de mostrarse deshabilitadas; reaparecen si el usuario cambia a una combinaci\u00F3n donde s\u00ED\n aplican, ya que isOptionAvailable() se reeval\u00FAa contra selectedSpecs() en cada cambio. -->\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button\n type=\"button\"\n class=\"w-7 h-7 rounded-full border-2 transition-[transform,box-shadow] shrink-0 cursor-pointer\"\n [class]=\"isSpecSelected(specType.id, opt.id) ? 'scale-110 shadow-md' : 'opacity-90 hover:opacity-100'\"\n [style.background-color]=\"opt.value\"\n [style.border-color]=\"isSpecSelected(specType.id, opt.id) ? 'var(--clx-text-label, #111)' : 'transparent'\"\n [clxTooltip]=\"opt.label ?? opt.value\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.label ?? opt.value }}\n </button>\n }\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\" (click)=\"_emitBuyNow()\">Comprar ahora</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\" (click)=\"_emitAddToCart()\">Agrega al carrito</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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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\">\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", "textColor", "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 });
|
|
14535
|
+
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 }, initialVariationId: { classPropertyName: "initialVariationId", publicName: "initialVariationId", 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 }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { addToCart: "addToCart", buyNow: "buyNow", wishlist: "wishlist", variationChange: "variationChange" }, 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 md: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 md:grid-cols-2 gap-8 md:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2014 each column sizes to its own content (no forced equal\n height, no position:sticky). A `sticky` gallery reads great in isolation, but a host app\n that already has its own `position: sticky` header (a full-width top bar, as opposed to\n this library's own `clx-app-layout` sidebar, which is `fixed` and never competes) forces\n the browser to keep recomputing both stickies' viewport-relative offsets together on every\n resize \u2014 confirmed as the source of a persistent resize-lag bug in codexly-store's product\n page. Not worth reintroducing until sticky positioning is made robust to an arbitrary host\n header. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"flex flex-col gap-3\">\n <div class=\"relative aspect-4/3\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track i; let i = $index) {\n <ng-template clxSlide>\n <div class=\"w-full h-full p-5 sm:p-12.5 md:p-5 lg:p-12.5\">\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-contain\"\n [loading]=\"i === 0 ? 'eager' : 'lazy'\"\n [attr.fetchpriority]=\"i === 0 ? 'high' : null\" />\n </div>\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=\"Agregar a favoritos\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\"\n (click)=\"wishlist.emit()\">\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 i; 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-2.5\">\n\n <!-- Stock status -->\n @if (v) {\n <span clx-badge [variant]=\"v.in_stock ? 'light' : 'solid'\" [color]=\"v.in_stock ? clxColor() : 'green'\" size=\"sm\" shape=\"pill\">\n @if (v.in_stock) {\n @if (v.stock_quantity != null) {\n {{ v.stock_quantity }} en stock\n } @else {\n En stock\n }\n } @else {\n Sin stock\n }\n </span>\n }\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-1\">\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-sm 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\">{{ v?.name || p.product_name }}</h1>\n @if (p.product_detail) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ p.product_detail }}</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>\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-2xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'$':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-base text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'$':'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 </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) \u2014 opciones no disponibles\n para la combinaci\u00F3n actual (ej. Talla S con Color Rojo) se ocultan por completo en vez\n de mostrarse deshabilitadas; reaparecen si el usuario cambia a una combinaci\u00F3n donde s\u00ED\n aplican, ya que isOptionAvailable() se reeval\u00FAa contra selectedSpecs() en cada cambio. -->\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button\n type=\"button\"\n class=\"w-7 h-7 rounded-full border-2 transition-[transform,box-shadow] shrink-0 cursor-pointer\"\n [class]=\"isSpecSelected(specType.id, opt.id) ? 'scale-110 shadow-md' : 'opacity-90 hover:opacity-100'\"\n [style.background-color]=\"opt.value\"\n [style.border-color]=\"isSpecSelected(specType.id, opt.id) ? 'var(--clx-text-label, #111)' : 'transparent'\"\n [clxTooltip]=\"opt.label ?? opt.value\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.label ?? opt.value }}\n </button>\n }\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\" (click)=\"_emitBuyNow()\">Comprar ahora</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\" (click)=\"_emitAddToCart()\">Agrega al carrito</button>\n </div>\n\n </div>\n </div>\n\n @if (!compact()) {\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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\">\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\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", "textColor", "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 });
|
|
14560
14536
|
}
|
|
14561
14537
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, decorators: [{
|
|
14562
14538
|
type: Component,
|
|
@@ -14578,8 +14554,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14578
14554
|
ClxTooltipDirective,
|
|
14579
14555
|
ClxListComponent,
|
|
14580
14556
|
ClxListItemComponent,
|
|
14581
|
-
], 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 md: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 md:grid-cols-2 gap-8 md:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2014 each column sizes to its own content (no forced equal\n height, no position:sticky). A `sticky` gallery reads great in isolation, but a host app\n that already has its own `position: sticky` header (a full-width top bar, as opposed to\n this library's own `clx-app-layout` sidebar, which is `fixed` and never competes) forces\n the browser to keep recomputing both stickies' viewport-relative offsets together on every\n resize \u2014 confirmed as the source of a persistent resize-lag bug in codexly-store's product\n page. Not worth reintroducing until sticky positioning is made robust to an arbitrary host\n header. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"flex flex-col gap-3\">\n <div class=\"relative aspect-4/3\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track i; let i = $index) {\n <ng-template clxSlide>\n <div class=\"w-full h-full p-5 sm:p-12.5 md:p-5 lg:p-12.5\">\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-contain\"\n [loading]=\"i === 0 ? 'eager' : 'lazy'\"\n [attr.fetchpriority]=\"i === 0 ? 'high' : null\" />\n </div>\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=\"Agregar a favoritos\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\"\n (click)=\"wishlist.emit()\">\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 i; 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-2.5\">\n\n <!-- Stock status -->\n @if (v) {\n <span clx-badge [variant]=\"v.in_stock ? 'light' : 'solid'\" [color]=\"v.in_stock ? clxColor() : 'green'\" size=\"sm\" shape=\"pill\">\n @if (v.in_stock) {\n @if (v.stock_quantity != null) {\n {{ v.stock_quantity }} en stock\n } @else {\n En stock\n }\n } @else {\n Sin stock\n }\n </span>\n }\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-1\">\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-sm 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\">{{ v?.name || p.product_name }}</h1>\n @if (p.product_detail) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ p.product_detail }}</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>\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-2xl 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-base 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 </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) \u2014 opciones no disponibles\n para la combinaci\u00F3n actual (ej. Talla S con Color Rojo) se ocultan por completo en vez\n de mostrarse deshabilitadas; reaparecen si el usuario cambia a una combinaci\u00F3n donde s\u00ED\n aplican, ya que isOptionAvailable() se reeval\u00FAa contra selectedSpecs() en cada cambio. -->\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button\n type=\"button\"\n class=\"w-7 h-7 rounded-full border-2 transition-[transform,box-shadow] shrink-0 cursor-pointer\"\n [class]=\"isSpecSelected(specType.id, opt.id) ? 'scale-110 shadow-md' : 'opacity-90 hover:opacity-100'\"\n [style.background-color]=\"opt.value\"\n [style.border-color]=\"isSpecSelected(specType.id, opt.id) ? 'var(--clx-text-label, #111)' : 'transparent'\"\n [clxTooltip]=\"opt.label ?? opt.value\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.label ?? opt.value }}\n </button>\n }\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\" (click)=\"_emitBuyNow()\">Comprar ahora</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\" (click)=\"_emitAddToCart()\">Agrega al carrito</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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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\">\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" }]
|
|
14582
|
-
}], ctorParameters: () => [], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }], initialVariationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialVariationId", 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 }] }], addToCart: [{ type: i0.Output, args: ["addToCart"] }], buyNow: [{ type: i0.Output, args: ["buyNow"] }], wishlist: [{ type: i0.Output, args: ["wishlist"] }], variationChange: [{ type: i0.Output, args: ["variationChange"] }], _carousel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClxCarouselComponent), { isSignal: true }] }] } });
|
|
14557
|
+
], 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 md: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 md:grid-cols-2 gap-8 md:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2014 each column sizes to its own content (no forced equal\n height, no position:sticky). A `sticky` gallery reads great in isolation, but a host app\n that already has its own `position: sticky` header (a full-width top bar, as opposed to\n this library's own `clx-app-layout` sidebar, which is `fixed` and never competes) forces\n the browser to keep recomputing both stickies' viewport-relative offsets together on every\n resize \u2014 confirmed as the source of a persistent resize-lag bug in codexly-store's product\n page. Not worth reintroducing until sticky positioning is made robust to an arbitrary host\n header. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"flex flex-col gap-3\">\n <div class=\"relative aspect-4/3\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track i; let i = $index) {\n <ng-template clxSlide>\n <div class=\"w-full h-full p-5 sm:p-12.5 md:p-5 lg:p-12.5\">\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-contain\"\n [loading]=\"i === 0 ? 'eager' : 'lazy'\"\n [attr.fetchpriority]=\"i === 0 ? 'high' : null\" />\n </div>\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=\"Agregar a favoritos\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\"\n (click)=\"wishlist.emit()\">\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 i; 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-2.5\">\n\n <!-- Stock status -->\n @if (v) {\n <span clx-badge [variant]=\"v.in_stock ? 'light' : 'solid'\" [color]=\"v.in_stock ? clxColor() : 'green'\" size=\"sm\" shape=\"pill\">\n @if (v.in_stock) {\n @if (v.stock_quantity != null) {\n {{ v.stock_quantity }} en stock\n } @else {\n En stock\n }\n } @else {\n Sin stock\n }\n </span>\n }\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-1\">\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-sm 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\">{{ v?.name || p.product_name }}</h1>\n @if (p.product_detail) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ p.product_detail }}</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>\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-2xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'$':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-base text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'$':'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 </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) \u2014 opciones no disponibles\n para la combinaci\u00F3n actual (ej. Talla S con Color Rojo) se ocultan por completo en vez\n de mostrarse deshabilitadas; reaparecen si el usuario cambia a una combinaci\u00F3n donde s\u00ED\n aplican, ya que isOptionAvailable() se reeval\u00FAa contra selectedSpecs() en cada cambio. -->\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button\n type=\"button\"\n class=\"w-7 h-7 rounded-full border-2 transition-[transform,box-shadow] shrink-0 cursor-pointer\"\n [class]=\"isSpecSelected(specType.id, opt.id) ? 'scale-110 shadow-md' : 'opacity-90 hover:opacity-100'\"\n [style.background-color]=\"opt.value\"\n [style.border-color]=\"isSpecSelected(specType.id, opt.id) ? 'var(--clx-text-label, #111)' : 'transparent'\"\n [clxTooltip]=\"opt.label ?? opt.value\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\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 @if (isOptionAvailable(specType.id, opt.id)) {\n <button clx-button\n type=\"button\"\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.label ?? opt.value }}\n </button>\n }\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\" (click)=\"_emitBuyNow()\">Comprar ahora</button>\n <button clx-button type=\"button\" variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\" (click)=\"_emitAddToCart()\">Agrega al carrito</button>\n </div>\n\n </div>\n </div>\n\n @if (!compact()) {\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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 [icon]=\"spec.icon ?? ''\">\n <div clxContent>\n <p class=\"text-sm font-medium text-clx-text-label\">{{ spec.name }}:</p>\n <p class=\"text-sm text-clx-text-muted mt-0.5\">{{ spec.value }}</p>\n </div>\n </clx-list-item>\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\">\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\n </div>\n}\n" }]
|
|
14558
|
+
}], ctorParameters: () => [], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }], initialVariationId: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialVariationId", 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 }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], addToCart: [{ type: i0.Output, args: ["addToCart"] }], buyNow: [{ type: i0.Output, args: ["buyNow"] }], wishlist: [{ type: i0.Output, args: ["wishlist"] }], variationChange: [{ type: i0.Output, args: ["variationChange"] }], _carousel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClxCarouselComponent), { isSignal: true }] }] } });
|
|
14559
|
+
|
|
14560
|
+
class ClxProductQuickViewComponent {
|
|
14561
|
+
ref = inject(CLX_MODAL_REF, { optional: true });
|
|
14562
|
+
data = inject(CLX_MODAL_DATA, { optional: true });
|
|
14563
|
+
_onAddToCart(event) {
|
|
14564
|
+
this.ref?.close(event);
|
|
14565
|
+
}
|
|
14566
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductQuickViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14567
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.15", type: ClxProductQuickViewComponent, isStandalone: true, selector: "clx-product-quick-view", ngImport: i0, template: `
|
|
14568
|
+
<clx-modal>
|
|
14569
|
+
<div clx-modal-title>{{ data?.product?.product_name }}</div>
|
|
14570
|
+
|
|
14571
|
+
<clx-product-detail
|
|
14572
|
+
[compact]="true"
|
|
14573
|
+
[product]="data?.product ?? null"
|
|
14574
|
+
[initialVariationId]="data?.initialVariationId ?? null"
|
|
14575
|
+
[clxColor]="data?.clxColor ?? 'indigo'"
|
|
14576
|
+
[currency]="data?.currency ?? 'COP'"
|
|
14577
|
+
(addToCart)="_onAddToCart($event)">
|
|
14578
|
+
</clx-product-detail>
|
|
14579
|
+
</clx-modal>
|
|
14580
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ClxModalComponent, selector: "clx-modal", inputs: ["size", "showClose", "confirmButton", "cancelButton", "showCancelButton"], outputs: ["confirmClick", "cancelClick"] }, { kind: "component", type: ClxProductDetailComponent, selector: "clx-product-detail", inputs: ["product", "initialVariationId", "clxColor", "loading", "currency", "compact"], outputs: ["addToCart", "buyNow", "wishlist", "variationChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14581
|
+
}
|
|
14582
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductQuickViewComponent, decorators: [{
|
|
14583
|
+
type: Component,
|
|
14584
|
+
args: [{
|
|
14585
|
+
selector: 'clx-product-quick-view',
|
|
14586
|
+
standalone: true,
|
|
14587
|
+
imports: [ClxModalComponent, ClxProductDetailComponent],
|
|
14588
|
+
template: `
|
|
14589
|
+
<clx-modal>
|
|
14590
|
+
<div clx-modal-title>{{ data?.product?.product_name }}</div>
|
|
14591
|
+
|
|
14592
|
+
<clx-product-detail
|
|
14593
|
+
[compact]="true"
|
|
14594
|
+
[product]="data?.product ?? null"
|
|
14595
|
+
[initialVariationId]="data?.initialVariationId ?? null"
|
|
14596
|
+
[clxColor]="data?.clxColor ?? 'indigo'"
|
|
14597
|
+
[currency]="data?.currency ?? 'COP'"
|
|
14598
|
+
(addToCart)="_onAddToCart($event)">
|
|
14599
|
+
</clx-product-detail>
|
|
14600
|
+
</clx-modal>
|
|
14601
|
+
`,
|
|
14602
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
14603
|
+
}]
|
|
14604
|
+
}] });
|
|
14583
14605
|
|
|
14584
14606
|
const WISHLIST_PAGE_SIZE_DEFAULT = 6;
|
|
14585
14607
|
const WISHLIST_SORT_OPTIONS = [
|
|
@@ -14709,22 +14731,19 @@ class ClxWishlistComponent {
|
|
|
14709
14731
|
<!-- ── Info Bar ─────────────────────────────────────────────────────── -->
|
|
14710
14732
|
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
|
|
14711
14733
|
<div class="flex items-center gap-2">
|
|
14712
|
-
<
|
|
14713
|
-
<span
|
|
14714
|
-
<span clx-badge variant="light" [color]="color()" size="sm">items</span>
|
|
14715
|
-
<span class="text-clx-text-muted text-sm">to your wishlist</span>
|
|
14734
|
+
<h2 class="text-base font-semibold text-clx-text-label">Productos</h2>
|
|
14735
|
+
<span clx-badge variant="light" [color]="color()" size="sm">{{ _totalItems() }}</span>
|
|
14716
14736
|
</div>
|
|
14717
14737
|
<button
|
|
14718
14738
|
clx-button
|
|
14719
14739
|
type="button"
|
|
14720
14740
|
variant="light"
|
|
14721
14741
|
[color]="color()"
|
|
14722
|
-
size="sm"
|
|
14723
14742
|
icon="arrow_forward"
|
|
14724
14743
|
iconPosition="right"
|
|
14725
14744
|
[disabled]="_totalItems() === 0"
|
|
14726
14745
|
(click)="handleCheckoutAll()"
|
|
14727
|
-
>
|
|
14746
|
+
>Agregar todo al carrito</button>
|
|
14728
14747
|
</div>
|
|
14729
14748
|
|
|
14730
14749
|
<!-- ── List ─────────────────────────────────────────────────────────── -->
|
|
@@ -14748,11 +14767,14 @@ class ClxWishlistComponent {
|
|
|
14748
14767
|
|
|
14749
14768
|
} @else if (_pagedItems().length === 0) {
|
|
14750
14769
|
|
|
14751
|
-
<
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14770
|
+
<clx-page-empty
|
|
14771
|
+
icon="favorite"
|
|
14772
|
+
title="Sin favoritos"
|
|
14773
|
+
description="No tienes productos guardados."
|
|
14774
|
+
[ctaColor]="color()"
|
|
14775
|
+
ctaIcon="storefront"
|
|
14776
|
+
ctaLabel="Ir a la tienda">
|
|
14777
|
+
</clx-page-empty>
|
|
14756
14778
|
|
|
14757
14779
|
} @else {
|
|
14758
14780
|
|
|
@@ -14796,10 +14818,10 @@ class ClxWishlistComponent {
|
|
|
14796
14818
|
|
|
14797
14819
|
<!-- Price -->
|
|
14798
14820
|
<div class="flex items-baseline gap-2 mt-2">
|
|
14799
|
-
<span [class]="_priceClass">{{ (item.sale_price ?? item.product_sale_price) | currency:'COP':'
|
|
14821
|
+
<span [class]="_priceClass">{{ (item.sale_price ?? item.product_sale_price) | currency:'COP':'$':'1.0-0' }}</span>
|
|
14800
14822
|
@if (item.has_discount && item.discount_price) {
|
|
14801
14823
|
<span class="text-sm text-clx-text-subtle line-through">
|
|
14802
|
-
{{ item.discount_price | currency:'COP':'
|
|
14824
|
+
{{ item.discount_price | currency:'COP':'$':'1.0-0' }}
|
|
14803
14825
|
</span>
|
|
14804
14826
|
}
|
|
14805
14827
|
</div>
|
|
@@ -14861,7 +14883,7 @@ class ClxWishlistComponent {
|
|
|
14861
14883
|
}
|
|
14862
14884
|
|
|
14863
14885
|
</div>
|
|
14864
|
-
`, isInline: true, 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", "textColor", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type:
|
|
14886
|
+
`, isInline: true, 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", "textColor", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxPaginationComponent, selector: "clx-pagination", inputs: ["totalItems", "color", "size", "showPageSize", "pageSizeOptions", "currentPage", "pageSize"], outputs: ["currentPageChange", "pageSizeChange", "pageChange", "sizeChange"] }, { kind: "component", type: ClxInputComponent, selector: "clx-input", inputs: ["label", "placeholder", "type", "color", "hint", "prefixIcon", "suffixIcon", "prefixText", "suffixText", "status", "statusMessage", "size", "value", "disabled", "autocomplete"] }, { kind: "component", type: ClxSelectComponent, selector: "clx-select", inputs: ["label", "placeholder", "options", "multiple", "searchable", "searchPlaceholder", "activeColor", "size", "hint", "errorMessage", "disabled", "async", "loadOptions", "debounceMs", "minChars"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }, { kind: "component", type: ClxPageEmptyComponent, selector: "clx-page-empty", inputs: ["icon", "title", "description", "ctaLabel", "ctaIcon", "ctaColor"], outputs: ["cta"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
14865
14887
|
}
|
|
14866
14888
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxWishlistComponent, decorators: [{
|
|
14867
14889
|
type: Component,
|
|
@@ -14873,12 +14895,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14873
14895
|
FormsModule,
|
|
14874
14896
|
ClxButtonComponent,
|
|
14875
14897
|
ClxBadgeComponent,
|
|
14876
|
-
ClxIconComponent,
|
|
14877
14898
|
ClxSkeletonComponent,
|
|
14878
14899
|
ClxPaginationComponent,
|
|
14879
14900
|
ClxInputComponent,
|
|
14880
14901
|
ClxSelectComponent,
|
|
14881
|
-
ClxTooltipDirective
|
|
14902
|
+
ClxTooltipDirective,
|
|
14903
|
+
ClxPageEmptyComponent
|
|
14882
14904
|
],
|
|
14883
14905
|
template: `
|
|
14884
14906
|
<div class="flex flex-col gap-6">
|
|
@@ -14911,22 +14933,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14911
14933
|
<!-- ── Info Bar ─────────────────────────────────────────────────────── -->
|
|
14912
14934
|
<div class="flex flex-col sm:flex-row sm:items-center justify-between gap-3">
|
|
14913
14935
|
<div class="flex items-center gap-2">
|
|
14914
|
-
<
|
|
14915
|
-
<span
|
|
14916
|
-
<span clx-badge variant="light" [color]="color()" size="sm">items</span>
|
|
14917
|
-
<span class="text-clx-text-muted text-sm">to your wishlist</span>
|
|
14936
|
+
<h2 class="text-base font-semibold text-clx-text-label">Productos</h2>
|
|
14937
|
+
<span clx-badge variant="light" [color]="color()" size="sm">{{ _totalItems() }}</span>
|
|
14918
14938
|
</div>
|
|
14919
14939
|
<button
|
|
14920
14940
|
clx-button
|
|
14921
14941
|
type="button"
|
|
14922
14942
|
variant="light"
|
|
14923
14943
|
[color]="color()"
|
|
14924
|
-
size="sm"
|
|
14925
14944
|
icon="arrow_forward"
|
|
14926
14945
|
iconPosition="right"
|
|
14927
14946
|
[disabled]="_totalItems() === 0"
|
|
14928
14947
|
(click)="handleCheckoutAll()"
|
|
14929
|
-
>
|
|
14948
|
+
>Agregar todo al carrito</button>
|
|
14930
14949
|
</div>
|
|
14931
14950
|
|
|
14932
14951
|
<!-- ── List ─────────────────────────────────────────────────────────── -->
|
|
@@ -14950,11 +14969,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14950
14969
|
|
|
14951
14970
|
} @else if (_pagedItems().length === 0) {
|
|
14952
14971
|
|
|
14953
|
-
<
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
|
|
14957
|
-
|
|
14972
|
+
<clx-page-empty
|
|
14973
|
+
icon="favorite"
|
|
14974
|
+
title="Sin favoritos"
|
|
14975
|
+
description="No tienes productos guardados."
|
|
14976
|
+
[ctaColor]="color()"
|
|
14977
|
+
ctaIcon="storefront"
|
|
14978
|
+
ctaLabel="Ir a la tienda">
|
|
14979
|
+
</clx-page-empty>
|
|
14958
14980
|
|
|
14959
14981
|
} @else {
|
|
14960
14982
|
|
|
@@ -14998,10 +15020,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14998
15020
|
|
|
14999
15021
|
<!-- Price -->
|
|
15000
15022
|
<div class="flex items-baseline gap-2 mt-2">
|
|
15001
|
-
<span [class]="_priceClass">{{ (item.sale_price ?? item.product_sale_price) | currency:'COP':'
|
|
15023
|
+
<span [class]="_priceClass">{{ (item.sale_price ?? item.product_sale_price) | currency:'COP':'$':'1.0-0' }}</span>
|
|
15002
15024
|
@if (item.has_discount && item.discount_price) {
|
|
15003
15025
|
<span class="text-sm text-clx-text-subtle line-through">
|
|
15004
|
-
{{ item.discount_price | currency:'COP':'
|
|
15026
|
+
{{ item.discount_price | currency:'COP':'$':'1.0-0' }}
|
|
15005
15027
|
</span>
|
|
15006
15028
|
}
|
|
15007
15029
|
</div>
|
|
@@ -15141,11 +15163,14 @@ class ClxCartComponent {
|
|
|
15141
15163
|
<!-- ── Empty ───────────────────────────────────────────────────────────────── -->
|
|
15142
15164
|
} @else if (items().length === 0) {
|
|
15143
15165
|
|
|
15144
|
-
<
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15166
|
+
<clx-page-empty
|
|
15167
|
+
icon="remove_shopping_cart"
|
|
15168
|
+
title="Carrito vacio"
|
|
15169
|
+
description="Tu carrito esta vacio. Agrega productos para continuar."
|
|
15170
|
+
[ctaColor]="color()"
|
|
15171
|
+
ctaIcon="storefront"
|
|
15172
|
+
ctaLabel="Ir a la tienda">
|
|
15173
|
+
</clx-page-empty>
|
|
15149
15174
|
|
|
15150
15175
|
<!-- ── Main layout ─────────────────────────────────────────────────────────── -->
|
|
15151
15176
|
} @else {
|
|
@@ -15158,19 +15183,19 @@ class ClxCartComponent {
|
|
|
15158
15183
|
<!-- Top bar -->
|
|
15159
15184
|
<div class="flex items-center justify-between">
|
|
15160
15185
|
<div class="flex items-center gap-2">
|
|
15161
|
-
<h2 class="text-base font-semibold text-clx-text-label">
|
|
15186
|
+
<h2 class="text-base font-semibold text-clx-text-label">Productos</h2>
|
|
15162
15187
|
<span clx-badge variant="light" [color]="color()" size="sm">{{ _totalUnits() }}</span>
|
|
15163
15188
|
</div>
|
|
15164
15189
|
<button
|
|
15165
|
-
clx-button type="button" variant="
|
|
15190
|
+
clx-button type="button" variant="light" color="red" icon="delete"
|
|
15166
15191
|
(click)="onClearCart.emit()">
|
|
15167
|
-
Vaciar
|
|
15192
|
+
Vaciar carrito
|
|
15168
15193
|
</button>
|
|
15169
15194
|
</div>
|
|
15170
15195
|
|
|
15171
15196
|
<!-- Item cards -->
|
|
15172
15197
|
@for (item of items(); track item.id) {
|
|
15173
|
-
<article class="bg-clx-surface rounded-2xl shadow-sm flex gap-0 overflow-hidden group transition-[box-shadow,transform] duration-300 hover:shadow-
|
|
15198
|
+
<article class="bg-clx-surface rounded-2xl shadow-sm flex gap-0 overflow-hidden group transition-[box-shadow,transform] duration-300 hover:shadow-md hover:-translate-y-0.5">
|
|
15174
15199
|
|
|
15175
15200
|
<!-- Image — fixed square -->
|
|
15176
15201
|
<div class="relative shrink-0 w-28 h-28 lg:w-36 lg:h-36 overflow-hidden bg-clx-surface-2">
|
|
@@ -15215,54 +15240,29 @@ class ClxCartComponent {
|
|
|
15215
15240
|
<p class="text-xs font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
|
|
15216
15241
|
</div>
|
|
15217
15242
|
|
|
15218
|
-
@if (item.rating) {
|
|
15219
|
-
<div class="flex items-center gap-1.5">
|
|
15220
|
-
<clx-rating [value]="item.rating" [max]="5" color="amber" />
|
|
15221
|
-
@if (item.review_count) {
|
|
15222
|
-
<span class="text-xs text-clx-text-subtle">({{ item.review_count }})</span>
|
|
15223
|
-
}
|
|
15224
|
-
</div>
|
|
15225
|
-
}
|
|
15226
|
-
|
|
15227
15243
|
<!-- Price + Quantity row -->
|
|
15228
15244
|
<div class="flex items-center justify-between gap-2 mt-auto flex-wrap">
|
|
15229
15245
|
|
|
15230
15246
|
<!-- Price -->
|
|
15231
15247
|
<div class="flex items-baseline gap-1.5">
|
|
15232
15248
|
<span class="text-base font-bold text-clx-text-label">
|
|
15233
|
-
{{ item.unit_price | currency:'COP':'
|
|
15249
|
+
{{ item.unit_price | currency:'COP':'$':'1.0-0' }}
|
|
15234
15250
|
</span>
|
|
15235
15251
|
@if (item.has_discount && item.original_price) {
|
|
15236
15252
|
<span class="text-xs text-clx-text-subtle line-through">
|
|
15237
|
-
{{ item.original_price | currency:'COP':'
|
|
15253
|
+
{{ item.original_price | currency:'COP':'$':'1.0-0' }}
|
|
15238
15254
|
</span>
|
|
15239
15255
|
}
|
|
15240
15256
|
</div>
|
|
15241
15257
|
|
|
15242
15258
|
<!-- Quantity control -->
|
|
15243
|
-
<
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
<span class="w-8 text-center text-sm font-semibold text-clx-text-label select-none">
|
|
15251
|
-
{{ item.quantity }}
|
|
15252
|
-
</span>
|
|
15253
|
-
<button
|
|
15254
|
-
clx-button type="button" variant="ghost" [color]="color()" size="sm"
|
|
15255
|
-
icon="add" [iconOnly]="true"
|
|
15256
|
-
[disabled]="!item.in_stock || (!!item.max_quantity && item.quantity >= item.max_quantity)"
|
|
15257
|
-
(click)="onQuantityChange.emit({ item, quantity: item.quantity + 1 })">
|
|
15258
|
-
</button>
|
|
15259
|
-
</div>
|
|
15260
|
-
|
|
15261
|
-
<!-- Line total -->
|
|
15262
|
-
<p class="text-sm font-bold text-clx-text-label">
|
|
15263
|
-
{{ (item.unit_price * item.quantity) | currency:'COP':'symbol':'1.0-0' }}
|
|
15264
|
-
</p>
|
|
15265
|
-
|
|
15259
|
+
<clx-number
|
|
15260
|
+
variant="stepper" size="sm" [color]="color()"
|
|
15261
|
+
[min]="1" [max]="item.max_quantity ?? null"
|
|
15262
|
+
[disabled]="!item.in_stock"
|
|
15263
|
+
[ngModel]="item.quantity"
|
|
15264
|
+
(ngModelChange)="onQuantityChange.emit({ item, quantity: $event })">
|
|
15265
|
+
</clx-number>
|
|
15266
15266
|
</div>
|
|
15267
15267
|
</div>
|
|
15268
15268
|
|
|
@@ -15327,12 +15327,12 @@ class ClxCartComponent {
|
|
|
15327
15327
|
<dl class="flex flex-col gap-2.5 text-sm">
|
|
15328
15328
|
<div class="flex justify-between text-clx-text-muted">
|
|
15329
15329
|
<dt>Subtotal <span class="text-clx-text-subtle text-xs">({{ _totalUnits() }} items)</span></dt>
|
|
15330
|
-
<dd class="font-medium">{{ _subtotal() | currency:'COP':'
|
|
15330
|
+
<dd class="font-medium">{{ _subtotal() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15331
15331
|
</div>
|
|
15332
15332
|
@if (_savingsAmount() > 0) {
|
|
15333
15333
|
<div class="flex justify-between text-emerald-600">
|
|
15334
15334
|
<dt>Descuento productos</dt>
|
|
15335
|
-
<dd class="font-medium">-{{ _savingsAmount() | currency:'COP':'
|
|
15335
|
+
<dd class="font-medium">-{{ _savingsAmount() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15336
15336
|
</div>
|
|
15337
15337
|
}
|
|
15338
15338
|
@if (coupon()?.valid) {
|
|
@@ -15341,18 +15341,18 @@ class ClxCartComponent {
|
|
|
15341
15341
|
Cupón
|
|
15342
15342
|
<code class="bg-emerald-50 px-1 rounded text-xs ml-1">{{ coupon()!.code }}</code>
|
|
15343
15343
|
</dt>
|
|
15344
|
-
<dd class="font-medium">-{{ _couponDiscount() | currency:'COP':'
|
|
15344
|
+
<dd class="font-medium">-{{ _couponDiscount() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15345
15345
|
</div>
|
|
15346
15346
|
}
|
|
15347
15347
|
<div class="flex justify-between border-t border-clx-border-soft pt-2.5">
|
|
15348
15348
|
<dt class="font-bold text-clx-text-label">Total</dt>
|
|
15349
|
-
<dd class="text-
|
|
15349
|
+
<dd class="text-lg font-black text-clx-text-label">{{ _total() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15350
15350
|
</div>
|
|
15351
15351
|
</dl>
|
|
15352
15352
|
|
|
15353
15353
|
<!-- Checkout -->
|
|
15354
15354
|
<button
|
|
15355
|
-
clx-button type="button" [color]="color()" variant="solid" size="
|
|
15355
|
+
clx-button type="button" [color]="color()" variant="solid" size="md"
|
|
15356
15356
|
icon="arrow_forward" iconPosition="right" [block]="true"
|
|
15357
15357
|
(click)="onCheckout.emit()">
|
|
15358
15358
|
Proceder al pago
|
|
@@ -15371,7 +15371,7 @@ class ClxCartComponent {
|
|
|
15371
15371
|
</div>
|
|
15372
15372
|
|
|
15373
15373
|
}
|
|
15374
|
-
`, isInline: true, 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", "textColor", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { 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: ClxInputComponent, selector: "clx-input", inputs: ["label", "placeholder", "type", "color", "hint", "prefixIcon", "suffixIcon", "prefixText", "suffixText", "status", "statusMessage", "size", "value", "disabled", "autocomplete"] }, { kind: "component", type:
|
|
15374
|
+
`, isInline: true, 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", "textColor", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { 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: ClxInputComponent, selector: "clx-input", inputs: ["label", "placeholder", "type", "color", "hint", "prefixIcon", "suffixIcon", "prefixText", "suffixText", "status", "statusMessage", "size", "value", "disabled", "autocomplete"] }, { kind: "component", type: ClxNumberComponent, selector: "clx-number", inputs: ["variant", "size", "color", "label", "placeholder", "hint", "prefixIcon", "min", "max", "step", "value", "disabled"] }, { kind: "component", type: ClxPageEmptyComponent, selector: "clx-page-empty", inputs: ["icon", "title", "description", "ctaLabel", "ctaIcon", "ctaColor"], outputs: ["cta"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
15375
15375
|
}
|
|
15376
15376
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxCartComponent, decorators: [{
|
|
15377
15377
|
type: Component,
|
|
@@ -15386,7 +15386,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15386
15386
|
ClxIconComponent,
|
|
15387
15387
|
ClxSkeletonComponent,
|
|
15388
15388
|
ClxInputComponent,
|
|
15389
|
-
|
|
15389
|
+
ClxNumberComponent,
|
|
15390
|
+
ClxPageEmptyComponent
|
|
15390
15391
|
],
|
|
15391
15392
|
encapsulation: ViewEncapsulation.None,
|
|
15392
15393
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
@@ -15421,11 +15422,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15421
15422
|
<!-- ── Empty ───────────────────────────────────────────────────────────────── -->
|
|
15422
15423
|
} @else if (items().length === 0) {
|
|
15423
15424
|
|
|
15424
|
-
<
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
|
|
15425
|
+
<clx-page-empty
|
|
15426
|
+
icon="remove_shopping_cart"
|
|
15427
|
+
title="Carrito vacio"
|
|
15428
|
+
description="Tu carrito esta vacio. Agrega productos para continuar."
|
|
15429
|
+
[ctaColor]="color()"
|
|
15430
|
+
ctaIcon="storefront"
|
|
15431
|
+
ctaLabel="Ir a la tienda">
|
|
15432
|
+
</clx-page-empty>
|
|
15429
15433
|
|
|
15430
15434
|
<!-- ── Main layout ─────────────────────────────────────────────────────────── -->
|
|
15431
15435
|
} @else {
|
|
@@ -15438,19 +15442,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15438
15442
|
<!-- Top bar -->
|
|
15439
15443
|
<div class="flex items-center justify-between">
|
|
15440
15444
|
<div class="flex items-center gap-2">
|
|
15441
|
-
<h2 class="text-base font-semibold text-clx-text-label">
|
|
15445
|
+
<h2 class="text-base font-semibold text-clx-text-label">Productos</h2>
|
|
15442
15446
|
<span clx-badge variant="light" [color]="color()" size="sm">{{ _totalUnits() }}</span>
|
|
15443
15447
|
</div>
|
|
15444
15448
|
<button
|
|
15445
|
-
clx-button type="button" variant="
|
|
15449
|
+
clx-button type="button" variant="light" color="red" icon="delete"
|
|
15446
15450
|
(click)="onClearCart.emit()">
|
|
15447
|
-
Vaciar
|
|
15451
|
+
Vaciar carrito
|
|
15448
15452
|
</button>
|
|
15449
15453
|
</div>
|
|
15450
15454
|
|
|
15451
15455
|
<!-- Item cards -->
|
|
15452
15456
|
@for (item of items(); track item.id) {
|
|
15453
|
-
<article class="bg-clx-surface rounded-2xl shadow-sm flex gap-0 overflow-hidden group transition-[box-shadow,transform] duration-300 hover:shadow-
|
|
15457
|
+
<article class="bg-clx-surface rounded-2xl shadow-sm flex gap-0 overflow-hidden group transition-[box-shadow,transform] duration-300 hover:shadow-md hover:-translate-y-0.5">
|
|
15454
15458
|
|
|
15455
15459
|
<!-- Image — fixed square -->
|
|
15456
15460
|
<div class="relative shrink-0 w-28 h-28 lg:w-36 lg:h-36 overflow-hidden bg-clx-surface-2">
|
|
@@ -15495,54 +15499,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15495
15499
|
<p class="text-xs font-mono text-clx-text-subtle mt-0.5">{{ item.sku }}</p>
|
|
15496
15500
|
</div>
|
|
15497
15501
|
|
|
15498
|
-
@if (item.rating) {
|
|
15499
|
-
<div class="flex items-center gap-1.5">
|
|
15500
|
-
<clx-rating [value]="item.rating" [max]="5" color="amber" />
|
|
15501
|
-
@if (item.review_count) {
|
|
15502
|
-
<span class="text-xs text-clx-text-subtle">({{ item.review_count }})</span>
|
|
15503
|
-
}
|
|
15504
|
-
</div>
|
|
15505
|
-
}
|
|
15506
|
-
|
|
15507
15502
|
<!-- Price + Quantity row -->
|
|
15508
15503
|
<div class="flex items-center justify-between gap-2 mt-auto flex-wrap">
|
|
15509
15504
|
|
|
15510
15505
|
<!-- Price -->
|
|
15511
15506
|
<div class="flex items-baseline gap-1.5">
|
|
15512
15507
|
<span class="text-base font-bold text-clx-text-label">
|
|
15513
|
-
{{ item.unit_price | currency:'COP':'
|
|
15508
|
+
{{ item.unit_price | currency:'COP':'$':'1.0-0' }}
|
|
15514
15509
|
</span>
|
|
15515
15510
|
@if (item.has_discount && item.original_price) {
|
|
15516
15511
|
<span class="text-xs text-clx-text-subtle line-through">
|
|
15517
|
-
{{ item.original_price | currency:'COP':'
|
|
15512
|
+
{{ item.original_price | currency:'COP':'$':'1.0-0' }}
|
|
15518
15513
|
</span>
|
|
15519
15514
|
}
|
|
15520
15515
|
</div>
|
|
15521
15516
|
|
|
15522
15517
|
<!-- Quantity control -->
|
|
15523
|
-
<
|
|
15524
|
-
|
|
15525
|
-
|
|
15526
|
-
|
|
15527
|
-
|
|
15528
|
-
|
|
15529
|
-
|
|
15530
|
-
<span class="w-8 text-center text-sm font-semibold text-clx-text-label select-none">
|
|
15531
|
-
{{ item.quantity }}
|
|
15532
|
-
</span>
|
|
15533
|
-
<button
|
|
15534
|
-
clx-button type="button" variant="ghost" [color]="color()" size="sm"
|
|
15535
|
-
icon="add" [iconOnly]="true"
|
|
15536
|
-
[disabled]="!item.in_stock || (!!item.max_quantity && item.quantity >= item.max_quantity)"
|
|
15537
|
-
(click)="onQuantityChange.emit({ item, quantity: item.quantity + 1 })">
|
|
15538
|
-
</button>
|
|
15539
|
-
</div>
|
|
15540
|
-
|
|
15541
|
-
<!-- Line total -->
|
|
15542
|
-
<p class="text-sm font-bold text-clx-text-label">
|
|
15543
|
-
{{ (item.unit_price * item.quantity) | currency:'COP':'symbol':'1.0-0' }}
|
|
15544
|
-
</p>
|
|
15545
|
-
|
|
15518
|
+
<clx-number
|
|
15519
|
+
variant="stepper" size="sm" [color]="color()"
|
|
15520
|
+
[min]="1" [max]="item.max_quantity ?? null"
|
|
15521
|
+
[disabled]="!item.in_stock"
|
|
15522
|
+
[ngModel]="item.quantity"
|
|
15523
|
+
(ngModelChange)="onQuantityChange.emit({ item, quantity: $event })">
|
|
15524
|
+
</clx-number>
|
|
15546
15525
|
</div>
|
|
15547
15526
|
</div>
|
|
15548
15527
|
|
|
@@ -15607,12 +15586,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15607
15586
|
<dl class="flex flex-col gap-2.5 text-sm">
|
|
15608
15587
|
<div class="flex justify-between text-clx-text-muted">
|
|
15609
15588
|
<dt>Subtotal <span class="text-clx-text-subtle text-xs">({{ _totalUnits() }} items)</span></dt>
|
|
15610
|
-
<dd class="font-medium">{{ _subtotal() | currency:'COP':'
|
|
15589
|
+
<dd class="font-medium">{{ _subtotal() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15611
15590
|
</div>
|
|
15612
15591
|
@if (_savingsAmount() > 0) {
|
|
15613
15592
|
<div class="flex justify-between text-emerald-600">
|
|
15614
15593
|
<dt>Descuento productos</dt>
|
|
15615
|
-
<dd class="font-medium">-{{ _savingsAmount() | currency:'COP':'
|
|
15594
|
+
<dd class="font-medium">-{{ _savingsAmount() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15616
15595
|
</div>
|
|
15617
15596
|
}
|
|
15618
15597
|
@if (coupon()?.valid) {
|
|
@@ -15621,18 +15600,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15621
15600
|
Cupón
|
|
15622
15601
|
<code class="bg-emerald-50 px-1 rounded text-xs ml-1">{{ coupon()!.code }}</code>
|
|
15623
15602
|
</dt>
|
|
15624
|
-
<dd class="font-medium">-{{ _couponDiscount() | currency:'COP':'
|
|
15603
|
+
<dd class="font-medium">-{{ _couponDiscount() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15625
15604
|
</div>
|
|
15626
15605
|
}
|
|
15627
15606
|
<div class="flex justify-between border-t border-clx-border-soft pt-2.5">
|
|
15628
15607
|
<dt class="font-bold text-clx-text-label">Total</dt>
|
|
15629
|
-
<dd class="text-
|
|
15608
|
+
<dd class="text-lg font-black text-clx-text-label">{{ _total() | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15630
15609
|
</div>
|
|
15631
15610
|
</dl>
|
|
15632
15611
|
|
|
15633
15612
|
<!-- Checkout -->
|
|
15634
15613
|
<button
|
|
15635
|
-
clx-button type="button" [color]="color()" variant="solid" size="
|
|
15614
|
+
clx-button type="button" [color]="color()" variant="solid" size="md"
|
|
15636
15615
|
icon="arrow_forward" iconPosition="right" [block]="true"
|
|
15637
15616
|
(click)="onCheckout.emit()">
|
|
15638
15617
|
Proceder al pago
|
|
@@ -15695,7 +15674,7 @@ class ClxCartSummaryDrawer {
|
|
|
15695
15674
|
<p class="text-xs text-clx-text-subtle">x{{ item.quantity }}</p>
|
|
15696
15675
|
</div>
|
|
15697
15676
|
<span class="text-sm font-semibold text-clx-text-label shrink-0">
|
|
15698
|
-
{{ (item.unit_price * item.quantity) | currency:'COP':'
|
|
15677
|
+
{{ (item.unit_price * item.quantity) | currency:'COP':'$':'1.0-0' }}
|
|
15699
15678
|
</span>
|
|
15700
15679
|
</li>
|
|
15701
15680
|
}
|
|
@@ -15708,12 +15687,12 @@ class ClxCartSummaryDrawer {
|
|
|
15708
15687
|
<dl class="space-y-2">
|
|
15709
15688
|
<div class="flex justify-between text-sm text-clx-text-muted">
|
|
15710
15689
|
<dt>Subtotal</dt>
|
|
15711
|
-
<dd class="font-medium">{{ data.subtotal | currency:'COP':'
|
|
15690
|
+
<dd class="font-medium">{{ data.subtotal | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15712
15691
|
</div>
|
|
15713
15692
|
@if (data.savingsAmount > 0) {
|
|
15714
15693
|
<div class="flex justify-between text-sm text-emerald-600">
|
|
15715
15694
|
<dt>Descuento</dt>
|
|
15716
|
-
<dd class="font-medium">-{{ data.savingsAmount | currency:'COP':'
|
|
15695
|
+
<dd class="font-medium">-{{ data.savingsAmount | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15717
15696
|
</div>
|
|
15718
15697
|
}
|
|
15719
15698
|
@if (data.coupon?.valid) {
|
|
@@ -15722,12 +15701,12 @@ class ClxCartSummaryDrawer {
|
|
|
15722
15701
|
Cupón
|
|
15723
15702
|
<code class="bg-emerald-50 px-1 rounded text-xs ml-1">{{ data.coupon!.code }}</code>
|
|
15724
15703
|
</dt>
|
|
15725
|
-
<dd class="font-medium">-{{ data.couponDiscount | currency:'COP':'
|
|
15704
|
+
<dd class="font-medium">-{{ data.couponDiscount | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15726
15705
|
</div>
|
|
15727
15706
|
}
|
|
15728
15707
|
<div class="border-t border-clx-border-soft pt-2 flex justify-between">
|
|
15729
15708
|
<dt class="font-bold text-clx-text-label">Total</dt>
|
|
15730
|
-
<dd class="text-xl font-black text-clx-text-label">{{ data.total | currency:'COP':'
|
|
15709
|
+
<dd class="text-xl font-black text-clx-text-label">{{ data.total | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15731
15710
|
</div>
|
|
15732
15711
|
</dl>
|
|
15733
15712
|
|
|
@@ -15784,7 +15763,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15784
15763
|
<p class="text-xs text-clx-text-subtle">x{{ item.quantity }}</p>
|
|
15785
15764
|
</div>
|
|
15786
15765
|
<span class="text-sm font-semibold text-clx-text-label shrink-0">
|
|
15787
|
-
{{ (item.unit_price * item.quantity) | currency:'COP':'
|
|
15766
|
+
{{ (item.unit_price * item.quantity) | currency:'COP':'$':'1.0-0' }}
|
|
15788
15767
|
</span>
|
|
15789
15768
|
</li>
|
|
15790
15769
|
}
|
|
@@ -15797,12 +15776,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15797
15776
|
<dl class="space-y-2">
|
|
15798
15777
|
<div class="flex justify-between text-sm text-clx-text-muted">
|
|
15799
15778
|
<dt>Subtotal</dt>
|
|
15800
|
-
<dd class="font-medium">{{ data.subtotal | currency:'COP':'
|
|
15779
|
+
<dd class="font-medium">{{ data.subtotal | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15801
15780
|
</div>
|
|
15802
15781
|
@if (data.savingsAmount > 0) {
|
|
15803
15782
|
<div class="flex justify-between text-sm text-emerald-600">
|
|
15804
15783
|
<dt>Descuento</dt>
|
|
15805
|
-
<dd class="font-medium">-{{ data.savingsAmount | currency:'COP':'
|
|
15784
|
+
<dd class="font-medium">-{{ data.savingsAmount | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15806
15785
|
</div>
|
|
15807
15786
|
}
|
|
15808
15787
|
@if (data.coupon?.valid) {
|
|
@@ -15811,12 +15790,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15811
15790
|
Cupón
|
|
15812
15791
|
<code class="bg-emerald-50 px-1 rounded text-xs ml-1">{{ data.coupon!.code }}</code>
|
|
15813
15792
|
</dt>
|
|
15814
|
-
<dd class="font-medium">-{{ data.couponDiscount | currency:'COP':'
|
|
15793
|
+
<dd class="font-medium">-{{ data.couponDiscount | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15815
15794
|
</div>
|
|
15816
15795
|
}
|
|
15817
15796
|
<div class="border-t border-clx-border-soft pt-2 flex justify-between">
|
|
15818
15797
|
<dt class="font-bold text-clx-text-label">Total</dt>
|
|
15819
|
-
<dd class="text-xl font-black text-clx-text-label">{{ data.total | currency:'COP':'
|
|
15798
|
+
<dd class="text-xl font-black text-clx-text-label">{{ data.total | currency:'COP':'$':'1.0-0' }}</dd>
|
|
15820
15799
|
</div>
|
|
15821
15800
|
</dl>
|
|
15822
15801
|
|
|
@@ -16269,5 +16248,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
16269
16248
|
* Generated bundle index. Do not edit.
|
|
16270
16249
|
*/
|
|
16271
16250
|
|
|
16272
|
-
export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNumberComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
16251
|
+
export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNumberComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProductQuickViewComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
16273
16252
|
//# sourceMappingURL=codexly-ui.mjs.map
|