@botiverse/raft-ui 0.59.1 → 0.60.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/components/button/button.mjs +1 -1
  3. package/dist/components/composer/composer-attachment.recipe.mjs +2 -3
  4. package/dist/components/composer/composer-attachments-scroll-area.d.mts +6 -0
  5. package/dist/components/composer/composer-attachments-scroll-area.mjs +20 -31
  6. package/dist/components/composer/composer.d.mts +8 -2
  7. package/dist/components/composer/composer.mjs +7 -9
  8. package/dist/components/composer/composer.recipe.mjs +1 -0
  9. package/dist/components/context-menu/context-menu.d.mts +1 -1
  10. package/dist/components/dropdown-menu/dropdown-menu.d.mts +1 -1
  11. package/dist/components/dropdown-menu/dropdown-menu.mjs +1 -1
  12. package/dist/components/kbd/index.d.mts +5 -2
  13. package/dist/components/kbd/kbd-keys.d.mts +12 -0
  14. package/dist/components/kbd/kbd-keys.mjs +297 -0
  15. package/dist/components/kbd/kbd-shortcut.d.mts +34 -0
  16. package/dist/components/kbd/kbd-shortcut.mjs +79 -0
  17. package/dist/components/kbd/kbd.d.mts +55 -2
  18. package/dist/components/kbd/kbd.mjs +39 -15
  19. package/dist/components/markdown/markdown-parts.d.mts +7 -2
  20. package/dist/components/markdown/markdown-parts.mjs +8 -3
  21. package/dist/components/markdown/markdown.recipe.mjs +1 -5
  22. package/dist/components/message-list/message-list.mjs +9 -15
  23. package/dist/components/message-list/message-list.recipe.mjs +1 -1
  24. package/dist/components/scroll-area/class-names.mjs +19 -0
  25. package/dist/components/scroll-area/gutters-binding.mjs +4 -0
  26. package/dist/components/scroll-area/index.d.mts +6 -2
  27. package/dist/components/scroll-area/scroll-area-gutters.d.mts +15 -0
  28. package/dist/components/scroll-area/scroll-area-gutters.mjs +60 -0
  29. package/dist/components/scroll-area/scroll-area-textarea.d.mts +14 -0
  30. package/dist/components/scroll-area/scroll-area-textarea.mjs +50 -0
  31. package/dist/components/scroll-area/scroll-area.css +720 -0
  32. package/dist/components/scroll-area/scroll-area.d.mts +24 -15
  33. package/dist/components/scroll-area/scroll-area.mjs +67 -45
  34. package/dist/components/scroll-area/scroll-geometry.mjs +58 -0
  35. package/dist/components/scroll-area/scroll-to-element.mjs +67 -0
  36. package/dist/components/scroll-area/types.d.mts +224 -0
  37. package/dist/components/scroll-area/use-rail-pointer.mjs +93 -0
  38. package/dist/components/scroll-area/use-scroll-area-container.d.mts +26 -0
  39. package/dist/components/scroll-area/use-scroll-area-container.mjs +150 -0
  40. package/dist/components/scroll-area/use-scrollbars.mjs +480 -0
  41. package/dist/components/search/search-trigger.d.mts +1 -1
  42. package/dist/components/sidebar/sidebar.d.mts +1 -1
  43. package/dist/components/sidebar/sidebar.mjs +24 -20
  44. package/dist/components/sidebar/sidebar.recipe.mjs +1 -6
  45. package/dist/components/tooltip/tooltip.mjs +8 -5
  46. package/dist/components/virtual-list/VirtualList.mjs +1 -1
  47. package/dist/index.d.mts +7 -3
  48. package/dist/index.mjs +5 -2
  49. package/dist/lib/inline-part.mjs +13 -0
  50. package/dist/lib/use-merged-ref.mjs +73 -47
  51. package/dist/lib/use-platform.d.mts +13 -0
  52. package/dist/lib/use-platform.mjs +29 -0
  53. package/dist/styles.css +1 -0
  54. package/dist/wip.d.mts +5 -1
  55. package/dist/wip.mjs +3 -1
  56. package/package.json +1 -1
  57. package/dist/components/scroll-area/scroll-area.recipe.mjs +0 -23
