codexly-ui 0.1.23 → 0.2.0
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
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, PLATFORM_ID, signal, computed, effect, Injectable, input, ChangeDetectionStrategy, ViewEncapsulation, Component, ElementRef, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, Directive, output, contentChildren, NgZone, model, untracked, forwardRef, viewChild, HostListener, ViewChildren, contentChild,
|
|
2
|
+
import { InjectionToken, inject, PLATFORM_ID, signal, computed, effect, Injectable, input, ChangeDetectionStrategy, ViewEncapsulation, Component, ElementRef, Renderer2, ApplicationRef, EnvironmentInjector, DestroyRef, createComponent, Directive, output, contentChildren, NgZone, model, untracked, forwardRef, viewChild, HostListener, ViewChildren, contentChild, ViewChild, Injector, ChangeDetectorRef, ContentChildren, Input, numberAttribute, booleanAttribute } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, CurrencyPipe, NgTemplateOutlet, DecimalPipe, NgStyle, DOCUMENT } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, FormsModule, NgControl, FormControl, ReactiveFormsModule, FormGroup, Validators } from '@angular/forms';
|
|
@@ -8,7 +8,6 @@ import { startWith, map, debounceTime, distinctUntilChanged, switchMap, of, catc
|
|
|
8
8
|
import * as i1$1 from '@angular/cdk/overlay';
|
|
9
9
|
import { ScrollStrategyOptions, OverlayModule } from '@angular/cdk/overlay';
|
|
10
10
|
import { ScrollingModule, CdkScrollable } from '@angular/cdk/scrolling';
|
|
11
|
-
import { Chart, LineController, BarController, PieController, DoughnutController, RadarController, PolarAreaController, CategoryScale, LinearScale, RadialLinearScale, BarElement, LineElement, PointElement, ArcElement, Filler, Tooltip, Legend } from 'chart.js';
|
|
12
11
|
import { RouterLink, RouterLinkActive } from '@angular/router';
|
|
13
12
|
|
|
14
13
|
// ── Parse 'red' | 'red-500' → { color, shade } ───────────────────────────────
|
|
@@ -993,7 +992,7 @@ const PRODUCT_TAG_VARIANT = {
|
|
|
993
992
|
'hot': 'solid',
|
|
994
993
|
};
|
|
995
994
|
|
|
996
|
-
const BUTTON_BASE_CLASS = 'relative overflow-hidden inline-flex items-center justify-center font-medium select-none transition-
|
|
995
|
+
const BUTTON_BASE_CLASS = 'relative overflow-hidden inline-flex items-center justify-center font-medium select-none transition-[color,background-color,border-color,box-shadow] duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2';
|
|
997
996
|
const BUTTON_SIZE_MAP = {
|
|
998
997
|
xxs: 'text-xs px-1.5 py-0.5 gap-0.5',
|
|
999
998
|
xs: 'text-xs px-2 py-1 gap-1',
|
|
@@ -1786,7 +1785,7 @@ class ClxProductComponent {
|
|
|
1786
1785
|
_buttonSize = computed(() => this._sm() ? 'sm' : 'md', ...(ngDevMode ? [{ debugName: "_buttonSize" }] : /* istanbul ignore next */ []));
|
|
1787
1786
|
_skeletonW = computed(() => this._sm() ? 'sm:w-32' : 'sm:w-44', ...(ngDevMode ? [{ debugName: "_skeletonW" }] : /* istanbul ignore next */ []));
|
|
1788
1787
|
_skeletonH = computed(() => this._sm() ? '160px' : '200px', ...(ngDevMode ? [{ debugName: "_skeletonH" }] : /* istanbul ignore next */ []));
|
|
1789
|
-
_cardClass = computed(() => `bg-clx-surface rounded-2xl shadow-sm transition-
|
|
1788
|
+
_cardClass = computed(() => `bg-clx-surface rounded-2xl shadow-sm transition-[box-shadow,transform] duration-300 overflow-hidden group hover:shadow-xl hover:-translate-y-0.5 ${this._h() ? 'flex flex-col sm:flex-row' : 'flex flex-col'}`, ...(ngDevMode ? [{ debugName: "_cardClass" }] : /* istanbul ignore next */ []));
|
|
1790
1789
|
_imageContainerClass = computed(() => this._h()
|
|
1791
1790
|
? `relative shrink-0 w-full aspect-square sm:aspect-auto ${this._sm() ? 'sm:w-32' : 'sm:w-44'} overflow-hidden rounded-t-2xl sm:rounded-t-none sm:rounded-l-2xl`
|
|
1792
1791
|
: 'relative w-full aspect-square overflow-hidden rounded-t-2xl', ...(ngDevMode ? [{ debugName: "_imageContainerClass" }] : /* istanbul ignore next */ []));
|
|
@@ -2347,7 +2346,7 @@ class ClxCarouselComponent {
|
|
|
2347
2346
|
@for (dot of _dotItems(); track dot.idx) {
|
|
2348
2347
|
<button
|
|
2349
2348
|
type="button"
|
|
2350
|
-
class="rounded-full transition-
|
|
2349
|
+
class="rounded-full transition-[width,background-color] duration-300 focus:outline-none cursor-pointer"
|
|
2351
2350
|
[class]="dot.cls"
|
|
2352
2351
|
(click)="goTo(dot.idx)"
|
|
2353
2352
|
[attr.aria-label]="'Slide ' + (dot.idx + 1)">
|
|
@@ -2413,7 +2412,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
2413
2412
|
@for (dot of _dotItems(); track dot.idx) {
|
|
2414
2413
|
<button
|
|
2415
2414
|
type="button"
|
|
2416
|
-
class="rounded-full transition-
|
|
2415
|
+
class="rounded-full transition-[width,background-color] duration-300 focus:outline-none cursor-pointer"
|
|
2417
2416
|
[class]="dot.cls"
|
|
2418
2417
|
(click)="goTo(dot.idx)"
|
|
2419
2418
|
[attr.aria-label]="'Slide ' + (dot.idx + 1)">
|
|
@@ -2635,7 +2634,7 @@ class ClxNumberComponent {
|
|
|
2635
2634
|
const focus = this._disabled() ? '' : resolveColor(this._color()).focusWithin;
|
|
2636
2635
|
const border = this._disabled() ? `${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED}` : CLX_BORDER_DEFAULT;
|
|
2637
2636
|
const cursor = this._disabled() ? 'cursor-not-allowed' : '';
|
|
2638
|
-
return `flex items-stretch ${size.container} bg-clx-surface ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focus} ${cursor} overflow-hidden transition-
|
|
2637
|
+
return `flex items-stretch ${size.container} bg-clx-surface ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focus} ${cursor} overflow-hidden transition-[border-color,box-shadow] duration-200`;
|
|
2639
2638
|
}, ...(ngDevMode ? [{ debugName: "_containerClass" }] : /* istanbul ignore next */ []));
|
|
2640
2639
|
/** Colored prefix icon cell — matches the input accent color */
|
|
2641
2640
|
_prefixCellCls = computed(() => {
|
|
@@ -3175,7 +3174,7 @@ class ClxProductDetailComponent {
|
|
|
3175
3174
|
specsLeft(specs) { return specs.slice(0, Math.ceil(specs.length / 2)); }
|
|
3176
3175
|
specsRight(specs) { return specs.slice(Math.ceil(specs.length / 2)); }
|
|
3177
3176
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3178
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProductDetailComponent, isStandalone: true, selector: "clx-product-detail", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, clxColor: { classPropertyName: "clxColor", publicName: "clxColor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_carousel", first: true, predicate: ClxCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-all\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxButtonGroupComponent, selector: "clx-button-group", inputs: ["label", "shape", "attached", "orientation"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxRatingComponent, selector: "clx-rating", inputs: ["value", "max", "color"] }, { kind: "component", type: ClxCarouselComponent, selector: "clx-carousel", inputs: ["clxColor", "autoPlay", "interval", "loop", "aspectRatio", "transparent"] }, { kind: "directive", type: ClxCarouselDirective, selector: "[clxSlide]" }, { kind: "component", type: ClxTabsComponent, selector: "clx-tabs", inputs: ["tabs", "clxColor", "activeTab"], outputs: ["activeTabChange"] }, { kind: "directive", type: ClxTabDirective, selector: "[clxTabPanel]", inputs: ["clxTabPanel"] }, { kind: "component", type: ClxNumberComponent, selector: "clx-number", inputs: ["variant", "size", "color", "label", "placeholder", "hint", "prefixIcon", "min", "max", "step", "value", "disabled"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }, { kind: "component", type: ClxListComponent, selector: "clx-list", inputs: ["color", "variant", "size", "numbered"] }, { kind: "component", type: ClxListItemComponent, selector: "clx-list-item", inputs: ["label", "sublabel", "icon", "meta", "metaColor", "disabled"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3177
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProductDetailComponent, isStandalone: true, selector: "clx-product-detail", inputs: { product: { classPropertyName: "product", publicName: "product", isSignal: true, isRequired: false, transformFunction: null }, clxColor: { classPropertyName: "clxColor", publicName: "clxColor", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, currency: { classPropertyName: "currency", publicName: "currency", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "_carousel", first: true, predicate: ClxCarouselComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxButtonGroupComponent, selector: "clx-button-group", inputs: ["label", "shape", "attached", "orientation"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }, { kind: "component", type: ClxSkeletonComponent, selector: "clx-skeleton", inputs: ["variant", "size", "width", "height"] }, { kind: "component", type: ClxRatingComponent, selector: "clx-rating", inputs: ["value", "max", "color"] }, { kind: "component", type: ClxCarouselComponent, selector: "clx-carousel", inputs: ["clxColor", "autoPlay", "interval", "loop", "aspectRatio", "transparent"] }, { kind: "directive", type: ClxCarouselDirective, selector: "[clxSlide]" }, { kind: "component", type: ClxTabsComponent, selector: "clx-tabs", inputs: ["tabs", "clxColor", "activeTab"], outputs: ["activeTabChange"] }, { kind: "directive", type: ClxTabDirective, selector: "[clxTabPanel]", inputs: ["clxTabPanel"] }, { kind: "component", type: ClxNumberComponent, selector: "clx-number", inputs: ["variant", "size", "color", "label", "placeholder", "hint", "prefixIcon", "min", "max", "step", "value", "disabled"] }, { kind: "directive", type: ClxTooltipDirective, selector: "[clxTooltip]", inputs: ["clxTooltip", "clxTooltipPosition", "clxTooltipColor", "clxTooltipSize", "clxTooltipDelay"] }, { kind: "component", type: ClxListComponent, selector: "clx-list", inputs: ["color", "variant", "size", "numbered"] }, { kind: "component", type: ClxListItemComponent, selector: "clx-list-item", inputs: ["label", "sublabel", "icon", "meta", "metaColor", "disabled"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "pipe", type: DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
3179
3178
|
}
|
|
3180
3179
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProductDetailComponent, decorators: [{
|
|
3181
3180
|
type: Component,
|
|
@@ -3197,7 +3196,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
3197
3196
|
ClxTooltipDirective,
|
|
3198
3197
|
ClxListComponent,
|
|
3199
3198
|
ClxListItemComponent,
|
|
3200
|
-
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-all\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n" }]
|
|
3199
|
+
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- \u2550\u2550 SKELETON \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (loading()) {\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 p-6\">\n <div class=\"space-y-3\">\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"420px\" class=\"rounded-2xl\"></clx-skeleton>\n <div class=\"flex gap-2\">\n @for (t of [1,2,3,4]; track t) {\n <clx-skeleton variant=\"rectangular\" width=\"80px\" height=\"80px\" class=\"rounded-xl\"></clx-skeleton>\n }\n </div>\n </div>\n <div class=\"space-y-4 pt-2\">\n <clx-skeleton variant=\"text\" size=\"lg\" width=\"70%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"sm\" width=\"40%\"></clx-skeleton>\n <clx-skeleton variant=\"text\" size=\"xl\" width=\"50%\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"100px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n <clx-skeleton variant=\"rectangular\" width=\"100%\" height=\"52px\" class=\"rounded-xl\"></clx-skeleton>\n </div>\n </div>\n}\n\n<!-- \u2550\u2550 CONTENT \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n@if (!loading() && product(); as p) {\n @let v = activeVariation();\n <div class=\"space-y-8\">\n\n <div class=\"grid grid-cols-1 xl:grid-cols-2 gap-8 xl:items-start\">\n\n <!-- \u2500\u2500 Column 1: Image Gallery \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-3\">\n <div class=\"relative\">\n <clx-carousel [clxColor]=\"clxColor()\" aspectRatio=\"4/3\" [loop]=\"true\">\n @for (img of v?.images ?? []; track img) {\n <ng-template clxSlide>\n <img [src]=\"img\" [alt]=\"p.product_name\" class=\"w-full h-full object-cover\" loading=\"lazy\" />\n </ng-template>\n }\n </clx-carousel>\n <div class=\"absolute top-3 right-3 z-10\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" shape=\"circle\" size=\"md\"\n [iconOnly]=\"true\" clxTooltip=\"Add to Wishlist\" [clxTooltipColor]=\"clxColor()\" clxTooltipPosition=\"left\">\n <span clx-icon name=\"favorite_border\" size=\"sm\"></span>\n </button>\n </div>\n </div>\n <div class=\"flex flex-wrap gap-2\">\n @for (img of v?.images ?? []; track img; let i = $index) {\n <img [src]=\"img\" [alt]=\"p.product_name\"\n class=\"w-20 h-20 rounded-xl object-cover border-[3px] cursor-pointer shrink-0 transition-[border-color,opacity]\"\n [class]=\"_carousel()?.currentPageIndex() === i\n ? 'border-' + clxColor() + '-500 opacity-100'\n : 'border-transparent opacity-60 hover:opacity-90'\"\n loading=\"lazy\"\n (click)=\"_carousel()?.goTo(i)\" />\n }\n </div>\n </div>\n\n <!-- \u2500\u2500 Column 2: Purchase Info \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"space-y-5\">\n\n <!-- Tags (st_products.tags) -->\n <div class=\"flex flex-wrap gap-2\">\n @for (tag of p.tags; track tag) {\n <span clx-badge variant=\"light\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">{{ tag }}</span>\n }\n </div>\n\n <!-- Title -->\n <div>\n <p class=\"text-xs text-clx-text-subtle uppercase tracking-wide font-medium\">{{ p.trademark }}</p>\n <h1 class=\"text-2xl font-bold text-clx-text-label leading-tight mt-0.5\">{{ p.product_name }}</h1>\n @if (v?.description) {\n <p class=\"text-clx-text-muted text-sm mt-1\">{{ v!.description }}</p>\n }\n </div>\n\n <!-- Rating -->\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <span class=\"text-sm text-clx-text-subtle\">({{ p.review_count }} reviews)</span>\n </div>\n\n <!-- Price block -->\n <div class=\"py-4\">\n <div class=\"flex items-baseline gap-3\">\n <span class=\"text-4xl font-black text-clx-text-label\">\n {{ finalPrice() | currency:currency():'symbol':'1.0-0' }}\n </span>\n @if (p.has_discount && p.discount_price) {\n <span class=\"text-lg text-clx-text-subtle line-through\">\n {{ p.discount_price | currency:currency():'symbol':'1.0-0' }}\n </span>\n <span clx-badge variant=\"solid\" [color]=\"clxColor()\" size=\"sm\" shape=\"pill\">\n -{{ discount() }}%\n </span>\n }\n </div>\n @if (v && !v.in_stock) {\n <p class=\"text-sm text-rose-500 font-medium mt-1\">Out of stock</p>\n }\n </div>\n\n <!-- Selectores de variaci\u00F3n (st_spec_types + st_spec_options) -->\n @for (specType of p.spec_types; track specType.id) {\n @if (specType.input_type === 'color') {\n <clx-button-group [label]=\"specType.name\" shape=\"circular\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"asColor(opt.value)\"\n shape=\"circle\" size=\"xs\" [iconOnly]=\"true\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n [clxTooltip]=\"opt.value\"\n [clxTooltipColor]=\"asColor(opt.value)\"\n clxTooltipPosition=\"top\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n </button>\n }\n </clx-button-group>\n } @else {\n <clx-button-group [label]=\"specType.name\" shape=\"flat\" [attached]=\"false\">\n @for (opt of specType.options; track opt.id) {\n <button clx-button\n [variant]=\"isSpecSelected(specType.id, opt.id) ? 'solid' : 'outline'\"\n [color]=\"clxColor()\" size=\"sm\"\n [disabled]=\"!isOptionAvailable(specType.id, opt.id)\"\n (click)=\"selectSpec(specType.id, opt.id)\">\n {{ opt.value }}\n </button>\n }\n </clx-button-group>\n }\n }\n\n <!-- Quantity -->\n <clx-number label=\"Quantity:\" variant=\"stepper\" [color]=\"clxColor()\"\n [min]=\"1\" [max]=\"99\" [ngModel]=\"quantity()\" (ngModelChange)=\"quantity.set($event)\">\n </clx-number>\n\n <!-- CTA -->\n <div class=\"flex gap-3\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"bolt\"\n [disabled]=\"!v?.in_stock\">Buy Now</button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"shopping_cart\"\n [disabled]=\"!v?.in_stock\">Add to Cart</button>\n </div>\n\n </div>\n </div>\n\n <!-- \u2500\u2500 Tabs \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <clx-tabs [tabs]=\"tabItems\" [clxColor]=\"clxColor()\" [(activeTab)]=\"activeTab\">\n\n <!-- Tab: Caracter\u00EDsticas generales (st_product_specs \u2014 ficha t\u00E9cnica global) -->\n <ng-template [clxTabPanel]=\"'general'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsLeft(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (spec of specsRight(p.product_specs); track spec.id) {\n <clx-list-item [label]=\"spec.name + ':'\" [sublabel]=\"spec.value\" [icon]=\"spec.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Especificaciones (st_spec_types \u2014 specs de la variaci\u00F3n activa) -->\n <ng-template [clxTabPanel]=\"'specs'\">\n <div class=\"grid grid-cols-1 sm:grid-cols-2 gap-x-8\">\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsLeft(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n <clx-list [color]=\"clxColor()\" variant=\"flush\" size=\"sm\">\n @for (st of specsRight(p.spec_types); track st.id) {\n <clx-list-item [label]=\"st.name + ':'\" [sublabel]=\"selectedOptionLabel(st)\" [icon]=\"st.icon ?? ''\" />\n }\n </clx-list>\n </div>\n </ng-template>\n\n <!-- Tab: Descripci\u00F3n (st_product_descriptions) -->\n <ng-template [clxTabPanel]=\"'description'\">\n <div class=\"space-y-5 max-w-3xl\">\n @for (block of p.descriptions; track block.id) {\n <div>\n @if (block.title) {\n <h3 class=\"text-base font-semibold text-clx-text-label mb-1\">{{ block.title }}</h3>\n }\n <p class=\"text-sm text-clx-text-muted leading-relaxed\">{{ block.body }}</p>\n </div>\n }\n </div>\n </ng-template>\n\n </clx-tabs>\n\n <!-- \u2500\u2500 Reviews \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <div class=\"grid grid-cols-1 xl:grid-cols-3 gap-8 border-t border-clx-border pt-8\">\n\n <div class=\"space-y-3\">\n <h2 class=\"text-base font-bold text-clx-text-label\">Customer Reviews</h2>\n <div class=\"flex items-end gap-3\">\n <span class=\"text-5xl font-black text-clx-text-label\">{{ p.rating | number:'1.1-1' }}</span>\n <div class=\"pb-1 space-y-1\">\n <clx-rating [value]=\"p.rating\" [color]=\"clxColor()\"></clx-rating>\n <p class=\"text-xs text-clx-text-muted\">{{ p.review_count }} verified ratings</p>\n </div>\n </div>\n <p class=\"text-sm font-semibold\" [class]=\"'text-' + clxColor() + '-600'\">Very Good</p>\n <div class=\"pt-2 space-y-2\">\n <button clx-button variant=\"solid\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"rate_review\">\n Leave Us a Review\n </button>\n <button clx-button variant=\"light\" [color]=\"clxColor()\" size=\"md\" [block]=\"true\" icon=\"flag\">\n Report abuse\n </button>\n </div>\n </div>\n\n <div class=\"lg:col-span-2 space-y-4\">\n @for (review of p.reviews ?? []; track review.id) {\n <div class=\"rounded-2xl overflow-hidden shadow-sm\">\n <div class=\"flex items-center gap-3 px-4 py-3\">\n <div class=\"w-10 h-10 rounded-full bg-clx-surface-2 flex items-center justify-center shrink-0\">\n <span class=\"text-sm font-bold text-clx-text-muted\">\n {{ review.author_name.substring(0,1) }}{{ review.author_name.split(' ')[1]?.substring(0,1) ?? '' }}\n </span>\n </div>\n <div class=\"flex-1 min-w-0\">\n <p class=\"font-semibold text-sm text-clx-text-label truncate\">{{ review.author_name }}</p>\n <p class=\"text-xs text-clx-text-subtle\">{{ review.created_at }}</p>\n </div>\n @if (review.is_verified) {\n <span clx-badge variant=\"light\" color=\"emerald\" size=\"sm\" shape=\"pill\">Verified</span>\n }\n </div>\n <div class=\"px-4 pb-4 space-y-2\">\n <div class=\"flex items-center gap-2\">\n <clx-rating [value]=\"review.rating\" [color]=\"clxColor()\"></clx-rating>\n @if (review.title) {\n <span class=\"text-sm font-semibold text-clx-text-label\">{{ review.title }}</span>\n }\n </div>\n @if (review.body) {\n <p class=\"text-sm text-clx-text-muted\">{{ review.body }}</p>\n }\n <div class=\"flex items-center gap-3 pt-1\">\n <span class=\"text-xs text-clx-text-subtle\">Helpful?</span>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_up\">{{ review.helpful }}</button>\n <button clx-button variant=\"ghost\" color=\"slate\" size=\"xs\" icon=\"thumb_down\">{{ review.not_helpful }}</button>\n </div>\n </div>\n </div>\n }\n </div>\n\n </div>\n\n </div>\n}\n" }]
|
|
3201
3200
|
}], ctorParameters: () => [], propDecorators: { product: [{ type: i0.Input, args: [{ isSignal: true, alias: "product", required: false }] }], clxColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "clxColor", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], currency: [{ type: i0.Input, args: [{ isSignal: true, alias: "currency", required: false }] }], _carousel: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ClxCarouselComponent), { isSignal: true }] }] } });
|
|
3202
3201
|
|
|
3203
3202
|
const SIZE_MAP = {
|
|
@@ -3448,7 +3447,7 @@ class ClxCheckboxComponent {
|
|
|
3448
3447
|
_onTouched = () => { };
|
|
3449
3448
|
_sizeConfig = computed(() => CHECKBOX_SIZE_MAP[this._size()], ...(ngDevMode ? [{ debugName: "_sizeConfig" }] : /* istanbul ignore next */ []));
|
|
3450
3449
|
_boxClass = computed(() => {
|
|
3451
|
-
const base = `${this._sizeConfig().box} flex items-center justify-center rounded border-2 transition-
|
|
3450
|
+
const base = `${this._sizeConfig().box} flex items-center justify-center rounded border-2 transition-colors duration-200`;
|
|
3452
3451
|
if (this._disabled()) {
|
|
3453
3452
|
return this._checked()
|
|
3454
3453
|
? `${base} border-clx-border bg-clx-border text-white`
|
|
@@ -3621,7 +3620,7 @@ class ClxSliderComponent {
|
|
|
3621
3620
|
_isInvalid = computed(() => this._wasTouched() && (this._ngControl?.control?.invalid ?? false), ...(ngDevMode ? [{ debugName: "_isInvalid" }] : /* istanbul ignore next */ []));
|
|
3622
3621
|
_trackClass = computed(() => 'absolute inset-x-0 top-1/2 -translate-y-1/2 rounded-full bg-clx-border overflow-visible', ...(ngDevMode ? [{ debugName: "_trackClass" }] : /* istanbul ignore next */ []));
|
|
3623
3622
|
_thumbClass = computed(() => {
|
|
3624
|
-
const base = 'absolute top-1/2 -translate-y-1/2 -translate-x-1/2 rounded-full bg-clx-surface border-[3px] shadow-md transition-
|
|
3623
|
+
const base = 'absolute top-1/2 -translate-y-1/2 -translate-x-1/2 rounded-full bg-clx-surface border-[3px] shadow-md transition-[border-color,box-shadow,transform] duration-75 pointer-events-none z-10';
|
|
3625
3624
|
const t = this._colorTokens();
|
|
3626
3625
|
const border = this._disabled() ? 'border-clx-border' : t.border;
|
|
3627
3626
|
const ring = this._isFocused() && !this._disabled()
|
|
@@ -3689,7 +3688,7 @@ class ClxSliderComponent {
|
|
|
3689
3688
|
|
|
3690
3689
|
<!-- Filled track -->
|
|
3691
3690
|
<div
|
|
3692
|
-
class="absolute left-0 top-0 h-full rounded-full transition-
|
|
3691
|
+
class="absolute left-0 top-0 h-full rounded-full transition-[width,background-color] duration-75"
|
|
3693
3692
|
[class]="_disabled() ? 'bg-clx-border' : _colorTokens().bg"
|
|
3694
3693
|
[style.width]="_pct() + '%'">
|
|
3695
3694
|
</div>
|
|
@@ -3788,7 +3787,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
3788
3787
|
|
|
3789
3788
|
<!-- Filled track -->
|
|
3790
3789
|
<div
|
|
3791
|
-
class="absolute left-0 top-0 h-full rounded-full transition-
|
|
3790
|
+
class="absolute left-0 top-0 h-full rounded-full transition-[width,background-color] duration-75"
|
|
3792
3791
|
[class]="_disabled() ? 'bg-clx-border' : _colorTokens().bg"
|
|
3793
3792
|
[style.width]="_pct() + '%'">
|
|
3794
3793
|
</div>
|
|
@@ -3974,7 +3973,7 @@ class ClxRadioComponent {
|
|
|
3974
3973
|
_size = computed(() => this.size() ?? this._group?.size() ?? this._themeSvc.config().defaultSize, ...(ngDevMode ? [{ debugName: "_size" }] : /* istanbul ignore next */ []));
|
|
3975
3974
|
_sizeConfig = computed(() => RADIO_SIZE_MAP[this._size()], ...(ngDevMode ? [{ debugName: "_sizeConfig" }] : /* istanbul ignore next */ []));
|
|
3976
3975
|
_ringClass = computed(() => {
|
|
3977
|
-
const base = `${this._sizeConfig().ring} rounded-full border-2 flex items-center justify-center transition-
|
|
3976
|
+
const base = `${this._sizeConfig().ring} rounded-full border-2 flex items-center justify-center transition-colors duration-200`;
|
|
3978
3977
|
if (this._isDisabled()) {
|
|
3979
3978
|
return this._checked()
|
|
3980
3979
|
? `${base} border-clx-border bg-clx-border`
|
|
@@ -3988,7 +3987,7 @@ class ClxRadioComponent {
|
|
|
3988
3987
|
return `${base} ${t.bgSubtle} ${t.borderLight}`;
|
|
3989
3988
|
}, ...(ngDevMode ? [{ debugName: "_ringClass" }] : /* istanbul ignore next */ []));
|
|
3990
3989
|
_dotClass = computed(() => {
|
|
3991
|
-
const base = `${this._sizeConfig().dot} rounded-full transition-
|
|
3990
|
+
const base = `${this._sizeConfig().dot} rounded-full transition-[transform,color,background-color] duration-200`;
|
|
3992
3991
|
if (!this._checked())
|
|
3993
3992
|
return `${base} scale-0`;
|
|
3994
3993
|
if (this._isDisabled())
|
|
@@ -4263,7 +4262,7 @@ class ClxInputComponent {
|
|
|
4263
4262
|
: this.status() !== 'default'
|
|
4264
4263
|
? this._statusCfg().ring.replace(/focus:/g, 'focus-within:')
|
|
4265
4264
|
: resolveColor(this._color()).focusWithin;
|
|
4266
|
-
return `relative flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focusCls} overflow-hidden transition-
|
|
4265
|
+
return `relative flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focusCls} overflow-hidden transition-[border-color,box-shadow] duration-200`;
|
|
4267
4266
|
}, ...(ngDevMode ? [{ debugName: "_wrapperClass" }] : /* istanbul ignore next */ []));
|
|
4268
4267
|
_inputClass = computed(() => {
|
|
4269
4268
|
const size = this._sizeConfig();
|
|
@@ -4281,7 +4280,7 @@ class ClxInputComponent {
|
|
|
4281
4280
|
const hasSuffix = this.type() === 'password' || this.status() !== 'default' || !!this.suffixIcon();
|
|
4282
4281
|
const pl = size.padDefaultL;
|
|
4283
4282
|
const pr = hasSuffix ? size.padRight : size.padDefaultR;
|
|
4284
|
-
const base = `w-full ${resolveRadius(this._themeSvc.config().borderRadius)} border ${size.input} ${pl} ${pr} outline-none transition-
|
|
4283
|
+
const base = `w-full ${resolveRadius(this._themeSvc.config().borderRadius)} border ${size.input} ${pl} ${pr} outline-none transition-[border-color,box-shadow] duration-200`;
|
|
4285
4284
|
if (this._disabled()) {
|
|
4286
4285
|
return `${base} ${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED} cursor-not-allowed ${CLX_TEXT_DISABLED} ${CLX_PLACEHOLDER}`;
|
|
4287
4286
|
}
|
|
@@ -4625,7 +4624,7 @@ class ClxSelectComponent {
|
|
|
4625
4624
|
_hintClass = computed(() => `${this._sizeConfig().hint} ${CLX_TEXT_HINT}`, ...(ngDevMode ? [{ debugName: "_hintClass" }] : /* istanbul ignore next */ []));
|
|
4626
4625
|
_triggerClass = computed(() => {
|
|
4627
4626
|
const s = this._sizeConfig();
|
|
4628
|
-
const base = `relative flex items-center ${resolveRadius(this._themeSvc.config().borderRadius)} border transition-
|
|
4627
|
+
const base = `relative flex items-center ${resolveRadius(this._themeSvc.config().borderRadius)} border transition-[border-color,box-shadow] duration-200 outline-none w-full overflow-hidden`;
|
|
4629
4628
|
if (this._disabled()) {
|
|
4630
4629
|
return `${base} ${s.minH} ${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED} cursor-not-allowed opacity-60`;
|
|
4631
4630
|
}
|
|
@@ -7391,185 +7390,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
7391
7390
|
}]
|
|
7392
7391
|
}], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], time: [{ type: i0.Input, args: [{ isSignal: true, alias: "time", required: false }] }], last: [{ type: i0.Input, args: [{ isSignal: true, alias: "last", required: false }] }] } });
|
|
7393
7392
|
|
|
7394
|
-
const CLX_CHART_DEFAULTS_NO_SCALES = {
|
|
7395
|
-
responsive: true,
|
|
7396
|
-
maintainAspectRatio: false,
|
|
7397
|
-
font: {
|
|
7398
|
-
family: 'Roboto, ui-sans-serif, system-ui, -apple-system, sans-serif',
|
|
7399
|
-
size: 12,
|
|
7400
|
-
},
|
|
7401
|
-
plugins: {
|
|
7402
|
-
legend: { display: true, position: 'top', align: 'center' },
|
|
7403
|
-
tooltip: { enabled: true },
|
|
7404
|
-
},
|
|
7405
|
-
};
|
|
7406
|
-
const CLX_CHART_DEFAULTS = {
|
|
7407
|
-
responsive: true,
|
|
7408
|
-
maintainAspectRatio: false,
|
|
7409
|
-
font: {
|
|
7410
|
-
family: 'Roboto, ui-sans-serif, system-ui, -apple-system, sans-serif',
|
|
7411
|
-
size: 12,
|
|
7412
|
-
},
|
|
7413
|
-
plugins: {
|
|
7414
|
-
legend: {
|
|
7415
|
-
display: true,
|
|
7416
|
-
position: 'top',
|
|
7417
|
-
align: 'center'
|
|
7418
|
-
},
|
|
7419
|
-
tooltip: {
|
|
7420
|
-
enabled: true
|
|
7421
|
-
},
|
|
7422
|
-
},
|
|
7423
|
-
scales: {
|
|
7424
|
-
x: {
|
|
7425
|
-
display: true,
|
|
7426
|
-
grid: {
|
|
7427
|
-
display: false
|
|
7428
|
-
},
|
|
7429
|
-
border: {
|
|
7430
|
-
color: CLX_COLOR_HEX.slate100
|
|
7431
|
-
},
|
|
7432
|
-
ticks: {
|
|
7433
|
-
color: CLX_COLOR_HEX.slate400
|
|
7434
|
-
}
|
|
7435
|
-
},
|
|
7436
|
-
y: {
|
|
7437
|
-
display: true,
|
|
7438
|
-
beginAtZero: true,
|
|
7439
|
-
grid: {
|
|
7440
|
-
display: true,
|
|
7441
|
-
color: CLX_COLOR_HEX.slate100
|
|
7442
|
-
},
|
|
7443
|
-
border: {
|
|
7444
|
-
color: CLX_COLOR_HEX.slate100
|
|
7445
|
-
},
|
|
7446
|
-
ticks: {
|
|
7447
|
-
color: CLX_COLOR_HEX.slate400
|
|
7448
|
-
}
|
|
7449
|
-
},
|
|
7450
|
-
},
|
|
7451
|
-
};
|
|
7452
|
-
const CLX_CHART_PALETTE = Object.values(CLX_COLOR_HEX);
|
|
7453
|
-
/** Versiones con opacidad 20% para backgrounds de áreas/barras */
|
|
7454
|
-
const CLX_CHART_PALETTE_ALPHA = CLX_CHART_PALETTE.map(hex => `${hex}33`);
|
|
7455
|
-
const AREA_TYPES = ['line', 'radar'];
|
|
7456
|
-
const MULTI_SLICE_TYPES = ['pie', 'doughnut', 'polarArea'];
|
|
7457
|
-
function shuffled(arr) {
|
|
7458
|
-
const a = [...arr];
|
|
7459
|
-
for (let i = a.length - 1; i > 0; i--) {
|
|
7460
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
7461
|
-
[a[i], a[j]] = [a[j], a[i]];
|
|
7462
|
-
}
|
|
7463
|
-
return a;
|
|
7464
|
-
}
|
|
7465
|
-
function applyChartDefaults(type, data) {
|
|
7466
|
-
const palette = shuffled(CLX_CHART_PALETTE);
|
|
7467
|
-
const paletteAlpha = palette.map(hex => `${hex}33`);
|
|
7468
|
-
const datasets = data.datasets.map((ds, i) => {
|
|
7469
|
-
const color = palette[i % palette.length];
|
|
7470
|
-
const alpha = paletteAlpha[i % paletteAlpha.length];
|
|
7471
|
-
if (MULTI_SLICE_TYPES.includes(type)) {
|
|
7472
|
-
const count = ds.data.length;
|
|
7473
|
-
return {
|
|
7474
|
-
...ds,
|
|
7475
|
-
backgroundColor: ds.backgroundColor ?? Array.from({ length: count }, (_, j) => palette[j % palette.length]),
|
|
7476
|
-
borderColor: ds.borderColor ?? '#fff',
|
|
7477
|
-
borderWidth: ds.borderWidth ?? 2,
|
|
7478
|
-
};
|
|
7479
|
-
}
|
|
7480
|
-
if (AREA_TYPES.includes(type)) {
|
|
7481
|
-
return {
|
|
7482
|
-
...ds,
|
|
7483
|
-
borderColor: ds.borderColor ?? color,
|
|
7484
|
-
backgroundColor: ds.backgroundColor ?? alpha,
|
|
7485
|
-
pointBackgroundColor: ds.pointBackgroundColor ?? color,
|
|
7486
|
-
fill: ds.fill ?? (type === 'line' ? false : true),
|
|
7487
|
-
tension: ds.tension ?? 0.4,
|
|
7488
|
-
};
|
|
7489
|
-
}
|
|
7490
|
-
return {
|
|
7491
|
-
...ds,
|
|
7492
|
-
backgroundColor: ds.backgroundColor ?? color,
|
|
7493
|
-
borderColor: ds.borderColor ?? color,
|
|
7494
|
-
borderWidth: ds.borderWidth ?? 0,
|
|
7495
|
-
barPercentage: ds.barPercentage ?? 0.5,
|
|
7496
|
-
categoryPercentage: ds.categoryPercentage ?? 0.6,
|
|
7497
|
-
};
|
|
7498
|
-
});
|
|
7499
|
-
return { ...data, datasets };
|
|
7500
|
-
}
|
|
7501
|
-
|
|
7502
|
-
Chart.register(LineController, BarController, PieController, DoughnutController, RadarController, PolarAreaController, CategoryScale, LinearScale, RadialLinearScale, BarElement, LineElement, PointElement, ArcElement, Filler, Tooltip, Legend);
|
|
7503
|
-
const NO_SCALE_TYPES = ['doughnut', 'pie', 'polarArea'];
|
|
7504
|
-
class ClxChartComponent {
|
|
7505
|
-
canvasRef;
|
|
7506
|
-
type = input.required(...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
7507
|
-
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
7508
|
-
options = input({}, ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
7509
|
-
height = input(300, ...(ngDevMode ? [{ debugName: "height" }] : /* istanbul ignore next */ []));
|
|
7510
|
-
ariaLabel = input(...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
7511
|
-
// SOLUCIÓN AL ERROR: Añadimos el input loading
|
|
7512
|
-
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
7513
|
-
_chart;
|
|
7514
|
-
_injector = inject(Injector);
|
|
7515
|
-
_hostHeight = computed(() => typeof this.height() === 'number' ? `${this.height()}px` : this.height(), ...(ngDevMode ? [{ debugName: "_hostHeight" }] : /* istanbul ignore next */ []));
|
|
7516
|
-
ngAfterViewInit() {
|
|
7517
|
-
this._createChart();
|
|
7518
|
-
effect(() => {
|
|
7519
|
-
const currentType = this.type();
|
|
7520
|
-
const currentData = this.data();
|
|
7521
|
-
if (this._chart) {
|
|
7522
|
-
this._chart.config.type = currentType;
|
|
7523
|
-
this._chart.data = applyChartDefaults(currentType, currentData);
|
|
7524
|
-
this._chart.update();
|
|
7525
|
-
}
|
|
7526
|
-
}, { injector: this._injector });
|
|
7527
|
-
}
|
|
7528
|
-
_createChart() {
|
|
7529
|
-
const ctx = this.canvasRef.nativeElement.getContext('2d');
|
|
7530
|
-
if (!ctx)
|
|
7531
|
-
return;
|
|
7532
|
-
const type = untracked(() => this.type());
|
|
7533
|
-
this._chart = new Chart(ctx, {
|
|
7534
|
-
type,
|
|
7535
|
-
data: applyChartDefaults(type, untracked(() => this.data())),
|
|
7536
|
-
options: { ...(NO_SCALE_TYPES.includes(type) ? CLX_CHART_DEFAULTS_NO_SCALES : CLX_CHART_DEFAULTS), ...untracked(() => this.options()) },
|
|
7537
|
-
});
|
|
7538
|
-
}
|
|
7539
|
-
ngOnDestroy() {
|
|
7540
|
-
this._chart?.destroy();
|
|
7541
|
-
}
|
|
7542
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7543
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxChartComponent, isStandalone: true, selector: "clx-chart", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true }], ngImport: i0, template: `
|
|
7544
|
-
<div class="clx-chart-container" [style.height]="_hostHeight()" [class.clx-loading]="loading()">
|
|
7545
|
-
<canvas #canvas role="img" [attr.aria-label]="ariaLabel() || 'Chart'"></canvas>
|
|
7546
|
-
|
|
7547
|
-
@if (loading()) {
|
|
7548
|
-
<div class="clx-chart-loader">
|
|
7549
|
-
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-500"></div>
|
|
7550
|
-
</div>
|
|
7551
|
-
}
|
|
7552
|
-
</div>
|
|
7553
|
-
`, isInline: true, styles: [":host{display:block;width:100%}.clx-chart-container{position:relative;width:100%}canvas{display:block;width:100%!important}.clx-chart-loader{position:absolute;inset:0;background:#fff9;display:flex;align-items:center;justify-content:center;z-index:10;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
7554
|
-
}
|
|
7555
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxChartComponent, decorators: [{
|
|
7556
|
-
type: Component,
|
|
7557
|
-
args: [{ selector: 'clx-chart', standalone: true, template: `
|
|
7558
|
-
<div class="clx-chart-container" [style.height]="_hostHeight()" [class.clx-loading]="loading()">
|
|
7559
|
-
<canvas #canvas role="img" [attr.aria-label]="ariaLabel() || 'Chart'"></canvas>
|
|
7560
|
-
|
|
7561
|
-
@if (loading()) {
|
|
7562
|
-
<div class="clx-chart-loader">
|
|
7563
|
-
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-500"></div>
|
|
7564
|
-
</div>
|
|
7565
|
-
}
|
|
7566
|
-
</div>
|
|
7567
|
-
`, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%}.clx-chart-container{position:relative;width:100%}canvas{display:block;width:100%!important}.clx-chart-loader{position:absolute;inset:0;background:#fff9;display:flex;align-items:center;justify-content:center;z-index:10;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}\n"] }]
|
|
7568
|
-
}], propDecorators: { canvasRef: [{
|
|
7569
|
-
type: ViewChild,
|
|
7570
|
-
args: ['canvas']
|
|
7571
|
-
}], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }] } });
|
|
7572
|
-
|
|
7573
7393
|
const COLOR_PICKER_SIZE_MAP = {
|
|
7574
7394
|
sm: { minH: 'min-h-8', text: 'text-sm', label: 'text-xs font-medium', hint: 'text-xs', px: 'px-2.5', swatchSz: 'w-4 h-4', btnSize: 'xs' },
|
|
7575
7395
|
md: { minH: 'min-h-10', text: 'text-sm', label: 'text-sm font-medium', hint: 'text-xs', px: 'px-3', swatchSz: 'w-5 h-5', btnSize: 'sm' },
|
|
@@ -7743,7 +7563,7 @@ class ClxColorPickerComponent {
|
|
|
7743
7563
|
}, ...(ngDevMode ? [{ debugName: "_displayClass" }] : /* istanbul ignore next */ []));
|
|
7744
7564
|
_triggerClass = computed(() => {
|
|
7745
7565
|
const s = this._sizeConfig();
|
|
7746
|
-
const base = `relative flex items-center ${resolveRadius(this._themeSvc.config().borderRadius)} border transition-
|
|
7566
|
+
const base = `relative flex items-center ${resolveRadius(this._themeSvc.config().borderRadius)} border transition-[border-color,box-shadow] duration-200 outline-none w-full`;
|
|
7747
7567
|
if (this._disabled()) {
|
|
7748
7568
|
return `${base} ${s.minH} ${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED} cursor-not-allowed opacity-60`;
|
|
7749
7569
|
}
|
|
@@ -8056,7 +7876,7 @@ class ClxColorPickerComponent {
|
|
|
8056
7876
|
@for (swatch of presets(); track swatch) {
|
|
8057
7877
|
<button
|
|
8058
7878
|
type="button"
|
|
8059
|
-
class="w-6 h-6 rounded border border-black/10 transition-
|
|
7879
|
+
class="w-6 h-6 rounded border border-black/10 transition-[transform,box-shadow] duration-150 hover:scale-110 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400"
|
|
8060
7880
|
[style.background-color]="swatch"
|
|
8061
7881
|
[title]="swatch"
|
|
8062
7882
|
(click)="_selectPreset(swatch)">
|
|
@@ -8223,7 +8043,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
8223
8043
|
@for (swatch of presets(); track swatch) {
|
|
8224
8044
|
<button
|
|
8225
8045
|
type="button"
|
|
8226
|
-
class="w-6 h-6 rounded border border-black/10 transition-
|
|
8046
|
+
class="w-6 h-6 rounded border border-black/10 transition-[transform,box-shadow] duration-150 hover:scale-110 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-slate-400"
|
|
8227
8047
|
[style.background-color]="swatch"
|
|
8228
8048
|
[title]="swatch"
|
|
8229
8049
|
(click)="_selectPreset(swatch)">
|
|
@@ -8345,7 +8165,7 @@ class ClxDatepickerComponent {
|
|
|
8345
8165
|
const focus = resolveColor(this._color()).focus;
|
|
8346
8166
|
const border = this._disabled() ? `${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED}` : `${status.border} focus:outline-none ${focus}`;
|
|
8347
8167
|
const cursor = this._disabled() ? 'cursor-not-allowed opacity-60' : 'cursor-pointer';
|
|
8348
|
-
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-
|
|
8168
|
+
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-[border-color,box-shadow] duration-200 select-none`;
|
|
8349
8169
|
}, ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
|
|
8350
8170
|
_displayClass = computed(() => {
|
|
8351
8171
|
const hasValue = !!this._value();
|
|
@@ -8763,7 +8583,7 @@ class ClxTimepickerComponent {
|
|
|
8763
8583
|
const focus = resolveColor(this._color()).focus;
|
|
8764
8584
|
const border = this._disabled() ? `${CLX_BORDER_DISABLED} ${CLX_BG_DISABLED}` : `${status.border} focus:outline-none ${focus}`;
|
|
8765
8585
|
const cursor = this._disabled() ? 'cursor-not-allowed opacity-60' : 'cursor-pointer';
|
|
8766
|
-
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-
|
|
8586
|
+
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-[border-color,box-shadow] duration-200 select-none`;
|
|
8767
8587
|
}, ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
|
|
8768
8588
|
_displayClass = computed(() => {
|
|
8769
8589
|
const hasValue = !!this._value();
|
|
@@ -9144,7 +8964,7 @@ class ClxDateRangePickerComponent {
|
|
|
9144
8964
|
const focus = resolveColor(this._color()).focus;
|
|
9145
8965
|
const border = this._disabled() ? 'border-gray-200 bg-gray-50' : `${status.border} focus:outline-none ${focus}`;
|
|
9146
8966
|
const cursor = this._disabled() ? 'cursor-not-allowed opacity-60' : 'cursor-pointer';
|
|
9147
|
-
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-
|
|
8967
|
+
return `relative flex items-stretch ${size.trigger} ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${cursor} overflow-hidden transition-[border-color,box-shadow] duration-200 select-none`;
|
|
9148
8968
|
}, ...(ngDevMode ? [{ debugName: "_triggerClass" }] : /* istanbul ignore next */ []));
|
|
9149
8969
|
_displayClass = computed(() => {
|
|
9150
8970
|
const color = this._disabled() ? 'text-clx-text-faint' : this._hasValue() ? 'text-clx-text-label' : 'text-clx-text-faint';
|
|
@@ -10004,7 +9824,7 @@ class ClxEditorComponent {
|
|
|
10004
9824
|
const focus = this.status() !== 'default'
|
|
10005
9825
|
? statusCfg.ring.replace(/focus:/g, 'focus-within:')
|
|
10006
9826
|
: resolveColor(this._color()).focusWithin;
|
|
10007
|
-
return `${r} border ${statusCfg.border} ${focus} overflow-hidden bg-clx-surface transition-
|
|
9827
|
+
return `${r} border ${statusCfg.border} ${focus} overflow-hidden bg-clx-surface transition-[border-color,box-shadow] duration-200`;
|
|
10008
9828
|
}, ...(ngDevMode ? [{ debugName: "_shellClass" }] : /* istanbul ignore next */ []));
|
|
10009
9829
|
_toolbarClass = computed(() => `flex flex-wrap items-center gap-1 ${this._sizeCfg().toolbar} border-b border-clx-border-soft bg-clx-surface`, ...(ngDevMode ? [{ debugName: "_toolbarClass" }] : /* istanbul ignore next */ []));
|
|
10010
9830
|
_bodyClass = computed(() => {
|
|
@@ -10644,11 +10464,11 @@ class ClxSwitchComponent {
|
|
|
10644
10464
|
_onTouched = () => { };
|
|
10645
10465
|
_sizeConfig = computed(() => SWITCH_SIZE_MAP[this._size()], ...(ngDevMode ? [{ debugName: "_sizeConfig" }] : /* istanbul ignore next */ []));
|
|
10646
10466
|
_trackClass = computed(() => {
|
|
10647
|
-
const base = `${this._sizeConfig().track} relative rounded-full transition-
|
|
10467
|
+
const base = `${this._sizeConfig().track} relative rounded-full transition-colors duration-200 flex-shrink-0`;
|
|
10648
10468
|
return `${base} ${this._checked() ? resolveColor(this._color()).bg : 'bg-gray-300'}`;
|
|
10649
10469
|
}, ...(ngDevMode ? [{ debugName: "_trackClass" }] : /* istanbul ignore next */ []));
|
|
10650
10470
|
_thumbClass = computed(() => {
|
|
10651
|
-
const base = `${this._sizeConfig().thumb} absolute top-[2px] left-[2px] bg-clx-surface rounded-full shadow-sm transition-
|
|
10471
|
+
const base = `${this._sizeConfig().thumb} absolute top-[2px] left-[2px] bg-clx-surface rounded-full shadow-sm transition-transform duration-200`;
|
|
10652
10472
|
return this._checked() ? `${base} ${this._sizeConfig().translate}` : base;
|
|
10653
10473
|
}, ...(ngDevMode ? [{ debugName: "_thumbClass" }] : /* istanbul ignore next */ []));
|
|
10654
10474
|
_labelClass = computed(() => `${this._sizeConfig().label} text-clx-text-label leading-none`, ...(ngDevMode ? [{ debugName: "_labelClass" }] : /* istanbul ignore next */ []));
|
|
@@ -10830,13 +10650,13 @@ class ClxTextareaComponent {
|
|
|
10830
10650
|
_wrapperClass = computed(() => {
|
|
10831
10651
|
const statusCfg = this._statusCfg();
|
|
10832
10652
|
if (this._disabled()) {
|
|
10833
|
-
return `flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${CLX_BORDER_DISABLED} overflow-hidden transition-
|
|
10653
|
+
return `flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${CLX_BORDER_DISABLED} overflow-hidden transition-[border-color,box-shadow] duration-200`;
|
|
10834
10654
|
}
|
|
10835
10655
|
const focusCls = this.status() !== 'default'
|
|
10836
10656
|
? statusCfg.ring.replace(/focus:/g, 'focus-within:')
|
|
10837
10657
|
: resolveColor(this._color()).focusWithin;
|
|
10838
10658
|
const border = statusCfg.border;
|
|
10839
|
-
return `flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focusCls} overflow-hidden transition-
|
|
10659
|
+
return `flex items-stretch ${resolveRadius(this._themeSvc.config().borderRadius)} border ${border} ${focusCls} overflow-hidden transition-[border-color,box-shadow] duration-200`;
|
|
10840
10660
|
}, ...(ngDevMode ? [{ debugName: "_wrapperClass" }] : /* istanbul ignore next */ []));
|
|
10841
10661
|
/** Prefix icon cell — flex column, full height of the wrapper */
|
|
10842
10662
|
_prefixCellCls = computed(() => {
|
|
@@ -11070,7 +10890,7 @@ class ClxUploadComponent {
|
|
|
11070
10890
|
_zoneClass = computed(() => {
|
|
11071
10891
|
const base = [
|
|
11072
10892
|
'flex flex-col items-center justify-center text-center',
|
|
11073
|
-
`w-full ${resolveContainerRadius(this._themeSvc.config().borderRadius)} border-2 border-dashed transition-
|
|
10893
|
+
`w-full ${resolveContainerRadius(this._themeSvc.config().borderRadius)} border-2 border-dashed transition-colors duration-200`,
|
|
11074
10894
|
this._sizeConfig().zone,
|
|
11075
10895
|
].join(' ');
|
|
11076
10896
|
const t = resolveColor(this._color());
|
|
@@ -11551,7 +11371,7 @@ class ClxWizardComponent {
|
|
|
11551
11371
|
}, ...(ngDevMode ? [{ debugName: "_rootClass" }] : /* istanbul ignore next */ []));
|
|
11552
11372
|
// ── Circle (vertical) ─────────────────────────────────────────────────────
|
|
11553
11373
|
_circleClass(i) {
|
|
11554
|
-
const base = 'relative z-10 flex items-center justify-center w-9 h-9 rounded-full transition-
|
|
11374
|
+
const base = 'relative z-10 flex items-center justify-center w-9 h-9 rounded-full transition-colors duration-200 shrink-0 focus:outline-none';
|
|
11555
11375
|
const status = this._stepStatus(i);
|
|
11556
11376
|
const color = this._color();
|
|
11557
11377
|
const ptr = !this._isTabDisabled(i) ? 'cursor-pointer' : 'cursor-default';
|
|
@@ -12040,7 +11860,7 @@ const NAV_ITEM_L1 = 'px-6 py-3';
|
|
|
12040
11860
|
const NAV_ITEM_L2 = 'pl-4 pr-3 py-2';
|
|
12041
11861
|
const NAV_ITEM_IDLE = 'text-clx-text-subtle';
|
|
12042
11862
|
// ── Children container ─────────────────────────────────────────────────────────
|
|
12043
|
-
const NAV_CHILDREN_WRAPPER = 'grid transition-
|
|
11863
|
+
const NAV_CHILDREN_WRAPPER = 'grid transition-[grid-template-rows] duration-300 ease-in-out';
|
|
12044
11864
|
const NAV_CHILDREN_INNER = 'overflow-hidden';
|
|
12045
11865
|
const NAV_CHILDREN_LIST = 'ml-6 py-1 space-y-0.5';
|
|
12046
11866
|
|
|
@@ -14916,7 +14736,7 @@ class ClxProgressBarComponent {
|
|
|
14916
14736
|
|
|
14917
14737
|
<!-- Fill -->
|
|
14918
14738
|
<div
|
|
14919
|
-
class="h-full rounded-full transition-
|
|
14739
|
+
class="h-full rounded-full transition-[width,background-color] duration-500 ease-out"
|
|
14920
14740
|
[class]="_fillCls()"
|
|
14921
14741
|
[style.width]="variant() === 'indeterminate' ? '40%' : _pct() + '%'">
|
|
14922
14742
|
</div>
|
|
@@ -14951,7 +14771,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
14951
14771
|
|
|
14952
14772
|
<!-- Fill -->
|
|
14953
14773
|
<div
|
|
14954
|
-
class="h-full rounded-full transition-
|
|
14774
|
+
class="h-full rounded-full transition-[width,background-color] duration-500 ease-out"
|
|
14955
14775
|
[class]="_fillCls()"
|
|
14956
14776
|
[style.width]="variant() === 'indeterminate' ? '40%' : _pct() + '%'">
|
|
14957
14777
|
</div>
|
|
@@ -15204,5 +15024,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15204
15024
|
* Generated bundle index. Do not edit.
|
|
15205
15025
|
*/
|
|
15206
15026
|
|
|
15207
|
-
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, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective,
|
|
15027
|
+
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, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxModalComponent, ClxModalService, ClxNavGroupComponent, ClxNumberComponent, ClxPageEmptyComponent, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, 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 };
|
|
15208
15028
|
//# sourceMappingURL=codexly-ui.mjs.map
|