@ajuarezso/sui-design-system 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10623,6 +10623,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10623
10623
  args: ['body']
10624
10624
  }] } });
10625
10625
 
10626
+ const VARIANT_ICON = {
10627
+ info: 'information-fill',
10628
+ success: 'checkbox-circle-fill',
10629
+ warning: 'alert-fill',
10630
+ error: 'error-warning-fill',
10631
+ };
10632
+ /**
10633
+ * SUI Modal Header — SUI Design System 2.0
10634
+ *
10635
+ * Figma file: 8p1k72aKKvzJV4XcvPS4VO
10636
+ * Component set: 466:4778 ("Modal Header [1.1]") — 6 Types × 2 Sizes
10637
+ * Types: Basic · Left Icon · Error · Warning · Success · Information
10638
+ * Sizes: Medium (min-height 80, title + description) ·
10639
+ * Small (min-height 56, título; icono FLAT 24 sin círculo)
10640
+ *
10641
+ * Es la ÚNICA fuente de verdad de la anatomía del header de modal: sui-modal
10642
+ * lo renderiza internamente y también se usa standalone para componer paneles
10643
+ * custom (par de sui-modal-footer).
10644
+ *
10645
+ * EXACT (Figma 466:4777 medium / 472:298 small — homologado con sui-modal):
10646
+ * Container flex align-center · padding 16px 56px 16px 20px (pr 56 reserva
10647
+ * el close absolute) · border-bottom stroke-soft-200 · bg white-0
10648
+ * · min-height 80 (small: 56) · gap 16 (small: 12; con icono: 14
10649
+ * en ambos sizes — cascade fix nodo "with-icon")
10650
+ * Title Label/Small (14/500/20/−0.006em), strong-950
10651
+ * Description Paragraph/X-Small (12/400/16), sub-600, margen-top 4
10652
+ * Status icon medium: círculo padding-10 radius-full state lighter/base,
10653
+ * icono 20 · small: flat 24 sin círculo (Figma "Small")
10654
+ * Close sui-compact-button ghost large, absolute top 16 right 16
10655
+ *
10656
+ * Tipos: `iconVariant` (semántico) o `icon` (custom, type Left Icon, círculo
10657
+ * neutral — prioridad). Ambos null → Basic.
10658
+ * `titleId`/`descriptionId` opcionales: ids para aria-labelledby/describedby
10659
+ * del dialog contenedor (los usa sui-modal).
10660
+ *
10661
+ * Usage:
10662
+ * <sui-modal-header title="Editar producto" description="Cambios en vivo."
10663
+ * iconVariant="info" (closed)="cerrar()" />
10664
+ * <sui-modal-header size="small" title="Filtros" (closed)="cerrar()" />
10665
+ */
10666
+ class SuiModalHeader {
10667
+ /** Título del header (Label/Small). */
10668
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
10669
+ /** Descripción bajo el título (Paragraph/X-Small). */
10670
+ description = input(null, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
10671
+ /** medium (80): título + descripción · small (56): título; icono flat 24. */
10672
+ size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
10673
+ /** Icono semántico de status (círculo state lighter/base en medium). */
10674
+ iconVariant = input(null, ...(ngDevMode ? [{ debugName: "iconVariant" }] : /* istanbul ignore next */ []));
10675
+ /** Icono custom (type "Left Icon" de Figma). Prioridad sobre iconVariant. */
10676
+ icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
10677
+ /** Muestra el botón de cerrar (default true). */
10678
+ showClose = input(true, ...(ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []));
10679
+ /** id del h2 del título — para aria-labelledby del dialog contenedor. */
10680
+ titleId = input(null, ...(ngDevMode ? [{ debugName: "titleId" }] : /* istanbul ignore next */ []));
10681
+ /** id del p de la descripción — para aria-describedby del dialog contenedor. */
10682
+ descriptionId = input(null, ...(ngDevMode ? [{ debugName: "descriptionId" }] : /* istanbul ignore next */ []));
10683
+ /** Click en el botón de cerrar. */
10684
+ closed = output();
10685
+ iconName = computed(() => {
10686
+ const custom = this.icon();
10687
+ if (custom)
10688
+ return custom;
10689
+ const v = this.iconVariant();
10690
+ return v ? VARIANT_ICON[v] : null;
10691
+ }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
10692
+ /** Variant efectivo para el data-attr del círculo (custom icon = neutral). */
10693
+ resolvedVariant = computed(() => {
10694
+ if (this.icon())
10695
+ return 'neutral';
10696
+ return this.iconVariant();
10697
+ }, ...(ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []));
10698
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
10699
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModalHeader, isStandalone: true, selector: "sui-modal-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, iconVariant: { classPropertyName: "iconVariant", publicName: "iconVariant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, titleId: { classPropertyName: "titleId", publicName: "titleId", isSignal: true, isRequired: false, transformFunction: null }, descriptionId: { classPropertyName: "descriptionId", publicName: "descriptionId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "attr.title": "null", "attr.data-sui-size": "size()", "attr.data-has-icon": "iconName() ? \"\" : null" } }, ngImport: i0, template: "@if (iconName(); as name) {\n <span class=\"sui-modal-header__icon\" [attr.data-variant]=\"resolvedVariant()\" aria-hidden=\"true\">\n <sui-icon [name]=\"name\" [size]=\"size() === 'small' ? 24 : 20\" />\n </span>\n}\n\n<div class=\"sui-modal-header__titles\">\n @if (title()) {\n <h2 class=\"sui-modal-header__title\" [attr.id]=\"titleId()\">{{ title() }}</h2>\n }\n @if (description(); as desc) {\n <p class=\"sui-modal-header__description\" [attr.id]=\"descriptionId()\">{{ desc }}</p>\n }\n</div>\n\n@if (showClose()) {\n <sui-compact-button\n class=\"sui-modal-header__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"closed.emit()\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;flex-shrink:0;gap:16px;padding:16px 56px 16px 20px;min-height:80px;background:var(--sui-bg-white-0, #fff);border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb);position:relative;overflow:hidden;box-sizing:border-box}:host([data-sui-size=small]){min-height:56px;gap:12px}:host([data-has-icon]){gap:14px}.sui-modal-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal-header__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal-header__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal-header__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal-header__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal-header__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f5f7fa);color:var(--sui-icon-sub-600, #5c5c5c)}:host([data-sui-size=small]) .sui-modal-header__icon{padding:0;background:transparent;align-self:center}.sui-modal-header__titles{display:block;flex:1 1 auto;min-width:0}.sui-modal-header__title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-sm-size, 14px);font-weight:var(--sui-type-label-sm-weight, 500);line-height:var(--sui-type-label-sm-line, 20px);letter-spacing:var(--sui-type-label-sm-spacing, -.006em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0;word-break:break-word}.sui-modal-header__description{margin:4px 0 0;font-family:var(--sui-font-sans);font-size:var(--sui-type-paragraph-xs-size, 12px);font-weight:var(--sui-type-paragraph-xs-weight, 400);line-height:var(--sui-type-paragraph-xs-line, 16px);letter-spacing:0;color:var(--sui-text-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal-header__description:first-child{margin-top:0}.sui-modal-header__close{position:absolute;top:16px;right:16px;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiCompactButton, selector: "sui-compact-button", inputs: ["icon", "variantStyle", "size", "fullRadius", "disabled", "href", "target", "rel", "type", "ariaLabel"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10700
+ }
10701
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalHeader, decorators: [{
10702
+ type: Component,
10703
+ args: [{ selector: 'sui-modal-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SuiIcon, SuiCompactButton], host: {
10704
+ /* Strip native `title` attr — patrón canon (ver CLAUDE.md del proyecto). */
10705
+ '[attr.title]': 'null',
10706
+ '[attr.data-sui-size]': 'size()',
10707
+ '[attr.data-has-icon]': 'iconName() ? "" : null',
10708
+ }, template: "@if (iconName(); as name) {\n <span class=\"sui-modal-header__icon\" [attr.data-variant]=\"resolvedVariant()\" aria-hidden=\"true\">\n <sui-icon [name]=\"name\" [size]=\"size() === 'small' ? 24 : 20\" />\n </span>\n}\n\n<div class=\"sui-modal-header__titles\">\n @if (title()) {\n <h2 class=\"sui-modal-header__title\" [attr.id]=\"titleId()\">{{ title() }}</h2>\n }\n @if (description(); as desc) {\n <p class=\"sui-modal-header__description\" [attr.id]=\"descriptionId()\">{{ desc }}</p>\n }\n</div>\n\n@if (showClose()) {\n <sui-compact-button\n class=\"sui-modal-header__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"closed.emit()\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;flex-shrink:0;gap:16px;padding:16px 56px 16px 20px;min-height:80px;background:var(--sui-bg-white-0, #fff);border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb);position:relative;overflow:hidden;box-sizing:border-box}:host([data-sui-size=small]){min-height:56px;gap:12px}:host([data-has-icon]){gap:14px}.sui-modal-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal-header__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal-header__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal-header__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal-header__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal-header__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f5f7fa);color:var(--sui-icon-sub-600, #5c5c5c)}:host([data-sui-size=small]) .sui-modal-header__icon{padding:0;background:transparent;align-self:center}.sui-modal-header__titles{display:block;flex:1 1 auto;min-width:0}.sui-modal-header__title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-sm-size, 14px);font-weight:var(--sui-type-label-sm-weight, 500);line-height:var(--sui-type-label-sm-line, 20px);letter-spacing:var(--sui-type-label-sm-spacing, -.006em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0;word-break:break-word}.sui-modal-header__description{margin:4px 0 0;font-family:var(--sui-font-sans);font-size:var(--sui-type-paragraph-xs-size, 12px);font-weight:var(--sui-type-paragraph-xs-weight, 400);line-height:var(--sui-type-paragraph-xs-line, 16px);letter-spacing:0;color:var(--sui-text-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal-header__description:first-child{margin-top:0}.sui-modal-header__close{position:absolute;top:16px;right:16px;flex-shrink:0}\n"] }]
10709
+ }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], iconVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconVariant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], titleId: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleId", required: false }] }], descriptionId: [{ type: i0.Input, args: [{ isSignal: true, alias: "descriptionId", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
10710
+
10626
10711
  /**
10627
10712
  * SUI Modal — SUI Design System 2.0
10628
10713
  *
@@ -10714,7 +10799,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
10714
10799
  * @input closeOnEscape — boolean — close on Escape key (default: true)
10715
10800
  * @input showClose — boolean — show X button (default: true)
10716
10801
  * @input iconVariant — SuiModalIconVariant | null — circular icon in header
10717
- * @input statusAlignment — 'horizontal' | 'vertical' — layout del icono+texto.
10802
+ * @input statusAlignment — 'horizontal' | 'vertical' | null — anatomía Status Modal (480:1372); null = header normal.
10718
10803
  * 'vertical' = patrón Status Modal de Figma (default: 'horizontal')
10719
10804
  * @input backdropBlur — boolean — blur(10px) del fondo. default true (look
10720
10805
  * glass del proyecto); opt-out con [backdropBlur]="false"
@@ -10743,11 +10828,11 @@ class SuiModal {
10743
10828
  contenedor circular bg `neutral-lighter` + color `sub-600`. Si NO se
10744
10829
  pasa y hay `iconVariant`, fallback al variant semántico. */
10745
10830
  headerIcon = input(null, ...(ngDevMode ? [{ debugName: "headerIcon" }] : /* istanbul ignore next */ []));
10746
- /** Layout del header con icono. `vertical` = patrón Status Modal de Figma
10747
- (node 480:1372): icono centrado arriba, texto centrado en columna,
10748
- tipografía escalada. Requiere `iconVariant` o `headerIcon` para tener
10749
- efecto visible. */
10750
- statusAlignment = input('horizontal', ...(ngDevMode ? [{ debugName: "statusAlignment" }] : /* istanbul ignore next */ []));
10831
+ /** Anatomía Status Modal de Figma (set 480:1372) — null (default) = header
10832
+ normal (Modal Header 466:4778). `horizontal`: tile cuadrado + texto en
10833
+ fila dentro del body (480:1366). `vertical`: icono centrado arriba +
10834
+ texto centrado en columna. Requiere `iconVariant` o `headerIcon`. */
10835
+ statusAlignment = input(null, ...(ngDevMode ? [{ debugName: "statusAlignment" }] : /* istanbul ignore next */ []));
10751
10836
  /** Aplica `backdrop-filter: blur(10px)` al overlay. Por defecto `true` —
10752
10837
  extra-feature "glass" del proyecto encima del overlay-gray plano del DS
10753
10838
  (rgba(51,51,51,0.24)). Pasar `[backdropBlur]="false"` lo quita y deja el
@@ -10942,14 +11027,12 @@ class SuiModal {
10942
11027
  /** data-variant del círculo: si hay variant semántico lo usa; si solo hay
10943
11028
  * headerIcon custom, retorna 'neutral'. */
10944
11029
  resolvedIconVariant = computed(() => this.iconVariant() ?? (this.headerIcon() ? 'neutral' : 'info'), ...(ngDevMode ? [{ debugName: "resolvedIconVariant" }] : /* istanbul ignore next */ []));
10945
- /** True cuando el modal está en modo Status vertical Y hay un icono que
10946
- * mostrar. En este modo el icono+texto se renderizan centrados en el body,
10947
- * no en el header horizontal. */
10948
- isStatusVertical = computed(() => this.statusAlignment() === 'vertical' && this.hasHeaderIcon(), ...(ngDevMode ? [{ debugName: "isStatusVertical" }] : /* istanbul ignore next */ []));
10949
- /** True cuando el header con icono debe renderizar el icono "flat" (24px sin
10950
- * círculo): patrón Figma "Modal Header / Small" (size sin description). Solo
10951
- * aplica en modo horizontal con icono y SIN description. */
10952
- isCompactHeader = computed(() => !this.isStatusVertical() && !this.description(), ...(ngDevMode ? [{ debugName: "isCompactHeader" }] : /* istanbul ignore next */ []));
11030
+ /** Modo Status Modal activo (statusAlignment seteado + icono presente):
11031
+ * el icono+texto se renderizan en el body con la anatomía 480:1372 y el
11032
+ * header queda solo con el close flotante. */
11033
+ isStatus = computed(() => this.statusAlignment() !== null && this.hasHeaderIcon(), ...(ngDevMode ? [{ debugName: "isStatus" }] : /* istanbul ignore next */ []));
11034
+ isStatusVertical = computed(() => this.isStatus() && this.statusAlignment() === 'vertical', ...(ngDevMode ? [{ debugName: "isStatusVertical" }] : /* istanbul ignore next */ []));
11035
+ isStatusHorizontal = computed(() => this.isStatus() && this.statusAlignment() === 'horizontal', ...(ngDevMode ? [{ debugName: "isStatusHorizontal" }] : /* istanbul ignore next */ []));
10953
11036
  // ── Element that had focus before opening (for restore) ───────────────────
10954
11037
  _previousFocus = null;
10955
11038
  _escapeHandler;
@@ -11042,16 +11125,16 @@ class SuiModal {
11042
11125
  container?.focus({ preventScroll: true });
11043
11126
  }
11044
11127
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
11045
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModal, isStandalone: true, selector: "sui-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, iconVariant: { classPropertyName: "iconVariant", publicName: "iconVariant", isSignal: true, isRequired: false, transformFunction: null }, headerIcon: { classPropertyName: "headerIcon", publicName: "headerIcon", isSignal: true, isRequired: false, transformFunction: null }, statusAlignment: { classPropertyName: "statusAlignment", publicName: "statusAlignment", isSignal: true, isRequired: false, transformFunction: null }, backdropBlur: { classPropertyName: "backdropBlur", publicName: "backdropBlur", isSignal: true, isRequired: false, transformFunction: null }, fullscreen: { classPropertyName: "fullscreen", publicName: "fullscreen", isSignal: true, isRequired: false, transformFunction: null }, fullBody: { classPropertyName: "fullBody", publicName: "fullBody", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { properties: { "attr.title": "null", "attr.data-sui-modal-open": "open() ? \"\" : null", "attr.data-sui-modal-fullscreen": "fullscreen() ? \"\" : null" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }, { propertyName: "bodyRef", first: true, predicate: ["bodyEl"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <!-- Overlay backdrop -->\n <div\n class=\"sui-modal__backdrop\"\n [class.sui-modal__backdrop--no-blur]=\"!backdropBlur()\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Dialog wrapper (also acts as click-outside target when backdrop is disabled) -->\n <div\n class=\"sui-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"description() ? descId : null\"\n >\n <!-- Container \u2014 click stops propagation so it doesn't close.\n tabindex=-1 hace que el container sea focusable program\u00E1ticamente\n (para a11y al abrir el modal) pero NO entra en el tab order. */ -->\n <div\n #container\n class=\"sui-modal__container\"\n [class.sui-modal__container--scroll-active]=\"scrollActive()\"\n [class.sui-modal__container--fullscreen]=\"fullscreen()\"\n [class.sui-modal__container--status-vertical]=\"isStatusVertical()\"\n [attr.data-sui-size]=\"size()\"\n tabindex=\"-1\"\n (click)=\"onContainerClick($event)\"\n >\n <!-- Header \u2014 modo HORIZONTAL (canon Figma \"Modal Header\").\n En modo Status vertical el icono+texto se mueven al body, as\u00ED que el\n header solo conserva el close button (si aplica). -->\n @if (title() || showClose()) {\n <header\n class=\"sui-modal__header\"\n [class.sui-modal__header--with-icon]=\"hasHeaderIcon() && !isStatusVertical()\"\n [class.sui-modal__header--compact]=\"isCompactHeader()\"\n [class.sui-modal__header--close-only]=\"isStatusVertical()\"\n >\n\n <!-- Icon badge (horizontal): c\u00EDrculo bg lighter + 20px icono.\n En Small (sin description) Figma lo muestra flat 24px sin c\u00EDrculo\n \u2192 la clase --compact del header lo controla v\u00EDa SCSS. -->\n @if (hasHeaderIcon() && !isStatusVertical()) {\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"isCompactHeader() ? 24 : 20\" />\n </div>\n }\n\n <!-- Title + Description (horizontal) -->\n @if (!isStatusVertical()) {\n <div class=\"sui-modal__titles\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__description\">{{ description() }}</p>\n }\n </div>\n }\n\n <!-- Close button \u2014 Figma 466:4778 lo modela como Compact Button [1.1]\n (close-line 20px, ghost). Canon: sui-compact-button (ver CLAUDE.md\n \"close X en modales\"), no un <button> maqueta. -->\n @if (showClose()) {\n <sui-compact-button\n class=\"sui-modal__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"close()\"\n />\n }\n </header>\n }\n\n <!-- Body \u2014 default slot (ng-content). El consumer proyecta cualquier markup aqu\u00ED. -->\n <div #bodyEl\n class=\"sui-modal__body\"\n [class.sui-modal__body--full]=\"fullBody()\"\n [class.sui-modal__body--status]=\"isStatusVertical()\">\n\n <!-- Status vertical: icono centrado arriba + texto centrado (Figma 480:1372).\n Tipograf\u00EDa escalada (Label/Medium 16 + Paragraph/Small 14). -->\n @if (isStatusVertical()) {\n <div class=\"sui-modal__status\">\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"24\" />\n </div>\n @if (title() || description()) {\n <div class=\"sui-modal__status-text\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__status-title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__status-description\">{{ description() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <ng-content />\n </div>\n\n <!-- Footer \u2014 named slot via attribute selector -->\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-modal__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);animation:sui-modal-backdrop-in var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)) both}.sui-modal__backdrop--no-blur{backdrop-filter:none;-webkit-backdrop-filter:none}.sui-modal{position:fixed;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box;pointer-events:none}.sui-modal__container{position:relative;display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--sui-bg-white-0, #ffffff);border:1px solid var(--sui-stroke-soft-200, #ebebeb);border-radius:var(--sui-radius-20, 20px);box-shadow:var(--sui-regular-shadow-medium, 0 16px 32px -12px rgba(14, 18, 27, .1));width:100%;margin-inline:auto;max-height:calc(100dvh - 32px);overflow-y:auto;animation:sui-modal-container-in .18s cubic-bezier(.16,1,.3,1) both;will-change:transform,opacity}.sui-modal__container[data-sui-size=small]{max-width:400px}.sui-modal__container[data-sui-size=medium]{max-width:440px}.sui-modal__container[data-sui-size=large]{max-width:560px}.sui-modal__container[data-sui-size=xlarge]{max-width:720px}.sui-modal__header{display:flex;align-items:center;flex-shrink:0;gap:16px;padding:16px 56px 16px 20px;border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);position:relative;overflow:hidden;box-sizing:border-box;min-height:80px;height:auto}.sui-modal__header.sui-modal__header--with-icon{gap:14px}.sui-modal__header.sui-modal__header--compact{min-height:56px;gap:12px}.sui-modal__header.sui-modal__header--compact.sui-modal__header--with-icon{gap:14px}.sui-modal__header.sui-modal__header--close-only{min-height:0;padding:0;border-bottom:none;background:transparent;overflow:visible}.sui-modal__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c)}.sui-modal__header--compact .sui-modal__icon{padding:0;background:transparent;align-self:center}.sui-modal__titles{display:block;flex:1 1 auto;min-width:0}.sui-modal__title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-sm-size, 14px);font-weight:var(--sui-type-label-sm-weight, 500);line-height:var(--sui-type-label-sm-line, 20px);letter-spacing:var(--sui-type-label-sm-spacing, -.006em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0;word-break:break-word}.sui-modal__description{margin:4px 0 0;font-family:var(--sui-font-sans);font-size:var(--sui-type-paragraph-xs-size, 12px);font-weight:var(--sui-type-paragraph-xs-weight, 400);line-height:var(--sui-type-paragraph-xs-line, 16px);letter-spacing:0;color:var(--sui-text-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__title+.sui-modal__description{margin-top:4px}.sui-modal__description:first-child{margin-top:0}.sui-modal__close{position:absolute;top:16px;right:16px;flex-shrink:0}.sui-modal__body{display:flex;flex-direction:column;gap:20px;padding:20px;flex:1 1 auto;background:var(--sui-bg-white-0, #ffffff);overflow-y:auto;max-height:calc(100dvh - 200px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.sui-modal__body:empty{display:none}.sui-modal__body--full{padding:0;gap:0}.sui-modal__status{display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.sui-modal__status .sui-modal__icon{align-self:center;padding:8px;border-radius:var(--sui-radius-10, 10px)}.sui-modal__status-text{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%}.sui-modal__status-title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-md-size, 16px);font-weight:var(--sui-type-label-md-weight, 500);line-height:var(--sui-type-label-md-line, 24px);letter-spacing:var(--sui-type-label-md-spacing, -.011em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__status-description{margin:0;font-family:var(--sui-font-sans);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-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}::ng-deep [slot=footer],.sui-modal__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 20px;box-sizing:border-box;border-top:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}.sui-modal__container--scroll-active ::ng-deep [slot=footer],.sui-modal__container--scroll-active .sui-modal__footer{box-shadow:0 -4px 8px #0e121b0f}@keyframes sui-modal-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes sui-modal-container-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.sui-modal__container:focus{outline:none}@media(max-width:768px){.sui-modal{align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top,16px)) max(16px,env(safe-area-inset-right,16px)) max(16px,env(safe-area-inset-bottom,16px)) max(16px,env(safe-area-inset-left,16px));box-sizing:border-box}.sui-modal__container{width:100%;max-width:100%;max-height:calc(50dvh - 16px);overflow:hidden;display:flex;flex-direction:column}.sui-modal__body{overflow-y:auto;flex:1 1 auto;max-height:calc(50dvh - 100px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen){max-height:calc(100dvh - 16px)}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen) .sui-modal__body{max-height:calc(100dvh - 200px)}.sui-modal__header,::ng-deep [slot=footer],.sui-modal__footer{flex-shrink:0}.sui-modal:has(.sui-modal__container--fullscreen){align-items:stretch;justify-content:stretch;padding:env(safe-area-inset-top,0px) 0 0}:host-context(html.platform-android) .sui-modal:has(.sui-modal__container--fullscreen){padding-bottom:var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))}.sui-modal__container--fullscreen,.sui-modal__container--fullscreen[data-sui-size=small],.sui-modal__container--fullscreen[data-sui-size=medium],.sui-modal__container--fullscreen[data-sui-size=large],.sui-modal__container--fullscreen[data-sui-size=xlarge]{width:100%;max-width:100%;height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));border-radius:24px;transition:height .22s ease,max-height .22s ease}:host-context(html.platform-android) .sui-modal__container--fullscreen,:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=small],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=medium],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=large],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=xlarge]{height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)))}.sui-modal__container--fullscreen .sui-modal__body{max-height:none;flex:1 1 auto;min-height:0;overflow-y:auto}}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiCompactButton, selector: "sui-compact-button", inputs: ["icon", "variantStyle", "size", "fullRadius", "disabled", "href", "target", "rel", "type", "ariaLabel"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11128
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModal, isStandalone: true, selector: "sui-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdrop: { classPropertyName: "closeOnBackdrop", publicName: "closeOnBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null }, iconVariant: { classPropertyName: "iconVariant", publicName: "iconVariant", isSignal: true, isRequired: false, transformFunction: null }, headerIcon: { classPropertyName: "headerIcon", publicName: "headerIcon", isSignal: true, isRequired: false, transformFunction: null }, statusAlignment: { classPropertyName: "statusAlignment", publicName: "statusAlignment", isSignal: true, isRequired: false, transformFunction: null }, backdropBlur: { classPropertyName: "backdropBlur", publicName: "backdropBlur", isSignal: true, isRequired: false, transformFunction: null }, fullscreen: { classPropertyName: "fullscreen", publicName: "fullscreen", isSignal: true, isRequired: false, transformFunction: null }, fullBody: { classPropertyName: "fullBody", publicName: "fullBody", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { properties: { "attr.title": "null", "attr.data-sui-modal-open": "open() ? \"\" : null", "attr.data-sui-modal-fullscreen": "fullscreen() ? \"\" : null" } }, viewQueries: [{ propertyName: "containerRef", first: true, predicate: ["container"], descendants: true }, { propertyName: "bodyRef", first: true, predicate: ["bodyEl"], descendants: true }], ngImport: i0, template: "@if (open()) {\n <!-- Overlay backdrop -->\n <div\n class=\"sui-modal__backdrop\"\n [class.sui-modal__backdrop--no-blur]=\"!backdropBlur()\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Dialog wrapper (also acts as click-outside target when backdrop is disabled) -->\n <div\n class=\"sui-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"description() ? descId : null\"\n >\n <!-- Container \u2014 click stops propagation so it doesn't close.\n tabindex=-1 hace que el container sea focusable program\u00E1ticamente\n (para a11y al abrir el modal) pero NO entra en el tab order. */ -->\n <div\n #container\n class=\"sui-modal__container\"\n [class.sui-modal__container--scroll-active]=\"scrollActive()\"\n [class.sui-modal__container--fullscreen]=\"fullscreen()\"\n [class.sui-modal__container--status-vertical]=\"isStatusVertical()\"\n [attr.data-sui-size]=\"size()\"\n tabindex=\"-1\"\n (click)=\"onContainerClick($event)\"\n >\n <!-- Header \u2014 delegado a sui-modal-header (fuente \u00FAnica de la anatom\u00EDa,\n Figma 466:4778). En modo Status el icono+texto viven en el body\n (Figma 480:1372 no tiene header) y solo queda el close flotante. -->\n @if (isStatus()) {\n @if (showClose()) {\n <sui-compact-button\n class=\"sui-modal__close-floating\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"close()\"\n />\n }\n } @else if (title() || showClose()) {\n <sui-modal-header\n class=\"sui-modal__header\"\n [title]=\"title() ?? ''\"\n [description]=\"description()\"\n [size]=\"description() ? 'medium' : 'small'\"\n [iconVariant]=\"iconVariant()\"\n [icon]=\"headerIcon()\"\n [showClose]=\"showClose()\"\n [titleId]=\"titleId\"\n [descriptionId]=\"descId\"\n (closed)=\"close()\"\n />\n }\n\n <!-- Body \u2014 default slot (ng-content). El consumer proyecta cualquier markup aqu\u00ED. -->\n <div #bodyEl\n class=\"sui-modal__body\"\n [class.sui-modal__body--full]=\"fullBody()\"\n [class.sui-modal__body--status]=\"isStatus()\">\n\n <!-- Status Modal (Figma 480:1372): vertical = icono arriba + texto\n centrado; horizontal (480:1366) = tile + texto en fila, alineado\n a la izquierda. Tipograf\u00EDa escalada (Label/Medium 16 + Paragraph/Small 14). -->\n @if (isStatus()) {\n <div class=\"sui-modal__status\" [class.sui-modal__status--row]=\"isStatusHorizontal()\">\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"24\" />\n </div>\n @if (title() || description()) {\n <div class=\"sui-modal__status-text\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__status-title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__status-description\">{{ description() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <ng-content />\n </div>\n\n <!-- Footer \u2014 named slot: proyectar <sui-modal-footer slot=\"footer\"> (canon)\n o markup custom. -->\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-modal__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);animation:sui-modal-backdrop-in var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)) both}.sui-modal__backdrop--no-blur{backdrop-filter:none;-webkit-backdrop-filter:none}.sui-modal{position:fixed;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box;pointer-events:none}.sui-modal__container{position:relative;display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--sui-bg-white-0, #ffffff);border:1px solid var(--sui-stroke-soft-200, #ebebeb);border-radius:var(--sui-radius-20, 20px);box-shadow:var(--sui-regular-shadow-medium, 0 16px 32px -12px rgba(14, 18, 27, .1));width:100%;margin-inline:auto;max-height:calc(100dvh - 32px);overflow-y:auto;animation:sui-modal-container-in .18s cubic-bezier(.16,1,.3,1) both;will-change:transform,opacity}.sui-modal__container[data-sui-size=small]{max-width:400px}.sui-modal__container[data-sui-size=medium]{max-width:440px}.sui-modal__container[data-sui-size=large]{max-width:560px}.sui-modal__container[data-sui-size=xlarge]{max-width:720px}.sui-modal__header{flex-shrink:0}.sui-modal__close-floating{position:absolute;top:16px;right:16px;z-index:1;flex-shrink:0}.sui-modal__body{display:flex;flex-direction:column;gap:20px;padding:20px;flex:1 1 auto;background:var(--sui-bg-white-0, #ffffff);overflow-y:auto;max-height:calc(100dvh - 200px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.sui-modal__body:empty{display:none}.sui-modal__body--full{padding:0;gap:0}.sui-modal__status{display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.sui-modal__status .sui-modal__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;padding:8px;border-radius:var(--sui-radius-10, 10px)}.sui-modal__status .sui-modal__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal__status .sui-modal__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal__status .sui-modal__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal__status .sui-modal__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal__status .sui-modal__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c)}.sui-modal__status--row{flex-direction:row;align-items:flex-start;text-align:left}.sui-modal__status--row .sui-modal__icon{align-self:flex-start}.sui-modal__status--row .sui-modal__status-text{align-items:flex-start}.sui-modal__status-text{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%}.sui-modal__status-title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-md-size, 16px);font-weight:var(--sui-type-label-md-weight, 500);line-height:var(--sui-type-label-md-line, 24px);letter-spacing:var(--sui-type-label-md-spacing, -.011em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__status-description{margin:0;font-family:var(--sui-font-sans);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-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}::ng-deep sui-modal-footer[slot=footer]{flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}::ng-deep [slot=footer]:not(sui-modal-footer),.sui-modal__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 20px;box-sizing:border-box;border-top:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}.sui-modal__container--scroll-active ::ng-deep [slot=footer],.sui-modal__container--scroll-active .sui-modal__footer{box-shadow:0 -4px 8px #0e121b0f}@keyframes sui-modal-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes sui-modal-container-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.sui-modal__container:focus{outline:none}@media(max-width:768px){.sui-modal{align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top,16px)) max(16px,env(safe-area-inset-right,16px)) max(16px,env(safe-area-inset-bottom,16px)) max(16px,env(safe-area-inset-left,16px));box-sizing:border-box}.sui-modal__container{width:100%;max-width:100%;max-height:calc(50dvh - 16px);overflow:hidden;display:flex;flex-direction:column}.sui-modal__body{overflow-y:auto;flex:1 1 auto;max-height:calc(50dvh - 100px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen){max-height:calc(100dvh - 16px)}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen) .sui-modal__body{max-height:calc(100dvh - 200px)}.sui-modal__header,::ng-deep [slot=footer],.sui-modal__footer{flex-shrink:0}.sui-modal:has(.sui-modal__container--fullscreen){align-items:stretch;justify-content:stretch;padding:env(safe-area-inset-top,0px) 0 0}:host-context(html.platform-android) .sui-modal:has(.sui-modal__container--fullscreen){padding-bottom:var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))}.sui-modal__container--fullscreen,.sui-modal__container--fullscreen[data-sui-size=small],.sui-modal__container--fullscreen[data-sui-size=medium],.sui-modal__container--fullscreen[data-sui-size=large],.sui-modal__container--fullscreen[data-sui-size=xlarge]{width:100%;max-width:100%;height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));border-radius:24px;transition:height .22s ease,max-height .22s ease}:host-context(html.platform-android) .sui-modal__container--fullscreen,:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=small],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=medium],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=large],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=xlarge]{height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)))}.sui-modal__container--fullscreen .sui-modal__body{max-height:none;flex:1 1 auto;min-height:0;overflow-y:auto}}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiCompactButton, selector: "sui-compact-button", inputs: ["icon", "variantStyle", "size", "fullRadius", "disabled", "href", "target", "rel", "type", "ariaLabel"], outputs: ["clicked"] }, { kind: "component", type: SuiModalHeader, selector: "sui-modal-header", inputs: ["title", "description", "size", "iconVariant", "icon", "showClose", "titleId", "descriptionId"], outputs: ["closed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11046
11129
  }
11047
11130
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModal, decorators: [{
11048
11131
  type: Component,
11049
- args: [{ selector: 'sui-modal', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SuiIcon, SuiCompactButton], host: {
11132
+ args: [{ selector: 'sui-modal', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [SuiIcon, SuiCompactButton, SuiModalHeader], host: {
11050
11133
  /* Strip native `title` attr — patrón canon Ontop (ver CLAUDE.md). */
11051
11134
  '[attr.title]': 'null',
11052
11135
  '[attr.data-sui-modal-open]': 'open() ? "" : null',
11053
11136
  '[attr.data-sui-modal-fullscreen]': 'fullscreen() ? "" : null',
11054
- }, template: "@if (open()) {\n <!-- Overlay backdrop -->\n <div\n class=\"sui-modal__backdrop\"\n [class.sui-modal__backdrop--no-blur]=\"!backdropBlur()\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Dialog wrapper (also acts as click-outside target when backdrop is disabled) -->\n <div\n class=\"sui-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"description() ? descId : null\"\n >\n <!-- Container \u2014 click stops propagation so it doesn't close.\n tabindex=-1 hace que el container sea focusable program\u00E1ticamente\n (para a11y al abrir el modal) pero NO entra en el tab order. */ -->\n <div\n #container\n class=\"sui-modal__container\"\n [class.sui-modal__container--scroll-active]=\"scrollActive()\"\n [class.sui-modal__container--fullscreen]=\"fullscreen()\"\n [class.sui-modal__container--status-vertical]=\"isStatusVertical()\"\n [attr.data-sui-size]=\"size()\"\n tabindex=\"-1\"\n (click)=\"onContainerClick($event)\"\n >\n <!-- Header \u2014 modo HORIZONTAL (canon Figma \"Modal Header\").\n En modo Status vertical el icono+texto se mueven al body, as\u00ED que el\n header solo conserva el close button (si aplica). -->\n @if (title() || showClose()) {\n <header\n class=\"sui-modal__header\"\n [class.sui-modal__header--with-icon]=\"hasHeaderIcon() && !isStatusVertical()\"\n [class.sui-modal__header--compact]=\"isCompactHeader()\"\n [class.sui-modal__header--close-only]=\"isStatusVertical()\"\n >\n\n <!-- Icon badge (horizontal): c\u00EDrculo bg lighter + 20px icono.\n En Small (sin description) Figma lo muestra flat 24px sin c\u00EDrculo\n \u2192 la clase --compact del header lo controla v\u00EDa SCSS. -->\n @if (hasHeaderIcon() && !isStatusVertical()) {\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"isCompactHeader() ? 24 : 20\" />\n </div>\n }\n\n <!-- Title + Description (horizontal) -->\n @if (!isStatusVertical()) {\n <div class=\"sui-modal__titles\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__description\">{{ description() }}</p>\n }\n </div>\n }\n\n <!-- Close button \u2014 Figma 466:4778 lo modela como Compact Button [1.1]\n (close-line 20px, ghost). Canon: sui-compact-button (ver CLAUDE.md\n \"close X en modales\"), no un <button> maqueta. -->\n @if (showClose()) {\n <sui-compact-button\n class=\"sui-modal__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"close()\"\n />\n }\n </header>\n }\n\n <!-- Body \u2014 default slot (ng-content). El consumer proyecta cualquier markup aqu\u00ED. -->\n <div #bodyEl\n class=\"sui-modal__body\"\n [class.sui-modal__body--full]=\"fullBody()\"\n [class.sui-modal__body--status]=\"isStatusVertical()\">\n\n <!-- Status vertical: icono centrado arriba + texto centrado (Figma 480:1372).\n Tipograf\u00EDa escalada (Label/Medium 16 + Paragraph/Small 14). -->\n @if (isStatusVertical()) {\n <div class=\"sui-modal__status\">\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"24\" />\n </div>\n @if (title() || description()) {\n <div class=\"sui-modal__status-text\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__status-title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__status-description\">{{ description() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <ng-content />\n </div>\n\n <!-- Footer \u2014 named slot via attribute selector -->\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-modal__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);animation:sui-modal-backdrop-in var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)) both}.sui-modal__backdrop--no-blur{backdrop-filter:none;-webkit-backdrop-filter:none}.sui-modal{position:fixed;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box;pointer-events:none}.sui-modal__container{position:relative;display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--sui-bg-white-0, #ffffff);border:1px solid var(--sui-stroke-soft-200, #ebebeb);border-radius:var(--sui-radius-20, 20px);box-shadow:var(--sui-regular-shadow-medium, 0 16px 32px -12px rgba(14, 18, 27, .1));width:100%;margin-inline:auto;max-height:calc(100dvh - 32px);overflow-y:auto;animation:sui-modal-container-in .18s cubic-bezier(.16,1,.3,1) both;will-change:transform,opacity}.sui-modal__container[data-sui-size=small]{max-width:400px}.sui-modal__container[data-sui-size=medium]{max-width:440px}.sui-modal__container[data-sui-size=large]{max-width:560px}.sui-modal__container[data-sui-size=xlarge]{max-width:720px}.sui-modal__header{display:flex;align-items:center;flex-shrink:0;gap:16px;padding:16px 56px 16px 20px;border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);position:relative;overflow:hidden;box-sizing:border-box;min-height:80px;height:auto}.sui-modal__header.sui-modal__header--with-icon{gap:14px}.sui-modal__header.sui-modal__header--compact{min-height:56px;gap:12px}.sui-modal__header.sui-modal__header--compact.sui-modal__header--with-icon{gap:14px}.sui-modal__header.sui-modal__header--close-only{min-height:0;padding:0;border-bottom:none;background:transparent;overflow:visible}.sui-modal__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:flex-start;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c)}.sui-modal__header--compact .sui-modal__icon{padding:0;background:transparent;align-self:center}.sui-modal__titles{display:block;flex:1 1 auto;min-width:0}.sui-modal__title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-sm-size, 14px);font-weight:var(--sui-type-label-sm-weight, 500);line-height:var(--sui-type-label-sm-line, 20px);letter-spacing:var(--sui-type-label-sm-spacing, -.006em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0;word-break:break-word}.sui-modal__description{margin:4px 0 0;font-family:var(--sui-font-sans);font-size:var(--sui-type-paragraph-xs-size, 12px);font-weight:var(--sui-type-paragraph-xs-weight, 400);line-height:var(--sui-type-paragraph-xs-line, 16px);letter-spacing:0;color:var(--sui-text-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__title+.sui-modal__description{margin-top:4px}.sui-modal__description:first-child{margin-top:0}.sui-modal__close{position:absolute;top:16px;right:16px;flex-shrink:0}.sui-modal__body{display:flex;flex-direction:column;gap:20px;padding:20px;flex:1 1 auto;background:var(--sui-bg-white-0, #ffffff);overflow-y:auto;max-height:calc(100dvh - 200px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.sui-modal__body:empty{display:none}.sui-modal__body--full{padding:0;gap:0}.sui-modal__status{display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.sui-modal__status .sui-modal__icon{align-self:center;padding:8px;border-radius:var(--sui-radius-10, 10px)}.sui-modal__status-text{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%}.sui-modal__status-title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-md-size, 16px);font-weight:var(--sui-type-label-md-weight, 500);line-height:var(--sui-type-label-md-line, 24px);letter-spacing:var(--sui-type-label-md-spacing, -.011em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__status-description{margin:0;font-family:var(--sui-font-sans);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-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}::ng-deep [slot=footer],.sui-modal__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 20px;box-sizing:border-box;border-top:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}.sui-modal__container--scroll-active ::ng-deep [slot=footer],.sui-modal__container--scroll-active .sui-modal__footer{box-shadow:0 -4px 8px #0e121b0f}@keyframes sui-modal-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes sui-modal-container-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.sui-modal__container:focus{outline:none}@media(max-width:768px){.sui-modal{align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top,16px)) max(16px,env(safe-area-inset-right,16px)) max(16px,env(safe-area-inset-bottom,16px)) max(16px,env(safe-area-inset-left,16px));box-sizing:border-box}.sui-modal__container{width:100%;max-width:100%;max-height:calc(50dvh - 16px);overflow:hidden;display:flex;flex-direction:column}.sui-modal__body{overflow-y:auto;flex:1 1 auto;max-height:calc(50dvh - 100px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen){max-height:calc(100dvh - 16px)}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen) .sui-modal__body{max-height:calc(100dvh - 200px)}.sui-modal__header,::ng-deep [slot=footer],.sui-modal__footer{flex-shrink:0}.sui-modal:has(.sui-modal__container--fullscreen){align-items:stretch;justify-content:stretch;padding:env(safe-area-inset-top,0px) 0 0}:host-context(html.platform-android) .sui-modal:has(.sui-modal__container--fullscreen){padding-bottom:var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))}.sui-modal__container--fullscreen,.sui-modal__container--fullscreen[data-sui-size=small],.sui-modal__container--fullscreen[data-sui-size=medium],.sui-modal__container--fullscreen[data-sui-size=large],.sui-modal__container--fullscreen[data-sui-size=xlarge]{width:100%;max-width:100%;height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));border-radius:24px;transition:height .22s ease,max-height .22s ease}:host-context(html.platform-android) .sui-modal__container--fullscreen,:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=small],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=medium],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=large],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=xlarge]{height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)))}.sui-modal__container--fullscreen .sui-modal__body{max-height:none;flex:1 1 auto;min-height:0;overflow-y:auto}}\n"] }]
11137
+ }, template: "@if (open()) {\n <!-- Overlay backdrop -->\n <div\n class=\"sui-modal__backdrop\"\n [class.sui-modal__backdrop--no-blur]=\"!backdropBlur()\"\n (click)=\"onBackdropClick()\"\n role=\"presentation\"\n aria-hidden=\"true\"\n ></div>\n\n <!-- Dialog wrapper (also acts as click-outside target when backdrop is disabled) -->\n <div\n class=\"sui-modal\"\n role=\"dialog\"\n aria-modal=\"true\"\n [attr.aria-labelledby]=\"title() ? titleId : null\"\n [attr.aria-describedby]=\"description() ? descId : null\"\n >\n <!-- Container \u2014 click stops propagation so it doesn't close.\n tabindex=-1 hace que el container sea focusable program\u00E1ticamente\n (para a11y al abrir el modal) pero NO entra en el tab order. */ -->\n <div\n #container\n class=\"sui-modal__container\"\n [class.sui-modal__container--scroll-active]=\"scrollActive()\"\n [class.sui-modal__container--fullscreen]=\"fullscreen()\"\n [class.sui-modal__container--status-vertical]=\"isStatusVertical()\"\n [attr.data-sui-size]=\"size()\"\n tabindex=\"-1\"\n (click)=\"onContainerClick($event)\"\n >\n <!-- Header \u2014 delegado a sui-modal-header (fuente \u00FAnica de la anatom\u00EDa,\n Figma 466:4778). En modo Status el icono+texto viven en el body\n (Figma 480:1372 no tiene header) y solo queda el close flotante. -->\n @if (isStatus()) {\n @if (showClose()) {\n <sui-compact-button\n class=\"sui-modal__close-floating\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"close()\"\n />\n }\n } @else if (title() || showClose()) {\n <sui-modal-header\n class=\"sui-modal__header\"\n [title]=\"title() ?? ''\"\n [description]=\"description()\"\n [size]=\"description() ? 'medium' : 'small'\"\n [iconVariant]=\"iconVariant()\"\n [icon]=\"headerIcon()\"\n [showClose]=\"showClose()\"\n [titleId]=\"titleId\"\n [descriptionId]=\"descId\"\n (closed)=\"close()\"\n />\n }\n\n <!-- Body \u2014 default slot (ng-content). El consumer proyecta cualquier markup aqu\u00ED. -->\n <div #bodyEl\n class=\"sui-modal__body\"\n [class.sui-modal__body--full]=\"fullBody()\"\n [class.sui-modal__body--status]=\"isStatus()\">\n\n <!-- Status Modal (Figma 480:1372): vertical = icono arriba + texto\n centrado; horizontal (480:1366) = tile + texto en fila, alineado\n a la izquierda. Tipograf\u00EDa escalada (Label/Medium 16 + Paragraph/Small 14). -->\n @if (isStatus()) {\n <div class=\"sui-modal__status\" [class.sui-modal__status--row]=\"isStatusHorizontal()\">\n <div class=\"sui-modal__icon\" [attr.data-variant]=\"resolvedIconVariant()\">\n <sui-icon [name]=\"iconName()\" [size]=\"24\" />\n </div>\n @if (title() || description()) {\n <div class=\"sui-modal__status-text\">\n @if (title()) {\n <h2 [id]=\"titleId\" class=\"sui-modal__status-title\">{{ title() }}</h2>\n }\n @if (description()) {\n <p [id]=\"descId\" class=\"sui-modal__status-description\">{{ description() }}</p>\n }\n </div>\n }\n </div>\n }\n\n <ng-content />\n </div>\n\n <!-- Footer \u2014 named slot: proyectar <sui-modal-footer slot=\"footer\"> (canon)\n o markup custom. -->\n <ng-content select=\"[slot=footer]\" />\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:host{display:contents}.sui-modal__backdrop{position:fixed;inset:0;z-index:1000;background-color:#3333333d;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);animation:sui-modal-backdrop-in var(--sui-motion-duration-fast, .2s) var(--sui-motion-ease-out, cubic-bezier(0, 0, .2, 1)) both}.sui-modal__backdrop--no-blur{backdrop-filter:none;-webkit-backdrop-filter:none}.sui-modal{position:fixed;inset:0;z-index:1001;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box;pointer-events:none}.sui-modal__container{position:relative;display:flex;flex-direction:column;overflow:hidden;pointer-events:auto;background:var(--sui-bg-white-0, #ffffff);border:1px solid var(--sui-stroke-soft-200, #ebebeb);border-radius:var(--sui-radius-20, 20px);box-shadow:var(--sui-regular-shadow-medium, 0 16px 32px -12px rgba(14, 18, 27, .1));width:100%;margin-inline:auto;max-height:calc(100dvh - 32px);overflow-y:auto;animation:sui-modal-container-in .18s cubic-bezier(.16,1,.3,1) both;will-change:transform,opacity}.sui-modal__container[data-sui-size=small]{max-width:400px}.sui-modal__container[data-sui-size=medium]{max-width:440px}.sui-modal__container[data-sui-size=large]{max-width:560px}.sui-modal__container[data-sui-size=xlarge]{max-width:720px}.sui-modal__header{flex-shrink:0}.sui-modal__close-floating{position:absolute;top:16px;right:16px;z-index:1;flex-shrink:0}.sui-modal__body{display:flex;flex-direction:column;gap:20px;padding:20px;flex:1 1 auto;background:var(--sui-bg-white-0, #ffffff);overflow-y:auto;max-height:calc(100dvh - 200px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}.sui-modal__body:empty{display:none}.sui-modal__body--full{padding:0;gap:0}.sui-modal__status{display:flex;flex-direction:column;align-items:center;text-align:center;gap:16px}.sui-modal__status .sui-modal__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;padding:8px;border-radius:var(--sui-radius-10, 10px)}.sui-modal__status .sui-modal__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal__status .sui-modal__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal__status .sui-modal__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal__status .sui-modal__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal__status .sui-modal__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f7f7f7);color:var(--sui-text-sub-600, #5c5c5c)}.sui-modal__status--row{flex-direction:row;align-items:flex-start;text-align:left}.sui-modal__status--row .sui-modal__icon{align-self:flex-start}.sui-modal__status--row .sui-modal__status-text{align-items:flex-start}.sui-modal__status-text{display:flex;flex-direction:column;align-items:center;gap:4px;width:100%}.sui-modal__status-title{margin:0;font-family:var(--sui-font-sans);font-size:var(--sui-type-label-md-size, 16px);font-weight:var(--sui-type-label-md-weight, 500);line-height:var(--sui-type-label-md-line, 24px);letter-spacing:var(--sui-type-label-md-spacing, -.011em);color:var(--sui-text-strong-950, #171717);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}.sui-modal__status-description{margin:0;font-family:var(--sui-font-sans);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-sub-600, #5c5c5c);font-feature-settings:\"ss11\" 1,\"calt\" 0,\"liga\" 0}::ng-deep sui-modal-footer[slot=footer]{flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}::ng-deep [slot=footer]:not(sui-modal-footer),.sui-modal__footer{display:flex;align-items:center;justify-content:flex-end;gap:12px;padding:16px 20px;box-sizing:border-box;border-top:1px solid var(--sui-stroke-soft-200, #ebebeb);background:var(--sui-bg-white-0, #ffffff);flex-shrink:0;position:relative;transition:box-shadow var(--sui-motion-duration-x-fast, .1s) var(--sui-motion-ease-out)}.sui-modal__container--scroll-active ::ng-deep [slot=footer],.sui-modal__container--scroll-active .sui-modal__footer{box-shadow:0 -4px 8px #0e121b0f}@keyframes sui-modal-backdrop-in{0%{opacity:0}to{opacity:1}}@keyframes sui-modal-container-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.sui-modal__container:focus{outline:none}@media(max-width:768px){.sui-modal{align-items:center;justify-content:center;padding:max(16px,env(safe-area-inset-top,16px)) max(16px,env(safe-area-inset-right,16px)) max(16px,env(safe-area-inset-bottom,16px)) max(16px,env(safe-area-inset-left,16px));box-sizing:border-box}.sui-modal__container{width:100%;max-width:100%;max-height:calc(50dvh - 16px);overflow:hidden;display:flex;flex-direction:column}.sui-modal__body{overflow-y:auto;flex:1 1 auto;max-height:calc(50dvh - 100px);-webkit-overflow-scrolling:touch;overscroll-behavior:contain}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen){max-height:calc(100dvh - 16px)}:host-context(html.platform-android) .sui-modal--kb-open .sui-modal__container:not(.sui-modal__container--fullscreen) .sui-modal__body{max-height:calc(100dvh - 200px)}.sui-modal__header,::ng-deep [slot=footer],.sui-modal__footer{flex-shrink:0}.sui-modal:has(.sui-modal__container--fullscreen){align-items:stretch;justify-content:stretch;padding:env(safe-area-inset-top,0px) 0 0}:host-context(html.platform-android) .sui-modal:has(.sui-modal__container--fullscreen){padding-bottom:var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px))}.sui-modal__container--fullscreen,.sui-modal__container--fullscreen[data-sui-size=small],.sui-modal__container--fullscreen[data-sui-size=medium],.sui-modal__container--fullscreen[data-sui-size=large],.sui-modal__container--fullscreen[data-sui-size=xlarge]{width:100%;max-width:100%;height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--sui-keyboard-h, 0px));border-radius:24px;transition:height .22s ease,max-height .22s ease}:host-context(html.platform-android) .sui-modal__container--fullscreen,:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=small],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=medium],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=large],:host-context(html.platform-android) .sui-modal__container--fullscreen[data-sui-size=xlarge]{height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)));max-height:calc(100dvh - env(safe-area-inset-top,0px) - var(--safe-area-inset-bottom, env(safe-area-inset-bottom, 0px)))}.sui-modal__container--fullscreen .sui-modal__body{max-height:none;flex:1 1 auto;min-height:0;overflow-y:auto}}\n"] }]
11055
11138
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], closeOnBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdrop", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], iconVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconVariant", required: false }] }], headerIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerIcon", required: false }] }], statusAlignment: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusAlignment", required: false }] }], backdropBlur: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropBlur", required: false }] }], fullscreen: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullscreen", required: false }] }], fullBody: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullBody", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], containerRef: [{
11056
11139
  type: ViewChild,
