@invana/ui 0.0.23 → 0.0.24

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.js CHANGED
@@ -3075,27 +3075,214 @@ function ChatSessionMessage({
3075
3075
  footer
3076
3076
  ] });
3077
3077
  }
3078
+ var NONE = Object.freeze([]);
3079
+ function same(a, b) {
3080
+ if (a.length !== b.length) return false;
3081
+ for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
3082
+ return true;
3083
+ }
3084
+ function useOverflowItems({
3085
+ count,
3086
+ enabled = true,
3087
+ pinnedIndex,
3088
+ reserve = 32
3089
+ }) {
3090
+ const containerEl = React23.useRef(null);
3091
+ const itemEls = React23.useRef([]);
3092
+ const widths = React23.useRef([]);
3093
+ const itemRefs = React23.useRef([]);
3094
+ const [hidden, setHidden] = React23.useState(NONE);
3095
+ const fit = React23.useCallback(() => {
3096
+ const el = containerEl.current;
3097
+ if (!el || !enabled) {
3098
+ setHidden((prev) => prev === NONE ? prev : NONE);
3099
+ return;
3100
+ }
3101
+ const gap = Number.parseFloat(getComputedStyle(el).columnGap) || 0;
3102
+ for (let i = 0; i < count; i++) {
3103
+ const item = itemEls.current[i];
3104
+ if (item && item.offsetParent !== null) widths.current[i] = item.offsetWidth + gap;
3105
+ }
3106
+ const budget = el.clientWidth;
3107
+ if (budget <= 0) return;
3108
+ let total = 0;
3109
+ for (let i = 0; i < count; i++) total += widths.current[i] ?? 0;
3110
+ if (total <= budget + gap) {
3111
+ setHidden((prev) => prev === NONE ? prev : NONE);
3112
+ return;
3113
+ }
3114
+ const next = [];
3115
+ let used = pinnedIndex != null ? widths.current[pinnedIndex] ?? 0 : 0;
3116
+ for (let i = 0; i < count; i++) {
3117
+ if (i === pinnedIndex) continue;
3118
+ const w = widths.current[i] ?? 0;
3119
+ if (used + w <= budget - reserve) used += w;
3120
+ else next.push(i);
3121
+ }
3122
+ setHidden((prev) => same(prev, next) ? prev : next);
3123
+ }, [count, enabled, pinnedIndex, reserve]);
3124
+ React23.useLayoutEffect(() => {
3125
+ widths.current = [];
3126
+ itemEls.current.length = count;
3127
+ setHidden((prev) => prev === NONE ? prev : NONE);
3128
+ }, [count]);
3129
+ React23.useLayoutEffect(() => {
3130
+ fit();
3131
+ if (!enabled || typeof ResizeObserver === "undefined") return;
3132
+ const observer = new ResizeObserver(() => fit());
3133
+ if (containerEl.current) observer.observe(containerEl.current);
3134
+ for (const item of itemEls.current) if (item) observer.observe(item);
3135
+ return () => observer.disconnect();
3136
+ }, [fit, enabled, hidden]);
3137
+ const containerRef = React23.useCallback((el) => {
3138
+ containerEl.current = el;
3139
+ }, []);
3140
+ const itemRef = React23.useCallback((index) => {
3141
+ let fn = itemRefs.current[index];
3142
+ if (!fn) {
3143
+ fn = (el) => {
3144
+ itemEls.current[index] = el;
3145
+ };
3146
+ itemRefs.current[index] = fn;
3147
+ }
3148
+ return fn;
3149
+ }, []);
3150
+ const isHidden = React23.useCallback(
3151
+ (index) => hidden.includes(index),
3152
+ [hidden]
3153
+ );
3154
+ return { containerRef, itemRef, hiddenIndices: hidden, isHidden };
3155
+ }
3156
+ var VARIANT = {
3157
+ /** The capsule: a filled, ringed chip. Toolbars, rails, header actions. */
3158
+ nav: {
3159
+ item: "rounded-control ring-1 ring-transparent",
3160
+ hover: "hover:bg-primary/10 hover:text-primary hover:ring-primary/25",
3161
+ open: "data-[state=open]:bg-primary/15 data-[state=open]:text-primary data-[state=open]:ring-primary/25",
3162
+ active: "bg-primary/15 text-primary ring-primary/25",
3163
+ strip: ""
3164
+ },
3165
+ /** The panel tab: accented fill with a rule under it, merging into the body. */
3166
+ underline: {
3167
+ item: "h-full rounded-none px-3 py-2",
3168
+ hover: "hover:text-foreground",
3169
+ open: "data-[state=open]:text-foreground",
3170
+ active: "bg-primary/10 text-primary border-b-2 border-primary mb-[-1px]",
3171
+ strip: "items-stretch"
3172
+ },
3173
+ /**
3174
+ * The workbook tab: boxed on top / left / right with an *open bottom*, so it
3175
+ * punches through the strip's own rule — the classic folder-tab notch.
3176
+ */
3177
+ folder: {
3178
+ item: "h-full rounded-none px-3 py-2 gap-1.5",
3179
+ hover: "hover:text-foreground",
3180
+ open: "data-[state=open]:text-foreground",
3181
+ active: "mb-[-1px] rounded-t-md border border-b-0 border-primary text-primary",
3182
+ strip: "items-stretch"
3183
+ }
3184
+ };
3185
+ var keyOf = (item) => item.key ?? item.name;
3078
3186
  var NavItems = ({
3079
3187
  items,
3080
3188
  orientation = "horizontal",
3081
3189
  tooltipSide = orientation === "vertical" ? "right" : "bottom",
3082
- iconClassName = orientation === "vertical" ? "w-5 h-5" : "w-4 h-4 flex-shrink-0"
3190
+ iconClassName = orientation === "vertical" ? "w-5 h-5" : "w-4 h-4 flex-shrink-0",
3191
+ variant = "nav",
3192
+ activeKey,
3193
+ onActiveChange,
3194
+ selectionMode = "none",
3195
+ panelId,
3196
+ overflow = false,
3197
+ overflowLabel = "More",
3198
+ className
3083
3199
  }) => {
3084
3200
  const isVertical = orientation === "vertical";
3085
- const [activeItem, setActiveItem] = React23__default.useState(null);
3086
- return /* @__PURE__ */ jsx(Fragment, { children: items.map((item) => {
3087
- const isActive = activeItem === item.name;
3088
- const padding = item.label ? "px-3 py-1.5" : "px-2 py-2";
3201
+ const isTabs = selectionMode === "tabs";
3202
+ const V = VARIANT[variant];
3203
+ const [internalActive, setInternalActive] = React23__default.useState(
3204
+ null
3205
+ );
3206
+ const isControlled = activeKey !== void 0;
3207
+ const currentKey = isControlled ? activeKey : internalActive;
3208
+ const activeIndex = items.findIndex((item) => keyOf(item) === currentKey);
3209
+ const nodes = React23__default.useRef({});
3210
+ const pendingFocus = React23__default.useRef(null);
3211
+ React23__default.useEffect(() => {
3212
+ const key = pendingFocus.current;
3213
+ if (!key) return;
3214
+ const node = nodes.current[key];
3215
+ if (!node) return;
3216
+ pendingFocus.current = null;
3217
+ node.focus();
3218
+ });
3219
+ const { containerRef, itemRef, hiddenIndices, isHidden } = useOverflowItems({
3220
+ count: items.length,
3221
+ enabled: overflow && !isVertical,
3222
+ pinnedIndex: activeIndex >= 0 ? activeIndex : void 0
3223
+ });
3224
+ const select = React23__default.useCallback(
3225
+ (item) => {
3226
+ if (item.disabled) return;
3227
+ const key = keyOf(item);
3228
+ item.onClick?.();
3229
+ if (!isControlled) {
3230
+ setInternalActive((prev) => isTabs ? key : prev === key ? null : key);
3231
+ }
3232
+ onActiveChange?.(key);
3233
+ },
3234
+ [isControlled, isTabs, onActiveChange]
3235
+ );
3236
+ const step = (from, delta) => {
3237
+ if (items.length === 0) return -1;
3238
+ let i = from < 0 ? delta > 0 ? -1 : 0 : from;
3239
+ for (let n = 0; n < items.length; n++) {
3240
+ i = (i + delta + items.length) % items.length;
3241
+ if (!items[i]?.disabled) return i;
3242
+ }
3243
+ return -1;
3244
+ };
3245
+ const edge = (delta) => {
3246
+ const start = delta > 0 ? -1 : items.length;
3247
+ return step(start, delta);
3248
+ };
3249
+ const handleKeyDown = (event) => {
3250
+ if (!isTabs) return;
3251
+ const next = isVertical ? "ArrowDown" : "ArrowRight";
3252
+ const prev = isVertical ? "ArrowUp" : "ArrowLeft";
3253
+ let target = -1;
3254
+ if (event.key === next) target = step(activeIndex, 1);
3255
+ else if (event.key === prev) target = step(activeIndex, -1);
3256
+ else if (event.key === "Home") target = edge(1);
3257
+ else if (event.key === "End") target = edge(-1);
3258
+ else return;
3259
+ const item = items[target];
3260
+ if (!item) return;
3261
+ event.preventDefault();
3262
+ pendingFocus.current = keyOf(item);
3263
+ select(item);
3264
+ };
3265
+ const renderItem = (item, index) => {
3266
+ const key = keyOf(item);
3267
+ const isActive = key === currentKey;
3089
3268
  const hasMenu = !item.href && Boolean(item.menuItems?.length);
3090
- const isInteractive = Boolean(item.href || item.onClick || hasMenu);
3091
- const itemClass = `relative inline-flex border-0 items-center justify-center gap-2
3092
- whitespace-nowrap rounded-control transition-colors
3093
- ring-1 ring-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring
3094
- ${padding}
3095
- ${isInteractive ? "cursor-pointer hover:bg-primary/10 hover:text-primary hover:ring-primary/25" : ""}
3096
- ${hasMenu ? "data-[state=open]:bg-primary/15 data-[state=open]:text-primary data-[state=open]:ring-primary/25" : ""}
3097
- ${isActive ? `bg-primary/15 text-primary ring-primary/25 ${item.activeClass || ""}` : ""}
3098
- ${item.className || ""}`;
3269
+ const asCaret = hasMenu && item.menuTrigger === "caret";
3270
+ const isInteractive = Boolean(
3271
+ item.href || item.onClick || hasMenu || isTabs
3272
+ );
3273
+ const padding = variant === "nav" ? item.label ? "px-3 py-1.5" : "px-2 py-2" : "";
3274
+ const itemClass = cn(
3275
+ `relative inline-flex border-0 items-center justify-center gap-2
3276
+ whitespace-nowrap transition-colors
3277
+ ring-1 ring-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring`,
3278
+ V.item,
3279
+ padding,
3280
+ isInteractive && !item.disabled && `cursor-pointer ${V.hover}`,
3281
+ hasMenu && !asCaret && V.open,
3282
+ item.disabled && "pointer-events-none opacity-50",
3283
+ isActive && cn(V.active, item.activeClass),
3284
+ item.className
3285
+ );
3099
3286
  const icon = item.icon && /* @__PURE__ */ jsx(
3100
3287
  item.icon,
3101
3288
  {
@@ -3103,41 +3290,79 @@ var NavItems = ({
3103
3290
  className: item.iconClassName || iconClassName
3104
3291
  }
3105
3292
  );
3106
- const label = item.label && /* @__PURE__ */ jsx("span", { children: item.label });
3293
+ const label = item.label && /* @__PURE__ */ jsx("span", { className: item.labelClassName, children: item.label });
3107
3294
  const badge = item.badge != null && /* @__PURE__ */ jsx(
3108
3295
  "span",
3109
3296
  {
3110
- className: "pointer-events-none absolute -right-0.5 -top-0.5 inline-flex h-3.5\n min-w-3.5 items-center justify-center rounded-full bg-primary px-1\n text-[9px] font-semibold leading-none text-primary-foreground",
3297
+ className: "pointer-events-none absolute -right-0.5 -top-0.5 inline-flex h-3.5\n min-w-3.5 items-center justify-center rounded-full bg-primary px-1\n text-[9px] font-semibold leading-none text-primary-foreground",
3111
3298
  children: item.badge
3112
3299
  }
3113
3300
  );
3301
+ const tabProps = isTabs ? {
3302
+ role: "tab",
3303
+ "aria-selected": isActive,
3304
+ "aria-controls": panelId?.(key),
3305
+ tabIndex: isActive || activeIndex < 0 && index === 0 ? 0 : -1
3306
+ } : {};
3307
+ const setNode = (el) => {
3308
+ nodes.current[key] = el;
3309
+ itemRef(index)(el);
3310
+ };
3311
+ const caret = asCaret && /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3312
+ "span",
3313
+ {
3314
+ role: "button",
3315
+ tabIndex: -1,
3316
+ "aria-label": `${item.name} menu`,
3317
+ onClick: (e) => e.stopPropagation(),
3318
+ className: "ml-0.5 grid size-4 shrink-0 cursor-pointer place-items-center\n rounded-control text-muted-foreground hover:bg-accent hover:text-foreground",
3319
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-3" })
3320
+ }
3321
+ ) });
3114
3322
  const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
3115
3323
  icon,
3116
3324
  label,
3325
+ caret,
3117
3326
  badge
3118
3327
  ] });
3119
- const control = item.href ? /* @__PURE__ */ jsx(
3328
+ const control = asCaret ? /* @__PURE__ */ jsx(
3329
+ "div",
3330
+ {
3331
+ ref: setNode,
3332
+ ...tabProps,
3333
+ style: item.style,
3334
+ onClick: () => select(item),
3335
+ className: itemClass,
3336
+ children: inner
3337
+ }
3338
+ ) : item.href ? /* @__PURE__ */ jsx(
3120
3339
  "a",
3121
3340
  {
3341
+ ref: setNode,
3122
3342
  href: item.href,
3123
- onClick: () => setActiveItem(item.name),
3343
+ style: item.style,
3344
+ onClick: () => select(item),
3124
3345
  className: itemClass,
3125
3346
  children: inner
3126
3347
  }
3127
- ) : item.onClick || hasMenu ? /* @__PURE__ */ jsx(
3348
+ ) : item.onClick || hasMenu || isTabs ? /* @__PURE__ */ jsx(
3128
3349
  "button",
3129
3350
  {
3351
+ ref: setNode,
3130
3352
  type: "button",
3353
+ disabled: item.disabled,
3354
+ ...tabProps,
3355
+ style: item.style,
3131
3356
  onClick: () => {
3132
- item.onClick?.();
3133
- if (!hasMenu) setActiveItem(isActive ? null : item.name);
3357
+ if (hasMenu) item.onClick?.();
3358
+ else select(item);
3134
3359
  },
3135
3360
  className: itemClass,
3136
3361
  children: inner
3137
3362
  }
3138
- ) : /* @__PURE__ */ jsx("div", { className: itemClass, children: inner });
3363
+ ) : /* @__PURE__ */ jsx("div", { ref: setNode, style: item.style, className: itemClass, children: inner });
3139
3364
  const withTooltip = /* @__PURE__ */ jsxs(Tooltip, { children: [
3140
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: hasMenu ? /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: control }) : control }),
3365
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: hasMenu && !asCaret ? /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: control }) : control }),
3141
3366
  /* @__PURE__ */ jsx(TooltipContent, { side: item.tooltipSide || tooltipSide, children: item.tooltip || item.name })
