innoboxrr-form-core 2.3.0 → 2.5.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/README.md CHANGED
@@ -1,49 +1,75 @@
1
1
  # innoboxrr-form-core
2
2
 
3
- Lo que comparten [`innoboxrr-form-elements`](../form-elements) (Vue) y
4
- [`innoboxrr-react-form-elements`](../react-form-elements) (React) y no depende
5
- de ningún framework.
3
+ Lo que comparten [`innoboxrr-form-elements`](../form-elements) (Vue),
4
+ [`innoboxrr-react-form-elements`](../react-form-elements) (React) y los dos
5
+ datatables, y no depende de ningún framework: el tema, los iconos, las hojas de
6
+ estilo, los archivos y las zonas horarias.
6
7
 
7
- Estaba duplicado en los dos paquetes, que es exactamente como dos copias
8
- empiezan a divergir.
8
+ Estaba duplicado en los paquetes, que es exactamente como dos copias empiezan a
9
+ divergir.
9
10
 
10
11
  ```
11
12
  npm i innoboxrr-form-core
12
13
  ```
13
14
 
14
- ## Tema
15
+ ## Estilos
16
+
17
+ ```js
18
+ import 'innoboxrr-form-core/styles'
19
+ ```
20
+
21
+ Una sola importación trae las tres hojas: `tokens.css` (las variables),
22
+ `layout.css` (las utilidades de maquetación) y `components.css` (los
23
+ componentes). Nada de lo generado necesita UIkit, Tailwind ni Font Awesome.
24
+
25
+ Colores, formas, densidad, capas y movimiento son variables CSS. Para cambiar el
26
+ aspecto de todo, se redefinen:
27
+
28
+ ```css
29
+ :root {
30
+ --fe-primary: #7c3aed;
31
+ --fe-radius: 10px;
32
+ --fe-density: 0.875;
33
+ }
34
+ ```
15
35
 
16
- Antes cada componente llevaba su cadena CSS incrustada como valor por defecto
17
- de `customClass` —repetida en los dos paquetes— y el código que genera
18
- `larapack-generator` esperaba `inputClass` y `buttonClass` de un mixin global
19
- que la aplicación anfitriona tenía que registrar sin que nada lo dijera.
36
+ El modo oscuro responde a la preferencia del sistema y a un `data-theme="dark"`
37
+ en la raíz; `data-theme="light"` fuerza el claro aunque el sistema esté en
38
+ oscuro.
20
39
 
21
- Ahora es un mapa de tokens que la aplicación ajusta **una vez**, al arrancar:
40
+ ## Tema
41
+
42
+ Un mapa de tokens que la aplicación ajusta **una vez**, al arrancar. Cada token
43
+ apunta a una clase del sistema propio (`fe-*`), así que el caso normal es no
44
+ tocarlo; sirve para apuntar un token a las clases de otro sistema visual cuando
45
+ la aplicación ya tiene el suyo:
22
46
 
23
47
  ```js
24
48
  import { setTheme } from 'innoboxrr-form-core'
25
49
 
26
50
  setTheme({
27
51
  input: 'form-control',
28
- select: 'form-select',
29
52
  button: 'btn btn-primary',
30
53
  })
31
54
  ```
32
55
 
33
- Los tokens:
34
-
35
56
  | Grupo | Tokens |
36
57
  |---|---|
37
58
  | Envoltorios | `field`, `fieldInner`, `label`, `help`, `helpIcon`, `error` |
38
59
  | Controles | `input`, `select`, `textarea`, `checkbox`, `radio`, `file` |
