@axzydev/axzy_ui_system 1.5.3 → 1.7.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/dist/index.cjs +6071 -4316
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +145 -1
- package/dist/index.d.ts +145 -1
- package/dist/index.js +4493 -2723
- package/dist/index.js.map +1 -1
- package/dist/layered.css +1 -1
- package/package.json +1 -1
- package/src/App.tsx +10 -0
- package/src/components/molecules/json-editor/json-editor-tree.tsx +235 -0
- package/src/components/molecules/json-editor/json-editor.index.ts +2 -0
- package/src/components/molecules/json-editor/json-editor.props.ts +82 -0
- package/src/components/molecules/json-editor/json-editor.tsx +972 -0
- package/src/components/molecules/json-editor/json-editor.utils.ts +717 -0
- package/src/components/molecules/json-editor/useJsonEditorKeyboard.ts +256 -0
- package/src/components/molecules/json-renderer/json-renderer.index.ts +2 -0
- package/src/components/molecules/json-renderer/json-renderer.props.ts +31 -0
- package/src/components/molecules/json-renderer/json-renderer.tsx +79 -0
- package/src/components/organisms/sidebar/sidebar.tsx +51 -14
- package/src/dev.css +24 -1
- package/src/hooks/useJsonRender.tsx +9 -0
- package/src/i18n/locales/en.ts +54 -0
- package/src/i18n/locales/es.ts +54 -0
- package/src/index.css +414 -0
- package/src/index.ts +10 -2
- package/src/sandbox/AxzyLogo.tsx +139 -0
- package/src/sandbox/i18n.ts +2 -0
- package/src/sandbox/navigation.ts +2 -0
- package/src/showcases/FeedbackShowcases.tsx +16 -5
- package/src/showcases/HomeShowcase.tsx +16 -9
- package/src/showcases/JsonEditorShowcase.tsx +150 -0
- package/src/showcases/JsonRendererShowcase.tsx +70 -0
- package/src/showcases/StructureShowcases.tsx +9 -3
package/src/i18n/locales/es.ts
CHANGED
|
@@ -160,6 +160,60 @@ const es: ITMessages = {
|
|
|
160
160
|
"themeProvider.presets.oceanicTeal": "Oceanic Teal 🌊",
|
|
161
161
|
"themeProvider.presets.goldenHour": "Golden Hour ☀️",
|
|
162
162
|
"themeProvider.presets.deepForest": "Deep Forest 🌲",
|
|
163
|
+
|
|
164
|
+
// -------------------------------------------------------- ITJSONEditor
|
|
165
|
+
"jsonEditor.ariaLabel": "Editor de JSON",
|
|
166
|
+
"jsonEditor.placeholder": '{\n "type": "button",\n "props": { "label": "Aceptar" }\n}',
|
|
167
|
+
"jsonEditor.valid": "JSON válido",
|
|
168
|
+
"jsonEditor.invalid": "JSON no válido",
|
|
169
|
+
"jsonEditor.invalidAt": "Error en línea {line}, columna {column}",
|
|
170
|
+
"jsonEditor.format": "Formatear",
|
|
171
|
+
"jsonEditor.formatHint": "Reindenta el documento (Mayús+Alt+F)",
|
|
172
|
+
"jsonEditor.minify": "Minificar",
|
|
173
|
+
"jsonEditor.sortAsc": "A-Z",
|
|
174
|
+
"jsonEditor.sortDesc": "Z-A",
|
|
175
|
+
"jsonEditor.escape": "Escapar",
|
|
176
|
+
"jsonEditor.unescape": "Desescapar",
|
|
177
|
+
"jsonEditor.copy": "Copiar",
|
|
178
|
+
"jsonEditor.copied": "Copiado",
|
|
179
|
+
"jsonEditor.copyFailed": "No se pudo copiar al portapapeles",
|
|
180
|
+
"jsonEditor.importFile": "Abrir",
|
|
181
|
+
"jsonEditor.download": "Descargar",
|
|
182
|
+
"jsonEditor.fileLoaded": "Archivo cargado",
|
|
183
|
+
"jsonEditor.fileError": "No se pudo leer el archivo",
|
|
184
|
+
"jsonEditor.applied": "Acción aplicada",
|
|
185
|
+
"jsonEditor.actionFailed": "La acción no se pudo aplicar",
|
|
186
|
+
"jsonEditor.viewMode": "Modo de vista",
|
|
187
|
+
"jsonEditor.modeText": "Texto",
|
|
188
|
+
"jsonEditor.modeTree": "Árbol",
|
|
189
|
+
"jsonEditor.viewSettings": "Vista",
|
|
190
|
+
"jsonEditor.wrap": "Ajuste",
|
|
191
|
+
"jsonEditor.lineNumbers": "Números",
|
|
192
|
+
"jsonEditor.folding": "Plegado",
|
|
193
|
+
"jsonEditor.indent": "Indentación",
|
|
194
|
+
"jsonEditor.indentNone": "Sin sangrar",
|
|
195
|
+
"jsonEditor.collapseAll": "Plegar todo",
|
|
196
|
+
"jsonEditor.expandAll": "Desplegar todo",
|
|
197
|
+
"jsonEditor.collapseBlock": "Plegar el bloque de la línea {line}",
|
|
198
|
+
"jsonEditor.expandBlock": "Desplegar el bloque de la línea {line}",
|
|
199
|
+
"jsonEditor.foldMore": "… {count} líneas plegadas",
|
|
200
|
+
"jsonEditor.expandNode": "Desplegar nodo",
|
|
201
|
+
"jsonEditor.collapseNode": "Plegar nodo",
|
|
202
|
+
"jsonEditor.jumpToLine": "Ir a la línea {line}",
|
|
203
|
+
"jsonEditor.childCount": "{count} hijos",
|
|
204
|
+
"jsonEditor.treeNeedsValid": "Corrige el JSON para ver el árbol",
|
|
205
|
+
"jsonEditor.treeTruncated": "Árbol recortado: demasiados nodos, usa la vista de texto",
|
|
206
|
+
"jsonEditor.statLines": "{count} líneas",
|
|
207
|
+
"jsonEditor.statNodes": "{count} nodos",
|
|
208
|
+
"jsonEditor.statDepth": "prof. {count}",
|
|
209
|
+
"jsonEditor.statRoot": "raíz: {kind}",
|
|
210
|
+
"jsonEditor.statSize": "tamaño: {size}",
|
|
211
|
+
"jsonEditor.kindObject": "objeto",
|
|
212
|
+
"jsonEditor.kindArray": "array",
|
|
213
|
+
"jsonEditor.kindString": "texto",
|
|
214
|
+
"jsonEditor.kindNumber": "número",
|
|
215
|
+
"jsonEditor.kindBoolean": "booleano",
|
|
216
|
+
"jsonEditor.kindNull": "nulo",
|
|
163
217
|
};
|
|
164
218
|
|
|
165
219
|
export default es;
|
package/src/index.css
CHANGED
|
@@ -169,4 +169,418 @@
|
|
|
169
169
|
:where(.it-table-pinned-right) {
|
|
170
170
|
box-shadow: inset 1px 0 0 0 var(--color-secondary-200);
|
|
171
171
|
}
|
|
172
|
+
|
|
173
|
+
/* ── ITJSONEditor ────────────────────────────────────────────────────────
|
|
174
|
+
Editor de código sobre <textarea>: una capa con el JSON resaltado se pinta
|
|
175
|
+
debajo del textarea transparente. Las dos capas comparten tipografía y
|
|
176
|
+
`line-height`, y el alto de línea lo mide el componente en el DOM
|
|
177
|
+
(`--it-json-editor-line`), de ahí que aquí solo se fije la métrica. */
|
|
178
|
+
:where(.it-json-editor-canvas) {
|
|
179
|
+
--it-json-editor-line: 21px;
|
|
180
|
+
background: #fbfcfd;
|
|
181
|
+
}
|
|
182
|
+
:where(.it-json-editor-canvas[data-canvas="ink"]) {
|
|
183
|
+
background: #0b1120;
|
|
184
|
+
}
|
|
185
|
+
:where(.dark .it-json-editor-canvas) {
|
|
186
|
+
background: #020617;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
:where(.it-json-editor-code) {
|
|
190
|
+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
191
|
+
font-size: 12.5px;
|
|
192
|
+
/* Misma métrica que el textarea: los dos consumen la variable que publica el
|
|
193
|
+
componente con el alto de línea real. */
|
|
194
|
+
line-height: var(--it-json-editor-line, 21px);
|
|
195
|
+
tab-size: 2;
|
|
196
|
+
color: #334155;
|
|
197
|
+
}
|
|
198
|
+
/* El relleno vive en `.it-json-editor-code`, que es la clase compartida por la
|
|
199
|
+
capa resaltada y el textarea: así las dos cajas de scroll tienen el mismo
|
|
200
|
+
contenido y desplazan igual, y el alto de cada línea es exactamente
|
|
201
|
+
`--it-json-editor-line` para que el gutter no se desincronice. */
|
|
202
|
+
:where(.it-json-editor-code) {
|
|
203
|
+
padding: 10px 12px;
|
|
204
|
+
}
|
|
205
|
+
:where(.it-json-editor-code-line) {
|
|
206
|
+
white-space: pre;
|
|
207
|
+
}
|
|
208
|
+
:where(.it-json-editor-highlight) {
|
|
209
|
+
position: absolute;
|
|
210
|
+
inset: 0;
|
|
211
|
+
z-index: 0;
|
|
212
|
+
pointer-events: none;
|
|
213
|
+
}
|
|
214
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-code) {
|
|
215
|
+
color: #cbd5e1;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Textarea: texto transparente y cursor visible, encima de la capa pintada.
|
|
219
|
+
Las métricas de texto van declaradas **aquí** y no heredadas de
|
|
220
|
+
`.it-json-editor-code`: el textarea no es hijo de esa capa, así que sin esto
|
|
221
|
+
usa la tipografía de la página y el caret del navegador deja de coincidir
|
|
222
|
+
con el glifo pintado (el clic cae en otro carácter). */
|
|
223
|
+
:where(.it-json-editor-textarea) {
|
|
224
|
+
position: absolute;
|
|
225
|
+
inset: 0;
|
|
226
|
+
z-index: 1;
|
|
227
|
+
width: 100%;
|
|
228
|
+
height: 100%;
|
|
229
|
+
margin: 0;
|
|
230
|
+
border: 0;
|
|
231
|
+
resize: none;
|
|
232
|
+
outline: none;
|
|
233
|
+
background: transparent;
|
|
234
|
+
color: transparent;
|
|
235
|
+
caret-color: #2563eb;
|
|
236
|
+
-webkit-text-fill-color: transparent;
|
|
237
|
+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
238
|
+
font-size: 12.5px;
|
|
239
|
+
line-height: var(--it-json-editor-line, 21px);
|
|
240
|
+
tab-size: 2;
|
|
241
|
+
letter-spacing: normal;
|
|
242
|
+
padding: 10px 12px;
|
|
243
|
+
white-space: pre;
|
|
244
|
+
overflow-wrap: normal;
|
|
245
|
+
word-break: normal;
|
|
246
|
+
}
|
|
247
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-textarea) {
|
|
248
|
+
caret-color: #7dd3fc;
|
|
249
|
+
}
|
|
250
|
+
:where(.it-json-editor-textarea)::placeholder {
|
|
251
|
+
color: #94a3b8;
|
|
252
|
+
-webkit-text-fill-color: #94a3b8;
|
|
253
|
+
}
|
|
254
|
+
:where(.it-json-editor-textarea)::selection {
|
|
255
|
+
background: rgb(37 99 235 / 0.25);
|
|
256
|
+
}
|
|
257
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-textarea)::selection {
|
|
258
|
+
background: rgb(125 211 252 / 0.25);
|
|
259
|
+
}
|
|
260
|
+
:where(.it-json-editor-nowrap) {
|
|
261
|
+
white-space: pre;
|
|
262
|
+
overflow: auto;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/* Gutter: números y controles de plegado, con la misma rejilla que el código. */
|
|
266
|
+
:where(.it-json-editor-gutter),
|
|
267
|
+
:where(.it-json-editor-linenumbers) {
|
|
268
|
+
background: rgb(148 163 184 / 0.08);
|
|
269
|
+
border-right: 1px solid rgb(148 163 184 / 0.22);
|
|
270
|
+
}
|
|
271
|
+
:where(.it-json-editor-gutter-row) {
|
|
272
|
+
display: flex;
|
|
273
|
+
align-items: flex-start;
|
|
274
|
+
justify-content: flex-end;
|
|
275
|
+
}
|
|
276
|
+
:where(.it-json-editor-fold) {
|
|
277
|
+
display: inline-flex;
|
|
278
|
+
align-items: center;
|
|
279
|
+
justify-content: center;
|
|
280
|
+
width: 16px;
|
|
281
|
+
height: 16px;
|
|
282
|
+
margin: 2px 1px 0 0;
|
|
283
|
+
border: 0;
|
|
284
|
+
border-radius: 4px;
|
|
285
|
+
background: transparent;
|
|
286
|
+
color: #64748b;
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
}
|
|
289
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-fold) {
|
|
290
|
+
color: #94a3b8;
|
|
291
|
+
}
|
|
292
|
+
:where(.it-json-editor-fold:hover) {
|
|
293
|
+
background: rgb(148 163 184 / 0.25);
|
|
294
|
+
color: #1d4ed8;
|
|
295
|
+
}
|
|
296
|
+
:where(.it-json-editor-fold:focus-visible) {
|
|
297
|
+
outline: 2px solid var(--color-primary-500);
|
|
298
|
+
outline-offset: 1px;
|
|
299
|
+
}
|
|
300
|
+
:where(.it-json-editor-linenumber) {
|
|
301
|
+
padding-right: 10px;
|
|
302
|
+
padding-left: 10px;
|
|
303
|
+
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
304
|
+
font-size: 11px;
|
|
305
|
+
line-height: var(--it-json-editor-line);
|
|
306
|
+
text-align: right;
|
|
307
|
+
color: #94a3b8;
|
|
308
|
+
white-space: pre;
|
|
309
|
+
}
|
|
310
|
+
:where(.it-json-editor-linenumber--active) {
|
|
311
|
+
color: #1d4ed8;
|
|
312
|
+
font-weight: 600;
|
|
313
|
+
}
|
|
314
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-linenumber) {
|
|
315
|
+
color: #64748b;
|
|
316
|
+
}
|
|
317
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-linenumber--active) {
|
|
318
|
+
color: #7dd3fc;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* Fondos de línea (cursor y error). */
|
|
322
|
+
:where(.it-json-editor-active-line) {
|
|
323
|
+
z-index: 0;
|
|
324
|
+
background: rgb(37 99 235 / 0.06);
|
|
325
|
+
}
|
|
326
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-active-line) {
|
|
327
|
+
background: rgb(148 197 253 / 0.07);
|
|
328
|
+
}
|
|
329
|
+
:where(.it-json-editor-error-line) {
|
|
330
|
+
z-index: 0;
|
|
331
|
+
background: rgb(244 63 94 / 0.12);
|
|
332
|
+
box-shadow: inset 2px 0 0 0 var(--color-danger-500);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* Tokens del resaltado. */
|
|
336
|
+
:where(.it-json-editor-tk-key) {
|
|
337
|
+
color: #0369a1;
|
|
338
|
+
}
|
|
339
|
+
:where(.it-json-editor-tk-string) {
|
|
340
|
+
color: #047857;
|
|
341
|
+
}
|
|
342
|
+
:where(.it-json-editor-tk-number) {
|
|
343
|
+
color: #b45309;
|
|
344
|
+
}
|
|
345
|
+
:where(.it-json-editor-tk-keyword),
|
|
346
|
+
:where(.it-json-editor-tk-null) {
|
|
347
|
+
color: #7c3aed;
|
|
348
|
+
}
|
|
349
|
+
:where(.it-json-editor-tk-punct) {
|
|
350
|
+
color: #64748b;
|
|
351
|
+
}
|
|
352
|
+
:where(.it-json-editor-tk-plain) {
|
|
353
|
+
color: #b91c1c;
|
|
354
|
+
text-decoration: underline wavy rgb(185 28 28 / 0.5);
|
|
355
|
+
}
|
|
356
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-key) {
|
|
357
|
+
color: #7dd3fc;
|
|
358
|
+
}
|
|
359
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-string) {
|
|
360
|
+
color: #86efac;
|
|
361
|
+
}
|
|
362
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-number) {
|
|
363
|
+
color: #fcd34d;
|
|
364
|
+
}
|
|
365
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-keyword),
|
|
366
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-null) {
|
|
367
|
+
color: #c4b5fd;
|
|
368
|
+
}
|
|
369
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-punct) {
|
|
370
|
+
color: #94a3b8;
|
|
371
|
+
}
|
|
372
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-plain) {
|
|
373
|
+
color: #fda4af;
|
|
374
|
+
text-decoration: underline wavy rgb(253 164 175 / 0.5);
|
|
375
|
+
}
|
|
376
|
+
:where(.it-json-editor-fold-marker) {
|
|
377
|
+
margin-left: 6px;
|
|
378
|
+
padding: 0 4px;
|
|
379
|
+
border-radius: 4px;
|
|
380
|
+
background: rgb(148 163 184 / 0.2);
|
|
381
|
+
font-size: 10.5px;
|
|
382
|
+
color: #64748b;
|
|
383
|
+
}
|
|
384
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-fold-marker) {
|
|
385
|
+
color: #94a3b8;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* Botonera de la barra superior. */
|
|
389
|
+
:where(.it-json-editor-tool) {
|
|
390
|
+
display: inline-flex;
|
|
391
|
+
align-items: center;
|
|
392
|
+
gap: 5px;
|
|
393
|
+
height: 24px;
|
|
394
|
+
padding: 0 8px;
|
|
395
|
+
border: 1px solid var(--color-secondary-200);
|
|
396
|
+
border-radius: 6px;
|
|
397
|
+
background: transparent;
|
|
398
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
399
|
+
font-size: 10px;
|
|
400
|
+
font-weight: 500;
|
|
401
|
+
letter-spacing: 0.06em;
|
|
402
|
+
text-transform: uppercase;
|
|
403
|
+
color: var(--color-secondary-600);
|
|
404
|
+
cursor: pointer;
|
|
405
|
+
transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease;
|
|
406
|
+
}
|
|
407
|
+
:where(.dark .it-json-editor-tool) {
|
|
408
|
+
border-color: var(--color-secondary-800);
|
|
409
|
+
color: var(--color-secondary-300);
|
|
410
|
+
}
|
|
411
|
+
:where(.it-json-editor-tool:hover:not(:disabled)) {
|
|
412
|
+
border-color: var(--color-primary-400);
|
|
413
|
+
background: var(--color-primary-50);
|
|
414
|
+
color: var(--color-primary-700);
|
|
415
|
+
}
|
|
416
|
+
:where(.dark .it-json-editor-tool:hover:not(:disabled)) {
|
|
417
|
+
border-color: var(--color-primary-500);
|
|
418
|
+
background: rgb(37 99 235 / 0.15);
|
|
419
|
+
color: var(--color-primary-300);
|
|
420
|
+
}
|
|
421
|
+
:where(.it-json-editor-tool:disabled) {
|
|
422
|
+
opacity: 0.4;
|
|
423
|
+
cursor: not-allowed;
|
|
424
|
+
}
|
|
425
|
+
:where(.it-json-editor-tool:focus-visible) {
|
|
426
|
+
outline: 2px solid var(--color-primary-500);
|
|
427
|
+
outline-offset: 1px;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/* Conmutador texto/árbol. */
|
|
431
|
+
:where(.it-json-editor-segment) {
|
|
432
|
+
display: inline-flex;
|
|
433
|
+
align-items: center;
|
|
434
|
+
border: 1px solid var(--color-secondary-200);
|
|
435
|
+
border-radius: 6px;
|
|
436
|
+
overflow: hidden;
|
|
437
|
+
}
|
|
438
|
+
:where(.dark .it-json-editor-segment) {
|
|
439
|
+
border-color: var(--color-secondary-800);
|
|
440
|
+
}
|
|
441
|
+
:where(.it-json-editor-segment-item) {
|
|
442
|
+
display: inline-flex;
|
|
443
|
+
align-items: center;
|
|
444
|
+
gap: 5px;
|
|
445
|
+
height: 24px;
|
|
446
|
+
padding: 0 8px;
|
|
447
|
+
border: 0;
|
|
448
|
+
background: transparent;
|
|
449
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
450
|
+
font-size: 10px;
|
|
451
|
+
font-weight: 500;
|
|
452
|
+
letter-spacing: 0.06em;
|
|
453
|
+
text-transform: uppercase;
|
|
454
|
+
color: var(--color-secondary-500);
|
|
455
|
+
cursor: pointer;
|
|
456
|
+
}
|
|
457
|
+
:where(.it-json-editor-segment-item--active) {
|
|
458
|
+
background: var(--color-primary-600);
|
|
459
|
+
color: #ffffff;
|
|
460
|
+
}
|
|
461
|
+
:where(.it-json-editor-segment-item:focus-visible) {
|
|
462
|
+
outline: 2px solid var(--color-primary-500);
|
|
463
|
+
outline-offset: -2px;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/* Interruptores de la fila de ajustes. */
|
|
467
|
+
:where(.it-json-editor-toggle) {
|
|
468
|
+
display: inline-flex;
|
|
469
|
+
align-items: center;
|
|
470
|
+
gap: 5px;
|
|
471
|
+
border: 0;
|
|
472
|
+
background: transparent;
|
|
473
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
474
|
+
font-size: 10px;
|
|
475
|
+
letter-spacing: 0.1em;
|
|
476
|
+
text-transform: uppercase;
|
|
477
|
+
color: var(--color-secondary-400);
|
|
478
|
+
cursor: pointer;
|
|
479
|
+
}
|
|
480
|
+
:where(.it-json-editor-toggle--on) {
|
|
481
|
+
color: var(--color-primary-700);
|
|
482
|
+
}
|
|
483
|
+
:where(.dark .it-json-editor-toggle--on) {
|
|
484
|
+
color: var(--color-primary-300);
|
|
485
|
+
}
|
|
486
|
+
:where(.it-json-editor-toggle-dot) {
|
|
487
|
+
display: inline-block;
|
|
488
|
+
width: 6px;
|
|
489
|
+
height: 6px;
|
|
490
|
+
border-radius: 999px;
|
|
491
|
+
background: currentColor;
|
|
492
|
+
opacity: 0.4;
|
|
493
|
+
}
|
|
494
|
+
:where(.it-json-editor-toggle--on .it-json-editor-toggle-dot) {
|
|
495
|
+
opacity: 1;
|
|
496
|
+
}
|
|
497
|
+
:where(.it-json-editor-toggle:focus-visible) {
|
|
498
|
+
outline: 2px solid var(--color-primary-500);
|
|
499
|
+
outline-offset: 1px;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/* Árbol navegable. */
|
|
503
|
+
:where(.it-json-editor-tree) {
|
|
504
|
+
height: 100%;
|
|
505
|
+
}
|
|
506
|
+
:where(.it-json-editor-tree-spacer) {
|
|
507
|
+
display: inline-block;
|
|
508
|
+
width: 14px;
|
|
509
|
+
flex-shrink: 0;
|
|
510
|
+
}
|
|
511
|
+
:where(.it-json-editor-tk-value) {
|
|
512
|
+
color: #334155;
|
|
513
|
+
}
|
|
514
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tk-value) {
|
|
515
|
+
color: #cbd5e1;
|
|
516
|
+
}
|
|
517
|
+
:where(.it-json-editor-tree-row) {
|
|
518
|
+
display: flex;
|
|
519
|
+
align-items: center;
|
|
520
|
+
gap: 4px;
|
|
521
|
+
min-height: 20px;
|
|
522
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
523
|
+
font-size: 11.5px;
|
|
524
|
+
line-height: 1.5;
|
|
525
|
+
color: #334155;
|
|
526
|
+
}
|
|
527
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tree-row) {
|
|
528
|
+
color: #cbd5e1;
|
|
529
|
+
}
|
|
530
|
+
:where(.it-json-editor-tree-row:hover) {
|
|
531
|
+
background: rgb(148 163 184 / 0.12);
|
|
532
|
+
}
|
|
533
|
+
:where(.it-json-editor-tree-toggle) {
|
|
534
|
+
display: inline-flex;
|
|
535
|
+
align-items: center;
|
|
536
|
+
justify-content: center;
|
|
537
|
+
width: 14px;
|
|
538
|
+
height: 14px;
|
|
539
|
+
border: 0;
|
|
540
|
+
border-radius: 3px;
|
|
541
|
+
background: transparent;
|
|
542
|
+
color: #64748b;
|
|
543
|
+
cursor: pointer;
|
|
544
|
+
}
|
|
545
|
+
:where(.it-json-editor-tree-badge) {
|
|
546
|
+
padding: 0 5px;
|
|
547
|
+
border-radius: 999px;
|
|
548
|
+
background: rgb(148 163 184 / 0.18);
|
|
549
|
+
font-size: 9.5px;
|
|
550
|
+
letter-spacing: 0.04em;
|
|
551
|
+
text-transform: uppercase;
|
|
552
|
+
color: #64748b;
|
|
553
|
+
}
|
|
554
|
+
:where(.it-json-editor-canvas[data-canvas="ink"] .it-json-editor-tree-badge) {
|
|
555
|
+
color: #94a3b8;
|
|
556
|
+
}
|
|
557
|
+
:where(.it-json-editor-tree-jump) {
|
|
558
|
+
display: inline-flex;
|
|
559
|
+
align-items: center;
|
|
560
|
+
gap: 3px;
|
|
561
|
+
margin-left: auto;
|
|
562
|
+
padding: 0 5px;
|
|
563
|
+
border: 0;
|
|
564
|
+
border-radius: 4px;
|
|
565
|
+
background: transparent;
|
|
566
|
+
font-family: "JetBrains Mono", ui-monospace, monospace;
|
|
567
|
+
font-size: 9.5px;
|
|
568
|
+
letter-spacing: 0.06em;
|
|
569
|
+
text-transform: uppercase;
|
|
570
|
+
color: #64748b;
|
|
571
|
+
cursor: pointer;
|
|
572
|
+
opacity: 0;
|
|
573
|
+
}
|
|
574
|
+
:where(.it-json-editor-tree-row:hover .it-json-editor-tree-jump),
|
|
575
|
+
:where(.it-json-editor-tree-jump:focus-visible) {
|
|
576
|
+
opacity: 1;
|
|
577
|
+
}
|
|
578
|
+
:where(.it-json-editor-tree-jump:hover) {
|
|
579
|
+
background: var(--color-primary-50);
|
|
580
|
+
color: var(--color-primary-700);
|
|
581
|
+
}
|
|
582
|
+
:where(.dark .it-json-editor-tree-jump:hover) {
|
|
583
|
+
background: rgb(37 99 235 / 0.2);
|
|
584
|
+
color: var(--color-primary-300);
|
|
585
|
+
}
|
|
172
586
|
}
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { useDebouncedSearch } from "./hooks/useDebouncedSearch";
|
|
|
6
6
|
import { useEditableRow } from "./hooks/useEditableRow";
|
|
7
7
|
import { useFloatingPanel } from "./hooks/useFloatingPanel";
|
|
8
8
|
import { useTableState, UseTableStateOptions, UseTableStateResult } from "./hooks/useTableState";
|
|
9
|
+
import useJsonRender from "./hooks/useJsonRender";
|
|
9
10
|
|
|
10
11
|
// COMPONENTES
|
|
11
12
|
import ITAccordion from "./components/molecules/accordion/accordion";
|
|
@@ -62,6 +63,8 @@ import ITTabs from "./components/molecules/tabs/tabs";
|
|
|
62
63
|
import ITTripleFilter from "./components/organisms/triple-filter/tripleFilter";
|
|
63
64
|
import ITToast from "./components/organisms/toast/toast";
|
|
64
65
|
import ITWysiwyg from "./components/molecules/wysiwyg/wysiwyg";
|
|
66
|
+
import ITJsonRenderer from "./components/molecules/json-renderer/json-renderer";
|
|
67
|
+
import ITJSONEditor from "./components/molecules/json-editor/json-editor";
|
|
65
68
|
|
|
66
69
|
// PROPS
|
|
67
70
|
import type { ITAlertProps } from "./components/molecules/alert/alert.props";
|
|
@@ -118,6 +121,8 @@ import type { ITTabsProps, ITTabItem } from "./components/molecules/tabs/tabs.pr
|
|
|
118
121
|
import type { ITTripleFilterProps, ITTripleFilterOption } from "./components/organisms/triple-filter/tripleFilter.props";
|
|
119
122
|
import type { ITToastProps } from "./components/organisms/toast/toast.props";
|
|
120
123
|
import type { ITWysiwygProps } from "./components/molecules/wysiwyg/wysiwyg.props";
|
|
124
|
+
import type { ITJsonRendererProps, JsonComponentNode, JsonComponentType } from "./components/molecules/json-renderer/json-renderer.props";
|
|
125
|
+
import type { ITJSONEditorProps } from "./components/molecules/json-editor/json-editor.props";
|
|
121
126
|
import type { FieldConfig, FieldConfigV2 } from "./types/field.types";
|
|
122
127
|
import type { ColumnFilters, ColumnFilterValue, TableColors, TableDensity, TableDesign, TableDesignProps, TableDesignSlot } from "./types/table.types";
|
|
123
128
|
|
|
@@ -144,7 +149,7 @@ import type { ITI18nProviderProps, ITI18nValue, ITLocale, ITMessages, ITMessages
|
|
|
144
149
|
|
|
145
150
|
export {
|
|
146
151
|
// Hooks
|
|
147
|
-
useClickOutside, useDebouncedSearch, useEditableRow, useFloatingPanel, useTableState,
|
|
152
|
+
useClickOutside, useDebouncedSearch, useEditableRow, useFloatingPanel, useTableState, useJsonRender,
|
|
148
153
|
createValidationSchema,
|
|
149
154
|
// Components
|
|
150
155
|
ITAccordion,
|
|
@@ -162,7 +167,8 @@ export {
|
|
|
162
167
|
useITTheme, useITThemeSafe, useITFlatAppearance, ITTimePicker, ITToast, ITWysiwyg,
|
|
163
168
|
UploadStatus, FileTypeEnum,
|
|
164
169
|
getContrastTextColor, isLightColor, resolveCssColor,
|
|
165
|
-
ITI18nProvider, useITTranslation, esMessages, enMessages
|
|
170
|
+
ITI18nProvider, useITTranslation, esMessages, enMessages,
|
|
171
|
+
ITJsonRenderer, ITJSONEditor
|
|
166
172
|
};
|
|
167
173
|
|
|
168
174
|
export type {
|
|
@@ -195,6 +201,8 @@ export {
|
|
|
195
201
|
ITTripleFilterProps, ITTripleFilterOption, ITThemeConfig, ITThemeProviderProps, ITThemePalette, ITThemeAppearance,
|
|
196
202
|
ITTimePickerProps, ITToastProps,
|
|
197
203
|
ITWysiwygProps,
|
|
204
|
+
ITJsonRendererProps, JsonComponentNode, JsonComponentType,
|
|
205
|
+
ITJSONEditorProps,
|
|
198
206
|
UseTableStateOptions, UseTableStateResult
|
|
199
207
|
};
|
|
200
208
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marca axzydev para el sitio (sandbox + portafolio).
|
|
3
|
+
*
|
|
4
|
+
* Vive en `src/sandbox/` a propósito: es chrome del sitio, **no** un componente
|
|
5
|
+
* publicado. Los assets son los SVG del kit (`axzydev-brand-kit/logos/svg`)
|
|
6
|
+
* copiados a `public/brand/`; no hay dependencias nuevas ni animaciones Lottie.
|
|
7
|
+
*
|
|
8
|
+
* El wordmark elige su variante según el tema resuelto: `logo-color` (tinta
|
|
9
|
+
* navy sobre claro) o `logo-dark` (texto claro sobre oscuro), de modo que el
|
|
10
|
+
* logo se lee en ambos modos sin recolorear nada a mano.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <AxzyLogo variante="icono" tamano={24} /> // navbar / topbar
|
|
15
|
+
* <AxzyLogo variante="wordmark" tamano={260} /> // hero / footer
|
|
16
|
+
* <AxzyLogo variante="loader" tamano={40} etiqueta="Cargando" />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { useITThemeSafe } from "@/theme/theme-context";
|
|
21
|
+
|
|
22
|
+
/** Forma del logo: solo ícono, wordmark completo o loader de marca. */
|
|
23
|
+
export type AxzyLogoVariante = "icono" | "wordmark" | "loader";
|
|
24
|
+
|
|
25
|
+
/** Props de `AxzyLogo`. */
|
|
26
|
+
export interface AxzyLogoProps {
|
|
27
|
+
/** Forma del logo. @default "wordmark" */
|
|
28
|
+
variante?: AxzyLogoVariante;
|
|
29
|
+
/** Ancho en píxeles. El alto se calcula solo por la proporción del SVG. @default 28 (icono/loader) · 240 (wordmark) */
|
|
30
|
+
tamano?: number;
|
|
31
|
+
/** Fuerza el tono del wordmark en lugar de seguir el tema. */
|
|
32
|
+
tono?: "claro" | "oscuro";
|
|
33
|
+
/**
|
|
34
|
+
* Texto alternativo del logo. Por defecto `"axzydev"` para el wordmark y
|
|
35
|
+
* `""` (decorativo) para el ícono, que suele ir acompañado del nombre.
|
|
36
|
+
*/
|
|
37
|
+
etiqueta?: string;
|
|
38
|
+
/** Clases del elemento raíz. */
|
|
39
|
+
className?: string;
|
|
40
|
+
/** Anima el ícono con un latido suave cuando `variante="loader"`. Respeta `prefers-reduced-motion`. */
|
|
41
|
+
latido?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Ruta del asset según la forma y el tono. */
|
|
45
|
+
const ASSETS: Record<AxzyLogoVariante, { claro: string; oscuro: string }> = {
|
|
46
|
+
icono: { claro: "/brand/icon.svg", oscuro: "/brand/icon.svg" },
|
|
47
|
+
wordmark: { claro: "/brand/logo-color.svg", oscuro: "/brand/logo-dark.svg" },
|
|
48
|
+
loader: { claro: "/brand/icon.svg", oscuro: "/brand/icon.svg" },
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Alto por defecto según la forma (el wordmark es 621×208). */
|
|
52
|
+
const ALTO_POR_TAMANO: Record<AxzyLogoVariante, number> = {
|
|
53
|
+
icono: 28,
|
|
54
|
+
wordmark: 240,
|
|
55
|
+
loader: 40,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Marca axzydev del sitio: SVG del kit, conmutada por tema y sin dependencias.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* <AxzyLogo variante="icono" tamano={24} />
|
|
64
|
+
* <AxzyLogo variante="wordmark" tamano={260} className="mb-6" />
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export const AxzyLogo = ({
|
|
68
|
+
variante = "wordmark",
|
|
69
|
+
tamano,
|
|
70
|
+
tono,
|
|
71
|
+
etiqueta,
|
|
72
|
+
className = "",
|
|
73
|
+
latido = true,
|
|
74
|
+
}: AxzyLogoProps) => {
|
|
75
|
+
const contexto = useITThemeSafe();
|
|
76
|
+
const modo = tono ?? (contexto?.resolvedTheme === "dark" ? "oscuro" : "claro");
|
|
77
|
+
const ancho = tamano ?? ALTO_POR_TAMANO[variante];
|
|
78
|
+
|
|
79
|
+
// El ícono mide 128×128; el wordmark, 621×208. El alto sale de la proporción.
|
|
80
|
+
const alto = variante === "icono" || variante === "loader" ? ancho : Math.round((ancho * 208) / 621);
|
|
81
|
+
const decorativo = etiqueta === "" || (etiqueta === undefined && variante !== "wordmark");
|
|
82
|
+
const alt = etiqueta ?? (variante === "wordmark" ? "axzydev" : "");
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<img
|
|
86
|
+
src={ASSETS[variante][modo]}
|
|
87
|
+
width={ancho}
|
|
88
|
+
height={alto}
|
|
89
|
+
alt={alt}
|
|
90
|
+
aria-hidden={decorativo || undefined}
|
|
91
|
+
draggable={false}
|
|
92
|
+
className={[
|
|
93
|
+
"select-none",
|
|
94
|
+
variante === "loader" && latido ? "it-logo-latido" : "",
|
|
95
|
+
className,
|
|
96
|
+
]
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join(" ")}
|
|
99
|
+
style={{ width: ancho, height: alto }}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Loader de marca: el ícono latiendo con un rótulo mono al lado.
|
|
106
|
+
*
|
|
107
|
+
* Es la versión estática del `loader` del kit (que allí es una animación Lottie)
|
|
108
|
+
* y se apoya en `ITLoader` para la etiqueta y el rol accesible.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```tsx
|
|
112
|
+
* <AxzyLoader etiqueta="Cargando componentes" />
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
export const AxzyLoader = ({
|
|
116
|
+
etiqueta,
|
|
117
|
+
tamano = 32,
|
|
118
|
+
className = "",
|
|
119
|
+
}: {
|
|
120
|
+
/** Texto que acompaña al ícono. */
|
|
121
|
+
etiqueta?: string;
|
|
122
|
+
/** Ancho del ícono en píxeles. @default 32 */
|
|
123
|
+
tamano?: number;
|
|
124
|
+
/** Clases del contenedor. */
|
|
125
|
+
className?: string;
|
|
126
|
+
}) => (
|
|
127
|
+
<span
|
|
128
|
+
role="status"
|
|
129
|
+
aria-live="polite"
|
|
130
|
+
className={`inline-flex items-center gap-3 ${className}`}
|
|
131
|
+
>
|
|
132
|
+
<AxzyLogo variante="loader" tamano={tamano} />
|
|
133
|
+
{etiqueta ? (
|
|
134
|
+
<span className="font-mono text-[11px] uppercase tracking-[0.14em] text-slate-500 dark:text-slate-400">
|
|
135
|
+
{etiqueta}
|
|
136
|
+
</span>
|
|
137
|
+
) : null}
|
|
138
|
+
</span>
|
|
139
|
+
);
|
package/src/sandbox/i18n.ts
CHANGED
|
@@ -20,6 +20,7 @@ export const sandboxMessages: ITMessagesByLocale = {
|
|
|
20
20
|
"sandbox.userMenu.portfolio": "Ir al Portafolio",
|
|
21
21
|
"sandbox.search.label": "Buscar componentes",
|
|
22
22
|
"sandbox.search.placeholder": "Buscar componente…",
|
|
23
|
+
"sandbox.loading": "Cargando…",
|
|
23
24
|
"sandbox.search.clear": "Limpiar búsqueda",
|
|
24
25
|
"sandbox.search.results": "{count} resultados",
|
|
25
26
|
|
|
@@ -967,6 +968,7 @@ export const sandboxMessages: ITMessagesByLocale = {
|
|
|
967
968
|
"sandbox.userMenu.portfolio": "Go to portfolio",
|
|
968
969
|
"sandbox.search.label": "Search components",
|
|
969
970
|
"sandbox.search.placeholder": "Search component…",
|
|
971
|
+
"sandbox.loading": "Loading…",
|
|
970
972
|
"sandbox.search.clear": "Clear search",
|
|
971
973
|
"sandbox.search.results": "{count} results",
|
|
972
974
|
|
|
@@ -104,6 +104,8 @@ export const SANDBOX_GROUPS: SandboxGroup[] = [
|
|
|
104
104
|
{ id: "toast", label: "ITToast" },
|
|
105
105
|
{ id: "loader", label: "ITLoader" },
|
|
106
106
|
{ id: "themeprovider", label: "ITThemeProvider" },
|
|
107
|
+
{ id: "jsonrenderer", label: "ITJsonRenderer (PoC)" },
|
|
108
|
+
{ id: "jsoneditor", label: "ITJSONEditor" },
|
|
107
109
|
],
|
|
108
110
|
},
|
|
109
111
|
];
|