@doscientos/ui 0.1.33 → 0.1.34
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 +25 -1
- package/dist/index.cjs +60 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +60 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -30,7 +30,7 @@ type UseAutosaveOptions<T> = {
|
|
|
30
30
|
enabled?: boolean;
|
|
31
31
|
serialize?: (data: T) => string;
|
|
32
32
|
};
|
|
33
|
-
/** Debounced
|
|
33
|
+
/** Debounced, serialized writes. saveNow flushes the debounce; errors remain in state. */
|
|
34
34
|
declare function useAutosave<T>({ data, onSave, debounceMs, enabled, serialize, }: UseAutosaveOptions<T>): {
|
|
35
35
|
status: AutosaveStatus;
|
|
36
36
|
error: Error | null;
|
|
@@ -856,7 +856,7 @@ type PaginationProps = {
|
|
|
856
856
|
ariaLabel?: string;
|
|
857
857
|
/** Optional description of the slice of results currently visible. */
|
|
858
858
|
summary?: React$1.ReactNode;
|
|
859
|
-
/** Number of neighbouring pages shown around the current page. */
|
|
859
|
+
/** Number of neighbouring pages shown around the current page (normalized to 0–10). */
|
|
860
860
|
siblingCount?: number;
|
|
861
861
|
className?: string;
|
|
862
862
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ type UseAutosaveOptions<T> = {
|
|
|
30
30
|
enabled?: boolean;
|
|
31
31
|
serialize?: (data: T) => string;
|
|
32
32
|
};
|
|
33
|
-
/** Debounced
|
|
33
|
+
/** Debounced, serialized writes. saveNow flushes the debounce; errors remain in state. */
|
|
34
34
|
declare function useAutosave<T>({ data, onSave, debounceMs, enabled, serialize, }: UseAutosaveOptions<T>): {
|
|
35
35
|
status: AutosaveStatus;
|
|
36
36
|
error: Error | null;
|
|
@@ -856,7 +856,7 @@ type PaginationProps = {
|
|
|
856
856
|
ariaLabel?: string;
|
|
857
857
|
/** Optional description of the slice of results currently visible. */
|
|
858
858
|
summary?: React$1.ReactNode;
|
|
859
|
-
/** Number of neighbouring pages shown around the current page. */
|
|
859
|
+
/** Number of neighbouring pages shown around the current page (normalized to 0–10). */
|
|
860
860
|
siblingCount?: number;
|
|
861
861
|
className?: string;
|
|
862
862
|
};
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ function useAsyncAction(action) {
|
|
|
13
13
|
pendingRef.current = true;
|
|
14
14
|
setStatus("pending");
|
|
15
15
|
setError(null);
|
|
16
|
+
setData(null);
|
|
16
17
|
try {
|
|
17
18
|
const result = await action(...args);
|
|
18
19
|
setData(result);
|
|
@@ -29,6 +30,7 @@ function useAsyncAction(action) {
|
|
|
29
30
|
[action]
|
|
30
31
|
);
|
|
31
32
|
const reset = useCallback(() => {
|
|
33
|
+
if (pendingRef.current) return;
|
|
32
34
|
setData(null);
|
|
33
35
|
setError(null);
|
|
34
36
|
setStatus("idle");
|
|
@@ -51,24 +53,45 @@ function useAutosave({
|
|
|
51
53
|
const saveRef = useRef2(onSave);
|
|
52
54
|
const serializeRef = useRef2(serialize);
|
|
53
55
|
const latestSaveId = useRef2(0);
|
|
56
|
+
const queue = useRef2(Promise.resolve());
|
|
57
|
+
const queuedCount = useRef2(0);
|
|
58
|
+
const timeoutRef = useRef2(void 0);
|
|
59
|
+
const mounted = useRef2(true);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
mounted.current = true;
|
|
62
|
+
return () => {
|
|
63
|
+
mounted.current = false;
|
|
64
|
+
clearTimeout(timeoutRef.current);
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
54
67
|
useEffect(() => {
|
|
55
68
|
saveRef.current = onSave;
|
|
56
69
|
serializeRef.current = serialize;
|
|
57
70
|
}, [onSave, serialize]);
|
|
58
|
-
const save = useCallback2(
|
|
71
|
+
const save = useCallback2((value, force = false) => {
|
|
72
|
+
clearTimeout(timeoutRef.current);
|
|
59
73
|
const saveId = ++latestSaveId.current;
|
|
74
|
+
const snapshot = serializeRef.current(value);
|
|
75
|
+
const write = saveRef.current;
|
|
76
|
+
queuedCount.current += 1;
|
|
60
77
|
setStatus("saving");
|
|
61
78
|
setError(null);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
const pending = queue.current.then(async () => {
|
|
80
|
+
try {
|
|
81
|
+
if (!mounted.current) return;
|
|
82
|
+
if (force || lastSaved.current !== snapshot) await write(value);
|
|
83
|
+
lastSaved.current = snapshot;
|
|
84
|
+
if (mounted.current && saveId === latestSaveId.current) setStatus("saved");
|
|
85
|
+
} catch (cause) {
|
|
86
|
+
if (!mounted.current || saveId !== latestSaveId.current) return;
|
|
87
|
+
setError(cause instanceof Error ? cause : new Error("No se pudo guardar."));
|
|
88
|
+
setStatus("error");
|
|
89
|
+
} finally {
|
|
90
|
+
queuedCount.current -= 1;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
queue.current = pending;
|
|
94
|
+
return pending;
|
|
72
95
|
}, []);
|
|
73
96
|
useEffect(() => {
|
|
74
97
|
if (!enabled) return;
|
|
@@ -77,11 +100,11 @@ function useAutosave({
|
|
|
77
100
|
lastSaved.current = snapshot;
|
|
78
101
|
return;
|
|
79
102
|
}
|
|
80
|
-
if (snapshot === lastSaved.current) return;
|
|
81
|
-
|
|
82
|
-
return () =>
|
|
103
|
+
if (snapshot === lastSaved.current && queuedCount.current === 0) return;
|
|
104
|
+
timeoutRef.current = setTimeout(() => void save(data), debounceMs);
|
|
105
|
+
return () => clearTimeout(timeoutRef.current);
|
|
83
106
|
}, [data, debounceMs, enabled, save]);
|
|
84
|
-
return { status, error, saveNow: () => save(data) };
|
|
107
|
+
return { status, error, saveNow: () => save(data, true) };
|
|
85
108
|
}
|
|
86
109
|
|
|
87
110
|
// src/hooks/use-clipboard.ts
|
|
@@ -1513,10 +1536,10 @@ function ComboboxContent({ className, ...props }) {
|
|
|
1513
1536
|
Popover,
|
|
1514
1537
|
{
|
|
1515
1538
|
"data-slot": "combobox-content",
|
|
1516
|
-
className: cn(
|
|
1539
|
+
className: (state) => cn(
|
|
1517
1540
|
floatingSurfaceClassName,
|
|
1518
1541
|
"max-h-72 w-(--trigger-width) overflow-hidden rounded-xl border border-border bg-background p-1.5 text-foreground",
|
|
1519
|
-
className
|
|
1542
|
+
typeof className === "function" ? className(state) : className
|
|
1520
1543
|
),
|
|
1521
1544
|
...props
|
|
1522
1545
|
}
|
|
@@ -1531,7 +1554,10 @@ function ComboboxList({
|
|
|
1531
1554
|
ListBox,
|
|
1532
1555
|
{
|
|
1533
1556
|
"data-slot": "combobox-list",
|
|
1534
|
-
className:
|
|
1557
|
+
className: (state) => cn(
|
|
1558
|
+
"max-h-64 overflow-y-auto",
|
|
1559
|
+
typeof className === "function" ? className(state) : className
|
|
1560
|
+
),
|
|
1535
1561
|
renderEmptyState: emptyState ? () => emptyState : void 0,
|
|
1536
1562
|
...props
|
|
1537
1563
|
}
|
|
@@ -1546,9 +1572,9 @@ function ComboboxItem({
|
|
|
1546
1572
|
ListBoxItem,
|
|
1547
1573
|
{
|
|
1548
1574
|
"data-slot": "combobox-item",
|
|
1549
|
-
className: cn(
|
|
1575
|
+
className: (state) => cn(
|
|
1550
1576
|
"flex w-full cursor-default items-center justify-between rounded-md px-2 py-2 text-sm outline-none transition-colors data-focused:bg-muted data-focused:text-foreground data-hovered:bg-muted data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
1551
|
-
className
|
|
1577
|
+
typeof className === "function" ? className(state) : className
|
|
1552
1578
|
),
|
|
1553
1579
|
...props,
|
|
1554
1580
|
children
|
|
@@ -1623,7 +1649,10 @@ function AutocompleteCombobox({
|
|
|
1623
1649
|
AriaComboBox,
|
|
1624
1650
|
{
|
|
1625
1651
|
...props,
|
|
1626
|
-
className:
|
|
1652
|
+
className: (state) => cn(
|
|
1653
|
+
"group/combobox flex w-full flex-col gap-1.5",
|
|
1654
|
+
typeof className === "function" ? className(state) : className
|
|
1655
|
+
),
|
|
1627
1656
|
items: filteredItems,
|
|
1628
1657
|
selectedKey,
|
|
1629
1658
|
inputValue,
|
|
@@ -2479,16 +2508,19 @@ function ErrorStateActions({ className, ...props }) {
|
|
|
2479
2508
|
|
|
2480
2509
|
// src/ui/error-boundary/error-boundary.tsx
|
|
2481
2510
|
import { jsx as jsx28, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2511
|
+
function normalizeError(cause) {
|
|
2512
|
+
return cause instanceof Error ? cause : new Error("No se pudo renderizar este contenido.", { cause });
|
|
2513
|
+
}
|
|
2482
2514
|
function changedResetKeys(previous = [], next = []) {
|
|
2483
2515
|
return previous.length !== next.length || previous.some((value, index) => !Object.is(value, next[index]));
|
|
2484
2516
|
}
|
|
2485
2517
|
var Boundary = class extends Component {
|
|
2486
2518
|
state = { error: null };
|
|
2487
2519
|
static getDerivedStateFromError(error) {
|
|
2488
|
-
return { error };
|
|
2520
|
+
return { error: normalizeError(error) };
|
|
2489
2521
|
}
|
|
2490
2522
|
componentDidCatch(error, info) {
|
|
2491
|
-
this.props.onError?.(error, info);
|
|
2523
|
+
this.props.onError?.(this.state.error ?? normalizeError(error), info);
|
|
2492
2524
|
}
|
|
2493
2525
|
componentDidUpdate(previousProps) {
|
|
2494
2526
|
if (this.state.error && changedResetKeys(previousProps.resetKeys, this.props.resetKeys))
|
|
@@ -2500,7 +2532,7 @@ var Boundary = class extends Component {
|
|
|
2500
2532
|
if (!this.state.error) return children;
|
|
2501
2533
|
if (typeof fallback === "function")
|
|
2502
2534
|
return fallback({ error: this.state.error, reset: this.reset });
|
|
2503
|
-
if (fallback) return fallback;
|
|
2535
|
+
if (fallback !== void 0) return fallback;
|
|
2504
2536
|
return /* @__PURE__ */ jsxs12(ErrorState, { children: [
|
|
2505
2537
|
/* @__PURE__ */ jsx28(ErrorStateIcon, {}),
|
|
2506
2538
|
/* @__PURE__ */ jsx28(ErrorStateTitle, { children: "No se pudo cargar este contenido" }),
|
|
@@ -3582,16 +3614,17 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
3582
3614
|
import * as React6 from "react";
|
|
3583
3615
|
import { jsx as jsx47, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
3584
3616
|
function visiblePages(page, pageCount, siblingCount) {
|
|
3617
|
+
const siblings = Number.isFinite(siblingCount) ? Math.min(10, Math.max(0, Math.floor(siblingCount))) : 1;
|
|
3585
3618
|
return [
|
|
3586
3619
|
.../* @__PURE__ */ new Set([
|
|
3587
3620
|
1,
|
|
3588
|
-
...Array.from({ length:
|
|
3621
|
+
...Array.from({ length: siblings * 2 + 1 }, (_, index) => page - siblings + index),
|
|
3589
3622
|
pageCount
|
|
3590
3623
|
])
|
|
3591
3624
|
].filter((item) => item >= 1 && item <= pageCount).sort((left, right) => left - right);
|
|
3592
3625
|
}
|
|
3593
3626
|
function normalizedPageCount(pageCount) {
|
|
3594
|
-
return Number.isFinite(pageCount) ? Math.max(0, Math.floor(pageCount)) : 0;
|
|
3627
|
+
return Number.isFinite(pageCount) ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(pageCount))) : 0;
|
|
3595
3628
|
}
|
|
3596
3629
|
function normalizedPage(page, pageCount) {
|
|
3597
3630
|
if (!Number.isFinite(page)) return 1;
|
|
@@ -3640,7 +3673,7 @@ function Pagination({
|
|
|
3640
3673
|
"aria-label": `P\xE1gina ${item}`,
|
|
3641
3674
|
onPress: () => onPageChange(item),
|
|
3642
3675
|
size: "icon",
|
|
3643
|
-
variant: item ===
|
|
3676
|
+
variant: item === currentPage ? "secondary" : "ghost",
|
|
3644
3677
|
children: item
|
|
3645
3678
|
}
|
|
3646
3679
|
)
|