@axzydev/axzy_ui_system 1.4.8 → 1.5.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/README.md +2 -11
- package/dist/index.cjs +1826 -1351
- 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 +115 -14
- package/dist/index.d.ts +115 -14
- package/dist/index.js +1481 -1010
- package/dist/index.js.map +1 -1
- package/dist/layered.css +1 -1
- package/package.json +3 -16
- package/src/App.tsx +90 -73
- package/src/components/atoms/badget/badget.tsx +23 -5
- package/src/components/atoms/chip/chip.tsx +3 -1
- package/src/components/atoms/image/image.tsx +3 -1
- package/src/components/atoms/input/input.tsx +8 -5
- package/src/components/atoms/loader/loader.tsx +3 -1
- package/src/components/atoms/slide/slide.props.ts +12 -0
- package/src/components/atoms/slide/slide.tsx +3 -0
- package/src/components/molecules/alert/alert.tsx +3 -1
- package/src/components/molecules/breadcrumbs/breadcrumbs.tsx +3 -1
- package/src/components/molecules/calendar/calendar.tsx +9 -6
- package/src/components/molecules/card/card.tsx +5 -2
- package/src/components/molecules/chip-input/chip-input.tsx +9 -7
- package/src/components/molecules/date-picker/datePicker.tsx +9 -9
- package/src/components/molecules/dropdown-menu/dropdown-menu.props.ts +1 -1
- package/src/components/molecules/dropdown-menu/dropdown-menu.tsx +6 -3
- package/src/components/molecules/field/field.tsx +3 -1
- package/src/components/molecules/form-header/form-header.tsx +3 -1
- package/src/components/molecules/line-bar-chart/line-bar-chart.props.ts +2 -2
- package/src/components/molecules/line-bar-chart/line-bar-chart.tsx +20 -15
- package/src/components/molecules/masked-input/masked-input.tsx +3 -1
- package/src/components/molecules/multi-select/multi-select.tsx +12 -9
- package/src/components/molecules/pagination/pagination.tsx +11 -5
- package/src/components/molecules/search-select/search-select.tsx +11 -9
- package/src/components/molecules/select/select.tsx +6 -4
- package/src/components/molecules/stepper/stepper.tsx +6 -4
- package/src/components/molecules/table/table.tsx +30 -28
- package/src/components/molecules/time-picker/timePicker.tsx +8 -6
- package/src/components/molecules/wysiwyg/wysiwyg.tsx +23 -12
- package/src/components/organisms/confirm-dialog/confirm-dialog.props.ts +4 -4
- package/src/components/organisms/confirm-dialog/confirm-dialog.tsx +16 -8
- package/src/components/organisms/data-table/dataTable.tsx +31 -25
- package/src/components/organisms/dialog/dialog.tsx +3 -0
- package/src/components/organisms/drawer/drawer.tsx +3 -0
- package/src/components/organisms/dropfile/dropfile.tsx +19 -17
- package/src/components/organisms/form-builder/fieldRenderer.tsx +4 -2
- package/src/components/organisms/navbar/navbar.tsx +4 -2
- package/src/components/organisms/page-header/page-header.tsx +3 -1
- package/src/components/organisms/searchTable/components/PaginationControls.tsx +8 -6
- package/src/components/organisms/searchTable/components/PaginationInfo.tsx +3 -1
- package/src/components/organisms/searchTable/components/SearchAndSortBar.tsx +7 -5
- package/src/components/organisms/searchTable/components/SearchInput.tsx +4 -2
- package/src/components/organisms/searchTable/components/SortButton.tsx +13 -11
- package/src/components/organisms/searchTable/components/TableEmptyState.tsx +4 -2
- package/src/components/organisms/searchTable/components/TableRow.tsx +6 -4
- package/src/components/organisms/searchTable/searchTable.tsx +4 -2
- package/src/components/organisms/sidebar/sidebar.props.ts +1 -1
- package/src/components/organisms/sidebar/sidebar.tsx +9 -4
- package/src/components/organisms/toast/toast.tsx +3 -1
- package/src/components/organisms/topbar/topbar.tsx +4 -2
- package/src/components/templates/page/page.props.ts +4 -4
- package/src/components/templates/page/page.tsx +6 -4
- package/src/components/theme-provider/themeProvider.tsx +28 -17
- package/src/dev.css +77 -2
- package/src/global.d.ts +10 -0
- package/src/i18n/context.ts +9 -0
- package/src/i18n/index.ts +22 -0
- package/src/i18n/locales/en.ts +163 -0
- package/src/i18n/locales/es.ts +165 -0
- package/src/i18n/provider.tsx +44 -0
- package/src/i18n/translator.ts +82 -0
- package/src/i18n/types.ts +54 -0
- package/src/i18n/useITTranslation.ts +20 -0
- package/src/index.css +0 -1
- package/src/index.ts +7 -1
- package/src/sandbox/LandingShowcase.tsx +224 -580
- package/src/sandbox/NotFoundShowcase.tsx +51 -36
- package/src/sandbox/TopbarSearch.tsx +6 -4
- package/src/sandbox/controls.tsx +180 -0
- package/src/sandbox/i18n.ts +1929 -0
- package/src/sandbox/icons.tsx +25 -0
- package/src/sandbox/locale.tsx +72 -0
- package/src/sandbox/ui.tsx +377 -0
- package/src/sandbox/useHashRoute.ts +46 -10
- package/src/showcases/DataShowcases.tsx +103 -87
- package/src/showcases/FeedbackShowcases.tsx +37 -30
- package/src/showcases/FormShowcases.tsx +302 -214
- package/src/showcases/GettingStartedShowcase.tsx +151 -145
- package/src/showcases/HelpShowcase.tsx +126 -128
- package/src/showcases/HomeShowcase.tsx +678 -482
- package/src/showcases/LayoutPrimitivesShowcases.tsx +129 -114
- package/src/showcases/NavigationShowcases.tsx +45 -37
- package/src/showcases/PageShowcases.tsx +171 -152
- package/src/showcases/ProductoDetalle.tsx +272 -129
- package/src/showcases/ShowcaseLayout.tsx +270 -216
- package/src/showcases/SizesShowcase.tsx +123 -64
- package/src/showcases/StructureShowcases.tsx +157 -131
- package/src/showcases/portfolioUi.tsx +153 -0
- package/src/showcases/techIcons.ts +3 -0
- package/src/utils/table.utils.ts +10 -2
- package/src/components/atoms/avatar/avatar.doc.mdx +0 -48
- package/src/components/atoms/avatar/avatar.stories.tsx +0 -64
- package/src/components/atoms/badget/badget.doc.mdx +0 -46
- package/src/components/atoms/badget/badget.stories.tsx +0 -75
- package/src/components/atoms/button/button.doc.mdx +0 -59
- package/src/components/atoms/button/button.stories.tsx +0 -173
- package/src/components/atoms/checkbox/checkbox.doc.mdx +0 -54
- package/src/components/atoms/checkbox/checkbox.stories.tsx +0 -53
- package/src/components/atoms/chip/chip.doc.mdx +0 -47
- package/src/components/atoms/chip/chip.stories.tsx +0 -64
- package/src/components/atoms/divider/divider.doc.mdx +0 -42
- package/src/components/atoms/divider/divider.stories.tsx +0 -33
- package/src/components/atoms/flex/flex.doc.mdx +0 -59
- package/src/components/atoms/flex/flex.stories.tsx +0 -70
- package/src/components/atoms/grid/grid.doc.mdx +0 -54
- package/src/components/atoms/grid/grid.stories.tsx +0 -71
- package/src/components/atoms/image/image.doc.mdx +0 -44
- package/src/components/atoms/image/image.stories.tsx +0 -48
- package/src/components/atoms/input/input.doc.mdx +0 -70
- package/src/components/atoms/input/input.stories.tsx +0 -113
- package/src/components/atoms/input-number/input-number.doc.mdx +0 -74
- package/src/components/atoms/input-number/input-number.stories.tsx +0 -111
- package/src/components/atoms/loader/loader.doc.mdx +0 -43
- package/src/components/atoms/loader/loader.stories.tsx +0 -104
- package/src/components/atoms/popover/popover.doc.mdx +0 -53
- package/src/components/atoms/popover/popover.stories.tsx +0 -24
- package/src/components/atoms/progress/progress.doc.mdx +0 -48
- package/src/components/atoms/progress/progress.stories.tsx +0 -39
- package/src/components/atoms/radio/radio.doc.mdx +0 -62
- package/src/components/atoms/radio/radio.stories.tsx +0 -48
- package/src/components/atoms/segmented-control/segmented-control.doc.mdx +0 -60
- package/src/components/atoms/segmented-control/segmented-control.stories.tsx +0 -62
- package/src/components/atoms/skeleton/skeleton.doc.mdx +0 -43
- package/src/components/atoms/skeleton/skeleton.stories.tsx +0 -29
- package/src/components/atoms/slide/slide.doc.mdx +0 -46
- package/src/components/atoms/slide/slide.stories.tsx +0 -120
- package/src/components/atoms/slider/slider.doc.mdx +0 -49
- package/src/components/atoms/slider/slider.stories.tsx +0 -29
- package/src/components/atoms/stack/stack.doc.mdx +0 -126
- package/src/components/atoms/stack/stack.stories.tsx +0 -283
- package/src/components/atoms/text/text.doc.mdx +0 -41
- package/src/components/atoms/text/text.stories.tsx +0 -66
- package/src/components/atoms/textarea/textarea.doc.mdx +0 -64
- package/src/components/atoms/textarea/textarea.stories.tsx +0 -26
- package/src/components/atoms/tooltip/tooltip.doc.mdx +0 -47
- package/src/components/atoms/tooltip/tooltip.stories.tsx +0 -19
- package/src/components/isolation/isolation.stories.tsx +0 -202
- package/src/components/molecules/accordion/accordion.doc.mdx +0 -47
- package/src/components/molecules/accordion/accordion.stories.tsx +0 -68
- package/src/components/molecules/alert/alert.doc.mdx +0 -48
- package/src/components/molecules/alert/alert.stories.tsx +0 -40
- package/src/components/molecules/breadcrumbs/breadcrumbs.doc.mdx +0 -57
- package/src/components/molecules/breadcrumbs/breadcrumbs.stories.tsx +0 -20
- package/src/components/molecules/calendar/calendar.doc.mdx +0 -76
- package/src/components/molecules/calendar/calendar.stories.tsx +0 -90
- package/src/components/molecules/card/card.doc.mdx +0 -54
- package/src/components/molecules/card/card.stories.tsx +0 -57
- package/src/components/molecules/chip-input/chip-input.doc.mdx +0 -44
- package/src/components/molecules/chip-input/chip-input.stories.tsx +0 -52
- package/src/components/molecules/date-picker/date-picker.doc.mdx +0 -65
- package/src/components/molecules/date-picker/date-picker.stories.tsx +0 -88
- package/src/components/molecules/dropdown-menu/dropdown-menu.doc.mdx +0 -46
- package/src/components/molecules/dropdown-menu/dropdown-menu.stories.tsx +0 -41
- package/src/components/molecules/empty-state/empty-state.doc.mdx +0 -50
- package/src/components/molecules/empty-state/empty-state.stories.tsx +0 -19
- package/src/components/molecules/field/field.doc.mdx +0 -43
- package/src/components/molecules/field/field.stories.tsx +0 -42
- package/src/components/molecules/form-header/form-header.doc.mdx +0 -38
- package/src/components/molecules/form-header/form-header.stories.tsx +0 -52
- package/src/components/molecules/masked-input/masked-input.doc.mdx +0 -78
- package/src/components/molecules/masked-input/masked-input.stories.tsx +0 -126
- package/src/components/molecules/multi-select/multi-select.doc.mdx +0 -55
- package/src/components/molecules/multi-select/multi-select.stories.tsx +0 -59
- package/src/components/molecules/pagination/pagination.doc.mdx +0 -62
- package/src/components/molecules/pagination/pagination.stories.tsx +0 -110
- package/src/components/molecules/search-select/search-select.doc.mdx +0 -77
- package/src/components/molecules/search-select/search-select.stories.tsx +0 -146
- package/src/components/molecules/select/select.doc.mdx +0 -75
- package/src/components/molecules/select/select.stories.tsx +0 -85
- package/src/components/molecules/stat-card/stat-card.doc.mdx +0 -48
- package/src/components/molecules/stat-card/stat-card.stories.tsx +0 -40
- package/src/components/molecules/stepper/stepper.doc.mdx +0 -54
- package/src/components/molecules/stepper/stepper.stories.tsx +0 -154
- package/src/components/molecules/table/table.doc.mdx +0 -140
- package/src/components/molecules/table/table.stories.tsx +0 -402
- package/src/components/molecules/tabs/tabs.doc.mdx +0 -52
- package/src/components/molecules/tabs/tabs.stories.tsx +0 -31
- package/src/components/molecules/time-picker/timePicker.doc.mdx +0 -68
- package/src/components/molecules/time-picker/timePicker.stories.tsx +0 -130
- package/src/components/molecules/wysiwyg/wysiwyg.stories.tsx +0 -95
- package/src/components/organisms/confirm-dialog/confirm-dialog.doc.mdx +0 -60
- package/src/components/organisms/confirm-dialog/confirm-dialog.stories.tsx +0 -32
- package/src/components/organisms/data-table/ITDataTable.doc.mdx +0 -132
- package/src/components/organisms/data-table/ITDataTable.stories.tsx +0 -353
- package/src/components/organisms/dialog/dialog.doc.mdx +0 -54
- package/src/components/organisms/dialog/dialog.stories.tsx +0 -126
- package/src/components/organisms/drawer/drawer.doc.mdx +0 -59
- package/src/components/organisms/drawer/drawer.stories.tsx +0 -40
- package/src/components/organisms/dropfile/dropfile.doc.mdx +0 -74
- package/src/components/organisms/dropfile/dropfile.stories.tsx +0 -93
- package/src/components/organisms/form-builder/formBuilder.doc.mdx +0 -251
- package/src/components/organisms/form-builder/formBuilder.stories.tsx +0 -914
- package/src/components/organisms/navbar/navbar.doc.mdx +0 -77
- package/src/components/organisms/navbar/navbar.stories.tsx +0 -83
- package/src/components/organisms/page-header/page-header.doc.mdx +0 -54
- package/src/components/organisms/page-header/page-header.stories.tsx +0 -74
- package/src/components/organisms/searchTable/searchTable.doc.mdx +0 -79
- package/src/components/organisms/searchTable/searchTable.stories.tsx +0 -73
- package/src/components/organisms/sidebar/sidebar.doc.mdx +0 -176
- package/src/components/organisms/sidebar/sidebar.stories.tsx +0 -234
- package/src/components/organisms/toast/toast.doc.mdx +0 -50
- package/src/components/organisms/toast/toast.stories.tsx +0 -137
- package/src/components/organisms/topbar/topbar.doc.mdx +0 -72
- package/src/components/organisms/topbar/topbar.stories.tsx +0 -79
- package/src/components/organisms/triple-filter/tripleFilter.doc.mdx +0 -62
- package/src/components/organisms/triple-filter/tripleFilter.stories.tsx +0 -31
- package/src/components/templates/layout/layout.doc.mdx +0 -53
- package/src/components/templates/layout/layout.stories.tsx +0 -113
- package/src/components/templates/page/page.doc.mdx +0 -86
- package/src/components/templates/page/page.stories.tsx +0 -97
- package/src/components/theme-provider/themeProvider.doc.mdx +0 -85
- package/src/components/theme-provider/themeProvider.stories.tsx +0 -58
|
@@ -1,62 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marco de las páginas de componente del sandbox (`#ui-system/<grupo>/<item>`):
|
|
3
|
+
* cabecera de la hoja, vitrina interactiva (vista previa / código), panel de
|
|
4
|
+
* propiedades y documentación, y galería de variaciones.
|
|
5
|
+
*
|
|
6
|
+
* Sigue `DESIGN.md` (AXZY Console): el bloque lo separan filetes de 1px, no
|
|
7
|
+
* cajas dentro de cajas; los controles vienen del kit compartido
|
|
8
|
+
* (`@/sandbox/ui` y `@/sandbox/controls`) para que el marco no introduzca
|
|
9
|
+
* colores que no pasan AA.
|
|
10
|
+
*/
|
|
11
|
+
|
|
1
12
|
import React, { useState } from "react";
|
|
2
|
-
import {
|
|
13
|
+
import { FaBookOpen, FaCheck, FaCode, FaCog, FaCopy, FaEye } from "react-icons/fa";
|
|
3
14
|
import ITGrid from "../components/atoms/grid/grid";
|
|
4
15
|
import { useITTheme } from "../components/theme-provider/themeProvider";
|
|
16
|
+
import { ControlSegmentado } from "@/sandbox/controls";
|
|
17
|
+
import { EYEBROW, FILETE, FOCO_CTA } from "@/sandbox/ui";
|
|
18
|
+
import { useITTranslation } from "@/i18n";
|
|
5
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Bloque de código con botón de copiar. Fondo tinta, mono y el acento de señal
|
|
22
|
+
* (`cyan-400`) reservado a la etiqueta, como manda el spec.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <CodeViewer code={`<ITButton>Guardar</ITButton>`} compact />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
6
29
|
export const CodeViewer: React.FC<{ code: string; compact?: boolean }> = ({ code, compact }) => {
|
|
30
|
+
const { t } = useITTranslation();
|
|
7
31
|
const [copied, setCopied] = useState(false);
|
|
32
|
+
|
|
8
33
|
const handleCopy = () => {
|
|
9
|
-
navigator.clipboard
|
|
34
|
+
navigator.clipboard?.writeText(code);
|
|
10
35
|
setCopied(true);
|
|
11
|
-
setTimeout(() => setCopied(false), 2000);
|
|
36
|
+
window.setTimeout(() => setCopied(false), 2000);
|
|
12
37
|
};
|
|
38
|
+
|
|
13
39
|
return (
|
|
14
|
-
<div className="relative rounded-
|
|
15
|
-
<div className="flex
|
|
16
|
-
<span className="text-[10px] uppercase
|
|
40
|
+
<div className="relative overflow-hidden rounded-[10px] border border-slate-800 bg-slate-950 text-slate-200">
|
|
41
|
+
<div className="flex items-center justify-between border-b border-slate-800 px-4 py-2.5">
|
|
42
|
+
<span className="font-mono text-[10px] uppercase tracking-[0.14em] text-cyan-400">
|
|
43
|
+
{t("showcase.layout.jsxCode")}
|
|
44
|
+
</span>
|
|
17
45
|
<button
|
|
46
|
+
type="button"
|
|
18
47
|
onClick={handleCopy}
|
|
19
|
-
className=
|
|
48
|
+
className={`flex items-center gap-1.5 rounded-[6px] px-2 py-1 font-mono text-[10px] uppercase tracking-[0.12em] text-slate-400 transition-colors hover:bg-slate-800 hover:text-white ${FOCO_CTA}`}
|
|
20
49
|
>
|
|
21
|
-
{copied ? <FaCheck size={11} className="text-
|
|
22
|
-
<span>{copied ? "
|
|
50
|
+
{copied ? <FaCheck size={11} className="text-cyan-400" /> : <FaCopy size={11} />}
|
|
51
|
+
<span>{copied ? t("showcase.layout.copied") : t("showcase.layout.copy")}</span>
|
|
23
52
|
</button>
|
|
24
53
|
</div>
|
|
25
|
-
<pre
|
|
54
|
+
<pre
|
|
55
|
+
className={`overflow-x-auto whitespace-pre-wrap p-4 font-mono text-xs leading-relaxed ${
|
|
56
|
+
compact ? "max-h-[420px]" : ""
|
|
57
|
+
} overflow-y-auto`}
|
|
58
|
+
>
|
|
26
59
|
<code>{code}</code>
|
|
27
60
|
</pre>
|
|
28
61
|
</div>
|
|
29
62
|
);
|
|
30
63
|
};
|
|
31
64
|
|
|
65
|
+
/** Una fila de la tabla de props. */
|
|
32
66
|
export interface PropDocEntry {
|
|
67
|
+
/** Nombre del prop. */
|
|
33
68
|
name: string;
|
|
69
|
+
/** Tipo TypeScript. */
|
|
34
70
|
type: string;
|
|
71
|
+
/** Valor por defecto. */
|
|
35
72
|
default?: string;
|
|
73
|
+
/** Descripción para el panel de documentación. */
|
|
36
74
|
description: string;
|
|
75
|
+
/** Marca el prop como obligatorio. */
|
|
37
76
|
required?: boolean;
|
|
38
77
|
}
|
|
39
78
|
|
|
79
|
+
/** Documentación de un componente, si el showcase la declara. */
|
|
40
80
|
export interface ComponentDoc {
|
|
81
|
+
/** Resumen de una línea. */
|
|
41
82
|
summary: string;
|
|
83
|
+
/** Descripción larga opcional. */
|
|
42
84
|
description?: string;
|
|
85
|
+
/** Ejemplos de uso (código). */
|
|
43
86
|
examples?: string[];
|
|
87
|
+
/** Tabla de props. */
|
|
44
88
|
props: PropDocEntry[];
|
|
89
|
+
/** Notas al pie. */
|
|
45
90
|
notes?: string[];
|
|
46
91
|
}
|
|
47
92
|
|
|
93
|
+
/** Props de `ShowcaseLayout`. */
|
|
48
94
|
export interface ShowcaseLayoutProps {
|
|
95
|
+
/** Nombre del componente. */
|
|
49
96
|
title: string;
|
|
97
|
+
/** Descripción corta bajo el título. */
|
|
50
98
|
description: string;
|
|
99
|
+
/** Demo interactiva. */
|
|
51
100
|
demo: React.ReactNode;
|
|
52
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Panel de controles (lo construye cada showcase). Si se omite, la vitrina
|
|
103
|
+
* ocupa todo el ancho y no se pinta panel: para páginas que solo muestran un
|
|
104
|
+
* ejemplo o una receta.
|
|
105
|
+
*/
|
|
106
|
+
controls?: React.ReactNode;
|
|
107
|
+
/** Código fuente que se muestra en la pestaña de código. */
|
|
53
108
|
code: string;
|
|
109
|
+
/** Galería de variaciones y estados. */
|
|
54
110
|
gallery?: React.ReactNode;
|
|
111
|
+
/** Documentación opcional (añade la pestaña "Docs"). */
|
|
55
112
|
doc?: ComponentDoc;
|
|
113
|
+
/**
|
|
114
|
+
* Ancho de la vitrina. `"columna"` (por defecto) la deja en 8/12 columnas con
|
|
115
|
+
* el panel al lado; `"completo"` la lleva a las 12 y baja el panel, para demos
|
|
116
|
+
* que son un layout entero (ITLayout, pantallas de ejemplo) y se recortaban.
|
|
117
|
+
* @default "columna"
|
|
118
|
+
*/
|
|
119
|
+
demoAncho?: "columna" | "completo";
|
|
56
120
|
}
|
|
57
121
|
|
|
58
122
|
type SandboxView = "preview" | "code";
|
|
59
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Página de un componente del sandbox: cabecera, vitrina con vista previa y
|
|
126
|
+
* código, panel lateral de propiedades/documentación y galería.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```tsx
|
|
130
|
+
* <ShowcaseLayout title="ITButton" description="…" demo={<ITButton>Guardar</ITButton>}
|
|
131
|
+
* controls={<ITSelect … />} code={code} gallery={<Gallery />} doc={doc} />
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
60
134
|
export const ShowcaseLayout: React.FC<ShowcaseLayoutProps> = ({
|
|
61
135
|
title,
|
|
62
136
|
description,
|
|
@@ -64,238 +138,218 @@ export const ShowcaseLayout: React.FC<ShowcaseLayoutProps> = ({
|
|
|
64
138
|
controls,
|
|
65
139
|
code,
|
|
66
140
|
gallery,
|
|
67
|
-
doc
|
|
141
|
+
doc,
|
|
142
|
+
demoAncho = "columna",
|
|
68
143
|
}) => {
|
|
144
|
+
const completo = demoAncho === "completo";
|
|
145
|
+
const { t } = useITTranslation();
|
|
69
146
|
const { resolvedTheme } = useITTheme();
|
|
70
|
-
const [activeTab, setActiveTab] = useState<"controls" | "docs">("controls");
|
|
147
|
+
const [activeTab, setActiveTab] = useState<"controls" | "docs">(controls ? "controls" : "docs");
|
|
71
148
|
const [sandboxView, setSandboxView] = useState<SandboxView>("preview");
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
{/* Title block */}
|
|
75
|
-
<div className="flex flex-col md:flex-row md:items-start justify-between gap-4">
|
|
76
|
-
<div className="flex-1 min-w-0">
|
|
77
|
-
<h1 className="text-3xl font-extrabold text-slate-800 dark:text-white tracking-tight flex items-center gap-3">
|
|
78
|
-
{title}
|
|
79
|
-
</h1>
|
|
80
|
-
<p className="text-slate-500 dark:text-slate-400 mt-1.5 text-sm md:text-base">{description}</p>
|
|
81
|
-
</div>
|
|
149
|
+
// Sin controles la vitrina se queda con todo el ancho.
|
|
150
|
+
const hayPanel = Boolean(controls) || Boolean(doc);
|
|
82
151
|
|
|
152
|
+
return (
|
|
153
|
+
<div className="animate-fadeIn pb-4">
|
|
154
|
+
{/* ─── CABECERA DE LA HOJA ─── */}
|
|
155
|
+
<header className={`border-b pb-7 ${FILETE}`}>
|
|
156
|
+
<p className={EYEBROW}>{t("showcase.layout.eyebrow")}</p>
|
|
157
|
+
<h1 className="mt-2.5 font-display text-[32px] font-bold tracking-[-0.02em] text-slate-900 dark:text-white sm:text-[40px]">
|
|
158
|
+
{title}
|
|
159
|
+
</h1>
|
|
160
|
+
<p className="mt-3 max-w-[70ch] text-[15px] leading-relaxed text-slate-600 dark:text-slate-300">
|
|
161
|
+
{description}
|
|
162
|
+
</p>
|
|
163
|
+
</header>
|
|
83
164
|
|
|
84
|
-
|
|
165
|
+
<div className="pt-8">
|
|
166
|
+
<ITGrid container columns={12} spacing={8}>
|
|
167
|
+
{/* ── VITRINA ── */}
|
|
168
|
+
<ITGrid item xs={12} md={completo || !hayPanel ? 12 : 8}>
|
|
169
|
+
<section
|
|
170
|
+
aria-label={t("showcase.layout.sandbox")}
|
|
171
|
+
className={`overflow-hidden rounded-[10px] border ${FILETE}`}
|
|
172
|
+
>
|
|
173
|
+
{/* Barra de la vitrina */}
|
|
174
|
+
<div className={`flex flex-wrap items-center justify-between gap-3 border-b px-4 py-2.5 ${FILETE}`}>
|
|
175
|
+
<h2 className={EYEBROW}>{t("showcase.layout.sandbox")}</h2>
|
|
85
176
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
</span>
|
|
177
|
+
<ControlSegmentado
|
|
178
|
+
etiqueta={t("showcase.layout.sandbox")}
|
|
179
|
+
valor={sandboxView}
|
|
180
|
+
onChange={(value) => setSandboxView(value === "code" ? "code" : "preview")}
|
|
181
|
+
opciones={[
|
|
182
|
+
{
|
|
183
|
+
value: "preview",
|
|
184
|
+
label: t("showcase.layout.preview"),
|
|
185
|
+
icono: <FaEye size={10} />,
|
|
186
|
+
},
|
|
187
|
+
{ value: "code", label: t("showcase.layout.code"), icono: <FaCode size={10} /> },
|
|
188
|
+
]}
|
|
189
|
+
/>
|
|
100
190
|
</div>
|
|
101
191
|
|
|
102
|
-
{/*
|
|
103
|
-
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
className=
|
|
107
|
-
sandboxView === "preview"
|
|
108
|
-
? "bg-primary-100 dark:bg-primary-900/40 text-primary-700 dark:text-primary-300"
|
|
109
|
-
: "text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200"
|
|
110
|
-
}`}
|
|
111
|
-
>
|
|
112
|
-
<FaEye size={10} />
|
|
113
|
-
Preview
|
|
114
|
-
</button>
|
|
115
|
-
<button
|
|
116
|
-
onClick={() => setSandboxView("code")}
|
|
117
|
-
className={`flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-semibold rounded-md transition-all ${
|
|
118
|
-
sandboxView === "code"
|
|
119
|
-
? "bg-primary-100 dark:bg-primary-900/40 text-primary-700 dark:text-primary-300"
|
|
120
|
-
: "text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200"
|
|
121
|
-
}`}
|
|
192
|
+
{/* Contenido */}
|
|
193
|
+
{sandboxView === "preview" ? (
|
|
194
|
+
<div
|
|
195
|
+
data-theme={resolvedTheme}
|
|
196
|
+
className="flex min-h-[280px] items-center justify-center overflow-x-auto bg-white p-6 dark:bg-slate-950 md:p-10"
|
|
122
197
|
>
|
|
123
|
-
<
|
|
124
|
-
Code
|
|
125
|
-
</button>
|
|
126
|
-
</div>
|
|
127
|
-
</div>
|
|
128
|
-
|
|
129
|
-
{/* Sandbox content */}
|
|
130
|
-
{sandboxView === "preview" ? (
|
|
131
|
-
<div
|
|
132
|
-
data-theme={resolvedTheme}
|
|
133
|
-
className="p-6 md:p-10 min-h-[320px] flex items-center justify-center transition-all duration-300 bg-white dark:bg-slate-950"
|
|
134
|
-
>
|
|
135
|
-
<div className="w-full flex justify-center">{demo}</div>
|
|
136
|
-
</div>
|
|
137
|
-
) : (
|
|
138
|
-
<div className="p-3 bg-slate-50 dark:bg-slate-800/50">
|
|
139
|
-
<CodeViewer code={code} compact />
|
|
140
|
-
</div>
|
|
141
|
-
)}
|
|
142
|
-
</div>
|
|
143
|
-
</ITGrid>
|
|
144
|
-
|
|
145
|
-
{/* ── RIGHT SIDEBAR: Configs / Docs ── */}
|
|
146
|
-
<ITGrid item as="aside" xs={12} md={4}>
|
|
147
|
-
<div className="md:sticky md:top-4">
|
|
148
|
-
<div className="bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-slate-700 shadow-sm overflow-hidden">
|
|
149
|
-
{/* Tab bar */}
|
|
150
|
-
{doc ? (
|
|
151
|
-
<div className="flex border-b border-slate-200 dark:border-slate-700">
|
|
152
|
-
<button
|
|
153
|
-
onClick={() => setActiveTab("controls")}
|
|
154
|
-
className={`flex-1 flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold transition-colors ${
|
|
155
|
-
activeTab === "controls"
|
|
156
|
-
? "text-primary-600 border-b-2 border-primary-600 bg-primary-50/40 dark:bg-primary-950/20 dark:text-primary-400 dark:border-primary-400"
|
|
157
|
-
: "text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200"
|
|
158
|
-
}`}
|
|
159
|
-
>
|
|
160
|
-
<FaCog size={11} />
|
|
161
|
-
Properties
|
|
162
|
-
</button>
|
|
163
|
-
<button
|
|
164
|
-
onClick={() => setActiveTab("docs")}
|
|
165
|
-
className={`flex-1 flex items-center justify-center gap-1.5 py-2.5 text-xs font-semibold transition-colors ${
|
|
166
|
-
activeTab === "docs"
|
|
167
|
-
? "text-primary-600 border-b-2 border-primary-600 bg-primary-50/40 dark:bg-primary-950/20 dark:text-primary-400 dark:border-primary-400"
|
|
168
|
-
: "text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-200"
|
|
169
|
-
}`}
|
|
170
|
-
>
|
|
171
|
-
<FaBookOpen size={11} />
|
|
172
|
-
Docs
|
|
173
|
-
</button>
|
|
198
|
+
<div className="flex w-full justify-center">{demo}</div>
|
|
174
199
|
</div>
|
|
175
|
-
) :
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
{activeTab === "controls" && (
|
|
179
|
-
<div className="p-4 space-y-4 max-h-[calc(100vh-160px)] overflow-y-auto">
|
|
180
|
-
<div className="space-y-4">{controls}</div>
|
|
200
|
+
) : (
|
|
201
|
+
<div className="p-3">
|
|
202
|
+
<CodeViewer code={code} compact />
|
|
181
203
|
</div>
|
|
182
204
|
)}
|
|
205
|
+
</section>
|
|
206
|
+
</ITGrid>
|
|
183
207
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
208
|
+
{/* ── PANEL LATERAL ── */}
|
|
209
|
+
{hayPanel && (
|
|
210
|
+
<ITGrid item xs={12} md={completo ? 12 : 4}>
|
|
211
|
+
<div className={completo ? "" : "md:sticky md:top-4"}>
|
|
212
|
+
<section
|
|
213
|
+
aria-label={t("showcase.layout.properties")}
|
|
214
|
+
className={`overflow-hidden rounded-[10px] border ${FILETE} ${
|
|
215
|
+
completo ? "max-w-[880px]" : ""
|
|
216
|
+
}`}
|
|
217
|
+
>
|
|
218
|
+
{doc ? (
|
|
219
|
+
<div
|
|
220
|
+
role="tablist"
|
|
221
|
+
aria-label={t("showcase.layout.properties")}
|
|
222
|
+
className={`flex items-stretch gap-1 border-b px-2 ${FILETE}`}
|
|
223
|
+
>
|
|
224
|
+
{(
|
|
225
|
+
[
|
|
226
|
+
{ id: "controls", label: t("showcase.layout.properties"), icono: <FaCog size={10} /> },
|
|
227
|
+
{ id: "docs", label: t("showcase.layout.docs"), icono: <FaBookOpen size={10} /> },
|
|
228
|
+
] as const
|
|
229
|
+
).map((tab) => {
|
|
230
|
+
const activa = activeTab === tab.id;
|
|
231
|
+
return (
|
|
232
|
+
<button
|
|
233
|
+
key={tab.id}
|
|
234
|
+
type="button"
|
|
235
|
+
role="tab"
|
|
236
|
+
aria-selected={activa}
|
|
237
|
+
onClick={() => setActiveTab(tab.id)}
|
|
238
|
+
className={`-mb-px inline-flex items-center gap-2 border-b-2 px-3 py-2.5 font-mono text-[10px] font-medium uppercase tracking-[0.14em] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/60 ${
|
|
239
|
+
activa
|
|
240
|
+
? "border-primary-700 text-primary-700 dark:border-primary-500 dark:text-primary-500"
|
|
241
|
+
: "border-transparent text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-white"
|
|
242
|
+
}`}
|
|
243
|
+
>
|
|
244
|
+
{tab.icono}
|
|
245
|
+
{tab.label}
|
|
246
|
+
</button>
|
|
247
|
+
);
|
|
248
|
+
})}
|
|
200
249
|
</div>
|
|
250
|
+
) : null}
|
|
201
251
|
|
|
202
|
-
|
|
203
|
-
<div
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<thead>
|
|
210
|
-
<tr className="bg-slate-50 dark:bg-slate-800">
|
|
211
|
-
<th className="text-left px-2 py-1.5 font-semibold text-slate-600 dark:text-slate-300 whitespace-nowrap">Prop</th>
|
|
212
|
-
<th className="text-left px-2 py-1.5 font-semibold text-slate-600 dark:text-slate-300 whitespace-nowrap">Type</th>
|
|
213
|
-
<th className="text-left px-2 py-1.5 font-semibold text-slate-600 dark:text-slate-300 whitespace-nowrap">Default</th>
|
|
214
|
-
</tr>
|
|
215
|
-
</thead>
|
|
216
|
-
<tbody>
|
|
217
|
-
{doc.props.map((prop, i) => (
|
|
218
|
-
<tr
|
|
219
|
-
key={prop.name}
|
|
220
|
-
className={`border-t border-slate-100 dark:border-slate-800 ${
|
|
221
|
-
i % 2 === 0 ? "bg-white dark:bg-slate-900" : "bg-slate-50/50 dark:bg-slate-800/50"
|
|
222
|
-
}`}
|
|
223
|
-
>
|
|
224
|
-
<td className="px-2 py-1.5 font-mono font-semibold text-primary-700 dark:text-primary-400 whitespace-nowrap">
|
|
225
|
-
{prop.name}
|
|
226
|
-
{prop.required ? <span className="text-danger-500 ml-0.5">*</span> : null}
|
|
227
|
-
</td>
|
|
228
|
-
<td className="px-2 py-1.5 font-mono text-slate-600 dark:text-slate-400 text-[10px]">
|
|
229
|
-
{prop.type}
|
|
230
|
-
</td>
|
|
231
|
-
<td className="px-2 py-1.5 font-mono text-slate-400 dark:text-slate-500 text-[10px]">
|
|
232
|
-
{prop.default || "—"}
|
|
233
|
-
</td>
|
|
234
|
-
</tr>
|
|
235
|
-
))}
|
|
236
|
-
</tbody>
|
|
237
|
-
</table>
|
|
238
|
-
</div>
|
|
239
|
-
{/* Detailed descriptions below the compact table */}
|
|
240
|
-
<div className="mt-2 space-y-1.5">
|
|
241
|
-
{doc.props.map((prop) => (
|
|
242
|
-
<div key={prop.name} className="text-[11px]">
|
|
243
|
-
<span className="font-mono font-semibold text-primary-700 dark:text-primary-400">{prop.name}</span>
|
|
244
|
-
<span className="text-slate-500 dark:text-slate-400"> — {prop.description}</span>
|
|
245
|
-
</div>
|
|
246
|
-
))}
|
|
247
|
-
</div>
|
|
252
|
+
{activeTab === "controls" && (
|
|
253
|
+
<div
|
|
254
|
+
className={`max-h-[calc(100vh-200px)] space-y-4 overflow-y-auto p-5 ${
|
|
255
|
+
completo ? "it-panel-ancho max-w-[880px]" : ""
|
|
256
|
+
}`}
|
|
257
|
+
>
|
|
258
|
+
{controls}
|
|
248
259
|
</div>
|
|
260
|
+
)}
|
|
249
261
|
|
|
250
|
-
|
|
251
|
-
|
|
262
|
+
{doc && activeTab === "docs" && (
|
|
263
|
+
<div
|
|
264
|
+
className={`max-h-[calc(100vh-200px)] space-y-6 overflow-y-auto p-5 ${
|
|
265
|
+
completo ? "it-panel-ancho max-w-[880px]" : ""
|
|
266
|
+
}`}
|
|
267
|
+
>
|
|
252
268
|
<div>
|
|
253
|
-
<
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
))}
|
|
269
|
+
<h2 className={EYEBROW}>{t("showcase.layout.overview")}</h2>
|
|
270
|
+
<p className="mt-2.5 text-[13px] leading-relaxed text-slate-700 dark:text-slate-300">
|
|
271
|
+
{doc.summary}
|
|
272
|
+
</p>
|
|
273
|
+
{doc.description && (
|
|
274
|
+
<p className="mt-2 text-[12px] leading-relaxed text-slate-500 dark:text-slate-400">
|
|
275
|
+
{doc.description}
|
|
276
|
+
</p>
|
|
277
|
+
)}
|
|
263
278
|
</div>
|
|
264
|
-
)}
|
|
265
279
|
|
|
266
|
-
{/* Notes */}
|
|
267
|
-
{doc.notes && doc.notes.length > 0 && (
|
|
268
280
|
<div>
|
|
269
|
-
<
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
<h2 className={EYEBROW}>{t("showcase.layout.props")}</h2>
|
|
282
|
+
<dl className={`mt-3 border-t ${FILETE}`}>
|
|
283
|
+
{doc.props.map((prop) => (
|
|
284
|
+
<div key={prop.name} className={`border-b py-3 ${FILETE}`}>
|
|
285
|
+
<dt className="flex flex-wrap items-baseline gap-x-2 font-mono text-[11px] font-semibold text-primary-700 dark:text-primary-500">
|
|
286
|
+
{prop.name}
|
|
287
|
+
{prop.required ? (
|
|
288
|
+
<span className="text-danger-500" title={t("showcase.common.required")}>
|
|
289
|
+
*
|
|
290
|
+
</span>
|
|
291
|
+
) : null}
|
|
292
|
+
<span className="font-mono text-[10px] font-normal text-slate-500 dark:text-slate-400">
|
|
293
|
+
{prop.type}
|
|
294
|
+
</span>
|
|
295
|
+
<span className="font-mono text-[10px] font-normal text-slate-500 dark:text-slate-400">
|
|
296
|
+
{`= ${prop.default || "—"}`}
|
|
297
|
+
</span>
|
|
298
|
+
</dt>
|
|
299
|
+
<dd className="mt-1.5 text-[12px] leading-relaxed text-slate-600 dark:text-slate-300">
|
|
300
|
+
{prop.description}
|
|
301
|
+
</dd>
|
|
302
|
+
</div>
|
|
278
303
|
))}
|
|
279
|
-
</
|
|
304
|
+
</dl>
|
|
280
305
|
</div>
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
306
|
+
|
|
307
|
+
{doc.examples && doc.examples.length > 0 && (
|
|
308
|
+
<div>
|
|
309
|
+
<h2 className={EYEBROW}>{t("showcase.layout.usageExamples")}</h2>
|
|
310
|
+
<div className="mt-3 space-y-2">
|
|
311
|
+
{doc.examples.map((example, i) => (
|
|
312
|
+
<pre
|
|
313
|
+
key={i}
|
|
314
|
+
className="overflow-x-auto rounded-[10px] border border-slate-800 bg-slate-950 p-3 font-mono text-[10px] leading-relaxed text-slate-200"
|
|
315
|
+
>
|
|
316
|
+
<code>{example}</code>
|
|
317
|
+
</pre>
|
|
318
|
+
))}
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
)}
|
|
322
|
+
|
|
323
|
+
{doc.notes && doc.notes.length > 0 && (
|
|
324
|
+
<div>
|
|
325
|
+
<h2 className={EYEBROW}>{t("showcase.layout.notes")}</h2>
|
|
326
|
+
<ul className={`mt-3 border-t ${FILETE}`}>
|
|
327
|
+
{doc.notes.map((note, i) => (
|
|
328
|
+
<li
|
|
329
|
+
key={i}
|
|
330
|
+
className={`border-b py-2.5 text-[12px] leading-relaxed text-slate-600 dark:text-slate-300 ${FILETE}`}
|
|
331
|
+
>
|
|
332
|
+
{note}
|
|
333
|
+
</li>
|
|
334
|
+
))}
|
|
335
|
+
</ul>
|
|
336
|
+
</div>
|
|
337
|
+
)}
|
|
338
|
+
</div>
|
|
339
|
+
)}
|
|
340
|
+
</section>
|
|
284
341
|
</div>
|
|
285
|
-
</
|
|
342
|
+
</ITGrid>
|
|
343
|
+
)}
|
|
286
344
|
</ITGrid>
|
|
287
|
-
</
|
|
345
|
+
</div>
|
|
288
346
|
|
|
289
|
-
{/*
|
|
347
|
+
{/* ─── GALERÍA ─── */}
|
|
290
348
|
{gallery && (
|
|
291
|
-
<
|
|
292
|
-
<
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
<div className="p-4">
|
|
296
|
-
{gallery}
|
|
297
|
-
</div>
|
|
298
|
-
</div>
|
|
349
|
+
<section className={`mt-12 border-t pt-8 ${FILETE}`} aria-label={t("showcase.layout.gallery")}>
|
|
350
|
+
<h2 className={EYEBROW}>{t("showcase.layout.gallery")}</h2>
|
|
351
|
+
<div className="mt-5">{gallery}</div>
|
|
352
|
+
</section>
|
|
299
353
|
)}
|
|
300
354
|
</div>
|
|
301
355
|
);
|