danielgm-ui 0.1.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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +372 -0
  3. package/TABLER-LICENSE.txt +21 -0
  4. package/dist/accordion.d.ts +49 -0
  5. package/dist/accordion.js +14 -0
  6. package/dist/aspect-ratio.d.ts +8 -0
  7. package/dist/aspect-ratio.js +8 -0
  8. package/dist/avatar.d.ts +27 -0
  9. package/dist/avatar.js +15 -0
  10. package/dist/breadcrumbs.d.ts +20 -0
  11. package/dist/breadcrumbs.js +5 -0
  12. package/dist/button.d.ts +44 -0
  13. package/dist/button.js +25 -0
  14. package/dist/carousel.d.ts +19 -0
  15. package/dist/carousel.js +133 -0
  16. package/dist/choice-group.d.ts +36 -0
  17. package/dist/choice-group.js +27 -0
  18. package/dist/combobox.d.ts +37 -0
  19. package/dist/combobox.js +57 -0
  20. package/dist/command-palette.d.ts +28 -0
  21. package/dist/command-palette.js +90 -0
  22. package/dist/container.d.ts +21 -0
  23. package/dist/container.js +10 -0
  24. package/dist/context-menu.d.ts +21 -0
  25. package/dist/context-menu.js +50 -0
  26. package/dist/custom-select.d.ts +45 -0
  27. package/dist/custom-select.js +26 -0
  28. package/dist/data-table.d.ts +53 -0
  29. package/dist/data-table.js +104 -0
  30. package/dist/date-picker.d.ts +43 -0
  31. package/dist/date-picker.js +142 -0
  32. package/dist/display.d.ts +63 -0
  33. package/dist/display.js +43 -0
  34. package/dist/drawer.d.ts +12 -0
  35. package/dist/drawer.js +29 -0
  36. package/dist/dropdown-menu.d.ts +47 -0
  37. package/dist/dropdown-menu.js +24 -0
  38. package/dist/empty-state.d.ts +13 -0
  39. package/dist/empty-state.js +8 -0
  40. package/dist/fields.d.ts +62 -0
  41. package/dist/fields.js +70 -0
  42. package/dist/file-upload.d.ts +33 -0
  43. package/dist/file-upload.js +111 -0
  44. package/dist/index.d.ts +48 -0
  45. package/dist/index.js +48 -0
  46. package/dist/internal/field-open.d.ts +2 -0
  47. package/dist/internal/field-open.js +15 -0
  48. package/dist/internal/focus.d.ts +4 -0
  49. package/dist/internal/focus.js +27 -0
  50. package/dist/internal/icons.d.ts +29 -0
  51. package/dist/internal/icons.js +32 -0
  52. package/dist/internal/navigation-origin.d.ts +2 -0
  53. package/dist/internal/navigation-origin.js +23 -0
  54. package/dist/internal/overlay-layer.d.ts +12 -0
  55. package/dist/internal/overlay-layer.js +14 -0
  56. package/dist/internal/pagination.d.ts +6 -0
  57. package/dist/internal/pagination.js +36 -0
  58. package/dist/internal/scroll-hints.d.ts +8 -0
  59. package/dist/internal/scroll-hints.js +108 -0
  60. package/dist/internal/state.d.ts +2 -0
  61. package/dist/internal/state.js +13 -0
  62. package/dist/internal/trigger-label.d.ts +5 -0
  63. package/dist/internal/trigger-label.js +26 -0
  64. package/dist/loader.d.ts +27 -0
  65. package/dist/loader.js +13 -0
  66. package/dist/modal.d.ts +23 -0
  67. package/dist/modal.js +30 -0
  68. package/dist/multi-select.d.ts +23 -0
  69. package/dist/multi-select.js +63 -0
  70. package/dist/navigation-menu.d.ts +26 -0
  71. package/dist/navigation-menu.js +27 -0
  72. package/dist/number-input.d.ts +14 -0
  73. package/dist/number-input.js +37 -0
  74. package/dist/pagination.d.ts +24 -0
  75. package/dist/pagination.js +60 -0
  76. package/dist/popover.d.ts +30 -0
  77. package/dist/popover.js +27 -0
  78. package/dist/progress.d.ts +18 -0
  79. package/dist/progress.js +9 -0
  80. package/dist/radio-group.d.ts +46 -0
  81. package/dist/radio-group.js +16 -0
  82. package/dist/resizable-panels.d.ts +22 -0
  83. package/dist/resizable-panels.js +70 -0
  84. package/dist/skeleton.d.ts +17 -0
  85. package/dist/skeleton.js +9 -0
  86. package/dist/slider.d.ts +41 -0
  87. package/dist/slider.js +29 -0
  88. package/dist/stepper.d.ts +25 -0
  89. package/dist/stepper.js +25 -0
  90. package/dist/styles.css +3369 -0
  91. package/dist/tabs.d.ts +32 -0
  92. package/dist/tabs.js +8 -0
  93. package/dist/toast.d.ts +54 -0
  94. package/dist/toast.js +107 -0
  95. package/dist/toggle-group.d.ts +32 -0
  96. package/dist/toggle-group.js +16 -0
  97. package/dist/toggles.d.ts +33 -0
  98. package/dist/toggles.js +29 -0
  99. package/dist/tooltip.d.ts +26 -0
  100. package/dist/tooltip.js +16 -0
  101. package/dist/transition.d.ts +27 -0
  102. package/dist/transition.js +148 -0
  103. package/dist/tree-view.d.ts +22 -0
  104. package/dist/tree-view.js +128 -0
  105. package/dist/typography.d.ts +23 -0
  106. package/dist/typography.js +20 -0
  107. package/dist/utils.d.ts +13 -0
  108. package/dist/utils.js +17 -0
  109. package/package.json +73 -0
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /** Árbol de selección única: expansión independiente, foco itinerante y navegación por nodos visibles. */
4
+ import { ExpandIcon, CollapseIcon, FolderIcon, FolderOpenIcon, FileIcon, } from './internal/icons.js';
5
+ import { useMemo, useRef, useState, } from 'react';
6
+ import { useControllable } from './internal/state.js';
7
+ import { cx } from './utils.js';
8
+ /** Flechas, Home/End, Enter/Espacio y búsqueda por prefijo. Un nodo desactivado desactiva también su rama. */
9
+ export function TreeView({ label, items, value, defaultValue = '', onValueChange, expanded, defaultExpanded = [], onExpandedChange, className, }) {
10
+ const [selected, select] = useControllable(value, defaultValue, onValueChange);
11
+ const [open, expand] = useControllable(expanded, defaultExpanded, onExpandedChange);
12
+ const [focused, setFocused] = useState('');
13
+ const elements = useRef(new Map());
14
+ const search = useRef({ text: '', time: 0 });
15
+ const expandedIds = useMemo(() => new Set(open), [open]);
16
+ const enabled = useMemo(() => {
17
+ const visible = [];
18
+ function collect(nodes, parent) {
19
+ for (const node of nodes) {
20
+ // Una rama desactivada tampoco participa en el recorrido de teclado.
21
+ if (node.disabled)
22
+ continue;
23
+ visible.push({ node, parent });
24
+ if (node.children && expandedIds.has(node.id))
25
+ collect(node.children, node.id);
26
+ }
27
+ }
28
+ collect(items);
29
+ return visible;
30
+ }, [items, expandedIds]);
31
+ const tabId = enabled.find((item) => item.node.id === focused)?.node.id ??
32
+ enabled.find((item) => item.node.id === selected)?.node.id ??
33
+ enabled[0]?.node.id;
34
+ function focus(id, reveal = true) {
35
+ if (id) {
36
+ setFocused(id);
37
+ const element = elements.current.get(id);
38
+ element?.focus({ preventScroll: true });
39
+ // El li incluye sus descendientes. Revelamos solo su fila para no desplazar
40
+ // ramas completas ni centrar innecesariamente el árbol o la página.
41
+ if (reveal)
42
+ element?.firstElementChild?.scrollIntoView({
43
+ block: 'nearest',
44
+ inline: 'nearest',
45
+ behavior: 'instant',
46
+ });
47
+ }
48
+ }
49
+ function toggle(node) {
50
+ expand(expandedIds.has(node.id) ? open.filter((id) => id !== node.id) : [...open, node.id]);
51
+ }
52
+ function key(event, node) {
53
+ if (event.target !== event.currentTarget)
54
+ return;
55
+ const index = enabled.findIndex((item) => item.node.id === node.id);
56
+ if (index < 0)
57
+ return;
58
+ const children = node.children?.length;
59
+ if (event.key === 'ArrowDown')
60
+ focus(enabled[index + 1]?.node.id);
61
+ else if (event.key === 'ArrowUp')
62
+ focus(enabled[index - 1]?.node.id);
63
+ else if (event.key === 'Home')
64
+ focus(enabled[0]?.node.id);
65
+ else if (event.key === 'End')
66
+ focus(enabled.at(-1)?.node.id);
67
+ else if (event.key === 'ArrowRight') {
68
+ if (children && !expandedIds.has(node.id))
69
+ toggle(node);
70
+ else if (children)
71
+ focus(enabled.find((item) => item.parent === node.id)?.node.id);
72
+ }
73
+ else if (event.key === 'ArrowLeft') {
74
+ if (children && expandedIds.has(node.id))
75
+ toggle(node);
76
+ else
77
+ focus(enabled[index].parent);
78
+ }
79
+ else if (event.key === 'Enter' || event.key === ' ')
80
+ select(node.id);
81
+ else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
82
+ const now = Date.now();
83
+ search.current = {
84
+ text: (now - search.current.time > 700 ? '' : search.current.text) +
85
+ event.key.toLocaleLowerCase(),
86
+ time: now,
87
+ };
88
+ const ordered = [...enabled.slice(index + 1), ...enabled.slice(0, index + 1)];
89
+ focus(ordered.find((item) => item.node.label.toLocaleLowerCase().startsWith(search.current.text))
90
+ ?.node.id);
91
+ }
92
+ else
93
+ return;
94
+ event.preventDefault();
95
+ event.stopPropagation();
96
+ }
97
+ function render(nodes, level = 1, inheritedDisabled = false) {
98
+ return nodes.map((node, index) => {
99
+ const blocked = inheritedDisabled || Boolean(node.disabled);
100
+ const branch = Boolean(node.children?.length);
101
+ const expanded = branch && expandedIds.has(node.id);
102
+ return (_jsxs("li", { role: "treeitem", "aria-label": node.label, "aria-level": level, "aria-posinset": index + 1, "aria-setsize": nodes.length, "aria-selected": selected === node.id, "aria-expanded": branch ? expanded : undefined, "aria-disabled": blocked || undefined, tabIndex: !blocked && tabId === node.id ? 0 : -1, ref: (element) => {
103
+ if (element)
104
+ elements.current.set(node.id, element);
105
+ else
106
+ elements.current.delete(node.id);
107
+ }, onFocus: (event) => {
108
+ if (event.target === event.currentTarget)
109
+ setFocused(node.id);
110
+ }, onKeyDown: (event) => key(event, node), children: [_jsxs("div", { className: "dgm-tree-row", style: { paddingInlineStart: `${0.5 + (level - 1) * 1.25}rem` }, onClick: () => {
111
+ if (!blocked) {
112
+ focus(node.id, false);
113
+ select(node.id);
114
+ }
115
+ }, children: [_jsx("span", { className: "dgm-tree-expander", "aria-hidden": "true", onClick: (event) => {
116
+ if (branch) {
117
+ event.stopPropagation();
118
+ if (!blocked) {
119
+ focus(node.id, false);
120
+ toggle(node);
121
+ }
122
+ }
123
+ }, children: branch ? expanded ? _jsx(CollapseIcon, {}) : _jsx(ExpandIcon, {}) : null }), _jsx("span", { className: "dgm-tree-node-icon", "aria-hidden": "true", children: node.icon ??
124
+ (branch ? expanded ? _jsx(FolderOpenIcon, {}) : _jsx(FolderIcon, {}) : _jsx(FileIcon, {})) }), _jsx("span", { children: node.label })] }), expanded && _jsx("ul", { role: "group", children: render(node.children, level + 1, blocked) })] }, node.id));
125
+ });
126
+ }
127
+ return (_jsx("ul", { role: "tree", "aria-label": label, className: cx('dgm-tree', className), children: render(items) }));
128
+ }
@@ -0,0 +1,23 @@
1
+ /** Texto semántico con la escala pública; funciona en servidor y no necesita proveedor. */
2
+ import type { HTMLAttributes, ReactElement } from 'react';
3
+ /** Función visual del texto, independiente del nivel semántico escogido con as. */
4
+ export type TypographyVariant = 'title' | 'subtitle' | 'body' | 'lead' | 'label' | 'caption' | 'code';
5
+ /** Elementos de texto; los controles y enlaces conservan sus componentes específicos. */
6
+ export type TypographyElement = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'small' | 'strong' | 'em' | 'code';
7
+ /** Colores semánticos del tema o el color del contenedor. */
8
+ export type TypographyTone = 'default' | 'muted' | 'primary' | 'danger' | 'inherit';
9
+ /** Conserva children, className, style, id, eventos y atributos ARIA nativos. */
10
+ export interface TypographyProps extends HTMLAttributes<HTMLElement> {
11
+ /** Presentación predeterminada de la escala. @defaultValue 'body' */
12
+ variant?: TypographyVariant;
13
+ /** Etiqueta HTML. Por defecto: title→h2, subtitle→h3, label→span, code→code, resto→p. */
14
+ as?: TypographyElement;
15
+ /** Color del texto; no cambia el tamaño ni el peso. @defaultValue 'default' */
16
+ tone?: TypographyTone;
17
+ }
18
+ /**
19
+ * Aplica estilos de lectura sin márgenes: el contenedor decide la separación.
20
+ * Usa as para respetar la jerarquía del documento; label es un estilo visual,
21
+ * no una etiqueta de formulario. No expone ref ni descarga fuentes.
22
+ */
23
+ export declare function Typography({ variant, as, tone, className, ...props }: TypographyProps): ReactElement;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cx } from './utils.js';
3
+ const elements = {
4
+ title: 'h2',
5
+ subtitle: 'h3',
6
+ body: 'p',
7
+ lead: 'p',
8
+ label: 'span',
9
+ caption: 'p',
10
+ code: 'code',
11
+ };
12
+ /**
13
+ * Aplica estilos de lectura sin márgenes: el contenedor decide la separación.
14
+ * Usa as para respetar la jerarquía del documento; label es un estilo visual,
15
+ * no una etiqueta de formulario. No expone ref ni descarga fuentes.
16
+ */
17
+ export function Typography({ variant = 'body', as, tone = 'default', className, ...props }) {
18
+ const Element = as ?? elements[variant];
19
+ return (_jsx(Element, { ...props, className: cx('dgm-typography', `dgm-typography--${variant}`, `dgm-typography--${tone}`, className) }));
20
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Une clases CSS e identificadores ARIA opcionales separados por espacios.
3
+ * Acepta condiciones como `loading && 'dgm-loading'` y descarta valores vacíos.
4
+ * No elimina duplicados ni resuelve conflictos entre reglas CSS.
5
+ */
6
+ export declare function cx(...values: Array<string | false | null | undefined>): string;
7
+ /**
8
+ * Distingue un contenido explícito de los valores que aquí significan «ausente».
9
+ * Conserva el número 0, que React sí representa y que una condición `!!value`
10
+ * descartaría. No inspecciona arrays, fragments ni el resultado de componentes.
11
+ * Se comparte entre el renderizado y ARIA para que no apunten a IDs inexistentes.
12
+ */
13
+ export declare function hasContent(value: unknown): boolean;
package/dist/utils.js ADDED
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Une clases CSS e identificadores ARIA opcionales separados por espacios.
3
+ * Acepta condiciones como `loading && 'dgm-loading'` y descarta valores vacíos.
4
+ * No elimina duplicados ni resuelve conflictos entre reglas CSS.
5
+ */
6
+ export function cx(...values) {
7
+ return values.filter(Boolean).join(' ');
8
+ }
9
+ /**
10
+ * Distingue un contenido explícito de los valores que aquí significan «ausente».
11
+ * Conserva el número 0, que React sí representa y que una condición `!!value`
12
+ * descartaría. No inspecciona arrays, fragments ni el resultado de componentes.
13
+ * Se comparte entre el renderizado y ARIA para que no apunten a IDs inexistentes.
14
+ */
15
+ export function hasContent(value) {
16
+ return value !== null && value !== undefined && typeof value !== 'boolean' && value !== '';
17
+ }
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "danielgm-ui",
3
+ "version": "0.1.0",
4
+ "description": "Accessible React components for Next.js and the web.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./styles.css": "./dist/styles.css",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE",
22
+ "TABLER-LICENSE.txt"
23
+ ],
24
+ "sideEffects": [
25
+ "**/*.css"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc -p tsconfig.json && node scripts/styles.mjs",
29
+ "dev": "node scripts/watch.mjs",
30
+ "prepack": "npm run build"
31
+ },
32
+ "peerDependencies": {
33
+ "react": "^18.2.0 || ^19.0.0",
34
+ "react-dom": "^18.2.0 || ^19.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "react": "^19.2.0",
38
+ "react-dom": "^19.2.0"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "license": "MIT",
44
+ "keywords": [
45
+ "react",
46
+ "nextjs",
47
+ "components",
48
+ "ui",
49
+ "typescript",
50
+ "accessible"
51
+ ],
52
+ "dependencies": {
53
+ "@radix-ui/react-accordion": "1.2.20",
54
+ "@radix-ui/react-avatar": "1.2.6",
55
+ "@radix-ui/react-context-menu": "2.3.7",
56
+ "@radix-ui/react-dialog": "1.1.23",
57
+ "@radix-ui/react-dropdown-menu": "2.1.24",
58
+ "@radix-ui/react-navigation-menu": "1.2.22",
59
+ "@radix-ui/react-popover": "1.1.23",
60
+ "@radix-ui/react-radio-group": "1.4.7",
61
+ "@radix-ui/react-select": "2.3.7",
62
+ "@radix-ui/react-slider": "1.4.7",
63
+ "@radix-ui/react-tabs": "1.1.21",
64
+ "@radix-ui/react-toast": "1.2.23",
65
+ "@radix-ui/react-toggle-group": "1.1.19",
66
+ "@radix-ui/react-tooltip": "1.2.16",
67
+ "@tabler/icons-react": "3.46.0",
68
+ "@tanstack/react-table": "9.2.4",
69
+ "cmdk": "1.1.1",
70
+ "date-fns": "4.4.0",
71
+ "react-day-picker": "10.0.1"
72
+ }
73
+ }