39
- | Botones | `button`, `buttonSecondary`, `buttonDanger`, `buttonLink` |
40
-
41
- Los valores de fábrica son los de UIkit + Tailwind que ya usaba el ecosistema,
42
- así que actualizar no cambia nada de aspecto.
43
-
44
- `customClass` sigue existiendo y **reemplaza** al token, para el caso puntual.
45
- Antes unos controles lo reemplazaban y otros lo sumaban a una clase incrustada;
46
- ahora se comportan todos igual.
60
+ | Botones | `button`, `buttonSecondary`, `buttonDanger`, `buttonLink`, `iconButton` |
61
+ | Navegación | `breadcrumb`, `breadcrumbLink`, `breadcrumbCurrent`, `breadcrumbSeparator`, `actionMenu`, `actionMenuItem`, `actionMenuDanger`, `kbd` |
62
+ | Superficies | `surface`, `surfaceRaised`, `toolbar`, `badge`, `badgePrimary`, `badgeSuccess`, `badgeDanger`, `badgeWarning` |
63
+ | Esqueletos | `skeleton`, `skeletonText`, `skeletonCircle`, `skeletonBlock` |
64
+ | Diálogos y drawers | `overlay`, `dialog`, `dialogSmall`, `dialogLarge`, `dialogHeader`, `dialogTitle`, `dialogBody`, `dialogFooter`, `drawer`, `drawerStart`, `drawerHeader`, `drawerTitle`, `drawerBody`, `drawerFooter` |
65
+ | Menús | `menu`, `menuList`, `menuItem`, `menuItemDanger`, `menuSeparator`, `menuLabel` |
66
+ | Paleta de comandos | `command`, `commandInput`, `commandList`, `commandGroup`, `commandItem`, `commandEmpty` |
67
+ | Avisos | `toast`, `toastSuccess`, `toastDanger`, `toastWarning`, `toastTitle`, `toastClose`, `toastRegion` |
68
+ | Tabla | `table`, `tableNumeric`, `tableSticky`, `tableSelect`, `tableResizer`, `tableEmpty`, `bulkBar`, `bulkCount` |
69
+ | Edición en línea | `editable` |
70
+ | Shell de aplicación | `shell`, `shellHeader`, `shellSidebar`, `shellMain` |
71
+
72
+ `customClass` **reemplaza** al token, para el caso puntual:
47
73
 
48
74
  ```js
49
75
  import { getTheme, resetTheme, onThemeChange, classFor } from 'innoboxrr-form-core'
@@ -55,9 +81,89 @@ resetTheme() // vuelve a fábrica (sobre todo para pruebas)
55
81
  onThemeChange(fn) // devuelve la función para dejar de escuchar
56
82
  ```
57
83
 
58
- Los dos paquetes de componentes se suscriben, así que **un `setTheme` en
59
- caliente repinta lo que ya esté montado**: leerlo directamente no lo haría,
60
- porque el tema es estado de módulo, fuera del framework.
84
+ Los paquetes de componentes se suscriben, así que **un `setTheme` en caliente
85
+ repinta lo que ya esté montado**.
86
+
87
+ ## Piezas de escritorio
88
+
89
+ Diálogos, drawers, menús y avisos se apoyan en lo que ya hace el navegador, sin
90
+ librerías de interfaz: `<dialog>` con `showModal()` pone la capa superior, el
91
+ fondo inerte, el foco atrapado, Escape para cerrar y la devolución del foco; el
92
+ atributo `popover` pone el cierre al pulsar fuera. Estas hojas solo los dibujan.
93
+ Los componentes de Vue y React envuelven exactamente este marcado.
94
+
95
+ ```html
96
+ <dialog class="fe-drawer">
97
+ <header class="fe-drawer-header">
98
+ <h2 class="fe-drawer-title">Nuevo producto</h2>
99
+ <button class="fe-icon-button" aria-label="Cerrar">…</button>
100
+ </header>
101
+ <div class="fe-drawer-body">…</div>
102
+ <footer class="fe-drawer-footer">…</footer>
103
+ </dialog>
104
+ ```
105
+
106
+ - **Diálogo**: `fe-dialog`, con `fe-dialog-sm` o `fe-dialog-lg` para el ancho.
107
+ - **Drawer**: `fe-drawer` a la derecha; `fe-drawer-start` lo pega a la izquierda.
108
+ - **Paleta de comandos**: `<dialog class="fe-dialog fe-command">` con
109
+ `fe-command-input` y una `fe-command-list` de `fe-command-item`; el elemento
110
+ activo lleva `aria-selected="true"`.
111
+ - **Avisos**: una `fe-toast-region` con `popover="manual"`, para seguir encima
112
+ de un drawer abierto con `showModal()`.
113
+ - **Menús**: `fe-menu` con `popover`, colocado con Floating UI.
114
+ - **Tabla**: `fe-table-select` para la columna de casillas, `data-selected` en
115
+ la fila, `fe-bulk-bar` para lo que se hace con la selección y
116
+ `fe-table-resizer` para cambiar el ancho de una columna.
117
+
118
+ Un `<dialog>` cerrado está oculto porque el navegador le pone `display: none`;
119
+ por eso ninguna regla fija `display` fuera del estado `[open]`. Las capas que no
120
+ viven en la capa superior —la cabecera fija de una tabla, un overlay dibujado a
121
+ mano, los tooltips— siguen la escala `--fe-z-*`, nunca un número suelto.
122
+
123
+ ## Iconos
124
+
125
+ Un nombre semántico y un mapa que decide de dónde sale el dibujo. Los valores son
126
+ nombres de Iconify (`coleccion:icono`):
127
+
128
+ ```js
129
+ import { setIcons, iconFor } from 'innoboxrr-form-core'
130
+
131
+ setIcons({ plus: 'lucide:plus', delete: 'lucide:trash-2' })
132
+ iconFor('plus') // 'lucide:plus'
133
+ iconFor('mdi:home') // un nombre completo pasa tal cual
134
+ ```
135
+
136
+ ## Avisos y confirmaciones
137
+
138
+ Estado de toda la aplicación, fuera del framework: quien avisa —un store, el
139
+ contrato de un modelo, la tabla— no necesita saber si detrás hay Vue o React.
140
+ Los paquetes de componentes lo pintan con su región de avisos y su anfitrión de
141
+ confirmaciones, que la aplicación monta una vez.
142
+
143
+ ```js
144
+ import { notify, notifySuccess, notifyError, confirmAction } from 'innoboxrr-form-core'
145
+
146
+ notifySuccess('Producto creado')
147
+ notifyError('No se pudo guardar', { title: 'Producto' })
148
+ notify({ message: 'Exportación en curso', variant: 'info', duration: 8000 })
149
+
150
+ if (await confirmAction({ message: '¿Borrar el producto?', variant: 'danger' })) {
151
+ // …
152
+ }
153
+ ```
154
+
155
+ - Un aviso se va a los cinco segundos; **uno de peligro se queda** hasta que se
156
+ cierra, porque quien no lo leyó a tiempo no sabría qué falló. `duration: 0` lo
157
+ deja fijo.
158
+ - No se apilan más de cinco: sale el más antiguo.
159
+ - `confirmAction` resuelve `true` o `false`. Una pregunta nueva con otra
160
+ pendiente da la anterior por cancelada.
161
+ - Sin un anfitrión montado, `confirmAction` usa `window.confirm`: una promesa que
162
+ no se resolviera dejaría colgada la acción que la espera.
163
+
164
+ Para pintarlos desde otro sitio: `getToasts`, `onToastsChange`, `dismiss`,
165
+ `getConfirmation`, `onConfirmationChange` y `resolveConfirmation`. `resetToasts`
166
+ y `resetConfirmation` vacían el estado entre pruebas.
61
167
 
