@botiverse/raft-ui 0.19.0 → 0.21.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.
@@ -12,9 +12,18 @@ import { Checkbox } from "@base-ui/react/checkbox";
12
12
  import { ScrollArea } from "@base-ui/react/scroll-area";
13
13
  import { Avatar } from "@base-ui/react";
14
14
  import { Menu } from "@base-ui/react/menu";
15
+ import { flushSync } from "react-dom";
15
16
  import { Toggle } from "@base-ui/react/toggle";
16
17
  import { Toolbar } from "@base-ui/react/toolbar";
17
18
  import { PointerSensor, TouchSensor, useSensor } from "@dnd-kit/core";
19
+ //#region src/lib/decision-width.ts
20
+ /**
21
+ * The width of every decision dialog (dialog.md#variants): AlertDialog and a
22
+ * `size="sm"` Dialog are both 400px, so every confirmation in a product is one
23
+ * width whichever of the two it is built on.
24
+ */
25
+ const decisionWidth = "max-w-100";
26
+ //#endregion
18
27
  //#region src/lib/head-edges.ts
19
28
  /**
20
29
  * The ends of a header (design/foundations/alignment.md#the-ends-of-a-header).
@@ -247,8 +256,8 @@ function Spinner({ size = "sm", variant = "default", className, render, ...props
247
256
  }
248
257
  //#endregion
249
258
  //#region src/components/button/button.tsx
250
- const sticker = (fill) => [`border-sticker-ink ${fill} text-sticker-ink ring-[1.5px] ring-sticker-edge`, "hover:press-overlay-sticker active:press-overlay-sticker"];
251
- const outline = (ink) => [`border-line-strong bg-layer-card ${ink}`, "hover:press-overlay active:press-overlay"];
259
+ const sticker = (fill) => [`border-sticker-ink ${fill} text-sticker-ink ring-[1.5px] ring-sticker-edge`, "hover:overlay-sticker-medium active:overlay-sticker-medium"];
260
+ const outline = (ink) => [`border-line-strong bg-layer-card ${ink}`, "hover:overlay-medium active:overlay-medium"];
252
261
  const textMd = [
253
262
  "h-8 gap-2 rounded-control px-3 py-0 text-control",
254
263
  "has-data-[icon=inline-start]:pl-2.5 has-data-[icon=inline-end]:pr-2.5",
@@ -291,11 +300,11 @@ const buttonVariants = tv$1({
291
300
  success: { root: outline("text-foreground") },
292
301
  "danger-secondary": { root: outline("text-danger-strong") },
293
302
  "danger-outline": { root: outline("text-danger-strong") },
294
- ghost: { root: ["border-transparent bg-transparent text-foreground", "hover:bg-fill-pressed active:bg-fill-pressed"] },
303
+ ghost: { root: ["border-transparent bg-transparent text-foreground", "hover:bg-fill-medium active:bg-fill-medium"] },
295
304
  "on-frame": { root: [
296
305
  "border-transparent bg-transparent text-foreground-on-frame",
297
- "hover:bg-fill-frame-pressed active:bg-fill-frame-pressed",
298
- "aria-expanded:bg-fill-frame-pressed data-popup-open:bg-fill-frame-pressed",
306
+ "hover:bg-fill-frame-medium active:bg-fill-frame-medium",
307
+ "aria-expanded:bg-fill-frame-medium data-popup-open:bg-fill-frame-medium",
299
308
  "disabled:border-transparent disabled:bg-transparent",
300
309
  "aria-disabled:border-transparent aria-disabled:bg-transparent"
301
310
  ] }
@@ -427,9 +436,9 @@ const dialog = tv$1({
427
436
  },
428
437
  variants: {
429
438
  size: {
430
- sm: { content: ["max-w-sm"] },
439
+ sm: { content: [decisionWidth] },
431
440
  md: { content: ["max-w-md"] },
432
- lg: { content: ["max-w-lg"] },
441
+ lg: { content: ["max-w-160"] },
433
442
  wide: { content: ["max-w-4xl h-[min(760px,calc(100dvh-2rem))]"] }
434
443
  },
435
444
  bar: {
@@ -616,6 +625,7 @@ const badge = tv$1({
616
625
  "font-sans text-caption font-semibold normal-case tracking-normal",
617
626
  "transition-[filter,opacity] duration-100",
618
627
  "[&_svg]:size-3.5 [&_svg]:shrink-0 [&_[data-slot='spinner']]:size-3 [&_[data-slot='spinner']]:text-xs",
628
+ "*:data-[slot=status]:lead-dot",
619
629
  "disabled:cursor-not-allowed disabled:bg-fill-muted disabled:text-foreground-disabled disabled:opacity-100 disabled:inset-ring-0"
620
630
  ] },
621
631
  variants: {
@@ -625,13 +635,13 @@ const badge = tv$1({
625
635
  "font-bold tabular-nums",
626
636
  "text-sticker-ink inset-ring-[1.5px] inset-ring-sticker-ink ring-[1.5px] ring-sticker-edge",
627
637
  "[&_svg]:size-[13px]",
628
- "enabled:hover:press-overlay-sticker"
638
+ "enabled:hover:overlay-sticker-medium enabled:active:overlay-sticker-medium"
629
639
  ] },
630
- soft: { root: ["text-foreground", "enabled:hover:press-overlay"] },
640
+ soft: { root: ["text-foreground", "enabled:hover:overlay-medium enabled:active:overlay-medium"] },
631
641
  outline: { root: [
632
642
  "font-mono text-mono-meta font-normal",
633
643
  "bg-transparent text-foreground-muted inset-ring inset-ring-line-hairline",
634
- "enabled:hover:bg-fill-pressed"
644
+ "enabled:hover:bg-fill-medium enabled:active:bg-fill-medium"
635
645
  ] }
636
646
  },
637
647
  variant: {
@@ -789,6 +799,36 @@ function Experimental(props) {
789
799
  }
790
800
  const Badge = Object.assign(BadgeRoot, { Experimental });
791
801
  //#endregion
802
+ //#region src/components/text-link/text-link.tsx
803
+ const textLinkVariants = tv$1({
804
+ base: [
805
+ "rounded-[2px]",
806
+ "decoration-[1.5px] underline-offset-[3px] not-disabled:hover:underline",
807
+ "outline-none focus-visible:shadow-focus",
808
+ "disabled:cursor-not-allowed disabled:text-foreground-disabled"
809
+ ],
810
+ variants: { variant: {
811
+ muted: ["font-medium text-foreground-muted", "hover:text-foreground"],
812
+ strong: ["font-semibold text-foreground"]
813
+ } },
814
+ defaultVariants: { variant: "muted" }
815
+ });
816
+ function TextLink({ variant, className, render, ...props }) {
817
+ const defaultProps = {
818
+ className: textLinkVariants({
819
+ variant,
820
+ className
821
+ }),
822
+ ...render ? {} : { type: "button" }
823
+ };
824
+ return useRender({
825
+ defaultTagName: "button",
826
+ render,
827
+ props: mergeProps(defaultProps, props),
828
+ state: { slot: "text-link" }
829
+ });
830
+ }
831
+ //#endregion
792
832
  //#region src/components/tooltip/tooltip.tsx
793
833
  const tooltip = tv$1({
794
834
  slots: {
@@ -934,7 +974,7 @@ const CONTENT_COLLISION_AVOIDANCE = {
934
974
  align: "shift",
935
975
  fallbackAxisSide: "none"
936
976
  };
937
- function TooltipContent({ align = "center", alignOffset = 0, anchor, arrowPadding, collisionAvoidance = CONTENT_COLLISION_AVOIDANCE, collisionBoundary, collisionPadding, disableAnchorTracking = false, positionMethod = "fixed", side = "top", sideOffset, sticky, container, portalProps, className, children, ...props }) {
977
+ function TooltipContent({ align = "center", alignOffset = 0, anchor, arrowPadding, collisionAvoidance = CONTENT_COLLISION_AVOIDANCE, collisionBoundary, collisionPadding, disableAnchorTracking, positionMethod = "fixed", side = "top", sideOffset, sticky, container, portalProps, className, children, ...props }) {
938
978
  const { positioner, content } = tooltip();
939
979
  const portalContainer = container !== void 0 ? container : portalProps?.container;
940
980
  return /* @__PURE__ */ jsx(TooltipPortal, {
@@ -1042,7 +1082,9 @@ const checkbox = tv$1({ slots: {
1042
1082
  "relative inline-flex size-5 shrink-0 touch-manipulation items-center justify-center outline-none",
1043
1083
  "rounded-sticker focus-visible:shadow-focus",
1044
1084
  "data-disabled:cursor-not-allowed",
1045
- "after:absolute after:-inset-x-3 after:-inset-y-2 after:content-['']"
1085
+ "after:absolute after:-inset-x-3 after:-inset-y-2 after:content-[''] pointer-coarse:after:-inset-y-3",
1086
+ "[label>&]:my-[max(0px,calc((1lh-1.25rem)/2))]",
1087
+ "[label>&]:after:-inset-y-[calc(max(0px,(1lh-1.25rem)/2)+4px)]"
1046
1088
  ],
1047
1089
  indicator: "pointer-events-none"
1048
1090
  } });
@@ -1307,13 +1349,13 @@ const dropdownMenu = tv$1({ slots: {
1307
1349
  content: [
1308
1350
  "max-h-(--available-height) overflow-hidden",
1309
1351
  "outline-none",
1310
- "flex min-w-60 flex-col gap-0 rounded-container bg-layer-popover p-1.5 text-foreground",
1352
+ "flex min-w-60 flex-col gap-0 rounded-container bg-layer-popover p-1 text-foreground",
1311
1353
  "shadow-float ring-1 ring-line-seam"
1312
1354
  ],
1313
1355
  item: [
1314
1356
  "flex w-full cursor-default select-none items-center",
1315
1357
  "text-left outline-none transition-colors",
1316
- "min-h-option gap-2.5 rounded-control px-2.5 py-option-inset",
1358
+ "min-h-option gap-2.5 rounded-chip px-2.5 py-option-inset",
1317
1359
  "font-sans text-callout font-medium text-foreground",
1318
1360
  "hover:bg-brand-soft data-highlighted:bg-brand-soft",
1319
1361
  "data-checked:font-bold data-[selected]:font-bold data-[emphasis=strong]:font-bold",
@@ -1324,7 +1366,7 @@ const dropdownMenu = tv$1({ slots: {
1324
1366
  radioItem: [
1325
1367
  "flex w-full cursor-default select-none items-center",
1326
1368
  "text-left outline-none transition-colors",
1327
- "min-h-option gap-2.5 rounded-control px-2.5 py-option-inset",
1369
+ "min-h-option gap-2.5 rounded-chip px-2.5 py-option-inset",
1328
1370
  "font-sans text-callout font-medium text-foreground",
1329
1371
  "hover:bg-brand-soft data-highlighted:bg-brand-soft",
1330
1372
  "data-checked:font-bold",
@@ -1335,7 +1377,7 @@ const dropdownMenu = tv$1({ slots: {
1335
1377
  submenuTrigger: [
1336
1378
  "flex w-full cursor-default select-none items-center",
1337
1379
  "text-left outline-none transition-colors",
1338
- "min-h-option gap-2.5 rounded-control px-2.5 py-option-inset",
1380
+ "min-h-option gap-2.5 rounded-chip px-2.5 py-option-inset",
1339
1381
  "font-sans text-callout font-medium text-foreground",
1340
1382
  "hover:bg-brand-soft data-highlighted:bg-brand-soft data-popup-open:bg-brand-soft",
1341
1383
  "data-disabled:pointer-events-none data-disabled:text-foreground-disabled",
@@ -1351,7 +1393,7 @@ const dropdownMenu = tv$1({ slots: {
1351
1393
  "font-mono text-mono-meta font-normal text-foreground-hint"
1352
1394
  ],
1353
1395
  itemCount: ["ml-auto inline-flex min-w-5 justify-center gap-0 px-1 tabular-nums"],
1354
- separator: ["-mx-1.5 my-1.5 h-px border-0 bg-line-hairline"],
1396
+ separator: ["-mx-1 my-1 h-px border-0 bg-line-hairline"],
1355
1397
  indicator: ["pointer-events-none ml-auto flex shrink-0 items-center justify-center", "size-4 text-foreground [&_svg]:size-4"],
1356
1398
  radioLabel: ["min-w-0 flex-1 truncate"]
1357
1399
  } });
@@ -1393,7 +1435,7 @@ function DropdownMenuPopup({ className, ...props }) {
1393
1435
  ...props
1394
1436
  });
1395
1437
  }
1396
- function DropdownMenuContent({ align = "start", alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding, disableAnchorTracking = false, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, ...props }) {
1438
+ function DropdownMenuContent({ align = "start", alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding, disableAnchorTracking, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, ...props }) {
1397
1439
  const resolvedSideOffset = sideOffset ?? 6;
1398
1440
  const { positioner, content } = dropdownMenu();
1399
1441
  return /* @__PURE__ */ jsx(DropdownMenuPortal, {
@@ -1581,10 +1623,157 @@ function DropdownMenuCheckboxItemIndicator({ className, ...props }) {
1581
1623
  ...props
1582
1624
  });
1583
1625
  }
1626
+ function contentBox(element) {
1627
+ const rect = element.getBoundingClientRect();
1628
+ if (rect.width === 0 && rect.height === 0) return void 0;
1629
+ const style = element.ownerDocument.defaultView?.getComputedStyle(element);
1630
+ const px = (value) => Number.parseFloat(value ?? "") || 0;
1631
+ return {
1632
+ left: rect.left + px(style?.borderLeftWidth) + px(style?.paddingLeft),
1633
+ right: rect.right - px(style?.borderRightWidth) - px(style?.paddingRight),
1634
+ top: rect.top + px(style?.borderTopWidth) + px(style?.paddingTop),
1635
+ bottom: rect.bottom - px(style?.borderBottomWidth) - px(style?.paddingBottom)
1636
+ };
1637
+ }
1638
+ /**
1639
+ * Whether laid-out text `rects` overflow `box`: past either inline edge, or
1640
+ * on a line whose middle is below the bottom edge (a clamped line is still
1641
+ * laid out, below the box; the middle, not the top, so a glyph box taller
1642
+ * than a tight line-height does not count as a cut).
1643
+ */
1644
+ function overflows(rects, box) {
1645
+ for (const rect of Array.from(rects)) {
1646
+ if (rect.width === 0 && rect.height === 0) continue;
1647
+ if (rect.right > box.right + .5 || rect.left < box.left - .5) return true;
1648
+ if (rect.top + rect.height / 2 > box.bottom + .5) return true;
1649
+ }
1650
+ return false;
1651
+ }
1652
+ /** Whether the text inside `element` overflows its content box. */
1653
+ function measureElement(element) {
1654
+ if (!element.isConnected) return void 0;
1655
+ const box = contentBox(element);
1656
+ if (!box) return void 0;
1657
+ const range = element.ownerDocument.createRange();
1658
+ range.selectNodeContents(element);
1659
+ return overflows(range.getClientRects(), box);
1660
+ }
1661
+ /**
1662
+ * Whether the inline `content` overflows `text`, the box that clips it.
1663
+ * Used where `text` holds more than the content (an Ellipsis's floats).
1664
+ */
1665
+ function measureContent(text, content) {
1666
+ if (!text.isConnected) return void 0;
1667
+ const box = contentBox(text);
1668
+ if (!box) return void 0;
1669
+ return overflows(content.getClientRects(), box);
1670
+ }
1671
+ /** Isolates, reads and restores one target now, outside the batch. */
1672
+ function readNow(target) {
1673
+ const restore = target.isolate?.();
1674
+ try {
1675
+ return target.read();
1676
+ } finally {
1677
+ restore?.();
1678
+ }
1679
+ }
1680
+ const targets = /* @__PURE__ */ new Set();
1681
+ const byElement = /* @__PURE__ */ new WeakMap();
1682
+ const pending = /* @__PURE__ */ new Set();
1683
+ let frame = 0;
1684
+ let resizeObserver;
1685
+ let mutationObserver;
1686
+ let fontsListening = false;
1687
+ function flush() {
1688
+ frame = 0;
1689
+ const batch = Array.from(pending).filter((target) => targets.has(target));
1690
+ pending.clear();
1691
+ const restores = batch.map((target) => target.isolate?.());
1692
+ const results = batch.map((target) => target.read());
1693
+ for (const restore of restores) restore?.();
1694
+ flushSync(() => {
1695
+ batch.forEach((target, index) => {
1696
+ if (targets.has(target)) target.commit(results[index]);
1697
+ });
1698
+ });
1699
+ }
1700
+ /** Asks for `target` to be measured in the next frame, before it paints. */
1701
+ function scheduleMeasure(target) {
1702
+ if (!targets.has(target)) return;
1703
+ pending.add(target);
1704
+ if (frame === 0 && typeof requestAnimationFrame === "function") frame = requestAnimationFrame(flush);
1705
+ }
1706
+ function scheduleAll() {
1707
+ for (const target of targets) scheduleMeasure(target);
1708
+ }
1709
+ function ownerOf(node) {
1710
+ for (let current = node; current; current = current.parentNode) {
1711
+ const target = byElement.get(current);
1712
+ if (target) return target;
1713
+ }
1714
+ }
1715
+ function observers(view) {
1716
+ if (!resizeObserver && "ResizeObserver" in view) resizeObserver = new view.ResizeObserver((entries) => {
1717
+ for (const entry of entries) {
1718
+ const target = byElement.get(entry.target);
1719
+ if (target) scheduleMeasure(target);
1720
+ }
1721
+ });
1722
+ if (!mutationObserver && "MutationObserver" in view) mutationObserver = new view.MutationObserver((records) => {
1723
+ for (const record of records) {
1724
+ const target = ownerOf(record.target);
1725
+ if (target) scheduleMeasure(target);
1726
+ }
1727
+ });
1728
+ const fonts = view.document.fonts;
1729
+ if (!fontsListening && fonts && typeof fonts.addEventListener === "function") {
1730
+ fonts.addEventListener("loadingdone", scheduleAll);
1731
+ fontsListening = true;
1732
+ }
1733
+ }
1734
+ /**
1735
+ * Starts watching `target`: the elements it names, the text under `watch`
1736
+ * and the page's fonts. Measures it in the next frame. Returns the cleanup.
1737
+ */
1738
+ function observeTruncation(target) {
1739
+ const observed = target.observe().filter((element) => element != null);
1740
+ const first = observed[0];
1741
+ const view = first?.ownerDocument.defaultView;
1742
+ if (!first || !view) return () => void 0;
1743
+ observers(view);
1744
+ targets.add(target);
1745
+ for (const element of observed) {
1746
+ byElement.set(element, target);
1747
+ resizeObserver?.observe(element);
1748
+ }
1749
+ const watched = target.watch();
1750
+ if (watched) {
1751
+ byElement.set(watched, target);
1752
+ mutationObserver?.observe(watched, {
1753
+ childList: true,
1754
+ characterData: true,
1755
+ subtree: true
1756
+ });
1757
+ }
1758
+ scheduleMeasure(target);
1759
+ return () => {
1760
+ targets.delete(target);
1761
+ pending.delete(target);
1762
+ for (const element of observed) {
1763
+ if (byElement.get(element) === target) byElement.delete(element);
1764
+ resizeObserver?.unobserve(element);
1765
+ }
1766
+ if (watched && byElement.get(watched) === target) byElement.delete(watched);
1767
+ if (targets.size === 0) {
1768
+ mutationObserver?.disconnect();
1769
+ mutationObserver = void 0;
1770
+ }
1771
+ };
1772
+ }
1584
1773
  //#endregion
1585
1774
  //#region src/lib/use-overflow-title.ts
1586
1775
  function cut(element) {
1587
- return element.scrollWidth > element.clientWidth + 1 || element.scrollHeight > element.clientHeight + 1;
1776
+ return measureElement(element) === true;
1588
1777
  }
1589
1778
  function assign(ref, node) {
1590
1779
  if (typeof ref === "function") ref(node);
@@ -1613,25 +1802,18 @@ function useOverflowTitle(ref, title) {
1613
1802
  cleanup.current = void 0;
1614
1803
  assign(ref, node);
1615
1804
  const view = node?.ownerDocument.defaultView;
1616
- if (!node || own || !view || !("ResizeObserver" in view)) return;
1617
- const update = () => {
1618
- const text = node.textContent?.trim() ?? "";
1619
- if (text && (cut(node) || Array.from(node.children).some(cut))) node.title = text;
1620
- else node.removeAttribute("title");
1621
- };
1622
- const resize = new view.ResizeObserver(update);
1623
- resize.observe(node);
1624
- for (const child of Array.from(node.children)) resize.observe(child);
1625
- const mutation = new view.MutationObserver(update);
1626
- mutation.observe(node, {
1627
- childList: true,
1628
- characterData: true,
1629
- subtree: true
1805
+ if (!node || own || !view) return;
1806
+ const children = Array.from(node.children);
1807
+ cleanup.current = observeTruncation({
1808
+ observe: () => [node, ...children],
1809
+ watch: () => node,
1810
+ read: () => cut(node) || children.some(cut),
1811
+ commit: (truncated) => {
1812
+ const text = node.textContent?.trim() ?? "";
1813
+ if (text && truncated) node.title = text;
1814
+ else node.removeAttribute("title");
1815
+ }
1630
1816
  });
1631
- cleanup.current = () => {
1632
- resize.disconnect();
1633
- mutation.disconnect();
1634
- };
1635
1817
  }, [own, ref]);
1636
1818
  }
1637
1819
  //#endregion
@@ -1928,11 +2110,11 @@ const messageItem = tv$1({
1928
2110
  "group/message relative flex h-fit gap-3",
1929
2111
  "hover:[--mi-toolbar-opacity:1] hover:[--mi-toolbar-pe:auto] focus-within:[--mi-toolbar-opacity:1] focus-within:[--mi-toolbar-pe:auto]",
1930
2112
  "has-data-popup-open:[--mi-toolbar-opacity:1] has-data-popup-open:[--mi-toolbar-pe:auto]",
1931
- "min-h-0 px-2 py-1 border-t-8 border-transparent bg-clip-padding",
2113
+ "min-h-0 px-2 py-timeline-row border-t-(length:--spacing-timeline-turn) border-transparent bg-clip-padding",
1932
2114
  "hover:[--mi-ct-color:var(--foreground-hint)] has-data-popup-open:[--mi-ct-color:var(--foreground-hint)]",
1933
2115
  "bg-(--mi-row-fill) [--mi-row-fill:initial]",
1934
- "hover:[--mi-row-fill:var(--fill-message-hover)]",
1935
- "data-popup-open:[--mi-row-fill:var(--fill-row-open)] has-data-popup-open:[--mi-row-fill:var(--fill-row-open)]",
2116
+ "hover:[--mi-row-fill:var(--fill-subtle)]",
2117
+ "data-popup-open:[--mi-row-fill:var(--fill-subtle)] has-data-popup-open:[--mi-row-fill:var(--fill-subtle)]",
1936
2118
  "has-data-[slot=message-item-search-match]:[--mi-row-fill:var(--info-soft)] has-data-[slot=message-item-search-match]:hover:[--mi-row-fill:var(--info-soft)]",
1937
2119
  "has-[[data-slot=message-multi-select-checkbox][data-checked]]:[--mi-row-fill:var(--info-soft)]",
1938
2120
  "has-[[data-slot=message-multi-select-checkbox][data-checked]]:hover:[--mi-row-fill:var(--info-soft)]"
@@ -1952,7 +2134,7 @@ const messageItem = tv$1({
1952
2134
  content: ["min-w-0 flex-1", "text-body text-foreground"],
1953
2135
  header: [
1954
2136
  "mb-px flex min-w-0 items-baseline gap-1.5 overflow-hidden",
1955
- "pointer-fine:pe-(--mi-toolbar-reserve,6.5rem)",
2137
+ "pointer-fine:pe-(--mi-toolbar-reserve,7rem)",
1956
2138
  "has-data-[slot=message-item-delegated-by]:[--mi-owner-basis:3rem] has-data-[slot=message-item-delegated-by]:[--mi-owner-flex:1_0]"
1957
2139
  ],
1958
2140
  senderGroup: [
@@ -2007,15 +2189,15 @@ const messageItem = tv$1({
2007
2189
  "absolute z-20 flex items-center",
2008
2190
  "opacity-(--mi-toolbar-opacity,0)",
2009
2191
  "[pointer-events:var(--mi-toolbar-pe,none)]",
2010
- "top-[-16px] right-3 gap-0.5 overflow-visible rounded-container p-0.5",
2192
+ "top-[-18px] right-3 gap-1 overflow-visible rounded-container p-1",
2011
2193
  "bg-layer-popover ring-1 ring-line-seam ring-inset shadow-float"
2012
2194
  ],
2013
2195
  toolbarButton: [
2014
2196
  "inline-flex shrink-0 items-center justify-center",
2015
2197
  "[&_svg]:shrink-0",
2016
- "size-7 rounded-control border-0 bg-transparent p-0",
2017
- "text-foreground-muted hover:bg-fill-pressed active:bg-fill-pressed",
2018
- "data-popup-open:bg-fill-pressed data-active:text-foreground",
2198
+ "size-7 rounded-chip border-0 bg-transparent p-0",
2199
+ "text-foreground-muted hover:bg-fill-medium active:bg-fill-medium",
2200
+ "data-popup-open:bg-fill-medium data-active:text-foreground",
2019
2201
  "outline-none focus-visible:shadow-focus",
2020
2202
  "[&_svg]:size-4"
2021
2203
  ]
@@ -2344,7 +2526,7 @@ const messageFooter = tv$1({
2344
2526
  "[&_svg]:shrink-0",
2345
2527
  "h-[22px] rounded-chip px-1.5",
2346
2528
  "text-caption font-semibold text-foreground-muted",
2347
- "bg-fill-muted hover:press-overlay active:press-overlay",
2529
+ "bg-fill-muted hover:overlay-medium active:overlay-medium",
2348
2530
  "outline-none focus-visible:shadow-focus",
2349
2531
  "[&_svg]:size-3.5 [&_svg]:text-foreground"
2350
2532
  ],
@@ -2358,7 +2540,7 @@ const messageFooter = tv$1({
2358
2540
  "transition-colors [&_svg]:shrink-0",
2359
2541
  "h-6 gap-1 rounded-chip border-0 px-2 shadow-none",
2360
2542
  "text-footnote font-bold text-foreground-muted",
2361
- "bg-fill-muted hover:press-overlay active:press-overlay",
2543
+ "bg-fill-muted hover:overlay-medium active:overlay-medium",
2362
2544
  "[&_svg]:size-3.5"
2363
2545
  ],
2364
2546
  badgeSeparator: ["text-foreground/45"]
@@ -2455,7 +2637,7 @@ const messageReaction = tv$1({ slots: {
2455
2637
  "inline-flex min-w-0 max-w-full items-center overflow-hidden whitespace-nowrap",
2456
2638
  "transition-colors",
2457
2639
  "h-6 gap-1 rounded-chip pr-2 pl-1.5 text-callout text-foreground",
2458
- "bg-fill-muted hover:press-overlay active:press-overlay",
2640
+ "bg-fill-muted hover:overlay-medium active:overlay-medium",
2459
2641
  "data-pressed:bg-attention-soft",
2460
2642
  "has-data-[slot=message-reaction-error-indicator]:bg-warning-soft",
2461
2643
  "outline-none focus-visible:shadow-focus",
@@ -2469,18 +2651,18 @@ const messageReaction = tv$1({ slots: {
2469
2651
  "transition-colors",
2470
2652
  "[&_svg]:shrink-0",
2471
2653
  "h-6 rounded-chip px-1.5 [&_svg]:size-4",
2472
- "bg-fill-muted text-foreground-muted hover:press-overlay active:press-overlay",
2654
+ "bg-fill-muted text-foreground-muted hover:overlay-medium active:overlay-medium",
2473
2655
  "outline-none focus-visible:shadow-focus"
2474
2656
  ],
2475
2657
  quickRow: [
2476
2658
  "flex shrink-0 items-center",
2477
- "justify-between gap-0.5 bg-layer-popover px-0.5 py-0.5",
2659
+ "justify-between gap-0.5 bg-layer-popover p-0",
2478
2660
  "[&>[role=menuitem]]:size-9 [&>[role=menuitem]]:p-0 *:[[role=menuitem]]:justify-center"
2479
2661
  ],
2480
2662
  quickButton: [
2481
2663
  "flex items-center justify-center",
2482
2664
  "bg-transparent transition-colors",
2483
- "size-9 rounded-control p-0 text-xl leading-none text-foreground-muted",
2665
+ "size-9 rounded-chip p-0 text-xl leading-none text-foreground-muted",
2484
2666
  "hover:bg-brand-soft data-highlighted:bg-brand-soft active:bg-brand-soft",
2485
2667
  "outline-none focus-visible:shadow-focus"
2486
2668
  ],
@@ -2688,7 +2870,7 @@ const chip = (fill) => [
2688
2870
  "[&_svg]:size-3.5 [&_svg]:text-foreground-muted",
2689
2871
  fill
2690
2872
  ];
2691
- const linkChip = (fill) => [...chip(fill), "text-foreground cursor-pointer hover:press-overlay active:press-overlay"];
2873
+ const linkChip = (fill) => [...chip(fill), "text-foreground cursor-pointer hover:overlay-medium active:overlay-medium"];
2692
2874
  const messageReference = tv$1({
2693
2875
  slots: {
2694
2876
  root: [
@@ -2710,7 +2892,7 @@ const messageReference = tv$1({
2710
2892
  "inline-flex cursor-pointer rounded-sticker px-[3px]",
2711
2893
  "font-semibold text-sticker-ink no-underline",
2712
2894
  "bg-brand inset-ring-[1.5px] inset-ring-sticker-ink ring-[1.5px] ring-sticker-edge",
2713
- "hover:press-overlay-sticker"
2895
+ "hover:overlay-sticker-medium active:overlay-sticker-medium"
2714
2896
  ] },
2715
2897
  secondary: { root: ["inline cursor-pointer font-bold text-foreground", "decoration-foreground decoration-[1.5px] underline-offset-[3px] hover:underline"] },
2716
2898
  accent: { root: linkChip("bg-attention-soft") },
@@ -2780,9 +2962,14 @@ const messageMultiSelect = tv$1({ slots: {
2780
2962
  ],
2781
2963
  toolbar: [
2782
2964
  "flex items-center",
2783
- "gap-2 rounded-container px-2.5 py-2",
2965
+ "gap-2 rounded-container py-1 pr-1 pl-2.5",
2966
+ "**:data-[slot=button]:h-7 **:data-[slot=button]:w-auto **:data-[slot=button]:min-w-7",
2967
+ "**:data-[slot=button]:rounded-chip",
2968
+ "**:data-[slot=button]:after:inset-x-[-3px] **:data-[slot=button]:first:after:left-[-9.5px] **:data-[slot=button]:last:after:right-[-9.5px]",
2969
+ "pointer-coarse:**:data-[slot=button]:after:inset-y-[-9.5px]",
2784
2970
  "bg-layer-popover ring-1 ring-line-seam shadow-float"
2785
- ]
2971
+ ],
2972
+ toolbarActions: ["flex min-w-0 flex-1 flex-wrap items-center justify-end", "gap-1"]
2786
2973
  } });
2787
2974
  //#endregion
2788
2975
  //#region src/components/message-item/message-multi-select.tsx
@@ -2807,6 +2994,17 @@ function MessageMultiSelectToolbar({ className, render, ...props }) {
2807
2994
  state: { slot: "message-multi-select-toolbar" }
2808
2995
  });
2809
2996
  }
2997
+ /** The toolbar's actions, at its end, 4px apart like every floating toolbar's buttons. */
2998
+ function MessageMultiSelectToolbarActions({ className, render, ...props }) {
2999
+ const { toolbarActions } = messageMultiSelect();
3000
+ const defaultProps = { className: toolbarActions({ className }) };
3001
+ return useRender({
3002
+ defaultTagName: "div",
3003
+ render,
3004
+ props: mergeProps(defaultProps, props),
3005
+ state: { slot: "message-multi-select-toolbar-actions" }
3006
+ });
3007
+ }
2810
3008
  function MessageMultiSelectCheckbox({ className, ...props }) {
2811
3009
  const { checkbox } = messageMultiSelect();
2812
3010
  return /* @__PURE__ */ jsx(Checkbox$1, {
@@ -2821,17 +3019,17 @@ function MessageMultiSelectCheckbox({ className, ...props }) {
2821
3019
  const messageTextSelectionToolbar = tv$1({ slots: {
2822
3020
  toolbar: [
2823
3021
  "flex min-w-0 items-center select-none",
2824
- "gap-0.5 overflow-visible rounded-container p-0.5 text-control font-bold",
3022
+ "gap-1 overflow-visible rounded-container p-1 text-control font-bold",
2825
3023
  "bg-layer-popover ring-1 ring-line-seam ring-inset shadow-float"
2826
3024
  ],
2827
3025
  button: [
2828
3026
  "flex shrink-0 items-center gap-1.5 outline-none transition-colors",
2829
- "h-7 rounded-control px-2.5 whitespace-nowrap text-foreground",
2830
- "hover:bg-fill-pressed active:bg-fill-pressed",
3027
+ "h-7 rounded-chip px-2.5 whitespace-nowrap text-foreground",
3028
+ "hover:bg-fill-medium active:bg-fill-medium",
2831
3029
  "focus-visible:shadow-focus",
2832
3030
  "[&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-foreground-muted"
2833
3031
  ],
2834
- separator: ["w-px shrink-0", "mx-0.5 h-5 bg-line-hairline"]
3032
+ separator: ["w-px shrink-0", "h-5 bg-line-hairline"]
2835
3033
  } });
2836
3034
  //#endregion
2837
3035
  //#region src/components/message-item/message-text-selection-toolbar.tsx
@@ -3091,10 +3289,15 @@ const messageList = tv$1({
3091
3289
  root: ["relative h-full min-h-0"],
3092
3290
  viewport: ["min-w-0 overscroll-none"],
3093
3291
  content: ["flex min-h-full w-full min-w-0 flex-col"],
3094
- dateDividerRoot: ["flex select-none items-center", "gap-2 px-4 py-3"],
3292
+ dateDividerRoot: [
3293
+ "flex select-none items-center",
3294
+ "gap-2 px-4",
3295
+ "pt-[calc(var(--spacing-timeline-section)-var(--spacing-timeline-row)-var(--text-mono-meta--line-height)/2)]",
3296
+ "pb-[calc(var(--spacing-timeline-section)-var(--spacing-timeline-lead)-var(--text-mono-meta--line-height)/2)]"
3297
+ ],
3095
3298
  dateDividerRule: ["flex-1", "min-w-3 border-t border-line-hairline"],
3096
3299
  dateDividerChip: ["inline-flex items-center", "font-mono text-mono-meta whitespace-nowrap text-foreground-hint"],
3097
- notice: ["text-center", "pb-2 font-mono text-mono-meta"],
3300
+ notice: ["text-center", "pt-timeline-lead pb-timeline-row font-mono text-mono-meta"],
3098
3301
  historyLimited: [
3099
3302
  "inline-flex items-center",
3100
3303
  "h-[22px] gap-1 rounded-chip px-1.5",
@@ -3383,4 +3586,4 @@ function useMouseOnlyPointerSensor(distance) {
3383
3586
  return useSensor(MouseOnlyPointerSensor, options);
3384
3587
  }
3385
3588
  //#endregion
3386
- export { MessageReactionTooltipMeta as $, ThemeStateContext as $n, DropdownMenuRadioItem as $t, messageEmbed as A, Badge as An, MessageItemContinuationTime as At, MessageReferencePending as B, DialogPortal as Bn, useOverflowTitle as Bt, MessageQuotedPreviewThread as C, CheckboxIndicator as Cn, MessageItemBody as Ct, MessageEmbedContent as D, TooltipPortal as Dn, MessageItemFooter as Dt, MessageEmbed as E, TooltipContent as En, MessageItemEmbedded as Et, MessageMultiSelectCheckbox as F, DialogDescription as Fn, AvatarBadge as Ft, MessageReactionCount as G, buttonVariants as Gn, DropdownMenuFooter as Gt, MessageReferenceUnavailable as H, DialogTitle as Hn, DropdownMenuCheckboxItem as Ht, MessageMultiSelectToolbar as I, DialogFooter as In, AvatarFallback as It, MessageReactionPickerContent as J, useParentOverlayKind as Jn, DropdownMenuItemLabel as Jt, MessageReactionErrorIndicator as K, Spinner as Kn, DropdownMenuItem as Kt, MessageReferenceChip as L, DialogHeader as Ln, AvatarGroup as Lt, MessageTextSelectionToolbarButton as M, DialogBody as Mn, MessageItem as Mt, MessageTextSelectionToolbarSeparator as N, DialogClose as Nn, searchHit as Nt, MessageEmbedFooter as O, TooltipProvider as On, MessageItemSearchMatch as Ot, MessageMultiSelect as P, DialogContent as Pn, Avatar$1 as Pt, MessageReactionTooltipContent as Q, useTheme as Qn, DropdownMenuRadioGroup as Qt, MessageReferenceIndicator as R, DialogNav as Rn, AvatarGroupCount as Rt, MessageQuotedPreviewText as S, Checkbox$1 as Sn, MessageItemAttachments as St, MessageQuotedPreviewUnavailable as T, Tooltip$1 as Tn, MessageItemEdited as Tt, MessageReactionAddButton as U, DialogTrigger as Un, DropdownMenuCheckboxItemIndicator as Ut, MessageReferenceText as V, DialogSurface as Vn, DropdownMenu as Vt, MessageReactionChip as W, Button$1 as Wn, DropdownMenuContent as Wt, MessageReactionQuickButton as X, resolveThemeScopeProps as Xn, DropdownMenuPopup as Xt, MessageReactionPickerStatic as Y, withOverlayLayer as Yn, DropdownMenuLabel as Yt, MessageReactionQuickRow as Z, useThemeScopeProps as Zn, DropdownMenuPortal as Zt, MessageQuotedPreviewAuthorName as _, ScrollAreaCorner as _n, MessageItemSender as _t, MessageListJumpPillDismiss as a, DropdownMenuTrigger as an, MessageItemBadgeSeparator as at, MessageQuotedPreviewHeader as b, ScrollAreaViewport as bn, MessageItemSenderGroup as bt, MessageListHistoryLimited as c, Panel as cn, MessageItemToolbar as ct, MessageQuotedPreview as d, PanelHeaderRoot as dn, MessageItemDelegatedBy as dt, DropdownMenuRadioItemIndicator as en, tv$1 as er, MessageReactionTooltipName as et, MessageQuotedPreviewAttachment as f, PanelScrollContent as fn, MessageItemDelegatedByButton as ft, MessageQuotedPreviewAuthorMeta as g, ScrollAreaContent as gn, MessageItemMeta as gt, MessageQuotedPreviewAuthorDelegatedBy as h, ScrollArea$1 as hn, MessageItemInlineStatus as ht, MessageListJumpPill as i, DropdownMenuSubmenuTrigger as in, MessageItemBadge as it, MessageTextSelectionToolbar as j, Dialog$1 as jn, MessageItemGutter as jt, MessageEmbedHeader as k, TooltipTrigger as kn, MessageItemAvatarSlot as kt, MessageListNotice as l, PanelBody as ln, MessageItemToolbarButton as lt, MessageQuotedPreviewAuthor as m, PanelSection as mn, MessageItemHeader as mt, useMouseOnlyPointerSensor as n, DropdownMenuShortcut as nn, headEdgePull as nr, MessageReactionTooltipNames as nt, MessageListJumpPillGroup as o, Kbd as on, MessageItemReadReceipt as ot, MessageQuotedPreviewAttachments as p, PanelScrollViewport as pn, MessageItemDelegatedByName as pt, MessageReactionGlyph as q, defaultNativeButton as qn, DropdownMenuItemCount as qt, MessageListJumpControls as r, DropdownMenuSubmenu as rn, headEdges as rr, MessageReactionTooltipSeparator as rt, MessageListDateDivider as s, KbdGroup as sn, MessageItemSavedIndicator as st, useHoldThenMoveTouchSensor as t, DropdownMenuSeparator as tn, controlIconInset as tr, MessageReactionTooltipNameText as tt, MessageList as u, PanelFooter as un, MessageItemDelegatedAvatar as ut, MessageQuotedPreviewChannel as v, ScrollAreaScrollbar as vn, MessageItemSenderBadges as vt, MessageQuotedPreviewTimestamp as w, PRESENCE_COLOR as wn, MessageItemContent as wt, MessageQuotedPreviewLoading as x, useMobileViewport as xn, MessageItemTime as xt, MessageQuotedPreviewContent as y, ScrollAreaThumb as yn, MessageItemSenderButton as yt, MessageReferenceLabel as z, DialogOverlay as zn, AvatarImage as zt };
3589
+ export { MessageReactionTooltipContent as $, Spinner as $n, DropdownMenuItemLabel as $t, messageEmbed as A, Tooltip$1 as An, MessageItemAvatarSlot as At, MessageReferenceLabel as B, DialogClose as Bn, AvatarImage as Bt, MessageQuotedPreviewThread as C, ScrollAreaScrollbar as Cn, MessageItemAttachments as Ct, MessageEmbedContent as D, Checkbox$1 as Dn, MessageItemEmbedded as Dt, MessageEmbed as E, useMobileViewport as En, MessageItemEdited as Et, MessageMultiSelectCheckbox as F, TextLink as Fn, Avatar$1 as Ft, MessageReactionChip as G, DialogNav as Gn, readNow as Gt, MessageReferenceText as H, DialogDescription as Hn, measureContent as Ht, MessageMultiSelectToolbar as I, textLinkVariants as In, AvatarBadge as It, MessageReactionGlyph as J, DialogSurface as Jn, DropdownMenuCheckboxItemIndicator as Jt, MessageReactionCount as K, DialogOverlay as Kn, DropdownMenu as Kt, MessageMultiSelectToolbarActions as L, Badge as Ln, AvatarFallback as Lt, MessageTextSelectionToolbarButton as M, TooltipPortal as Mn, MessageItemGutter as Mt, MessageTextSelectionToolbarSeparator as N, TooltipProvider as Nn, MessageItem as Nt, MessageEmbedFooter as O, CheckboxIndicator as On, MessageItemFooter as Ot, MessageMultiSelect as P, TooltipTrigger as Pn, searchHit as Pt, MessageReactionQuickRow as Q, buttonVariants as Qn, DropdownMenuItemCount as Qt, MessageReferenceChip as R, Dialog$1 as Rn, AvatarGroup as Rt, MessageQuotedPreviewText as S, ScrollAreaCorner as Sn, MessageItemTime as St, MessageQuotedPreviewUnavailable as T, ScrollAreaViewport as Tn, MessageItemContent as Tt, MessageReferenceUnavailable as U, DialogFooter as Un, measureElement as Ut, MessageReferencePending as V, DialogContent as Vn, useOverflowTitle as Vt, MessageReactionAddButton as W, DialogHeader as Wn, observeTruncation as Wt, MessageReactionPickerStatic as X, DialogTrigger as Xn, DropdownMenuFooter as Xt, MessageReactionPickerContent as Y, DialogTitle as Yn, DropdownMenuContent as Yt, MessageReactionQuickButton as Z, Button$1 as Zn, DropdownMenuItem as Zt, MessageQuotedPreviewAuthorName as _, PanelScrollContent as _n, MessageItemMeta as _t, MessageListJumpPillDismiss as a, DropdownMenuRadioItemIndicator as an, useTheme as ar, MessageItemBadge as at, MessageQuotedPreviewHeader as b, ScrollArea$1 as bn, MessageItemSenderButton as bt, MessageListHistoryLimited as c, DropdownMenuSubmenu as cn, controlIconInset as cr, MessageItemSavedIndicator as ct, MessageQuotedPreview as d, Kbd as dn, decisionWidth as dr, MessageItemDelegatedAvatar as dt, DropdownMenuLabel as en, defaultNativeButton as er, MessageReactionTooltipMeta as et, MessageQuotedPreviewAttachment as f, KbdGroup as fn, MessageItemDelegatedBy as ft, MessageQuotedPreviewAuthorMeta as g, PanelHeaderRoot as gn, MessageItemInlineStatus as gt, MessageQuotedPreviewAuthorDelegatedBy as h, PanelFooter as hn, MessageItemHeader as ht, MessageListJumpPill as i, DropdownMenuRadioItem as in, useThemeScopeProps as ir, MessageReactionTooltipSeparator as it, MessageTextSelectionToolbar as j, TooltipContent as jn, MessageItemContinuationTime as jt, MessageEmbedHeader as k, PRESENCE_COLOR as kn, MessageItemSearchMatch as kt, MessageListNotice as l, DropdownMenuSubmenuTrigger as ln, headEdgePull as lr, MessageItemToolbar as lt, MessageQuotedPreviewAuthor as m, PanelBody as mn, MessageItemDelegatedByName as mt, useMouseOnlyPointerSensor as n, DropdownMenuPortal as nn, withOverlayLayer as nr, MessageReactionTooltipNameText as nt, MessageListJumpPillGroup as o, DropdownMenuSeparator as on, ThemeStateContext as or, MessageItemBadgeSeparator as ot, MessageQuotedPreviewAttachments as p, Panel as pn, MessageItemDelegatedByButton as pt, MessageReactionErrorIndicator as q, DialogPortal as qn, DropdownMenuCheckboxItem as qt, MessageListJumpControls as r, DropdownMenuRadioGroup as rn, resolveThemeScopeProps as rr, MessageReactionTooltipNames as rt, MessageListDateDivider as s, DropdownMenuShortcut as sn, tv$1 as sr, MessageItemReadReceipt as st, useHoldThenMoveTouchSensor as t, DropdownMenuPopup as tn, useParentOverlayKind as tr, MessageReactionTooltipName as tt, MessageList as u, DropdownMenuTrigger as un, headEdges as ur, MessageItemToolbarButton as ut, MessageQuotedPreviewChannel as v, PanelScrollViewport as vn, MessageItemSender as vt, MessageQuotedPreviewTimestamp as w, ScrollAreaThumb as wn, MessageItemBody as wt, MessageQuotedPreviewLoading as x, ScrollAreaContent as xn, MessageItemSenderGroup as xt, MessageQuotedPreviewContent as y, PanelSection as yn, MessageItemSenderBadges as yt, MessageReferenceIndicator as z, DialogBody as zn, AvatarGroupCount as zt };