@l3mpire/ui 3.2.1 → 3.3.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/index.mjs CHANGED
@@ -15,9 +15,9 @@ function cn(...inputs) {
15
15
  }
16
16
 
17
17
  // src/components/ui/browser-tab.tsx
18
- import * as React3 from "react";
18
+ import * as React4 from "react";
19
19
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
20
- import { Icon as Icon3, faXmarkOutline, faGripDotsVerticalSolid, faPlusSolid, faChevronDownSolid } from "@l3mpire/icons";
20
+ import { Icon as Icon3, faXmarkOutline, faPenOutline, faGripDotsVerticalSolid, faPlusSolid, faChevronDownSolid } from "@l3mpire/icons";
21
21
 
22
22
  // src/components/ui/badge.tsx
23
23
  import * as React from "react";
@@ -44,19 +44,19 @@ var badgeVariants = cva(
44
44
  warning: "",
45
45
  neutral: ""
46
46
  },
47
- // Categorical tones self-contained soft style (bg + text + border).
48
- // When `tone` is set it overrides variant/type (handled in the component).
47
+ // Categorical palette. Colors come from {variant, tone} compound variants below,
48
+ // so a tone combines with solid / light / outlined just like `type` does.
49
49
  tone: {
50
- indigo: "bg-badge-indigo-bg text-badge-indigo-text border-badge-indigo-border",
51
- rose: "bg-badge-rose-bg text-badge-rose-text border-badge-rose-border",
52
- lime: "bg-badge-lime-bg text-badge-lime-text border-badge-lime-border",
53
- violet: "bg-badge-violet-bg text-badge-violet-text border-badge-violet-border",
54
- cyan: "bg-badge-cyan-bg text-badge-cyan-text border-badge-cyan-border",
55
- orange: "bg-badge-orange-bg text-badge-orange-text border-badge-orange-border",
56
- emerald: "bg-badge-emerald-bg text-badge-emerald-text border-badge-emerald-border",
57
- fuchsia: "bg-badge-fuchsia-bg text-badge-fuchsia-text border-badge-fuchsia-border",
58
- amber: "bg-badge-amber-bg text-badge-amber-text border-badge-amber-border",
59
- slate: "bg-badge-slate-bg text-badge-slate-text border-badge-slate-border"
50
+ indigo: "",
51
+ rose: "",
52
+ lime: "",
53
+ violet: "",
54
+ cyan: "",
55
+ orange: "",
56
+ emerald: "",
57
+ fuchsia: "",
58
+ amber: "",
59
+ slate: ""
60
60
  },
