@photon-ai/pho-ui 4.3.0 → 4.4.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/dist/chunks/animated-height-I44sUq0n.js +48 -0
- package/dist/chunks/animated-height-I44sUq0n.js.map +1 -0
- package/dist/chunks/{basic-page-65eFgq8o.js → basic-page-ijv-ijUB.js} +534 -519
- package/dist/chunks/basic-page-ijv-ijUB.js.map +1 -0
- package/dist/chunks/bubble-eaoLJP4N.js +88 -0
- package/dist/chunks/bubble-eaoLJP4N.js.map +1 -0
- package/dist/chunks/{button-CdqS_t5a.js → button-CgUS0j3D.js} +4 -4
- package/dist/chunks/button-CgUS0j3D.js.map +1 -0
- package/dist/chunks/chat-DUqWlXqt.js +619 -0
- package/dist/chunks/chat-DUqWlXqt.js.map +1 -0
- package/dist/chunks/{code-block-BuDIo8Q0.js → code-block-BGgbp-6Q.js} +12 -12
- package/dist/chunks/{code-block-BuDIo8Q0.js.map → code-block-BGgbp-6Q.js.map} +1 -1
- package/dist/chunks/collapsible-Dv306QOT.js +40 -0
- package/dist/chunks/collapsible-Dv306QOT.js.map +1 -0
- package/dist/chunks/command-BfCCRaoc.js +225 -0
- package/dist/chunks/command-BfCCRaoc.js.map +1 -0
- package/dist/chunks/{copy-button-B_B15mEi.js → copy-button-D8XyP0oR.js} +10 -10
- package/dist/chunks/copy-button-D8XyP0oR.js.map +1 -0
- package/dist/chunks/{data-table-BeUwsjmX.js → data-table-Mog6m3d9.js} +2 -2
- package/dist/chunks/{data-table-BeUwsjmX.js.map → data-table-Mog6m3d9.js.map} +1 -1
- package/dist/chunks/{description-list-C-mwe4ki.js → description-list-8qm83WZB.js} +17 -17
- package/dist/chunks/description-list-8qm83WZB.js.map +1 -0
- package/dist/chunks/{dialog-BYiAFetB.js → dialog-DeM4axJ6.js} +47 -51
- package/dist/chunks/{dialog-BYiAFetB.js.map → dialog-DeM4axJ6.js.map} +1 -1
- package/dist/chunks/{error-BAQgnde7.js → error-VvHnteyf.js} +2 -2
- package/dist/chunks/{error-BAQgnde7.js.map → error-VvHnteyf.js.map} +1 -1
- package/dist/chunks/{filter-bar-DTaLgQr0.js → filter-bar-BcpeTKCC.js} +38 -36
- package/dist/chunks/filter-bar-BcpeTKCC.js.map +1 -0
- package/dist/chunks/{log-list-BERiO4UJ.js → log-list-Didt-MV4.js} +2 -2
- package/dist/chunks/{log-list-BERiO4UJ.js.map → log-list-Didt-MV4.js.map} +1 -1
- package/dist/chunks/message-CTml-TrB.js +89 -0
- package/dist/chunks/message-CTml-TrB.js.map +1 -0
- package/dist/chunks/{scroll-area-Zik8t1Mk.js → scroll-area-DSwD9th7.js} +2 -2
- package/dist/chunks/{scroll-area-Zik8t1Mk.js.map → scroll-area-DSwD9th7.js.map} +1 -1
- package/dist/chunks/{sidebar-DRPe5CAh.js → sidebar-BmloUwJQ.js} +57 -57
- package/dist/chunks/sidebar-BmloUwJQ.js.map +1 -0
- package/dist/chunks/{toast-72Wwlzg9.js → toast-DUvjSZF7.js} +3 -3
- package/dist/chunks/{toast-72Wwlzg9.js.map → toast-DUvjSZF7.js.map} +1 -1
- package/dist/chunks/{trace-Hku-rImp.js → trace-CjOi3_IP.js} +2 -2
- package/dist/chunks/{trace-Hku-rImp.js.map → trace-CjOi3_IP.js.map} +1 -1
- package/dist/components/accordion.js +3 -3
- package/dist/components/accordion.js.map +1 -1
- package/dist/components/bubble.js +6 -0
- package/dist/components/button.js +1 -1
- package/dist/components/chat.js +5 -0
- package/dist/components/code-block.js +1 -1
- package/dist/components/collapsible.js +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/copy-button.js +1 -1
- package/dist/components/data-table.js +1 -1
- package/dist/components/description-list.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/error.js +1 -1
- package/dist/components/filter-bar.js +1 -1
- package/dist/components/log-list.js +1 -1
- package/dist/components/message.js +7 -0
- package/dist/components/scroll-area.js +1 -1
- package/dist/components/toast.js +1 -1
- package/dist/components/trace.js +1 -1
- package/dist/index.js +145 -136
- package/dist/sections/basic-page.js +2 -2
- package/dist/sections/sidebar.js +1 -1
- package/dist/src/components/bubble/bubble.d.ts +112 -0
- package/dist/src/components/bubble/index.d.ts +1 -0
- package/dist/src/components/chat/chat.d.ts +301 -0
- package/dist/src/components/chat/index.d.ts +1 -0
- package/dist/src/components/collapsible/collapsible.d.ts +1 -1
- package/dist/src/components/command/command.d.ts +14 -4
- package/dist/src/components/command/index.d.ts +1 -1
- package/dist/src/components/filter-bar/filter-bar.d.ts +5 -0
- package/dist/src/components/message/index.d.ts +2 -0
- package/dist/src/components/message/message-status.d.ts +22 -0
- package/dist/src/components/message/message.d.ts +78 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/sections/sidebar/sidebar.d.ts +10 -1
- package/dist/src/utils/animated-height.d.ts +6 -0
- package/package.json +13 -1
- package/dist/chunks/animated-height-CCO-Ocoz.js +0 -48
- package/dist/chunks/animated-height-CCO-Ocoz.js.map +0 -1
- package/dist/chunks/basic-page-65eFgq8o.js.map +0 -1
- package/dist/chunks/button-CdqS_t5a.js.map +0 -1
- package/dist/chunks/collapsible-if7ncPbI.js +0 -28
- package/dist/chunks/collapsible-if7ncPbI.js.map +0 -1
- package/dist/chunks/command-ZagVyDx7.js +0 -192
- package/dist/chunks/command-ZagVyDx7.js.map +0 -1
- package/dist/chunks/copy-button-B_B15mEi.js.map +0 -1
- package/dist/chunks/description-list-C-mwe4ki.js.map +0 -1
- package/dist/chunks/filter-bar-DTaLgQr0.js.map +0 -1
- package/dist/chunks/sidebar-DRPe5CAh.js.map +0 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { ComponentProps, Ref } from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
/**
|
|
4
|
+
* Bubble — one message's surface: the rounded chip that carries the text,
|
|
5
|
+
* an image, or a line of prose, aligned to whichever side its author sits
|
|
6
|
+
* on. It knows nothing about who sent it or when; `Message` owns the row
|
|
7
|
+
* (avatar, header, footer) and `Chat` owns the thread.
|
|
8
|
+
*
|
|
9
|
+
* Design notes:
|
|
10
|
+
* - Monochrome, like every Pho surface. The received message is the card
|
|
11
|
+
* surface with the site hairline; the sent message is the inverted chip
|
|
12
|
+
* (the site's "msgbbl" token — literally its message bubble). There is
|
|
13
|
+
* no tinted brand bubble because there is no brand hue.
|
|
14
|
+
* - `base` radius with a `sm` tail corner on the author's side, so the
|
|
15
|
+
* bubble points at its sender the way the dashboard's already does.
|
|
16
|
+
* - `Content` renders through Base UI's `render`, so a bubble can be a
|
|
17
|
+
* `button` (open the message's record) or a link without a wrapper;
|
|
18
|
+
* the hover wash and focus ring only apply then.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Surface axis — a closed monochrome set. `outlined` is the default:
|
|
22
|
+
* the received message. `inverse` is the sent one.
|
|
23
|
+
*/
|
|
24
|
+
export declare const BUBBLE_VARIANTS: {
|
|
25
|
+
outlined: {
|
|
26
|
+
classes: string;
|
|
27
|
+
description: string;
|
|
28
|
+
};
|
|
29
|
+
inverse: {
|
|
30
|
+
classes: string;
|
|
31
|
+
description: string;
|
|
32
|
+
};
|
|
33
|
+
subtle: {
|
|
34
|
+
classes: string;
|
|
35
|
+
description: string;
|
|
36
|
+
};
|
|
37
|
+
ghost: {
|
|
38
|
+
classes: string;
|
|
39
|
+
description: string;
|
|
40
|
+
};
|
|
41
|
+
error: {
|
|
42
|
+
classes: string;
|
|
43
|
+
description: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export type BubbleVariant = keyof typeof BUBBLE_VARIANTS;
|
|
47
|
+
export type BubbleAlign = "start" | "end";
|
|
48
|
+
/**
|
|
49
|
+
* Consecutive bubbles from one author — a tighter stack than the gap
|
|
50
|
+
* between messages, so they read as one turn.
|
|
51
|
+
*/
|
|
52
|
+
declare function Group({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
53
|
+
export interface BubbleRootProps extends ComponentProps<"div"> {
|
|
54
|
+
/** Surface. @default "outlined" */
|
|
55
|
+
variant?: BubbleVariant;
|
|
56
|
+
/** Which side the author sits on. @default "start" */
|
|
57
|
+
align?: BubbleAlign;
|
|
58
|
+
ref?: Ref<HTMLDivElement>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The bubble's column: the surface (`Content`) with anything anchored to
|
|
62
|
+
* it (`Reactions`). Caps at 80% of the row so the other side stays open;
|
|
63
|
+
* `ghost` runs full width.
|
|
64
|
+
*/
|
|
65
|
+
declare function Root({ variant, align, className, ...props }: BubbleRootProps): import("react").JSX.Element;
|
|
66
|
+
export interface BubbleContentProps extends useRender.ComponentProps<"div"> {
|
|
67
|
+
/**
|
|
68
|
+
* The bubble whose record is open beside the thread — a brand ring
|
|
69
|
+
* lifts it off the page. Pair with `aria-pressed` or `aria-current`
|
|
70
|
+
* on an interactive bubble so the state is announced too.
|
|
71
|
+
*/
|
|
72
|
+
selected?: boolean;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The surface itself. Text wraps and keeps its line breaks. Pass
|
|
76
|
+
* `render={<button type="button" />}` (or a router link) to make the
|
|
77
|
+
* bubble the control that opens the message — it then takes the hover
|
|
78
|
+
* wash and the focus ring.
|
|
79
|
+
*/
|
|
80
|
+
declare function Content({ className, render, selected, ...props }: BubbleContentProps): import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>>;
|
|
81
|
+
export interface BubbleReactionsProps extends ComponentProps<"div"> {
|
|
82
|
+
/** Which edge of the bubble the pill hangs from. @default "bottom" */
|
|
83
|
+
side?: "top" | "bottom";
|
|
84
|
+
/** Which corner. Defaults to the corner away from the tail. */
|
|
85
|
+
align?: BubbleAlign;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A small pill hanging off a corner of the bubble — an emoji tapback, a
|
|
89
|
+
* count. The bubble's column reserves no room for it: it overlaps the
|
|
90
|
+
* edge, as tapbacks do.
|
|
91
|
+
*/
|
|
92
|
+
declare function Reactions({ side, align, className, ...props }: BubbleReactionsProps): import("react").JSX.Element;
|
|
93
|
+
/**
|
|
94
|
+
* A message's surface. `Root` takes the `variant` and `align`; `Content`
|
|
95
|
+
* is the chip (a `div`, or a `button` / link through `render`);
|
|
96
|
+
* `Reactions` hangs off a corner. Stack one author's consecutive bubbles
|
|
97
|
+
* in a `Group`.
|
|
98
|
+
*
|
|
99
|
+
* ```tsx
|
|
100
|
+
* <Bubble.Root variant="inverse" align="end">
|
|
101
|
+
* <Bubble.Content>On my way.</Bubble.Content>
|
|
102
|
+
* <Bubble.Reactions>👍</Bubble.Reactions>
|
|
103
|
+
* </Bubble.Root>
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare const Bubble: {
|
|
107
|
+
Root: typeof Root;
|
|
108
|
+
Content: typeof Content;
|
|
109
|
+
Reactions: typeof Reactions;
|
|
110
|
+
Group: typeof Group;
|
|
111
|
+
};
|
|
112
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Bubble, BUBBLE_VARIANTS, type BubbleAlign, type BubbleContentProps, type BubbleReactionsProps, type BubbleRootProps, type BubbleVariant, } from './bubble';
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { AnchorHTMLAttributes, ButtonHTMLAttributes, ComponentProps, ReactNode, Ref } from 'react';
|
|
2
|
+
import { InputProps } from '../input';
|
|
3
|
+
import { StatusViewProps } from '../status-view';
|
|
4
|
+
/**
|
|
5
|
+
* Chat — an inbox in one card: the conversations down the left, the open
|
|
6
|
+
* thread on the right with its messages scrolling up from the composer.
|
|
7
|
+
* It composes the smaller parts (`Message` rows of `Bubble`s in a
|
|
8
|
+
* `ScrollArea`, an `Input` for search, `Button`s to send and go back) the
|
|
9
|
+
* way `Sidebar` composes a rail: rows that press, one active, links
|
|
10
|
+
* through the host's `LinkProvider`.
|
|
11
|
+
*
|
|
12
|
+
* Two layouts. `default` seats both panes side by side — the divider
|
|
13
|
+
* between them drags so either pane can grow, each down to a min width.
|
|
14
|
+
* `compact` shows one at a time — the list, then the thread with a way
|
|
15
|
+
* back — for a narrow column or a phone. Opening a conversation pushes
|
|
16
|
+
* the thread in from the right; back pops the list in from the left, a
|
|
17
|
+
* short drift on `TRAVEL_LINEAR` with a `FADE_SWAP` fade. `auto` is
|
|
18
|
+
* compact only while the frame is narrower than 42rem (a container
|
|
19
|
+
* query, so it follows the card, not the viewport). Which pane is up is
|
|
20
|
+
* `pane`, controlled or not; opening a conversation moves to the thread,
|
|
21
|
+
* the header's back button returns.
|
|
22
|
+
*
|
|
23
|
+
* Presentational, like every Pho part: the page fetches, formats times,
|
|
24
|
+
* and decides who is who. The thread stays pinned to its newest message
|
|
25
|
+
* while the reader is at the bottom, and keeps its place when earlier
|
|
26
|
+
* pages arrive above.
|
|
27
|
+
*/
|
|
28
|
+
export type ChatLayout = "default" | "compact" | "auto";
|
|
29
|
+
export type ChatPane = "list" | "thread";
|
|
30
|
+
/** Push is 1 (thread from the right); pop is −1 (list from the left). */
|
|
31
|
+
export type ChatPaneDirection = 1 | -1;
|
|
32
|
+
/**
|
|
33
|
+
* The compact pane swap — incoming travels `PANE_TRAVEL_PX` on
|
|
34
|
+
* `TRAVEL_LINEAR`, fades and breathes `BLUR_PX` on `FADE_SWAP`; outgoing
|
|
35
|
+
* drifts `PANE_LEAVE_PX` the other way. Under reduced motion: opacity
|
|
36
|
+
* only, and instant.
|
|
37
|
+
*/
|
|
38
|
+
export declare function paneSwapMotion(direction: ChatPaneDirection, reduceMotion?: boolean | null): {
|
|
39
|
+
initial: {
|
|
40
|
+
opacity: number;
|
|
41
|
+
x?: undefined;
|
|
42
|
+
filter?: undefined;
|
|
43
|
+
};
|
|
44
|
+
animate: {
|
|
45
|
+
opacity: number;
|
|
46
|
+
x?: undefined;
|
|
47
|
+
filter?: undefined;
|
|
48
|
+
};
|
|
49
|
+
exit: {
|
|
50
|
+
opacity: number;
|
|
51
|
+
x?: undefined;
|
|
52
|
+
filter?: undefined;
|
|
53
|
+
};
|
|
54
|
+
transition: {
|
|
55
|
+
duration: number;
|
|
56
|
+
x?: undefined;
|
|
57
|
+
opacity?: undefined;
|
|
58
|
+
filter?: undefined;
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
initial: {
|
|
62
|
+
x: number;
|
|
63
|
+
opacity: number;
|
|
64
|
+
filter: string;
|
|
65
|
+
};
|
|
66
|
+
animate: {
|
|
67
|
+
x: number;
|
|
68
|
+
opacity: number;
|
|
69
|
+
filter: string;
|
|
70
|
+
};
|
|
71
|
+
exit: {
|
|
72
|
+
x: number;
|
|
73
|
+
opacity: number;
|
|
74
|
+
filter: string;
|
|
75
|
+
};
|
|
76
|
+
transition: {
|
|
77
|
+
x: {
|
|
78
|
+
readonly duration: 0.2;
|
|
79
|
+
readonly ease: "linear";
|
|
80
|
+
};
|
|
81
|
+
opacity: {
|
|
82
|
+
readonly duration: 0.2;
|
|
83
|
+
readonly ease: "easeOut";
|
|
84
|
+
};
|
|
85
|
+
filter: {
|
|
86
|
+
readonly duration: 0.2;
|
|
87
|
+
readonly ease: "easeOut";
|
|
88
|
+
};
|
|
89
|
+
duration?: undefined;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* DOM handlers whose React signatures clash with Motion's gesture props.
|
|
94
|
+
* Same omit list as `Button` — swap panes and conversation rows render
|
|
95
|
+
* through `motion.*`.
|
|
96
|
+
*/
|
|
97
|
+
type MotionHandlerConflicts = "onAnimationStart" | "onAnimationEnd" | "onAnimationIteration" | "onDrag" | "onDragStart" | "onDragEnd" | "onDragEnter" | "onDragExit" | "onDragLeave" | "onDragOver" | "onDrop";
|
|
98
|
+
export interface ChatRootProps extends ComponentProps<"div"> {
|
|
99
|
+
/**
|
|
100
|
+
* `default` shows both panes; `compact` one at a time; `auto` is
|
|
101
|
+
* compact while the frame is narrower than 42rem.
|
|
102
|
+
* @default "default"
|
|
103
|
+
*/
|
|
104
|
+
layout?: ChatLayout;
|
|
105
|
+
/** The pane that is up in a compact layout. Pair with `onPaneChange`. */
|
|
106
|
+
pane?: ChatPane;
|
|
107
|
+
/** Initial pane when uncontrolled. @default "list" */
|
|
108
|
+
defaultPane?: ChatPane;
|
|
109
|
+
/** Called with the next pane — a row opened a thread, back was pressed. */
|
|
110
|
+
onPaneChange?: (pane: ChatPane) => void;
|
|
111
|
+
ref?: Ref<HTMLDivElement>;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The card. Give it a height (`h-[32rem]`, or `min-h-0 flex-1` in a
|
|
115
|
+
* column that fills the page); the panes scroll inside it.
|
|
116
|
+
*/
|
|
117
|
+
declare function Root({ layout, pane: paneProp, defaultPane, onPaneChange, className, style, ref, ...props }: ChatRootProps): import("react").JSX.Element;
|
|
118
|
+
/** The left pane — search above, conversations below, on the page wash. */
|
|
119
|
+
declare function List({ className, children, id: idProp, ...props }: ComponentProps<"aside">): import("react").JSX.Element;
|
|
120
|
+
export interface ChatSearchProps extends Omit<InputProps, "size" | "icon" | "label" | "hint" | "labelTrailing"> {
|
|
121
|
+
}
|
|
122
|
+
/** The search row pinned over the conversations — an `sm` `Input`. */
|
|
123
|
+
declare function Search({ className, placeholder, ...props }: ChatSearchProps): import("react").JSX.Element;
|
|
124
|
+
/**
|
|
125
|
+
* The scrolling part of the list. Put a `ConversationList` in it — or a
|
|
126
|
+
* `ConversationsLoading`, an `Empty` — and anything that belongs after
|
|
127
|
+
* the rows (a load-older button).
|
|
128
|
+
*/
|
|
129
|
+
declare function Conversations({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
130
|
+
/** The rows. */
|
|
131
|
+
declare function ConversationList({ className, ...props }: ComponentProps<"ul">): import("react").JSX.Element;
|
|
132
|
+
/**
|
|
133
|
+
* DOM handlers whose React signatures clash with Motion's gesture props.
|
|
134
|
+
* Same omit list as `Button` — rows render through `motion.*`.
|
|
135
|
+
*/
|
|
136
|
+
interface ConversationBaseProps {
|
|
137
|
+
/** Who — a number, a name, the members of a group. */
|
|
138
|
+
title: ReactNode;
|
|
139
|
+
/** When — the page's relative time (`2d ago`), trailing. */
|
|
140
|
+
time?: ReactNode;
|
|
141
|
+
/** The latest message, one truncated line. */
|
|
142
|
+
preview?: ReactNode;
|
|
143
|
+
/** Replace the default avatar (a person, or people for a `group`). */
|
|
144
|
+
avatar?: ReactNode;
|
|
145
|
+
/** A group conversation — the default avatar shows people. */
|
|
146
|
+
group?: boolean;
|
|
147
|
+
/** The open conversation. */
|
|
148
|
+
active?: boolean;
|
|
149
|
+
className?: string;
|
|
150
|
+
}
|
|
151
|
+
export interface ChatConversationLinkProps extends ConversationBaseProps, Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof ConversationBaseProps | MotionHandlerConflicts> {
|
|
152
|
+
/** Destination — rendered through the host's `LinkProvider`. */
|
|
153
|
+
href: string;
|
|
154
|
+
}
|
|
155
|
+
export interface ChatConversationButtonProps extends ConversationBaseProps, Omit<ButtonHTMLAttributes<HTMLButtonElement>, keyof ConversationBaseProps | MotionHandlerConflicts> {
|
|
156
|
+
href?: undefined;
|
|
157
|
+
}
|
|
158
|
+
export type ChatConversationProps = ChatConversationLinkProps | ChatConversationButtonProps;
|
|
159
|
+
/**
|
|
160
|
+
* One conversation — a link when `href` is given (through the host's
|
|
161
|
+
* `LinkProvider`), otherwise a button. Opening it in a compact layout
|
|
162
|
+
* brings the thread up.
|
|
163
|
+
*/
|
|
164
|
+
declare function Conversation({ title, time, preview, avatar, group, active, className, href, onClick, ...rest }: ChatConversationProps): import("react").JSX.Element;
|
|
165
|
+
/** The right pane — header, messages, and the docked footer, on the card. */
|
|
166
|
+
declare function Thread({ className, children, ...props }: ComponentProps<"section">): import("react").JSX.Element;
|
|
167
|
+
export interface ChatHeaderProps extends ComponentProps<"header"> {
|
|
168
|
+
/** The other side's avatar — an `Avatar.Root`. */
|
|
169
|
+
avatar?: ReactNode;
|
|
170
|
+
/** Controls at the trailing edge — a details button, a menu. */
|
|
171
|
+
actions?: ReactNode;
|
|
172
|
+
/** The back button's accessible name. @default "Back to conversations" */
|
|
173
|
+
backLabel?: string;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Who the thread is with. Children are a `Title` and a `Description`.
|
|
177
|
+
* In a compact layout a back button leads the row; `auto` shows it only
|
|
178
|
+
* while the frame is narrow.
|
|
179
|
+
*/
|
|
180
|
+
declare function Header({ avatar, actions, backLabel, className, children, ...props }: ChatHeaderProps): import("react").JSX.Element;
|
|
181
|
+
/** The other side's name. Inline extras (a copy button, a badge) sit after it. */
|
|
182
|
+
declare function Title({ className, children, ...props }: ComponentProps<"h2">): import("react").JSX.Element;
|
|
183
|
+
/** One line under the title — from whom, a status. */
|
|
184
|
+
declare function Description({ className, ...props }: ComponentProps<"p">): import("react").JSX.Element;
|
|
185
|
+
export interface ChatMessagesProps extends ComponentProps<"div"> {
|
|
186
|
+
/** Earlier pages exist — a button at the top asks for them. */
|
|
187
|
+
hasEarlier?: boolean;
|
|
188
|
+
/** The earlier page is on its way. */
|
|
189
|
+
loadingEarlier?: boolean;
|
|
190
|
+
/** Ask for the page before the first message shown. */
|
|
191
|
+
onLoadEarlier?: () => void;
|
|
192
|
+
/** The button's label. @default "Load earlier messages" */
|
|
193
|
+
earlierLabel?: ReactNode;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The messages, oldest to newest, on the thread surface. The pane starts at
|
|
197
|
+
* the bottom and stays there as messages arrive unless the reader has
|
|
198
|
+
* scrolled up; an earlier page keeps what they were reading in place.
|
|
199
|
+
* Children are `Message` rows and `Divider`s.
|
|
200
|
+
*/
|
|
201
|
+
declare function Messages({ hasEarlier, loadingEarlier, onLoadEarlier, earlierLabel, className, children, ...props }: ChatMessagesProps): import("react").JSX.Element;
|
|
202
|
+
/** A centered caption in the thread — the day, "Unread". */
|
|
203
|
+
declare function Divider({ className, children, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
204
|
+
/** The docked bar under the messages — usually a `Composer`. */
|
|
205
|
+
declare function Footer({ className, ...props }: ComponentProps<"footer">): import("react").JSX.Element;
|
|
206
|
+
export interface ChatComposerProps extends Omit<ComponentProps<"form">, "onSubmit" | "prefix" | "children"> {
|
|
207
|
+
/** The draft. */
|
|
208
|
+
value: string;
|
|
209
|
+
onValueChange: (value: string) => void;
|
|
210
|
+
/** Enter, or the send button. Not called while `sending` or with nothing to send. */
|
|
211
|
+
onSend: () => void;
|
|
212
|
+
placeholder?: string;
|
|
213
|
+
/** The send is in flight — the button spins, the box waits. */
|
|
214
|
+
sending?: boolean;
|
|
215
|
+
disabled?: boolean;
|
|
216
|
+
/**
|
|
217
|
+
* There is something to send besides text (an attachment). By default
|
|
218
|
+
* the send button wakes when the draft has a non-blank character.
|
|
219
|
+
*/
|
|
220
|
+
canSend?: boolean;
|
|
221
|
+
/** Controls at the start of the bottom row — an add-attachment button. */
|
|
222
|
+
prefix?: ReactNode;
|
|
223
|
+
/** A quiet line between `prefix` and the send button — a count, a size. */
|
|
224
|
+
meta?: ReactNode;
|
|
225
|
+
/** The send button's accessible name. @default "Send" */
|
|
226
|
+
sendLabel?: string;
|
|
227
|
+
/** Above the text — attachment thumbnails. */
|
|
228
|
+
children?: ReactNode;
|
|
229
|
+
/** The `<textarea>`. */
|
|
230
|
+
textareaRef?: Ref<HTMLTextAreaElement>;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The message box: text that grows with the draft, Enter to send and
|
|
234
|
+
* Shift+Enter for a new line, one round send button. Attachments are the
|
|
235
|
+
* page's: put their thumbnails in `children`, the button that adds them
|
|
236
|
+
* in `prefix`, and flip `canSend` when they alone should send.
|
|
237
|
+
*/
|
|
238
|
+
declare function Composer({ value, onValueChange, onSend, placeholder, sending, disabled, canSend, prefix, meta, sendLabel, children, textareaRef, className, ...props }: ChatComposerProps): import("react").JSX.Element;
|
|
239
|
+
export interface ChatEmptyProps extends StatusViewProps {
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* The standing-in view for either pane — no conversations, no thread
|
|
243
|
+
* chosen, nothing said yet. `StatusView` at card size, centered in
|
|
244
|
+
* whatever room the pane has.
|
|
245
|
+
*/
|
|
246
|
+
declare function Empty({ className, size, ...props }: ChatEmptyProps): import("react").JSX.Element;
|
|
247
|
+
/** Bones in the shape of conversation rows — avatar, who, when, preview. */
|
|
248
|
+
declare function ConversationsLoading({ rows }: {
|
|
249
|
+
rows?: number;
|
|
250
|
+
}): import("react").JSX.Element;
|
|
251
|
+
/** Bones in a thread's shape — theirs left, ours right. */
|
|
252
|
+
declare function MessagesLoading(): import("react").JSX.Element;
|
|
253
|
+
/**
|
|
254
|
+
* The composed inbox. Assemble the two panes and fill them:
|
|
255
|
+
*
|
|
256
|
+
* ```tsx
|
|
257
|
+
* <Chat.Root layout="auto" className="h-[32rem]">
|
|
258
|
+
* <Chat.List>
|
|
259
|
+
* <Chat.Search value={query} onChange={…} />
|
|
260
|
+
* <Chat.Conversations>
|
|
261
|
+
* <Chat.ConversationList>
|
|
262
|
+
* <Chat.Conversation title="+1 (315) 997-8332" time="2d ago" preview="…" active />
|
|
263
|
+
* </Chat.ConversationList>
|
|
264
|
+
* </Chat.Conversations>
|
|
265
|
+
* </Chat.List>
|
|
266
|
+
* <Chat.Thread>
|
|
267
|
+
* <Chat.Header avatar={<Avatar.Root size="md">…</Avatar.Root>}>
|
|
268
|
+
* <Chat.Title>+1 (315) 997-8332</Chat.Title>
|
|
269
|
+
* <Chat.Description>From …</Chat.Description>
|
|
270
|
+
* </Chat.Header>
|
|
271
|
+
* <Chat.Messages>
|
|
272
|
+
* <Chat.Divider>September 12</Chat.Divider>
|
|
273
|
+
* <Message.Root>…</Message.Root>
|
|
274
|
+
* </Chat.Messages>
|
|
275
|
+
* <Chat.Footer>
|
|
276
|
+
* <Chat.Composer value={draft} onValueChange={setDraft} onSend={send} />
|
|
277
|
+
* </Chat.Footer>
|
|
278
|
+
* </Chat.Thread>
|
|
279
|
+
* </Chat.Root>
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
export declare const Chat: {
|
|
283
|
+
Root: typeof Root;
|
|
284
|
+
List: typeof List;
|
|
285
|
+
Search: typeof Search;
|
|
286
|
+
Conversations: typeof Conversations;
|
|
287
|
+
ConversationList: typeof ConversationList;
|
|
288
|
+
Conversation: typeof Conversation;
|
|
289
|
+
Thread: typeof Thread;
|
|
290
|
+
Header: typeof Header;
|
|
291
|
+
Title: typeof Title;
|
|
292
|
+
Description: typeof Description;
|
|
293
|
+
Messages: typeof Messages;
|
|
294
|
+
Divider: typeof Divider;
|
|
295
|
+
Footer: typeof Footer;
|
|
296
|
+
Composer: typeof Composer;
|
|
297
|
+
Empty: typeof Empty;
|
|
298
|
+
ConversationsLoading: typeof ConversationsLoading;
|
|
299
|
+
MessagesLoading: typeof MessagesLoading;
|
|
300
|
+
};
|
|
301
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Chat, type ChatComposerProps, type ChatConversationButtonProps, type ChatConversationLinkProps, type ChatConversationProps, type ChatEmptyProps, type ChatHeaderProps, type ChatLayout, type ChatMessagesProps, type ChatPane, type ChatRootProps, type ChatSearchProps, } from './chat';
|
|
@@ -5,7 +5,7 @@ type StyledProps<T extends ElementType> = Omit<ComponentProps<T>, "className"> &
|
|
|
5
5
|
className?: string;
|
|
6
6
|
};
|
|
7
7
|
declare function Trigger({ className, ...props }: StyledProps<typeof BaseCollapsible.Trigger>): import("react").JSX.Element;
|
|
8
|
-
declare function Panel({ className, ...props }: StyledProps<typeof BaseCollapsible.Panel>): import("react").JSX.Element;
|
|
8
|
+
declare function Panel({ className, onTransitionRun, onTransitionEnd, onTransitionCancel, ...props }: StyledProps<typeof BaseCollapsible.Panel>): import("react").JSX.Element;
|
|
9
9
|
/**
|
|
10
10
|
* Show/hide a region of content, built on Base UI `Collapsible` with a smooth
|
|
11
11
|
* height animation. Control with `open` / `onOpenChange` or leave uncontrolled
|
|
@@ -18,6 +18,7 @@ declare function Group({ className, ...props }: ComponentProps<typeof CommandPri
|
|
|
18
18
|
* - `result` — flat search hit (breadcrumb + trailing scope)
|
|
19
19
|
*/
|
|
20
20
|
export type CommandItemLevel = "item" | "subitem" | "subsubitem" | "result";
|
|
21
|
+
export type CommandItemSize = "sm" | "md";
|
|
21
22
|
type ItemPrimitiveProps = ComponentProps<typeof CommandPrimitive.Item>;
|
|
22
23
|
export interface CommandItemProps extends Omit<ItemPrimitiveProps, "children" | "title"> {
|
|
23
24
|
/**
|
|
@@ -39,6 +40,12 @@ export interface CommandItemProps extends Omit<ItemPrimitiveProps, "children" |
|
|
|
39
40
|
* has an icon; omit when the whole result set is icon-less.
|
|
40
41
|
*/
|
|
41
42
|
iconSlot?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Row density. `sm` tightens padding and type for chip popovers
|
|
45
|
+
* (Filter Bar options). Palette destinations stay `md`.
|
|
46
|
+
* @default "md"
|
|
47
|
+
*/
|
|
48
|
+
size?: CommandItemSize;
|
|
42
49
|
/** Primary label. Prefer this over free-form children for the shared layout. */
|
|
43
50
|
title?: ReactNode;
|
|
44
51
|
/**
|
|
@@ -58,13 +65,16 @@ export interface CommandItemProps extends Omit<ItemPrimitiveProps, "children" |
|
|
|
58
65
|
*/
|
|
59
66
|
children?: ReactNode;
|
|
60
67
|
}
|
|
61
|
-
/** Leading icon column — `size-4`,
|
|
62
|
-
declare function ItemIcon({ className, ...props }: ComponentProps<"span">
|
|
68
|
+
/** Leading icon column — `size-4` at `md`, tighter at `sm`. */
|
|
69
|
+
declare function ItemIcon({ className, size, ...props }: ComponentProps<"span"> & {
|
|
70
|
+
size?: CommandItemSize;
|
|
71
|
+
}): import("react").JSX.Element;
|
|
63
72
|
/** Primary label — medium + primary ink on `item` rows. */
|
|
64
|
-
declare function ItemTitle({ className, level, ...props }: ComponentProps<"span"> & {
|
|
73
|
+
declare function ItemTitle({ className, level, size, ...props }: ComponentProps<"span"> & {
|
|
65
74
|
level?: CommandItemLevel;
|
|
75
|
+
size?: CommandItemSize;
|
|
66
76
|
}): import("react").JSX.Element;
|
|
67
|
-
declare function Item({ className, level, icon, iconSlot, title, path, scope, external, children, value, ...props }: CommandItemProps): import("react").JSX.Element;
|
|
77
|
+
declare function Item({ className, level, size, icon, iconSlot, title, path, scope, external, children, value, ...props }: CommandItemProps): import("react").JSX.Element;
|
|
68
78
|
declare function Separator({ className, ...props }: ComponentProps<typeof CommandPrimitive.Separator>): import("react").JSX.Element;
|
|
69
79
|
declare function Loading({ className, ...props }: ComponentProps<typeof CommandPrimitive.Loading>): import("react").JSX.Element;
|
|
70
80
|
type DialogRootProps = ComponentProps<typeof PhoDialog.Root>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Command, useCommandState, type CommandItemLevel, type CommandItemProps, } from './command';
|
|
1
|
+
export { Command, useCommandState, type CommandItemLevel, type CommandItemProps, type CommandItemSize, } from './command';
|
|
@@ -21,6 +21,11 @@ import { ComponentProps, ReactNode, Ref } from 'react';
|
|
|
21
21
|
export interface FilterOption {
|
|
22
22
|
value: string;
|
|
23
23
|
label: string;
|
|
24
|
+
/**
|
|
25
|
+
* Rich option row (a badge, mono path). Search and the set chip still
|
|
26
|
+
* use `label` and `value` strings.
|
|
27
|
+
*/
|
|
28
|
+
title?: ReactNode;
|
|
24
29
|
}
|
|
25
30
|
interface FilterDefinitionBase {
|
|
26
31
|
/** The key in `filters` this chip reads and writes. */
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One row in a thread, enough to decide whether its outbound status
|
|
3
|
+
* caption should show. Inbound rows leave `outbound` off.
|
|
4
|
+
*/
|
|
5
|
+
export interface MessageStatusItem {
|
|
6
|
+
outbound?: boolean;
|
|
7
|
+
/** Delivered, Sent, Failed — or a token like `delivered`. */
|
|
8
|
+
status?: string | null;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The coalesce key for a row: outbound status word, lowercased. Inbound
|
|
12
|
+
* and empty statuses are `null`, so they break a run. A failure keeps its
|
|
13
|
+
* whole text (`failed. 30007`) so two different error codes never
|
|
14
|
+
* collapse into one caption.
|
|
15
|
+
*/
|
|
16
|
+
export declare function messageStatusKey(outbound: boolean, status: string | null | undefined): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* Whether this row should render its outbound status (Delivered, Sent,
|
|
19
|
+
* Failed). Only the last message in a consecutive same-status run shows
|
|
20
|
+
* it. Inbound never does.
|
|
21
|
+
*/
|
|
22
|
+
export declare function shouldShowMessageStatus(messages: readonly MessageStatusItem[], index: number): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Message — one turn in a thread: the row that seats an avatar beside a
|
|
4
|
+
* column of header, bubble, and footer, on the author's side. It owns the
|
|
5
|
+
* row layout and nothing else: the surface is `Bubble`'s, the scrolling
|
|
6
|
+
* and the composer are `Chat`'s.
|
|
7
|
+
*
|
|
8
|
+
* Design notes:
|
|
9
|
+
* - `align="end"` mirrors the row — avatar on the right, column
|
|
10
|
+
* right-aligned — for the reader's own messages.
|
|
11
|
+
* - The avatar sits at the row's bottom, level with the bubble. When a
|
|
12
|
+
* `Footer` (status) sits under the bubble, the avatar shifts up by one
|
|
13
|
+
* line so it stays beside the surface.
|
|
14
|
+
* - `Time` sits beside the bubble, last-line aligned — right of inbound,
|
|
15
|
+
* left of outbound — and is invisible until the row is hovered or
|
|
16
|
+
* focused. `Footer` is the status caption under the bubble (Delivered,
|
|
17
|
+
* Failed). Inbound has no status.
|
|
18
|
+
*/
|
|
19
|
+
export type MessageAlign = "start" | "end";
|
|
20
|
+
/** Consecutive messages from one author, spaced as one turn. */
|
|
21
|
+
declare function Group({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
22
|
+
export interface MessageRootProps extends ComponentProps<"div"> {
|
|
23
|
+
/** Which side the author sits on. @default "start" */
|
|
24
|
+
align?: MessageAlign;
|
|
25
|
+
}
|
|
26
|
+
/** The row: avatar beside the content column, mirrored for `end`. */
|
|
27
|
+
declare function Root({ align, className, ...props }: MessageRootProps): import("react").JSX.Element;
|
|
28
|
+
/**
|
|
29
|
+
* The avatar's seat — pass an `Avatar.Root`. Bottom-aligned with the
|
|
30
|
+
* bubble; lifts by one footer line when the message has a `Footer`.
|
|
31
|
+
*/
|
|
32
|
+
declare function Avatar({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
33
|
+
/**
|
|
34
|
+
* Header over the bubble; time beside it; status under it. Inbound is
|
|
35
|
+
* `[bubble][time]`. Outbound is `[time][bubble]` with `Footer` below
|
|
36
|
+
* the bubble column.
|
|
37
|
+
*/
|
|
38
|
+
declare function Content({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
39
|
+
/** Who — the sender's name over the bubble, secondary ink. */
|
|
40
|
+
declare function Header({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
41
|
+
/**
|
|
42
|
+
* Clock beside the bubble, last-line aligned. Description ink, tabular.
|
|
43
|
+
* Inbound sits to the right; outbound to the left. The slot stays in
|
|
44
|
+
* layout; the digits show when the row is hovered or focused.
|
|
45
|
+
*/
|
|
46
|
+
declare function Time({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
47
|
+
/**
|
|
48
|
+
* Status under the bubble — Delivered, Failed. Inbound leaves it off.
|
|
49
|
+
* Description ink.
|
|
50
|
+
*/
|
|
51
|
+
declare function Footer({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
|
|
52
|
+
/**
|
|
53
|
+
* A turn in a thread. `Root` takes `align`; `Avatar` seats an
|
|
54
|
+
* `Avatar.Root`; `Content` places `Header` over the bubble, `Time`
|
|
55
|
+
* beside it, and `Footer` under it.
|
|
56
|
+
*
|
|
57
|
+
* ```tsx
|
|
58
|
+
* <Message.Root align="end">
|
|
59
|
+
* <Message.Content>
|
|
60
|
+
* <Bubble.Root variant="inverse" align="end">
|
|
61
|
+
* <Bubble.Content>On my way.</Bubble.Content>
|
|
62
|
+
* </Bubble.Root>
|
|
63
|
+
* <Message.Time>2:47 PM</Message.Time>
|
|
64
|
+
* <Message.Footer>Delivered.</Message.Footer>
|
|
65
|
+
* </Message.Content>
|
|
66
|
+
* </Message.Root>
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare const Message: {
|
|
70
|
+
Root: typeof Root;
|
|
71
|
+
Group: typeof Group;
|
|
72
|
+
Avatar: typeof Avatar;
|
|
73
|
+
Content: typeof Content;
|
|
74
|
+
Header: typeof Header;
|
|
75
|
+
Time: typeof Time;
|
|
76
|
+
Footer: typeof Footer;
|
|
77
|
+
};
|
|
78
|
+
export {};
|
package/dist/src/index.d.ts
CHANGED
|
@@ -28,3 +28,6 @@ export * from './components/log-list';
|
|
|
28
28
|
export * from './components/description-list';
|
|
29
29
|
export * from './components/code-block';
|
|
30
30
|
export * from './components/trace';
|
|
31
|
+
export * from './components/bubble';
|
|
32
|
+
export * from './components/message';
|
|
33
|
+
export * from './components/chat';
|
|
@@ -126,6 +126,13 @@ interface ItemBaseProps {
|
|
|
126
126
|
icon?: Slottable;
|
|
127
127
|
/** Marks the row as the current destination (adds `aria-current="page"`). */
|
|
128
128
|
active?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Let the label break onto two lines instead of truncating. Default
|
|
131
|
+
* rows stay a single truncated line so the rail keeps even height.
|
|
132
|
+
* The row still uses `min-h-9`; wrap only grows it when the text
|
|
133
|
+
* actually breaks. Caps at two lines.
|
|
134
|
+
*/
|
|
135
|
+
wrap?: boolean;
|
|
129
136
|
children?: ReactNode;
|
|
130
137
|
className?: string;
|
|
131
138
|
}
|
|
@@ -149,8 +156,10 @@ export type SidebarItemProps = SidebarItemLinkProps | SidebarItemButtonProps;
|
|
|
149
156
|
* A nav row — a link when `href` is given (rendered through the host's
|
|
150
157
|
* `LinkProvider`), otherwise a button. `active` lifts the row onto the
|
|
151
158
|
* primary surface; `external` opens a new tab and appends a ↗ cue.
|
|
159
|
+
* `wrap` drops the single-line truncate so a long product name can sit
|
|
160
|
+
* on two lines; other rows stay one line.
|
|
152
161
|
*/
|
|
153
|
-
declare function Item({ icon, active, className, children, href, external, ...rest }: SidebarItemProps): import("react").JSX.Element;
|
|
162
|
+
declare function Item({ icon, active, wrap, className, children, href, external, ...rest }: SidebarItemProps): import("react").JSX.Element;
|
|
154
163
|
export interface SidebarSubmenuProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | MotionHandlerConflicts> {
|
|
155
164
|
/** The parent row's label. */
|
|
156
165
|
label: ReactNode;
|
|
@@ -4,6 +4,12 @@ import { ValueAnimationTransition } from 'motion/react';
|
|
|
4
4
|
* Animates its own height to follow the measured height of `children`, so
|
|
5
5
|
* content swaps (search filtering, skeleton → data) glide instead of jumping.
|
|
6
6
|
* Honors `prefers-reduced-motion` by snapping height with no spring.
|
|
7
|
+
*
|
|
8
|
+
* The container clips only while the spring is in flight. ResizeObserver
|
|
9
|
+
* callbacks run after layout but before paint, so the clip lands before the
|
|
10
|
+
* swap frame can show; once the spring settles it is lifted again, so a focus
|
|
11
|
+
* ring, an effect button's rim, or any other overhang on the last row paints
|
|
12
|
+
* normally at rest instead of being cut off at the container's edge.
|
|
7
13
|
*/
|
|
8
14
|
export declare function AnimatedHeight({ className, transition, children, }: {
|
|
9
15
|
className?: string;
|