@nextlyhq/ui 0.0.2-alpha.50 → 0.0.2-alpha.52

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 CHANGED
@@ -72,8 +72,9 @@ as a Tailwind v3 preset from `@nextlyhq/ui/tailwind-preset`.
72
72
  **Display:** `Badge`, `Card`, `Alert`, `Separator`, `Skeleton`, `Progress`
73
73
  **Toggles:** `Checkbox`, `RadioGroup`, `Switch`, `Collapsible`
74
74
  **Layout and disclosure:** `Accordion`, `Avatar`, `Tabs`, `Tooltip`, `Popover`
75
+ **Resizable regions:** `ResizablePanelGroup`, `ResizablePanel`, `ResizableHandle`
75
76
  **Overlays:** `Dialog`, `AlertDialog`, `Sheet`
76
- **Menus and command palette:** `DropdownMenu`, `Select`, `Command`
77
+ **Menus and command palette:** `DropdownMenu`, `ContextMenu`, `Select`, `Command`
77
78
  **Feedback:** `Spinner`, `Toaster` (with `toast()` helper)
78
79
  **Tables:** `Table` primitives, `ResponsiveTable`, `TableSearch`, `TablePagination`, `TableSkeleton`, `TableEmpty`, `TableError`, `TableLoading`
79
80
  **Providers:** `PortalProvider`, `usePortalContainer`
@@ -118,7 +119,8 @@ Tailwind's internal `--tw-*` registrations, and the ancestor classes `dark:` and
118
119
 
119
120
  ### Overlays need a portal container
120
121
 
121
- AlertDialog, Command, Dialog, DropdownMenu, Popover, Select, Sheet and Tooltip render
122
+ AlertDialog, Command, ContextMenu, Dialog, DropdownMenu, Popover, Select, Sheet and
123
+ Tooltip render
122
124
  their overlay through a portal, which defaults to `document.body` — outside the wrapper,
123
125
  where the scoped rules and tokens do not reach. Triggers would look right and the menus
124
126
  they open would not. Point them back inside with `PortalProvider`:
package/dist/index.cjs CHANGED
@@ -74,6 +74,20 @@ __export(index_exports, {
74
74
  CommandList: () => CommandList,
75
75
  CommandSeparator: () => CommandSeparator,
76
76
  CommandShortcut: () => CommandShortcut,
77
+ ContextMenu: () => ContextMenu,
78
+ ContextMenuCheckboxItem: () => ContextMenuCheckboxItem,
79
+ ContextMenuContent: () => ContextMenuContent,
80
+ ContextMenuGroup: () => ContextMenuGroup,
81
+ ContextMenuItem: () => ContextMenuItem,
82
+ ContextMenuLabel: () => ContextMenuLabel,
83
+ ContextMenuRadioGroup: () => ContextMenuRadioGroup,
84
+ ContextMenuRadioItem: () => ContextMenuRadioItem,
85
+ ContextMenuSeparator: () => ContextMenuSeparator,
86
+ ContextMenuShortcut: () => ContextMenuShortcut,
87
+ ContextMenuSub: () => ContextMenuSub,
88
+ ContextMenuSubContent: () => ContextMenuSubContent,
89
+ ContextMenuSubTrigger: () => ContextMenuSubTrigger,
90
+ ContextMenuTrigger: () => ContextMenuTrigger,
77
91
  Dialog: () => Dialog,
78
92
  DialogClose: () => DialogClose,
79
93
  DialogContent: () => DialogContent,
@@ -111,6 +125,9 @@ __export(index_exports, {
111
125
  Progress: () => Progress,
112
126
  RadioGroup: () => RadioGroup,
113
127
  RadioGroupItem: () => RadioGroupItem,
128
+ ResizableHandle: () => ResizableHandle,
129
+ ResizablePanel: () => ResizablePanel,
130
+ ResizablePanelGroup: () => ResizablePanelGroup,
114
131
  Select: () => Select,
115
132
  SelectContent: () => SelectContent,
116
133
  SelectGroup: () => SelectGroup,
@@ -1167,10 +1184,12 @@ var DialogOverlay = (0, import_react14.forwardRef)(({ className, ...props }, ref
1167
1184
  ref,
1168
1185
  "data-slot": "dialog-overlay",
1169
1186
  className: cn(
1170
- // A modal scrim: a black wash is the point, so it stays a literal
1171
- // rather than a surface token. Painting it from `background` would
1172
- // make it a white veil in light mode and near-invisible in dark.
1173
- "fixed inset-0 z-50 bg-black/80 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",
1187
+ // A modal scrim, from the `--nx-overlay` token rather than a surface
1188
+ // token. A black wash is the point — painting it from `background` would
1189
+ // make it a white veil in light mode but the alpha still has to differ
1190
+ // per mode, because what it composites over is white in one and mid-tone
1191
+ // in the other.
1192
+ "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",
1174
1193
  className
1175
1194
  ),
1176
1195
  ...props
@@ -1287,10 +1306,12 @@ var AlertDialogOverlay = (0, import_react15.forwardRef)(({ className, ...props }
1287
1306
  {
1288
1307
  ref,
1289
1308
  className: cn(
1290
- // A modal scrim: a black wash is the point, so it stays a literal
1291
- // rather than a surface token. Painting it from `background` would
1292
- // make it a white veil in light mode and near-invisible in dark.
1293
- "fixed inset-0 z-50 bg-black/80 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",
1309
+ // A modal scrim, from the `--nx-overlay` token rather than a surface
1310
+ // token. A black wash is the point — painting it from `background` would
1311
+ // make it a white veil in light mode but the alpha still has to differ
1312
+ // per mode, because what it composites over is white in one and mid-tone
1313
+ // in the other.
1314
+ "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",
1294
1315
  className
1295
1316
  ),
1296
1317
  ...props
@@ -1712,10 +1733,12 @@ var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PUR
1712
1733
  DialogPrimitive2.Overlay,
1713
1734
  {
1714
1735
  className: cn(
1715
- // A modal scrim: a black wash is the point, so it stays a literal
1716
- // rather than a surface token. Painting it from `background` would
1717
- // make it a white veil in light mode and near-invisible in dark.
1718
- "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm",
1736
+ // A modal scrim, from the `--nx-overlay` token rather than a surface
1737
+ // token. A black wash is the point — painting it from `background` would
1738
+ // make it a white veil in light mode but the alpha still has to differ
1739
+ // per mode, because what it composites over is white in one and mid-tone
1740
+ // in the other.
1741
+ "fixed inset-0 z-50 bg-overlay backdrop-blur-sm",
1719
1742
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
1720
1743
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1721
1744
  className
@@ -1830,10 +1853,12 @@ var CommandDialogOverlay = (0, import_react17.forwardRef)(({ className, ...props
1830
1853
  {
1831
1854
  ref,
1832
1855
  className: cn(
1833
- // A modal scrim: a black wash is the point, so it stays a literal
1834
- // rather than a surface token. Painting it from `background` would
1835
- // make it a white veil in light mode and near-invisible in dark.
1836
- "fixed inset-0 z-[99] bg-black/80 backdrop-blur-sm",
1856
+ // A modal scrim, from the `--nx-overlay` token rather than a surface
1857
+ // token. A black wash is the point — painting it from `background` would
1858
+ // make it a white veil in light mode but the alpha still has to differ
1859
+ // per mode, because what it composites over is white in one and mid-tone
1860
+ // in the other.
1861
+ "fixed inset-0 z-[99] bg-overlay backdrop-blur-sm",
1837
1862
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
1838
1863
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
1839
1864
  "transition-opacity duration-200",
@@ -2278,6 +2303,192 @@ var TableSkeleton = ({
2278
2303
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "table-wrapper rounded-md border border-border bg-card overflow-hidden", children: content });
2279
2304
  };
2280
2305
  TableSkeleton.displayName = "TableSkeleton";
2306
+
2307
+ // src/components/context-menu.tsx
2308
+ var ContextMenuPrimitive = __toESM(require("@radix-ui/react-context-menu"), 1);
2309
+ var import_lucide_react12 = require("lucide-react");
2310
+ var React9 = __toESM(require("react"), 1);
2311
+ var import_jsx_runtime34 = require("react/jsx-runtime");
2312
+ var menuItemBase2 = "cursor-pointer transition-colors data-[highlighted]:bg-muted data-[highlighted]:text-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50";
2313
+ 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]";
2314
+ var ContextMenu = ContextMenuPrimitive.Root;
2315
+ var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
2316
+ var ContextMenuGroup = ContextMenuPrimitive.Group;
2317
+ var ContextMenuSub = ContextMenuPrimitive.Sub;
2318
+ var ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
2319
+ var ContextMenuSubTrigger = React9.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2320
+ ContextMenuPrimitive.SubTrigger,
2321
+ {
2322
+ ref,
2323
+ className: cn(
2324
+ "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",
2325
+ menuItemBase2,
2326
+ inset && "pl-8",
2327
+ className
2328
+ ),
2329
+ ...props,
2330
+ children: [
2331
+ children,
2332
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react12.ChevronRight, { className: "ml-auto" })
2333
+ ]
2334
+ }
2335
+ ));
2336
+ ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
2337
+ var ContextMenuSubContent = React9.forwardRef(({ className, ...props }, ref) => {
2338
+ const portalContainer = usePortalContainer();
2339
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2340
+ ContextMenuPrimitive.SubContent,
2341
+ {
2342
+ ref,
2343
+ className: cn(menuSurface, className),
2344
+ ...props
2345
+ }
2346
+ ) });
2347
+ });
2348
+ ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
2349
+ var ContextMenuContent = React9.forwardRef(({ className, ...props }, ref) => {
2350
+ const portalContainer = usePortalContainer();
2351
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ContextMenuPrimitive.Portal, { container: portalContainer, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2352
+ ContextMenuPrimitive.Content,
2353
+ {
2354
+ ref,
2355
+ className: cn(menuSurface, className),
2356
+ ...props
2357
+ }
2358
+ ) });
2359
+ });
2360
+ ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
2361
+ var ContextMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2362
+ ContextMenuPrimitive.Item,
2363
+ {
2364
+ ref,
2365
+ className: cn(
2366
+ "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",
2367
+ menuItemBase2,
2368
+ inset && "pl-8",
2369
+ className
2370
+ ),
2371
+ ...props
2372
+ }
2373
+ ));
2374
+ ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
2375
+ var ContextMenuCheckboxItem = React9.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2376
+ ContextMenuPrimitive.CheckboxItem,
2377
+ {
2378
+ ref,
2379
+ className: cn(
2380
+ "relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
2381
+ menuItemBase2,
2382
+ className
2383
+ ),
2384
+ checked,
2385
+ ...props,
2386
+ children: [
2387
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react12.Check, { className: "h-4 w-4" }) }) }),
2388
+ children
2389
+ ]
2390
+ }
2391
+ ));
2392
+ ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
2393
+ var ContextMenuRadioItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
2394
+ ContextMenuPrimitive.RadioItem,
2395
+ {
2396
+ ref,
2397
+ className: cn(
2398
+ "relative flex select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none",
2399
+ menuItemBase2,
2400
+ className
2401
+ ),
2402
+ ...props,
2403
+ children: [
2404
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ContextMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_lucide_react12.Circle, { className: "h-2 w-2 fill-current" }) }) }),
2405
+ children
2406
+ ]
2407
+ }
2408
+ ));
2409
+ ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
2410
+ var ContextMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2411
+ ContextMenuPrimitive.Label,
2412
+ {
2413
+ ref,
2414
+ className: cn(
2415
+ "px-2 py-1.5 text-sm font-semibold text-foreground",
2416
+ inset && "pl-8",
2417
+ className
2418
+ ),
2419
+ ...props
2420
+ }
2421
+ ));
2422
+ ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
2423
+ var ContextMenuSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2424
+ ContextMenuPrimitive.Separator,
2425
+ {
2426
+ ref,
2427
+ className: cn("-mx-1 my-1 h-px bg-border", className),
2428
+ ...props
2429
+ }
2430
+ ));
2431
+ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
2432
+ var ContextMenuShortcut = ({
2433
+ className,
2434
+ ...props
2435
+ }) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
2436
+ "span",
2437
+ {
2438
+ className: cn(
2439
+ "ml-auto text-xs tracking-widest text-muted-foreground",
2440
+ className
2441
+ ),
2442
+ ...props
2443
+ }
2444
+ );
2445
+ ContextMenuShortcut.displayName = "ContextMenuShortcut";
2446
+
2447
+ // src/components/resizable.tsx
2448
+ var import_lucide_react13 = require("lucide-react");
2449
+ var ResizablePrimitive = __toESM(require("react-resizable-panels"), 1);
2450
+ var import_jsx_runtime35 = require("react/jsx-runtime");
2451
+ var ResizablePanelGroup = ({
2452
+ className,
2453
+ ...props
2454
+ }) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
2455
+ ResizablePrimitive.Group,
2456
+ {
2457
+ className: cn("h-full w-full", className),
2458
+ ...props
2459
+ }
2460
+ );
2461
+ var ResizablePanel = ResizablePrimitive.Panel;
2462
+ var ResizableHandle = ({
2463
+ withGrip,
2464
+ className,
2465
+ children,
2466
+ ...props
2467
+ }) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
2468
+ ResizablePrimitive.Separator,
2469
+ {
2470
+ className: cn(
2471
+ // The drawn line is 1px; the element around it is wider and transparent, so the pointer
2472
+ // target is comfortably larger than what it appears to grab (WCAG 2.5.8).
2473
+ "relative flex items-center justify-center bg-border",
2474
+ // Keyed off `aria-orientation`, which is what the separator actually carries, and read as
2475
+ // the ARIA spec defines it: the attribute describes the SEPARATOR, not the group. A
2476
+ // horizontal group puts its panels side by side, so its separator is a vertical line.
2477
+ "aria-[orientation=vertical]:w-px aria-[orientation=horizontal]:h-px",
2478
+ "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
2479
+ // Reachable without precision pointing, without drawing a heavier divider: the hit area
2480
+ // grows across the line, so a vertical line widens and a horizontal one deepens.
2481
+ "after:absolute after:inset-0",
2482
+ "aria-[orientation=vertical]:after:-inset-x-1 aria-[orientation=horizontal]:after:-inset-y-1",
2483
+ className
2484
+ ),
2485
+ ...props,
2486
+ children: [
2487
+ withGrip ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border border-border bg-border", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react13.GripVertical, { className: "h-2.5 w-2.5 text-muted-foreground" }) }) : null,
2488
+ children
2489
+ ]
2490
+ }
2491
+ );
2281
2492
  // Annotate the CommonJS export names for ESM import in node:
2282
2493
  0 && (module.exports = {
2283
2494
  Accordion,
@@ -2323,6 +2534,20 @@ TableSkeleton.displayName = "TableSkeleton";
2323
2534
  CommandList,
2324
2535
  CommandSeparator,
2325
2536
  CommandShortcut,
2537
+ ContextMenu,
2538
+ ContextMenuCheckboxItem,
2539
+ ContextMenuContent,
2540
+ ContextMenuGroup,
2541
+ ContextMenuItem,
2542
+ ContextMenuLabel,
2543
+ ContextMenuRadioGroup,
2544
+ ContextMenuRadioItem,
2545
+ ContextMenuSeparator,
2546
+ ContextMenuShortcut,
2547
+ ContextMenuSub,
2548
+ ContextMenuSubContent,
2549
+ ContextMenuSubTrigger,
2550
+ ContextMenuTrigger,
2326
2551
  Dialog,
2327
2552
  DialogClose,
2328
2553
  DialogContent,
@@ -2360,6 +2585,9 @@ TableSkeleton.displayName = "TableSkeleton";
2360
2585
  Progress,
2361
2586
  RadioGroup,
2362
2587
  RadioGroupItem,
2588
+ ResizableHandle,
2589
+ ResizablePanel,
2590
+ ResizablePanelGroup,
2363
2591
  Select,
2364
2592
  SelectContent,
2365
2593
  SelectGroup,