@botiverse/raft-ui 0.59.2 → 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.
- package/CHANGELOG.md +38 -0
- package/dist/components/composer/composer-attachment.recipe.mjs +2 -3
- package/dist/components/composer/composer-attachments-scroll-area.d.mts +6 -0
- package/dist/components/composer/composer-attachments-scroll-area.mjs +20 -31
- package/dist/components/composer/composer.d.mts +8 -2
- package/dist/components/composer/composer.mjs +7 -9
- package/dist/components/composer/composer.recipe.mjs +1 -0
- package/dist/components/context-menu/context-menu.d.mts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.mts +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.mjs +1 -1
- package/dist/components/kbd/index.d.mts +5 -2
- package/dist/components/kbd/kbd-keys.d.mts +12 -0
- package/dist/components/kbd/kbd-keys.mjs +297 -0
- package/dist/components/kbd/kbd-shortcut.d.mts +34 -0
- package/dist/components/kbd/kbd-shortcut.mjs +79 -0
- package/dist/components/kbd/kbd.d.mts +55 -2
- package/dist/components/kbd/kbd.mjs +39 -15
- package/dist/components/markdown/markdown-parts.d.mts +7 -2
- package/dist/components/markdown/markdown-parts.mjs +8 -3
- package/dist/components/markdown/markdown.recipe.mjs +1 -5
- package/dist/components/message-list/message-list.mjs +9 -15
- package/dist/components/message-list/message-list.recipe.mjs +1 -1
- package/dist/components/scroll-area/class-names.mjs +19 -0
- package/dist/components/scroll-area/gutters-binding.mjs +4 -0
- package/dist/components/scroll-area/index.d.mts +6 -2
- package/dist/components/scroll-area/scroll-area-gutters.d.mts +15 -0
- package/dist/components/scroll-area/scroll-area-gutters.mjs +60 -0
- package/dist/components/scroll-area/scroll-area-textarea.d.mts +14 -0
- package/dist/components/scroll-area/scroll-area-textarea.mjs +50 -0
- package/dist/components/scroll-area/scroll-area.css +720 -0
- package/dist/components/scroll-area/scroll-area.d.mts +24 -15
- package/dist/components/scroll-area/scroll-area.mjs +67 -45
- package/dist/components/scroll-area/scroll-geometry.mjs +58 -0
- package/dist/components/scroll-area/scroll-to-element.mjs +67 -0
- package/dist/components/scroll-area/types.d.mts +224 -0
- package/dist/components/scroll-area/use-rail-pointer.mjs +93 -0
- package/dist/components/scroll-area/use-scroll-area-container.d.mts +26 -0
- package/dist/components/scroll-area/use-scroll-area-container.mjs +150 -0
- package/dist/components/scroll-area/use-scrollbars.mjs +480 -0
- package/dist/components/search/search-trigger.d.mts +1 -1
- package/dist/components/sidebar/sidebar.d.mts +1 -1
- package/dist/components/sidebar/sidebar.mjs +24 -20
- package/dist/components/sidebar/sidebar.recipe.mjs +1 -6
- package/dist/components/tooltip/tooltip.mjs +8 -5
- package/dist/components/virtual-list/VirtualList.mjs +1 -1
- package/dist/index.d.mts +7 -3
- package/dist/index.mjs +5 -2
- package/dist/lib/inline-part.mjs +13 -0
- package/dist/lib/use-merged-ref.mjs +73 -47
- package/dist/lib/use-platform.d.mts +13 -0
- package/dist/lib/use-platform.mjs +29 -0
- package/dist/styles.css +1 -0
- package/dist/wip.d.mts +5 -1
- package/dist/wip.mjs +3 -1
- package/package.json +1 -1
- 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
|
-
|
|
4
|
-
|
|
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({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
37
|
-
|
|
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
|
-
/**
|
|
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(
|
|
94
|
+
return /* @__PURE__ */ jsx(ScrollArea, {
|
|
91
95
|
"data-slot": "markdown-table-scroll",
|
|
96
|
+
...props,
|
|
92
97
|
className: tableScroll({ className }),
|
|
93
|
-
|
|
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
|
|
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
|
|
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__ */
|
|
30
|
+
return /* @__PURE__ */ jsx("div", {
|
|
32
31
|
"data-slot": "message-list",
|
|
33
32
|
className: root({ className: rootClassName }),
|
|
34
|
-
children:
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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 };
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
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 };
|