@axzydev/axzy_ui_system 1.6.0 → 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 +6053 -4317
- 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 +4363 -2612
- 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/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 +6 -1
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
VolverArriba,
|
|
28
28
|
} from "./portfolioUi";
|
|
29
29
|
import { useITTranslation } from "@/i18n";
|
|
30
|
+
import { AxzyLogo } from "@/sandbox/AxzyLogo";
|
|
30
31
|
|
|
31
32
|
const CV_URL = "/Martin_Amaro_CV_ES_2026.pdf";
|
|
32
33
|
const GITHUB_URL = "https://github.com/maag070208";
|
|
@@ -125,9 +126,7 @@ const PortfolioNav = () => {
|
|
|
125
126
|
<nav aria-label={t("showcase.home.sectionNav")} className={HOJA}>
|
|
126
127
|
<div className="flex h-14 items-center gap-4">
|
|
127
128
|
<a href="#sobre-mi" className="flex items-center gap-2.5">
|
|
128
|
-
<
|
|
129
|
-
AA
|
|
130
|
-
</span>
|
|
129
|
+
<AxzyLogo variante="icono" tamano={24} />
|
|
131
130
|
<ITText
|
|
132
131
|
as="span"
|
|
133
132
|
className="hidden font-display !text-[13px] !font-bold -tracking-[0.01em] text-slate-900 dark:text-white sm:block"
|
|
@@ -441,6 +440,10 @@ export const HomeShowcase = () => {
|
|
|
441
440
|
</a>
|
|
442
441
|
</ITFlex>
|
|
443
442
|
|
|
443
|
+
<ITFlex align="center" className="it-reveal !mt-8">
|
|
444
|
+
<AxzyLogo variante="wordmark" tamano={300} />
|
|
445
|
+
</ITFlex>
|
|
446
|
+
|
|
444
447
|
<div className="mt-10 grid gap-10 lg:grid-cols-[minmax(0,1fr)_auto] lg:gap-14">
|
|
445
448
|
<div className="min-w-0">
|
|
446
449
|
<ITText
|
|
@@ -783,12 +786,16 @@ export const HomeShowcase = () => {
|
|
|
783
786
|
<div
|
|
784
787
|
className={`${HOJA} flex flex-col items-start justify-between gap-3 py-7 sm:flex-row sm:items-center`}
|
|
785
788
|
>
|
|
786
|
-
<
|
|
787
|
-
|
|
788
|
-
className="
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
789
|
+
<div className="flex items-center gap-4">
|
|
790
|
+
<AxzyLogo variante="wordmark" tamano={190} />
|
|
791
|
+
<span aria-hidden="true" className="h-8 w-px bg-slate-200 dark:bg-slate-800" />
|
|
792
|
+
<ITText
|
|
793
|
+
as="p"
|
|
794
|
+
className="font-mono !text-[11px] uppercase !tracking-[0.14em] text-slate-500 dark:text-slate-400"
|
|
795
|
+
>
|
|
796
|
+
{`Asael Amaro · ${t("showcase.home.role")}`}
|
|
797
|
+
</ITText>
|
|
798
|
+
</div>
|
|
792
799
|
<div className="flex flex-wrap items-center gap-x-5 gap-y-2">
|
|
793
800
|
<ITText
|
|
794
801
|
as="span"
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import React, { useMemo, useState } from "react";
|
|
2
|
+
import { ITCard, ITJSONEditor, ITFlex } from "../index";
|
|
3
|
+
import { ShowcaseLayout } from "./ShowcaseLayout";
|
|
4
|
+
|
|
5
|
+
/** Documento de arranque de la demo. */
|
|
6
|
+
const initial = `[
|
|
7
|
+
{
|
|
8
|
+
"type": "card",
|
|
9
|
+
"props": { "title": "Demo JSON Editor" },
|
|
10
|
+
"children": [
|
|
11
|
+
{ "type": "text", "text": "Edita este JSON y mira el preview" },
|
|
12
|
+
{ "type": "button", "props": { "label": "Aceptar" } }
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
]`;
|
|
16
|
+
|
|
17
|
+
export const JsonEditorShowcase: React.FC = () => {
|
|
18
|
+
const [value, setValue] = useState(initial);
|
|
19
|
+
|
|
20
|
+
/** Un documento más grande para que luzcan el plegado y el árbol. */
|
|
21
|
+
const bigDocument = useMemo(
|
|
22
|
+
() =>
|
|
23
|
+
JSON.stringify(
|
|
24
|
+
{
|
|
25
|
+
app: "axzy-ui-system",
|
|
26
|
+
version: "1.6.0",
|
|
27
|
+
layers: {
|
|
28
|
+
atoms: ["button", "input", "text", "flex", "grid", "stack"],
|
|
29
|
+
molecules: ["card", "alert", "table", "json-editor"],
|
|
30
|
+
organisms: ["data-table", "dialog", "sidebar", "navbar"],
|
|
31
|
+
},
|
|
32
|
+
flags: { darkMode: true, i18n: true, a11y: true, treeView: true },
|
|
33
|
+
limits: { maxDepth: 12, maxNodes: 5000, timeout: null },
|
|
34
|
+
},
|
|
35
|
+
null,
|
|
36
|
+
2
|
|
37
|
+
),
|
|
38
|
+
[]
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const code = `<ITJSONEditor
|
|
42
|
+
value={json}
|
|
43
|
+
onChange={setJson}
|
|
44
|
+
onParse={handleParse}
|
|
45
|
+
mode="text" // "text" | "tree"
|
|
46
|
+
indentSize={2} // 0 | 2 | 4 | 8
|
|
47
|
+
height={420}
|
|
48
|
+
showToolbar
|
|
49
|
+
showViewSettings
|
|
50
|
+
showValidation
|
|
51
|
+
showStatusBar
|
|
52
|
+
showFoldGutter
|
|
53
|
+
showLineNumbers
|
|
54
|
+
/>`;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<ShowcaseLayout
|
|
58
|
+
title="ITJSONEditor"
|
|
59
|
+
description="Editor JSON con resaltado, gutter plegable, errores por línea/columna y árbol navegable. Sin dependencias nuevas."
|
|
60
|
+
demo={
|
|
61
|
+
<ITFlex direction="column" gap={4} className="w-full">
|
|
62
|
+
<ITJSONEditor id="json-editor-demo" value={value} onChange={setValue} height={420} indentSize={2} />
|
|
63
|
+
</ITFlex>
|
|
64
|
+
}
|
|
65
|
+
gallery={
|
|
66
|
+
<ITFlex direction="column" gap={4} className="w-full">
|
|
67
|
+
<ITCard title="Vista de árbol (mode="tree")">
|
|
68
|
+
<ITJSONEditor
|
|
69
|
+
value={bigDocument}
|
|
70
|
+
readOnly
|
|
71
|
+
mode="tree"
|
|
72
|
+
treeShowLines
|
|
73
|
+
height={320}
|
|
74
|
+
showToolbar={false}
|
|
75
|
+
showViewSettings={false}
|
|
76
|
+
/>
|
|
77
|
+
</ITCard>
|
|
78
|
+
<ITCard title="Documento grande con plegado">
|
|
79
|
+
<ITJSONEditor value={bigDocument} onChange={() => undefined} height={320} />
|
|
80
|
+
</ITCard>
|
|
81
|
+
<ITCard title="Lienzo claro y ajuste de línea (canvasTheme="light", wrapLines)">
|
|
82
|
+
<ITJSONEditor
|
|
83
|
+
value={bigDocument}
|
|
84
|
+
readOnly
|
|
85
|
+
canvasTheme="light"
|
|
86
|
+
wrapLines
|
|
87
|
+
height={260}
|
|
88
|
+
showTransformActions={false}
|
|
89
|
+
showImportButton={false}
|
|
90
|
+
/>
|
|
91
|
+
</ITCard>
|
|
92
|
+
<ITCard title="Estado de error: línea y columna señaladas">
|
|
93
|
+
<ITJSONEditor
|
|
94
|
+
value={'{\n "a": 1,\n "b": ,\n "c": 3\n}'}
|
|
95
|
+
height={220}
|
|
96
|
+
showStatusBar
|
|
97
|
+
/>
|
|
98
|
+
</ITCard>
|
|
99
|
+
</ITFlex>
|
|
100
|
+
}
|
|
101
|
+
code={code}
|
|
102
|
+
doc={{
|
|
103
|
+
summary: "Editor JSON para prototipar con ITJsonRenderer",
|
|
104
|
+
description:
|
|
105
|
+
"El resaltado se pinta en una capa bajo un textarea nativo, así que conserva el deshacer del navegador y no añade dependencias. Valida con JSON.parse y traduce el error a línea y columna.",
|
|
106
|
+
examples: [
|
|
107
|
+
'<ITJSONEditor value={json} onChange={setJson} />',
|
|
108
|
+
'<ITJSONEditor value={json} mode="tree" treeShowLines />',
|
|
109
|
+
'<ITJSONEditor value={json} indentSize={4} wrapLines canvasTheme="light" />',
|
|
110
|
+
'<ITJSONEditor value={json} readOnly showToolbar={false} height="100%" />',
|
|
111
|
+
],
|
|
112
|
+
props: [
|
|
113
|
+
{ name: "value", type: "string", default: '""', description: "Documento JSON como cadena." },
|
|
114
|
+
{ name: "onChange", type: "(v: string) => void", default: "—", description: "Se dispara con el texto completo en cada cambio." },
|
|
115
|
+
{ name: "onParse", type: "(parsed, isValid, error?) => void", default: "—", description: "Valor parseado y estado tras cada validación." },
|
|
116
|
+
{ name: "mode", type: '"text" | "tree"', default: '"text"', description: "Modo inicial del lienzo." },
|
|
117
|
+
{ name: "showModeSwitch", type: "boolean", default: "true", description: "Conmutador texto/árbol en la barra." },
|
|
118
|
+
{ name: "showToolbar", type: "boolean", default: "true", description: "Barra superior de acciones." },
|
|
119
|
+
{ name: "showViewSettings", type: "boolean", default: "true", description: "Fila de ajustes de vista." },
|
|
120
|
+
{ name: "showValidation", type: "boolean", default: "true", description: "Indicador válido/ inválido con L:C." },
|
|
121
|
+
{ name: "showStatusBar", type: "boolean", default: "true", description: "Pie con líneas, nodos, profundidad y tamaño." },
|
|
122
|
+
{ name: "showLineNumbers", type: "boolean", default: "true", description: "Números de línea en el gutter." },
|
|
123
|
+
{ name: "showFoldGutter", type: "boolean", default: "true", description: "Gutter de plegado de bloques." },
|
|
124
|
+
{ name: "showTransformActions", type: "boolean", default: "true", description: "Formatear, minificar, ordenar, escapar." },
|
|
125
|
+
{ name: "showCopyButton", type: "boolean", default: "true", description: "Botón de copiar el documento." },
|
|
126
|
+
{ name: "showImportButton", type: "boolean", default: "true", description: "Carga de un archivo .json." },
|
|
127
|
+
{ name: "showDownloadButton", type: "boolean", default: "true", description: "Descarga del documento." },
|
|
128
|
+
{ name: "indentSize", type: "number", default: "2", description: "Espacios por nivel (0, 2, 4 u 8)." },
|
|
129
|
+
{ name: "wrapLines", type: "boolean", default: "false", description: "Ajuste de línea dentro del ancho." },
|
|
130
|
+
{ name: "treeShowLines", type: "boolean", default: "false", description: "Muestra la línea de cada nodo y permite saltar." },
|
|
131
|
+
{ name: "canvasTheme", type: '"ink" | "light"', default: '"ink"', description: "Paleta del lienzo de código." },
|
|
132
|
+
{ name: "height", type: "number | string", default: "340", description: "Alto del área de edición." },
|
|
133
|
+
{ name: "readOnly", type: "boolean", default: "false", description: "Solo lectura, sin acciones de edición." },
|
|
134
|
+
{ name: "actions", type: "ReactNode", default: "—", description: "Acciones propias al final de la barra." },
|
|
135
|
+
{ name: "className", type: "string", default: "—", description: "Clases del contenedor raíz." },
|
|
136
|
+
{ name: "textareaClassName", type: "string", default: "—", description: "Clases extra del textarea." },
|
|
137
|
+
{ name: "errorLine", type: "number", default: "—", description: "Línea a marcar como errónea desde fuera." },
|
|
138
|
+
],
|
|
139
|
+
notes: [
|
|
140
|
+
"Atajos: Tab indenta el bloque, Mayús+Tab lo desangra, Mayús+Alt+F formatea, +M minifica y +S ordena.",
|
|
141
|
+
"Las llaves, corchetes y comillas se cierran solos y se borran por parejas.",
|
|
142
|
+
"Con wrapLines activo el resaltado de línea vigente se desactiva: la posición dependería de las vueltas de cada línea.",
|
|
143
|
+
"Es totalmente independiente de ITJsonRenderer: los une solo el JSON que tú les pases.",
|
|
144
|
+
],
|
|
145
|
+
}}
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default JsonEditorShowcase;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { ITCard, ITJsonRenderer } from "../index";
|
|
3
|
+
import { ShowcaseLayout } from "./ShowcaseLayout";
|
|
4
|
+
|
|
5
|
+
const exampleWithChildren = [
|
|
6
|
+
{
|
|
7
|
+
type: "alert" as const,
|
|
8
|
+
props: { variant: "info" as const, title: "Información" },
|
|
9
|
+
text: "Esto se renderiza desde JSON",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
type: "card" as const,
|
|
13
|
+
props: { title: "Tarjeta desde JSON" },
|
|
14
|
+
children: [
|
|
15
|
+
{ type: "text" as const, text: "Contenido dentro de la tarjeta" },
|
|
16
|
+
{
|
|
17
|
+
type: "flex" as const,
|
|
18
|
+
props: { gap: 2, justify: "end" as const },
|
|
19
|
+
children: [
|
|
20
|
+
{ type: "button" as const, props: { label: "Cancelar", color: "gray" as const, variant: "outlined" as const } },
|
|
21
|
+
{ type: "button" as const, props: { label: "Aceptar", color: "primary" as const } },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export const JsonRendererShowcase: React.FC = () => {
|
|
29
|
+
const [jsonText, setJsonText] = useState(JSON.stringify(exampleWithChildren, null, 2));
|
|
30
|
+
|
|
31
|
+
let parsed: any = exampleWithChildren;
|
|
32
|
+
try {
|
|
33
|
+
parsed = JSON.parse(jsonText);
|
|
34
|
+
} catch {
|
|
35
|
+
parsed = exampleWithChildren;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<ShowcaseLayout
|
|
40
|
+
title="ITJsonRenderer"
|
|
41
|
+
description="Renderiza componentes del UI System a partir de un JSON."
|
|
42
|
+
doc={{
|
|
43
|
+
summary: "PoC: Builder JSON para AXZY UI System",
|
|
44
|
+
description:
|
|
45
|
+
"Permite construir interfaces pasándole un árbol JSON con type, props, children/text.",
|
|
46
|
+
examples: [
|
|
47
|
+
'<ITJsonRenderer json={{ type: "button", props: { label: "Click" } }} />',
|
|
48
|
+
],
|
|
49
|
+
props: [],
|
|
50
|
+
}}
|
|
51
|
+
demo={
|
|
52
|
+
<ITCard title="Preview">
|
|
53
|
+
<ITJsonRenderer json={parsed} />
|
|
54
|
+
</ITCard>
|
|
55
|
+
}
|
|
56
|
+
code={jsonText}
|
|
57
|
+
controls={
|
|
58
|
+
<ITCard title="JSON Editor (editable)">
|
|
59
|
+
<textarea
|
|
60
|
+
value={jsonText}
|
|
61
|
+
onChange={(e) => setJsonText(e.target.value)}
|
|
62
|
+
className="w-full h-64 font-mono text-sm border rounded p-3"
|
|
63
|
+
/>
|
|
64
|
+
</ITCard>
|
|
65
|
+
}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export default JsonRendererShowcase;
|
|
@@ -37,6 +37,7 @@ import type { ITSidebarProps } from "../index";
|
|
|
37
37
|
import { ShowcaseLayout, CodeViewer } from "./ShowcaseLayout";
|
|
38
38
|
import { EjemploContenedor } from "@/sandbox/ui";
|
|
39
39
|
import { useITTranslation } from "@/i18n";
|
|
40
|
+
import { AxzyLogo } from "@/sandbox/AxzyLogo";
|
|
40
41
|
|
|
41
42
|
// ─────────────────────────────────────────
|
|
42
43
|
// 1. ITCard Showcase
|
|
@@ -972,7 +973,7 @@ export const LayoutShowcase = () => {
|
|
|
972
973
|
const [navActiveId, setNavActiveId] = useState<string | null>("1");
|
|
973
974
|
|
|
974
975
|
const topBar = {
|
|
975
|
-
logo: <
|
|
976
|
+
logo: <AxzyLogo variante="icono" tamano={36} etiqueta="" />,
|
|
976
977
|
logoText: "AXZY Console",
|
|
977
978
|
centerContent: (
|
|
978
979
|
<input
|
|
@@ -1155,6 +1156,7 @@ export const LayoutShowcase = () => {
|
|
|
1155
1156
|
numero="02"
|
|
1156
1157
|
titulo={t("showcase.structure.galleryNavbarStandalone")}
|
|
1157
1158
|
codigo={`<ITNavbar
|
|
1159
|
+
logo={<AxzyLogo variante="icono" tamano={28} etiqueta="" />}
|
|
1158
1160
|
logoText="AXZY"
|
|
1159
1161
|
navigationItems={[
|
|
1160
1162
|
{ id: "1", label: "Inicio", icon: <FaHome />, isActive: true },
|
|
@@ -1169,6 +1171,7 @@ export const LayoutShowcase = () => {
|
|
|
1169
1171
|
>
|
|
1170
1172
|
<div className="h-[380px] overflow-hidden [&>div]:!h-full">
|
|
1171
1173
|
<ITNavbar
|
|
1174
|
+
logo={<AxzyLogo variante="icono" tamano={28} etiqueta="" />}
|
|
1172
1175
|
logoText="AXZY"
|
|
1173
1176
|
navigationItems={navbarItems}
|
|
1174
1177
|
userMenu={{
|
|
@@ -1197,6 +1200,7 @@ export const LayoutShowcase = () => {
|
|
|
1197
1200
|
numero="03"
|
|
1198
1201
|
titulo={t("showcase.structure.galleryNavbarSubmenus")}
|
|
1199
1202
|
codigo={`<ITNavbar
|
|
1203
|
+
logo={<AxzyLogo variante="icono" tamano={28} etiqueta="" />}
|
|
1200
1204
|
logoText="Admin"
|
|
1201
1205
|
navigationItems={[
|
|
1202
1206
|
{ id: "u", label: "Usuarios", icon: <FaUsers /> },
|
|
@@ -1215,6 +1219,7 @@ export const LayoutShowcase = () => {
|
|
|
1215
1219
|
>
|
|
1216
1220
|
<div className="h-[380px] overflow-hidden [&>div]:!h-full">
|
|
1217
1221
|
<ITNavbar
|
|
1222
|
+
logo={<AxzyLogo variante="icono" tamano={28} etiqueta="" />}
|
|
1218
1223
|
logoText="Admin"
|
|
1219
1224
|
navigationItems={[
|
|
1220
1225
|
{ id: "u", label: t("showcase.structure.navUsers"), icon: <FaUsers /> },
|