panelui-web 0.10.1 → 0.11.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/components/alert/index.d.ts +15 -8
- package/dist/components/alert/index.js +65 -18
- package/dist/components/alert-dialog/index.d.ts +9 -3
- package/dist/components/alert-dialog/index.js +23 -7
- package/dist/components/avatar/index.d.ts +9 -3
- package/dist/components/avatar/index.js +34 -10
- package/dist/components/badge/index.d.ts +57 -0
- package/dist/components/badge/index.js +61 -0
- package/dist/components/bar-picker/index.d.ts +8 -1
- package/dist/components/bar-picker/index.js +35 -26
- package/dist/components/button/index.d.ts +68 -46
- package/dist/components/button/index.js +38 -2
- package/dist/components/button-group/index.d.ts +11 -5
- package/dist/components/button-group/index.js +31 -7
- package/dist/components/canvas/index.d.ts +9 -3
- package/dist/components/canvas/index.js +53 -25
- package/dist/components/card/index.d.ts +13 -7
- package/dist/components/card/index.js +45 -17
- package/dist/components/checkbox/index.d.ts +73 -0
- package/dist/components/checkbox/index.js +100 -0
- package/dist/components/chip/index.d.ts +79 -0
- package/dist/components/chip/index.js +112 -0
- package/dist/components/choice-cards/index.d.ts +11 -5
- package/dist/components/choice-cards/index.js +25 -6
- package/dist/components/command-dock/index.d.ts +16 -9
- package/dist/components/command-dock/index.js +76 -19
- package/dist/components/day-grid/index.d.ts +12 -6
- package/dist/components/day-grid/index.js +71 -27
- package/dist/components/dialog/index.d.ts +19 -12
- package/dist/components/dialog/index.js +76 -24
- package/dist/components/feedback/index.d.ts +20 -13
- package/dist/components/feedback/index.js +83 -27
- package/dist/components/field/index.d.ts +85 -0
- package/dist/components/field/index.js +90 -0
- package/dist/components/flow/index.d.ts +21 -14
- package/dist/components/flow/index.js +56 -20
- package/dist/components/frame/index.d.ts +17 -11
- package/dist/components/frame/index.js +73 -22
- package/dist/components/input/index.d.ts +9 -24
- package/dist/components/input/index.js +53 -6
- package/dist/components/inspector/index.d.ts +69 -63
- package/dist/components/inspector/index.js +31 -9
- package/dist/components/kpi/index.d.ts +20 -14
- package/dist/components/kpi/index.js +111 -36
- package/dist/components/label/index.d.ts +10 -4
- package/dist/components/label/index.js +39 -9
- package/dist/components/lane-board/index.d.ts +15 -9
- package/dist/components/lane-board/index.js +97 -57
- package/dist/components/menu/index.d.ts +10 -4
- package/dist/components/menu/index.js +28 -10
- package/dist/components/message/index.d.ts +15 -9
- package/dist/components/message/index.js +71 -19
- package/dist/components/not-found/index.d.ts +10 -4
- package/dist/components/not-found/index.js +48 -12
- package/dist/components/planet/index.d.ts +11 -5
- package/dist/components/planet/index.js +73 -20
- package/dist/components/prompt/index.d.ts +30 -23
- package/dist/components/prompt/index.js +148 -52
- package/dist/components/radio-group/index.d.ts +124 -0
- package/dist/components/radio-group/index.js +216 -0
- package/dist/components/range-meter/index.d.ts +9 -3
- package/dist/components/range-meter/index.js +61 -27
- package/dist/components/rolling-number/index.d.ts +8 -1
- package/dist/components/rolling-number/index.js +15 -6
- package/dist/components/select/index.d.ts +7 -1
- package/dist/components/select/index.js +13 -4
- package/dist/components/sheet/index.d.ts +8 -2
- package/dist/components/sheet/index.js +27 -15
- package/dist/components/slider/index.d.ts +11 -4
- package/dist/components/slider/index.js +30 -10
- package/dist/components/soundwave/index.d.ts +8 -2
- package/dist/components/soundwave/index.js +26 -6
- package/dist/components/stat/index.d.ts +13 -7
- package/dist/components/stat/index.js +45 -15
- package/dist/components/table/index.d.ts +128 -0
- package/dist/components/table/index.js +145 -0
- package/dist/components/tabs/index.d.ts +7 -1
- package/dist/components/tabs/index.js +8 -2
- package/dist/components/textarea/index.d.ts +0 -23
- package/dist/components/textarea/index.js +22 -5
- package/dist/components/tilt-card/index.d.ts +9 -3
- package/dist/components/tilt-card/index.js +28 -8
- package/dist/components/timeline/index.d.ts +20 -13
- package/dist/components/timeline/index.js +166 -59
- package/dist/components/toast/dither-text.d.ts +13 -0
- package/dist/components/toast/dither-text.js +143 -0
- package/dist/components/toast/dither.d.ts +29 -0
- package/dist/components/toast/dither.js +153 -0
- package/dist/components/toast/index.d.ts +108 -0
- package/dist/components/toast/index.js +225 -0
- package/dist/components/toolbar/index.d.ts +9 -3
- package/dist/components/toolbar/index.js +23 -6
- package/dist/components/workbench/index.d.ts +50 -43
- package/dist/components/workbench/index.js +77 -20
- package/dist/components/xy-pad/index.d.ts +9 -3
- package/dist/components/xy-pad/index.js +13 -2
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
4
|
* LaneBoard — lanes side by side, each holding cards that can be dragged
|
|
5
5
|
* within a lane and from one lane to another.
|
|
@@ -46,6 +46,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
46
46
|
import { ScrollArea } from '@base-ui/react/scroll-area';
|
|
47
47
|
import { useCallback, useEffect, useLayoutEffect, useRef, useState, } from 'react';
|
|
48
48
|
import { tv } from 'tailwind-variants';
|
|
49
|
+
import { mergeProps } from '@base-ui/react/merge-props';
|
|
50
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
49
51
|
const laneBoardVariants = tv({
|
|
50
52
|
slots: {
|
|
51
53
|
root: 'relative w-full',
|
|
@@ -186,7 +188,7 @@ function whereIs(lanes, id) {
|
|
|
186
188
|
}
|
|
187
189
|
return null;
|
|
188
190
|
}
|
|
189
|
-
function LaneBoardRoot({ lanes: controlled, defaultLanes, onLanesChange, onMove, renderCard, renderLaneFooter, cardName = (card) => card.id, label = 'Board', height = '28rem', className, style, ...props }) {
|
|
191
|
+
function LaneBoardRoot({ lanes: controlled, defaultLanes, onLanesChange, onMove, renderCard, renderLaneFooter, cardName = (card) => card.id, label = 'Board', height = '28rem', className, style, render, ...props }) {
|
|
190
192
|
const slots = laneBoardVariants();
|
|
191
193
|
const [internal, setInternal] = useState(defaultLanes ?? []);
|
|
192
194
|
const settled = controlled ?? internal;
|
|
@@ -605,83 +607,121 @@ function LaneBoardRoot({ lanes: controlled, defaultLanes, onLanesChange, onMove,
|
|
|
605
607
|
});
|
|
606
608
|
const carried = carry ? whereIs(shown, carry.id) : null;
|
|
607
609
|
const carriedLane = carried ? shown.find((lane) => lane.id === carried.lane) : undefined;
|
|
608
|
-
return (
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
610
|
+
return useRender({
|
|
611
|
+
defaultTagName: 'div',
|
|
612
|
+
render,
|
|
613
|
+
props: mergeProps({
|
|
614
|
+
ref: root,
|
|
615
|
+
role: 'group',
|
|
616
|
+
'aria-label': label,
|
|
617
|
+
className: slots.root({ className }),
|
|
618
|
+
style: { height: height === 'auto' ? undefined : height, ...style },
|
|
619
|
+
children: (_jsxs(_Fragment, { children: [_jsxs(ScrollArea.Root, { className: slots.board(), children: [_jsx(ScrollArea.Viewport, { ref: scroller, className: slots.boardViewport(), children: _jsx("div", { className: slots.lanes(), children: shown.map((lane) => (_jsxs("section", { ref: (node) => {
|
|
620
|
+
if (node)
|
|
621
|
+
sections.current.set(lane.id, node);
|
|
622
|
+
else
|
|
623
|
+
sections.current.delete(lane.id);
|
|
624
|
+
}, "aria-label": typeof lane.title === 'string' ? lane.title : undefined, "data-over": carried?.lane === lane.id ? '' : undefined, className: laneBoardVariants({ over: carried?.lane === lane.id }).lane(), children: [_jsxs("header", { className: slots.laneHeader(), children: [_jsxs("div", { className: slots.laneHeading(), children: [lane.color ? (_jsx("span", { "aria-hidden": "true", className: laneBoardVariants({ color: lane.color }).laneDot() })) : null, _jsx("h3", { className: slots.laneTitle(), children: lane.title })] }), _jsx("span", { className: laneBoardVariants({
|
|
625
|
+
full: lane.limit !== undefined && lane.cards.length > lane.limit,
|
|
626
|
+
}).laneCount(), children: lane.limit === undefined ? lane.cards.length : `${lane.cards.length}/${lane.limit}` })] }), _jsxs(ScrollArea.Root, { className: slots.laneScroller(), children: [_jsx(ScrollArea.Viewport, { ref: (node) => {
|
|
627
|
+
if (node)
|
|
628
|
+
viewports.current.set(lane.id, node);
|
|
629
|
+
else
|
|
630
|
+
viewports.current.delete(lane.id);
|
|
631
|
+
}, className: slots.laneViewport(), children: _jsx("ol", { className: slots.list(), children: lane.cards.map((card) => {
|
|
632
|
+
const isCarried = carry?.id === card.id;
|
|
633
|
+
const state = !isCarried ? 'rest' : carry.by === 'pointer' ? 'placeholder' : 'held';
|
|
634
|
+
return (_jsx("li", { ref: (node) => {
|
|
635
|
+
if (node)
|
|
636
|
+
cards.current.set(card.id, node);
|
|
637
|
+
else
|
|
638
|
+
cards.current.delete(card.id);
|
|
639
|
+
}, tabIndex: 0, "aria-roledescription": "Card that can be moved", "aria-label": cardName(card), "data-card": card.id, "data-carried": isCarried ? carry.by : undefined, className: laneBoardVariants({ state }).card(), onPointerDown: (event) => onPointerDown(event, card.id), onKeyDown: (event) => onKeyDown(event, card), onBlur: () => {
|
|
640
|
+
// Focus leaving a card held with the keyboard puts it
|
|
641
|
+
// back: nothing is steering it any more.
|
|
642
|
+
if (carry?.by === 'keys' &&
|
|
643
|
+
carry.id === card.id &&
|
|
644
|
+
!cards.current.get(card.id)?.matches(':focus')) {
|
|
645
|
+
requestAnimationFrame(() => {
|
|
646
|
+
if (document.activeElement !== cards.current.get(card.id)) {
|
|
647
|
+
setDraft(null);
|
|
648
|
+
setCarry(null);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
644
651
|
}
|
|
645
|
-
});
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
652
|
+
}, children: renderCard(card, { lane, carried: isCarried }) }, card.id));
|
|
653
|
+
}) }) }), _jsx(ScrollArea.Scrollbar, { orientation: "vertical", className: slots.scrollbar(), children: _jsx(ScrollArea.Thumb, { className: slots.thumb() }) })] }), _jsx("div", { className: slots.laneFooter(), children: renderLaneFooter?.(lane) })] }, lane.id))) }) }), _jsx(ScrollArea.Scrollbar, { orientation: "horizontal", className: slots.scrollbar(), children: _jsx(ScrollArea.Thumb, { className: slots.thumb() }) })] }), carry?.by === 'pointer' && carried && carriedLane ? (_jsx("div", { ref: overlay, "aria-hidden": "true", className: slots.overlay(), style: { width: drag.current?.width }, children: renderCard(carried.card, { lane: carriedLane, carried: true }) })) : null, _jsx("span", { "aria-live": "assertive", className: "sr-only", children: said })] })),
|
|
654
|
+
}, props),
|
|
655
|
+
});
|
|
649
656
|
}
|
|
650
657
|
LaneBoardRoot.displayName = 'LaneBoard';
|
|
651
658
|
/** A card's name. */
|
|
652
|
-
function LaneBoardTitle({ className, ...props }) {
|
|
653
|
-
return
|
|
659
|
+
function LaneBoardTitle({ className, render, ...props }) {
|
|
660
|
+
return useRender({
|
|
661
|
+
defaultTagName: 'div',
|
|
662
|
+
render,
|
|
663
|
+
props: mergeProps({ className: laneBoardVariants().title({ className }) }, props),
|
|
664
|
+
});
|
|
654
665
|
}
|
|
655
666
|
LaneBoardTitle.displayName = 'LaneBoard.Title';
|
|
656
667
|
/** A card's reference, in a fixed-width face so a column of them lines up. */
|
|
657
|
-
function LaneBoardCode({ className, ...props }) {
|
|
658
|
-
return
|
|
668
|
+
function LaneBoardCode({ className, render, ...props }) {
|
|
669
|
+
return useRender({
|
|
670
|
+
defaultTagName: 'div',
|
|
671
|
+
render,
|
|
672
|
+
props: mergeProps({ className: laneBoardVariants().code({ className }) }, props),
|
|
673
|
+
});
|
|
659
674
|
}
|
|
660
675
|
LaneBoardCode.displayName = 'LaneBoard.Code';
|
|
661
676
|
/** The last line of a card: something at each end. */
|
|
662
|
-
function LaneBoardRow({ className, ...props }) {
|
|
663
|
-
return
|
|
677
|
+
function LaneBoardRow({ className, render, ...props }) {
|
|
678
|
+
return useRender({
|
|
679
|
+
defaultTagName: 'div',
|
|
680
|
+
render,
|
|
681
|
+
props: mergeProps({ className: laneBoardVariants().row({ className }) }, props),
|
|
682
|
+
});
|
|
664
683
|
}
|
|
665
684
|
LaneBoardRow.displayName = 'LaneBoard.Row';
|
|
666
685
|
/** How far along a card is, as a row of dashes with the done ones lit. */
|
|
667
|
-
function LaneBoardSteps({ value, max = 5, color = 'primary', label = 'Progress', className, ...props }) {
|
|
686
|
+
function LaneBoardSteps({ value, max = 5, color = 'primary', label = 'Progress', className, render, ...props }) {
|
|
668
687
|
const slots = laneBoardVariants({ color });
|
|
669
|
-
return (
|
|
688
|
+
return useRender({
|
|
689
|
+
defaultTagName: 'div',
|
|
690
|
+
render,
|
|
691
|
+
props: mergeProps({
|
|
692
|
+
role: 'img',
|
|
693
|
+
'aria-label': `${label}: ${value} of ${max}`,
|
|
694
|
+
className: slots.steps({ className }),
|
|
695
|
+
children: (_jsx(_Fragment, { children: Array.from({ length: max }, (_, index) => (_jsx("span", { className: laneBoardVariants({ lit: index < value }).step() }, index))) })),
|
|
696
|
+
}, props),
|
|
697
|
+
});
|
|
670
698
|
}
|
|
671
699
|
LaneBoardSteps.displayName = 'LaneBoard.Steps';
|
|
672
700
|
/** A word in a pill, for a card's state. */
|
|
673
|
-
function LaneBoardTag({ color = 'primary', className, ...props }) {
|
|
674
|
-
return
|
|
701
|
+
function LaneBoardTag({ color = 'primary', className, render, ...props }) {
|
|
702
|
+
return useRender({
|
|
703
|
+
defaultTagName: 'span',
|
|
704
|
+
render,
|
|
705
|
+
props: mergeProps({ className: laneBoardVariants({ color }).tag({ className }) }, props),
|
|
706
|
+
});
|
|
675
707
|
}
|
|
676
708
|
LaneBoardTag.displayName = 'LaneBoard.Tag';
|
|
677
709
|
/** A short figure at the end of a card's last line: a time, a count. */
|
|
678
|
-
function LaneBoardMeta({ className, ...props }) {
|
|
679
|
-
return
|
|
710
|
+
function LaneBoardMeta({ className, render, ...props }) {
|
|
711
|
+
return useRender({
|
|
712
|
+
defaultTagName: 'span',
|
|
713
|
+
render,
|
|
714
|
+
props: mergeProps({ className: laneBoardVariants().meta({ className }) }, props),
|
|
715
|
+
});
|
|
680
716
|
}
|
|
681
717
|
LaneBoardMeta.displayName = 'LaneBoard.Meta';
|
|
682
718
|
/** Who a card belongs to, as initials in a small circle. */
|
|
683
|
-
function LaneBoardAvatar({ className, ...props }) {
|
|
684
|
-
return
|
|
719
|
+
function LaneBoardAvatar({ className, render, ...props }) {
|
|
720
|
+
return useRender({
|
|
721
|
+
defaultTagName: 'span',
|
|
722
|
+
render,
|
|
723
|
+
props: mergeProps({ 'data-slot': 'lane-board-avatar', className: laneBoardVariants().avatar({ className }) }, props),
|
|
724
|
+
});
|
|
685
725
|
}
|
|
686
726
|
LaneBoardAvatar.displayName = 'LaneBoard.Avatar';
|
|
687
727
|
export const LaneBoard = Object.assign(LaneBoardRoot, {
|
|
@@ -695,4 +735,4 @@ export const LaneBoard = Object.assign(LaneBoardRoot, {
|
|
|
695
735
|
});
|
|
696
736
|
/* By name as well, for a Server Component, which cannot dot into a client
|
|
697
737
|
module. */
|
|
698
|
-
export { LaneBoardTitle, LaneBoardCode, LaneBoardRow, LaneBoardSteps, LaneBoardTag, LaneBoardMeta, LaneBoardAvatar
|
|
738
|
+
export { LaneBoardTitle, LaneBoardCode, LaneBoardRow, LaneBoardSteps, LaneBoardTag, LaneBoardMeta, LaneBoardAvatar };
|
|
@@ -42,6 +42,12 @@
|
|
|
42
42
|
*/
|
|
43
43
|
import { Menu as BaseMenu } from '@base-ui/react/menu';
|
|
44
44
|
import type { ComponentProps, ReactNode } from 'react';
|
|
45
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
46
|
+
import type { ElementType as RenderElementType } from 'react';
|
|
47
|
+
/** Draws a part as another element, or composes it with a component: `render={<a href="/" />}`. */
|
|
48
|
+
type RenderProp<Tag extends RenderElementType> = {
|
|
49
|
+
render?: useRender.ComponentProps<Tag>['render'];
|
|
50
|
+
};
|
|
45
51
|
export interface MenuProps extends BaseMenu.Root.Props {
|
|
46
52
|
}
|
|
47
53
|
/** Holds whether the menu is open. Takes `open`/`onOpenChange`, `defaultOpen` and `modal`. */
|
|
@@ -157,28 +163,28 @@ declare namespace MenuGroupLabel {
|
|
|
157
163
|
export interface MenuSeparatorProps extends ComponentProps<'div'> {
|
|
158
164
|
}
|
|
159
165
|
/** A rule between groups of items. */
|
|
160
|
-
declare function MenuSeparator({ className, ...props }: MenuSeparatorProps): import("react").
|
|
166
|
+
declare function MenuSeparator({ className, render, ...props }: MenuSeparatorProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
161
167
|
declare namespace MenuSeparator {
|
|
162
168
|
var displayName: string;
|
|
163
169
|
}
|
|
164
170
|
export interface MenuDescriptionProps extends ComponentProps<'span'> {
|
|
165
171
|
}
|
|
166
172
|
/** What an item does, in quieter words after its label. */
|
|
167
|
-
declare function MenuDescription({ className, ...props }: MenuDescriptionProps): import("react").
|
|
173
|
+
declare function MenuDescription({ className, render, ...props }: MenuDescriptionProps & RenderProp<'span'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
168
174
|
declare namespace MenuDescription {
|
|
169
175
|
var displayName: string;
|
|
170
176
|
}
|
|
171
177
|
export interface MenuShortcutProps extends ComponentProps<'kbd'> {
|
|
172
178
|
}
|
|
173
179
|
/** The keys for an item, at its end. It only shows them: wire the keys up where the action lives. */
|
|
174
|
-
declare function MenuShortcut({ className, ...props }: MenuShortcutProps): import("react").
|
|
180
|
+
declare function MenuShortcut({ className, render, ...props }: MenuShortcutProps & RenderProp<'kbd'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
175
181
|
declare namespace MenuShortcut {
|
|
176
182
|
var displayName: string;
|
|
177
183
|
}
|
|
178
184
|
export interface MenuBadgeProps extends ComponentProps<'span'> {
|
|
179
185
|
}
|
|
180
186
|
/** A small count or flag at an item's end: how many need attention, or that something is new. */
|
|
181
|
-
declare function MenuBadge({ className, ...props }: MenuBadgeProps): import("react").
|
|
187
|
+
declare function MenuBadge({ className, render, ...props }: MenuBadgeProps & RenderProp<'span'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
182
188
|
declare namespace MenuBadge {
|
|
183
189
|
var displayName: string;
|
|
184
190
|
}
|
|
@@ -44,6 +44,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
44
44
|
*/
|
|
45
45
|
import { Menu as BaseMenu } from '@base-ui/react/menu';
|
|
46
46
|
import { tv } from 'tailwind-variants';
|
|
47
|
+
import { mergeProps } from '@base-ui/react/merge-props';
|
|
48
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
47
49
|
const menuVariants = tv({
|
|
48
50
|
slots: {
|
|
49
51
|
positioner: 'z-50 outline-none',
|
|
@@ -113,7 +115,7 @@ function MenuCheckboxItem({ className, children, ...props }) {
|
|
|
113
115
|
MenuCheckboxItem.displayName = 'Menu.CheckboxItem';
|
|
114
116
|
/** Radio items of which one is chosen. Takes `value` and `onValueChange`. */
|
|
115
117
|
function MenuRadioGroup({ className, ...props }) {
|
|
116
|
-
return _jsx(BaseMenu.RadioGroup, { "data-slot": "menu-radio-group", className: menuVariants().group({ className }), ...props });
|
|
118
|
+
return (_jsx(BaseMenu.RadioGroup, { "data-slot": "menu-radio-group", className: menuVariants().group({ className }), ...props }));
|
|
117
119
|
}
|
|
118
120
|
MenuRadioGroup.displayName = 'Menu.RadioGroup';
|
|
119
121
|
/** One choice in a radio group, with a check at its end while chosen. */
|
|
@@ -145,27 +147,43 @@ function MenuGroup({ className, ...props }) {
|
|
|
145
147
|
MenuGroup.displayName = 'Menu.Group';
|
|
146
148
|
/** The heading of a group. Screen readers announce the group by it. */
|
|
147
149
|
function MenuGroupLabel({ className, ...props }) {
|
|
148
|
-
return _jsx(BaseMenu.GroupLabel, { "data-slot": "menu-group-label", className: menuVariants().groupLabel({ className }), ...props });
|
|
150
|
+
return (_jsx(BaseMenu.GroupLabel, { "data-slot": "menu-group-label", className: menuVariants().groupLabel({ className }), ...props }));
|
|
149
151
|
}
|
|
150
152
|
MenuGroupLabel.displayName = 'Menu.GroupLabel';
|
|
151
153
|
/** A rule between groups of items. */
|
|
152
|
-
function MenuSeparator({ className, ...props }) {
|
|
153
|
-
return
|
|
154
|
+
function MenuSeparator({ className, render, ...props }) {
|
|
155
|
+
return useRender({
|
|
156
|
+
defaultTagName: 'div',
|
|
157
|
+
render,
|
|
158
|
+
props: mergeProps({ role: 'separator', 'data-slot': 'menu-separator', className: menuVariants().separator({ className }) }, props),
|
|
159
|
+
});
|
|
154
160
|
}
|
|
155
161
|
MenuSeparator.displayName = 'Menu.Separator';
|
|
156
162
|
/** What an item does, in quieter words after its label. */
|
|
157
|
-
function MenuDescription({ className, ...props }) {
|
|
158
|
-
return
|
|
163
|
+
function MenuDescription({ className, render, ...props }) {
|
|
164
|
+
return useRender({
|
|
165
|
+
defaultTagName: 'span',
|
|
166
|
+
render,
|
|
167
|
+
props: mergeProps({ 'data-slot': 'menu-description', className: menuVariants().description({ className }) }, props),
|
|
168
|
+
});
|
|
159
169
|
}
|
|
160
170
|
MenuDescription.displayName = 'Menu.Description';
|
|
161
171
|
/** The keys for an item, at its end. It only shows them: wire the keys up where the action lives. */
|
|
162
|
-
function MenuShortcut({ className, ...props }) {
|
|
163
|
-
return
|
|
172
|
+
function MenuShortcut({ className, render, ...props }) {
|
|
173
|
+
return useRender({
|
|
174
|
+
defaultTagName: 'kbd',
|
|
175
|
+
render,
|
|
176
|
+
props: mergeProps({ 'data-slot': 'menu-shortcut', className: menuVariants().shortcut({ className }) }, props),
|
|
177
|
+
});
|
|
164
178
|
}
|
|
165
179
|
MenuShortcut.displayName = 'Menu.Shortcut';
|
|
166
180
|
/** A small count or flag at an item's end: how many need attention, or that something is new. */
|
|
167
|
-
function MenuBadge({ className, ...props }) {
|
|
168
|
-
return
|
|
181
|
+
function MenuBadge({ className, render, ...props }) {
|
|
182
|
+
return useRender({
|
|
183
|
+
defaultTagName: 'span',
|
|
184
|
+
render,
|
|
185
|
+
props: mergeProps({ 'data-slot': 'menu-badge', className: menuVariants().badge({ className }) }, props),
|
|
186
|
+
});
|
|
169
187
|
}
|
|
170
188
|
MenuBadge.displayName = 'Menu.Badge';
|
|
171
189
|
export const Menu = Object.assign(MenuRoot, {
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { ElementType as RenderElementType } from 'react';
|
|
4
|
+
/** Draws a part as another element, or composes it with a component: `render={<a href="/" />}`. */
|
|
5
|
+
type RenderProp<Tag extends RenderElementType> = {
|
|
6
|
+
render?: useRender.ComponentProps<Tag>['render'];
|
|
7
|
+
};
|
|
2
8
|
export type MessageFrom = 'user' | 'assistant';
|
|
3
9
|
export interface MessageProps extends ComponentProps<'div'> {
|
|
4
10
|
/** Who wrote it. A person's turn is a bubble on the trailing side; the assistant's is prose. */
|
|
@@ -26,28 +32,28 @@ declare namespace MessageGroup {
|
|
|
26
32
|
export interface MessageAvatarProps extends ComponentProps<'div'> {
|
|
27
33
|
}
|
|
28
34
|
/** Who it is from, beside the turn's first line. Leave it empty to keep the space. */
|
|
29
|
-
declare function MessageAvatar({ className, ...props }: MessageAvatarProps): import("react").
|
|
35
|
+
declare function MessageAvatar({ className, render, ...props }: MessageAvatarProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
30
36
|
declare namespace MessageAvatar {
|
|
31
37
|
var displayName: string;
|
|
32
38
|
}
|
|
33
39
|
export interface MessageContentProps extends ComponentProps<'div'> {
|
|
34
40
|
}
|
|
35
41
|
/** The column with the header, the bubble, the attachments and the actions. */
|
|
36
|
-
declare function MessageContent({ className, ...props }: MessageContentProps): import("react").
|
|
42
|
+
declare function MessageContent({ className, render, ...props }: MessageContentProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
37
43
|
declare namespace MessageContent {
|
|
38
44
|
var displayName: string;
|
|
39
45
|
}
|
|
40
46
|
export interface MessageHeaderProps extends ComponentProps<'div'> {
|
|
41
47
|
}
|
|
42
48
|
/** A line above the turn: a name in `<strong>`, a time, a model. */
|
|
43
|
-
declare function MessageHeader({ className, ...props }: MessageHeaderProps): import("react").
|
|
49
|
+
declare function MessageHeader({ className, render, ...props }: MessageHeaderProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
44
50
|
declare namespace MessageHeader {
|
|
45
51
|
var displayName: string;
|
|
46
52
|
}
|
|
47
53
|
export interface MessageBubbleProps extends ComponentProps<'div'> {
|
|
48
54
|
}
|
|
49
55
|
/** The surface of a person's turn. On the assistant's it draws nothing, and the text is the page's. */
|
|
50
|
-
declare function MessageBubble({ className, ...props }: MessageBubbleProps): import("react").
|
|
56
|
+
declare function MessageBubble({ className, render, ...props }: MessageBubbleProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
51
57
|
declare namespace MessageBubble {
|
|
52
58
|
var displayName: string;
|
|
53
59
|
}
|
|
@@ -57,14 +63,14 @@ export interface MessageBubbleContentProps extends ComponentProps<'div'> {
|
|
|
57
63
|
* The text. Paragraphs, lists, inline code, code blocks and headings inside
|
|
58
64
|
* it are set as prose, so rendered Markdown can go straight in.
|
|
59
65
|
*/
|
|
60
|
-
declare function MessageBubbleContent({ className, children, ...props }: MessageBubbleContentProps): import("react").
|
|
66
|
+
declare function MessageBubbleContent({ className, children, render, ...props }: MessageBubbleContentProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
61
67
|
declare namespace MessageBubbleContent {
|
|
62
68
|
var displayName: string;
|
|
63
69
|
}
|
|
64
70
|
export interface MessageFooterProps extends ComponentProps<'div'> {
|
|
65
71
|
}
|
|
66
72
|
/** A line under the turn: sent, read, a model and how long it took. */
|
|
67
|
-
declare function MessageFooter({ className, ...props }: MessageFooterProps): import("react").
|
|
73
|
+
declare function MessageFooter({ className, render, ...props }: MessageFooterProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
68
74
|
declare namespace MessageFooter {
|
|
69
75
|
var displayName: string;
|
|
70
76
|
}
|
|
@@ -107,7 +113,7 @@ export interface MessageBranchProps extends Omit<ComponentProps<'div'>, 'onChang
|
|
|
107
113
|
onIndexChange: (index: number) => void;
|
|
108
114
|
}
|
|
109
115
|
/** "‹ 2 / 3 ›": steps between the versions of an answer that was retried or edited. */
|
|
110
|
-
declare function MessageBranch({ count, index, onIndexChange, className, ...props }: MessageBranchProps): import("react").
|
|
116
|
+
declare function MessageBranch({ count, index, onIndexChange, className, render, ...props }: MessageBranchProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
111
117
|
declare namespace MessageBranch {
|
|
112
118
|
var displayName: string;
|
|
113
119
|
}
|
|
@@ -124,7 +130,7 @@ declare namespace MessageStatus {
|
|
|
124
130
|
export interface MessageAttachmentsProps extends ComponentProps<'div'> {
|
|
125
131
|
}
|
|
126
132
|
/** The files sent with a turn, above its bubble. */
|
|
127
|
-
declare function MessageAttachments({ className, ...props }: MessageAttachmentsProps): import("react").
|
|
133
|
+
declare function MessageAttachments({ className, render, ...props }: MessageAttachmentsProps & RenderProp<'div'>): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
128
134
|
declare namespace MessageAttachments {
|
|
129
135
|
var displayName: string;
|
|
130
136
|
}
|
|
@@ -139,7 +145,7 @@ export interface MessageAttachmentProps extends Omit<ComponentProps<'div'>, 'chi
|
|
|
139
145
|
icon?: ReactNode;
|
|
140
146
|
}
|
|
141
147
|
/** One sent file: a picture, or a card with a glyph, the name and its size. */
|
|
142
|
-
declare function MessageAttachment({ name, src, meta, icon, className, ...props }: MessageAttachmentProps): import("react").JSX.Element;
|
|
148
|
+
declare function MessageAttachment({ name, src, meta, icon, className, render, ...props }: MessageAttachmentProps & RenderProp<'div'>): import("react").JSX.Element;
|
|
143
149
|
declare namespace MessageAttachment {
|
|
144
150
|
var displayName: string;
|
|
145
151
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
/**
|
|
4
4
|
* Message — one turn of a conversation with an assistant.
|
|
5
5
|
*
|
|
@@ -49,6 +49,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
49
49
|
import { Tooltip } from '@base-ui/react/tooltip';
|
|
50
50
|
import { createContext, useContext, useEffect, useRef, useState, } from 'react';
|
|
51
51
|
import { tv } from 'tailwind-variants';
|
|
52
|
+
import { mergeProps } from '@base-ui/react/merge-props';
|
|
53
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
52
54
|
const messageVariants = tv({
|
|
53
55
|
slots: {
|
|
54
56
|
root: 'group/message flex w-full gap-3',
|
|
@@ -156,45 +158,73 @@ function MessageGroup({ from = 'assistant', className, ...props }) {
|
|
|
156
158
|
}
|
|
157
159
|
MessageGroup.displayName = 'Message.Group';
|
|
158
160
|
/** Who it is from, beside the turn's first line. Leave it empty to keep the space. */
|
|
159
|
-
function MessageAvatar({ className, ...props }) {
|
|
160
|
-
return
|
|
161
|
+
function MessageAvatar({ className, render, ...props }) {
|
|
162
|
+
return useRender({
|
|
163
|
+
defaultTagName: 'div',
|
|
164
|
+
render,
|
|
165
|
+
props: mergeProps({ 'data-slot': 'message-avatar', className: messageVariants().avatar({ className }) }, props),
|
|
166
|
+
});
|
|
161
167
|
}
|
|
162
168
|
MessageAvatar.displayName = 'Message.Avatar';
|
|
163
169
|
/** The column with the header, the bubble, the attachments and the actions. */
|
|
164
|
-
function MessageContent({ className, ...props }) {
|
|
170
|
+
function MessageContent({ className, render, ...props }) {
|
|
165
171
|
const { from } = useContext(MessageContext);
|
|
166
|
-
return
|
|
172
|
+
return useRender({
|
|
173
|
+
defaultTagName: 'div',
|
|
174
|
+
render,
|
|
175
|
+
props: mergeProps({ 'data-slot': 'message-content', className: messageVariants({ from }).content({ className }) }, props),
|
|
176
|
+
});
|
|
167
177
|
}
|
|
168
178
|
MessageContent.displayName = 'Message.Content';
|
|
169
179
|
/** A line above the turn: a name in `<strong>`, a time, a model. */
|
|
170
|
-
function MessageHeader({ className, ...props }) {
|
|
180
|
+
function MessageHeader({ className, render, ...props }) {
|
|
171
181
|
const { from } = useContext(MessageContext);
|
|
172
|
-
return
|
|
182
|
+
return useRender({
|
|
183
|
+
defaultTagName: 'div',
|
|
184
|
+
render,
|
|
185
|
+
props: mergeProps({ 'data-slot': 'message-header', className: messageVariants({ from }).header({ className }) }, props),
|
|
186
|
+
});
|
|
173
187
|
}
|
|
174
188
|
MessageHeader.displayName = 'Message.Header';
|
|
175
189
|
/** The surface of a person's turn. On the assistant's it draws nothing, and the text is the page's. */
|
|
176
|
-
function MessageBubble({ className, ...props }) {
|
|
190
|
+
function MessageBubble({ className, render, ...props }) {
|
|
177
191
|
const { from } = useContext(MessageContext);
|
|
178
|
-
return
|
|
192
|
+
return useRender({
|
|
193
|
+
defaultTagName: 'div',
|
|
194
|
+
render,
|
|
195
|
+
props: mergeProps({ 'data-slot': 'message-bubble', className: messageVariants({ from }).bubble({ className }) }, props),
|
|
196
|
+
});
|
|
179
197
|
}
|
|
180
198
|
MessageBubble.displayName = 'Message.Bubble';
|
|
181
199
|
/**
|
|
182
200
|
* The text. Paragraphs, lists, inline code, code blocks and headings inside
|
|
183
201
|
* it are set as prose, so rendered Markdown can go straight in.
|
|
184
202
|
*/
|
|
185
|
-
function MessageBubbleContent({ className, children, ...props }) {
|
|
203
|
+
function MessageBubbleContent({ className, children, render, ...props }) {
|
|
186
204
|
const { from, streaming } = useContext(MessageContext);
|
|
187
205
|
const slots = messageVariants({ from });
|
|
188
206
|
// The caret follows the last word: after the text itself, or inside the last block.
|
|
189
207
|
const plain = typeof children === 'string' || typeof children === 'number';
|
|
190
208
|
const caret = streaming ? (plain ? slots.caret() : slots.caretLast()) : undefined;
|
|
191
|
-
return (
|
|
209
|
+
return useRender({
|
|
210
|
+
defaultTagName: 'div',
|
|
211
|
+
render,
|
|
212
|
+
props: mergeProps({
|
|
213
|
+
'data-slot': 'message-bubble-content',
|
|
214
|
+
className: slots.bubbleContent({ className: [caret, className] }),
|
|
215
|
+
children: _jsx(_Fragment, { children: children }),
|
|
216
|
+
}, props),
|
|
217
|
+
});
|
|
192
218
|
}
|
|
193
219
|
MessageBubbleContent.displayName = 'Message.BubbleContent';
|
|
194
220
|
/** A line under the turn: sent, read, a model and how long it took. */
|
|
195
|
-
function MessageFooter({ className, ...props }) {
|
|
221
|
+
function MessageFooter({ className, render, ...props }) {
|
|
196
222
|
const { from } = useContext(MessageContext);
|
|
197
|
-
return
|
|
223
|
+
return useRender({
|
|
224
|
+
defaultTagName: 'div',
|
|
225
|
+
render,
|
|
226
|
+
props: mergeProps({ 'data-slot': 'message-footer', className: messageVariants({ from }).footer({ className }) }, props),
|
|
227
|
+
});
|
|
198
228
|
}
|
|
199
229
|
MessageFooter.displayName = 'Message.Footer';
|
|
200
230
|
/** The row of actions under a turn. */
|
|
@@ -227,9 +257,19 @@ function MessageAction({ label, children, copy, pressed, onClick, className, ...
|
|
|
227
257
|
}
|
|
228
258
|
MessageAction.displayName = 'Message.Action';
|
|
229
259
|
/** "‹ 2 / 3 ›": steps between the versions of an answer that was retried or edited. */
|
|
230
|
-
function MessageBranch({ count, index, onIndexChange, className, ...props }) {
|
|
260
|
+
function MessageBranch({ count, index, onIndexChange, className, render, ...props }) {
|
|
231
261
|
const slots = messageVariants();
|
|
232
|
-
return (
|
|
262
|
+
return useRender({
|
|
263
|
+
defaultTagName: 'div',
|
|
264
|
+
render,
|
|
265
|
+
props: mergeProps({
|
|
266
|
+
role: 'group',
|
|
267
|
+
'aria-label': 'Versions',
|
|
268
|
+
'data-slot': 'message-branch',
|
|
269
|
+
className: slots.branch({ className }),
|
|
270
|
+
children: (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", "aria-label": "Previous version", className: slots.branchButton(), disabled: index <= 0, onClick: () => onIndexChange(index - 1), children: _jsx(ChevronGlyph, { flip: true }) }), _jsxs("span", { "aria-live": "polite", className: "min-w-9 text-center", children: [index + 1, " / ", count] }), _jsx("button", { type: "button", "aria-label": "Next version", className: slots.branchButton(), disabled: index >= count - 1, onClick: () => onIndexChange(index + 1), children: _jsx(ChevronGlyph, {}) })] })),
|
|
271
|
+
}, props),
|
|
272
|
+
});
|
|
233
273
|
}
|
|
234
274
|
MessageBranch.displayName = 'Message.Branch';
|
|
235
275
|
/**
|
|
@@ -241,18 +281,30 @@ function MessageStatus({ className, ...props }) {
|
|
|
241
281
|
}
|
|
242
282
|
MessageStatus.displayName = 'Message.Status';
|
|
243
283
|
/** The files sent with a turn, above its bubble. */
|
|
244
|
-
function MessageAttachments({ className, ...props }) {
|
|
284
|
+
function MessageAttachments({ className, render, ...props }) {
|
|
245
285
|
const { from } = useContext(MessageContext);
|
|
246
|
-
return (
|
|
286
|
+
return useRender({
|
|
287
|
+
defaultTagName: 'div',
|
|
288
|
+
render,
|
|
289
|
+
props: mergeProps({ 'data-slot': 'message-attachments', className: messageVariants({ from }).attachments({ className }) }, props),
|
|
290
|
+
});
|
|
247
291
|
}
|
|
248
292
|
MessageAttachments.displayName = 'Message.Attachments';
|
|
249
293
|
/** One sent file: a picture, or a card with a glyph, the name and its size. */
|
|
250
|
-
function MessageAttachment({ name, src, meta, icon, className, ...props }) {
|
|
294
|
+
function MessageAttachment({ name, src, meta, icon, className, render, ...props }) {
|
|
251
295
|
const slots = messageVariants();
|
|
252
296
|
if (src) {
|
|
253
297
|
return (_jsx("div", { "data-slot": "message-attachment", className: slots.attachment({ className }), ...props, children: _jsx("img", { src: src, alt: name, className: slots.attachmentImage() }) }));
|
|
254
298
|
}
|
|
255
|
-
return (
|
|
299
|
+
return useRender({
|
|
300
|
+
defaultTagName: 'div',
|
|
301
|
+
render,
|
|
302
|
+
props: mergeProps({
|
|
303
|
+
'data-slot': 'message-attachment',
|
|
304
|
+
className: slots.attachment({ className: [slots.attachmentFile(), className] }),
|
|
305
|
+
children: (_jsxs(_Fragment, { children: [_jsx("span", { className: slots.attachmentGlyph(), children: icon ?? _jsx(FileGlyph, {}) }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: slots.attachmentName(), children: name }), meta ? _jsx("span", { className: slots.attachmentMeta(), children: meta }) : null] })] })),
|
|
306
|
+
}, props),
|
|
307
|
+
});
|
|
256
308
|
}
|
|
257
309
|
MessageAttachment.displayName = 'Message.Attachment';
|
|
258
310
|
/* -------------------------------------------------------------------------- */
|