@ajuarezso/sui-design-system 0.18.4 → 0.18.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ajuarezso/sui-design-system",
3
- "version": "0.18.4",
3
+ "version": "0.18.7",
4
4
  "description": "SUI Design System — librería de componentes Angular (SUI 2.0).",
5
5
  "license": "UNLICENSED",
6
6
  "publishConfig": {
@@ -1759,7 +1759,7 @@ declare class SuiButton {
1759
1759
  readonly disabled: _angular_core.InputSignal<boolean>;
1760
1760
  readonly leftIcon: _angular_core.InputSignal<string | null>;
1761
1761
  readonly rightIcon: _angular_core.InputSignal<string | null>;
1762
- readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
1762
+ readonly type: _angular_core.InputSignal<"reset" | "submit" | "button">;
1763
1763
  /** Intercept click/Enter/Space — cuando type=submit, busca el form padre y
1764
1764
  dispara requestSubmit(). Reset hace lo mismo con form.reset(). Disabled
1765
1765
  bloquea todo. */
@@ -2265,7 +2265,7 @@ declare class SuiLinkButton {
2265
2265
  readonly href: _angular_core.InputSignal<string | null>;
2266
2266
  readonly target: _angular_core.InputSignal<string | null>;
2267
2267
  readonly rel: _angular_core.InputSignal<string | null>;
2268
- readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
2268
+ readonly type: _angular_core.InputSignal<"reset" | "submit" | "button">;
2269
2269
  readonly ariaLabel: _angular_core.InputSignal<string | null>;
2270
2270
  readonly clicked: _angular_core.OutputEmitterRef<MouseEvent>;
2271
2271
  readonly iconSize: _angular_core.Signal<number>;
@@ -3171,7 +3171,7 @@ declare class SuiCompactButton {
3171
3171
  readonly href: _angular_core.InputSignal<string | null>;
3172
3172
  readonly target: _angular_core.InputSignal<string | null>;
3173
3173
  readonly rel: _angular_core.InputSignal<string | null>;
3174
- readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
3174
+ readonly type: _angular_core.InputSignal<"reset" | "submit" | "button">;
3175
3175
  readonly ariaLabel: _angular_core.InputSignal<string>;
3176
3176
  readonly clicked: _angular_core.OutputEmitterRef<MouseEvent>;
3177
3177
  readonly iconSize: _angular_core.Signal<number>;
@@ -5259,7 +5259,7 @@ declare class SuiFancyButton {
5259
5259
  readonly href: _angular_core.InputSignal<string | null>;
5260
5260
  readonly target: _angular_core.InputSignal<string | null>;
5261
5261
  readonly rel: _angular_core.InputSignal<string | null>;
5262
- readonly htmlType: _angular_core.InputSignal<"button" | "submit" | "reset">;
5262
+ readonly htmlType: _angular_core.InputSignal<"reset" | "submit" | "button">;
5263
5263
  readonly ariaLabel: _angular_core.InputSignal<string | null>;
5264
5264
  readonly clicked: _angular_core.OutputEmitterRef<MouseEvent>;
5265
5265
  readonly iconSize: _angular_core.Signal<number>;
@@ -5576,7 +5576,7 @@ declare class SuiFileUpload {
5576
5576
  protected readonly inputRef: _angular_core.Signal<ElementRef<HTMLInputElement> | undefined>;
5577
5577
  protected readonly dragging: _angular_core.WritableSignal<boolean>;
5578
5578
  protected readonly internalError: _angular_core.WritableSignal<string | null>;
5579
- protected readonly state: _angular_core.Signal<"default" | "error" | "disabled" | "dragover">;
5579
+ protected readonly state: _angular_core.Signal<"dragover" | "error" | "default" | "disabled">;
5580
5580
  protected readonly resolvedTitle: _angular_core.Signal<string>;
5581
5581
  protected readonly resolvedSubtitle: _angular_core.Signal<string>;
5582
5582
  protected readonly resolvedErrorMessage: _angular_core.Signal<string | null>;
@@ -6226,7 +6226,7 @@ declare class SuiImageUpload {
6226
6226
  * (matchea el escalado del contenedor 32→40 en SCSS). */
6227
6227
  protected readonly iconSize: _angular_core.Signal<20 | 16>;
6228
6228
  protected readonly hasSrc: _angular_core.Signal<boolean>;
6229
- protected readonly state: _angular_core.Signal<"filled" | "disabled" | "dragover" | "empty">;
6229
+ protected readonly state: _angular_core.Signal<"dragover" | "filled" | "disabled" | "empty">;
6230
6230
  protected readonly resolvedTitle: _angular_core.Signal<string>;
6231
6231
  protected readonly resolvedSubtitle: _angular_core.Signal<string>;
6232
6232
  onHostClick(): void;
@@ -7042,6 +7042,32 @@ declare class SuiKeyIcon {
7042
7042
  * contenido desde scrollTop 0 (solo por handle). Aquí SÍ soportamos ese
7043
7043
  * handoff (patrón Apple Maps nativo) vía touchmove no-pasivo + takeover.
7044
7044
  *
7045
+ * ── Modelo de movimiento (2026-09) ──────────────────────────────────────────
7046
+ *
7047
+ * Dos capas: `.sui-sheet` es un marco FIJO de alto constante
7048
+ * H = min(contenido, maxBreakpoint·100dvh, viewport − safe-top − 16px), anclado
7049
+ * abajo, que recorta (radius + squircle) y no captura toques; adentro,
7050
+ * `.sui-sheet__panel` (fondo, asa y body) es lo único que se mueve, con la
7051
+ * propiedad `translate` (compositor):
7052
+ *
7053
+ * y(p) = max(0, H − p·vh) visible(p) = min(H, p·vh)
7054
+ *
7055
+ * donde vh es el alto del viewport en px. Así al 25% se ven 25dvh del sheet, la
7056
+ * parte que baja queda recortada por el marco (las esquinas inferiores
7057
+ * redondeadas siguen a la vista, como antes) y el área libre del viewport sigue
7058
+ * siendo del contenido de fondo. Misma semántica que la versión anterior, que
7059
+ * animaba `max-height`, pero sin layout por frame: durante el drag no se toca
7060
+ * ningún signal ni binding — el `translate` del panel y la opacidad del
7061
+ * backdrop se escriben directo en el DOM dentro de un requestAnimationFrame
7062
+ * coalescido (una escritura por frame, gana el último pointermove). Los signals
7063
+ * `progress`, `currentBreakpoint` y `dragging` cambian al empezar/terminar el
7064
+ * drag y al snap, no por movimiento.
7065
+ *
7066
+ * Se usa `translate` (propiedad individual) y NO `transform`, y sobre el panel
7067
+ * y no sobre `.sui-sheet`: un consumer puede seguir escribiendo su propio
7068
+ * `transform`/`left`/`width` sobre `.sui-sheet` (ej. centrarlo en desktop) sin
7069
+ * pisar el movimiento.
7070
+ *
7045
7071
  * Uso típico para tracking de pedido con mapa abajo:
7046
7072
  * ```html
7047
7073
  * <sui-modal-sheet
@@ -7057,6 +7083,7 @@ declare class SuiKeyIcon {
7057
7083
  */
7058
7084
  declare class SuiModalSheet implements OnDestroy {
7059
7085
  private readonly doc;
7086
+ private readonly renderer;
7060
7087
  private readonly navbarVisibility;
7061
7088
  /** ID único por instancia para el counter centralizado del navbar. */
7062
7089
  private readonly _sheetId;
@@ -7083,53 +7110,90 @@ declare class SuiModalSheet implements OnDestroy {
7083
7110
  readonly fullBody: _angular_core.InputSignal<boolean>;
7084
7111
  readonly closed: _angular_core.OutputEmitterRef<void>;
7085
7112
  readonly breakpointChange: _angular_core.OutputEmitterRef<number>;
7113
+ /** Marco fijo que recorta; se mide acá (alto H). */
7086
7114
  containerRef?: ElementRef<HTMLElement>;
7115
+ /** Capa que se mueve (`translate`). */
7116
+ panelRef?: ElementRef<HTMLElement>;
7117
+ backdropRef?: ElementRef<HTMLElement>;
7087
7118
  handleRef?: ElementRef<HTMLElement>;
7088
7119
  bodyRef?: ElementRef<HTMLElement>;
7089
7120
  /** Breakpoint actual (0-1). Cambia al snap, no durante el drag. */
7090
7121
  readonly currentBreakpoint: _angular_core.WritableSignal<number>;
7091
- /** Progress en vivo durante el drag (0-1). Expuesto como readonly al
7092
- template (binding `--sheet-progress`) y al public para que el consumer
7093
- pueda leerlo si quiere reaccionar. */
7094
- protected readonly liveProgress: _angular_core.WritableSignal<number>;
7122
+ /** Progress EN REPOSO (0-1): el breakpoint al que el sheet está o hacia el
7123
+ que va. Durante el drag NO se actualiza (el movimiento vive en el DOM,
7124
+ ver header): cambia al soltar y al snap. Expuesto al template como
7125
+ `--sheet-progress` y al consumer como `progress`. */
7126
+ protected readonly restProgress: _angular_core.WritableSignal<number>;
7095
7127
  readonly progress: _angular_core.Signal<number>;
7096
- /** True mientras el usuario está arrastrando. Desactiva CSS transition. */
7128
+ /** True mientras el usuario está arrastrando. Se setea al arrancar y al
7129
+ soltar; la clase CSS que apaga la transición se maneja imperativa en el
7130
+ mismo tick que la escritura del `translate` (ver `beginDrag`/`snapTo`). */
7097
7131
  readonly dragging: _angular_core.WritableSignal<boolean>;
7098
- /** Opacity del backdrop calculada según el progress vivo. */
7132
+ /** Opacity del backdrop para el progress en reposo. La opacidad viva del
7133
+ drag se escribe directo en el DOM; este computed queda como API. */
7099
7134
  readonly backdropOpacity: _angular_core.Signal<number>;
7100
7135
  /** True si el backdrop debe capturar pointer events (current > backdropBreakpoint). */
7101
7136
  readonly backdropInteractive: _angular_core.Signal<boolean>;
7102
- /** CAP de altura del sheet — `min(progress·100dvh, viewport - safe-top - 16)`.
7103
- Se bindea como max-height con `height: max-content` en el scss: el sheet
7104
- NUNCA mide más que su contenido (sin espacio vacío al final cuando el
7105
- contenido termina antes del breakpoint), y el breakpoint actúa como techo.
7106
- Cuando progress=0.25 el sheet ocupa a lo sumo 25dvh y el resto del
7107
- viewport queda VACÍO → contenido detrás (mapa) interactivo. */
7108
- readonly heightCss: _angular_core.Signal<string>;
7137
+ /** Breakpoint máximo del array (1 si está vacío). */
7138
+ private readonly maxBreakpoint;
7139
+ /** CAP ESTÁTICO de altura — `min(maxBp·100dvh, viewport − safe-top − 16)`.
7140
+ Con `height: max-content` en el scss el sheet mide su contenido y este
7141
+ techo lo acota. Depende solo de `breakpoints`: no cambia por drag ni por
7142
+ snap, así que no fuerza layout durante el gesto. */
7143
+ readonly maxHeightCss: _angular_core.Signal<string>;
7109
7144
  /** True cuando el sheet está al breakpoint máximo del array. En ese punto
7110
7145
  habilitamos scroll del body (touch-action: pan-y) — el user ya no puede
7111
7146
  expandir más, así que se prioriza ver el contenido sobre el drag. En el
7112
7147
  resto de breakpoints el body actúa como handle gigante (touch-action:
7113
- none) y solo el drag controla la altura del sheet. */
7148
+ none) y solo el drag controla la posición del sheet. */
7114
7149
  readonly atMaxBreakpoint: _angular_core.Signal<boolean>;
7150
+ /** Alto medido del sheet (px). Se mide al abrir, al empezar un drag y
7151
+ cuando el contenido cambia de tamaño (ResizeObserver). */
7152
+ private sheetHeight;
7153
+ /** Alto del viewport (px) = 1 unidad de progress. */
7154
+ private viewportHeight;
7115
7155
  private dragStartY;
7116
7156
  private dragStartProgress;
7117
- private wrapperHeight;
7118
7157
  private pointerId;
7119
7158
  /** Para calcular velocity al final */
7120
7159
  private lastMoveTime;
7121
7160
  private lastMoveY;
7122
7161
  private velocityY;
7162
+ /** Último progress pedido por el dedo; lo consume el rAF. */
7163
+ private pendingProgress;
7164
+ private frameId;
7123
7165
  /** Flag para distinguir drag iniciado en body (scroll-then-drag) vs en handle.
7124
7166
  En body, el drag NO arranca con pointerdown — sólo si pointermove
7125
7167
  excede un threshold y la condición de scroll lo permite. Sirve para no
7126
7168
  robar tap/click a buttons internos. */
7127
7169
  private bodyDragArmed;
7128
7170
  /** Threshold de movimiento (px) para decidir que un pointermove en body es
7129
- drag (no tap). Patrón iOS estándar ~6-10px. */
7171
+ drag (no tap). 5px = más sensible que el iOS canon de 8px: el dueño pidió
7172
+ "como nativo" y el 8 sentía que tardaba en activar. Trade-off: 5px puede
7173
+ activar drag con micro-movements al hacer tap, pero la heurística
7174
+ shouldIgnoreBodyDrag protege inputs/select/option. */
7130
7175
  private static readonly BODY_DRAG_THRESHOLD_PX;
7176
+ /** Lookahead de velocidad al soltar (ms): predice dónde estaría el dedo y
7177
+ snapea ahí. Permite que un swipe rápido brinque breakpoints sin saltarse
7178
+ los intermedios. 80ms validado en device: a 150 se saltaba el 0.7 entre
7179
+ 0.5 y 1; a 0 el sheet se sentía pesado. */
7180
+ private static readonly VELOCITY_LOOKAHEAD_MS;
7181
+ /** Duración del snap: se acota entre estos dos valores según distancia
7182
+ restante / velocidad del dedo (ver `snapDuration`). */
7183
+ private static readonly SNAP_MIN_MS;
7184
+ private static readonly SNAP_MAX_MS;
7185
+ private static readonly CLASS_PANEL_DRAGGING;
7186
+ private static readonly CLASS_BACKDROP_DRAGGING;
7187
+ /** Cerrado = el panel baja todo su alto y el marco lo recorta entero. Se usa
7188
+ `100%` (y no el H medido) para que el cierre quede bien aunque el
7189
+ contenido cambie de tamaño a mitad de camino. */
7190
+ private static readonly TRANSLATE_CLOSED;
7131
7191
  private wasOpen;
7132
7192
  private escapeHandler?;
7193
+ private closeTimer;
7194
+ private closeTransitionHandler?;
7195
+ private resizeObserver?;
7196
+ private windowResizeHandler?;
7133
7197
  constructor();
7134
7198
  ngOnDestroy(): void;
7135
7199
  /** Mueve el sheet a un breakpoint específico programáticamente.
@@ -7143,6 +7207,40 @@ declare class SuiModalSheet implements OnDestroy {
7143
7207
  private touchMoveHandler?;
7144
7208
  private attachTouchSuppressor;
7145
7209
  private detachTouchSuppressor;
7210
+ /** Mide alto del sheet y del viewport. Devuelve false si todavía no hay
7211
+ layout (container sin render o entorno sin medidas, ej. jsdom). Es la
7212
+ ÚNICA lectura de layout del gesto: se hace al abrir, al pointerdown y
7213
+ cuando cambia el tamaño — nunca por pointermove. */
7214
+ private measure;
7215
+ /** Desplazamiento vertical (px) para un progress: `max(0, H − p·vh)`. */
7216
+ private yFor;
7217
+ /** Valor de `translate` para un progress. */
7218
+ private translateFor;
7219
+ /** Progress EFECTIVO de un breakpoint: el que corresponde al y que el sheet
7220
+ muestra de verdad. Con contenido corto varios breakpoints valen y = 0 y
7221
+ su progress efectivo es H/vh, no el nominal — es el punto de partida
7222
+ correcto para que el dedo mueva 1:1 desde ahí. */
7223
+ private effectiveProgress;
7224
+ /** Progress real del sheet leyendo el `translate` computado del panel —
7225
+ sirve para agarrarlo a mitad de una transición sin que salte al
7226
+ breakpoint de destino. Si no se puede leer (jsdom, valor no numérico,
7227
+ un calc() a mitad de la entrada) cae al progress efectivo del
7228
+ `currentBreakpoint`. */
7229
+ private progressFromDom;
7230
+ private writeTranslate;
7231
+ private writeBackdropOpacity;
7232
+ private setTransitionDuration;
7233
+ private setDraggingClasses;
7234
+ /** Coalesce: guarda el último progress y escribe UNA vez por frame. */
7235
+ private scheduleFrame;
7236
+ private flushFrame;
7237
+ private cancelFrame;
7238
+ private observeSize;
7239
+ private stopObservingSize;
7240
+ private onSizeChange;
7241
+ /** Arranque común del drag (handle o body ya armado): congela la transición
7242
+ en curso, lee la posición real y marca `dragging`. */
7243
+ private beginDrag;
7146
7244
  protected onPointerDown(event: PointerEvent): void;
7147
7245
  protected onPointerMove(event: PointerEvent): void;
7148
7246
  protected onPointerUp(event: PointerEvent): void;
@@ -7152,8 +7250,26 @@ declare class SuiModalSheet implements OnDestroy {
7152
7250
  /** Heurística: ignorar drag si el target es un input/textarea/select/button
7153
7251
  interactivo. El user está intentando interactuar, no arrastrar. */
7154
7252
  private shouldIgnoreBodyDrag;
7253
+ /** Duración del snap en función de la distancia restante y la velocidad del
7254
+ dedo (px/ms): un fling rápido cierra la distancia en poco tiempo; un
7255
+ release lento o un snap programático usa la duración larga. Acotado a
7256
+ [180, 350] ms. */
7257
+ private snapDuration;
7258
+ /**
7259
+ * Lleva el sheet a `breakpoint`.
7260
+ * @param fromProgress progress desde el que sale (default: el de reposo);
7261
+ * solo influye en la duración.
7262
+ * @param velocityPxMs velocidad del dedo al soltar, para acortar el snap.
7263
+ */
7155
7264
  private snapTo;
7156
- private findClosestBreakpoint;
7265
+ private scheduleClose;
7266
+ private cancelPendingClose;
7267
+ /** Breakpoint cuyo desplazamiento (`yFor`) queda más cerca de `y`. Varios
7268
+ breakpoints pueden compartir el mismo y (todos los que superan el alto
7269
+ del contenido valen 0): en ese empate gana el actual si está entre
7270
+ ellos, si no el mayor — así un toque-arrastre al máximo no cambia de
7271
+ breakpoint ni apaga el scroll del body. */
7272
+ private closestBreakpointByY;
7157
7273
  /** Fórmula linear entre (backdropBreakpoint, 0) y (1, 1). Igual que Ionic. */
7158
7274
  private computeBackdropOpacity;
7159
7275
  protected onBackdropClick(): void;
@@ -7795,7 +7911,7 @@ declare class SuiNotification {
7795
7911
  readonly dismissible: _angular_core.InputSignal<boolean>;
7796
7912
  readonly unread: _angular_core.InputSignal<boolean>;
7797
7913
  /** Item body type. 'basic' keeps the legacy/alert layout (no body slot). */
7798
- readonly type: _angular_core.InputSignal<"basic" | "file" | "button" | "message">;
7914
+ readonly type: _angular_core.InputSignal<"message" | "button" | "basic" | "file">;
7799
7915
  /** When true, item paints the Figma hover bg + reveals the more-2-line button. */
7800
7916
  readonly showMore: _angular_core.InputSignal<boolean>;
7801
7917
  /** Forces the hover affordance visible (e.g. keyboard-focused row). */
@@ -9719,7 +9835,7 @@ declare class SuiSocialButton {
9719
9835
  readonly href: _angular_core.InputSignal<string | null>;
9720
9836
  readonly target: _angular_core.InputSignal<string | null>;
9721
9837
  readonly rel: _angular_core.InputSignal<string | null>;
9722
- readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
9838
+ readonly type: _angular_core.InputSignal<"reset" | "submit" | "button">;
9723
9839
  readonly ariaLabel: _angular_core.InputSignal<string | null>;
9724
9840
  readonly clicked: _angular_core.OutputEmitterRef<MouseEvent>;
9725
9841
  /** Disabled efectivo: el input disabled O el estado loading. */