codexly-ui 0.14.4 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/codexly-ui.mjs +634 -93
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +175 -19
package/fesm2022/codexly-ui.mjs
CHANGED
|
@@ -10,6 +10,8 @@ import * as i1 from '@angular/cdk/overlay';
|
|
|
10
10
|
import { ScrollStrategyOptions, OverlayModule } from '@angular/cdk/overlay';
|
|
11
11
|
import { ScrollingModule, CdkScrollable } from '@angular/cdk/scrolling';
|
|
12
12
|
import { Router, NavigationEnd, RouterLink, RouterLinkActive } from '@angular/router';
|
|
13
|
+
import * as i1$2 from '@angular/cdk/drag-drop';
|
|
14
|
+
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
13
15
|
|
|
14
16
|
// ── Parse 'red' | 'red-500' → { color, shade } ───────────────────────────────
|
|
15
17
|
function parseColorInput(input) {
|
|
@@ -2147,6 +2149,9 @@ class ClxProgressBarComponent {
|
|
|
2147
2149
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2148
2150
|
showValue = input(false, ...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
|
|
2149
2151
|
valueFormat = input('percent', ...(ngDevMode ? [{ debugName: "valueFormat" }] : /* istanbul ignore next */ []));
|
|
2152
|
+
/** Only read when variant()==='segmented' — ignores value()/max() entirely, each segment's
|
|
2153
|
+
* width is its own value as a fraction of the segments' combined total. */
|
|
2154
|
+
segments = input([], ...(ngDevMode ? [{ debugName: "segments" }] : /* istanbul ignore next */ []));
|
|
2150
2155
|
_pct = computed(() => {
|
|
2151
2156
|
const m = this.max();
|
|
2152
2157
|
if (!m)
|
|
@@ -2177,8 +2182,17 @@ class ClxProgressBarComponent {
|
|
|
2177
2182
|
cls += ' clx-pb-striped';
|
|
2178
2183
|
return cls;
|
|
2179
2184
|
}, ...(ngDevMode ? [{ debugName: "_fillCls" }] : /* istanbul ignore next */ []));
|
|
2185
|
+
_segmentPcts = computed(() => {
|
|
2186
|
+
const segs = this.segments();
|
|
2187
|
+
const total = segs.reduce((sum, s) => sum + s.value, 0) || 1;
|
|
2188
|
+
return segs.map(s => ({
|
|
2189
|
+
pct: (s.value / total) * 100,
|
|
2190
|
+
cls: resolveColor(s.color).bg,
|
|
2191
|
+
label: s.label,
|
|
2192
|
+
}));
|
|
2193
|
+
}, ...(ngDevMode ? [{ debugName: "_segmentPcts" }] : /* istanbul ignore next */ []));
|
|
2180
2194
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProgressBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2181
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProgressBarComponent, isStandalone: true, selector: "clx-progress-bar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex flex-col gap-1.5 w-full" }, ngImport: i0, template: `
|
|
2195
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxProgressBarComponent, isStandalone: true, selector: "clx-progress-bar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, valueFormat: { classPropertyName: "valueFormat", publicName: "valueFormat", isSignal: true, isRequired: false, transformFunction: null }, segments: { classPropertyName: "segments", publicName: "segments", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex flex-col gap-1.5 w-full" }, ngImport: i0, template: `
|
|
2182
2196
|
@if (label() || showValue()) {
|
|
2183
2197
|
<div class="flex items-center justify-between gap-2">
|
|
2184
2198
|
@if (label()) {
|
|
@@ -2192,23 +2206,42 @@ class ClxProgressBarComponent {
|
|
|
2192
2206
|
</div>
|
|
2193
2207
|
}
|
|
2194
2208
|
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
[class]="_trackH()"
|
|
2199
|
-
role="progressbar"
|
|
2200
|
-
[attr.aria-valuenow]="variant() === 'indeterminate' ? null : value()"
|
|
2201
|
-
[attr.aria-valuemin]="0"
|
|
2202
|
-
[attr.aria-valuemax]="max()"
|
|
2203
|
-
[attr.aria-label]="label() || null">
|
|
2204
|
-
|
|
2205
|
-
<!-- Fill -->
|
|
2209
|
+
@if (variant() === 'segmented') {
|
|
2210
|
+
<!-- Track: one flex child per segment, own color each, widths normalized to the segments'
|
|
2211
|
+
own value sum — independent of value()/max(), which this variant ignores. -->
|
|
2206
2212
|
<div
|
|
2207
|
-
class="
|
|
2208
|
-
[class]="
|
|
2209
|
-
|
|
2213
|
+
class="w-full flex overflow-hidden rounded-full bg-clx-surface-2 gap-0.5"
|
|
2214
|
+
[class]="_trackH()"
|
|
2215
|
+
role="img"
|
|
2216
|
+
[attr.aria-label]="label() || null">
|
|
2217
|
+
@for (seg of _segmentPcts(); track $index) {
|
|
2218
|
+
<div
|
|
2219
|
+
class="h-full first:rounded-l-full last:rounded-r-full"
|
|
2220
|
+
[class]="seg.cls"
|
|
2221
|
+
[style.width.%]="seg.pct"
|
|
2222
|
+
[attr.title]="seg.label">
|
|
2223
|
+
</div>
|
|
2224
|
+
}
|
|
2210
2225
|
</div>
|
|
2211
|
-
|
|
2226
|
+
} @else {
|
|
2227
|
+
<!-- Track -->
|
|
2228
|
+
<div
|
|
2229
|
+
class="w-full overflow-hidden rounded-full bg-clx-surface-2"
|
|
2230
|
+
[class]="_trackH()"
|
|
2231
|
+
role="progressbar"
|
|
2232
|
+
[attr.aria-valuenow]="variant() === 'indeterminate' ? null : value()"
|
|
2233
|
+
[attr.aria-valuemin]="0"
|
|
2234
|
+
[attr.aria-valuemax]="max()"
|
|
2235
|
+
[attr.aria-label]="label() || null">
|
|
2236
|
+
|
|
2237
|
+
<!-- Fill -->
|
|
2238
|
+
<div
|
|
2239
|
+
class="h-full rounded-full transition-[width,background-color] duration-500 ease-out"
|
|
2240
|
+
[class]="_fillCls()"
|
|
2241
|
+
[style.width]="variant() === 'indeterminate' ? '40%' : _pct() + '%'">
|
|
2242
|
+
</div>
|
|
2243
|
+
</div>
|
|
2244
|
+
}
|
|
2212
2245
|
`, isInline: true, styles: ["@keyframes clx-pb-indeterminate{0%{transform:translate(-100%) scaleX(.4)}40%{transform:translate(0) scaleX(.4)}to{transform:translate(100%) scaleX(.4)}}.clx-pb-indeterminate{animation:clx-pb-indeterminate 1.4s ease-in-out infinite}@keyframes clx-pb-stripe{0%{background-position:1rem 0}to{background-position:0 0}}.clx-pb-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.18) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.18) 50%,rgba(255,255,255,.18) 75%,transparent 75%,transparent);background-size:1rem 1rem;animation:clx-pb-stripe 1s linear infinite}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2213
2246
|
}
|
|
2214
2247
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxProgressBarComponent, decorators: [{
|
|
@@ -2227,25 +2260,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
2227
2260
|
</div>
|
|
2228
2261
|
}
|
|
2229
2262
|
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
[class]="_trackH()"
|
|
2234
|
-
role="progressbar"
|
|
2235
|
-
[attr.aria-valuenow]="variant() === 'indeterminate' ? null : value()"
|
|
2236
|
-
[attr.aria-valuemin]="0"
|
|
2237
|
-
[attr.aria-valuemax]="max()"
|
|
2238
|
-
[attr.aria-label]="label() || null">
|
|
2239
|
-
|
|
2240
|
-
<!-- Fill -->
|
|
2263
|
+
@if (variant() === 'segmented') {
|
|
2264
|
+
<!-- Track: one flex child per segment, own color each, widths normalized to the segments'
|
|
2265
|
+
own value sum — independent of value()/max(), which this variant ignores. -->
|
|
2241
2266
|
<div
|
|
2242
|
-
class="
|
|
2243
|
-
[class]="
|
|
2244
|
-
|
|
2267
|
+
class="w-full flex overflow-hidden rounded-full bg-clx-surface-2 gap-0.5"
|
|
2268
|
+
[class]="_trackH()"
|
|
2269
|
+
role="img"
|
|
2270
|
+
[attr.aria-label]="label() || null">
|
|
2271
|
+
@for (seg of _segmentPcts(); track $index) {
|
|
2272
|
+
<div
|
|
2273
|
+
class="h-full first:rounded-l-full last:rounded-r-full"
|
|
2274
|
+
[class]="seg.cls"
|
|
2275
|
+
[style.width.%]="seg.pct"
|
|
2276
|
+
[attr.title]="seg.label">
|
|
2277
|
+
</div>
|
|
2278
|
+
}
|
|
2245
2279
|
</div>
|
|
2246
|
-
|
|
2280
|
+
} @else {
|
|
2281
|
+
<!-- Track -->
|
|
2282
|
+
<div
|
|
2283
|
+
class="w-full overflow-hidden rounded-full bg-clx-surface-2"
|
|
2284
|
+
[class]="_trackH()"
|
|
2285
|
+
role="progressbar"
|
|
2286
|
+
[attr.aria-valuenow]="variant() === 'indeterminate' ? null : value()"
|
|
2287
|
+
[attr.aria-valuemin]="0"
|
|
2288
|
+
[attr.aria-valuemax]="max()"
|
|
2289
|
+
[attr.aria-label]="label() || null">
|
|
2290
|
+
|
|
2291
|
+
<!-- Fill -->
|
|
2292
|
+
<div
|
|
2293
|
+
class="h-full rounded-full transition-[width,background-color] duration-500 ease-out"
|
|
2294
|
+
[class]="_fillCls()"
|
|
2295
|
+
[style.width]="variant() === 'indeterminate' ? '40%' : _pct() + '%'">
|
|
2296
|
+
</div>
|
|
2297
|
+
</div>
|
|
2298
|
+
}
|
|
2247
2299
|
`, styles: ["@keyframes clx-pb-indeterminate{0%{transform:translate(-100%) scaleX(.4)}40%{transform:translate(0) scaleX(.4)}to{transform:translate(100%) scaleX(.4)}}.clx-pb-indeterminate{animation:clx-pb-indeterminate 1.4s ease-in-out infinite}@keyframes clx-pb-stripe{0%{background-position:1rem 0}to{background-position:0 0}}.clx-pb-striped{background-image:linear-gradient(45deg,rgba(255,255,255,.18) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.18) 50%,rgba(255,255,255,.18) 75%,transparent 75%,transparent);background-size:1rem 1rem;animation:clx-pb-stripe 1s linear infinite}\n"] }]
|
|
2248
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }] } });
|
|
2300
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], valueFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueFormat", required: false }] }], segments: [{ type: i0.Input, args: [{ isSignal: true, alias: "segments", required: false }] }] } });
|
|
2249
2301
|
|
|
2250
2302
|
class ClxRatingComponent {
|
|
2251
2303
|
_themeSvc = inject(ClxThemeService);
|
|
@@ -10549,6 +10601,9 @@ class ClxWizardComponent {
|
|
|
10549
10601
|
prevLabel = input('Anterior', ...(ngDevMode ? [{ debugName: "prevLabel" }] : /* istanbul ignore next */ []));
|
|
10550
10602
|
nextLabel = input('Siguiente', ...(ngDevMode ? [{ debugName: "nextLabel" }] : /* istanbul ignore next */ []));
|
|
10551
10603
|
finishLabel = input('Finalizar', ...(ngDevMode ? [{ debugName: "finishLabel" }] : /* istanbul ignore next */ []));
|
|
10604
|
+
/** Shows a spinner on the finish button and disables it — for an async (finish) handler that
|
|
10605
|
+
* takes a moment (an HTTP call), so the consumer doesn't need its own separate loading label. */
|
|
10606
|
+
finishLoading = input(false, ...(ngDevMode ? [{ debugName: "finishLoading" }] : /* istanbul ignore next */ []));
|
|
10552
10607
|
// ── Outputs ────────────────────────────────────────────────────────────────
|
|
10553
10608
|
stepChange = output();
|
|
10554
10609
|
finish = output();
|
|
@@ -10657,7 +10712,7 @@ class ClxWizardComponent {
|
|
|
10657
10712
|
return `${base} border-2 border-clx-border text-clx-text-subtle bg-clx-surface ${ptr}`;
|
|
10658
10713
|
}
|
|
10659
10714
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxWizardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10660
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxWizardComponent, isStandalone: true, selector: "clx-wizard", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, activeTextColor: { classPropertyName: "activeTextColor", publicName: "activeTextColor", isSignal: true, isRequired: false, transformFunction: null }, underlineColor: { classPropertyName: "underlineColor", publicName: "underlineColor", isSignal: true, isRequired: false, transformFunction: null }, stepColor: { classPropertyName: "stepColor", publicName: "stepColor", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, finishLabel: { classPropertyName: "finishLabel", publicName: "finishLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepChange: "stepChange", finish: "finish" }, queries: [{ propertyName: "_stepQuery", predicate: ClxStepComponent }], ngImport: i0, template: `
|
|
10715
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxWizardComponent, isStandalone: true, selector: "clx-wizard", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, activeTextColor: { classPropertyName: "activeTextColor", publicName: "activeTextColor", isSignal: true, isRequired: false, transformFunction: null }, underlineColor: { classPropertyName: "underlineColor", publicName: "underlineColor", isSignal: true, isRequired: false, transformFunction: null }, stepColor: { classPropertyName: "stepColor", publicName: "stepColor", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, prevLabel: { classPropertyName: "prevLabel", publicName: "prevLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, finishLabel: { classPropertyName: "finishLabel", publicName: "finishLabel", isSignal: true, isRequired: false, transformFunction: null }, finishLoading: { classPropertyName: "finishLoading", publicName: "finishLoading", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepChange: "stepChange", finish: "finish" }, queries: [{ propertyName: "_stepQuery", predicate: ClxStepComponent }], ngImport: i0, template: `
|
|
10661
10716
|
<div [class]="_rootClass()">
|
|
10662
10717
|
|
|
10663
10718
|
<!-- ══ HORIZONTAL: clx-tabs indicator ═══════════════════════════════ -->
|
|
@@ -10755,7 +10810,8 @@ class ClxWizardComponent {
|
|
|
10755
10810
|
size="sm"
|
|
10756
10811
|
icon="check_circle"
|
|
10757
10812
|
iconPosition="right"
|
|
10758
|
-
[disabled]="!_currentStepValid()"
|
|
10813
|
+
[disabled]="!_currentStepValid() || finishLoading()"
|
|
10814
|
+
[loading]="finishLoading()"
|
|
10759
10815
|
(click)="_onFinish()"
|
|
10760
10816
|
>{{ finishLabel() }}</button>
|
|
10761
10817
|
}
|
|
@@ -10864,7 +10920,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
10864
10920
|
size="sm"
|
|
10865
10921
|
icon="check_circle"
|
|
10866
10922
|
iconPosition="right"
|
|
10867
|
-
[disabled]="!_currentStepValid()"
|
|
10923
|
+
[disabled]="!_currentStepValid() || finishLoading()"
|
|
10924
|
+
[loading]="finishLoading()"
|
|
10868
10925
|
(click)="_onFinish()"
|
|
10869
10926
|
>{{ finishLabel() }}</button>
|
|
10870
10927
|
}
|
|
@@ -10872,7 +10929,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
10872
10929
|
</div>
|
|
10873
10930
|
</div>
|
|
10874
10931
|
`, styles: ["@keyframes clx-wizard-fade-slide{0%{opacity:0;transform:translate(10px)}to{opacity:1;transform:translate(0)}}.clx-wizard-step-enter{animation:clx-wizard-fade-slide .22s cubic-bezier(.4,0,.2,1) both}@keyframes clx-wizard-fill{0%{width:0%}to{width:100%}}.clx-wizard-connector-fill{animation:clx-wizard-fill .3s ease both}clx-step[data-active=false]{display:none}\n"] }]
|
|
10875
|
-
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], activeTextColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTextColor", required: false }] }], underlineColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "underlineColor", required: false }] }], stepColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepColor", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], finishLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "finishLabel", required: false }] }], stepChange: [{ type: i0.Output, args: ["stepChange"] }], finish: [{ type: i0.Output, args: ["finish"] }], _stepQuery: [{
|
|
10932
|
+
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], activeTextColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeTextColor", required: false }] }], underlineColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "underlineColor", required: false }] }], stepColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepColor", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], prevLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "prevLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], finishLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "finishLabel", required: false }] }], finishLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "finishLoading", required: false }] }], stepChange: [{ type: i0.Output, args: ["stepChange"] }], finish: [{ type: i0.Output, args: ["finish"] }], _stepQuery: [{
|
|
10876
10933
|
type: ContentChildren,
|
|
10877
10934
|
args: [ClxStepComponent]
|
|
10878
10935
|
}] } });
|
|
@@ -15892,13 +15949,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
15892
15949
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], retryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabel", required: false }] }], backLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "backLabel", required: false }] }], errorId: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorId", required: false }] }], retry: [{ type: i0.Output, args: ["retry"] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
15893
15950
|
|
|
15894
15951
|
class ClxStatCardComponent {
|
|
15952
|
+
_themeSvc = inject(ClxThemeService);
|
|
15895
15953
|
metric = input.required(...(ngDevMode ? [{ debugName: "metric" }] : /* istanbul ignore next */ []));
|
|
15896
15954
|
chartData = input([30, 45, 28, 60, 40, 70, 55, 80, 50, 90], ...(ngDevMode ? [{ debugName: "chartData" }] : /* istanbul ignore next */ []));
|
|
15897
15955
|
color = input('indigo', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
15898
15956
|
layout = input('horizontal', ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
|
|
15899
15957
|
_hostClass = computed(() => {
|
|
15900
15958
|
const border = resolveColor(this.color()).borderLight;
|
|
15901
|
-
const
|
|
15959
|
+
const radius = resolveContainerRadius(this._themeSvc.config().borderRadius);
|
|
15960
|
+
const base = `bg-clx-surface ${radius} shadow-md border ${border} p-5 w-full overflow-hidden min-w-[260px]`;
|
|
15902
15961
|
return `flex items-center gap-4 ${base}`;
|
|
15903
15962
|
}, ...(ngDevMode ? [{ debugName: "_hostClass" }] : /* istanbul ignore next */ []));
|
|
15904
15963
|
_barHeights = computed(() => {
|
|
@@ -15916,6 +15975,13 @@ class ClxStatCardComponent {
|
|
|
15916
15975
|
return CLX_COLOR_HEX[color] ?? CLX_COLOR_HEX.indigo;
|
|
15917
15976
|
}, ...(ngDevMode ? [{ debugName: "_lineColor" }] : /* istanbul ignore next */ []));
|
|
15918
15977
|
_gradId = computed(() => `spark-grad-${this.color()}`, ...(ngDevMode ? [{ debugName: "_gradId" }] : /* istanbul ignore next */ []));
|
|
15978
|
+
/** A widget with no meaningful period-over-period comparison (e.g. a plain point-in-time count
|
|
15979
|
+
* like "pending commissions") passes trend: '' — hides the trend badge/row entirely instead of
|
|
15980
|
+
* rendering an empty pill with just an arrow icon and no text. */
|
|
15981
|
+
_hasTrend = computed(() => {
|
|
15982
|
+
const t = this.metric().trend;
|
|
15983
|
+
return t !== '' && t !== null && t !== undefined;
|
|
15984
|
+
}, ...(ngDevMode ? [{ debugName: "_hasTrend" }] : /* istanbul ignore next */ []));
|
|
15919
15985
|
_trendColor = computed(() => {
|
|
15920
15986
|
const d = this.metric().trendDirection;
|
|
15921
15987
|
return d === 'up' ? 'green' : d === 'down' ? 'red' : 'slate';
|
|
@@ -15926,7 +15992,7 @@ class ClxStatCardComponent {
|
|
|
15926
15992
|
}, ...(ngDevMode ? [{ debugName: "_trendArrowIcon" }] : /* istanbul ignore next */ []));
|
|
15927
15993
|
_trendTextClass = computed(() => {
|
|
15928
15994
|
const d = this.metric().trendDirection;
|
|
15929
|
-
return d === 'up' ? 'text-green-500' : d === 'down' ? 'text-red-500' : 'text-
|
|
15995
|
+
return d === 'up' ? 'text-green-500' : d === 'down' ? 'text-red-500' : 'text-clx-text-subtle';
|
|
15930
15996
|
}, ...(ngDevMode ? [{ debugName: "_trendTextClass" }] : /* istanbul ignore next */ []));
|
|
15931
15997
|
_trendIcon = computed(() => {
|
|
15932
15998
|
const d = this.metric().trendDirection;
|
|
@@ -15989,18 +16055,20 @@ class ClxStatCardComponent {
|
|
|
15989
16055
|
|
|
15990
16056
|
<!-- Text block -->
|
|
15991
16057
|
<div class="flex flex-col gap-1 min-w-0 flex-1">
|
|
15992
|
-
<span class="text-sm text-
|
|
15993
|
-
<span class="text-2xl font-semibold text-
|
|
16058
|
+
<span class="text-sm text-clx-text-muted truncate">{{ metric().title }}</span>
|
|
16059
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">
|
|
15994
16060
|
{{ _formattedValue() }}
|
|
15995
16061
|
</span>
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
|
|
16062
|
+
@if (_hasTrend()) {
|
|
16063
|
+
<span clx-badge
|
|
16064
|
+
[color]="_trendColor()"
|
|
16065
|
+
variant="light"
|
|
16066
|
+
shape="pill"
|
|
16067
|
+
class="self-start gap-1 mt-0.5">
|
|
16068
|
+
<span clx-icon [name]="_trendIcon()" size="xxs"></span>
|
|
16069
|
+
{{ metric().trend }}
|
|
16070
|
+
</span>
|
|
16071
|
+
}
|
|
16004
16072
|
</div>
|
|
16005
16073
|
|
|
16006
16074
|
<!-- Sparkline -->
|
|
@@ -16026,8 +16094,8 @@ class ClxStatCardComponent {
|
|
|
16026
16094
|
<div class="w-11 h-11 rounded-full flex items-center justify-center mb-2" [class]="_iconBgSubtle()">
|
|
16027
16095
|
<span clx-icon [name]="metric().icon" size="md" [class]="_iconTextBase()"></span>
|
|
16028
16096
|
</div>
|
|
16029
|
-
<span class="text-sm text-
|
|
16030
|
-
<span class="text-2xl font-semibold text-
|
|
16097
|
+
<span class="text-sm text-clx-text-muted truncate">{{ metric().title }}</span>
|
|
16098
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">{{ _formattedValue() }}</span>
|
|
16031
16099
|
</div>
|
|
16032
16100
|
|
|
16033
16101
|
<!-- Col derecha: barras + tendencia -->
|
|
@@ -16042,27 +16110,31 @@ class ClxStatCardComponent {
|
|
|
16042
16110
|
}
|
|
16043
16111
|
</div>
|
|
16044
16112
|
<!-- Tendencia -->
|
|
16045
|
-
|
|
16046
|
-
|
|
16047
|
-
|
|
16048
|
-
|
|
16049
|
-
|
|
16113
|
+
@if (_hasTrend()) {
|
|
16114
|
+
<div class="flex items-center gap-1 text-xs text-clx-text-subtle whitespace-nowrap">
|
|
16115
|
+
{{ metric().trendDirection === 'up' ? 'Increased By' : 'Decreased By' }}
|
|
16116
|
+
<span class="font-semibold" [class]="_trendTextClass()">{{ metric().trend }}</span>
|
|
16117
|
+
<span clx-icon [name]="_trendArrowIcon()" size="sm" [class]="_trendTextClass()"></span>
|
|
16118
|
+
</div>
|
|
16119
|
+
}
|
|
16050
16120
|
</div>
|
|
16051
16121
|
}
|
|
16052
16122
|
|
|
16053
16123
|
@if (layout() === 'vertical') {
|
|
16054
16124
|
<!-- Col izquierda: badge + valor + título -->
|
|
16055
16125
|
<div class="flex flex-col justify-between flex-1 min-w-0 gap-1">
|
|
16056
|
-
|
|
16057
|
-
|
|
16058
|
-
|
|
16059
|
-
|
|
16060
|
-
|
|
16061
|
-
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
|
|
16065
|
-
|
|
16126
|
+
@if (_hasTrend()) {
|
|
16127
|
+
<span clx-badge
|
|
16128
|
+
[color]="_trendColor()"
|
|
16129
|
+
variant="light"
|
|
16130
|
+
shape="pill"
|
|
16131
|
+
class="self-start gap-1">
|
|
16132
|
+
<span clx-icon [name]="_trendIcon()" size="xxs"></span>
|
|
16133
|
+
{{ metric().trend }}
|
|
16134
|
+
</span>
|
|
16135
|
+
}
|
|
16136
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">{{ _formattedValue() }}</span>
|
|
16137
|
+
<span class="text-xs font-semibold tracking-widest text-clx-text-subtle uppercase">{{ metric().title }}</span>
|
|
16066
16138
|
</div>
|
|
16067
16139
|
|
|
16068
16140
|
<!-- Col derecha: solo icono -->
|
|
@@ -16092,18 +16164,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
16092
16164
|
|
|
16093
16165
|
<!-- Text block -->
|
|
16094
16166
|
<div class="flex flex-col gap-1 min-w-0 flex-1">
|
|
16095
|
-
<span class="text-sm text-
|
|
16096
|
-
<span class="text-2xl font-semibold text-
|
|
16167
|
+
<span class="text-sm text-clx-text-muted truncate">{{ metric().title }}</span>
|
|
16168
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">
|
|
16097
16169
|
{{ _formattedValue() }}
|
|
16098
16170
|
</span>
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16171
|
+
@if (_hasTrend()) {
|
|
16172
|
+
<span clx-badge
|
|
16173
|
+
[color]="_trendColor()"
|
|
16174
|
+
variant="light"
|
|
16175
|
+
shape="pill"
|
|
16176
|
+
class="self-start gap-1 mt-0.5">
|
|
16177
|
+
<span clx-icon [name]="_trendIcon()" size="xxs"></span>
|
|
16178
|
+
{{ metric().trend }}
|
|
16179
|
+
</span>
|
|
16180
|
+
}
|
|
16107
16181
|
</div>
|
|
16108
16182
|
|
|
16109
16183
|
<!-- Sparkline -->
|
|
@@ -16129,8 +16203,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
16129
16203
|
<div class="w-11 h-11 rounded-full flex items-center justify-center mb-2" [class]="_iconBgSubtle()">
|
|
16130
16204
|
<span clx-icon [name]="metric().icon" size="md" [class]="_iconTextBase()"></span>
|
|
16131
16205
|
</div>
|
|
16132
|
-
<span class="text-sm text-
|
|
16133
|
-
<span class="text-2xl font-semibold text-
|
|
16206
|
+
<span class="text-sm text-clx-text-muted truncate">{{ metric().title }}</span>
|
|
16207
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">{{ _formattedValue() }}</span>
|
|
16134
16208
|
</div>
|
|
16135
16209
|
|
|
16136
16210
|
<!-- Col derecha: barras + tendencia -->
|
|
@@ -16145,27 +16219,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
16145
16219
|
}
|
|
16146
16220
|
</div>
|
|
16147
16221
|
<!-- Tendencia -->
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16222
|
+
@if (_hasTrend()) {
|
|
16223
|
+
<div class="flex items-center gap-1 text-xs text-clx-text-subtle whitespace-nowrap">
|
|
16224
|
+
{{ metric().trendDirection === 'up' ? 'Increased By' : 'Decreased By' }}
|
|
16225
|
+
<span class="font-semibold" [class]="_trendTextClass()">{{ metric().trend }}</span>
|
|
16226
|
+
<span clx-icon [name]="_trendArrowIcon()" size="sm" [class]="_trendTextClass()"></span>
|
|
16227
|
+
</div>
|
|
16228
|
+
}
|
|
16153
16229
|
</div>
|
|
16154
16230
|
}
|
|
16155
16231
|
|
|
16156
16232
|
@if (layout() === 'vertical') {
|
|
16157
16233
|
<!-- Col izquierda: badge + valor + título -->
|
|
16158
16234
|
<div class="flex flex-col justify-between flex-1 min-w-0 gap-1">
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16235
|
+
@if (_hasTrend()) {
|
|
16236
|
+
<span clx-badge
|
|
16237
|
+
[color]="_trendColor()"
|
|
16238
|
+
variant="light"
|
|
16239
|
+
shape="pill"
|
|
16240
|
+
class="self-start gap-1">
|
|
16241
|
+
<span clx-icon [name]="_trendIcon()" size="xxs"></span>
|
|
16242
|
+
{{ metric().trend }}
|
|
16243
|
+
</span>
|
|
16244
|
+
}
|
|
16245
|
+
<span class="text-2xl font-semibold text-clx-text leading-tight">{{ _formattedValue() }}</span>
|
|
16246
|
+
<span class="text-xs font-semibold tracking-widest text-clx-text-subtle uppercase">{{ metric().title }}</span>
|
|
16169
16247
|
</div>
|
|
16170
16248
|
|
|
16171
16249
|
<!-- Col derecha: solo icono -->
|
|
@@ -16177,6 +16255,469 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
16177
16255
|
}]
|
|
16178
16256
|
}], ctorParameters: () => [], propDecorators: { metric: [{ type: i0.Input, args: [{ isSignal: true, alias: "metric", required: true }] }], chartData: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartData", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }] } });
|
|
16179
16257
|
|
|
16258
|
+
/** Standard chrome for any dashboard widget (stat card, chart, table, list...) — header with
|
|
16259
|
+
* title + an optional drag handle + an overlay menu for per-widget actions (configure, resize,
|
|
16260
|
+
* remove), plus shared loading/empty/error states so individual widgets never re-implement them.
|
|
16261
|
+
* Widget content itself is projected via the default <ng-content>; callers keep full control of
|
|
16262
|
+
* what renders inside once state() is 'ready'. */
|
|
16263
|
+
class ClxWidgetCardComponent {
|
|
16264
|
+
_themeSvc = inject(ClxThemeService);
|
|
16265
|
+
title = input.required(...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
16266
|
+
state = input('ready', ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
16267
|
+
draggable = input(false, ...(ngDevMode ? [{ debugName: "draggable" }] : /* istanbul ignore next */ []));
|
|
16268
|
+
menuActions = input([], ...(ngDevMode ? [{ debugName: "menuActions" }] : /* istanbul ignore next */ []));
|
|
16269
|
+
menuLabel = input('Opciones del widget', ...(ngDevMode ? [{ debugName: "menuLabel" }] : /* istanbul ignore next */ []));
|
|
16270
|
+
emptyMessage = input('Sin datos en el rango seleccionado', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
16271
|
+
errorMessage = input('No se pudo cargar este widget', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
16272
|
+
retryLabel = input('Reintentar', ...(ngDevMode ? [{ debugName: "retryLabel" }] : /* istanbul ignore next */ []));
|
|
16273
|
+
menuAction = output();
|
|
16274
|
+
retry = output();
|
|
16275
|
+
_sso = inject(ScrollStrategyOptions);
|
|
16276
|
+
_scrollStrategy = this._sso.reposition();
|
|
16277
|
+
_positions = [
|
|
16278
|
+
{ originX: 'end', originY: 'bottom', overlayX: 'end', overlayY: 'top', offsetY: 4 },
|
|
16279
|
+
{ originX: 'end', originY: 'top', overlayX: 'end', overlayY: 'bottom', offsetY: -4 },
|
|
16280
|
+
];
|
|
16281
|
+
_menuOpen = signal(false, ...(ngDevMode ? [{ debugName: "_menuOpen" }] : /* istanbul ignore next */ []));
|
|
16282
|
+
_menuPanelClass = computed(() => {
|
|
16283
|
+
const t = resolveColor(this._themeSvc.cardBorderColor());
|
|
16284
|
+
return `w-48 p-1.5 bg-clx-surface rounded-xl shadow-xl border ${t.borderLight} overflow-hidden mt-1`;
|
|
16285
|
+
}, ...(ngDevMode ? [{ debugName: "_menuPanelClass" }] : /* istanbul ignore next */ []));
|
|
16286
|
+
_hostClass = computed(() => {
|
|
16287
|
+
const t = resolveColor(this._themeSvc.cardBorderColor());
|
|
16288
|
+
const radius = resolveContainerRadius(this._themeSvc.config().borderRadius);
|
|
16289
|
+
return `flex flex-col bg-clx-surface ${radius} border ${t.borderLight} shadow-sm overflow-hidden h-full`;
|
|
16290
|
+
}, ...(ngDevMode ? [{ debugName: "_hostClass" }] : /* istanbul ignore next */ []));
|
|
16291
|
+
_toggleMenu() { this._menuOpen.update(v => !v); }
|
|
16292
|
+
_closeMenu() { this._menuOpen.set(false); }
|
|
16293
|
+
_onMenuKeydown(event) {
|
|
16294
|
+
if (event.key === 'Escape')
|
|
16295
|
+
this._closeMenu();
|
|
16296
|
+
}
|
|
16297
|
+
_onMenuAction(action) {
|
|
16298
|
+
this.menuAction.emit(action);
|
|
16299
|
+
this._closeMenu();
|
|
16300
|
+
}
|
|
16301
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxWidgetCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16302
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxWidgetCardComponent, isStandalone: true, selector: "clx-widget-card", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, menuActions: { classPropertyName: "menuActions", publicName: "menuActions", isSignal: true, isRequired: false, transformFunction: null }, menuLabel: { classPropertyName: "menuLabel", publicName: "menuLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, retryLabel: { classPropertyName: "retryLabel", publicName: "retryLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuAction: "menuAction", retry: "retry" }, host: { properties: { "class": "_hostClass()" } }, ngImport: i0, template: `
|
|
16303
|
+
<div class="flex items-center justify-between gap-2 px-4 py-3 border-b border-clx-border-soft shrink-0">
|
|
16304
|
+
<div class="flex items-center gap-2 min-w-0">
|
|
16305
|
+
@if (draggable()) {
|
|
16306
|
+
<span clx-icon name="drag_indicator" size="sm" class="text-clx-text-subtle cursor-grab shrink-0"></span>
|
|
16307
|
+
}
|
|
16308
|
+
<p class="text-sm font-semibold text-clx-text-label truncate">{{ title() }}</p>
|
|
16309
|
+
</div>
|
|
16310
|
+
|
|
16311
|
+
@if (menuActions().length) {
|
|
16312
|
+
<button
|
|
16313
|
+
#origin="cdkOverlayOrigin"
|
|
16314
|
+
cdkOverlayOrigin
|
|
16315
|
+
type="button"
|
|
16316
|
+
class="shrink-0 w-7 h-7 rounded-lg flex items-center justify-center text-clx-text-subtle hover:bg-clx-surface-2 cursor-pointer"
|
|
16317
|
+
[attr.aria-label]="menuLabel()"
|
|
16318
|
+
(click)="_toggleMenu()">
|
|
16319
|
+
<span clx-icon name="more_vert" size="sm"></span>
|
|
16320
|
+
</button>
|
|
16321
|
+
|
|
16322
|
+
<ng-template
|
|
16323
|
+
cdkConnectedOverlay
|
|
16324
|
+
[cdkConnectedOverlayOrigin]="origin"
|
|
16325
|
+
[cdkConnectedOverlayOpen]="_menuOpen()"
|
|
16326
|
+
[cdkConnectedOverlayPositions]="_positions"
|
|
16327
|
+
[cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
|
|
16328
|
+
[cdkConnectedOverlayPush]="true"
|
|
16329
|
+
(overlayOutsideClick)="_closeMenu()"
|
|
16330
|
+
(overlayKeydown)="_onMenuKeydown($event)">
|
|
16331
|
+
<div [class]="_menuPanelClass()">
|
|
16332
|
+
@for (item of menuActions(); track item.action) {
|
|
16333
|
+
<button
|
|
16334
|
+
type="button"
|
|
16335
|
+
class="w-full text-left px-3 py-2 rounded-lg text-sm flex items-center gap-2 hover:bg-clx-surface-2 cursor-pointer"
|
|
16336
|
+
[class]="item.danger ? 'text-red-600' : 'text-clx-text-label'"
|
|
16337
|
+
(click)="_onMenuAction(item.action)">
|
|
16338
|
+
<span clx-icon [name]="item.icon" size="sm" [class]="item.danger ? 'text-red-600' : 'text-clx-text-subtle'"></span>
|
|
16339
|
+
{{ item.label }}
|
|
16340
|
+
</button>
|
|
16341
|
+
}
|
|
16342
|
+
</div>
|
|
16343
|
+
</ng-template>
|
|
16344
|
+
}
|
|
16345
|
+
</div>
|
|
16346
|
+
|
|
16347
|
+
<div class="flex-1 min-h-0 overflow-auto">
|
|
16348
|
+
@switch (state()) {
|
|
16349
|
+
@case ('loading') {
|
|
16350
|
+
<div class="h-full flex flex-col gap-3 justify-center p-4">
|
|
16351
|
+
<clx-skeleton variant="text" width="100%" height="12px" />
|
|
16352
|
+
<clx-skeleton variant="text" width="85%" height="12px" />
|
|
16353
|
+
<clx-skeleton variant="text" width="92%" height="12px" />
|
|
16354
|
+
</div>
|
|
16355
|
+
}
|
|
16356
|
+
@case ('empty') {
|
|
16357
|
+
<div class="h-full flex flex-col items-center justify-center gap-2 p-6 text-center">
|
|
16358
|
+
<div class="w-11 h-11 rounded-xl bg-clx-surface-2 flex items-center justify-center">
|
|
16359
|
+
<span clx-icon name="inbox" size="md" class="text-clx-text-subtle"></span>
|
|
16360
|
+
</div>
|
|
16361
|
+
<p class="text-xs text-clx-text-subtle">{{ emptyMessage() }}</p>
|
|
16362
|
+
</div>
|
|
16363
|
+
}
|
|
16364
|
+
@case ('error') {
|
|
16365
|
+
<div class="h-full flex flex-col items-center justify-center gap-3 p-6 text-center">
|
|
16366
|
+
<div class="w-11 h-11 rounded-xl bg-red-50 flex items-center justify-center">
|
|
16367
|
+
<span clx-icon name="error" size="md" class="text-red-600"></span>
|
|
16368
|
+
</div>
|
|
16369
|
+
<p class="text-xs text-clx-text-subtle">{{ errorMessage() }}</p>
|
|
16370
|
+
<button
|
|
16371
|
+
type="button"
|
|
16372
|
+
class="text-xs font-semibold px-3 py-1.5 rounded-lg border border-clx-border text-clx-text-label hover:bg-clx-surface-2 cursor-pointer"
|
|
16373
|
+
(click)="retry.emit()">
|
|
16374
|
+
{{ retryLabel() }}
|
|
16375
|
+
</button>
|
|
16376
|
+
</div>
|
|
16377
|
+
}
|
|
16378
|
+
@default {
|
|
16379
|
+
<ng-content />
|
|
16380
|
+
}
|
|
16381
|
+
}
|
|
16382
|
+
</div>
|
|
16383
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
16384
|
+
}
|
|
16385
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxWidgetCardComponent, decorators: [{
|
|
16386
|
+
type: Component,
|
|
16387
|
+
args: [{
|
|
16388
|
+
selector: 'clx-widget-card',
|
|
16389
|
+
standalone: true,
|
|
16390
|
+
imports: [OverlayModule, ClxIconComponent, ClxSkeletonComponent],
|
|
16391
|
+
encapsulation: ViewEncapsulation.None,
|
|
16392
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16393
|
+
host: { '[class]': '_hostClass()' },
|
|
16394
|
+
template: `
|
|
16395
|
+
<div class="flex items-center justify-between gap-2 px-4 py-3 border-b border-clx-border-soft shrink-0">
|
|
16396
|
+
<div class="flex items-center gap-2 min-w-0">
|
|
16397
|
+
@if (draggable()) {
|
|
16398
|
+
<span clx-icon name="drag_indicator" size="sm" class="text-clx-text-subtle cursor-grab shrink-0"></span>
|
|
16399
|
+
}
|
|
16400
|
+
<p class="text-sm font-semibold text-clx-text-label truncate">{{ title() }}</p>
|
|
16401
|
+
</div>
|
|
16402
|
+
|
|
16403
|
+
@if (menuActions().length) {
|
|
16404
|
+
<button
|
|
16405
|
+
#origin="cdkOverlayOrigin"
|
|
16406
|
+
cdkOverlayOrigin
|
|
16407
|
+
type="button"
|
|
16408
|
+
class="shrink-0 w-7 h-7 rounded-lg flex items-center justify-center text-clx-text-subtle hover:bg-clx-surface-2 cursor-pointer"
|
|
16409
|
+
[attr.aria-label]="menuLabel()"
|
|
16410
|
+
(click)="_toggleMenu()">
|
|
16411
|
+
<span clx-icon name="more_vert" size="sm"></span>
|
|
16412
|
+
</button>
|
|
16413
|
+
|
|
16414
|
+
<ng-template
|
|
16415
|
+
cdkConnectedOverlay
|
|
16416
|
+
[cdkConnectedOverlayOrigin]="origin"
|
|
16417
|
+
[cdkConnectedOverlayOpen]="_menuOpen()"
|
|
16418
|
+
[cdkConnectedOverlayPositions]="_positions"
|
|
16419
|
+
[cdkConnectedOverlayScrollStrategy]="_scrollStrategy"
|
|
16420
|
+
[cdkConnectedOverlayPush]="true"
|
|
16421
|
+
(overlayOutsideClick)="_closeMenu()"
|
|
16422
|
+
(overlayKeydown)="_onMenuKeydown($event)">
|
|
16423
|
+
<div [class]="_menuPanelClass()">
|
|
16424
|
+
@for (item of menuActions(); track item.action) {
|
|
16425
|
+
<button
|
|
16426
|
+
type="button"
|
|
16427
|
+
class="w-full text-left px-3 py-2 rounded-lg text-sm flex items-center gap-2 hover:bg-clx-surface-2 cursor-pointer"
|
|
16428
|
+
[class]="item.danger ? 'text-red-600' : 'text-clx-text-label'"
|
|
16429
|
+
(click)="_onMenuAction(item.action)">
|
|
16430
|
+
<span clx-icon [name]="item.icon" size="sm" [class]="item.danger ? 'text-red-600' : 'text-clx-text-subtle'"></span>
|
|
16431
|
+
{{ item.label }}
|
|
16432
|
+
</button>
|
|
16433
|
+
}
|
|
16434
|
+
</div>
|
|
16435
|
+
</ng-template>
|
|
16436
|
+
}
|
|
16437
|
+
</div>
|
|
16438
|
+
|
|
16439
|
+
<div class="flex-1 min-h-0 overflow-auto">
|
|
16440
|
+
@switch (state()) {
|
|
16441
|
+
@case ('loading') {
|
|
16442
|
+
<div class="h-full flex flex-col gap-3 justify-center p-4">
|
|
16443
|
+
<clx-skeleton variant="text" width="100%" height="12px" />
|
|
16444
|
+
<clx-skeleton variant="text" width="85%" height="12px" />
|
|
16445
|
+
<clx-skeleton variant="text" width="92%" height="12px" />
|
|
16446
|
+
</div>
|
|
16447
|
+
}
|
|
16448
|
+
@case ('empty') {
|
|
16449
|
+
<div class="h-full flex flex-col items-center justify-center gap-2 p-6 text-center">
|
|
16450
|
+
<div class="w-11 h-11 rounded-xl bg-clx-surface-2 flex items-center justify-center">
|
|
16451
|
+
<span clx-icon name="inbox" size="md" class="text-clx-text-subtle"></span>
|
|
16452
|
+
</div>
|
|
16453
|
+
<p class="text-xs text-clx-text-subtle">{{ emptyMessage() }}</p>
|
|
16454
|
+
</div>
|
|
16455
|
+
}
|
|
16456
|
+
@case ('error') {
|
|
16457
|
+
<div class="h-full flex flex-col items-center justify-center gap-3 p-6 text-center">
|
|
16458
|
+
<div class="w-11 h-11 rounded-xl bg-red-50 flex items-center justify-center">
|
|
16459
|
+
<span clx-icon name="error" size="md" class="text-red-600"></span>
|
|
16460
|
+
</div>
|
|
16461
|
+
<p class="text-xs text-clx-text-subtle">{{ errorMessage() }}</p>
|
|
16462
|
+
<button
|
|
16463
|
+
type="button"
|
|
16464
|
+
class="text-xs font-semibold px-3 py-1.5 rounded-lg border border-clx-border text-clx-text-label hover:bg-clx-surface-2 cursor-pointer"
|
|
16465
|
+
(click)="retry.emit()">
|
|
16466
|
+
{{ retryLabel() }}
|
|
16467
|
+
</button>
|
|
16468
|
+
</div>
|
|
16469
|
+
}
|
|
16470
|
+
@default {
|
|
16471
|
+
<ng-content />
|
|
16472
|
+
}
|
|
16473
|
+
}
|
|
16474
|
+
</div>
|
|
16475
|
+
`,
|
|
16476
|
+
}]
|
|
16477
|
+
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], menuActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuActions", required: false }] }], menuLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuLabel", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], retryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "retryLabel", required: false }] }], menuAction: [{ type: i0.Output, args: ["menuAction"] }], retry: [{ type: i0.Output, args: ["retry"] }] } });
|
|
16478
|
+
|
|
16479
|
+
/** Drop-in cell for a `clxCell` table column: label + inline progress bar + trailing value —
|
|
16480
|
+
* e.g. "Canadá [████████░░] 6,192" rows in a "sales by country/branch" dashboard widget. Mount it
|
|
16481
|
+
* inside `<ng-template clxCell let-row>` instead of hand-building the flex row each time. */
|
|
16482
|
+
class ClxTableProgressCellComponent {
|
|
16483
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
16484
|
+
value = input.required(...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
16485
|
+
max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
16486
|
+
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
16487
|
+
/** Optional leading glyph (e.g. a flag emoji) shown before the label. */
|
|
16488
|
+
leadingIcon = input(undefined, ...(ngDevMode ? [{ debugName: "leadingIcon" }] : /* istanbul ignore next */ []));
|
|
16489
|
+
/** Overrides the trailing number's text (e.g. a formatted "6,192") — falls back to the raw value(). */
|
|
16490
|
+
displayValue = input(undefined, ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
16491
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxTableProgressCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16492
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxTableProgressCellComponent, isStandalone: true, selector: "clx-table-progress-cell", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, displayValue: { classPropertyName: "displayValue", publicName: "displayValue", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex items-center gap-2.5 w-full" }, ngImport: i0, template: `
|
|
16493
|
+
@if (leadingIcon()) {
|
|
16494
|
+
<span class="text-base shrink-0">{{ leadingIcon() }}</span>
|
|
16495
|
+
}
|
|
16496
|
+
<span class="text-sm text-clx-text-label shrink-0 w-24 truncate">{{ label() }}</span>
|
|
16497
|
+
<div class="flex-1 min-w-0">
|
|
16498
|
+
<clx-progress-bar [value]="value()" [max]="max()" [color]="color()" size="xs" />
|
|
16499
|
+
</div>
|
|
16500
|
+
<span class="text-sm font-semibold text-clx-text tabular-nums shrink-0">{{ displayValue() ?? value() }}</span>
|
|
16501
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ClxProgressBarComponent, selector: "clx-progress-bar", inputs: ["value", "max", "color", "size", "variant", "label", "showValue", "valueFormat", "segments"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
16502
|
+
}
|
|
16503
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxTableProgressCellComponent, decorators: [{
|
|
16504
|
+
type: Component,
|
|
16505
|
+
args: [{
|
|
16506
|
+
selector: 'clx-table-progress-cell',
|
|
16507
|
+
standalone: true,
|
|
16508
|
+
imports: [ClxProgressBarComponent],
|
|
16509
|
+
encapsulation: ViewEncapsulation.None,
|
|
16510
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16511
|
+
host: { class: 'flex items-center gap-2.5 w-full' },
|
|
16512
|
+
template: `
|
|
16513
|
+
@if (leadingIcon()) {
|
|
16514
|
+
<span class="text-base shrink-0">{{ leadingIcon() }}</span>
|
|
16515
|
+
}
|
|
16516
|
+
<span class="text-sm text-clx-text-label shrink-0 w-24 truncate">{{ label() }}</span>
|
|
16517
|
+
<div class="flex-1 min-w-0">
|
|
16518
|
+
<clx-progress-bar [value]="value()" [max]="max()" [color]="color()" size="xs" />
|
|
16519
|
+
</div>
|
|
16520
|
+
<span class="text-sm font-semibold text-clx-text tabular-nums shrink-0">{{ displayValue() ?? value() }}</span>
|
|
16521
|
+
`,
|
|
16522
|
+
}]
|
|
16523
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], leadingIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "leadingIcon", required: false }] }], displayValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayValue", required: false }] }] } });
|
|
16524
|
+
|
|
16525
|
+
/** Drop-in cell for a `clxCell` table column: avatar (or initials) + label on the left, a status
|
|
16526
|
+
* pill on the right — e.g. a "recent orders" dashboard widget row like "Orden #4582 ⋯ Entregado".
|
|
16527
|
+
* Mount it inside `<ng-template clxCell let-row>` instead of hand-building the flex row each time. */
|
|
16528
|
+
class ClxTableStatusCellComponent {
|
|
16529
|
+
label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
16530
|
+
avatarSrc = input(null, ...(ngDevMode ? [{ debugName: "avatarSrc" }] : /* istanbul ignore next */ []));
|
|
16531
|
+
avatarInitials = input(null, ...(ngDevMode ? [{ debugName: "avatarInitials" }] : /* istanbul ignore next */ []));
|
|
16532
|
+
avatarColor = input(undefined, ...(ngDevMode ? [{ debugName: "avatarColor" }] : /* istanbul ignore next */ []));
|
|
16533
|
+
statusLabel = input.required(...(ngDevMode ? [{ debugName: "statusLabel" }] : /* istanbul ignore next */ []));
|
|
16534
|
+
statusColor = input('slate', ...(ngDevMode ? [{ debugName: "statusColor" }] : /* istanbul ignore next */ []));
|
|
16535
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxTableStatusCellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16536
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.15", type: ClxTableStatusCellComponent, isStandalone: true, selector: "clx-table-status-cell", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, avatarSrc: { classPropertyName: "avatarSrc", publicName: "avatarSrc", isSignal: true, isRequired: false, transformFunction: null }, avatarInitials: { classPropertyName: "avatarInitials", publicName: "avatarInitials", isSignal: true, isRequired: false, transformFunction: null }, avatarColor: { classPropertyName: "avatarColor", publicName: "avatarColor", isSignal: true, isRequired: false, transformFunction: null }, statusLabel: { classPropertyName: "statusLabel", publicName: "statusLabel", isSignal: true, isRequired: true, transformFunction: null }, statusColor: { classPropertyName: "statusColor", publicName: "statusColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "flex items-center justify-between gap-3 w-full" }, ngImport: i0, template: `
|
|
16537
|
+
<div class="flex items-center gap-2.5 min-w-0">
|
|
16538
|
+
<clx-avatar [src]="avatarSrc()" [initials]="avatarInitials()" [color]="avatarColor()" size="xs" />
|
|
16539
|
+
<span class="text-sm text-clx-text-label truncate">{{ label() }}</span>
|
|
16540
|
+
</div>
|
|
16541
|
+
<span clx-badge [color]="statusColor()" variant="light" shape="pill" size="xs" class="shrink-0">
|
|
16542
|
+
{{ statusLabel() }}
|
|
16543
|
+
</span>
|
|
16544
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ClxAvatarComponent, selector: "clx-avatar", inputs: ["src", "initials", "iconName", "color", "size", "shape", "alt"] }, { kind: "component", type: ClxBadgeComponent, selector: "span[clx-badge]", inputs: ["variant", "color", "size", "shape", "positioned"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
16545
|
+
}
|
|
16546
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxTableStatusCellComponent, decorators: [{
|
|
16547
|
+
type: Component,
|
|
16548
|
+
args: [{
|
|
16549
|
+
selector: 'clx-table-status-cell',
|
|
16550
|
+
standalone: true,
|
|
16551
|
+
imports: [ClxAvatarComponent, ClxBadgeComponent],
|
|
16552
|
+
encapsulation: ViewEncapsulation.None,
|
|
16553
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16554
|
+
host: { class: 'flex items-center justify-between gap-3 w-full' },
|
|
16555
|
+
template: `
|
|
16556
|
+
<div class="flex items-center gap-2.5 min-w-0">
|
|
16557
|
+
<clx-avatar [src]="avatarSrc()" [initials]="avatarInitials()" [color]="avatarColor()" size="xs" />
|
|
16558
|
+
<span class="text-sm text-clx-text-label truncate">{{ label() }}</span>
|
|
16559
|
+
</div>
|
|
16560
|
+
<span clx-badge [color]="statusColor()" variant="light" shape="pill" size="xs" class="shrink-0">
|
|
16561
|
+
{{ statusLabel() }}
|
|
16562
|
+
</span>
|
|
16563
|
+
`,
|
|
16564
|
+
}]
|
|
16565
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], avatarInitials: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarInitials", required: false }] }], avatarColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarColor", required: false }] }], statusLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusLabel", required: true }] }], statusColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusColor", required: false }] }] } });
|
|
16566
|
+
|
|
16567
|
+
/** Content template for one grid cell — `<ng-template clxGridItem let-item>...</ng-template>`,
|
|
16568
|
+
* mirroring the `clxCell`/`clxColumn` convention ClxTableComponent already uses for projected
|
|
16569
|
+
* per-row templates. Typically a <clx-widget-card> wrapping whatever the widget actually renders. */
|
|
16570
|
+
class ClxGridItemDirective {
|
|
16571
|
+
templateRef;
|
|
16572
|
+
constructor(templateRef) {
|
|
16573
|
+
this.templateRef = templateRef;
|
|
16574
|
+
}
|
|
16575
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxGridItemDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
16576
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.15", type: ClxGridItemDirective, isStandalone: true, selector: "ng-template[clxGridItem]", ngImport: i0 });
|
|
16577
|
+
}
|
|
16578
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxGridItemDirective, decorators: [{
|
|
16579
|
+
type: Directive,
|
|
16580
|
+
args: [{ selector: 'ng-template[clxGridItem]', standalone: true }]
|
|
16581
|
+
}], ctorParameters: () => [{ type: i0.TemplateRef }] });
|
|
16582
|
+
/** Content-agnostic configurable dashboard grid: positions/sizes projected widgets on a CSS grid
|
|
16583
|
+
* using column/row units, supports drag-to-reorder (via Angular CDK's CdkDropList/CdkDrag — no
|
|
16584
|
+
* new dependency, @angular/cdk is already pulled in by ClxProfileComponent/ClxWidgetCardComponent's
|
|
16585
|
+
* overlay usage) and resize-by-dragging a corner handle. Persistence is the caller's job: listen
|
|
16586
|
+
* to (layoutChange) and save the resulting ClxGridItem[] (e.g. to rp_dashboard_layouts.layout). */
|
|
16587
|
+
class ClxDashboardGridComponent {
|
|
16588
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
16589
|
+
columns = input(4, ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
|
|
16590
|
+
rowHeight = input(92, ...(ngDevMode ? [{ debugName: "rowHeight" }] : /* istanbul ignore next */ []));
|
|
16591
|
+
gap = input(16, ...(ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []));
|
|
16592
|
+
editable = input(false, ...(ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []));
|
|
16593
|
+
layoutChange = output();
|
|
16594
|
+
itemResize = output();
|
|
16595
|
+
_itemTemplate = contentChild(ClxGridItemDirective, ...(ngDevMode ? [{ debugName: "_itemTemplate" }] : /* istanbul ignore next */ []));
|
|
16596
|
+
_gridCols = computed(() => `repeat(${this.columns()}, minmax(0, 1fr))`, ...(ngDevMode ? [{ debugName: "_gridCols" }] : /* istanbul ignore next */ []));
|
|
16597
|
+
_resizing = null;
|
|
16598
|
+
_onDrop(event) {
|
|
16599
|
+
const next = [...this.items()];
|
|
16600
|
+
moveItemInArray(next, event.previousIndex, event.currentIndex);
|
|
16601
|
+
this.layoutChange.emit(next);
|
|
16602
|
+
}
|
|
16603
|
+
_onDragMoved(_event) {
|
|
16604
|
+
// Reordering is handled by cdkDropListDropped above; this hook exists for future free-form
|
|
16605
|
+
// (x/y pixel) positioning if a consumer needs it — not required for a reorderable column grid.
|
|
16606
|
+
}
|
|
16607
|
+
_startResize(event, item) {
|
|
16608
|
+
event.preventDefault();
|
|
16609
|
+
event.stopPropagation();
|
|
16610
|
+
this._resizing = { item, startX: event.clientX, startY: event.clientY, startW: item.w, startH: item.h };
|
|
16611
|
+
const cellW = event.target.closest('[style*="grid-column"]')?.clientWidth
|
|
16612
|
+
?? (this.rowHeight() * 2);
|
|
16613
|
+
const onMove = (e) => {
|
|
16614
|
+
if (!this._resizing)
|
|
16615
|
+
return;
|
|
16616
|
+
const dx = e.clientX - this._resizing.startX;
|
|
16617
|
+
const dy = e.clientY - this._resizing.startY;
|
|
16618
|
+
const deltaCols = Math.round(dx / (cellW / this._resizing.startW || 1));
|
|
16619
|
+
const deltaRows = Math.round(dy / this.rowHeight());
|
|
16620
|
+
const nextW = Math.max(item.minW ?? 1, this._resizing.startW + deltaCols);
|
|
16621
|
+
const nextH = Math.max(item.minH ?? 1, this._resizing.startH + deltaRows);
|
|
16622
|
+
if (nextW !== item.w || nextH !== item.h) {
|
|
16623
|
+
item.w = nextW;
|
|
16624
|
+
item.h = nextH;
|
|
16625
|
+
this.itemResize.emit({ id: item.id, w: nextW, h: nextH });
|
|
16626
|
+
}
|
|
16627
|
+
};
|
|
16628
|
+
const onUp = () => {
|
|
16629
|
+
this._resizing = null;
|
|
16630
|
+
this.layoutChange.emit([...this.items()]);
|
|
16631
|
+
window.removeEventListener('pointermove', onMove);
|
|
16632
|
+
window.removeEventListener('pointerup', onUp);
|
|
16633
|
+
};
|
|
16634
|
+
window.addEventListener('pointermove', onMove);
|
|
16635
|
+
window.addEventListener('pointerup', onUp);
|
|
16636
|
+
}
|
|
16637
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDashboardGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16638
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxDashboardGridComponent, isStandalone: true, selector: "clx-dashboard-grid", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rowHeight: { classPropertyName: "rowHeight", publicName: "rowHeight", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { layoutChange: "layoutChange", itemResize: "itemResize" }, host: { classAttribute: "block w-full" }, queries: [{ propertyName: "_itemTemplate", first: true, predicate: ClxGridItemDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
16639
|
+
<div
|
|
16640
|
+
cdkDropList
|
|
16641
|
+
[cdkDropListDisabled]="!editable()"
|
|
16642
|
+
(cdkDropListDropped)="_onDrop($event)"
|
|
16643
|
+
class="grid w-full"
|
|
16644
|
+
[style.grid-template-columns]="_gridCols()"
|
|
16645
|
+
[style.grid-auto-rows.px]="rowHeight()"
|
|
16646
|
+
[style.gap.px]="gap()">
|
|
16647
|
+
@for (item of items(); track item.id) {
|
|
16648
|
+
<div
|
|
16649
|
+
cdkDrag
|
|
16650
|
+
[cdkDragDisabled]="!editable()"
|
|
16651
|
+
[cdkDragData]="item"
|
|
16652
|
+
(cdkDragMoved)="_onDragMoved($event)"
|
|
16653
|
+
class="relative min-w-0"
|
|
16654
|
+
[class.cursor-grab]="editable()"
|
|
16655
|
+
[style.grid-column]="'span ' + item.w"
|
|
16656
|
+
[style.grid-row]="'span ' + item.h">
|
|
16657
|
+
|
|
16658
|
+
<ng-container
|
|
16659
|
+
[ngTemplateOutlet]="_itemTemplate()?.templateRef ?? null"
|
|
16660
|
+
[ngTemplateOutletContext]="{ $implicit: item }">
|
|
16661
|
+
</ng-container>
|
|
16662
|
+
|
|
16663
|
+
@if (editable()) {
|
|
16664
|
+
<div
|
|
16665
|
+
class="absolute -right-1 -bottom-1 w-3.5 h-3.5 rounded bg-clx-primary border-2 border-clx-surface shadow cursor-nwse-resize"
|
|
16666
|
+
(pointerdown)="_startResize($event, item)">
|
|
16667
|
+
</div>
|
|
16668
|
+
}
|
|
16669
|
+
</div>
|
|
16670
|
+
}
|
|
16671
|
+
</div>
|
|
16672
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
16673
|
+
}
|
|
16674
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxDashboardGridComponent, decorators: [{
|
|
16675
|
+
type: Component,
|
|
16676
|
+
args: [{
|
|
16677
|
+
selector: 'clx-dashboard-grid',
|
|
16678
|
+
standalone: true,
|
|
16679
|
+
imports: [NgTemplateOutlet, DragDropModule],
|
|
16680
|
+
encapsulation: ViewEncapsulation.None,
|
|
16681
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
16682
|
+
host: { class: 'block w-full' },
|
|
16683
|
+
template: `
|
|
16684
|
+
<div
|
|
16685
|
+
cdkDropList
|
|
16686
|
+
[cdkDropListDisabled]="!editable()"
|
|
16687
|
+
(cdkDropListDropped)="_onDrop($event)"
|
|
16688
|
+
class="grid w-full"
|
|
16689
|
+
[style.grid-template-columns]="_gridCols()"
|
|
16690
|
+
[style.grid-auto-rows.px]="rowHeight()"
|
|
16691
|
+
[style.gap.px]="gap()">
|
|
16692
|
+
@for (item of items(); track item.id) {
|
|
16693
|
+
<div
|
|
16694
|
+
cdkDrag
|
|
16695
|
+
[cdkDragDisabled]="!editable()"
|
|
16696
|
+
[cdkDragData]="item"
|
|
16697
|
+
(cdkDragMoved)="_onDragMoved($event)"
|
|
16698
|
+
class="relative min-w-0"
|
|
16699
|
+
[class.cursor-grab]="editable()"
|
|
16700
|
+
[style.grid-column]="'span ' + item.w"
|
|
16701
|
+
[style.grid-row]="'span ' + item.h">
|
|
16702
|
+
|
|
16703
|
+
<ng-container
|
|
16704
|
+
[ngTemplateOutlet]="_itemTemplate()?.templateRef ?? null"
|
|
16705
|
+
[ngTemplateOutletContext]="{ $implicit: item }">
|
|
16706
|
+
</ng-container>
|
|
16707
|
+
|
|
16708
|
+
@if (editable()) {
|
|
16709
|
+
<div
|
|
16710
|
+
class="absolute -right-1 -bottom-1 w-3.5 h-3.5 rounded bg-clx-primary border-2 border-clx-surface shadow cursor-nwse-resize"
|
|
16711
|
+
(pointerdown)="_startResize($event, item)">
|
|
16712
|
+
</div>
|
|
16713
|
+
}
|
|
16714
|
+
</div>
|
|
16715
|
+
}
|
|
16716
|
+
</div>
|
|
16717
|
+
`,
|
|
16718
|
+
}]
|
|
16719
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rowHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "rowHeight", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], layoutChange: [{ type: i0.Output, args: ["layoutChange"] }], itemResize: [{ type: i0.Output, args: ["itemResize"] }], _itemTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => ClxGridItemDirective), { isSignal: true }] }] } });
|
|
16720
|
+
|
|
16180
16721
|
const PRODUCT_TAG_LABEL = {
|
|
16181
16722
|
'new': 'Nuevo',
|
|
16182
16723
|
'sale': 'Oferta',
|
|
@@ -18780,5 +19321,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
18780
19321
|
* Generated bundle index. Do not edit.
|
|
18781
19322
|
*/
|
|
18782
19323
|
|
|
18783
|
-
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, ClxCardExpiryInputComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCardNumberInputComponent, ClxCardValidators, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxCollapseComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorImageModalComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNotificationComponent, ClxNumberComponent, ClxOtpComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProductQuickViewComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSocialIconComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableActionsComponent, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, detectClxCardBrand, isClxCardExpired, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
19324
|
+
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, ClxCardExpiryInputComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCardNumberInputComponent, ClxCardValidators, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxCollapseComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDashboardGridComponent, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorImageModalComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxGridItemDirective, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNotificationComponent, ClxNumberComponent, ClxOtpComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProductQuickViewComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSocialIconComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableActionsComponent, ClxTableComponent, ClxTableProgressCellComponent, ClxTableStatusCellComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWidgetCardComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, detectClxCardBrand, isClxCardExpired, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
18784
19325
|
//# sourceMappingURL=codexly-ui.mjs.map
|