@@ -0,0 +1,79 @@
1
+ import { tv } from "../../lib/tv.mjs";
2
+ import { markInlinePart } from "../../lib/inline-part.mjs";
3
+ import { Kbd, KbdGroup } from "./kbd.mjs";
4
+ import { useKeyboardPlatform } from "../../lib/use-platform.mjs";
5
+ import { resolveKbdKeys } from "./kbd-keys.mjs";
6
+ import { ArrowBigUp, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ChevronUp, Command, CornerDownLeft, Delete, Option } from "lucide-react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/kbd/kbd-shortcut.tsx
9
+ const ICONS = {
10
+ "chevron-up": ChevronUp,
11
+ option: Option,
12
+ "arrow-big-up": ArrowBigUp,
13
+ command: Command,
14
+ "corner-down-left": CornerDownLeft,
15
+ delete: Delete,
16
+ "arrow-up": ArrowUp,
17
+ "arrow-down": ArrowDown,
18
+ "arrow-left": ArrowLeft,
19
+ "arrow-right": ArrowRight
20
+ };
21
+ const kbdShortcut = tv({
22
+ slots: {
23
+ root: ["inline-flex shrink-0 items-center"],
24
+ cap: ["data-[glyph=icon]:px-0"],
25
+ text: ["block leading-none [text-box:trim-both_cap_alphabetic]"],
26
+ icon: ["block shrink-0"],
27
+ label: ["sr-only"]
28
+ },
29
+ variants: { size: {
30
+ sm: { cap: ["h-4"] },
31
+ md: {}
32
+ } },
33
+ defaultVariants: { size: "sm" }
34
+ });
35
+ /**
36
+ * One shortcut from key names: a cap per key, with the platform's drawings
37
+ * (icons on a Mac, words elsewhere), and the shortcut in words for a screen
38
+ * reader. Alternatives ("⌘↑ / ⌘↓") are two KbdShortcut with a separator
39
+ * between them, written by the caller.
40
+ */
41
+ function KbdShortcut({ keys, size = "sm", platform: platformProp, label, className, ...props }) {
42
+ const detected = useKeyboardPlatform();
43
+ const platform = platformProp ?? detected;
44
+ const resolved = resolveKbdKeys(keys, platform);
45
+ const slots = kbdShortcut({ size });
46
+ return /* @__PURE__ */ jsxs("span", {
47
+ "data-slot": "kbd-shortcut",
48
+ "data-platform": platform,
49
+ className: slots.root({ className }),
50
+ ...props,
51
+ children: [/* @__PURE__ */ jsx(KbdGroup, {
52
+ "aria-hidden": "true",
53
+ children: resolved.map((key, index) => {
54
+ const Icon = key.icon ? ICONS[key.icon] : void 0;
55
+ return /* @__PURE__ */ jsx(Kbd, {
56
+ size,
57
+ "data-glyph": Icon ? "icon" : "text",
58
+ className: slots.cap(),
59
+ children: Icon ? /* @__PURE__ */ jsx(Icon, {
60
+ "data-slot": "kbd-icon",
61
+ className: slots.icon(),
62
+ "aria-hidden": "true"
63
+ }) : /* @__PURE__ */ jsx("span", {
64
+ "data-slot": "kbd-text",
65
+ className: slots.text(),
66
+ children: key.text
67
+ })
68
+ }, `${index}-${key.name}`);
69
+ })
70
+ }), /* @__PURE__ */ jsx("span", {
71
+ "data-slot": "kbd-shortcut-label",
72
+ className: slots.label(),
73
+ children: label ?? resolved.map((key) => key.label).join(" ")
74
+ })]
75
+ });
76
+ }
77
+ markInlinePart(KbdShortcut);
78
+ //#endregion
79
+ export { KbdShortcut };
@@ -1,7 +1,60 @@
1
+ import { VariantProps } from "../../lib/tv.mjs";
1
2
  import { ComponentPropsWithRef } from "react";
2
3
  //#region src/components/kbd/kbd.d.ts
