@lessly/ui 4.0.0 → 4.1.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.
@@ -336,11 +336,57 @@ var SheetDescription = React3.forwardRef(({ className, ...props }, ref) => /* @_
336
336
  ));
337
337
  SheetDescription.displayName = SheetPrimitive.Description.displayName;
338
338
 
339
- // src/components/entity-row.tsx
339
+ // src/components/scroll-area.tsx
340
340
  import * as React4 from "react";
341
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
342
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
343
+ var ScrollArea = React4.forwardRef(({ className, children, viewportClassName, viewportProps, type = "scroll", scrollHideDelay = 600, ...props }, ref) => /* @__PURE__ */ jsxs3(
344
+ ScrollAreaPrimitive.Root,
345
+ {
346
+ ref,
347
+ type,
348
+ scrollHideDelay,
349
+ className: cn("group/scroll relative overflow-hidden", className),
350
+ ...props,
351
+ children: [
352
+ /* @__PURE__ */ jsx4(
353
+ ScrollAreaPrimitive.Viewport,
354
+ {
355
+ ...viewportProps,
356
+ className: cn("scroll-overlay-viewport h-full w-full rounded-[inherit]", viewportClassName),
357
+ children
358
+ }
359
+ ),
360
+ /* @__PURE__ */ jsx4(ScrollBar, {}),
361
+ /* @__PURE__ */ jsx4(ScrollAreaPrimitive.Corner, {})
362
+ ]
363
+ }
364
+ ));
365
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
366
+ var ScrollBar = React4.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx4(
367
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
368
+ {
369
+ ref,
370
+ orientation,
371
+ forceMount: true,
372
+ className: cn(
373
+ "motion-scroll-overlay flex touch-none select-none p-[2px] opacity-0",
374
+ "data-[state=visible]:opacity-100 group-hover/scroll:opacity-100 hover:opacity-100",
375
+ orientation === "vertical" && "h-full w-2",
376
+ orientation === "horizontal" && "h-2 flex-col",
377
+ className
378
+ ),
379
+ ...props,
380
+ children: /* @__PURE__ */ jsx4(ScrollAreaPrimitive.ScrollAreaThumb, { className: "relative flex-1 rounded-full bg-border-strong" })
381
+ }
382
+ ));
383
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
384
+
385
+ // src/components/entity-row.tsx
386
+ import * as React5 from "react";
341
387
  import { Slot as Slot2 } from "@radix-ui/react-slot";
342
388
  import { ChevronDown, ChevronRight } from "lucide-react";
343
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
389
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
344
390
  var rowClass = "flex w-full items-center gap-3 px-4 py-2.5 text-left";
345
391
  var plateClass = "relative isolate after:pointer-events-none after:absolute after:inset-x-1.5 after:inset-y-1 after:-z-10 after:rounded-lg hover:after:bg-[var(--hov-bg)] disabled:hover:after:bg-transparent focus-visible:outline-none focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-border-focus";
346
392
  var stackClass = "flex-col items-stretch gap-1";
@@ -348,25 +394,25 @@ var caretMotion = {
348
394
  transitionDuration: "var(--motion-duration-normal)",
349
395
  transitionTimingFunction: "var(--motion-easing-standard)"
350
396
  };
