@tinya-code/gas-admin-ui 0.2.0-alpha.11 → 0.2.0-alpha.13

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
@@ -310,6 +310,228 @@ The shell starts at `/login` and, once authenticated, shows the sidebar menu and
310
310
 
311
311
  ---
312
312
 
313
+ ## Todos los tipos de campo del formulario
314
+
315
+ Esta es la referencia completa de todos los tipos de campo que puedes declarar en `ResourceSchema.fields`. Cada tipo tiene su propio comportamiento de renderizado, validación y propiedades específicas.
316
+
317
+ | Tipo | Descripción | Uso típico |
318
+ |------|-------------|------------|
319
+ | `text` | Input de una línea para texto corto | Nombres, slugs, URLs cortas |
320
+ | `textarea` | Área de texto multilínea | Descripciones largas, notas |
321
+ | `slug` | Slug generado automáticamente de otro campo | Identificadores amigables para SEO |
322
+ | `number` | Campo numérico con controles de incremento | Cantidades, precios, edades |
323
+ | `currency` | Campo monetario con formato de moneda | Precios, montos, saldos |
324
+ | `boolean` | Interruptor (toggle) o casilla de verificación | Estados activos/inactivos |
325
+ | `select` | Desplegable con radios para 2-4 opciones o dropdown para más | Estados, categorías pequeñas |
326
+ | `dropdown` | Desplegable nativo (`<select>`) SIEMPRE, sin mutar a radios | Estados con muchas opciones |
327
+ | `rich-select` | Selector visual con tarjetas y preview HTML personalizado | Opciones con iconos, colores, estados visuales |
328
+ | `multiselect` | Selección múltiple de opciones | Tags, etiquetas múltiples |
329
+ | `url` | Campo para URLs válidas | Enlaces externos, sitios web |
330
+ | `email` | Campo de email con validación de formato | Correos electrónicos |
331
+ | `phone` | Campo de teléfono con formato telefónico | Números de teléfono |
332
+ | `date` | Selector de fecha (ISO `YYYY-MM-DD`) | Fechas de nacimiento, citas |
333
+ | `time` | Selector de hora | Horas de apertura, citas |
334
+ | `readonly-text` | Texto de solo lectura que no se envía al back | IDs generados, timestamps |
335
+ | `relation` | Relación con otro recurso (fuente de datos) | Clientes, productos, usuarios relacionados |
336
+ | `image` | Subida y vista previa de imágenes | Logos, fotos de perfil |
337
+ | `file` | Subida de archivos genéricos (PDF, DOCX, etc.) | Documentos, adjuntos |
338
+ | `group` | Grupo de campos con tarjeta, colapsable o inline | Secciones de formulario relacionadas |
339
+ | `list` | Lista repetible de campos (items) | Múltiples direcciones, teléfonos |
340
+ | `string-list` | Lista simple de strings | Tags simples, palabras clave |
341
+ | `key-value` | Tabla de pares clave-valor | Metadatos, configuraciones personalizadas |
342
+ | `color` | Selector de color nativo (`<input type="color">`) | Colores primarios, secundarios, temas |
343
+
344
+ ### Ejemplos por tipo
345
+
346
+ A continuación verás cómo declarar cada tipo en tu schema, con sus propiedades específicas:
347
+
348
+ #### `text` — Input de una línea
349
+
350
+ ```ts
351
+ { key: 'name', type: 'text', label: 'Nombre del Negocio', required: true, validators: { minLength: 2, maxLength: 120 }, section: 'general', width: 6 }
352
+ ```
353
+
354
+ #### `textarea` — Área de texto multilínea
355
+
356
+ ```ts
357
+ { key: 'description', type: 'textarea', label: 'Descripción', validators: { maxLength: 500 }, section: 'general', width: 12 }
358
+ ```
359
+
360
+ #### `slug` — Identificador amigable
361
+
362
+ ```ts
363
+ { key: 'slug', type: 'slug', from: 'name', label: 'Slug', required: true, lockAfterCreate: true, section: 'general', width: 6 }
364
+ ```
365
+
366
+ #### `number` — Campo numérico
367
+
368
+ ```ts
369
+ { key: 'minVisits', type: 'number', label: 'Visitas Mínimas', required: true, min: 0, section: 'general', width: 6 }
370
+ ```
371
+
372
+ #### `currency` — Campo monetario
373
+
374
+ ```ts
375
+ { key: 'price', type: 'currency', label: 'Precio', validators: { min: 0 }, section: 'pricing', width: 6 }
376
+ ```
377
+
378
+ #### `boolean` — Interruptor / Casilla
379
+
380
+ ```ts
381
+ { key: 'active', type: 'boolean', label: 'Activo', section: 'general', width: 3 }
382
+ ```
383
+
384
+ #### `select` — Desplegable (radios si 2-4 opciones, dropdown si más)
385
+
386
+ ```ts
387
+ { key: 'status', type: 'select', label: 'Estado', required: true, options: [
388
+ { value: 'active', label: 'Activo' },
389
+ { value: 'inactive', label: 'Inactivo' },
390
+ { value: 'pending', label: 'Pendiente' },
391
+ ], section: 'general', width: 6 }
392
+ ```
393
+
394
+ #### `dropdown` — Desplegable nativo SIEMPRE
395
+
396
+ ```ts
397
+ { key: 'timezone', type: 'dropdown', label: 'Zona Horaria', required: true, section: 'general', width: 6, default: 'America/Lima', options: [
398
+ { value: 'America/Lima', label: 'Lima (Perú)' },
399
+ { value: 'America/Bogota', label: 'Bogotá (Colombia)' },
400
+ { value: 'America/Mexico_City', label: 'Ciudad de México' },
401
+ ], }
402
+ ```
403
+
404
+ #### `rich-select` — Selector visual con tarjetas
405
+
406
+ ```ts
407
+ { key: 'cardStyle', type: 'rich-select', label: 'Estilo de Tarjeta', cardWidth: 3, section: 'branding', width: 12,
408
+ options: [
409
+ { value: 'none', label: 'Ninguno', preview: '<span class="w-8 h-8 bg-amber-300 rounded-sm flex items-center justify-center text-xs font-medium text-amber-900">Ninguna</span>' },
410
+ { value: 'monthly', label: 'Mensual', preview: '<span class="w-8 h-8 bg-blue-100 rounded-sm flex items-center justify-center text-xs font-medium text-blue-900">Mensual</span>' },
411
+ { value: 'yearly', label: 'Anual', preview: '<span class="w-8 h-8 bg-green-100 rounded-sm flex items-center justify-center text-xs font-medium text-green-900">Anual</span>' },
412
+ ], }
413
+ ```
414
+
415
+ #### `multiselect` — Selección múltiple
416
+
417
+ ```ts
418
+ { key: 'tags', type: 'multiselect', label: 'Etiquetas', section: 'tags', width: 12, options: [
419
+ { value: 'vip', label: 'Cliente VIP' },
420
+ { value: 'new', label: 'Cliente Nuevo' },
421
+ { value: 'inactive', label: 'Inactivo' },
422
+ ], }
423
+ ```
424
+
425
+ #### `url` — Campo de URL
426
+
427
+ ```ts
428
+ { key: 'website', type: 'url', label: 'Sitio Web', placeholder: 'https://ejemplo.com', section: 'contact', width: 12 }
429
+ ```
430
+
431
+ #### `email` — Campo de correo electrónico
432
+
433
+ ```ts
434
+ { key: 'email', type: 'email', label: 'Correo Electrónico', required: true, section: 'contact', width: 12 }
435
+ ```
436
+
437
+ #### `phone` — Campo de teléfono
438
+
439
+ ```ts
440
+ { key: 'phone', type: 'phone', label: 'Teléfono', section: 'contact', width: 6 }
441
+ ```
442
+
443
+ #### `date` — Selector de fecha
444
+
445
+ ```ts
446
+ { key: 'birthDate', type: 'date', label: 'Fecha de Nacimiento', section: 'personal', width: 6 }
447
+ ```
448
+
449
+ #### `time` — Selector de hora
450
+
451
+ ```ts
452
+ { key: 'openingTime', type: 'time', label: 'Hora de Apertura', section: 'hours', width: 6 }
453
+ ```
454
+
455
+ #### `readonly-text` — Texto de solo lectura
456
+
457
+ ```ts
458
+ { key: 'memberId', type: 'readonly-text', label: 'ID Membresía', readonly: true, section: 'general', width: 6 }
459
+ ```
460
+
461
+ #### `relation` — Relación con otro recurso
462
+
463
+ ```ts
464
+ { key: 'clientId', type: 'relation', label: 'Cliente', source: { resource: 'clients', labelField: 'name', valueField: 'membershipId' }, section: 'association', width: 12 }
465
+ ```
466
+
467
+ #### `image` — Subida de imagen
468
+
469
+ ```ts
470
+ { key: 'logoUrl', type: 'image', label: 'Logo', section: 'branding', width: 12, accept: 'image/*', maxSizeMB: 2 }
471
+ ```
472
+
473
+ #### `file` — Subida de archivo genérico
474
+
475
+ ```ts
476
+ { key: 'document', type: 'file', label: 'Documento', section: 'files', width: 12, accept: '.pdf,.doc,.docx', maxSizeMB: 5 }
477
+ ```
478
+
479
+ #### `group` — Grupo de campos
480
+
481
+ ```ts
482
+ { key: 'address', type: 'group', label: 'Dirección', display: 'card', section: 'location', width: 12, fields: [
483
+ { key: 'street', type: 'text', label: 'Calle', width: 6 },
484
+ { key: 'city', type: 'text', label: 'Ciudad', width: 6 },
485
+ ]},
486
+ ```
487
+
488
+ #### `list` — Lista repetible de items
489
+
490
+ ```ts
491
+ { key: 'phones', type: 'list', label: 'Teléfonos', itemFields: [
492
+ { key: 'number', type: 'phone', label: 'Número', width: 6 },
493
+ { key: 'type', type: 'select', label: 'Tipo', options: [{ value: 'mobile', label: 'Móvil' }, { value: 'home', label: 'Hogar' }], width: 6 },
494
+ ], section: 'contact', width: 12 }
495
+ ```
496
+
497
+ #### `string-list` — Lista simple de strings
498
+
499
+ ```ts
500
+ { key: 'skills', type: 'string-list', label: 'Habilidades', itemType: 'text', section: 'skills', width: 12 }
501
+ ```
502
+
503
+ #### `key-value` — Pares clave-valor
504
+
505
+ ```ts
506
+ { key: 'metadata', type: 'key-value', label: 'Metadatos', section: 'advanced', width: 12 }
507
+ ```
508
+
509
+ #### `color` — Selector de color
510
+
511
+ ```ts
512
+ { key: 'colorPrimary', type: 'color', label: 'Color Primario', placeholder: '#4A2C11', section: 'branding', width: 6, default: '#4A2C11' }
513
+ ```
514
+
515
+ ### Propiedades comunes a todos los campos
516
+
517
+ | Propiedad | Tipo | Descripción |
518
+ |-----------|------|-------------|
519
+ | `key` | `string` | Nombre de la propiedad en el JSON que envía/recibe el back. |
520
+ | `label` | `string` | Rótulo visible para el usuario en el formulario y la ficha. |
521
+ | `help` | `string` | Texto corto de ayuda que se muestra debajo del campo. |
522
+ | `placeholder` | `string` | Texto sugerente que se muestra dentro del input cuando está vacío. |
523
+ | `required` | `boolean` | Si es obligatorio. El back también lo valida (R7.4). |
524
+ | `default` | `any` | Valor por defecto si el registro no trae este campo (ej. `default: 'none'` en un `select`/`dropdown`). |
525
+ | `readonly` | `boolean` | Si el campo es solo lectura (no editable en el formulario). |
526
+ | `width` | `1-12` | Ancho en la grilla del formulario (1–12), igual que un widget del dashboard. |
527
+ | `section` | `string` | Id de la sección/pestaña del layout a la que pertenece (base.md §4). |
528
+ | `description` | `string` | Descripción corta de para qué sirve este campo. Se muestra como tooltip al pasar el cursor sobre el rótulo. |
529
+ | `docLink` | `string` | URL de documentación externa para este campo (se abre al hacer clic en el tooltip). |
530
+ | `validators` | `object` | Reglas de validación (`minLength`, `maxLength`, `pattern`, `min`, `max`, `unique`). |
531
+ | `access` | `object` | Nivel de acceso requerido (`read`, `write`) — solo UX, el back vuelve a verificar en cada petición. |
532
+
533
+ ---
534
+
313
535
  ## Schema examples (real implementations)
