@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
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
import { PRESETS } from "../components/theme-provider/themePresets";
|
|
16
16
|
import { ShowcaseLayout } from "./ShowcaseLayout";
|
|
17
17
|
import { useITTranslation } from "@/i18n";
|
|
18
|
+
import { AxzyLoader, AxzyLogo } from "@/sandbox/AxzyLogo";
|
|
18
19
|
|
|
19
20
|
// 1. ITDialog Showcase
|
|
20
21
|
export const DialogShowcase = () => {
|
|
@@ -237,11 +238,21 @@ export const LoaderShowcase = () => {
|
|
|
237
238
|
</>
|
|
238
239
|
}
|
|
239
240
|
gallery={
|
|
240
|
-
<div className="
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
<div className="space-y-6">
|
|
242
|
+
<div className="flex flex-wrap items-center gap-6">
|
|
243
|
+
<ITLoader variant="spinner" size="md" color="primary" />
|
|
244
|
+
<ITLoader variant="dots" size="md" color="success" />
|
|
245
|
+
<div className="w-32"><ITLoader variant="bar" size="md" color="danger" /></div>
|
|
246
|
+
<ITLoader variant="pulse" size="md" color="purple" />
|
|
247
|
+
</div>
|
|
248
|
+
|
|
249
|
+
{/* Loader de marca: el ícono axzydev con un latido suave. En el kit la
|
|
250
|
+
versión animada es Lottie; aquí se usa el SVG estático. */}
|
|
251
|
+
<div className="flex flex-wrap items-center gap-8 border-t border-slate-200 pt-6 dark:border-slate-800">
|
|
252
|
+
<AxzyLoader etiqueta={t("sandbox.loading")} />
|
|
253
|
+
<AxzyLoader etiqueta={t("sandbox.loading")} tamano={24} />
|
|
254
|
+
<AxzyLogo variante="loader" tamano={56} etiqueta="axzydev" />
|
|
255
|
+
</div>
|
|
245
256
|
</div>
|
|
246
257
|
}
|
|
247
258
|
doc={{
|
|
@@ -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 /> },
|
|
@@ -1304,7 +1309,7 @@ export const LayoutShowcase = () => {
|
|
|
1304
1309
|
{ name: "children", type: "React.ReactNode", required: true, description: "Contenido principal." },
|
|
1305
1310
|
{ name: "className", type: "string", description: "Clases del wrapper externo." },
|
|
1306
1311
|
{ name: "contentClassName", type: "string", description: "Clases del contenedor de contenido." },
|
|
1307
|
-
{ name: "sidebar.header", type: "React.ReactNode", description: "Slot opcional sobre la navegación (ej. wordmark o filtro). Oculto al colapsar." },
|
|
1312
|
+
{ name: "sidebar.header", type: "React.ReactNode", description: "Slot opcional sobre la navegación (ej. wordmark o filtro). Oculto al colapsar, pero reserva su altura." },
|
|
1308
1313
|
{ name: "sidebar.notification", type: "ITSidebarNotification", description: "Fila de notificación (icono + label + ITBadget) sobre la navegación: { count, icon?, label?, onClick?, badgeProps? }. Visible también al colapsar." },
|
|
1309
1314
|
{ name: "sidebar.navigationItems[].badge", type: "number | string", description: "Contador que se renderiza con ITBadget en el ítem." },
|
|
1310
1315
|
{ name: "sidebar.navigationItems[].badgeProps", type: "ITBadgetProps", description: "Estilo del badge del ítem (color, size, variant, className para padding)." },
|
|
@@ -1312,9 +1317,10 @@ export const LayoutShowcase = () => {
|
|
|
1312
1317
|
notes: [
|
|
1313
1318
|
"`subitems` acepta entradas planas o grupos con `label`+`items`; el título del grupo no es foco ni un tercer nivel y cada grupo se nombra por `aria-labelledby`. En el riel colapsado el flyout aplana los grupos (sin títulos).",
|
|
1314
1319
|
"El sidebar hereda aria-current/aria-expanded y acepta un slot header opcional.",
|
|
1315
|
-
"Los badges por ítem (`badge` + `badgeProps`) y la fila `notification` se dibujan con el átomo `ITBadget`; el padding se ajusta con `badgeProps.className`.",
|
|
1320
|
+
"Los badges por ítem (`badge` + `badgeProps`) y la fila `notification` se dibujan con el átomo `ITBadget`; el padding se ajusta con `badgeProps.className`. `badge` es un contador: en el riel colapsado solo caben ≤3 caracteres y un texto largo se degrada a un punto.",
|
|
1316
1321
|
"Con `sidebar.isCollapsed` omitido el contenido reserva 88px (hover expande sobre el contenido). Si lo controlas a `false`, reserva 280px y no tapa el contenido.",
|
|
1317
1322
|
"El riel colapsado se expande automáticamente al pasar el cursor por encima; no hay botón de colapso.",
|
|
1323
|
+
"Riel y panel comparten columna de iconos y alto de fila: los iconos no se mueven al expandir/colapsar. El slot `header` reserva su altura (invisible) en el riel por el mismo motivo.",
|
|
1318
1324
|
],
|
|
1319
1325
|
}}
|
|
1320
1326
|
/>
|