@doscientos/ui 0.1.15 → 0.1.17
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 +17 -0
- package/dist/index.cjs +124 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +35 -5
- package/dist/index.d.ts +35 -5
- package/dist/index.js +124 -55
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,11 +55,28 @@ El combobox es composable: la aplicación controla datos, peticiones y caché; l
|
|
|
55
55
|
## Desarrollo
|
|
56
56
|
|
|
57
57
|
- `pnpm test`: pruebas unitarias y de renderizado.
|
|
58
|
+
- `pnpm test:storybook`: renderizado, accesibilidad e interacciones de todas las stories en Chromium.
|
|
58
59
|
- `pnpm typecheck`: contrato TypeScript.
|
|
59
60
|
- `pnpm build`: distribución JS, tipos y CSS Tailwind compilado.
|
|
60
61
|
- `pnpm storybook`: catálogo local en el puerto 6006.
|
|
61
62
|
- `pnpm build-storybook`: sitio estático en `storybook-static/`, listo para publicar en `ui.doscientos.es`.
|
|
62
63
|
|
|
64
|
+
Storybook genera documentación automática para todo el catálogo y ofrece temas
|
|
65
|
+
claro/oscuro y viewports móvil, tablet y escritorio. Chromatic captura cada
|
|
66
|
+
story en claro escritorio, oscuro escritorio y claro móvil. Para activar el job
|
|
67
|
+
visual de CI, configura `CHROMATIC_PROJECT_TOKEN` como secreto del repositorio;
|
|
68
|
+
el valor se consume mediante el entorno y nunca se pasa como argumento del CLI.
|
|
69
|
+
|
|
70
|
+
### Criterio de stories
|
|
71
|
+
|
|
72
|
+
Cada componente público debe tener una story propia. Cuando apliquen, incluye
|
|
73
|
+
estado por defecto, variantes, disabled o read-only, error, carga o vacío,
|
|
74
|
+
contenido largo y viewport estrecho. Los controles interactivos deben añadir
|
|
75
|
+
un flujo `play` que cubra su comportamiento principal con teclado y foco.
|
|
76
|
+
|
|
77
|
+
Las stories deben usar datos ficticios y permanecer independientes de rutas,
|
|
78
|
+
APIs, autenticación y estado de producto.
|
|
79
|
+
|
|
63
80
|
## Criterio de crecimiento
|
|
64
81
|
|
|
65
82
|
Un componente entra cuando ya resuelve dos contextos reales o una necesidad transversal de accesibilidad. No se incorporan entidades de negocio, consultas, rutas ni variaciones visuales exclusivas de un cliente.
|
package/dist/index.cjs
CHANGED
|
@@ -364,6 +364,7 @@ function getTextMatchParts(text, query) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
// src/ui/accordion/accordion.tsx
|
|
367
|
+
var React = require("react");
|
|
367
368
|
var import_lucide_react = require("lucide-react");
|
|
368
369
|
var import_react_aria_components = require("react-aria-components");
|
|
369
370
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -372,7 +373,7 @@ function Accordion({ className, ...props }) {
|
|
|
372
373
|
import_react_aria_components.DisclosureGroup,
|
|
373
374
|
{
|
|
374
375
|
"data-slot": "accordion",
|
|
375
|
-
className: cn("flex w-full flex-col", className),
|
|
376
|
+
className: cn("flex w-full flex-col text-foreground", className),
|
|
376
377
|
...props
|
|
377
378
|
}
|
|
378
379
|
);
|
|
@@ -398,7 +399,7 @@ function AccordionTrigger({
|
|
|
398
399
|
slot: "trigger",
|
|
399
400
|
"data-slot": "accordion-trigger",
|
|
400
401
|
className: cn(
|
|
401
|
-
"group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-medium transition-
|
|
402
|
+
"group/accordion-trigger relative flex flex-1 items-start justify-between gap-3 rounded-lg border border-transparent px-2.5 py-2.5 text-left text-sm font-medium text-foreground transition-colors outline-none hover:bg-muted/50 aria-expanded:bg-muted/50 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
402
403
|
className
|
|
403
404
|
),
|
|
404
405
|
...props,
|
|
@@ -422,18 +423,22 @@ function AccordionTrigger({
|
|
|
422
423
|
}
|
|
423
424
|
) });
|
|
424
425
|
}
|
|
425
|
-
function AccordionContent({
|
|
426
|
+
function AccordionContent({
|
|
427
|
+
className,
|
|
428
|
+
children,
|
|
429
|
+
...props
|
|
430
|
+
}) {
|
|
426
431
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
427
432
|
import_react_aria_components.DisclosurePanel,
|
|
428
433
|
{
|
|
429
434
|
"data-slot": "accordion-content",
|
|
430
|
-
className: "h-(--disclosure-panel-height) overflow-clip text-sm transition-[height] data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
435
|
+
className: "h-(--disclosure-panel-height) overflow-clip text-sm text-muted-foreground transition-[height] data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
431
436
|
...props,
|
|
432
437
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
433
438
|
"div",
|
|
434
439
|
{
|
|
435
440
|
className: cn(
|
|
436
|
-
"pt-0 pb-
|
|
441
|
+
"px-2.5 pt-0 pb-3 [&_a]:text-foreground [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-primary [&_p:not(:last-child)]:mb-4",
|
|
437
442
|
className
|
|
438
443
|
),
|
|
439
444
|
children
|
|
@@ -1171,7 +1176,7 @@ function DrawerDescription({ className, ...props }) {
|
|
|
1171
1176
|
}
|
|
1172
1177
|
|
|
1173
1178
|
// src/ui/dropdown-menu/dropdown-menu.tsx
|
|
1174
|
-
var
|
|
1179
|
+
var React2 = require("react");
|
|
1175
1180
|
var import_class_variance_authority5 = require("class-variance-authority");
|
|
1176
1181
|
var import_lucide_react4 = require("lucide-react");
|
|
1177
1182
|
var import_react_aria_components11 = require("react-aria-components");
|
|
@@ -1674,7 +1679,7 @@ function FormRow({ label, htmlFor, required, hint, error, className, children })
|
|
|
1674
1679
|
var import_react_aria_components14 = require("react-aria-components");
|
|
1675
1680
|
|
|
1676
1681
|
// src/ui/tooltip/tooltip.tsx
|
|
1677
|
-
var
|
|
1682
|
+
var React3 = __toESM(require("react"), 1);
|
|
1678
1683
|
var import_react_aria_components13 = require("react-aria-components");
|
|
1679
1684
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1680
1685
|
function TooltipTrigger({
|
|
@@ -1682,7 +1687,7 @@ function TooltipTrigger({
|
|
|
1682
1687
|
children,
|
|
1683
1688
|
...props
|
|
1684
1689
|
}) {
|
|
1685
|
-
const [trigger, tooltip] =
|
|
1690
|
+
const [trigger, tooltip] = React3.Children.toArray(children);
|
|
1686
1691
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1687
1692
|
import_react_aria_components13.TooltipTrigger,
|
|
1688
1693
|
{
|
|
@@ -2586,59 +2591,124 @@ function SubmitButton({ pendingLabel = "Guardando\u2026", loading = false, child
|
|
|
2586
2591
|
}
|
|
2587
2592
|
|
|
2588
2593
|
// src/ui/switch/switch.tsx
|
|
2594
|
+
var import_react12 = require("react");
|
|
2589
2595
|
var import_react_aria_components25 = require("react-aria-components");
|
|
2590
2596
|
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2591
|
-
var
|
|
2592
|
-
sm: {
|
|
2593
|
-
|
|
2597
|
+
var switchSizes = {
|
|
2598
|
+
sm: {
|
|
2599
|
+
control: "h-4 w-[1.875rem] p-0.5",
|
|
2600
|
+
thumb: "h-3",
|
|
2601
|
+
idleWidth: "0.75rem",
|
|
2602
|
+
activeWidth: "1rem",
|
|
2603
|
+
selectedOffset: "0.875rem",
|
|
2604
|
+
activeSelectedOffset: "0.625rem"
|
|
2605
|
+
},
|
|
2606
|
+
md: {
|
|
2607
|
+
control: "h-5 w-9 p-0.5",
|
|
2608
|
+
thumb: "h-4",
|
|
2609
|
+
idleWidth: "1rem",
|
|
2610
|
+
activeWidth: "1.25rem",
|
|
2611
|
+
selectedOffset: "1rem",
|
|
2612
|
+
activeSelectedOffset: "0.75rem"
|
|
2613
|
+
},
|
|
2614
|
+
lg: {
|
|
2615
|
+
control: "h-6 w-11 p-0.5",
|
|
2616
|
+
thumb: "h-5",
|
|
2617
|
+
idleWidth: "1.25rem",
|
|
2618
|
+
activeWidth: "1.5rem",
|
|
2619
|
+
selectedOffset: "1.25rem",
|
|
2620
|
+
activeSelectedOffset: "1rem"
|
|
2621
|
+
}
|
|
2594
2622
|
};
|
|
2595
|
-
function Switch({
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2623
|
+
function Switch({
|
|
2624
|
+
className,
|
|
2625
|
+
children,
|
|
2626
|
+
description,
|
|
2627
|
+
icon,
|
|
2628
|
+
inputRef,
|
|
2629
|
+
isDisabled,
|
|
2630
|
+
isReadOnly,
|
|
2631
|
+
selectedIcon,
|
|
2632
|
+
size = "sm",
|
|
2633
|
+
...props
|
|
2634
|
+
}) {
|
|
2635
|
+
const styles = switchSizes[size];
|
|
2636
|
+
const fallbackInputRef = (0, import_react12.useRef)(null);
|
|
2637
|
+
const resolvedInputRef = inputRef ?? fallbackInputRef;
|
|
2638
|
+
(0, import_react12.useEffect)(() => {
|
|
2639
|
+
const input = resolvedInputRef.current;
|
|
2640
|
+
if (!input) return;
|
|
2641
|
+
const handleDirectionalKey = (event) => {
|
|
2642
|
+
if (event.target !== input || event.defaultPrevented || isDisabled || isReadOnly || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
|
|
2643
|
+
const nextSelected = event.key === "ArrowRight" ? true : event.key === "ArrowLeft" ? false : null;
|
|
2644
|
+
if (nextSelected === null) return;
|
|
2645
|
+
event.preventDefault();
|
|
2646
|
+
if (input.checked !== nextSelected) input.click();
|
|
2647
|
+
};
|
|
2648
|
+
const ownerDocument = input.ownerDocument;
|
|
2649
|
+
ownerDocument.addEventListener("keydown", handleDirectionalKey);
|
|
2650
|
+
return () => ownerDocument.removeEventListener("keydown", handleDirectionalKey);
|
|
2651
|
+
}, [isDisabled, isReadOnly, resolvedInputRef]);
|
|
2652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2653
|
+
import_react_aria_components25.Switch,
|
|
2599
2654
|
{
|
|
2600
2655
|
"data-slot": "switch",
|
|
2601
2656
|
"data-size": size,
|
|
2602
|
-
|
|
2603
|
-
|
|
2657
|
+
inputRef: resolvedInputRef,
|
|
2658
|
+
isDisabled,
|
|
2659
|
+
isReadOnly,
|
|
2660
|
+
className: cn(
|
|
2661
|
+
"group/switch inline-flex cursor-pointer items-center gap-3 text-sm text-foreground outline-none select-none",
|
|
2604
2662
|
"data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
2605
|
-
|
|
2663
|
+
className
|
|
2606
2664
|
),
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
"
|
|
2616
|
-
"
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
"
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2665
|
+
...props,
|
|
2666
|
+
children: (state) => {
|
|
2667
|
+
const isThumbActive = state.isHovered || state.isPressed;
|
|
2668
|
+
const thumbOffset = state.isSelected ? isThumbActive ? styles.activeSelectedOffset : styles.selectedOffset : "0";
|
|
2669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
2670
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2671
|
+
"span",
|
|
2672
|
+
{
|
|
2673
|
+
"aria-hidden": "true",
|
|
2674
|
+
"data-slot": "switch-control",
|
|
2675
|
+
className: cn(
|
|
2676
|
+
"relative inline-flex shrink-0 items-center overflow-hidden rounded-full border border-border bg-input shadow-inner",
|
|
2677
|
+
"transition-[background-color,border-color,box-shadow] duration-200 ease-out motion-reduce:transition-none",
|
|
2678
|
+
"group-data-hovered/switch:bg-muted-foreground/25",
|
|
2679
|
+
"group-data-selected/switch:border-primary group-data-selected/switch:bg-primary",
|
|
2680
|
+
"group-data-selected/switch:group-data-hovered/switch:bg-primary/85",
|
|
2681
|
+
"group-data-focus-visible/switch:ring-3 group-data-focus-visible/switch:ring-ring/50",
|
|
2682
|
+
styles.control
|
|
2683
|
+
),
|
|
2684
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2685
|
+
"span",
|
|
2686
|
+
{
|
|
2687
|
+
"data-slot": "switch-thumb",
|
|
2688
|
+
style: {
|
|
2689
|
+
transform: `translate3d(${thumbOffset}, 0, 0)`,
|
|
2690
|
+
width: isThumbActive ? styles.activeWidth : styles.idleWidth
|
|
2691
|
+
},
|
|
2692
|
+
className: cn(
|
|
2693
|
+
"grid shrink-0 place-items-center rounded-full border border-border/60 bg-background text-[0.625rem] text-muted-foreground shadow-sm",
|
|
2694
|
+
"will-change-[transform,width] transition-[transform,width,background-color,color,border-color] duration-[240ms] ease-[cubic-bezier(0.2,0.8,0.2,1)] motion-reduce:transition-none",
|
|
2695
|
+
"group-data-selected/switch:border-primary-foreground/20",
|
|
2696
|
+
"group-data-selected/switch:bg-primary-foreground group-data-selected/switch:text-primary",
|
|
2697
|
+
styles.thumb
|
|
2698
|
+
),
|
|
2699
|
+
children: state.isSelected ? selectedIcon ?? icon : icon
|
|
2700
|
+
}
|
|
2701
|
+
)
|
|
2702
|
+
}
|
|
2703
|
+
),
|
|
2704
|
+
children || description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "grid gap-0.5 leading-tight", children: [
|
|
2705
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { "data-slot": "switch-label", className: "font-medium", children: typeof children === "function" ? children(state) : children }) : null,
|
|
2706
|
+
description ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { "data-slot": "switch-description", className: "text-xs font-normal text-muted-foreground", children: description }) : null
|
|
2707
|
+
] }) : null
|
|
2708
|
+
] });
|
|
2709
|
+
}
|
|
2640
2710
|
}
|
|
2641
|
-
)
|
|
2711
|
+
);
|
|
2642
2712
|
}
|
|
2643
2713
|
|
|
2644
2714
|
// src/ui/table/table.tsx
|
|
@@ -2743,7 +2813,7 @@ function TabsContent({ className, ...props }) {
|
|
|
2743
2813
|
}
|
|
2744
2814
|
|
|
2745
2815
|
// src/ui/toast/toast.tsx
|
|
2746
|
-
var
|
|
2816
|
+
var import_react13 = require("react");
|
|
2747
2817
|
var import_sileo = require("sileo");
|
|
2748
2818
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2749
2819
|
function toSileoOptions({ title, description, duration, position, action }) {
|
|
@@ -2798,7 +2868,7 @@ function ToastViewport({ position, visiblePosition, className }) {
|
|
|
2798
2868
|
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Toaster, { position });
|
|
2799
2869
|
}
|
|
2800
2870
|
function Toast({ id, title, description, variant = "default", action, state = "open", duration = 0, position, onDismiss }) {
|
|
2801
|
-
(0,
|
|
2871
|
+
(0, import_react13.useEffect)(() => {
|
|
2802
2872
|
if (state !== "open") return;
|
|
2803
2873
|
const toastId = create({ title, description, variant, action, duration, position });
|
|
2804
2874
|
return () => {
|