@ajuarezso/sui-design-system 0.7.25 → 0.8.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.
|
@@ -1659,6 +1659,10 @@ const SIZE_PX$1 = {
|
|
|
1659
1659
|
md: 24,
|
|
1660
1660
|
lg: 32,
|
|
1661
1661
|
xl: 40,
|
|
1662
|
+
/* 48px — requerido por el leading Brand del Content Label size Large
|
|
1663
|
+
(Figma 2945:5652: logo de marca raw a 48×48). Aditivo, no es un size del
|
|
1664
|
+
set Major Brand Logos (nativo 32×32, escala vectorial sin pérdida). */
|
|
1665
|
+
'2xl': 48,
|
|
1662
1666
|
};
|
|
1663
1667
|
/**
|
|
1664
1668
|
* SUI Brand Logo — SUI Design System 2.0
|
|
@@ -2306,6 +2310,187 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
2306
2310
|
}, template: "<ng-content select=\"[sui-card-header]\" />\n<div class=\"sui-card__body\">\n <ng-content />\n</div>\n<ng-content select=\"[sui-card-media]\" />\n<ng-content select=\"[sui-card-footer]\" />\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;box-sizing:border-box;background:var(--sui-bg-white-0);border-radius:var(--sui-radius-16);border:1px solid transparent;overflow:hidden;outline:none;transition:box-shadow var(--sui-motion-duration-x-fast, .12s) var(--sui-motion-ease-out, ease-out),border-color var(--sui-motion-duration-x-fast, .12s) var(--sui-motion-ease-out, ease-out),transform var(--sui-motion-duration-x-fast, .12s) var(--sui-motion-ease-out, ease-out)}:host([data-sui-variant=default]){border-color:var(--sui-stroke-soft-200);box-shadow:var(--sui-shadow-x-small)}:host([data-sui-variant=elevated]){border-color:var(--sui-card-elevated-border, transparent);box-shadow:var(--sui-shadow-medium)}:host([data-sui-variant=flat]){border-color:var(--sui-stroke-soft-200);box-shadow:none}:host([data-sui-size=small]){--sui-card-padding-x: 16px;padding:16px;gap:12px}:host([data-sui-size=medium]){--sui-card-padding-x: 20px;padding:20px;gap:16px}:host([data-sui-size=large]){--sui-card-padding-x: 24px;padding:24px;gap:20px}:host([data-sui-size=xlarge]){--sui-card-padding-x: 28px;padding:28px;gap:24px}:host([data-sui-interactive]){cursor:pointer;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;touch-action:manipulation}:host([data-sui-interactive]:hover){transform:translateY(-1px)}:host([data-sui-interactive][data-sui-variant=default]:hover){border-color:var(--sui-stroke-sub-300);box-shadow:var(--sui-shadow-medium)}:host([data-sui-interactive][data-sui-variant=elevated]:hover){box-shadow:var(--sui-custom-shadow-large, var(--sui-shadow-medium))}:host([data-sui-interactive][data-sui-variant=flat]:hover){border-color:var(--sui-stroke-sub-300);background:var(--sui-bg-weak-50, #f7f7f7)}:host([data-sui-interactive]:active:not(:focus-visible)){transform:scale(.99)}:host([data-sui-interactive]:focus-visible){box-shadow:0 0 0 2px var(--sui-bg-white-0),0 0 0 4px var(--sui-state-information-base, #335cff)}::ng-deep [sui-card-header]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}::ng-deep [sui-card-footer]{display:flex;align-items:center;gap:12px}::ng-deep [sui-card-media]{display:block;margin-left:calc(-1 * var(--sui-card-padding-x, 20px));margin-right:calc(-1 * var(--sui-card-padding-x, 20px));margin-bottom:calc(-1 * var(--sui-card-padding-x, 20px));overflow:hidden;border-bottom-left-radius:inherit;border-bottom-right-radius:inherit}:host:has(::ng-deep [sui-card-footer]) ::ng-deep [sui-card-media]{margin-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.sui-card__body{display:flex;flex-direction:column;flex:1 1 auto;min-width:0}:host:has(>.sui-card__body:only-child){gap:0}\n"] }]
|
|
2307
2311
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }] } });
|
|
2308
2312
|
|
|
2313
|
+
/** Orden EXACTO del set de Figma 2942:9880 (11 colores; `disabled` no es un color de serie). */
|
|
2314
|
+
const SUI_CHART_LEGEND_COLORS = [
|
|
2315
|
+
'gray', 'light-gray', 'blue', 'orange', 'red', 'green',
|
|
2316
|
+
'yellow', 'purple', 'sky', 'pink', 'teal',
|
|
2317
|
+
];
|
|
2318
|
+
/**
|
|
2319
|
+
* Ciclo de auto-asignación de colores para series de chart (usado por
|
|
2320
|
+
* `<sui-chart-legend>` cuando un item no trae color explícito).
|
|
2321
|
+
* NO es canon de Figma (el set no define orden de series): arranca en `blue`
|
|
2322
|
+
* (primera serie de facto del DS) y deja los grises al final para que los
|
|
2323
|
+
* primeros N series de cualquier chart salgan con color.
|
|
2324
|
+
*/
|
|
2325
|
+
const SUI_CHART_SERIES_COLORS = [
|
|
2326
|
+
'blue', 'orange', 'red', 'green', 'yellow', 'purple',
|
|
2327
|
+
'sky', 'pink', 'teal', 'gray', 'light-gray',
|
|
2328
|
+
];
|
|
2329
|
+
/**
|
|
2330
|
+
* Mapa color → hex canónico resuelto (valores de los tokens `--sui-state-*-base`
|
|
2331
|
+
* que Figma bindea en cada variant). Útil para alimentar la MISMA paleta a la
|
|
2332
|
+
* lib de charts del consumer (echarts `series[].color`, etc.) y que el dot de
|
|
2333
|
+
* la leyenda matchee 1:1 el color pintado en la gráfica.
|
|
2334
|
+
*/
|
|
2335
|
+
const SUI_CHART_LEGEND_HEX = {
|
|
2336
|
+
gray: '#7b7b7b', // state/faded/base
|
|
2337
|
+
'light-gray': '#d1d1d1', // icon/disabled-300
|
|
2338
|
+
blue: '#335cff', // state/information/base
|
|
2339
|
+
orange: '#fa7319', // state/warning/base
|
|
2340
|
+
red: '#fb3748', // state/error/base
|
|
2341
|
+
green: '#1fc16b', // state/success/base
|
|
2342
|
+
yellow: '#f6b51e', // state/away/base
|
|
2343
|
+
purple: '#7d52f4', // state/feature/base
|
|
2344
|
+
sky: '#47c2ff', // state/verified/base
|
|
2345
|
+
pink: '#fb4ba3', // state/highlighted/base
|
|
2346
|
+
teal: '#22d3bb', // state/stable/base
|
|
2347
|
+
disabled: '#d1d1d1', // icon/disabled-300 (mismo dot que light-gray)
|
|
2348
|
+
};
|
|
2349
|
+
/**
|
|
2350
|
+
* SUI Chart Legend Dot — SUI Design System 2.0
|
|
2351
|
+
*
|
|
2352
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO
|
|
2353
|
+
* Node: 2942:9880 "Chart Legend Dots [1.1]" — VERIFIED via MCP
|
|
2354
|
+
*
|
|
2355
|
+
* Átomo decorativo de las leyendas de chart: el punto de color de una serie.
|
|
2356
|
+
* Render 100% CSS (el SVG de Figma es circle fill + stroke blanco + drop
|
|
2357
|
+
* shadow — se replica con background + box-shadow, sin assets).
|
|
2358
|
+
*
|
|
2359
|
+
* EXACT (pulled from Figma 2942:9880 via get_metadata + get_design_context +
|
|
2360
|
+
* SVG del asset del ellipse):
|
|
2361
|
+
* - 22 variants en figma = 11 colores × 2 sizes (Medium 20 / Small 16)
|
|
2362
|
+
* - Container: 20×20 (medium) / 16×16 (small)
|
|
2363
|
+
* - Ellipse SIEMPRE 12×12 centrado (circle r=6) — solo cambia el container
|
|
2364
|
+
* (medium inset 20% = 4px; small inset 12.5% = 2px)
|
|
2365
|
+
* - Ring interno blanco: stroke 2px en r=5 (`stroke/white-0`) → core de
|
|
2366
|
+
* color visible ≈8px + anillo blanco 2px hasta el borde (separa el dot
|
|
2367
|
+
* del fill del chart en fondos no-blancos)
|
|
2368
|
+
* - Drop shadow: Figma var `regular-shadow/small` = 0 2px 4px 0 #1b1c1d0a
|
|
2369
|
+
* (SIN token en la lib — solo existen regular-shadow x-small y medium;
|
|
2370
|
+
* se usa el valor EXACT literal en el scss)
|
|
2371
|
+
*
|
|
2372
|
+
* Color tokens (bound en Figma, verificados en src/styles/sui-tokens.scss):
|
|
2373
|
+
* gray → --sui-state-faded-base (#7b7b7b)
|
|
2374
|
+
* light-gray → --sui-icon-disabled-300 (#d1d1d1)
|
|
2375
|
+
* blue → --sui-state-information-base (#335cff)
|
|
2376
|
+
* orange → --sui-state-warning-base (#fa7319)
|
|
2377
|
+
* red → --sui-state-error-base (#fb3748)
|
|
2378
|
+
* green → --sui-state-success-base (#1fc16b)
|
|
2379
|
+
* yellow → --sui-state-away-base (#f6b51e)
|
|
2380
|
+
* purple → --sui-state-feature-base (#7d52f4)
|
|
2381
|
+
* sky → --sui-state-verified-base (#47c2ff)
|
|
2382
|
+
* pink → --sui-state-highlighted-base (#fb4ba3)
|
|
2383
|
+
* teal → --sui-state-stable-base (#22d3bb)
|
|
2384
|
+
* disabled → --sui-icon-disabled-300 (#d1d1d1, igual a light-gray)
|
|
2385
|
+
*
|
|
2386
|
+
* `customColor` acepta cualquier CSS color (hex de una paleta echarts custom)
|
|
2387
|
+
* y sobreescribe el preset — mismo patrón que `customHex` de sui-color-dot.
|
|
2388
|
+
*
|
|
2389
|
+
* A11y: decorativo puro (aria-hidden). El significado lo lleva el label del
|
|
2390
|
+
* `<sui-chart-legend>` que lo compone.
|
|
2391
|
+
*
|
|
2392
|
+
* Usage:
|
|
2393
|
+
* <sui-chart-legend-dot color="blue" />
|
|
2394
|
+
* <sui-chart-legend-dot color="green" size="small" />
|
|
2395
|
+
* <sui-chart-legend-dot [customColor]="'#8b5cf6'" />
|
|
2396
|
+
*/
|
|
2397
|
+
class SuiChartLegendDot {
|
|
2398
|
+
/** Color canon de la serie. Default `gray` (variant default del set Figma). */
|
|
2399
|
+
color = input('gray', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
2400
|
+
/** Size del container: `medium` 20×20 / `small` 16×16. El dot es 12×12 en ambos. */
|
|
2401
|
+
size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2402
|
+
/**
|
|
2403
|
+
* CSS color custom (override del preset) para series fuera de la paleta
|
|
2404
|
+
* canon — ej. colores de una paleta echarts propia. Si presente, ignora
|
|
2405
|
+
* `color` a nivel visual.
|
|
2406
|
+
*/
|
|
2407
|
+
customColor = input(null, ...(ngDevMode ? [{ debugName: "customColor" }] : /* istanbul ignore next */ []));
|
|
2408
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiChartLegendDot, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2409
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiChartLegendDot, isStandalone: true, selector: "sui-chart-legend-dot", inputs: { color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, customColor: { classPropertyName: "customColor", publicName: "customColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "aria-hidden": "true" }, properties: { "attr.data-sui-color": "color()", "attr.data-sui-size": "size()", "attr.data-sui-custom": "customColor() ? \"\" : null", "style.--sui-chart-legend-dot-c": "customColor() || null" } }, ngImport: i0, template: '<span class="sui-chart-legend-dot__ellipse"></span>', isInline: true, styles: ["@charset \"UTF-8\";:host{--sui-chart-legend-dot-c: var(--sui-state-faded-base)}:host{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;flex-shrink:0}:host([data-sui-size=small]){width:16px;height:16px}:host([data-sui-color=light-gray]){--sui-chart-legend-dot-c: var(--sui-icon-disabled-300)}:host([data-sui-color=blue]){--sui-chart-legend-dot-c: var(--sui-state-information-base)}:host([data-sui-color=orange]){--sui-chart-legend-dot-c: var(--sui-state-warning-base)}:host([data-sui-color=red]){--sui-chart-legend-dot-c: var(--sui-state-error-base)}:host([data-sui-color=green]){--sui-chart-legend-dot-c: var(--sui-state-success-base)}:host([data-sui-color=yellow]){--sui-chart-legend-dot-c: var(--sui-state-away-base)}:host([data-sui-color=purple]){--sui-chart-legend-dot-c: var(--sui-state-feature-base)}:host([data-sui-color=sky]){--sui-chart-legend-dot-c: var(--sui-state-verified-base)}:host([data-sui-color=pink]){--sui-chart-legend-dot-c: var(--sui-state-highlighted-base)}:host([data-sui-color=teal]){--sui-chart-legend-dot-c: var(--sui-state-stable-base)}:host([data-sui-color=disabled]){--sui-chart-legend-dot-c: var(--sui-icon-disabled-300)}.sui-chart-legend-dot__ellipse{width:12px;height:12px;border-radius:var(--sui-radius-full);background:var(--sui-chart-legend-dot-c);box-shadow:inset 0 0 0 2px var(--sui-stroke-white-0),0 2px 4px #1b1c1d0a}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2410
|
+
}
|
|
2411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiChartLegendDot, decorators: [{
|
|
2412
|
+
type: Component,
|
|
2413
|
+
args: [{ selector: 'sui-chart-legend-dot', standalone: true, template: '<span class="sui-chart-legend-dot__ellipse"></span>', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2414
|
+
'aria-hidden': 'true',
|
|
2415
|
+
'[attr.data-sui-color]': 'color()',
|
|
2416
|
+
'[attr.data-sui-size]': 'size()',
|
|
2417
|
+
'[attr.data-sui-custom]': 'customColor() ? "" : null',
|
|
2418
|
+
'[style.--sui-chart-legend-dot-c]': 'customColor() || null',
|
|
2419
|
+
}, styles: ["@charset \"UTF-8\";:host{--sui-chart-legend-dot-c: var(--sui-state-faded-base)}:host{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;flex-shrink:0}:host([data-sui-size=small]){width:16px;height:16px}:host([data-sui-color=light-gray]){--sui-chart-legend-dot-c: var(--sui-icon-disabled-300)}:host([data-sui-color=blue]){--sui-chart-legend-dot-c: var(--sui-state-information-base)}:host([data-sui-color=orange]){--sui-chart-legend-dot-c: var(--sui-state-warning-base)}:host([data-sui-color=red]){--sui-chart-legend-dot-c: var(--sui-state-error-base)}:host([data-sui-color=green]){--sui-chart-legend-dot-c: var(--sui-state-success-base)}:host([data-sui-color=yellow]){--sui-chart-legend-dot-c: var(--sui-state-away-base)}:host([data-sui-color=purple]){--sui-chart-legend-dot-c: var(--sui-state-feature-base)}:host([data-sui-color=sky]){--sui-chart-legend-dot-c: var(--sui-state-verified-base)}:host([data-sui-color=pink]){--sui-chart-legend-dot-c: var(--sui-state-highlighted-base)}:host([data-sui-color=teal]){--sui-chart-legend-dot-c: var(--sui-state-stable-base)}:host([data-sui-color=disabled]){--sui-chart-legend-dot-c: var(--sui-icon-disabled-300)}.sui-chart-legend-dot__ellipse{width:12px;height:12px;border-radius:var(--sui-radius-full);background:var(--sui-chart-legend-dot-c);box-shadow:inset 0 0 0 2px var(--sui-stroke-white-0),0 2px 4px #1b1c1d0a}\n"] }]
|
|
2420
|
+
}], propDecorators: { color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], customColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "customColor", required: false }] }] } });
|
|
2421
|
+
|
|
2422
|
+
/**
|
|
2423
|
+
* SUI Chart Legend — SUI Design System 2.0
|
|
2424
|
+
*
|
|
2425
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO
|
|
2426
|
+
* Node: 2942:9934 "Chart Legends [1.1]" — VERIFIED via MCP
|
|
2427
|
+
*
|
|
2428
|
+
* Leyenda de chart: recibe `items[]` y COMPONE `<sui-chart-legend-dot>`
|
|
2429
|
+
* (átomo, Figma 2942:9880) + label por serie — patrón familia breadcrumbs
|
|
2430
|
+
* (sui-breadcrumbs compone sui-breadcrumb-item).
|
|
2431
|
+
*
|
|
2432
|
+
* EXACT (pulled from Figma 2942:9934 via get_metadata + get_design_context):
|
|
2433
|
+
* - 12 variants en figma = 12 colores (Gray, Light Gray, Blue, Orange, Red,
|
|
2434
|
+
* Green, Yellow, Purple, Sky, Pink, Teal, Disabled). El set define el
|
|
2435
|
+
* ITEM individual (dot + label, 70×16); NO define orientaciones — el eje
|
|
2436
|
+
* `orientation` es prop de layout para consumo real con charts.
|
|
2437
|
+
* - Item: flex row, gap 4px, dot Small (16×16, ellipse 12×12)
|
|
2438
|
+
* - Label: Inter Medium 12/16 ls 0 (`Label/X Small`), color text/sub-600
|
|
2439
|
+
* - Disabled: label text/disabled-300 (#d1d1d1) + dot gris pálido
|
|
2440
|
+
* - Separación entre items: 24px (layout del frame del set)
|
|
2441
|
+
*
|
|
2442
|
+
* Colores: si un item no trae `color` ni `customColor`, se auto-asigna
|
|
2443
|
+
* ciclando `SUI_CHART_SERIES_COLORS` por índice (arranca en `blue`; NO es
|
|
2444
|
+
* canon Figma, es convención de consumo — el set no define orden de series).
|
|
2445
|
+
*
|
|
2446
|
+
* A11y: host `role="list"` + items `role="listitem"`; el dot es decorativo
|
|
2447
|
+
* (aria-hidden en el átomo).
|
|
2448
|
+
*
|
|
2449
|
+
* Usage:
|
|
2450
|
+
* <sui-chart-legend [items]="[
|
|
2451
|
+
* { label: 'Ventas', color: 'blue', value: '64%' },
|
|
2452
|
+
* { label: 'Devoluciones', color: 'red' },
|
|
2453
|
+
* { label: 'Archivadas', disabled: true },
|
|
2454
|
+
* ]" />
|
|
2455
|
+
*
|
|
2456
|
+
* <!-- auto-colores (blue, orange, red, …) + layout vertical -->
|
|
2457
|
+
* <sui-chart-legend orientation="vertical" [items]="[
|
|
2458
|
+
* { label: 'Lima' }, { label: 'Arequipa' }, { label: 'Cusco' },
|
|
2459
|
+
* ]" />
|
|
2460
|
+
*/
|
|
2461
|
+
class SuiChartLegend {
|
|
2462
|
+
/** Series de la leyenda, en orden de render. */
|
|
2463
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
2464
|
+
/**
|
|
2465
|
+
* Disposición de los items: `horizontal` (row con wrap, default) o
|
|
2466
|
+
* `vertical` (columna — leyendas laterales de donut/pie).
|
|
2467
|
+
*/
|
|
2468
|
+
orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
2469
|
+
/** Items con color efectivo resuelto (disabled > customColor > color > ciclo auto). */
|
|
2470
|
+
resolvedItems = computed(() => this.items().map((item, i) => {
|
|
2471
|
+
if (item.disabled) {
|
|
2472
|
+
return { data: item, color: 'disabled', customColor: null };
|
|
2473
|
+
}
|
|
2474
|
+
if (item.customColor) {
|
|
2475
|
+
return { data: item, color: 'gray', customColor: item.customColor };
|
|
2476
|
+
}
|
|
2477
|
+
return {
|
|
2478
|
+
data: item,
|
|
2479
|
+
color: item.color ?? SUI_CHART_SERIES_COLORS[i % SUI_CHART_SERIES_COLORS.length],
|
|
2480
|
+
customColor: null,
|
|
2481
|
+
};
|
|
2482
|
+
}), ...(ngDevMode ? [{ debugName: "resolvedItems" }] : /* istanbul ignore next */ []));
|
|
2483
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiChartLegend, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2484
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiChartLegend, isStandalone: true, selector: "sui-chart-legend", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "list" }, properties: { "attr.data-sui-orientation": "orientation()" } }, ngImport: i0, template: "@for (entry of resolvedItems(); track $index) {\n <span\n class=\"sui-chart-legend__item\"\n role=\"listitem\"\n [class.sui-chart-legend__item--disabled]=\"entry.data.disabled\"\n >\n <sui-chart-legend-dot\n size=\"small\"\n [color]=\"entry.color\"\n [customColor]=\"entry.customColor\"\n />\n <span class=\"sui-chart-legend__label\">{{ entry.data.label }}</span>\n @if (entry.data.value !== undefined && entry.data.value !== null) {\n <span class=\"sui-chart-legend__value\">{{ entry.data.value }}</span>\n }\n </span>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-wrap:wrap;align-items:center;gap:12px 24px;font-family:var(--sui-font-sans);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}:host([data-sui-orientation=vertical]){flex-direction:column;align-items:flex-start;gap:12px}.sui-chart-legend__item{display:inline-flex;align-items:center;gap:4px}.sui-chart-legend__label{font-size:12px;font-weight:500;line-height:16px;letter-spacing:0;color:var(--sui-text-sub-600);white-space:nowrap}.sui-chart-legend__value{font-size:12px;font-weight:500;line-height:16px;letter-spacing:0;color:var(--sui-text-strong-950);white-space:nowrap}.sui-chart-legend__item--disabled .sui-chart-legend__label,.sui-chart-legend__item--disabled .sui-chart-legend__value{color:var(--sui-text-disabled-300)}\n"], dependencies: [{ kind: "component", type: SuiChartLegendDot, selector: "sui-chart-legend-dot", inputs: ["color", "size", "customColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2485
|
+
}
|
|
2486
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiChartLegend, decorators: [{
|
|
2487
|
+
type: Component,
|
|
2488
|
+
args: [{ selector: 'sui-chart-legend', standalone: true, imports: [SuiChartLegendDot], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2489
|
+
'role': 'list',
|
|
2490
|
+
'[attr.data-sui-orientation]': 'orientation()',
|
|
2491
|
+
}, template: "@for (entry of resolvedItems(); track $index) {\n <span\n class=\"sui-chart-legend__item\"\n role=\"listitem\"\n [class.sui-chart-legend__item--disabled]=\"entry.data.disabled\"\n >\n <sui-chart-legend-dot\n size=\"small\"\n [color]=\"entry.color\"\n [customColor]=\"entry.customColor\"\n />\n <span class=\"sui-chart-legend__label\">{{ entry.data.label }}</span>\n @if (entry.data.value !== undefined && entry.data.value !== null) {\n <span class=\"sui-chart-legend__value\">{{ entry.data.value }}</span>\n }\n </span>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-wrap:wrap;align-items:center;gap:12px 24px;font-family:var(--sui-font-sans);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}:host([data-sui-orientation=vertical]){flex-direction:column;align-items:flex-start;gap:12px}.sui-chart-legend__item{display:inline-flex;align-items:center;gap:4px}.sui-chart-legend__label{font-size:12px;font-weight:500;line-height:16px;letter-spacing:0;color:var(--sui-text-sub-600);white-space:nowrap}.sui-chart-legend__value{font-size:12px;font-weight:500;line-height:16px;letter-spacing:0;color:var(--sui-text-strong-950);white-space:nowrap}.sui-chart-legend__item--disabled .sui-chart-legend__label,.sui-chart-legend__item--disabled .sui-chart-legend__value{color:var(--sui-text-disabled-300)}\n"] }]
|
|
2492
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
|
|
2493
|
+
|
|
2309
2494
|
// large/xlarge: project extension (no-Figma)
|
|
2310
2495
|
/**
|
|
2311
2496
|
* SUI Checkbox — SUI Design System 2.0
|
|
@@ -5072,143 +5257,421 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5072
5257
|
}, template: "<!--\n Trigger DIV interno \u2014 patr\u00F3n canon sui-select. La interacci\u00F3n\n (click/keyboard/role/aria/tabindex) y el anclaje del overlay viven ac\u00E1, NO\n en el host. El host custom-element NO debe colgar (click)+(touchend\u2192blur)\n porque el blur() s\u00EDncrono en touchend cancela el click sint\u00E9tico de iOS\n WebKit y el menu no abre. Moverlo a un div interno sin touch handlers\n elimina la causa ra\u00EDz por equivalencia con sui-select (probado en iOS real).\n-->\n<div\n #triggerEl\n class=\"sui-compact-select__trigger\"\n role=\"button\"\n [attr.tabindex]=\"mergedDisabled() ? null : 0\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"mergedDisabled() ? '' : null\"\n [class.sui-compact-select__trigger--open]=\"isOpen()\"\n [class.sui-compact-select__trigger--error]=\"error()\"\n [class.sui-compact-select__trigger--disabled]=\"mergedDisabled()\"\n (click)=\"onTriggerClick($event)\"\n (keydown.enter)=\"onTriggerClick($event)\"\n (keydown.space)=\"onTriggerClick($event); $event.preventDefault()\"\n>\n <!-- Leading slot seg\u00FAn type. Prioriza el selected item; sino usa el input est\u00E1tico. -->\n @switch (type()) {\n @case ('icon') {\n @if (displayIcon()) {\n <sui-icon class=\"sui-compact-select__leading\" [name]=\"displayIcon()!\" [size]=\"20\" />\n }\n }\n @case ('country') {\n @if (displayFlag()) {\n <sui-flag class=\"sui-compact-select__leading\" [name]=\"displayFlag()!\" [size]=\"flagSize()\" />\n }\n }\n }\n\n <!-- Value / placeholder text (basic + country muestran texto; icon usualmente sin). -->\n @if (type() !== 'icon') {\n <span class=\"sui-compact-select__value\" [attr.data-sui-placeholder]=\"hasValue() ? null : ''\">\n {{ hasValue() ? displayValue() : placeholder() }}\n </span>\n }\n\n <!-- Trailing arrow. -->\n <sui-icon class=\"sui-compact-select__arrow\" [name]=\"arrowIcon()\" [size]=\"20\" />\n</div>\n\n<!-- Overlay menu \u2014 delegado a sui-dropdown-menu. El trigger DIV interno es el\n [origin]=triggerEl; el menu solo gestiona el panel.\n Solo se renderea cuando hay items (mode 2). -->\n@if (items().length > 0) {\n <sui-dropdown-menu\n [origin]=\"triggerEl\"\n [disabled]=\"mergedDisabled()\"\n [minWidth]=\"200\"\n panelClass=\"sui-compact-select__overlay-pane\"\n (openedChange)=\"onMenuOpenedChange($event)\"\n >\n <ng-template suiDropdownPanel>\n <div class=\"sui-compact-select__menu\">\n @for (item of items(); track item.value) {\n <sui-dropdown-item\n mode=\"option\"\n [label]=\"item.label\"\n [sublabel]=\"item.sublabel ?? ''\"\n [selected]=\"item.value === selected()?.value\"\n [disabled]=\"item.disabled ?? false\"\n (click)=\"selectItem(item)\"\n >\n @if (item.flag) {\n <sui-flag slot=\"leading\" [name]=\"item.flag\" size=\"sm\" />\n } @else if (item.icon) {\n <sui-icon slot=\"leading\" [name]=\"item.icon\" [size]=\"20\" />\n }\n </sui-dropdown-item>\n }\n </div>\n </ng-template>\n </sui-dropdown-menu>\n}\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;flex-shrink:0;box-sizing:border-box;vertical-align:middle;font-family:var(--sui-font-sans, sans-serif)}.sui-compact-select__trigger{display:inline-flex;align-items:center;flex-shrink:0;box-sizing:border-box;background:var(--sui-bg-white-0, #fff);border:1px solid var(--sui-stroke-soft-200, #ebebeb);box-shadow:0 1px 2px #0a0d1408;cursor:pointer;-webkit-user-select:none;user-select:none;outline:none;transition:background-color .1s ease,border-color .1s ease,box-shadow .1s ease;font-family:var(--sui-font-sans, sans-serif);font-size:var(--sui-type-paragraph-sm-size, 14px);font-weight:var(--sui-type-paragraph-sm-weight, 400);line-height:var(--sui-type-paragraph-sm-line, 20px);letter-spacing:var(--sui-type-paragraph-sm-spacing, -.006em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}:host([data-sui-size=medium]) .sui-compact-select__trigger{padding:9px 10px;gap:4px;border-radius:var(--sui-radius-10, 10px)}:host([data-sui-size=small]) .sui-compact-select__trigger{padding:7px 8px;gap:4px;border-radius:var(--sui-radius-8, 8px)}:host([data-sui-size=xsmall]) .sui-compact-select__trigger{padding:5px 6px;gap:2px;border-radius:var(--sui-radius-8, 8px)}:host([data-sui-type=basic][data-sui-size=medium]) .sui-compact-select__trigger{padding:9px 10px 9px 12px}:host([data-sui-type=basic][data-sui-size=small]) .sui-compact-select__trigger{padding:7px 8px 7px 12px}:host([data-sui-type=basic][data-sui-size=xsmall]) .sui-compact-select__trigger{padding:5px 6px 5px 10px}.sui-compact-select__trigger:not(.sui-compact-select__trigger--disabled):not(.sui-compact-select__trigger--error):not(.sui-compact-select__trigger--open):hover{background:var(--sui-bg-weak-50, #f7f7f7);border-color:transparent;box-shadow:none}.sui-compact-select__trigger:not(.sui-compact-select__trigger--disabled):focus-visible,.sui-compact-select__trigger--open:not(.sui-compact-select__trigger--disabled){outline:none;background:var(--sui-bg-white-0, #fff);border-color:var(--sui-stroke-strong-950, #171717);box-shadow:0 0 0 2px var(--sui-bg-white-0, #fff),0 0 0 4px var(--sui-slate-alpha-16, rgba(153, 160, 174, .16))}.sui-compact-select__trigger--error:not(.sui-compact-select__trigger--disabled){border-color:var(--sui-state-error-base, #fb3748)}.sui-compact-select__trigger--error:not(.sui-compact-select__trigger--disabled):focus-visible,.sui-compact-select__trigger--error.sui-compact-select__trigger--open:not(.sui-compact-select__trigger--disabled){outline:none;border-color:var(--sui-state-error-base, #fb3748);box-shadow:0 0 0 2px var(--sui-bg-white-0, #fff),0 0 0 4px var(--sui-red-alpha-16, rgba(251, 55, 72, .16))}.sui-compact-select__trigger--disabled{background:var(--sui-bg-weak-50, #f7f7f7);border-color:transparent;color:var(--sui-text-disabled-300, #d1d1d1);cursor:not-allowed;pointer-events:none;box-shadow:none}.sui-compact-select__trigger--disabled .sui-compact-select__leading{opacity:.48}.sui-compact-select__trigger--disabled .sui-compact-select__arrow{color:var(--sui-icon-disabled-300, #d1d1d1)}.sui-compact-select__leading{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;color:var(--sui-text-sub-600, #5c5c5c)}:host([data-sui-filled]) .sui-compact-select__leading{color:var(--sui-icon-strong-950, #171717)}.sui-compact-select__value{flex:1 0 auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}.sui-compact-select__value[data-sui-placeholder]{color:var(--sui-text-sub-600, #5c5c5c)}.sui-compact-select__trigger--disabled .sui-compact-select__value[data-sui-placeholder]{color:var(--sui-text-disabled-300, #d1d1d1)}.sui-compact-select__arrow{flex-shrink:0;color:var(--sui-text-sub-600, #5c5c5c);transition:transform .12s ease}\n"] }]
|
|
5073
5258
|
}], ctorParameters: () => [], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], flag: [{ type: i0.Input, args: [{ isSignal: true, alias: "flag", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }, { type: i0.Output, args: ["selectedChange"] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], selectedChange: [{ type: i0.Output, args: ["selectedChange"] }], _menu: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SuiDropdownMenu), { isSignal: true }] }], triggerEl: [{ type: i0.ViewChild, args: ['triggerEl', { isSignal: true }] }] } });
|
|
5074
5259
|
|
|
5260
|
+
/** Set de los 9 colores SUI 2.0 para iterar desde el consumer (previews, demos). */
|
|
5261
|
+
const SUI_KEY_ICON_COLORS = [
|
|
5262
|
+
'gray', 'blue', 'orange', 'red', 'green', 'yellow', 'purple', 'pink', 'teal',
|
|
5263
|
+
];
|
|
5264
|
+
/** Set de los 5 tamaños canon, para iterar desde el consumer. */
|
|
5265
|
+
const SUI_KEY_ICON_SIZES = [32, 40, 48, 56, 64];
|
|
5075
5266
|
/**
|
|
5076
|
-
* SUI
|
|
5267
|
+
* SUI Key Icon — SUI Design System 2.0
|
|
5077
5268
|
*
|
|
5078
|
-
*
|
|
5079
|
-
*
|
|
5080
|
-
*
|
|
5081
|
-
* sui-form-label.ts, que lista explícitamente 263:1850 / 266:2814, y por el
|
|
5082
|
-
* screenshot "Label * (Optional)"). NO es el ContentCard.
|
|
5083
|
-
*
|
|
5084
|
-
* El fileKey `8p1k72aKKvzJV4XcvPS4VO` que se usaba en todo el DS es el archivo
|
|
5085
|
-
* de ASSETS DE MARCA de SUI (sus únicas páginas son "Cover" y "Brand";
|
|
5086
|
-
* contiene Visa/Mastercard/Stripe/PayPal logos, NO la librería de componentes).
|
|
5087
|
-
* El nodo real del ContentCard / ContentLabel vive en OTRO archivo de SUI
|
|
5088
|
-
* (la librería "Base Components") al que esta conexión MCP no tiene acceso.
|
|
5089
|
-
* Por lo tanto NINGUNA medida de layout, gap, leading o card-provider de este
|
|
5090
|
-
* componente está confirmada pixel-exacta contra Figma — son inferencias del
|
|
5091
|
-
* patrón SUI ContentLabel estándar + la descripción del SUI-FIGMA-CHECKLIST.
|
|
5092
|
-
* Ver PENDING VERIFY al final y la entrada en PENDIENTES.md.
|
|
5093
|
-
*
|
|
5094
|
-
* Componente NUEVO de la auditoría (descrito en SUI-FIGMA-CHECKLIST.md:86): es el
|
|
5095
|
-
* `ContentLabel` (fila de contenido con leading visual + título/subtítulo + badge
|
|
5096
|
-
* inline) ENVUELTO en una card:
|
|
5097
|
-
* bg-white-0, border 1px stroke-soft-200, radius 12px, padding 16px,
|
|
5098
|
-
* drop-shadow x-small.
|
|
5099
|
-
* Trailing: en lugar del badge/switch del ContentLabel original, una card lleva
|
|
5100
|
-
* un botón X de dismiss (close-line 20px via sui-icon) a la derecha.
|
|
5101
|
-
*
|
|
5102
|
-
* Anatomía (flex row, gap 12, items-center):
|
|
5103
|
-
* [ leading 40×40 ] [ text block (flex-1) ] [ X dismiss 20px ]
|
|
5104
|
-
* text block = Title row (title + sui-badge inline) + Subtitle.
|
|
5105
|
-
*
|
|
5106
|
-
* 6 tipos de leading (input `type`):
|
|
5107
|
-
* basic → sin leading
|
|
5108
|
-
* left-icon → cuadro 40×40 radius-10 border stroke-soft-200 bg-white-0,
|
|
5109
|
-
* sui-icon `icon` 20px color icon-sub-600
|
|
5110
|
-
* avatar → sui-avatar size=md (40px) via input `avatar` (config u src)
|
|
5111
|
-
* card-provider → cuadro 40×28 (ratio tarjeta) radius-6 con brand logo centrado
|
|
5112
|
-
* brand → cuadro 40×40 radius-10 border + sui-brand-logo `brand`
|
|
5113
|
-
* company → sui-avatar size=md con companyLogoSrc / iniciales
|
|
5114
|
-
*
|
|
5115
|
-
* Badge (input `badge: SuiBadgeConfig | string | null`): vive DENTRO del Title row
|
|
5116
|
-
* (al lado del título), usando <sui-badge>. String shorthand = solo el label con los
|
|
5117
|
-
* defaults de la card (color 'orange', variant 'lighter', size 'small'); el objeto
|
|
5118
|
-
* SuiBadgeConfig { label, color?, variant?, size? } controla el badge completo.
|
|
5119
|
-
* El DS de Figma especifica AZUL (state/information/light #c0d5ff → sui-badge
|
|
5120
|
-
* color="blue"). El proyecto Master Pedidos prefiere NARANJA por branding, así que
|
|
5121
|
-
* el fallback de color = 'orange'; cualquier consumer que necesite el color del DS
|
|
5122
|
-
* u otro semántico pasa `[badge]="{ label: 'X', color: 'blue' }"` sin forkear el
|
|
5123
|
-
* template. La tipografía del badge small es Subheading/2X Small 11/12 UPPERCASE
|
|
5124
|
-
* tracking 0.22px (0.02em), provista por el propio sui-badge.
|
|
5269
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO — set "Key Icons [1.1]" = nodo 263:1850.
|
|
5270
|
+
* Componente NUEVO (no existía como SUI). Contenedor circular de icono usado como
|
|
5271
|
+
* leading element en list rows, content-labels, empty-states, notificaciones, etc.
|
|
5125
5272
|
*
|
|
5126
|
-
*
|
|
5127
|
-
* bg/white-0 → --sui-bg-white-0 (#ffffff, card bg + leading bg)
|
|
5128
|
-
* stroke/soft-200 → --sui-stroke-soft-200 (#ebebeb, card border + leading border)
|
|
5129
|
-
* text/strong-950 → --sui-text-strong-950 (#171717, title)
|
|
5130
|
-
* text/sub-600 → --sui-text-sub-600 (#5c5c5c, subtitle)
|
|
5131
|
-
* icon/sub-600 → --sui-icon-sub-600 (#5c5c5c, leading icon + X idle)
|
|
5132
|
-
* text/strong-950 → --sui-text-strong-950 (#171717, X icon on hover)
|
|
5133
|
-
* bg/weak-50 → --sui-bg-weak-50 (#f7f7f7, X hover bg)
|
|
5134
|
-
* text/disabled-300 → --sui-text-disabled-300 (#d1d1d1, title cuando disabled)
|
|
5135
|
-
* icon/disabled-300 → --sui-icon-disabled-300 (#d1d1d1, leading/X cuando disabled)
|
|
5136
|
-
* radius-12 → --sui-radius-12 (card)
|
|
5137
|
-
* radius-10 → --sui-radius-10 (leading box icon/brand)
|
|
5138
|
-
* radius-6 → --sui-radius-6 (card-provider box)
|
|
5139
|
-
* shadow x-small → --sui-shadow-x-small (0 1px 2px 0 #0a0d1408)
|
|
5273
|
+
* 90 combinaciones = Style(2: stroke|lighter) × Color(9) × Size(5: 32/40/48/56/64).
|
|
5140
5274
|
*
|
|
5141
|
-
*
|
|
5142
|
-
*
|
|
5143
|
-
*
|
|
5275
|
+
* ── Style ──────────────────────────────────────────────────────────────────
|
|
5276
|
+
* stroke → bg `--sui-bg-white-0` + border 1px `--sui-stroke-soft-200`
|
|
5277
|
+
* + drop-shadow `--sui-shadow-x-small` + radius-full.
|
|
5278
|
+
* El icono interior toma el `*-base` del color.
|
|
5279
|
+
* lighter → bg del `*-lighter` del color (sin borde, sin sombra) + radius-full.
|
|
5280
|
+
* El icono interior toma el `*-base` del color.
|
|
5144
5281
|
*
|
|
5145
|
-
*
|
|
5146
|
-
*
|
|
5282
|
+
* ── Color → token map (Figma exacto; ver SUI-FIGMA-CHECKLIST.md) ──────────────
|
|
5283
|
+
* gray → faded base #7b7b7b / lighter #f5f5f5
|
|
5284
|
+
* blue → information base #335cff / lighter #ebf1ff
|
|
5285
|
+
* orange → warning base #fa7319 / lighter #fff3eb
|
|
5286
|
+
* red → error base #fb3748 / lighter #ffebec
|
|
5287
|
+
* green → success base #1fc16b / lighter #e3f7ec
|
|
5288
|
+
* yellow → away base #f6b51e / lighter #fffaeb
|
|
5289
|
+
* purple → feature base #7d52f4 / lighter #efebff
|
|
5290
|
+
* pink → highlighted base #fb4ba3 / lighter #ffebf4
|
|
5291
|
+
* teal → verified base #47c2ff / lighter #ebf8ff
|
|
5292
|
+
*
|
|
5293
|
+
* ── Icono ────────────────────────────────────────────────────────────────────
|
|
5294
|
+
* Render SIEMPRE vía <sui-icon name="..."> (regla del proyecto — nunca SVG
|
|
5295
|
+
* inline). Tamaño MEDIDO en Figma 263:1850: size/2 en 40/48/56/64
|
|
5296
|
+
* (20/24/28/32), pero Small (32) usa icono 20px (padding 6, NO 16=size/2) —
|
|
5297
|
+
* Figma no baja el glyph de 20px para mantener legibilidad.
|
|
5298
|
+
* El <sui-icon> recibe su tamaño DIRECTO vía [size]="iconSize()" (su @Input),
|
|
5299
|
+
* NO vía custom prop CSS — sui-icon lee solo su @Input `size`, no una variable.
|
|
5300
|
+
* El color del icono = `*-base` del color, vía la custom prop `--sui-key-icon-fg`.
|
|
5147
5301
|
*
|
|
5148
|
-
*
|
|
5149
|
-
*
|
|
5150
|
-
*
|
|
5151
|
-
*
|
|
5152
|
-
*
|
|
5153
|
-
*
|
|
5154
|
-
*
|
|
5155
|
-
*
|
|
5156
|
-
*
|
|
5157
|
-
*
|
|
5158
|
-
*
|
|
5159
|
-
*
|
|
5160
|
-
*
|
|
5161
|
-
*
|
|
5162
|
-
*
|
|
5163
|
-
*
|
|
5164
|
-
*
|
|
5165
|
-
*
|
|
5166
|
-
*
|
|
5167
|
-
*
|
|
5168
|
-
*
|
|
5169
|
-
* -
|
|
5170
|
-
*
|
|
5171
|
-
*
|
|
5302
|
+
* Display-only: NO es un control de formulario (sin CVA) y NO es clickeable
|
|
5303
|
+
* (sin touchstart/touchend ni role=button). Si en el futuro se vuelve interactivo
|
|
5304
|
+
* habría que envolverlo en un <button> con el fix iOS :active (ver CLAUDE.md).
|
|
5305
|
+
*
|
|
5306
|
+
* ── Dark mode ─────────────────────────────────────────────────────────────────
|
|
5307
|
+
* El style `stroke` usa bg `--sui-bg-white-0` (igual que los otros 104 usos del
|
|
5308
|
+
* token en SUI). El proyecto NO tiene color-scheme dark hoy (no hay bloque
|
|
5309
|
+
* prefers-color-scheme / .dark / [data-theme] en sui-tokens.scss). Si se agrega,
|
|
5310
|
+
* `--sui-bg-white-0` se redefine UNA vez a nivel token y todo SUI —incluido este
|
|
5311
|
+
* stroke bg— adapta. NO hardcodear un bg distinto acá: divergiría de Figma (la
|
|
5312
|
+
* spec del KeyIcon stroke ES bg-white-0) y del resto del DS.
|
|
5313
|
+
*
|
|
5314
|
+
* FIGMA-VERIFIED 2026-07-23 — set "Key Icons [1.1]" nodo 263:1850 (mismo file):
|
|
5315
|
+
* - Estructura confirmada vía get_metadata(263:1850): 90 symbols exactos =
|
|
5316
|
+
* Style(Stroke|Lighter) × Color(Gray/Blue/Orange/Red/Green/Yellow/Purple/
|
|
5317
|
+
* Pink/Teal) × Size(Small 32 / Medium 40 / Large 48 / X-Large 56 / 2X-Large 64).
|
|
5318
|
+
* - Stroke (263:1849, 264:2386): bg `--bg/white-0` + border 1px solid
|
|
5319
|
+
* `--stroke/soft-200` (#ebebeb) + `rounded-[var(--radius-full,999px)]` +
|
|
5320
|
+
* drop-shadow regular-shadow/x-small (0 1px 2px rgba(10,13,20,0.03)) ✓
|
|
5321
|
+
* — matchea `--sui-bg-white-0` / `--sui-stroke-soft-200` / `--sui-radius-full`
|
|
5322
|
+
* / `--sui-shadow-x-small` de sui-tokens.scss 1:1.
|
|
5323
|
+
* - Lighter (264:2716, 264:2604, 264:2496): bg `--state/<x>/lighter`
|
|
5324
|
+
* (faded #f5f5f5, information #ebf1ff), sin borde ni sombra, radius-full ✓.
|
|
5325
|
+
* - Icono (glyph placeholder `user-6-line` de RemixIcon, color `*-base`,
|
|
5326
|
+
* confirmado en screenshot del set completo): 64→32 (p16), 56→28 (p14),
|
|
5327
|
+
* 48→24 (p12), 40→20 (p10) = size/2 ✓; PERO Small 32→20 (p6), NO 16.
|
|
5328
|
+
* Desviación corregida en `iconSize` (piso de 20px).
|
|
5329
|
+
*/
|
|
5330
|
+
class SuiKeyIcon {
|
|
5331
|
+
/** RemixIcon name (sin prefijo), e.g. 'mail-line', 'home-5-fill'. Se pasa a <sui-icon>. */
|
|
5332
|
+
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
5333
|
+
/**
|
|
5334
|
+
* Estilo del contenedor. `style` choca con la property `style` del HTMLElement,
|
|
5335
|
+
* así que el input se llama `styleVariant` (host binding `data-sui-style`).
|
|
5336
|
+
*/
|
|
5337
|
+
styleVariant = input('stroke', ...(ngDevMode ? [{ debugName: "styleVariant" }] : /* istanbul ignore next */ []));
|
|
5338
|
+
/** Color del set canon (9). */
|
|
5339
|
+
color = input('gray', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
5340
|
+
/** Tamaño del contenedor en px. Uno de 32/40/48/56/64. */
|
|
5341
|
+
size = input(40, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
5342
|
+
/**
|
|
5343
|
+
* Tamaño del icono interno. Figma 263:1850 (medido por variant): size/2 en
|
|
5344
|
+
* 40/48/56/64, pero Small (32) mantiene el glyph en 20px (piso de legibilidad
|
|
5345
|
+
* — 264:2712/264:2716 usan padding 6, icono 20, NO 16).
|
|
5346
|
+
*/
|
|
5347
|
+
iconSize = computed(() => Math.max(20, this.size() / 2), ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
5348
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiKeyIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5349
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiKeyIcon, isStandalone: true, selector: "sui-key-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, styleVariant: { classPropertyName: "styleVariant", publicName: "styleVariant", 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 } }, host: { properties: { "attr.data-sui-style": "styleVariant()", "attr.data-sui-color": "color()", "style.--sui-key-icon-size.px": "size()", "attr.title": "null" } }, ngImport: i0, template: "<sui-icon\n class=\"sui-key-icon__icon\"\n [name]=\"name()\"\n [size]=\"iconSize()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;box-sizing:border-box;width:var(--sui-key-icon-size, 40px);height:var(--sui-key-icon-size, 40px);border-radius:var(--sui-radius-full);vertical-align:middle;--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter);background:var(--sui-key-icon-bg)}:host([data-sui-color=gray]){--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter)}:host([data-sui-color=blue]){--sui-key-icon-fg: var(--sui-state-information-base);--sui-key-icon-lighter: var(--sui-state-information-lighter)}:host([data-sui-color=orange]){--sui-key-icon-fg: var(--sui-state-warning-base);--sui-key-icon-lighter: var(--sui-state-warning-lighter)}:host([data-sui-color=red]){--sui-key-icon-fg: var(--sui-state-error-base);--sui-key-icon-lighter: var(--sui-state-error-lighter)}:host([data-sui-color=green]){--sui-key-icon-fg: var(--sui-state-success-base);--sui-key-icon-lighter: var(--sui-state-success-lighter)}:host([data-sui-color=yellow]){--sui-key-icon-fg: var(--sui-state-away-base);--sui-key-icon-lighter: var(--sui-state-away-lighter)}:host([data-sui-color=purple]){--sui-key-icon-fg: var(--sui-state-feature-base);--sui-key-icon-lighter: var(--sui-state-feature-lighter)}:host([data-sui-color=pink]){--sui-key-icon-fg: var(--sui-state-highlighted-base);--sui-key-icon-lighter: var(--sui-state-highlighted-lighter)}:host([data-sui-color=teal]){--sui-key-icon-fg: var(--sui-state-verified-base);--sui-key-icon-lighter: var(--sui-state-verified-lighter)}:host([data-sui-style=stroke]){--sui-key-icon-bg: var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);box-shadow:var(--sui-shadow-x-small)}:host([data-sui-style=lighter]){--sui-key-icon-bg: var(--sui-key-icon-lighter);border:none;box-shadow:none}.sui-key-icon__icon{display:inline-flex;color:var(--sui-key-icon-fg);line-height:0}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5350
|
+
}
|
|
5351
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiKeyIcon, decorators: [{
|
|
5352
|
+
type: Component,
|
|
5353
|
+
args: [{ selector: 'sui-key-icon', standalone: true, imports: [SuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
5354
|
+
/* data-sui-style + data-sui-color son los DRIVERS del styling per-variante en
|
|
5355
|
+
el SCSS. `size` NO se expone como data-attr: el SCSS dimensiona vía la custom
|
|
5356
|
+
prop --sui-key-icon-size, y el icono interno vía [size]="iconSize()". */
|
|
5357
|
+
'[attr.data-sui-style]': 'styleVariant()',
|
|
5358
|
+
'[attr.data-sui-color]': 'color()',
|
|
5359
|
+
'[style.--sui-key-icon-size.px]': 'size()',
|
|
5360
|
+
/* Strip native `title` attr — patrón canon Ontop (ver CLAUDE.md). */
|
|
5361
|
+
'[attr.title]': 'null',
|
|
5362
|
+
}, template: "<sui-icon\n class=\"sui-key-icon__icon\"\n [name]=\"name()\"\n [size]=\"iconSize()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;box-sizing:border-box;width:var(--sui-key-icon-size, 40px);height:var(--sui-key-icon-size, 40px);border-radius:var(--sui-radius-full);vertical-align:middle;--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter);background:var(--sui-key-icon-bg)}:host([data-sui-color=gray]){--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter)}:host([data-sui-color=blue]){--sui-key-icon-fg: var(--sui-state-information-base);--sui-key-icon-lighter: var(--sui-state-information-lighter)}:host([data-sui-color=orange]){--sui-key-icon-fg: var(--sui-state-warning-base);--sui-key-icon-lighter: var(--sui-state-warning-lighter)}:host([data-sui-color=red]){--sui-key-icon-fg: var(--sui-state-error-base);--sui-key-icon-lighter: var(--sui-state-error-lighter)}:host([data-sui-color=green]){--sui-key-icon-fg: var(--sui-state-success-base);--sui-key-icon-lighter: var(--sui-state-success-lighter)}:host([data-sui-color=yellow]){--sui-key-icon-fg: var(--sui-state-away-base);--sui-key-icon-lighter: var(--sui-state-away-lighter)}:host([data-sui-color=purple]){--sui-key-icon-fg: var(--sui-state-feature-base);--sui-key-icon-lighter: var(--sui-state-feature-lighter)}:host([data-sui-color=pink]){--sui-key-icon-fg: var(--sui-state-highlighted-base);--sui-key-icon-lighter: var(--sui-state-highlighted-lighter)}:host([data-sui-color=teal]){--sui-key-icon-fg: var(--sui-state-verified-base);--sui-key-icon-lighter: var(--sui-state-verified-lighter)}:host([data-sui-style=stroke]){--sui-key-icon-bg: var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);box-shadow:var(--sui-shadow-x-small)}:host([data-sui-style=lighter]){--sui-key-icon-bg: var(--sui-key-icon-lighter);border:none;box-shadow:none}.sui-key-icon__icon{display:inline-flex;color:var(--sui-key-icon-fg);line-height:0}\n"] }]
|
|
5363
|
+
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], styleVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleVariant", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
5364
|
+
|
|
5365
|
+
class SuiSwitch {
|
|
5366
|
+
size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
5367
|
+
checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
5368
|
+
checkedChange = output();
|
|
5369
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
5370
|
+
_disabledByForm = signal(false, ...(ngDevMode ? [{ debugName: "_disabledByForm" }] : /* istanbul ignore next */ []));
|
|
5371
|
+
isDisabled = computed(() => this.disabled() || this._disabledByForm(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
5372
|
+
/** CVA buffer — usado SOLO en form mode (formControlName/formControl).
|
|
5373
|
+
* Activado cuando `registerOnChange` se llama (Angular Forms lo hace). */
|
|
5374
|
+
_cvaValue = signal(false, ...(ngDevMode ? [{ debugName: "_cvaValue" }] : /* istanbul ignore next */ []));
|
|
5375
|
+
_useCvaValue = signal(false, ...(ngDevMode ? [{ debugName: "_useCvaValue" }] : /* istanbul ignore next */ []));
|
|
5376
|
+
/** Estado VISIBLE — input del parent en uso normal, _cvaValue en form mode. */
|
|
5377
|
+
effectiveChecked = computed(() => {
|
|
5378
|
+
if (this._useCvaValue())
|
|
5379
|
+
return this._cvaValue();
|
|
5380
|
+
return this.checked();
|
|
5381
|
+
}, ...(ngDevMode ? [{ debugName: "effectiveChecked" }] : /* istanbul ignore next */ []));
|
|
5382
|
+
_onChange = () => { };
|
|
5383
|
+
_onTouched = () => { };
|
|
5384
|
+
onToggle(e) {
|
|
5385
|
+
if (this.isDisabled())
|
|
5386
|
+
return;
|
|
5387
|
+
e.preventDefault();
|
|
5388
|
+
const next = !this.effectiveChecked();
|
|
5389
|
+
/* Patrón controlled: SOLO emitir intent. NO mutamos el input directamente
|
|
5390
|
+
(es input, no model). En form mode, actualizamos el buffer CVA porque
|
|
5391
|
+
los reactive forms no llaman writeValue después de un user change. */
|
|
5392
|
+
if (this._useCvaValue()) {
|
|
5393
|
+
this._cvaValue.set(next);
|
|
5394
|
+
}
|
|
5395
|
+
this.checkedChange.emit(next);
|
|
5396
|
+
this._onChange(next);
|
|
5397
|
+
this._onTouched();
|
|
5398
|
+
}
|
|
5399
|
+
writeValue(v) {
|
|
5400
|
+
this._cvaValue.set(!!v);
|
|
5401
|
+
this._useCvaValue.set(true);
|
|
5402
|
+
}
|
|
5403
|
+
registerOnChange(fn) {
|
|
5404
|
+
this._onChange = fn;
|
|
5405
|
+
this._useCvaValue.set(true);
|
|
5406
|
+
}
|
|
5407
|
+
registerOnTouched(fn) {
|
|
5408
|
+
this._onTouched = fn;
|
|
5409
|
+
}
|
|
5410
|
+
setDisabledState(isDisabled) {
|
|
5411
|
+
this._disabledByForm.set(isDisabled);
|
|
5412
|
+
}
|
|
5413
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5414
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiSwitch, isStandalone: true, selector: "sui-switch", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange" }, host: { listeners: { "click": "onToggle($event)", "keydown.space": "onToggle($event)", "keydown.enter": "onToggle($event)", "touchstart": "$event.currentTarget", "touchend": "$any($event.currentTarget).blur()" }, properties: { "attr.data-sui-size": "size()", "attr.data-sui-checked": "effectiveChecked() ? \"\" : null", "attr.data-sui-disabled": "isDisabled() ? \"\" : null", "attr.role": "\"switch\"", "attr.aria-checked": "effectiveChecked() ? \"true\" : \"false\"", "attr.aria-disabled": "isDisabled() ? \"true\" : null", "attr.tabindex": "isDisabled() ? \"-1\" : \"0\"" } }, providers: [
|
|
5415
|
+
{
|
|
5416
|
+
provide: NG_VALUE_ACCESSOR,
|
|
5417
|
+
useExisting: forwardRef(() => SuiSwitch),
|
|
5418
|
+
multi: true,
|
|
5419
|
+
},
|
|
5420
|
+
], ngImport: i0, template: "<span class=\"sui-switch__track\"></span>\n<span class=\"sui-switch__thumb\">\n <span class=\"sui-switch__dot\" aria-hidden=\"true\"></span>\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:inline-block;position:relative;width:32px;height:20px;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.sui-switch__track{position:absolute;top:2px;left:2px;width:28px;height:16px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__thumb{position:absolute;top:4px;left:4px;width:12px;height:12px;border-radius:999px;background:var(--sui-static-white, #ffffff);box-shadow:var(--sui-shadow-switch-thumb);display:flex;align-items:center;justify-content:center;transition:left var(--sui-motion-duration-fast) var(--sui-motion-ease-out),top var(--sui-motion-duration-fast) var(--sui-motion-ease-out),width var(--sui-motion-duration-fast) var(--sui-motion-ease-out),height var(--sui-motion-duration-fast) var(--sui-motion-ease-out),box-shadow var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__dot{width:4px;height:4px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}:host([data-sui-checked]) .sui-switch__track{background:var(--sui-primary-base)}:host([data-sui-checked]) .sui-switch__thumb{left:16px}:host([data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-base)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__track{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__dot{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__track{background:var(--sui-primary-dark)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-dark)}:host(:active:not([data-sui-disabled])) .sui-switch__thumb{width:10px;height:10px;top:5px}:host(:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host(:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]){cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]) .sui-switch__track{background:var(--sui-bg-white-0);box-shadow:inset 0 0 0 1px var(--sui-stroke-soft-200)}:host([data-sui-disabled]) .sui-switch__thumb{width:10px;height:10px;top:5px;background:var(--sui-bg-soft-200);box-shadow:none}:host([data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]) .sui-switch__dot{display:none}:host([data-sui-size=large]){width:40px;height:24px}:host([data-sui-size=large]) .sui-switch__track{width:36px;height:20px}:host([data-sui-size=large]) .sui-switch__thumb{width:16px;height:16px;top:4px;left:4px}:host([data-sui-size=large][data-sui-checked]) .sui-switch__thumb{left:20px}:host([data-sui-size=large]:active:not([data-sui-disabled])) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=large][data-sui-disabled]) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=xlarge]){width:48px;height:28px}:host([data-sui-size=xlarge]) .sui-switch__track{width:44px;height:24px}:host([data-sui-size=xlarge]) .sui-switch__thumb{width:20px;height:20px;top:4px;left:4px}:host([data-sui-size=xlarge][data-sui-checked]) .sui-switch__thumb{left:24px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:25px}:host([data-sui-size=xlarge][data-sui-disabled]) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:25px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5421
|
+
}
|
|
5422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSwitch, decorators: [{
|
|
5423
|
+
type: Component,
|
|
5424
|
+
args: [{ selector: 'sui-switch', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
5425
|
+
{
|
|
5426
|
+
provide: NG_VALUE_ACCESSOR,
|
|
5427
|
+
useExisting: forwardRef(() => SuiSwitch),
|
|
5428
|
+
multi: true,
|
|
5429
|
+
},
|
|
5430
|
+
], host: {
|
|
5431
|
+
'[attr.data-sui-size]': 'size()',
|
|
5432
|
+
'[attr.data-sui-checked]': 'effectiveChecked() ? "" : null',
|
|
5433
|
+
'[attr.data-sui-disabled]': 'isDisabled() ? "" : null',
|
|
5434
|
+
'[attr.role]': '"switch"',
|
|
5435
|
+
'[attr.aria-checked]': 'effectiveChecked() ? "true" : "false"',
|
|
5436
|
+
'[attr.aria-disabled]': 'isDisabled() ? "true" : null',
|
|
5437
|
+
'[attr.tabindex]': 'isDisabled() ? "-1" : "0"',
|
|
5438
|
+
'(click)': 'onToggle($event)',
|
|
5439
|
+
'(keydown.space)': 'onToggle($event)',
|
|
5440
|
+
'(keydown.enter)': 'onToggle($event)',
|
|
5441
|
+
/* iOS WKWebView fix — ver CLAUDE.md "iOS :active stuck en custom buttons". */
|
|
5442
|
+
'(touchstart)': '$event.currentTarget',
|
|
5443
|
+
'(touchend)': '$any($event.currentTarget).blur()',
|
|
5444
|
+
}, template: "<span class=\"sui-switch__track\"></span>\n<span class=\"sui-switch__thumb\">\n <span class=\"sui-switch__dot\" aria-hidden=\"true\"></span>\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:inline-block;position:relative;width:32px;height:20px;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.sui-switch__track{position:absolute;top:2px;left:2px;width:28px;height:16px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__thumb{position:absolute;top:4px;left:4px;width:12px;height:12px;border-radius:999px;background:var(--sui-static-white, #ffffff);box-shadow:var(--sui-shadow-switch-thumb);display:flex;align-items:center;justify-content:center;transition:left var(--sui-motion-duration-fast) var(--sui-motion-ease-out),top var(--sui-motion-duration-fast) var(--sui-motion-ease-out),width var(--sui-motion-duration-fast) var(--sui-motion-ease-out),height var(--sui-motion-duration-fast) var(--sui-motion-ease-out),box-shadow var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__dot{width:4px;height:4px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}:host([data-sui-checked]) .sui-switch__track{background:var(--sui-primary-base)}:host([data-sui-checked]) .sui-switch__thumb{left:16px}:host([data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-base)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__track{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__dot{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__track{background:var(--sui-primary-dark)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-dark)}:host(:active:not([data-sui-disabled])) .sui-switch__thumb{width:10px;height:10px;top:5px}:host(:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host(:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]){cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]) .sui-switch__track{background:var(--sui-bg-white-0);box-shadow:inset 0 0 0 1px var(--sui-stroke-soft-200)}:host([data-sui-disabled]) .sui-switch__thumb{width:10px;height:10px;top:5px;background:var(--sui-bg-soft-200);box-shadow:none}:host([data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]) .sui-switch__dot{display:none}:host([data-sui-size=large]){width:40px;height:24px}:host([data-sui-size=large]) .sui-switch__track{width:36px;height:20px}:host([data-sui-size=large]) .sui-switch__thumb{width:16px;height:16px;top:4px;left:4px}:host([data-sui-size=large][data-sui-checked]) .sui-switch__thumb{left:20px}:host([data-sui-size=large]:active:not([data-sui-disabled])) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=large][data-sui-disabled]) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=xlarge]){width:48px;height:28px}:host([data-sui-size=xlarge]) .sui-switch__track{width:44px;height:24px}:host([data-sui-size=xlarge]) .sui-switch__thumb{width:20px;height:20px;top:4px;left:4px}:host([data-sui-size=xlarge][data-sui-checked]) .sui-switch__thumb{left:24px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:25px}:host([data-sui-size=xlarge][data-sui-disabled]) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:25px}\n"] }]
|
|
5445
|
+
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], checkedChange: [{ type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
5446
|
+
|
|
5447
|
+
/**
|
|
5448
|
+
* SUI Content Label — SUI Design System 2.0
|
|
5449
|
+
*
|
|
5450
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO — set "Content Label [1.1]" nodo 2945:5539
|
|
5451
|
+
* (FIGMA-VERIFIED 2026-07-23: metadata + design context + screenshot del set).
|
|
5452
|
+
* 10 variants = Type(5: Basic | Left Icon | Avatar | Brand | Company)
|
|
5453
|
+
* × Size(2: Medium 40 | Large 48).
|
|
5454
|
+
*
|
|
5455
|
+
* Fila de contenido SIN card: [ leading ] [ text block flex-1 ] [ trailing ].
|
|
5456
|
+
* Es la pieza base de la familia content — el Content Card (2942:9503) es este
|
|
5457
|
+
* mismo row envuelto en una card con botón X (ver sui-content-card, que COMPONE
|
|
5458
|
+
* este componente).
|
|
5459
|
+
*
|
|
5460
|
+
* EXACT (del design context de los nodos 2945:5540/5548/5557/5575/5584/5628):
|
|
5461
|
+
* row → flex, items-center, gap 14
|
|
5462
|
+
* text block → flex-col, gap 4, flex 1 1 0, min-width 0
|
|
5463
|
+
* title row → flex, items-center, gap 4
|
|
5464
|
+
* label medium → Inter Medium 14/20 ls -0.084px, text/strong-950 (Label/Small)
|
|
5465
|
+
* label large → Inter Medium 16/24 ls -0.176px, text/strong-950 (Label/Medium)
|
|
5466
|
+
* sublabel → Inter Regular 12/16 ls 0, text/sub-600 (ambos sizes)
|
|
5467
|
+
* descr medium → Inter Regular 12/16 ls 0, text/sub-600 (Paragraph/X Small)
|
|
5468
|
+
* descr large → Inter Regular 14/20 ls -0.084px, text/sub-600 (Paragraph/Small)
|
|
5469
|
+
* left-icon → instancia "Key Icons [1.1]" stroke: medium p-10 + icono 20
|
|
5470
|
+
* (= 40px), large p-12 + icono 24 (= 48px), radius-full,
|
|
5471
|
+
* border stroke-soft-200, bg white-0, shadow x-small
|
|
5472
|
+
* → se compone <sui-key-icon size 40/48 styleVariant="stroke">.
|
|
5473
|
+
* avatar → sui-avatar 40px (size lg) / 48px (size xl), radius-full.
|
|
5474
|
+
* brand → logo de marca RAW 40/48px (Spotify en el set), SIN caja.
|
|
5475
|
+
* company → círculo de empresa 40/48px (Synergy en el set) → sui-avatar
|
|
5476
|
+
* con companyLogoSrc / iniciales (mismo patrón del Content Card).
|
|
5477
|
+
* badge trailing → Badge [1.1] px-8 py-2 radius-full, texto Inter Medium 12/16
|
|
5478
|
+
* = <sui-badge size="medium"> (Label/X Small, sin uppercase).
|
|
5479
|
+
* Figma: bg state/information/light #c0d5ff + texto
|
|
5480
|
+
* state/information/dark #122368 (= sui-badge color "blue");
|
|
5481
|
+
* el fallback del proyecto es color 'orange' (branding).
|
|
5482
|
+
* toggle → Switch [1.1] 32×20 = <sui-switch size="medium">.
|
|
5483
|
+
*
|
|
5484
|
+
* Token map (Figma → sui-tokens):
|
|
5485
|
+
* text/strong-950 → --sui-text-strong-950 (label)
|
|
5486
|
+
* text/sub-600 → --sui-text-sub-600 (sublabel + description)
|
|
5487
|
+
* Label/Small → --sui-type-label-sm-* (label medium)
|
|
5488
|
+
* Label/Medium → --sui-type-label-md-* (label large)
|
|
5489
|
+
* Paragraph/X Small → --sui-type-paragraph-xs-* (sublabel + descr medium)
|
|
5490
|
+
* Paragraph/Small → --sui-type-paragraph-sm-* (descr large)
|
|
5491
|
+
*
|
|
5492
|
+
* Extensiones del proyecto (NO son ejes del set de Figma, documentadas):
|
|
5493
|
+
* - `badgePlacement='title'` — coloca el badge inline en el title row, como lo
|
|
5494
|
+
* renderiza el Content Card (2942:9503). Default 'trailing' (canon del set).
|
|
5495
|
+
* - `disabled` — atenúa texto/leading a tokens disabled-300 y bloquea el
|
|
5496
|
+
* switch. Heredado de la familia (el Content Card lo expone) para que la
|
|
5497
|
+
* composición no pierda el estado.
|
|
5498
|
+
*
|
|
5499
|
+
* Usage:
|
|
5500
|
+
* <sui-content-label label="Notificaciones" sublabel="(Push)"
|
|
5501
|
+
* description="Recibe avisos de tus pedidos"
|
|
5502
|
+
* [toggle]="true" [(toggleChecked)]="pushOn" />
|
|
5503
|
+
* <sui-content-label type="left-icon" icon="user-6-line" size="large"
|
|
5504
|
+
* label="Perfil" description="Datos de tu cuenta" badge="NUEVO" />
|
|
5505
|
+
* <sui-content-label type="avatar" [avatar]="{ initials: 'AT' }"
|
|
5506
|
+
* label="Ana Torres" description="ana@correo.com" />
|
|
5507
|
+
*/
|
|
5508
|
+
class SuiContentLabel {
|
|
5509
|
+
/** Tipo de leading visual. */
|
|
5510
|
+
type = input('basic', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
5511
|
+
/** Size del set: medium (leading 40, Label/Small) | large (leading 48, Label/Medium). */
|
|
5512
|
+
size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
5513
|
+
/** Label principal — Label/Small (medium) / Label/Medium (large), text-strong-950. */
|
|
5514
|
+
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
5515
|
+
/** Sublabel inline al lado del label — Paragraph/X Small, text-sub-600. Vacío = no se renderiza. */
|
|
5516
|
+
sublabel = input('', ...(ngDevMode ? [{ debugName: "sublabel" }] : /* istanbul ignore next */ []));
|
|
5517
|
+
/** Descripción bajo el title row — Paragraph/X Small (medium) / Paragraph/Small (large), text-sub-600. */
|
|
5518
|
+
description = input('', ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
5519
|
+
/** RemixIcon name (sin 'ri-') para type=left-icon — va al sui-key-icon. */
|
|
5520
|
+
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
5521
|
+
/** Avatar del leading (type=avatar / company) — string shorthand (src directo)
|
|
5522
|
+
o SuiAvatarConfig { src?, initials?, color? }. */
|
|
5523
|
+
avatar = input(null, ...(ngDevMode ? [{ debugName: "avatar" }] : /* istanbul ignore next */ []));
|
|
5524
|
+
avatarCfg = computed(() => {
|
|
5525
|
+
const a = this.avatar();
|
|
5526
|
+
return a ? (typeof a === 'string' ? { src: a } : a) : null;
|
|
5527
|
+
}, ...(ngDevMode ? [{ debugName: "avatarCfg" }] : /* istanbul ignore next */ []));
|
|
5528
|
+
/** Logo de empresa para type=company (mini-avatar bottom-right del sui-avatar). */
|
|
5529
|
+
companyLogoSrc = input(null, ...(ngDevMode ? [{ debugName: "companyLogoSrc" }] : /* istanbul ignore next */ []));
|
|
5530
|
+
/** Marca para type=brand (logo raw, sin caja). */
|
|
5531
|
+
brand = input(null, ...(ngDevMode ? [{ debugName: "brand" }] : /* istanbul ignore next */ []));
|
|
5532
|
+
/** Badge — string shorthand o SuiBadgeConfig. Fallbacks: color 'orange'
|
|
5533
|
+
(branding; el DS de Figma usa 'blue'), variant 'lighter', size 'medium'
|
|
5534
|
+
(Figma: Badge px-8 py-2 texto 12/16 = sui-badge medium). null/'' = sin badge. */
|
|
5535
|
+
badge = input(null, ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
5536
|
+
badgeCfg = computed(() => {
|
|
5537
|
+
const b = this.badge();
|
|
5538
|
+
return b ? (typeof b === 'string' ? { label: b } : b) : null;
|
|
5539
|
+
}, ...(ngDevMode ? [{ debugName: "badgeCfg" }] : /* istanbul ignore next */ []));
|
|
5540
|
+
/** Dónde renderiza el badge: 'trailing' (canon Figma) | 'title' (composición Content Card). */
|
|
5541
|
+
badgePlacement = input('trailing', ...(ngDevMode ? [{ debugName: "badgePlacement" }] : /* istanbul ignore next */ []));
|
|
5542
|
+
/** Muestra el switch trailing (eje Toggle del set). */
|
|
5543
|
+
toggle = input(false, ...(ngDevMode ? [{ debugName: "toggle" }] : /* istanbul ignore next */ []));
|
|
5544
|
+
/** Estado del switch — two-way: [(toggleChecked)]. */
|
|
5545
|
+
toggleChecked = input(false, ...(ngDevMode ? [{ debugName: "toggleChecked" }] : /* istanbul ignore next */ []));
|
|
5546
|
+
toggleCheckedChange = output();
|
|
5547
|
+
/** Atenúa texto/leading a tokens disabled-300 y bloquea el switch (extensión de familia). */
|
|
5548
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
5549
|
+
/** True si hay leading visual (todo menos basic). */
|
|
5550
|
+
hasLeading = computed(() => this.type() !== 'basic', ...(ngDevMode ? [{ debugName: "hasLeading" }] : /* istanbul ignore next */ []));
|
|
5551
|
+
/** Leading = 40px (medium) / 48px (large) — ancla la altura del row. */
|
|
5552
|
+
keyIconSize = computed(() => (this.size() === 'large' ? 48 : 40), ...(ngDevMode ? [{ debugName: "keyIconSize" }] : /* istanbul ignore next */ []));
|
|
5553
|
+
avatarSize = computed(() => (this.size() === 'large' ? 'xl' : 'lg'), ...(ngDevMode ? [{ debugName: "avatarSize" }] : /* istanbul ignore next */ []));
|
|
5554
|
+
brandLogoSize = computed(() => (this.size() === 'large' ? '2xl' : 'xl'), ...(ngDevMode ? [{ debugName: "brandLogoSize" }] : /* istanbul ignore next */ []));
|
|
5555
|
+
onToggleChange(checked) {
|
|
5556
|
+
this.toggleCheckedChange.emit(checked);
|
|
5557
|
+
}
|
|
5558
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiContentLabel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5559
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiContentLabel, isStandalone: true, selector: "sui-content-label", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, sublabel: { classPropertyName: "sublabel", publicName: "sublabel", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, companyLogoSrc: { classPropertyName: "companyLogoSrc", publicName: "companyLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, badgePlacement: { classPropertyName: "badgePlacement", publicName: "badgePlacement", isSignal: true, isRequired: false, transformFunction: null }, toggle: { classPropertyName: "toggle", publicName: "toggle", isSignal: true, isRequired: false, transformFunction: null }, toggleChecked: { classPropertyName: "toggleChecked", publicName: "toggleChecked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toggleCheckedChange: "toggleCheckedChange" }, host: { properties: { "attr.data-sui-type": "type()", "attr.data-sui-size": "size()", "attr.data-sui-disabled": "disabled() ? \"\" : null", "attr.role": "\"group\"", "attr.aria-label": "label() || null", "attr.aria-disabled": "disabled() ? \"true\" : null" } }, ngImport: i0, template: "@if (hasLeading()) {\n <div class=\"sui-content-label__leading\">\n @switch (type()) {\n @case ('left-icon') {\n @if (icon(); as i) {\n <sui-key-icon [name]=\"i\" [size]=\"keyIconSize()\" styleVariant=\"stroke\" color=\"gray\" />\n }\n }\n\n @case ('avatar') {\n <sui-avatar\n [size]=\"avatarSize()\"\n [src]=\"avatarCfg()?.src ?? null\"\n [initials]=\"avatarCfg()?.initials ?? ''\"\n [color]=\"avatarCfg()?.color ?? 'slate'\"\n [alt]=\"label()\"\n />\n }\n\n @case ('company') {\n <sui-avatar\n [size]=\"avatarSize()\"\n [src]=\"avatarCfg()?.src ?? null\"\n [initials]=\"avatarCfg()?.initials ?? ''\"\n [color]=\"avatarCfg()?.color ?? 'slate'\"\n [alt]=\"label()\"\n [companyLogoSrc]=\"companyLogoSrc()\"\n [status]=\"companyLogoSrc() ? 'company' : null\"\n />\n }\n\n @case ('brand') {\n @if (brand(); as b) {\n <sui-brand-logo [company]=\"b\" [size]=\"brandLogoSize()\" />\n }\n }\n }\n </div>\n}\n\n<div class=\"sui-content-label__text\">\n <div class=\"sui-content-label__title-row\">\n <span class=\"sui-content-label__label\">{{ label() }}</span>\n @if (sublabel()) {\n <span class=\"sui-content-label__sublabel\">{{ sublabel() }}</span>\n }\n @if (badgePlacement() === 'title' && badgeCfg(); as bcfg) {\n <sui-badge\n class=\"sui-content-label__badge\"\n [color]=\"bcfg.color ?? 'orange'\"\n [variant]=\"bcfg.variant ?? 'lighter'\"\n [size]=\"bcfg.size ?? 'medium'\"\n [disabled]=\"disabled()\"\n >\n {{ bcfg.label }}\n </sui-badge>\n }\n </div>\n @if (description()) {\n <span class=\"sui-content-label__description\">{{ description() }}</span>\n }\n</div>\n\n@if (badgePlacement() === 'trailing' && badgeCfg(); as bcfg) {\n <sui-badge\n class=\"sui-content-label__badge sui-content-label__badge--trailing\"\n [color]=\"bcfg.color ?? 'orange'\"\n [variant]=\"bcfg.variant ?? 'lighter'\"\n [size]=\"bcfg.size ?? 'medium'\"\n [disabled]=\"disabled()\"\n >\n {{ bcfg.label }}\n </sui-badge>\n}\n\n@if (toggle()) {\n <sui-switch\n class=\"sui-content-label__toggle\"\n size=\"medium\"\n [checked]=\"toggleChecked()\"\n [disabled]=\"disabled()\"\n (checkedChange)=\"onToggleChange($event)\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:14px;box-sizing:border-box;width:100%;font-family:var(--sui-font-sans, \"Inter\", system-ui, sans-serif);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-content-label__leading{flex-shrink:0;display:flex;align-items:center;justify-content:center}.sui-content-label__text{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:4px}.sui-content-label__title-row{display:flex;align-items:center;gap:4px;min-width:0}.sui-content-label__label{min-width:0;font-size:var(--sui-type-label-sm-size);font-weight:var(--sui-type-label-sm-weight);line-height:var(--sui-type-label-sm-line);letter-spacing:var(--sui-type-label-sm-spacing);color:var(--sui-text-strong-950);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-content-label__sublabel{flex-shrink:0;font-size:var(--sui-type-paragraph-xs-size);font-weight:var(--sui-type-paragraph-xs-weight);line-height:var(--sui-type-paragraph-xs-line);letter-spacing:var(--sui-type-paragraph-xs-spacing);color:var(--sui-text-sub-600);white-space:nowrap}.sui-content-label__description{font-size:var(--sui-type-paragraph-xs-size);font-weight:var(--sui-type-paragraph-xs-weight);line-height:var(--sui-type-paragraph-xs-line);letter-spacing:var(--sui-type-paragraph-xs-spacing);color:var(--sui-text-sub-600);overflow-wrap:break-word}:host([data-sui-size=large]) .sui-content-label__label{font-size:var(--sui-type-label-md-size);line-height:var(--sui-type-label-md-line);letter-spacing:var(--sui-type-label-md-spacing)}:host([data-sui-size=large]) .sui-content-label__description{font-size:var(--sui-type-paragraph-sm-size);line-height:var(--sui-type-paragraph-sm-line);letter-spacing:var(--sui-type-paragraph-sm-spacing)}.sui-content-label__badge,.sui-content-label__toggle{flex-shrink:0}:host([data-sui-disabled]) .sui-content-label__label{color:var(--sui-text-disabled-300)}:host([data-sui-disabled]) .sui-content-label__sublabel,:host([data-sui-disabled]) .sui-content-label__description{color:var(--sui-text-disabled-300)}:host([data-sui-disabled]) .sui-content-label__leading{opacity:.5}\n"], dependencies: [{ kind: "component", type: SuiKeyIcon, selector: "sui-key-icon", inputs: ["name", "styleVariant", "color", "size"] }, { kind: "component", type: SuiBadge, selector: "sui-badge", inputs: ["color", "variant", "size", "type", "disabled"] }, { kind: "component", type: SuiAvatar, selector: "sui-avatar", inputs: ["size", "src", "alt", "initials", "color", "status", "memojiSrc", "illustrationSrc", "icon", "companyLogoSrc", "topBadge", "bgColor"] }, { kind: "component", type: SuiBrandLogo, selector: "sui-brand-logo", inputs: ["company", "variant", "size", "href", "target", "rel", "disabled", "ariaLabel"] }, { kind: "component", type: SuiSwitch, selector: "sui-switch", inputs: ["size", "checked", "disabled"], outputs: ["checkedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5560
|
+
}
|
|
5561
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiContentLabel, decorators: [{
|
|
5562
|
+
type: Component,
|
|
5563
|
+
args: [{ selector: 'sui-content-label', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SuiKeyIcon, SuiBadge, SuiAvatar, SuiBrandLogo, SuiSwitch], host: {
|
|
5564
|
+
'[attr.data-sui-type]': 'type()',
|
|
5565
|
+
'[attr.data-sui-size]': 'size()',
|
|
5566
|
+
'[attr.data-sui-disabled]': 'disabled() ? "" : null',
|
|
5567
|
+
'[attr.role]': '"group"',
|
|
5568
|
+
'[attr.aria-label]': 'label() || null',
|
|
5569
|
+
'[attr.aria-disabled]': 'disabled() ? "true" : null',
|
|
5570
|
+
}, template: "@if (hasLeading()) {\n <div class=\"sui-content-label__leading\">\n @switch (type()) {\n @case ('left-icon') {\n @if (icon(); as i) {\n <sui-key-icon [name]=\"i\" [size]=\"keyIconSize()\" styleVariant=\"stroke\" color=\"gray\" />\n }\n }\n\n @case ('avatar') {\n <sui-avatar\n [size]=\"avatarSize()\"\n [src]=\"avatarCfg()?.src ?? null\"\n [initials]=\"avatarCfg()?.initials ?? ''\"\n [color]=\"avatarCfg()?.color ?? 'slate'\"\n [alt]=\"label()\"\n />\n }\n\n @case ('company') {\n <sui-avatar\n [size]=\"avatarSize()\"\n [src]=\"avatarCfg()?.src ?? null\"\n [initials]=\"avatarCfg()?.initials ?? ''\"\n [color]=\"avatarCfg()?.color ?? 'slate'\"\n [alt]=\"label()\"\n [companyLogoSrc]=\"companyLogoSrc()\"\n [status]=\"companyLogoSrc() ? 'company' : null\"\n />\n }\n\n @case ('brand') {\n @if (brand(); as b) {\n <sui-brand-logo [company]=\"b\" [size]=\"brandLogoSize()\" />\n }\n }\n }\n </div>\n}\n\n<div class=\"sui-content-label__text\">\n <div class=\"sui-content-label__title-row\">\n <span class=\"sui-content-label__label\">{{ label() }}</span>\n @if (sublabel()) {\n <span class=\"sui-content-label__sublabel\">{{ sublabel() }}</span>\n }\n @if (badgePlacement() === 'title' && badgeCfg(); as bcfg) {\n <sui-badge\n class=\"sui-content-label__badge\"\n [color]=\"bcfg.color ?? 'orange'\"\n [variant]=\"bcfg.variant ?? 'lighter'\"\n [size]=\"bcfg.size ?? 'medium'\"\n [disabled]=\"disabled()\"\n >\n {{ bcfg.label }}\n </sui-badge>\n }\n </div>\n @if (description()) {\n <span class=\"sui-content-label__description\">{{ description() }}</span>\n }\n</div>\n\n@if (badgePlacement() === 'trailing' && badgeCfg(); as bcfg) {\n <sui-badge\n class=\"sui-content-label__badge sui-content-label__badge--trailing\"\n [color]=\"bcfg.color ?? 'orange'\"\n [variant]=\"bcfg.variant ?? 'lighter'\"\n [size]=\"bcfg.size ?? 'medium'\"\n [disabled]=\"disabled()\"\n >\n {{ bcfg.label }}\n </sui-badge>\n}\n\n@if (toggle()) {\n <sui-switch\n class=\"sui-content-label__toggle\"\n size=\"medium\"\n [checked]=\"toggleChecked()\"\n [disabled]=\"disabled()\"\n (checkedChange)=\"onToggleChange($event)\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:14px;box-sizing:border-box;width:100%;font-family:var(--sui-font-sans, \"Inter\", system-ui, sans-serif);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-content-label__leading{flex-shrink:0;display:flex;align-items:center;justify-content:center}.sui-content-label__text{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:4px}.sui-content-label__title-row{display:flex;align-items:center;gap:4px;min-width:0}.sui-content-label__label{min-width:0;font-size:var(--sui-type-label-sm-size);font-weight:var(--sui-type-label-sm-weight);line-height:var(--sui-type-label-sm-line);letter-spacing:var(--sui-type-label-sm-spacing);color:var(--sui-text-strong-950);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-content-label__sublabel{flex-shrink:0;font-size:var(--sui-type-paragraph-xs-size);font-weight:var(--sui-type-paragraph-xs-weight);line-height:var(--sui-type-paragraph-xs-line);letter-spacing:var(--sui-type-paragraph-xs-spacing);color:var(--sui-text-sub-600);white-space:nowrap}.sui-content-label__description{font-size:var(--sui-type-paragraph-xs-size);font-weight:var(--sui-type-paragraph-xs-weight);line-height:var(--sui-type-paragraph-xs-line);letter-spacing:var(--sui-type-paragraph-xs-spacing);color:var(--sui-text-sub-600);overflow-wrap:break-word}:host([data-sui-size=large]) .sui-content-label__label{font-size:var(--sui-type-label-md-size);line-height:var(--sui-type-label-md-line);letter-spacing:var(--sui-type-label-md-spacing)}:host([data-sui-size=large]) .sui-content-label__description{font-size:var(--sui-type-paragraph-sm-size);line-height:var(--sui-type-paragraph-sm-line);letter-spacing:var(--sui-type-paragraph-sm-spacing)}.sui-content-label__badge,.sui-content-label__toggle{flex-shrink:0}:host([data-sui-disabled]) .sui-content-label__label{color:var(--sui-text-disabled-300)}:host([data-sui-disabled]) .sui-content-label__sublabel,:host([data-sui-disabled]) .sui-content-label__description{color:var(--sui-text-disabled-300)}:host([data-sui-disabled]) .sui-content-label__leading{opacity:.5}\n"] }]
|
|
5571
|
+
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], sublabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sublabel", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], companyLogoSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "companyLogoSrc", required: false }] }], brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], badgePlacement: [{ type: i0.Input, args: [{ isSignal: true, alias: "badgePlacement", required: false }] }], toggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggle", required: false }] }], toggleChecked: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleChecked", required: false }] }], toggleCheckedChange: [{ type: i0.Output, args: ["toggleCheckedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
5572
|
+
|
|
5573
|
+
/**
|
|
5574
|
+
* SUI Content Card — SUI Design System 2.0
|
|
5575
|
+
*
|
|
5576
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO — set "Content Card [1.1]" nodo 2942:9503
|
|
5577
|
+
* (FIGMA-VERIFIED 2026-07-23: metadata + design context + screenshot del set;
|
|
5578
|
+
* cierra el ⚠️ "referencia no verificada" del 2026-05-29 — el nodo real SÍ vive
|
|
5579
|
+
* en este fileKey). 6 variants = Type(Basic | Left Icon | Avatar | Card Provider
|
|
5580
|
+
* | Brand | Company), un solo size (row de 40px, frames de ejemplo 360×72).
|
|
5581
|
+
*
|
|
5582
|
+
* Es el Content Label (set 2945:5539) envuelto en una card — este componente
|
|
5583
|
+
* COMPONE <sui-content-label size="medium" badgePlacement="title"> (la deuda
|
|
5584
|
+
* "extraer el row a sui-content-label" del 2026-05-29 quedó saldada).
|
|
5585
|
+
*
|
|
5586
|
+
* EXACT (design context de 2942:9504/9512/9530 + screenshot):
|
|
5587
|
+
* card → bg white-0, border 1px stroke-soft-200, radius-12, padding 16,
|
|
5588
|
+
* shadow x-small, flex row gap 14 items-center
|
|
5589
|
+
* text block → flex-col gap 4; title row gap 4 (rendereado por sui-content-label)
|
|
5590
|
+
* title → Inter Medium 14/20 ls -0.084px, text/strong-950 (Label/Small)
|
|
5591
|
+
* sublabel → Inter Regular 12/16, text/sub-600 — inline al lado del título
|
|
5592
|
+
* subtitle → Inter Regular 12/16, text/sub-600 (Paragraph/X Small) — la
|
|
5593
|
+
* "description" del label (el nodo 2945 la llama description)
|
|
5594
|
+
* badge → inline en el title row DESPUÉS del sublabel; Badge px-8 py-2
|
|
5595
|
+
* radius-full, texto Inter Medium 11/12 UPPERCASE tracking 0.22px
|
|
5596
|
+
* (Subheading/2X Small) = sui-badge size="small". Figma: bg
|
|
5597
|
+
* state/information/light #c0d5ff + texto state/information/dark
|
|
5598
|
+
* #122368 (= color "blue"); fallback del proyecto = 'orange'.
|
|
5599
|
+
* left-icon → instancia "Key Icons [1.1]" stroke 40px (p-10 + icono 20,
|
|
5600
|
+
* radius-full, border stroke-soft-200, shadow x-small)
|
|
5601
|
+
* avatar → sui-avatar 40px (= size lg; ojo: md es 32px)
|
|
5602
|
+
* brand → logo de marca RAW 40px, SIN caja (Spotify en el set)
|
|
5603
|
+
* company → círculo de empresa 40px (Synergy en el set)
|
|
5604
|
+
* card-provider → tile 32×24 radius-4 con la marca de la tarjeta (Mastercard
|
|
5605
|
+
* en el set, asset con bg #252525 propio)
|
|
5606
|
+
* X dismiss → close-line 20px a la derecha (gap 14 del row)
|
|
5607
|
+
*
|
|
5608
|
+
* Correcciones aplicadas en la verificación 2026-07-23 (antes inferido ≠ Figma):
|
|
5609
|
+
* - gap del row 12 → 14 · gap del text block 2 → 4 · gap del title row 6 → 4
|
|
5610
|
+
* - subtitle 14/20 (Paragraph/Small) → 12/16 (Paragraph/X Small)
|
|
5611
|
+
* - left-icon: cuadro 40×40 radius-10 → sui-key-icon circular (radius-full)
|
|
5612
|
+
* - avatar: size md (32px) → lg (40px)
|
|
5613
|
+
* - brand: cuadro con borde → logo raw 40px sin caja
|
|
5614
|
+
* - card-provider: 40×28 radius-6 → 32×24 radius-4
|
|
5615
|
+
* - nuevo input `sublabel` (el set lo trae en el title row; faltaba)
|
|
5616
|
+
*
|
|
5617
|
+
* Adaptaciones deliberadas (documentadas, NO son drift):
|
|
5618
|
+
* - card-provider: el asset de Figma es el tile Mastercard con bg #252525
|
|
5619
|
+
* propio del arte. Sin card-tiles como asset en la lib, se renderiza el
|
|
5620
|
+
* brand logo centrado en un tile blanco 32×24 con borde stroke-soft-200.
|
|
5621
|
+
* - Badge fallback color 'orange' (branding del proyecto; el DS usa blue).
|
|
5622
|
+
* Cualquier consumer pasa `[badge]="{ label: 'X', color: 'blue' }"`.
|
|
5172
5623
|
* - X dismiss hover/active: hover → bg-weak-50 + icon strong-950, active →
|
|
5173
5624
|
* scale(0.96). INFERIDO, el set no publica estados del botón. PRESERVAR.
|
|
5174
|
-
* - disabled
|
|
5175
|
-
*
|
|
5176
|
-
*
|
|
5625
|
+
* - disabled: extensión del proyecto (el set no publica eje State); tokens
|
|
5626
|
+
* disabled-300 por consistencia con sui-badge/sui-form-label.
|
|
5627
|
+
*
|
|
5628
|
+
* iOS :active — el botón X es clickeable custom: lleva (touchstart)/(touchend)
|
|
5629
|
+
* para liberar el estado active en WKWebView (regla del proyecto).
|
|
5177
5630
|
*
|
|
5178
5631
|
* Usage:
|
|
5179
5632
|
* <sui-content-card type="left-icon" icon="bank-card-line"
|
|
5180
5633
|
* title="Visa **** 4242" subtitle="Expira 09/27"
|
|
5181
5634
|
* badge="Principal" (dismiss)="onRemove()" />
|
|
5182
5635
|
* <sui-content-card type="avatar" [avatar]="{ src: user.photo, initials: 'AT' }"
|
|
5183
|
-
* title="Ana Torres" subtitle="ana@correo.com" />
|
|
5636
|
+
* title="Ana Torres" sublabel="(Admin)" subtitle="ana@correo.com" />
|
|
5184
5637
|
* <sui-content-card type="brand" brand="stripe" title="Stripe" subtitle="Conectado"
|
|
5185
5638
|
* [badge]="{ label: 'Activo', color: 'green' }" />
|
|
5186
5639
|
*/
|
|
5187
5640
|
class SuiContentCard {
|
|
5188
5641
|
/** Tipo de leading visual. */
|
|
5189
5642
|
type = input('basic', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
5190
|
-
/** Título — Label/Small, text-strong-950. */
|
|
5643
|
+
/** Título — Label/Small 14/20, text-strong-950. */
|
|
5191
5644
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
5192
|
-
/**
|
|
5645
|
+
/** Sublabel inline al lado del título — Paragraph/X Small 12/16, text-sub-600
|
|
5646
|
+
(Figma 2942:9517). Vacío = no se renderiza. */
|
|
5647
|
+
sublabel = input('', ...(ngDevMode ? [{ debugName: "sublabel" }] : /* istanbul ignore next */ []));
|
|
5648
|
+
/** Subtítulo (la "description" del Content Label) — Paragraph/X Small 12/16, text-sub-600. */
|
|
5193
5649
|
subtitle = input('', ...(ngDevMode ? [{ debugName: "subtitle" }] : /* istanbul ignore next */ []));
|
|
5194
|
-
/** Badge inline (Title row) — string shorthand ('Principal')
|
|
5195
|
-
(label + color/variant/size, tipado como sui-badge).
|
|
5196
|
-
color 'orange' (branding; el DS de Figma usa 'blue'),
|
|
5197
|
-
size 'small'. null/'' = sin badge. */
|
|
5650
|
+
/** Badge inline (Title row, después del sublabel) — string shorthand ('Principal')
|
|
5651
|
+
o SuiBadgeConfig (label + color/variant/size, tipado como sui-badge).
|
|
5652
|
+
Fallbacks de la card: color 'orange' (branding; el DS de Figma usa 'blue'),
|
|
5653
|
+
variant 'lighter', size 'small'. null/'' = sin badge. */
|
|
5198
5654
|
badge = input(null, ...(ngDevMode ? [{ debugName: "badge" }] : /* istanbul ignore next */ []));
|
|
5655
|
+
/** Config normalizado COMPLETO (fallbacks de la card aplicados) — se pasa al
|
|
5656
|
+
sui-content-label compuesto, cuyo fallback de size es 'medium' (canon del
|
|
5657
|
+
label); la card fija size 'small' (Subheading/2X Small del nodo 2942:9518). */
|
|
5199
5658
|
badgeCfg = computed(() => {
|
|
5200
5659
|
const b = this.badge();
|
|
5201
|
-
|
|
5660
|
+
if (!b)
|
|
5661
|
+
return null;
|
|
5662
|
+
const cfg = typeof b === 'string' ? { label: b } : b;
|
|
5663
|
+
return {
|
|
5664
|
+
label: cfg.label,
|
|
5665
|
+
color: cfg.color ?? 'orange',
|
|
5666
|
+
variant: cfg.variant ?? 'lighter',
|
|
5667
|
+
size: cfg.size ?? 'small',
|
|
5668
|
+
};
|
|
5202
5669
|
}, ...(ngDevMode ? [{ debugName: "badgeCfg" }] : /* istanbul ignore next */ []));
|
|
5203
5670
|
/** RemixIcon name (sin 'ri-') para type=left-icon. */
|
|
5204
5671
|
icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
5205
5672
|
/** Avatar del leading (type=avatar / company) — string shorthand (src directo)
|
|
5206
5673
|
o SuiAvatarConfig { src?, initials?, color? }. null = sin avatar. */
|
|
5207
5674
|
avatar = input(null, ...(ngDevMode ? [{ debugName: "avatar" }] : /* istanbul ignore next */ []));
|
|
5208
|
-
avatarCfg = computed(() => {
|
|
5209
|
-
const a = this.avatar();
|
|
5210
|
-
return a ? (typeof a === 'string' ? { src: a } : a) : null;
|
|
5211
|
-
}, ...(ngDevMode ? [{ debugName: "avatarCfg" }] : /* istanbul ignore next */ []));
|
|
5212
5675
|
/** Logo de empresa para type=company (mini-avatar bottom-right del sui-avatar). */
|
|
5213
5676
|
companyLogoSrc = input(null, ...(ngDevMode ? [{ debugName: "companyLogoSrc" }] : /* istanbul ignore next */ []));
|
|
5214
5677
|
/** Marca para type=brand / card-provider. */
|
|
@@ -5226,17 +5689,24 @@ class SuiContentCard {
|
|
|
5226
5689
|
dismiss = output();
|
|
5227
5690
|
/** True si hay leading visual (todo menos basic). */
|
|
5228
5691
|
hasLeading = computed(() => this.type() !== 'basic', ...(ngDevMode ? [{ debugName: "hasLeading" }] : /* istanbul ignore next */ []));
|
|
5692
|
+
/** Type que se delega al sui-content-label compuesto. card-provider no existe
|
|
5693
|
+
en el set del label (2945:5539) → la card renderiza ese leading ella misma
|
|
5694
|
+
y el label va en 'basic' (solo text block). */
|
|
5695
|
+
labelType = computed(() => {
|
|
5696
|
+
const t = this.type();
|
|
5697
|
+
return t === 'card-provider' ? 'basic' : t;
|
|
5698
|
+
}, ...(ngDevMode ? [{ debugName: "labelType" }] : /* istanbul ignore next */ []));
|
|
5229
5699
|
onDismiss(event) {
|
|
5230
5700
|
if (this.disabled())
|
|
5231
5701
|
return;
|
|
5232
5702
|
this.dismiss.emit(event);
|
|
5233
5703
|
}
|
|
5234
5704
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiContentCard, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5235
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiContentCard, isStandalone: true, selector: "sui-content-card", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, companyLogoSrc: { classPropertyName: "companyLogoSrc", publicName: "companyLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, dismissAriaLabel: { classPropertyName: "dismissAriaLabel", publicName: "dismissAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismiss: "dismiss" }, host: { properties: { "attr.title": "null", "attr.data-sui-type": "type()", "attr.data-sui-disabled": "disabled() ? \"\" : null", "attr.role": "\"group\"", "attr.aria-label": "title() || null", "attr.aria-disabled": "disabled() ? \"true\" : null" } }, ngImport: i0, template: "
|
|
5705
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiContentCard, isStandalone: true, selector: "sui-content-card", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, sublabel: { classPropertyName: "sublabel", publicName: "sublabel", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, companyLogoSrc: { classPropertyName: "companyLogoSrc", publicName: "companyLogoSrc", isSignal: true, isRequired: false, transformFunction: null }, brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, dismissAriaLabel: { classPropertyName: "dismissAriaLabel", publicName: "dismissAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dismiss: "dismiss" }, host: { properties: { "attr.title": "null", "attr.data-sui-type": "type()", "attr.data-sui-disabled": "disabled() ? \"\" : null", "attr.role": "\"group\"", "attr.aria-label": "title() || null", "attr.aria-disabled": "disabled() ? \"true\" : null" } }, ngImport: i0, template: "<!-- card-provider no existe en el set del Content Label (2945:5539): la card\n renderiza ese leading (tile 32\u00D724) y delega el resto al label en 'basic'. -->\n@if (type() === 'card-provider') {\n <div class=\"sui-content-card__card-box\">\n @if (brand(); as b) {\n <sui-brand-logo [company]=\"b\" size=\"sm\" />\n }\n </div>\n}\n\n<sui-content-label\n class=\"sui-content-card__label\"\n [type]=\"labelType()\"\n size=\"medium\"\n [label]=\"title()\"\n [sublabel]=\"sublabel()\"\n [description]=\"subtitle()\"\n [icon]=\"icon()\"\n [avatar]=\"avatar()\"\n [companyLogoSrc]=\"companyLogoSrc()\"\n [brand]=\"brand()\"\n [badge]=\"badgeCfg()\"\n badgePlacement=\"title\"\n [disabled]=\"disabled()\"\n/>\n\n@if (dismissible()) {\n <button\n type=\"button\"\n class=\"sui-content-card__dismiss\"\n [attr.aria-label]=\"dismissAriaLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"onDismiss($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"close-line\" [size]=\"20\" />\n </button>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:14px;box-sizing:border-box;width:100%;padding:16px;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:var(--sui-radius-12);box-shadow:var(--sui-shadow-x-small);font-family:var(--sui-font-sans, \"Inter\", system-ui, sans-serif);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-content-card__label{flex:1 1 0;min-width:0}.sui-content-card__card-box{box-sizing:border-box;flex-shrink:0;width:32px;height:24px;display:inline-flex;align-items:center;justify-content:center;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:var(--sui-radius-4)}.sui-content-card__dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;padding:0;width:20px;height:20px;background:transparent;border:0;border-radius:var(--sui-radius-4);color:var(--sui-icon-sub-600);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,color .15s ease,transform .12s ease}.sui-content-card__dismiss:hover{background:var(--sui-bg-weak-50);color:var(--sui-text-strong-950)}.sui-content-card__dismiss:active{transform:scale(.96)}.sui-content-card__dismiss:focus-visible{outline:2px solid var(--sui-primary-base);outline-offset:2px}.sui-content-card__dismiss:disabled{color:var(--sui-icon-disabled-300);cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]){pointer-events:none}:host([data-sui-disabled]) .sui-content-card__card-box{opacity:.5}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiBrandLogo, selector: "sui-brand-logo", inputs: ["company", "variant", "size", "href", "target", "rel", "disabled", "ariaLabel"] }, { kind: "component", type: SuiContentLabel, selector: "sui-content-label", inputs: ["type", "size", "label", "sublabel", "description", "icon", "avatar", "companyLogoSrc", "brand", "badge", "badgePlacement", "toggle", "toggleChecked", "disabled"], outputs: ["toggleCheckedChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
5236
5706
|
}
|
|
5237
5707
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiContentCard, decorators: [{
|
|
5238
5708
|
type: Component,
|
|
5239
|
-
args: [{ selector: 'sui-content-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SuiIcon,
|
|
5709
|
+
args: [{ selector: 'sui-content-card', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SuiIcon, SuiBrandLogo, SuiContentLabel], host: {
|
|
5240
5710
|
/* Strip native `title` attr — patrón canon Ontop (ver CLAUDE.md). El input
|
|
5241
5711
|
`title` sigue accesible como property; sólo se borra del DOM para evitar
|
|
5242
5712
|
el tooltip nativo gris del browser. */
|
|
@@ -5246,8 +5716,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
5246
5716
|
'[attr.role]': '"group"',
|
|
5247
5717
|
'[attr.aria-label]': 'title() || null',
|
|
5248
5718
|
'[attr.aria-disabled]': 'disabled() ? "true" : null',
|
|
5249
|
-
}, template: "
|
|
5250
|
-
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], companyLogoSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "companyLogoSrc", required: false }] }], brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissAriaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
|
|
5719
|
+
}, template: "<!-- card-provider no existe en el set del Content Label (2945:5539): la card\n renderiza ese leading (tile 32\u00D724) y delega el resto al label en 'basic'. -->\n@if (type() === 'card-provider') {\n <div class=\"sui-content-card__card-box\">\n @if (brand(); as b) {\n <sui-brand-logo [company]=\"b\" size=\"sm\" />\n }\n </div>\n}\n\n<sui-content-label\n class=\"sui-content-card__label\"\n [type]=\"labelType()\"\n size=\"medium\"\n [label]=\"title()\"\n [sublabel]=\"sublabel()\"\n [description]=\"subtitle()\"\n [icon]=\"icon()\"\n [avatar]=\"avatar()\"\n [companyLogoSrc]=\"companyLogoSrc()\"\n [brand]=\"brand()\"\n [badge]=\"badgeCfg()\"\n badgePlacement=\"title\"\n [disabled]=\"disabled()\"\n/>\n\n@if (dismissible()) {\n <button\n type=\"button\"\n class=\"sui-content-card__dismiss\"\n [attr.aria-label]=\"dismissAriaLabel()\"\n [disabled]=\"disabled()\"\n (click)=\"onDismiss($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"close-line\" [size]=\"20\" />\n </button>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:14px;box-sizing:border-box;width:100%;padding:16px;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:var(--sui-radius-12);box-shadow:var(--sui-shadow-x-small);font-family:var(--sui-font-sans, \"Inter\", system-ui, sans-serif);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-content-card__label{flex:1 1 0;min-width:0}.sui-content-card__card-box{box-sizing:border-box;flex-shrink:0;width:32px;height:24px;display:inline-flex;align-items:center;justify-content:center;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:var(--sui-radius-4)}.sui-content-card__dismiss{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;padding:0;width:20px;height:20px;background:transparent;border:0;border-radius:var(--sui-radius-4);color:var(--sui-icon-sub-600);cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,color .15s ease,transform .12s ease}.sui-content-card__dismiss:hover{background:var(--sui-bg-weak-50);color:var(--sui-text-strong-950)}.sui-content-card__dismiss:active{transform:scale(.96)}.sui-content-card__dismiss:focus-visible{outline:2px solid var(--sui-primary-base);outline-offset:2px}.sui-content-card__dismiss:disabled{color:var(--sui-icon-disabled-300);cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]){pointer-events:none}:host([data-sui-disabled]) .sui-content-card__card-box{opacity:.5}\n"] }]
|
|
5720
|
+
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], sublabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sublabel", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], companyLogoSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "companyLogoSrc", required: false }] }], brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], dismissAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissAriaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
|
|
5251
5721
|
|
|
5252
5722
|
/**
|
|
5253
5723
|
* SUI Content Divider — SUI Design System 2.0
|
|
@@ -6871,88 +7341,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
6871
7341
|
}, template: "", styles: [":host{display:block;height:1px;width:100%;background:var(--sui-stroke-soft-200, #ebebeb);flex-shrink:0}:host(.sui-divider--vertical){display:inline-block;width:1px;height:100%;min-height:16px}\n"] }]
|
|
6872
7342
|
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
|
|
6873
7343
|
|
|
6874
|
-
class SuiSwitch {
|
|
6875
|
-
size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
6876
|
-
checked = input(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
6877
|
-
checkedChange = output();
|
|
6878
|
-
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
6879
|
-
_disabledByForm = signal(false, ...(ngDevMode ? [{ debugName: "_disabledByForm" }] : /* istanbul ignore next */ []));
|
|
6880
|
-
isDisabled = computed(() => this.disabled() || this._disabledByForm(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
6881
|
-
/** CVA buffer — usado SOLO en form mode (formControlName/formControl).
|
|
6882
|
-
* Activado cuando `registerOnChange` se llama (Angular Forms lo hace). */
|
|
6883
|
-
_cvaValue = signal(false, ...(ngDevMode ? [{ debugName: "_cvaValue" }] : /* istanbul ignore next */ []));
|
|
6884
|
-
_useCvaValue = signal(false, ...(ngDevMode ? [{ debugName: "_useCvaValue" }] : /* istanbul ignore next */ []));
|
|
6885
|
-
/** Estado VISIBLE — input del parent en uso normal, _cvaValue en form mode. */
|
|
6886
|
-
effectiveChecked = computed(() => {
|
|
6887
|
-
if (this._useCvaValue())
|
|
6888
|
-
return this._cvaValue();
|
|
6889
|
-
return this.checked();
|
|
6890
|
-
}, ...(ngDevMode ? [{ debugName: "effectiveChecked" }] : /* istanbul ignore next */ []));
|
|
6891
|
-
_onChange = () => { };
|
|
6892
|
-
_onTouched = () => { };
|
|
6893
|
-
onToggle(e) {
|
|
6894
|
-
if (this.isDisabled())
|
|
6895
|
-
return;
|
|
6896
|
-
e.preventDefault();
|
|
6897
|
-
const next = !this.effectiveChecked();
|
|
6898
|
-
/* Patrón controlled: SOLO emitir intent. NO mutamos el input directamente
|
|
6899
|
-
(es input, no model). En form mode, actualizamos el buffer CVA porque
|
|
6900
|
-
los reactive forms no llaman writeValue después de un user change. */
|
|
6901
|
-
if (this._useCvaValue()) {
|
|
6902
|
-
this._cvaValue.set(next);
|
|
6903
|
-
}
|
|
6904
|
-
this.checkedChange.emit(next);
|
|
6905
|
-
this._onChange(next);
|
|
6906
|
-
this._onTouched();
|
|
6907
|
-
}
|
|
6908
|
-
writeValue(v) {
|
|
6909
|
-
this._cvaValue.set(!!v);
|
|
6910
|
-
this._useCvaValue.set(true);
|
|
6911
|
-
}
|
|
6912
|
-
registerOnChange(fn) {
|
|
6913
|
-
this._onChange = fn;
|
|
6914
|
-
this._useCvaValue.set(true);
|
|
6915
|
-
}
|
|
6916
|
-
registerOnTouched(fn) {
|
|
6917
|
-
this._onTouched = fn;
|
|
6918
|
-
}
|
|
6919
|
-
setDisabledState(isDisabled) {
|
|
6920
|
-
this._disabledByForm.set(isDisabled);
|
|
6921
|
-
}
|
|
6922
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6923
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiSwitch, isStandalone: true, selector: "sui-switch", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checkedChange: "checkedChange" }, host: { listeners: { "click": "onToggle($event)", "keydown.space": "onToggle($event)", "keydown.enter": "onToggle($event)", "touchstart": "$event.currentTarget", "touchend": "$any($event.currentTarget).blur()" }, properties: { "attr.data-sui-size": "size()", "attr.data-sui-checked": "effectiveChecked() ? \"\" : null", "attr.data-sui-disabled": "isDisabled() ? \"\" : null", "attr.role": "\"switch\"", "attr.aria-checked": "effectiveChecked() ? \"true\" : \"false\"", "attr.aria-disabled": "isDisabled() ? \"true\" : null", "attr.tabindex": "isDisabled() ? \"-1\" : \"0\"" } }, providers: [
|
|
6924
|
-
{
|
|
6925
|
-
provide: NG_VALUE_ACCESSOR,
|
|
6926
|
-
useExisting: forwardRef(() => SuiSwitch),
|
|
6927
|
-
multi: true,
|
|
6928
|
-
},
|
|
6929
|
-
], ngImport: i0, template: "<span class=\"sui-switch__track\"></span>\n<span class=\"sui-switch__thumb\">\n <span class=\"sui-switch__dot\" aria-hidden=\"true\"></span>\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:inline-block;position:relative;width:32px;height:20px;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.sui-switch__track{position:absolute;top:2px;left:2px;width:28px;height:16px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__thumb{position:absolute;top:4px;left:4px;width:12px;height:12px;border-radius:999px;background:var(--sui-static-white, #ffffff);box-shadow:var(--sui-shadow-switch-thumb);display:flex;align-items:center;justify-content:center;transition:left var(--sui-motion-duration-fast) var(--sui-motion-ease-out),top var(--sui-motion-duration-fast) var(--sui-motion-ease-out),width var(--sui-motion-duration-fast) var(--sui-motion-ease-out),height var(--sui-motion-duration-fast) var(--sui-motion-ease-out),box-shadow var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__dot{width:4px;height:4px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}:host([data-sui-checked]) .sui-switch__track{background:var(--sui-primary-base)}:host([data-sui-checked]) .sui-switch__thumb{left:16px}:host([data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-base)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__track{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__dot{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__track{background:var(--sui-primary-dark)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-dark)}:host(:active:not([data-sui-disabled])) .sui-switch__thumb{width:10px;height:10px;top:5px}:host(:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host(:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]){cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]) .sui-switch__track{background:var(--sui-bg-white-0);box-shadow:inset 0 0 0 1px var(--sui-stroke-soft-200)}:host([data-sui-disabled]) .sui-switch__thumb{width:10px;height:10px;top:5px;background:var(--sui-bg-soft-200);box-shadow:none}:host([data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]) .sui-switch__dot{display:none}:host([data-sui-size=large]){width:40px;height:24px}:host([data-sui-size=large]) .sui-switch__track{width:36px;height:20px}:host([data-sui-size=large]) .sui-switch__thumb{width:16px;height:16px;top:4px;left:4px}:host([data-sui-size=large][data-sui-checked]) .sui-switch__thumb{left:20px}:host([data-sui-size=large]:active:not([data-sui-disabled])) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=large][data-sui-disabled]) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=xlarge]){width:48px;height:28px}:host([data-sui-size=xlarge]) .sui-switch__track{width:44px;height:24px}:host([data-sui-size=xlarge]) .sui-switch__thumb{width:20px;height:20px;top:4px;left:4px}:host([data-sui-size=xlarge][data-sui-checked]) .sui-switch__thumb{left:24px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:25px}:host([data-sui-size=xlarge][data-sui-disabled]) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:25px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
6930
|
-
}
|
|
6931
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSwitch, decorators: [{
|
|
6932
|
-
type: Component,
|
|
6933
|
-
args: [{ selector: 'sui-switch', changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
6934
|
-
{
|
|
6935
|
-
provide: NG_VALUE_ACCESSOR,
|
|
6936
|
-
useExisting: forwardRef(() => SuiSwitch),
|
|
6937
|
-
multi: true,
|
|
6938
|
-
},
|
|
6939
|
-
], host: {
|
|
6940
|
-
'[attr.data-sui-size]': 'size()',
|
|
6941
|
-
'[attr.data-sui-checked]': 'effectiveChecked() ? "" : null',
|
|
6942
|
-
'[attr.data-sui-disabled]': 'isDisabled() ? "" : null',
|
|
6943
|
-
'[attr.role]': '"switch"',
|
|
6944
|
-
'[attr.aria-checked]': 'effectiveChecked() ? "true" : "false"',
|
|
6945
|
-
'[attr.aria-disabled]': 'isDisabled() ? "true" : null',
|
|
6946
|
-
'[attr.tabindex]': 'isDisabled() ? "-1" : "0"',
|
|
6947
|
-
'(click)': 'onToggle($event)',
|
|
6948
|
-
'(keydown.space)': 'onToggle($event)',
|
|
6949
|
-
'(keydown.enter)': 'onToggle($event)',
|
|
6950
|
-
/* iOS WKWebView fix — ver CLAUDE.md "iOS :active stuck en custom buttons". */
|
|
6951
|
-
'(touchstart)': '$event.currentTarget',
|
|
6952
|
-
'(touchend)': '$any($event.currentTarget).blur()',
|
|
6953
|
-
}, template: "<span class=\"sui-switch__track\"></span>\n<span class=\"sui-switch__thumb\">\n <span class=\"sui-switch__dot\" aria-hidden=\"true\"></span>\n</span>\n", styles: ["@charset \"UTF-8\";:host{display:inline-block;position:relative;width:32px;height:20px;cursor:pointer;outline:none;box-sizing:border-box;-webkit-tap-highlight-color:transparent}.sui-switch__track{position:absolute;top:2px;left:2px;width:28px;height:16px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__thumb{position:absolute;top:4px;left:4px;width:12px;height:12px;border-radius:999px;background:var(--sui-static-white, #ffffff);box-shadow:var(--sui-shadow-switch-thumb);display:flex;align-items:center;justify-content:center;transition:left var(--sui-motion-duration-fast) var(--sui-motion-ease-out),top var(--sui-motion-duration-fast) var(--sui-motion-ease-out),width var(--sui-motion-duration-fast) var(--sui-motion-ease-out),height var(--sui-motion-duration-fast) var(--sui-motion-ease-out),box-shadow var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}.sui-switch__dot{width:4px;height:4px;border-radius:999px;background:var(--sui-bg-soft-200);transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out)}:host([data-sui-checked]) .sui-switch__track{background:var(--sui-primary-base)}:host([data-sui-checked]) .sui-switch__thumb{left:16px}:host([data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-base)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__track{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__dot{background:var(--sui-bg-sub-300)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__track{background:var(--sui-primary-dark)}:host(:hover:not([data-sui-disabled])[data-sui-checked]) .sui-switch__dot{background:var(--sui-primary-dark)}:host(:active:not([data-sui-disabled])) .sui-switch__thumb{width:10px;height:10px;top:5px}:host(:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host(:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]){cursor:not-allowed;pointer-events:none}:host([data-sui-disabled]) .sui-switch__track{background:var(--sui-bg-white-0);box-shadow:inset 0 0 0 1px var(--sui-stroke-soft-200)}:host([data-sui-disabled]) .sui-switch__thumb{width:10px;height:10px;top:5px;background:var(--sui-bg-soft-200);box-shadow:none}:host([data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:17px}:host([data-sui-disabled]) .sui-switch__dot{display:none}:host([data-sui-size=large]){width:40px;height:24px}:host([data-sui-size=large]) .sui-switch__track{width:36px;height:20px}:host([data-sui-size=large]) .sui-switch__thumb{width:16px;height:16px;top:4px;left:4px}:host([data-sui-size=large][data-sui-checked]) .sui-switch__thumb{left:20px}:host([data-sui-size=large]:active:not([data-sui-disabled])) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=large][data-sui-disabled]) .sui-switch__thumb{width:14px;height:14px;top:5px}:host([data-sui-size=large][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=large][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:21px}:host([data-sui-size=xlarge]){width:48px;height:28px}:host([data-sui-size=xlarge]) .sui-switch__track{width:44px;height:24px}:host([data-sui-size=xlarge]) .sui-switch__thumb{width:20px;height:20px;top:4px;left:4px}:host([data-sui-size=xlarge][data-sui-checked]) .sui-switch__thumb{left:24px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled]):not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge]:active:not([data-sui-disabled])[data-sui-checked]) .sui-switch__thumb{left:25px}:host([data-sui-size=xlarge][data-sui-disabled]) .sui-switch__thumb{width:18px;height:18px;top:5px}:host([data-sui-size=xlarge][data-sui-disabled]:not([data-sui-checked])) .sui-switch__thumb{left:5px}:host([data-sui-size=xlarge][data-sui-disabled][data-sui-checked]) .sui-switch__thumb{left:25px}\n"] }]
|
|
6954
|
-
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }], checkedChange: [{ type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
6955
|
-
|
|
6956
7344
|
/**
|
|
6957
7345
|
* SUI Drawer Footer — SUI Design System 2.0
|
|
6958
7346
|
*
|
|
@@ -10126,105 +10514,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
10126
10514
|
}, template: "<!-- Brand logo (circle 40 / 48 seg\u00FAn appearance) -->\n<div class=\"sui-integration-switch__brand\" aria-hidden=\"true\">\n <ng-content select=\"[sui-integration-brand]\">\n @if (brandIconSrc(); as src) {\n <img [src]=\"src\" alt=\"\" class=\"sui-integration-switch__brand-img\" />\n } @else if (brandIcon(); as icon) {\n <sui-icon [name]=\"icon\" [size]=\"appearance() === 'list' ? 32 : 24\" />\n }\n </ng-content>\n</div>\n\n<!-- Title + description block -->\n<div class=\"sui-integration-switch__text\">\n <div class=\"sui-integration-switch__title-row\">\n <span class=\"sui-integration-switch__title\">{{ title() }}</span>\n @if (badgeCfg(); as bcfg) {\n <sui-badge\n class=\"sui-integration-switch__badge\"\n [color]=\"bcfg.color ?? 'orange'\"\n [variant]=\"bcfg.variant ?? 'light'\"\n [size]=\"bcfg.size ?? 'small'\"\n >{{ bcfg.label }}</sui-badge>\n }\n </div>\n @if (description(); as desc) {\n <p class=\"sui-integration-switch__description\">{{ desc }}</p>\n }\n</div>\n\n<!-- Manage button (trailing en horizontal, full-width en vertical) -->\n@if (manageCfg(); as mcfg) {\n <button\n type=\"button\"\n class=\"sui-integration-switch__manage\"\n [attr.aria-label]=\"mcfg.label\"\n [disabled]=\"isDisabled()\"\n (click)=\"onManageClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon [name]=\"mcfg.icon\" [size]=\"20\" />\n <span class=\"sui-integration-switch__manage-label\">{{ mcfg.label }}</span>\n </button>\n}\n\n<!-- Switch (inline en horizontal \u00B7 absolute top-right en vertical) -->\n@if (showToggle()) {\n <sui-switch\n class=\"sui-integration-switch__toggle\"\n [checked]=\"effectiveActive()\"\n [disabled]=\"isDisabled()\"\n (checkedChange)=\"onSwitchChange($event)\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{position:relative;display:flex;box-sizing:border-box;width:100%;font-family:var(--sui-font-sans, \"Inter\", system-ui, sans-serif);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}:host([data-sui-type=horizontal]){flex-direction:row;align-items:center;gap:14px}:host([data-sui-type=vertical]){flex-direction:column;align-items:flex-start;gap:14px}:host([data-sui-appearance=card]){padding:16px;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:12px;box-shadow:var(--sui-shadow-x-small)}:host([data-sui-appearance=list]){padding:0;background:transparent;border:0}.sui-integration-switch__brand{box-sizing:border-box;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;padding:8px;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:999px;box-shadow:var(--sui-shadow-x-small);overflow:hidden}:host([data-sui-appearance=card]) .sui-integration-switch__brand{width:40px;height:40px}:host([data-sui-appearance=list]) .sui-integration-switch__brand{width:48px;height:48px}.sui-integration-switch__brand-img{width:100%;height:100%;object-fit:contain;display:block}.sui-integration-switch__text{flex:1 0 0;min-width:0;display:flex;flex-direction:column;align-items:flex-start;gap:4px}.sui-integration-switch__title-row{display:flex;align-items:center;gap:4px;flex-wrap:wrap}.sui-integration-switch__title{color:var(--sui-text-strong-950);font-weight:500;word-break:break-word}:host([data-sui-appearance=card]) .sui-integration-switch__title{font-size:14px;line-height:20px;letter-spacing:-.006em}:host([data-sui-appearance=list]) .sui-integration-switch__title{font-size:16px;line-height:24px;letter-spacing:-.011em}.sui-integration-switch__description{margin:0;color:var(--sui-text-sub-600);font-weight:400;word-break:break-word}:host([data-sui-appearance=card]) .sui-integration-switch__description{font-size:12px;line-height:16px}:host([data-sui-appearance=list]) .sui-integration-switch__description{font-size:14px;line-height:20px;letter-spacing:-.006em}.sui-integration-switch__badge{flex-shrink:0}.sui-integration-switch__manage{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:8px;background:var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);border-radius:8px;box-shadow:var(--sui-shadow-x-small);color:var(--sui-text-sub-600);font-family:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent;transition:background-color .15s ease,transform .12s ease}.sui-integration-switch__manage:hover:not(:disabled){background:var(--sui-bg-weak-50)}.sui-integration-switch__manage:active:not(:disabled){transform:scale(.97)}.sui-integration-switch__manage:focus-visible{outline:2px solid var(--sui-primary-base);outline-offset:2px}.sui-integration-switch__manage:disabled{opacity:.4;cursor:not-allowed}.sui-integration-switch__manage-label{padding:0 4px;font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em}:host([data-sui-type=vertical]) .sui-integration-switch__manage{width:100%}.sui-integration-switch__toggle{flex-shrink:0}:host([data-sui-type=vertical]) .sui-integration-switch__toggle{position:absolute;top:19px;right:19px}:host([data-sui-type=vertical][data-sui-appearance=list]) .sui-integration-switch__toggle{top:12px;right:12px}:host([data-sui-disabled]){opacity:.5;pointer-events:none}\n"] }]
|
|
10127
10515
|
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], brandIconSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIconSrc", required: false }] }], brandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "brandIcon", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }], manage: [{ type: i0.Input, args: [{ isSignal: true, alias: "manage", required: false }] }], showToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToggle", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], activeChange: [{ type: i0.Output, args: ["activeChange"] }], manageClick: [{ type: i0.Output, args: ["manageClick"] }] } });
|
|
10128
10516
|
|
|
10129
|
-
/** Set de los 9 colores SUI 2.0 para iterar desde el consumer (previews, demos). */
|
|
10130
|
-
const SUI_KEY_ICON_COLORS = [
|
|
10131
|
-
'gray', 'blue', 'orange', 'red', 'green', 'yellow', 'purple', 'pink', 'teal',
|
|
10132
|
-
];
|
|
10133
|
-
/** Set de los 5 tamaños canon, para iterar desde el consumer. */
|
|
10134
|
-
const SUI_KEY_ICON_SIZES = [32, 40, 48, 56, 64];
|
|
10135
|
-
/**
|
|
10136
|
-
* SUI Key Icon — SUI Design System 2.0
|
|
10137
|
-
*
|
|
10138
|
-
* Figma file: 8p1k72aKKvzJV4XcvPS4VO — grupo "Key Components" → "KeyIcons [1.1]".
|
|
10139
|
-
* Componente NUEVO (no existía como SUI). Contenedor circular de icono usado como
|
|
10140
|
-
* leading element en list rows, content-labels, empty-states, notificaciones, etc.
|
|
10141
|
-
*
|
|
10142
|
-
* 90 combinaciones = Style(2: stroke|lighter) × Color(9) × Size(5: 32/40/48/56/64).
|
|
10143
|
-
*
|
|
10144
|
-
* ── Style ──────────────────────────────────────────────────────────────────
|
|
10145
|
-
* stroke → bg `--sui-bg-white-0` + border 1px `--sui-stroke-soft-200`
|
|
10146
|
-
* + drop-shadow `--sui-shadow-x-small` + radius-full.
|
|
10147
|
-
* El icono interior toma el `*-base` del color.
|
|
10148
|
-
* lighter → bg del `*-lighter` del color (sin borde, sin sombra) + radius-full.
|
|
10149
|
-
* El icono interior toma el `*-base` del color.
|
|
10150
|
-
*
|
|
10151
|
-
* ── Color → token map (Figma exacto; ver SUI-FIGMA-CHECKLIST.md) ──────────────
|
|
10152
|
-
* gray → faded base #7b7b7b / lighter #f5f5f5
|
|
10153
|
-
* blue → information base #335cff / lighter #ebf1ff
|
|
10154
|
-
* orange → warning base #fa7319 / lighter #fff3eb
|
|
10155
|
-
* red → error base #fb3748 / lighter #ffebec
|
|
10156
|
-
* green → success base #1fc16b / lighter #e3f7ec
|
|
10157
|
-
* yellow → away base #f6b51e / lighter #fffaeb
|
|
10158
|
-
* purple → feature base #7d52f4 / lighter #efebff
|
|
10159
|
-
* pink → highlighted base #fb4ba3 / lighter #ffebf4
|
|
10160
|
-
* teal → verified base #47c2ff / lighter #ebf8ff
|
|
10161
|
-
*
|
|
10162
|
-
* ── Icono ────────────────────────────────────────────────────────────────────
|
|
10163
|
-
* Render SIEMPRE vía <sui-icon name="..."> (regla del proyecto — nunca SVG
|
|
10164
|
-
* inline). Tamaño = size / 2 (Figma: el icono ocupa el 50% del contenedor).
|
|
10165
|
-
* El <sui-icon> recibe su tamaño DIRECTO vía [size]="iconSize()" (su @Input),
|
|
10166
|
-
* NO vía custom prop CSS — sui-icon lee solo su @Input `size`, no una variable.
|
|
10167
|
-
* El color del icono = `*-base` del color, vía la custom prop `--sui-key-icon-fg`.
|
|
10168
|
-
*
|
|
10169
|
-
* Display-only: NO es un control de formulario (sin CVA) y NO es clickeable
|
|
10170
|
-
* (sin touchstart/touchend ni role=button). Si en el futuro se vuelve interactivo
|
|
10171
|
-
* habría que envolverlo en un <button> con el fix iOS :active (ver CLAUDE.md).
|
|
10172
|
-
*
|
|
10173
|
-
* ── Dark mode ─────────────────────────────────────────────────────────────────
|
|
10174
|
-
* El style `stroke` usa bg `--sui-bg-white-0` (igual que los otros 104 usos del
|
|
10175
|
-
* token en SUI). El proyecto NO tiene color-scheme dark hoy (no hay bloque
|
|
10176
|
-
* prefers-color-scheme / .dark / [data-theme] en sui-tokens.scss). Si se agrega,
|
|
10177
|
-
* `--sui-bg-white-0` se redefine UNA vez a nivel token y todo SUI —incluido este
|
|
10178
|
-
* stroke bg— adapta. NO hardcodear un bg distinto acá: divergiría de Figma (la
|
|
10179
|
-
* spec del KeyIcon stroke ES bg-white-0) y del resto del DS.
|
|
10180
|
-
*
|
|
10181
|
-
* PENDING VERIFY (Figma — NO verificado pixel-perfect):
|
|
10182
|
-
* - El component set "KeyIcons" NO está en el file 8p1k72aKKvzJV4XcvPS4VO.
|
|
10183
|
-
* Verificado 2026-05-29 vía MCP: get_metadata(file) lista solo 2 páginas
|
|
10184
|
-
* (`0:1 Cover`, `2771:1469 Brand`); la página Brand son brand-logos / crypto /
|
|
10185
|
-
* app-store badges, sin ningún nodo KeyIcon. El node 266:2814 (del prompt
|
|
10186
|
-
* original) resuelve a "Label [1.1]", NO a KeyIcons. KeyIcons vive en OTRO file
|
|
10187
|
-
* de SUI no accesible con este fileKey.
|
|
10188
|
-
* - Los valores actuales (color/lighter/base, size, icon=size/2, stroke=bg-white-0
|
|
10189
|
-
* + border stroke-soft-200 + shadow-x-small) provienen de la auditoría previa
|
|
10190
|
-
* (.claude/sui-audit/reaudit-reports.json + SUI-FIGMA-CHECKLIST.md líneas 84/105),
|
|
10191
|
-
* NO de un render en vivo de KeyIcons. Todos los tokens matchean 1:1 con
|
|
10192
|
-
* sui-tokens.scss, pero NO se hizo comparación visual contra el nodo real.
|
|
10193
|
-
* - Pendiente: identificar el fileKey/nodeId real del set KeyIcons y hacer un
|
|
10194
|
-
* get_screenshot para validar radius (¿círculo full vs radio fijo grande?),
|
|
10195
|
-
* border width, y el size del icono interno antes de marcar Figma-verified.
|
|
10196
|
-
*/
|
|
10197
|
-
class SuiKeyIcon {
|
|
10198
|
-
/** RemixIcon name (sin prefijo), e.g. 'mail-line', 'home-5-fill'. Se pasa a <sui-icon>. */
|
|
10199
|
-
name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
10200
|
-
/**
|
|
10201
|
-
* Estilo del contenedor. `style` choca con la property `style` del HTMLElement,
|
|
10202
|
-
* así que el input se llama `styleVariant` (host binding `data-sui-style`).
|
|
10203
|
-
*/
|
|
10204
|
-
styleVariant = input('stroke', ...(ngDevMode ? [{ debugName: "styleVariant" }] : /* istanbul ignore next */ []));
|
|
10205
|
-
/** Color del set canon (9). */
|
|
10206
|
-
color = input('gray', ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
10207
|
-
/** Tamaño del contenedor en px. Uno de 32/40/48/56/64. */
|
|
10208
|
-
size = input(40, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
10209
|
-
/** Tamaño del icono interno = 50% del contenedor (Figma). */
|
|
10210
|
-
iconSize = computed(() => this.size() / 2, ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
|
|
10211
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiKeyIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10212
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiKeyIcon, isStandalone: true, selector: "sui-key-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null }, styleVariant: { classPropertyName: "styleVariant", publicName: "styleVariant", 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 } }, host: { properties: { "attr.data-sui-style": "styleVariant()", "attr.data-sui-color": "color()", "style.--sui-key-icon-size.px": "size()", "attr.title": "null" } }, ngImport: i0, template: "<sui-icon\n class=\"sui-key-icon__icon\"\n [name]=\"name()\"\n [size]=\"iconSize()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;box-sizing:border-box;width:var(--sui-key-icon-size, 40px);height:var(--sui-key-icon-size, 40px);border-radius:var(--sui-radius-full);vertical-align:middle;--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter);background:var(--sui-key-icon-bg)}:host([data-sui-color=gray]){--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter)}:host([data-sui-color=blue]){--sui-key-icon-fg: var(--sui-state-information-base);--sui-key-icon-lighter: var(--sui-state-information-lighter)}:host([data-sui-color=orange]){--sui-key-icon-fg: var(--sui-state-warning-base);--sui-key-icon-lighter: var(--sui-state-warning-lighter)}:host([data-sui-color=red]){--sui-key-icon-fg: var(--sui-state-error-base);--sui-key-icon-lighter: var(--sui-state-error-lighter)}:host([data-sui-color=green]){--sui-key-icon-fg: var(--sui-state-success-base);--sui-key-icon-lighter: var(--sui-state-success-lighter)}:host([data-sui-color=yellow]){--sui-key-icon-fg: var(--sui-state-away-base);--sui-key-icon-lighter: var(--sui-state-away-lighter)}:host([data-sui-color=purple]){--sui-key-icon-fg: var(--sui-state-feature-base);--sui-key-icon-lighter: var(--sui-state-feature-lighter)}:host([data-sui-color=pink]){--sui-key-icon-fg: var(--sui-state-highlighted-base);--sui-key-icon-lighter: var(--sui-state-highlighted-lighter)}:host([data-sui-color=teal]){--sui-key-icon-fg: var(--sui-state-verified-base);--sui-key-icon-lighter: var(--sui-state-verified-lighter)}:host([data-sui-style=stroke]){--sui-key-icon-bg: var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);box-shadow:var(--sui-shadow-x-small)}:host([data-sui-style=lighter]){--sui-key-icon-bg: var(--sui-key-icon-lighter);border:none;box-shadow:none}.sui-key-icon__icon{display:inline-flex;color:var(--sui-key-icon-fg);line-height:0}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
10213
|
-
}
|
|
10214
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiKeyIcon, decorators: [{
|
|
10215
|
-
type: Component,
|
|
10216
|
-
args: [{ selector: 'sui-key-icon', standalone: true, imports: [SuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
10217
|
-
/* data-sui-style + data-sui-color son los DRIVERS del styling per-variante en
|
|
10218
|
-
el SCSS. `size` NO se expone como data-attr: el SCSS dimensiona vía la custom
|
|
10219
|
-
prop --sui-key-icon-size, y el icono interno vía [size]="iconSize()". */
|
|
10220
|
-
'[attr.data-sui-style]': 'styleVariant()',
|
|
10221
|
-
'[attr.data-sui-color]': 'color()',
|
|
10222
|
-
'[style.--sui-key-icon-size.px]': 'size()',
|
|
10223
|
-
/* Strip native `title` attr — patrón canon Ontop (ver CLAUDE.md). */
|
|
10224
|
-
'[attr.title]': 'null',
|
|
10225
|
-
}, template: "<sui-icon\n class=\"sui-key-icon__icon\"\n [name]=\"name()\"\n [size]=\"iconSize()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;box-sizing:border-box;width:var(--sui-key-icon-size, 40px);height:var(--sui-key-icon-size, 40px);border-radius:var(--sui-radius-full);vertical-align:middle;--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter);background:var(--sui-key-icon-bg)}:host([data-sui-color=gray]){--sui-key-icon-fg: var(--sui-state-faded-base);--sui-key-icon-lighter: var(--sui-state-faded-lighter)}:host([data-sui-color=blue]){--sui-key-icon-fg: var(--sui-state-information-base);--sui-key-icon-lighter: var(--sui-state-information-lighter)}:host([data-sui-color=orange]){--sui-key-icon-fg: var(--sui-state-warning-base);--sui-key-icon-lighter: var(--sui-state-warning-lighter)}:host([data-sui-color=red]){--sui-key-icon-fg: var(--sui-state-error-base);--sui-key-icon-lighter: var(--sui-state-error-lighter)}:host([data-sui-color=green]){--sui-key-icon-fg: var(--sui-state-success-base);--sui-key-icon-lighter: var(--sui-state-success-lighter)}:host([data-sui-color=yellow]){--sui-key-icon-fg: var(--sui-state-away-base);--sui-key-icon-lighter: var(--sui-state-away-lighter)}:host([data-sui-color=purple]){--sui-key-icon-fg: var(--sui-state-feature-base);--sui-key-icon-lighter: var(--sui-state-feature-lighter)}:host([data-sui-color=pink]){--sui-key-icon-fg: var(--sui-state-highlighted-base);--sui-key-icon-lighter: var(--sui-state-highlighted-lighter)}:host([data-sui-color=teal]){--sui-key-icon-fg: var(--sui-state-verified-base);--sui-key-icon-lighter: var(--sui-state-verified-lighter)}:host([data-sui-style=stroke]){--sui-key-icon-bg: var(--sui-bg-white-0);border:1px solid var(--sui-stroke-soft-200);box-shadow:var(--sui-shadow-x-small)}:host([data-sui-style=lighter]){--sui-key-icon-bg: var(--sui-key-icon-lighter);border:none;box-shadow:none}.sui-key-icon__icon{display:inline-flex;color:var(--sui-key-icon-fg);line-height:0}\n"] }]
|
|
10226
|
-
}], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }], styleVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleVariant", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
10227
|
-
|
|
10228
10517
|
/**
|
|
10229
10518
|
* SUI Modal Sheet — bottom sheet con breakpoints (estilo Apple Maps / Ionic ion-modal sheet).
|
|
10230
10519
|
*
|
|
@@ -12054,6 +12343,262 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
12054
12343
|
}, template: "<!-- \u2550\u2550 SUI Pagination \u2014 SUI 2.0 (Figma 513:3681 / 513:3892) \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<div class=\"sui-pagination\">\n\n <!-- \u2500\u2500 Info text \u2500\u2500 -->\n @if (showInfo() && total() > 0) {\n <p class=\"sui-pagination__info\">\n @if (infoFormat() === 'pages') {\n Page <strong>{{ currentPage() }}</strong> of <strong>{{ totalPages() }}</strong>\n } @else {\n Mostrando <strong>{{ rangeStart() }}-{{ rangeEnd() }}</strong> de <strong>{{ total() }}</strong>\n }\n </p>\n }\n\n <!-- \u2500\u2500 Page buttons \u2500\u2500 -->\n <nav class=\"sui-pagination__nav\" aria-label=\"Paginaci\u00F3n\">\n\n <!-- First page (firstLast) -->\n @if (firstLast()) {\n <button\n type=\"button\"\n class=\"sui-pagination__btn sui-pagination__btn--nav\"\n [class.sui-pagination__btn--disabled]=\"!hasPrev\"\n [disabled]=\"!hasPrev\"\n (click)=\"first()\"\n (touchstart)=\"$any($event.currentTarget)\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n aria-label=\"Primera p\u00E1gina\"\n >\n <i class=\"ri-arrow-left-double-line\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Prev page (nextPrevious) -->\n @if (nextPrevious()) {\n <button\n type=\"button\"\n class=\"sui-pagination__btn sui-pagination__btn--nav\"\n [class.sui-pagination__btn--disabled]=\"!hasPrev\"\n [disabled]=\"!hasPrev\"\n (click)=\"prev()\"\n (touchstart)=\"$any($event.currentTarget)\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n aria-label=\"P\u00E1gina anterior\"\n >\n <i class=\"ri-arrow-left-s-line\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Page numbers with ellipsis -->\n @for (page of displayPages(); track $index) {\n @if (page === null) {\n <!-- Ellipsis: celda id\u00E9ntica a los n\u00FAmeros (bg/white-0 + border + padding) -->\n <span class=\"sui-pagination__btn sui-pagination__btn--ellipsis\" aria-hidden=\"true\">\u2026</span>\n } @else {\n <button\n type=\"button\"\n class=\"sui-pagination__btn sui-pagination__btn--page\"\n [class.sui-pagination__btn--active]=\"page === currentPage()\"\n (click)=\"goTo(page)\"\n (keydown)=\"onKeydown($event, page)\"\n (touchstart)=\"$any($event.currentTarget)\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n [attr.aria-current]=\"page === currentPage() ? 'page' : null\"\n [attr.aria-label]=\"'P\u00E1gina ' + page\"\n >\n {{ page }}\n </button>\n }\n }\n\n <!-- Next page (nextPrevious) -->\n @if (nextPrevious()) {\n <button\n type=\"button\"\n class=\"sui-pagination__btn sui-pagination__btn--nav\"\n [class.sui-pagination__btn--disabled]=\"!hasNext\"\n [disabled]=\"!hasNext\"\n (click)=\"next()\"\n (touchstart)=\"$any($event.currentTarget)\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n aria-label=\"P\u00E1gina siguiente\"\n >\n <i class=\"ri-arrow-right-s-line\" aria-hidden=\"true\"></i>\n </button>\n }\n\n <!-- Last page (firstLast) -->\n @if (firstLast()) {\n <button\n type=\"button\"\n class=\"sui-pagination__btn sui-pagination__btn--nav\"\n [class.sui-pagination__btn--disabled]=\"!hasNext\"\n [disabled]=\"!hasNext\"\n (click)=\"last()\"\n (touchstart)=\"$any($event.currentTarget)\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n aria-label=\"\u00DAltima p\u00E1gina\"\n >\n <i class=\"ri-arrow-right-double-line\" aria-hidden=\"true\"></i>\n </button>\n }\n\n </nav>\n\n <!-- \u2500\u2500 Advanced panel: page-size compact-select \u2500\u2500 -->\n @if (pageSizeItems().length > 0) {\n <div class=\"sui-pagination__advanced\">\n <sui-compact-select\n size=\"xsmall\"\n [items]=\"pageSizeItems()\"\n [selected]=\"selectedPageSizeItem()\"\n (selectedChange)=\"onPageSizeSelected($event)\"\n />\n </div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:host{display:block}.sui-pagination{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;font-family:var(--sui-font-sans);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-pagination__info{margin:0;font-size:var(--sui-type-paragraph-sm-size);font-weight:var(--sui-type-paragraph-sm-weight);line-height:var(--sui-type-paragraph-sm-line);letter-spacing:var(--sui-type-paragraph-sm-spacing);color:var(--sui-text-sub-600)}.sui-pagination__info strong{font-weight:500;color:var(--sui-text-strong-950)}.sui-pagination__nav{display:flex;align-items:center;gap:8px}.sui-pagination__advanced{display:flex;align-items:center}.sui-pagination__btn{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;border:1px solid transparent;background:transparent;cursor:pointer;flex-shrink:0;-webkit-user-select:none;user-select:none;outline:none;transition:background-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out),border-color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out),color var(--sui-motion-duration-x-fast) var(--sui-motion-ease-out);font-family:var(--sui-font-sans);font-weight:var(--sui-type-label-sm-weight);letter-spacing:var(--sui-type-label-sm-spacing);line-height:1;color:var(--sui-text-sub-600)}.sui-pagination__btn:focus-visible{box-shadow:0 0 0 2px var(--sui-bg-white-0),0 0 0 4px var(--sui-primary-alpha-10)}:host(:not([data-sui-type=group])) .sui-pagination__btn--page:not(.sui-pagination__btn--active),:host(:not([data-sui-type=group])) .sui-pagination__btn--ellipsis{border-color:var(--sui-stroke-soft-200)}:host([data-sui-size=medium]) .sui-pagination__btn{height:32px;min-width:32px;border-radius:var(--sui-radius-8);padding:6px;font-size:var(--sui-type-label-sm-size)}:host([data-sui-size=small]) .sui-pagination__btn{height:28px;min-width:28px;border-radius:var(--sui-radius-8);padding:4px;font-size:var(--sui-type-label-xs-size)}:host([data-sui-type=full-radius]) .sui-pagination__btn--page,:host([data-sui-type=full-radius]) .sui-pagination__btn--ellipsis{border-radius:var(--sui-radius-full)}.sui-pagination__btn--page:hover:not(:disabled){background:var(--sui-bg-weak-50)}.sui-pagination__btn--page.sui-pagination__btn--active{background:var(--sui-bg-weak-50);color:var(--sui-text-sub-600);cursor:default}.sui-pagination__btn--nav i{font-size:20px;line-height:1}.sui-pagination__btn--nav:hover:not(:disabled){background:var(--sui-bg-weak-50)}:host(:not([data-sui-type=group])) .sui-pagination__btn--page:not(.sui-pagination__btn--active):hover:not(:disabled){border-color:transparent}.sui-pagination__btn--ellipsis{background:var(--sui-bg-white-0);color:var(--sui-text-sub-600);cursor:default;pointer-events:none}.sui-pagination__btn--disabled,.sui-pagination__btn:disabled{color:var(--sui-text-disabled-300);background:transparent;cursor:not-allowed;pointer-events:none}:host([data-sui-type=group]) .sui-pagination__nav{gap:0;overflow:clip;border-radius:var(--sui-radius-8);isolation:isolate}:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn{border-color:var(--sui-stroke-soft-200);border-radius:0}:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn:not(:first-child){margin-left:-1px}:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn:hover:not(:disabled),:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn.sui-pagination__btn--active,:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn:focus-visible{position:relative;z-index:1}:host([data-sui-type=group]) .sui-pagination__nav .sui-pagination__btn--page{padding-inline:14px}\n"] }]
|
|
12055
12344
|
}], propDecorators: { total: [{ type: i0.Input, args: [{ isSignal: true, alias: "total", required: true }] }], pageSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSize", required: false }] }, { type: i0.Output, args: ["pageSizeChange"] }], siblingCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "siblingCount", required: false }] }], showInfo: [{ type: i0.Input, args: [{ isSignal: true, alias: "showInfo", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], firstLast: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstLast", required: false }] }], nextPrevious: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextPrevious", required: false }] }], infoFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "infoFormat", required: false }] }], pageSizeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageSizeOptions", required: false }] }], currentPage: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentPage", required: false }] }, { type: i0.Output, args: ["currentPageChange"] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], pageSizeChange: [{ type: i0.Output, args: ["pageSizeChange"] }] } });
|
|
12056
12345
|
|
|
12346
|
+
/** Condiciones default — las 3 del set de Figma, en español (tuteo). */
|
|
12347
|
+
const SUI_PASSWORD_STRENGTH_DEFAULT_CONDITIONS = [
|
|
12348
|
+
{ label: 'Al menos 1 mayúscula', test: (v) => /\p{Lu}/u.test(v) },
|
|
12349
|
+
{ label: 'Al menos 1 número', test: (v) => /\d/.test(v) },
|
|
12350
|
+
{ label: 'Al menos 8 caracteres', test: (v) => v.length >= 8 },
|
|
12351
|
+
];
|
|
12352
|
+
/** Labels por nivel para el `aria-valuetext` (configurables vía `levelLabels`). */
|
|
12353
|
+
const SUI_PASSWORD_STRENGTH_DEFAULT_LEVEL_LABELS = {
|
|
12354
|
+
empty: 'Sin contraseña',
|
|
12355
|
+
weak: 'Contraseña débil',
|
|
12356
|
+
moderate: 'Contraseña moderada',
|
|
12357
|
+
strong: 'Contraseña fuerte',
|
|
12358
|
+
};
|
|
12359
|
+
/**
|
|
12360
|
+
* sui-password-strength — SUI Design System 2.0 · Password Strength
|
|
12361
|
+
*
|
|
12362
|
+
* Figma: 8p1k72aKKvzJV4XcvPS4VO — frame "Password Strength [1.1]" node 327:8202.
|
|
12363
|
+
* VERIFIED via MCP (`get_metadata` + `get_design_context` + `get_variable_defs`
|
|
12364
|
+
* + `get_screenshot`, 2026-07-23).
|
|
12365
|
+
*
|
|
12366
|
+
* Indicador de fuerza de contraseña: barra segmentada de 3 niveles + caption +
|
|
12367
|
+
* checklist de condiciones. 4 variants del set (eje Strength):
|
|
12368
|
+
*
|
|
12369
|
+
* - ⚪️ Empty (327:8201): 0 segmentos llenos · todas las condiciones con
|
|
12370
|
+
* check gris (icon/soft-400) — estado neutro, aún sin tipear.
|
|
12371
|
+
* - 🔴 Weak (327:8239): segmento 1 lleno (error/base) · cumplidas con check
|
|
12372
|
+
* verde, NO cumplidas con close-circle gris.
|
|
12373
|
+
* - 🟡 Moderate (327:8258): segmentos 1-2 llenos (error + warning/base).
|
|
12374
|
+
* - 🟢 Strong (327:8277): 3 segmentos llenos (error + warning + success/base).
|
|
12375
|
+
*
|
|
12376
|
+
* OJO: cada segmento tiene su color FIJO (1=error, 2=warning, 3=success) y se
|
|
12377
|
+
* llenan progresivamente — en Strong la barra es roja+naranja+verde, NO toda verde.
|
|
12378
|
+
*
|
|
12379
|
+
* EXACT (pulled from Figma 2026-07-23, verified):
|
|
12380
|
+
* - Contenedor: flex-col, gap 8px, padding-top 6px, width 100% (Figma fija 300
|
|
12381
|
+
* como ejemplo — el componente es full-width, el consumer restringe).
|
|
12382
|
+
* - Fila "Level": flex gap 8px; cada segmento flex:1, height 4px, radius 1.2px.
|
|
12383
|
+
* - Segmento vacío: bg/soft-200 #ebebeb · lleno: state/error/base #fb3748 ·
|
|
12384
|
+
* state/warning/base #fa7319 · state/success/base #1fc16b.
|
|
12385
|
+
* - Caption y condiciones: text/sub-600 #5c5c5c, Inter Regular 12/lh16
|
|
12386
|
+
* (Paragraph/XSmall), font-feature-settings 'ss11' 1,'calt' 0,'liga' 0.
|
|
12387
|
+
* - Fila condición: flex gap 4px, items-center; icono 16px.
|
|
12388
|
+
* - Icono check (cumplida / estado empty): checkbox-circle-fill — verde
|
|
12389
|
+
* state/success/base cumplida, gris icon/soft-400 #a3a3a3 en empty.
|
|
12390
|
+
* - Icono no cumplida (weak/moderate): close-circle-fill gris icon/soft-400.
|
|
12391
|
+
* - Copy Figma "Must contain at least;" → "Debe contener al menos:" (ES).
|
|
12392
|
+
*
|
|
12393
|
+
* Derivación automática del nivel (cuando `strength` no se fuerza):
|
|
12394
|
+
* - `value` vacío → 'empty'
|
|
12395
|
+
* - todas las condiciones cumplidas → 'strong'
|
|
12396
|
+
* - cumplidas ≥ mitad del total → 'moderate'
|
|
12397
|
+
* - resto → 'weak'
|
|
12398
|
+
* (con las 3 condiciones default: 3=strong, 2=moderate, 0-1=weak — igual al set.)
|
|
12399
|
+
*
|
|
12400
|
+
* Inputs:
|
|
12401
|
+
* - value: string — la contraseña; evalúa condiciones y deriva el nivel.
|
|
12402
|
+
* - strength: SuiPasswordStrengthLevel | null (default null) — override
|
|
12403
|
+
* manual del nivel; si está presente gana sobre el derivado.
|
|
12404
|
+
* - caption: string (default 'Debe contener al menos:') — '' lo oculta.
|
|
12405
|
+
* - conditions: SuiPasswordStrengthCondition[] — checklist configurable
|
|
12406
|
+
* (default: las 3 del set en español). [] oculta la lista.
|
|
12407
|
+
* - levelLabels: Partial<Record<level, string>> — textos del aria-valuetext.
|
|
12408
|
+
* - ariaLabel: string (default 'Seguridad de la contraseña') — label del
|
|
12409
|
+
* progressbar.
|
|
12410
|
+
*
|
|
12411
|
+
* Output:
|
|
12412
|
+
* - strengthChange: SuiPasswordStrengthLevel — emitido cuando el nivel
|
|
12413
|
+
* resuelto cambia (no emite el estado inicial).
|
|
12414
|
+
*
|
|
12415
|
+
* A11y: la barra es role="progressbar" (aria-valuemin=0, aria-valuemax=3,
|
|
12416
|
+
* aria-valuenow=segmentos llenos, aria-valuetext=label del nivel); la checklist
|
|
12417
|
+
* es <ul>/<li> semántica con los iconos aria-hidden.
|
|
12418
|
+
*
|
|
12419
|
+
* Usage:
|
|
12420
|
+
* <sui-password-strength [value]="password()" (strengthChange)="onStrength($event)" />
|
|
12421
|
+
* <sui-password-strength strength="moderate" [conditions]="[]" caption="" />
|
|
12422
|
+
*/
|
|
12423
|
+
class SuiPasswordStrength {
|
|
12424
|
+
/** Contraseña a evaluar — deriva las condiciones cumplidas y el nivel. */
|
|
12425
|
+
value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
12426
|
+
/** Override manual del nivel — presente gana sobre el derivado de `value`. */
|
|
12427
|
+
strength = input(null, ...(ngDevMode ? [{ debugName: "strength" }] : /* istanbul ignore next */ []));
|
|
12428
|
+
/** Caption sobre la checklist. '' = oculto. */
|
|
12429
|
+
caption = input('Debe contener al menos:', ...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
|
|
12430
|
+
/** Checklist de condiciones. [] = sin checklist (solo barra + caption). */
|
|
12431
|
+
conditions = input(SUI_PASSWORD_STRENGTH_DEFAULT_CONDITIONS, ...(ngDevMode ? [{ debugName: "conditions" }] : /* istanbul ignore next */ []));
|
|
12432
|
+
/** Textos del nivel para lectores de pantalla (merge sobre los defaults ES). */
|
|
12433
|
+
levelLabels = input({}, ...(ngDevMode ? [{ debugName: "levelLabels" }] : /* istanbul ignore next */ []));
|
|
12434
|
+
/** Label accesible del progressbar. */
|
|
12435
|
+
ariaLabel = input('Seguridad de la contraseña', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
12436
|
+
/** Emite el nivel resuelto cada vez que cambia (no emite el inicial). */
|
|
12437
|
+
strengthChange = output();
|
|
12438
|
+
/** Condiciones evaluadas: `met` manual gana; sino corre `test` sobre `value`. */
|
|
12439
|
+
conditionStates = computed(() => this.conditions().map((c) => ({
|
|
12440
|
+
label: c.label,
|
|
12441
|
+
met: c.met ?? this.runTest(c.test, this.value()),
|
|
12442
|
+
})), ...(ngDevMode ? [{ debugName: "conditionStates" }] : /* istanbul ignore next */ []));
|
|
12443
|
+
/** Nivel resuelto: override explícito o derivado de las condiciones. */
|
|
12444
|
+
resolvedStrength = computed(() => {
|
|
12445
|
+
const forced = this.strength();
|
|
12446
|
+
if (forced)
|
|
12447
|
+
return forced;
|
|
12448
|
+
if (!this.value())
|
|
12449
|
+
return 'empty';
|
|
12450
|
+
const states = this.conditionStates();
|
|
12451
|
+
if (!states.length)
|
|
12452
|
+
return 'strong';
|
|
12453
|
+
const met = states.filter((s) => s.met).length;
|
|
12454
|
+
if (met === states.length)
|
|
12455
|
+
return 'strong';
|
|
12456
|
+
if (met >= states.length / 2)
|
|
12457
|
+
return 'moderate';
|
|
12458
|
+
return 'weak';
|
|
12459
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedStrength" }] : /* istanbul ignore next */ []));
|
|
12460
|
+
/** Segmentos llenos de la barra (0-3) — también el aria-valuenow. */
|
|
12461
|
+
filledSegments = computed(() => ({ empty: 0, weak: 1, moderate: 2, strong: 3 })[this.resolvedStrength()], ...(ngDevMode ? [{ debugName: "filledSegments" }] : /* istanbul ignore next */ []));
|
|
12462
|
+
/** aria-valuetext del nivel actual (levelLabels del consumer sobre defaults). */
|
|
12463
|
+
levelLabel = computed(() => ({ ...SUI_PASSWORD_STRENGTH_DEFAULT_LEVEL_LABELS, ...this.levelLabels() })[this.resolvedStrength()], ...(ngDevMode ? [{ debugName: "levelLabel" }] : /* istanbul ignore next */ []));
|
|
12464
|
+
/** Icono por condición: check (cumplida o estado empty) vs close (fallida). */
|
|
12465
|
+
iconName(met) {
|
|
12466
|
+
if (met)
|
|
12467
|
+
return 'checkbox-circle-fill';
|
|
12468
|
+
return this.resolvedStrength() === 'empty' ? 'checkbox-circle-fill' : 'close-circle-fill';
|
|
12469
|
+
}
|
|
12470
|
+
previousStrength = null;
|
|
12471
|
+
constructor() {
|
|
12472
|
+
effect(() => {
|
|
12473
|
+
const s = this.resolvedStrength();
|
|
12474
|
+
if (this.previousStrength !== null && this.previousStrength !== s) {
|
|
12475
|
+
this.strengthChange.emit(s);
|
|
12476
|
+
}
|
|
12477
|
+
this.previousStrength = s;
|
|
12478
|
+
});
|
|
12479
|
+
}
|
|
12480
|
+
runTest(test, value) {
|
|
12481
|
+
if (!test)
|
|
12482
|
+
return false;
|
|
12483
|
+
/* RegExp con flag /g es stateful (lastIndex) — se clona sin flags de estado. */
|
|
12484
|
+
if (test instanceof RegExp)
|
|
12485
|
+
return new RegExp(test.source, test.flags.replace(/[gy]/g, '')).test(value);
|
|
12486
|
+
return test(value);
|
|
12487
|
+
}
|
|
12488
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiPasswordStrength, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12489
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiPasswordStrength, isStandalone: true, selector: "sui-password-strength", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, strength: { classPropertyName: "strength", publicName: "strength", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, conditions: { classPropertyName: "conditions", publicName: "conditions", isSignal: true, isRequired: false, transformFunction: null }, levelLabels: { classPropertyName: "levelLabels", publicName: "levelLabels", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { strengthChange: "strengthChange" }, host: { properties: { "attr.data-sui-strength": "resolvedStrength()" } }, ngImport: i0, template: "<!-- Barra segmentada (fila \"Level\" \u2014 Figma 327:8184): 3 segmentos de color fijo\n (1=error, 2=warning, 3=success) que se llenan progresivamente. -->\n<div\n class=\"sui-password-strength__level\"\n role=\"progressbar\"\n [attr.aria-label]=\"ariaLabel()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"3\"\n [attr.aria-valuenow]=\"filledSegments()\"\n [attr.aria-valuetext]=\"levelLabel()\"\n>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--error\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 1\"\n ></span>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--warning\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 2\"\n ></span>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--success\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 3\"\n ></span>\n</div>\n\n@if (caption()) {\n <p class=\"sui-password-strength__caption\">{{ caption() }}</p>\n}\n\n@if (conditionStates().length) {\n <ul class=\"sui-password-strength__conditions\">\n @for (c of conditionStates(); track $index) {\n <li class=\"sui-password-strength__condition\" [class.sui-password-strength__condition--met]=\"c.met\">\n <sui-icon\n class=\"sui-password-strength__condition-icon\"\n [name]=\"iconName(c.met)\"\n [size]=\"16\"\n aria-hidden=\"true\"\n />\n <span class=\"sui-password-strength__condition-label\">{{ c.label }}</span>\n </li>\n }\n </ul>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:8px;padding-top:6px;width:100%;box-sizing:border-box}.sui-password-strength__level{display:flex;gap:8px;width:100%}.sui-password-strength__bar{flex:1 1 0;min-width:1px;height:4px;border-radius:1.2px;background:var(--sui-bg-soft-200, #ebebeb);transition:background-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}.sui-password-strength__bar--error.sui-password-strength__bar--on{background:var(--sui-state-error-base, #fb3748)}.sui-password-strength__bar--warning.sui-password-strength__bar--on{background:var(--sui-state-warning-base, #fa7319)}.sui-password-strength__bar--success.sui-password-strength__bar--on{background:var(--sui-state-success-base, #1fc16b)}.sui-password-strength__caption{margin:0;color:var(--sui-text-sub-600, #5c5c5c);font-size:12px;font-weight:400;line-height:16px;overflow-wrap:break-word;font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-password-strength__conditions{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;width:100%}.sui-password-strength__condition{display:flex;align-items:center;gap:4px;width:100%}.sui-password-strength__condition-icon{flex:none;color:var(--sui-icon-soft-400, #a3a3a3)}.sui-password-strength__condition--met .sui-password-strength__condition-icon{color:var(--sui-state-success-base, #1fc16b)}.sui-password-strength__condition-label{flex:1 1 0;min-width:1px;color:var(--sui-text-sub-600, #5c5c5c);font-size:12px;font-weight:400;line-height:16px;overflow-wrap:break-word;font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}@media(prefers-reduced-motion:reduce){.sui-password-strength__bar{transition:none}}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12490
|
+
}
|
|
12491
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiPasswordStrength, decorators: [{
|
|
12492
|
+
type: Component,
|
|
12493
|
+
args: [{ selector: 'sui-password-strength', standalone: true, imports: [SuiIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
12494
|
+
'[attr.data-sui-strength]': 'resolvedStrength()',
|
|
12495
|
+
}, template: "<!-- Barra segmentada (fila \"Level\" \u2014 Figma 327:8184): 3 segmentos de color fijo\n (1=error, 2=warning, 3=success) que se llenan progresivamente. -->\n<div\n class=\"sui-password-strength__level\"\n role=\"progressbar\"\n [attr.aria-label]=\"ariaLabel()\"\n aria-valuemin=\"0\"\n aria-valuemax=\"3\"\n [attr.aria-valuenow]=\"filledSegments()\"\n [attr.aria-valuetext]=\"levelLabel()\"\n>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--error\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 1\"\n ></span>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--warning\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 2\"\n ></span>\n <span\n class=\"sui-password-strength__bar sui-password-strength__bar--success\"\n [class.sui-password-strength__bar--on]=\"filledSegments() >= 3\"\n ></span>\n</div>\n\n@if (caption()) {\n <p class=\"sui-password-strength__caption\">{{ caption() }}</p>\n}\n\n@if (conditionStates().length) {\n <ul class=\"sui-password-strength__conditions\">\n @for (c of conditionStates(); track $index) {\n <li class=\"sui-password-strength__condition\" [class.sui-password-strength__condition--met]=\"c.met\">\n <sui-icon\n class=\"sui-password-strength__condition-icon\"\n [name]=\"iconName(c.met)\"\n [size]=\"16\"\n aria-hidden=\"true\"\n />\n <span class=\"sui-password-strength__condition-label\">{{ c.label }}</span>\n </li>\n }\n </ul>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:8px;padding-top:6px;width:100%;box-sizing:border-box}.sui-password-strength__level{display:flex;gap:8px;width:100%}.sui-password-strength__bar{flex:1 1 0;min-width:1px;height:4px;border-radius:1.2px;background:var(--sui-bg-soft-200, #ebebeb);transition:background-color var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1))}.sui-password-strength__bar--error.sui-password-strength__bar--on{background:var(--sui-state-error-base, #fb3748)}.sui-password-strength__bar--warning.sui-password-strength__bar--on{background:var(--sui-state-warning-base, #fa7319)}.sui-password-strength__bar--success.sui-password-strength__bar--on{background:var(--sui-state-success-base, #1fc16b)}.sui-password-strength__caption{margin:0;color:var(--sui-text-sub-600, #5c5c5c);font-size:12px;font-weight:400;line-height:16px;overflow-wrap:break-word;font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-password-strength__conditions{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none;width:100%}.sui-password-strength__condition{display:flex;align-items:center;gap:4px;width:100%}.sui-password-strength__condition-icon{flex:none;color:var(--sui-icon-soft-400, #a3a3a3)}.sui-password-strength__condition--met .sui-password-strength__condition-icon{color:var(--sui-state-success-base, #1fc16b)}.sui-password-strength__condition-label{flex:1 1 0;min-width:1px;color:var(--sui-text-sub-600, #5c5c5c);font-size:12px;font-weight:400;line-height:16px;overflow-wrap:break-word;font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}@media(prefers-reduced-motion:reduce){.sui-password-strength__bar{transition:none}}\n"] }]
|
|
12496
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], strength: [{ type: i0.Input, args: [{ isSignal: true, alias: "strength", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], conditions: [{ type: i0.Input, args: [{ isSignal: true, alias: "conditions", required: false }] }], levelLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelLabels", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], strengthChange: [{ type: i0.Output, args: ["strengthChange"] }] } });
|
|
12497
|
+
|
|
12498
|
+
/** Los 8 tipos canon del set de Figma (mismo orden que el frame). */
|
|
12499
|
+
const SUI_PAYMENT_ICON_TYPES = [
|
|
12500
|
+
'water',
|
|
12501
|
+
'gas',
|
|
12502
|
+
'electricity',
|
|
12503
|
+
'donate',
|
|
12504
|
+
'internet',
|
|
12505
|
+
'phone',
|
|
12506
|
+
'rent',
|
|
12507
|
+
'tax',
|
|
12508
|
+
];
|
|
12509
|
+
/**
|
|
12510
|
+
* SUI Payment Icon — SUI Design System 2.0
|
|
12511
|
+
*
|
|
12512
|
+
* Figma file: 8p1k72aKKvzJV4XcvPS4VO — set "Payment Icons [1.1]" = nodo 2942:9995.
|
|
12513
|
+
* Icono circular que identifica el TIPO de un pago/servicio (agua, gas, luz,
|
|
12514
|
+
* donación, internet, teléfono, alquiler, impuestos) en listas de pagos,
|
|
12515
|
+
* historial de transacciones y selectores de categoría de servicio.
|
|
12516
|
+
*
|
|
12517
|
+
* NO es un set de assets (tipo sui-flag/sui-brand-logo): cada variant del Figma
|
|
12518
|
+
* es un círculo `radius-full` con bg `state/*-lighter` + un glyph RemixIcon fill
|
|
12519
|
+
* de 20px en el `state/*-base` — exactamente la anatomía de `sui-key-icon`
|
|
12520
|
+
* styleVariant='lighter'. Por eso este componente es un WRAPPER SEMÁNTICO que
|
|
12521
|
+
* COMPONE <sui-key-icon> (regla del DS: componer, no duplicar): fija el estilo
|
|
12522
|
+
* en 'lighter' y mapea `type` → { icono, color }.
|
|
12523
|
+
*
|
|
12524
|
+
* ── Type → icono/color (Figma exacto, fills verificados en los 8 vectores) ──
|
|
12525
|
+
* water → drop-fill teal verified base #47c2ff / lighter #ebf8ff
|
|
12526
|
+
* gas → fire-fill red error base #fb3748 / lighter #ffebec
|
|
12527
|
+
* electricity → lightbulb-flash-fill yellow away base #f6b51e / lighter #fffaeb
|
|
12528
|
+
* donate → hand-heart-fill pink highlighted base #fb4ba3 / lighter #ffebf4
|
|
12529
|
+
* internet → wifi-fill blue information base #335cff / lighter #ebf1ff
|
|
12530
|
+
* phone → cellphone-fill orange warning base #fa7319 / lighter #fff3eb
|
|
12531
|
+
* rent → home-smile-fill green success base #1fc16b / lighter #e3f7ec
|
|
12532
|
+
* tax → file-list-fill purple feature base #7d52f4 / lighter #efebff
|
|
12533
|
+
*
|
|
12534
|
+
* EXACT (pulled from Figma 2942:9995, verified 2026-07-23):
|
|
12535
|
+
* - Contenedor: 40×40, padding 10, radius `--radius-full` (999px), bg *-lighter.
|
|
12536
|
+
* - Glyph: 20×20 RemixIcon fill (layer names literales del set: drop-fill,
|
|
12537
|
+
* fire-fill, lightbulb-flash-fill, hand-heart-fill, wifi-fill, cellphone-fill,
|
|
12538
|
+
* home-smile-fill, file-list-fill — los 8 existen en el font RemixIcon del DS).
|
|
12539
|
+
* - Sin borde, sin sombra (idéntico a key-icon lighter).
|
|
12540
|
+
*
|
|
12541
|
+
* PENDING VERIFY (convención propia del DS, no viene del set):
|
|
12542
|
+
* - El set de Figma solo define el tamaño 40. Los demás tamaños (32/48/56/64)
|
|
12543
|
+
* heredan la escala canon de sui-key-icon (icono = size/2 con piso 20px).
|
|
12544
|
+
*
|
|
12545
|
+
* Display-only: no es control de formulario ni clickeable. Decorativo por
|
|
12546
|
+
* default (`aria-hidden`); con `ariaLabel` se anuncia como imagen (`role="img"`).
|
|
12547
|
+
*
|
|
12548
|
+
* Usage:
|
|
12549
|
+
* <sui-payment-icon type="water" />
|
|
12550
|
+
* <sui-payment-icon type="rent" [size]="48" ariaLabel="Pago de alquiler" />
|
|
12551
|
+
*/
|
|
12552
|
+
const TYPE_ICON = {
|
|
12553
|
+
water: 'drop-fill',
|
|
12554
|
+
gas: 'fire-fill',
|
|
12555
|
+
electricity: 'lightbulb-flash-fill',
|
|
12556
|
+
donate: 'hand-heart-fill',
|
|
12557
|
+
internet: 'wifi-fill',
|
|
12558
|
+
phone: 'cellphone-fill',
|
|
12559
|
+
rent: 'home-smile-fill',
|
|
12560
|
+
tax: 'file-list-fill',
|
|
12561
|
+
};
|
|
12562
|
+
const TYPE_COLOR = {
|
|
12563
|
+
water: 'teal',
|
|
12564
|
+
gas: 'red',
|
|
12565
|
+
electricity: 'yellow',
|
|
12566
|
+
donate: 'pink',
|
|
12567
|
+
internet: 'blue',
|
|
12568
|
+
phone: 'orange',
|
|
12569
|
+
rent: 'green',
|
|
12570
|
+
tax: 'purple',
|
|
12571
|
+
};
|
|
12572
|
+
class SuiPaymentIcon {
|
|
12573
|
+
/** Tipo de pago/servicio (ver SUI_PAYMENT_ICON_TYPES). Define icono + color. */
|
|
12574
|
+
type = input.required(...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
12575
|
+
/** Tamaño del contenedor en px. Canon Figma = 40; la escala es la de sui-key-icon. */
|
|
12576
|
+
size = input(40, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
12577
|
+
/**
|
|
12578
|
+
* Aria-label opcional. Si se provee, se anuncia como imagen (`role="img"`);
|
|
12579
|
+
* si no, se considera decorativo (`aria-hidden="true"`) — el caso típico,
|
|
12580
|
+
* porque el icono acompaña un texto que ya nombra el servicio.
|
|
12581
|
+
*/
|
|
12582
|
+
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
12583
|
+
/** RemixIcon name derivado del type (glyphs literales del set de Figma). */
|
|
12584
|
+
iconName = computed(() => TYPE_ICON[this.type()], ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
|
|
12585
|
+
/** Color semántico de sui-key-icon derivado del type. */
|
|
12586
|
+
keyColor = computed(() => TYPE_COLOR[this.type()], ...(ngDevMode ? [{ debugName: "keyColor" }] : /* istanbul ignore next */ []));
|
|
12587
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiPaymentIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12588
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.17", type: SuiPaymentIcon, isStandalone: true, selector: "sui-payment-icon", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-sui-type": "type()", "attr.aria-hidden": "ariaLabel() ? null : \"true\"", "attr.role": "ariaLabel() ? \"img\" : null", "attr.aria-label": "ariaLabel()", "attr.title": "null" } }, ngImport: i0, template: "<sui-key-icon\n class=\"sui-payment-icon__key\"\n [name]=\"iconName()\"\n styleVariant=\"lighter\"\n [color]=\"keyColor()\"\n [size]=\"size()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;flex:0 0 auto;vertical-align:middle;line-height:1}\n"], dependencies: [{ kind: "component", type: SuiKeyIcon, selector: "sui-key-icon", inputs: ["name", "styleVariant", "color", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
12589
|
+
}
|
|
12590
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiPaymentIcon, decorators: [{
|
|
12591
|
+
type: Component,
|
|
12592
|
+
args: [{ selector: 'sui-payment-icon', standalone: true, imports: [SuiKeyIcon], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
12593
|
+
'[attr.data-sui-type]': 'type()',
|
|
12594
|
+
'[attr.aria-hidden]': 'ariaLabel() ? null : "true"',
|
|
12595
|
+
'[attr.role]': 'ariaLabel() ? "img" : null',
|
|
12596
|
+
'[attr.aria-label]': 'ariaLabel()',
|
|
12597
|
+
/* Strip native `title` attr — patrón canon Ontop (ver CLAUDE.md). */
|
|
12598
|
+
'[attr.title]': 'null',
|
|
12599
|
+
}, template: "<sui-key-icon\n class=\"sui-payment-icon__key\"\n [name]=\"iconName()\"\n styleVariant=\"lighter\"\n [color]=\"keyColor()\"\n [size]=\"size()\"\n/>\n", styles: ["@charset \"UTF-8\";:host{display:inline-flex;flex:0 0 auto;vertical-align:middle;line-height:1}\n"] }]
|
|
12600
|
+
}], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }] } });
|
|
12601
|
+
|
|
12057
12602
|
class SuiPopover {
|
|
12058
12603
|
/* ── Tail / position ── */
|
|
12059
12604
|
/** Placement axis del tail relativo al trigger (12 variantes Figma). */
|
|
@@ -13896,7 +14441,7 @@ class SuiSidebar {
|
|
|
13896
14441
|
this.searchSubmitted.emit(this.searchValue());
|
|
13897
14442
|
}
|
|
13898
14443
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSidebar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13899
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiSidebar, isStandalone: true, selector: "sui-sidebar", inputs: { collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, indicatorColor: { classPropertyName: "indicatorColor", publicName: "indicatorColor", isSignal: true, isRequired: false, transformFunction: null }, brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, showHeaderButton: { classPropertyName: "showHeaderButton", publicName: "showHeaderButton", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchValue: { classPropertyName: "searchValue", publicName: "searchValue", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, secondaryItems: { classPropertyName: "secondaryItems", publicName: "secondaryItems", isSignal: true, isRequired: false, transformFunction: null }, supportingItems: { classPropertyName: "supportingItems", publicName: "supportingItems", isSignal: true, isRequired: false, transformFunction: null }, supportingAnchorBottom: { classPropertyName: "supportingAnchorBottom", publicName: "supportingAnchorBottom", isSignal: true, isRequired: false, transformFunction: null }, itemsLabel: { classPropertyName: "itemsLabel", publicName: "itemsLabel", isSignal: true, isRequired: false, transformFunction: null }, secondaryItemsLabel: { classPropertyName: "secondaryItemsLabel", publicName: "secondaryItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, supportingItemsLabel: { classPropertyName: "supportingItemsLabel", publicName: "supportingItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, activeRoute: { classPropertyName: "activeRoute", publicName: "activeRoute", isSignal: true, isRequired: false, transformFunction: null }, profile: { classPropertyName: "profile", publicName: "profile", isSignal: true, isRequired: false, transformFunction: null }, profileDropdown: { classPropertyName: "profileDropdown", publicName: "profileDropdown", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, closeOnNavigate: { classPropertyName: "closeOnNavigate", publicName: "closeOnNavigate", isSignal: true, isRequired: false, transformFunction: null }, showBackdrop: { classPropertyName: "showBackdrop", publicName: "showBackdrop", isSignal: true, isRequired: false, transformFunction: null }, mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchValue: "searchValueChange", open: "openChange", itemClicked: "itemClicked", logoutClicked: "logoutClicked", backdropClicked: "backdropClicked", headerButtonClicked: "headerButtonClicked", profileClicked: "profileClicked", searchSubmitted: "searchSubmitted" }, host: { properties: { "attr.title": "null", "attr.data-sui-open": "open() ? \"\" : null", "attr.data-sui-mobile-mode": "mobileMode()", "attr.data-sui-collapsed": "collapsed() ? \"\" : null", "attr.data-sui-indicator": "indicatorColor()" } }, ngImport: i0, template: "@if (showBackdrop() && open()) {\n <div class=\"sui-sidebar-backdrop\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\n}\n\n<aside\n class=\"sui-sidebar\"\n [class.sui-sidebar--open]=\"open()\"\n [class.sui-sidebar--collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n>\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <header class=\"sui-sidebar__header\">\n <div class=\"sui-sidebar__header-card\">\n <div class=\"sui-sidebar__brand-logo\">\n @if (brandCfg().logo) {\n <img [src]=\"brandCfg().logo\" [alt]=\"brandCfg().name\" referrerpolicy=\"no-referrer\" />\n } @else if (brandCfg().fallback) {\n <span class=\"sui-sidebar__brand-fallback\">{{ brandCfg().fallback }}</span>\n } @else {\n <sui-icon name=\"building-line\" [size]=\"20\" />\n }\n </div>\n @if (!collapsed()) {\n <div class=\"sui-sidebar__header-info\">\n <span class=\"sui-sidebar__header-name\">{{ brandCfg().name }}</span>\n @if (brandCfg().subtitle) {\n @if (brandCfg().subtitleAsBadge) {\n <sui-badge variant=\"filled\" color=\"orange\" size=\"small\">{{ brandCfg().subtitle }}</sui-badge>\n } @else {\n <span class=\"sui-sidebar__header-subtitle\">{{ brandCfg().subtitle }}</span>\n }\n }\n </div>\n @if (showHeaderButton()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn\"\n aria-label=\"Cambiar workspace\"\n (click)=\"onHeaderButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"expand-up-down-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n <div class=\"sui-sidebar__divider\" role=\"separator\"></div>\n </header>\n\n <!-- \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"sui-sidebar__content\">\n <!-- Search slot (Figma prop search=true) -->\n @if (!collapsed() && searchCfg(); as s) {\n <div class=\"sui-sidebar__search\">\n <sui-icon class=\"sui-sidebar__search-icon\" name=\"search-2-line\" [size]=\"20\" />\n <input\n class=\"sui-sidebar__search-input\"\n type=\"text\"\n [placeholder]=\"s.placeholder\"\n [value]=\"searchValue()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown.enter)=\"onSearchSubmit()\"\n />\n @if (s.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ s.shortcut }}</span>\n }\n </div>\n }\n\n @if (items().length > 0) {\n <div class=\"sui-sidebar__section\">\n @if (itemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ itemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of items(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n @if (secondaryItems().length > 0) {\n <div class=\"sui-sidebar__section sui-sidebar__section--secondary\">\n @if (secondaryItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ secondaryItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of secondaryItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Supporting Content (Figma supContent) \u2014 ancla al fondo cuando aplica -->\n @if (supportingItems().length > 0) {\n <div\n class=\"sui-sidebar__section sui-sidebar__section--supporting\"\n [class.sui-sidebar__section--anchor-bottom]=\"supportingAnchorBottom()\"\n >\n @if (supportingItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ supportingItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of supportingItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Feature Card slot (Figma FeatureCard=On) \u2014 promo opcional, oculto en collapsed -->\n @if (!collapsed()) {\n <div class=\"sui-sidebar__feature-card\">\n <ng-content select=\"[feature-card]\"></ng-content>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Footer (profile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 @if (profile(); as p) {\n <footer class=\"sui-sidebar__footer\">\n <div class=\"sui-sidebar__divider sui-sidebar__divider--top\" role=\"separator\"></div>\n <div class=\"sui-sidebar__profile\">\n <sui-avatar\n size=\"lg\"\n [src]=\"p.avatarUrl ?? null\"\n [alt]=\"p.name\"\n [initials]=\"p.initials ?? ''\"\n [status]=\"p.status ?? null\"\n color=\"slate\"\n />\n @if (!collapsed()) {\n <div class=\"sui-sidebar__profile-info\">\n <div class=\"sui-sidebar__profile-name-row\">\n <span class=\"sui-sidebar__profile-name\">{{ p.name }}</span>\n @if (p.verified) {\n <!-- Figma usa verified-fill (glyph propio SUI); el match m\u00E1s\n cercano en RemixIcon es verified-badge-fill. -->\n <sui-icon\n class=\"sui-sidebar__profile-verified\"\n name=\"verified-badge-fill\"\n [size]=\"20\"\n aria-label=\"Verificado\"\n />\n }\n </div>\n @if (p.email) {\n <span class=\"sui-sidebar__profile-email\">{{ p.email }}</span>\n }\n </div>\n @if (profileDropdown()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn sui-sidebar__compact-btn--ghost\"\n aria-label=\"Opciones de perfil\"\n (click)=\"onProfileButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"arrow-right-s-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n </footer>\n }\n</aside>\n\n<!-- \u2500\u2500 Item template (compartido entre todas las secciones) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #itemTpl let-item>\n @if (item.route && !item.action) {\n <a\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"sui-sidebar__item--active\"\n [attr.target]=\"item.external ? '_blank' : null\"\n [attr.rel]=\"item.external ? 'noopener noreferrer' : null\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--active]=\"isItemActive(item)\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </button>\n }\n</ng-template>\n\n<ng-template #itemBody let-item>\n @if (item.colorDot) {\n <span\n class=\"sui-sidebar__item-dot\"\n [style.background-color]=\"item.colorDot\"\n aria-hidden=\"true\"\n ></span>\n } @else if (item.icon) {\n <sui-icon class=\"sui-sidebar__item-icon\" [name]=\"item.icon\" [size]=\"20\" />\n }\n @if (!collapsed()) {\n <span class=\"sui-sidebar__item-label\">{{ item.label }}</span>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <sui-badge\n class=\"sui-sidebar__item-badge\"\n variant=\"filled\"\n [color]=\"item.variant === 'danger' ? 'red' : 'orange'\"\n size=\"small\"\n type=\"number\"\n >{{ item.badge }}</sui-badge>\n }\n @if (item.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ item.shortcut }}</span>\n }\n <!-- Chevron del item activo (Figma): visibilidad controlada por CSS via\n .sui-sidebar__item--active (cubre tanto isItemActive como RouterLinkActive). -->\n <sui-icon class=\"sui-sidebar__item-chevron\" name=\"arrow-right-s-line\" [size]=\"20\" />\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:contents;font-family:var(--font-sans, \"Satoshi\", system-ui, sans-serif)}.sui-sidebar-backdrop{position:fixed;inset:0;z-index:299;background:#0006;animation:sui-sidebar-fade-in .2s ease-out}.sui-sidebar{display:flex;flex-direction:column;flex-shrink:0;width:240px;height:100dvh;background:var(--sui-bg-white-0, #ffffff);border-right:1px solid var(--sui-stroke-soft-200, #ebebeb);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-sidebar__header{position:relative;padding:12px;padding-top:calc(12px + env(safe-area-inset-top,0px))}.sui-sidebar__header-card{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);background:var(--sui-bg-white-0, #ffffff);overflow:hidden}.sui-sidebar__brand-logo{flex-shrink:0;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c);overflow:hidden}.sui-sidebar__brand-logo img{width:100%;height:100%;object-fit:cover;display:block}.sui-sidebar__brand-fallback{font-size:18px;line-height:1}.sui-sidebar__compact-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1px;border-radius:var(--sui-radius-6, 6px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));color:var(--sui-text-sub-600, #5c5c5c);cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__compact-btn:hover{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__compact-btn:focus-visible{outline:2px solid var(--sui-state-information-base, #335cff);outline-offset:-1px}.sui-sidebar__compact-btn:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__compact-btn--ghost{border-color:transparent;box-shadow:none;background:transparent}.sui-sidebar__header-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;align-items:flex-start}.sui-sidebar__header-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__header-subtitle{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__divider{position:absolute;bottom:0;left:20px;right:20px;height:1px;background:var(--sui-stroke-soft-200, #ebebeb)}.sui-sidebar__divider--top{top:0;bottom:auto}.sui-sidebar__content{flex:1;display:flex;flex-direction:column;gap:20px;padding:20px 20px 16px;overflow-y:auto;min-height:0}.sui-sidebar__section{display:flex;flex-direction:column;gap:8px;flex-shrink:0}.sui-sidebar__section--secondary,.sui-sidebar__section--supporting{gap:6px}.sui-sidebar__section--anchor-bottom{margin-top:auto}.sui-sidebar__section-label{padding:4px;font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__section-label--collapsed{padding:4px 0;text-align:center}.sui-sidebar__search{display:flex;align-items:center;gap:8px;width:100%;padding:8px 8px 8px 10px;border-radius:var(--sui-radius-8, 8px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));box-sizing:border-box}.sui-sidebar__search-icon{flex-shrink:0;display:inline-flex;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__search-input{flex:1;min-width:0;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;font-weight:400;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717)}.sui-sidebar__search-input::placeholder{color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__shortcut{flex-shrink:0;display:inline-flex;align-items:center;box-sizing:border-box;padding:2px 6px;border-radius:var(--sui-radius-4, 4px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3);white-space:nowrap}.sui-sidebar__nav{display:flex;flex-direction:column;gap:4px}.sui-sidebar__item{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:var(--sui-radius-8, 8px);width:100%;background:transparent;border:none;font-family:inherit;text-align:left;text-decoration:none;color:inherit;cursor:pointer;position:relative;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__item:hover{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item:hover .sui-sidebar__item-label,.sui-sidebar__item:hover .sui-sidebar__item-icon{color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__item:focus-visible{outline:2px solid var(--_sui-sidebar-indicator, var(--sui-primary-base, #fa7319));outline-offset:-2px}.sui-sidebar__item:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--sui-text-sub-600, #5c5c5c);transition:color .12s ease-out}.sui-sidebar__item-label{flex:1;font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .12s ease-out}.sui-sidebar__item-badge{flex-shrink:0}.sui-sidebar__item-dot{flex-shrink:0;width:8px;height:8px;margin:6px;border-radius:999px}.sui-sidebar__item-chevron{flex-shrink:0;display:none;color:var(--sui-text-sub-600, #5c5c5c)}:host{--_sui-sidebar-indicator: var(--sui-primary-base, #fa7319)}:host([data-sui-indicator=information]){--_sui-sidebar-indicator: var(--sui-state-information-base, #335cff)}.sui-sidebar__item--active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item--active .sui-sidebar__item-label{color:var(--sui-text-strong-950, #171717)}.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--_sui-sidebar-indicator)}.sui-sidebar__item--active .sui-sidebar__item-chevron{display:inline-flex;color:var(--sui-text-sub-600, #5c5c5c)}.sui-sidebar__item--active:before{content:\"\";position:absolute;left:-20px;top:50%;transform:translateY(-50%);width:4px;height:20px;background:var(--_sui-sidebar-indicator);border-radius:0 4px 4px 0}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--active:hover{background:var(--sui-bg-weak-50, #f7f7f7)}}.sui-sidebar__item--danger .sui-sidebar__item-icon,.sui-sidebar__item--danger .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--danger:hover{background:var(--sui-red-alpha-10, rgba(251, 55, 72, .0980392157))}.sui-sidebar__item--danger:hover .sui-sidebar__item-icon,.sui-sidebar__item--danger:hover .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}}.sui-sidebar__item--danger:active{background:var(--sui-red-alpha-16, rgba(251, 55, 72, .1607843137))}.sui-sidebar__footer{position:relative;padding:12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.sui-sidebar__profile{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);overflow:hidden}.sui-sidebar__profile-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;height:40px;justify-content:center}.sui-sidebar__profile-name-row{display:flex;align-items:center;gap:2px;min-width:0}.sui-sidebar__profile-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__profile-verified{flex-shrink:0;display:inline-flex;color:var(--sui-state-verified-base, #47c2ff)}.sui-sidebar__profile-email{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__feature-card{width:100%}.sui-sidebar__feature-card:not(:has(*)){display:none}:host([data-sui-collapsed]) .sui-sidebar{width:80px}:host([data-sui-collapsed]) .sui-sidebar__header-card,:host([data-sui-collapsed]) .sui-sidebar__profile{justify-content:center}:host([data-sui-collapsed]) .sui-sidebar__content{padding-inline:12px}:host([data-sui-collapsed]) .sui-sidebar__item{justify-content:center;padding:8px}:host([data-sui-collapsed]) .sui-sidebar__item--active:before{left:-12px}@media(max-width:767px){.sui-sidebar{position:fixed;top:0;left:0;bottom:0;height:100dvh;z-index:300;width:min(86vw,360px);transform:translate(-100%);transition:transform .25s cubic-bezier(.23,1,.32,1);border-right:none;border-radius:0 24px 24px 0;overflow:hidden;box-shadow:4px 0 24px #0e121b00}.sui-sidebar--open{transform:translate(0);box-shadow:4px 0 24px #0e121b1a}:host([data-sui-mobile-mode=sheet]) .sui-sidebar{width:calc(100vw - 40px);max-width:none}.sui-sidebar__item{gap:14px;padding:14px 12px;border-radius:var(--sui-radius-10, 10px);transition:transform .16s cubic-bezier(.23,1,.32,1),background-color .16s cubic-bezier(.23,1,.32,1)}.sui-sidebar__item:active{transform:scale(.98);background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{width:24px;height:24px}.sui-sidebar__item-label{font-size:17px;line-height:24px;letter-spacing:-.01em}.sui-sidebar__item--active{background:var(--sui-orange-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-sidebar__item--active .sui-sidebar__item-label,.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--sui-primary-base, #fa7319)}.sui-sidebar__item--active:before{display:none}}@keyframes sui-sidebar-fade-in{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiAvatar, selector: "sui-avatar", inputs: ["size", "src", "alt", "initials", "color", "status", "memojiSrc", "illustrationSrc", "icon", "companyLogoSrc", "topBadge", "bgColor"] }, { kind: "component", type: SuiBadge, selector: "sui-badge", inputs: ["color", "variant", "size", "type", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14444
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiSidebar, isStandalone: true, selector: "sui-sidebar", inputs: { collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, indicatorColor: { classPropertyName: "indicatorColor", publicName: "indicatorColor", isSignal: true, isRequired: false, transformFunction: null }, brand: { classPropertyName: "brand", publicName: "brand", isSignal: true, isRequired: false, transformFunction: null }, showHeaderButton: { classPropertyName: "showHeaderButton", publicName: "showHeaderButton", isSignal: true, isRequired: false, transformFunction: null }, search: { classPropertyName: "search", publicName: "search", isSignal: true, isRequired: false, transformFunction: null }, searchValue: { classPropertyName: "searchValue", publicName: "searchValue", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, secondaryItems: { classPropertyName: "secondaryItems", publicName: "secondaryItems", isSignal: true, isRequired: false, transformFunction: null }, supportingItems: { classPropertyName: "supportingItems", publicName: "supportingItems", isSignal: true, isRequired: false, transformFunction: null }, supportingAnchorBottom: { classPropertyName: "supportingAnchorBottom", publicName: "supportingAnchorBottom", isSignal: true, isRequired: false, transformFunction: null }, itemsLabel: { classPropertyName: "itemsLabel", publicName: "itemsLabel", isSignal: true, isRequired: false, transformFunction: null }, secondaryItemsLabel: { classPropertyName: "secondaryItemsLabel", publicName: "secondaryItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, supportingItemsLabel: { classPropertyName: "supportingItemsLabel", publicName: "supportingItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, activeRoute: { classPropertyName: "activeRoute", publicName: "activeRoute", isSignal: true, isRequired: false, transformFunction: null }, profile: { classPropertyName: "profile", publicName: "profile", isSignal: true, isRequired: false, transformFunction: null }, profileDropdown: { classPropertyName: "profileDropdown", publicName: "profileDropdown", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, closeOnNavigate: { classPropertyName: "closeOnNavigate", publicName: "closeOnNavigate", isSignal: true, isRequired: false, transformFunction: null }, showBackdrop: { classPropertyName: "showBackdrop", publicName: "showBackdrop", isSignal: true, isRequired: false, transformFunction: null }, mobileMode: { classPropertyName: "mobileMode", publicName: "mobileMode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchValue: "searchValueChange", open: "openChange", itemClicked: "itemClicked", logoutClicked: "logoutClicked", backdropClicked: "backdropClicked", headerButtonClicked: "headerButtonClicked", profileClicked: "profileClicked", searchSubmitted: "searchSubmitted" }, host: { properties: { "attr.title": "null", "attr.data-sui-open": "open() ? \"\" : null", "attr.data-sui-mobile-mode": "mobileMode()", "attr.data-sui-collapsed": "collapsed() ? \"\" : null", "attr.data-sui-indicator": "indicatorColor()" } }, ngImport: i0, template: "@if (showBackdrop() && open()) {\n <div class=\"sui-sidebar-backdrop\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\n}\n\n<aside\n class=\"sui-sidebar\"\n [class.sui-sidebar--open]=\"open()\"\n [class.sui-sidebar--collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n>\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <header class=\"sui-sidebar__header\">\n <div class=\"sui-sidebar__header-card\">\n <div class=\"sui-sidebar__brand-logo\">\n @if (brandCfg().logo) {\n <img [src]=\"brandCfg().logo\" [alt]=\"brandCfg().name\" referrerpolicy=\"no-referrer\" />\n } @else if (brandCfg().fallback) {\n <span class=\"sui-sidebar__brand-fallback\">{{ brandCfg().fallback }}</span>\n } @else {\n <sui-icon name=\"building-line\" [size]=\"20\" />\n }\n </div>\n @if (!collapsed()) {\n <div class=\"sui-sidebar__header-info\">\n <span class=\"sui-sidebar__header-name\">{{ brandCfg().name }}</span>\n @if (brandCfg().subtitle) {\n @if (brandCfg().subtitleAsBadge) {\n <sui-badge variant=\"filled\" color=\"orange\" size=\"small\">{{ brandCfg().subtitle }}</sui-badge>\n } @else {\n <span class=\"sui-sidebar__header-subtitle\">{{ brandCfg().subtitle }}</span>\n }\n }\n </div>\n @if (showHeaderButton()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn\"\n aria-label=\"Cambiar workspace\"\n (click)=\"onHeaderButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"expand-up-down-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n <div class=\"sui-sidebar__divider\" role=\"separator\"></div>\n </header>\n\n <!-- \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"sui-sidebar__content\">\n <!-- Search slot (Figma prop search=true) -->\n @if (!collapsed() && searchCfg(); as s) {\n <div class=\"sui-sidebar__search\">\n <sui-icon class=\"sui-sidebar__search-icon\" name=\"search-2-line\" [size]=\"20\" />\n <input\n class=\"sui-sidebar__search-input\"\n type=\"text\"\n [placeholder]=\"s.placeholder\"\n [value]=\"searchValue()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown.enter)=\"onSearchSubmit()\"\n />\n @if (s.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ s.shortcut }}</span>\n }\n </div>\n }\n\n @if (items().length > 0) {\n <div class=\"sui-sidebar__section\">\n @if (itemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ itemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of items(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n @if (secondaryItems().length > 0) {\n <div class=\"sui-sidebar__section sui-sidebar__section--secondary\">\n @if (secondaryItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ secondaryItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of secondaryItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Supporting Content (Figma supContent) \u2014 ancla al fondo cuando aplica -->\n @if (supportingItems().length > 0) {\n <div\n class=\"sui-sidebar__section sui-sidebar__section--supporting\"\n [class.sui-sidebar__section--anchor-bottom]=\"supportingAnchorBottom()\"\n >\n @if (supportingItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ supportingItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of supportingItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Feature Card slot (Figma FeatureCard=On) \u2014 promo opcional, oculto en collapsed -->\n @if (!collapsed()) {\n <div class=\"sui-sidebar__feature-card\">\n <ng-content select=\"[feature-card]\"></ng-content>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Footer (profile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 @if (profile(); as p) {\n <footer class=\"sui-sidebar__footer\">\n <div class=\"sui-sidebar__divider sui-sidebar__divider--top\" role=\"separator\"></div>\n <div class=\"sui-sidebar__profile\">\n <sui-avatar\n size=\"lg\"\n [src]=\"p.avatarUrl ?? null\"\n [alt]=\"p.name\"\n [initials]=\"p.initials ?? ''\"\n [status]=\"p.status ?? null\"\n color=\"slate\"\n />\n @if (!collapsed()) {\n <div class=\"sui-sidebar__profile-info\">\n <div class=\"sui-sidebar__profile-name-row\">\n <span class=\"sui-sidebar__profile-name\">{{ p.name }}</span>\n @if (p.verified) {\n <!-- Figma usa verified-fill (glyph propio SUI); el match m\u00E1s\n cercano en RemixIcon es verified-badge-fill. -->\n <sui-icon\n class=\"sui-sidebar__profile-verified\"\n name=\"verified-badge-fill\"\n [size]=\"20\"\n aria-label=\"Verificado\"\n />\n }\n </div>\n @if (p.email) {\n <span class=\"sui-sidebar__profile-email\">{{ p.email }}</span>\n }\n </div>\n @if (profileDropdown()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn sui-sidebar__compact-btn--ghost\"\n aria-label=\"Opciones de perfil\"\n (click)=\"onProfileButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"arrow-right-s-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n </footer>\n }\n</aside>\n\n<!-- \u2500\u2500 Item template (compartido entre todas las secciones) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #itemTpl let-item>\n @if (item.route && !item.action) {\n <a\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"sui-sidebar__item--active\"\n [attr.target]=\"item.external ? '_blank' : null\"\n [attr.rel]=\"item.external ? 'noopener noreferrer' : null\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--active]=\"isItemActive(item)\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </button>\n }\n</ng-template>\n\n<ng-template #itemBody let-item>\n @if (item.colorDot) {\n <span\n class=\"sui-sidebar__item-dot\"\n [style.background-color]=\"item.colorDot\"\n aria-hidden=\"true\"\n ></span>\n } @else if (item.icon) {\n <sui-icon class=\"sui-sidebar__item-icon\" [name]=\"item.icon\" [size]=\"20\" />\n }\n @if (!collapsed()) {\n <span class=\"sui-sidebar__item-label\">{{ item.label }}</span>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <sui-badge\n class=\"sui-sidebar__item-badge\"\n variant=\"filled\"\n [color]=\"item.variant === 'danger' ? 'red' : 'orange'\"\n size=\"small\"\n type=\"number\"\n >{{ item.badge }}</sui-badge>\n }\n @if (item.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ item.shortcut }}</span>\n }\n <!-- Chevron del item activo (Figma): visibilidad controlada por CSS via\n .sui-sidebar__item--active (cubre tanto isItemActive como RouterLinkActive). -->\n <sui-icon class=\"sui-sidebar__item-chevron\" name=\"arrow-right-s-line\" [size]=\"20\" />\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:contents;font-family:var(--font-sans, \"Satoshi\", system-ui, sans-serif)}.sui-sidebar-backdrop{position:fixed;inset:0;z-index:299;background:#0006;animation:sui-sidebar-fade-in .2s ease-out}.sui-sidebar{display:flex;flex-direction:column;flex-shrink:0;width:272px;height:100dvh;background:var(--sui-bg-white-0, #ffffff);border-right:1px solid var(--sui-stroke-soft-200, #ebebeb);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-sidebar__header{position:relative;padding:12px;padding-top:calc(12px + env(safe-area-inset-top,0px))}.sui-sidebar__header-card{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);background:var(--sui-bg-white-0, #ffffff);overflow:hidden}.sui-sidebar__brand-logo{flex-shrink:0;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c);overflow:hidden}.sui-sidebar__brand-logo img{width:100%;height:100%;object-fit:cover;display:block}.sui-sidebar__brand-fallback{font-size:18px;line-height:1}.sui-sidebar__compact-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1px;border-radius:var(--sui-radius-6, 6px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));color:var(--sui-text-sub-600, #5c5c5c);cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__compact-btn:hover{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__compact-btn:focus-visible{outline:2px solid var(--sui-state-information-base, #335cff);outline-offset:-1px}.sui-sidebar__compact-btn:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__compact-btn--ghost{border-color:transparent;box-shadow:none;background:transparent}.sui-sidebar__header-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;align-items:flex-start}.sui-sidebar__header-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__header-subtitle{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__divider{position:absolute;bottom:0;left:20px;right:20px;height:1px;background:var(--sui-stroke-soft-200, #ebebeb)}.sui-sidebar__divider--top{top:0;bottom:auto}.sui-sidebar__content{flex:1;display:flex;flex-direction:column;gap:20px;padding:20px 20px 16px;overflow-y:auto;overflow-x:hidden;min-height:0}.sui-sidebar__section{display:flex;flex-direction:column;gap:8px;flex-shrink:0}.sui-sidebar__section--secondary,.sui-sidebar__section--supporting{gap:6px}.sui-sidebar__section--anchor-bottom{margin-top:auto}.sui-sidebar__section-label{padding:4px;font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__section-label--collapsed{padding:4px 0;text-align:center}.sui-sidebar__search{display:flex;align-items:center;gap:8px;width:100%;padding:8px 8px 8px 10px;border-radius:var(--sui-radius-8, 8px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));box-sizing:border-box}.sui-sidebar__search-icon{flex-shrink:0;display:inline-flex;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__search-input{flex:1;min-width:0;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;font-weight:400;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717)}.sui-sidebar__search-input::placeholder{color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__shortcut{flex-shrink:0;display:inline-flex;align-items:center;box-sizing:border-box;padding:2px 6px;border-radius:var(--sui-radius-4, 4px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3);white-space:nowrap}.sui-sidebar__nav{display:flex;flex-direction:column;gap:4px}.sui-sidebar__item{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:var(--sui-radius-8, 8px);width:100%;background:transparent;border:none;font-family:inherit;text-align:left;text-decoration:none;color:inherit;cursor:pointer;position:relative;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__item:hover{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item:hover .sui-sidebar__item-label,.sui-sidebar__item:hover .sui-sidebar__item-icon{color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__item:focus-visible{outline:2px solid var(--_sui-sidebar-indicator, var(--sui-primary-base, #fa7319));outline-offset:-2px}.sui-sidebar__item:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--sui-text-sub-600, #5c5c5c);transition:color .12s ease-out}.sui-sidebar__item-label{flex:1;font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .12s ease-out}.sui-sidebar__item-badge{flex-shrink:0}.sui-sidebar__item-dot{flex-shrink:0;width:8px;height:8px;margin:6px;border-radius:999px}.sui-sidebar__item-chevron{flex-shrink:0;display:none;color:var(--sui-text-sub-600, #5c5c5c)}:host{--_sui-sidebar-indicator: var(--sui-primary-base, #fa7319)}:host([data-sui-indicator=information]){--_sui-sidebar-indicator: var(--sui-state-information-base, #335cff)}.sui-sidebar__item--active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item--active .sui-sidebar__item-label{color:var(--sui-text-strong-950, #171717)}.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--_sui-sidebar-indicator)}.sui-sidebar__item--active .sui-sidebar__item-chevron{display:inline-flex;color:var(--sui-text-sub-600, #5c5c5c)}.sui-sidebar__item--active:before{content:\"\";position:absolute;left:-20px;top:50%;transform:translateY(-50%);width:4px;height:20px;background:var(--_sui-sidebar-indicator);border-radius:0 4px 4px 0}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--active:hover{background:var(--sui-bg-weak-50, #f7f7f7)}}.sui-sidebar__item--danger .sui-sidebar__item-icon,.sui-sidebar__item--danger .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--danger:hover{background:var(--sui-red-alpha-10, rgba(251, 55, 72, .0980392157))}.sui-sidebar__item--danger:hover .sui-sidebar__item-icon,.sui-sidebar__item--danger:hover .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}}.sui-sidebar__item--danger:active{background:var(--sui-red-alpha-16, rgba(251, 55, 72, .1607843137))}.sui-sidebar__footer{position:relative;padding:12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.sui-sidebar__profile{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);overflow:hidden}.sui-sidebar__profile-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;height:40px;justify-content:center}.sui-sidebar__profile-name-row{display:flex;align-items:center;gap:2px;min-width:0}.sui-sidebar__profile-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__profile-verified{flex-shrink:0;display:inline-flex;color:var(--sui-state-verified-base, #47c2ff)}.sui-sidebar__profile-email{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__feature-card{width:100%}.sui-sidebar__feature-card:not(:has(*)){display:none}:host([data-sui-collapsed]) .sui-sidebar{width:80px}:host([data-sui-collapsed]) .sui-sidebar__header-card,:host([data-sui-collapsed]) .sui-sidebar__profile{justify-content:center}:host([data-sui-collapsed]) .sui-sidebar__content{padding-inline:12px}:host([data-sui-collapsed]) .sui-sidebar__item{justify-content:center;padding:8px}:host([data-sui-collapsed]) .sui-sidebar__item--active:before{left:-12px}@media(max-width:767px){.sui-sidebar{position:fixed;top:0;left:0;bottom:0;height:100dvh;z-index:300;width:min(86vw,360px);transform:translate(-100%);transition:transform .25s cubic-bezier(.23,1,.32,1);border-right:none;border-radius:0 24px 24px 0;overflow:hidden;box-shadow:4px 0 24px #0e121b00}.sui-sidebar--open{transform:translate(0);box-shadow:4px 0 24px #0e121b1a}:host([data-sui-mobile-mode=sheet]) .sui-sidebar{width:calc(100vw - 40px);max-width:none}.sui-sidebar__item{gap:14px;padding:14px 12px;border-radius:var(--sui-radius-10, 10px);transition:transform .16s cubic-bezier(.23,1,.32,1),background-color .16s cubic-bezier(.23,1,.32,1)}.sui-sidebar__item:active{transform:scale(.98);background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{width:24px;height:24px}.sui-sidebar__item-label{font-size:17px;line-height:24px;letter-spacing:-.01em}.sui-sidebar__item--active{background:var(--sui-orange-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-sidebar__item--active .sui-sidebar__item-label,.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--sui-primary-base, #fa7319)}.sui-sidebar__item--active:before{display:none}}@keyframes sui-sidebar-fade-in{0%{opacity:0}to{opacity:1}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiAvatar, selector: "sui-avatar", inputs: ["size", "src", "alt", "initials", "color", "status", "memojiSrc", "illustrationSrc", "icon", "companyLogoSrc", "topBadge", "bgColor"] }, { kind: "component", type: SuiBadge, selector: "sui-badge", inputs: ["color", "variant", "size", "type", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13900
14445
|
}
|
|
13901
14446
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiSidebar, decorators: [{
|
|
13902
14447
|
type: Component,
|
|
@@ -13907,7 +14452,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
13907
14452
|
'[attr.data-sui-mobile-mode]': 'mobileMode()',
|
|
13908
14453
|
'[attr.data-sui-collapsed]': 'collapsed() ? "" : null',
|
|
13909
14454
|
'[attr.data-sui-indicator]': 'indicatorColor()',
|
|
13910
|
-
}, template: "@if (showBackdrop() && open()) {\n <div class=\"sui-sidebar-backdrop\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\n}\n\n<aside\n class=\"sui-sidebar\"\n [class.sui-sidebar--open]=\"open()\"\n [class.sui-sidebar--collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n>\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <header class=\"sui-sidebar__header\">\n <div class=\"sui-sidebar__header-card\">\n <div class=\"sui-sidebar__brand-logo\">\n @if (brandCfg().logo) {\n <img [src]=\"brandCfg().logo\" [alt]=\"brandCfg().name\" referrerpolicy=\"no-referrer\" />\n } @else if (brandCfg().fallback) {\n <span class=\"sui-sidebar__brand-fallback\">{{ brandCfg().fallback }}</span>\n } @else {\n <sui-icon name=\"building-line\" [size]=\"20\" />\n }\n </div>\n @if (!collapsed()) {\n <div class=\"sui-sidebar__header-info\">\n <span class=\"sui-sidebar__header-name\">{{ brandCfg().name }}</span>\n @if (brandCfg().subtitle) {\n @if (brandCfg().subtitleAsBadge) {\n <sui-badge variant=\"filled\" color=\"orange\" size=\"small\">{{ brandCfg().subtitle }}</sui-badge>\n } @else {\n <span class=\"sui-sidebar__header-subtitle\">{{ brandCfg().subtitle }}</span>\n }\n }\n </div>\n @if (showHeaderButton()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn\"\n aria-label=\"Cambiar workspace\"\n (click)=\"onHeaderButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"expand-up-down-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n <div class=\"sui-sidebar__divider\" role=\"separator\"></div>\n </header>\n\n <!-- \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"sui-sidebar__content\">\n <!-- Search slot (Figma prop search=true) -->\n @if (!collapsed() && searchCfg(); as s) {\n <div class=\"sui-sidebar__search\">\n <sui-icon class=\"sui-sidebar__search-icon\" name=\"search-2-line\" [size]=\"20\" />\n <input\n class=\"sui-sidebar__search-input\"\n type=\"text\"\n [placeholder]=\"s.placeholder\"\n [value]=\"searchValue()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown.enter)=\"onSearchSubmit()\"\n />\n @if (s.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ s.shortcut }}</span>\n }\n </div>\n }\n\n @if (items().length > 0) {\n <div class=\"sui-sidebar__section\">\n @if (itemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ itemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of items(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n @if (secondaryItems().length > 0) {\n <div class=\"sui-sidebar__section sui-sidebar__section--secondary\">\n @if (secondaryItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ secondaryItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of secondaryItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Supporting Content (Figma supContent) \u2014 ancla al fondo cuando aplica -->\n @if (supportingItems().length > 0) {\n <div\n class=\"sui-sidebar__section sui-sidebar__section--supporting\"\n [class.sui-sidebar__section--anchor-bottom]=\"supportingAnchorBottom()\"\n >\n @if (supportingItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ supportingItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of supportingItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Feature Card slot (Figma FeatureCard=On) \u2014 promo opcional, oculto en collapsed -->\n @if (!collapsed()) {\n <div class=\"sui-sidebar__feature-card\">\n <ng-content select=\"[feature-card]\"></ng-content>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Footer (profile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 @if (profile(); as p) {\n <footer class=\"sui-sidebar__footer\">\n <div class=\"sui-sidebar__divider sui-sidebar__divider--top\" role=\"separator\"></div>\n <div class=\"sui-sidebar__profile\">\n <sui-avatar\n size=\"lg\"\n [src]=\"p.avatarUrl ?? null\"\n [alt]=\"p.name\"\n [initials]=\"p.initials ?? ''\"\n [status]=\"p.status ?? null\"\n color=\"slate\"\n />\n @if (!collapsed()) {\n <div class=\"sui-sidebar__profile-info\">\n <div class=\"sui-sidebar__profile-name-row\">\n <span class=\"sui-sidebar__profile-name\">{{ p.name }}</span>\n @if (p.verified) {\n <!-- Figma usa verified-fill (glyph propio SUI); el match m\u00E1s\n cercano en RemixIcon es verified-badge-fill. -->\n <sui-icon\n class=\"sui-sidebar__profile-verified\"\n name=\"verified-badge-fill\"\n [size]=\"20\"\n aria-label=\"Verificado\"\n />\n }\n </div>\n @if (p.email) {\n <span class=\"sui-sidebar__profile-email\">{{ p.email }}</span>\n }\n </div>\n @if (profileDropdown()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn sui-sidebar__compact-btn--ghost\"\n aria-label=\"Opciones de perfil\"\n (click)=\"onProfileButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"arrow-right-s-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n </footer>\n }\n</aside>\n\n<!-- \u2500\u2500 Item template (compartido entre todas las secciones) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #itemTpl let-item>\n @if (item.route && !item.action) {\n <a\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"sui-sidebar__item--active\"\n [attr.target]=\"item.external ? '_blank' : null\"\n [attr.rel]=\"item.external ? 'noopener noreferrer' : null\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--active]=\"isItemActive(item)\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </button>\n }\n</ng-template>\n\n<ng-template #itemBody let-item>\n @if (item.colorDot) {\n <span\n class=\"sui-sidebar__item-dot\"\n [style.background-color]=\"item.colorDot\"\n aria-hidden=\"true\"\n ></span>\n } @else if (item.icon) {\n <sui-icon class=\"sui-sidebar__item-icon\" [name]=\"item.icon\" [size]=\"20\" />\n }\n @if (!collapsed()) {\n <span class=\"sui-sidebar__item-label\">{{ item.label }}</span>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <sui-badge\n class=\"sui-sidebar__item-badge\"\n variant=\"filled\"\n [color]=\"item.variant === 'danger' ? 'red' : 'orange'\"\n size=\"small\"\n type=\"number\"\n >{{ item.badge }}</sui-badge>\n }\n @if (item.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ item.shortcut }}</span>\n }\n <!-- Chevron del item activo (Figma): visibilidad controlada por CSS via\n .sui-sidebar__item--active (cubre tanto isItemActive como RouterLinkActive). -->\n <sui-icon class=\"sui-sidebar__item-chevron\" name=\"arrow-right-s-line\" [size]=\"20\" />\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:contents;font-family:var(--font-sans, \"Satoshi\", system-ui, sans-serif)}.sui-sidebar-backdrop{position:fixed;inset:0;z-index:299;background:#0006;animation:sui-sidebar-fade-in .2s ease-out}.sui-sidebar{display:flex;flex-direction:column;flex-shrink:0;width:240px;height:100dvh;background:var(--sui-bg-white-0, #ffffff);border-right:1px solid var(--sui-stroke-soft-200, #ebebeb);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-sidebar__header{position:relative;padding:12px;padding-top:calc(12px + env(safe-area-inset-top,0px))}.sui-sidebar__header-card{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);background:var(--sui-bg-white-0, #ffffff);overflow:hidden}.sui-sidebar__brand-logo{flex-shrink:0;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c);overflow:hidden}.sui-sidebar__brand-logo img{width:100%;height:100%;object-fit:cover;display:block}.sui-sidebar__brand-fallback{font-size:18px;line-height:1}.sui-sidebar__compact-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1px;border-radius:var(--sui-radius-6, 6px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));color:var(--sui-text-sub-600, #5c5c5c);cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__compact-btn:hover{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__compact-btn:focus-visible{outline:2px solid var(--sui-state-information-base, #335cff);outline-offset:-1px}.sui-sidebar__compact-btn:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__compact-btn--ghost{border-color:transparent;box-shadow:none;background:transparent}.sui-sidebar__header-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;align-items:flex-start}.sui-sidebar__header-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__header-subtitle{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__divider{position:absolute;bottom:0;left:20px;right:20px;height:1px;background:var(--sui-stroke-soft-200, #ebebeb)}.sui-sidebar__divider--top{top:0;bottom:auto}.sui-sidebar__content{flex:1;display:flex;flex-direction:column;gap:20px;padding:20px 20px 16px;overflow-y:auto;min-height:0}.sui-sidebar__section{display:flex;flex-direction:column;gap:8px;flex-shrink:0}.sui-sidebar__section--secondary,.sui-sidebar__section--supporting{gap:6px}.sui-sidebar__section--anchor-bottom{margin-top:auto}.sui-sidebar__section-label{padding:4px;font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__section-label--collapsed{padding:4px 0;text-align:center}.sui-sidebar__search{display:flex;align-items:center;gap:8px;width:100%;padding:8px 8px 8px 10px;border-radius:var(--sui-radius-8, 8px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));box-sizing:border-box}.sui-sidebar__search-icon{flex-shrink:0;display:inline-flex;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__search-input{flex:1;min-width:0;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;font-weight:400;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717)}.sui-sidebar__search-input::placeholder{color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__shortcut{flex-shrink:0;display:inline-flex;align-items:center;box-sizing:border-box;padding:2px 6px;border-radius:var(--sui-radius-4, 4px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3);white-space:nowrap}.sui-sidebar__nav{display:flex;flex-direction:column;gap:4px}.sui-sidebar__item{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:var(--sui-radius-8, 8px);width:100%;background:transparent;border:none;font-family:inherit;text-align:left;text-decoration:none;color:inherit;cursor:pointer;position:relative;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__item:hover{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item:hover .sui-sidebar__item-label,.sui-sidebar__item:hover .sui-sidebar__item-icon{color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__item:focus-visible{outline:2px solid var(--_sui-sidebar-indicator, var(--sui-primary-base, #fa7319));outline-offset:-2px}.sui-sidebar__item:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--sui-text-sub-600, #5c5c5c);transition:color .12s ease-out}.sui-sidebar__item-label{flex:1;font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .12s ease-out}.sui-sidebar__item-badge{flex-shrink:0}.sui-sidebar__item-dot{flex-shrink:0;width:8px;height:8px;margin:6px;border-radius:999px}.sui-sidebar__item-chevron{flex-shrink:0;display:none;color:var(--sui-text-sub-600, #5c5c5c)}:host{--_sui-sidebar-indicator: var(--sui-primary-base, #fa7319)}:host([data-sui-indicator=information]){--_sui-sidebar-indicator: var(--sui-state-information-base, #335cff)}.sui-sidebar__item--active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item--active .sui-sidebar__item-label{color:var(--sui-text-strong-950, #171717)}.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--_sui-sidebar-indicator)}.sui-sidebar__item--active .sui-sidebar__item-chevron{display:inline-flex;color:var(--sui-text-sub-600, #5c5c5c)}.sui-sidebar__item--active:before{content:\"\";position:absolute;left:-20px;top:50%;transform:translateY(-50%);width:4px;height:20px;background:var(--_sui-sidebar-indicator);border-radius:0 4px 4px 0}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--active:hover{background:var(--sui-bg-weak-50, #f7f7f7)}}.sui-sidebar__item--danger .sui-sidebar__item-icon,.sui-sidebar__item--danger .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--danger:hover{background:var(--sui-red-alpha-10, rgba(251, 55, 72, .0980392157))}.sui-sidebar__item--danger:hover .sui-sidebar__item-icon,.sui-sidebar__item--danger:hover .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}}.sui-sidebar__item--danger:active{background:var(--sui-red-alpha-16, rgba(251, 55, 72, .1607843137))}.sui-sidebar__footer{position:relative;padding:12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.sui-sidebar__profile{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);overflow:hidden}.sui-sidebar__profile-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;height:40px;justify-content:center}.sui-sidebar__profile-name-row{display:flex;align-items:center;gap:2px;min-width:0}.sui-sidebar__profile-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__profile-verified{flex-shrink:0;display:inline-flex;color:var(--sui-state-verified-base, #47c2ff)}.sui-sidebar__profile-email{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__feature-card{width:100%}.sui-sidebar__feature-card:not(:has(*)){display:none}:host([data-sui-collapsed]) .sui-sidebar{width:80px}:host([data-sui-collapsed]) .sui-sidebar__header-card,:host([data-sui-collapsed]) .sui-sidebar__profile{justify-content:center}:host([data-sui-collapsed]) .sui-sidebar__content{padding-inline:12px}:host([data-sui-collapsed]) .sui-sidebar__item{justify-content:center;padding:8px}:host([data-sui-collapsed]) .sui-sidebar__item--active:before{left:-12px}@media(max-width:767px){.sui-sidebar{position:fixed;top:0;left:0;bottom:0;height:100dvh;z-index:300;width:min(86vw,360px);transform:translate(-100%);transition:transform .25s cubic-bezier(.23,1,.32,1);border-right:none;border-radius:0 24px 24px 0;overflow:hidden;box-shadow:4px 0 24px #0e121b00}.sui-sidebar--open{transform:translate(0);box-shadow:4px 0 24px #0e121b1a}:host([data-sui-mobile-mode=sheet]) .sui-sidebar{width:calc(100vw - 40px);max-width:none}.sui-sidebar__item{gap:14px;padding:14px 12px;border-radius:var(--sui-radius-10, 10px);transition:transform .16s cubic-bezier(.23,1,.32,1),background-color .16s cubic-bezier(.23,1,.32,1)}.sui-sidebar__item:active{transform:scale(.98);background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{width:24px;height:24px}.sui-sidebar__item-label{font-size:17px;line-height:24px;letter-spacing:-.01em}.sui-sidebar__item--active{background:var(--sui-orange-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-sidebar__item--active .sui-sidebar__item-label,.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--sui-primary-base, #fa7319)}.sui-sidebar__item--active:before{display:none}}@keyframes sui-sidebar-fade-in{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
14455
|
+
}, template: "@if (showBackdrop() && open()) {\n <div class=\"sui-sidebar-backdrop\" (click)=\"onBackdropClick()\" aria-hidden=\"true\"></div>\n}\n\n<aside\n class=\"sui-sidebar\"\n [class.sui-sidebar--open]=\"open()\"\n [class.sui-sidebar--collapsed]=\"collapsed()\"\n role=\"navigation\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n>\n <!-- \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n <header class=\"sui-sidebar__header\">\n <div class=\"sui-sidebar__header-card\">\n <div class=\"sui-sidebar__brand-logo\">\n @if (brandCfg().logo) {\n <img [src]=\"brandCfg().logo\" [alt]=\"brandCfg().name\" referrerpolicy=\"no-referrer\" />\n } @else if (brandCfg().fallback) {\n <span class=\"sui-sidebar__brand-fallback\">{{ brandCfg().fallback }}</span>\n } @else {\n <sui-icon name=\"building-line\" [size]=\"20\" />\n }\n </div>\n @if (!collapsed()) {\n <div class=\"sui-sidebar__header-info\">\n <span class=\"sui-sidebar__header-name\">{{ brandCfg().name }}</span>\n @if (brandCfg().subtitle) {\n @if (brandCfg().subtitleAsBadge) {\n <sui-badge variant=\"filled\" color=\"orange\" size=\"small\">{{ brandCfg().subtitle }}</sui-badge>\n } @else {\n <span class=\"sui-sidebar__header-subtitle\">{{ brandCfg().subtitle }}</span>\n }\n }\n </div>\n @if (showHeaderButton()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn\"\n aria-label=\"Cambiar workspace\"\n (click)=\"onHeaderButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"expand-up-down-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n <div class=\"sui-sidebar__divider\" role=\"separator\"></div>\n </header>\n\n <!-- \u2500\u2500 Content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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=\"sui-sidebar__content\">\n <!-- Search slot (Figma prop search=true) -->\n @if (!collapsed() && searchCfg(); as s) {\n <div class=\"sui-sidebar__search\">\n <sui-icon class=\"sui-sidebar__search-icon\" name=\"search-2-line\" [size]=\"20\" />\n <input\n class=\"sui-sidebar__search-input\"\n type=\"text\"\n [placeholder]=\"s.placeholder\"\n [value]=\"searchValue()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown.enter)=\"onSearchSubmit()\"\n />\n @if (s.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ s.shortcut }}</span>\n }\n </div>\n }\n\n @if (items().length > 0) {\n <div class=\"sui-sidebar__section\">\n @if (itemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ itemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of items(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n @if (secondaryItems().length > 0) {\n <div class=\"sui-sidebar__section sui-sidebar__section--secondary\">\n @if (secondaryItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ secondaryItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of secondaryItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Supporting Content (Figma supContent) \u2014 ancla al fondo cuando aplica -->\n @if (supportingItems().length > 0) {\n <div\n class=\"sui-sidebar__section sui-sidebar__section--supporting\"\n [class.sui-sidebar__section--anchor-bottom]=\"supportingAnchorBottom()\"\n >\n @if (supportingItemsLabel()) {\n <div class=\"sui-sidebar__section-label\" [class.sui-sidebar__section-label--collapsed]=\"collapsed()\">{{ supportingItemsLabel() }}</div>\n }\n <nav class=\"sui-sidebar__nav\">\n @for (item of supportingItems(); track item.value) {\n <ng-container *ngTemplateOutlet=\"itemTpl; context: { $implicit: item }\"></ng-container>\n }\n </nav>\n </div>\n }\n\n <!-- Feature Card slot (Figma FeatureCard=On) \u2014 promo opcional, oculto en collapsed -->\n @if (!collapsed()) {\n <div class=\"sui-sidebar__feature-card\">\n <ng-content select=\"[feature-card]\"></ng-content>\n </div>\n }\n </div>\n\n <!-- \u2500\u2500 Footer (profile) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 @if (profile(); as p) {\n <footer class=\"sui-sidebar__footer\">\n <div class=\"sui-sidebar__divider sui-sidebar__divider--top\" role=\"separator\"></div>\n <div class=\"sui-sidebar__profile\">\n <sui-avatar\n size=\"lg\"\n [src]=\"p.avatarUrl ?? null\"\n [alt]=\"p.name\"\n [initials]=\"p.initials ?? ''\"\n [status]=\"p.status ?? null\"\n color=\"slate\"\n />\n @if (!collapsed()) {\n <div class=\"sui-sidebar__profile-info\">\n <div class=\"sui-sidebar__profile-name-row\">\n <span class=\"sui-sidebar__profile-name\">{{ p.name }}</span>\n @if (p.verified) {\n <!-- Figma usa verified-fill (glyph propio SUI); el match m\u00E1s\n cercano en RemixIcon es verified-badge-fill. -->\n <sui-icon\n class=\"sui-sidebar__profile-verified\"\n name=\"verified-badge-fill\"\n [size]=\"20\"\n aria-label=\"Verificado\"\n />\n }\n </div>\n @if (p.email) {\n <span class=\"sui-sidebar__profile-email\">{{ p.email }}</span>\n }\n </div>\n @if (profileDropdown()) {\n <button\n type=\"button\"\n class=\"sui-sidebar__compact-btn sui-sidebar__compact-btn--ghost\"\n aria-label=\"Opciones de perfil\"\n (click)=\"onProfileButtonClick($event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <sui-icon name=\"arrow-right-s-line\" [size]=\"20\" />\n </button>\n }\n }\n </div>\n </footer>\n }\n</aside>\n\n<!-- \u2500\u2500 Item template (compartido entre todas las secciones) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #itemTpl let-item>\n @if (item.route && !item.action) {\n <a\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [routerLink]=\"item.route\"\n routerLinkActive=\"sui-sidebar__item--active\"\n [attr.target]=\"item.external ? '_blank' : null\"\n [attr.rel]=\"item.external ? 'noopener noreferrer' : null\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </a>\n } @else {\n <button\n type=\"button\"\n class=\"sui-sidebar__item\"\n [class.sui-sidebar__item--active]=\"isItemActive(item)\"\n [class.sui-sidebar__item--danger]=\"item.variant === 'danger'\"\n [attr.title]=\"collapsed() ? (item.tooltip ?? item.label) : null\"\n [attr.aria-label]=\"collapsed() ? item.label : null\"\n (click)=\"onItemClick(item, $event)\"\n (touchstart)=\"$event.currentTarget\"\n (touchend)=\"$any($event.currentTarget).blur()\"\n >\n <ng-container *ngTemplateOutlet=\"itemBody; context: { $implicit: item }\"></ng-container>\n </button>\n }\n</ng-template>\n\n<ng-template #itemBody let-item>\n @if (item.colorDot) {\n <span\n class=\"sui-sidebar__item-dot\"\n [style.background-color]=\"item.colorDot\"\n aria-hidden=\"true\"\n ></span>\n } @else if (item.icon) {\n <sui-icon class=\"sui-sidebar__item-icon\" [name]=\"item.icon\" [size]=\"20\" />\n }\n @if (!collapsed()) {\n <span class=\"sui-sidebar__item-label\">{{ item.label }}</span>\n @if (item.badge !== undefined && item.badge !== null && item.badge !== '') {\n <sui-badge\n class=\"sui-sidebar__item-badge\"\n variant=\"filled\"\n [color]=\"item.variant === 'danger' ? 'red' : 'orange'\"\n size=\"small\"\n type=\"number\"\n >{{ item.badge }}</sui-badge>\n }\n @if (item.shortcut) {\n <span class=\"sui-sidebar__shortcut\">{{ item.shortcut }}</span>\n }\n <!-- Chevron del item activo (Figma): visibilidad controlada por CSS via\n .sui-sidebar__item--active (cubre tanto isItemActive como RouterLinkActive). -->\n <sui-icon class=\"sui-sidebar__item-chevron\" name=\"arrow-right-s-line\" [size]=\"20\" />\n }\n</ng-template>\n", styles: ["@charset \"UTF-8\";:host{display:contents;font-family:var(--font-sans, \"Satoshi\", system-ui, sans-serif)}.sui-sidebar-backdrop{position:fixed;inset:0;z-index:299;background:#0006;animation:sui-sidebar-fade-in .2s ease-out}.sui-sidebar{display:flex;flex-direction:column;flex-shrink:0;width:272px;height:100dvh;background:var(--sui-bg-white-0, #ffffff);border-right:1px solid var(--sui-stroke-soft-200, #ebebeb);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-sidebar__header{position:relative;padding:12px;padding-top:calc(12px + env(safe-area-inset-top,0px))}.sui-sidebar__header-card{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);background:var(--sui-bg-white-0, #ffffff);overflow:hidden}.sui-sidebar__brand-logo{flex-shrink:0;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:999px;background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c);overflow:hidden}.sui-sidebar__brand-logo img{width:100%;height:100%;object-fit:cover;display:block}.sui-sidebar__brand-fallback{font-size:18px;line-height:1}.sui-sidebar__compact-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;padding:1px;border-radius:var(--sui-radius-6, 6px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));color:var(--sui-text-sub-600, #5c5c5c);cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__compact-btn:hover{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__compact-btn:focus-visible{outline:2px solid var(--sui-state-information-base, #335cff);outline-offset:-1px}.sui-sidebar__compact-btn:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__compact-btn--ghost{border-color:transparent;box-shadow:none;background:transparent}.sui-sidebar__header-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;align-items:flex-start}.sui-sidebar__header-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__header-subtitle{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.sui-sidebar__divider{position:absolute;bottom:0;left:20px;right:20px;height:1px;background:var(--sui-stroke-soft-200, #ebebeb)}.sui-sidebar__divider--top{top:0;bottom:auto}.sui-sidebar__content{flex:1;display:flex;flex-direction:column;gap:20px;padding:20px 20px 16px;overflow-y:auto;overflow-x:hidden;min-height:0}.sui-sidebar__section{display:flex;flex-direction:column;gap:8px;flex-shrink:0}.sui-sidebar__section--secondary,.sui-sidebar__section--supporting{gap:6px}.sui-sidebar__section--anchor-bottom{margin-top:auto}.sui-sidebar__section-label{padding:4px;font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__section-label--collapsed{padding:4px 0;text-align:center}.sui-sidebar__search{display:flex;align-items:center;gap:8px;width:100%;padding:8px 8px 8px 10px;border-radius:var(--sui-radius-8, 8px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);box-shadow:var(--sui-regular-shadow-x-small, 0 1px 2px 0 rgba(10, 13, 20, .031372549));box-sizing:border-box}.sui-sidebar__search-icon{flex-shrink:0;display:inline-flex;color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__search-input{flex:1;min-width:0;border:none;outline:none;background:transparent;font-family:inherit;font-size:14px;font-weight:400;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717)}.sui-sidebar__search-input::placeholder{color:var(--sui-text-soft-400, #a3a3a3)}.sui-sidebar__shortcut{flex-shrink:0;display:inline-flex;align-items:center;box-sizing:border-box;padding:2px 6px;border-radius:var(--sui-radius-4, 4px);border:1px solid var(--sui-stroke-soft-200, #ebebeb);font-size:12px;font-weight:500;line-height:16px;letter-spacing:.04em;text-transform:uppercase;color:var(--sui-text-soft-400, #a3a3a3);white-space:nowrap}.sui-sidebar__nav{display:flex;flex-direction:column;gap:4px}.sui-sidebar__item{display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:var(--sui-radius-8, 8px);width:100%;background:transparent;border:none;font-family:inherit;text-align:left;text-decoration:none;color:inherit;cursor:pointer;position:relative;transition:background-color .12s ease-out,color .12s ease-out}@media(hover:hover)and (pointer:fine){.sui-sidebar__item:hover{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item:hover .sui-sidebar__item-label,.sui-sidebar__item:hover .sui-sidebar__item-icon{color:var(--sui-text-strong-950, #171717)}}.sui-sidebar__item:focus-visible{outline:2px solid var(--_sui-sidebar-indicator, var(--sui-primary-base, #fa7319));outline-offset:-2px}.sui-sidebar__item:active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--sui-text-sub-600, #5c5c5c);transition:color .12s ease-out}.sui-sidebar__item-label{flex:1;font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .12s ease-out}.sui-sidebar__item-badge{flex-shrink:0}.sui-sidebar__item-dot{flex-shrink:0;width:8px;height:8px;margin:6px;border-radius:999px}.sui-sidebar__item-chevron{flex-shrink:0;display:none;color:var(--sui-text-sub-600, #5c5c5c)}:host{--_sui-sidebar-indicator: var(--sui-primary-base, #fa7319)}:host([data-sui-indicator=information]){--_sui-sidebar-indicator: var(--sui-state-information-base, #335cff)}.sui-sidebar__item--active{background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item--active .sui-sidebar__item-label{color:var(--sui-text-strong-950, #171717)}.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--_sui-sidebar-indicator)}.sui-sidebar__item--active .sui-sidebar__item-chevron{display:inline-flex;color:var(--sui-text-sub-600, #5c5c5c)}.sui-sidebar__item--active:before{content:\"\";position:absolute;left:-20px;top:50%;transform:translateY(-50%);width:4px;height:20px;background:var(--_sui-sidebar-indicator);border-radius:0 4px 4px 0}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--active:hover{background:var(--sui-bg-weak-50, #f7f7f7)}}.sui-sidebar__item--danger .sui-sidebar__item-icon,.sui-sidebar__item--danger .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}@media(hover:hover)and (pointer:fine){.sui-sidebar__item--danger:hover{background:var(--sui-red-alpha-10, rgba(251, 55, 72, .0980392157))}.sui-sidebar__item--danger:hover .sui-sidebar__item-icon,.sui-sidebar__item--danger:hover .sui-sidebar__item-label{color:var(--sui-state-error-base, #fb3748)}}.sui-sidebar__item--danger:active{background:var(--sui-red-alpha-16, rgba(251, 55, 72, .1607843137))}.sui-sidebar__footer{position:relative;padding:12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.sui-sidebar__profile{display:flex;align-items:center;gap:12px;padding:12px;border-radius:var(--sui-radius-10, 10px);overflow:hidden}.sui-sidebar__profile-info{flex:1;display:flex;flex-direction:column;gap:4px;min-width:0;height:40px;justify-content:center}.sui-sidebar__profile-name-row{display:flex;align-items:center;gap:2px;min-width:0}.sui-sidebar__profile-name{font-size:14px;font-weight:500;line-height:20px;letter-spacing:-.006em;color:var(--sui-text-strong-950, #171717);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__profile-verified{flex-shrink:0;display:inline-flex;color:var(--sui-state-verified-base, #47c2ff)}.sui-sidebar__profile-email{font-size:12px;font-weight:400;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sui-sidebar__feature-card{width:100%}.sui-sidebar__feature-card:not(:has(*)){display:none}:host([data-sui-collapsed]) .sui-sidebar{width:80px}:host([data-sui-collapsed]) .sui-sidebar__header-card,:host([data-sui-collapsed]) .sui-sidebar__profile{justify-content:center}:host([data-sui-collapsed]) .sui-sidebar__content{padding-inline:12px}:host([data-sui-collapsed]) .sui-sidebar__item{justify-content:center;padding:8px}:host([data-sui-collapsed]) .sui-sidebar__item--active:before{left:-12px}@media(max-width:767px){.sui-sidebar{position:fixed;top:0;left:0;bottom:0;height:100dvh;z-index:300;width:min(86vw,360px);transform:translate(-100%);transition:transform .25s cubic-bezier(.23,1,.32,1);border-right:none;border-radius:0 24px 24px 0;overflow:hidden;box-shadow:4px 0 24px #0e121b00}.sui-sidebar--open{transform:translate(0);box-shadow:4px 0 24px #0e121b1a}:host([data-sui-mobile-mode=sheet]) .sui-sidebar{width:calc(100vw - 40px);max-width:none}.sui-sidebar__item{gap:14px;padding:14px 12px;border-radius:var(--sui-radius-10, 10px);transition:transform .16s cubic-bezier(.23,1,.32,1),background-color .16s cubic-bezier(.23,1,.32,1)}.sui-sidebar__item:active{transform:scale(.98);background:var(--sui-bg-weak-50, #f7f7f7)}.sui-sidebar__item-icon{width:24px;height:24px}.sui-sidebar__item-label{font-size:17px;line-height:24px;letter-spacing:-.01em}.sui-sidebar__item--active{background:var(--sui-orange-alpha-10, rgba(250, 115, 25, .1019607843))}.sui-sidebar__item--active .sui-sidebar__item-label,.sui-sidebar__item--active .sui-sidebar__item-icon{color:var(--sui-primary-base, #fa7319)}.sui-sidebar__item--active:before{display:none}}@keyframes sui-sidebar-fade-in{0%{opacity:0}to{opacity:1}}\n"] }]
|
|
13911
14456
|
}], propDecorators: { collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], indicatorColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "indicatorColor", required: false }] }], brand: [{ type: i0.Input, args: [{ isSignal: true, alias: "brand", required: false }] }], showHeaderButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeaderButton", required: false }] }], search: [{ type: i0.Input, args: [{ isSignal: true, alias: "search", required: false }] }], searchValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchValue", required: false }] }, { type: i0.Output, args: ["searchValueChange"] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], secondaryItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryItems", required: false }] }], supportingItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "supportingItems", required: false }] }], supportingAnchorBottom: [{ type: i0.Input, args: [{ isSignal: true, alias: "supportingAnchorBottom", required: false }] }], itemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemsLabel", required: false }] }], secondaryItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryItemsLabel", required: false }] }], supportingItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "supportingItemsLabel", required: false }] }], activeRoute: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeRoute", required: false }] }], profile: [{ type: i0.Input, args: [{ isSignal: true, alias: "profile", required: false }] }], profileDropdown: [{ type: i0.Input, args: [{ isSignal: true, alias: "profileDropdown", required: false }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], closeOnNavigate: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnNavigate", required: false }] }], showBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBackdrop", required: false }] }], mobileMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mobileMode", required: false }] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], logoutClicked: [{ type: i0.Output, args: ["logoutClicked"] }], backdropClicked: [{ type: i0.Output, args: ["backdropClicked"] }], headerButtonClicked: [{ type: i0.Output, args: ["headerButtonClicked"] }], profileClicked: [{ type: i0.Output, args: ["profileClicked"] }], searchSubmitted: [{ type: i0.Output, args: ["searchSubmitted"] }] } });
|
|
13912
14457
|
|
|
13913
14458
|
class SuiSlider {
|
|
@@ -17786,5 +18331,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
17786
18331
|
* Generated bundle index. Do not edit.
|
|
17787
18332
|
*/
|
|
17788
18333
|
|
|
17789
|
-
export { DAY_LABELS_ES, DEFAULT_DURATION_PRESETS, DEFAULT_PRESETS, EMPTY_STATE_FOX_EMOJI, SUI_BRAND_LOGO_COMPANIES, SUI_COLOR_DOT_COLORS, SUI_COLOR_DOT_HEX, SUI_CUSTOM_ICONS, SUI_EMOJI_MAP, SUI_FLAG_NAMES, SUI_HEX_TO_COLOR, SUI_KEY_ICON_COLORS, SUI_KEY_ICON_SIZES, SUI_NAVBAR_VISIBILITY, SUI_PRODUCT_FALLBACK_COLORS, SUI_TAB_BAR, SuiAccordion, SuiAccordionContent, SuiActivityFeed, SuiActivityFilter, SuiAlert, SuiAppStoreBadge, SuiAvatar, SuiAvatarGroup, SuiBadge, SuiBanner, SuiBrandLogo, SuiBreadcrumbItem, SuiBreadcrumbs, SuiButton, SuiButtonGroup, SuiButtonGroupItem, SuiCard, SuiCheckbox, SuiCheckboxCard, SuiCheckboxLabel, SuiCircularProgressBar, SuiColorDot, SuiColorPicker, SuiCommandMenuFooter, SuiCommandMenuItem, SuiCommandMenuSearch, SuiCompactAvatarGroup, SuiCompactButton, SuiCompactSelect, SuiCompactSelectForInput, SuiContentCard, SuiContentDivider, SuiCounterInput, SuiDateSelector, SuiDatepicker, SuiDayCell, SuiDayLabel, SuiDivider, SuiDrawerFooter, SuiDrawerHeader, SuiDropdownCaption, SuiDropdownItem, SuiDropdownMenu, SuiDropdownPanel, SuiDropdownSearch, SuiEmoji, SuiEmptyState, SuiFancyButton, SuiFileIcon, SuiFileUpload, SuiFileUploadCard, SuiFilterBar, SuiFilterItem, SuiFilterPanelFooter, SuiFilterPanelHeader, SuiFlag, SuiFormHint, SuiFormLabel, SuiIcon, SuiImageUpload, SuiImageUploadProfile, SuiImgRetry, SuiInlineInput, SuiInlineSelect, SuiInput, SuiIntegrationSwitch, SuiKbd, SuiKeyIcon, SuiLinkButton, SuiModal, SuiModalFooter, SuiModalHeader, SuiModalSheet, SuiNotification, SuiNotificationFooter, SuiNotificationTabMenu, SuiOtpInput, SuiPageHeader, SuiPagination, SuiPeriodRange, SuiPopover, SuiProductCard, SuiProgressBar, SuiProgressBarLabel, SuiRadio, SuiRadioCard, SuiRadioGroup, SuiRadioLabel, SuiRating, SuiRichEditor, SuiRichEditorItem, SuiSegmentedControl, SuiSelect, SuiSidebar, SuiSlider, SuiSocialButton, SuiStatusBadge, SuiStepper, SuiStoreCard, SuiSwitch, SuiSwitchCard, SuiSwitchLabel, SuiTabChips, SuiTabMenuHorizontal, SuiTabMenuVertical, SuiTable, SuiTableCellDirective, SuiTag, SuiTagInput, SuiTextarea, SuiTimePicker, SuiTimePickerDuration, SuiTimePickerItem, SuiTimePickerStatus, SuiToastOutlet, SuiToastService, SuiTooltip, SuiTooltipPanel, buildCalendarGrid, buildHourList, buildMinuteList, formatDateInput, formatDateShort, formatMonthYear, formatTime, isSameTime, normalizeHex, pad2, parseTime, to12h, to24h };
|
|
18334
|
+
export { DAY_LABELS_ES, DEFAULT_DURATION_PRESETS, DEFAULT_PRESETS, EMPTY_STATE_FOX_EMOJI, SUI_BRAND_LOGO_COMPANIES, SUI_CHART_LEGEND_COLORS, SUI_CHART_LEGEND_HEX, SUI_CHART_SERIES_COLORS, SUI_COLOR_DOT_COLORS, SUI_COLOR_DOT_HEX, SUI_CUSTOM_ICONS, SUI_EMOJI_MAP, SUI_FLAG_NAMES, SUI_HEX_TO_COLOR, SUI_KEY_ICON_COLORS, SUI_KEY_ICON_SIZES, SUI_NAVBAR_VISIBILITY, SUI_PASSWORD_STRENGTH_DEFAULT_CONDITIONS, SUI_PASSWORD_STRENGTH_DEFAULT_LEVEL_LABELS, SUI_PAYMENT_ICON_TYPES, SUI_PRODUCT_FALLBACK_COLORS, SUI_TAB_BAR, SuiAccordion, SuiAccordionContent, SuiActivityFeed, SuiActivityFilter, SuiAlert, SuiAppStoreBadge, SuiAvatar, SuiAvatarGroup, SuiBadge, SuiBanner, SuiBrandLogo, SuiBreadcrumbItem, SuiBreadcrumbs, SuiButton, SuiButtonGroup, SuiButtonGroupItem, SuiCard, SuiChartLegend, SuiChartLegendDot, SuiCheckbox, SuiCheckboxCard, SuiCheckboxLabel, SuiCircularProgressBar, SuiColorDot, SuiColorPicker, SuiCommandMenuFooter, SuiCommandMenuItem, SuiCommandMenuSearch, SuiCompactAvatarGroup, SuiCompactButton, SuiCompactSelect, SuiCompactSelectForInput, SuiContentCard, SuiContentDivider, SuiContentLabel, SuiCounterInput, SuiDateSelector, SuiDatepicker, SuiDayCell, SuiDayLabel, SuiDivider, SuiDrawerFooter, SuiDrawerHeader, SuiDropdownCaption, SuiDropdownItem, SuiDropdownMenu, SuiDropdownPanel, SuiDropdownSearch, SuiEmoji, SuiEmptyState, SuiFancyButton, SuiFileIcon, SuiFileUpload, SuiFileUploadCard, SuiFilterBar, SuiFilterItem, SuiFilterPanelFooter, SuiFilterPanelHeader, SuiFlag, SuiFormHint, SuiFormLabel, SuiIcon, SuiImageUpload, SuiImageUploadProfile, SuiImgRetry, SuiInlineInput, SuiInlineSelect, SuiInput, SuiIntegrationSwitch, SuiKbd, SuiKeyIcon, SuiLinkButton, SuiModal, SuiModalFooter, SuiModalHeader, SuiModalSheet, SuiNotification, SuiNotificationFooter, SuiNotificationTabMenu, SuiOtpInput, SuiPageHeader, SuiPagination, SuiPasswordStrength, SuiPaymentIcon, SuiPeriodRange, SuiPopover, SuiProductCard, SuiProgressBar, SuiProgressBarLabel, SuiRadio, SuiRadioCard, SuiRadioGroup, SuiRadioLabel, SuiRating, SuiRichEditor, SuiRichEditorItem, SuiSegmentedControl, SuiSelect, SuiSidebar, SuiSlider, SuiSocialButton, SuiStatusBadge, SuiStepper, SuiStoreCard, SuiSwitch, SuiSwitchCard, SuiSwitchLabel, SuiTabChips, SuiTabMenuHorizontal, SuiTabMenuVertical, SuiTable, SuiTableCellDirective, SuiTag, SuiTagInput, SuiTextarea, SuiTimePicker, SuiTimePickerDuration, SuiTimePickerItem, SuiTimePickerStatus, SuiToastOutlet, SuiToastService, SuiTooltip, SuiTooltipPanel, buildCalendarGrid, buildHourList, buildMinuteList, formatDateInput, formatDateShort, formatMonthYear, formatTime, isSameTime, normalizeHex, pad2, parseTime, to12h, to24h };
|
|
17790
18335
|
//# sourceMappingURL=ajuarezso-sui-design-system.mjs.map
|