orbital-ds 0.9.0 → 0.10.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.
Files changed (73) hide show
  1. package/AGENTS.md +18 -1
  2. package/components.manifest.json +388 -1
  3. package/contract.json +5 -0
  4. package/dist/hooks/use-ds-messages.d.ts +59 -1
  5. package/dist/hooks/use-ds-messages.js +6 -0
  6. package/dist/lib/echarts-presets.d.ts +153 -0
  7. package/dist/lib/echarts-presets.js +311 -0
  8. package/dist/lib/echarts-server.d.ts +15 -0
  9. package/dist/lib/echarts-server.js +15 -0
  10. package/dist/lib/echarts-setup.d.ts +4 -0
  11. package/dist/lib/echarts-setup.js +60 -0
  12. package/dist/lib/echarts-theme.d.ts +36 -0
  13. package/dist/lib/echarts-theme.js +142 -0
  14. package/dist/lib/i18n.d.ts +57 -1
  15. package/dist/lib/i18n.js +169 -3
  16. package/dist/styles.css +43 -5
  17. package/dist/themes/friendly.css +3 -1
  18. package/dist/themes/friendly.scoped.css +3 -1
  19. package/dist/themes/friendly.tokens.json +45 -0
  20. package/dist/themes/qratia.tokens.json +49 -0
  21. package/dist/themes/tactile.css +3 -1
  22. package/dist/themes/tactile.scoped.css +3 -1
  23. package/dist/themes/tactile.tokens.json +42 -0
  24. package/dist/themes/twitter.css +3 -1
  25. package/dist/themes/twitter.scoped.css +3 -1
  26. package/dist/themes/twitter.tokens.json +45 -0
  27. package/dist/themes/zyro.css +3 -1
  28. package/dist/themes/zyro.scoped.css +3 -1
  29. package/dist/themes/zyro.tokens.json +46 -0
  30. package/dist/ui/calendar.js +4 -0
  31. package/dist/ui/code-block.d.ts +14 -0
  32. package/dist/ui/code-block.js +106 -0
  33. package/dist/ui/data-table.d.ts +185 -0
  34. package/dist/ui/data-table.js +714 -0
  35. package/dist/ui/date-picker.d.ts +65 -0
  36. package/dist/ui/date-picker.js +362 -0
  37. package/dist/ui/dropzone.d.ts +42 -0
  38. package/dist/ui/dropzone.js +220 -0
  39. package/dist/ui/echart.d.ts +31 -0
  40. package/dist/ui/echart.js +88 -0
  41. package/dist/ui/eyebrow.d.ts +7 -0
  42. package/dist/ui/eyebrow.js +16 -0
  43. package/dist/ui/filter-bar.d.ts +36 -0
  44. package/dist/ui/filter-bar.js +193 -0
  45. package/dist/ui/heatmap-grid.d.ts +39 -0
  46. package/dist/ui/heatmap-grid.js +195 -0
  47. package/dist/ui/i18n-provider.js +3 -3
  48. package/dist/ui/legend.d.ts +30 -0
  49. package/dist/ui/legend.js +124 -0
  50. package/dist/ui/notifications.d.ts +69 -0
  51. package/dist/ui/notifications.js +335 -0
  52. package/dist/ui/page-header.d.ts +19 -0
  53. package/dist/ui/page-header.js +132 -0
  54. package/dist/ui/panel.d.ts +12 -0
  55. package/dist/ui/panel.js +41 -0
  56. package/dist/ui/proportion-bar.d.ts +27 -0
  57. package/dist/ui/proportion-bar.js +92 -0
  58. package/dist/ui/sparkline.d.ts +26 -0
  59. package/dist/ui/sparkline.js +97 -0
  60. package/dist/ui/stat.d.ts +61 -0
  61. package/dist/ui/stat.js +238 -0
  62. package/dist/ui/status-badge.d.ts +38 -0
  63. package/dist/ui/status-badge.js +153 -0
  64. package/dist/ui/stepper.d.ts +20 -0
  65. package/dist/ui/stepper.js +152 -0
  66. package/dist/ui/timeline.d.ts +29 -0
  67. package/dist/ui/timeline.js +157 -0
  68. package/docs/GRAFICOS.md +125 -0
  69. package/docs/adr/0001-rtl-clases-logicas.md +78 -0
  70. package/package.json +171 -160
  71. package/scripts/doctor.mjs +0 -0
  72. package/scripts/i18n.mjs +0 -0
  73. package/scripts/init.mjs +1 -0
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "tactile",
3
+ "light": {
4
+ "palette": [
5
+ "#f2b33d",
6
+ "#17624f",
7
+ "#2f6fb0",
8
+ "#b53a22",
9
+ "#8b5a9e",
10
+ "#2a649e",
11
+ "#7a5200",
12
+ "#ae3821"
13
+ ],
14
+ "foreground": "#2a2233",
15
+ "muted": "rgba(42, 34, 51, 0.7)",
16
+ "border": "rgba(42, 34, 51, 0.14)",
17
+ "surface": "#fffcf4",
18
+ "surfaceForeground": "#2a2233",
19
+ "fontSans": "'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
20
+ "fontDisplay": "'Fraunces', Georgia, 'Times New Roman', serif",
21
+ "motionBaseMs": 160,
22
+ "motionSlowMs": 240
23
+ },
24
+ "dark": {
25
+ "palette": [
26
+ "#f2b33d",
27
+ "#5cc9a8",
28
+ "#7db3f0",
29
+ "#ff8266",
30
+ "#c79ad8"
31
+ ],
32
+ "foreground": "#f4ebda",
33
+ "muted": "rgba(244, 235, 218, 0.72)",
34
+ "border": "rgba(244, 235, 218, 0.14)",
35
+ "surface": "#2c2636",
36
+ "surfaceForeground": "#f4ebda",
37
+ "fontSans": "'Figtree', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif",
38
+ "fontDisplay": "'Fraunces', Georgia, 'Times New Roman', serif",
39
+ "motionBaseMs": 160,
40
+ "motionSlowMs": 240
41
+ }
42
+ }
@@ -266,7 +266,9 @@
266
266
  }