3142
3367
  ] });
3143
3368
  return /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
@@ -3148,28 +3373,7 @@ var NavItems = ({
3148
3373
  {
3149
3374
  side: isVertical ? "right" : "bottom",
3150
3375
  align: isVertical ? "start" : "end",
3151
- children: item.menuItems?.map((menuItem) => {
3152
- const MenuIcon = menuItem.icon;
3153
- const gutter = item.menuItems?.some((m) => m.icon);
3154
- return /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
3155
- menuItem.separatorBefore && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3156
- /* @__PURE__ */ jsxs(
3157
- DropdownMenuItem,
3158
- {
3159
- disabled: menuItem.disabled,
3160
- onSelect: () => menuItem.onSelect?.(),
3161
- className: cn(
3162
- menuItem.destructive && "text-destructive focus:bg-destructive/15 focus:text-destructive hover:bg-destructive/10 hover:text-destructive"
3163
- ),
3164
- children: [
3165
- MenuIcon ? /* @__PURE__ */ jsx(MenuIcon, {}) : gutter ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-4 shrink-0" }) : null,
3166
- /* @__PURE__ */ jsx("span", { className: "truncate", children: menuItem.label }),
3167
- menuItem.shortcut && /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: menuItem.shortcut })
3168
- ]
3169
- }
3170
- )
3171
- ] }, menuItem.id);
3172
- })
3376
+ children: renderMenuRows(item.menuItems)
3173
3377
  }