61
61
  size: {
62
62
  sm: [
@@ -94,9 +94,40 @@ var badgeVariants = cva(
94
94
  { variant: "outlined", type: "success", class: "border-badge-outlined-success-border text-badge-outlined-success-text" },
95
95
  { variant: "outlined", type: "critical", class: "border-badge-outlined-critical-border text-badge-outlined-critical-text" },
96
96
  { variant: "outlined", type: "warning", class: "border-badge-outlined-warning-border text-badge-outlined-warning-text" },
97
- { variant: "outlined", type: "neutral", class: "border-badge-outlined-neutral-border text-badge-outlined-neutral-text" }
97
+ { variant: "outlined", type: "neutral", class: "border-badge-outlined-neutral-border text-badge-outlined-neutral-text" },
98
+ // ── Categorical tones × variant ──────────────────────────────────────
99
+ { variant: "solid", tone: "indigo", class: "bg-badge-solid-indigo-bg text-badge-solid-indigo-text" },
100
+ { variant: "solid", tone: "rose", class: "bg-badge-solid-rose-bg text-badge-solid-rose-text" },
101
+ { variant: "solid", tone: "lime", class: "bg-badge-solid-lime-bg text-badge-solid-lime-text" },
102
+ { variant: "solid", tone: "violet", class: "bg-badge-solid-violet-bg text-badge-solid-violet-text" },
103
+ { variant: "solid", tone: "cyan", class: "bg-badge-solid-cyan-bg text-badge-solid-cyan-text" },
104
+ { variant: "solid", tone: "orange", class: "bg-badge-solid-orange-bg text-badge-solid-orange-text" },
105
+ { variant: "solid", tone: "emerald", class: "bg-badge-solid-emerald-bg text-badge-solid-emerald-text" },
106
+ { variant: "solid", tone: "fuchsia", class: "bg-badge-solid-fuchsia-bg text-badge-solid-fuchsia-text" },
107
+ { variant: "solid", tone: "amber", class: "bg-badge-solid-amber-bg text-badge-solid-amber-text" },
108
+ { variant: "solid", tone: "slate", class: "bg-badge-solid-slate-bg text-badge-solid-slate-text" },
109
+ { variant: "light", tone: "indigo", class: "bg-badge-light-indigo-bg text-badge-light-indigo-text" },
110
+ { variant: "light", tone: "rose", class: "bg-badge-light-rose-bg text-badge-light-rose-text" },
111
+ { variant: "light", tone: "lime", class: "bg-badge-light-lime-bg text-badge-light-lime-text" },
112
+ { variant: "light", tone: "violet", class: "bg-badge-light-violet-bg text-badge-light-violet-text" },
113
+ { variant: "light", tone: "cyan", class: "bg-badge-light-cyan-bg text-badge-light-cyan-text" },
114
+ { variant: "light", tone: "orange", class: "bg-badge-light-orange-bg text-badge-light-orange-text" },
115
+ { variant: "light", tone: "emerald", class: "bg-badge-light-emerald-bg text-badge-light-emerald-text" },
116
+ { variant: "light", tone: "fuchsia", class: "bg-badge-light-fuchsia-bg text-badge-light-fuchsia-text" },
117
+ { variant: "light", tone: "amber", class: "bg-badge-light-amber-bg text-badge-light-amber-text" },
118
+ { variant: "light", tone: "slate", class: "bg-badge-light-slate-bg text-badge-light-slate-text" },
119
+ { variant: "outlined", tone: "indigo", class: "border-badge-outlined-indigo-border text-badge-outlined-indigo-text" },
120
+ { variant: "outlined", tone: "rose", class: "border-badge-outlined-rose-border text-badge-outlined-rose-text" },
121
+ { variant: "outlined", tone: "lime", class: "border-badge-outlined-lime-border text-badge-outlined-lime-text" },
122
+ { variant: "outlined", tone: "violet", class: "border-badge-outlined-violet-border text-badge-outlined-violet-text" },
123
+ { variant: "outlined", tone: "cyan", class: "border-badge-outlined-cyan-border text-badge-outlined-cyan-text" },
124
+ { variant: "outlined", tone: "orange", class: "border-badge-outlined-orange-border text-badge-outlined-orange-text" },
125
+ { variant: "outlined", tone: "emerald", class: "border-badge-outlined-emerald-border text-badge-outlined-emerald-text" },
126
+ { variant: "outlined", tone: "fuchsia", class: "border-badge-outlined-fuchsia-border text-badge-outlined-fuchsia-text" },
127
+ { variant: "outlined", tone: "amber", class: "border-badge-outlined-amber-border text-badge-outlined-amber-text" },
128
+ { variant: "outlined", tone: "slate", class: "border-badge-outlined-slate-border text-badge-outlined-slate-text" }
98
129
  ],
99
- // variant/type defaults are applied in the component so `tone` can suppress them.
130
+ // variant/type defaults are applied in the component so `tone` can suppress `type`.
100
131
  defaultVariants: {
101
132
  size: "md"
102
133
  }
@@ -104,16 +135,15 @@ var badgeVariants = cva(
104
135
  );
105
136
  var Badge = React.forwardRef(
106
137
  ({ className, variant, type, tone, size, icon, children, ...props }, ref) => {
107
- const tonal = tone != null;
108
138
  return /* @__PURE__ */ jsxs(
109
139
  "span",
110
140
  {
111
141
  ref,
112
142
  className: cn(
113
143
  badgeVariants({
114
- // A categorical tone is self-contained and overrides variant/type.
115
- variant: tonal ? void 0 : variant ?? "solid",
116
- type: tonal ? void 0 : type ?? "primary",
144
+ variant: variant ?? "solid",
145
+ // `tone` and `type` share the color axis — when a tone is set it wins.
146
+ type: tone != null ? void 0 : type ?? "primary",
117
147
  tone,
118
148
  size
119
149
  }),
@@ -386,17 +416,78 @@ var Button = React2.forwardRef(
386
416
  );
387
417
  Button.displayName = "Button";
388
418
 
419
+ // src/components/ui/tooltip.tsx
420
+ import * as React3 from "react";
421
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
422
+ import { cva as cva3 } from "class-variance-authority";
423
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
424
+ var tooltipContentVariants = cva3(
425
+ [
426
+ "inline-flex items-center z-50",
427
+ "gap-xs",
428
+ "px-base py-sm",
429
+ "rounded-lg",
430
+ "shadow-lg",
431
+ "text-sm",
432
+ "font-regular",
433
+ "leading-sm",
434
+ "data-[state=delayed-open]:animate-[tooltip-in_150ms_ease-out]",
435
+ "data-[state=instant-open]:animate-[tooltip-in_0ms]",
436
+ "data-[state=closed]:animate-[tooltip-out_100ms_ease-in]"
437
+ ],
438
+ {
439
+ variants: {
440
+ type: {
441
+ default: [
442
+ "bg-tooltip-default-bg",
443
+ "text-tooltip-default-text"
444
+ ],
445
+ invert: [
446
+ "bg-tooltip-invert-bg",
447
+ "text-tooltip-invert-text",
448
+ "border border-tooltip-invert-border"
449
+ ]
450
+ }
451
+ },
452
+ defaultVariants: {
453
+ type: "default"
454
+ }
455
+ }
456
+ );
457
+ var TooltipProvider = TooltipPrimitive.Provider;
458
+ var Tooltip = TooltipPrimitive.Root;
459
+ var TooltipTrigger = TooltipPrimitive.Trigger;
460
+ var TooltipContent = React3.forwardRef(({ className, type, hasArrow = true, sideOffset = 4, children, ...props }, ref) => /* @__PURE__ */ jsx3(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs3(
461
+ TooltipPrimitive.Content,
462
+ {
463
+ ref,
464
+ sideOffset,
465
+ className: cn(tooltipContentVariants({ type, className })),
466
+ ...props,
467
+ children: [
468
+ children,
469
+ hasArrow && /* @__PURE__ */ jsx3(
470
+ TooltipPrimitive.Arrow,
471
+ {
472
+ className: type === "default" ? "fill-tooltip-default-bg" : "fill-tooltip-invert-bg"
473
+ }
474
+ )
475
+ ]
476
+ }
477
+ ) }));
478
+ TooltipContent.displayName = "TooltipContent";
479
+
389
480
  // src/components/ui/browser-tab.tsx
390
- import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
391
- var BrowserTabContext = React3.createContext(null);
392
- var BrowserTabItem = React3.forwardRef(
393
- ({ className, icon, label, badge, isActive = false, onClose, onRename, ...props }, ref) => {
394
- const [isHovered, setIsHovered] = React3.useState(false);
395
- const [isEditing, setIsEditing] = React3.useState(false);
396
- const [editValue, setEditValue] = React3.useState(label);
397
- const inputRef = React3.useRef(null);
398
- const ctx = React3.useContext(BrowserTabContext);
399
- React3.useEffect(() => {
481
+ import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
482
+ var BrowserTabContext = React4.createContext(null);
483
+ var BrowserTabItem = React4.forwardRef(
484
+ ({ className, icon, label, badge, isActive = false, pinned = false, isEditable = false, onEdit, onClose, onRename, ...props }, ref) => {
485
+ const [isHovered, setIsHovered] = React4.useState(false);
486
+ const [isEditing, setIsEditing] = React4.useState(false);
487
+ const [editValue, setEditValue] = React4.useState(label);
488
+ const inputRef = React4.useRef(null);
489
+ const ctx = React4.useContext(BrowserTabContext);
490
+ React4.useEffect(() => {
400
491
  if (isEditing && inputRef.current) {
401
492
  inputRef.current.focus();
402
493
  inputRef.current.select();
@@ -425,7 +516,7 @@ var BrowserTabItem = React3.forwardRef(
425
516
  const isDragged = ctx?.draggable && ctx.dragIndex === ctx.itemIndex;
426
517
  const isDropTarget = ctx?.draggable && ctx.dropIndex === ctx.itemIndex && ctx.dragIndex !== ctx.itemIndex;
427
518
  const showGrip = ctx?.draggable && isHovered;
428
- return /* @__PURE__ */ jsxs3(
519
+ const tab = /* @__PURE__ */ jsxs4(
429
520
  "div",
430
521
  {
431
522
  ref,
@@ -442,15 +533,15 @@ var BrowserTabItem = React3.forwardRef(
442
533
  ...dragProps,
443
534
  ...props,
444
535
  children: [
445
- /* @__PURE__ */ jsxs3(
536
+ /* @__PURE__ */ jsxs4(
446
537
  "div",
447
538
  {
448
539
  className: cn(
449
- "flex items-center gap-base px-xs py-2xs transition-[background-color,border-radius,box-shadow]",
540
+ "relative flex items-center gap-base px-xs py-2xs transition-[background-color,border-radius,box-shadow]",
450
541
  isHovered && !isActive ? "bg-browser-tab-item-hover-bg rounded-sm shadow-sm" : "bg-browser-tab-item-bg rounded-base"
451
542
  ),
452
543
  children: [
453
- icon && /* @__PURE__ */ jsx3("div", { className: "shrink-0", children: /* @__PURE__ */ jsx3(
544
+ icon && /* @__PURE__ */ jsx4("div", { className: "shrink-0", children: /* @__PURE__ */ jsx4(
454
545
  Icon3,
455
546
  {
456
547
  icon: showGrip ? faGripDotsVerticalSolid : icon,
@@ -460,7 +551,7 @@ var BrowserTabItem = React3.forwardRef(
460
551
  )
461
552
  }
462
553
  ) }),
463
- isEditing ? /* @__PURE__ */ jsx3(
554
+ isEditing ? /* @__PURE__ */ jsx4(
464
555
  "input",
465
556
  {
466
557
  ref: inputRef,
@@ -479,7 +570,7 @@ var BrowserTabItem = React3.forwardRef(
479
570
  ),
480
571
  style: { width: `${Math.max(editValue.length + 1, 2)}ch` }
481
572
  }
482
- ) : /* @__PURE__ */ jsx3(
573
+ ) : /* @__PURE__ */ jsx4(
483
574
  "span",
484
575
  {
485
576
  className: cn(
@@ -496,46 +587,86 @@ var BrowserTabItem = React3.forwardRef(
496
587
  children: label
497
588
  }
498
589
  ),
499
- badge && /* @__PURE__ */ jsx3(Badge, { variant: "light", type: "neutral", size: "sm", children: badge }),
500
- onClose && /* @__PURE__ */ jsx3(
501
- "button",
590
+ badge && /* @__PURE__ */ jsx4(Badge, { variant: "light", type: "neutral", size: "sm", children: badge }),
591
+ !pinned && (isEditable || onClose) && /* @__PURE__ */ jsxs4(
592
+ "div",
502
593
  {
503
- onClick: (e) => {
504
- e.stopPropagation();
505
- onClose(e);
506
- },
594
+ "aria-hidden": !isHovered,
507
595
  className: cn(
508
- "shrink-0 flex items-center justify-center cursor-pointer",
509
- isActive ? "text-browser-tab-item-active-icon" : "text-browser-tab-item-inactive-icon"
596
+ "absolute right-0 top-0 bottom-0 flex items-center justify-end gap-2xs pl-2xl pr-2xs",
597
+ "transition-opacity duration-150 bg-gradient-to-l from-[72%] to-transparent",
598
+ isActive ? "from-browser-tab-item-bg rounded-r-base" : "from-browser-tab-item-hover-bg rounded-r-sm",
599
+ isHovered ? "opacity-100" : "opacity-0 pointer-events-none"
510
600
  ),
511
- "aria-label": `Close ${label}`,
512
- children: /* @__PURE__ */ jsx3(Icon3, { icon: faXmarkOutline, size: "xs" })
601
+ children: [
602
+ isEditable && /* @__PURE__ */ jsx4(
603
+ "button",
604
+ {
605
+ onClick: (e) => {
606
+ e.stopPropagation();
607
+ onEdit?.(e);
608
+ },
609
+ tabIndex: isHovered ? 0 : -1,
610
+ className: cn(
611
+ "shrink-0 flex items-center justify-center cursor-pointer rounded-2xs p-2xs",
612
+ "hover:bg-black/5 transition-colors",
613
+ isActive ? "text-browser-tab-item-active-icon" : "text-browser-tab-item-inactive-icon"
614
+ ),
615
+ "aria-label": `Edit ${label}`,
616
+ children: /* @__PURE__ */ jsx4(Icon3, { icon: faPenOutline, size: "xs" })
617
+ }
618
+ ),
619
+ onClose && /* @__PURE__ */ jsx4(
620
+ "button",
621
+ {
622
+ onClick: (e) => {
623
+ e.stopPropagation();
624
+ onClose(e);
625
+ },
626
+ tabIndex: isHovered ? 0 : -1,
627
+ className: cn(
628
+ "shrink-0 flex items-center justify-center cursor-pointer rounded-2xs p-2xs",
629
+ "hover:bg-black/5 transition-colors",
630
+ isActive ? "text-browser-tab-item-active-icon" : "text-browser-tab-item-inactive-icon"
631
+ ),
632
+ "aria-label": `Close ${label}`,
633
+ children: /* @__PURE__ */ jsx4(Icon3, { icon: faXmarkOutline, size: "xs" })
634
+ }
635
+ )
636
+ ]
513
637
  }
514
638
  )
515
639
  ]
516
640
  }
517
641
  ),
518
- isActive && /* @__PURE__ */ jsxs3(Fragment, { children: [
519
- /* @__PURE__ */ jsx3("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 left-[-1px] w-px h-[8px] bg-browser-tab-item-bg" }),
520
- /* @__PURE__ */ jsx3("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 right-[-1px] w-px h-[8px] bg-browser-tab-item-bg" }),
521
- /* @__PURE__ */ jsxs3("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 left-[-8px] size-[8px]", children: [
522
- /* @__PURE__ */ jsx3("span", { className: "absolute bottom-0 left-0 right-0 h-px bg-browser-tab-item-bg" }),
523
- /* @__PURE__ */ jsx3("span", { className: "absolute inset-0 rounded-br-[8px] border-b border-r border-solid border-browser-tab-item-border" })
642
+ isActive && /* @__PURE__ */ jsxs4(Fragment, { children: [
643
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 left-[-1px] w-px h-[8px] bg-browser-tab-item-bg" }),
644
+ /* @__PURE__ */ jsx4("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 right-[-1px] w-px h-[8px] bg-browser-tab-item-bg" }),
645
+ /* @__PURE__ */ jsxs4("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 left-[-8px] size-[8px]", children: [
646
+ /* @__PURE__ */ jsx4("span", { className: "absolute bottom-0 left-0 right-0 h-px bg-browser-tab-item-bg" }),
647
+ /* @__PURE__ */ jsx4("span", { className: "absolute inset-0 rounded-br-[8px] border-b border-r border-solid border-browser-tab-item-border" })
524
648
  ] }),
525
- /* @__PURE__ */ jsxs3("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 right-[-8px] size-[8px]", children: [
526
- /* @__PURE__ */ jsx3("span", { className: "absolute bottom-0 left-0 right-0 h-px bg-browser-tab-item-bg" }),
527
- /* @__PURE__ */ jsx3("span", { className: "absolute inset-0 rounded-bl-[8px] border-b border-l border-solid border-browser-tab-item-border" })
649
+ /* @__PURE__ */ jsxs4("span", { "aria-hidden": true, className: "pointer-events-none absolute bottom-0 right-[-8px] size-[8px]", children: [
650
+ /* @__PURE__ */ jsx4("span", { className: "absolute bottom-0 left-0 right-0 h-px bg-browser-tab-item-bg" }),
651
+ /* @__PURE__ */ jsx4("span", { className: "absolute inset-0 rounded-bl-[8px] border-b border-l border-solid border-browser-tab-item-border" })
528
652
  ] })
529
653
  ] })
530
654
  ]
531
655
  }
532
656
  );
657
+ if (pinned) {
658
+ return /* @__PURE__ */ jsx4(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs4(Tooltip, { children: [
659
+ /* @__PURE__ */ jsx4(TooltipTrigger, { asChild: true, children: tab }),
660
+ /* @__PURE__ */ jsx4(TooltipContent, { side: "bottom", hasArrow: false, children: "Pinned tab" })
661
+ ] }) });
662
+ }
663
+ return tab;
533
664
  }
534
665
  );
535
666
  BrowserTabItem.displayName = "BrowserTabItem";
536
667
  function useOverflowDetection(containerRef, childCount) {
537
- const [visibleCount, setVisibleCount] = React3.useState(childCount);
538
- React3.useEffect(() => {
668
+ const [visibleCount, setVisibleCount] = React4.useState(childCount);
669
+ React4.useEffect(() => {
539
670
  const container = containerRef.current;
540
671
  if (!container) return;
541
672
  const measure = () => {
@@ -563,12 +694,12 @@ function useOverflowDetection(containerRef, childCount) {
563
694
  }, [containerRef, childCount]);
564
695
  return visibleCount;
565
696
  }
566
- var BrowserTab = React3.forwardRef(
697
+ var BrowserTab = React4.forwardRef(
567
698
  ({ className, children, onAddTab, draggable = false, onReorder, onOverflowSelect, ...props }, ref) => {
568
- const [dragIndex, setDragIndex] = React3.useState(null);
569
- const [dropIndex, setDropIndex] = React3.useState(null);
570
- const tabsContainerRef = React3.useRef(null);
571
- const childArray = React3.Children.toArray(children).filter(React3.isValidElement);
699
+ const [dragIndex, setDragIndex] = React4.useState(null);
700
+ const [dropIndex, setDropIndex] = React4.useState(null);
701
+ const tabsContainerRef = React4.useRef(null);
702
+ const childArray = React4.Children.toArray(children).filter(React4.isValidElement);
572
703
  const visibleCount = useOverflowDetection(tabsContainerRef, childArray.length);
573
704
  const hasOverflow = visibleCount < childArray.length;
574
705
  const ctxBase = {
@@ -602,7 +733,7 @@ var BrowserTab = React3.forwardRef(
602
733
  isActive: childProps.isActive
603
734
  };
604
735
  });
605
- return /* @__PURE__ */ jsxs3(
736
+ return /* @__PURE__ */ jsxs4(
606
737
  "div",
607
738
  {
608
739
  ref,
@@ -612,15 +743,15 @@ var BrowserTab = React3.forwardRef(
612
743
  ),
613
744
  ...props,
614
745
  children: [
615
- /* @__PURE__ */ jsxs3(
746
+ /* @__PURE__ */ jsxs4(
616
747
  "div",
617
748
  {
618
749
  ref: tabsContainerRef,
619
750
  className: "flex items-center flex-1 min-w-0 pl-base",
620
751
  style: { overflowX: "clip", overflowY: "visible" },
621
752
  children: [
622
- childArray.map((child, index) => /* @__PURE__ */ jsx3(BrowserTabContext.Provider, { value: { ...ctxBase, itemIndex: index }, children: child }, index)),
623
- onAddTab && !hasOverflow && /* @__PURE__ */ jsx3(
753
+ childArray.map((child, index) => /* @__PURE__ */ jsx4(BrowserTabContext.Provider, { value: { ...ctxBase, itemIndex: index }, children: child }, index)),
754
+ onAddTab && !hasOverflow && /* @__PURE__ */ jsx4(
624
755
  Button,
625
756
  {
626
757
  className: "ml-base",
@@ -636,8 +767,8 @@ var BrowserTab = React3.forwardRef(
636
767
  ]
637
768
  }
638
769
  ),
639
- hasOverflow && /* @__PURE__ */ jsxs3(DropdownMenuPrimitive.Root, { children: [
640
- /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx3(
770
+ hasOverflow && /* @__PURE__ */ jsxs4(DropdownMenuPrimitive.Root, { children: [
771
+ /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsx4(
641
772
  Button,
642
773
  {
643
774
  className: "mb-sm",
@@ -649,7 +780,7 @@ var BrowserTab = React3.forwardRef(
649
780
  "aria-label": "Show more tabs"
650
781
  }
651
782
  ) }),
652
- /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
783
+ /* @__PURE__ */ jsx4(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
653
784
  DropdownMenuPrimitive.Content,
654
785
  {
655
786
  sideOffset: 4,
@@ -661,7 +792,7 @@ var BrowserTab = React3.forwardRef(
661
792
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
662
793
  "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2"
663
794
  ),
664
- children: hiddenItems.map((item) => /* @__PURE__ */ jsxs3(
795
+ children: hiddenItems.map((item) => /* @__PURE__ */ jsxs4(
665
796
  DropdownMenuPrimitive.Item,
666
797
  {
667
798
  className: cn(
@@ -674,7 +805,7 @@ var BrowserTab = React3.forwardRef(
674
805
  }
675
806
  },
676
807
  children: [
677
- item.icon && /* @__PURE__ */ jsx3(
808
+ item.icon && /* @__PURE__ */ jsx4(
678
809
  Icon3,
679
810
  {
680
811
  icon: item.icon,
@@ -684,7 +815,7 @@ var BrowserTab = React3.forwardRef(
684
815
  )
685
816
  }
686
817
  ),
687
- /* @__PURE__ */ jsx3(
818
+ /* @__PURE__ */ jsx4(
688
819
  "span",
689
820
  {
690
821
  className: cn(
@@ -694,7 +825,7 @@ var BrowserTab = React3.forwardRef(
694
825
  children: item.label
695
826
  }
696
827
  ),
697
- item.badge && /* @__PURE__ */ jsx3(Badge, { variant: "light", type: "neutral", size: "sm", children: item.badge })
828
+ item.badge && /* @__PURE__ */ jsx4(Badge, { variant: "light", type: "neutral", size: "sm", children: item.badge })
698
829
  ]
699
830
  },
700
831
  item.index
@@ -702,7 +833,7 @@ var BrowserTab = React3.forwardRef(
702
833
  }
703
834
  ) })
704
835
  ] }),
705
- onAddTab && hasOverflow && /* @__PURE__ */ jsx3(
836
+ onAddTab && hasOverflow && /* @__PURE__ */ jsx4(
706
837
  Button,
707
838
  {
708
839
  className: "mb-sm",
@@ -723,7 +854,7 @@ var BrowserTab = React3.forwardRef(
723
854
  BrowserTab.displayName = "BrowserTab";
724
855
 
725
856
  // src/components/ui/bulk-action.tsx
726
- import * as React5 from "react";
857
+ import * as React6 from "react";
727
858
  import {
728
859
  Icon as Icon5,
729
860
  faXmarkOutline as faXmarkOutline2,
@@ -731,10 +862,10 @@ import {
731
862
  } from "@l3mpire/icons";
732
863
 
733
864
  // src/components/ui/dropdown-menu.tsx
734
- import * as React4 from "react";
865
+ import * as React5 from "react";
735
866
  import * as DropdownMenuPrimitive2 from "@radix-ui/react-dropdown-menu";
736
867
  import { Icon as Icon4 } from "@l3mpire/icons";
737
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
868
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
738
869
  var textSm = "text-sm font-regular leading-sm";
739
870
  var textXs = "text-xs font-regular leading-xs";
740
871
  var textXsMedium = "text-xs font-medium leading-xs";
@@ -747,13 +878,13 @@ var containerStyle = [
747
878
  "p-xs",
748
879
  "shadow-lg"
749
880
  ];
750
- var DropdownMenu = React4.forwardRef(
751
- ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx4("div", { ref, className: cn(containerStyle, className), ...props, children })
881
+ var DropdownMenu = React5.forwardRef(
882
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx5("div", { ref, className: cn(containerStyle, className), ...props, children })
752
883
  );
753
884
  DropdownMenu.displayName = "DropdownMenu";
754
885
  var DropdownMenuRoot = DropdownMenuPrimitive2.Root;
755
886
  var DropdownMenuTrigger = DropdownMenuPrimitive2.Trigger;
756
- var DropdownMenuContent = React4.forwardRef(({ className, sideOffset = 4, children, ...props }, ref) => /* @__PURE__ */ jsx4(DropdownMenuPrimitive2.Portal, { children: /* @__PURE__ */ jsx4(
887
+ var DropdownMenuContent = React5.forwardRef(({ className, sideOffset = 4, children, ...props }, ref) => /* @__PURE__ */ jsx5(DropdownMenuPrimitive2.Portal, { children: /* @__PURE__ */ jsx5(
757
888
  DropdownMenuPrimitive2.Content,
758
889
  {
759
890
  ref,
@@ -772,12 +903,12 @@ var DropdownMenuContent = React4.forwardRef(({ className, sideOffset = 4, childr
772
903
  }
773
904
  ) }));
774
905
  DropdownMenuContent.displayName = "DropdownMenuContent";
775
- var DropdownMenuList = React4.forwardRef(
776
- ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx4("div", { ref, className: cn("flex flex-col", className), role: "listbox", ...props, children })
906
+ var DropdownMenuList = React5.forwardRef(
907
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx5("div", { ref, className: cn("flex flex-col", className), role: "listbox", ...props, children })
777
908
  );
778
909
  DropdownMenuList.displayName = "DropdownMenuList";
779
910
  var itemStyle = "flex items-center gap-base p-base rounded-base cursor-pointer hover:bg-dropdown-item-hover";
780
- var DropdownMenuItem = React4.forwardRef(
911
+ var DropdownMenuItem = React5.forwardRef(
781
912
  ({
782
913
  className,
783
914
  icon,
@@ -792,7 +923,7 @@ var DropdownMenuItem = React4.forwardRef(
792
923
  onClick,
793
924
  ...props
794
925
  }, ref) => {
795
- const handleClick = React4.useCallback(
926
+ const handleClick = React5.useCallback(
796
927
  (e) => {
797
928
  const target = e.target;
798
929
  if (!target.closest("button[role='checkbox']")) {
@@ -805,7 +936,7 @@ var DropdownMenuItem = React4.forwardRef(
805
936
  },
806
937
  [onClick]
807
938
  );
808
- return /* @__PURE__ */ jsxs4(
939
+ return /* @__PURE__ */ jsxs5(
809
940
  "div",
810
941
  {
811
942
  ref,
@@ -822,7 +953,7 @@ var DropdownMenuItem = React4.forwardRef(
822
953
  children,
823
954
  avatar,
824
955
  flag,
825
- icon && /* @__PURE__ */ jsx4(
956
+ icon && /* @__PURE__ */ jsx5(
826
957
  Icon4,
827
958
  {
828
959
  icon,
@@ -830,9 +961,9 @@ var DropdownMenuItem = React4.forwardRef(
830
961
  className: "shrink-0 text-dropdown-item-icon"
831
962
  }
832
963
  ),
833
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 items-center gap-sm min-w-0", children: [
834
- /* @__PURE__ */ jsx4("span", { className: cn("truncate shrink-0", textSm, "text-dropdown-item-text"), children: label }),
835
- description && /* @__PURE__ */ jsx4("span", { className: cn("truncate", textXs, "text-dropdown-item-secondary"), children: description })
964
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-1 items-center gap-sm min-w-0", children: [
965
+ /* @__PURE__ */ jsx5("span", { className: cn("truncate shrink-0", textSm, "text-dropdown-item-text"), children: label }),
966
+ description && /* @__PURE__ */ jsx5("span", { className: cn("truncate", textXs, "text-dropdown-item-secondary"), children: description })
836
967
  ] }),
837
968
  badge,
838
969
  action
@@ -842,7 +973,7 @@ var DropdownMenuItem = React4.forwardRef(
842
973
  }
843
974
  );
844
975
  DropdownMenuItem.displayName = "DropdownMenuItem";
845
- var DropdownMenuRadixItem = React4.forwardRef(
976
+ var DropdownMenuRadixItem = React5.forwardRef(
846
977
  ({
847
978
  className,
848
979
  icon,
@@ -854,7 +985,7 @@ var DropdownMenuRadixItem = React4.forwardRef(
854
985
  action,
855
986
  children,
856
987
  ...props
857
- }, ref) => /* @__PURE__ */ jsxs4(
988
+ }, ref) => /* @__PURE__ */ jsxs5(
858
989
  DropdownMenuPrimitive2.Item,
859
990
  {
860
991
  ref,
@@ -868,7 +999,7 @@ var DropdownMenuRadixItem = React4.forwardRef(
868
999
  children,
869
1000
  avatar,
870
1001
  flag,
871
- icon && /* @__PURE__ */ jsx4(
1002
+ icon && /* @__PURE__ */ jsx5(
872
1003
  Icon4,
873
1004
  {
874
1005
  icon,
@@ -876,9 +1007,9 @@ var DropdownMenuRadixItem = React4.forwardRef(
876
1007
  className: "shrink-0 text-dropdown-item-icon"
877
1008
  }
878
1009
  ),
879
- /* @__PURE__ */ jsxs4("div", { className: "flex flex-1 items-center gap-sm min-w-0", children: [
880
- /* @__PURE__ */ jsx4("span", { className: cn("truncate shrink-0", textSm, "text-dropdown-item-text"), children: label }),
881
- description && /* @__PURE__ */ jsx4("span", { className: cn("truncate", textXs, "text-dropdown-item-secondary"), children: description })
1010
+ /* @__PURE__ */ jsxs5("div", { className: "flex flex-1 items-center gap-sm min-w-0", children: [
1011
+ /* @__PURE__ */ jsx5("span", { className: cn("truncate shrink-0", textSm, "text-dropdown-item-text"), children: label }),
1012
+ description && /* @__PURE__ */ jsx5("span", { className: cn("truncate", textXs, "text-dropdown-item-secondary"), children: description })
882
1013
  ] }),
883
1014
  badge,
884
1015
  action
@@ -887,7 +1018,7 @@ var DropdownMenuRadixItem = React4.forwardRef(
887
1018
  )
888
1019
  );
889
1020
  DropdownMenuRadixItem.displayName = "DropdownMenuRadixItem";
890
- var DropdownMenuHeading = React4.forwardRef(({ className, action, children, ...props }, ref) => /* @__PURE__ */ jsxs4(
1021
+ var DropdownMenuHeading = React5.forwardRef(({ className, action, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
891
1022
  "div",
892
1023
  {
893
1024
  ref,
@@ -897,7 +1028,7 @@ var DropdownMenuHeading = React4.forwardRef(({ className, action, children, ...p
897
1028
  ),
898
1029
  ...props,
899
1030
  children: [
900
- /* @__PURE__ */ jsx4("span", { className: cn("flex-1 truncate uppercase", textXsMedium, "text-dropdown-heading-text"), children }),
1031
+ /* @__PURE__ */ jsx5("span", { className: cn("flex-1 truncate uppercase", textXsMedium, "text-dropdown-heading-text"), children }),
901
1032
  action
902
1033
  ]
903
1034
  }
@@ -912,7 +1043,7 @@ var clearStyle = [
912
1043
  "shadow-sm",
913
1044
  "cursor-pointer"
914
1045
  ];
915
- var DropdownMenuClear = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx4(
1046
+ var DropdownMenuClear = React5.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx5(
916
1047
  "button",
917
1048
  {
918
1049
  ref,
@@ -925,10 +1056,10 @@ var DropdownMenuClear = React4.forwardRef(({ className, children, ...props }, re
925
1056
  DropdownMenuClear.displayName = "DropdownMenuClear";
926
1057
 
927
1058
  // src/components/ui/bulk-action.tsx
928
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1059
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
929
1060
  var GAP_PX = 8;
930
1061
  var MORE_BTN_FALLBACK = 36;
931
- var BulkAction = React5.forwardRef(
1062
+ var BulkAction = React6.forwardRef(
932
1063
  ({
933
1064
  count,
934
1065
  onClear,
@@ -939,11 +1070,11 @@ var BulkAction = React5.forwardRef(
939
1070
  className,
940
1071
  ...props
941
1072
  }, ref) => {
942
- const slotRef = React5.useRef(null);
943
- const measureRef = React5.useRef(null);
944
- const moreBtnMeasureRef = React5.useRef(null);
945
- const [visibleCount, setVisibleCount] = React5.useState(actions.length);
946
- React5.useLayoutEffect(() => {
1073
+ const slotRef = React6.useRef(null);
1074
+ const measureRef = React6.useRef(null);
1075
+ const moreBtnMeasureRef = React6.useRef(null);
1076
+ const [visibleCount, setVisibleCount] = React6.useState(actions.length);
1077
+ React6.useLayoutEffect(() => {
947
1078
  const slot = slotRef.current;
948
1079
  const measure = measureRef.current;
949
1080
  if (!slot || !measure) return;
@@ -983,7 +1114,7 @@ var BulkAction = React5.forwardRef(
983
1114
  }, [actions]);
984
1115
  const visibleItems = actions.slice(0, visibleCount);
985
1116
  const overflowItems = actions.slice(visibleCount);
986
- return /* @__PURE__ */ jsxs5(
1117
+ return /* @__PURE__ */ jsxs6(
987
1118
  "div",
988
1119
  {
989
1120
  ref,
@@ -999,20 +1130,20 @@ var BulkAction = React5.forwardRef(
999
1130
  ),
1000
1131
  ...props,
1001
1132
  children: [
1002
- /* @__PURE__ */ jsxs5("span", { className: "text-sm font-regular leading-sm text-bulk-action-count whitespace-nowrap shrink-0", children: [
1133
+ /* @__PURE__ */ jsxs6("span", { className: "text-sm font-regular leading-sm text-bulk-action-count whitespace-nowrap shrink-0", children: [
1003
1134
  count,
1004
1135
  " ",
1005
1136
  countLabel
1006
1137
  ] }),
1007
- /* @__PURE__ */ jsxs5(
1138
+ /* @__PURE__ */ jsxs6(
1008
1139
  "div",
1009
1140
  {
1010
1141
  ref: slotRef,
1011
1142
  className: "relative flex flex-1 items-center gap-base min-w-0 overflow-hidden",
1012
1143
  children: [
1013
- visibleItems.map((item) => /* @__PURE__ */ jsx5(ActionButton, { item }, item.id)),
1014
- overflowItems.length > 0 && /* @__PURE__ */ jsxs5(DropdownMenuRoot, { children: [
1015
- /* @__PURE__ */ jsx5(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(
1144
+ visibleItems.map((item) => /* @__PURE__ */ jsx6(ActionButton, { item }, item.id)),
1145
+ overflowItems.length > 0 && /* @__PURE__ */ jsxs6(DropdownMenuRoot, { children: [
1146
+ /* @__PURE__ */ jsx6(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx6(
1016
1147
  Button,
1017
1148
  {
1018
1149
  type: "button",
@@ -1024,7 +1155,7 @@ var BulkAction = React5.forwardRef(
1024
1155
  "aria-label": "More actions"
1025
1156
  }
1026
1157
  ) }),
1027
- /* @__PURE__ */ jsx5(DropdownMenuContent, { align: "end", side: "top", sideOffset: 8, children: overflowItems.map((item) => /* @__PURE__ */ jsx5(
1158
+ /* @__PURE__ */ jsx6(DropdownMenuContent, { align: "end", side: "top", sideOffset: 8, children: overflowItems.map((item) => /* @__PURE__ */ jsx6(
1028
1159
  DropdownMenuItem,
1029
1160
  {
1030
1161
  icon: item.icon,
@@ -1034,29 +1165,29 @@ var BulkAction = React5.forwardRef(
1034
1165
  item.id
1035
1166
  )) })
1036
1167
  ] }),
1037
- /* @__PURE__ */ jsx5(
1168
+ /* @__PURE__ */ jsx6(
1038
1169
  "div",
1039
1170
  {
1040
1171
  ref: measureRef,
1041
1172
  "aria-hidden": true,
1042
1173
  className: "pointer-events-none absolute inset-0 flex items-center gap-base opacity-0 invisible",
1043
- children: actions.map((item) => /* @__PURE__ */ jsx5(ActionButton, { item, tabIndex: -1 }, `measure-${item.id}`))
1174
+ children: actions.map((item) => /* @__PURE__ */ jsx6(ActionButton, { item, tabIndex: -1 }, `measure-${item.id}`))
1044
1175
  }
1045
1176
  ),
1046
- /* @__PURE__ */ jsx5(
1177
+ /* @__PURE__ */ jsx6(
1047
1178
  "button",
1048
1179
  {
1049
1180
  ref: moreBtnMeasureRef,
1050
1181
  "aria-hidden": true,
1051
1182
  tabIndex: -1,
1052
1183
  className: "pointer-events-none absolute opacity-0 invisible h-8 w-8 min-w-8",
1053
- children: /* @__PURE__ */ jsx5(Icon5, { icon: faEllipsisOutline, size: "sm" })
1184
+ children: /* @__PURE__ */ jsx6(Icon5, { icon: faEllipsisOutline, size: "sm" })
1054
1185
  }
1055
1186
  )
1056
1187
  ]
1057
1188
  }
1058
1189
  ),
1059
- /* @__PURE__ */ jsx5(
1190
+ /* @__PURE__ */ jsx6(
1060
1191
  Button,
1061
1192
  {
1062
1193
  type: "button",
@@ -1076,7 +1207,7 @@ var BulkAction = React5.forwardRef(
1076
1207
  }
1077
1208
  );
1078
1209
  BulkAction.displayName = "BulkAction";
1079
- var ActionButton = ({ item, tabIndex }) => /* @__PURE__ */ jsx5(
1210
+ var ActionButton = ({ item, tabIndex }) => /* @__PURE__ */ jsx6(
1080
1211
  Button,
1081
1212
  {
1082
1213
  type: "button",
@@ -1092,67 +1223,6 @@ var ActionButton = ({ item, tabIndex }) => /* @__PURE__ */ jsx5(
1092
1223
  }
1093
1224
  );
1094
1225
 
1095
- // src/components/ui/tooltip.tsx
1096
- import * as React6 from "react";
1097
- import * as TooltipPrimitive from "@radix-ui/react-tooltip";
1098
- import { cva as cva3 } from "class-variance-authority";
1099
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1100
- var tooltipContentVariants = cva3(
1101
- [
1102
- "inline-flex items-center z-50",
1103
- "gap-xs",
1104
- "px-base py-sm",
1105
- "rounded-lg",
1106
- "shadow-lg",
1107
- "text-sm",
1108
- "font-regular",
1109
- "leading-sm",
1110
- "data-[state=delayed-open]:animate-[tooltip-in_150ms_ease-out]",
1111
- "data-[state=instant-open]:animate-[tooltip-in_0ms]",
1112
- "data-[state=closed]:animate-[tooltip-out_100ms_ease-in]"
1113
- ],
1114
- {
1115
- variants: {
1116
- type: {
1117
- default: [
1118
- "bg-tooltip-default-bg",
1119
- "text-tooltip-default-text"
1120
- ],
1121
- invert: [
1122
- "bg-tooltip-invert-bg",
1123
- "text-tooltip-invert-text",
1124
- "border border-tooltip-invert-border"
1125
- ]
1126
- }
1127
- },
1128
- defaultVariants: {
1129
- type: "default"
1130
- }
1131
- }
1132
- );
1133
- var TooltipProvider = TooltipPrimitive.Provider;
1134
- var Tooltip = TooltipPrimitive.Root;
1135
- var TooltipTrigger = TooltipPrimitive.Trigger;
1136
- var TooltipContent = React6.forwardRef(({ className, type, hasArrow = true, sideOffset = 4, children, ...props }, ref) => /* @__PURE__ */ jsx6(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs6(
1137
- TooltipPrimitive.Content,
1138
- {
1139
- ref,
1140
- sideOffset,
1141
- className: cn(tooltipContentVariants({ type, className })),
1142
- ...props,
1143
- children: [
1144
- children,
1145
- hasArrow && /* @__PURE__ */ jsx6(
1146
- TooltipPrimitive.Arrow,
1147
- {
1148
- className: type === "default" ? "fill-tooltip-default-bg" : "fill-tooltip-invert-bg"
1149
- }
1150
- )
1151
- ]
1152
- }
1153
- ) }));
1154
- TooltipContent.displayName = "TooltipContent";
1155
-
1156
1226
  // src/components/ui/truncated-text.tsx
1157
1227
  import * as React7 from "react";
1158
1228
  import * as TooltipPrimitive2 from "@radix-ui/react-tooltip";