@botiverse/raft-ui 0.80.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 +59 -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 +17 -3
- package/dist/components/composer/composer-drop-overlay.d.mts +9 -4
- package/dist/components/composer/composer-drop-overlay.mjs +2 -5
- package/dist/components/composer/sortable-composer-attachments.mjs +2 -3
- package/dist/components/drag/drag-lift.d.mts +10 -6
- package/dist/components/drag/drag-lift.mjs +11 -9
- 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/scroll-area.css +15 -2
- 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/components/tabs/tabs.mjs +2 -3
- package/dist/components/task-dnd/task-dnd.d.mts +5 -1
- 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,62 @@
|
|
|
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
|
+
|
|
39
|
+
## [0.81.0](https://github.com/botiverse/raft-design/compare/v0.80.0...v0.81.0) (2026-11-09)
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- **ScrollArea's scrollbars paint over everything inside the area**: the gutters layer is at the highest `z-index`, and the area's root is a stacking context of its own (`isolation: isolate`), so a sticky heading or any other positioned content inside the area, whatever its `z-index`, no longer covers the thumb, with sticky and absolute gutters alike, and the scrollbars still never paint over anything outside the area.
|
|
44
|
+
- Why: in the Raft app's activity list each day's sticky heading (an opaque background at z-15) painted over the thumb as it slid by, cutting it into pieces, while the gutters were at z-1 (Artea, #proj-raft-ui:21bae128). Starting the scrollbar below the stuck heading (`railInset`) fixed only the heading at the top, not the ones scrolling past.
|
|
45
|
+
- Affects: content inside a ScrollArea can no longer cover anything outside it, whatever its `z-index`: a popup, a menu or a dragged copy rendered in place inside an area stacks with the area. Render those through a portal (raft-ui's overlays do, and now `DragLift` by default, below). The scrollbars' strip at the edge now takes the pointer over positioned content there too, as it already did over the rest. How the scrollbars look is unchanged.
|
|
46
|
+
- Docs: https://raft-design.botiverse.build/components/scroll-area/
|
|
47
|
+
- **`DragLift` renders the copy in `document.body` by default**: the lifted copy goes through a portal to the body unless `container` names another element, or `null` keeps it in place; the portal keeps the theme scope it was rendered in. `TaskDragOverlay` follows, as `SortableTabsList` and `SortableComposerAttachments` already did.
|
|
48
|
+
- Why: in place inside a ScrollArea, now a stacking context, the copy couldn't rise above anything outside the area. On the Raft app's Tasks board a dragged card was cut off by the left rail and covered by the top bar (`TaskDragOverlay` with no `container`).
|
|
49
|
+
- Affects: a `DragLift` or `TaskDragOverlay` without `container` now renders its copy in the body: CSS that styles the copy through an ancestor of the item (`.board [data-slot=drag-lift]`) no longer reaches it, and neither do CSS variables set on that ancestor; style the copy through its own children. The writing direction (`dir`) is carried over, below. Pass `container={null}` for the old in-place copy. How the copy looks is unchanged.
|
|
50
|
+
- Docs: https://raft-design.botiverse.build/components/drag/#anatomy
|
|
51
|
+
- **In a right-to-left layout the dragged copy keeps its direction**: `DragLift`'s portal carries the item's computed writing direction (`dir`) to the body, as it carries the theme scope.
|
|
52
|
+
- Why: in the body, the copy took its direction from `<html>`, so an item dragged out of a right-to-left container came out left-to-right (Jasper's review of #1094).
|
|
53
|
+
- Affects: a copy of an item in a `dir="rtl"` container now lays out right-to-left. Nothing else around the item reaches the copy (font, colour, a container's custom properties); the docs now say so.
|
|
54
|
+
- Docs: https://raft-design.botiverse.build/components/drag/#anatomy
|
|
55
|
+
- **ChoiceList's row actions keep clear of the scrollbar**: in a list that scrolls (search on, or `fill`), a row's action sits 12px from the end instead of 4px, and rows with an action keep their text 52px from the end instead of 44px.
|
|
56
|
+
- Why: the scrollbar's 16px strip at the end of a ScrollArea now paints over and takes the pointer from everything in the area; the last 8px of each 32px action lay under it, so a click there paged the list instead.
|
|
57
|
+
- Affects: in a scrolling ChoiceList, each action moves 8px toward the start, and a long name or description cuts off 8px sooner. A list that doesn't scroll is unchanged.
|
|
58
|
+
- Docs: https://raft-design.botiverse.build/components/choice-list/#behavior
|
|
59
|
+
|
|
1
60
|
## [0.80.0](https://github.com/botiverse/raft-design/compare/v0.79.0...v0.80.0) (2026-11-09)
|
|
2
61
|
|
|
3
62
|
### Changed
|
|
@@ -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)]",
|
|
@@ -31,14 +32,27 @@ const choiceList = tv({
|
|
|
31
32
|
footer: ["shrink-0 border-t border-line-seam p-1"]
|
|
32
33
|
},
|
|
33
34
|
variants: {
|
|
34
|
-
scroll: { true: {
|
|
35
|
+
scroll: { true: {
|
|
36
|
+
scroller: ["max-h-72"],
|
|
37
|
+
action: ["pr-3"]
|
|
38
|
+
} },
|
|
35
39
|
fill: { true: {
|
|
36
40
|
root: ["flex min-h-0 flex-1 flex-col"],
|
|
37
41
|
frame: ["min-h-0 flex-1"],
|
|
38
|
-
scroller: ["flex-1"]
|
|
42
|
+
scroller: ["flex-1"],
|
|
43
|
+
action: ["pr-3"]
|
|
39
44
|
} },
|
|
40
45
|
hasAction: { true: { item: ["pr-11"] } }
|
|
41
|
-
}
|
|
46
|
+
},
|
|
47
|
+
compoundVariants: [{
|
|
48
|
+
scroll: true,
|
|
49
|
+
hasAction: true,
|
|
50
|
+
class: { item: ["pr-13"] }
|
|
51
|
+
}, {
|
|
52
|
+
fill: true,
|
|
53
|
+
hasAction: true,
|
|
54
|
+
class: { item: ["pr-13"] }
|
|
55
|
+
}]
|
|
42
56
|
});
|
|
43
57
|
//#endregion
|
|
44
58
|
export { choiceList };
|
|
@@ -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,6 +1,6 @@
|
|
|
1
1
|
import { ComposerAttachmentsScrollArea } from "./composer-attachments-scroll-area.mjs";
|
|
2
2
|
import { createDragAnnouncements, dragInstructions } from "../drag/drag-announcements.mjs";
|
|
3
|
-
import { DragLift, useDragSiblingTransition
|
|
3
|
+
import { DragLift, useDragSiblingTransition } from "../drag/drag-lift.mjs";
|
|
4
4
|
import { useDragSensors } from "../drag/drag-sensors.mjs";
|
|
5
5
|
import { DropPlaceholder } from "../drag/drop-placeholder.mjs";
|
|
6
6
|
import { Children, createContext, isValidElement, use, useCallback, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
@@ -87,7 +87,6 @@ function SortableComposerAttachmentsRoot({ items, onReorder, children, messages,
|
|
|
87
87
|
const draftIdsRef = useRef([]);
|
|
88
88
|
const lastReorderPointerRef = useRef(null);
|
|
89
89
|
const sensors = useDragSensors();
|
|
90
|
-
const liftContainer = useLiftContainer(container);
|
|
91
90
|
const attachments = useMemo(() => attachmentsById(children), [children]);
|
|
92
91
|
const itemIds = useMemo(() => items.map(String), [items]);
|
|
93
92
|
const [announced] = useState(() => ({
|
|
@@ -186,7 +185,7 @@ function SortableComposerAttachmentsRoot({ items, onReorder, children, messages,
|
|
|
186
185
|
})
|
|
187
186
|
}), /* @__PURE__ */ jsx(DragLift, {
|
|
188
187
|
className: "rounded-control",
|
|
189
|
-
container
|
|
188
|
+
container,
|
|
190
189
|
children: activeId && overlay ? overlay : null
|
|
191
190
|
})]
|
|
192
191
|
});
|
|
@@ -50,8 +50,8 @@ export declare function keepGrabInside(proxyWidth: number, inset?: number): Modi
|
|
|
50
50
|
export declare function cancelDrag(win?: Window): void;
|
|
51
51
|
/**
|
|
52
52
|
* Above every raft-ui layer (popovers 50, a stacked dialog 60, toasts and the
|
|
53
|
-
* lightbox 70) and an app's own top layers
|
|
54
|
-
*
|
|
53
|
+
* lightbox 70) and an app's own top layers, among the layers rendered in
|
|
54
|
+
* `document.body`, where the copy goes by default. dnd-kit's own default.
|
|
55
55
|
*/
|
|
56
56
|
export declare const DRAG_LIFT_Z_INDEX = 999;
|
|
57
57
|
export type DragLiftProps = {
|
|
@@ -74,10 +74,14 @@ export type DragLiftProps = {
|
|
|
74
74
|
*/
|
|
75
75
|
autoScroll?: boolean;
|
|
76
76
|
/**
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
77
|
+
* Where the copy renders: `document.body` by default, so no ancestor holds
|
|
78
|
+
* it in, neither a stacking context (a ScrollArea, an `isolate`) it couldn't
|
|
79
|
+
* rise out of nor a transform (a drawer, a dialog) that would offset a
|
|
80
|
+
* `position: fixed` copy. Another element renders it there, and `null` in
|
|
81
|
+
* place. It keeps the theme scope it was rendered in (`light` / `dark`), as
|
|
82
|
+
* raft-ui's portals do, and the item's writing direction (`dir`). Nothing
|
|
83
|
+
* else is inherited from where it was picked up (font, colour, custom
|
|
84
|
+
* properties a container sets): give the copy its own styles.
|
|
81
85
|
*/
|
|
82
86
|
container?: Element | DocumentFragment | null;
|
|
83
87
|
/** @default DRAG_LIFT_Z_INDEX (999) */
|
|
@@ -110,17 +110,16 @@ function cancelDrag(win = window) {
|
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* Above every raft-ui layer (popovers 50, a stacked dialog 60, toasts and the
|
|
113
|
-
* lightbox 70) and an app's own top layers
|
|
114
|
-
*
|
|
113
|
+
* lightbox 70) and an app's own top layers, among the layers rendered in
|
|
114
|
+
* `document.body`, where the copy goes by default. dnd-kit's own default.
|
|
115
115
|
*/
|
|
116
116
|
const DRAG_LIFT_Z_INDEX = 999;
|
|
117
117
|
const noSubscribe = () => () => {};
|
|
118
118
|
const clientBody = () => document.body;
|
|
119
119
|
const serverBody = () => null;
|
|
120
120
|
/**
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* matches), `null` is in place, and an element is that element.
|
|
121
|
+
* Where the copy goes: `undefined` is the body (once on the client, so
|
|
122
|
+
* hydration matches), `null` is in place, and an element is that element.
|
|
124
123
|
*/
|
|
125
124
|
function useLiftContainer(container) {
|
|
126
125
|
const body = useSyncExternalStore(noSubscribe, clientBody, serverBody);
|
|
@@ -141,8 +140,10 @@ function useLiftContainer(container) {
|
|
|
141
140
|
function DragLift({ children, className, style, modifiers, autoScroll = true, container, zIndex = 999 }) {
|
|
142
141
|
const { lift } = drag();
|
|
143
142
|
const { resolvedMode } = useTheme();
|
|
143
|
+
const target = useLiftContainer(container);
|
|
144
144
|
const reduced = useSyncExternalStore(subscribeReducedMotion, reducedMotion, () => false);
|
|
145
|
-
const { activatorEvent } = useDndContext();
|
|
145
|
+
const { activatorEvent, activeNode } = useDndContext();
|
|
146
|
+
const dir = useMemo(() => activeNode ? getComputedStyle(activeNode).direction : void 0, [activeNode]);
|
|
146
147
|
const liftStyle = useMemo(() => isKeyboardEvent(activatorEvent) ? {
|
|
147
148
|
translate: KEYBOARD_OFFSET,
|
|
148
149
|
...style
|
|
@@ -162,11 +163,12 @@ function DragLift({ children, className, style, modifiers, autoScroll = true, co
|
|
|
162
163
|
})
|
|
163
164
|
})
|
|
164
165
|
});
|
|
165
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DragSession, { autoScroll }),
|
|
166
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DragSession, { autoScroll }), target ? createPortal(/* @__PURE__ */ jsx("div", {
|
|
166
167
|
"data-slot": "drag-lift-portal",
|
|
167
168
|
className: cn("contents", resolvedMode),
|
|
169
|
+
dir,
|
|
168
170
|
children: overlay
|
|
169
|
-
}),
|
|
171
|
+
}), target) : overlay] });
|
|
170
172
|
}
|
|
171
173
|
/** Where the pointer is during a drag: auto-scroll and the refusal hint read it. */
|
|
172
174
|
const pointer = {
|
|
@@ -273,4 +275,4 @@ function autoScrollAt(x, y) {
|
|
|
273
275
|
if (dy) window.scrollBy(0, dy);
|
|
274
276
|
}
|
|
275
277
|
//#endregion
|
|
276
|
-
export { DRAG_AUTO_SCROLL_ZONE_PX, DRAG_KEYBOARD_OFFSET_PX, DRAG_LIFT_Z_INDEX, DRAG_SETTLE, DRAG_SIBLING_TRANSITION, DROP_GLIDE, DragLift, LIFT_CLASS, ORIGIN_OPACITY, autoScrollAt, cancelDrag, dragPointer, keepGrabInside, useDragSiblingTransition
|
|
278
|
+
export { DRAG_AUTO_SCROLL_ZONE_PX, DRAG_KEYBOARD_OFFSET_PX, DRAG_LIFT_Z_INDEX, DRAG_SETTLE, DRAG_SIBLING_TRANSITION, DROP_GLIDE, DragLift, LIFT_CLASS, ORIGIN_OPACITY, autoScrollAt, cancelDrag, dragPointer, keepGrabInside, useDragSiblingTransition };
|
|
@@ -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
|
]
|
|
@@ -452,11 +452,24 @@
|
|
|
452
452
|
resize: vertical;
|
|
453
453
|
}
|
|
454
454
|
|
|
455
|
-
/*
|
|
455
|
+
/*
|
|
456
|
+
* The scrollbars paint over everything in the area, as native ones do: a
|
|
457
|
+
* sticky day heading with its own background and `z-index` (z-15 in an
|
|
458
|
+
* activity list) covered the thumb as it slid by, cutting it into pieces.
|
|
459
|
+
* The root is a stacking context of its own (`isolation: isolate`), so the
|
|
460
|
+
* layer's z-index ranks it only among the area's own content and never
|
|
461
|
+
* lifts it over anything outside the area: a fixed bar, a popup. What
|
|
462
|
+
* must cover things outside the area portals out of it, as raft-ui's
|
|
463
|
+
* overlays do.
|
|
464
|
+
*/
|
|
465
|
+
.r-scroll-area {
|
|
466
|
+
isolation: isolate;
|
|
467
|
+
}
|
|
468
|
+
/* The gutters layer: out of the way of the content, but for each gutter itself; above all of it. */
|
|
456
469
|
.r-scroll-area > .r-scroll-area__gutters {
|
|
457
470
|
pointer-events: none;
|
|
458
471
|
user-select: none;
|
|
459
|
-
z-index:
|
|
472
|
+
z-index: 2147483647;
|
|
460
473
|
}
|
|
461
474
|
/*
|
|
462
475
|
* Sticky: a zero-height layer at the top of the viewport, the container's
|
|
@@ -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"],
|