@miguimono/json-schema 2.0.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/LICENSE +21 -0
- package/README.md +255 -0
- package/dist/schema/README.md +421 -0
- package/dist/schema/fesm2022/json-schema.mjs +1654 -0
- package/dist/schema/fesm2022/json-schema.mjs.map +1 -0
- package/dist/schema/index.d.ts +5 -0
- package/dist/schema/lib/components/schema-card.component.d.ts +128 -0
- package/dist/schema/lib/components/schema-links.component.d.ts +61 -0
- package/dist/schema/lib/components/schema.component.d.ts +115 -0
- package/dist/schema/lib/models.d.ts +1 -0
- package/dist/schema/lib/services/json-adapter.service.d.ts +1 -0
- package/dist/schema/lib/services/schema-layout.service.d.ts +1 -0
- package/dist/schema/lib/shared/models.d.ts +319 -0
- package/dist/schema/lib/shared/services/json-adapter.service.d.ts +12 -0
- package/dist/schema/lib/shared/services/schema-layout.service.d.ts +21 -0
- package/dist/schema/ng16/fesm2022/json-schema-ng16.mjs +1656 -0
- package/dist/schema/ng16/fesm2022/json-schema-ng16.mjs.map +1 -0
- package/dist/schema/ng16/index.d.ts +5 -0
- package/dist/schema/ng16/lib/components/schema-card.component.d.ts +64 -0
- package/dist/schema/ng16/lib/components/schema-links.component.d.ts +28 -0
- package/dist/schema/ng16/lib/components/schema.component.d.ts +132 -0
- package/dist/schema/ng16/lib/models.d.ts +1 -0
- package/dist/schema/ng16/lib/services/json-adapter.service.d.ts +1 -0
- package/dist/schema/ng16/lib/services/schema-layout.service.d.ts +1 -0
- package/dist/schema/ng16/lib/shared/models.d.ts +319 -0
- package/dist/schema/ng16/lib/shared/services/json-adapter.service.d.ts +12 -0
- package/dist/schema/ng16/lib/shared/services/schema-layout.service.d.ts +21 -0
- package/dist/schema/ng16/public-api.d.ts +6 -0
- package/dist/schema/public-api.d.ts +5 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Miguimono
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# JSON Schema
|
|
2
|
+
|
|
3
|
+
Esta librería tiene **dos variantes** de build:
|
|
4
|
+
|
|
5
|
+
- `projects/schema-ng19`: build principal para Angular moderno (en este repo se usa Angular 19).
|
|
6
|
+
- `projects/schema-ng16`: build compatible con Angular 16 (export en subpath `./ng16`).
|
|
7
|
+
|
|
8
|
+
Ambas se construyen desde **la raíz** del repo. No necesitas instalar dependencias dentro de `projects/schema-ng19` ni `projects/schema-ng16`.
|
|
9
|
+
|
|
10
|
+
## Requisitos y versiones
|
|
11
|
+
|
|
12
|
+
- Node.js: **no hay `engines` definidos** en los `package.json`, por lo que debes usar una versión compatible con tu Angular objetivo.
|
|
13
|
+
- NPM: la versión incluida con tu Node.
|
|
14
|
+
- Angular CLI: viene como dependencia del workspace cuando instalas en la raíz.
|
|
15
|
+
|
|
16
|
+
Recomendación práctica usando `nvm`:
|
|
17
|
+
|
|
18
|
+
- Para construir la variante principal (Angular moderno): `nvm use 22`
|
|
19
|
+
- Para probar compatibilidad Angular 16 en entornos antiguos: `nvm use 16` (o una versión LTS más nueva si tu entorno lo permite)
|
|
20
|
+
|
|
21
|
+
Si cambias de versión de Node, **reinstala dependencias en la raíz** para evitar binarios incompatibles.
|
|
22
|
+
|
|
23
|
+
## Instalación (única, en la raíz)
|
|
24
|
+
|
|
25
|
+
Desde la raíz del repo:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
nvm use 22
|
|
29
|
+
npm install
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Esto crea un **solo** `node_modules` en la raíz.
|
|
33
|
+
Las carpetas `projects/schema-ng19/node_modules` y `projects/schema-ng16/node_modules` **no deberían existir**.
|
|
34
|
+
|
|
35
|
+
## Compilación
|
|
36
|
+
|
|
37
|
+
Desde la raíz del repo:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# build Angular moderno
|
|
41
|
+
npm run build:schema-ng19
|
|
42
|
+
|
|
43
|
+
# build Angular 16 (subpath ./ng16)
|
|
44
|
+
npm run build:schema-ng16
|
|
45
|
+
|
|
46
|
+
# build de ambas
|
|
47
|
+
npm run build
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Los artefactos quedan en:
|
|
51
|
+
|
|
52
|
+
- `dist/schema/` (principal)
|
|
53
|
+
- `dist/schema/ng16/` (compatibilidad)
|
|
54
|
+
|
|
55
|
+
## Empaquetado (npm pack)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm run pack
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Esto:
|
|
62
|
+
|
|
63
|
+
1. Construye ambas variantes.
|
|
64
|
+
2. Genera un `.tgz` en la raíz, por ejemplo `json-schema-x.y.z.tgz`.
|
|
65
|
+
|
|
66
|
+
Si quieres empaquetar manualmente desde la carpeta de salida:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cd dist/schema
|
|
70
|
+
npm pack
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Consumo en proyectos
|
|
74
|
+
|
|
75
|
+
Import normal (Angular moderno):
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { SchemaComponent } from "@miguimono/json-schema";
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Import explícito Angular 19:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { SchemaComponent } from "@miguimono/json-schema/ng19";
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Import compatible Angular 16:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { SchemaComponent } from "@miguimono/json-schema/ng16";
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## ¿Qué hace la librería?
|
|
94
|
+
|
|
95
|
+
Convierte un JSON arbitrario en un **grafo visual interactivo** de cards y enlaces.
|
|
96
|
+
Incluye normalización del JSON, layout jerárquico determinista y render con pan/zoom.
|
|
97
|
+
|
|
98
|
+
## Módulos y responsabilidades
|
|
99
|
+
|
|
100
|
+
- `SchemaComponent`: orquesta el pipeline completo (normalización → layout → render), maneja pan/zoom, overlays y toolbar.
|
|
101
|
+
- `SchemaCardComponent`: renderiza un nodo como card, admite `cardTemplate`, badges e imagen opcional.
|
|
102
|
+
- `SchemaLinksComponent`: dibuja las aristas en SVG según el estilo configurado.
|
|
103
|
+
- `JsonAdapterService`: normaliza el JSON en nodos/aristas con metadatos.
|
|
104
|
+
- `SchemaLayoutService`: calcula posiciones y puntos de aristas.
|
|
105
|
+
- `models.ts`: contratos y `DEFAULT_SETTINGS`.
|
|
106
|
+
|
|
107
|
+
## Flujo interno (alto nivel)
|
|
108
|
+
|
|
109
|
+
1. `JsonAdapterService` normaliza el JSON en `NormalizedGraph`.
|
|
110
|
+
2. `SchemaLayoutService` calcula posiciones y puntos de aristas.
|
|
111
|
+
3. `SchemaComponent` renderiza cards/enlaces y gestiona pan/zoom.
|
|
112
|
+
|
|
113
|
+
## Recomendaciones de performance
|
|
114
|
+
|
|
115
|
+
- Para grafos muy grandes, considera:
|
|
116
|
+
- `dataView.previewMaxKeys` bajo (ej. 3–8).
|
|
117
|
+
- `dataView.maxDepth` (ej. 3–6).
|
|
118
|
+
- `dataView.autoResizeCards: false` si necesitas mayor velocidad.
|
|
119
|
+
- `viewport.height` más alto si el grafo es muy vertical.
|
|
120
|
+
- Si usas imágenes, define `dataView.imageSizePx` y `imageFit` para evitar relayouts.
|
|
121
|
+
|
|
122
|
+
## Troubleshooting (errores comunes)
|
|
123
|
+
|
|
124
|
+
- `Cannot destructure property 'pos' of 'file.referencedFiles[index]' ...`
|
|
125
|
+
Suele indicar incompatibilidad de TypeScript. Para Angular 19 usa TS `~5.5.x`.
|
|
126
|
+
- `Could not find the '@angular-devkit/build-angular:ng-packagr' builder`
|
|
127
|
+
Verifica que `@angular-devkit/build-angular` y `ng-packagr` estén en `devDependencies`.
|
|
128
|
+
- `Unknown argument: verbose`
|
|
129
|
+
Usa `npx ng ...` para forzar el CLI local del proyecto.
|
|
130
|
+
- Si el esquema no se re-renderiza tras mutar el JSON, reasigna `data` con un
|
|
131
|
+
nuevo objeto (cache referencial).
|
|
132
|
+
|
|
133
|
+
## Estructura recomendada (mantenimiento)
|
|
134
|
+
|
|
135
|
+
- `projects/schema-ng19`: build principal (Angular 19).
|
|
136
|
+
- `projects/schema-ng16`: build compatibilidad (Angular 16).
|
|
137
|
+
- `projects/schema-shared`: fuente única de modelos y servicios.
|
|
138
|
+
- `scripts/sync-shared.js`: copia `schema-shared` dentro de cada build antes de compilar.
|
|
139
|
+
- `projects/schema-shared/src/lib/styles`: tokens, mixins y base de estilos.
|
|
140
|
+
|
|
141
|
+
Notas de mantenimiento:
|
|
142
|
+
|
|
143
|
+
- **No edites** manualmente las copias dentro de `schema-ng16/src/lib/shared` ni `schema-ng19/src/lib/shared`.
|
|
144
|
+
- Haz cambios en `projects/schema-shared/src/lib` y compila (el script las sincroniza).
|
|
145
|
+
- Mantén la versión **única** en el `package.json` raíz (se sincroniza a los subproyectos).
|
|
146
|
+
- Puedes verificar sincronización con `npm run check:shared`.
|
|
147
|
+
- Para builds limpios: `npm run clean:dist` (funciona en Windows, macOS y Linux).
|
|
148
|
+
|
|
149
|
+
## Uso rápido (Angular 19 / 16)
|
|
150
|
+
|
|
151
|
+
### Angular 19 (default)
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { SchemaComponent } from "@miguimono/json-schema";
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Angular 16
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { SchemaComponent } from "@miguimono/json-schema/ng16";
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Ejemplo mínimo
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { Component } from "@angular/core";
|
|
167
|
+
import { CommonModule } from "@angular/common";
|
|
168
|
+
import { SchemaComponent } from "@miguimono/json-schema";
|
|
169
|
+
|
|
170
|
+
@Component({
|
|
171
|
+
selector: "app-demo",
|
|
172
|
+
standalone: true,
|
|
173
|
+
imports: [CommonModule, SchemaComponent],
|
|
174
|
+
template: `<schema [data]="data"></schema>`,
|
|
175
|
+
})
|
|
176
|
+
export class DemoComponent {
|
|
177
|
+
data = {
|
|
178
|
+
root: {
|
|
179
|
+
name: "Root",
|
|
180
|
+
children: [{ name: "Child A" }, { name: "Child B" }],
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Ejemplo con settings básicos
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { SchemaSettings, DEFAULT_SETTINGS } from "@miguimono/json-schema";
|
|
190
|
+
|
|
191
|
+
const settings: SchemaSettings = {
|
|
192
|
+
...DEFAULT_SETTINGS,
|
|
193
|
+
layout: {
|
|
194
|
+
...DEFAULT_SETTINGS.layout,
|
|
195
|
+
layoutDirection: "RIGHT",
|
|
196
|
+
linkStyle: "curve",
|
|
197
|
+
},
|
|
198
|
+
dataView: {
|
|
199
|
+
...DEFAULT_SETTINGS.dataView,
|
|
200
|
+
titleKeyPriority: ["name", "title", "id"],
|
|
201
|
+
previewMaxKeys: 5,
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```html
|
|
207
|
+
<schema [data]="data" [settings]="settings"></schema>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## Instalación directa desde `.tgz` local (sin publicar)
|
|
211
|
+
|
|
212
|
+
Si copiaste el paquete a `lib/json-schema-x.y.z.tgz` dentro del proyecto consumidor:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
npm install ./lib/json-schema-x.y.z.tgz
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Luego:
|
|
219
|
+
|
|
220
|
+
- Angular 19+:
|
|
221
|
+
```ts
|
|
222
|
+
import { SchemaComponent } from "@miguimono/json-schema";
|
|
223
|
+
```
|
|
224
|
+
- Angular 19 explícito:
|
|
225
|
+
```ts
|
|
226
|
+
import { SchemaComponent } from "@miguimono/json-schema/ng19";
|
|
227
|
+
```
|
|
228
|
+
- Angular 16:
|
|
229
|
+
```ts
|
|
230
|
+
import { SchemaComponent } from "@miguimono/json-schema/ng16";
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Nota: el `.tgz` puede estar en cualquier ruta local; usa la ruta relativa o absoluta.
|
|
234
|
+
|
|
235
|
+
## Notas importantes
|
|
236
|
+
|
|
237
|
+
- Hay **3 `package.json`**:
|
|
238
|
+
- `package.json` raíz: scripts y exports.
|
|
239
|
+
- `projects/schema-ng19/package.json`: metadata del build principal.
|
|
240
|
+
- `projects/schema-ng16/package.json`: metadata del build `ng16`.
|
|
241
|
+
- **Solo se instala en la raíz**.
|
|
242
|
+
Si instalas dentro de `projects/schema-ng19` o `projects/schema-ng16`, tendrás tres `node_modules` y eso genera inconsistencias.
|
|
243
|
+
|
|
244
|
+
## Limpieza si ya instalaste en subproyectos
|
|
245
|
+
|
|
246
|
+
Si ya creaste `node_modules` dentro de los subproyectos, bórralos y vuelve a instalar en la raíz:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
rm -rf projects/schema-ng19/node_modules projects/schema-ng16/node_modules
|
|
250
|
+
npm install
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Licencia
|
|
254
|
+
|
|
255
|
+
MIT — Copyright (c) 2026 Miguimono
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# @miguimono/json-schema
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
**Schema** es una librería para **Angular 19** que transforma cualquier objeto **JSON arbitrario** en un **grafo visual interactivo** (cards + conexiones).
|
|
9
|
+
Construida con **standalone components**, **Angular Signals** e `input()`. Compatible con Angular Material 19 (opcional en tu app).
|
|
10
|
+
|
|
11
|
+
Pensada para explorar, depurar y presentar jerarquías de datos complejos en aplicaciones empresariales.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Tabla de contenidos
|
|
16
|
+
|
|
17
|
+
- [@miguimono/json-schema](#miguimonoschema)
|
|
18
|
+
- [Tabla de contenidos](#tabla-de-contenidos)
|
|
19
|
+
- [✨ Características](#-características)
|
|
20
|
+
- [📦 Instalación](#-instalación)
|
|
21
|
+
- [🧠 Conceptos y arquitectura](#-conceptos-y-arquitectura)
|
|
22
|
+
- [🧩 Componentes públicos](#-componentes-públicos)
|
|
23
|
+
- [🧪 Ejemplos](#-ejemplos)
|
|
24
|
+
- [Ejemplo básico (solo JSON)](#ejemplo-básico-solo-json)
|
|
25
|
+
- [Ejemplo completo (todas las entradas)](#ejemplo-completo-todas-las-entradas)
|
|
26
|
+
- [🔎 API](#-api)
|
|
27
|
+
- [Inputs de `<schema>`](#inputs-de-schema)
|
|
28
|
+
- [`SchemaSettings`](#schemasettings)
|
|
29
|
+
- [Estilos de enlaces](#estilos-de-enlaces)
|
|
30
|
+
- [✅ Buenas prácticas](#-buenas-prácticas)
|
|
31
|
+
- [❓ FAQ](#-faq)
|
|
32
|
+
- [🧭 Roadmap / Notas de versión](#-roadmap--notas-de-versión)
|
|
33
|
+
- [📄 Licencia](#-licencia)
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## ✨ Características
|
|
38
|
+
|
|
39
|
+
- Convierte **cualquier JSON** en un grafo navegable (sin premodelar).
|
|
40
|
+
- **Layout determinista** tipo _tidy tree_: sin solapes, orden estable tal cual el JSON.
|
|
41
|
+
- Dirección de flujo **RIGHT** (izq→der) o **DOWN** (arriba→abajo).
|
|
42
|
+
- **Alineación** del padre: con el **primer hijo** o **centrado** respecto a sus hijos.
|
|
43
|
+
- **Enlaces**: curva, ortogonal o línea recta (con animación suave en relayout).
|
|
44
|
+
- **Zoom, pan, reset** y **fit-to-view** automáticos.
|
|
45
|
+
- **Cards personalizables** vía `ng-template` (título + atributos + badges, o tu propio markup).
|
|
46
|
+
- **Auto-resize**: mide el DOM real y reacomoda el layout hasta estabilizar.
|
|
47
|
+
- **Collapse/Expand** por card (opcional) con preservación de “slots”.
|
|
48
|
+
- **Acento visual por clave booleana**: bordes/rellenos según `true/false/null`.
|
|
49
|
+
- Tooling moderno: **TypeScript 5**, **Angular Signals**, standalone components.
|
|
50
|
+
|
|
51
|
+
> **Nota**: La librería expone una API de alto nivel. Internamente utiliza:
|
|
52
|
+
>
|
|
53
|
+
> - `JsonAdapterService`: JSON → grafo (nodos/aristas) con metadatos.
|
|
54
|
+
> - `SchemaLayoutService`: posiciones deterministas + puntos de enlace.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 📦 Instalación
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm i @miguimono/json-schema
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Peer deps:**
|
|
65
|
+
|
|
66
|
+
- `@angular/core` `^19.0.0`
|
|
67
|
+
- `@angular/common` `^19.0.0`
|
|
68
|
+
- `@angular/cdk` `^19.0.0` (si usas Material en tu app)
|
|
69
|
+
- `rxjs` `~7.8.0`
|
|
70
|
+
- TypeScript `5.x`
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 🧠 Conceptos y arquitectura
|
|
75
|
+
|
|
76
|
+
- **Nodo (SchemaNode):** card con `label`/título, preview de atributos y badges de arrays.
|
|
77
|
+
El adapter determina orden entre hermanos (prop `jsonMeta.childOrder`) para preservar **el orden del JSON**.
|
|
78
|
+
- **Arista (SchemaEdge):** une dos nodos (`source` → `target`) y contiene `points` (start/bends/end).
|
|
79
|
+
- **Grafo normalizado (NormalizedGraph):** `nodes + edges + meta`.
|
|
80
|
+
- **Layout:** el servicio organiza los nodos por profundidad y subárboles.
|
|
81
|
+
- `layoutDirection`: `RIGHT` o `DOWN`.
|
|
82
|
+
- `layoutAlign`: `'firstChild' | 'center'`.
|
|
83
|
+
- `linkStyle`: `'curve' | 'orthogonal' | 'line'`.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 🧩 Componentes públicos
|
|
88
|
+
|
|
89
|
+
| Componente | Descripción rápida |
|
|
90
|
+
| ---------------------- | ------------------------------------------------------------------------------------------ |
|
|
91
|
+
| `SchemaComponent` | Orquestador (pan/zoom, render de cards y enlaces, medición, relayout y colapso/expansión). |
|
|
92
|
+
| `SchemaCardComponent` | Card genérica por nodo. Soporta `ng-template` para personalizar contenido. |
|
|
93
|
+
| `SchemaLinksComponent` | Dibuja todas las aristas en un único `<svg>`. |
|
|
94
|
+
|
|
95
|
+
> Usualmente **solo importas** `SchemaComponent`. Los demás son internos.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 🧪 Ejemplos
|
|
100
|
+
|
|
101
|
+
### Ejemplo básico (solo JSON)
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
// app/demo-basic.component.ts
|
|
105
|
+
// ---------------------------------------------------------
|
|
106
|
+
// Ejemplo mínimo: envío únicamente un JSON.
|
|
107
|
+
// ---------------------------------------------------------
|
|
108
|
+
import { Component } from '@angular/core';
|
|
109
|
+
import { CommonModule } from '@angular/common';
|
|
110
|
+
import { SchemaComponent } from '@miguimono/json-schema';
|
|
111
|
+
|
|
112
|
+
@Component({
|
|
113
|
+
selector: 'app-demo-basic',
|
|
114
|
+
standalone: true,
|
|
115
|
+
imports: [CommonModule, SchemaComponent],
|
|
116
|
+
template: \`
|
|
117
|
+
<schema [data]="exampleJson"></schema>
|
|
118
|
+
\`,
|
|
119
|
+
})
|
|
120
|
+
export class DemoBasicComponent {
|
|
121
|
+
exampleJson = {
|
|
122
|
+
central: {
|
|
123
|
+
central_name: 'Centro | Bogotá',
|
|
124
|
+
cables: [
|
|
125
|
+
{ cable_name: 'GA-05', in_damage: true },
|
|
126
|
+
{ cable_name: 'GA-06', in_damage: false },
|
|
127
|
+
],
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Ejemplo completo (todas las entradas)
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// app/demo-full.component.ts
|
|
137
|
+
// ---------------------------------------------------------
|
|
138
|
+
// Demostración completa: settings, template, mensajes y estados.
|
|
139
|
+
// ---------------------------------------------------------
|
|
140
|
+
import { Component, signal } from '@angular/core';
|
|
141
|
+
import { CommonModule } from '@angular/common';
|
|
142
|
+
import { SchemaComponent, DEFAULT_SETTINGS, SchemaSettings } from '@miguimono/json-schema';
|
|
143
|
+
|
|
144
|
+
@Component({
|
|
145
|
+
selector: 'app-demo-full',
|
|
146
|
+
standalone: true,
|
|
147
|
+
imports: [CommonModule, SchemaComponent],
|
|
148
|
+
template: \`
|
|
149
|
+
<schema
|
|
150
|
+
[data]="data()"
|
|
151
|
+
[settings]="settings"
|
|
152
|
+
[cardTemplate]="cardTpl"
|
|
153
|
+
[isLoading]="isLoading()"
|
|
154
|
+
[isError]="isError()"
|
|
155
|
+
[emptyMessage]="'No hay datos para mostrar'"
|
|
156
|
+
[loadingMessage]="'Cargando…'"
|
|
157
|
+
[errorMessage]="'No se pudo renderizar el esquema'"
|
|
158
|
+
(nodeClick)="onNodeClick($event)"
|
|
159
|
+
(linkClick)="onLinkClick($event)"
|
|
160
|
+
></schema>
|
|
161
|
+
|
|
162
|
+
<!-- Template personalizado para cada card -->
|
|
163
|
+
<ng-template #cardTpl let-node>
|
|
164
|
+
<div style="padding:12px 14px; max-width:360px">
|
|
165
|
+
<div style="font-weight:700; margin-bottom:6px">
|
|
166
|
+
{{ node.jsonMeta?.title || node.label }}
|
|
167
|
+
</div>
|
|
168
|
+
<div *ngIf="node.jsonMeta?.attributes as attrs">
|
|
169
|
+
<div *ngFor="let e of (attrs | keyvalue)" style="font-size:12px; margin:2px 0">
|
|
170
|
+
<strong style="opacity:.7">{{ e.key }}:</strong> {{ e.value }}
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
</ng-template>
|
|
175
|
+
\`,
|
|
176
|
+
})
|
|
177
|
+
export class DemoFullComponent {
|
|
178
|
+
// Datos reactivos (puedes reemplazar por tu fachada)
|
|
179
|
+
data = signal<any>({
|
|
180
|
+
nivel: 'nivel 0',
|
|
181
|
+
children: [
|
|
182
|
+
{ nivel: 'Nivel 1', info: '...', children: [] },
|
|
183
|
+
{ nivel: 'Nivel 2', info: '...', children: [] },
|
|
184
|
+
],
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Settings (parte de ellos, usando DEFAULT_SETTINGS como base)
|
|
188
|
+
settings: SchemaSettings = {
|
|
189
|
+
...DEFAULT_SETTINGS,
|
|
190
|
+
layout: {
|
|
191
|
+
...DEFAULT_SETTINGS.layout,
|
|
192
|
+
layoutDirection: 'RIGHT', // RIGHT | DOWN
|
|
193
|
+
layoutAlign: 'firstChild', // firstChild | center
|
|
194
|
+
linkStyle: 'curve', // curve | orthogonal | line
|
|
195
|
+
straightThresholdDx: 160,
|
|
196
|
+
curveTension: 80,
|
|
197
|
+
snapChainSegmentsY: true, // alinear cadenas lineales
|
|
198
|
+
},
|
|
199
|
+
colors: {
|
|
200
|
+
...DEFAULT_SETTINGS.colors,
|
|
201
|
+
linkStroke: '#019df4',
|
|
202
|
+
linkStrokeWidth: 2,
|
|
203
|
+
accentByKey: 'certified', // toma true/false/null de node.data[certified]
|
|
204
|
+
accentFill: true,
|
|
205
|
+
showColorTrue: true,
|
|
206
|
+
showColorFalse: true,
|
|
207
|
+
showColorNull: true,
|
|
208
|
+
},
|
|
209
|
+
dataView: {
|
|
210
|
+
...DEFAULT_SETTINGS.dataView,
|
|
211
|
+
titleKeyPriority: ['name', 'title', 'id', 'label'],
|
|
212
|
+
previewMaxKeys: 4,
|
|
213
|
+
treatScalarArraysAsAttribute: true,
|
|
214
|
+
collapseArrayContainers: true,
|
|
215
|
+
collapseSingleChildWrappers: true,
|
|
216
|
+
enableCollapse: true, // muestra botón por card si tiene hijos
|
|
217
|
+
defaultNodeSize: { width: 220, height: 96 },
|
|
218
|
+
noWrapKeys: ['service_number'], // muestra esas claves en una sola línea
|
|
219
|
+
maxCardWidth: 380, // restricciones a la medición
|
|
220
|
+
maxCardHeight: null,
|
|
221
|
+
autoResizeCards: true,
|
|
222
|
+
measureExtraWidthPx: 24,
|
|
223
|
+
measureExtraHeightPx: 0,
|
|
224
|
+
},
|
|
225
|
+
viewport: {
|
|
226
|
+
...DEFAULT_SETTINGS.viewport,
|
|
227
|
+
height: 800,
|
|
228
|
+
minHeight: 480,
|
|
229
|
+
showToolbar: true,
|
|
230
|
+
},
|
|
231
|
+
messages: {
|
|
232
|
+
...DEFAULT_SETTINGS.messages,
|
|
233
|
+
isLoading: false,
|
|
234
|
+
isError: false,
|
|
235
|
+
emptyMessage: 'No hay datos para mostrar',
|
|
236
|
+
loadingMessage: 'Cargando…',
|
|
237
|
+
errorMessage: 'Error al cargar el esquema',
|
|
238
|
+
},
|
|
239
|
+
debug: {
|
|
240
|
+
...DEFAULT_SETTINGS.debug,
|
|
241
|
+
measure: false,
|
|
242
|
+
layout: false,
|
|
243
|
+
paintBounds: false,
|
|
244
|
+
exposeOnWindow: false,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// Estados (por ejemplo, mientras llega el JSON)
|
|
249
|
+
isLoading = signal(false);
|
|
250
|
+
isError = signal(false);
|
|
251
|
+
|
|
252
|
+
onNodeClick(n: any) {
|
|
253
|
+
console.log('nodeClick', n);
|
|
254
|
+
}
|
|
255
|
+
onLinkClick(e: any) {
|
|
256
|
+
console.log('linkClick', e);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 🔎 API
|
|
264
|
+
|
|
265
|
+
### Inputs de `<schema>`
|
|
266
|
+
|
|
267
|
+
| Input | Tipo | Default | Descripción |
|
|
268
|
+
| ---------------- | -------------------------- | ------------------------------ | -------------------------------------------------------------------------- |
|
|
269
|
+
| `data` | `any` | — | **Requerido.** JSON arbitrario a visualizar. |
|
|
270
|
+
| `settings` | `SchemaSettings \| null` | `DEFAULT_SETTINGS` | Configuración por secciones. Los valores no provistos heredan del default. |
|
|
271
|
+
| `cardTemplate` | `TemplateRef<any> \| null` | `null` | Plantilla personalizada para cada card (el nodo llega como `$implicit`). |
|
|
272
|
+
| `isLoading` | `boolean` | `false` | Fuerza overlay de carga (también configurable en `settings.messages`). |
|
|
273
|
+
| `isError` | `boolean` | `false` | Fuerza overlay de error (también configurable en `settings.messages`). |
|
|
274
|
+
| `emptyMessage` | `string` | `'No hay datos para mostrar'` | Texto del estado vacío. |
|
|
275
|
+
| `loadingMessage` | `string` | `'Cargando…'` | Texto del estado de carga. |
|
|
276
|
+
| `errorMessage` | `string` | `'Error al cargar el esquema'` | Texto del estado de error. |
|
|
277
|
+
|
|
278
|
+
**Outputs**
|
|
279
|
+
|
|
280
|
+
| Output | Payload | Descripción |
|
|
281
|
+
| ----------- | ------------ | ----------------------------------------- |
|
|
282
|
+
| `nodeClick` | `SchemaNode` | Se emite al hacer click sobre una card. |
|
|
283
|
+
| `linkClick` | `SchemaEdge` | Se emite al hacer click sobre una arista. |
|
|
284
|
+
|
|
285
|
+
> El layout y la medición son internos. El contenedor solo provee `data` y, opcionalmente, `settings` y `cardTemplate`.
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### `SchemaSettings`
|
|
290
|
+
|
|
291
|
+
Las opciones están **agrupadas por secciones**. Cualquier sección/propiedad omitida toma su valor desde `DEFAULT_SETTINGS` (puedes importarlo).
|
|
292
|
+
|
|
293
|
+
**layout**
|
|
294
|
+
|
|
295
|
+
| Propiedad | Tipo | Default | Descripción |
|
|
296
|
+
| --------------------- | ----------------------------------- | -------------- | ------------------------------------------------------------------------------- |
|
|
297
|
+
| `layoutDirection` | `'RIGHT' \| 'DOWN'` | `'RIGHT'` | Orientación del grafo. |
|
|
298
|
+
| `layoutAlign` | `'firstChild' \| 'center'` | `'firstChild'` | Alineación vertical (RIGHT) u horizontal (DOWN) del padre respecto a sus hijos. |
|
|
299
|
+
| `linkStyle` | `'curve' \| 'orthogonal' \| 'line'` | `'curve'` | Estilo visual de aristas. |
|
|
300
|
+
| `curveTension` | `number` | `80` | Tensión para curvas; clamp 20–200. |
|
|
301
|
+
| `straightThresholdDx` | `number` | `160` | Si `dx < threshold`, una curva se dibuja recta para evitar curvas muy cerradas. |
|
|
302
|
+
| `snapChainSegmentsY` | `boolean` | `false` | Alinea cadenas lineales (out=1) al eje del hijo para “líneas rectas”. |
|
|
303
|
+
|
|
304
|
+
**dataView**
|
|
305
|
+
|
|
306
|
+
| Propiedad | Tipo | Default |
|
|
307
|
+
| ------------------------------ | --------------------------------- | ------------------------------- |
|
|
308
|
+
| `titleKeyPriority` | `string[]` | `['name','title','id','label']` |
|
|
309
|
+
| `hiddenKeysGlobal` | `string[]` | `[]` |
|
|
310
|
+
| `titleMode` | `'auto' \| 'none'` | `'auto'` |
|
|
311
|
+
| `previewMaxKeys` | `number` | `4` |
|
|
312
|
+
| `treatScalarArraysAsAttribute` | `boolean` | `true` |
|
|
313
|
+
| `collapseArrayContainers` | `boolean` | `true` |
|
|
314
|
+
| `collapseSingleChildWrappers` | `boolean` | `true` |
|
|
315
|
+
| `maxDepth` | `number \| null` | `null` |
|
|
316
|
+
| `defaultNodeSize` | `{ width:number; height:number }` | `{220,96}` |
|
|
317
|
+
| `noWrapKeys` | `string[]` | `[]` |
|
|
318
|
+
| `maxCardWidth` | `number \| null` | `null` |
|
|
319
|
+
| `maxCardHeight` | `number \| null` | `null` |
|
|
320
|
+
| `autoResizeCards` | `boolean` | `true` |
|
|
321
|
+
| `measureExtraWidthPx` | `number` | `24` |
|
|
322
|
+
| `measureExtraHeightPx` | `number` | `0` |
|
|
323
|
+
| `enableCollapse` | `boolean` | `false` |
|
|
324
|
+
|
|
325
|
+
**colors**
|
|
326
|
+
|
|
327
|
+
| Propiedad | Tipo | Default | Comentario |
|
|
328
|
+
| -------------------------- | ---------------- | --------- | --------------------------------------------------- |
|
|
329
|
+
| `linkStroke` | `string` | `#019df4` | Color de aristas. |
|
|
330
|
+
| `linkStrokeWidth` | `number` | `2` | Grosor de aristas. |
|
|
331
|
+
| `accentByKey` | `string \| null` | `null` | Clave booleana en `node.data` para acento por card. |
|
|
332
|
+
| `accentFill` | `boolean` | `false` | Relleno además del borde. |
|
|
333
|
+
| `accentInverse` | `boolean` | `false` | Invierte mapping de colores. |
|
|
334
|
+
| `showColorTrue/False/Null` | `boolean` | `false` | Habilita color por cada caso. |
|
|
335
|
+
|
|
336
|
+
**viewport**
|
|
337
|
+
|
|
338
|
+
| Propiedad | Tipo | Default |
|
|
339
|
+
| ------------- | --------- | ------- |
|
|
340
|
+
| `height` | `number` | `800` |
|
|
341
|
+
| `minHeight` | `number` | `480` |
|
|
342
|
+
| `showToolbar` | `boolean` | `true` |
|
|
343
|
+
|
|
344
|
+
**messages**
|
|
345
|
+
|
|
346
|
+
| Propiedad | Tipo | Default |
|
|
347
|
+
| ---------------- | --------- | ------------------------------ |
|
|
348
|
+
| `isLoading` | `boolean` | `false` |
|
|
349
|
+
| `isError` | `boolean` | `false` |
|
|
350
|
+
| `emptyMessage` | `string` | `'No hay datos para mostrar'` |
|
|
351
|
+
| `loadingMessage` | `string` | `'Cargando…'` |
|
|
352
|
+
| `errorMessage` | `string` | `'Error al cargar el esquema'` |
|
|
353
|
+
|
|
354
|
+
**debug**
|
|
355
|
+
|
|
356
|
+
| Propiedad | Tipo | Default |
|
|
357
|
+
| ---------------- | --------- | ------- |
|
|
358
|
+
| `measure` | `boolean` | `false` |
|
|
359
|
+
| `layout` | `boolean` | `false` |
|
|
360
|
+
| `paintBounds` | `boolean` | `false` |
|
|
361
|
+
| `exposeOnWindow` | `boolean` | `false` |
|
|
362
|
+
|
|
363
|
+
> Para ver todos los defaults en código, revisa `DEFAULT_SETTINGS` (exportado desde `projects/schema-ng19/src/lib/models.ts`).
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
### Estilos de enlaces
|
|
368
|
+
|
|
369
|
+
- **`curve`** (default): curva cúbica con tensión configurable (`curveTension`).
|
|
370
|
+
Si la separación horizontal `dx` es pequeña (< `straightThresholdDx`), se renderiza recta.
|
|
371
|
+
- **`orthogonal`**: segmentos en “L” (con codo intermedio).
|
|
372
|
+
- **`line`**: línea recta simple.
|
|
373
|
+
|
|
374
|
+
Cámbialo desde la toolbar integrada o vía `settings.layout.linkStyle`.
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## ✅ Buenas prácticas
|
|
379
|
+
|
|
380
|
+
- Pasa `data` ya “listo para leer”; el adapter colapsa _wrappers_ triviales y arrays escalares (opcional).
|
|
381
|
+
- Si usas `cardTemplate`, **no dependas** de orden de claves en objetos; accede por `node.data.tuClave`.
|
|
382
|
+
- Si activas `enableCollapse`, deja que el contenedor preserve el estado de colapso si recreas el componente.
|
|
383
|
+
- Para árboles muy altos, puedes aumentar `viewport.height` o usar el ajuste automático del stage (incluido en el componente).
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## ❓ FAQ
|
|
388
|
+
|
|
389
|
+
**¿Cómo personalizo el botón de colapso (dirección del caret)?**
|
|
390
|
+
El icono se determina en `SchemaCardComponent` (método `arrowGlyph()`), que muestra **◀/▶** para `RIGHT` y **▲/▼** para `DOWN`, según `isCollapsed`.
|
|
391
|
+
|
|
392
|
+
**¿Se respeta el orden del JSON?**
|
|
393
|
+
Sí. El adapter genera `jsonMeta.childOrder` y el layout lo respeta en todas las capas.
|
|
394
|
+
|
|
395
|
+
**¿Por qué una arista curva a veces se ve recta?**
|
|
396
|
+
Si `dx < straightThresholdDx`, se dibuja recta para evitar curvas muy cerradas. Ajusta ese umbral en `settings.layout`.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## 🧭 Roadmap / Notas de versión
|
|
401
|
+
|
|
402
|
+
- **0.4.11**
|
|
403
|
+
|
|
404
|
+
- Layout **tidy** determinista (sin solapes, orden estable).
|
|
405
|
+
- Alineación `firstChild` real (padre al centro de la **card** del primer hijo).
|
|
406
|
+
- **Snap** opcional de cadenas (alineación perfecta en columnas).
|
|
407
|
+
- Restauración de `curve/line` con puntos `[start,end]` (el renderer aplica la curva).
|
|
408
|
+
- Mejora en stage dinámico (evita “recortes” en árboles profundos).
|
|
409
|
+
|
|
410
|
+
- **0.4.10**
|
|
411
|
+
- Migración a `SchemaSettings` + `DEFAULT_SETTINGS`.
|
|
412
|
+
- Cards con botón de colapso/expansión opcional.
|
|
413
|
+
- Acento visual por clave booleana.
|
|
414
|
+
|
|
415
|
+
> Cambios _breaking_: si venías de una versión con `options`, migra a `settings` (misma estructura, agrupada por secciones).
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## 📄 Licencia
|
|
420
|
+
|
|
421
|
+
[MIT](./LICENSE) © 2025 [Miguel Niño (@miguimono)](https://github.com/miguimono)
|