3174
3378
  )
3175
3379
  ] }) : withTooltip,
@@ -3181,22 +3385,132 @@ var NavItems = ({
3181
3385
  }
3182
3386
  )
3183
3387
  ] }, item.key || item.name);
3184
- }) });
3388
+ };
3389
+ const rendered = items.map(
3390
+ (item, index) => isHidden(index) ? null : renderItem(item, index)
3391
+ );
3392
+ const overflowTrigger = hiddenIndices.length > 0 && /* @__PURE__ */ jsxs(DropdownMenu, { children: [
3393
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
3394
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
3395
+ "button",
3396
+ {
3397
+ type: "button",
3398
+ "aria-label": overflowLabel,
3399
+ className: cn(
3400
+ `relative inline-flex shrink-0 items-center justify-center border-0
3401
+ transition-colors ring-1 ring-transparent focus-visible:outline-none
3402
+ focus-visible:ring-2 focus-visible:ring-ring cursor-pointer`,
3403
+ V.item,
3404
+ variant === "nav" && "px-2 py-2",
3405
+ V.hover,
3406
+ V.open
3407
+ ),
3408
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { className: iconClassName })
3409
+ }
3410
+ ) }) }),
3411
+ /* @__PURE__ */ jsx(TooltipContent, { side: tooltipSide, children: overflowLabel })
3412
+ ] }),
3413
+ /* @__PURE__ */ jsx(DropdownMenuContent, { align: "end", children: hiddenIndices.map((index) => {
3414
+ const item = items[index];
3415
+ if (!item) return null;
3416
+ const Icon = item.icon;
3417
+ return /* @__PURE__ */ jsxs(
3418
+ DropdownMenuItem,
3419
+ {
3420
+ disabled: item.disabled,
3421
+ onSelect: () => select(item),
3422
+ children: [
3423
+ Icon ? /* @__PURE__ */ jsx(Icon, {}) : /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-4 shrink-0" }),
3424
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label ?? item.name })
3425
+ ]
3426
+ },
3427
+ keyOf(item)
3428
+ );
3429
+ }) })
3430
+ ] });
3431
+ if (!isTabs && !overflow) {
3432
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: rendered });
3433
+ }
3434
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(
3435
+ "div",
3436
+ {
3437
+ ref: containerRef,
3438
+ role: isTabs ? "tablist" : void 0,
3439
+ "aria-orientation": isTabs ? orientation : void 0,
3440
+ onKeyDown: handleKeyDown,
3441
+ className: cn(
3442
+ "flex min-w-0",
3443
+ isVertical ? "flex-col items-center gap-1" : "items-center gap-1",
3444
+ V.strip,
3445
+ className
3446
+ ),
3447
+ children: [
3448
+ rendered,
3449
+ overflowTrigger
3450
+ ]
3451
+ }
3452
+ ) });
3185
3453
  };
