@avenue-ticketing/ui 0.4.0 → 0.6.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.
- package/dist/react/avatar.d.ts +42 -0
- package/dist/react/avatar.js +159 -0
- package/dist/react/avatar.js.map +1 -0
- package/dist/react/badge.d.ts +12 -0
- package/dist/react/badge.js +35 -1
- package/dist/react/badge.js.map +1 -1
- package/dist/react/button.d.ts +1 -1
- package/dist/react/button.js +3 -3
- package/dist/react/button.js.map +1 -1
- package/dist/react/calendar.d.ts +13 -0
- package/dist/react/calendar.js +4639 -0
- package/dist/react/calendar.js.map +1 -0
- package/dist/react/card.d.ts +11 -0
- package/dist/react/card.js +113 -0
- package/dist/react/card.js.map +1 -0
- package/dist/react/checkbox.d.ts +11 -0
- package/dist/react/checkbox.js +129 -0
- package/dist/react/checkbox.js.map +1 -0
- package/dist/react/datetime-picker.d.ts +21 -0
- package/dist/react/datetime-picker.js +6124 -0
- package/dist/react/datetime-picker.js.map +1 -0
- package/dist/react/dialog.js +1 -1
- package/dist/react/dialog.js.map +1 -1
- package/dist/react/dropdown.d.ts +34 -9
- package/dist/react/dropdown.js +295 -144
- package/dist/react/dropdown.js.map +1 -1
- package/dist/react/input.d.ts +7 -0
- package/dist/react/input.js +15 -2
- package/dist/react/input.js.map +1 -1
- package/dist/react/pagination.d.ts +28 -0
- package/dist/react/pagination.js +262 -0
- package/dist/react/pagination.js.map +1 -0
- package/dist/react/popover.d.ts +76 -0
- package/dist/react/popover.js +564 -0
- package/dist/react/popover.js.map +1 -0
- package/dist/react/scroll-header.js +13 -1
- package/dist/react/scroll-header.js.map +1 -1
- package/dist/react/scroll-wheel.d.ts +45 -0
- package/dist/react/scroll-wheel.js +557 -0
- package/dist/react/scroll-wheel.js.map +1 -0
- package/dist/react/select.d.ts +62 -0
- package/dist/react/select.js +889 -0
- package/dist/react/select.js.map +1 -0
- package/dist/react/sheet.js +1 -1
- package/dist/react/sheet.js.map +1 -1
- package/dist/react/switch.d.ts +38 -0
- package/dist/react/switch.js +117 -0
- package/dist/react/switch.js.map +1 -0
- package/dist/react/table-pagination.d.ts +15 -0
- package/dist/react/table-pagination.js +1153 -0
- package/dist/react/table-pagination.js.map +1 -0
- package/dist/react/table-view/column-menu.d.ts +15 -0
- package/dist/react/table-view/column-menu.js +955 -0
- package/dist/react/table-view/column-menu.js.map +1 -0
- package/dist/react/table-view/index.d.ts +70 -0
- package/dist/react/table-view/index.js +2190 -0
- package/dist/react/table-view/index.js.map +1 -0
- package/dist/react/table.d.ts +86 -0
- package/dist/react/table.js +414 -0
- package/dist/react/table.js.map +1 -0
- package/dist/react/tabs.d.ts +9 -3
- package/dist/react/tabs.js +204 -48
- package/dist/react/tabs.js.map +1 -1
- package/dist/react/textarea.d.ts +6 -0
- package/dist/react/textarea.js +33 -0
- package/dist/react/textarea.js.map +1 -0
- package/dist/react/time-picker.d.ts +22 -0
- package/dist/react/time-picker.js +856 -0
- package/dist/react/time-picker.js.map +1 -0
- package/dist/react/tooltip.d.ts +45 -0
- package/dist/react/tooltip.js +540 -0
- package/dist/react/tooltip.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,2190 @@
|
|
|
1
|
+
import * as React5 from 'react';
|
|
2
|
+
import React5__default, { useState, useCallback, forwardRef, useImperativeHandle, memo, useRef, useLayoutEffect, useMemo, useEffect, startTransition } from 'react';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import { X, MoreVertical, ArrowLeft, ArrowRight, ChevronUp, ChevronDown, Pin, PinOff, EyeOff, GripVertical, ArrowDown, ArrowUp } from 'lucide-react';
|
|
7
|
+
import { createPortal } from 'react-dom';
|
|
8
|
+
|
|
9
|
+
// src/react/table-view/meta.ts
|
|
10
|
+
function getTableViewColumnDisableReorder(column) {
|
|
11
|
+
return Boolean(column.columnDef.meta?.tableView?.disableColumnReorder);
|
|
12
|
+
}
|
|
13
|
+
function flexRender(Comp, props) {
|
|
14
|
+
return !Comp ? null : isReactComponent(Comp) ? /* @__PURE__ */ React5.createElement(Comp, props) : Comp;
|
|
15
|
+
}
|
|
16
|
+
function isReactComponent(component) {
|
|
17
|
+
return isClassComponent(component) || typeof component === "function" || isExoticComponent(component);
|
|
18
|
+
}
|
|
19
|
+
function isClassComponent(component) {
|
|
20
|
+
return typeof component === "function" && (() => {
|
|
21
|
+
const proto = Object.getPrototypeOf(component);
|
|
22
|
+
return proto.prototype && proto.prototype.isReactComponent;
|
|
23
|
+
})();
|
|
24
|
+
}
|
|
25
|
+
function isExoticComponent(component) {
|
|
26
|
+
return typeof component === "object" && typeof component.$$typeof === "symbol" && ["react.memo", "react.forward_ref"].includes(component.$$typeof.description);
|
|
27
|
+
}
|
|
28
|
+
function cn(...inputs) {
|
|
29
|
+
return twMerge(clsx(inputs));
|
|
30
|
+
}
|
|
31
|
+
var CHECKBOX_TICK_DELAY_MS = 60;
|
|
32
|
+
var CHECKBOX_TICK_DRAW_MS = 100;
|
|
33
|
+
function CheckboxAnimatedCheckMark() {
|
|
34
|
+
const lineRef = useRef(null);
|
|
35
|
+
useLayoutEffect(() => {
|
|
36
|
+
const poly = lineRef.current;
|
|
37
|
+
if (!poly || typeof poly.getTotalLength !== "function") return;
|
|
38
|
+
const len = poly.getTotalLength();
|
|
39
|
+
if (len <= 0) return;
|
|
40
|
+
poly.style.strokeDasharray = `${len}`;
|
|
41
|
+
poly.style.strokeDashoffset = `${len}`;
|
|
42
|
+
if (typeof poly.animate !== "function") {
|
|
43
|
+
poly.style.strokeDashoffset = "0";
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const anim = poly.animate(
|
|
47
|
+
[{ strokeDashoffset: len }, { strokeDashoffset: 0 }],
|
|
48
|
+
{
|
|
49
|
+
duration: CHECKBOX_TICK_DRAW_MS,
|
|
50
|
+
delay: CHECKBOX_TICK_DELAY_MS,
|
|
51
|
+
easing: "cubic-bezier(0.45, 0, 0.2, 1)",
|
|
52
|
+
fill: "forwards"
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
return () => anim.cancel();
|
|
56
|
+
}, []);
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
"svg",
|
|
59
|
+
{
|
|
60
|
+
className: "size-4 shrink-0 overflow-visible",
|
|
61
|
+
viewBox: "0 0 24 24",
|
|
62
|
+
"aria-hidden": true,
|
|
63
|
+
children: /* @__PURE__ */ jsx(
|
|
64
|
+
"polyline",
|
|
65
|
+
{
|
|
66
|
+
ref: lineRef,
|
|
67
|
+
points: "4 12 9 17 20 6",
|
|
68
|
+
fill: "none",
|
|
69
|
+
stroke: "currentColor",
|
|
70
|
+
strokeWidth: "3",
|
|
71
|
+
strokeLinecap: "round",
|
|
72
|
+
strokeLinejoin: "round"
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
var Checkbox = React5.forwardRef(
|
|
79
|
+
({
|
|
80
|
+
checked: checkedProp,
|
|
81
|
+
defaultChecked = false,
|
|
82
|
+
onCheckedChange,
|
|
83
|
+
indeterminate = false,
|
|
84
|
+
disabled = false,
|
|
85
|
+
className,
|
|
86
|
+
onClick,
|
|
87
|
+
...rest
|
|
88
|
+
}, ref) => {
|
|
89
|
+
const isControlled = checkedProp !== void 0;
|
|
90
|
+
const [uncontrolledChecked, setUncontrolledChecked] = useState(defaultChecked);
|
|
91
|
+
const checked = isControlled ? checkedProp : uncontrolledChecked;
|
|
92
|
+
const ariaChecked = indeterminate ? "mixed" : checked ? true : false;
|
|
93
|
+
return /* @__PURE__ */ jsx(
|
|
94
|
+
"button",
|
|
95
|
+
{
|
|
96
|
+
ref,
|
|
97
|
+
type: "button",
|
|
98
|
+
role: "checkbox",
|
|
99
|
+
"data-slot": "checkbox",
|
|
100
|
+
"data-state": indeterminate ? "indeterminate" : checked ? "checked" : "unchecked",
|
|
101
|
+
disabled,
|
|
102
|
+
"aria-checked": ariaChecked,
|
|
103
|
+
className: cn(
|
|
104
|
+
"ring-offset-background focus-visible:ring-primary/40 inline-flex shrink-0 items-center justify-center rounded-md border border-transparent p-0 outline-none select-none",
|
|
105
|
+
"focus-visible:ring-2 focus-visible:ring-offset-2",
|
|
106
|
+
"disabled:cursor-not-allowed",
|
|
107
|
+
className
|
|
108
|
+
),
|
|
109
|
+
onClick: (e) => {
|
|
110
|
+
onClick?.(e);
|
|
111
|
+
if (e.defaultPrevented) return;
|
|
112
|
+
if (disabled) return;
|
|
113
|
+
if (isControlled) {
|
|
114
|
+
onCheckedChange?.(!checked);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
setUncontrolledChecked((prev) => {
|
|
118
|
+
const next = !prev;
|
|
119
|
+
onCheckedChange?.(next);
|
|
120
|
+
return next;
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
...rest,
|
|
124
|
+
children: /* @__PURE__ */ jsx("span", { className: "pointer-events-none", children: /* @__PURE__ */ jsx(
|
|
125
|
+
"span",
|
|
126
|
+
{
|
|
127
|
+
"aria-hidden": true,
|
|
128
|
+
className: cn(
|
|
129
|
+
"flex size-5 shrink-0 items-center justify-center rounded-[4px] border",
|
|
130
|
+
!disabled && (indeterminate ? "border-primary bg-primary text-background" : checked ? "border-primary bg-primary text-background" : "border-primary/20 bg-background"),
|
|
131
|
+
disabled && (indeterminate ? "border-transparent bg-primary/45 text-primary-foreground" : checked ? "border-transparent bg-primary/45 text-primary-foreground" : "border-primary/10 bg-muted/25")
|
|
132
|
+
),
|
|
133
|
+
children: indeterminate ? /* @__PURE__ */ jsx(
|
|
134
|
+
"span",
|
|
135
|
+
{
|
|
136
|
+
className: "size-2.5 shrink-0 rounded-[2px] border border-primary/20 bg-background",
|
|
137
|
+
"aria-hidden": true
|
|
138
|
+
}
|
|
139
|
+
) : checked ? /* @__PURE__ */ jsx(CheckboxAnimatedCheckMark, {}) : null
|
|
140
|
+
}
|
|
141
|
+
) })
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
Checkbox.displayName = "Checkbox";
|
|
147
|
+
var sizeClass = {
|
|
148
|
+
xs: "h-8 min-h-8 gap-2 px-4 text-sm has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-3",
|
|
149
|
+
default: "h-10 min-h-10 gap-2 px-5 text-sm has-[>svg]:px-4 [&_svg:not([class*='size-'])]:size-4",
|
|
150
|
+
lg: "h-11 min-h-11 gap-2 px-6 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5"
|
|
151
|
+
};
|
|
152
|
+
var iconOnlySizeClass = {
|
|
153
|
+
xs: "size-8 min-h-8 min-w-8 gap-0 p-0 [&_svg:not([class*='size-'])]:size-3",
|
|
154
|
+
default: "size-10 min-h-10 min-w-10 gap-0 p-0 [&_svg:not([class*='size-'])]:size-4",
|
|
155
|
+
lg: "size-11 min-h-11 min-w-11 gap-0 p-0 [&_svg:not([class*='size-'])]:size-5"
|
|
156
|
+
};
|
|
157
|
+
var roundedClass = {
|
|
158
|
+
full: "rounded-full",
|
|
159
|
+
lg: "rounded-lg",
|
|
160
|
+
md: "rounded-md"
|
|
161
|
+
};
|
|
162
|
+
var variantClass = {
|
|
163
|
+
primary: "bg-primary text-background border border-transparent hover:bg-primary/90 active:bg-primary/85",
|
|
164
|
+
secondary: "bg-background text-primary border border-primary/10 hover:bg-primary/5",
|
|
165
|
+
destructive: "bg-background text-red-500 border border-red-500/25 hover:bg-red-500/5",
|
|
166
|
+
success: "bg-background text-green-500 border border-green-500/25 hover:bg-green-500/5"
|
|
167
|
+
};
|
|
168
|
+
var Button = React5.forwardRef(
|
|
169
|
+
({
|
|
170
|
+
className,
|
|
171
|
+
type = "button",
|
|
172
|
+
variant = "secondary",
|
|
173
|
+
rounded: roundedProp,
|
|
174
|
+
size = "default",
|
|
175
|
+
iconOnly = false,
|
|
176
|
+
disabled,
|
|
177
|
+
...props
|
|
178
|
+
}, ref) => {
|
|
179
|
+
const rounded = roundedProp ?? (iconOnly ? "md" : "full");
|
|
180
|
+
return /* @__PURE__ */ jsx(
|
|
181
|
+
"button",
|
|
182
|
+
{
|
|
183
|
+
type,
|
|
184
|
+
disabled,
|
|
185
|
+
"data-slot": "button",
|
|
186
|
+
"data-icon-only": iconOnly ? "" : void 0,
|
|
187
|
+
className: cn(
|
|
188
|
+
"inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap outline-none scale-100 transition-[color,background-color,box-shadow,transform] duration-150 ease-out active:scale-[0.98] active:duration-100 active:ease-linear [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
189
|
+
"disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
190
|
+
"focus-visible:border-ring font-medium lg:tracking-wide focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
191
|
+
iconOnly ? iconOnlySizeClass[size] : sizeClass[size],
|
|
192
|
+
roundedClass[rounded],
|
|
193
|
+
variantClass[variant],
|
|
194
|
+
className
|
|
195
|
+
),
|
|
196
|
+
ref,
|
|
197
|
+
...props
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
Button.displayName = "Button";
|
|
203
|
+
var DROPDOWN_PANEL_OPEN_EASING = "cubic-bezier(0,0.55,0.45,1)";
|
|
204
|
+
var DROPDOWN_PANEL_CLOSE_EASING = "cubic-bezier(0.55,0,1,0.45)";
|
|
205
|
+
var DROPDOWN_MENU_MIN_WIDTH_PX = 192;
|
|
206
|
+
var DROPDOWN_MOBILE_SHEET_MAX_PX = 1024;
|
|
207
|
+
var DROPDOWN_MOBILE_SHEET_MOTION_MS = 175;
|
|
208
|
+
var DROPDOWN_MOBILE_SHEET_ENTRY_EASING = "cubic-bezier(0.85, 0, 0.15, 1)";
|
|
209
|
+
var DROPDOWN_MOBILE_SHEET_EXIT_EASING = "cubic-bezier(0.85, 0, 1, 0.15)";
|
|
210
|
+
var DROPDOWN_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX = 120;
|
|
211
|
+
function resolveDropdownMobileSheet(mobileOptions) {
|
|
212
|
+
return {
|
|
213
|
+
sheet: mobileOptions?.sheet ?? true,
|
|
214
|
+
title: mobileOptions?.title,
|
|
215
|
+
sheetExtraClassName: mobileOptions?.className,
|
|
216
|
+
contentClassName: mobileOptions?.contentClassName
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
var DROPDOWN_SUB_CONTENT_ATTR = "data-dropdown-sub-content";
|
|
220
|
+
var DROPDOWN_PANEL_SHADOW = "shadow-[0_12px_32px_-8px_rgba(0,0,0,0.18),0_2px_6px_-2px_rgba(0,0,0,0.06)] dark:shadow-[0_12px_32px_-8px_rgba(0,0,0,0.55),0_2px_6px_-2px_rgba(0,0,0,0.35)]";
|
|
221
|
+
var DROPDOWN_PANEL_SCROLL = "[&_*]:[scrollbar-width:none] [&_*::-webkit-scrollbar]:hidden [&_*]:overscroll-contain";
|
|
222
|
+
function preventMenuWheelChain(menu, e) {
|
|
223
|
+
let el = e.target;
|
|
224
|
+
while (el && menu.contains(el)) {
|
|
225
|
+
const oy = getComputedStyle(el).overflowY;
|
|
226
|
+
if ((oy === "auto" || oy === "scroll") && el.scrollHeight > el.clientHeight) {
|
|
227
|
+
const atTop = el.scrollTop <= 0;
|
|
228
|
+
const atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight;
|
|
229
|
+
if (e.deltaY < 0 && !atTop || e.deltaY > 0 && !atBottom) return;
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
el = el.parentElement;
|
|
233
|
+
}
|
|
234
|
+
e.preventDefault();
|
|
235
|
+
}
|
|
236
|
+
var DROPDOWN_SHEET_MENU_TEXT = "max-[1024px]:text-base";
|
|
237
|
+
var DROPDOWN_SHEET_MENU_SHORTCUT = "max-[1024px]:text-sm";
|
|
238
|
+
var DROPDOWN_CONTENT_ORIGIN = {
|
|
239
|
+
bottom: "top center",
|
|
240
|
+
top: "bottom center",
|
|
241
|
+
left: "right center",
|
|
242
|
+
right: "left center"
|
|
243
|
+
};
|
|
244
|
+
var DROPDOWN_CONTENT_HIDDEN = {
|
|
245
|
+
bottom: "translateY(-4px) scale(0.97)",
|
|
246
|
+
top: "translateY(4px) scale(0.97)",
|
|
247
|
+
left: "translateX(4px) scale(0.97)",
|
|
248
|
+
right: "translateX(-4px) scale(0.97)"
|
|
249
|
+
};
|
|
250
|
+
function computePos(trigger, menu, side, align, offset, pad) {
|
|
251
|
+
const tr = trigger.getBoundingClientRect();
|
|
252
|
+
const mr = menu.getBoundingClientRect();
|
|
253
|
+
const vw = window.innerWidth;
|
|
254
|
+
const vh = window.innerHeight;
|
|
255
|
+
const sx = window.scrollX;
|
|
256
|
+
const sy = window.scrollY;
|
|
257
|
+
let top = 0;
|
|
258
|
+
let left = 0;
|
|
259
|
+
let effectiveSide = side;
|
|
260
|
+
const calc = (s) => {
|
|
261
|
+
switch (s) {
|
|
262
|
+
case "bottom":
|
|
263
|
+
top = tr.bottom + sy + offset;
|
|
264
|
+
if (align === "start") left = tr.left + sx;
|
|
265
|
+
else if (align === "end") left = tr.right + sx - mr.width;
|
|
266
|
+
else left = tr.left + sx + tr.width / 2 - mr.width / 2;
|
|
267
|
+
break;
|
|
268
|
+
case "top":
|
|
269
|
+
top = tr.top + sy - mr.height - offset;
|
|
270
|
+
if (align === "start") left = tr.left + sx;
|
|
271
|
+
else if (align === "end") left = tr.right + sx - mr.width;
|
|
272
|
+
else left = tr.left + sx + tr.width / 2 - mr.width / 2;
|
|
273
|
+
break;
|
|
274
|
+
case "right":
|
|
275
|
+
left = tr.right + sx + offset;
|
|
276
|
+
if (align === "start") top = tr.top + sy;
|
|
277
|
+
else if (align === "end") top = tr.bottom + sy - mr.height;
|
|
278
|
+
else top = tr.top + sy + tr.height / 2 - mr.height / 2;
|
|
279
|
+
break;
|
|
280
|
+
case "left":
|
|
281
|
+
left = tr.left + sx - mr.width - offset;
|
|
282
|
+
if (align === "start") top = tr.top + sy;
|
|
283
|
+
else if (align === "end") top = tr.bottom + sy - mr.height;
|
|
284
|
+
else top = tr.top + sy + tr.height / 2 - mr.height / 2;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
calc(side);
|
|
289
|
+
if (side === "bottom" && top + mr.height > vh + sy - pad) {
|
|
290
|
+
const ft = tr.top + sy - mr.height - offset;
|
|
291
|
+
if (ft >= sy + pad) {
|
|
292
|
+
effectiveSide = "top";
|
|
293
|
+
top = ft;
|
|
294
|
+
}
|
|
295
|
+
} else if (side === "top" && top < sy + pad) {
|
|
296
|
+
const ft = tr.bottom + sy + offset;
|
|
297
|
+
if (ft + mr.height <= vh + sy - pad) {
|
|
298
|
+
effectiveSide = "bottom";
|
|
299
|
+
top = ft;
|
|
300
|
+
}
|
|
301
|
+
} else if (side === "right" && left + mr.width > vw + sx - pad) {
|
|
302
|
+
const fl = tr.left + sx - mr.width - offset;
|
|
303
|
+
if (fl >= sx + pad) {
|
|
304
|
+
effectiveSide = "left";
|
|
305
|
+
left = fl;
|
|
306
|
+
}
|
|
307
|
+
} else if (side === "left" && left < sx + pad) {
|
|
308
|
+
const fl = tr.right + sx + offset;
|
|
309
|
+
if (fl + mr.width <= vw + sx - pad) {
|
|
310
|
+
effectiveSide = "right";
|
|
311
|
+
left = fl;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
left = Math.max(sx + pad, Math.min(left, vw + sx - mr.width - pad));
|
|
315
|
+
top = Math.max(sy + pad, Math.min(top, vh + sy - mr.height - pad));
|
|
316
|
+
return { top, left, side: effectiveSide };
|
|
317
|
+
}
|
|
318
|
+
function useIsMobile(breakpoint = 1025) {
|
|
319
|
+
const [isMobile, setIsMobile] = useState(() => {
|
|
320
|
+
if (typeof window === "undefined") return false;
|
|
321
|
+
return window.matchMedia(`(max-width: ${breakpoint - 1}px)`).matches;
|
|
322
|
+
});
|
|
323
|
+
useEffect(() => {
|
|
324
|
+
const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
|
|
325
|
+
const handler = (e) => setIsMobile(e.matches);
|
|
326
|
+
mq.addEventListener("change", handler);
|
|
327
|
+
return () => mq.removeEventListener("change", handler);
|
|
328
|
+
}, [breakpoint]);
|
|
329
|
+
return isMobile;
|
|
330
|
+
}
|
|
331
|
+
var DropdownContext = React5__default.createContext(void 0);
|
|
332
|
+
function useDropdown() {
|
|
333
|
+
const ctx = React5__default.useContext(DropdownContext);
|
|
334
|
+
if (!ctx)
|
|
335
|
+
throw new Error("Dropdown components must be used within <Dropdown />");
|
|
336
|
+
return ctx;
|
|
337
|
+
}
|
|
338
|
+
React5__default.createContext(void 0);
|
|
339
|
+
var Dropdown = ({
|
|
340
|
+
children,
|
|
341
|
+
open: controlledOpen,
|
|
342
|
+
onOpenChange
|
|
343
|
+
}) => {
|
|
344
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
345
|
+
const isControlled = controlledOpen !== void 0;
|
|
346
|
+
const open = isControlled ? controlledOpen : internalOpen;
|
|
347
|
+
const triggerRef = useRef(null);
|
|
348
|
+
const [radioValues, setRadioValues] = useState({});
|
|
349
|
+
const setOpen = useCallback(
|
|
350
|
+
(v) => {
|
|
351
|
+
if (!isControlled) setInternalOpen(v);
|
|
352
|
+
onOpenChange?.(v);
|
|
353
|
+
},
|
|
354
|
+
[isControlled, onOpenChange]
|
|
355
|
+
);
|
|
356
|
+
const setRadioValue = useCallback((group, value) => {
|
|
357
|
+
setRadioValues((prev) => ({ ...prev, [group]: value }));
|
|
358
|
+
}, []);
|
|
359
|
+
const ctx = useMemo(
|
|
360
|
+
() => ({ open, setOpen, triggerRef, radioValues, setRadioValue }),
|
|
361
|
+
[open, setOpen, radioValues, setRadioValue]
|
|
362
|
+
);
|
|
363
|
+
return /* @__PURE__ */ jsx(DropdownContext.Provider, { value: ctx, children });
|
|
364
|
+
};
|
|
365
|
+
function mergeTriggerRef(triggerRef, node, childRef) {
|
|
366
|
+
triggerRef.current = node;
|
|
367
|
+
if (typeof childRef === "function") childRef(node);
|
|
368
|
+
else if (childRef && typeof childRef === "object")
|
|
369
|
+
childRef.current = node;
|
|
370
|
+
}
|
|
371
|
+
var DropdownTrigger = React5__default.forwardRef(
|
|
372
|
+
({
|
|
373
|
+
children,
|
|
374
|
+
asChild,
|
|
375
|
+
className,
|
|
376
|
+
onClick: onClickProp,
|
|
377
|
+
disabled,
|
|
378
|
+
...buttonProps
|
|
379
|
+
}, ref) => {
|
|
380
|
+
const { open, setOpen, triggerRef } = useDropdown();
|
|
381
|
+
const handleClick = useCallback(
|
|
382
|
+
(e) => {
|
|
383
|
+
onClickProp?.(e);
|
|
384
|
+
e.stopPropagation();
|
|
385
|
+
if (disabled) return;
|
|
386
|
+
setOpen(!open);
|
|
387
|
+
},
|
|
388
|
+
[disabled, onClickProp, open, setOpen]
|
|
389
|
+
);
|
|
390
|
+
const setButtonRef = useCallback(
|
|
391
|
+
(el) => {
|
|
392
|
+
triggerRef.current = el;
|
|
393
|
+
if (typeof ref === "function") ref(el);
|
|
394
|
+
else if (ref) ref.current = el;
|
|
395
|
+
},
|
|
396
|
+
[ref, triggerRef]
|
|
397
|
+
);
|
|
398
|
+
if (asChild && React5__default.isValidElement(children)) {
|
|
399
|
+
const child = children;
|
|
400
|
+
return React5__default.cloneElement(child, {
|
|
401
|
+
ref: (node) => {
|
|
402
|
+
mergeTriggerRef(
|
|
403
|
+
triggerRef,
|
|
404
|
+
node,
|
|
405
|
+
child.ref
|
|
406
|
+
);
|
|
407
|
+
},
|
|
408
|
+
className: cn("group", child.props.className),
|
|
409
|
+
onClick: (e) => {
|
|
410
|
+
child.props.onClick?.(e);
|
|
411
|
+
handleClick(e);
|
|
412
|
+
},
|
|
413
|
+
"aria-expanded": open,
|
|
414
|
+
"aria-haspopup": "menu",
|
|
415
|
+
"data-state": open ? "open" : "closed",
|
|
416
|
+
...disabled !== void 0 ? {
|
|
417
|
+
disabled
|
|
418
|
+
} : {}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return /* @__PURE__ */ jsx(
|
|
422
|
+
Button,
|
|
423
|
+
{
|
|
424
|
+
ref: setButtonRef,
|
|
425
|
+
type: "button",
|
|
426
|
+
...buttonProps,
|
|
427
|
+
disabled,
|
|
428
|
+
className: cn("group", className),
|
|
429
|
+
"aria-expanded": open,
|
|
430
|
+
"aria-haspopup": "menu",
|
|
431
|
+
"data-state": open ? "open" : "closed",
|
|
432
|
+
onClick: handleClick,
|
|
433
|
+
children
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
DropdownTrigger.displayName = "DropdownTrigger";
|
|
439
|
+
var DropdownMobileClose = React5__default.forwardRef(({ className, type = "button", ...props }, ref) => {
|
|
440
|
+
return /* @__PURE__ */ jsxs(
|
|
441
|
+
"button",
|
|
442
|
+
{
|
|
443
|
+
ref,
|
|
444
|
+
type,
|
|
445
|
+
className: cn(
|
|
446
|
+
"z-100 flex size-12 shrink-0 cursor-pointer items-center justify-center rounded-full transition-all hover:bg-secondary-background active:scale-[0.96]",
|
|
447
|
+
className
|
|
448
|
+
),
|
|
449
|
+
...props,
|
|
450
|
+
children: [
|
|
451
|
+
/* @__PURE__ */ jsx(X, { className: "size-5.5" }),
|
|
452
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
453
|
+
]
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
});
|
|
457
|
+
DropdownMobileClose.displayName = "DropdownMobileClose";
|
|
458
|
+
function DropdownMobileBottomSheetPortal({
|
|
459
|
+
open,
|
|
460
|
+
isAnimating,
|
|
461
|
+
slideEntrance,
|
|
462
|
+
slideOffsetPx,
|
|
463
|
+
sheetTitle,
|
|
464
|
+
sheetExtraClassName,
|
|
465
|
+
contentClassName,
|
|
466
|
+
onRequestClose,
|
|
467
|
+
menuRef,
|
|
468
|
+
portalZClassName = "z-50",
|
|
469
|
+
isSubPortal = false,
|
|
470
|
+
children,
|
|
471
|
+
className,
|
|
472
|
+
style,
|
|
473
|
+
...panelProps
|
|
474
|
+
}) {
|
|
475
|
+
const sheetMotion = open ? DROPDOWN_MOBILE_SHEET_ENTRY_EASING : DROPDOWN_MOBILE_SHEET_EXIT_EASING;
|
|
476
|
+
const sheetHiddenTransform = slideEntrance ? `translateY(${slideOffsetPx}px)` : "translateY(100%)";
|
|
477
|
+
return createPortal(
|
|
478
|
+
/* @__PURE__ */ jsxs(
|
|
479
|
+
"div",
|
|
480
|
+
{
|
|
481
|
+
...isSubPortal ? { [DROPDOWN_SUB_CONTENT_ATTR]: "" } : {},
|
|
482
|
+
className: cn(
|
|
483
|
+
"fixed inset-0 flex items-end justify-center p-0",
|
|
484
|
+
portalZClassName
|
|
485
|
+
),
|
|
486
|
+
children: [
|
|
487
|
+
/* @__PURE__ */ jsx(
|
|
488
|
+
"div",
|
|
489
|
+
{
|
|
490
|
+
className: cn(
|
|
491
|
+
"fixed inset-0 bg-black/40 dark:bg-black/60",
|
|
492
|
+
isAnimating ? "opacity-100" : "opacity-0"
|
|
493
|
+
),
|
|
494
|
+
style: {
|
|
495
|
+
transitionProperty: "opacity",
|
|
496
|
+
transitionDuration: `${DROPDOWN_MOBILE_SHEET_MOTION_MS}ms`,
|
|
497
|
+
transitionTimingFunction: sheetMotion
|
|
498
|
+
},
|
|
499
|
+
onClick: onRequestClose
|
|
500
|
+
}
|
|
501
|
+
),
|
|
502
|
+
/* @__PURE__ */ jsxs(
|
|
503
|
+
"div",
|
|
504
|
+
{
|
|
505
|
+
...panelProps,
|
|
506
|
+
ref: menuRef,
|
|
507
|
+
className: cn(
|
|
508
|
+
"bg-background border-primary/8 relative z-10 flex w-full max-h-[min(90dvh,calc(100dvh-env(safe-area-inset-bottom,0px)))] flex-col overflow-hidden shadow-2xl outline-none",
|
|
509
|
+
"rounded-t-2xl rounded-b-none border-x-0 border-b-0 border-t",
|
|
510
|
+
DROPDOWN_PANEL_SCROLL,
|
|
511
|
+
sheetExtraClassName,
|
|
512
|
+
className
|
|
513
|
+
),
|
|
514
|
+
style: {
|
|
515
|
+
transform: isAnimating ? "translateY(0)" : sheetHiddenTransform,
|
|
516
|
+
opacity: isAnimating ? 1 : 0,
|
|
517
|
+
transitionProperty: "transform, opacity",
|
|
518
|
+
transitionDuration: `${DROPDOWN_MOBILE_SHEET_MOTION_MS}ms`,
|
|
519
|
+
transitionTimingFunction: sheetMotion,
|
|
520
|
+
...style
|
|
521
|
+
},
|
|
522
|
+
children: [
|
|
523
|
+
/* @__PURE__ */ jsxs(
|
|
524
|
+
"div",
|
|
525
|
+
{
|
|
526
|
+
className: cn(
|
|
527
|
+
"flex w-full shrink-0 items-center py-2 pl-4 pr-2",
|
|
528
|
+
sheetTitle ? "justify-between gap-3" : "justify-end"
|
|
529
|
+
),
|
|
530
|
+
children: [
|
|
531
|
+
sheetTitle ? /* @__PURE__ */ jsx("p", { className: "text-foreground min-w-0 flex-1 truncate text-base font-semibold", children: sheetTitle }) : null,
|
|
532
|
+
/* @__PURE__ */ jsx(
|
|
533
|
+
DropdownMobileClose,
|
|
534
|
+
{
|
|
535
|
+
onClick: (e) => {
|
|
536
|
+
e.stopPropagation();
|
|
537
|
+
onRequestClose();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
)
|
|
541
|
+
]
|
|
542
|
+
}
|
|
543
|
+
),
|
|
544
|
+
/* @__PURE__ */ jsx(
|
|
545
|
+
"div",
|
|
546
|
+
{
|
|
547
|
+
className: cn(
|
|
548
|
+
"min-h-0 flex-1 overflow-y-auto pb-[calc(5rem+env(safe-area-inset-bottom,0px))]",
|
|
549
|
+
contentClassName
|
|
550
|
+
),
|
|
551
|
+
children
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
]
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
),
|
|
560
|
+
document.body
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
var DropdownContent = ({
|
|
564
|
+
children,
|
|
565
|
+
side = "bottom",
|
|
566
|
+
align = "start",
|
|
567
|
+
offset = 10,
|
|
568
|
+
duration = 80,
|
|
569
|
+
viewportPadding = 8,
|
|
570
|
+
closeOnEscape = true,
|
|
571
|
+
minWidth = "trigger",
|
|
572
|
+
loop = true,
|
|
573
|
+
mobileOptions,
|
|
574
|
+
slideEntrance = true,
|
|
575
|
+
slideEntranceOffsetPx: slideEntranceOffsetPxProp,
|
|
576
|
+
className,
|
|
577
|
+
style,
|
|
578
|
+
...props
|
|
579
|
+
}) => {
|
|
580
|
+
const isMobile = useIsMobile(DROPDOWN_MOBILE_SHEET_MAX_PX + 1);
|
|
581
|
+
const { open, setOpen, triggerRef } = useDropdown();
|
|
582
|
+
const [shouldRender, setShouldRender] = useState(false);
|
|
583
|
+
const [isAnimating, setIsAnimating] = useState(false);
|
|
584
|
+
const [pos, setPos] = useState({ top: -9999, left: -9999, side });
|
|
585
|
+
const [triggerW, setTriggerW] = useState(0);
|
|
586
|
+
const menuRef = useRef(null);
|
|
587
|
+
const resolvedMobile = resolveDropdownMobileSheet(mobileOptions);
|
|
588
|
+
const isMobileSheet = isMobile && resolvedMobile.sheet;
|
|
589
|
+
const slideOffsetPx = slideEntranceOffsetPxProp ?? DROPDOWN_MOBILE_SHEET_SLIDE_ENTRANCE_OFFSET_DEFAULT_PX;
|
|
590
|
+
useEffect(() => {
|
|
591
|
+
if (open) {
|
|
592
|
+
setShouldRender(true);
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (!isMobileSheet) {
|
|
596
|
+
setShouldRender(false);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
setIsAnimating(false);
|
|
600
|
+
const t = setTimeout(
|
|
601
|
+
() => setShouldRender(false),
|
|
602
|
+
DROPDOWN_MOBILE_SHEET_MOTION_MS
|
|
603
|
+
);
|
|
604
|
+
return () => clearTimeout(t);
|
|
605
|
+
}, [open, isMobileSheet]);
|
|
606
|
+
useEffect(() => {
|
|
607
|
+
if (!shouldRender || !open) return;
|
|
608
|
+
let raf2 = 0;
|
|
609
|
+
const raf1 = requestAnimationFrame(() => {
|
|
610
|
+
raf2 = requestAnimationFrame(() => setIsAnimating(true));
|
|
611
|
+
});
|
|
612
|
+
return () => {
|
|
613
|
+
cancelAnimationFrame(raf1);
|
|
614
|
+
if (raf2) cancelAnimationFrame(raf2);
|
|
615
|
+
};
|
|
616
|
+
}, [shouldRender, open]);
|
|
617
|
+
useLayoutEffect(() => {
|
|
618
|
+
if (!shouldRender || !triggerRef.current || !menuRef.current) return;
|
|
619
|
+
const update = () => {
|
|
620
|
+
if (!triggerRef.current || !menuRef.current) return;
|
|
621
|
+
setTriggerW(triggerRef.current.getBoundingClientRect().width);
|
|
622
|
+
setPos(
|
|
623
|
+
computePos(
|
|
624
|
+
triggerRef.current,
|
|
625
|
+
menuRef.current,
|
|
626
|
+
side,
|
|
627
|
+
align,
|
|
628
|
+
offset,
|
|
629
|
+
viewportPadding
|
|
630
|
+
)
|
|
631
|
+
);
|
|
632
|
+
};
|
|
633
|
+
update();
|
|
634
|
+
window.addEventListener("resize", update);
|
|
635
|
+
return () => {
|
|
636
|
+
window.removeEventListener("resize", update);
|
|
637
|
+
};
|
|
638
|
+
}, [shouldRender, side, align, offset, viewportPadding]);
|
|
639
|
+
useEffect(() => {
|
|
640
|
+
if (!open || isMobileSheet) return;
|
|
641
|
+
const isInsideMenu = (t) => t instanceof Node && (!!menuRef.current?.contains(t) || !!triggerRef.current?.contains(t) || t instanceof Element && !!t.closest(`[${DROPDOWN_SUB_CONTENT_ATTR}]`));
|
|
642
|
+
const onScroll = (e) => {
|
|
643
|
+
if (!isInsideMenu(e.target)) setOpen(false);
|
|
644
|
+
};
|
|
645
|
+
window.addEventListener("scroll", onScroll, true);
|
|
646
|
+
return () => window.removeEventListener("scroll", onScroll, true);
|
|
647
|
+
}, [open, isMobileSheet, setOpen, triggerRef]);
|
|
648
|
+
useEffect(() => {
|
|
649
|
+
if (!shouldRender || isMobileSheet) return;
|
|
650
|
+
const menu = menuRef.current;
|
|
651
|
+
if (!menu) return;
|
|
652
|
+
const onWheel = (e) => preventMenuWheelChain(menu, e);
|
|
653
|
+
menu.addEventListener("wheel", onWheel, { passive: false });
|
|
654
|
+
return () => menu.removeEventListener("wheel", onWheel);
|
|
655
|
+
}, [shouldRender, isMobileSheet]);
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
if (isAnimating && menuRef.current) {
|
|
658
|
+
menuRef.current.focus();
|
|
659
|
+
}
|
|
660
|
+
}, [isAnimating]);
|
|
661
|
+
useEffect(() => {
|
|
662
|
+
if (!open) return;
|
|
663
|
+
const handler = (e) => {
|
|
664
|
+
const t = e.target;
|
|
665
|
+
if (menuRef.current?.contains(t) || triggerRef.current?.contains(t))
|
|
666
|
+
return;
|
|
667
|
+
const el = e.target instanceof Element ? e.target : null;
|
|
668
|
+
if (el?.closest?.(`[${DROPDOWN_SUB_CONTENT_ATTR}]`)) return;
|
|
669
|
+
setOpen(false);
|
|
670
|
+
};
|
|
671
|
+
document.addEventListener("mousedown", handler);
|
|
672
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
673
|
+
}, [open, setOpen, triggerRef]);
|
|
674
|
+
useEffect(() => {
|
|
675
|
+
if (!open) return;
|
|
676
|
+
const handler = (e) => {
|
|
677
|
+
const menu = menuRef.current;
|
|
678
|
+
if (!menu) return;
|
|
679
|
+
const focusedEl = document.activeElement;
|
|
680
|
+
if (focusedEl && !menu.contains(focusedEl)) return;
|
|
681
|
+
const items = getItems(menu);
|
|
682
|
+
const idx = items.indexOf(focusedEl);
|
|
683
|
+
switch (e.key) {
|
|
684
|
+
case "Escape":
|
|
685
|
+
if (closeOnEscape) {
|
|
686
|
+
e.preventDefault();
|
|
687
|
+
setOpen(false);
|
|
688
|
+
triggerRef.current?.focus();
|
|
689
|
+
}
|
|
690
|
+
break;
|
|
691
|
+
case "ArrowDown":
|
|
692
|
+
e.preventDefault();
|
|
693
|
+
if (items.length === 0) break;
|
|
694
|
+
if (idx === -1 || idx === items.length - 1 && loop)
|
|
695
|
+
items[0]?.focus();
|
|
696
|
+
else if (idx < items.length - 1) items[idx + 1]?.focus();
|
|
697
|
+
break;
|
|
698
|
+
case "ArrowUp":
|
|
699
|
+
e.preventDefault();
|
|
700
|
+
if (items.length === 0) break;
|
|
701
|
+
if (idx <= 0 && loop) items[items.length - 1]?.focus();
|
|
702
|
+
else if (idx > 0) items[idx - 1]?.focus();
|
|
703
|
+
break;
|
|
704
|
+
case "Home":
|
|
705
|
+
e.preventDefault();
|
|
706
|
+
items[0]?.focus();
|
|
707
|
+
break;
|
|
708
|
+
case "End":
|
|
709
|
+
e.preventDefault();
|
|
710
|
+
items[items.length - 1]?.focus();
|
|
711
|
+
break;
|
|
712
|
+
case "Tab":
|
|
713
|
+
setOpen(false);
|
|
714
|
+
break;
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
window.addEventListener("keydown", handler);
|
|
718
|
+
return () => window.removeEventListener("keydown", handler);
|
|
719
|
+
}, [open, closeOnEscape, loop, setOpen, triggerRef]);
|
|
720
|
+
useEffect(() => {
|
|
721
|
+
if (!open || !isMobileSheet) return;
|
|
722
|
+
document.body.style.overflow = "hidden";
|
|
723
|
+
return () => {
|
|
724
|
+
document.body.style.overflow = "";
|
|
725
|
+
};
|
|
726
|
+
}, [open, isMobileSheet]);
|
|
727
|
+
if (!shouldRender || typeof document === "undefined") return null;
|
|
728
|
+
if (isMobileSheet) {
|
|
729
|
+
return /* @__PURE__ */ jsx(
|
|
730
|
+
DropdownMobileBottomSheetPortal,
|
|
731
|
+
{
|
|
732
|
+
...props,
|
|
733
|
+
open,
|
|
734
|
+
isAnimating,
|
|
735
|
+
slideEntrance,
|
|
736
|
+
slideOffsetPx,
|
|
737
|
+
sheetTitle: resolvedMobile.title,
|
|
738
|
+
sheetExtraClassName: resolvedMobile.sheetExtraClassName,
|
|
739
|
+
contentClassName: resolvedMobile.contentClassName,
|
|
740
|
+
onRequestClose: () => setOpen(false),
|
|
741
|
+
menuRef,
|
|
742
|
+
portalZClassName: "z-50",
|
|
743
|
+
className,
|
|
744
|
+
style,
|
|
745
|
+
role: "menu",
|
|
746
|
+
"aria-orientation": "vertical",
|
|
747
|
+
tabIndex: -1,
|
|
748
|
+
children
|
|
749
|
+
}
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
const resolvedMinW = minWidth === "trigger" ? Math.max(triggerW, DROPDOWN_MENU_MIN_WIDTH_PX) : minWidth;
|
|
753
|
+
return createPortal(
|
|
754
|
+
/* @__PURE__ */ jsx(
|
|
755
|
+
"div",
|
|
756
|
+
{
|
|
757
|
+
...props,
|
|
758
|
+
ref: menuRef,
|
|
759
|
+
role: "menu",
|
|
760
|
+
"aria-orientation": "vertical",
|
|
761
|
+
tabIndex: -1,
|
|
762
|
+
className: cn(
|
|
763
|
+
"bg-background border-primary/8 absolute z-50 overflow-hidden rounded-xl border py-1.5 outline-none",
|
|
764
|
+
DROPDOWN_PANEL_SHADOW,
|
|
765
|
+
DROPDOWN_PANEL_SCROLL,
|
|
766
|
+
className
|
|
767
|
+
),
|
|
768
|
+
style: {
|
|
769
|
+
position: "absolute",
|
|
770
|
+
top: pos.top,
|
|
771
|
+
left: pos.left,
|
|
772
|
+
minWidth: resolvedMinW,
|
|
773
|
+
transformOrigin: DROPDOWN_CONTENT_ORIGIN[pos.side],
|
|
774
|
+
transform: isAnimating ? "none" : DROPDOWN_CONTENT_HIDDEN[pos.side],
|
|
775
|
+
opacity: isAnimating ? 1 : 0,
|
|
776
|
+
transitionProperty: "opacity, transform",
|
|
777
|
+
transitionDuration: `${duration}ms`,
|
|
778
|
+
transitionTimingFunction: isAnimating ? DROPDOWN_PANEL_OPEN_EASING : DROPDOWN_PANEL_CLOSE_EASING,
|
|
779
|
+
...style
|
|
780
|
+
},
|
|
781
|
+
children
|
|
782
|
+
}
|
|
783
|
+
),
|
|
784
|
+
document.body
|
|
785
|
+
);
|
|
786
|
+
};
|
|
787
|
+
function getItems(menu) {
|
|
788
|
+
return Array.from(
|
|
789
|
+
menu.querySelectorAll(
|
|
790
|
+
'[role="menuitem"]:not([aria-disabled="true"]),[role="menuitemcheckbox"]:not([aria-disabled="true"]),[role="menuitemradio"]:not([aria-disabled="true"])'
|
|
791
|
+
)
|
|
792
|
+
);
|
|
793
|
+
}
|
|
794
|
+
var DropdownItem = ({
|
|
795
|
+
children,
|
|
796
|
+
disabled = false,
|
|
797
|
+
destructive = false,
|
|
798
|
+
icon,
|
|
799
|
+
shortcut,
|
|
800
|
+
closeOnSelect = true,
|
|
801
|
+
inset = false,
|
|
802
|
+
className,
|
|
803
|
+
onClick,
|
|
804
|
+
...props
|
|
805
|
+
}) => {
|
|
806
|
+
const { setOpen } = useDropdown();
|
|
807
|
+
const handleClick = (e) => {
|
|
808
|
+
if (disabled) return;
|
|
809
|
+
onClick?.(e);
|
|
810
|
+
if (closeOnSelect) setOpen(false);
|
|
811
|
+
};
|
|
812
|
+
const handleKeyDown = (e) => {
|
|
813
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
814
|
+
e.preventDefault();
|
|
815
|
+
handleClick(e);
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
return /* @__PURE__ */ jsxs(
|
|
819
|
+
"div",
|
|
820
|
+
{
|
|
821
|
+
...props,
|
|
822
|
+
role: "menuitem",
|
|
823
|
+
tabIndex: disabled ? void 0 : -1,
|
|
824
|
+
"aria-disabled": disabled,
|
|
825
|
+
onClick: handleClick,
|
|
826
|
+
onKeyDown: handleKeyDown,
|
|
827
|
+
className: cn(
|
|
828
|
+
"relative mx-1.5 flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors duration-0 outline-none select-none",
|
|
829
|
+
DROPDOWN_SHEET_MENU_TEXT,
|
|
830
|
+
inset && "pl-9",
|
|
831
|
+
!disabled && "cursor-pointer",
|
|
832
|
+
disabled && "lg:cursor-not-allowed",
|
|
833
|
+
!disabled && !destructive && "text-foreground hover:bg-primary/8 focus-visible:bg-primary/8 dark:hover:bg-primary/4 dark:focus-visible:bg-primary/4",
|
|
834
|
+
!disabled && destructive && "text-destructive hover:bg-destructive/10 focus-visible:bg-destructive/10 dark:text-destructive-foreground dark:hover:bg-destructive-foreground/18 dark:focus-visible:bg-destructive-foreground/18",
|
|
835
|
+
disabled && !destructive && "text-foreground/45 dark:text-foreground/50",
|
|
836
|
+
disabled && destructive && "bg-destructive/5 text-destructive/75 dark:bg-destructive-foreground/12 dark:text-destructive-foreground/78",
|
|
837
|
+
className
|
|
838
|
+
),
|
|
839
|
+
children: [
|
|
840
|
+
icon && /* @__PURE__ */ jsx("span", { className: "flex size-4 shrink-0 items-center justify-center", children: icon }),
|
|
841
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children }),
|
|
842
|
+
shortcut ? /* @__PURE__ */ jsx(
|
|
843
|
+
"span",
|
|
844
|
+
{
|
|
845
|
+
className: cn(
|
|
846
|
+
"ml-auto text-xs tracking-widest",
|
|
847
|
+
DROPDOWN_SHEET_MENU_SHORTCUT,
|
|
848
|
+
destructive ? "text-destructive/70 dark:text-destructive-foreground/80" : "opacity-40"
|
|
849
|
+
),
|
|
850
|
+
children: shortcut
|
|
851
|
+
}
|
|
852
|
+
) : null
|
|
853
|
+
]
|
|
854
|
+
}
|
|
855
|
+
);
|
|
856
|
+
};
|
|
857
|
+
var DropdownSeparator = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
858
|
+
"div",
|
|
859
|
+
{
|
|
860
|
+
role: "separator",
|
|
861
|
+
className: cn("border-primary/10 my-1.5 border-t", className),
|
|
862
|
+
...props
|
|
863
|
+
}
|
|
864
|
+
);
|
|
865
|
+
React5__default.createContext(
|
|
866
|
+
void 0
|
|
867
|
+
);
|
|
868
|
+
|
|
869
|
+
// src/react/table-view/helpers.ts
|
|
870
|
+
function getSelectedRowIds(table) {
|
|
871
|
+
return table.getSelectedRowModel().rows.map((r) => r.id);
|
|
872
|
+
}
|
|
873
|
+
function moveColumnInOrder(order, sourceId, targetId) {
|
|
874
|
+
const from = order.indexOf(sourceId);
|
|
875
|
+
const to = order.indexOf(targetId);
|
|
876
|
+
if (from < 0 || to < 0 || from === to) return order;
|
|
877
|
+
const next = [...order];
|
|
878
|
+
const [moved] = next.splice(from, 1);
|
|
879
|
+
if (moved) next.splice(to, 0, moved);
|
|
880
|
+
return next;
|
|
881
|
+
}
|
|
882
|
+
function getColumnHeaderLabel(header) {
|
|
883
|
+
const h = header.column.columnDef.header;
|
|
884
|
+
if (typeof h === "string") return h;
|
|
885
|
+
return header.column.id;
|
|
886
|
+
}
|
|
887
|
+
function getTableLeafColumnOrderList(table) {
|
|
888
|
+
const o = table.getState().columnOrder;
|
|
889
|
+
if (o && o.length > 0) return [...o];
|
|
890
|
+
return table.getVisibleLeafColumns().map((c) => c.id);
|
|
891
|
+
}
|
|
892
|
+
function moveTableColumnOneStep(table, columnId, direction) {
|
|
893
|
+
const list = getTableLeafColumnOrderList(table);
|
|
894
|
+
const i = list.indexOf(columnId);
|
|
895
|
+
if (i < 0) return;
|
|
896
|
+
const next = [...list];
|
|
897
|
+
if (direction === "left" && i > 0) {
|
|
898
|
+
[next[i - 1], next[i]] = [next[i], next[i - 1]];
|
|
899
|
+
} else if (direction === "right" && i < next.length - 1) {
|
|
900
|
+
[next[i + 1], next[i]] = [next[i], next[i + 1]];
|
|
901
|
+
} else {
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
table.setColumnOrder(next);
|
|
905
|
+
}
|
|
906
|
+
function getColumnPinningStyle(column) {
|
|
907
|
+
const pin = column.getIsPinned();
|
|
908
|
+
if (!pin) return {};
|
|
909
|
+
const left = pin === "left" ? column.getStart("left") : void 0;
|
|
910
|
+
const right = pin === "right" ? column.getAfter("right") : void 0;
|
|
911
|
+
const zi = 20 + (column.getPinnedIndex() >= 0 ? column.getPinnedIndex() : 0);
|
|
912
|
+
return {
|
|
913
|
+
position: "sticky",
|
|
914
|
+
left: left == null ? void 0 : `${left}px`,
|
|
915
|
+
right: right == null ? void 0 : `${right}px`,
|
|
916
|
+
zIndex: zi
|
|
917
|
+
};
|
|
918
|
+
}
|
|
919
|
+
function getColumnPinningClassName(column) {
|
|
920
|
+
return column.getIsPinned() ? "bg-background" : void 0;
|
|
921
|
+
}
|
|
922
|
+
var ColumnHeaderMenuInner = forwardRef(function ColumnHeaderMenuInner2({ table, header, columnSort, columnReorder }, ref) {
|
|
923
|
+
const [open, setOpen] = useState(false);
|
|
924
|
+
useImperativeHandle(
|
|
925
|
+
ref,
|
|
926
|
+
() => ({
|
|
927
|
+
open: () => {
|
|
928
|
+
setOpen(true);
|
|
929
|
+
}
|
|
930
|
+
}),
|
|
931
|
+
[]
|
|
932
|
+
);
|
|
933
|
+
const col = header.column;
|
|
934
|
+
const id = col.id;
|
|
935
|
+
const canPin = col.getCanPin();
|
|
936
|
+
const pin = col.getIsPinned();
|
|
937
|
+
const list = getTableLeafColumnOrderList(table);
|
|
938
|
+
const idx = list.indexOf(id);
|
|
939
|
+
const reorderLocked = getTableViewColumnDisableReorder(col);
|
|
940
|
+
const canMoveLeft = columnReorder && !reorderLocked && idx > 0;
|
|
941
|
+
const canMoveRight = columnReorder && !reorderLocked && idx >= 0 && idx < list.length - 1;
|
|
942
|
+
const canSort = columnSort && col.getCanSort();
|
|
943
|
+
const hasMoveSection = canMoveLeft || canMoveRight;
|
|
944
|
+
const hasSortSection = !!canSort;
|
|
945
|
+
const hasPinSection = canPin;
|
|
946
|
+
const hasHideSection = col.getCanHide();
|
|
947
|
+
if (!hasMoveSection && !hasSortSection && !hasPinSection && !hasHideSection) {
|
|
948
|
+
return null;
|
|
949
|
+
}
|
|
950
|
+
const showSepBeforeHide = hasHideSection && (hasMoveSection || hasSortSection || hasPinSection);
|
|
951
|
+
return /* @__PURE__ */ jsx(
|
|
952
|
+
"div",
|
|
953
|
+
{
|
|
954
|
+
className: cn(
|
|
955
|
+
"flex shrink-0 self-stretch items-center",
|
|
956
|
+
"opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 has-[[data-state=open]]:opacity-100"
|
|
957
|
+
),
|
|
958
|
+
onClick: (e) => e.stopPropagation(),
|
|
959
|
+
children: /* @__PURE__ */ jsxs(Dropdown, { open, onOpenChange: setOpen, children: [
|
|
960
|
+
/* @__PURE__ */ jsx(DropdownTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
961
|
+
Button,
|
|
962
|
+
{
|
|
963
|
+
type: "button",
|
|
964
|
+
size: "xs",
|
|
965
|
+
iconOnly: true,
|
|
966
|
+
rounded: "full",
|
|
967
|
+
className: "touch-manipulation border-none bg-transparent shadow-none",
|
|
968
|
+
"aria-label": "Column options",
|
|
969
|
+
children: /* @__PURE__ */ jsx(MoreVertical, { className: "size-3.5", strokeWidth: 2.25, "aria-hidden": true })
|
|
970
|
+
}
|
|
971
|
+
) }),
|
|
972
|
+
/* @__PURE__ */ jsxs(DropdownContent, { align: "end", side: "bottom", offset: 4, children: [
|
|
973
|
+
hasMoveSection ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
974
|
+
/* @__PURE__ */ jsx(
|
|
975
|
+
DropdownItem,
|
|
976
|
+
{
|
|
977
|
+
disabled: !canMoveLeft,
|
|
978
|
+
icon: /* @__PURE__ */ jsx(
|
|
979
|
+
ArrowLeft,
|
|
980
|
+
{
|
|
981
|
+
className: "size-3.5",
|
|
982
|
+
strokeWidth: 2.25,
|
|
983
|
+
"aria-hidden": true
|
|
984
|
+
}
|
|
985
|
+
),
|
|
986
|
+
onClick: () => {
|
|
987
|
+
if (canMoveLeft) moveTableColumnOneStep(table, id, "left");
|
|
988
|
+
},
|
|
989
|
+
children: "Move to the left"
|
|
990
|
+
}
|
|
991
|
+
),
|
|
992
|
+
/* @__PURE__ */ jsx(
|
|
993
|
+
DropdownItem,
|
|
994
|
+
{
|
|
995
|
+
disabled: !canMoveRight,
|
|
996
|
+
icon: /* @__PURE__ */ jsx(
|
|
997
|
+
ArrowRight,
|
|
998
|
+
{
|
|
999
|
+
className: "size-3.5",
|
|
1000
|
+
strokeWidth: 2.25,
|
|
1001
|
+
"aria-hidden": true
|
|
1002
|
+
}
|
|
1003
|
+
),
|
|
1004
|
+
onClick: () => {
|
|
1005
|
+
if (canMoveRight) moveTableColumnOneStep(table, id, "right");
|
|
1006
|
+
},
|
|
1007
|
+
children: "Move to the right"
|
|
1008
|
+
}
|
|
1009
|
+
)
|
|
1010
|
+
] }) : null,
|
|
1011
|
+
hasMoveSection && (hasSortSection || hasPinSection) ? /* @__PURE__ */ jsx(DropdownSeparator, {}) : null,
|
|
1012
|
+
hasSortSection ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1013
|
+
/* @__PURE__ */ jsx(
|
|
1014
|
+
DropdownItem,
|
|
1015
|
+
{
|
|
1016
|
+
icon: /* @__PURE__ */ jsx(
|
|
1017
|
+
ChevronUp,
|
|
1018
|
+
{
|
|
1019
|
+
className: "size-3.5",
|
|
1020
|
+
strokeWidth: 2.25,
|
|
1021
|
+
"aria-hidden": true
|
|
1022
|
+
}
|
|
1023
|
+
),
|
|
1024
|
+
onClick: () => {
|
|
1025
|
+
col.toggleSorting(false);
|
|
1026
|
+
},
|
|
1027
|
+
children: "Sort ascending"
|
|
1028
|
+
}
|
|
1029
|
+
),
|
|
1030
|
+
/* @__PURE__ */ jsx(
|
|
1031
|
+
DropdownItem,
|
|
1032
|
+
{
|
|
1033
|
+
icon: /* @__PURE__ */ jsx(
|
|
1034
|
+
ChevronDown,
|
|
1035
|
+
{
|
|
1036
|
+
className: "size-3.5",
|
|
1037
|
+
strokeWidth: 2.25,
|
|
1038
|
+
"aria-hidden": true
|
|
1039
|
+
}
|
|
1040
|
+
),
|
|
1041
|
+
onClick: () => {
|
|
1042
|
+
col.toggleSorting(true);
|
|
1043
|
+
},
|
|
1044
|
+
children: "Sort descending"
|
|
1045
|
+
}
|
|
1046
|
+
)
|
|
1047
|
+
] }) : null,
|
|
1048
|
+
hasSortSection && hasPinSection ? /* @__PURE__ */ jsx(DropdownSeparator, {}) : null,
|
|
1049
|
+
hasPinSection ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1050
|
+
pin !== "left" ? /* @__PURE__ */ jsx(
|
|
1051
|
+
DropdownItem,
|
|
1052
|
+
{
|
|
1053
|
+
icon: /* @__PURE__ */ jsx(Pin, { className: "size-3.5", strokeWidth: 2.25, "aria-hidden": true }),
|
|
1054
|
+
onClick: () => {
|
|
1055
|
+
col.pin("left");
|
|
1056
|
+
},
|
|
1057
|
+
children: "Pin to the left"
|
|
1058
|
+
}
|
|
1059
|
+
) : null,
|
|
1060
|
+
pin !== "right" ? /* @__PURE__ */ jsx(
|
|
1061
|
+
DropdownItem,
|
|
1062
|
+
{
|
|
1063
|
+
icon: /* @__PURE__ */ jsx(
|
|
1064
|
+
Pin,
|
|
1065
|
+
{
|
|
1066
|
+
className: "size-3.5 -scale-x-100",
|
|
1067
|
+
strokeWidth: 2.25,
|
|
1068
|
+
"aria-hidden": true
|
|
1069
|
+
}
|
|
1070
|
+
),
|
|
1071
|
+
onClick: () => {
|
|
1072
|
+
col.pin("right");
|
|
1073
|
+
},
|
|
1074
|
+
children: "Pin to the right"
|
|
1075
|
+
}
|
|
1076
|
+
) : null,
|
|
1077
|
+
pin ? /* @__PURE__ */ jsx(
|
|
1078
|
+
DropdownItem,
|
|
1079
|
+
{
|
|
1080
|
+
icon: /* @__PURE__ */ jsx(
|
|
1081
|
+
PinOff,
|
|
1082
|
+
{
|
|
1083
|
+
className: "size-3.5",
|
|
1084
|
+
strokeWidth: 2.25,
|
|
1085
|
+
"aria-hidden": true
|
|
1086
|
+
}
|
|
1087
|
+
),
|
|
1088
|
+
onClick: () => {
|
|
1089
|
+
col.pin(false);
|
|
1090
|
+
},
|
|
1091
|
+
children: "Unpin column"
|
|
1092
|
+
}
|
|
1093
|
+
) : null
|
|
1094
|
+
] }) : null,
|
|
1095
|
+
showSepBeforeHide ? /* @__PURE__ */ jsx(DropdownSeparator, {}) : null,
|
|
1096
|
+
hasHideSection ? /* @__PURE__ */ jsx(
|
|
1097
|
+
DropdownItem,
|
|
1098
|
+
{
|
|
1099
|
+
icon: /* @__PURE__ */ jsx(EyeOff, { className: "size-3.5", strokeWidth: 2.25, "aria-hidden": true }),
|
|
1100
|
+
onClick: () => {
|
|
1101
|
+
col.toggleVisibility(false);
|
|
1102
|
+
setOpen(false);
|
|
1103
|
+
},
|
|
1104
|
+
children: "Hide column"
|
|
1105
|
+
}
|
|
1106
|
+
) : null
|
|
1107
|
+
] })
|
|
1108
|
+
] })
|
|
1109
|
+
}
|
|
1110
|
+
);
|
|
1111
|
+
});
|
|
1112
|
+
ColumnHeaderMenuInner.displayName = "ColumnHeaderMenuInner";
|
|
1113
|
+
var ColumnHeaderMenu = memo(ColumnHeaderMenuInner);
|
|
1114
|
+
ColumnHeaderMenu.displayName = "ColumnHeaderMenu";
|
|
1115
|
+
var TABLE_VIEW_PERSIST_STORAGE_KEY = "@avenueticket/ui/table-view";
|
|
1116
|
+
var TABLE_VIEW_PERSIST_DEBOUNCE_MS = 200;
|
|
1117
|
+
function emptyRoot() {
|
|
1118
|
+
return { tables: {} };
|
|
1119
|
+
}
|
|
1120
|
+
function readRoot() {
|
|
1121
|
+
if (typeof window === "undefined") return emptyRoot();
|
|
1122
|
+
try {
|
|
1123
|
+
const raw = localStorage.getItem(TABLE_VIEW_PERSIST_STORAGE_KEY);
|
|
1124
|
+
if (!raw) return emptyRoot();
|
|
1125
|
+
const parsed = JSON.parse(raw);
|
|
1126
|
+
if (!parsed || typeof parsed !== "object") return emptyRoot();
|
|
1127
|
+
const tables = parsed.tables;
|
|
1128
|
+
if (!tables || typeof tables !== "object") return emptyRoot();
|
|
1129
|
+
const out = {};
|
|
1130
|
+
for (const [k, v] of Object.entries(tables)) {
|
|
1131
|
+
if (v && typeof v === "object" && v.v === 1) {
|
|
1132
|
+
out[k] = v;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return { tables: out };
|
|
1136
|
+
} catch {
|
|
1137
|
+
return emptyRoot();
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
function writeRoot(root) {
|
|
1141
|
+
if (typeof window === "undefined") return;
|
|
1142
|
+
try {
|
|
1143
|
+
localStorage.setItem(TABLE_VIEW_PERSIST_STORAGE_KEY, JSON.stringify(root));
|
|
1144
|
+
} catch {
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
function readSnapshot(persistKey) {
|
|
1148
|
+
const row = readRoot().tables[persistKey];
|
|
1149
|
+
return row?.v === 1 ? row : null;
|
|
1150
|
+
}
|
|
1151
|
+
function writeSnapshot(persistKey, snapshot) {
|
|
1152
|
+
const root = readRoot();
|
|
1153
|
+
root.tables[persistKey] = snapshot;
|
|
1154
|
+
writeRoot(root);
|
|
1155
|
+
}
|
|
1156
|
+
function mergePersistedColumnOrder(persisted, defaultOrder) {
|
|
1157
|
+
if (!persisted?.length) return defaultOrder;
|
|
1158
|
+
const allowed = new Set(defaultOrder);
|
|
1159
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1160
|
+
const next = [];
|
|
1161
|
+
for (const id of persisted) {
|
|
1162
|
+
if (allowed.has(id) && !seen.has(id)) {
|
|
1163
|
+
next.push(id);
|
|
1164
|
+
seen.add(id);
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
for (const id of defaultOrder) {
|
|
1168
|
+
if (!seen.has(id)) {
|
|
1169
|
+
next.push(id);
|
|
1170
|
+
seen.add(id);
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return next;
|
|
1174
|
+
}
|
|
1175
|
+
function filterColumnSizingForIds(sizing, allowed) {
|
|
1176
|
+
if (!sizing) return {};
|
|
1177
|
+
const next = {};
|
|
1178
|
+
for (const [id, w] of Object.entries(sizing)) {
|
|
1179
|
+
if (allowed.has(id) && typeof w === "number" && Number.isFinite(w)) {
|
|
1180
|
+
next[id] = w;
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
return next;
|
|
1184
|
+
}
|
|
1185
|
+
function normalizePersistedPinning(raw, allowed) {
|
|
1186
|
+
return {
|
|
1187
|
+
left: (raw?.left ?? []).filter((id) => allowed.has(id)),
|
|
1188
|
+
right: (raw?.right ?? []).filter((id) => allowed.has(id))
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
function filterColumnVisibilityForIds(visibility, allowed) {
|
|
1192
|
+
if (!visibility) return {};
|
|
1193
|
+
const next = {};
|
|
1194
|
+
for (const [id, vis] of Object.entries(visibility)) {
|
|
1195
|
+
if (allowed.has(id) && vis === false) {
|
|
1196
|
+
next[id] = false;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
return next;
|
|
1200
|
+
}
|
|
1201
|
+
function shallowEqualColumnOrder(a, b) {
|
|
1202
|
+
if (a.length !== b.length) return false;
|
|
1203
|
+
return a.every((id, i) => id === b[i]);
|
|
1204
|
+
}
|
|
1205
|
+
function useTableViewPersistence(table, persistKey, opts) {
|
|
1206
|
+
const { columnResize, columnHeaderMenu } = opts;
|
|
1207
|
+
const hydratedRef = useRef(false);
|
|
1208
|
+
const skipNextSaveRef = useRef(false);
|
|
1209
|
+
const prevPersistKeyRef = useRef(void 0);
|
|
1210
|
+
const prevLeafIdsKeyRef = useRef("");
|
|
1211
|
+
const prevGatesKeyRef = useRef("");
|
|
1212
|
+
const leafIdsKey = useMemo(
|
|
1213
|
+
() => table.getAllLeafColumns().map((c) => c.id).join("\0"),
|
|
1214
|
+
[table]
|
|
1215
|
+
);
|
|
1216
|
+
const gatesKey = `${columnResize}\0${columnHeaderMenu}`;
|
|
1217
|
+
useLayoutEffect(() => {
|
|
1218
|
+
if (!persistKey) {
|
|
1219
|
+
hydratedRef.current = true;
|
|
1220
|
+
prevPersistKeyRef.current = void 0;
|
|
1221
|
+
return;
|
|
1222
|
+
}
|
|
1223
|
+
const persistChanged = prevPersistKeyRef.current !== persistKey;
|
|
1224
|
+
const leafChanged = prevLeafIdsKeyRef.current !== leafIdsKey;
|
|
1225
|
+
const gatesChanged = prevGatesKeyRef.current !== gatesKey;
|
|
1226
|
+
if (!persistChanged && !leafChanged && !gatesChanged && hydratedRef.current) {
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
prevPersistKeyRef.current = persistKey;
|
|
1230
|
+
prevLeafIdsKeyRef.current = leafIdsKey;
|
|
1231
|
+
prevGatesKeyRef.current = gatesKey;
|
|
1232
|
+
skipNextSaveRef.current = true;
|
|
1233
|
+
const allowed = new Set(table.getAllLeafColumns().map((c) => c.id));
|
|
1234
|
+
if (allowed.size === 0) {
|
|
1235
|
+
hydratedRef.current = true;
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
const saved = readSnapshot(persistKey);
|
|
1239
|
+
const defaultOrder = table.getAllLeafColumns().map((c) => c.id);
|
|
1240
|
+
const cur = table.getState();
|
|
1241
|
+
const curPin = cur.columnPinning ?? { left: [], right: [] };
|
|
1242
|
+
if (saved) {
|
|
1243
|
+
const nextOrder = mergePersistedColumnOrder(
|
|
1244
|
+
saved.columnOrder,
|
|
1245
|
+
defaultOrder
|
|
1246
|
+
);
|
|
1247
|
+
if (!shallowEqualColumnOrder(nextOrder, cur.columnOrder)) {
|
|
1248
|
+
table.setColumnOrder(nextOrder);
|
|
1249
|
+
}
|
|
1250
|
+
if (columnHeaderMenu && saved.columnPinning) {
|
|
1251
|
+
const nextPin = normalizePersistedPinning(saved.columnPinning, allowed);
|
|
1252
|
+
const pinEq = shallowEqualColumnOrder(nextPin.left ?? [], curPin.left ?? []) && shallowEqualColumnOrder(nextPin.right ?? [], curPin.right ?? []);
|
|
1253
|
+
if (!pinEq) {
|
|
1254
|
+
table.setColumnPinning(nextPin);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
if (columnResize && saved.columnSizing) {
|
|
1258
|
+
const nextSizing = filterColumnSizingForIds(
|
|
1259
|
+
saved.columnSizing,
|
|
1260
|
+
allowed
|
|
1261
|
+
);
|
|
1262
|
+
if (JSON.stringify(nextSizing) !== JSON.stringify(cur.columnSizing)) {
|
|
1263
|
+
table.setColumnSizing(nextSizing);
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
if (columnHeaderMenu && saved.columnVisibility != null) {
|
|
1267
|
+
const nextVis = filterColumnVisibilityForIds(
|
|
1268
|
+
saved.columnVisibility,
|
|
1269
|
+
allowed
|
|
1270
|
+
);
|
|
1271
|
+
const curVis = cur.columnVisibility ?? {};
|
|
1272
|
+
if (JSON.stringify(nextVis) !== JSON.stringify(curVis)) {
|
|
1273
|
+
table.setColumnVisibility(nextVis);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
hydratedRef.current = true;
|
|
1278
|
+
}, [
|
|
1279
|
+
persistKey,
|
|
1280
|
+
table,
|
|
1281
|
+
leafIdsKey,
|
|
1282
|
+
gatesKey,
|
|
1283
|
+
columnResize,
|
|
1284
|
+
columnHeaderMenu
|
|
1285
|
+
]);
|
|
1286
|
+
const s = table.getState();
|
|
1287
|
+
const persistSerial = persistKey == null ? "" : JSON.stringify({
|
|
1288
|
+
columnOrder: s.columnOrder,
|
|
1289
|
+
columnSizing: columnResize ? s.columnSizing : null,
|
|
1290
|
+
columnPinning: columnHeaderMenu ? s.columnPinning : null,
|
|
1291
|
+
columnVisibility: columnHeaderMenu ? s.columnVisibility : null
|
|
1292
|
+
});
|
|
1293
|
+
useEffect(() => {
|
|
1294
|
+
if (!persistKey || !hydratedRef.current) return;
|
|
1295
|
+
if (skipNextSaveRef.current) {
|
|
1296
|
+
skipNextSaveRef.current = false;
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
const id = window.setTimeout(() => {
|
|
1300
|
+
const st = table.getState();
|
|
1301
|
+
writeSnapshot(persistKey, {
|
|
1302
|
+
v: 1,
|
|
1303
|
+
columnOrder: st.columnOrder,
|
|
1304
|
+
...columnResize ? { columnSizing: st.columnSizing } : {},
|
|
1305
|
+
...columnHeaderMenu ? {
|
|
1306
|
+
columnPinning: st.columnPinning,
|
|
1307
|
+
columnVisibility: st.columnVisibility
|
|
1308
|
+
} : {}
|
|
1309
|
+
});
|
|
1310
|
+
}, TABLE_VIEW_PERSIST_DEBOUNCE_MS);
|
|
1311
|
+
return () => window.clearTimeout(id);
|
|
1312
|
+
}, [
|
|
1313
|
+
persistKey,
|
|
1314
|
+
persistSerial,
|
|
1315
|
+
table,
|
|
1316
|
+
columnResize,
|
|
1317
|
+
columnHeaderMenu
|
|
1318
|
+
]);
|
|
1319
|
+
}
|
|
1320
|
+
var defaultTableConfig = {
|
|
1321
|
+
sortableColumnIds: /* @__PURE__ */ new Set(),
|
|
1322
|
+
enableColumnSort: true,
|
|
1323
|
+
enableColumnReorder: false,
|
|
1324
|
+
enableColumnResize: false,
|
|
1325
|
+
columnDragState: null
|
|
1326
|
+
};
|
|
1327
|
+
var TableConfigContext = React5.createContext(null);
|
|
1328
|
+
TableConfigContext.displayName = "TableConfigContext";
|
|
1329
|
+
function setColumnDragPreview(e, options) {
|
|
1330
|
+
if (!e.dataTransfer) return;
|
|
1331
|
+
e.dataTransfer.effectAllowed = "move";
|
|
1332
|
+
const width = options.width ?? 80;
|
|
1333
|
+
const height = options.height ?? 100;
|
|
1334
|
+
const el = document.createElement("div");
|
|
1335
|
+
el.setAttribute("data-table-drag-preview", "");
|
|
1336
|
+
const dark = typeof window !== "undefined" && window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1337
|
+
const bg = dark ? "rgba(24,24,26,0.95)" : "rgba(255,255,255,0.96)";
|
|
1338
|
+
const fg = dark ? "rgba(250,250,250,0.95)" : "rgba(10,10,10,0.92)";
|
|
1339
|
+
const border = dark ? "1px solid rgba(255,255,255,0.12)" : "1px solid rgba(0,0,0,0.1)";
|
|
1340
|
+
const shadow = "0 12px 32px rgba(0,0,0,0.2),0 0 0 1px rgba(0,0,0,0.04)";
|
|
1341
|
+
el.style.cssText = [
|
|
1342
|
+
"position:fixed",
|
|
1343
|
+
"left:0",
|
|
1344
|
+
"top:0",
|
|
1345
|
+
"z-index:100000",
|
|
1346
|
+
"pointer-events:none",
|
|
1347
|
+
"box-sizing:border-box",
|
|
1348
|
+
`width:${width}px`,
|
|
1349
|
+
`min-height:${height}px`,
|
|
1350
|
+
"display:flex",
|
|
1351
|
+
"flex-direction:column",
|
|
1352
|
+
"align-items:center",
|
|
1353
|
+
"justify-content:flex-start",
|
|
1354
|
+
"gap:8px",
|
|
1355
|
+
`padding:10px 8px 12px`,
|
|
1356
|
+
`color:${fg}`,
|
|
1357
|
+
`background:${bg}`,
|
|
1358
|
+
`border:${border}`,
|
|
1359
|
+
"border-radius:8px",
|
|
1360
|
+
`box-shadow:${shadow}`
|
|
1361
|
+
].join(";");
|
|
1362
|
+
const bar = document.createElement("div");
|
|
1363
|
+
bar.style.cssText = `width:3px;flex:1;min-height:32px;border-radius:2px;background:${dark ? "rgba(80,200,150,0.4)" : "rgba(20,80,200,0.2)"};align-self:stretch;`;
|
|
1364
|
+
const t = document.createElement("div");
|
|
1365
|
+
t.textContent = options.title;
|
|
1366
|
+
t.style.cssText = "font:600 11px/1.2 system-ui,-apple-system,sans-serif;text-align:center;word-break:break-word;max-width:100%;";
|
|
1367
|
+
el.appendChild(t);
|
|
1368
|
+
el.appendChild(bar);
|
|
1369
|
+
el.style.minHeight = `${height}px`;
|
|
1370
|
+
document.body.appendChild(el);
|
|
1371
|
+
void el.offsetWidth;
|
|
1372
|
+
e.dataTransfer.setDragImage(
|
|
1373
|
+
el,
|
|
1374
|
+
options.hotspotX ?? width / 2,
|
|
1375
|
+
options.hotspotY ?? 28
|
|
1376
|
+
);
|
|
1377
|
+
requestAnimationFrame(() => {
|
|
1378
|
+
if (el.parentNode) el.parentNode.removeChild(el);
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
var COLUMN_DRAG_TH_STRIP = "relative z-20 box-border overflow-hidden rounded-t-lg border border-primary/20 bg-primary/8 opacity-70 shadow-sm";
|
|
1382
|
+
var COLUMN_DRAG_TD_STRIP = "overflow-hidden border-x border-primary/15 bg-primary/5 opacity-70";
|
|
1383
|
+
var columnDragThClasses = (config, columnId) => {
|
|
1384
|
+
if (!config.enableColumnReorder || !config.columnDragState) return void 0;
|
|
1385
|
+
const d = config.columnDragState;
|
|
1386
|
+
const isSource = d.draggingId === columnId;
|
|
1387
|
+
const isDrop = d.dropTargetId === columnId && d.draggingId != null && d.draggingId !== columnId;
|
|
1388
|
+
if (isSource || isDrop) {
|
|
1389
|
+
return COLUMN_DRAG_TH_STRIP;
|
|
1390
|
+
}
|
|
1391
|
+
return void 0;
|
|
1392
|
+
};
|
|
1393
|
+
var columnDragTdClasses = (config, columnId) => {
|
|
1394
|
+
if (!config.enableColumnReorder || !config.columnDragState) return void 0;
|
|
1395
|
+
const d = config.columnDragState;
|
|
1396
|
+
const isSource = d.draggingId === columnId;
|
|
1397
|
+
const isDrop = d.dropTargetId === columnId && d.draggingId != null && d.draggingId !== columnId;
|
|
1398
|
+
if (isSource || isDrop) {
|
|
1399
|
+
return COLUMN_DRAG_TD_STRIP;
|
|
1400
|
+
}
|
|
1401
|
+
return void 0;
|
|
1402
|
+
};
|
|
1403
|
+
var Table = React5.forwardRef(
|
|
1404
|
+
({
|
|
1405
|
+
className,
|
|
1406
|
+
containerClassName,
|
|
1407
|
+
sortableColumns,
|
|
1408
|
+
enableColumnSort: enableColumnSortFromProps,
|
|
1409
|
+
enableColumnReorder: enableColumnReorderFromProps,
|
|
1410
|
+
enableColumnResize: enableColumnResizeFromProps,
|
|
1411
|
+
columnDragState: columnDragStateFromProps,
|
|
1412
|
+
...props
|
|
1413
|
+
}, ref) => {
|
|
1414
|
+
const config = React5.useMemo(() => {
|
|
1415
|
+
const sortableColumnIds = new Set(sortableColumns ?? []);
|
|
1416
|
+
return {
|
|
1417
|
+
sortableColumnIds,
|
|
1418
|
+
enableColumnSort: enableColumnSortFromProps ?? true,
|
|
1419
|
+
enableColumnReorder: enableColumnReorderFromProps ?? false,
|
|
1420
|
+
enableColumnResize: enableColumnResizeFromProps ?? false,
|
|
1421
|
+
columnDragState: columnDragStateFromProps ?? null
|
|
1422
|
+
};
|
|
1423
|
+
}, [
|
|
1424
|
+
sortableColumns,
|
|
1425
|
+
enableColumnSortFromProps,
|
|
1426
|
+
enableColumnReorderFromProps,
|
|
1427
|
+
enableColumnResizeFromProps,
|
|
1428
|
+
columnDragStateFromProps
|
|
1429
|
+
]);
|
|
1430
|
+
return /* @__PURE__ */ jsx(
|
|
1431
|
+
"div",
|
|
1432
|
+
{
|
|
1433
|
+
"data-slot": "table-container",
|
|
1434
|
+
"data-table-sort": config.enableColumnSort ? "on" : "off",
|
|
1435
|
+
"data-table-reorder": config.enableColumnReorder ? "on" : "off",
|
|
1436
|
+
"data-table-resize": config.enableColumnResize ? "on" : "off",
|
|
1437
|
+
className: cn("relative w-full overflow-x-auto", containerClassName),
|
|
1438
|
+
children: /* @__PURE__ */ jsx(TableConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsx(
|
|
1439
|
+
"table",
|
|
1440
|
+
{
|
|
1441
|
+
ref,
|
|
1442
|
+
"data-slot": "table",
|
|
1443
|
+
className: cn(
|
|
1444
|
+
"min-w-full w-max caption-bottom text-sm",
|
|
1445
|
+
className
|
|
1446
|
+
),
|
|
1447
|
+
...props
|
|
1448
|
+
}
|
|
1449
|
+
) })
|
|
1450
|
+
}
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
);
|
|
1454
|
+
Table.displayName = "Table";
|
|
1455
|
+
var TableHeader = React5.forwardRef(({ className, ...props }, ref) => {
|
|
1456
|
+
const config = React5.useContext(TableConfigContext) ?? defaultTableConfig;
|
|
1457
|
+
const hasSortableColumns = config.enableColumnSort && config.sortableColumnIds.size > 0;
|
|
1458
|
+
return /* @__PURE__ */ jsx(
|
|
1459
|
+
"thead",
|
|
1460
|
+
{
|
|
1461
|
+
ref,
|
|
1462
|
+
"data-slot": "table-header",
|
|
1463
|
+
className: cn(
|
|
1464
|
+
hasSortableColumns && "[&_tr:hover]:bg-transparent!",
|
|
1465
|
+
className
|
|
1466
|
+
),
|
|
1467
|
+
...props
|
|
1468
|
+
}
|
|
1469
|
+
);
|
|
1470
|
+
});
|
|
1471
|
+
TableHeader.displayName = "TableHeader";
|
|
1472
|
+
var TableBody = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1473
|
+
"tbody",
|
|
1474
|
+
{
|
|
1475
|
+
ref,
|
|
1476
|
+
"data-slot": "table-body",
|
|
1477
|
+
className: cn(
|
|
1478
|
+
"[&>tr:last-child>td:not([data-table-column-drag-strip])]:border-b-0",
|
|
1479
|
+
className
|
|
1480
|
+
),
|
|
1481
|
+
...props
|
|
1482
|
+
}
|
|
1483
|
+
));
|
|
1484
|
+
TableBody.displayName = "TableBody";
|
|
1485
|
+
var TableFooter = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1486
|
+
"tfoot",
|
|
1487
|
+
{
|
|
1488
|
+
ref,
|
|
1489
|
+
"data-slot": "table-footer",
|
|
1490
|
+
className: cn(
|
|
1491
|
+
"border-t border-primary/10 bg-primary/5 font-medium",
|
|
1492
|
+
className
|
|
1493
|
+
),
|
|
1494
|
+
...props
|
|
1495
|
+
}
|
|
1496
|
+
));
|
|
1497
|
+
TableFooter.displayName = "TableFooter";
|
|
1498
|
+
var TableRow = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1499
|
+
"tr",
|
|
1500
|
+
{
|
|
1501
|
+
ref,
|
|
1502
|
+
"data-slot": "table-row",
|
|
1503
|
+
className: cn(
|
|
1504
|
+
"transition-colors duration-0 hover:bg-primary/3 data-[state=selected]:bg-primary/10",
|
|
1505
|
+
className
|
|
1506
|
+
),
|
|
1507
|
+
...props
|
|
1508
|
+
}
|
|
1509
|
+
));
|
|
1510
|
+
TableRow.displayName = "TableRow";
|
|
1511
|
+
var columnDragHandleIconClass = cn(
|
|
1512
|
+
"text-primary/55 hover:text-primary/80",
|
|
1513
|
+
"cursor-grab active:cursor-grabbing touch-none",
|
|
1514
|
+
"shrink-0"
|
|
1515
|
+
);
|
|
1516
|
+
var TableColumnDragHandle = React5.forwardRef(function TableColumnDragHandle2({ columnId, previewLabel, className, onDragStart, onDragEnd, title, ...rest }, ref) {
|
|
1517
|
+
return /* @__PURE__ */ jsx(
|
|
1518
|
+
"span",
|
|
1519
|
+
{
|
|
1520
|
+
ref,
|
|
1521
|
+
className: cn(
|
|
1522
|
+
"inline-flex select-none items-center justify-center",
|
|
1523
|
+
columnDragHandleIconClass,
|
|
1524
|
+
className
|
|
1525
|
+
),
|
|
1526
|
+
title: title ?? "Drag to reorder this column",
|
|
1527
|
+
tabIndex: -1,
|
|
1528
|
+
"aria-label": "Drag to reorder this column",
|
|
1529
|
+
draggable: true,
|
|
1530
|
+
onDragStart: (e) => {
|
|
1531
|
+
e.dataTransfer.setData("text/plain", columnId);
|
|
1532
|
+
setColumnDragPreview(e, { title: previewLabel ?? "Column" });
|
|
1533
|
+
onDragStart?.(e);
|
|
1534
|
+
},
|
|
1535
|
+
onDragEnd,
|
|
1536
|
+
onClick: (ev) => ev.stopPropagation(),
|
|
1537
|
+
onKeyDown: (ev) => {
|
|
1538
|
+
if (ev.key === " " || ev.key === "Enter") {
|
|
1539
|
+
ev.preventDefault();
|
|
1540
|
+
}
|
|
1541
|
+
ev.stopPropagation();
|
|
1542
|
+
},
|
|
1543
|
+
"data-slot": "table-column-drag-handle",
|
|
1544
|
+
...rest,
|
|
1545
|
+
children: /* @__PURE__ */ jsx(
|
|
1546
|
+
GripVertical,
|
|
1547
|
+
{
|
|
1548
|
+
className: "size-4 pointer-events-none",
|
|
1549
|
+
strokeWidth: 2.25,
|
|
1550
|
+
"aria-hidden": true
|
|
1551
|
+
}
|
|
1552
|
+
)
|
|
1553
|
+
}
|
|
1554
|
+
);
|
|
1555
|
+
});
|
|
1556
|
+
TableColumnDragHandle.displayName = "TableColumnDragHandle";
|
|
1557
|
+
function TableHeaderSortControl({
|
|
1558
|
+
activeSort,
|
|
1559
|
+
onRequest,
|
|
1560
|
+
className
|
|
1561
|
+
}) {
|
|
1562
|
+
const isActiveSort = activeSort === "asc" || activeSort === "desc";
|
|
1563
|
+
return /* @__PURE__ */ jsx(
|
|
1564
|
+
"span",
|
|
1565
|
+
{
|
|
1566
|
+
className: cn("inline-flex shrink-0 items-stretch pl-0", className),
|
|
1567
|
+
children: onRequest ? /* @__PURE__ */ jsx("span", { className: "flex shrink-0 items-stretch", children: /* @__PURE__ */ jsx(
|
|
1568
|
+
"button",
|
|
1569
|
+
{
|
|
1570
|
+
type: "button",
|
|
1571
|
+
className: "text-primary/90 hover:text-primary/95 inline-flex min-h-10 w-8 min-w-8 touch-manipulation items-center justify-center self-center rounded p-0 md:min-h-12",
|
|
1572
|
+
onClick: (e) => {
|
|
1573
|
+
e.stopPropagation();
|
|
1574
|
+
onRequest(e);
|
|
1575
|
+
},
|
|
1576
|
+
title: "Change sort",
|
|
1577
|
+
"aria-label": "Change sort order",
|
|
1578
|
+
children: isActiveSort ? activeSort === "desc" ? /* @__PURE__ */ jsx(
|
|
1579
|
+
ArrowDown,
|
|
1580
|
+
{
|
|
1581
|
+
className: "size-3.5 shrink-0",
|
|
1582
|
+
strokeWidth: 2.25,
|
|
1583
|
+
"aria-hidden": true
|
|
1584
|
+
}
|
|
1585
|
+
) : /* @__PURE__ */ jsx(
|
|
1586
|
+
ArrowUp,
|
|
1587
|
+
{
|
|
1588
|
+
className: "size-3.5 shrink-0",
|
|
1589
|
+
strokeWidth: 2.25,
|
|
1590
|
+
"aria-hidden": true
|
|
1591
|
+
}
|
|
1592
|
+
) : /* @__PURE__ */ jsx(
|
|
1593
|
+
ArrowUp,
|
|
1594
|
+
{
|
|
1595
|
+
className: "text-primary/85 size-3.5 shrink-0 opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
1596
|
+
strokeWidth: 2.25,
|
|
1597
|
+
"aria-hidden": true
|
|
1598
|
+
}
|
|
1599
|
+
)
|
|
1600
|
+
}
|
|
1601
|
+
) }) : isActiveSort ? /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center", children: activeSort === "desc" ? /* @__PURE__ */ jsx(
|
|
1602
|
+
ArrowDown,
|
|
1603
|
+
{
|
|
1604
|
+
className: "size-3.5 shrink-0 self-center text-primary/90",
|
|
1605
|
+
strokeWidth: 2.25,
|
|
1606
|
+
"aria-hidden": true
|
|
1607
|
+
}
|
|
1608
|
+
) : /* @__PURE__ */ jsx(
|
|
1609
|
+
ArrowUp,
|
|
1610
|
+
{
|
|
1611
|
+
className: "size-3.5 shrink-0 self-center text-primary/90",
|
|
1612
|
+
strokeWidth: 2.25,
|
|
1613
|
+
"aria-hidden": true
|
|
1614
|
+
}
|
|
1615
|
+
) }) : /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center", children: /* @__PURE__ */ jsx(
|
|
1616
|
+
ArrowUp,
|
|
1617
|
+
{
|
|
1618
|
+
className: "text-primary/85 size-3.5 shrink-0 self-center opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100",
|
|
1619
|
+
strokeWidth: 2.25,
|
|
1620
|
+
"aria-hidden": true
|
|
1621
|
+
}
|
|
1622
|
+
) })
|
|
1623
|
+
}
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
var TableHead = React5.forwardRef(
|
|
1627
|
+
({
|
|
1628
|
+
className,
|
|
1629
|
+
columnId,
|
|
1630
|
+
children,
|
|
1631
|
+
activeSort,
|
|
1632
|
+
onColumnResizeStart,
|
|
1633
|
+
isColumnResizing,
|
|
1634
|
+
style,
|
|
1635
|
+
headerEnd,
|
|
1636
|
+
...props
|
|
1637
|
+
}, ref) => {
|
|
1638
|
+
const config = React5.useContext(TableConfigContext) ?? defaultTableConfig;
|
|
1639
|
+
const showSortUI = config.enableColumnSort && columnId !== void 0 && config.sortableColumnIds.has(columnId);
|
|
1640
|
+
const isActiveSort = showSortUI && (activeSort === "asc" || activeSort === "desc");
|
|
1641
|
+
const hasHeaderEnd = headerEnd != null && headerEnd !== false;
|
|
1642
|
+
const showResizer = config.enableColumnResize && typeof onColumnResizeStart === "function";
|
|
1643
|
+
const drag = columnId ? columnDragThClasses(config, columnId) : void 0;
|
|
1644
|
+
return /* @__PURE__ */ jsxs(
|
|
1645
|
+
"th",
|
|
1646
|
+
{
|
|
1647
|
+
ref,
|
|
1648
|
+
"data-resizing": isColumnResizing ? 1 : void 0,
|
|
1649
|
+
"data-slot": "table-head",
|
|
1650
|
+
"data-column-id": columnId,
|
|
1651
|
+
"data-sortable": showSortUI ? "true" : void 0,
|
|
1652
|
+
"data-sorted": isActiveSort ? activeSort ?? void 0 : void 0,
|
|
1653
|
+
"aria-sort": isActiveSort && activeSort ? activeSort === "desc" ? "descending" : "ascending" : showSortUI ? "none" : void 0,
|
|
1654
|
+
className: cn(
|
|
1655
|
+
"h-10 min-w-0 px-3 text-left align-middle text-sm font-bold text-primary transition-colors duration-0 md:h-12 md:px-4 [&:has([role=checkbox])]:pr-0",
|
|
1656
|
+
!drag && "border-b border-primary/10",
|
|
1657
|
+
showResizer && "relative",
|
|
1658
|
+
// th cursor-pointer is often overridden by child button default cursor
|
|
1659
|
+
(showSortUI || hasHeaderEnd) && "group hover:bg-primary/5 [&_button]:cursor-pointer",
|
|
1660
|
+
drag,
|
|
1661
|
+
isColumnResizing && "opacity-100",
|
|
1662
|
+
className
|
|
1663
|
+
),
|
|
1664
|
+
style,
|
|
1665
|
+
...props,
|
|
1666
|
+
children: [
|
|
1667
|
+
showSortUI ? /* @__PURE__ */ jsxs("span", { className: "inline-flex h-full w-full min-h-0 min-w-0 max-w-full items-center justify-start gap-0.5", children: [
|
|
1668
|
+
/* @__PURE__ */ jsx("span", { className: "min-h-0 min-w-0 flex-1 text-left [&_[data-slot=table-column-drag-handle]]:cursor-grab [&_[data-slot=table-column-drag-handle]]:active:cursor-grabbing", children }),
|
|
1669
|
+
hasHeaderEnd ? /* @__PURE__ */ jsx("span", { className: "inline-flex min-h-0 min-w-0 shrink-0 items-center", children: headerEnd }) : null
|
|
1670
|
+
] }) : hasHeaderEnd ? /* @__PURE__ */ jsxs("span", { className: "inline-flex h-full w-full min-h-0 min-w-0 max-w-full items-center justify-start gap-0.5", children: [
|
|
1671
|
+
/* @__PURE__ */ jsx("span", { className: "min-h-0 min-w-0 flex-1 text-left [&_[data-slot=table-column-drag-handle]]:cursor-grab [&_[data-slot=table-column-drag-handle]]:active:cursor-grabbing", children }),
|
|
1672
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex min-h-0 min-w-0 shrink-0 items-center", children: headerEnd })
|
|
1673
|
+
] }) : children,
|
|
1674
|
+
showResizer && /* @__PURE__ */ jsx(
|
|
1675
|
+
"div",
|
|
1676
|
+
{
|
|
1677
|
+
role: "separator",
|
|
1678
|
+
title: "Drag to resize",
|
|
1679
|
+
onMouseDown: onColumnResizeStart,
|
|
1680
|
+
onTouchStart: onColumnResizeStart,
|
|
1681
|
+
className: cn(
|
|
1682
|
+
// keep handle inside this th — negative right overlapped the next cell (bad with sticky/pinned columns)
|
|
1683
|
+
"absolute top-0 right-0 z-1 h-full w-2.5 min-w-2.5 max-w-2.5 touch-none",
|
|
1684
|
+
"cursor-col-resize select-none",
|
|
1685
|
+
isColumnResizing ? "bg-primary/35" : "bg-primary/0 hover:bg-primary/25"
|
|
1686
|
+
),
|
|
1687
|
+
"data-slot": "table-column-resize-handle",
|
|
1688
|
+
"aria-hidden": true
|
|
1689
|
+
}
|
|
1690
|
+
)
|
|
1691
|
+
]
|
|
1692
|
+
}
|
|
1693
|
+
);
|
|
1694
|
+
}
|
|
1695
|
+
);
|
|
1696
|
+
TableHead.displayName = "TableHead";
|
|
1697
|
+
var TableCell = React5.forwardRef(
|
|
1698
|
+
({ className, style, columnId, ...props }, ref) => {
|
|
1699
|
+
const config = React5.useContext(TableConfigContext) ?? defaultTableConfig;
|
|
1700
|
+
const drag = columnId ? columnDragTdClasses(config, columnId) : void 0;
|
|
1701
|
+
const columnDragStrip = Boolean(drag);
|
|
1702
|
+
return /* @__PURE__ */ jsx(
|
|
1703
|
+
"td",
|
|
1704
|
+
{
|
|
1705
|
+
ref,
|
|
1706
|
+
"data-slot": "table-cell",
|
|
1707
|
+
"data-table-column-drag-strip": columnDragStrip ? "" : void 0,
|
|
1708
|
+
className: cn(
|
|
1709
|
+
"min-w-0 border-b border-primary/10 p-3 align-middle text-sm text-primary/90 md:p-4 [&:has([role=checkbox])]:pr-0",
|
|
1710
|
+
drag,
|
|
1711
|
+
className
|
|
1712
|
+
),
|
|
1713
|
+
style,
|
|
1714
|
+
"data-column-id": columnId,
|
|
1715
|
+
...props
|
|
1716
|
+
}
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
);
|
|
1720
|
+
TableCell.displayName = "TableCell";
|
|
1721
|
+
function sizingUpdaterToFn(updater) {
|
|
1722
|
+
return typeof updater === "function" ? updater : () => updater;
|
|
1723
|
+
}
|
|
1724
|
+
function useRafBatchedColumnSizing(setColumnSizing) {
|
|
1725
|
+
const rafRef = useRef(null);
|
|
1726
|
+
const queueRef = useRef(
|
|
1727
|
+
[]
|
|
1728
|
+
);
|
|
1729
|
+
useEffect(
|
|
1730
|
+
() => () => {
|
|
1731
|
+
if (rafRef.current != null) {
|
|
1732
|
+
cancelAnimationFrame(rafRef.current);
|
|
1733
|
+
rafRef.current = null;
|
|
1734
|
+
}
|
|
1735
|
+
},
|
|
1736
|
+
[]
|
|
1737
|
+
);
|
|
1738
|
+
return useCallback(
|
|
1739
|
+
(updater) => {
|
|
1740
|
+
queueRef.current.push(sizingUpdaterToFn(updater));
|
|
1741
|
+
if (rafRef.current != null) return;
|
|
1742
|
+
rafRef.current = requestAnimationFrame(() => {
|
|
1743
|
+
rafRef.current = null;
|
|
1744
|
+
const fns = queueRef.current;
|
|
1745
|
+
queueRef.current = [];
|
|
1746
|
+
if (fns.length === 0) return;
|
|
1747
|
+
setColumnSizing((prev) => fns.reduce((acc, f) => f(acc), prev));
|
|
1748
|
+
});
|
|
1749
|
+
},
|
|
1750
|
+
[setColumnSizing]
|
|
1751
|
+
);
|
|
1752
|
+
}
|
|
1753
|
+
function useTransitionColumnSizing(setColumnSizing) {
|
|
1754
|
+
return useCallback(
|
|
1755
|
+
(updater) => {
|
|
1756
|
+
startTransition(() => {
|
|
1757
|
+
setColumnSizing(updater);
|
|
1758
|
+
});
|
|
1759
|
+
},
|
|
1760
|
+
[setColumnSizing]
|
|
1761
|
+
);
|
|
1762
|
+
}
|
|
1763
|
+
var EMPTY_STRING_ARRAY = [];
|
|
1764
|
+
var tableViewColumnRoundTop = "overflow-hidden rounded-t-lg";
|
|
1765
|
+
var tableViewColumnRoundBottom = "overflow-hidden rounded-b-lg";
|
|
1766
|
+
var TableViewColumnHead = React5.memo(
|
|
1767
|
+
function TableViewColumnHead2(props) {
|
|
1768
|
+
const {
|
|
1769
|
+
header,
|
|
1770
|
+
table,
|
|
1771
|
+
options,
|
|
1772
|
+
getColumnMinClassName,
|
|
1773
|
+
onHeaderCellDragOver,
|
|
1774
|
+
onHeaderCellDrop,
|
|
1775
|
+
onHeaderContextMenu,
|
|
1776
|
+
setDraggedId,
|
|
1777
|
+
setDropTargetId,
|
|
1778
|
+
endColumnDrag,
|
|
1779
|
+
registerColumnMenu
|
|
1780
|
+
} = props;
|
|
1781
|
+
const id = header.column.id;
|
|
1782
|
+
const canSort = header.column.getCanSort() && options.columnSort;
|
|
1783
|
+
const isSorted = header.column.getIsSorted();
|
|
1784
|
+
const hSize = header.getSize();
|
|
1785
|
+
const canResize = options.columnResize && header.column.getCanResize();
|
|
1786
|
+
const resizer = header.getResizeHandler();
|
|
1787
|
+
const onSort = header.column.getToggleSortingHandler();
|
|
1788
|
+
const runSort = useCallback(
|
|
1789
|
+
(e) => {
|
|
1790
|
+
onSort?.(e);
|
|
1791
|
+
},
|
|
1792
|
+
[onSort]
|
|
1793
|
+
);
|
|
1794
|
+
const setMenuRef = useCallback(
|
|
1795
|
+
(h) => {
|
|
1796
|
+
registerColumnMenu(id, h);
|
|
1797
|
+
},
|
|
1798
|
+
[id, registerColumnMenu]
|
|
1799
|
+
);
|
|
1800
|
+
const onDragStartReorder = useCallback(() => {
|
|
1801
|
+
setDraggedId(id);
|
|
1802
|
+
setDropTargetId(null);
|
|
1803
|
+
}, [id, setDraggedId, setDropTargetId]);
|
|
1804
|
+
const disableColumnReorder = getTableViewColumnDisableReorder(
|
|
1805
|
+
header.column
|
|
1806
|
+
);
|
|
1807
|
+
const showReorderHandle = options.columnReorder && !disableColumnReorder;
|
|
1808
|
+
const headerInnerGap = showReorderHandle ? "gap-2" : "gap-1.5";
|
|
1809
|
+
const pinStyle = getColumnPinningStyle(header.column);
|
|
1810
|
+
const sizeStyle = options.columnResize ? {
|
|
1811
|
+
width: hSize,
|
|
1812
|
+
minWidth: header.column.columnDef.minSize,
|
|
1813
|
+
maxWidth: header.column.columnDef.maxSize
|
|
1814
|
+
} : void 0;
|
|
1815
|
+
return /* @__PURE__ */ jsx(
|
|
1816
|
+
TableHead,
|
|
1817
|
+
{
|
|
1818
|
+
colSpan: header.colSpan,
|
|
1819
|
+
className: cn(
|
|
1820
|
+
tableViewColumnRoundTop,
|
|
1821
|
+
!options.columnResize && getColumnMinClassName?.(id),
|
|
1822
|
+
getColumnPinningClassName(header.column),
|
|
1823
|
+
header.column.getIsPinned() && "hover:bg-[color-mix(in_oklab,var(--color-primary)_5%,var(--color-background))]",
|
|
1824
|
+
options.columnHeaderMenu && !header.isPlaceholder && "group"
|
|
1825
|
+
),
|
|
1826
|
+
style: { ...pinStyle, ...sizeStyle },
|
|
1827
|
+
columnId: id,
|
|
1828
|
+
activeSort: canSort ? isSorted === "asc" || isSorted === "desc" ? isSorted : null : null,
|
|
1829
|
+
onColumnResizeStart: canResize ? resizer : void 0,
|
|
1830
|
+
isColumnResizing: header.column.getIsResizing(),
|
|
1831
|
+
headerEnd: options.columnHeaderMenu && !header.isPlaceholder ? /* @__PURE__ */ jsx(
|
|
1832
|
+
ColumnHeaderMenu,
|
|
1833
|
+
{
|
|
1834
|
+
ref: setMenuRef,
|
|
1835
|
+
table,
|
|
1836
|
+
header,
|
|
1837
|
+
columnSort: options.columnSort,
|
|
1838
|
+
columnReorder: options.columnReorder
|
|
1839
|
+
}
|
|
1840
|
+
) : void 0,
|
|
1841
|
+
onContextMenu: options.columnHeaderMenu && !header.isPlaceholder ? onHeaderContextMenu : void 0,
|
|
1842
|
+
onDragOver: onHeaderCellDragOver,
|
|
1843
|
+
onDrop: options.columnReorder ? onHeaderCellDrop : void 0,
|
|
1844
|
+
children: /* @__PURE__ */ jsxs(
|
|
1845
|
+
"span",
|
|
1846
|
+
{
|
|
1847
|
+
className: cn(
|
|
1848
|
+
"box-border flex h-full min-h-0 w-full min-w-0 max-w-full flex-1 items-center",
|
|
1849
|
+
headerInnerGap
|
|
1850
|
+
),
|
|
1851
|
+
children: [
|
|
1852
|
+
showReorderHandle ? /* @__PURE__ */ jsx(
|
|
1853
|
+
TableColumnDragHandle,
|
|
1854
|
+
{
|
|
1855
|
+
className: "shrink-0 self-center",
|
|
1856
|
+
columnId: id,
|
|
1857
|
+
previewLabel: getColumnHeaderLabel(header),
|
|
1858
|
+
onDragStart: onDragStartReorder,
|
|
1859
|
+
onDragEnd: endColumnDrag
|
|
1860
|
+
}
|
|
1861
|
+
) : null,
|
|
1862
|
+
header.isPlaceholder ? null : canSort ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1863
|
+
/* @__PURE__ */ jsxs("span", { className: "inline-flex w-max min-w-0 max-w-full shrink-0 items-center gap-1", children: [
|
|
1864
|
+
/* @__PURE__ */ jsx(
|
|
1865
|
+
"button",
|
|
1866
|
+
{
|
|
1867
|
+
type: "button",
|
|
1868
|
+
className: "text-primary hover:text-primary/90 m-0 min-h-10 min-w-0 max-w-full cursor-pointer truncate border-0 bg-transparent py-0 pr-0 pl-0 text-left text-sm font-bold leading-snug md:min-h-12",
|
|
1869
|
+
onClick: runSort,
|
|
1870
|
+
children: flexRender(
|
|
1871
|
+
header.column.columnDef.header,
|
|
1872
|
+
header.getContext()
|
|
1873
|
+
)
|
|
1874
|
+
}
|
|
1875
|
+
),
|
|
1876
|
+
/* @__PURE__ */ jsx(
|
|
1877
|
+
TableHeaderSortControl,
|
|
1878
|
+
{
|
|
1879
|
+
activeSort: isSorted === "asc" || isSorted === "desc" ? isSorted : null,
|
|
1880
|
+
onRequest: runSort
|
|
1881
|
+
}
|
|
1882
|
+
)
|
|
1883
|
+
] }),
|
|
1884
|
+
/* @__PURE__ */ jsx(
|
|
1885
|
+
"button",
|
|
1886
|
+
{
|
|
1887
|
+
type: "button",
|
|
1888
|
+
className: "m-0 min-h-10 min-w-0 flex-1 cursor-pointer self-stretch border-0 bg-transparent p-0 shadow-none md:min-h-12 focus-visible:ring-2 focus-visible:ring-primary/20 focus-visible:ring-offset-0",
|
|
1889
|
+
"aria-label": "Change sort",
|
|
1890
|
+
title: "Change sort",
|
|
1891
|
+
onClick: runSort
|
|
1892
|
+
}
|
|
1893
|
+
)
|
|
1894
|
+
] }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 self-center text-left", children: flexRender(header.column.columnDef.header, header.getContext()) })
|
|
1895
|
+
]
|
|
1896
|
+
}
|
|
1897
|
+
)
|
|
1898
|
+
}
|
|
1899
|
+
);
|
|
1900
|
+
},
|
|
1901
|
+
(prev, next) => {
|
|
1902
|
+
if (prev.header.id !== next.header.id) return false;
|
|
1903
|
+
if (prev.header.column.getIsResizing() !== next.header.column.getIsResizing()) {
|
|
1904
|
+
return false;
|
|
1905
|
+
}
|
|
1906
|
+
if (prev.header.column.getIsSorted() !== next.header.column.getIsSorted()) {
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1909
|
+
if (prev.header.getSize() !== next.header.getSize()) return false;
|
|
1910
|
+
if (prev.header.column.getIsPinned() !== next.header.column.getIsPinned()) {
|
|
1911
|
+
return false;
|
|
1912
|
+
}
|
|
1913
|
+
if (prev.header.isPlaceholder !== next.header.isPlaceholder) return false;
|
|
1914
|
+
if (getTableViewColumnDisableReorder(prev.header.column) !== getTableViewColumnDisableReorder(next.header.column)) {
|
|
1915
|
+
return false;
|
|
1916
|
+
}
|
|
1917
|
+
if (prev.options.columnSort !== next.options.columnSort) return false;
|
|
1918
|
+
if (prev.options.columnReorder !== next.options.columnReorder) return false;
|
|
1919
|
+
if (prev.options.columnResize !== next.options.columnResize) return false;
|
|
1920
|
+
if (prev.options.columnHeaderMenu !== next.options.columnHeaderMenu) {
|
|
1921
|
+
return false;
|
|
1922
|
+
}
|
|
1923
|
+
if (prev.getColumnMinClassName !== next.getColumnMinClassName) {
|
|
1924
|
+
return false;
|
|
1925
|
+
}
|
|
1926
|
+
if (prev.draggedId !== next.draggedId) {
|
|
1927
|
+
return false;
|
|
1928
|
+
}
|
|
1929
|
+
if (prev.table !== next.table) return false;
|
|
1930
|
+
if (prev.onHeaderCellDragOver !== next.onHeaderCellDragOver) return false;
|
|
1931
|
+
if (prev.onHeaderCellDrop !== next.onHeaderCellDrop) return false;
|
|
1932
|
+
if (prev.onHeaderContextMenu !== next.onHeaderContextMenu) return false;
|
|
1933
|
+
if (prev.setDraggedId !== next.setDraggedId) return false;
|
|
1934
|
+
if (prev.setDropTargetId !== next.setDropTargetId) return false;
|
|
1935
|
+
if (prev.endColumnDrag !== next.endColumnDrag) return false;
|
|
1936
|
+
if (prev.registerColumnMenu !== next.registerColumnMenu) return false;
|
|
1937
|
+
return true;
|
|
1938
|
+
}
|
|
1939
|
+
);
|
|
1940
|
+
var TableViewDataRow = React5.memo(function TableViewDataRow2({
|
|
1941
|
+
row,
|
|
1942
|
+
getColumnMinClassName,
|
|
1943
|
+
options,
|
|
1944
|
+
isLastRow
|
|
1945
|
+
}) {
|
|
1946
|
+
return /* @__PURE__ */ jsxs(
|
|
1947
|
+
TableRow,
|
|
1948
|
+
{
|
|
1949
|
+
className: "relative isolate",
|
|
1950
|
+
"data-state": row.getIsSelected() ? "selected" : void 0,
|
|
1951
|
+
children: [
|
|
1952
|
+
options.rowSelection ? /* @__PURE__ */ jsx(
|
|
1953
|
+
TableCell,
|
|
1954
|
+
{
|
|
1955
|
+
className: cn(
|
|
1956
|
+
"w-10 min-w-10 max-w-12 shrink-0 !px-2 !py-3 text-center align-middle md:!px-2.5 md:!py-4",
|
|
1957
|
+
isLastRow && tableViewColumnRoundBottom
|
|
1958
|
+
),
|
|
1959
|
+
onClick: (e) => e.stopPropagation(),
|
|
1960
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex w-full items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
1961
|
+
Checkbox,
|
|
1962
|
+
{
|
|
1963
|
+
className: "scale-90",
|
|
1964
|
+
checked: row.getIsSelected(),
|
|
1965
|
+
disabled: !row.getCanSelect(),
|
|
1966
|
+
onCheckedChange: (next) => {
|
|
1967
|
+
if (!row.getCanSelect()) return;
|
|
1968
|
+
row.toggleSelected(!!next);
|
|
1969
|
+
},
|
|
1970
|
+
"aria-label": "Select this row"
|
|
1971
|
+
}
|
|
1972
|
+
) })
|
|
1973
|
+
}
|
|
1974
|
+
) : null,
|
|
1975
|
+
row.getVisibleCells().map((cell) => {
|
|
1976
|
+
const cid = cell.column.id;
|
|
1977
|
+
const cSize = cell.column.getSize();
|
|
1978
|
+
const cellPin = getColumnPinningStyle(cell.column);
|
|
1979
|
+
const cellSize = options.columnResize ? {
|
|
1980
|
+
width: cSize,
|
|
1981
|
+
minWidth: cell.column.columnDef.minSize,
|
|
1982
|
+
maxWidth: cell.column.columnDef.maxSize
|
|
1983
|
+
} : {};
|
|
1984
|
+
return /* @__PURE__ */ jsx(
|
|
1985
|
+
TableCell,
|
|
1986
|
+
{
|
|
1987
|
+
columnId: cid,
|
|
1988
|
+
className: cn(
|
|
1989
|
+
!options.columnResize ? getColumnMinClassName?.(cid) : void 0,
|
|
1990
|
+
getColumnPinningClassName(cell.column),
|
|
1991
|
+
isLastRow && tableViewColumnRoundBottom
|
|
1992
|
+
),
|
|
1993
|
+
style: { ...cellPin, ...cellSize },
|
|
1994
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
1995
|
+
},
|
|
1996
|
+
cell.id
|
|
1997
|
+
);
|
|
1998
|
+
})
|
|
1999
|
+
]
|
|
2000
|
+
}
|
|
2001
|
+
);
|
|
2002
|
+
});
|
|
2003
|
+
function TableView({
|
|
2004
|
+
table,
|
|
2005
|
+
sortableColumnIds: sortableColumns,
|
|
2006
|
+
options: optionsProp,
|
|
2007
|
+
getColumnMinClassName,
|
|
2008
|
+
containerClassName,
|
|
2009
|
+
persistKey
|
|
2010
|
+
}) {
|
|
2011
|
+
const options = useMemo(
|
|
2012
|
+
() => ({
|
|
2013
|
+
columnSort: optionsProp?.columnSort ?? true,
|
|
2014
|
+
columnReorder: optionsProp?.columnReorder ?? false,
|
|
2015
|
+
columnResize: optionsProp?.columnResize ?? false,
|
|
2016
|
+
rowSelection: optionsProp?.rowSelection ?? false,
|
|
2017
|
+
columnHeaderMenu: optionsProp?.columnHeaderMenu ?? false
|
|
2018
|
+
}),
|
|
2019
|
+
[
|
|
2020
|
+
optionsProp?.columnSort,
|
|
2021
|
+
optionsProp?.columnReorder,
|
|
2022
|
+
optionsProp?.columnResize,
|
|
2023
|
+
optionsProp?.rowSelection,
|
|
2024
|
+
optionsProp?.columnHeaderMenu
|
|
2025
|
+
]
|
|
2026
|
+
);
|
|
2027
|
+
useTableViewPersistence(table, persistKey, {
|
|
2028
|
+
columnResize: options.columnResize,
|
|
2029
|
+
columnHeaderMenu: options.columnHeaderMenu
|
|
2030
|
+
});
|
|
2031
|
+
const [draggedId, setDraggedId] = useState(null);
|
|
2032
|
+
const [dropTargetId, setDropTargetId] = useState(null);
|
|
2033
|
+
const columnMenuByIdRef = useRef({});
|
|
2034
|
+
const tableForMenu = table;
|
|
2035
|
+
const endColumnDrag = useCallback(() => {
|
|
2036
|
+
setDraggedId(null);
|
|
2037
|
+
setDropTargetId(null);
|
|
2038
|
+
}, []);
|
|
2039
|
+
const onDragOverCell = useCallback(
|
|
2040
|
+
(e) => e.preventDefault(),
|
|
2041
|
+
[]
|
|
2042
|
+
);
|
|
2043
|
+
const onHeaderContextMenu = useCallback(
|
|
2044
|
+
(e) => {
|
|
2045
|
+
const t = e.currentTarget;
|
|
2046
|
+
const colId = t.getAttribute("data-column-id");
|
|
2047
|
+
if (!colId) return;
|
|
2048
|
+
e.preventDefault();
|
|
2049
|
+
e.stopPropagation();
|
|
2050
|
+
columnMenuByIdRef.current[colId]?.open();
|
|
2051
|
+
},
|
|
2052
|
+
[]
|
|
2053
|
+
);
|
|
2054
|
+
const onHeaderCellDrop = useCallback(
|
|
2055
|
+
(e) => {
|
|
2056
|
+
e.preventDefault();
|
|
2057
|
+
const toId = e.currentTarget.getAttribute("data-column-id");
|
|
2058
|
+
if (!toId) return;
|
|
2059
|
+
const from = e.dataTransfer.getData("text/plain");
|
|
2060
|
+
if (!from || from === toId) return;
|
|
2061
|
+
table.setColumnOrder((o) => moveColumnInOrder([...o], from, toId));
|
|
2062
|
+
endColumnDrag();
|
|
2063
|
+
},
|
|
2064
|
+
[table, endColumnDrag]
|
|
2065
|
+
);
|
|
2066
|
+
const onHeaderCellDragOver = useCallback(
|
|
2067
|
+
(e) => {
|
|
2068
|
+
onDragOverCell(e);
|
|
2069
|
+
if (!options.columnReorder || !draggedId) return;
|
|
2070
|
+
const colId = e.currentTarget.getAttribute("data-column-id");
|
|
2071
|
+
if (colId) setDropTargetId(colId);
|
|
2072
|
+
},
|
|
2073
|
+
[onDragOverCell, options.columnReorder, draggedId, setDropTargetId]
|
|
2074
|
+
);
|
|
2075
|
+
const registerColumnMenu = useCallback(
|
|
2076
|
+
(columnId, h) => {
|
|
2077
|
+
if (h) columnMenuByIdRef.current[columnId] = h;
|
|
2078
|
+
else delete columnMenuByIdRef.current[columnId];
|
|
2079
|
+
},
|
|
2080
|
+
[]
|
|
2081
|
+
);
|
|
2082
|
+
const sortableForTable = useMemo(
|
|
2083
|
+
() => options.columnSort ? sortableColumns : EMPTY_STRING_ARRAY,
|
|
2084
|
+
[options.columnSort, sortableColumns]
|
|
2085
|
+
);
|
|
2086
|
+
const columnDragState = useMemo(
|
|
2087
|
+
() => options.columnReorder ? { draggingId: draggedId, dropTargetId } : null,
|
|
2088
|
+
[options.columnReorder, draggedId, dropTargetId]
|
|
2089
|
+
);
|
|
2090
|
+
const pageRows = table.getRowModel().rows;
|
|
2091
|
+
const dataRowOptions = useMemo(
|
|
2092
|
+
() => ({
|
|
2093
|
+
columnResize: options.columnResize,
|
|
2094
|
+
rowSelection: options.rowSelection
|
|
2095
|
+
}),
|
|
2096
|
+
[options.columnResize, options.rowSelection]
|
|
2097
|
+
);
|
|
2098
|
+
return /* @__PURE__ */ jsxs(
|
|
2099
|
+
Table,
|
|
2100
|
+
{
|
|
2101
|
+
className: "border-separate border-spacing-0",
|
|
2102
|
+
sortableColumns: sortableForTable,
|
|
2103
|
+
enableColumnSort: options.columnSort,
|
|
2104
|
+
enableColumnReorder: options.columnReorder,
|
|
2105
|
+
enableColumnResize: options.columnResize,
|
|
2106
|
+
columnDragState,
|
|
2107
|
+
containerClassName: containerClassName ?? "min-w-0",
|
|
2108
|
+
children: [
|
|
2109
|
+
/* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => {
|
|
2110
|
+
const allPageSelected = table.getIsAllPageRowsSelected();
|
|
2111
|
+
const somePageSelected = table.getIsSomePageRowsSelected();
|
|
2112
|
+
return /* @__PURE__ */ jsxs(TableRow, { className: "relative isolate", children: [
|
|
2113
|
+
options.rowSelection ? /* @__PURE__ */ jsx(
|
|
2114
|
+
TableHead,
|
|
2115
|
+
{
|
|
2116
|
+
className: cn(
|
|
2117
|
+
"w-10 min-w-10 max-w-12 shrink-0 !px-2 text-center align-middle md:!px-2.5",
|
|
2118
|
+
tableViewColumnRoundTop
|
|
2119
|
+
),
|
|
2120
|
+
onDragOver: onDragOverCell,
|
|
2121
|
+
scope: "col",
|
|
2122
|
+
children: /* @__PURE__ */ jsx("span", { className: "inline-flex w-full items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
2123
|
+
Checkbox,
|
|
2124
|
+
{
|
|
2125
|
+
className: "scale-90",
|
|
2126
|
+
checked: allPageSelected,
|
|
2127
|
+
indeterminate: !allPageSelected && somePageSelected,
|
|
2128
|
+
onClick: (e) => {
|
|
2129
|
+
e.stopPropagation();
|
|
2130
|
+
table.getToggleAllPageRowsSelectedHandler()(e);
|
|
2131
|
+
e.preventDefault();
|
|
2132
|
+
},
|
|
2133
|
+
title: "Select all on this page",
|
|
2134
|
+
"aria-label": "Select all rows on this page"
|
|
2135
|
+
}
|
|
2136
|
+
) })
|
|
2137
|
+
}
|
|
2138
|
+
) : null,
|
|
2139
|
+
headerGroup.headers.map((header) => /* @__PURE__ */ jsx(
|
|
2140
|
+
TableViewColumnHead,
|
|
2141
|
+
{
|
|
2142
|
+
table: tableForMenu,
|
|
2143
|
+
header,
|
|
2144
|
+
options,
|
|
2145
|
+
getColumnMinClassName,
|
|
2146
|
+
draggedId,
|
|
2147
|
+
onHeaderCellDragOver,
|
|
2148
|
+
onHeaderCellDrop,
|
|
2149
|
+
onHeaderContextMenu,
|
|
2150
|
+
setDraggedId,
|
|
2151
|
+
setDropTargetId,
|
|
2152
|
+
endColumnDrag,
|
|
2153
|
+
registerColumnMenu
|
|
2154
|
+
},
|
|
2155
|
+
header.id
|
|
2156
|
+
))
|
|
2157
|
+
] }, headerGroup.id);
|
|
2158
|
+
}) }),
|
|
2159
|
+
/* @__PURE__ */ jsx(TableBody, { children: pageRows.map((row, rowIndex) => /* @__PURE__ */ jsx(
|
|
2160
|
+
TableViewDataRow,
|
|
2161
|
+
{
|
|
2162
|
+
row,
|
|
2163
|
+
getColumnMinClassName,
|
|
2164
|
+
options: dataRowOptions,
|
|
2165
|
+
isLastRow: rowIndex === pageRows.length - 1
|
|
2166
|
+
},
|
|
2167
|
+
row.id
|
|
2168
|
+
)) })
|
|
2169
|
+
]
|
|
2170
|
+
}
|
|
2171
|
+
);
|
|
2172
|
+
}
|
|
2173
|
+
/*! Bundled license information:
|
|
2174
|
+
|
|
2175
|
+
@tanstack/react-table/build/lib/index.mjs:
|
|
2176
|
+
(**
|
|
2177
|
+
* react-table
|
|
2178
|
+
*
|
|
2179
|
+
* Copyright (c) TanStack
|
|
2180
|
+
*
|
|
2181
|
+
* This source code is licensed under the MIT license found in the
|
|
2182
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
2183
|
+
*
|
|
2184
|
+
* @license MIT
|
|
2185
|
+
*)
|
|
2186
|
+
*/
|
|
2187
|
+
|
|
2188
|
+
export { TABLE_VIEW_PERSIST_STORAGE_KEY, TableView, getColumnHeaderLabel, getSelectedRowIds, moveColumnInOrder, useRafBatchedColumnSizing, useTransitionColumnSizing };
|
|
2189
|
+
//# sourceMappingURL=index.js.map
|
|
2190
|
+
//# sourceMappingURL=index.js.map
|