@botiverse/raft-ui 0.81.0 → 0.82.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/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/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 +3 -0
- package/dist/components/list-row/list-row.recipe.mjs +1 -0
- 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/resizable/resizable.recipe.mjs +4 -4
- package/dist/components/scroll-area/use-scrollbars.mjs +2 -1
- 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 +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
## [0.82.0](https://github.com/botiverse/raft-design/compare/v0.81.0...v0.82.0) (2026-11-09)
|
|
2
|
+
|
|
3
|
+
### Changed
|
|
4
|
+
|
|
5
|
+
- **OtterIndicator uses Ottie's approved four poses**: relaxed side-lying, quiet typing, a puzzled head tilt with a question mark, and one celebratory hop. The SVG props and ref remain supported. It pauses outside the viewport and in hidden documents; reduced motion shows a still. The HTML art layer sizes from the SVG box so Safari/WebKit scales it correctly at 40px and larger.
|
|
6
|
+
- Why: the previous unrelated otter drawing and sleeping wait pose did not match Ottie or the recent-activity card (Artea's approved B study).
|
|
7
|
+
- Affects: consumers of OtterIndicator, including Raft's recent-activity card. Artwork loads as separate transparent WebP files only for a displayed status; there is no frame timer or per-frame React update.
|
|
8
|
+
- Docs: https://raft-design.botiverse.build/components/steps/#ottie-illustration
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- **`ComposerDropOverlayPrompt` takes its text as `children`, which is required**: the icon cluster stays, and the text under it is what you pass. It no longer falls back to the built-in "Drop files to attach", and children no longer replace the icons.
|
|
13
|
+
- Why: the component library carried product copy in English that no app could translate (Remy's helper-text sweep, #proj-workspace:#250).
|
|
14
|
+
- Affects: `<ComposerDropOverlayPrompt />` no longer type-checks; pass the text, e.g. `<ComposerDropOverlayPrompt>{t("dropToAttach")}</ComposerDropOverlayPrompt>`. A caller that passed children for a label without icons uses `ComposerDropOverlayLabel` instead.
|
|
15
|
+
- Docs: https://raft-design.botiverse.build/components/composer/
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Data parts beside the explanation parts**: three additive parts, so data no longer has to sit in a slot meant for a sentence that explains. Nothing existing changes: no prop, part or style is renamed or restyled.
|
|
20
|
+
- `ListRowSubtitle`: data about a row's subject under its title (an agent's description, a channel's topic, an app's byline), in the title's ink at 400 and `text-footnote`. It follows the row's tone and disabled state with the title. `ListRowDescription` stays the place for a setting's consequence.
|
|
21
|
+
- ChoiceList items take `meta`: lines of data people compare across rows (a quota, free disk, a count, a status), in `text-footnote` in `foreground-muted` as the description is, after the `description` lines. A row still draws at most two lines in all, the description's first; a meta line has a description line's height, so moving a line from one to the other doesn't move the rows. Radios and checkboxes are described by the description lines, then the meta lines.
|
|
22
|
+
- `MessageActionCardHeaderMeta`: the time on a resolved card, in Space Mono at the hint tier: a line of its own under the title, or the end of the `MessageActionCardHeaderDescription` line it is placed in ("Approved by Martin · 10:51").
|
|
23
|
+
- Why: grey text is to mean one of two things, a sentence written to explain or a component's own notes on its data (times, counts, IDs), and data people read as the content uses the body ink. Apps had put data in the explanation parts (`ListRowDescription`, a ChoiceList item's `description`, `MessageActionCardHeaderDescription`) because there was nowhere else for it; these parts give it a place before those parts are kept for explanations (Kirby, Remy's helper-text plan).
|
|
24
|
+
- Affects: nothing until an app uses them. Data moved into `ListRowSubtitle` gets darker and a size smaller than in `ListRowDescription`; data moved into a ChoiceList item's `meta` looks as it did in `description`; a time moved into `MessageActionCardHeaderMeta` is set in Space Mono at the hint tier.
|
|
25
|
+
- Docs: https://raft-design.botiverse.build/components/list-row/#data-and-explanation, https://raft-design.botiverse.build/components/choice-list/#content, https://raft-design.botiverse.build/components/message-action-card/#anatomy
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **A Resizable seam's handle no longer covers the scrollbar beside it**: the 12px handle (24px under a coarse pointer) lies over the start of the panel after the boundary instead of straddling it; its hover and focus line stays on the seam.
|
|
30
|
+
- Why: a panel's scrollbar runs along its end edge, the seam's other side, and the centered handle covered its last 6px, where the thumb is, so dragging the thumb resized the panel instead (Raft app's Activity list, #proj-raft-ui:21bae128).
|
|
31
|
+
- Affects: the handle now takes the pointer over the first 12px of the next panel (24px by touch) instead of 6px on each side. Nothing else moves.
|
|
32
|
+
- Docs: https://raft-design.botiverse.build/components/resizable/#behavior
|
|
33
|
+
|
|
34
|
+
- **ScrollArea measures in the frame after mounting, not while React commits**: where a `ResizeObserver` watches the sizes, the first read of the container's `clientHeight` and `scrollHeight` waits for the next animation frame, as every later one already did. Without a `ResizeObserver` it still measures at once.
|
|
35
|
+
- Why: the read in the commit forced a layout of the whole page each time an area mounted. Entering a server in the Raft app mounts the sidebar, the message list and the panels at once, and those reads took about 120ms of layout (InNOut's measurement, #proj-frontend:#40).
|
|
36
|
+
- Affects: the frame runs before the paint that first shows the area, so nothing on screen changes. Until it runs, an overflowing area has no thumb length and no overflow classes, and `onEdgeChange` is first called in it: code that reads them in a layout effect right after mounting finds them unset, and can call `actionsRef.measure` for a measure at once.
|
|
37
|
+
- Docs: https://raft-design.botiverse.build/components/scroll-area/
|
|
38
|
+
|
|
1
39
|
## [0.81.0](https://github.com/botiverse/raft-design/compare/v0.80.0...v0.81.0) (2026-11-09)
|
|
2
40
|
|
|
3
41
|
### Fixed
|
|
@@ -11,6 +11,14 @@ export type ChoiceListItem = {
|
|
|
11
11
|
* (null, false or "") is not drawn. Colour inside a line is the caller's.
|
|
12
12
|
*/
|
|
13
13
|
description?: ReactNode | readonly ReactNode[];
|
|
14
|
+
/**
|
|
15
|
+
* Lines of data under the description: what people compare across rows,
|
|
16
|
+
* such as a quota, free disk or a count ("120 GB free · 3 agents"), drawn
|
|
17
|
+
* as the description is (muted), after it. The row still draws at most two
|
|
18
|
+
* lines under the name, the description's first. An empty line is not
|
|
19
|
+
* drawn. Colour inside a line is the caller's.
|
|
20
|
+
*/
|
|
21
|
+
meta?: ReactNode | readonly ReactNode[];
|
|
14
22
|
/** Drawn before the radio's or checkbox's row text: an avatar, an icon. */
|
|
15
23
|
media?: ReactNode;
|
|
16
24
|
/**
|
|
@@ -18,6 +18,13 @@ function isDrawn(line) {
|
|
|
18
18
|
function descriptionLines(description) {
|
|
19
19
|
return (Array.isArray(description) ? description : [description]).filter(isDrawn);
|
|
20
20
|
}
|
|
21
|
+
function rowLines(item) {
|
|
22
|
+
const description = descriptionLines(item.description).slice(0, MAX_DESCRIPTION_LINES);
|
|
23
|
+
return {
|
|
24
|
+
description,
|
|
25
|
+
meta: descriptionLines(item.meta).slice(0, MAX_DESCRIPTION_LINES - description.length)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
21
28
|
function CutLine({ id, slot, className, children }) {
|
|
22
29
|
const ref = useOverflowTitle();
|
|
23
30
|
return /* @__PURE__ */ jsx("span", {
|
|
@@ -133,6 +140,7 @@ function ChoiceList(props) {
|
|
|
133
140
|
if (process.env.NODE_ENV === "production") return;
|
|
134
141
|
if (!ariaLabel && !ariaLabelledBy) console.warn("raft-ui: a ChoiceList has neither aria-label nor aria-labelledby.");
|
|
135
142
|
if (items.some((item) => descriptionLines(item.description).length > MAX_DESCRIPTION_LINES)) console.warn(`raft-ui: a ChoiceList item has more than ${MAX_DESCRIPTION_LINES} description lines; only the first ${MAX_DESCRIPTION_LINES} are drawn.`);
|
|
143
|
+
else if (items.some((item) => descriptionLines(item.description).length + descriptionLines(item.meta).length > MAX_DESCRIPTION_LINES)) console.warn(`raft-ui: a ChoiceList item has more than ${MAX_DESCRIPTION_LINES} description and meta lines together; only the first ${MAX_DESCRIPTION_LINES} are drawn, the description's first.`);
|
|
136
144
|
}, [
|
|
137
145
|
ariaLabel,
|
|
138
146
|
ariaLabelledBy,
|
|
@@ -166,13 +174,14 @@ function ChoiceList(props) {
|
|
|
166
174
|
};
|
|
167
175
|
const rowElement = (item) => {
|
|
168
176
|
const id = `${baseId}-${items.indexOf(item)}`;
|
|
169
|
-
const lines =
|
|
177
|
+
const { description: lines, meta } = rowLines(item);
|
|
170
178
|
const rowDisabled = disabled || item.disabled === true;
|
|
179
|
+
const describedBy = [lines.length > 0 ? `${id}-description` : null, meta.length > 0 ? `${id}-meta` : null].filter(Boolean);
|
|
171
180
|
const markProps = {
|
|
172
181
|
value: item.value,
|
|
173
182
|
disabled: item.disabled,
|
|
174
183
|
"aria-labelledby": `${id}-label`,
|
|
175
|
-
"aria-describedby":
|
|
184
|
+
"aria-describedby": describedBy.length > 0 ? describedBy.join(" ") : void 0
|
|
176
185
|
};
|
|
177
186
|
return /* @__PURE__ */ jsxs("label", {
|
|
178
187
|
"data-slot": "choice-list-item",
|
|
@@ -188,20 +197,32 @@ function ChoiceList(props) {
|
|
|
188
197
|
/* @__PURE__ */ jsxs("span", {
|
|
189
198
|
"data-slot": "choice-list-body",
|
|
190
199
|
className: slots.body(),
|
|
191
|
-
children: [
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ jsx(CutLine, {
|
|
202
|
+
id: `${id}-label`,
|
|
203
|
+
slot: "choice-list-label",
|
|
204
|
+
className: slots.label(),
|
|
205
|
+
children: item.label
|
|
206
|
+
}),
|
|
207
|
+
lines.length > 0 ? /* @__PURE__ */ jsx("span", {
|
|
208
|
+
id: `${id}-description`,
|
|
209
|
+
className: "contents",
|
|
210
|
+
children: lines.map((line, index) => /* @__PURE__ */ jsx(CutLine, {
|
|
211
|
+
slot: "choice-list-description",
|
|
212
|
+
className: slots.description(),
|
|
213
|
+
children: line
|
|
214
|
+
}, index))
|
|
215
|
+
}) : null,
|
|
216
|
+
meta.length > 0 ? /* @__PURE__ */ jsx("span", {
|
|
217
|
+
id: `${id}-meta`,
|
|
218
|
+
className: "contents",
|
|
219
|
+
children: meta.map((line, index) => /* @__PURE__ */ jsx(CutLine, {
|
|
220
|
+
slot: "choice-list-meta",
|
|
221
|
+
className: slots.meta(),
|
|
222
|
+
children: line
|
|
223
|
+
}, index))
|
|
224
|
+
}) : null
|
|
225
|
+
]
|
|
205
226
|
})
|
|
206
227
|
]
|
|
207
228
|
}, item.value);
|
|
@@ -22,6 +22,7 @@ const choiceList = tv({
|
|
|
22
22
|
body: ["grid min-w-0 flex-1 gap-0.5"],
|
|
23
23
|
label: ["truncate font-semibold text-foreground", "in-data-disabled:text-foreground-disabled"],
|
|
24
24
|
description: ["block truncate font-sans text-footnote font-normal text-foreground-muted", "in-data-disabled:text-foreground-disabled"],
|
|
25
|
+
meta: ["block truncate font-sans text-footnote font-normal text-foreground-muted", "in-data-disabled:text-foreground-disabled"],
|
|
25
26
|
action: [
|
|
26
27
|
"relative z-10 col-start-2 flex h-lh items-center self-start pr-1",
|
|
27
28
|
"mt-option-inset pointer-coarse:mt-[calc((--spacing(11)-1lh)/2)]",
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import { useRender } from "@base-ui/react/use-render";
|
|
2
3
|
//#region src/components/composer/composer-drop-overlay.d.ts
|
|
3
4
|
export type ComposerDropOverlayProps = useRender.ComponentProps<"div">;
|
|
4
|
-
export declare function ComposerDropOverlay({ className, render, ...props }: ComposerDropOverlayProps):
|
|
5
|
+
export declare function ComposerDropOverlay({ className, render, ...props }: ComposerDropOverlayProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
5
6
|
export type ComposerDropOverlayLabelProps = useRender.ComponentProps<"span">;
|
|
6
|
-
export declare function ComposerDropOverlayLabel({ className, render, ...props }: ComposerDropOverlayLabelProps):
|
|
7
|
-
export type ComposerDropOverlayPromptProps = ComposerDropOverlayLabelProps
|
|
8
|
-
|
|
7
|
+
export declare function ComposerDropOverlayLabel({ className, render, ...props }: ComposerDropOverlayLabelProps): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
8
|
+
export type ComposerDropOverlayPromptProps = Omit<ComposerDropOverlayLabelProps, "children"> & {
|
|
9
|
+
/** What the prompt says, such as "Drop files to attach": the caller's copy, in its locale. */
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
};
|
|
12
|
+
/** The label with the files-and-upload icon cluster above the caller's text. */
|
|
13
|
+
export declare function ComposerDropOverlayPrompt({ children, ...props }: ComposerDropOverlayPromptProps): React.JSX.Element;
|
|
9
14
|
//#endregion
|
|
@@ -28,12 +28,9 @@ function ComposerDropOverlayLabel({ className, render, ...props }) {
|
|
|
28
28
|
props: mergeProps(defaultProps, props)
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
+
/** The label with the files-and-upload icon cluster above the caller's text. */
|
|
31
32
|
function ComposerDropOverlayPrompt({ children, ...props }) {
|
|
32
33
|
const { dropOverlayIcon, dropOverlayIconCluster } = composerDropOverlay();
|
|
33
|
-
if (children) return /* @__PURE__ */ jsx(ComposerDropOverlayLabel, {
|
|
34
|
-
...props,
|
|
35
|
-
children
|
|
36
|
-
});
|
|
37
34
|
return /* @__PURE__ */ jsxs(ComposerDropOverlayLabel, {
|
|
38
35
|
...props,
|
|
39
36
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
@@ -53,7 +50,7 @@ function ComposerDropOverlayPrompt({ children, ...props }) {
|
|
|
53
50
|
children: /* @__PURE__ */ jsx(Image, { className: "text-foreground-muted" })
|
|
54
51
|
})
|
|
55
52
|
]
|
|
56
|
-
}), /* @__PURE__ */ jsx("span", { children
|
|
53
|
+
}), /* @__PURE__ */ jsx("span", { children })]
|
|
57
54
|
});
|
|
58
55
|
}
|
|
59
56
|
//#endregion
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { ListRow, ListRowBody, ListRowBodyProps, ListRowBottom, ListRowBottomProps, ListRowChevron, ListRowChevronProps, ListRowDescription, ListRowDescriptionProps, ListRowGroup, ListRowGroupProps, ListRowIcon, ListRowIconProps, ListRowMeta, ListRowMetaProps, ListRowProps, ListRowTitle, ListRowTitleProps, ListRowTop, ListRowTopProps, ListRowValue, ListRowValueProps } from "./list-row.mjs";
|
|
2
|
-
export { ListRow, ListRowBody, type ListRowBodyProps, ListRowBottom, type ListRowBottomProps, ListRowChevron, type ListRowChevronProps, ListRowDescription, type ListRowDescriptionProps, ListRowGroup, type ListRowGroupProps, ListRowIcon, type ListRowIconProps, ListRowMeta, type ListRowMetaProps, type ListRowProps, ListRowTitle, type ListRowTitleProps, ListRowTop, type ListRowTopProps, ListRowValue, type ListRowValueProps };
|
|
1
|
+
import { ListRow, ListRowBody, ListRowBodyProps, ListRowBottom, ListRowBottomProps, ListRowChevron, ListRowChevronProps, ListRowDescription, ListRowDescriptionProps, ListRowGroup, ListRowGroupProps, ListRowIcon, ListRowIconProps, ListRowMeta, ListRowMetaProps, ListRowProps, ListRowSubtitle, ListRowSubtitleProps, ListRowTitle, ListRowTitleProps, ListRowTop, ListRowTopProps, ListRowValue, ListRowValueProps } from "./list-row.mjs";
|
|
2
|
+
export { ListRow, ListRowBody, type ListRowBodyProps, ListRowBottom, type ListRowBottomProps, ListRowChevron, type ListRowChevronProps, ListRowDescription, type ListRowDescriptionProps, ListRowGroup, type ListRowGroupProps, ListRowIcon, type ListRowIconProps, ListRowMeta, type ListRowMetaProps, type ListRowProps, ListRowSubtitle, type ListRowSubtitleProps, ListRowTitle, type ListRowTitleProps, ListRowTop, type ListRowTopProps, ListRowValue, type ListRowValueProps };
|
|
@@ -47,6 +47,15 @@ export declare function ListRowBottom({ className, render, ...props }: ListRowBo
|
|
|
47
47
|
export type ListRowTitleProps = useRender.ComponentProps<"span">;
|
|
48
48
|
/** 16/24 600 on one line; the row's tone sets its weight and ink. */
|
|
49
49
|
export declare function ListRowTitle({ className, render, ...props }: ListRowTitleProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
50
|
+
export type ListRowSubtitleProps = useRender.ComponentProps<"span">;
|
|
51
|
+
/**
|
|
52
|
+
* Data about the row's subject on the line under the title: an agent's or a
|
|
53
|
+
* channel's description, a channel's topic, a person's role, an app's byline.
|
|
54
|
+
* 400 in the row's ink, a size under the title, cut to one line. A setting's
|
|
55
|
+
* consequence goes in `ListRowDescription`; a time, a date or a gray count in
|
|
56
|
+
* `ListRowMeta`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function ListRowSubtitle({ className, render, ...props }: ListRowSubtitleProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
50
59
|
export type ListRowDescriptionProps = useRender.ComponentProps<"span"> & {
|
|
51
60
|
/** Let the text run onto more lines instead of truncating: a setting's
|
|
52
61
|
* consequence. */
|
|
@@ -109,6 +109,25 @@ function ListRowTitle({ className, render, ...props }) {
|
|
|
109
109
|
props: mergeProps(defaultProps, props)
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Data about the row's subject on the line under the title: an agent's or a
|
|
114
|
+
* channel's description, a channel's topic, a person's role, an app's byline.
|
|
115
|
+
* 400 in the row's ink, a size under the title, cut to one line. A setting's
|
|
116
|
+
* consequence goes in `ListRowDescription`; a time, a date or a gray count in
|
|
117
|
+
* `ListRowMeta`.
|
|
118
|
+
*/
|
|
119
|
+
function ListRowSubtitle({ className, render, ...props }) {
|
|
120
|
+
const { subtitle } = listRow();
|
|
121
|
+
const defaultProps = {
|
|
122
|
+
"data-slot": "list-row-subtitle",
|
|
123
|
+
className: subtitle({ className })
|
|
124
|
+
};
|
|
125
|
+
return useRender({
|
|
126
|
+
defaultTagName: "span",
|
|
127
|
+
render,
|
|
128
|
+
props: mergeProps(defaultProps, props)
|
|
129
|
+
});
|
|
130
|
+
}
|
|
112
131
|
/** The preview (who spoke first: "Wug: …") or a setting's consequence, 14/20 ink-2. */
|
|
113
132
|
function ListRowDescription({ className, render, wrap = false, ...props }) {
|
|
114
133
|
const { description } = listRow({ wrap });
|
|
@@ -164,4 +183,4 @@ function ListRowChevron({ className, render, ...props }) {
|
|
|
164
183
|
});
|
|
165
184
|
}
|
|
166
185
|
//#endregion
|
|
167
|
-
export { ListRow, ListRowBody, ListRowBottom, ListRowChevron, ListRowDescription, ListRowGroup, ListRowIcon, ListRowMeta, ListRowTitle, ListRowTop, ListRowValue };
|
|
186
|
+
export { ListRow, ListRowBody, ListRowBottom, ListRowChevron, ListRowDescription, ListRowGroup, ListRowIcon, ListRowMeta, ListRowSubtitle, ListRowTitle, ListRowTop, ListRowValue };
|
|
@@ -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[];
|
|
@@ -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[];
|
|
@@ -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[];
|
|
@@ -25,6 +25,7 @@ const listRow = tv({
|
|
|
25
25
|
"text-body font-semibold",
|
|
26
26
|
"group-data-[tone=unread]/list-row:font-bold"
|
|
27
27
|
],
|
|
28
|
+
subtitle: ["min-w-0 flex-1 truncate", "text-footnote font-normal text-(--list-row-ink)"],
|
|
28
29
|
description: ["min-w-0 flex-1 truncate", "text-callout text-(--list-row-ink-2)"],
|
|
29
30
|
meta: ["min-w-0 truncate", "font-mono text-mono-meta font-normal tabular-nums text-(--list-row-ink-3)"],
|
|
30
31
|
value: ["max-w-[45%] shrink-0 truncate", "text-subhead text-(--list-row-ink-3)"],
|
|
@@ -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",
|
|
@@ -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"],
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/components/steps/otter-animation-visibility.ts
|
|
2
|
+
/** One observer/listener per document, regardless of the number of illustrations. */
|
|
3
|
+
const documents = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
function observeOtterAnimation(node) {
|
|
5
|
+
const doc = node.ownerDocument;
|
|
6
|
+
let manager = documents.get(doc);
|
|
7
|
+
if (!manager) {
|
|
8
|
+
const visible = /* @__PURE__ */ new Map();
|
|
9
|
+
const update = (element, intersects) => {
|
|
10
|
+
element.dataset.animate = String(intersects && !doc.hidden);
|
|
11
|
+
};
|
|
12
|
+
const onVisibility = () => {
|
|
13
|
+
for (const [element, intersects] of visible) update(element, intersects);
|
|
14
|
+
};
|
|
15
|
+
const Observer = doc.defaultView?.IntersectionObserver;
|
|
16
|
+
const observer = Observer ? new Observer((entries) => {
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
const element = entry.target;
|
|
19
|
+
if (!visible.has(element)) continue;
|
|
20
|
+
visible.set(element, entry.isIntersecting);
|
|
21
|
+
update(element, entry.isIntersecting);
|
|
22
|
+
}
|
|
23
|
+
}) : null;
|
|
24
|
+
doc.addEventListener("visibilitychange", onVisibility);
|
|
25
|
+
manager = { observe(element) {
|
|
26
|
+
visible.set(element, !observer);
|
|
27
|
+
update(element, !observer);
|
|
28
|
+
observer?.observe(element);
|
|
29
|
+
return () => {
|
|
30
|
+
observer?.unobserve(element);
|
|
31
|
+
visible.delete(element);
|
|
32
|
+
delete element.dataset.animate;
|
|
33
|
+
if (visible.size === 0) {
|
|
34
|
+
observer?.disconnect();
|
|
35
|
+
doc.removeEventListener("visibilitychange", onVisibility);
|
|
36
|
+
documents.delete(doc);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
} };
|
|
40
|
+
documents.set(doc, manager);
|
|
41
|
+
}
|
|
42
|
+
return manager.observe(node);
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { observeOtterAnimation };
|