3186
- var NavBase = ({ className = "", orientation, sections }) => {
3454
+ function renderMenuRows(menuItems) {
3455
+ const gutter = menuItems?.some((m) => m.icon);
3456
+ return menuItems?.map((menuItem) => {
3457
+ const MenuIcon = menuItem.icon;
3458
+ return /* @__PURE__ */ jsxs(React23__default.Fragment, { children: [
3459
+ menuItem.separatorBefore && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3460
+ /* @__PURE__ */ jsxs(
3461
+ DropdownMenuItem,
3462
+ {
3463
+ disabled: menuItem.disabled,
3464
+ onSelect: () => menuItem.onSelect?.(),
3465
+ className: cn(
3466
+ menuItem.destructive && "text-destructive focus:bg-destructive/15 focus:text-destructive hover:bg-destructive/10 hover:text-destructive"
3467
+ ),
3468
+ children: [
3469
+ MenuIcon ? /* @__PURE__ */ jsx(MenuIcon, {}) : gutter ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-4 shrink-0" }) : null,
3470
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: menuItem.label }),
3471
+ menuItem.shortcut && /* @__PURE__ */ jsx(DropdownMenuShortcut, { children: menuItem.shortcut })
3472
+ ]
3473
+ }
3474
+ )
3475
+ ] }, menuItem.id);
3476
+ });
3477
+ }
3478
+ var NavBase = ({
3479
+ className = "",
3480
+ orientation,
3481
+ sections
3482
+ }) => {
3187
3483
  const isVertical = orientation === "vertical";
3188
3484
  const containerClass = isVertical ? `flex flex-col items-center h-full ${className}` : `flex items-center w-full ${className}`;
3189
3485
  const sectionWrapperClass = isVertical ? "flex flex-col items-center gap-1" : "flex items-center gap-1 ";
3190
3486
  return /* @__PURE__ */ jsxs("nav", { className: containerClass, children: [
3191
- sections.start?.content && /* @__PURE__ */ jsx("div", { className: `${sectionWrapperClass} ${sections.start.className || ""}`, children: sections.start.content }),
3192
- sections.center?.content ? /* @__PURE__ */ jsx("div", { className: `flex-1 ${isVertical ? "" : "flex justify-center items-center gap-1"} ${sections.center.className || ""}`, children: sections.center.content }) : (
3487
+ sections.start?.content && /* @__PURE__ */ jsx(
3488
+ "div",
3489
+ {
3490
+ className: `${sectionWrapperClass} ${sections.start.className || ""}`,
3491
+ children: sections.start.content
3492
+ }
3493
+ ),
3494
+ sections.center?.content ? /* @__PURE__ */ jsx(
3495
+ "div",
3496
+ {
3497
+ className: `flex-1 ${isVertical ? "" : "flex justify-center items-center gap-1"} ${sections.center.className || ""}`,
3498
+ children: sections.center.content
3499
+ }
3500
+ ) : (
3193
3501
  // Empty spacer to push end section to the bottom/right
3194
3502
  /* @__PURE__ */ jsx("div", { className: "flex-1" })
3195
3503
  ),
3196
- sections.end?.content && /* @__PURE__ */ jsx("div", { className: `${sectionWrapperClass} ${isVertical ? "" : "ml-auto"} ${sections.end.className || ""}`, children: sections.end.content })
3504
+ sections.end?.content && /* @__PURE__ */ jsx(
3505
+ "div",
3506
+ {
3507
+ className: `${sectionWrapperClass} ${isVertical ? "" : "ml-auto"} ${sections.end.className || ""}`,
3508
+ children: sections.end.content
3509
+ }
3510
+ )
3197
3511
  ] });
3198
3512
  };
3199
- var NavHorizontalItems = ({ items }) => /* @__PURE__ */ jsx(NavItems, { items, orientation: "horizontal" });
3513
+ var NavHorizontalItems = (props) => /* @__PURE__ */ jsx(NavItems, { ...props, orientation: "horizontal" });
3200
3514
  var NavHorizontal = ({
3201
3515
  left,
3202
3516
  leftNavItems,
@@ -4230,7 +4544,7 @@ var MetricGrid = React23.forwardRef(
4230
4544
  )
4231
4545
  );
4232
4546
  MetricGrid.displayName = "MetricGrid";
4233
- var NavVerticalItems = ({ items }) => /* @__PURE__ */ jsx(NavItems, { items, orientation: "vertical" });
4547
+ var NavVerticalItems = (props) => /* @__PURE__ */ jsx(NavItems, { ...props, orientation: "vertical" });
4234
4548
  var NavVertical = ({
4235
4549
  className = "",
4236
4550
  top,
@@ -4935,6 +5249,9 @@ function TabbedPanel({
4935
5249
  activeTab,
4936
5250
  onTabChange,
4937
5251
  headerActions,
5252
+ overflow = false,
5253
+ overflowLabel = "More panels",
5254
+ keepMounted = false,
4938
5255
  className,
4939
5256
  headerClassName,
4940
5257
  bodyClassName,
@@ -4949,34 +5266,64 @@ function TabbedPanel({
4949
5266
  }
4950
5267
  onTabChange?.(value);
4951
5268
  };
4952
- return /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsx(Tabs, { value: currentTab, onValueChange: handleTabChange, className: "h-full", children: /* @__PURE__ */ jsxs(Card, { className: cn("h-full border rounded-none", className), children: [
4953
- /* @__PURE__ */ jsxs(CardHeader, { className: `flex flex-row items-center justify-between py-0 border-b h-[30px] px-0 space-y-0 ${headerClassName || ""}`, children: [
4954
- /* @__PURE__ */ jsx(TabsList, { className: "h-full bg-transparent p-0 gap-0 rounded-none", children: tabs.map((tab) => /* @__PURE__ */ jsxs(
4955
- TabsTrigger,
5269
+ const uid = React23__default.useId();
5270
+ const panelId = (value) => `${uid}-panel-${value}`;
5271
+ const items = React23__default.useMemo(
5272
+ () => tabs.map((tab) => ({
5273
+ key: tab.value,
5274
+ name: tab.name ?? (typeof tab.label === "string" ? tab.label : tab.value),
5275
+ label: tab.label,
5276
+ icon: tab.icon,
5277
+ disabled: tab.disabled
5278
+ })),
5279
+ [tabs]
5280
+ );
5281
+ return /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(Card, { className: cn("flex h-full min-h-0 flex-col border rounded-none", className), children: [
5282
+ /* @__PURE__ */ jsxs(
5283
+ "div",
5284
+ {
5285
+ className: cn(
5286
+ "flex h-[30px] shrink-0 flex-row items-stretch border-b",
5287
+ headerClassName
5288
+ ),
5289
+ children: [
5290
+ /* @__PURE__ */ jsx(
5291
+ NavItems,
5292
+ {
5293
+ items,
5294
+ variant: "underline",
5295
+ selectionMode: "tabs",
5296
+ activeKey: currentTab,
5297
+ onActiveChange: handleTabChange,
5298
+ panelId,
5299
+ overflow,
5300
+ overflowLabel,
5301
+ className: "min-w-0 flex-1 gap-0",
5302
+ iconClassName: "h-3.5 w-3.5 shrink-0"
5303
+ }
5304
+ ),
5305
+ headerActions && headerActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "ml-auto flex h-full shrink-0 items-center gap-1 pr-1", children: /* @__PURE__ */ jsx(NavHorizontalItems, { items: headerActions }) })
5306
+ ]
5307
+ }
5308
+ ),
5309
+ tabs.map((tab) => {
5310
+ const active = tab.value === currentTab;
5311
+ if (!keepMounted && !active) return null;
5312
+ return /* @__PURE__ */ jsx(
5313
+ "div",
4956
5314
  {
4957
- value: tab.value,
4958
- disabled: tab.disabled,
4959
- className: "h-full text-muted-foreground hover:text-foreground data-[state=active]:bg-primary/10 data-[state=active]:text-primary data-[state=active]:border-b-2 data-[state=active]:border-primary data-[state=active]:mb-[-1px] rounded-none px-3 py-2",
4960
- children: [
4961
- tab.icon && /* @__PURE__ */ jsx(tab.icon, { className: "h-3.5 w-3.5 mr-1.5" }),
4962
- tab.label
4963
- ]
5315
+ id: panelId(tab.value),
5316
+ role: "tabpanel",
5317
+ "aria-label": tab.name ?? (typeof tab.label === "string" ? tab.label : tab.value),
5318
+ hidden: !active,
5319
+ className: cn("m-0 min-h-0 flex-1 overflow-y-auto", bodyClassName),
5320
+ children: tab.content
4964
5321
  },
4965
5322
  tab.value
4966
- )) }),
4967
- headerActions && headerActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "ml-auto flex h-full shrink-0 items-center gap-1 pr-1", children: /* @__PURE__ */ jsx(NavHorizontalItems, { items: headerActions }) })
4968
- ] }),
4969
- tabs.map((tab) => /* @__PURE__ */ jsx(
4970
- TabsContent,
4971
- {
4972
- value: tab.value,
4973
- className: `h-[calc(100%-30px)] m-0 ${bodyClassName || ""}`,
4974
- children: /* @__PURE__ */ jsx(CardContent, { className: "overflow-y-auto h-full p-0", children: tab.content })
4975
- },
4976
- tab.value
4977
- )),
4978
- footerContent && /* @__PURE__ */ jsx(CardFooter, { className: footerClassName, children: footerContent })
4979
- ] }) }) }) });
5323
+ );
5324
+ }),
5325
+ footerContent && /* @__PURE__ */ jsx(CardFooter, { className: cn("shrink-0", footerClassName), children: footerContent })
5326
+ ] }) }) });
4980
5327
  }