267
267
 
268
268
  /* Tarjetas: planas, con filete, sin elevación */
269
- [data-slot='card'] {
269
+ [data-slot='card'],
270
+ [data-slot='panel']:is([data-variant='default'], [data-variant='outline']),
271
+ [data-slot='stat'][data-variant='card'] {
270
272
  border: var(--ds-rule-w) solid var(--border);
271
273
  box-shadow: none;
272
274
  }
@@ -266,7 +266,9 @@
266
266
  }
267
267
 
268
268
  /* Tarjetas: planas, con filete, sin elevación */
269
- [data-slot='card'] {
269
+ [data-slot='card'],
270
+ [data-slot='panel']:is([data-variant='default'], [data-variant='outline']),
271
+ [data-slot='stat'][data-variant='card'] {
270
272
  border: var(--ds-rule-w) solid var(--border);
271
273
  box-shadow: none;
272
274
  }
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "twitter",
3
+ "light": {
4
+ "palette": [
5
+ "#1d9bf0",
6
+ "#00ba7c",
7
+ "#ffd400",
8
+ "#f91880",
9
+ "#7856ff",
10
+ "#1573b1",
11
+ "#007c53",
12
+ "#8a6d00",
13
+ "#d4141f"
14
+ ],
15
+ "foreground": "#0f1419",
16
+ "muted": "#536471",
17
+ "border": "#eff3f4",
18
+ "surface": "#ffffff",
19
+ "surfaceForeground": "#0f1419",
20
+ "fontSans": "'Chirp', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
21
+ "fontDisplay": "'Chirp', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
22
+ "motionBaseMs": 200,
23
+ "motionSlowMs": 300
24
+ },
25
+ "dark": {
26
+ "palette": [
27
+ "#1d9bf0",
28
+ "#00ba7c",
29
+ "#ffd400",
30
+ "#f91880",
31
+ "#7856ff",
32
+ "#4db3f5",
33
+ "#ff5a64"
34
+ ],
35
+ "foreground": "#f7f9f9",
36
+ "muted": "#8b98a5",
37
+ "border": "#38444d",
38
+ "surface": "#1e2732",
39
+ "surfaceForeground": "#f7f9f9",
40
+ "fontSans": "'Chirp', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
41
+ "fontDisplay": "'Chirp', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif",
42
+ "motionBaseMs": 200,
43
+ "motionSlowMs": 300
44
+ }
45
+ }
@@ -323,7 +323,9 @@
323
323
  }
