@botiverse/raft-ui 0.20.0 → 0.21.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 +105 -0
- package/codemods/button-sizes.mjs +340 -0
- package/dist/cn.mjs +8 -1
- package/dist/foundation.css +13 -0
- package/dist/{index-RFu5pOr7.d.mts → index-CP05_pvu.d.mts} +41 -2
- package/dist/index.d.mts +2 -22
- package/dist/index.mjs +53 -62
- package/dist/styles.css +58 -0
- package/dist/tokens.json +24 -0
- package/dist/{touch-drag-BA_Fxs2Z.mjs → touch-drag-B7uLTWXe.mjs} +205 -26
- package/dist/wip.d.mts +100 -3
- package/dist/wip.mjs +347 -3
- package/package.json +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,108 @@
|
|
|
1
|
+
## [0.21.0](https://github.com/botiverse/raft-design/compare/v0.20.1...v0.21.0) (2026-10-22)
|
|
2
|
+
|
|
3
|
+
0.20.1 was not published to npm. This release includes its changes, listed under [0.20.1](https://github.com/botiverse/raft-design/blob/v0.21.0/packages/ui/CHANGELOG.md#0201-2026-10-22) in the changelog.
|
|
4
|
+
|
|
5
|
+
### Design System
|
|
6
|
+
|
|
7
|
+
- **Timeline rhythm**: a conversation uses three distances between its lines, measured from text to text: 8px between the rows of one turn, the message step (16px) between turns, and the section step (24px) at a boundary: either side of a date line, from the top of the list to its first line, and from the last line to the composer's frame. It applies to MessageItem, SystemMessage, SystemMessageGroupHeader, MessageListDateDivider, MessageListNotice, ThreadPanelOriginalMessage, ThreadPanelReplySummary, ThreadPanelReplyCount, ConversationPanelFooter and ThreadPanelFooter. ([#694](https://github.com/botiverse/raft-design/pull/694))
|
|
8
|
+
- Why: each part kept its own spacing, so a date line sat closer to the message above it than to the one below and looked attached to it, an event line had more space under it than over it, and the composer's frame read as touching the last message; the parts now read one rhythm from tokens, one step wider for each kind of break.
|
|
9
|
+
- Affects: new tokens `timeline-gap-message` 16px, `timeline-gap-section` 24px and `timeline-row-inset` 4px (the reach of a row's highlight above and below its text).
|
|
10
|
+
- Docs: https://raft-design.botiverse.build/foundations/spacing/#timeline-rhythm
|
|
11
|
+
- **A control and its label**: a checkbox, radio or switch sits 8px before its label, centered on the label's first line, and keeps its size wherever it sits. In a settings row with a description, both ends center on the title's first line. A tap between two options lands on the nearer one. It applies to Checkbox, RadioGroupItem and ListRow; FieldItem already followed it. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
12
|
+
- Why: a box in a `<label>` row followed the row instead of the text's line, so callers nudged it with a margin, and a settings row's ends centered on the title and description together, level with neither; the components now place the control themselves.
|
|
13
|
+
- Affects: switch 50 × 30px and checkbox and radio 20px, unchanged; 8px from control to label.
|
|
14
|
+
- Docs: https://raft-design.botiverse.build/foundations/alignment/#a-control-and-its-label
|
|
15
|
+
|
|
16
|
+
### Breaking Changes
|
|
17
|
+
|
|
18
|
+
- **ConversationPanelFooter** and **ThreadPanelFooter**: no space of their own above the composer; the end of the list sets it. ([#694](https://github.com/botiverse/raft-design/pull/694))
|
|
19
|
+
- Why: the footer's 12px stacked on whatever space the list left under its last message, so the gap to the composer differed from list to list; now the list ends with one token and the composer's frame sits a section step, 24px, under the last line.
|
|
20
|
+
- Affects: footer top padding 12px → 0; `pb-timeline-end` is 20px (the 24px section step less the last row's 4px inset).
|
|
21
|
+
- Migrate: end your message list with `pb-timeline-end` under its last row, in place of any spacer you had there; without it the composer moves 12px closer to the last message. You can also start the list with `pt-timeline-start` over its first row, so its top follows the same step.
|
|
22
|
+
- Docs: https://raft-design.botiverse.build/components/conversation-panel/
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **Timeline spacing utilities**: `pt-timeline-start` and `pb-timeline-end` for the top and end of a message list you build, and `timeline-message`, `timeline-section`, `timeline-row`, `timeline-turn` and `timeline-lead`, which the components use. All are registered with the `cn` helper, so they merge with other padding and margin classes. ([#694](https://github.com/botiverse/raft-design/pull/694))
|
|
27
|
+
- Why: a list's top and end were written by hand in each product, which is how the gaps drifted; two utilities now give the section step with the rows' own insets taken out.
|
|
28
|
+
- Affects: `timeline-start` 12px, `timeline-end` 20px, `timeline-turn` 8px, `timeline-lead` 12px, `timeline-message` 16px, `timeline-section` 24px, `timeline-row` 4px. Use only `timeline-start` and `timeline-end` in a product.
|
|
29
|
+
- Docs: https://raft-design.botiverse.build/foundations/spacing/#timeline-rhythm
|
|
30
|
+
- **`ButtonSize`** and **`DeprecatedButtonSize`** types, and the **`button-sizes` codemod**, which renames deprecated Button sizes to the size they render as. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
31
|
+
- Why: the deprecated names could only be found by hand, and `sm` and `xs` are also sizes of other components; the codemod parses TSX and renames `size` only on Buttons, the raft-ui parts that pass `size` to a Button and wrappers you name, plus `icon-sm` / `icon-xs` on any element and `size` in `buttonVariants()` calls.
|
|
32
|
+
- Affects: run `node node_modules/@botiverse/raft-ui/codemods/button-sizes.mjs <src> [--dry] [--components=MyButton]`; it renames `xs`, `sm` → `md` and `icon-xs`, `icon-sm` → `icon-md`, then lists every `sm`, `xs`, `icon-sm` and `icon-xs` it left for review. It needs `@babel/parser`, a new optional peer dependency (`pnpm add -D @babel/parser`); nothing else uses it.
|
|
33
|
+
- Docs: https://raft-design.botiverse.build/components/button/#sizes
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **Button** `size`: `xs` and `sm` are deprecated aliases of `md`, and `icon-xs` and `icon-sm` of `icon-md`, kept until raft-ui 1.0. They already rendered as those sizes, so nothing on screen changes. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
38
|
+
- Why: nine names for five sizes made a smaller button look available where there is none; a new Size by place table says which size each place takes.
|
|
39
|
+
- Affects: sizes `md` (32px), `lg`, `xl`, `icon-md` and `icon-lg`; `size` is typed `ButtonSize | DeprecatedButtonSize`, so every existing size name still type-checks. No runtime warning.
|
|
40
|
+
- Docs: https://raft-design.botiverse.build/components/button/#size-by-place
|
|
41
|
+
- **Checkbox** and **RadioGroupItem** directly in a `<label>`: the box takes one line of the label's height and centers on it, so it sits on the first line in an `items-start` row and on the one line in an `items-center` row, at any min-height. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
42
|
+
- Why: the box followed the row rather than the text's line, so it sat above the center of a line taller than 20px and callers added a `margin-top`; see A control and its label above.
|
|
43
|
+
- Affects: vertical margin `max(0, (1lh - 20px) / 2)` from the `<label>`'s type (2px on a 24px line); the box stays 20px and a `text-xs` row stays 20px tall. A `margin-top` you added to line it up is no longer needed. Set the label's type on the `<label>`, use `items-start` when the text can wrap, and give a wrapping `text-xs` label `leading-5`.
|
|
44
|
+
- Docs: https://raft-design.botiverse.build/foundations/alignment/#a-control-and-its-label
|
|
45
|
+
- **DescriptionList** `direction="inline"`: every fact is at most 24rem wide, or the row's width if that is narrower, and keeps the same 24px between facts and 8px between lines as the others. ([#697](https://github.com/botiverse/raft-design/pull/697))
|
|
46
|
+
- Why: a long value, such as a message, made its fact as wide as the row on a line of its own, so one line of facts no longer read as one flow; every fact now wraps the same way, and a long value wraps at the cap, or is cut there when the caller truncates it.
|
|
47
|
+
- Affects: fact `max-width` none → `min(100%, 24rem)` (384px); plain text longer than that wraps inside the 24rem. To cut a long value on one line instead, truncate it with an ellipsis and make the whole value available elsewhere, such as a tooltip.
|
|
48
|
+
- Docs: https://raft-design.botiverse.build/components/description-list/
|
|
49
|
+
- **ListRow** `variant="plain"` with a description: the leading icon, avatar or tile and the trailing switch, checkbox, radio, value or chevron center on the title's first line instead of the middle of the title and description. With a title alone, nothing changes. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
50
|
+
- Why: with a description the ends sat between the title and the description, level with neither and with no line of text.
|
|
51
|
+
- Affects: the ends move without changing size, so row heights are unchanged (54px on a phone for a one-line row with a switch).
|
|
52
|
+
- Docs: https://raft-design.botiverse.build/components/list-row/
|
|
53
|
+
- **MessageListDateDivider**, **SystemMessage**, **SystemMessageGroupHeader**, **MessageListNotice**, **ThreadPanelOriginalMessage**, **ThreadPanelReplySummary** and **ThreadPanelReplyCount**: spaced on the timeline rhythm. ([#694](https://github.com/botiverse/raft-design/pull/694))
|
|
54
|
+
- Why: see Timeline rhythm above.
|
|
55
|
+
- Affects: a date line's rule sits 24px from the text above and below it (was 24px / 32px on a phone, 25px / 33px on a desktop); SystemMessage padding 12px / 12px → 12px / 4px, 16px from the text on both sides; a closed SystemMessageGroupHeader keeps the same 12px / 4px around its disclosure's text (padding 6px / 6px → 6px top and −2px bottom on a phone, 7px and −1px on a desktop), and an open one keeps its 6px under the header; MessageListNotice padding 0 / 8px → 12px / 4px; ThreadPanelOriginalMessage bottom padding 8px → 20px and ThreadPanelReplySummary top padding 8px → 12px, so the thread's rule sits 24px from the text on both sides; ThreadPanelReplyCount gains 4px above it (margin 0 / 4px → 4px / 4px). MessageItem keeps its 4px / 8px, now read from the tokens.
|
|
56
|
+
- Docs: https://raft-design.botiverse.build/foundations/spacing/#timeline-rhythm
|
|
57
|
+
|
|
58
|
+
### Fixed
|
|
59
|
+
|
|
60
|
+
- **Select**, **Combobox**, **ComboboxSelect** and **InputGroup**: a value cut with an ellipsis gets its full text as a `title` whenever it is cut. ([#695](https://github.com/botiverse/raft-design/pull/695))
|
|
61
|
+
- Why: the check compared whole pixels with 1px to spare, so it missed cuts of about 0.6–1.3px that still showed an ellipsis, and it did not measure again when a web font finished loading; it now compares fractional sizes and measures again after fonts load.
|
|
62
|
+
- Affects: tolerance 1px (whole pixels) → 0.5px (fractional).
|
|
63
|
+
- Docs: https://raft-design.botiverse.build/components/select/
|
|
64
|
+
- **Checkbox** and **RadioGroupItem** hit areas: in a `<label>` row the box or circle reaches 4px past its line, half the 8px gap to the next option, so a tap between two options lands on the nearer one; the label is the target for the rest. On its own, its hit area is 44px tall on a touch screen. ([#686](https://github.com/botiverse/raft-design/pull/686))
|
|
65
|
+
- Why: each option's hit area reached across the gap and the next option's covered it, so a tap just under one option could select the next one.
|
|
66
|
+
- Affects: standalone touch hit area 44px tall (was 36px for a checkbox, 33px for a radio); standalone mouse hit area unchanged; in a `<label>` row the hit area is the line plus 4px above and below, for every pointer.
|
|
67
|
+
- Docs: https://raft-design.botiverse.build/foundations/alignment/#a-control-and-its-label
|
|
68
|
+
|
|
69
|
+
## [0.20.1](https://github.com/botiverse/raft-design/compare/v0.20.0...v0.20.1) (2026-10-22)
|
|
70
|
+
|
|
71
|
+
### Design System
|
|
72
|
+
|
|
73
|
+
- **A mark that leads text**: an icon or status light that starts a line of text is centered on the first line of that text and stays there when the text wraps or a description follows. Only the place is shared; each component keeps its own icon size and gap. A status light beside text is always 9px. It applies to Banner, PanelNotice, ToastIcon, MessageActionCardNotice, Badge and PanelActivity. ([#670](https://github.com/botiverse/raft-design/pull/670), [#687](https://github.com/botiverse/raft-design/pull/687))
|
|
74
|
+
- Why: each component placed its mark with its own fixed offset, which held for one type size and drifted at the next; one rule, the line box center (the cap-height center in Space Grotesk), now places every mark.
|
|
75
|
+
- Affects: offset `(1lh - size) / 2` on the row's own type; status light 9px with a 1.5px ink edge.
|
|
76
|
+
- Docs: https://raft-design.botiverse.build/foundations/alignment/#a-mark-that-leads-text
|
|
77
|
+
- **Popups stay on their trigger**: when the window or a pane scrolls under an open popup, the popup moves with the element that opened it. A context menu stays with the point where it was opened. It applies to SelectContent, ComboboxContent, PopoverContent, PreviewCardContent and NotificationCenterPopup. ([#669](https://github.com/botiverse/raft-design/pull/669))
|
|
78
|
+
- Why: popups stayed where they opened while the page scrolled, pointing at whatever had scrolled into place; the wrappers no longer turn Base UI's anchor tracking off.
|
|
79
|
+
- Docs: https://raft-design.botiverse.build/foundations/elevation/#popups
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- **`lead-icon`** and **`lead-dot`** utilities: center an icon (`lead-icon`) or a `Status` light (`lead-dot`) you place yourself on the first line of the text beside it. ([#670](https://github.com/botiverse/raft-design/pull/670), [#687](https://github.com/botiverse/raft-design/pull/687))
|
|
84
|
+
- Why: a mark placed outside the components above had no way to follow the same rule except a hand-tuned margin.
|
|
85
|
+
- Affects: `lead-dot` sizes the light 9px with a 1.5px edge, so don't pass the `Status` a `size`. Both read `1lh`, so put the text's type on the row that holds the mark and the text.
|
|
86
|
+
- Docs: https://raft-design.botiverse.build/foundations/alignment/#a-mark-that-leads-text
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
- **Status** in Banner, PanelNotice, ToastIcon, Badge and PanelActivity: held at 9px and centered on the first line, whatever `size` or vertical margin it was given. ([#670](https://github.com/botiverse/raft-design/pull/670), [#687](https://github.com/botiverse/raft-design/pull/687))
|
|
91
|
+
- Why: the same light showed at different sizes in a toast, a banner and a chip; a light beside text has one size, 9px, the least color that tells green from yellow from orange, plus its ink edges.
|
|
92
|
+
- Affects: a `Status` passed `xs` (6px), `sm` (8px) or `lg` (11px) in these components renders 9px; the `xs` edge 1px → 1.5px (its 1px corner stays). The default `md` is unchanged, as are icon sizes and gaps.
|
|
93
|
+
- Docs: https://raft-design.botiverse.build/components/status/#sizes
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
|
|
97
|
+
- **PanelNotice**: a leading status light or icon is centered on the first line of the notice's text. ([#670](https://github.com/botiverse/raft-design/pull/670), [#687](https://github.com/botiverse/raft-design/pull/687))
|
|
98
|
+
- Why: the mark sat at the top of the first line, a light 6.5px above the line's center on a desktop (5.5px on a phone) and a 16px icon 3px (2px); the notice now follows A mark that leads text.
|
|
99
|
+
- Affects: icon size and gap are unchanged (your icon's size, 10px before the text).
|
|
100
|
+
- Docs: https://raft-design.botiverse.build/components/panel/
|
|
101
|
+
- **Popups**: SelectContent, ComboboxContent, PopoverContent, PreviewCardContent and NotificationCenterPopup follow their trigger while the window or a scrolling pane moves. ([#669](https://github.com/botiverse/raft-design/pull/669))
|
|
102
|
+
- Why: these wrappers turned anchor tracking off by default, so an open popup kept its opening position and drifted off its trigger as soon as anything scrolled; they now leave it to Base UI's default.
|
|
103
|
+
- Affects: `disableAnchorTracking` default `true` → unset (Base UI's default, tracking on). ContextMenuContent drops its `true` default too; it is anchored to a point, so it looks the same. Pass `disableAnchorTracking` to turn it off for one popup. Select still turns tracking off with `alignItemWithTrigger`.
|
|
104
|
+
- Docs: https://raft-design.botiverse.build/foundations/elevation/#popups
|
|
105
|
+
|
|
1
106
|
## [0.20.0](https://github.com/botiverse/raft-design/compare/v0.19.0...v0.20.0) (2026-10-22)
|
|
2
107
|
|
|
3
108
|
### Design System
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Renames Button's duplicate sizes to the one they always rendered as.
|
|
3
|
+
//
|
|
4
|
+
// node node_modules/@botiverse/raft-ui/codemods/button-sizes.mjs <dir-or-file>... [--dry] [--components=MyButton,…]
|
|
5
|
+
//
|
|
6
|
+
// `xs` and `sm` render exactly as `md`, and `icon-xs` and `icon-sm` exactly as
|
|
7
|
+
// `icon-md`, so nothing on screen changes: xs, sm -> md; icon-xs, icon-sm ->
|
|
8
|
+
// icon-md. The old names keep working as deprecated aliases until raft-ui 1.0,
|
|
9
|
+
// so the rewrite can land at any time after upgrading.
|
|
10
|
+
//
|
|
11
|
+
// Needs @babel/parser, an optional peer dependency of raft-ui: install it
|
|
12
|
+
// in the project you migrate (`pnpm add -D @babel/parser`).
|
|
13
|
+
//
|
|
14
|
+
// Each file is parsed as TypeScript and JSX (@babel/parser), so comments,
|
|
15
|
+
// strings and JSX text never confuse it, and a Button anywhere is found: as a
|
|
16
|
+
// child, in another component's prop (`actions={<Button …/>}`,
|
|
17
|
+
// `render={<Button …/>}`), in a callback. It rewrites:
|
|
18
|
+
// - the `size` of `<Button>`, of the raft-ui parts that pass `size` to a
|
|
19
|
+
// Button (BUTTON_COMPONENTS), and of the components named with
|
|
20
|
+
// `--components`, for your own wrappers: a string (`size="sm"`,
|
|
21
|
+
// `size={"sm"}`) or the strings in an expression (`size={inHead ? "sm" :
|
|
22
|
+
// "lg"}`);
|
|
23
|
+
// - `icon-sm` and `icon-xs` in the `size` of any JSX element: only Button has
|
|
24
|
+
// those names;
|
|
25
|
+
// - `size: "sm"` in a `buttonVariants({…})` call.
|
|
26
|
+
// `sm` and `xs` are names other components use too (Dialog, Banner, Avatar,
|
|
27
|
+
// Spinner …), so nothing else is touched. It then lists every `sm`, `xs`,
|
|
28
|
+
// `icon-sm` and `icon-xs` string it left, with the element it belongs to, for
|
|
29
|
+
// review by hand: a size kept in a variable, a wrapper you didn't name, a test.
|
|
30
|
+
import { readdirSync, readFileSync, realpathSync, statSync, writeFileSync } from "node:fs";
|
|
31
|
+
import { createRequire } from "node:module";
|
|
32
|
+
import path from "node:path";
|
|
33
|
+
import { fileURLToPath } from "node:url";
|
|
34
|
+
|
|
35
|
+
let babelParse;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @babel/parser is an optional peer dependency of raft-ui: only this codemod
|
|
39
|
+
* uses it. Look in the project being migrated first, then beside raft-ui.
|
|
40
|
+
*/
|
|
41
|
+
function loadParser() {
|
|
42
|
+
if (babelParse) return babelParse;
|
|
43
|
+
for (const from of [path.join(process.cwd(), "package.json"), import.meta.url]) {
|
|
44
|
+
try {
|
|
45
|
+
babelParse = createRequire(from)("@babel/parser").parse;
|
|
46
|
+
return babelParse;
|
|
47
|
+
} catch {
|
|
48
|
+
// Try the next place.
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
throw new Error(
|
|
52
|
+
"install @babel/parser to run this codemod (it parses your TSX): pnpm add -D @babel/parser",
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Deprecated Button size -> the size it renders as. */
|
|
57
|
+
export const BUTTON_SIZE_RENAMES = {
|
|
58
|
+
xs: "md",
|
|
59
|
+
sm: "md",
|
|
60
|
+
"icon-xs": "icon-md",
|
|
61
|
+
"icon-sm": "icon-md",
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** raft-ui components whose `size` is a Button size. */
|
|
65
|
+
export const BUTTON_COMPONENTS = [
|
|
66
|
+
"Button",
|
|
67
|
+
"AlertDialogAction",
|
|
68
|
+
"AlertDialogCancel",
|
|
69
|
+
"AlertDialogClose",
|
|
70
|
+
"AnnouncementDialogAction",
|
|
71
|
+
"AnnouncementDialogSecondaryAction",
|
|
72
|
+
"ComposerSubmit",
|
|
73
|
+
"CopyableCodeAction",
|
|
74
|
+
"DialogClose",
|
|
75
|
+
"DrawerClose",
|
|
76
|
+
"FileAction",
|
|
77
|
+
"SidebarSectionControl",
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const ICON_ONLY = new Set(["icon-xs", "icon-sm"]);
|
|
81
|
+
const OLD = new Set(Object.keys(BUTTON_SIZE_RENAMES));
|
|
82
|
+
|
|
83
|
+
function parseSource(source, file) {
|
|
84
|
+
const ext = path.extname(file);
|
|
85
|
+
const plugins =
|
|
86
|
+
ext === ".ts" || ext === ".mts" || ext === ".cts" ? ["typescript"] : ["typescript", "jsx"];
|
|
87
|
+
return loadParser()(source, {
|
|
88
|
+
sourceType: "unambiguous",
|
|
89
|
+
plugins,
|
|
90
|
+
errorRecovery: true,
|
|
91
|
+
allowReturnOutsideFunction: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** Depth-first walk over a Babel AST, with each node's parent chain. */
|
|
96
|
+
function walk(node, visit, parents = []) {
|
|
97
|
+
if (!node || typeof node.type !== "string") return;
|
|
98
|
+
visit(node, parents);
|
|
99
|
+
const next = [...parents, node];
|
|
100
|
+
for (const key of Object.keys(node)) {
|
|
101
|
+
if (key === "loc" || key === "start" || key === "end" || key === "extra") continue;
|
|
102
|
+
const value = node[key];
|
|
103
|
+
if (Array.isArray(value)) for (const child of value) walk(child, visit, next);
|
|
104
|
+
else if (value && typeof value.type === "string") walk(value, visit, next);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function elementName(name) {
|
|
109
|
+
if (!name) return "";
|
|
110
|
+
if (name.type === "JSXIdentifier") return name.name;
|
|
111
|
+
if (name.type === "JSXMemberExpression")
|
|
112
|
+
return `${elementName(name.object)}.${name.property.name}`;
|
|
113
|
+
if (name.type === "JSXNamespacedName") return `${name.namespace.name}:${name.name.name}`;
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** The string literals a `size` value can resolve to, without entering nested functions or JSX. */
|
|
118
|
+
function sizeStrings(node, out = []) {
|
|
119
|
+
if (!node) return out;
|
|
120
|
+
switch (node.type) {
|
|
121
|
+
case "StringLiteral":
|
|
122
|
+
out.push(node);
|
|
123
|
+
break;
|
|
124
|
+
case "TemplateLiteral":
|
|
125
|
+
if (node.expressions.length === 0 && node.quasis.length === 1) out.push(node);
|
|
126
|
+
break;
|
|
127
|
+
case "JSXExpressionContainer":
|
|
128
|
+
case "ParenthesizedExpression":
|
|
129
|
+
case "TSAsExpression":
|
|
130
|
+
case "TSSatisfiesExpression":
|
|
131
|
+
case "TSNonNullExpression":
|
|
132
|
+
sizeStrings(node.expression, out);
|
|
133
|
+
break;
|
|
134
|
+
case "ConditionalExpression":
|
|
135
|
+
sizeStrings(node.consequent, out);
|
|
136
|
+
sizeStrings(node.alternate, out);
|
|
137
|
+
break;
|
|
138
|
+
case "LogicalExpression":
|
|
139
|
+
sizeStrings(node.left, out);
|
|
140
|
+
sizeStrings(node.right, out);
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const literalValue = (node) =>
|
|
149
|
+
node.type === "StringLiteral" ? node.value : node.quasis[0].value.cooked;
|
|
150
|
+
|
|
151
|
+
function lineOf(source, index) {
|
|
152
|
+
let line = 1;
|
|
153
|
+
for (let i = 0; i < index; i += 1) if (source.charCodeAt(i) === 10) line += 1;
|
|
154
|
+
return line;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Renames the deprecated sizes in one file. Returns the new source and the
|
|
159
|
+
* strings it left, as `{ line, value, where }`.
|
|
160
|
+
*/
|
|
161
|
+
export function migrateButtonSizes(
|
|
162
|
+
source,
|
|
163
|
+
{ file = "file.tsx", components = BUTTON_COMPONENTS } = {},
|
|
164
|
+
) {
|
|
165
|
+
const buttons = new Set(components);
|
|
166
|
+
const ast = parseSource(source, file);
|
|
167
|
+
const edits = new Map();
|
|
168
|
+
const rename = (literal) => {
|
|
169
|
+
const value = literalValue(literal);
|
|
170
|
+
const quote = source[literal.start];
|
|
171
|
+
edits.set(literal.start, {
|
|
172
|
+
end: literal.end,
|
|
173
|
+
text: `${quote}${BUTTON_SIZE_RENAMES[value]}${quote}`,
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
const handled = new Set();
|
|
177
|
+
|
|
178
|
+
walk(ast.program, (node) => {
|
|
179
|
+
if (node.type === "JSXOpeningElement") {
|
|
180
|
+
const name = elementName(node.name);
|
|
181
|
+
const isButton = buttons.has(name);
|
|
182
|
+
for (const attribute of node.attributes) {
|
|
183
|
+
if (attribute.type !== "JSXAttribute" || attribute.name.name !== "size") continue;
|
|
184
|
+
for (const literal of sizeStrings(attribute.value)) {
|
|
185
|
+
const value = literalValue(literal);
|
|
186
|
+
if (!OLD.has(value)) continue;
|
|
187
|
+
handled.add(literal.start);
|
|
188
|
+
if (isButton || ICON_ONLY.has(value)) rename(literal);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (
|
|
193
|
+
node.type === "CallExpression" &&
|
|
194
|
+
node.callee.type === "Identifier" &&
|
|
195
|
+
node.callee.name === "buttonVariants"
|
|
196
|
+
) {
|
|
197
|
+
for (const argument of node.arguments) {
|
|
198
|
+
if (argument.type !== "ObjectExpression") continue;
|
|
199
|
+
for (const property of argument.properties) {
|
|
200
|
+
if (property.type !== "ObjectProperty") continue;
|
|
201
|
+
const key = property.key.type === "Identifier" ? property.key.name : property.key.value;
|
|
202
|
+
if (key !== "size") continue;
|
|
203
|
+
for (const literal of sizeStrings(property.value)) {
|
|
204
|
+
if (!OLD.has(literalValue(literal))) continue;
|
|
205
|
+
handled.add(literal.start);
|
|
206
|
+
rename(literal);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
// Every deprecated name still standing, and what it belongs to.
|
|
214
|
+
const left = [];
|
|
215
|
+
walk(ast.program, (node, parents) => {
|
|
216
|
+
// A test that matches the source (`/size="sm"/`) has to change with it.
|
|
217
|
+
if (node.type === "RegExpLiteral") {
|
|
218
|
+
const name = /["'](icon-)?(sm|xs)["']/.exec(node.pattern);
|
|
219
|
+
if (name) {
|
|
220
|
+
left.push({
|
|
221
|
+
line: lineOf(source, node.start),
|
|
222
|
+
value: name[0].slice(1, -1),
|
|
223
|
+
where: "a regular expression",
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const isString =
|
|
229
|
+
node.type === "StringLiteral" ||
|
|
230
|
+
(node.type === "TemplateLiteral" &&
|
|
231
|
+
node.expressions.length === 0 &&
|
|
232
|
+
node.quasis.length === 1);
|
|
233
|
+
if (!isString || !OLD.has(literalValue(node)) || edits.has(node.start)) return;
|
|
234
|
+
let where = "a string";
|
|
235
|
+
let prop = "";
|
|
236
|
+
for (let i = parents.length - 1; i >= 0; i -= 1) {
|
|
237
|
+
const parent = parents[i];
|
|
238
|
+
if (parent.type === "JSXAttribute" && !prop) prop = ` ${parent.name.name}`;
|
|
239
|
+
if (parent.type === "JSXOpeningElement") {
|
|
240
|
+
where = `<${elementName(parent.name)}${prop}>`;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
if (parent.type === "JSXElement" || parent.type === "JSXFragment") break;
|
|
244
|
+
}
|
|
245
|
+
left.push({ line: lineOf(source, node.start), value: literalValue(node), where });
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
let out = source;
|
|
249
|
+
for (const start of [...edits.keys()].sort((a, b) => b - a)) {
|
|
250
|
+
const { end, text } = edits.get(start);
|
|
251
|
+
out = out.slice(0, start) + text + out.slice(end);
|
|
252
|
+
}
|
|
253
|
+
return { source: out, left };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** The source with the deprecated sizes renamed (see migrateButtonSizes). */
|
|
257
|
+
export function renameButtonSizes(source, components = BUTTON_COMPONENTS, file = "file.tsx") {
|
|
258
|
+
return migrateButtonSizes(source, { file, components }).source;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"]);
|
|
262
|
+
const SKIP = new Set(["node_modules", "dist", "build", ".git"]);
|
|
263
|
+
|
|
264
|
+
function* walkFiles(target) {
|
|
265
|
+
const stat = statSync(target);
|
|
266
|
+
if (stat.isFile()) {
|
|
267
|
+
if (EXTENSIONS.has(path.extname(target))) yield target;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
for (const name of readdirSync(target)) {
|
|
271
|
+
if (SKIP.has(name) || name.startsWith(".")) continue;
|
|
272
|
+
yield* walkFiles(path.join(target, name));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function main(argv) {
|
|
277
|
+
const dry = argv.includes("--dry");
|
|
278
|
+
const option = argv.find((arg) => arg.startsWith("--components="));
|
|
279
|
+
const components = option
|
|
280
|
+
? [...BUTTON_COMPONENTS, ...option.slice("--components=".length).split(",").filter(Boolean)]
|
|
281
|
+
: BUTTON_COMPONENTS;
|
|
282
|
+
const targets = argv.filter((arg) => !arg.startsWith("--"));
|
|
283
|
+
if (targets.length === 0) {
|
|
284
|
+
console.error("usage: button-sizes.mjs <dir-or-file>... [--dry] [--components=MyButton,…]");
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
let changed = 0;
|
|
288
|
+
const review = [];
|
|
289
|
+
try {
|
|
290
|
+
loadParser();
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.error(error.message);
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
const groups = new Map();
|
|
296
|
+
for (const target of targets) {
|
|
297
|
+
for (const file of walkFiles(target)) {
|
|
298
|
+
const before = readFileSync(file, "utf8");
|
|
299
|
+
if (!/["'`](?:icon-)?(?:sm|xs)["'`]/.test(before)) continue;
|
|
300
|
+
let result;
|
|
301
|
+
try {
|
|
302
|
+
result = migrateButtonSizes(before, { file, components });
|
|
303
|
+
} catch (error) {
|
|
304
|
+
review.push(`${file}: could not parse (${error.message}); not changed`);
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
for (const { line, value, where } of result.left) {
|
|
308
|
+
review.push(`${file}:${line} "${value}" in ${where}`);
|
|
309
|
+
groups.set(where, (groups.get(where) ?? 0) + 1);
|
|
310
|
+
}
|
|
311
|
+
if (result.source === before) continue;
|
|
312
|
+
changed += 1;
|
|
313
|
+
console.log(`${dry ? "would update" : "updated"} ${file}`);
|
|
314
|
+
if (!dry) writeFileSync(file, result.source);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
console.log(`${changed} file${changed === 1 ? "" : "s"} ${dry ? "to update" : "updated"}`);
|
|
318
|
+
if (review.length > 0) {
|
|
319
|
+
console.log(
|
|
320
|
+
"\nLeft as they are; check each by hand (another component's size, a variable, your own wrapper).",
|
|
321
|
+
);
|
|
322
|
+
console.log("\nBy element and prop:");
|
|
323
|
+
for (const [where, count] of [...groups].sort((a, b) => b[1] - a[1])) {
|
|
324
|
+
console.log(` ${String(count).padStart(4)} ${where}`);
|
|
325
|
+
}
|
|
326
|
+
console.log("\nEach one:");
|
|
327
|
+
for (const where of review) console.log(` ${where}`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Run only when invoked directly (see token-names.mjs: pnpm installs through
|
|
332
|
+
// symlinks, so compare real paths).
|
|
333
|
+
function isInvokedDirectly() {
|
|
334
|
+
try {
|
|
335
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));
|
|
336
|
+
} catch {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (isInvokedDirectly()) main(process.argv.slice(2));
|
package/dist/cn.mjs
CHANGED
|
@@ -11,7 +11,14 @@ const twMerge = extendTailwindMerge({ extend: {
|
|
|
11
11
|
"embedded-inset",
|
|
12
12
|
"option",
|
|
13
13
|
"option-inset",
|
|
14
|
-
"icon-inset"
|
|
14
|
+
"icon-inset",
|
|
15
|
+
"timeline-message",
|
|
16
|
+
"timeline-section",
|
|
17
|
+
"timeline-row",
|
|
18
|
+
"timeline-turn",
|
|
19
|
+
"timeline-lead",
|
|
20
|
+
"timeline-end",
|
|
21
|
+
"timeline-start"
|
|
15
22
|
] },
|
|
16
23
|
classGroups: {
|
|
17
24
|
shadow: [{ shadow: [
|
package/dist/foundation.css
CHANGED
|
@@ -310,6 +310,19 @@
|
|
|
310
310
|
/* A chip or a button embedded in a field: the control height less the embedded
|
|
311
311
|
inset above and below, so the field keeps its height. */
|
|
312
312
|
--control-embedded-size: 32px;
|
|
313
|
+
/* The message step of a timeline: from the last line of one turn to the first
|
|
314
|
+
line of the next (a sender line, an event line). Every row keeps the row
|
|
315
|
+
inset above and below its text; the first row of a turn adds the rest above
|
|
316
|
+
it. */
|
|
317
|
+
--timeline-gap-message: 16px;
|
|
318
|
+
/* The section step of a timeline, one step wider than the message step: either
|
|
319
|
+
side of a date line, from the top of the list to the first line, and from
|
|
320
|
+
the last line to the composer, so a boundary reads as one and the last
|
|
321
|
+
message never sits on the composer. */
|
|
322
|
+
--timeline-gap-section: 24px;
|
|
323
|
+
/* How far a timeline row's hover and selected highlight reaches above and
|
|
324
|
+
below its text. Two rows of one turn sit two insets apart. */
|
|
325
|
+
--timeline-row-inset: 4px;
|
|
313
326
|
--sticker-ink: oklch(0.1813 0.005 17.62);
|
|
314
327
|
--sticker-paper: oklch(1 0 0);
|
|
315
328
|
--sticker-edge: oklch(0.1813 0.005 17.62 / 0);
|
|
@@ -253,7 +253,26 @@ declare const buttonVariants: import("tailwind-variants/lite").TVReturnType<{
|
|
|
253
253
|
content: string;
|
|
254
254
|
loadingIndicator: string;
|
|
255
255
|
}>>;
|
|
256
|
-
type
|
|
256
|
+
type ButtonVariantProps = VariantProps<typeof buttonVariants>;
|
|
257
|
+
/** The Button sizes: `md`, `lg`, `xl`, `icon-md` and `icon-lg`. */
|
|
258
|
+
type ButtonSize = "md" | "lg" | "xl" | "icon-md" | "icon-lg";
|
|
259
|
+
/**
|
|
260
|
+
* Deprecated: `xs` and `sm` render as `md`, `icon-xs` and `icon-sm` as
|
|
261
|
+
* `icon-md`. Removed in raft-ui 1.0; run
|
|
262
|
+
* `node node_modules/@botiverse/raft-ui/codemods/button-sizes.mjs <src>`.
|
|
263
|
+
*/
|
|
264
|
+
type DeprecatedButtonSize = "xs" | "sm" | "icon-xs" | "icon-sm";
|
|
265
|
+
type ButtonProps = StyledProps<Button.Props> & Omit<ButtonVariantProps, "size"> & DataAttributes & {
|
|
266
|
+
/**
|
|
267
|
+
* `md` (32px) and `icon-md` for rows, cards, banners, toolbars and panel
|
|
268
|
+
* headers; `lg` and `icon-lg` (the control height) for dialog footers,
|
|
269
|
+
* forms and beside a field; `xl` for a full-width call to action. The size
|
|
270
|
+
* follows the place: see Button › Size by place.
|
|
271
|
+
*
|
|
272
|
+
* `xs`, `sm`, `icon-xs` and `icon-sm` are deprecated aliases of `md` and
|
|
273
|
+
* `icon-md`, removed in raft-ui 1.0 (`codemods/button-sizes.mjs`).
|
|
274
|
+
*/
|
|
275
|
+
size?: "md" | "lg" | "xl" | "icon-md" | "icon-lg" | DeprecatedButtonSize;
|
|
257
276
|
loading?: boolean;
|
|
258
277
|
loadingLabel?: string;
|
|
259
278
|
};
|
|
@@ -314,6 +333,26 @@ type DialogNavProps = useRender.ComponentProps<"nav">;
|
|
|
314
333
|
/** The section list of a wide (`size="wide"`) dialog, inside a `bar` body. */
|
|
315
334
|
declare function DialogNav({ className, render, ...props }: DialogNavProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
316
335
|
//#endregion
|
|
336
|
+
//#region src/components/text-link/text-link.d.ts
|
|
337
|
+
declare const textLinkVariants: import("tailwind-variants/lite").TVReturnType<{
|
|
338
|
+
variant: {
|
|
339
|
+
muted: string[];
|
|
340
|
+
strong: string[];
|
|
341
|
+
};
|
|
342
|
+
}, undefined, string[], {
|
|
343
|
+
variant: {
|
|
344
|
+
muted: string[];
|
|
345
|
+
strong: string[];
|
|
346
|
+
};
|
|
347
|
+
}, undefined, import("tailwind-variants/lite").TVReturnTypeLike<{
|
|
348
|
+
variant: {
|
|
349
|
+
muted: string[];
|
|
350
|
+
strong: string[];
|
|
351
|
+
};
|
|
352
|
+
}, undefined>>;
|
|
353
|
+
type TextLinkProps = useRender.ComponentProps<"button"> & VariantProps<typeof textLinkVariants>;
|
|
354
|
+
declare function TextLink({ variant, className, render, ...props }: TextLinkProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
355
|
+
//#endregion
|
|
317
356
|
//#region src/lib/presence.d.ts
|
|
318
357
|
/**
|
|
319
358
|
* The five status lights of the design system. Each colour is a fixed
|
|
@@ -1098,4 +1137,4 @@ type MessageListJumpPillDismissProps = StyledProps<Button.Props> & DataAttribute
|
|
|
1098
1137
|
};
|
|
1099
1138
|
declare function MessageListJumpPillDismiss({ className, children, render, nativeButton, ...props }: MessageListJumpPillDismissProps): import("react").JSX.Element;
|
|
1100
1139
|
//#endregion
|
|
1101
|
-
export { MessageMultiSelect as $, MessageItemGutterProps as $n, DropdownMenuRadioItemProps as $r, MessageItemBadgeSeparator as $t, MessageQuotedPreviewChannel as A,
|
|
1140
|
+
export { MessageMultiSelect as $, DeprecatedButtonSize as $i, MessageItemGutterProps as $n, DropdownMenuRadioItemProps as $r, MessageItemBadgeSeparator as $t, MessageQuotedPreviewChannel as A, DialogContentProps as Ai, MessageItemSenderGroupProps as An, DropdownMenuCheckboxItemProps as Ar, MessageReactionGlyphProps as At, MessageQuotedPreviewTextProps as B, DialogOverlayProps as Bi, MessageItemEdited as Bn, DropdownMenuItemProps as Br, MessageReactionTooltipContentProps as Bt, MessageQuotedPreviewAuthorDelegatedBy as C, textLinkVariants as Ci, MessageItemMetaProps as Cn, TooltipProviderProps as Cr, MessageReactionChip as Ct, MessageQuotedPreviewAuthorName as D, DialogClose as Di, MessageItemSenderButton as Dn, DropdownMenuCheckboxItem as Dr, MessageReactionErrorIndicator as Dt, MessageQuotedPreviewAuthorMetaProps as E, DialogBodyProps as Ei, MessageItemSenderBadgesProps as En, DropdownMenu as Er, MessageReactionCountProps as Et, MessageQuotedPreviewHeaderProps as F, DialogHeader as Fi, MessageItemAttachmentsProps as Fn, DropdownMenuItem as Fr, MessageReactionQuickButton as Ft, MessageQuotedPreviewUnavailable as G, DialogSurfaceProps as Gi, MessageItemFooterProps as Gn, DropdownMenuPortal as Gr, MessageReactionTooltipNameText as Gt, MessageQuotedPreviewThreadProps as H, DialogPortalProps as Hi, MessageItemEmbedded as Hn, DropdownMenuLabelProps as Hr, MessageReactionTooltipMetaProps as Ht, MessageQuotedPreviewLoading as I, DialogHeaderProps as Ii, MessageItemBody as In, DropdownMenuItemCount as Ir, MessageReactionQuickButtonProps as It, MessageTextSelectionToolbarButton as J, DialogTrigger as Ji, MessageItemAvatarSlot as Jn, DropdownMenuRadioGroup as Jr, MessageReactionTooltipNamesProps as Jt, MessageQuotedPreviewUnavailableProps as K, DialogTitle as Ki, MessageItemSearchMatch as Kn, DropdownMenuPortalProps as Kr, MessageReactionTooltipNameTextProps as Kt, MessageQuotedPreviewLoadingProps as L, DialogNav as Li, MessageItemBodyProps as Ln, DropdownMenuItemCountProps as Lr, MessageReactionQuickRow as Lt, MessageQuotedPreviewContent as M, DialogDescriptionProps as Mi, MessageItemTime as Mn, DropdownMenuContentProps as Mr, MessageReactionPickerContentProps as Mt, MessageQuotedPreviewContentProps as N, DialogFooter as Ni, MessageItemTimeProps as Nn, DropdownMenuFooter as Nr, MessageReactionPickerStatic as Nt, MessageQuotedPreviewAuthorNameProps as O, DialogCloseProps as Oi, MessageItemSenderButtonProps as On, DropdownMenuCheckboxItemIndicator as Or, MessageReactionErrorIndicatorProps as Ot, MessageQuotedPreviewHeader as P, DialogFooterProps as Pi, MessageItemAttachments as Pn, DropdownMenuFooterProps as Pr, MessageReactionPickerStaticProps as Pt, MessageTextSelectionToolbarSeparatorProps as Q, ButtonSize as Qi, MessageItemGutter as Qn, DropdownMenuRadioItemIndicatorProps as Qr, MessageItemBadgeProps as Qt, MessageQuotedPreviewProps as R, DialogNavProps as Ri, MessageItemContent as Rn, DropdownMenuItemLabel as Rr, MessageReactionQuickRowProps as Rt, MessageQuotedPreviewAuthor as S, TextLinkProps as Si, MessageItemMeta as Sn, TooltipProvider as Sr, MessageReactionAddButtonProps as St, MessageQuotedPreviewAuthorMeta as T, DialogBody as Ti, MessageItemSenderBadges as Tn, TooltipTriggerProps as Tr, MessageReactionCount as Tt, MessageQuotedPreviewTimestamp as U, DialogProps as Ui, MessageItemEmbeddedProps as Un, DropdownMenuPopup as Ur, MessageReactionTooltipName as Ut, MessageQuotedPreviewThread as V, DialogPortal as Vi, MessageItemEditedProps as Vn, DropdownMenuLabel as Vr, MessageReactionTooltipMeta as Vt, MessageQuotedPreviewTimestampProps as W, DialogSurface as Wi, MessageItemFooter as Wn, DropdownMenuPopupProps as Wr, MessageReactionTooltipNameProps as Wt, MessageTextSelectionToolbarProps as X, Button$1 as Xi, MessageItemContinuationTime as Xn, DropdownMenuRadioItem as Xr, MessageReactionTooltipSeparatorProps as Xt, MessageTextSelectionToolbarButtonProps as Y, DialogTriggerProps as Yi, MessageItemAvatarSlotProps as Yn, DropdownMenuRadioGroupProps as Yr, MessageReactionTooltipSeparator as Yt, MessageTextSelectionToolbarSeparator as Z, ButtonProps as Zi, MessageItemContinuationTimeProps as Zn, DropdownMenuRadioItemIndicator as Zr, MessageItemBadge as Zt, MessageQuotedPreview as _, CheckboxIndicatorProps as _i, MessageItemDelegatedByProps as _n, TooltipContent as _r, MessageReferenceUnavailable as _t, MessageListJumpPillDismissProps as a, DropdownMenuSubmenuProps as ai, MessageItemSavedIndicatorProps as an, AvatarBadgeProps as ar, MessageMultiSelectToolbarActionsProps as at, MessageQuotedPreviewAttachments as b, Presence as bi, MessageItemInlineStatus as bn, TooltipPortalProps as br, MessageReferenceTextVariant as bt, MessageListJumpPillProps as c, DropdownMenuTrigger as ci, MessageItemToolbarButtonProps as cn, AvatarGroup as cr, MessageReferenceChipProps as ct, MessageListHistoryLimited as d, KbdGroup as di, MessageItemDelegatedAvatarProps as dn, AvatarGroupProps as dr, MessageReferenceLabel as dt, buttonVariants as ea, DropdownMenuSeparator as ei, MessageItemBadgeSeparatorProps as en, MessageItem as er, MessageMultiSelectCheckbox as et, MessageListHistoryLimitedProps as f, KbdGroupProps as fi, MessageItemDelegatedBy as fn, AvatarImage as fr, MessageReferenceLabelProps as ft, MessageListProps as g, CheckboxIndicator as gi, MessageItemDelegatedByNameProps as gn, Tooltip$1 as gr, MessageReferenceTextProps as gt, MessageList as h, BadgeProps as hi, MessageItemDelegatedByName as hn, AvatarSize as hr, MessageReferenceText as ht, MessageListJumpPillDismiss as i, DropdownMenuSubmenu as ii, MessageItemSavedIndicator as in, AvatarBadgeOffset as ir, MessageMultiSelectToolbarActions as it, MessageQuotedPreviewChannelProps as j, DialogDescription as ji, MessageItemSenderProps as jn, DropdownMenuContent as jr, MessageReactionPickerContent as jt, MessageQuotedPreviewAuthorProps as k, DialogContent as ki, MessageItemSenderGroup as kn, DropdownMenuCheckboxItemIndicatorProps as kr, MessageReactionGlyph as kt, MessageListDateDivider as l, DropdownMenuTriggerProps as li, MessageItemToolbarProps as ln, AvatarGroupCount as lr, MessageReferenceIndicator as lt, MessageListNoticeProps as m, Badge as mi, MessageItemDelegatedByButtonProps as mn, AvatarProps as mr, MessageReferencePendingProps as mt, MessageListJumpControlsProps as n, DataAttributes as na, DropdownMenuShortcut as ni, MessageItemReadReceipt as nn, Avatar$1 as nr, MessageMultiSelectProps as nt, MessageListJumpPillGroup as o, DropdownMenuSubmenuTrigger as oi, MessageItemToolbar as on, AvatarFallback as or, MessageMultiSelectToolbarProps as ot, MessageListNotice as p, KbdProps as pi, MessageItemDelegatedByButton as pn, AvatarImageProps as pr, MessageReferencePending as pt, MessageTextSelectionToolbar as q, DialogTitleProps as qi, MessageItemSearchMatchProps as qn, DropdownMenuProps as qr, MessageReactionTooltipNames as qt, MessageListJumpPill as r, StyledProps as ra, DropdownMenuShortcutProps as ri, MessageItemReadReceiptProps as rn, AvatarBadge as rr, MessageMultiSelectToolbar as rt, MessageListJumpPillGroupProps as s, DropdownMenuSubmenuTriggerProps as si, MessageItemToolbarButton as sn, AvatarFallbackProps as sr, MessageReferenceChip as st, MessageListJumpControls as t, VariantProps as ta, DropdownMenuSeparatorProps as ti, MessageItemBadgeStatus as tn, MessageItemProps as tr, MessageMultiSelectCheckboxProps as tt, MessageListDateDividerProps as u, Kbd as ui, MessageItemDelegatedAvatar as un, AvatarGroupCountProps as ur, MessageReferenceIndicatorProps as ut, MessageQuotedPreviewAttachment as v, Checkbox$1 as vi, MessageItemHeader as vn, TooltipContentProps as vr, MessageReferenceUnavailableProps as vt, MessageQuotedPreviewAuthorDelegatedByProps as w, Dialog$1 as wi, MessageItemSender as wn, TooltipTrigger as wr, MessageReactionChipProps as wt, MessageQuotedPreviewAttachmentsProps as x, TextLink as xi, MessageItemInlineStatusProps as xn, TooltipProps as xr, MessageReactionAddButton as xt, MessageQuotedPreviewAttachmentProps as y, CheckboxProps as yi, MessageItemHeaderProps as yn, TooltipPortal as yr, MessageReferenceChipVariant as yt, MessageQuotedPreviewText as z, DialogOverlay as zi, MessageItemContentProps as zn, DropdownMenuItemLabelProps as zr, MessageReactionTooltipContent as zt };
|