62
168
  ## Archivos
63
169
 
@@ -76,10 +182,6 @@ hay que meter en el `FormData`.
76
182
 
77
183
  `validateFiles` es la misma función devolviendo una promesa, por compatibilidad.
78
184
 
79
- La vista previa de lo que no es imagen es un `data:` URI. Antes era una URL de
80
- `icon-library.com`: cada archivo disparaba una petición a un tercero que puede
81
- caerse o cambiar.
82
-
83
185
  ## Zonas horarias
84
186
 
85
187
  ```js
package/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * innoboxrr-form-core
3
3
  *
4
- * Lo que comparten innoboxrr-form-elements y innoboxrr-react-form-elements y
5
- * no depende de ningun framework: el tema, la validacion de archivos y la
6
- * lista de zonas horarias.
4
+ * Lo que comparten los paquetes de interfaz innoboxrr —los componentes de Vue
5
+ * y de React y los dos datatables— y no depende de ningun framework: el tema,
6
+ * los iconos, los avisos y confirmaciones, la validacion de archivos y la lista
7
+ * de zonas horarias.
7
8
  *
8
- * Estaba duplicado en los dos paquetes, que es exactamente como dos copias
9
+ * Estaba duplicado en los paquetes, que es exactamente como dos copias
9
10
  * empiezan a divergir.
10
11
  */
11
12
 
@@ -27,6 +28,21 @@ export {
27
28
  setIcons,
28
29
  } from './src/icons.js'
29
30
 
31
+ export {
32
+ confirmAction,
33
+ dismiss,
34
+ getConfirmation,
35
+ getToasts,
36
+ notify,
37
+ notifyError,
38
+ notifySuccess,
39
+ onConfirmationChange,
40
+ onToastsChange,
41
+ resetConfirmation,
42
+ resetToasts,
43
+ resolveConfirmation,
44
+ } from './src/feedback.js'
45
+
30
46
  export {
31
47
  FILE_ICON,
32
48
  describeFiles,
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "innoboxrr-form-core",
3
- "version": "2.3.0",
4
- "description": "El nucleo agnostico de los formularios innoboxrr: tema, archivos y zonas horarias.",
3
+ "version": "2.5.0",
4
+ "description": "El nucleo agnostico de la interfaz innoboxrr: tema, iconos, estilos, archivos y zonas horarias.",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "exports": {
8
8
  ".": "./index.js",
9
9
  "./theme": "./src/theme.js",
10
10
  "./icons": "./src/icons.js",
11
+ "./feedback": "./src/feedback.js",
11
12
  "./files": "./src/files.js",
12
13
  "./timezone": "./src/timezone.js",
13
14
  "./styles": "./styles.css",