324
324
 
325
325
  /* Tarjetas: contenido casi opaco con filo superior luminoso */
326
- [data-slot='card'] {
326
+ [data-slot='card'],
327
+ [data-slot='panel'][data-variant='default'],
328
+ [data-slot='stat'][data-variant='card'] {
327
329
  border: var(--ds-rule-w) solid var(--zy-card-bs);
328
330
  border-top-color: var(--zy-card-bt);
329
331
  }
@@ -323,7 +323,9 @@
323
323
  }
324
324
 
325
325
  /* Tarjetas: contenido casi opaco con filo superior luminoso */
326
- [data-slot='card'] {
326
+ [data-slot='card'],
327
+ [data-slot='panel'][data-variant='default'],
328
+ [data-slot='stat'][data-variant='card'] {
327
329
  border: var(--ds-rule-w) solid var(--zy-card-bs);
328
330
  border-top-color: var(--zy-card-bt);
329
331
  }
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "zyro",
3
+ "light": {
4
+ "palette": [
5
+ "#0349fe",
6
+ "#14bd44",
7
+ "#ffb300",
8
+ "#eb1919",
9
+ "#9747ff",
10
+ "#1267a1",
11
+ "#0b742a",
12
+ "#845f00",
13
+ "#c21414"
14
+ ],
15
+ "foreground": "rgba(14, 22, 48, 0.92)",
16
+ "muted": "rgba(14, 22, 48, 0.66)",
17
+ "border": "rgba(168, 190, 235, 0.3)",
18
+ "surface": "#ffffff",
19
+ "surfaceForeground": "rgba(14, 22, 48, 0.92)",
20
+ "fontSans": "'Roboto', system-ui, -apple-system, sans-serif",
21
+ "fontDisplay": "'Montserrat', system-ui, -apple-system, sans-serif",
22
+ "motionBaseMs": 200,
23
+ "motionSlowMs": 300
24
+ },
25
+ "dark": {
26
+ "palette": [
27
+ "#36b3ed",
28
+ "#14bd44",
29
+ "#ffb300",
30
+ "#eb1919",
31
+ "#9747ff",
32
+ "#70b7e3",
33
+ "#3cc864",
34
+ "#ff6b6b"
35
+ ],
36
+ "foreground": "rgba(255, 255, 255, 0.94)",
37
+ "muted": "rgba(255, 255, 255, 0.68)",
38
+ "border": "rgba(255, 255, 255, 0.07)",
39
+ "surface": "rgba(22, 32, 68, 0.97)",
40
+ "surfaceForeground": "rgba(255, 255, 255, 0.94)",
41
+ "fontSans": "'Roboto', system-ui, -apple-system, sans-serif",
42
+ "fontDisplay": "'Montserrat', system-ui, -apple-system, sans-serif",
43
+ "motionBaseMs": 200,
44
+ "motionSlowMs": 300
45
+ }
46
+ }
@@ -7,6 +7,7 @@ import {
7
7
  getDefaultClassNames
8
8
  } from "react-day-picker";
9
9
  import { Button, buttonVariants } from "./button";
10
+ import { useDsMessages } from "../hooks/use-ds-messages";
10
11
  import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react";