3
- export type KbdProps = ComponentPropsWithRef<"kbd">;
4
- export declare function Kbd({ className, ...props }: KbdProps): import("react").JSX.Element;
4
+ declare const kbd: import("tailwind-variants/lite").TVReturnType<{
5
+ size: {
6
+ sm: {
7
+ root: string[];
8
+ };
9
+ md: {
10
+ root: string[];
11
+ };
12
+ };
13
+ }, {
14
+ root: string[];
15
+ group: string[];
16
+ }, undefined, {
17
+ size: {
18
+ sm: {
19
+ root: string[];
20
+ };
21
+ md: {
22
+ root: string[];
23
+ };
24
+ };
25
+ }, {
26
+ root: string[];
27
+ group: string[];
28
+ }, import("tailwind-variants/lite").TVReturnTypeLike<{
29
+ size: {
30
+ sm: {
31
+ root: string[];
32
+ };
33
+ md: {
34
+ root: string[];
35
+ };
36
+ };
37
+ }, {
38
+ root: string[];
39
+ group: string[];
40
+ }>>;
41
+ export type KbdSize = NonNullable<VariantProps<typeof kbd>["size"]>;
42
+ export type KbdProps = ComponentPropsWithRef<"kbd"> & {
43
+ /**
44
+ * `sm` (the default) is a hint beside something else: a menu item, a
45
+ * tooltip, the search trigger, an input. `md` is a key that is the content,
46
+ * in a list of shortcuts.
47
+ */
48
+ size?: KbdSize;
49
+ };
50
+ /**
51
+ * One keyboard key in a cap, a native `kbd`: at `sm`, the default, a hint
52
+ * beside a menu item, a tooltip's text or a field; at `md`, a key that is the
53
+ * content, as in a list of shortcuts. One key per cap: write a shortcut as a
54
+ * KbdGroup of Kbd, or from key names with KbdShortcut.
55
+ */
56
+ export declare function Kbd({ className, size, ...props }: KbdProps): import("react").JSX.Element;
5
57
  export type KbdGroupProps = ComponentPropsWithRef<"span">;
58
+ /** Caps of one shortcut, 4px apart. */
6
59
  export declare function KbdGroup({ className, ...props }: KbdGroupProps): import("react").JSX.Element;
7
60
  //#endregion
@@ -1,27 +1,49 @@
1
1
  import { tv } from "../../lib/tv.mjs";