4981
5328
  var TemplatePicker = React23.forwardRef(({ heading, options, value, onSelect, footnote, className, ...props }, ref) => /* @__PURE__ */ jsxs(
4982
5329
  "div",
@@ -5088,27 +5435,93 @@ var TerminalLine = React23.forwardRef(
5088
5435
  )
5089
5436
  );
5090
5437
  TerminalLine.displayName = "TerminalLine";
5091
- var TimelineList = React23.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx("ol", { ref, className: cn("flex flex-col", className), ...props, children }));
5438
+ var TimelineVariantContext = React23.createContext("columns");
5439
+ var RAIL_MARKER_OFFSET = "h-[0.692rem]";
5440
+ var RAIL_FOOTER_TAIL = "h-[1.067rem]";
5441
+ var TimelineList = React23.forwardRef(({ className, variant = "columns", children, ...props }, ref) => /* @__PURE__ */ jsx(TimelineVariantContext.Provider, { value: variant, children: /* @__PURE__ */ jsx("ol", { ref, className: cn("flex flex-col", className), ...props, children }) }));
5092
5442
  TimelineList.displayName = "TimelineList";
5093
- var TimelineEntry = React23.forwardRef(({ when, title, marker, className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
5094
- "li",
5095
- {
5096
- ref,
5097
- className: cn("flex gap-2 border-b border-border py-1.5 last:border-b-0", className),
5098
- ...props,
5099
- children: [
5100
- /* @__PURE__ */ jsxs("span", { className: "flex w-[72px] shrink-0 items-baseline gap-1.5 text-meta text-muted-foreground", children: [
5101
- marker ? /* @__PURE__ */ jsx("span", { className: "translate-y-1", children: marker }) : null,
5102
- /* @__PURE__ */ jsx("span", { className: "truncate", children: when })
5103
- ] }),
5104
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
5105
- title != null ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: title }) : null,
5106
- children
5107
- ] })
5108
- ]
5443
+ function RailGutter({ marker }) {
5444
+ return /* @__PURE__ */ jsxs("span", { className: "flex w-2.5 shrink-0 flex-col items-center", children: [
5445
+ /* @__PURE__ */ jsx(
5446
+ "span",
5447
+ {
5448
+ "aria-hidden": true,
5449
+ className: cn(
5450
+ "w-px shrink-0 bg-border group-first/entry:bg-transparent",
5451
+ RAIL_MARKER_OFFSET
5452
+ )
5453
+ }
5454
+ ),
5455
+ marker,
5456
+ /* @__PURE__ */ jsx(
5457
+ "span",
5458
+ {
5459
+ "aria-hidden": true,
5460
+ className: "w-px flex-1 bg-border group-last/entry:bg-transparent"
5461
+ }
5462
+ )
5463
+ ] });
5464
+ }
5465
+ var TimelineEntry = React23.forwardRef(({ when, title, marker, className, children, ...props }, ref) => {
5466
+ const variant = React23.useContext(TimelineVariantContext);
5467
+ if (variant === "rail") {
5468
+ return /* @__PURE__ */ jsxs(
5469
+ "li",
5470
+ {
5471
+ ref,
5472
+ className: cn("group/entry flex gap-2.5", className),
5473
+ ...props,
5474
+ children: [
5475
+ /* @__PURE__ */ jsx(RailGutter, { marker }),
5476
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5 pb-4 group-last/entry:pb-0", children: [
5477
+ /* @__PURE__ */ jsx("span", { className: "text-meta text-muted-foreground", children: when }),
5478
+ title != null ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: title }) : null,
5479
+ children
5480
+ ] })
5481
+ ]
5482
+ }
5483
+ );
5109
5484
  }