11057
11140
  args: ['container']
@@ -11060,81 +11143,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
11060
11143
  args: ['bodyEl']
11061
11144
  }] } });
11062
11145
 
11063
- const VARIANT_ICON = {
11064
- info: 'information-fill',
11065
- success: 'checkbox-circle-fill',
11066
- warning: 'alert-fill',
11067
- error: 'error-warning-fill',
11068
- };
11069
- /**
11070
- * SUI Modal Header — SUI Design System 2.0
11071
- *
11072
- * Figma file: 8p1k72aKKvzJV4XcvPS4VO
11073
- * Component set: 466:4778 ("Modal Header [1.1]") — 6 Types × 2 Sizes
11074
- * Types: Basic · Left Icon · Error · Warning · Success · Information
11075
- * Sizes: Medium (80, title 14/20 Medium + description 12/16) · Small (56, solo title)
11076
- *
11077
- * Componente STANDALONE para componer modales/paneles custom — el mismo header
11078
- * que sui-modal renderiza internamente, ahora como pieza independiente (igual
11079
- * que drawer-header/drawer-footer para drawers).
11080
- *
11081
- * EXACT (Figma 466:4777 medium / 472:298 small):
11082
- * Container bg white-0 · border-bottom stroke-soft-200 · flex gap-16
11083
- * (small: gap-12) · padding 16px 16px 16px 20px
11084
- * Title Inter Medium 14/20 ls -0.084px, text-strong-950
11085
- * Description Inter Regular 12/16, text-sub-600 (solo medium)
11086
- * Status icon círculo padding-10 radius-full, state lighter bg + base color
11087
- * (mismos tokens que sui-modal)
11088
- * Close compact button ghost (icon close-line 20), top-right
11089
- *
11090
- * Tipos: `iconVariant` (semántico) o `icon` (custom, tipo Left Icon).
11091
- * `icon` custom tiene prioridad; con ambos null → Basic (sin icono).
11092
- *
11093
- * Usage:
11094
- * <sui-modal-header title="Editar producto" description="Cambios en vivo."
11095
- * iconVariant="info" (closed)="cerrar()" />
11096
- * <sui-modal-header size="small" title="Filtros" (closed)="cerrar()" />
11097
- */
11098
- class SuiModalHeader {
11099
- /** Título del header (14/20 Medium). */
11100
- title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
11101
- /** Descripción bajo el título (solo size medium). */
11102
- description = input(null, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
11103
- /** medium (80): title + description · small (56): solo title. */
11104
- size = input('medium', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
11105
- /** Icono semántico de status (círculo state lighter/base). */
11106
- iconVariant = input(null, ...(ngDevMode ? [{ debugName: "iconVariant" }] : /* istanbul ignore next */ []));
11107
- /** Icono custom (tipo "Left Icon" de Figma). Prioridad sobre iconVariant. */
11108
- icon = input(null, ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
11109
- /** Muestra el botón de cerrar (default true). */
11110
- showClose = input(true, ...(ngDevMode ? [{ debugName: "showClose" }] : /* istanbul ignore next */ []));
11111
- /** Click en el botón de cerrar. */
11112
- closed = output();
11113
- iconName = computed(() => {
11114
- const custom = this.icon();
11115
- if (custom)
11116
- return custom;
11117
- const v = this.iconVariant();
11118
- return v ? VARIANT_ICON[v] : null;
11119
- }, ...(ngDevMode ? [{ debugName: "iconName" }] : /* istanbul ignore next */ []));
11120
- /** Variant efectivo para el data-attr del círculo (custom icon = neutral). */
11121
- resolvedVariant = computed(() => {
11122
- if (this.icon())
11123
- return 'neutral';
11124
- return this.iconVariant();
11125
- }, ...(ngDevMode ? [{ debugName: "resolvedVariant" }] : /* istanbul ignore next */ []));
11126
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalHeader, deps: [], target: i0.ɵɵFactoryTarget.Component });
11127
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SuiModalHeader, isStandalone: true, selector: "sui-modal-header", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, iconVariant: { classPropertyName: "iconVariant", publicName: "iconVariant", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, showClose: { classPropertyName: "showClose", publicName: "showClose", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "attr.title": "null", "attr.data-sui-size": "size()" } }, ngImport: i0, template: "@if (iconName(); as name) {\n <span class=\"sui-modal-header__icon\" [attr.data-variant]=\"resolvedVariant()\" aria-hidden=\"true\">\n <sui-icon [name]=\"name\" [size]=\"20\" />\n </span>\n}\n\n<div class=\"sui-modal-header__titles\">\n <h2 class=\"sui-modal-header__title\">{{ title() }}</h2>\n @if (size() === 'medium' && description(); as desc) {\n <p class=\"sui-modal-header__description\">{{ desc }}</p>\n }\n</div>\n\n@if (showClose()) {\n <sui-compact-button\n class=\"sui-modal-header__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"closed.emit()\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:16px;padding:16px 16px 16px 20px;background:var(--sui-bg-white-0, #fff);border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb)}:host[data-sui-size=small]{gap:12px}.sui-modal-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal-header__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal-header__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal-header__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal-header__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal-header__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f5f7fa);color:var(--sui-icon-sub-600, #5c5c5c)}.sui-modal-header__titles{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:4px}.sui-modal-header__title{margin:0;font-size:14px;line-height:20px;font-weight:500;letter-spacing:-.084px;color:var(--sui-text-strong-950, #171717);overflow-wrap:break-word}.sui-modal-header__description{margin:0;font-size:12px;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);overflow-wrap:break-word}.sui-modal-header__close{flex-shrink:0;align-self:flex-start}\n"], dependencies: [{ kind: "component", type: SuiIcon, selector: "sui-icon", inputs: ["name", "size", "color"] }, { kind: "component", type: SuiCompactButton, selector: "sui-compact-button", inputs: ["icon", "variantStyle", "size", "fullRadius", "disabled", "href", "target", "rel", "type", "ariaLabel"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
11128
- }
11129
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SuiModalHeader, decorators: [{
11130
- type: Component,
11131
- args: [{ selector: 'sui-modal-header', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [SuiIcon, SuiCompactButton], host: {
11132
- /* Strip native `title` attr — patrón canon (ver CLAUDE.md del proyecto). */
11133
- '[attr.title]': 'null',
11134
- '[attr.data-sui-size]': 'size()',
11135
- }, template: "@if (iconName(); as name) {\n <span class=\"sui-modal-header__icon\" [attr.data-variant]=\"resolvedVariant()\" aria-hidden=\"true\">\n <sui-icon [name]=\"name\" [size]=\"20\" />\n </span>\n}\n\n<div class=\"sui-modal-header__titles\">\n <h2 class=\"sui-modal-header__title\">{{ title() }}</h2>\n @if (size() === 'medium' && description(); as desc) {\n <p class=\"sui-modal-header__description\">{{ desc }}</p>\n }\n</div>\n\n@if (showClose()) {\n <sui-compact-button\n class=\"sui-modal-header__close\"\n icon=\"close-line\"\n variantStyle=\"ghost\"\n size=\"large\"\n ariaLabel=\"Cerrar\"\n (clicked)=\"closed.emit()\"\n />\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;align-items:center;gap:16px;padding:16px 16px 16px 20px;background:var(--sui-bg-white-0, #fff);border-bottom:1px solid var(--sui-stroke-soft-200, #ebebeb)}:host[data-sui-size=small]{gap:12px}.sui-modal-header__icon{display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:10px;border-radius:var(--sui-radius-full, 999px)}.sui-modal-header__icon[data-variant=error]{background:var(--sui-state-error-lighter, #ffebec);color:var(--sui-state-error-base, #fb3748)}.sui-modal-header__icon[data-variant=warning]{background:var(--sui-state-warning-lighter, #fff3eb);color:var(--sui-state-warning-base, #fa7319)}.sui-modal-header__icon[data-variant=success]{background:var(--sui-state-success-lighter, #e3f7ec);color:var(--sui-state-success-base, #1fc16b)}.sui-modal-header__icon[data-variant=info]{background:var(--sui-state-information-lighter, #ebf1ff);color:var(--sui-state-information-base, #335cff)}.sui-modal-header__icon[data-variant=neutral]{background:var(--sui-bg-weak-50, #f5f7fa);color:var(--sui-icon-sub-600, #5c5c5c)}.sui-modal-header__titles{flex:1 1 0;min-width:0;display:flex;flex-direction:column;gap:4px}.sui-modal-header__title{margin:0;font-size:14px;line-height:20px;font-weight:500;letter-spacing:-.084px;color:var(--sui-text-strong-950, #171717);overflow-wrap:break-word}.sui-modal-header__description{margin:0;font-size:12px;line-height:16px;color:var(--sui-text-sub-600, #5c5c5c);overflow-wrap:break-word}.sui-modal-header__close{flex-shrink:0;align-self:flex-start}\n"] }]
11136
- }], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], iconVariant: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconVariant", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
11137
-
11138
11146
  /**
11139
11147
  * SUI Modal Footer — SUI Design System 2.0
11140
11148
  *