@ajuarezso/sui-design-system 0.20.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/INDEX.md +75 -80
- package/docs/sui-accordion/README.md +171 -0
- package/docs/sui-activity-feed/README.md +155 -0
- package/docs/sui-activity-filter/README.md +100 -0
- package/docs/sui-alert/README.md +13 -0
- package/docs/sui-badge/README.md +17 -0
- package/docs/sui-banner/README.md +190 -0
- package/docs/sui-breadcrumb-item/README.md +96 -0
- package/docs/sui-breadcrumbs/README.md +122 -0
- package/docs/sui-button/README.md +36 -0
- package/docs/sui-card/README.md +168 -0
- package/docs/sui-chart-legend/README.md +140 -0
- package/docs/sui-chart-legend-dot/README.md +118 -0
- package/docs/sui-checkbox-card/README.md +150 -0
- package/docs/sui-command-menu-footer/README.md +100 -0
- package/docs/sui-command-menu-item/README.md +140 -0
- package/docs/sui-command-menu-search/README.md +105 -0
- package/docs/sui-compact-select/README.md +130 -0
- package/docs/sui-compact-select-for-input/README.md +120 -0
- package/docs/sui-content-card/README.md +147 -0
- package/docs/sui-content-label/README.md +148 -0
- package/docs/sui-counter-input/README.md +148 -0
- package/docs/sui-date-selector/README.md +98 -0
- package/docs/sui-datepicker/README.md +197 -0
- package/docs/sui-day-cell/README.md +118 -0
- package/docs/sui-day-label/README.md +81 -0
- package/docs/sui-drawer-footer/README.md +127 -0
- package/docs/sui-drawer-header/README.md +140 -0
- package/docs/sui-dropdown-caption/README.md +92 -0
- package/docs/sui-dropdown-item/README.md +163 -0
- package/docs/sui-dropdown-menu/README.md +196 -0
- package/docs/sui-dropdown-search/README.md +113 -0
- package/docs/sui-empty-state/README.md +145 -0
- package/docs/sui-file-upload/README.md +154 -0
- package/docs/sui-file-upload-card/README.md +129 -0
- package/docs/sui-filter/README.md +181 -0
- package/docs/sui-href/README.md +85 -0
- package/docs/sui-image-upload/README.md +200 -0
- package/docs/sui-image-upload-profile/README.md +145 -0
- package/docs/sui-img-retry/README.md +107 -0
- package/docs/sui-inline-input/README.md +104 -0
- package/docs/sui-inline-select/README.md +101 -0
- package/docs/sui-input/README.md +247 -0
- package/docs/sui-integration-switch/README.md +142 -0
- package/docs/sui-modal/README.md +238 -0
- package/docs/sui-modal-footer/README.md +178 -0
- package/docs/sui-modal-header/README.md +115 -0
- package/docs/sui-modal-sheet/README.md +170 -0
- package/docs/sui-notification/README.md +179 -0
- package/docs/sui-notification-footer/README.md +98 -0
- package/docs/sui-notification-tab-menu/README.md +112 -0
- package/docs/sui-otp-input/README.md +116 -0
- package/docs/sui-page-header/README.md +123 -0
- package/docs/sui-pagination/README.md +146 -0
- package/docs/sui-password-strength/README.md +99 -0
- package/docs/sui-period-range/README.md +93 -0
- package/docs/sui-popover/README.md +178 -0
- package/docs/sui-product-card/README.md +173 -0
- package/docs/sui-radio-card/README.md +160 -0
- package/docs/sui-rating/README.md +7 -6
- package/docs/sui-rich-editor/README.md +114 -0
- package/docs/sui-segmented-control/README.md +3 -0
- package/docs/sui-select/README.md +183 -0
- package/docs/sui-sidebar/README.md +217 -0
- package/docs/sui-stepper/README.md +166 -0
- package/docs/sui-store-card/README.md +147 -0
- package/docs/sui-switch-card/README.md +149 -0
- package/docs/sui-switch-label/README.md +3 -0
- package/docs/sui-tab-chips/README.md +188 -0
- package/docs/sui-tab-menu-horizontal/README.md +142 -0
- package/docs/sui-tab-menu-vertical/README.md +136 -0
- package/docs/sui-table/README.md +264 -0
- package/docs/sui-tag-input/README.md +123 -0
- package/docs/sui-textarea/README.md +160 -0
- package/docs/sui-time-picker/README.md +240 -0
- package/docs/sui-toast/README.md +190 -0
- package/docs/sui-tooltip/README.md +201 -0
- package/docs/sui-topbar/README.md +153 -0
- package/docs/sui-topbar-button/README.md +95 -0
- package/docs/sui-topbar-item/README.md +97 -0
- package/docs/sui-topbar-user/README.md +83 -0
- package/fesm2022/ajuarezso-sui-design-system.mjs +291 -246
- package/fesm2022/ajuarezso-sui-design-system.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ajuarezso-sui-design-system.d.ts +208 -50
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-href
|
|
3
|
+
selector: a[suiHref]
|
|
4
|
+
resumen: Directiva para los <a> del DS que reciben un href configurable; los links internos navegan con el Router sin recargar la app
|
|
5
|
+
alternativas: [routerLink (link interno escrito en la plantilla de la app), sui-link-button (acción con forma de link, ya usa suiHref por dentro)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-href
|
|
9
|
+
|
|
10
|
+
Story: [Utilities/Href](https://sui-design-system.web.app/?path=/docs/utilities-href--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** dentro de un componente del DS que recibe un `href` por input y lo pinta en un `<a>`:
|
|
15
|
+
en vez de `[attr.href]="href()"`, `[suiHref]="href()"`. Así un `href="/cliente/pedidos"` que
|
|
16
|
+
viene de la app navega **sin recargar el WebView** (en Capacitor, una recarga pierde el estado y
|
|
17
|
+
tarda segundos) y uno externo se abre normal.
|
|
18
|
+
|
|
19
|
+
Ya lo usan `sui-link-button`, `sui-compact-button`, `sui-fancy-button`, `sui-social-button`,
|
|
20
|
+
`sui-breadcrumb-item`, `sui-topbar-item`, `sui-brand-logo`, `sui-app-store-badge`, `sui-rating` y
|
|
21
|
+
`sui-progress-bar-label`.
|
|
22
|
+
|
|
23
|
+
**No lo uses** para:
|
|
24
|
+
|
|
25
|
+
- Un link interno que escribes en una plantilla de la app: `routerLink`. Es lo que usa la app
|
|
26
|
+
(98 usos, 0 de `suiHref` el 03-10-2026) y además marca el link activo.
|
|
27
|
+
- Un botón que ejecuta algo: `sui-button` o `sui-link-button` con `(clicked)`.
|
|
28
|
+
|
|
29
|
+
## Qué variante usar
|
|
30
|
+
|
|
31
|
+
> **No está en la guía del DS: es una utilidad de SUI**, sin Figma ni variantes.
|
|
32
|
+
|
|
33
|
+
No tiene variantes. Lo que decide qué hace es la URL:
|
|
34
|
+
|
|
35
|
+
| `suiHref` | qué hace al tocarlo | fuente |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| empieza con `/` (no `//`) | `router.navigateByUrl()`: navegación dentro de la app, conserva query y `#` | componente |
|
|
38
|
+
| `https://…`, `mailto:`, `tel:`, `#…`, `//host` | lo que haga el navegador | componente |
|
|
39
|
+
| cualquiera, con `target` distinto de `_self` | lo que haga el navegador (nueva pestaña) | componente |
|
|
40
|
+
| cualquiera, con cmd/ctrl/shift/alt o botón del medio | lo que haga el navegador | componente |
|
|
41
|
+
| `null` o `''` | el `<a>` queda **sin** `href` (no navegable) | componente |
|
|
42
|
+
|
|
43
|
+
## Tamaño en mobile y en web
|
|
44
|
+
|
|
45
|
+
No aplica: es una directiva, no dibuja nada. El tamaño es el del componente que la usa.
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
<!-- api:inicio -->
|
|
50
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
51
|
+
|
|
52
|
+
| input | tipo | default |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `suiHref` | `string \| null` | `null` |
|
|
55
|
+
|
|
56
|
+
Outputs: ninguno.
|
|
57
|
+
<!-- api:fin -->
|
|
58
|
+
|
|
59
|
+
Solo se aplica a `<a>` (`selector: a[suiHref]`).
|
|
60
|
+
|
|
61
|
+
## Trampas
|
|
62
|
+
|
|
63
|
+
- **El atributo `href` real queda puesto**: el clic del medio, «copiar enlace» y «abrir en
|
|
64
|
+
pestaña nueva» siguen funcionando. Solo el clic normal se intercepta.
|
|
65
|
+
- **Sin Router no intercepta nada**: en Storybook o en una app sin `provideRouter` es un `href`
|
|
66
|
+
común y corriente (recarga la página).
|
|
67
|
+
- **Si el componente ya hizo `preventDefault()`** en su propio `(click)`, la directiva no navega.
|
|
68
|
+
Útil para un link que a veces solo emite un evento.
|
|
69
|
+
- **No marca el link activo** (`routerLinkActive` no lo ve). Para menús de la app, `routerLink`.
|
|
70
|
+
- Un `href` relativo sin `/` inicial (`pedidos/123`) **no** se intercepta: lo resuelve el
|
|
71
|
+
navegador contra la URL actual y recarga. Pasa rutas absolutas.
|
|
72
|
+
|
|
73
|
+
## Ejemplo
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<!-- Dentro del template de un componente del DS -->
|
|
77
|
+
<a class="sui-link-button" [suiHref]="href()" [attr.target]="target()">
|
|
78
|
+
<ng-content />
|
|
79
|
+
</a>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<!-- Desde la app: el componente del DS ya lo resuelve -->
|
|
84
|
+
<sui-link-button href="/cliente/pedidos">Ver mis pedidos</sui-link-button>
|
|
85
|
+
```
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-image-upload
|
|
3
|
+
selector: sui-image-upload
|
|
4
|
+
resumen: Subir una imagen y ver su vista previa en el mismo lugar (logo, portada, foto de producto, comprobante)
|
|
5
|
+
alternativas: [sui-image-upload-profile (foto de perfil con botones Subir/Cambiar/Eliminar al lado), sui-file-upload (documentos que no son foto: PDF, Excel), app-image-cropper (el recortador de la app, que se abre desde el lápiz)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-image-upload
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Upload/Image Upload](https://sui-design-system.web.app/?path=/docs/molecules-upload-image-upload--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para subir **una imagen** y que la persona la vea apenas la elige: el logo y la portada
|
|
15
|
+
del local, la foto de un producto, la foto de perfil, la captura del Yape o del comprobante, el QR
|
|
16
|
+
de cobro del repartidor, el banner de una campaña.
|
|
17
|
+
|
|
18
|
+
**No lo uses** para:
|
|
19
|
+
|
|
20
|
+
- Documentos que no son foto (PDF, Excel): `sui-file-upload`.
|
|
21
|
+
- Varias imágenes a la vez: no lo soporta; una por campo.
|
|
22
|
+
- La miniatura de una opción de producto (36 px dentro de una fila): `option-image` de la app.
|
|
23
|
+
|
|
24
|
+
El archivo que entrega **no se sube tal cual**: pasa por `ImageCompressorService` (HEIC → JPEG,
|
|
25
|
+
1200 px + miniatura de 400) y, si hay que encuadrarlo, por `app-image-cropper` antes. Ver Trampas.
|
|
26
|
+
|
|
27
|
+
## Qué variante usar
|
|
28
|
+
|
|
29
|
+
> **La guía del DS no tiene página para este componente** (el «Image Upload» del Figma de origen
|
|
30
|
+
> es otra cosa: la foto con botones, que en SUI es `sui-image-upload-profile`). Todo es
|
|
31
|
+
> **propuesta, falta aprobación**.
|
|
32
|
+
>
|
|
33
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app` (sin prototipos ni vitrinas): **13 usos en
|
|
34
|
+
> 10 pantallas**. `shape`: 11 `rect`, 2 `circle`. `size`: 7 `xl`, 3 `lg`, 3 sin size (fluidos).
|
|
35
|
+
> `fluid`: 6. `editable`: 3 `true`, 2 según haya imagen, 1 `false`, 7 sin poner.
|
|
36
|
+
|
|
37
|
+
### `shape` — según cómo se va a ver la imagen después
|
|
38
|
+
|
|
39
|
+
| valor | cuándo | fuente |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `circle` (default) | **Solo la foto de una persona** (perfil del cliente, del repartidor, del usuario del local). Así se ve después en `sui-avatar`. | propuesta |
|
|
42
|
+
| `rect` | **Todo lo demás**: el logo del local (en el home se ve como cuadrado redondeado), la portada, la foto del producto, comprobantes, QR, banners. | propuesta |
|
|
43
|
+
|
|
44
|
+
### `size` y `fluid` — según la forma de la imagen
|
|
45
|
+
|
|
46
|
+
| valor | px | cuándo | fuente |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `fluid` | ancho del contenedor, alto hasta 320 | **Capturas y documentos** (comprobante, Yape, QR) y **imágenes apaisadas** (portada 16:9, banner). Una captura de celular es vertical: en un cuadrado se recorta. | propuesta |
|
|
49
|
+
| `xl` | 200 | **Imágenes cuadradas**: logo, foto del producto, foto de perfil. | propuesta |
|
|
50
|
+
| `lg` (default) | 160 | Imagen cuadrada al lado de otra cosa en la misma fila (el logo junto al nombre del local en web). | propuesta |
|
|
51
|
+
| `md` | 120 | No usar: chico para ver si la foto quedó bien. | no usar |
|
|
52
|
+
| `sm` | 80 | No usar: no entra el texto (el subtítulo se esconde). | no usar |
|
|
53
|
+
|
|
54
|
+
### `editable` — qué hace el lápiz
|
|
55
|
+
|
|
56
|
+
| valor | cuándo | fuente |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `true` | **Siempre.** Con imagen muestra dos botones a la vista: lápiz y tacho. El lápiz emite `editRequested`: si la pantalla tiene recortador, lo abre (`app-image-cropper`); si no, llama a `abrirSelector()` para elegir otra (como el Yape del repartidor). | propuesta |
|
|
59
|
+
| `false` (default) | No usar: con imagen, el lápiz aparece **solo al pasar el mouse** (en el celular no se ve) y el «Quitar» de abajo es un botón aparte (32 px). | no usar |
|
|
60
|
+
|
|
61
|
+
### Textos: `title`, `subtitle`
|
|
62
|
+
|
|
63
|
+
| input | cuándo | fuente |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `title` | Verbo + qué: «Subir logo», «Subir comprobante», «Subir captura del pago». | propuesta |
|
|
66
|
+
| `subtitle` | Formatos y tamaño, **solo los que el componente acepta** (JPG, PNG o WebP), o el encuadre que se va a aplicar («se recorta a 16:9»). Mientras procesa: «Procesando…». | propuesta |
|
|
67
|
+
|
|
68
|
+
### `maxSize`, `disabled`, `src`
|
|
69
|
+
|
|
70
|
+
| input | cuándo | fuente |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `maxSize` | Siempre, en **bytes**. 10 MB para capturas y comprobantes, 20–50 MB para fotos que se van a comprimir. | propuesta |
|
|
73
|
+
| `disabled` | Mientras se comprime o se sube (`subiendo()`), para que no se elija otra encima. | propuesta |
|
|
74
|
+
| `src` (model) | La URL guardada, o la vista previa local mientras se sube. Con `[(src)]` el componente la pone solo al elegir. | propuesta |
|
|
75
|
+
|
|
76
|
+
### Usos de hoy que rompen la propuesta
|
|
77
|
+
|
|
78
|
+
- **5 subtítulos prometen HEIC**: hasta el 03-10-2026 el componente lo rechazaba; con la versión
|
|
79
|
+
nueva del DS ya pasa (ver Trampas por la vista previa en Chrome):
|
|
80
|
+
`components/plan-change-modal/plan-change-modal.html:150`, `pages/driver/driver-wallet/driver-wallet.html:243`,
|
|
81
|
+
`pages/promociones/promociones.html:185` y `:269`, `pages/customer/order-tracking/order-tracking.html:985`.
|
|
82
|
+
- **1 logo en círculo** → `rect`: `pages/business-onboarding/step-info/step-info.html:42` (en
|
|
83
|
+
`mi-negocio.html:518` el mismo logo es `rect`, y en el home del cliente se ve cuadrado).
|
|
84
|
+
- **3 imágenes en cuadrado que deberían ir `fluid`**: comprobantes en
|
|
85
|
+
`components/plan-change-modal/plan-change-modal.html:150` y `pages/central/central-gastos/central-gastos.html:118`;
|
|
86
|
+
la portada 16:9 en `pages/mi-negocio/mi-negocio.html:572` (en el onboarding ya va `fluid`).
|
|
87
|
+
- **8 sin `editable`**: `components/avatar-editor/avatar-editor.ts:33` (pone `false` aunque tiene
|
|
88
|
+
recortador), `pages/customer/order-tracking/order-tracking.html:985` (cliente, solo celular),
|
|
89
|
+
`components/plan-change-modal/plan-change-modal.html:150`, `pages/central/central-gastos/central-gastos.html:118`,
|
|
90
|
+
`pages/promociones/promociones.html:185` y `:269`, y `pages/business-onboarding/step-info/step-info.html:42` y `:56`.
|
|
91
|
+
- **2 áreas de subida armadas a mano** que van con este componente (`rect`, `fluid`, `editable`):
|
|
92
|
+
`components/renewal-modal/renewal-modal.html:64` (comprobante, con SVG propio) y
|
|
93
|
+
`pages/products/add-product/add-product.html:223` (foto del producto, con dropzone propia).
|
|
94
|
+
No cuenta `components/option-image/option-image.ts:68`: es una miniatura de 36 px en una fila.
|
|
95
|
+
|
|
96
|
+
## Tamaño en mobile y en web
|
|
97
|
+
|
|
98
|
+
En mobile se toca con el dedo: lo que se toca mide **44 px o más**. El área vacía se toca entera
|
|
99
|
+
(80 a 200 px), así que pasa; los botones con imagen, no. En pantallas de los dos se elige con el
|
|
100
|
+
servicio de breakpoints de la app (`bp`, en `services/breakpoints.service.ts`).
|
|
101
|
+
|
|
102
|
+
| uso | mobile | web | fuente |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| comprobante, captura, QR, portada, banner | `fluid` | `fluid` (en una columna de ≤ 480 px) | propuesta |
|
|
105
|
+
| logo, foto de producto, foto de perfil | `xl` (200) | `xl` (200), o `lg` (160) al lado del nombre | propuesta |
|
|
106
|
+
| lápiz y tacho (`editable`) | 40 px (32 en `sm`) | 40 px | canon (aprobado por el dueño, 03-10-2026), extensión SUI |
|
|
107
|
+
| «Quitar» (sin `editable`) | 32 px (`sui-button` `xsmall`) | 32 px | canon (aprobado por el dueño, 03-10-2026) |
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<sui-image-upload shape="rect" [size]="bp.isMobile() ? 'xl' : 'lg'" [editable]="true"
|
|
111
|
+
[src]="logo()" [maxSize]="50 * 1024 * 1024" title="Subir logo"
|
|
112
|
+
subtitle="JPG, PNG o WebP — máx 50 MB"
|
|
113
|
+
(imageSelected)="alElegirLogo($event)" (editRequested)="abrirRecortador()"
|
|
114
|
+
(removed)="quitarLogo()" />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Desde el 03-10-2026 el lápiz y el tacho miden **40** (antes 34; en `sm`, de 80 de lado, no entran dos
|
|
118
|
+
de 40 y quedan en 32) y el «Quitar» es un `sui-button` `xsmall` de **32** (antes 28). En `circle`
|
|
119
|
+
los dos botones van centrados abajo, dentro del círculo.
|
|
120
|
+
|
|
121
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
122
|
+
|
|
123
|
+
Nada se borra del DS. Lo marcado «no usar» no tiene caso en la app de hoy; si un flujo nuevo cae
|
|
124
|
+
en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
|
|
125
|
+
|
|
126
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| `size="md"` (120) | chico para ver si la foto quedó bien | una grilla de fotos extra del producto (galería) |
|
|
129
|
+
| `size="sm"` (80) | no entra el texto | una fila de varias miniaturas con su «+» |
|
|
130
|
+
| `editable=false` | el lápiz solo aparece con el mouse; en el celular no se ve | una pantalla solo de web donde reemplazar al pasar el mouse sea lo esperado |
|
|
131
|
+
| `shape="circle"` para algo que no es una persona | el logo y los productos se ven cuadrados | — |
|
|
132
|
+
| para PDF | no muestra vista previa de documentos | — (va `sui-file-upload`) |
|
|
133
|
+
|
|
134
|
+
## API
|
|
135
|
+
|
|
136
|
+
<!-- api:inicio -->
|
|
137
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
138
|
+
|
|
139
|
+
| input | tipo | default |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `fluid` | `boolean` | `false` |
|
|
142
|
+
| `shape` | `'circle' \| 'rect'` | `'circle'` |
|
|
143
|
+
| `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'lg'` |
|
|
144
|
+
| `src` · model, `[(src)]` | `string \| null` | `null` |
|
|
145
|
+
| `maxSize` | `number` | `0` |
|
|
146
|
+
| `title` | `string \| null` | `null` |
|
|
147
|
+
| `subtitle` | `string \| null` | `null` |
|
|
148
|
+
| `disabled` | `boolean` | `false` |
|
|
149
|
+
| `editable` | `boolean` | `false` |
|
|
150
|
+
|
|
151
|
+
| output | payload |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `imageSelected` | `File` |
|
|
154
|
+
| `removed` | `void` |
|
|
155
|
+
| `editRequested` | `void` |
|
|
156
|
+
| `errorEvent` | `string` |
|
|
157
|
+
<!-- api:fin -->
|
|
158
|
+
|
|
159
|
+
Método público: `abrirSelector()` — abre el selector de archivo (para el lápiz cuando no hay
|
|
160
|
+
recortador; se llama con una referencia: `#qr` → `qr.abrirSelector()`).
|
|
161
|
+
|
|
162
|
+
## Trampas
|
|
163
|
+
|
|
164
|
+
- **Acepta HEIC/HEIF** desde el 03-10-2026 (por tipo y, como Chrome suele dejar el tipo vacío, por
|
|
165
|
+
extensión). **La vista previa de un HEIC no se ve en Chrome** (solo Safari lo dibuja): el
|
|
166
|
+
componente pone el archivo crudo como `src`, así que en Android o en la compu queda en blanco
|
|
167
|
+
hasta que la pantalla lo pasa por `ImageCompressorService` y pone el JPG en `src`.
|
|
168
|
+
- El mensaje de tipo no soportado dice «Tipo no soportado. Usa JPG, PNG, WebP, GIF o HEIC.»
|
|
169
|
+
(antes en voseo).
|
|
170
|
+
- **El default de `shape` es `circle`** y el de `size` es `lg`: para un logo o un comprobante hay
|
|
171
|
+
que pasar los dos.
|
|
172
|
+
- **Con `fluid`, `size` no hace nada** (`promociones.html:185` pasa `size="lg"` y `fluid` a la vez).
|
|
173
|
+
- **`removed` ya vacía `src`** por dentro; quien lo usa solo limpia su `File` y su estado.
|
|
174
|
+
- **Al elegir, pone la vista previa sola** (`src` = data URL) y emite el `File` original, sin
|
|
175
|
+
comprimir ni recortar. Comprimir y recortar es trabajo de la pantalla.
|
|
176
|
+
- Con imagen y sin `editable`, **el componente mide el cuadrado + 8 + 32** (el «Quitar» queda
|
|
177
|
+
dentro; antes se salía y tapaba lo de abajo). Al reservar espacio en un layout, contar ese alto.
|
|
178
|
+
- Con `circle` + `editable` los botones van centrados abajo, sobre la foto (antes, en la esquina, el
|
|
179
|
+
círculo recortaba el tacho).
|
|
180
|
+
- Con `src` puesto, tocar el área vacía no hace nada: para elegir otra va el lápiz o `abrirSelector()`.
|
|
181
|
+
- El `alt` de la vista previa dice «Vista previa».
|
|
182
|
+
- El atributo `title` del host se borra solo (no sale el tooltip gris del navegador).
|
|
183
|
+
- Ya trae el arreglo de iOS para el `:active` pegado.
|
|
184
|
+
|
|
185
|
+
## Ejemplo
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<!-- Comprobante: ancho completo, el lápiz elige otra captura -->
|
|
189
|
+
<sui-image-upload #comprobante shape="rect" [fluid]="true" [editable]="true"
|
|
190
|
+
[src]="vistaPrevia()" [maxSize]="10 * 1024 * 1024"
|
|
191
|
+
title="Subir comprobante" subtitle="Captura del Yape o del banco — máx 10 MB"
|
|
192
|
+
(imageSelected)="alElegir($event)" (editRequested)="comprobante.abrirSelector()"
|
|
193
|
+
(removed)="quitar()" />
|
|
194
|
+
|
|
195
|
+
<!-- Foto del producto: cuadrada, el lápiz abre el recortador -->
|
|
196
|
+
<sui-image-upload shape="rect" size="xl" [editable]="true" [src]="foto()"
|
|
197
|
+
title="Subir foto" subtitle="JPG, PNG o WebP — se comprime sola"
|
|
198
|
+
(imageSelected)="alElegir($event)" (editRequested)="abrirRecortador()"
|
|
199
|
+
(removed)="quitarFoto()" />
|
|
200
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-image-upload-profile
|
|
3
|
+
selector: sui-image-upload-profile
|
|
4
|
+
resumen: Foto de perfil o logo en círculo con los botones Subir, o Eliminar y Cambiar, al lado
|
|
5
|
+
alternativas: [sui-image-upload (la imagen grande con su vista previa y el lápiz que abre el recortador; es lo que usa hoy la app), sui-avatar (solo mostrar la foto)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-image-upload-profile
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Upload/Image Upload Profile](https://sui-design-system.web.app/?path=/docs/molecules-upload-image-upload-profile--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** en una **pantalla de ajustes** donde la foto es un dato más de la cuenta: un círculo
|
|
15
|
+
chico (56–64 px) con su texto y los botones al lado, en una fila de un formulario.
|
|
16
|
+
|
|
17
|
+
**No lo uses** para:
|
|
18
|
+
|
|
19
|
+
- **La foto de perfil de la app hoy**: `app-avatar-editor` usa `sui-image-upload` `circle` `xl`
|
|
20
|
+
con el recortador, en las tres pantallas de perfil (cliente, repartidor, local). Una foto de
|
|
21
|
+
200 px que se ve antes de guardar es mejor para quien se sube su cara por primera vez.
|
|
22
|
+
- El logo del local: en la app el logo se ve **cuadrado** (home del cliente) y este componente lo
|
|
23
|
+
muestra en círculo.
|
|
24
|
+
- Comprobantes, portadas o fotos de productos: `sui-image-upload`.
|
|
25
|
+
- Solo mostrar la foto: `sui-avatar`.
|
|
26
|
+
|
|
27
|
+
## Qué variante usar
|
|
28
|
+
|
|
29
|
+
> **La guía del DS no tiene página para este componente** (existe en el Figma de origen, sin
|
|
30
|
+
> texto de uso). Todo es **propuesta, falta aprobación**.
|
|
31
|
+
>
|
|
32
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app`: **0 usos**. La foto de perfil va con
|
|
33
|
+
> `app-avatar-editor` (3 pantallas).
|
|
34
|
+
|
|
35
|
+
### `type`
|
|
36
|
+
|
|
37
|
+
| valor | cuándo | fuente |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `avatar` (default) | La foto de una persona. Vacío muestra una silueta. | propuesta |
|
|
40
|
+
| `company` | Un negocio. Vacío muestra edificios. Ojo: lo muestra en círculo. | propuesta |
|
|
41
|
+
|
|
42
|
+
### `alignment`
|
|
43
|
+
|
|
44
|
+
| valor | cuándo | fuente |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| `vertical` (default) | Con texto: título y requisitos («Mín. 400 × 400 px, PNG o JPEG»), avatar de 64. | propuesta |
|
|
47
|
+
| `horizontal` | Sin texto, solo los botones al lado del avatar de 56. Cuando el label ya está arriba (`sui-form-label`). | propuesta |
|
|
48
|
+
|
|
49
|
+
### Textos y estados
|
|
50
|
+
|
|
51
|
+
| input | cuándo | fuente |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `title` | Qué es: «Tu foto», «Foto de perfil». Solo se ve en `vertical`. | propuesta |
|
|
54
|
+
| `subtitle` | Requisitos reales: formatos que se aceptan y para qué se usa («La ve el cliente cuando llevas su pedido»). | propuesta |
|
|
55
|
+
| `labels` | Ya vienen en español con tuteo (Subir, Eliminar, Cambiar). Cambiarlos solo si el contexto pide otro verbo («Quitar»). | propuesta |
|
|
56
|
+
| `imageUrl` | La URL guardada. Con imagen muestra Eliminar + Cambiar. | propuesta |
|
|
57
|
+
| `companyLogoSrc` | Solo con `type="company"`: el logo, que gana sobre `imageUrl`. | propuesta |
|
|
58
|
+
| `loading` | **Siempre** mientras se comprime y se sube: deshabilita los botones y atenúa la foto. | propuesta |
|
|
59
|
+
| `disabled` | La persona no puede cambiarla (cuenta verificada con foto bloqueada). | propuesta |
|
|
60
|
+
|
|
61
|
+
Usos de hoy que rompen la regla: **0**.
|
|
62
|
+
|
|
63
|
+
## Tamaño en mobile y en web
|
|
64
|
+
|
|
65
|
+
**No tiene `size`.** El avatar mide 64 (vertical) o 56 (horizontal) y los botones son `sui-button`
|
|
66
|
+
`xsmall` de **32 px**: en mobile **no llegan** a los 44 px.
|
|
67
|
+
|
|
68
|
+
| uso | mobile | web | fuente |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| foto en una pantalla de ajustes | — **no hay tamaño**: botones de 32 | `vertical`, botones de 32 | medido |
|
|
71
|
+
|
|
72
|
+
```html
|
|
73
|
+
<!-- Solo web, hasta que tenga size -->
|
|
74
|
+
<sui-image-upload-profile title="Foto de perfil" subtitle="JPG o PNG, mín. 400 × 400 px"
|
|
75
|
+
[imageUrl]="foto()" [loading]="subiendo()"
|
|
76
|
+
(upload)="input.click()" (change)="input.click()" (remove)="quitar()" />
|
|
77
|
+
<input #input type="file" accept="image/jpeg,image/png,image/webp" hidden (change)="alElegir($event)" />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Sin tamaño suficiente para mobile.** Hace falta en el DS un `size` que lleve los botones a
|
|
81
|
+
`large` (48 px). Mientras tanto, en el celular va `sui-image-upload` `circle` `xl`.
|
|
82
|
+
|
|
83
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
84
|
+
|
|
85
|
+
Nada se borra del DS. Lo marcado «no usar» no tiene caso en la app de hoy; si un flujo nuevo cae
|
|
86
|
+
en la columna de la derecha, se usa (aprobado por el dueño, 03-10-2026).
|
|
87
|
+
|
|
88
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| todo el componente (0 usos) | la foto de perfil va con `app-avatar-editor` (grande, con recortador) | ajustes del equipo del local en web (foto de cada usuario en una fila) |
|
|
91
|
+
| `type="company"` | el logo del local se ve cuadrado, no en círculo | si el DS le suma la forma cuadrada |
|
|
92
|
+
| `alignment="horizontal"` | sin caso | una fila de una tabla de usuarios del local, con el nombre en la columna de al lado |
|
|
93
|
+
|
|
94
|
+
## API
|
|
95
|
+
|
|
96
|
+
<!-- api:inicio -->
|
|
97
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
98
|
+
|
|
99
|
+
| input | tipo | default |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `imageUrl` | `string \| null` | `null` |
|
|
102
|
+
| `companyLogoSrc` | `string \| null` | `null` |
|
|
103
|
+
| `title` | `string` | `'Subir imagen'` |
|
|
104
|
+
| `subtitle` | `string` | `'Mín. 400x400px, PNG o JPEG'` |
|
|
105
|
+
| `alignment` | `'vertical' \| 'horizontal'` | `'vertical'` |
|
|
106
|
+
| `type` | `'avatar' \| 'company'` | `'avatar'` |
|
|
107
|
+
| `labels` | `SuiImageUploadProfileLabels` | `{}` |
|
|
108
|
+
| `disabled` | `boolean` | `false` |
|
|
109
|
+
| `loading` | `boolean` | `false` |
|
|
110
|
+
|
|
111
|
+
| output | payload |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `upload` | `void` |
|
|
114
|
+
| `remove` | `void` |
|
|
115
|
+
| `change` | `void` |
|
|
116
|
+
<!-- api:fin -->
|
|
117
|
+
|
|
118
|
+
Es `ControlValueAccessor` de la URL (`string | null`); `remove` la deja en `null`.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
interface SuiImageUploadProfileLabels { upload?: string; remove?: string; change?: string; }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Trampas
|
|
125
|
+
|
|
126
|
+
- **No abre el selector de archivos**: no tiene `<input type="file">`. «Subir» y «Cambiar» solo
|
|
127
|
+
emiten `upload` y `change`; quien lo usa pone su propio input (y luego el compresor y el
|
|
128
|
+
recortador).
|
|
129
|
+
- **El avatar siempre es gris** (`color="gray"` fijo): no sigue el color por rol aprobado (local
|
|
130
|
+
naranja, repartidor verde, cliente azul) para el estado vacío.
|
|
131
|
+
- **El orden de los botones lo fija el componente**: Eliminar (rojo) a la izquierda, Cambiar a la
|
|
132
|
+
derecha. No sigue el orden del footer (secundario a la izquierda, principal a la derecha).
|
|
133
|
+
- `type="company"` es un círculo igual que el avatar.
|
|
134
|
+
- En `horizontal` no se ve el texto aunque se pase `title`.
|
|
135
|
+
- `loading` también deshabilita; no muestra spinner.
|
|
136
|
+
- El atributo `title` del host se borra solo (no sale el tooltip gris del navegador); el `title`
|
|
137
|
+
sí se usa como `alt` de la foto.
|
|
138
|
+
|
|
139
|
+
## Ejemplo
|
|
140
|
+
|
|
141
|
+
```html
|
|
142
|
+
<sui-image-upload-profile title="Foto de perfil" subtitle="La ve el cliente cuando llevas su pedido"
|
|
143
|
+
[imageUrl]="foto()" [loading]="subiendo()"
|
|
144
|
+
(upload)="elegir()" (change)="elegir()" (remove)="quitar()" />
|
|
145
|
+
```
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-img-retry
|
|
3
|
+
selector: img[suiImgRetry]
|
|
4
|
+
resumen: Directiva que reintenta cargar un <img> cuando falla la red y marca cuándo cargó o se dio por perdido
|
|
5
|
+
alternativas: [sui-avatar (foto de persona o logo con iniciales de respaldo), sui-image-upload (subir una imagen)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-img-retry
|
|
9
|
+
|
|
10
|
+
Story: [Utilities/Img Retry](https://sui-design-system.web.app/?path=/docs/utilities-img-retry--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** en los `<img>` de contenido remoto que **tienen que verse** aunque la red falle un
|
|
15
|
+
segundo: portadas y logos de locales, banners, fotos de productos. Un `<img>` normal que falla
|
|
16
|
+
queda roto hasta que se vuelve a crear; con la directiva se reintenta solo, como en una app
|
|
17
|
+
nativa.
|
|
18
|
+
|
|
19
|
+
**No lo uses** para:
|
|
20
|
+
|
|
21
|
+
- Íconos o imágenes locales del bundle (`/assets/…`): no fallan por red.
|
|
22
|
+
- Una foto de persona con respaldo de iniciales: `sui-avatar` ya resuelve el caso sin foto.
|
|
23
|
+
- Reemplazar el cache: el cache en disco lo dan los headers del Storage
|
|
24
|
+
(`cache-control: public, max-age=31536000, immutable`). La directiva solo cubre las cargas
|
|
25
|
+
que **fallaron**.
|
|
26
|
+
|
|
27
|
+
## Qué variante usar
|
|
28
|
+
|
|
29
|
+
> **No está en la guía del DS: es una utilidad de SUI**, sin Figma ni variantes.
|
|
30
|
+
>
|
|
31
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app`: 20 `<img>` con la directiva (15 en
|
|
32
|
+
> `pages/customer/store-browser/store-browser.html`, 3 en `category-browser`, 1 en `promos`, 1 en
|
|
33
|
+
> `components/sedes`) de 124 `<img>` en total. En el DS la usa `sui-store-card`.
|
|
34
|
+
|
|
35
|
+
No tiene variantes ni inputs. Lo que hace:
|
|
36
|
+
|
|
37
|
+
| momento | qué pasa | fuente |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| falla la carga | reintenta a 1 s, 3 s y 8 s (tres intentos) | componente |
|
|
40
|
+
| desde el segundo reintento | antes de reintentar, vuelve a bajar la imagen con `fetch(…, { cache: 'reload' })` para pisar una copia rota que haya quedado en el cache | componente |
|
|
41
|
+
| vuelve la red (`online`) | si la imagen no está cargada, reintenta de inmediato y reinicia el contador | componente |
|
|
42
|
+
| carga bien | agrega la clase `sui-img-loaded` y quita `data-sui-img-dead` | componente |
|
|
43
|
+
| se agotan los reintentos | pone el atributo `data-sui-img-dead` | componente |
|
|
44
|
+
| cambia el `src` | el contador arranca de cero para la URL nueva | componente |
|
|
45
|
+
|
|
46
|
+
| dónde | regla | fuente |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| imágenes del Storage en el home y los listados del cliente | siempre con la directiva | propuesta (es donde está hoy, y donde se vio el bug del 10-07-2026: portadas grises tras un corte) |
|
|
49
|
+
| el resto de `<img>` remotos | sumarla cuando la imagen sea parte de la decisión (la foto del producto en la carta) | propuesta |
|
|
50
|
+
|
|
51
|
+
## Tamaño en mobile y en web
|
|
52
|
+
|
|
53
|
+
No aplica: es una directiva, no dibuja nada. El tamaño es el del `<img>`.
|
|
54
|
+
|
|
55
|
+
## API
|
|
56
|
+
|
|
57
|
+
<!-- api:inicio -->
|
|
58
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
59
|
+
|
|
60
|
+
Inputs: ninguno.
|
|
61
|
+
|
|
62
|
+
Outputs: ninguno.
|
|
63
|
+
<!-- api:fin -->
|
|
64
|
+
|
|
65
|
+
Solo se aplica a `<img>` (`selector: img[suiImgRetry]`). El `src` se pone como siempre
|
|
66
|
+
(`[src]="url"`). Lo que expone hacia el CSS:
|
|
67
|
+
|
|
68
|
+
| marca | cuándo |
|
|
69
|
+
|---|---|
|
|
70
|
+
| clase `sui-img-loaded` | la imagen cargó |
|
|
71
|
+
| atributo `data-sui-img-dead` | se rindió tras tres reintentos |
|
|
72
|
+
|
|
73
|
+
## Trampas
|
|
74
|
+
|
|
75
|
+
- **Sin CSS tuyo no se nota nada de lo de arriba.** Para el fundido y el respaldo, la pantalla
|
|
76
|
+
pone las reglas (así lo hacen `store-browser.scss` y `promos.scss`):
|
|
77
|
+
|
|
78
|
+
```scss
|
|
79
|
+
img { opacity: 0; transition: opacity 0.25s ease-out; }
|
|
80
|
+
img.sui-img-loaded { opacity: 1; }
|
|
81
|
+
img[data-sui-img-dead] { display: none; } /* o mostrar un placeholder detrás */
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Sin la regla de `data-sui-img-dead`, la imagen perdida muestra el ícono roto del navegador.
|
|
85
|
+
- **Con `opacity: 0` y sin la directiva, la imagen nunca aparece.** Si copias el CSS, copia
|
|
86
|
+
también `suiImgRetry`.
|
|
87
|
+
- **El `fetch` del reintento necesita CORS** en el servidor de la imagen (el bucket de Storage ya
|
|
88
|
+
lo tiene). Contra otro dominio sin CORS ese paso falla en silencio y queda el reintento común.
|
|
89
|
+
- **No borra el cache completo** a propósito: solo la entrada de esa URL. Borrarlo todo mataría
|
|
90
|
+
la ventaja de no volver a bajar nada.
|
|
91
|
+
- Funciona igual con `loading="lazy"` y `decoding="async"`.
|
|
92
|
+
|
|
93
|
+
## Ejemplo
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<img class="tarjeta__img" suiImgRetry [src]="local.coverUrl" [alt]="local.name"
|
|
97
|
+
loading="lazy" decoding="async" />
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```scss
|
|
101
|
+
.tarjeta__img {
|
|
102
|
+
opacity: 0;
|
|
103
|
+
transition: opacity 0.25s ease-out;
|
|
104
|
+
&.sui-img-loaded { opacity: 1; }
|
|
105
|
+
&[data-sui-img-dead] { display: none; }
|
|
106
|
+
}
|
|
107
|
+
```
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sui-inline-input
|
|
3
|
+
selector: sui-inline-input
|
|
4
|
+
resumen: Texto que se edita en su lugar: en reposo muestra el dato y un lápiz; al tocarlo, campo con ✓ y ✕
|
|
5
|
+
alternativas: [sui-input (campo de formulario, siempre editable), sui-modal con sui-input (editar con más contexto o varios datos a la vez)]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# sui-inline-input
|
|
9
|
+
|
|
10
|
+
Story: [Molecules/Input/Inline Input](https://sui-design-system.web.app/?path=/docs/molecules-input-inline-input--docs)
|
|
11
|
+
|
|
12
|
+
## Cuándo usarlo / cuándo no
|
|
13
|
+
|
|
14
|
+
**Úsalo** para corregir **un solo dato de una línea** en una lista o ficha, sin abrir un modal:
|
|
15
|
+
renombrar una categoría de la carta, el alias de una dirección. En reposo se lee como texto con un
|
|
16
|
+
lápiz; al tocar el lápiz pasa a campo con ✓ (confirmar) y ✕ (cancelar). Enter confirma y Escape
|
|
17
|
+
cancela.
|
|
18
|
+
|
|
19
|
+
**No lo uses** para:
|
|
20
|
+
|
|
21
|
+
- Un formulario: `sui-input`, que siempre está editable.
|
|
22
|
+
- Varios datos que se editan juntos o que necesitan explicación: un modal con sus `sui-input`.
|
|
23
|
+
- Un dato con validación compleja o que dispara algo grande (precio, estado): mejor un flujo con
|
|
24
|
+
confirmación.
|
|
25
|
+
|
|
26
|
+
Regla corta: **un dato, en su lugar, que se corrige rápido → inline · varios o delicados → modal.**
|
|
27
|
+
|
|
28
|
+
## Qué variante usar
|
|
29
|
+
|
|
30
|
+
> **La guía del DS no tiene página para este componente.** Viene del Figma («Inline Input»).
|
|
31
|
+
> Todo lo de abajo es **propuesta, falta aprobación**.
|
|
32
|
+
>
|
|
33
|
+
> Uso medido el 03-10-2026 en `master-pedidos/src/app`: **0 usos**. Hay listas con campos siempre
|
|
34
|
+
> abiertos que se parecen (`pages/super-admin/master-settings/master-settings.html:99`, nombre de
|
|
35
|
+
> cada categoría del home), pero ahí se editan varias filas y se guarda todo junto: está bien con
|
|
36
|
+
> `sui-input`.
|
|
37
|
+
|
|
38
|
+
| prop / evento | cuándo | fuente |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `value` | El dato. `[(value)]` o `formControlName`, nunca los dos. | API |
|
|
41
|
+
| `placeholder` | Lo que se ve si está vacío: «Sin nombre». **Siempre**: el default es «Placeholder text...». | propuesta, falta aprobación |
|
|
42
|
+
| `leftIcon` | Un ícono que dice qué dato es (`price-tag-3-line` para una categoría). `false` si el texto se explica solo. El default es `user-3-line`. | propuesta, falta aprobación |
|
|
43
|
+
| `editLabel` | Nombre accesible del lápiz: «Editar nombre». | propuesta, falta aprobación |
|
|
44
|
+
| `error` | El valor escrito no sirve (vacío, repetido). Solo se ve en edición; no trae mensaje. | propuesta, falta aprobación |
|
|
45
|
+
| `disabled` | Mientras se guarda. | propuesta, falta aprobación |
|
|
46
|
+
| `(confirm)` | Guardar. Llega el texto nuevo. | API |
|
|
47
|
+
| `(cancel)` · `(edit)` | Volver atrás sin guardar · avisar que se empezó a editar. | API |
|
|
48
|
+
|
|
49
|
+
## Tamaño en mobile y en web
|
|
50
|
+
|
|
51
|
+
**No tiene `size`**: mide 36 px de alto y sus botones (lápiz, ✓, ✕) son de 24 × 24. El texto ya
|
|
52
|
+
sube a 16 px en mobile (sin zoom de iOS). **No tiene tamaño suficiente para mobile**: los botones
|
|
53
|
+
de 24 px quedan lejos de los 44 que pide un dedo. Usarlo en el panel web; en el teléfono, editar
|
|
54
|
+
con un `sui-input` `large`.
|
|
55
|
+
|
|
56
|
+
| uso | mobile | web |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| renombrar en una lista | `sui-input` `large` en un modal | este, 36 px |
|
|
59
|
+
|
|
60
|
+
## «No usar»: por qué no hoy y cuándo sí
|
|
61
|
+
|
|
62
|
+
| qué | por qué no hoy | cuándo sí, en un flujo nuevo |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| el componente entero (0 usos) | no hay datos que se corrijan sueltos en una lista | renombrar una categoría de la carta en web, o el alias de una dirección guardada |
|
|
65
|
+
| `leftIcon` default (`user-3-line`) | casi nunca el dato es una persona | el nombre de un miembro del equipo |
|
|
66
|
+
|
|
67
|
+
## API
|
|
68
|
+
|
|
69
|
+
<!-- api:inicio -->
|
|
70
|
+
<!-- generada: no editar a mano — `npm run docs` -->
|
|
71
|
+
|
|
72
|
+
| input | tipo | default |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `value` · model, `[(value)]` | `string` | `''` |
|
|
75
|
+
| `placeholder` | `string` | `'Placeholder text...'` |
|
|
76
|
+
| `leftIcon` | `string \| false` | `'user-3-line'` |
|
|
77
|
+
| `error` | `boolean` | `false` |
|
|
78
|
+
| `disabled` | `boolean` | `false` |
|
|
79
|
+
| `editLabel` | `string` | `'Editar'` |
|
|
80
|
+
|
|
81
|
+
| output | payload |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `confirm` | `string` |
|
|
84
|
+
| `cancel` | `void` |
|
|
85
|
+
| `edit` | `void` |
|
|
86
|
+
<!-- api:fin -->
|
|
87
|
+
|
|
88
|
+
Implementa `ControlValueAccessor`.
|
|
89
|
+
|
|
90
|
+
## Trampas
|
|
91
|
+
|
|
92
|
+
- **Los defaults están pensados para la story**: `placeholder` «Placeholder text...» y
|
|
93
|
+
`leftIcon` `user-3-line`. Pasa los dos siempre.
|
|
94
|
+
- `error` no trae mensaje: decir qué falta en otro lado (toast o hint cercano).
|
|
95
|
+
- Cancelar restaura el texto de antes; `(confirm)` es el único momento de guardar.
|
|
96
|
+
- Ocupa todo el ancho de su contenedor.
|
|
97
|
+
|
|
98
|
+
## Ejemplo
|
|
99
|
+
|
|
100
|
+
```html
|
|
101
|
+
<sui-inline-input [(value)]="nombreCategoria" placeholder="Sin nombre" leftIcon="price-tag-3-line"
|
|
102
|
+
editLabel="Editar nombre" [error]="!nombreCategoria().trim()"
|
|
103
|
+
(confirm)="renombrar($event)" />
|
|
104
|
+
```
|