2
+ import { markInlinePart } from "../../lib/inline-part.mjs";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  //#region src/components/kbd/kbd.tsx
4
- const kbd = tv({ slots: {
5
- root: [
6
- "pointer-events-none inline-flex w-fit shrink-0 items-center justify-center gap-1",
7
- "whitespace-nowrap select-none",
8
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-3",
9
- "min-w-4 rounded-[3px] px-1",
10
- "font-mono text-mono-meta font-normal text-foreground-hint",
11
- "inset-ring inset-ring-line-hairline",
12
- "in-data-[slot=tooltip-content]:text-foreground-on-hud/70",
13
- "in-data-[slot=tooltip-content]:shadow-[inset_0_0_0_1px_color-mix(in_oklch,var(--foreground-on-hud)_70%,transparent)]"
14
- ],
15
- group: ["inline-flex items-center gap-1"]
16
- } });
17
- function Kbd({ className, ...props }) {
18
- const { root } = kbd();
5
+ const kbd = tv({
6
+ slots: {
7
+ root: [
8
+ "pointer-events-none inline-flex w-fit shrink-0 items-center justify-center gap-1",
9
+ "whitespace-nowrap select-none [&_svg]:pointer-events-none",
10
+ "font-mono font-normal",
11
+ "inset-ring inset-ring-line-hairline"
12
+ ],
13
+ group: ["inline-flex items-center gap-1"]
14
+ },
15
+ variants: { size: {
16
+ sm: { root: [
17
+ "[&_svg:not([class*='size-'])]:size-3",
18
+ "min-w-4 rounded-[3px] px-1",
19
+ "text-mono-meta text-foreground-hint",
20
+ "in-data-[slot=tooltip-content]:text-foreground-on-hud/70",
21
+ "in-data-[slot=tooltip-content]:shadow-[inset_0_0_0_1px_color-mix(in_oklch,var(--foreground-on-hud)_70%,transparent)]"
22
+ ] },
23
+ md: { root: [
24
+ "[&_svg:not([class*='size-'])]:size-3.5",
25
+ "h-6 min-w-6 rounded-sticker px-1.5",
26
+ "text-mono-code text-foreground-muted",
27
+ "bg-fill-muted"
28
+ ] }
29
+ } },
30
+ defaultVariants: { size: "sm" }
31
+ });
32
+ /**
33
+ * One keyboard key in a cap, a native `kbd`: at `sm`, the default, a hint
34
+ * beside a menu item, a tooltip's text or a field; at `md`, a key that is the
35
+ * content, as in a list of shortcuts. One key per cap: write a shortcut as a
36
+ * KbdGroup of Kbd, or from key names with KbdShortcut.
37
+ */
38
+ function Kbd({ className, size = "sm", ...props }) {
39
+ const { root } = kbd({ size });
19
40
  return /* @__PURE__ */ jsx("kbd", {
20
41
  "data-slot": "kbd",
21
42
  className: root({ className }),
22
43
  ...props
23
44
  });
24
45
  }
46
+ /** Caps of one shortcut, 4px apart. */
25
47
  function KbdGroup({ className, ...props }) {
26
48
  const { group } = kbd();
27
49
  return /* @__PURE__ */ jsx("span", {
@@ -30,5 +52,7 @@ function KbdGroup({ className, ...props }) {
30
52
  ...props
31
53
  });
32
54
  }
55
+ markInlinePart(Kbd);
56
+ markInlinePart(KbdGroup);
33
57
  //#endregion
34
58
  export { Kbd, KbdGroup };
@@ -2,6 +2,7 @@ import { CheckboxProps } from "../checkbox/checkbox.mjs";
2
2
  import "../checkbox/index.mjs";
3
3
  import { InlineCodeProps } from "../inline-code/inline-code.mjs";
4
4
  import "../inline-code/index.mjs";
5
+ import { ScrollAreaProps } from "../scroll-area/types.mjs";
5
6
  import { ComponentPropsWithRef } from "react";
6
7
  //#region src/components/markdown/markdown-parts.d.ts
7
8
  declare const HEADING_TAGS: {
@@ -33,8 +34,12 @@ export type MarkdownBlockquoteProps = ComponentPropsWithRef<"blockquote">;
33
34
  export declare function MarkdownBlockquote({ className, ...props }: MarkdownBlockquoteProps): import("react").JSX.Element;
34
35
  export type MarkdownRuleProps = ComponentPropsWithRef<"hr">;
35
36
  export declare function MarkdownRule({ className, ...props }: MarkdownRuleProps): import("react").JSX.Element;
36
- export type MarkdownTableScrollProps = ComponentPropsWithRef<"div">;
37
- /** Horizontal scroll container for wide tables. */
37
+ /** ScrollArea's props but `orientation`: the table scrolls sideways only. */
38
+ export type MarkdownTableScrollProps = Omit<ScrollAreaProps, "orientation">;
39
+ /**
40
+ * Horizontal ScrollArea for a wide table, with its thin overlay scrollbar. It only overflows
41
+ * sideways, so it never holds back the page's vertical scroll.
42
+ */
38
43
  export declare function MarkdownTableScroll({ className, ...props }: MarkdownTableScrollProps): import("react").JSX.Element;
39
44
  export type MarkdownTableProps = ComponentPropsWithRef<"table">;
40
45
  export declare function MarkdownTable({ className, ...props }: MarkdownTableProps): import("react").JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import { Checkbox } from "../checkbox/checkbox.mjs";
2
+ import { ScrollArea } from "../scroll-area/scroll-area.mjs";
2
3
  import { InlineCode } from "../inline-code/inline-code.mjs";
3
4
  import { markdown } from "./markdown.recipe.mjs";
4
5
  import { jsx } from "react/jsx-runtime";
@@ -84,13 +85,17 @@ function MarkdownRule({ className, ...props }) {
84
85
  ...props
85
86
  });
86
87
  }
87
- /** Horizontal scroll container for wide tables. */
88
+ /**
89
+ * Horizontal ScrollArea for a wide table, with its thin overlay scrollbar. It only overflows
90
+ * sideways, so it never holds back the page's vertical scroll.
91
+ */
88
92
  function MarkdownTableScroll({ className, ...props }) {
89
93
  const { tableScroll } = markdown();
90
- return /* @__PURE__ */ jsx("div", {
94
+ return /* @__PURE__ */ jsx(ScrollArea, {
91
95
  "data-slot": "markdown-table-scroll",
96
+ ...props,
92
97
  className: tableScroll({ className }),
93
- ...props
98
+ orientation: "horizontal"
94
99
  });
95
100
  }
96
101
  function MarkdownTable({ className, ...props }) {
@@ -17,11 +17,7 @@ const markdown = tv({
17
17
  listItem: ["mb-0.5"],
18
18
  blockquote: ["my-1 border-l-2 border-line-seam pl-2.5", "text-foreground-muted not-italic"],
19
19
  rule: ["my-3 border-0 border-t border-line-hairline"],
20
- tableScroll: [
21
- "overflow-x-auto",
22
- "my-2 w-fit max-w-full",
23
- "rounded-container border border-line-hairline bg-layer-card"
24
- ],
20
+ tableScroll: ["my-2 w-fit max-w-full", "rounded-container border border-line-hairline bg-layer-card"],
25
21
  table: ["border-collapse", "border-0 text-callout"],
26
22
  tableRow: ["last:[&>td]:border-b-0"],
27
23
  headerCell: [
@@ -1,11 +1,10 @@
1
1
  import { useMobileViewport } from "../../lib/use-mobile-viewport.mjs";
2
- import { ScrollArea, ScrollAreaContent, ScrollAreaScrollbar, ScrollAreaThumb, ScrollAreaViewport } from "../scroll-area/scroll-area.mjs";
2
+ import { ScrollArea } from "../scroll-area/scroll-area.mjs";
3
3
  import { PanelScrollViewport } from "../panel/panel.mjs";
4
4
  import { messageList } from "./message-list.recipe.mjs";
5
5
  import { useMemo } from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { jsx } from "react/jsx-runtime";
7
7
  //#region src/components/message-list/message-list.tsx
8
- const contentStyle = { minWidth: 0 };
9
8
  function MessageList({ children, className, render, rootClassName, style, ...props }) {
10
9
  const isMobile = useMobileViewport();
11
10
  const { content, root, viewport } = messageList();
@@ -28,24 +27,19 @@ function MessageList({ children, className, render, rootClassName, style, ...pro
28
27
  })
29
28
  })
30
29
  });
31
- return /* @__PURE__ */ jsxs(ScrollArea, {
30
+ return /* @__PURE__ */ jsx("div", {
32
31
  "data-slot": "message-list",
33
32
  className: root({ className: rootClassName }),
34
- children: [/* @__PURE__ */ jsx(ScrollAreaViewport, {
33
+ children: /* @__PURE__ */ jsx(ScrollArea, {
35
34
  ...props,
36
35
  render,
37
36
  "data-slot": "message-list-viewport",
37
+ trigger: "scroll",
38
38
  className: viewport({ className }),
39
- style: viewportStyle,
40
- children: /* @__PURE__ */ jsx(ScrollAreaContent, {
41
- className: content(),
42
- style: contentStyle,
43
- children
44
- })
45
- }), /* @__PURE__ */ jsx(ScrollAreaScrollbar, {
46
- className: "me-1.5 px-0 py-1",
47
- children: /* @__PURE__ */ jsx(ScrollAreaThumb, {})
48
- })]
39
+ contentClassName: content(),
40
+ style,
41
+ children
42
+ })
49
43
  });
50
44
  }
51
45
  //#endregion
@@ -3,7 +3,7 @@ import { tv } from "../../lib/tv.mjs";
3
3
  const messageList = tv({
4
4
  slots: {
5
5
  root: ["relative h-full min-h-0"],
6
- viewport: ["min-w-0 overscroll-none"],
6
+ viewport: ["size-full min-h-0 min-w-0 overscroll-none"],
7
7
  content: ["flex min-h-full w-full min-w-0 flex-col"],
8
8
  dateDividerRoot: [
9
9
  "flex select-none items-center",
@@ -0,0 +1,19 @@
1
+ import { clsx } from "cnfast";
2
+ //#region src/components/scroll-area/class-names.ts
3
+ /**
4
+ * The root's rendered modifier classes, shared by every ScrollArea root.
5
+ * `--{none,contain}-overscroll-{y,x}` is on only for an axis that has a
6
+ * gutter, i.e. really scrolls right now, so an area that only overflows
7
+ * sideways never holds back the page's vertical scroll; the container takes
8
+ * them (scroll-area.css).
9
+ *
10
+ * The classes that change while scrolling (`--scrolling`, `--dragging`,
11
+ * `--rtl`, `--overflow-{y,x}-{start,end}`) are not rendered: `useScrollbars`
12
+ * sets them on the element, so scrolling never renders.
13
+ */
14
+ function scrollAreaClassNames(state) {
15
+ const { rails } = state;
16
+ return clsx("r-scroll-area", `r-scroll-area--${state.size}`, `r-scroll-area--${state.trigger}-trigger`, `r-scroll-area--${state.orientation}-orientation`, `r-scroll-area--${state.guttersPosition}-gutters`, state.overscroll !== "auto" && rails.yRail && `r-scroll-area--${state.overscroll}-overscroll-y`, state.overscroll !== "auto" && rails.xRail && `r-scroll-area--${state.overscroll}-overscroll-x`, state.fade && "r-scroll-area--fade");
17
+ }
18
+ //#endregion
19
+ export { scrollAreaClassNames };
@@ -0,0 +1,4 @@
1
+ //#region src/components/scroll-area/gutters-binding.ts
2
+ const fromGuttersBinding = (binding) => binding;
3
+ //#endregion
4
+ export { fromGuttersBinding };
@@ -1,2 +1,6 @@
1
- import { ScrollArea, ScrollAreaContent, ScrollAreaContentProps, ScrollAreaCorner, ScrollAreaCornerProps, ScrollAreaProps, ScrollAreaScrollbar, ScrollAreaScrollbarProps, ScrollAreaThumb, ScrollAreaThumbProps, ScrollAreaViewport, ScrollAreaViewportProps } from "./scroll-area.mjs";
2
- export { ScrollArea, ScrollAreaContent, type ScrollAreaContentProps, ScrollAreaCorner, type ScrollAreaCornerProps, type ScrollAreaProps, ScrollAreaScrollbar, type ScrollAreaScrollbarProps, ScrollAreaThumb, type ScrollAreaThumbProps, ScrollAreaViewport, type ScrollAreaViewportProps };
1
+ import { ScrollAreaActions, ScrollAreaContainer, ScrollAreaContainerOptions, ScrollAreaContainerProps, ScrollAreaContentProps, ScrollAreaEdges, ScrollAreaFrameProps, ScrollAreaGuttersBinding, ScrollAreaGuttersPosition, ScrollAreaGuttersProps, ScrollAreaOptions, ScrollAreaOrientation, ScrollAreaOverscroll, ScrollAreaOwnProps, ScrollAreaProps, ScrollAreaRailInset, ScrollAreaScrollToElementOptions, ScrollAreaSize, ScrollAreaTextareaOwnProps, ScrollAreaTextareaProps, ScrollAreaTrigger } from "./types.mjs";
2
+ import { ScrollArea, ScrollAreaContent } from "./scroll-area.mjs";
3
+ import { ScrollAreaGutters } from "./scroll-area-gutters.mjs";
4
+ import { ScrollAreaTextarea } from "./scroll-area-textarea.mjs";
5
+ import { useScrollAreaContainer } from "./use-scroll-area-container.mjs";
6
+ export { ScrollArea, type ScrollAreaActions, type ScrollAreaContainer, type ScrollAreaContainerOptions, type ScrollAreaContainerProps, ScrollAreaContent, type ScrollAreaContentProps, type ScrollAreaEdges, type ScrollAreaFrameProps, ScrollAreaGutters, type ScrollAreaGuttersBinding, type ScrollAreaGuttersPosition, type ScrollAreaGuttersProps, type ScrollAreaOptions, type ScrollAreaOrientation, type ScrollAreaOverscroll, type ScrollAreaOwnProps, type ScrollAreaProps, type ScrollAreaRailInset, type ScrollAreaScrollToElementOptions, type ScrollAreaSize, ScrollAreaTextarea, type ScrollAreaTextareaOwnProps, type ScrollAreaTextareaProps, type ScrollAreaTrigger, useScrollAreaContainer };
@@ -0,0 +1,15 @@
1
+ import { ScrollAreaGuttersProps } from "./types.mjs";
2
+ //#region src/components/scroll-area/scroll-area-gutters.d.ts
3
+ /**
4
+ * The scrollbars of a container bound with `useScrollAreaContainer`: spread
5
+ * its `guttersProps` here, and render it where `guttersPosition` says (as in
6
+ * the demo). `sticky` gutters: the container's first child, a zero-height
7
+ * layer stuck to the top of the viewport, laid over its padding box. It is in
8
+ * flow, so it is one of the container's children for a grid, a flex row,
9
+ * `gap` and sibling selectors: lay the content out in a wrapper inside. `absolute` gutters: right after the
10
+ * container, a layer laid over the frame. A gutter appears for each axis with
11
+ * something to scroll. Hidden from assistive technology, which uses the
12
+ * native scrolling.
13
+ */
14
+ export declare function ScrollAreaGutters({ binding }: ScrollAreaGuttersProps): import("react").JSX.Element;
15
+ //#endregion
@@ -0,0 +1,60 @@
1
+ import { fromGuttersBinding } from "./gutters-binding.mjs";
2
+ import { useRailPointer } from "./use-rail-pointer.mjs";
3
+ import { clsx } from "cnfast";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/components/scroll-area/scroll-area-gutters.tsx
6
+ /** One scrollbar: the gutter (an invisible hover and paging target) and its thumb, sized and moved by the script. */
7
+ function ScrollAreaGutter({ axis, containerRef, shortened, thumbRef, onDraggingChange }) {
8
+ const { dragging, railHandlers, thumbHandlers } = useRailPointer({
9
+ axis,
10
+ containerRef,
11
+ onDraggingChange
12
+ });
13
+ return /* @__PURE__ */ jsx("div", {
14
+ ...railHandlers,
15
+ "data-slot": "scroll-area-scrollbar",
16
+ "data-orientation": axis === "y" ? "vertical" : "horizontal",
17
+ className: clsx("r-scroll-area__gutter", axis === "y" ? "r-scroll-area__gutter--vertical" : "r-scroll-area__gutter--horizontal", dragging && "r-scroll-area__gutter--dragging", shortened && "r-scroll-area__gutter--shortened"),
18
+ children: /* @__PURE__ */ jsx("div", {
19
+ ...thumbHandlers,
20
+ "data-slot": "scroll-area-thumb",
21
+ className: "r-scroll-area__thumb",
22
+ ref: thumbRef
23
+ })
24
+ });
25
+ }
26
+ /**
27
+ * The scrollbars of a container bound with `useScrollAreaContainer`: spread
28
+ * its `guttersProps` here, and render it where `guttersPosition` says (as in
29
+ * the demo). `sticky` gutters: the container's first child, a zero-height
30
+ * layer stuck to the top of the viewport, laid over its padding box. It is in
31
+ * flow, so it is one of the container's children for a grid, a flex row,
32
+ * `gap` and sibling selectors: lay the content out in a wrapper inside. `absolute` gutters: right after the
33
+ * container, a layer laid over the frame. A gutter appears for each axis with
34
+ * something to scroll. Hidden from assistive technology, which uses the
35
+ * native scrolling.
36
+ */
37
+ function ScrollAreaGutters({ binding }) {
38
+ const { containerRef, guttersRef, onDraggingChange, rails, xThumbRef, yThumbRef } = fromGuttersBinding(binding);
39
+ return /* @__PURE__ */ jsxs("div", {
40
+ "aria-hidden": "true",
41
+ "data-slot": "scroll-area-gutters",
42
+ className: "r-scroll-area__gutters",
43
+ ref: guttersRef,
44
+ children: [rails.yRail ? /* @__PURE__ */ jsx(ScrollAreaGutter, {
45
+ axis: "y",
46
+ containerRef,
47
+ shortened: rails.xRail,
48
+ thumbRef: yThumbRef,
49
+ onDraggingChange
50
+ }) : null, rails.xRail ? /* @__PURE__ */ jsx(ScrollAreaGutter, {
51
+ axis: "x",
52
+ containerRef,
53
+ shortened: rails.yRail,
54
+ thumbRef: xThumbRef,
55
+ onDraggingChange
56
+ }) : null]
57
+ });
58
+ }
59
+ //#endregion
60
+ export { ScrollAreaGutters };
@@ -0,0 +1,14 @@
1
+ import { ScrollAreaTextareaProps } from "./types.mjs";
2
+ //#region src/components/scroll-area/scroll-area-textarea.d.ts
3
+ /**
4
+ * A native `<textarea>` with ScrollArea's overlay scrollbar:
5
+ * `useScrollAreaContainer` with `guttersPosition="absolute"` and the textarea
6
+ * as its container (it can't hold children), the gutters beside it in the
7
+ * frame, as in the demo's textarea example. Its own `scrollHeight` is the
8
+ * content size: it is measured on every input and render, and when the box
9
+ * resizes. Native props, `ref`, `className`, `style` and `onScroll` go to the
10
+ * textarea; `wrapperClassName` and `wrapperStyle` to the frame. It is
11
+ * focusable itself, so it takes no `tabIndex` from the area.
12
+ */
13
+ export declare function ScrollAreaTextarea({ className, hideDelay, onInput, overscroll, ref, size, trigger, wrapperClassName, wrapperStyle, ...props }: ScrollAreaTextareaProps): import("react").JSX.Element;
14
+ //#endregion
@@ -0,0 +1,50 @@
1
+ import { cn } from "../../cn.mjs";
2
+ import { ScrollAreaGutters } from "./scroll-area-gutters.mjs";
3
+ import { useScrollAreaContainer } from "./use-scroll-area-container.mjs";
4
+ import { useLayoutEffect, useMemo } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/components/scroll-area/scroll-area-textarea.tsx
7
+ /**
8
+ * A native `<textarea>` with ScrollArea's overlay scrollbar:
9
+ * `useScrollAreaContainer` with `guttersPosition="absolute"` and the textarea
10
+ * as its container (it can't hold children), the gutters beside it in the
11
+ * frame, as in the demo's textarea example. Its own `scrollHeight` is the
12
+ * content size: it is measured on every input and render, and when the box
13
+ * resizes. Native props, `ref`, `className`, `style` and `onScroll` go to the
14
+ * textarea; `wrapperClassName` and `wrapperStyle` to the frame. It is
15
+ * focusable itself, so it takes no `tabIndex` from the area.
16
+ */
17
+ function ScrollAreaTextarea({ className, hideDelay = 600, onInput, overscroll = "none", ref, size = "medium", trigger = "hover", wrapperClassName, wrapperStyle, ...props }) {
18
+ const { containerProps, frameProps, guttersProps, measure } = useScrollAreaContainer({
19
+ containerRef: ref,
20
+ guttersPosition: "absolute",
21
+ hideDelay,
22
+ overscroll,
23
+ size,
24
+ trigger
25
+ });
26
+ const frameStyle = useMemo(() => ({
27
+ ...wrapperStyle,
28
+ ...frameProps.style
29
+ }), [frameProps, wrapperStyle]);
30
+ useLayoutEffect(() => measure());
31
+ const handleInput = (event) => {
32
+ measure();
33
+ onInput?.(event);
34
+ };
35
+ return /* @__PURE__ */ jsxs("div", {
36
+ ...frameProps,
37
+ "data-slot": "scroll-area-textarea",
38
+ className: cn(frameProps.className, "r-scroll-area--textarea", wrapperClassName),
39
+ style: frameStyle,
40
+ children: [/* @__PURE__ */ jsx("textarea", {
41
+ ...containerProps,
42
+ tabIndex: void 0,
43
+ ...props,
44
+ className: cn(containerProps.className, "r-scroll-area__textarea", className),
45
+ onInput: handleInput
46
+ }), /* @__PURE__ */ jsx(ScrollAreaGutters, { ...guttersProps })]
47
+ });
48
+ }
49
+ //#endregion
50
+ export { ScrollAreaTextarea };