danielgm-ui 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data-table.d.ts +8 -2
- package/dist/data-table.js +21 -4
- package/dist/slider.d.ts +2 -0
- package/dist/slider.js +11 -3
- package/dist/styles.css +66 -3
- package/package.json +1 -1
package/dist/data-table.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ export interface DataColumn<T extends object> {
|
|
|
10
10
|
sortable?: boolean;
|
|
11
11
|
/** Participa en el buscador global. @defaultValue true */
|
|
12
12
|
searchable?: boolean;
|
|
13
|
-
|
|
13
|
+
/** Alineación compartida por cabecera y celdas. @defaultValue 'start' */
|
|
14
|
+
align?: 'start' | 'center' | 'end';
|
|
14
15
|
/** Ancho estable CSS (px si es número); las columnas sin ancho reparten el espacio restante. */
|
|
15
16
|
width?: CSSProperties['width'];
|
|
16
17
|
}
|
|
@@ -27,7 +28,12 @@ export interface DataTableProps<T extends object> {
|
|
|
27
28
|
caption: string;
|
|
28
29
|
/** Orden controlado. Usa [] para quitarlo. */
|
|
29
30
|
sorting?: DataTableSort[];
|
|
31
|
+
/** Orden base: conserva aria-sort pero no muestra flecha. */
|
|
30
32
|
defaultSorting?: DataTableSort[];
|
|
33
|
+
/** Habilita las cabeceras ordenables; cada columna puede desactivarlas. @defaultValue true */
|
|
34
|
+
sortable?: boolean;
|
|
35
|
+
/** Delega la ordenación al consumidor sin reordenar data. @defaultValue false */
|
|
36
|
+
manualSorting?: boolean;
|
|
31
37
|
onSortingChange?: (sorting: DataTableSort[]) => void;
|
|
32
38
|
/** Buscador de todas las columnas habilitadas. @defaultValue true */
|
|
33
39
|
searchable?: boolean;
|
|
@@ -50,4 +56,4 @@ export interface DataTableProps<T extends object> {
|
|
|
50
56
|
className?: string;
|
|
51
57
|
}
|
|
52
58
|
/** Paginación y selección conservan IDs reales. El filtrado devuelve a la primera página. */
|
|
53
|
-
export declare function DataTable<T extends object>({ data, columns, getRowId, caption, sorting, defaultSorting, onSortingChange, searchable, searchPlaceholder, pageSize, page, onPageChange, selectable, selection, defaultSelection, onSelectionChange, loading, emptyMessage, locale, className, }: DataTableProps<T>): ReactElement;
|
|
59
|
+
export declare function DataTable<T extends object>({ data, columns, getRowId, caption, sorting, sortable, manualSorting, defaultSorting, onSortingChange, searchable, searchPlaceholder, pageSize, page, onPageChange, selectable, selection, defaultSelection, onSelectionChange, loading, emptyMessage, locale, className, }: DataTableProps<T>): ReactElement;
|
package/dist/data-table.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/** Tabla HTML con operaciones locales. TanStack calcula filas filtradas y ordenadas sin mutar data. */
|
|
4
|
-
import { ArrowUpIcon, ArrowDownIcon
|
|
4
|
+
import { ArrowUpIcon, ArrowDownIcon } from './internal/icons.js';
|
|
5
5
|
import { useEffect, useMemo, useRef, useState, } from 'react';
|
|
6
6
|
import { useTable, tableFeatures, rowSortingFeature, columnFilteringFeature, globalFilteringFeature, createSortedRowModel, createFilteredRowModel, filterFn_includesString, functionalUpdate, } from '@tanstack/react-table';
|
|
7
7
|
import { Button } from './button.js';
|
|
@@ -20,7 +20,7 @@ const features = tableFeatures({
|
|
|
20
20
|
filterFns: { includesString: filterFn_includesString },
|
|
21
21
|
});
|
|
22
22
|
/** Paginación y selección conservan IDs reales. El filtrado devuelve a la primera página. */
|
|
23
|
-
export function DataTable({ data, columns, getRowId, caption, sorting, defaultSorting = [], onSortingChange, searchable = true, searchPlaceholder, pageSize = 10, page, onPageChange, selectable = false, selection, defaultSelection = [], onSelectionChange, loading = false, emptyMessage, locale = 'en', className, }) {
|
|
23
|
+
export function DataTable({ data, columns, getRowId, caption, sorting, sortable = true, manualSorting = false, defaultSorting = [], onSortingChange, searchable = true, searchPlaceholder, pageSize = 10, page, onPageChange, selectable = false, selection, defaultSelection = [], onSelectionChange, loading = false, emptyMessage, locale = 'en', className, }) {
|
|
24
24
|
const [sort, changeSort] = useControllable(sorting, defaultSorting, onSortingChange);
|
|
25
25
|
const [currentPage, changePage] = useControllable(page, 1, onPageChange);
|
|
26
26
|
const [selected, changeSelection] = useControllable(selection, defaultSelection, onSelectionChange ? (next) => onSelectionChange([...next]) : undefined);
|
|
@@ -55,6 +55,7 @@ export function DataTable({ data, columns, getRowId, caption, sorting, defaultSo
|
|
|
55
55
|
changeSort(functionalUpdate(updater, sort));
|
|
56
56
|
changePage(1);
|
|
57
57
|
},
|
|
58
|
+
manualSorting,
|
|
58
59
|
globalFilterFn: 'includesString',
|
|
59
60
|
enableMultiSort: false,
|
|
60
61
|
});
|
|
@@ -89,11 +90,27 @@ export function DataTable({ data, columns, getRowId, caption, sorting, defaultSo
|
|
|
89
90
|
} }) })), columns.map((column) => {
|
|
90
91
|
const instance = table.getColumn(column.id);
|
|
91
92
|
const direction = instance.getIsSorted();
|
|
92
|
-
|
|
93
|
+
const baseline = defaultSorting.find((item) => item.id === column.id);
|
|
94
|
+
const showArrow = Boolean(direction && !(baseline && baseline.desc === (direction === 'desc')));
|
|
95
|
+
return (_jsx("th", { scope: "col", "data-align": column.align ?? 'start', style: { textAlign: column.align ?? 'start' }, "aria-sort": direction === 'asc'
|
|
93
96
|
? 'ascending'
|
|
94
97
|
: direction === 'desc'
|
|
95
98
|
? 'descending'
|
|
96
|
-
: undefined, children:
|
|
99
|
+
: undefined, children: sortable && instance.getCanSort() ? (_jsxs(Button, { variant: "ghost", size: "sm", className: "dgm-table-sort", "data-sorted": showArrow || undefined, disabled: loading, onClick: () => {
|
|
100
|
+
// El orden base alterna siempre con su inverso, también en números.
|
|
101
|
+
if (baseline) {
|
|
102
|
+
changeSort([
|
|
103
|
+
{
|
|
104
|
+
id: column.id,
|
|
105
|
+
desc: direction ? direction !== 'desc' : !baseline.desc,
|
|
106
|
+
},
|
|
107
|
+
]);
|
|
108
|
+
changePage(1);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
instance.toggleSorting();
|
|
112
|
+
}
|
|
113
|
+
}, children: [_jsx("span", { className: "dgm-table-sort-label", children: column.header }), _jsx("span", { className: "dgm-table-sort-icon", "aria-hidden": "true", children: direction === 'desc' ? _jsx(ArrowDownIcon, {}) : _jsx(ArrowUpIcon, {}) })] })) : (column.header) }, column.id));
|
|
97
114
|
})] }) }), _jsx("tbody", { children: loading ? (Array.from({ length: Math.min(size, 5) }, (_, index) => (_jsx("tr", { children: _jsx("td", { colSpan: columns.length + (selectable ? 1 : 0), children: _jsx(Skeleton, { height: "1.5rem" }) }) }, index)))) : visible.length ? (visible.map((row) => (_jsxs("tr", { "data-selected": selectedIds.has(row.id) || undefined, children: [selectable && (_jsx("td", { children: _jsx(Checkbox, { checked: selectedIds.has(row.id), label: _jsxs("span", { className: "dgm-visually-hidden", children: [es ? 'Seleccionar fila' : 'Select row', " ", row.id] }), onChange: (event) => changeSelection(event.target.checked
|
|
98
115
|
? [...new Set([...selected, row.id])]
|
|
99
116
|
: selected.filter((id) => id !== row.id)) }) })), columns.map((column) => (_jsx("td", { style: { textAlign: column.align ?? 'start' }, children: column.cell ? column.cell(row.original) : column.accessor(row.original) }, column.id)))] }, row.id)))) : (_jsx("tr", { children: _jsx("td", { colSpan: columns.length + (selectable ? 1 : 0), className: "dgm-table-empty", children: emptyMessage ?? (es ? 'No hay resultados.' : 'No results.') }) })) })] }) }), _jsxs("div", { className: "dgm-table-footer", children: [_jsx("p", { role: "status", children: loading
|
package/dist/slider.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export interface SliderBaseProps {
|
|
|
10
10
|
step?: number;
|
|
11
11
|
disabled?: boolean;
|
|
12
12
|
name?: string;
|
|
13
|
+
/** Visibilidad visual de los extremos en Slider y RangeSlider; conserva foco y accesibilidad. @defaultValue 'always' */
|
|
14
|
+
thumbVisibility?: 'always' | 'interaction';
|
|
13
15
|
/** Valor visible y aria-valuetext; útil para porcentajes, unidades o precios. */
|
|
14
16
|
formatValue?: (value: number) => string;
|
|
15
17
|
/** Marcas informativas, sin interacción propia. Deben estar entre min y max. */
|
package/dist/slider.js
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/** Radix mantiene teclado, gestos táctiles y valores de formulario; la librería aporta etiquetas y estilo. */
|
|
4
|
-
import { useId } from 'react';
|
|
4
|
+
import { useId, useState, useEffect } from 'react';
|
|
5
5
|
import * as Primitive from '@radix-ui/react-slider';
|
|
6
6
|
import { useControllable } from './internal/state.js';
|
|
7
7
|
import { cx, hasContent } from './utils.js';
|
|
8
8
|
/** Infraestructura interna; cada API pública mantiene un número fijo de controles. */
|
|
9
|
-
function SliderControl({ label, description, error, min = 0, max = 100, step = 1, disabled, name, formatValue = String, marks = [], className, id, values, change, commit, thumbLabels, }) {
|
|
9
|
+
function SliderControl({ label, description, error, min = 0, max = 100, step = 1, disabled, name, thumbVisibility = 'always', formatValue = String, marks = [], className, id, values, change, commit, thumbLabels, }) {
|
|
10
10
|
const generated = useId();
|
|
11
|
+
const [activePointer, setActivePointer] = useState(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (disabled)
|
|
14
|
+
setActivePointer(null);
|
|
15
|
+
}, [disabled]);
|
|
11
16
|
const controlId = id ?? `dgm-slider-${generated}`;
|
|
12
17
|
if (![min, max, step].every(Number.isFinite) || min >= max || step <= 0) {
|
|
13
18
|
throw new RangeError('Slider requires finite min < max and step > 0.');
|
|
14
19
|
}
|
|
15
20
|
const describedBy = cx(hasContent(description) && `${controlId}-description`, hasContent(error) && `${controlId}-error`) || undefined;
|
|
16
|
-
return (_jsxs("div", { className: cx('dgm-field', 'dgm-slider-field', className), id: controlId, children: [_jsxs("div", { className: "dgm-slider-heading", children: [_jsx("span", { className: "dgm-label", id: `${controlId}-label`, children: label }), _jsx("span", { className: "dgm-description", "aria-hidden": "true", children: values.map(formatValue).join(' – ') })] }), _jsxs(Primitive.Root, { className: "dgm-slider",
|
|
21
|
+
return (_jsxs("div", { className: cx('dgm-field', 'dgm-slider-field', className), id: controlId, children: [_jsxs("div", { className: "dgm-slider-heading", children: [_jsx("span", { className: "dgm-label", id: `${controlId}-label`, children: label }), _jsx("span", { className: "dgm-description", "aria-hidden": "true", children: values.map(formatValue).join(' – ') })] }), _jsxs(Primitive.Root, { className: "dgm-slider", "data-thumb-visibility": thumbVisibility, "data-dragging": !disabled && activePointer !== null ? '' : undefined, onPointerDownCapture: (event) => {
|
|
22
|
+
if (!disabled && event.button === 0)
|
|
23
|
+
setActivePointer(event.pointerId);
|
|
24
|
+
}, onPointerUpCapture: () => setActivePointer(null), onPointerCancelCapture: () => setActivePointer(null), onLostPointerCapture: () => setActivePointer(null), value: values, onValueChange: change, onValueCommit: commit, min: min, max: max, step: step, disabled: disabled, name: name, children: [_jsx(Primitive.Track, { className: "dgm-slider-track", children: _jsx(Primitive.Range, { className: "dgm-slider-range" }) }), values.map((value, index) => (_jsx(Primitive.Thumb, { name: name, className: "dgm-slider-thumb", "aria-labelledby": `${controlId}-label${thumbLabels ? ` ${controlId}-thumb-${index}` : ''}`, "aria-describedby": describedBy, "aria-invalid": hasContent(error) || undefined, "aria-valuetext": formatValue(value) }, index)))] }), thumbLabels?.map((text, index) => (_jsx("span", { id: `${controlId}-thumb-${index}`, className: "dgm-visually-hidden", children: text }, index))), marks.length > 0 && (_jsx("div", { className: "dgm-slider-marks", "aria-hidden": "true", children: marks
|
|
17
25
|
.filter((mark) => mark.value >= min && mark.value <= max)
|
|
18
26
|
.map((mark) => (_jsx("span", { style: { left: `${(100 * (mark.value - min)) / (max - min)}%` }, children: mark.label ?? formatValue(mark.value) }, mark.value))) })), hasContent(description) && (_jsx("span", { id: `${controlId}-description`, className: "dgm-description", children: description })), hasContent(error) && (_jsx("span", { id: `${controlId}-error`, className: "dgm-error", children: error }))] }));
|
|
19
27
|
}
|
package/dist/styles.css
CHANGED
|
@@ -2759,8 +2759,54 @@ button.dgm-step:hover:not(:disabled),
|
|
|
2759
2759
|
font-weight: var(--dgm-font-weight-semibold);
|
|
2760
2760
|
background: var(--dgm-subtle);
|
|
2761
2761
|
}
|
|
2762
|
-
.dgm-data-table th .dgm-
|
|
2763
|
-
|
|
2762
|
+
.dgm-data-table th .dgm-table-sort {
|
|
2763
|
+
--dgm-table-sort-space: 1.125rem;
|
|
2764
|
+
display: inline-block;
|
|
2765
|
+
position: relative;
|
|
2766
|
+
max-width: 100%;
|
|
2767
|
+
padding-inline: var(--dgm-table-sort-space);
|
|
2768
|
+
text-align: inherit;
|
|
2769
|
+
white-space: normal;
|
|
2770
|
+
}
|
|
2771
|
+
.dgm-table-sort-label {
|
|
2772
|
+
position: relative;
|
|
2773
|
+
display: inline-block;
|
|
2774
|
+
transition: transform 240ms ease;
|
|
2775
|
+
}
|
|
2776
|
+
.dgm-table-sort-icon {
|
|
2777
|
+
position: absolute;
|
|
2778
|
+
inset-inline-end: 0.5625rem;
|
|
2779
|
+
top: 50%;
|
|
2780
|
+
width: 0.875rem;
|
|
2781
|
+
height: 0.875rem;
|
|
2782
|
+
opacity: 0;
|
|
2783
|
+
transform: translateY(-50%) scale(0.5);
|
|
2784
|
+
transition:
|
|
2785
|
+
opacity 240ms ease,
|
|
2786
|
+
transform 240ms ease;
|
|
2787
|
+
}
|
|
2788
|
+
.dgm-table-sort-icon svg {
|
|
2789
|
+
width: 100%;
|
|
2790
|
+
height: 100%;
|
|
2791
|
+
}
|
|
2792
|
+
.dgm-table-sort[data-sorted] .dgm-table-sort-icon {
|
|
2793
|
+
opacity: 1;
|
|
2794
|
+
transform: translateY(-50%) scale(1);
|
|
2795
|
+
}
|
|
2796
|
+
.dgm-data-table th .dgm-table-sort[data-sorted] .dgm-table-sort-label {
|
|
2797
|
+
transform: translateX(-0.5625rem);
|
|
2798
|
+
}
|
|
2799
|
+
.dgm-data-table th[data-align='start'] .dgm-table-sort {
|
|
2800
|
+
margin-inline-start: calc(-1 * var(--dgm-table-sort-space));
|
|
2801
|
+
}
|
|
2802
|
+
[dir='rtl'] .dgm-data-table th .dgm-table-sort[data-sorted] .dgm-table-sort-label {
|
|
2803
|
+
transform: translateX(0.5625rem);
|
|
2804
|
+
}
|
|
2805
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2806
|
+
.dgm-table-sort-label,
|
|
2807
|
+
.dgm-table-sort-icon {
|
|
2808
|
+
transition: none;
|
|
2809
|
+
}
|
|
2764
2810
|
}
|
|
2765
2811
|
.dgm-data-table tr[data-selected] {
|
|
2766
2812
|
background: var(--dgm-subtle);
|
|
@@ -3084,6 +3130,22 @@ button.dgm-step:disabled {
|
|
|
3084
3130
|
box-shadow: 0 2px 5px #0002;
|
|
3085
3131
|
cursor: grab;
|
|
3086
3132
|
}
|
|
3133
|
+
/* Opacidad conserva la geometría, el área táctil y los controles accesibles. */
|
|
3134
|
+
.dgm-slider[data-thumb-visibility='interaction'] .dgm-slider-thumb {
|
|
3135
|
+
opacity: 0;
|
|
3136
|
+
transition: opacity 0.15s ease;
|
|
3137
|
+
}
|
|
3138
|
+
.dgm-slider[data-thumb-visibility='interaction']:not([data-disabled]):focus-within
|
|
3139
|
+
.dgm-slider-thumb,
|
|
3140
|
+
.dgm-slider[data-thumb-visibility='interaction']:not([data-disabled])[data-dragging]
|
|
3141
|
+
.dgm-slider-thumb {
|
|
3142
|
+
opacity: 1;
|
|
3143
|
+
}
|
|
3144
|
+
@media (hover: hover) {
|
|
3145
|
+
.dgm-slider[data-thumb-visibility='interaction']:not([data-disabled]):hover .dgm-slider-thumb {
|
|
3146
|
+
opacity: 1;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3087
3149
|
.dgm-slider-thumb::after {
|
|
3088
3150
|
content: '';
|
|
3089
3151
|
position: absolute;
|
|
@@ -3529,7 +3591,8 @@ button.dgm-step:disabled {
|
|
|
3529
3591
|
.dgm-navigation-content {
|
|
3530
3592
|
animation: none;
|
|
3531
3593
|
}
|
|
3532
|
-
.dgm-toggle-item
|
|
3594
|
+
.dgm-toggle-item,
|
|
3595
|
+
.dgm-slider[data-thumb-visibility='interaction'] .dgm-slider-thumb {
|
|
3533
3596
|
transition: none;
|
|
3534
3597
|
}
|
|
3535
3598
|
}
|