@botiverse/raft-ui 0.81.0 → 0.83.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 +80 -0
- package/dist/components/choice-list/choice-list.d.mts +8 -0
- package/dist/components/choice-list/choice-list.mjs +37 -16
- package/dist/components/choice-list/choice-list.recipe.mjs +1 -0
- package/dist/components/composer/composer-drop-overlay.d.mts +9 -4
- package/dist/components/composer/composer-drop-overlay.mjs +2 -5
- package/dist/components/dialog/dialog-sheet-context.mjs +7 -2
- package/dist/components/dialog/dialog-sheet.d.mts +3 -2
- package/dist/components/dialog/dialog-sheet.mjs +29 -43
- package/dist/components/dialog/dialog.d.mts +12 -1
- package/dist/components/dialog/dialog.mjs +50 -10
- package/dist/components/fit-toolbar/fit-toolbar.d.mts +110 -0
- package/dist/components/fit-toolbar/fit-toolbar.mjs +469 -0
- package/dist/components/fit-toolbar/fit-toolbar.recipe.mjs +21 -0
- package/dist/components/fit-toolbar/index.d.mts +2 -0
- package/dist/components/list-row/index.d.mts +2 -2
- package/dist/components/list-row/list-row.d.mts +9 -0
- package/dist/components/list-row/list-row.mjs +20 -1
- package/dist/components/list-row/list-row.recipe.d.mts +6 -3
- package/dist/components/list-row/list-row.recipe.mjs +8 -2
- package/dist/components/message-action-card/index.d.mts +2 -2
- package/dist/components/message-action-card/message-action-card.d.mts +8 -0
- package/dist/components/message-action-card/message-action-card.mjs +16 -1
- package/dist/components/message-action-card/message-action-card.recipe.mjs +5 -0
- package/dist/components/mobile-nav/mobile-nav-server.d.mts +21 -8
- package/dist/components/mobile-nav/mobile-nav-server.mjs +142 -13
- package/dist/components/resizable/resizable.recipe.mjs +4 -4
- package/dist/components/scroll-area/use-scrollbars.mjs +2 -1
- package/dist/components/segmented-control/segmented-control.d.mts +1 -1
- package/dist/components/segmented-control/segmented-control.mjs +11 -2
- package/dist/components/selection-toolbar/index.d.mts +2 -0
- package/dist/components/selection-toolbar/selection-toolbar.d.mts +100 -0
- package/dist/components/selection-toolbar/selection-toolbar.mjs +217 -0
- package/dist/components/selection-toolbar/selection-toolbar.recipe.mjs +42 -0
- package/dist/components/steps/otter-animation-visibility.mjs +45 -0
- package/dist/components/steps/otter-indicator.css +131 -106
- package/dist/components/steps/otter-indicator.d.mts +5 -8
- package/dist/components/steps/otter-indicator.mjs +38 -314
- package/dist/components/steps/ottie-assets/error.webp +0 -0
- package/dist/components/steps/ottie-assets/finish.webp +0 -0
- package/dist/components/steps/ottie-assets/process.webp +0 -0
- package/dist/components/steps/ottie-assets/wait.webp +0 -0
- package/dist/index.d.mts +5 -4
- package/dist/index.mjs +5 -4
- package/dist/lib/label-value-fit.mjs +33 -6
- package/dist/lib/use-mobile-viewport.mjs +5 -2
- package/dist/lib/use-soft-keyboard.mjs +72 -0
- package/dist/wip.d.mts +6 -3
- package/dist/wip.mjs +4 -3
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
5
5
|
root: string;
|
|
6
6
|
};
|
|
7
7
|
plain: {
|
|
8
|
-
root: string;
|
|
8
|
+
root: string[];
|
|
9
9
|
};
|
|
10
10
|
entry: {
|
|
11
11
|
root: string;
|
|
@@ -36,6 +36,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
36
36
|
body: string[];
|
|
37
37
|
line: string[];
|
|
38
38
|
title: string[];
|
|
39
|
+
subtitle: string[];
|
|
39
40
|
description: string[];
|
|
40
41
|
meta: string[];
|
|
41
42
|
value: string[];
|
|
@@ -46,7 +47,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
46
47
|
root: string;
|
|
47
48
|
};
|
|
48
49
|
plain: {
|
|
49
|
-
root: string;
|
|
50
|
+
root: string[];
|
|
50
51
|
};
|
|
51
52
|
entry: {
|
|
52
53
|
root: string;
|
|
@@ -77,6 +78,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
77
78
|
body: string[];
|
|
78
79
|
line: string[];
|
|
79
80
|
title: string[];
|
|
81
|
+
subtitle: string[];
|
|
80
82
|
description: string[];
|
|
81
83
|
meta: string[];
|
|
82
84
|
value: string[];
|
|
@@ -87,7 +89,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
87
89
|
root: string;
|
|
88
90
|
};
|
|
89
91
|
plain: {
|
|
90
|
-
root: string;
|
|
92
|
+
root: string[];
|
|
91
93
|
};
|
|
92
94
|
entry: {
|
|
93
95
|
root: string;
|
|
@@ -118,6 +120,7 @@ export declare const listRow: import("tailwind-variants/lite").TVReturnType<{
|
|
|
118
120
|
body: string[];
|
|
119
121
|
line: string[];
|
|
120
122
|
title: string[];
|
|
123
|
+
subtitle: string[];
|
|
121
124
|
description: string[];
|
|
122
125
|
meta: string[];
|
|
123
126
|
value: string[];
|
|
@@ -7,6 +7,7 @@ const listRow = tv({
|
|
|
7
7
|
"group/list-row flex w-full min-w-0 items-center gap-3 py-3 text-left",
|
|
8
8
|
"font-sans no-underline",
|
|
9
9
|
"[--list-row-ink:var(--foreground)] [--list-row-ink-2:var(--foreground-muted)] [--list-row-ink-3:var(--foreground-hint)]",
|
|
10
|
+
"[--list-row-status-space:0px]",
|
|
10
11
|
"text-(--list-row-ink)",
|
|
11
12
|
"not-disabled:not-aria-disabled:data-[tone=unread]:[--list-row-ink-2:var(--foreground)]",
|
|
12
13
|
"not-disabled:not-aria-disabled:data-[tone=muted]:[--list-row-ink:var(--foreground-muted)]",
|
|
@@ -18,13 +19,14 @@ const listRow = tv({
|
|
|
18
19
|
"aria-disabled:[--list-row-ink-2:var(--foreground-disabled)] aria-disabled:[--list-row-ink-3:var(--foreground-disabled)]"
|
|
19
20
|
],
|
|
20
21
|
icon: ["flex shrink-0 items-center justify-center", "text-(--list-row-ink-3) [&>svg]:size-5 [&>svg]:shrink-0"],
|
|
21
|
-
body: ["flex min-w-0 flex-1 flex-col gap-0.5"],
|
|
22
|
+
body: ["flex min-w-0 flex-1 flex-col gap-0.5", "-mb-(--list-row-status-space,0px)"],
|
|
22
23
|
line: ["flex min-w-0 items-center gap-2"],
|
|
23
24
|
title: [
|
|
24
25
|
"min-w-0 flex-1 truncate",
|
|
25
26
|
"text-body font-semibold",
|
|
26
27
|
"group-data-[tone=unread]/list-row:font-bold"
|
|
27
28
|
],
|
|
29
|
+
subtitle: ["min-w-0 flex-1 truncate", "text-footnote font-normal text-(--list-row-ink)"],
|
|
28
30
|
description: ["min-w-0 flex-1 truncate", "text-callout text-(--list-row-ink-2)"],
|
|
29
31
|
meta: ["min-w-0 truncate", "font-mono text-mono-meta font-normal tabular-nums text-(--list-row-ink-3)"],
|
|
30
32
|
value: ["max-w-[45%] shrink-0 truncate", "text-subhead text-(--list-row-ink-3)"],
|
|
@@ -33,7 +35,11 @@ const listRow = tv({
|
|
|
33
35
|
variants: {
|
|
34
36
|
variant: {
|
|
35
37
|
default: { root: "min-h-16 pointer-coarse:min-h-14 pointer-coarse:py-2 [--list-row-rule-start:63px]" },
|
|
36
|
-
plain: { root:
|
|
38
|
+
plain: { root: [
|
|
39
|
+
"py-(--settings-row-inset) pb-[calc(var(--settings-row-inset)+var(--list-row-status-space))]",
|
|
40
|
+
"has-[>[data-slot=list-row-body]>[data-slot=save-status]]:[--list-row-status-space:calc(--spacing(1)+var(--text-footnote--line-height))]",
|
|
41
|
+
"[--list-row-rule-start:16px]"
|
|
42
|
+
] },
|
|
37
43
|
entry: { root: "" }
|
|
38
44
|
},
|
|
39
45
|
interactive: {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardActionsNoteProps, MessageActionCardActionsProps, MessageActionCardCollapseTrigger, MessageActionCardCollapseTriggerProps, MessageActionCardCompletion, MessageActionCardCompletionProps, MessageActionCardContent, MessageActionCardContentProps, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderDescriptionProps, MessageActionCardHeaderIcon, MessageActionCardHeaderIconProps, MessageActionCardHeaderProps, MessageActionCardHeaderStatus, MessageActionCardHeaderStatusProps, MessageActionCardHeaderTitle, MessageActionCardHeaderTitleProps, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardHintLabelProps, MessageActionCardHintProps, MessageActionCardNotice, MessageActionCardNoticeProps, MessageActionCardProperties, MessageActionCardPropertiesProps, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyLabelProps, MessageActionCardPropertyProps, MessageActionCardPropertyValue, MessageActionCardPropertyValueProps, MessageActionCardProps, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeDescriptionProps, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListLabelProps, MessageActionCardScopeListProps, MessageActionCardScopeListViewport, MessageActionCardScopeListViewportProps, MessageActionCardScopeName, MessageActionCardScopeNameProps, MessageActionCardScopeProps, MessageActionCardStatus, MessageActionCardStatusProps } from "./message-action-card.mjs";
|
|
2
|
-
export { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, type MessageActionCardActionsNoteProps, type MessageActionCardActionsProps, MessageActionCardCollapseTrigger, type MessageActionCardCollapseTriggerProps, MessageActionCardCompletion, type MessageActionCardCompletionProps, MessageActionCardContent, type MessageActionCardContentProps, MessageActionCardHeader, MessageActionCardHeaderDescription, type MessageActionCardHeaderDescriptionProps, MessageActionCardHeaderIcon, type MessageActionCardHeaderIconProps, type MessageActionCardHeaderProps, MessageActionCardHeaderStatus, type MessageActionCardHeaderStatusProps, MessageActionCardHeaderTitle, type MessageActionCardHeaderTitleProps, MessageActionCardHint, MessageActionCardHintLabel, type MessageActionCardHintLabelProps, type MessageActionCardHintProps, MessageActionCardNotice, type MessageActionCardNoticeProps, MessageActionCardProperties, type MessageActionCardPropertiesProps, MessageActionCardProperty, MessageActionCardPropertyLabel, type MessageActionCardPropertyLabelProps, type MessageActionCardPropertyProps, MessageActionCardPropertyValue, type MessageActionCardPropertyValueProps, type MessageActionCardProps, MessageActionCardScope, MessageActionCardScopeDescription, type MessageActionCardScopeDescriptionProps, MessageActionCardScopeList, MessageActionCardScopeListLabel, type MessageActionCardScopeListLabelProps, type MessageActionCardScopeListProps, MessageActionCardScopeListViewport, type MessageActionCardScopeListViewportProps, MessageActionCardScopeName, type MessageActionCardScopeNameProps, type MessageActionCardScopeProps, MessageActionCardStatus, type MessageActionCardStatusProps };
|
|
1
|
+
import { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardActionsNoteProps, MessageActionCardActionsProps, MessageActionCardCollapseTrigger, MessageActionCardCollapseTriggerProps, MessageActionCardCompletion, MessageActionCardCompletionProps, MessageActionCardContent, MessageActionCardContentProps, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderDescriptionProps, MessageActionCardHeaderIcon, MessageActionCardHeaderIconProps, MessageActionCardHeaderMeta, MessageActionCardHeaderMetaProps, MessageActionCardHeaderProps, MessageActionCardHeaderStatus, MessageActionCardHeaderStatusProps, MessageActionCardHeaderTitle, MessageActionCardHeaderTitleProps, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardHintLabelProps, MessageActionCardHintProps, MessageActionCardNotice, MessageActionCardNoticeProps, MessageActionCardProperties, MessageActionCardPropertiesProps, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyLabelProps, MessageActionCardPropertyProps, MessageActionCardPropertyValue, MessageActionCardPropertyValueProps, MessageActionCardProps, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeDescriptionProps, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListLabelProps, MessageActionCardScopeListProps, MessageActionCardScopeListViewport, MessageActionCardScopeListViewportProps, MessageActionCardScopeName, MessageActionCardScopeNameProps, MessageActionCardScopeProps, MessageActionCardStatus, MessageActionCardStatusProps } from "./message-action-card.mjs";
|
|
2
|
+
export { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, type MessageActionCardActionsNoteProps, type MessageActionCardActionsProps, MessageActionCardCollapseTrigger, type MessageActionCardCollapseTriggerProps, MessageActionCardCompletion, type MessageActionCardCompletionProps, MessageActionCardContent, type MessageActionCardContentProps, MessageActionCardHeader, MessageActionCardHeaderDescription, type MessageActionCardHeaderDescriptionProps, MessageActionCardHeaderIcon, type MessageActionCardHeaderIconProps, MessageActionCardHeaderMeta, type MessageActionCardHeaderMetaProps, type MessageActionCardHeaderProps, MessageActionCardHeaderStatus, type MessageActionCardHeaderStatusProps, MessageActionCardHeaderTitle, type MessageActionCardHeaderTitleProps, MessageActionCardHint, MessageActionCardHintLabel, type MessageActionCardHintLabelProps, type MessageActionCardHintProps, MessageActionCardNotice, type MessageActionCardNoticeProps, MessageActionCardProperties, type MessageActionCardPropertiesProps, MessageActionCardProperty, MessageActionCardPropertyLabel, type MessageActionCardPropertyLabelProps, type MessageActionCardPropertyProps, MessageActionCardPropertyValue, type MessageActionCardPropertyValueProps, type MessageActionCardProps, MessageActionCardScope, MessageActionCardScopeDescription, type MessageActionCardScopeDescriptionProps, MessageActionCardScopeList, MessageActionCardScopeListLabel, type MessageActionCardScopeListLabelProps, type MessageActionCardScopeListProps, MessageActionCardScopeListViewport, type MessageActionCardScopeListViewportProps, MessageActionCardScopeName, type MessageActionCardScopeNameProps, type MessageActionCardScopeProps, MessageActionCardStatus, type MessageActionCardStatusProps };
|
|
@@ -23,6 +23,13 @@ export declare function MessageActionCardHeaderTitle({ className, render, ...pro
|
|
|
23
23
|
* MessageActionCardHeaderTitle; it stays visible while the card is folded.
|
|
24
24
|
*/
|
|
25
25
|
export declare function MessageActionCardHeaderDescription({ className, render, ...props }: useRender.ComponentProps<"span">): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
26
|
+
/**
|
|
27
|
+
* The time on a resolved card, in Space Mono at the hint tier. Place it
|
|
28
|
+
* inside MessageActionCardHeaderTitle for a line of its own under the title,
|
|
29
|
+
* or at the end of MessageActionCardHeaderDescription to close its line:
|
|
30
|
+
* "Approved by Martin · 10:51". It stays visible while the card is folded.
|
|
31
|
+
*/
|
|
32
|
+
export declare function MessageActionCardHeaderMeta({ className, render, ...props }: MessageActionCardHeaderMetaProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
26
33
|
/**
|
|
27
34
|
* The card's state label in the header: plain text led by a square pixel in
|
|
28
35
|
* the variant's colour, so a column of "Done" cards does not shout.
|
|
@@ -64,6 +71,7 @@ export type MessageActionCardProps = useRender.ComponentProps<"div"> & {
|
|
|
64
71
|
export type MessageActionCardHeaderIconProps = useRender.ComponentProps<"span">;
|
|
65
72
|
export type MessageActionCardHeaderTitleProps = useRender.ComponentProps<"span">;
|
|
66
73
|
export type MessageActionCardHeaderDescriptionProps = useRender.ComponentProps<"span">;
|
|
74
|
+
export type MessageActionCardHeaderMetaProps = useRender.ComponentProps<"span">;
|
|
67
75
|
export type MessageActionCardStatusProps = BadgeProps;
|
|
68
76
|
export type MessageActionCardCollapseTriggerProps = Omit<ComponentProps<typeof Collapsible.Trigger>, "className"> & {
|
|
69
77
|
className?: string;
|
|
@@ -79,6 +79,21 @@ function MessageActionCardHeaderDescription({ className, render, ...props }) {
|
|
|
79
79
|
state: { slot: "message-action-card-header-description" }
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* The time on a resolved card, in Space Mono at the hint tier. Place it
|
|
84
|
+
* inside MessageActionCardHeaderTitle for a line of its own under the title,
|
|
85
|
+
* or at the end of MessageActionCardHeaderDescription to close its line:
|
|
86
|
+
* "Approved by Martin · 10:51". It stays visible while the card is folded.
|
|
87
|
+
*/
|
|
88
|
+
function MessageActionCardHeaderMeta({ className, render, ...props }) {
|
|
89
|
+
const { headerMeta } = messageActionCard();
|
|
90
|
+
return useRender({
|
|
91
|
+
defaultTagName: "span",
|
|
92
|
+
render,
|
|
93
|
+
props: mergeProps({ className: headerMeta({ className }) }, props),
|
|
94
|
+
state: { slot: "message-action-card-header-meta" }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
82
97
|
const STATUS_TONES = {
|
|
83
98
|
default: "neutral",
|
|
84
99
|
muted: "neutral",
|
|
@@ -292,4 +307,4 @@ function MessageActionCardActionsNote({ className, render, ...props }) {
|
|
|
292
307
|
});
|
|
293
308
|
}
|
|
294
309
|
//#endregion
|
|
295
|
-
export { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardCollapseTrigger, MessageActionCardCompletion, MessageActionCardContent, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderIcon, MessageActionCardHeaderStatus, MessageActionCardHeaderTitle, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardNotice, MessageActionCardProperties, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyValue, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListViewport, MessageActionCardScopeName, MessageActionCardStatus };
|
|
310
|
+
export { MessageActionCard, MessageActionCardActions, MessageActionCardActionsNote, MessageActionCardCollapseTrigger, MessageActionCardCompletion, MessageActionCardContent, MessageActionCardHeader, MessageActionCardHeaderDescription, MessageActionCardHeaderIcon, MessageActionCardHeaderMeta, MessageActionCardHeaderStatus, MessageActionCardHeaderTitle, MessageActionCardHint, MessageActionCardHintLabel, MessageActionCardNotice, MessageActionCardProperties, MessageActionCardProperty, MessageActionCardPropertyLabel, MessageActionCardPropertyValue, MessageActionCardScope, MessageActionCardScopeDescription, MessageActionCardScopeList, MessageActionCardScopeListLabel, MessageActionCardScopeListViewport, MessageActionCardScopeName, MessageActionCardStatus };
|
|
@@ -16,6 +16,11 @@ const messageActionCard = tv({
|
|
|
16
16
|
],
|
|
17
17
|
headerTitle: ["min-w-0 flex-1", "pt-[calc((27px-1lh)/2)]"],
|
|
18
18
|
headerDescription: ["block", "mt-0.5 text-footnote font-normal text-foreground-muted"],
|
|
19
|
+
headerMeta: [
|
|
20
|
+
"block in-data-[slot=message-action-card-header-description]:inline",
|
|
21
|
+
"mt-0.5 in-data-[slot=message-action-card-header-description]:mt-0",
|
|
22
|
+
"font-mono text-mono-meta font-normal tabular-nums text-foreground-hint"
|
|
23
|
+
],
|
|
19
24
|
headerStatus: ["ml-auto shrink-0", "mt-[calc((27px-1lh)/2)] text-caption font-semibold text-foreground-muted"],
|
|
20
25
|
status: [
|
|
21
26
|
"inline-flex h-auto items-center gap-1.5 rounded-none border-0 bg-transparent p-0 shadow-none",
|
|
@@ -19,19 +19,32 @@ export declare function MobileNavServerItem({ className, id, ref, onClick, onCon
|
|
|
19
19
|
export type MobileNavServerPopoverContentProps = PopoverContentProps;
|
|
20
20
|
/**
|
|
21
21
|
* The popover above the tab bar, 8px from each side of it and 8px above it,
|
|
22
|
-
* as tall as its content and at most 60% of the screen.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
22
|
+
* as tall as its content and at most 60% of the screen. The one exception:
|
|
23
|
+
* the list always keeps one whole server row, so where the parts after it
|
|
24
|
+
* leave less, the popover grows past 60% as far as that row needs (the
|
|
25
|
+
* floor, measured from its children into `--mobile-nav-server-popover-floor`).
|
|
26
|
+
* Where even that doesn't fit, the whole popover scrolls, the footer and the
|
|
27
|
+
* pages with it: the children sit in a ScrollArea
|
|
28
|
+
* (`data-slot="mobile-nav-server-popover-scroll"`) inside the popup. It stops below the top safe area (a notch in a standalone
|
|
29
|
+
* web app): Base UI's collision padding takes only pixels, so the height cap
|
|
30
|
+
* subtracts `env(safe-area-inset-top)`. The bottom needs none: the tab bar
|
|
31
|
+
* under the popover already pads the bottom safe area. A column:
|
|
27
32
|
* `MobileNavServerPopoverList` takes the room left and scrolls, and the
|
|
28
33
|
* destinations and the footer after it stay in view.
|
|
34
|
+
*
|
|
35
|
+
* Focus on open goes to the current server's row (`aria-current="true"` in
|
|
36
|
+
* the list), which the list has already scrolled into view, so focusing it
|
|
37
|
+
* never scrolls the list back to the top. A touch opens it with focus on the
|
|
38
|
+
* popover itself, without scrolling, so no keyboard comes up. `initialFocus`
|
|
39
|
+
* overrides this.
|
|
29
40
|
*/
|
|
30
|
-
export declare function MobileNavServerPopoverContent({ anchor, side, align, sideOffset, collisionPadding, className, ...props }: MobileNavServerPopoverContentProps): import("react").JSX.Element;
|
|
41
|
+
export declare function MobileNavServerPopoverContent({ anchor, side, align, sideOffset, collisionPadding, initialFocus, className, children, ref, ...props }: MobileNavServerPopoverContentProps): import("react").JSX.Element;
|
|
31
42
|
export type MobileNavServerPopoverListProps = ScrollAreaProps;
|
|
32
43
|
/** The server list: takes the room left in the popover and scrolls inside it,
|
|
33
|
-
* a ScrollArea (a column with no gap, so its gutters move nothing).
|
|
34
|
-
|
|
44
|
+
* a ScrollArea (a column with no gap, so its gutters move nothing). It is
|
|
45
|
+
* never shorter than one whole two-line row, and it opens scrolled to the
|
|
46
|
+
* current server's row (`aria-current="true"`), with no animation. */
|
|
47
|
+
export declare function MobileNavServerPopoverList({ className, ref, ...props }: MobileNavServerPopoverListProps): import("react").JSX.Element;
|
|
35
48
|
export type MobileNavServerPopoverGroupProps = ComponentPropsWithRef<"div">;
|
|
36
49
|
/** Rows that always stay in view, such as the footer actions. */
|
|
37
50
|
export declare function MobileNavServerPopoverGroup({ className, ...props }: MobileNavServerPopoverGroupProps): import("react").JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { tv } from "../../lib/tv.mjs";
|
|
2
|
+
import { scrollToElement } from "../scroll-area/scroll-to-element.mjs";
|
|
2
3
|
import { ScrollArea } from "../scroll-area/scroll-area.mjs";
|
|
3
4
|
import { MobileNavItem } from "./mobile-nav.mjs";
|
|
4
5
|
import "../../lib/touch-drag.mjs";
|
|
@@ -16,9 +17,10 @@ const mobileNavServer = tv({ slots: {
|
|
|
16
17
|
content: [
|
|
17
18
|
"flex flex-col",
|
|
18
19
|
"w-[calc(var(--anchor-width)-16px)] min-w-0",
|
|
19
|
-
"max-h-[min(60dvh,calc(var(--available-height)-env(safe-area-inset-top,0px)))]"
|
|
20
|
+
"max-h-[min(max(60dvh,var(--mobile-nav-server-popover-floor,0px)),calc(var(--available-height)-env(safe-area-inset-top,0px)))]"
|
|
20
21
|
],
|
|
21
|
-
|
|
22
|
+
scroll: ["flex min-h-0 flex-col"],
|
|
23
|
+
list: ["flex min-h-[calc(var(--spacing-option)+var(--text-mono-meta--line-height)+(--spacing(2)))] flex-1 flex-col p-1"],
|
|
22
24
|
group: ["flex shrink-0 flex-col p-1"],
|
|
23
25
|
row: [
|
|
24
26
|
"flex w-full shrink-0 cursor-default select-none items-center",
|
|
@@ -26,7 +28,7 @@ const mobileNavServer = tv({ slots: {
|
|
|
26
28
|
"min-h-option gap-2.5 rounded-chip px-2.5 py-option-inset",
|
|
27
29
|
"font-sans text-callout font-medium text-foreground",
|
|
28
30
|
"hover:bg-brand-soft active:bg-brand-soft focus-visible:bg-brand-soft",
|
|
29
|
-
"aria-
|
|
31
|
+
"aria-current:font-bold",
|
|
30
32
|
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&>svg:not([class*='size-'])]:size-4",
|
|
31
33
|
"[&>svg]:text-foreground-muted",
|
|
32
34
|
"*:data-[slot=avatar]:size-5 *:data-[slot=avatar]:shrink-0"
|
|
@@ -162,21 +164,49 @@ function MobileNavServerItem({ className, id, ref, onClick, onContextMenu, onPoi
|
|
|
162
164
|
}
|
|
163
165
|
/**
|
|
164
166
|
* The popover above the tab bar, 8px from each side of it and 8px above it,
|
|
165
|
-
* as tall as its content and at most 60% of the screen.
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
167
|
+
* as tall as its content and at most 60% of the screen. The one exception:
|
|
168
|
+
* the list always keeps one whole server row, so where the parts after it
|
|
169
|
+
* leave less, the popover grows past 60% as far as that row needs (the
|
|
170
|
+
* floor, measured from its children into `--mobile-nav-server-popover-floor`).
|
|
171
|
+
* Where even that doesn't fit, the whole popover scrolls, the footer and the
|
|
172
|
+
* pages with it: the children sit in a ScrollArea
|
|
173
|
+
* (`data-slot="mobile-nav-server-popover-scroll"`) inside the popup. It stops below the top safe area (a notch in a standalone
|
|
174
|
+
* web app): Base UI's collision padding takes only pixels, so the height cap
|
|
175
|
+
* subtracts `env(safe-area-inset-top)`. The bottom needs none: the tab bar
|
|
176
|
+
* under the popover already pads the bottom safe area. A column:
|
|
170
177
|
* `MobileNavServerPopoverList` takes the room left and scrolls, and the
|
|
171
178
|
* destinations and the footer after it stay in view.
|
|
179
|
+
*
|
|
180
|
+
* Focus on open goes to the current server's row (`aria-current="true"` in
|
|
181
|
+
* the list), which the list has already scrolled into view, so focusing it
|
|
182
|
+
* never scrolls the list back to the top. A touch opens it with focus on the
|
|
183
|
+
* popover itself, without scrolling, so no keyboard comes up. `initialFocus`
|
|
184
|
+
* overrides this.
|
|
172
185
|
*/
|
|
173
|
-
function MobileNavServerPopoverContent({ anchor, side = "top", align = "center", sideOffset = 8, collisionPadding = 8, className, ...props }) {
|
|
186
|
+
function MobileNavServerPopoverContent({ anchor, side = "top", align = "center", sideOffset = 8, collisionPadding = 8, initialFocus, className, children, ref, ...props }) {
|
|
174
187
|
const { triggerRef } = useMobileNavServerContext("MobileNavServerPopoverContent");
|
|
175
|
-
const { content } = mobileNavServer();
|
|
188
|
+
const { content, scroll } = mobileNavServer();
|
|
189
|
+
const popupRef = useRef(null);
|
|
176
190
|
const tabBar = useCallback(() => {
|
|
177
191
|
const trigger = triggerRef.current;
|
|
178
192
|
return trigger?.closest("[data-slot=mobile-nav-root]") ?? trigger;
|
|
179
193
|
}, [triggerRef]);
|
|
194
|
+
const setRef = useCallback((node) => {
|
|
195
|
+
popupRef.current = node;
|
|
196
|
+
assignRef(ref, node);
|
|
197
|
+
if (!node) return;
|
|
198
|
+
return () => {
|
|
199
|
+
popupRef.current = null;
|
|
200
|
+
assignRef(ref, null);
|
|
201
|
+
};
|
|
202
|
+
}, [ref]);
|
|
203
|
+
const setScrollRef = useCallback((node) => {
|
|
204
|
+
if (node) return keepOneRow(node);
|
|
205
|
+
}, []);
|
|
206
|
+
const focusCurrent = useCallback((openType) => {
|
|
207
|
+
if (openType === "touch") return true;
|
|
208
|
+
return popupRef.current?.querySelector(CURRENT_ROW) ?? true;
|
|
209
|
+
}, []);
|
|
180
210
|
return /* @__PURE__ */ jsx(PopoverContent, {
|
|
181
211
|
"data-slot": "mobile-nav-server-popover-content",
|
|
182
212
|
anchor: anchor ?? tabBar,
|
|
@@ -184,16 +214,115 @@ function MobileNavServerPopoverContent({ anchor, side = "top", align = "center",
|
|
|
184
214
|
align,
|
|
185
215
|
sideOffset,
|
|
186
216
|
collisionPadding,
|
|
217
|
+
initialFocus: initialFocus ?? focusCurrent,
|
|
187
218
|
className: content({ className }),
|
|
188
|
-
|
|
219
|
+
ref: setRef,
|
|
220
|
+
...props,
|
|
221
|
+
children: /* @__PURE__ */ jsx(ScrollArea, {
|
|
222
|
+
"data-slot": "mobile-nav-server-popover-scroll",
|
|
223
|
+
overscroll: "contain",
|
|
224
|
+
tabIndex: -1,
|
|
225
|
+
ref: setScrollRef,
|
|
226
|
+
className: scroll(),
|
|
227
|
+
children
|
|
228
|
+
})
|
|
189
229
|
});
|
|
190
230
|
}
|
|
231
|
+
const LIST_SLOT = "mobile-nav-server-popover-list";
|
|
232
|
+
const CURRENT_ROW = `[data-slot=${LIST_SLOT}] [aria-current="true"]`;
|
|
233
|
+
const GUTTERS_SLOT = "scroll-area-gutters";
|
|
234
|
+
/** Padding and border along the block axis. */
|
|
235
|
+
function blockFrame(element) {
|
|
236
|
+
const style = getComputedStyle(element);
|
|
237
|
+
return parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Writes the popover's floor onto the popup, its height with the list at its
|
|
241
|
+
* one-row minimum: the list's `min-height` plus the height of every other
|
|
242
|
+
* part in the scroll area, and the popup's and the area's own padding and
|
|
243
|
+
* border. Watched as the parts change.
|
|
244
|
+
*/
|
|
245
|
+
function keepOneRow(area) {
|
|
246
|
+
const popup = area.parentElement;
|
|
247
|
+
const measure = () => {
|
|
248
|
+
if (!popup) return;
|
|
249
|
+
let floor = blockFrame(popup) + blockFrame(area);
|
|
250
|
+
for (const child of area.children) {
|
|
251
|
+
if (!(child instanceof HTMLElement) || child.dataset.slot === GUTTERS_SLOT) continue;
|
|
252
|
+
const style = getComputedStyle(child);
|
|
253
|
+
if (style.display === "none" || style.position === "absolute" || style.position === "fixed") continue;
|
|
254
|
+
floor += parseFloat(style.marginTop) + parseFloat(style.marginBottom);
|
|
255
|
+
floor += child.dataset.slot === LIST_SLOT ? parseFloat(style.minHeight) || 0 : child.getBoundingClientRect().height;
|
|
256
|
+
}
|
|
257
|
+
popup.style.setProperty("--mobile-nav-server-popover-floor", `${floor}px`);
|
|
258
|
+
};
|
|
259
|
+
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
|
|
260
|
+
const watch = () => {
|
|
261
|
+
resize?.disconnect();
|
|
262
|
+
for (const child of area.children) if (child instanceof HTMLElement && child.dataset.slot !== LIST_SLOT) resize?.observe(child);
|
|
263
|
+
measure();
|
|
264
|
+
};
|
|
265
|
+
const mutation = new MutationObserver(watch);
|
|
266
|
+
mutation.observe(area, { childList: true });
|
|
267
|
+
watch();
|
|
268
|
+
return () => {
|
|
269
|
+
resize?.disconnect();
|
|
270
|
+
mutation.disconnect();
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Opens the list on the current server: scrolls it, and only it, to the row
|
|
275
|
+
* with `aria-current="true"` at once, with no animation, and again as the
|
|
276
|
+
* list takes its final size, until people scroll or press in it themselves.
|
|
277
|
+
*/
|
|
278
|
+
function openOnCurrent(list) {
|
|
279
|
+
let pinned = true;
|
|
280
|
+
const show = () => {
|
|
281
|
+
if (!pinned) return;
|
|
282
|
+
const current = list.querySelector("[aria-current=\"true\"]");
|
|
283
|
+
if (!current) return;
|
|
284
|
+
const offset = parseFloat(getComputedStyle(list).paddingBottom) || 0;
|
|
285
|
+
scrollToElement(list, current, "vertical", {
|
|
286
|
+
block: "nearest",
|
|
287
|
+
offset
|
|
288
|
+
});
|
|
289
|
+
};
|
|
290
|
+
const release = () => {
|
|
291
|
+
pinned = false;
|
|
292
|
+
};
|
|
293
|
+
const events = [
|
|
294
|
+
"pointerdown",
|
|
295
|
+
"touchstart",
|
|
296
|
+
"wheel",
|
|
297
|
+
"keydown"
|
|
298
|
+
];
|
|
299
|
+
for (const type of events) list.addEventListener(type, release, { passive: true });
|
|
300
|
+
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(show);
|
|
301
|
+
resize?.observe(list);
|
|
302
|
+
show();
|
|
303
|
+
return () => {
|
|
304
|
+
resize?.disconnect();
|
|
305
|
+
for (const type of events) list.removeEventListener(type, release);
|
|
306
|
+
};
|
|
307
|
+
}
|
|
191
308
|
/** The server list: takes the room left in the popover and scrolls inside it,
|
|
192
|
-
* a ScrollArea (a column with no gap, so its gutters move nothing).
|
|
193
|
-
|
|
309
|
+
* a ScrollArea (a column with no gap, so its gutters move nothing). It is
|
|
310
|
+
* never shorter than one whole two-line row, and it opens scrolled to the
|
|
311
|
+
* current server's row (`aria-current="true"`), with no animation. */
|
|
312
|
+
function MobileNavServerPopoverList({ className, ref, ...props }) {
|
|
194
313
|
const { list } = mobileNavServer();
|
|
314
|
+
const setRef = useCallback((node) => {
|
|
315
|
+
assignRef(ref, node);
|
|
316
|
+
if (!node) return;
|
|
317
|
+
const stop = openOnCurrent(node);
|
|
318
|
+
return () => {
|
|
319
|
+
stop();
|
|
320
|
+
assignRef(ref, null);
|
|
321
|
+
};
|
|
322
|
+
}, [ref]);
|
|
195
323
|
return /* @__PURE__ */ jsx(ScrollArea, {
|
|
196
324
|
"data-slot": "mobile-nav-server-popover-list",
|
|
325
|
+
ref: setRef,
|
|
197
326
|
overscroll: "contain",
|
|
198
327
|
tabIndex: -1,
|
|
199
328
|
...props,
|
|
@@ -5,17 +5,17 @@ const resizable = tv({ slots: {
|
|
|
5
5
|
panel: ["min-h-0 min-w-0"],
|
|
6
6
|
handle: [
|
|
7
7
|
"right-0 z-10 cursor-ew-resize touch-none select-none",
|
|
8
|
-
"relative -
|
|
8
|
+
"relative -mr-3 flex w-3 shrink-0 items-center justify-center pointer-coarse:-mr-6 pointer-coarse:w-6",
|
|
9
9
|
"before:pointer-events-none before:absolute before:transition-colors before:content-['']",
|
|
10
10
|
"focus-visible:outline-none focus-visible:before:outline-2 focus-visible:before:outline-offset-2 focus-visible:before:outline-foreground",
|
|
11
|
-
"data-[orientation=horizontal]:-
|
|
11
|
+
"data-[orientation=horizontal]:-mb-3 data-[orientation=horizontal]:mr-0 data-[orientation=horizontal]:h-3 data-[orientation=horizontal]:w-full data-[orientation=horizontal]:cursor-ns-resize pointer-coarse:data-[orientation=horizontal]:-mb-6 pointer-coarse:data-[orientation=horizontal]:mr-0 pointer-coarse:data-[orientation=horizontal]:h-6",
|
|
12
12
|
"bg-transparent",
|
|
13
|
-
"before:top-0 before
|
|
13
|
+
"before:top-0 before:-left-px before:h-full before:w-px before:translate-none before:rounded-none",
|
|
14
14
|
"before:bg-transparent",
|
|
15
15
|
"hover:before:bg-foreground-muted",
|
|
16
16
|
"data-[separator=active]:before:bg-foreground-muted",
|
|
17
17
|
"focus-visible:keyboard:before:w-0.5 focus-visible:keyboard:before:bg-foreground focus-visible:before:outline-none",
|
|
18
|
-
"data-[orientation=horizontal]:before
|
|
18
|
+
"data-[orientation=horizontal]:before:-top-px data-[orientation=horizontal]:before:left-0",
|
|
19
19
|
"data-[orientation=horizontal]:before:h-px data-[orientation=horizontal]:before:w-full",
|
|
20
20
|
"data-[orientation=horizontal]:focus-visible:keyboard:before:h-0.5"
|
|
21
21
|
]
|
|
@@ -399,7 +399,8 @@ function useScrollbars({ containerRef, contentRef, fadeRef, guttersPosition, roo
|
|
|
399
399
|
/** Binds the observers and the scroll listener to `container`; returns what undoes it. */
|
|
400
400
|
const bind = useCallback((container, content, root) => {
|
|
401
401
|
container.addEventListener("scroll", handleScroll, { passive: true });
|
|
402
|
-
measure(true);
|
|
402
|
+
if (typeof ResizeObserver === "undefined") measure(true);
|
|
403
|
+
else scheduleFrame(true);
|
|
403
404
|
const classes = root && typeof MutationObserver !== "undefined" ? new MutationObserver(applyClasses) : null;
|
|
404
405
|
if (root) classes?.observe(root, {
|
|
405
406
|
attributeFilter: ["class"],
|
|
@@ -28,7 +28,7 @@ export type SegmentedControlProps<T extends string = string> = StyledProps<Radio
|
|
|
28
28
|
*/
|
|
29
29
|
variant?: "default" | "on-frame";
|
|
30
30
|
};
|
|
31
|
-
export declare function SegmentedControl<T extends string = string>({ disabled, iconsOnlyBelow, variant, className, ref, ...props }: SegmentedControlProps<T>): import("react").JSX.Element;
|
|
31
|
+
export declare function SegmentedControl<T extends string = string>({ disabled, iconsOnlyBelow: iconsOnlyBelowProp, variant, className, ref, ...props }: SegmentedControlProps<T>): import("react").JSX.Element;
|
|
32
32
|
export type SegmentedControlItemProps<T extends string = string> = StyledProps<Radio.Root.Props<T>>;
|
|
33
33
|
export declare function SegmentedControlItem<T extends string = string>({ className, ref, ...props }: SegmentedControlItemProps<T>): import("react").JSX.Element;
|
|
34
34
|
export type SegmentedControlLabelProps = ComponentPropsWithRef<"span">;
|
|
@@ -2,6 +2,7 @@ import { tv } from "../../lib/tv.mjs";
|
|
|
2
2
|
import { useMergedRef } from "../../lib/use-merged-ref.mjs";
|
|
3
3
|
import { useTapActivation } from "../../lib/tap-activation.mjs";
|
|
4
4
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../tooltip/tooltip.mjs";
|
|
5
|
+
import { useInFitToolbar } from "../fit-toolbar/fit-toolbar.mjs";
|
|
5
6
|
import { createContext, use, useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
import { Radio } from "@base-ui/react/radio";
|
|
@@ -51,6 +52,11 @@ const segmentedControl = tv({
|
|
|
51
52
|
xl: { root: ["@max-xl:**:data-[slot=segmented-control-item]:relative @max-xl:**:data-[slot=segmented-control-item]:w-(--segment-size) @max-xl:**:data-[slot=segmented-control-item]:px-0", "@max-xl:**:data-[slot=segmented-control-label]:sr-only @max-xl:**:data-[slot=segmented-control-count]:sr-only"] },
|
|
52
53
|
"2xl": { root: ["@max-2xl:**:data-[slot=segmented-control-item]:relative @max-2xl:**:data-[slot=segmented-control-item]:w-(--segment-size) @max-2xl:**:data-[slot=segmented-control-item]:px-0", "@max-2xl:**:data-[slot=segmented-control-label]:sr-only @max-2xl:**:data-[slot=segmented-control-count]:sr-only"] }
|
|
53
54
|
},
|
|
55
|
+
inFitToolbar: { true: { root: [
|
|
56
|
+
"shrink-0",
|
|
57
|
+
"data-fit-label:**:data-[slot=segmented-control-item]:relative data-fit-label:**:data-[slot=segmented-control-item]:w-(--segment-size) data-fit-label:**:data-[slot=segmented-control-item]:px-0",
|
|
58
|
+
"data-fit-label:**:data-[slot=segmented-control-label]:sr-only data-fit-label:**:data-[slot=segmented-control-count]:sr-only"
|
|
59
|
+
] } },
|
|
54
60
|
iconsOnlyMeasured: { true: { root: ["data-icons-only:**:data-[slot=segmented-control-item]:relative data-icons-only:**:data-[slot=segmented-control-item]:w-(--segment-size) data-icons-only:**:data-[slot=segmented-control-item]:px-0", "data-icons-only:**:data-[slot=segmented-control-label]:sr-only data-icons-only:**:data-[slot=segmented-control-count]:sr-only"] } }
|
|
55
61
|
}
|
|
56
62
|
});
|
|
@@ -216,11 +222,14 @@ function useIconsOnlyWarning(ref, iconsOnlyBelow) {
|
|
|
216
222
|
}
|
|
217
223
|
}, [ref, iconsOnlyBelow]);
|
|
218
224
|
}
|
|
219
|
-
function SegmentedControl({ disabled = false, iconsOnlyBelow, variant = "default", className, ref, ...props }) {
|
|
225
|
+
function SegmentedControl({ disabled = false, iconsOnlyBelow: iconsOnlyBelowProp, variant = "default", className, ref, ...props }) {
|
|
226
|
+
const inFitToolbar = useInFitToolbar();
|
|
227
|
+
const iconsOnlyBelow = inFitToolbar ? void 0 : iconsOnlyBelowProp;
|
|
220
228
|
const preset = isIconsOnlyPreset(iconsOnlyBelow);
|
|
221
229
|
const { root } = segmentedControl({
|
|
222
230
|
iconsOnlyBelow: preset ? iconsOnlyBelow : void 0,
|
|
223
231
|
iconsOnlyMeasured: iconsOnlyBelow !== void 0 && !preset ? true : void 0,
|
|
232
|
+
inFitToolbar: inFitToolbar || void 0,
|
|
224
233
|
variant
|
|
225
234
|
});
|
|
226
235
|
const rootRef = useRef(null);
|
|
@@ -242,7 +251,7 @@ function SegmentedControl({ disabled = false, iconsOnlyBelow, variant = "default
|
|
|
242
251
|
else if (end > track.scrollLeft + track.clientWidth) track.scrollLeft = end - track.clientWidth;
|
|
243
252
|
}, [overflowing, value]);
|
|
244
253
|
return /* @__PURE__ */ jsx(SegmentedControlIconsOnlyContext, {
|
|
245
|
-
value: iconsOnlyBelow !== void 0,
|
|
254
|
+
value: inFitToolbar || iconsOnlyBelow !== void 0,
|
|
246
255
|
children: /* @__PURE__ */ jsx(RadioGroup, {
|
|
247
256
|
ref: setRef,
|
|
248
257
|
disabled,
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { SelectionToolbar, SelectionToolbarAction, SelectionToolbarActionProps, SelectionToolbarActions, SelectionToolbarActionsProps, SelectionToolbarClose, SelectionToolbarCloseProps, SelectionToolbarCount, SelectionToolbarCountProps, SelectionToolbarCountValue, SelectionToolbarCountValueProps, SelectionToolbarDock, SelectionToolbarDockProps, SelectionToolbarHint, SelectionToolbarHintProps, SelectionToolbarItem, SelectionToolbarItemProps, SelectionToolbarMore, SelectionToolbarMoreItems, SelectionToolbarMoreProps, SelectionToolbarProps } from "./selection-toolbar.mjs";
|
|
2
|
+
export { SelectionToolbar, SelectionToolbarAction, type SelectionToolbarActionProps, SelectionToolbarActions, type SelectionToolbarActionsProps, SelectionToolbarClose, type SelectionToolbarCloseProps, SelectionToolbarCount, type SelectionToolbarCountProps, SelectionToolbarCountValue, type SelectionToolbarCountValueProps, SelectionToolbarDock, type SelectionToolbarDockProps, SelectionToolbarHint, type SelectionToolbarHintProps, SelectionToolbarItem, type SelectionToolbarItemProps, SelectionToolbarMore, SelectionToolbarMoreItems, type SelectionToolbarMoreProps, type SelectionToolbarProps };
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { ButtonProps } from "../button/button.mjs";
|
|
2
|
+
import "../button/index.mjs";
|
|
3
|
+
import { FitToolbarGroupProps, FitToolbarMoreItems, FitToolbarProps } from "../fit-toolbar/fit-toolbar.mjs";
|
|
4
|
+
import "../fit-toolbar/index.mjs";
|
|
5
|
+
import { ReactElement, ReactNode } from "react";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
|
+
//#region src/components/selection-toolbar/selection-toolbar.d.ts
|
|
8
|
+
export type SelectionToolbarDockProps = useRender.ComponentProps<"div">;
|
|
9
|
+
/**
|
|
10
|
+
* Where the toolbar floats: centered, 12px above the bottom of the list or
|
|
11
|
+
* conversation it sits in (plus the safe area), 20px from its sides. Its
|
|
12
|
+
* parent must be positioned.
|
|
13
|
+
*/
|
|
14
|
+
export declare function SelectionToolbarDock({ className, render, ...props }: SelectionToolbarDockProps): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
15
|
+
export type SelectionToolbarProps = Omit<FitToolbarProps, "wrap" | "orientation">;
|
|
16
|
+
/**
|
|
17
|
+
* The floating toolbar for selected items (messages, tasks): the count, an
|
|
18
|
+
* optional hint, the actions on the selection, More while some are out of
|
|
19
|
+
* the row, then ×. One row at any width: what doesn't fit gives way, measured
|
|
20
|
+
* in the width it floats in, and never wraps. A `role="toolbar"`, one Tab
|
|
21
|
+
* stop with the arrow keys inside: give it an `aria-label`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function SelectionToolbar({ className, ...props }: SelectionToolbarProps): import("react").JSX.Element;
|
|
24
|
+
export type SelectionToolbarCountProps = useRender.ComponentProps<"span">;
|
|
25
|
+
/**
|
|
26
|
+
* What the actions act on ("3 selected"), first. Announced when it changes.
|
|
27
|
+
* Put the number in `SelectionToolbarCountValue`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function SelectionToolbarCount({ className, render, ...props }: SelectionToolbarCountProps): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
30
|
+
export type SelectionToolbarCountValueProps = useRender.ComponentProps<"span">;
|
|
31
|
+
/** The number in the count, in Space Mono. */
|
|
32
|
+
export declare function SelectionToolbarCountValue({ className, render, ...props }: SelectionToolbarCountValueProps): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
33
|
+
export type SelectionToolbarHintProps = useRender.ComponentProps<"span">;
|
|
34
|
+
/**
|
|
35
|
+
* A short line after the count, such as "1 will be skipped". The first to
|
|
36
|
+
* give way: it is then read by screen readers only.
|
|
37
|
+
*/
|
|
38
|
+
export declare function SelectionToolbarHint({ className, render, ...props }: SelectionToolbarHintProps): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
39
|
+
export type SelectionToolbarItemProps = {
|
|
40
|
+
/** The control, such as `<Checkbox />`. It keeps its own role and keys. */
|
|
41
|
+
children: ReactElement<Record<string, unknown>>;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Any other control of the toolbar, such as a thread's select-all checkbox
|
|
45
|
+
* before the count, so the arrow keys reach it. It takes the toolbar's focus
|
|
46
|
+
* handling only: the control keeps its role and its own keys.
|
|
47
|
+
*/
|
|
48
|
+
export declare function SelectionToolbarItem({ children }: SelectionToolbarItemProps): import("react").JSX.Element;
|
|
49
|
+
export type SelectionToolbarActionsProps = Omit<FitToolbarGroupProps, "wrapOrder" | "firstLine" | "collapseOrder" | "collapsed">;
|
|
50
|
+
/** The actions on the selection, in one row. */
|
|
51
|
+
export declare function SelectionToolbarActions({ className, ...props }: SelectionToolbarActionsProps): import("react").JSX.Element;
|
|
52
|
+
export type SelectionToolbarActionProps = Omit<ButtonProps, "variant" | "size" | "children"> & {
|
|
53
|
+
/** The action's 14px icon. */
|
|
54
|
+
icon: ReactNode;
|
|
55
|
+
/** The label. While only the icon shows, the label is its accessible name and its tooltip. */
|
|
56
|
+
children: ReactNode;
|
|
57
|
+
/** Moves into More before the labels give way, the last first. */
|
|
58
|
+
secondary?: boolean;
|
|
59
|
+
} & ({
|
|
60
|
+
menu?: false;
|
|
61
|
+
/**
|
|
62
|
+
* What the action is in More's menu while it is there. By default a
|
|
63
|
+
* `DropdownMenuItem` with its icon and label that calls its `onClick`.
|
|
64
|
+
*/
|
|
65
|
+
moreItem?: ReactNode;
|
|
66
|
+
} | {
|
|
67
|
+
/** The action opens a menu: a 12px chevron follows the label. Open the menu upward. */
|
|
68
|
+
menu: true;
|
|
69
|
+
/**
|
|
70
|
+
* Required: its menu in More's (a `DropdownMenuSubmenu` with the same
|
|
71
|
+
* choices). Its `onClick` only opens its own menu, so it has no
|
|
72
|
+
* default, and without one it would vanish into More.
|
|
73
|
+
*/
|
|
74
|
+
moreItem: ReactNode;
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* One action on the selection: a 14px icon and a label, an `md` ghost button
|
|
78
|
+
* with a mouse on a desktop, a 44px bar button showing its icon alone on a
|
|
79
|
+
* phone and a touch screen.
|
|
80
|
+
*/
|
|
81
|
+
export declare function SelectionToolbarAction({ icon, children, secondary, menu, moreItem, className, onClick, disabled, ...props }: SelectionToolbarActionProps): import("react").JSX.Element;
|
|
82
|
+
export type SelectionToolbarMoreProps = Omit<ButtonProps, "variant" | "size" | "aria-label"> & {
|
|
83
|
+
/** Its accessible name, such as "More actions". */
|
|
84
|
+
"aria-label": string;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* More, after the actions, shown only while some are in it. Render it as a
|
|
88
|
+
* `DropdownMenuTrigger` whose menu opens upward (`side="top"`), with
|
|
89
|
+
* `SelectionToolbarMoreItems` in the menu.
|
|
90
|
+
*/
|
|
91
|
+
export declare function SelectionToolbarMore({ className, children, ...props }: SelectionToolbarMoreProps): import("react").JSX.Element;
|
|
92
|
+
/** The actions in More, in their order, each as its `moreItem`: put it in More's menu. */
|
|
93
|
+
export declare const SelectionToolbarMoreItems: typeof FitToolbarMoreItems;
|
|
94
|
+
export type SelectionToolbarCloseProps = Omit<ButtonProps, "variant" | "size" | "aria-label"> & {
|
|
95
|
+
/** Its accessible name, such as "Cancel". */
|
|
96
|
+
"aria-label": string;
|
|
97
|
+
};
|
|
98
|
+
/** ×, last: ends the selection, as Escape does. */
|
|
99
|
+
export declare function SelectionToolbarClose({ className, children, ...props }: SelectionToolbarCloseProps): import("react").JSX.Element;
|
|
100
|
+
//#endregion
|