314
536
 
315
537
  The examples below are taken from a production consumer of this library.
@@ -4504,6 +4504,96 @@ i0.ɵɵngDeclareClassMetadata({
4504
4504
  }]
4505
4505
  }
4506
4506
  });
4507
- export { API_DRIVER, API_URL, ApiError, ApiService, AuthService, COLUMN_FORMAT_TYPES, ComposerHost, ConfirmDialog, DEFAULT_RESPONSE_UNWRAP, Dashboard, DataSourceService, ErrorMapperService, FIREBASE_AUTH_ADAPTER, FieldHost, FormView, GAS_SCHEMAS, ListView, Login, MAX_DEPTH, NotificationService, ResourcePage, SESSION_TOKEN_KEY, SESSION_USER_KEY, SUPPORTED_FIELD_TYPE_LIST, SchemaCompositionError, Sidebar, Toast, UploadService, VALUE_SOURCES, actionType, actionTypes, actionsFor, allSchemas, apiErrorInterceptor, authGuard, buildFormSchema, buildPayload, childTree, columnFormatDescriptors, fieldDescriptors, getAction, getAuth, get as getRenderDescriptor, getSchema, groupTree, interpolateTemplate, isSupported as isRenderSupported, isSupported, isShareAction, isTriggerAction, itemTree, layoutDescriptors, listTree, resource_page_exports as n, provideFirebaseAdapter, provideGasAdmin, provideRenderDescriptors, registerAction, register as registerRenderDescriptor, renderKinds, renewedTokenOf, resolveShare, resourceRoutes, seedModel, setSchemaCatalog, shellRoutes, stringItemTree, composer_host_exports as t, unregister as unregisterRenderDescriptor, validateComposition, viewDescriptors };
4507
+ const schemaDescriptions = {
4508
+ key: "Nombre de la propiedad en el JSON que envía/recibe el back.",
4509
+ label: "Rótulo visible para el usuario en el formulario y la ficha.",
4510
+ help: "Texto corto de ayuda que se muestra debajo del campo.",
4511
+ placeholder: "Texto sugerente que se muestra dentro del input cuando está vacío.",
4512
+ required: "Si es obligatorio. El back también lo valida (R7.4).",
4513
+ default: "Valor por defecto si el registro no trae este campo (ej. `default: \"none\"` en un `select`/`dropdown`).",
4514
+ readonly: "Si el campo es solo lectura (no editable en el formulario).",
4515
+ readonlyOn: "Bloquea el campo solo en creación, solo en edición o siempre.",
4516
+ readonlyWhen: "Condición bajo la cual el campo es solo lectura (expresión sobre otros campos).",
4517
+ visibleWhen: "Condición bajo la cual el campo se muestra u oculta.",
4518
+ hiddenOn: "Oculta el campo en creación, en edición o siempre.",
4519
+ dependsOn: "Selección dependiente (guía §1: país → ciudad). Clave del campo padre del mismo nivel.",
4520
+ validators: "Reglas de validación (mínimo, máximo, patrón, unicidad, etc.).",
4521
+ width: "Ancho en la grilla del formulario (1–12), igual que un widget del dashboard.",
4522
+ section: "Id de la sección/pestaña del layout a la que pertenece (base.md §4).",
4523
+ read: "Código de nivel de acceso requerido para leer el campo.",
4524
+ write: "Código de nivel de acceso requerido para escribir el campo.",
4525
+ description: "Descripción corta de para qué sirve este campo. Se muestra como tooltip al pasar el cursor sobre el rótulo.",
4526
+ docLink: "URL de documentación externa para este campo (se abre al hacer clic en el tooltip).",
4527
+ value: "Valor que se envía al back cuando se elige esta opción.",
4528
+ labelOption: "Texto visible de la opción.",
4529
+ disabled: "Si la opción está deshabilitada (no se puede elegir).",
4530
+ type: "Tipo de campo: `text`, `color`, `number`, `currency`, `boolean`, `select`, `dropdown`, `rich-select`, `multiselect`, `url`, `email`, `phone`, `date`, `time`, `readonly-text`, `slug`, `textarea`, `relation`, `image`, `file`, `group`, `list`, `string-list`, `key-value`.",
4531
+ maxLength: "Longitud máxima de caracteres permitida.",
4532
+ pattern: "Expresión regular que debe cumplir el valor.",
4533
+ rows: "Número de filas visibles del textarea.",
4534
+ minWords: "Cantidad mínima de palabras.",
4535
+ maxWords: "Cantidad máxima de palabras.",
4536
+ tokens: "Marcadores insertables como chips bajo el área (plantillas de mensaje).",
4537
+ from: "Campo del registro del que se autogenera el slug.",
4538
+ lockAfterCreate: "Bloquea el campo una vez creado el registro (por defecto: sí).",
4539
+ min: "Valor mínimo permitido.",
4540
+ max: "Valor máximo permitido.",
4541
+ step: "Incremento entre valores permitidos.",
4542
+ decimals: "Número de decimales mostrados.",
4543
+ currencyFrom: "Campo del registro del que se toma la moneda (ej. `currency`).",
4544
+ trueLabel: "Texto que se muestra cuando el valor es verdadero.",
4545
+ falseLabel: "Texto que se muestra cuando el valor es falso.",
4546
+ source: "De dónde salen las opciones: `{ resource, view?, params?, … }` (F8 · R6.5).",
4547
+ resource: "Recurso declarado (`resource.id`): su listado es el de las opciones.",
4548
+ view: "Vista declarada en `resource.views` (opcional): filtra en el back.",
4549
+ params: "Valores interpolados para la vista (`{campo}` ← contexto).",
4550
+ labelField: "Etiqueta por defecto de las filas (si no, `titleField` del recurso).",
4551
+ valueField: "Valor por defecto de las filas (si no, `keyField` del recurso).",
4552
+ secondaryField: "Segundo dato a mostrar junto a la etiqueta (ej. \"Juan Pérez · DNI 123\").",
4553
+ onlyActive: "Cargar solo registros activos (lo exige además la FK en el back).",
4554
+ accept: "Tipos aceptados (ej. `image/*`, `image/png,image/jpeg` o `pdf,docx`).",
4555
+ maxSizeMB: "Tamaño máximo del archivo en megabytes.",
4556
+ aspectRatio: "Relación de aspecto de la vista previa (ej. `16/9`).",
4557
+ previewSize: "Tamaño de la vista previa.",
4558
+ formatCurrency: "Campo del registro del que se toma la moneda (ej. `currency`).",
4559
+ display: "Presentación del grupo: `card`, `collapsible` o `inline`.",
4560
+ fields: "Campos de cada item (cualquier tipo, incluso `group` o `list`).",
4561
+ minItems: "Cantidad mínima de items.",
4562
+ maxItems: "Cantidad máxima de items.",
4563
+ sortable: "Si se puede reordenar (por defecto: sí).",
4564
+ positionField: "Campo donde se guarda el orden dentro de cada item (`position`).",
4565
+ addLabel: "Etiqueta del botón para agregar un item nuevo.",
4566
+ emptyText: "Texto que se muestra cuando no hay items.",
4567
+ itemDisplay: "Cómo se muestra cada item: `card`, `row` o `accordion`.",
4568
+ itemFields: "Campos de cada item (cualquier tipo, incluso `group` o `list`).",
4569
+ itemTitle: "Campo del item usado como título cuando está colapsado.",
4570
+ primaryFirst: "El primer item tiene significado especial (ej. imagen principal).",
4571
+ itemType: "Tipo permitido de cada item (base.md §9: solo `text`, `url` o `email`).",
4572
+ sort: "Si la lista se ordena alfabéticamente o por posición.",
4573
+ filter: "Si el listado permite filtrado por texto.",
4574
+ search: "Campos buscables en el listado.",
4575
+ filters: "Filtros declarados para el listado.",
4576
+ listColumns: "Columnas que se muestran en el listado.",
4577
+ searchable: "Si el campo es buscable.",
4578
+ filterable: "Si el campo es filtrable.",
4579
+ sortableItems: "Si los items de la lista se pueden reordenar.",
4580
+ groupBy: "Campo por el que agrupar los items.",
4581
+ cardWidth: "Ancho de cada tarjeta de opción en la grilla (1–12). Por defecto `4` (3 tarjetas por fila en escritorio).",
4582
+ cardCols: "Cuántas tarjetas mostrar por fila en el punto de ruptura `lg`. Sobrescribe el cálculo automático basado en `cardWidth`.",
4583
+ hintMetric: "Texto secundario bajo la cifra (estático, va en el schema).",
4584
+ unitChart: "Sufijo de las cifras del eje («unidades», «S/»).",
4585
+ segments: "Segmentos de la barra de distribución porcentual.",
4586
+ actions: "Acciones de navegación por fila.",
4587
+ labelAction: "Etiqueta de la acción.",
4588
+ icon: "Icono de la acción.",
4589
+ navigateTo: "Ruta de destino de la acción.",
4590
+ variant: "Variante visual: `primary`, `secondary` u `outline`.",
4591
+ widgets: "Widgets del panel. Se declara en `ResourceSchema.widgets` — no en `fields`, porque un KPI no es un campo.",
4592
+ mobileWidth: "Ancho en la grilla en mobile (1–12). Por defecto `12` (ancho completo, apilado).",
4593
+ sourceWidget: "De dónde saca sus datos: `DataSource` o `{ kind: \"payload\" }`.",
4594
+ hintWidget: "Texto secundario bajo la cifra (estático, va en el schema).",
4595
+ unitWidget: "Sufijo de las cifras del eje."
4596
+ };
4597
+ export { API_DRIVER, API_URL, ApiError, ApiService, AuthService, COLUMN_FORMAT_TYPES, ComposerHost, ConfirmDialog, DEFAULT_RESPONSE_UNWRAP, Dashboard, DataSourceService, ErrorMapperService, FIREBASE_AUTH_ADAPTER, FieldHost, FormView, GAS_SCHEMAS, ListView, Login, MAX_DEPTH, NotificationService, ResourcePage, SESSION_TOKEN_KEY, SESSION_USER_KEY, SUPPORTED_FIELD_TYPE_LIST, SchemaCompositionError, Sidebar, Toast, UploadService, VALUE_SOURCES, actionType, actionTypes, actionsFor, allSchemas, apiErrorInterceptor, authGuard, buildFormSchema, buildPayload, childTree, columnFormatDescriptors, fieldDescriptors, getAction, getAuth, get as getRenderDescriptor, getSchema, groupTree, interpolateTemplate, isSupported as isRenderSupported, isSupported, isShareAction, isTriggerAction, itemTree, layoutDescriptors, listTree, resource_page_exports as n, provideFirebaseAdapter, provideGasAdmin, provideRenderDescriptors, registerAction, register as registerRenderDescriptor, renderKinds, renewedTokenOf, resolveShare, resourceRoutes, schemaDescriptions, seedModel, setSchemaCatalog, shellRoutes, stringItemTree, composer_host_exports as t, unregister as unregisterRenderDescriptor, validateComposition, viewDescriptors };
4508
4598
 
4509
4599
  //# sourceMappingURL=tinya-code-gas-admin-ui.mjs.map