@nextlyhq/ui 0.0.2-alpha.51 → 0.0.2-alpha.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/index.cjs +565 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +423 -8
- package/dist/index.d.ts +423 -8
- package/dist/index.mjs +547 -16
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.scoped.css +1 -1
- package/dist/tailwind-preset.cjs +7 -0
- package/dist/tailwind-preset.cjs.map +1 -1
- package/dist/tailwind-preset.d.cts +4 -0
- package/dist/tailwind-preset.d.ts +4 -0
- package/dist/tailwind-preset.mjs +7 -0
- package/dist/tailwind-preset.mjs.map +1 -1
- package/dist/theme.css +26 -0
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +2 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +7 -4
package/dist/index.mjs
CHANGED
|
@@ -1004,10 +1004,12 @@ var DialogOverlay = forwardRef17(({ className, ...props }, ref) => /* @__PURE__
|
|
|
1004
1004
|
ref,
|
|
1005
1005
|
"data-slot": "dialog-overlay",
|
|
1006
1006
|
className: cn(
|
|
1007
|
-
// A modal scrim
|
|
1008
|
-
//
|
|
1009
|
-
// make it a white veil in light mode
|
|
1010
|
-
|
|
1007
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1008
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1009
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1010
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1011
|
+
// in the other.
|
|
1012
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm transition-opacity duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1011
1013
|
className
|
|
1012
1014
|
),
|
|
1013
1015
|
...props
|
|
@@ -1126,10 +1128,12 @@ var AlertDialogOverlay = forwardRef18(({ className, ...props }, ref) => /* @__PU
|
|
|
1126
1128
|
{
|
|
1127
1129
|
ref,
|
|
1128
1130
|
className: cn(
|
|
1129
|
-
// A modal scrim
|
|
1130
|
-
//
|
|
1131
|
-
// make it a white veil in light mode
|
|
1132
|
-
|
|
1131
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1132
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1133
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1134
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1135
|
+
// in the other.
|
|
1136
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm transition-opacity duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1133
1137
|
className
|
|
1134
1138
|
),
|
|
1135
1139
|
...props
|
|
@@ -1551,10 +1555,12 @@ var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
1551
1555
|
DialogPrimitive2.Overlay,
|
|
1552
1556
|
{
|
|
1553
1557
|
className: cn(
|
|
1554
|
-
// A modal scrim
|
|
1555
|
-
//
|
|
1556
|
-
// make it a white veil in light mode
|
|
1557
|
-
|
|
1558
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1559
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1560
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1561
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1562
|
+
// in the other.
|
|
1563
|
+
"fixed inset-0 z-50 bg-overlay backdrop-blur-sm",
|
|
1558
1564
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1559
1565
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1560
1566
|
className
|
|
@@ -1669,10 +1675,12 @@ var CommandDialogOverlay = forwardRef22(({ className, ...props }, ref) => /* @__
|
|
|
1669
1675
|
{
|
|
1670
1676
|
ref,
|
|
1671
1677
|
className: cn(
|
|
1672
|
-
// A modal scrim
|
|
1673
|
-
//
|
|
1674
|
-
// make it a white veil in light mode
|
|
1675
|
-
|
|
1678
|
+
// A modal scrim, from the `--nx-overlay` token rather than a surface
|
|
1679
|
+
// token. A black wash is the point — painting it from `background` would
|
|
1680
|
+
// make it a white veil in light mode — but the alpha still has to differ
|
|
1681
|
+
// per mode, because what it composites over is white in one and mid-tone
|
|
1682
|
+
// in the other.
|
|
1683
|
+
"fixed inset-0 z-[99] bg-overlay backdrop-blur-sm",
|
|
1676
1684
|
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
1677
1685
|
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1678
1686
|
"transition-opacity duration-200",
|
|
@@ -2123,6 +2131,511 @@ var TableSkeleton = ({
|
|
|
2123
2131
|
return /* @__PURE__ */ jsx33("div", { className: "table-wrapper rounded-md border border-border bg-card overflow-hidden", children: content });
|
|
2124
2132
|
};
|
|
2125
2133
|
TableSkeleton.displayName = "TableSkeleton";
|
|
2134
|
+
|
|
2135
|
+
// src/components/context-menu.tsx
|
|
2136
|
+
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
2137
|
+
import { Check as Check4, ChevronRight as ChevronRight2, Circle as Circle2 } from "lucide-react";
|
|
2138
|
+
import * as React9 from "react";
|
|
2139
|
+
import { jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2140
|
+
var menuItemBase2 = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
|
|
2141
|
+
var menuSurface = "z-50 max-h-[var(--radix-context-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-lg border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 origin-[--radix-context-menu-content-transform-origin]";
|
|
2142
|
+
var ContextMenu = ContextMenuPrimitive.Root;
|
|
2143
|
+
var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
2144
|
+
var ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
2145
|
+
var ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
2146
|
+
var ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
2147
|
+
var ContextMenuSubTrigger = React9.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
|
|
2148
|
+
ContextMenuPrimitive.SubTrigger,
|
|
2149
|
+
{
|
|
2150
|
+
ref,
|
|
2151
|
+
className: cn(
|
|
2152
|
+
"flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-muted [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2153
|
+
menuItemBase2,
|
|
2154
|
+
inset && "pl-8",
|
|
2155
|
+
className
|
|
2156
|
+
),
|
|
2157
|
+
...props,
|
|
2158
|
+
children: [
|
|
2159
|
+
children,
|
|
2160
|
+
/* @__PURE__ */ jsx34(ChevronRight2, { className: "ml-auto" })
|
|
2161
|
+
]
|
|
2162
|
+
}
|
|
2163
|
+
));
|
|
2164
|
+
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
2165
|
+
var ContextMenuSubContent = React9.forwardRef(({ className, ...props }, ref) => {
|
|
2166
|
+
const portalContainer = usePortalContainer();
|
|
2167
|
+
return /* @__PURE__ */ jsx34(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx34(
|
|
2168
|
+
ContextMenuPrimitive.SubContent,
|
|
2169
|
+
{
|
|
2170
|
+
ref,
|
|
2171
|
+
className: cn(menuSurface, className),
|
|
2172
|
+
...props
|
|
2173
|
+
}
|
|
2174
|
+
) });
|
|
2175
|
+
});
|
|
2176
|
+
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
2177
|
+
var ContextMenuContent = React9.forwardRef(({ className, ...props }, ref) => {
|
|
2178
|
+
const portalContainer = usePortalContainer();
|
|
2179
|
+
return /* @__PURE__ */ jsx34(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ jsx34(
|
|
2180
|
+
ContextMenuPrimitive.Content,
|
|
2181
|
+
{
|
|
2182
|
+
ref,
|
|
2183
|
+
className: cn(menuSurface, className),
|
|
2184
|
+
...props
|
|
2185
|
+
}
|
|
2186
|
+
) });
|
|
2187
|
+
});
|
|
2188
|
+
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
2189
|
+
var ContextMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx34(
|
|
2190
|
+
ContextMenuPrimitive.Item,
|
|
2191
|
+
{
|
|
2192
|
+
ref,
|
|
2193
|
+
className: cn(
|
|
2194
|
+
"relative flex select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2195
|
+
menuItemBase2,
|
|
2196
|
+
inset && "pl-8",
|
|
2197
|
+
className
|
|
2198
|
+
),
|
|
2199
|
+
...props
|
|
2200
|
+
}
|
|
2201
|
+
));
|
|
2202
|
+
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
2203
|
+
var ContextMenuCheckboxItem = React9.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs13(
|
|
2204
|
+
ContextMenuPrimitive.CheckboxItem,
|
|
2205
|
+
{
|
|
2206
|
+
ref,
|
|
2207
|
+
className: cn(
|
|
2208
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
2209
|
+
menuItemBase2,
|
|
2210
|
+
className
|
|
2211
|
+
),
|
|
2212
|
+
checked,
|
|
2213
|
+
...props,
|
|
2214
|
+
children: [
|
|
2215
|
+
/* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(Check4, { className: "h-4 w-4" }) }) }),
|
|
2216
|
+
children
|
|
2217
|
+
]
|
|
2218
|
+
}
|
|
2219
|
+
));
|
|
2220
|
+
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
|
|
2221
|
+
var ContextMenuRadioItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs13(
|
|
2222
|
+
ContextMenuPrimitive.RadioItem,
|
|
2223
|
+
{
|
|
2224
|
+
ref,
|
|
2225
|
+
className: cn(
|
|
2226
|
+
"relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
|
|
2227
|
+
menuItemBase2,
|
|
2228
|
+
className
|
|
2229
|
+
),
|
|
2230
|
+
...props,
|
|
2231
|
+
children: [
|
|
2232
|
+
/* @__PURE__ */ jsx34("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx34(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx34(Circle2, { className: "h-2 w-2 fill-current" }) }) }),
|
|
2233
|
+
children
|
|
2234
|
+
]
|
|
2235
|
+
}
|
|
2236
|
+
));
|
|
2237
|
+
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
2238
|
+
var ContextMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx34(
|
|
2239
|
+
ContextMenuPrimitive.Label,
|
|
2240
|
+
{
|
|
2241
|
+
ref,
|
|
2242
|
+
className: cn(
|
|
2243
|
+
"px-2 py-1.5 text-sm font-semibold text-foreground",
|
|
2244
|
+
inset && "pl-8",
|
|
2245
|
+
className
|
|
2246
|
+
),
|
|
2247
|
+
...props
|
|
2248
|
+
}
|
|
2249
|
+
));
|
|
2250
|
+
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
2251
|
+
var ContextMenuSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx34(
|
|
2252
|
+
ContextMenuPrimitive.Separator,
|
|
2253
|
+
{
|
|
2254
|
+
ref,
|
|
2255
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
2256
|
+
...props
|
|
2257
|
+
}
|
|
2258
|
+
));
|
|
2259
|
+
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
2260
|
+
var ContextMenuShortcut = ({
|
|
2261
|
+
className,
|
|
2262
|
+
...props
|
|
2263
|
+
}) => /* @__PURE__ */ jsx34(
|
|
2264
|
+
"span",
|
|
2265
|
+
{
|
|
2266
|
+
className: cn(
|
|
2267
|
+
"ml-auto text-xs tracking-widest text-muted-foreground",
|
|
2268
|
+
className
|
|
2269
|
+
),
|
|
2270
|
+
...props
|
|
2271
|
+
}
|
|
2272
|
+
);
|
|
2273
|
+
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
2274
|
+
|
|
2275
|
+
// src/components/resizable.tsx
|
|
2276
|
+
import { GripVertical } from "lucide-react";
|
|
2277
|
+
import * as ResizablePrimitive from "react-resizable-panels";
|
|
2278
|
+
import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2279
|
+
var ResizablePanelGroup = ({
|
|
2280
|
+
className,
|
|
2281
|
+
...props
|
|
2282
|
+
}) => /* @__PURE__ */ jsx35(
|
|
2283
|
+
ResizablePrimitive.Group,
|
|
2284
|
+
{
|
|
2285
|
+
className: cn("h-full w-full", className),
|
|
2286
|
+
...props
|
|
2287
|
+
}
|
|
2288
|
+
);
|
|
2289
|
+
var ResizablePanel = ResizablePrimitive.Panel;
|
|
2290
|
+
var ResizableHandle = ({
|
|
2291
|
+
withGrip,
|
|
2292
|
+
className,
|
|
2293
|
+
children,
|
|
2294
|
+
...props
|
|
2295
|
+
}) => /* @__PURE__ */ jsxs14(
|
|
2296
|
+
ResizablePrimitive.Separator,
|
|
2297
|
+
{
|
|
2298
|
+
className: cn(
|
|
2299
|
+
// The drawn line is 1px; the element around it is wider and transparent, so the pointer
|
|
2300
|
+
// target is comfortably larger than what it appears to grab (WCAG 2.5.8).
|
|
2301
|
+
"relative flex items-center justify-center bg-border",
|
|
2302
|
+
// Keyed off `aria-orientation`, which is what the separator actually carries, and read as
|
|
2303
|
+
// the ARIA spec defines it: the attribute describes the SEPARATOR, not the group. A
|
|
2304
|
+
// horizontal group puts its panels side by side, so its separator is a vertical line.
|
|
2305
|
+
"aria-[orientation=vertical]:w-px aria-[orientation=horizontal]:h-px",
|
|
2306
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
|
|
2307
|
+
// Reachable without precision pointing, without drawing a heavier divider: the hit area
|
|
2308
|
+
// grows across the line, so a vertical line widens and a horizontal one deepens.
|
|
2309
|
+
"after:absolute after:inset-0",
|
|
2310
|
+
"aria-[orientation=vertical]:after:-inset-x-1 aria-[orientation=horizontal]:after:-inset-y-1",
|
|
2311
|
+
className
|
|
2312
|
+
),
|
|
2313
|
+
...props,
|
|
2314
|
+
children: [
|
|
2315
|
+
withGrip ? /* @__PURE__ */ jsx35("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-border", children: /* @__PURE__ */ jsx35(GripVertical, { className: "h-2.5 w-2.5 text-muted-foreground" }) }) : null,
|
|
2316
|
+
children
|
|
2317
|
+
]
|
|
2318
|
+
}
|
|
2319
|
+
);
|
|
2320
|
+
|
|
2321
|
+
// src/components/tree-view.tsx
|
|
2322
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2323
|
+
import { ChevronRight as ChevronRight3 } from "lucide-react";
|
|
2324
|
+
import * as React10 from "react";
|
|
2325
|
+
import { jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2326
|
+
var ROW_HEIGHT = 28;
|
|
2327
|
+
var INDENT_PER_LEVEL = 12;
|
|
2328
|
+
function textOf(node) {
|
|
2329
|
+
if (typeof node.textValue === "string") return node.textValue;
|
|
2330
|
+
return typeof node.label === "string" ? node.label : "";
|
|
2331
|
+
}
|
|
2332
|
+
function flatten(nodes, expanded) {
|
|
2333
|
+
const rows = [];
|
|
2334
|
+
const pending = [{ list: nodes, index: 0, level: 0 }];
|
|
2335
|
+
while (pending.length > 0) {
|
|
2336
|
+
const frame = pending[pending.length - 1];
|
|
2337
|
+
if (frame === void 0 || frame.index >= frame.list.length) {
|
|
2338
|
+
pending.pop();
|
|
2339
|
+
continue;
|
|
2340
|
+
}
|
|
2341
|
+
const node = frame.list[frame.index];
|
|
2342
|
+
const posInSet = frame.index;
|
|
2343
|
+
frame.index += 1;
|
|
2344
|
+
if (node === void 0) continue;
|
|
2345
|
+
const hasChildren = node.children !== void 0;
|
|
2346
|
+
rows.push({
|
|
2347
|
+
node,
|
|
2348
|
+
level: frame.level,
|
|
2349
|
+
setSize: frame.list.length,
|
|
2350
|
+
posInSet,
|
|
2351
|
+
parentId: frame.parentId,
|
|
2352
|
+
hasChildren
|
|
2353
|
+
});
|
|
2354
|
+
if (hasChildren && expanded.has(node.id)) {
|
|
2355
|
+
pending.push({
|
|
2356
|
+
list: node.children ?? [],
|
|
2357
|
+
index: 0,
|
|
2358
|
+
level: frame.level + 1,
|
|
2359
|
+
parentId: node.id
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
return rows;
|
|
2364
|
+
}
|
|
2365
|
+
function useControllable(controlled, fallback) {
|
|
2366
|
+
const [uncontrolled, setUncontrolled] = React10.useState(fallback);
|
|
2367
|
+
return [
|
|
2368
|
+
controlled === void 0 ? uncontrolled : controlled,
|
|
2369
|
+
setUncontrolled
|
|
2370
|
+
];
|
|
2371
|
+
}
|
|
2372
|
+
var TreeView = React10.forwardRef(
|
|
2373
|
+
({
|
|
2374
|
+
nodes,
|
|
2375
|
+
expandedIds,
|
|
2376
|
+
defaultExpandedIds,
|
|
2377
|
+
onExpandedChange,
|
|
2378
|
+
selectedId,
|
|
2379
|
+
defaultSelectedId,
|
|
2380
|
+
onSelectedChange,
|
|
2381
|
+
className,
|
|
2382
|
+
"aria-label": ariaLabel,
|
|
2383
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2384
|
+
"aria-describedby": ariaDescribedBy,
|
|
2385
|
+
...props
|
|
2386
|
+
}, forwardedRef) => {
|
|
2387
|
+
const scrollRef = React10.useRef(null);
|
|
2388
|
+
const attachScroll = React10.useCallback(
|
|
2389
|
+
(node) => {
|
|
2390
|
+
scrollRef.current = node;
|
|
2391
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
2392
|
+
else if (forwardedRef !== null && forwardedRef !== void 0) {
|
|
2393
|
+
forwardedRef.current = node;
|
|
2394
|
+
}
|
|
2395
|
+
},
|
|
2396
|
+
[forwardedRef]
|
|
2397
|
+
);
|
|
2398
|
+
const [expandedState, setExpandedState] = useControllable(
|
|
2399
|
+
expandedIds === void 0 ? void 0 : [...expandedIds],
|
|
2400
|
+
[...defaultExpandedIds ?? []]
|
|
2401
|
+
);
|
|
2402
|
+
const expanded = React10.useMemo(
|
|
2403
|
+
() => new Set(expandedIds ?? expandedState),
|
|
2404
|
+
[expandedIds, expandedState]
|
|
2405
|
+
);
|
|
2406
|
+
const [selected, setSelected] = useControllable(
|
|
2407
|
+
selectedId === void 0 ? void 0 : selectedId,
|
|
2408
|
+
defaultSelectedId ?? null
|
|
2409
|
+
);
|
|
2410
|
+
const rows = React10.useMemo(
|
|
2411
|
+
() => flatten(nodes, expanded),
|
|
2412
|
+
[nodes, expanded]
|
|
2413
|
+
);
|
|
2414
|
+
const [activeId, setActiveId] = React10.useState(null);
|
|
2415
|
+
const activeIndex = Math.max(
|
|
2416
|
+
0,
|
|
2417
|
+
rows.findIndex((row) => row.node.id === (activeId ?? selected))
|
|
2418
|
+
);
|
|
2419
|
+
const virtualizer = useVirtualizer({
|
|
2420
|
+
count: rows.length,
|
|
2421
|
+
getScrollElement: () => scrollRef.current,
|
|
2422
|
+
estimateSize: () => ROW_HEIGHT,
|
|
2423
|
+
overscan: 8
|
|
2424
|
+
});
|
|
2425
|
+
const commitExpanded = (next) => {
|
|
2426
|
+
const ids = [...next];
|
|
2427
|
+
if (expandedIds === void 0) setExpandedState(ids);
|
|
2428
|
+
onExpandedChange?.(ids);
|
|
2429
|
+
};
|
|
2430
|
+
const setExpansion = (id, open) => {
|
|
2431
|
+
const next = new Set(expanded);
|
|
2432
|
+
if (open) next.add(id);
|
|
2433
|
+
else next.delete(id);
|
|
2434
|
+
commitExpanded(next);
|
|
2435
|
+
};
|
|
2436
|
+
const choose = (id) => {
|
|
2437
|
+
if (selectedId === void 0) setSelected(id);
|
|
2438
|
+
onSelectedChange?.(id);
|
|
2439
|
+
};
|
|
2440
|
+
const focusRow = (index) => {
|
|
2441
|
+
const row = rows[index];
|
|
2442
|
+
if (row === void 0) return;
|
|
2443
|
+
setActiveId(row.node.id);
|
|
2444
|
+
virtualizer.scrollToIndex(index, { align: "auto" });
|
|
2445
|
+
requestAnimationFrame(() => {
|
|
2446
|
+
const element = scrollRef.current?.querySelector(
|
|
2447
|
+
`[data-tree-index="${index}"]`
|
|
2448
|
+
);
|
|
2449
|
+
element?.focus();
|
|
2450
|
+
});
|
|
2451
|
+
};
|
|
2452
|
+
const step = (from, delta) => {
|
|
2453
|
+
for (let index = from + delta; index >= 0 && index < rows.length; index += delta) {
|
|
2454
|
+
if (rows[index]?.node.disabled !== true) return index;
|
|
2455
|
+
}
|
|
2456
|
+
return from;
|
|
2457
|
+
};
|
|
2458
|
+
const typeahead = React10.useRef({ query: "", at: 0 });
|
|
2459
|
+
const onKeyDown = (event) => {
|
|
2460
|
+
const index = activeIndex;
|
|
2461
|
+
const row = rows[index];
|
|
2462
|
+
if (row === void 0) return;
|
|
2463
|
+
switch (event.key) {
|
|
2464
|
+
case "ArrowDown":
|
|
2465
|
+
event.preventDefault();
|
|
2466
|
+
focusRow(step(index, 1));
|
|
2467
|
+
return;
|
|
2468
|
+
case "ArrowUp":
|
|
2469
|
+
event.preventDefault();
|
|
2470
|
+
focusRow(step(index, -1));
|
|
2471
|
+
return;
|
|
2472
|
+
case "ArrowRight":
|
|
2473
|
+
event.preventDefault();
|
|
2474
|
+
if (row.hasChildren && !expanded.has(row.node.id)) {
|
|
2475
|
+
setExpansion(row.node.id, true);
|
|
2476
|
+
} else if (row.hasChildren) {
|
|
2477
|
+
for (let child = index + 1; child < rows.length && (rows[child]?.level ?? 0) > row.level; child += 1) {
|
|
2478
|
+
if (rows[child]?.parentId === row.node.id && rows[child]?.node.disabled !== true) {
|
|
2479
|
+
focusRow(child);
|
|
2480
|
+
break;
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return;
|
|
2485
|
+
case "ArrowLeft":
|
|
2486
|
+
event.preventDefault();
|
|
2487
|
+
if (row.hasChildren && expanded.has(row.node.id)) {
|
|
2488
|
+
setExpansion(row.node.id, false);
|
|
2489
|
+
} else if (row.parentId !== void 0) {
|
|
2490
|
+
let ancestor = row.parentId;
|
|
2491
|
+
while (ancestor !== void 0) {
|
|
2492
|
+
const at = rows.findIndex(
|
|
2493
|
+
(candidate) => candidate.node.id === ancestor
|
|
2494
|
+
);
|
|
2495
|
+
if (at < 0) break;
|
|
2496
|
+
if (rows[at]?.node.disabled !== true) {
|
|
2497
|
+
focusRow(at);
|
|
2498
|
+
break;
|
|
2499
|
+
}
|
|
2500
|
+
ancestor = rows[at]?.parentId;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
return;
|
|
2504
|
+
case "Home":
|
|
2505
|
+
event.preventDefault();
|
|
2506
|
+
focusRow(rows[0]?.node.disabled === true ? step(0, 1) : 0);
|
|
2507
|
+
return;
|
|
2508
|
+
case "End": {
|
|
2509
|
+
event.preventDefault();
|
|
2510
|
+
const last = rows.length - 1;
|
|
2511
|
+
focusRow(rows[last]?.node.disabled === true ? step(last, -1) : last);
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
case "Enter":
|
|
2515
|
+
case " ":
|
|
2516
|
+
event.preventDefault();
|
|
2517
|
+
if (row.node.disabled !== true) choose(row.node.id);
|
|
2518
|
+
return;
|
|
2519
|
+
case "*": {
|
|
2520
|
+
event.preventDefault();
|
|
2521
|
+
const next = new Set(expanded);
|
|
2522
|
+
for (const sibling of rows) {
|
|
2523
|
+
if (sibling.parentId === row.parentId && sibling.hasChildren) {
|
|
2524
|
+
next.add(sibling.node.id);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
commitExpanded(next);
|
|
2528
|
+
return;
|
|
2529
|
+
}
|
|
2530
|
+
default:
|
|
2531
|
+
break;
|
|
2532
|
+
}
|
|
2533
|
+
if (event.key.length !== 1 || event.metaKey || event.ctrlKey || event.altKey) {
|
|
2534
|
+
return;
|
|
2535
|
+
}
|
|
2536
|
+
event.preventDefault();
|
|
2537
|
+
const now = Date.now();
|
|
2538
|
+
const state = typeahead.current;
|
|
2539
|
+
state.query = now - state.at > 500 ? event.key : state.query + event.key;
|
|
2540
|
+
state.at = now;
|
|
2541
|
+
const query = state.query.toLowerCase();
|
|
2542
|
+
for (let offset = 1; offset <= rows.length; offset += 1) {
|
|
2543
|
+
const candidate = rows[(index + offset) % rows.length];
|
|
2544
|
+
if (candidate === void 0 || candidate.node.disabled === true)
|
|
2545
|
+
continue;
|
|
2546
|
+
if (textOf(candidate.node).toLowerCase().startsWith(query)) {
|
|
2547
|
+
focusRow(rows.indexOf(candidate));
|
|
2548
|
+
return;
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
};
|
|
2552
|
+
const virtualItems = virtualizer.getVirtualItems();
|
|
2553
|
+
const usable = (index) => rows[index]?.node.disabled !== true;
|
|
2554
|
+
const tabStopIndex = virtualItems.some((item) => item.index === activeIndex) && usable(activeIndex) ? activeIndex : virtualItems.find((item) => usable(item.index))?.index ?? -1;
|
|
2555
|
+
return /* @__PURE__ */ jsx36(
|
|
2556
|
+
"div",
|
|
2557
|
+
{
|
|
2558
|
+
ref: attachScroll,
|
|
2559
|
+
className: cn("overflow-auto", className),
|
|
2560
|
+
...props,
|
|
2561
|
+
children: /* @__PURE__ */ jsx36(
|
|
2562
|
+
"div",
|
|
2563
|
+
{
|
|
2564
|
+
role: "tree",
|
|
2565
|
+
"aria-label": ariaLabel,
|
|
2566
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2567
|
+
"aria-describedby": ariaDescribedBy,
|
|
2568
|
+
onKeyDown,
|
|
2569
|
+
style: { height: virtualizer.getTotalSize(), position: "relative" },
|
|
2570
|
+
children: virtualItems.map((item) => {
|
|
2571
|
+
const row = rows[item.index];
|
|
2572
|
+
if (row === void 0) return null;
|
|
2573
|
+
const isSelected = selected === row.node.id;
|
|
2574
|
+
return /* @__PURE__ */ jsxs15(
|
|
2575
|
+
"div",
|
|
2576
|
+
{
|
|
2577
|
+
"data-tree-index": item.index,
|
|
2578
|
+
role: "treeitem",
|
|
2579
|
+
"aria-level": row.level + 1,
|
|
2580
|
+
"aria-setsize": row.setSize,
|
|
2581
|
+
"aria-posinset": row.posInSet + 1,
|
|
2582
|
+
"aria-selected": isSelected,
|
|
2583
|
+
"aria-expanded": row.hasChildren ? expanded.has(row.node.id) : void 0,
|
|
2584
|
+
"aria-disabled": row.node.disabled === true ? true : void 0,
|
|
2585
|
+
tabIndex: item.index === tabStopIndex ? 0 : -1,
|
|
2586
|
+
onFocus: () => setActiveId(row.node.id),
|
|
2587
|
+
onClick: () => {
|
|
2588
|
+
if (row.node.disabled === true) return;
|
|
2589
|
+
setActiveId(row.node.id);
|
|
2590
|
+
choose(row.node.id);
|
|
2591
|
+
},
|
|
2592
|
+
className: cn(
|
|
2593
|
+
"absolute left-0 flex w-full select-none items-center gap-1 rounded-sm pr-2 text-sm outline-none",
|
|
2594
|
+
"focus-visible:ring-1 focus-visible:ring-ring",
|
|
2595
|
+
row.node.disabled === true ? "pointer-events-none opacity-50" : "cursor-pointer",
|
|
2596
|
+
isSelected ? "bg-muted text-foreground" : "hover:bg-muted/50"
|
|
2597
|
+
),
|
|
2598
|
+
style: {
|
|
2599
|
+
height: item.size,
|
|
2600
|
+
transform: `translateY(${item.start}px)`,
|
|
2601
|
+
paddingLeft: 4 + row.level * INDENT_PER_LEVEL
|
|
2602
|
+
},
|
|
2603
|
+
children: [
|
|
2604
|
+
/* @__PURE__ */ jsx36(
|
|
2605
|
+
"span",
|
|
2606
|
+
{
|
|
2607
|
+
"aria-hidden": "true",
|
|
2608
|
+
className: "flex size-4 shrink-0 items-center justify-center",
|
|
2609
|
+
onClick: (event) => {
|
|
2610
|
+
if (!row.hasChildren) return;
|
|
2611
|
+
event.stopPropagation();
|
|
2612
|
+
setExpansion(row.node.id, !expanded.has(row.node.id));
|
|
2613
|
+
},
|
|
2614
|
+
children: row.hasChildren ? /* @__PURE__ */ jsx36(
|
|
2615
|
+
ChevronRight3,
|
|
2616
|
+
{
|
|
2617
|
+
className: cn(
|
|
2618
|
+
"size-3.5 text-muted-foreground transition-transform",
|
|
2619
|
+
expanded.has(row.node.id) && "rotate-90"
|
|
2620
|
+
)
|
|
2621
|
+
}
|
|
2622
|
+
) : null
|
|
2623
|
+
}
|
|
2624
|
+
),
|
|
2625
|
+
row.node.icon !== void 0 ? /* @__PURE__ */ jsx36("span", { className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground", children: row.node.icon }) : null,
|
|
2626
|
+
/* @__PURE__ */ jsx36("span", { className: "truncate", children: row.node.label })
|
|
2627
|
+
]
|
|
2628
|
+
},
|
|
2629
|
+
row.node.id
|
|
2630
|
+
);
|
|
2631
|
+
})
|
|
2632
|
+
}
|
|
2633
|
+
)
|
|
2634
|
+
}
|
|
2635
|
+
);
|
|
2636
|
+
}
|
|
2637
|
+
);
|
|
2638
|
+
TreeView.displayName = "TreeView";
|
|
2126
2639
|
export {
|
|
2127
2640
|
Accordion,
|
|
2128
2641
|
AccordionContent,
|
|
@@ -2167,6 +2680,20 @@ export {
|
|
|
2167
2680
|
CommandList,
|
|
2168
2681
|
CommandSeparator,
|
|
2169
2682
|
CommandShortcut,
|
|
2683
|
+
ContextMenu,
|
|
2684
|
+
ContextMenuCheckboxItem,
|
|
2685
|
+
ContextMenuContent,
|
|
2686
|
+
ContextMenuGroup,
|
|
2687
|
+
ContextMenuItem,
|
|
2688
|
+
ContextMenuLabel,
|
|
2689
|
+
ContextMenuRadioGroup,
|
|
2690
|
+
ContextMenuRadioItem,
|
|
2691
|
+
ContextMenuSeparator,
|
|
2692
|
+
ContextMenuShortcut,
|
|
2693
|
+
ContextMenuSub,
|
|
2694
|
+
ContextMenuSubContent,
|
|
2695
|
+
ContextMenuSubTrigger,
|
|
2696
|
+
ContextMenuTrigger,
|
|
2170
2697
|
Dialog,
|
|
2171
2698
|
DialogClose,
|
|
2172
2699
|
DialogContent,
|
|
@@ -2204,6 +2731,9 @@ export {
|
|
|
2204
2731
|
Progress,
|
|
2205
2732
|
RadioGroup,
|
|
2206
2733
|
RadioGroupItem,
|
|
2734
|
+
ResizableHandle,
|
|
2735
|
+
ResizablePanel,
|
|
2736
|
+
ResizablePanelGroup,
|
|
2207
2737
|
Select,
|
|
2208
2738
|
SelectContent,
|
|
2209
2739
|
SelectGroup,
|
|
@@ -2253,6 +2783,7 @@ export {
|
|
|
2253
2783
|
TooltipContent,
|
|
2254
2784
|
TooltipProvider,
|
|
2255
2785
|
TooltipTrigger,
|
|
2786
|
+
TreeView,
|
|
2256
2787
|
alertVariants,
|
|
2257
2788
|
avatarVariants,
|
|
2258
2789
|
badgeVariants,
|