351
- var EntityRow = React4.forwardRef(function EntityRow2({ mark, title, badge, sub, meta, summary, opens = "page", expanded, asChild = false, className, children, ...props }, ref) {
397
+ var EntityRow = React5.forwardRef(function EntityRow2({ mark, title, badge, sub, meta, summary, opens = "page", expanded, asChild = false, className, children, ...props }, ref) {
352
398
  if (process.env.NODE_ENV !== "production" && opens === "disclosure" && expanded === void 0) {
353
399
  console.warn(
354
400
  '[EntityRow] `opens="disclosure"` needs `expanded`: it draws the caret AND sets `aria-expanded`, and without it the row renders a caret that never turns and states no state at all. Pass `expanded={open}`, or use `opens="page"` / `opens="modal"`.'
355
401
  );
356
402
  }
357
- const line = /* @__PURE__ */ jsxs3(Fragment2, { children: [
403
+ const line = /* @__PURE__ */ jsxs4(Fragment2, { children: [
358
404
  mark,
359
- /* @__PURE__ */ jsxs3("span", { className: "min-w-0 flex-1", children: [
360
- /* @__PURE__ */ jsxs3("span", { className: "flex min-h-5 items-center gap-2", children: [
361
- /* @__PURE__ */ jsx4("span", { className: cn("truncate text-sm text-text-primary", opens !== "none" && "font-medium"), children: title }),
362
- badge != null && /* @__PURE__ */ jsx4("span", { className: "flex h-5 shrink-0 items-center", children: badge })
405
+ /* @__PURE__ */ jsxs4("span", { className: "min-w-0 flex-1", children: [
406
+ /* @__PURE__ */ jsxs4("span", { className: "flex min-h-5 items-center gap-2", children: [
407
+ /* @__PURE__ */ jsx5("span", { className: cn("truncate text-sm text-text-primary", opens !== "none" && "font-medium"), children: title }),
408
+ badge != null && /* @__PURE__ */ jsx5("span", { className: "flex h-5 shrink-0 items-center", children: badge })
363
409
  ] }),
364
- sub != null && /* @__PURE__ */ jsx4("span", { className: "block truncate text-xs text-text-secondary", children: sub })
410
+ sub != null && /* @__PURE__ */ jsx5("span", { className: "block truncate text-xs text-text-secondary", children: sub })
365
411
  ] }),
366
- meta != null && /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-sm text-text-secondary", children: meta }),
367
- opens !== "none" && /* @__PURE__ */ jsxs3("span", { className: "flex size-4 shrink-0 items-center justify-center", children: [
368
- opens === "page" && /* @__PURE__ */ jsx4(ChevronRight, { className: "size-4 text-text-tertiary", "aria-hidden": true }),
369
- opens === "disclosure" && /* @__PURE__ */ jsx4(
412
+ meta != null && /* @__PURE__ */ jsx5("span", { className: "shrink-0 text-sm text-text-secondary", children: meta }),
413
+ opens !== "none" && /* @__PURE__ */ jsxs4("span", { className: "flex size-4 shrink-0 items-center justify-center", children: [
414
+ opens === "page" && /* @__PURE__ */ jsx5(ChevronRight, { className: "size-4 text-text-tertiary", "aria-hidden": true }),
415
+ opens === "disclosure" && /* @__PURE__ */ jsx5(
370
416
  ChevronDown,
371
417
  {
372
418
  className: cn(
@@ -379,20 +425,20 @@ var EntityRow = React4.forwardRef(function EntityRow2({ mark, title, badge, sub,
379
425
  )
380
426
  ] })
381
427
  ] });
382
- const content = summary == null ? line : /* @__PURE__ */ jsxs3(Fragment2, { children: [
383
- /* @__PURE__ */ jsx4("span", { className: "flex w-full items-center gap-3", children: line }),
384
- /* @__PURE__ */ jsx4("span", { className: "block w-full text-xs text-text-secondary", children: summary })
428
+ const content = summary == null ? line : /* @__PURE__ */ jsxs4(Fragment2, { children: [
429
+ /* @__PURE__ */ jsx5("span", { className: "flex w-full items-center gap-3", children: line }),
430
+ /* @__PURE__ */ jsx5("span", { className: "block w-full text-xs text-text-secondary", children: summary })
385
431
  ] });
386
432
  const classes = cn(rowClass, opens !== "none" && ["cursor-pointer", plateClass], summary != null && stackClass, className);
387
433
  const stateProps = opens === "disclosure" ? { "aria-expanded": expanded } : void 0;
388
434
  if (opens === "none") {
389
- return /* @__PURE__ */ jsx4("div", { ...props, ref, className: classes, children: content });
435
+ return /* @__PURE__ */ jsx5("div", { ...props, ref, className: classes, children: content });
390
436
  }
391
437
  if (asChild) {
392
- const child = React4.Children.only(children);
393
- return /* @__PURE__ */ jsx4(Slot2, { ...props, ref, className: classes, ...stateProps, children: React4.cloneElement(child, stateProps, content) });
438
+ const child = React5.Children.only(children);
439
+ return /* @__PURE__ */ jsx5(Slot2, { ...props, ref, className: classes, ...stateProps, children: React5.cloneElement(child, stateProps, content) });
394
440
  }
395
- return /* @__PURE__ */ jsx4("button", { ...props, ref, type: "button", className: classes, ...stateProps, children: content });
441
+ return /* @__PURE__ */ jsx5("button", { ...props, ref, type: "button", className: classes, ...stateProps, children: content });
396
442
  });
397
443
  EntityRow.displayName = "EntityRow";
398
444
 
@@ -438,10 +484,10 @@ function useSidebar(options = {}) {
438
484
  }
439
485
 
440
486
  // src/components/nav-row.tsx
441
- import * as React5 from "react";
487
+ import * as React6 from "react";
442
488
  import { Slot as Slot3 } from "@radix-ui/react-slot";
443
489
  import { ChevronDown as ChevronDown2, ChevronRight as ChevronRight2 } from "lucide-react";
444
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
490
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
445
491
  var base = "flex w-full cursor-pointer items-center text-left text-sm transition-colors duration-fast focus-visible:outline-none";
446
492
  var ring = "focus-visible:ring-2 focus-visible:ring-border-focus";
447
493
  var plate = "relative isolate after:pointer-events-none after:absolute after:inset-x-1.5 after:inset-y-1 after:-z-10 after:rounded-lg";
@@ -467,14 +513,14 @@ var state = {
467
513
  }
468
514
  };
469
515
  function Mark({ mark, open }) {
470
- return /* @__PURE__ */ jsx5(
516
+ return /* @__PURE__ */ jsx6(
471
517
  "span",
472
518
  {
473
519
  className: cn(
474
520
  "flex size-5 items-center justify-center",
475
521
  mark === "drill" ? "rounded-md transition-colors duration-fast group-hover/nav-row:bg-[color-mix(in_srgb,var(--text-primary)_10%,transparent)]" : "text-text-tertiary"
476
522
  ),
477
- children: mark === "drill" ? /* @__PURE__ */ jsx5(ChevronRight2, { className: "size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx5(
523
+ children: mark === "drill" ? /* @__PURE__ */ jsx6(ChevronRight2, { className: "size-4", "aria-hidden": "true" }) : /* @__PURE__ */ jsx6(
478
524
  ChevronDown2,
479
525
  {
480
526
  className: "size-4",
@@ -485,11 +531,11 @@ function Mark({ mark, open }) {
485
531
  }
486
532
  );
487
533
  }
488
- var NavRow = React5.forwardRef(function NavRow2({ icon, label, sub, active = false, variant, trailing, mark, markOpen, mutedTrailing = false, hideLabel = false, asChild = false, className, children, ...props }, ref) {
534
+ var NavRow = React6.forwardRef(function NavRow2({ icon, label, sub, active = false, variant, trailing, mark, markOpen, mutedTrailing = false, hideLabel = false, asChild = false, className, children, ...props }, ref) {
489
535
  const card = variant === "card";
490
- const adornment = mark ? !hideLabel && /* @__PURE__ */ jsx5(Mark, { mark, open: markOpen }) : trailing;
491
- const content = /* @__PURE__ */ jsxs4(Fragment3, { children: [
492
- Boolean(icon) && /* @__PURE__ */ jsx5(
536
+ const adornment = mark ? !hideLabel && /* @__PURE__ */ jsx6(Mark, { mark, open: markOpen }) : trailing;
537
+ const content = /* @__PURE__ */ jsxs5(Fragment3, { children: [
538
+ Boolean(icon) && /* @__PURE__ */ jsx6(
493
539
  "span",
494
540
  {
495
541
  className: cn(
@@ -500,11 +546,11 @@ var NavRow = React5.forwardRef(function NavRow2({ icon, label, sub, active = fal
500
546
  children: icon
501
547
  }
502
548
  ),
503
- !hideLabel && (card ? /* @__PURE__ */ jsxs4("span", { "data-slot": "nav-row-label", className: "min-w-0 flex-1", children: [
504
- /* @__PURE__ */ jsx5("span", { className: "block truncate", children: label }),
505
- Boolean(sub) && /* @__PURE__ */ jsx5("span", { className: "block truncate text-xs text-text-secondary", children: sub })
506
- ] }) : /* @__PURE__ */ jsx5("span", { "data-slot": "nav-row-label", className: "min-w-0 flex-1 truncate", children: label })),
507
- Boolean(adornment) && /* @__PURE__ */ jsx5(
549
+ !hideLabel && (card ? /* @__PURE__ */ jsxs5("span", { "data-slot": "nav-row-label", className: "min-w-0 flex-1", children: [
550
+ /* @__PURE__ */ jsx6("span", { className: "block truncate", children: label }),
551
+ Boolean(sub) && /* @__PURE__ */ jsx6("span", { className: "block truncate text-xs text-text-secondary", children: sub })
552
+ ] }) : /* @__PURE__ */ jsx6("span", { "data-slot": "nav-row-label", className: "min-w-0 flex-1 truncate", children: label })),
553
+ Boolean(adornment) && /* @__PURE__ */ jsx6(
508
554
  "span",
509
555
  {
510
556
  "data-slot": "nav-row-trailing",
@@ -515,7 +561,7 @@ var NavRow = React5.forwardRef(function NavRow2({ icon, label, sub, active = fal
515
561
  children: adornment
516
562
  }
517
563
  ),
518
- card && /* @__PURE__ */ jsx5("span", { className: "size-4 shrink-0", "aria-hidden": "true" })
564
+ card && /* @__PURE__ */ jsx6("span", { className: "size-4 shrink-0", "aria-hidden": "true" })
519
565
  ] });
520
566
  const classes = cn(
521
567
  base,
@@ -527,20 +573,20 @@ var NavRow = React5.forwardRef(function NavRow2({ icon, label, sub, active = fal
527
573
  );
528
574
  const expanded = mark === "disclosure" ? markOpen : void 0;
529
575
  if (asChild) {
530
- const child = React5.Children.only(children);
531
- return /* @__PURE__ */ jsx5(Slot3, { ref, className: classes, "aria-label": hideLabel ? label : void 0, "aria-expanded": expanded, ...props, children: React5.cloneElement(child, void 0, content) });
576
+ const child = React6.Children.only(children);
577
+ return /* @__PURE__ */ jsx6(Slot3, { ref, className: classes, "aria-label": hideLabel ? label : void 0, "aria-expanded": expanded, ...props, children: React6.cloneElement(child, void 0, content) });
532
578
  }
533
- return /* @__PURE__ */ jsx5("button", { ref, type: "button", className: classes, "aria-label": hideLabel ? label : void 0, "aria-expanded": expanded, ...props, children: content });
579
+ return /* @__PURE__ */ jsx6("button", { ref, type: "button", className: classes, "aria-label": hideLabel ? label : void 0, "aria-expanded": expanded, ...props, children: content });
534
580
  });
535
581
  NavRow.displayName = "NavRow";
536
582
 
537
583
  // src/components/rail-toggle.tsx
538
- import * as React6 from "react";
539
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
584
+ import * as React7 from "react";
585
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
540
586
  var RAIL_COLUMN_BOX = "flex size-10 shrink-0 items-center justify-center [&>*]:shrink-0";
541
587
  var BAR_TRAVEL = 6;
542
588
  function RailMark({ collapsed, className }) {
543
- return /* @__PURE__ */ jsxs5(
589
+ return /* @__PURE__ */ jsxs6(
544
590
  "svg",
545
591
  {
546
592
  xmlns: "http://www.w3.org/2000/svg",
@@ -553,8 +599,8 @@ function RailMark({ collapsed, className }) {
553
599
  className: cn("size-4", className),
554
600
  "aria-hidden": "true",
555
601
  children: [
556
- /* @__PURE__ */ jsx6("rect", { "data-slot": "rail-mark-frame", x: "3", y: "3", width: "18", height: "18", rx: "2" }),
557
- /* @__PURE__ */ jsx6(
602
+ /* @__PURE__ */ jsx7("rect", { "data-slot": "rail-mark-frame", x: "3", y: "3", width: "18", height: "18", rx: "2" }),
603
+ /* @__PURE__ */ jsx7(
558
604
  "path",
559
605
  {
560
606
  "data-slot": "rail-mark-bar",
@@ -567,8 +613,8 @@ function RailMark({ collapsed, className }) {
567
613
  }
568
614
  );
569
615
  }
570
- var RailToggle = React6.forwardRef(function RailToggle2({ collapsed, className, "aria-label": ariaLabel, ...rest }, ref) {
571
- return /* @__PURE__ */ jsx6(
616
+ var RailToggle = React7.forwardRef(function RailToggle2({ collapsed, className, "aria-label": ariaLabel, ...rest }, ref) {
617
+ return /* @__PURE__ */ jsx7(
572
618
  "button",
573
619
  {
574
620
  ref,
@@ -581,7 +627,7 @@ var RailToggle = React6.forwardRef(function RailToggle2({ collapsed, className,
581
627
  className
582
628
  ),
583
629
  ...rest,
584
- children: /* @__PURE__ */ jsx6(RailMark, { collapsed })
630
+ children: /* @__PURE__ */ jsx7(RailMark, { collapsed })
585
631
  }
586
632
  );
587
633
  });
@@ -604,6 +650,8 @@ export {
604
650
  SheetFooter,
605
651
  SheetTitle,
606
652
  SheetDescription,
653
+ ScrollArea,
654
+ ScrollBar,
607
655
  EntityRow,
608
656
  useIsMobile,
609
657
  useSidebar,
package/dist/index.d.ts CHANGED
@@ -848,7 +848,27 @@ declare const Collapsible: React$1.ForwardRefExoticComponent<CollapsiblePrimitiv
848
848
  declare const CollapsibleTrigger: React$1.ForwardRefExoticComponent<CollapsiblePrimitive.CollapsibleTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
849
849
  declare const CollapsibleContent: React$1.ForwardRefExoticComponent<Omit<CollapsiblePrimitive.CollapsibleContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
850
850
 
851
- declare const ScrollArea: React$1.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
851
+ /** A scroll region whose bar is drawn OVER the content rather than beside it (#2357).
852
+ *
853
+ * The platform's own bar is two things we don't want: on Windows and Linux it takes a lane out of
854
+ * the layout, so a region that starts scrolling reflows everything in it, and it is painted by the
855
+ * OS in a grey that answers to neither theme. This draws the bar itself, absolutely positioned, on
856
+ * the kit's own border token — so one declaration is correct in light and dark.
857
+ *
858
+ * `type="scroll"` plus `forceMount` is what makes it appear only when it is wanted. Radix keeps
859
+ * `data-state` on the bar — `visible` while the region is being scrolled, `hidden` once
860
+ * `scrollHideDelay` has passed — and the bar stays mounted so the pointer can bring it back too:
861
+ * hovering anywhere over the region is the other half of the rule, and CSS alone answers it.
862
+ */
863
+ declare const ScrollArea: React$1.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
864
+ /** Classes for the scrolling viewport — where a scroll region's own padding belongs, so that
865
+ * the bar rides over the padding instead of being inset by it. */
866
+ viewportClassName?: string;
867
+ /** Forwarded to the viewport, so a caller can reach the element that actually scrolls. */
868
+ viewportProps?: React$1.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Viewport> & {
869
+ [key: `data-${string}`]: string;
870
+ };
871
+ } & React$1.RefAttributes<HTMLDivElement>>;
852
872
  declare const ScrollBar: React$1.ForwardRefExoticComponent<Omit<ScrollAreaPrimitive.ScrollAreaScrollbarProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
853
873
 
854
874
  /**
@@ -2917,10 +2937,9 @@ declare const Col: React$1.ForwardRefExoticComponent<ColProps & React$1.RefAttri
2917
2937
  /**
2918
2938
  * The page column: the one grid a console page lays its cards on, in one of two widths.
2919
2939
  *
2920
- * `reading` (the default) is capped and centred in the well the width a page of cards, a form, a
2921
- * settings page, an overview or an entity detail is read at, which is most of the console. `full`
2922
- * drops the cap and fills the well, for a page whose main content is a table, a matrix, a roster, a
2923
- * log or a chart: something that gets better with horizontal room.
2940
+ * `reading` (the default) is capped and centred in the well, which is most of the console; `full`
2941
+ * drops the cap and fills it. Which one a page takes is Guidelines/Page & navigation/Page column's
2942
+ * answer.
2924
2943
  *
2925
2944
  * It writes no horizontal padding, ever. `AppShell` spells the inset once for `main` and the
2926
2945
  * top-bar row together, so a column that padded itself again would push the page off the trail
@@ -3010,7 +3029,7 @@ type ConnectorStatus = 'active' | 'needs-reconnect' | 'not-connected';
3010
3029
  interface ConnectorCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
3011
3030
  /**
3012
3031
  * The account name — what this connector is linked WITH, never a bare provider name and never a
3013
- * bare "Connected" (#270). E.g. "GitHub acme", "Google Ads ads@acme.com".
3032
+ * bare "Connected" (#270). E.g. "GitHub: acme", "Google Ads: ads@acme.com".
3014
3033
  */
3015
3034
  name: string;
3016
3035
  /** What kind of external account this is, in the provider's words: "GitHub organization". */