11
12
  function Calendar({
12
13
  className,
@@ -20,6 +21,7 @@ function Calendar({
20
21
  ...props
21
22
  }) {
22
23
  const defaultClassNames = getDefaultClassNames();
24
+ const t = useDsMessages();
23
25
  return /* @__PURE__ */ jsx(
24
26
  DayPicker,
25
27
  {
@@ -32,6 +34,7 @@ function Calendar({
32
34
  ),
33
35
  captionLayout,
34
36
  locale,
37
+ labels: { labelPrevious: () => t.calendarPrevious, labelNext: () => t.calendarNext, ...props.labels },
35
38
  formatters: {
36
39
  formatMonthDropdown: (date) => date.toLocaleString(locale?.code, { month: "short" }),
37
40
  ...formatters
@@ -188,6 +191,7 @@ function CalendarDayButton({
188
191
  ...props
189
192
  }) {
190
193
  const defaultClassNames = getDefaultClassNames();
194
+ const t = useDsMessages();
191
195
  const ref = React.useRef(null);
192
196
  React.useEffect(() => {
193
197
  if (modifiers.focused) ref.current?.focus();
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+
3
+ declare function CodeBlock({ code, html, language, title, showLineNumbers, copyable, className, ...props }: Omit<React.ComponentProps<"div">, "title"> & {
4
+ code: string;
5
+ html?: string;
6
+ language?: string;
7
+ title?: React.ReactNode;
8
+ showLineNumbers?: boolean;
9
+ copyable?: boolean;
10
+ }): React.JSX.Element;
11
+ /** Código en línea, dentro de un texto. */
12
+ declare function Code({ className, ...props }: React.ComponentProps<"code">): React.JSX.Element;
13
+
14
+ export { Code, CodeBlock };
@@ -0,0 +1,106 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { CheckIcon, CopyIcon } from "lucide-react";
5
+ import { useDsMessages } from "../hooks/use-ds-messages";
6
+ import { cn } from "../lib/utils";
7
+ import { Button } from "./button";
8
+ function CodeBlock({
9
+ code,
10
+ html,
11
+ language,
12
+ title,
13
+ showLineNumbers = false,
14
+ copyable = true,
15
+ className,
16
+ ...props
17
+ }) {
18
+ const t = useDsMessages();
19
+ const [copied, setCopied] = React.useState(false);
20
+ React.useEffect(() => {
21
+ if (!copied) return;
22
+ const id = window.setTimeout(() => setCopied(false), 2e3);
23
+ return () => window.clearTimeout(id);
24
+ }, [copied]);
25
+ const copy = async () => {
26
+ try {
27
+ await navigator.clipboard.writeText(code);
28
+ setCopied(true);
29
+ } catch {
30
+ }
31
+ };
32
+ const lines = code.replace(/\n$/, "").split("\n");
33
+ const header = title || language;
34
+ return /* @__PURE__ */ jsxs(
35
+ "div",
36
+ {
37
+ "data-slot": "code-block",
38
+ "data-language": language,
39
+ className: cn(
40
+ "group/code-block relative min-w-0 overflow-hidden rounded-code border border-border bg-(--ds-code-bg) text-(--ds-code-fg)",
41
+ className
42
+ ),
43
+ ...props,
44
+ children: [
45
+ header && /* @__PURE__ */ jsxs(
46
+ "div",
47
+ {
48
+ "data-slot": "code-block-header",
49
+ className: "flex items-center gap-2 border-b border-border ps-(--ds-code-p) pe-2 py-1 text-xs text-(--ds-code-muted)",
50
+ children: [
51
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-mono", children: title ?? language }),
52
+ title && language && /* @__PURE__ */ jsx("span", { className: "font-mono uppercase", children: language }),
53
+ copyable && /* @__PURE__ */ jsx(CopyButton, { copied, onCopy: copy, label: copied ? t.codeCopied : t.codeCopy })
54
+ ]
55
+ }
56
+ ),
57
+ !header && copyable && /* @__PURE__ */ jsx("div", { className: "absolute end-2 top-2 opacity-0 transition-opacity duration-(--ds-motion-snap) group-hover/code-block:opacity-100 group-focus-within/code-block:opacity-100", children: /* @__PURE__ */ jsx(CopyButton, { copied, onCopy: copy, label: copied ? t.codeCopied : t.codeCopy }) }),
58
+ /* @__PURE__ */ jsx(
59
+ "pre",
60
+ {
61
+ "data-slot": "code-block-pre",
62
+ dir: "ltr",
63
+ className: "overflow-x-auto p-(--ds-code-p) font-mono text-xs leading-relaxed",
64
+ children: html ? /* @__PURE__ */ jsx("code", { "data-slot": "code-block-code", dangerouslySetInnerHTML: { __html: html } }) : showLineNumbers ? /* @__PURE__ */ jsx("code", { "data-slot": "code-block-code", className: "table", children: lines.map((line, i) => /* @__PURE__ */ jsxs("span", { "data-slot": "code-block-line", className: "table-row", children: [
65
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "table-cell pe-4 text-end text-(--ds-code-muted) select-none", children: i + 1 }),
66
+ /* @__PURE__ */ jsx("span", { className: "table-cell whitespace-pre", children: line || " " })
67
+ ] }, i)) }) : /* @__PURE__ */ jsx("code", { "data-slot": "code-block-code", children: code })
68
+ }
69
+ ),
70
+ /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? t.codeCopied : null })
71
+ ]
72
+ }
73
+ );
74
+ }
75
+ function CopyButton({ copied, onCopy, label }) {
76
+ return /* @__PURE__ */ jsx(
77
+ Button,
78
+ {
79
+ "data-slot": "code-block-copy",
80
+ type: "button",
81
+ variant: "ghost",
82
+ size: "icon-xs",
83
+ "aria-label": label,
84
+ title: label,
85
+ onClick: onCopy,
86
+ children: copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {})
87
+ }
88
+ );
89
+ }
90
+ function Code({ className, ...props }) {
91
+ return /* @__PURE__ */ jsx(
92
+ "code",
93
+ {
94
+ "data-slot": "code",
95
+ className: cn(
96
+ "rounded-sm bg-(--ds-code-bg) px-(--ds-code-inline-px) py-0.5 font-mono text-(length:--ds-code-inline-size) text-(--ds-code-fg)",
97
+ className
98
+ ),
99
+ ...props
100
+ }
101
+ );
102
+ }
103
+ export {
104
+ Code,
105
+ CodeBlock
106
+ };
@@ -0,0 +1,185 @@
1
+ import * as _tanstack_react_table from '@tanstack/react-table';
2
+ import { ColumnDef, SortingState, ColumnFiltersState, ColumnVisibilityState, RowSelectionState } from '@tanstack/react-table';
3
+ import * as React from 'react';
4
+ import { DsDataTone } from './legend.js';
5
+
6
+ /** Opción de un filtro `select`. */
7
+ interface DataTableFilterOption {
8
+ value: string;
9
+ label: React.ReactNode;
10
+ }
11
+ /** `columnDef.meta` de una columna de DataTable. */
12
+ interface DataTableColumnMeta {
13
+ /** Alineación lógica de cabecera y celdas (por defecto `start`; `end` si es numérica). */
14
+ align?: "start" | "end" | "center";
15
+ /** Cifra: tabular-nums, alineada al final, formato Intl del idioma activo; null → «—». */
16
+ numeric?: boolean;
17
+ /** Opciones de Intl.NumberFormat para las columnas numéricas. */
18
+ format?: Intl.NumberFormatOptions;
19
+ /** Filtro propio de la columna en la barra de herramientas. */
20
+ filter?: "text" | "select";
21
+ /** Opciones del filtro `select`. */
22
+ filterOptions?: DataTableFilterOption[];
23
+ /** Nombre de la columna (menú de columnas, filtros) cuando la cabecera no es texto. */
24
+ label?: string;
25
+ /** Clases extra para la cabecera y las celdas de la columna. */
26
+ className?: string;
27
+ }
28
+ /**
29
+ * Lo que sabe hacer la tabla. TanStack Table 9 registra las features de forma
30
+ * explícita (lo que no está aquí no entra en el bundle ni en los tipos). Los
31
+ * modelos de filas van detrás de su feature. La paginación la hace DataTable
32
+ * (recorta una página fuera de rango en vez de mostrar una tabla vacía), por
33
+ * eso no registra `rowPaginationFeature`.
34
+ */
35
+ declare const dataTableFeatures: {
36
+ rowSortingFeature: _tanstack_react_table.TableFeature;
37
+ columnFilteringFeature: _tanstack_react_table.TableFeature;
38
+ globalFilteringFeature: _tanstack_react_table.TableFeature;
39
+ columnVisibilityFeature: _tanstack_react_table.TableFeature;
40
+ rowSelectionFeature: _tanstack_react_table.TableFeature;
41
+ sortedRowModel: (table: _tanstack_react_table.Table<any, any>) => () => _tanstack_react_table.RowModel<any, any>;
42
+ filteredRowModel: (table: _tanstack_react_table.Table<any, any>) => () => _tanstack_react_table.RowModel<any, any>;
43
+ filterFns: {
44
+ includesString: _tanstack_react_table.CreatedFilterFn<any, any>;
45
+ equalsString: _tanstack_react_table.CreatedFilterFn<any, any>;
46
+ };
47
+ sortFns: {
48
+ alphanumeric: _tanstack_react_table.CreatedSortFn<any, any>;
49
+ text: _tanstack_react_table.CreatedSortFn<any, any>;
50
+ basic: _tanstack_react_table.CreatedSortFn<any, any>;
51
+ datetime: _tanstack_react_table.CreatedSortFn<any, any>;
52
+ number: _tanstack_react_table.CreatedSortFn<any, any>;
53
+ };
54
+ columnMeta: DataTableColumnMeta;
55
+ };
56
+ type DataTableFeatures = typeof dataTableFeatures;
57
+ /** Columna de DataTable: así la declaran las pantallas. */
58
+ type DataTableColumn<TData extends object> = ColumnDef<DataTableFeatures, TData, unknown>;
59
+ /** Ayudante tipado para declarar columnas (`helper.accessor("calls", {…})`). */
60
+ declare function createDataTableColumnHelper<TData extends object>(): _tanstack_react_table.ColumnHelper<{
61
+ rowSortingFeature: _tanstack_react_table.TableFeature;
62
+ columnFilteringFeature: _tanstack_react_table.TableFeature;
63
+ globalFilteringFeature: _tanstack_react_table.TableFeature;
64
+ columnVisibilityFeature: _tanstack_react_table.TableFeature;
65
+ rowSelectionFeature: _tanstack_react_table.TableFeature;
66
+ sortedRowModel: (table: _tanstack_react_table.Table<any, any>) => () => _tanstack_react_table.RowModel<any, any>;
67
+ filteredRowModel: (table: _tanstack_react_table.Table<any, any>) => () => _tanstack_react_table.RowModel<any, any>;
68
+ filterFns: {
69
+ includesString: _tanstack_react_table.CreatedFilterFn<any, any>;
70
+ equalsString: _tanstack_react_table.CreatedFilterFn<any, any>;
71
+ };
72
+ sortFns: {
73
+ alphanumeric: _tanstack_react_table.CreatedSortFn<any, any>;
74
+ text: _tanstack_react_table.CreatedSortFn<any, any>;
75
+ basic: _tanstack_react_table.CreatedSortFn<any, any>;
76
+ datetime: _tanstack_react_table.CreatedSortFn<any, any>;
77
+ number: _tanstack_react_table.CreatedSortFn<any, any>;
78
+ };
79
+ columnMeta: DataTableColumnMeta;
80
+ }, TData>;
81
+ /** Estado completo de la tabla (controlable con `state` / `onStateChange`). */
82
+ interface DataTableState {
83
+ /** Búsqueda global. */
84
+ search: string;
85
+ /** Orden (`[{ id, desc }]`, varias columnas con Mayús). */
86
+ sorting: SortingState;
87
+ /** Página, desde 1. */
88
+ page: number;
89
+ pageSize: number;
90
+ columnFilters: ColumnFiltersState;
91
+ columnVisibility: ColumnVisibilityState;
92
+ rowSelection: RowSelectionState;
93
+ }
94
+ declare const DATA_TABLE_PAGE_SIZES: readonly [10, 20, 50, 100];
95
+ /**
96
+ * Estado de la tabla en search params. Lo que está en su valor por defecto no
97
+ * se escribe (URL limpia). La selección de filas no viaja: es efímera.
98
+ *
99
+ * - `q`: búsqueda · `sort`: `col` asc, `-col` desc, varias separadas por comas
100
+ * - `page` (desde 1) · `size`: filas por página
101
+ * - `hide`: columnas ocultas separadas por comas
102
+ * - `f.<columna>`: valor del filtro de esa columna
103
+ */
104
+ type DataTableSearch = {
105
+ q?: string;
106
+ sort?: string;
107
+ page?: number;
108
+ size?: number;
109
+ hide?: string;
110
+ } & {
111
+ [filter: `f.${string}`]: string | undefined;
112
+ };
113
+ /**
114
+ * `validateSearch` para rutas con tabla: se queda solo con los valores válidos.
115
+ * El router puede convertir `?q=123` en número: se pasa a texto. Sin recortar
116
+ * la búsqueda (se valida en cada pulsación y se comería el espacio recién
117
+ * escrito); solo se descarta si está vacía.
118
+ */
119
+ declare function validateDataTableSearch(search: Record<string, unknown>, options?: {
120
+ pageSizes?: readonly number[];
121
+ }): DataTableSearch;
122
+ /** Search params (validados aquí) → estado parcial para `state`. */
123
+ declare function dataTableStateFromSearch(search: Record<string, unknown>, options?: {
124
+ pageSizes?: readonly number[];
125
+ }): Partial<DataTableState>;
126
+ /** Estado → search params limpios (sin valores por defecto ni selección). */
127
+ declare function dataTableStateToSearch(state: Partial<DataTableState>, options?: {
128
+ pageSizes?: readonly number[];
129
+ }): DataTableSearch;
130
+ /** Cifra con el formato Intl del idioma activo; null/undefined/NaN → «—». */
131
+ declare function DataTableNumber({ value, format, className, }: {
132
+ value: number | null | undefined;
133
+ format?: Intl.NumberFormatOptions;
134
+ className?: string;
135
+ }): React.JSX.Element;
136
+ /**
137
+ * Celda de ranking: la cifra y una ProportionBar con su proporción sobre `max`
138
+ * (p. ej. el mayor valor de la columna). null → «—» y barra rayada de «sin
139
+ * dato», nunca una barra a 0. La barra es decorativa (aria-hidden): la cifra
140
+ * ya da el valor al lector de pantalla.
141
+ */
142
+ declare function DataTableBarCell({ value, max, format, tone, className, }: {
143
+ value: number | null | undefined;
144
+ max: number;
145
+ format?: Intl.NumberFormatOptions;
146
+ tone?: DsDataTone;
147
+ className?: string;
148
+ }): React.JSX.Element;
149
+ interface DataTableProps<TData extends object> {
150
+ columns: DataTableColumn<TData>[];
151
+ data: TData[];
152
+ /** Id estable de cada fila (selección que sobrevive a ordenar y filtrar). Por defecto, el índice. */
153
+ getRowId?: (row: TData, index: number) => string;
154
+ /** Estado controlado (todo o parte). */
155
+ state?: Partial<DataTableState>;
156
+ /** Cada cambio de estado, completo. Buscar, ordenar o filtrar vuelve a la página 1. */
157
+ onStateChange?: (state: DataTableState) => void;
158
+ /** Estado inicial cuando no se controla. */
159
+ defaultState?: Partial<DataTableState>;
160
+ /** Buscador global (por defecto, sí). */
161
+ searchable?: boolean;
162
+ /** Casillas de selección de filas. */
163
+ selectable?: boolean;
164
+ /** Menú de columnas visibles (por defecto, sí). */
165
+ columnToggle?: boolean;
166
+ /** Opciones de filas por página. */
167
+ pageSizes?: readonly number[];
168
+ /** Mientras carga se pintan filas skeleton y la tabla queda aria-busy. */
169
+ loading?: boolean;
170
+ /** Qué pintar si no hay filas (por defecto, Empty con «Sin resultados»). */
171
+ empty?: React.ReactNode;
172
+ /** Fila pulsable (ratón, Enter o Espacio). */
173
+ onRowClick?: (row: TData) => void;
174
+ /** Hueco de la barra de herramientas para acciones de la pantalla. */
175
+ toolbar?: React.ReactNode;
176
+ /** Acciones al final de cada fila (botón, menú…). */
177
+ rowActions?: (row: TData) => React.ReactNode;
178
+ density?: "comfortable" | "compact";
179
+ /** Nombre accesible de la tabla. */
180
+ "aria-label"?: string;
181
+ className?: string;
182
+ }
183
+ declare function DataTable<TData extends object>({ columns, data, getRowId, state: controlled, onStateChange, defaultState, searchable, selectable, columnToggle, pageSizes, loading, empty, onRowClick, toolbar, rowActions, density, "aria-label": ariaLabel, className, }: DataTableProps<TData>): React.JSX.Element;
184
+
185
+ export { DATA_TABLE_PAGE_SIZES, DataTable, DataTableBarCell, type DataTableColumn, type DataTableColumnMeta, type DataTableFeatures, type DataTableFilterOption, DataTableNumber, type DataTableProps, type DataTableSearch, type DataTableState, createDataTableColumnHelper, dataTableFeatures, dataTableStateFromSearch, dataTableStateToSearch, validateDataTableSearch };