5110
- ));
5485
+ return /* @__PURE__ */ jsxs(
5486
+ "li",
5487
+ {
5488
+ ref,
5489
+ className: cn("flex gap-2 border-b border-border py-1.5 last:border-b-0", className),
5490
+ ...props,
5491
+ children: [
5492
+ /* @__PURE__ */ jsxs("span", { className: "flex w-[72px] shrink-0 items-baseline gap-1.5 text-meta text-muted-foreground", children: [
5493
+ marker ? /* @__PURE__ */ jsx("span", { className: "translate-y-1", children: marker }) : null,
5494
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: when })
5495
+ ] }),
5496
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
5497
+ title != null ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: title }) : null,
5498
+ children
5499
+ ] })
5500
+ ]
5501
+ }
5502
+ );
5503
+ });
5111
5504
  TimelineEntry.displayName = "TimelineEntry";
5505
+ var TimelineFooter = React23.forwardRef(({ className, children, ...props }, ref) => {
5506
+ const variant = React23.useContext(TimelineVariantContext);
5507
+ if (variant === "rail") {
5508
+ return /* @__PURE__ */ jsxs(
5509
+ "li",
5510
+ {
5511
+ ref,
5512
+ role: "presentation",
5513
+ className: cn("flex gap-2.5", className),
5514
+ ...props,
5515
+ children: [
5516
+ /* @__PURE__ */ jsx("span", { className: "flex w-2.5 shrink-0 justify-center", children: /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("w-px bg-border", RAIL_FOOTER_TAIL) }) }),
5517
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 pt-1.5", children })
5518
+ ]
5519
+ }
5520
+ );
5521
+ }
5522
+ return /* @__PURE__ */ jsx("li", { ref, role: "presentation", className: cn("pt-1.5", className), ...props, children });
5523
+ });
5524
+ TimelineFooter.displayName = "TimelineFooter";
5112
5525
  var Toolbar = () => {
5113
5526
  return /* @__PURE__ */ jsxs("div", { className: "flex h-5 items-center space-x-2", children: [
5114
5527
  /* @__PURE__ */ jsx(
@@ -5695,6 +6108,6 @@ var Typography = {
5695
6108
  Pre: TypographyPre
5696
6109
  };
5697
6110
 
5698
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AgentChip, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppStatusBar, Avatar, AvatarFallback, AvatarImage, Badge, BarChartH, BarChartV, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, ButtonWithTooltip, CannotAnswerCard, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardWithHeader, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChatSession, ChatSessionActivityRow, ChatSessionActivitySubLine, ChatSessionComposer, ChatSessionContextChip, ChatSessionDisclosure, ChatSessionMessage, ChatSessionMessageOptions, ChatSessionProgressLine, ChatSessionPromptRow, ChatSessionStatusBar, ChatSessionTaskGroup, ChatSessionTaskRow, CitationList, CitationMarker, CitationRow, ClarifyCard, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextBar, DiagnosisCard, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffList, DiffRow, DivergingBar, DotRating, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmissionCard, EmissionHeader, EmptyState, EmptyStateLock, ErrorBoundary, FilterBar, FilterChip, HeatStrip, HoverCard, HoverCardContent, HoverCardTrigger, Item3 as Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Legend, LegendItem, MenuItem, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MetricGrid, MetricTile, NavBase, NavHorizontal, NavHorizontalItems, NavItems, NavVertical, NavVerticalItems, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NestedMenu, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PanelContent, PanelStack, Popover, PopoverContent, PopoverTrigger, Progress, PropertyList, PropertyRow, ProposalCard, RatingControl, RepairNote, ResizableHandle, ResizablePanel, ResizablePanelGroup, RetryNote, RichSelect, ScrollArea, ScrollBar, SearchInput, SectionHeader, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Sparkline, Spinner, StatusDot, TabbedPanel, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TemplatePicker, Terminal, TerminalLine, TimelineEntry, TimelineList, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Toolbar, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tour, TreeItem, TreeView, Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyH5, TypographyH6, TypographyInlineCode, TypographyLarge, TypographyLead, TypographyList, TypographyMuted, TypographyP, TypographyPre, TypographySmall, UnderDevelopment, agentChipVariants, badgeVariants, buttonGroupVariants, buttonVariants, chatSessionGutterClass, cn, navigationMenuTriggerStyle, statusDotVariants, toggleVariants, useSidebar, useTour };
6111
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AgentChip, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppStatusBar, Avatar, AvatarFallback, AvatarImage, Badge, BarChartH, BarChartV, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, ButtonWithTooltip, CannotAnswerCard, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardWithHeader, Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, ChatSession, ChatSessionActivityRow, ChatSessionActivitySubLine, ChatSessionComposer, ChatSessionContextChip, ChatSessionDisclosure, ChatSessionMessage, ChatSessionMessageOptions, ChatSessionProgressLine, ChatSessionPromptRow, ChatSessionStatusBar, ChatSessionTaskGroup, ChatSessionTaskRow, CitationList, CitationMarker, CitationRow, ClarifyCard, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextBar, DiagnosisCard, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiffList, DiffRow, DivergingBar, DotRating, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmissionCard, EmissionHeader, EmptyState, EmptyStateLock, ErrorBoundary, FilterBar, FilterChip, HeatStrip, HoverCard, HoverCardContent, HoverCardTrigger, Item3 as Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Legend, LegendItem, MenuItem, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, MetricGrid, MetricTile, NavBase, NavHorizontal, NavHorizontalItems, NavItems, NavVertical, NavVerticalItems, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, NestedMenu, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, PanelContent, PanelStack, Popover, PopoverContent, PopoverTrigger, Progress, PropertyList, PropertyRow, ProposalCard, RatingControl, RepairNote, ResizableHandle, ResizablePanel, ResizablePanelGroup, RetryNote, RichSelect, ScrollArea, ScrollBar, SearchInput, SectionHeader, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Sparkline, Spinner, StatusDot, TabbedPanel, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TemplatePicker, Terminal, TerminalLine, TimelineEntry, TimelineFooter, TimelineList, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Toolbar, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Tour, TreeItem, TreeView, Typography, TypographyBlockquote, TypographyH1, TypographyH2, TypographyH3, TypographyH4, TypographyH5, TypographyH6, TypographyInlineCode, TypographyLarge, TypographyLead, TypographyList, TypographyMuted, TypographyP, TypographyPre, TypographySmall, UnderDevelopment, agentChipVariants, badgeVariants, buttonGroupVariants, buttonVariants, chatSessionGutterClass, cn, navigationMenuTriggerStyle, statusDotVariants, toggleVariants, useOverflowItems, useSidebar, useTour };
5699
6112
  //# sourceMappingURL=index.js.map
5700
6113
  //# sourceMappingURL=index.js.map