@7onic-ui/react 0.3.9 → 0.3.11
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/README.md +2 -2
- package/dist/chart.mjs +3 -9
- package/dist/chart.mjs.map +1 -1
- package/dist/chunk-2WIIXHOV.mjs +148 -0
- package/dist/chunk-2WIIXHOV.mjs.map +1 -0
- package/dist/chunk-53MIUPSY.mjs +13 -0
- package/dist/chunk-53MIUPSY.mjs.map +1 -0
- package/dist/chunk-BN5BEA3V.mjs +195 -0
- package/dist/chunk-BN5BEA3V.mjs.map +1 -0
- package/dist/chunk-C5D3VRNJ.mjs +504 -0
- package/dist/chunk-C5D3VRNJ.mjs.map +1 -0
- package/dist/chunk-COW3B62M.mjs +214 -0
- package/dist/chunk-COW3B62M.mjs.map +1 -0
- package/dist/chunk-CTH6SN5Y.mjs +114 -0
- package/dist/chunk-CTH6SN5Y.mjs.map +1 -0
- package/dist/chunk-D3NTQNDW.mjs +440 -0
- package/dist/chunk-D3NTQNDW.mjs.map +1 -0
- package/dist/chunk-DDRYEJBJ.mjs +164 -0
- package/dist/chunk-DDRYEJBJ.mjs.map +1 -0
- package/dist/chunk-DJAEXCRU.mjs +190 -0
- package/dist/chunk-DJAEXCRU.mjs.map +1 -0
- package/dist/chunk-DYYQOHQR.mjs +214 -0
- package/dist/chunk-DYYQOHQR.mjs.map +1 -0
- package/dist/chunk-EG2GTK65.mjs +443 -0
- package/dist/chunk-EG2GTK65.mjs.map +1 -0
- package/dist/chunk-FHUAH6AJ.mjs +93 -0
- package/dist/chunk-FHUAH6AJ.mjs.map +1 -0
- package/dist/chunk-GD4YE5AE.mjs +209 -0
- package/dist/chunk-GD4YE5AE.mjs.map +1 -0
- package/dist/chunk-HHX4GABH.mjs +129 -0
- package/dist/chunk-HHX4GABH.mjs.map +1 -0
- package/dist/chunk-HS2VRYSX.mjs +148 -0
- package/dist/chunk-HS2VRYSX.mjs.map +1 -0
- package/dist/chunk-IHHI3LIN.mjs +155 -0
- package/dist/chunk-IHHI3LIN.mjs.map +1 -0
- package/dist/chunk-IJ2FZ3L5.mjs +159 -0
- package/dist/chunk-IJ2FZ3L5.mjs.map +1 -0
- package/dist/chunk-IPCIC2BI.mjs +148 -0
- package/dist/chunk-IPCIC2BI.mjs.map +1 -0
- package/dist/chunk-JCJEVXER.mjs +170 -0
- package/dist/chunk-JCJEVXER.mjs.map +1 -0
- package/dist/chunk-KBPYAMGS.mjs +157 -0
- package/dist/chunk-KBPYAMGS.mjs.map +1 -0
- package/dist/chunk-L55ABE4H.mjs +283 -0
- package/dist/chunk-L55ABE4H.mjs.map +1 -0
- package/dist/chunk-LJJ6K4IU.mjs +318 -0
- package/dist/chunk-LJJ6K4IU.mjs.map +1 -0
- package/dist/chunk-ND6TUVP2.mjs +148 -0
- package/dist/chunk-ND6TUVP2.mjs.map +1 -0
- package/dist/chunk-NWFMJWGX.mjs +165 -0
- package/dist/chunk-NWFMJWGX.mjs.map +1 -0
- package/dist/chunk-PTAPPOKU.mjs +117 -0
- package/dist/chunk-PTAPPOKU.mjs.map +1 -0
- package/dist/chunk-PVTBM7V7.mjs +316 -0
- package/dist/chunk-PVTBM7V7.mjs.map +1 -0
- package/dist/chunk-Q5WVLK2L.mjs +77 -0
- package/dist/chunk-Q5WVLK2L.mjs.map +1 -0
- package/dist/chunk-R7FJEO4K.mjs +252 -0
- package/dist/chunk-R7FJEO4K.mjs.map +1 -0
- package/dist/chunk-RKSB2N5L.mjs +206 -0
- package/dist/chunk-RKSB2N5L.mjs.map +1 -0
- package/dist/chunk-S4DGVKBK.mjs +151 -0
- package/dist/chunk-S4DGVKBK.mjs.map +1 -0
- package/dist/chunk-S4T4PU7F.mjs +114 -0
- package/dist/chunk-S4T4PU7F.mjs.map +1 -0
- package/dist/chunk-SDDAGZWA.mjs +224 -0
- package/dist/chunk-SDDAGZWA.mjs.map +1 -0
- package/dist/chunk-SZPZOGPC.mjs +394 -0
- package/dist/chunk-SZPZOGPC.mjs.map +1 -0
- package/dist/chunk-T5A4APEL.mjs +140 -0
- package/dist/chunk-T5A4APEL.mjs.map +1 -0
- package/dist/chunk-V5UFWYFI.mjs +255 -0
- package/dist/chunk-V5UFWYFI.mjs.map +1 -0
- package/dist/chunk-W6YNEU53.mjs +175 -0
- package/dist/chunk-W6YNEU53.mjs.map +1 -0
- package/dist/chunk-XK52LYR4.mjs +182 -0
- package/dist/chunk-XK52LYR4.mjs.map +1 -0
- package/dist/chunk-YIAH6KHV.mjs +164 -0
- package/dist/chunk-YIAH6KHV.mjs.map +1 -0
- package/dist/chunk-YZ7HHFKA.mjs +375 -0
- package/dist/chunk-YZ7HHFKA.mjs.map +1 -0
- package/dist/chunk-ZDRUTJ4T.mjs +119 -0
- package/dist/chunk-ZDRUTJ4T.mjs.map +1 -0
- package/dist/components/accordion.mjs +19 -0
- package/dist/components/accordion.mjs.map +1 -0
- package/dist/components/alert.mjs +15 -0
- package/dist/components/alert.mjs.map +1 -0
- package/dist/components/avatar.mjs +23 -0
- package/dist/components/avatar.mjs.map +1 -0
- package/dist/components/badge.mjs +11 -0
- package/dist/components/badge.mjs.map +1 -0
- package/dist/components/breadcrumb.mjs +23 -0
- package/dist/components/breadcrumb.mjs.map +1 -0
- package/dist/components/button-group.mjs +11 -0
- package/dist/components/button-group.mjs.map +1 -0
- package/dist/components/button.mjs +12 -0
- package/dist/components/button.mjs.map +1 -0
- package/dist/components/card.mjs +25 -0
- package/dist/components/card.mjs.map +1 -0
- package/dist/components/chat-input.mjs +15 -0
- package/dist/components/chat-input.mjs.map +1 -0
- package/dist/components/chat-message.mjs +17 -0
- package/dist/components/chat-message.mjs.map +1 -0
- package/dist/components/checkbox.mjs +12 -0
- package/dist/components/checkbox.mjs.map +1 -0
- package/dist/components/divider.mjs +11 -0
- package/dist/components/divider.mjs.map +1 -0
- package/dist/components/drawer.mjs +33 -0
- package/dist/components/drawer.mjs.map +1 -0
- package/dist/components/dropdown.mjs +35 -0
- package/dist/components/dropdown.mjs.map +1 -0
- package/dist/components/field.mjs +19 -0
- package/dist/components/field.mjs.map +1 -0
- package/dist/components/icon-button.mjs +12 -0
- package/dist/components/icon-button.mjs.map +1 -0
- package/dist/components/input.mjs +12 -0
- package/dist/components/input.mjs.map +1 -0
- package/dist/components/metric-card.mjs +23 -0
- package/dist/components/metric-card.mjs.map +1 -0
- package/dist/components/modal.mjs +57 -0
- package/dist/components/modal.mjs.map +1 -0
- package/dist/components/navigation-menu.mjs +27 -0
- package/dist/components/navigation-menu.mjs.map +1 -0
- package/dist/components/pagination.mjs +33 -0
- package/dist/components/pagination.mjs.map +1 -0
- package/dist/components/popover.mjs +23 -0
- package/dist/components/popover.mjs.map +1 -0
- package/dist/components/progress.mjs +11 -0
- package/dist/components/progress.mjs.map +1 -0
- package/dist/components/quick-reply.mjs +15 -0
- package/dist/components/quick-reply.mjs.map +1 -0
- package/dist/components/radio-group.mjs +16 -0
- package/dist/components/radio-group.mjs.map +1 -0
- package/dist/components/segmented.mjs +15 -0
- package/dist/components/segmented.mjs.map +1 -0
- package/dist/components/select.mjs +24 -0
- package/dist/components/select.mjs.map +1 -0
- package/dist/components/skeleton.mjs +11 -0
- package/dist/components/skeleton.mjs.map +1 -0
- package/dist/components/slider.mjs +12 -0
- package/dist/components/slider.mjs.map +1 -0
- package/dist/components/spinner.mjs +11 -0
- package/dist/components/spinner.mjs.map +1 -0
- package/dist/components/switch.mjs +12 -0
- package/dist/components/switch.mjs.map +1 -0
- package/dist/components/table.mjs +23 -0
- package/dist/components/table.mjs.map +1 -0
- package/dist/components/tabs.mjs +19 -0
- package/dist/components/tabs.mjs.map +1 -0
- package/dist/components/textarea.mjs +12 -0
- package/dist/components/textarea.mjs.map +1 -0
- package/dist/components/toast.mjs +13 -0
- package/dist/components/toast.mjs.map +1 -0
- package/dist/components/toggle-group.mjs +15 -0
- package/dist/components/toggle-group.mjs.map +1 -0
- package/dist/components/toggle.mjs +11 -0
- package/dist/components/toggle.mjs.map +1 -0
- package/dist/components/tooltip.mjs +21 -0
- package/dist/components/tooltip.mjs.map +1 -0
- package/dist/components/typing-indicator.mjs +11 -0
- package/dist/components/typing-indicator.mjs.map +1 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.js +95 -21
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +296 -7536
- package/dist/index.mjs.map +1 -1
- package/llms.txt +50 -32
- package/package.json +14 -14
- package/dist/chart.d.mts +0 -147
- package/dist/index.d.mts +0 -1535
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
cn
|
|
4
|
+
} from "./chunk-53MIUPSY.mjs";
|
|
5
|
+
|
|
6
|
+
// src/components/ui/button-group.tsx
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
var ButtonGroupContext = React.createContext(null);
|
|
9
|
+
function useButtonGroup() {
|
|
10
|
+
return React.useContext(ButtonGroupContext);
|
|
11
|
+
}
|
|
12
|
+
var ButtonGroup = React.forwardRef(
|
|
13
|
+
({
|
|
14
|
+
className,
|
|
15
|
+
orientation = "horizontal",
|
|
16
|
+
attached = true,
|
|
17
|
+
variant,
|
|
18
|
+
size,
|
|
19
|
+
radius,
|
|
20
|
+
fontWeight,
|
|
21
|
+
disabled,
|
|
22
|
+
children,
|
|
23
|
+
...props
|
|
24
|
+
}, ref) => {
|
|
25
|
+
const contextValue = React.useMemo(() => ({
|
|
26
|
+
variant,
|
|
27
|
+
size,
|
|
28
|
+
radius,
|
|
29
|
+
fontWeight,
|
|
30
|
+
disabled
|
|
31
|
+
}), [variant, size, radius, fontWeight, disabled]);
|
|
32
|
+
return /* @__PURE__ */ React.createElement(ButtonGroupContext.Provider, { value: contextValue }, /* @__PURE__ */ React.createElement(
|
|
33
|
+
"div",
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
role: "group",
|
|
37
|
+
className: cn(
|
|
38
|
+
"inline-flex",
|
|
39
|
+
orientation === "vertical" ? "flex-col" : "flex-row",
|
|
40
|
+
// Attached mode: use negative margin to overlap borders, raise z-index on hover/focus
|
|
41
|
+
attached && orientation === "horizontal" && [
|
|
42
|
+
"[&>*:not(:first-child)]:rounded-l-none",
|
|
43
|
+
"[&>*:not(:last-child)]:rounded-r-none",
|
|
44
|
+
"[&>*:not(:first-child)]:-ml-px",
|
|
45
|
+
"[&>*]:relative",
|
|
46
|
+
"[&>*:hover]:z-10",
|
|
47
|
+
"[&>*:focus-visible]:z-10",
|
|
48
|
+
"[&>*:active]:scale-none",
|
|
49
|
+
"[&>*:hover]:border-border"
|
|
50
|
+
],
|
|
51
|
+
attached && orientation === "vertical" && [
|
|
52
|
+
"[&>*:not(:first-child)]:rounded-t-none",
|
|
53
|
+
"[&>*:not(:last-child)]:rounded-b-none",
|
|
54
|
+
"[&>*:not(:first-child)]:-mt-px",
|
|
55
|
+
"[&>*]:relative",
|
|
56
|
+
"[&>*]:w-full",
|
|
57
|
+
"[&>*:hover]:z-10",
|
|
58
|
+
"[&>*:focus-visible]:z-10",
|
|
59
|
+
"[&>*:active]:scale-none",
|
|
60
|
+
"[&>*:hover]:border-border"
|
|
61
|
+
],
|
|
62
|
+
!attached && "gap-2",
|
|
63
|
+
className
|
|
64
|
+
),
|
|
65
|
+
...props
|
|
66
|
+
},
|
|
67
|
+
children
|
|
68
|
+
));
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
ButtonGroup.displayName = "ButtonGroup";
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
useButtonGroup,
|
|
75
|
+
ButtonGroup
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=chunk-Q5WVLK2L.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/button-group.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\n\n// ButtonGroup Context\ntype ButtonGroupContextValue = {\n variant?: 'outline' | 'ghost'\n size?: 'xs' | 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n fontWeight?: 'normal' | 'semibold'\n disabled?: boolean\n}\n\nconst ButtonGroupContext = React.createContext<ButtonGroupContextValue | null>(null)\n\nexport function useButtonGroup() {\n return React.useContext(ButtonGroupContext)\n}\n\nexport interface ButtonGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n orientation?: 'horizontal' | 'vertical'\n attached?: boolean\n variant?: 'outline' | 'ghost'\n size?: 'xs' | 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n fontWeight?: 'normal' | 'semibold'\n disabled?: boolean\n}\n\nconst ButtonGroup = React.forwardRef<HTMLDivElement, ButtonGroupProps>(\n ({\n className,\n orientation = 'horizontal',\n attached = true,\n variant,\n size,\n radius,\n fontWeight,\n disabled,\n children,\n ...props\n }, ref) => {\n const contextValue = React.useMemo(() => ({\n variant,\n size,\n radius,\n fontWeight,\n disabled,\n }), [variant, size, radius, fontWeight, disabled])\n\n return (\n <ButtonGroupContext.Provider value={contextValue}>\n <div\n ref={ref}\n role=\"group\"\n className={cn(\n 'inline-flex',\n orientation === 'vertical' ? 'flex-col' : 'flex-row',\n // Attached mode: use negative margin to overlap borders, raise z-index on hover/focus\n attached && orientation === 'horizontal' && [\n '[&>*:not(:first-child)]:rounded-l-none',\n '[&>*:not(:last-child)]:rounded-r-none',\n '[&>*:not(:first-child)]:-ml-px',\n '[&>*]:relative',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n '[&>*:hover]:border-border',\n ],\n attached && orientation === 'vertical' && [\n '[&>*:not(:first-child)]:rounded-t-none',\n '[&>*:not(:last-child)]:rounded-b-none',\n '[&>*:not(:first-child)]:-mt-px',\n '[&>*]:relative',\n '[&>*]:w-full',\n '[&>*:hover]:z-10',\n '[&>*:focus-visible]:z-10',\n '[&>*:active]:scale-none',\n '[&>*:hover]:border-border',\n ],\n !attached && 'gap-2',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </ButtonGroupContext.Provider>\n )\n }\n)\nButtonGroup.displayName = 'ButtonGroup'\n\nexport { ButtonGroup }\n"],"mappings":";;;;;;AAEA,YAAY,WAAW;AAYvB,IAAM,qBAA2B,oBAA8C,IAAI;AAE5E,SAAS,iBAAiB;AAC/B,SAAa,iBAAW,kBAAkB;AAC5C;AAYA,IAAM,cAAoB;AAAA,EACxB,CAAC;AAAA,IACC;AAAA,IACA,cAAc;AAAA,IACd,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GAAG,QAAQ;AACT,UAAM,eAAqB,cAAQ,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,CAAC,SAAS,MAAM,QAAQ,YAAY,QAAQ,CAAC;AAEjD,WACE,oCAAC,mBAAmB,UAAnB,EAA4B,OAAO,gBAClC;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,aAAa,aAAa;AAAA;AAAA,UAE1C,YAAY,gBAAgB,gBAAgB;AAAA,YAC1C;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,YAAY,gBAAgB,cAAc;AAAA,YACxC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,CAAC,YAAY;AAAA,UACb;AAAA,QACF;AAAA,QACC,GAAG;AAAA;AAAA,MAEH;AAAA,IACH,CACF;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;","names":[]}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
TypingIndicator
|
|
4
|
+
} from "./chunk-S4T4PU7F.mjs";
|
|
5
|
+
import {
|
|
6
|
+
Avatar,
|
|
7
|
+
AvatarFallback,
|
|
8
|
+
AvatarImage
|
|
9
|
+
} from "./chunk-GD4YE5AE.mjs";
|
|
10
|
+
import {
|
|
11
|
+
cn
|
|
12
|
+
} from "./chunk-53MIUPSY.mjs";
|
|
13
|
+
|
|
14
|
+
// src/components/ui/chat-message.tsx
|
|
15
|
+
import * as React from "react";
|
|
16
|
+
var ChatMessageContext = React.createContext({
|
|
17
|
+
role: "assistant",
|
|
18
|
+
variant: "bubble",
|
|
19
|
+
color: "default",
|
|
20
|
+
size: "default",
|
|
21
|
+
radius: "2xl",
|
|
22
|
+
tail: true,
|
|
23
|
+
typing: false,
|
|
24
|
+
actions: void 0
|
|
25
|
+
});
|
|
26
|
+
var bubblePaddingMap = {
|
|
27
|
+
sm: "px-3 py-1.5",
|
|
28
|
+
default: "px-3.5 py-2",
|
|
29
|
+
lg: "px-4 py-2.5"
|
|
30
|
+
};
|
|
31
|
+
var bubbleTextMap = {
|
|
32
|
+
sm: "text-sm",
|
|
33
|
+
default: "text-md",
|
|
34
|
+
lg: "text-base"
|
|
35
|
+
};
|
|
36
|
+
var footerTextMap = {
|
|
37
|
+
sm: "text-2xs",
|
|
38
|
+
default: "text-2xs",
|
|
39
|
+
lg: "text-xs"
|
|
40
|
+
};
|
|
41
|
+
var rowGapMap = {
|
|
42
|
+
sm: "gap-2",
|
|
43
|
+
default: "gap-2.5",
|
|
44
|
+
lg: "gap-3"
|
|
45
|
+
};
|
|
46
|
+
var avatarGapMap = {
|
|
47
|
+
sm: "gap-1.5",
|
|
48
|
+
md: "gap-2.5",
|
|
49
|
+
lg: "gap-3"
|
|
50
|
+
};
|
|
51
|
+
var chatAvatarSizeMap = {
|
|
52
|
+
sm: "w-6 h-6",
|
|
53
|
+
// 24px
|
|
54
|
+
md: "w-7 h-7",
|
|
55
|
+
// 28px
|
|
56
|
+
lg: "w-8 h-8"
|
|
57
|
+
// 32px
|
|
58
|
+
};
|
|
59
|
+
var chatAvatarFontMap = {
|
|
60
|
+
sm: "text-2xs",
|
|
61
|
+
md: "text-2xs",
|
|
62
|
+
lg: "text-xs"
|
|
63
|
+
};
|
|
64
|
+
var bubbleRadiusTailMap = {
|
|
65
|
+
md: { assistant: "rounded-tl-md rounded-tr-md rounded-br-md rounded-bl-none", user: "rounded-tl-md rounded-tr-md rounded-br-none rounded-bl-md" },
|
|
66
|
+
lg: { assistant: "rounded-tl-lg rounded-tr-lg rounded-br-lg rounded-bl-none", user: "rounded-tl-lg rounded-tr-lg rounded-br-none rounded-bl-lg" },
|
|
67
|
+
xl: { assistant: "rounded-tl-xl rounded-tr-xl rounded-br-xl rounded-bl-none", user: "rounded-tl-xl rounded-tr-xl rounded-br-none rounded-bl-xl" },
|
|
68
|
+
"2xl": { assistant: "rounded-tl-2xl rounded-tr-2xl rounded-br-2xl rounded-bl-none", user: "rounded-tl-2xl rounded-tr-2xl rounded-br-none rounded-bl-2xl" }
|
|
69
|
+
};
|
|
70
|
+
var bubbleRadiusSymMap = {
|
|
71
|
+
md: "rounded-md",
|
|
72
|
+
lg: "rounded-lg",
|
|
73
|
+
xl: "rounded-xl",
|
|
74
|
+
"2xl": "rounded-2xl"
|
|
75
|
+
};
|
|
76
|
+
function getBubbleColors(color, variant) {
|
|
77
|
+
if (variant === "flat") {
|
|
78
|
+
return color === "muted" ? "bg-background-muted text-foreground" : "text-foreground";
|
|
79
|
+
}
|
|
80
|
+
switch (color) {
|
|
81
|
+
case "default":
|
|
82
|
+
return "bg-background-paper border border-border text-foreground";
|
|
83
|
+
case "muted":
|
|
84
|
+
return "bg-background-muted text-foreground";
|
|
85
|
+
case "primary":
|
|
86
|
+
return "bg-primary text-primary-foreground";
|
|
87
|
+
case "dark":
|
|
88
|
+
return "bg-foreground text-background";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
var builtInStatusLabels = {
|
|
92
|
+
sending: { label: "Sending...", className: "text-text-subtle" },
|
|
93
|
+
sent: { label: "Sent", className: "text-text-subtle" },
|
|
94
|
+
read: { label: "Read", className: "text-text-subtle" },
|
|
95
|
+
error: { label: "Failed", className: "text-error" }
|
|
96
|
+
};
|
|
97
|
+
var typingSizeMap = {
|
|
98
|
+
sm: "sm",
|
|
99
|
+
default: "sm",
|
|
100
|
+
lg: "default"
|
|
101
|
+
};
|
|
102
|
+
var typingMinWidthMap = {
|
|
103
|
+
sm: "min-w-12",
|
|
104
|
+
default: "min-w-12",
|
|
105
|
+
lg: "min-w-16"
|
|
106
|
+
};
|
|
107
|
+
var ChatMessage = React.forwardRef(
|
|
108
|
+
({
|
|
109
|
+
className,
|
|
110
|
+
role = "assistant",
|
|
111
|
+
variant = "bubble",
|
|
112
|
+
color = "default",
|
|
113
|
+
size = "default",
|
|
114
|
+
radius = "2xl",
|
|
115
|
+
tail = true,
|
|
116
|
+
typing = false,
|
|
117
|
+
avatarSize,
|
|
118
|
+
actions,
|
|
119
|
+
children,
|
|
120
|
+
...props
|
|
121
|
+
}, ref) => {
|
|
122
|
+
const ctx = React.useMemo(
|
|
123
|
+
() => ({ role, variant, color, size, radius, tail, typing, actions }),
|
|
124
|
+
[role, variant, color, size, radius, tail, typing, actions]
|
|
125
|
+
);
|
|
126
|
+
const gapClass = avatarSize ? avatarGapMap[avatarSize] : rowGapMap[size];
|
|
127
|
+
return /* @__PURE__ */ React.createElement(ChatMessageContext.Provider, { value: ctx }, /* @__PURE__ */ React.createElement(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
ref,
|
|
131
|
+
className: cn(
|
|
132
|
+
"group/message flex items-end",
|
|
133
|
+
gapClass,
|
|
134
|
+
role === "user" && variant !== "flat" ? "flex-row-reverse" : "flex-row",
|
|
135
|
+
className
|
|
136
|
+
),
|
|
137
|
+
...props
|
|
138
|
+
},
|
|
139
|
+
children
|
|
140
|
+
));
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
ChatMessage.displayName = "ChatMessage";
|
|
144
|
+
function DefaultAiIcon() {
|
|
145
|
+
return /* @__PURE__ */ React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor", className: "w-3/5 h-3/5", "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("path", { d: "M12 3l1.8 5.4 5.4 1.8-5.4 1.8L12 17.4l-1.8-5.4L4.8 10.2l5.4-1.8z" }), /* @__PURE__ */ React.createElement("path", { d: "M19.5 3.5l.8 2.4 2.4.8-2.4.8L19.5 10l-.8-2.5-2.4-.8 2.4-.8z", opacity: ".6" }), /* @__PURE__ */ React.createElement("path", { d: "M4.5 14.5l.7 2 2 .7-2 .7L4.5 20l-.7-2-2-.7 2-.7z", opacity: ".4" }));
|
|
146
|
+
}
|
|
147
|
+
var ChatMessageAvatar = React.forwardRef(
|
|
148
|
+
({ className, size: avatarSize = "md", src, alt = "Avatar", initials, icon }, ref) => /* @__PURE__ */ React.createElement(
|
|
149
|
+
Avatar,
|
|
150
|
+
{
|
|
151
|
+
ref,
|
|
152
|
+
"aria-hidden": "true",
|
|
153
|
+
className: cn(chatAvatarSizeMap[avatarSize], "shrink-0", className)
|
|
154
|
+
},
|
|
155
|
+
src && /* @__PURE__ */ React.createElement(AvatarImage, { src, alt }),
|
|
156
|
+
/* @__PURE__ */ React.createElement(AvatarFallback, { className: cn("font-semibold", chatAvatarFontMap[avatarSize]) }, icon ?? (initials || /* @__PURE__ */ React.createElement(DefaultAiIcon, null)))
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
ChatMessageAvatar.displayName = "ChatMessageAvatar";
|
|
160
|
+
var ChatMessageContent = React.forwardRef(
|
|
161
|
+
({ className, children, ...props }, ref) => {
|
|
162
|
+
const { role, variant, color, size, radius, tail, typing, actions } = React.useContext(ChatMessageContext);
|
|
163
|
+
const isTyping = !!typing;
|
|
164
|
+
const typingProps = typeof typing === "object" ? typing : {};
|
|
165
|
+
const isDarkBg = color === "primary" || color === "dark";
|
|
166
|
+
const invertDots = variant === "bubble" && isDarkBg;
|
|
167
|
+
const effectiveTail = variant === "flat" ? false : tail;
|
|
168
|
+
const radiusClasses = effectiveTail ? bubbleRadiusTailMap[radius][role] : bubbleRadiusSymMap[radius];
|
|
169
|
+
const bubble = /* @__PURE__ */ React.createElement(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
ref,
|
|
173
|
+
className: cn(
|
|
174
|
+
bubbleTextMap[size],
|
|
175
|
+
variant === "bubble" && "max-w-[75%]",
|
|
176
|
+
isTyping && [typingMinWidthMap[size], "text-center"],
|
|
177
|
+
getBubbleColors(color, variant),
|
|
178
|
+
(variant === "bubble" || variant === "flat") && bubblePaddingMap[size],
|
|
179
|
+
(variant === "bubble" || variant === "flat" && color === "muted") && radiusClasses,
|
|
180
|
+
className
|
|
181
|
+
),
|
|
182
|
+
...props
|
|
183
|
+
},
|
|
184
|
+
isTyping ? /* @__PURE__ */ React.createElement(
|
|
185
|
+
TypingIndicator,
|
|
186
|
+
{
|
|
187
|
+
size: typingSizeMap[size],
|
|
188
|
+
color: "muted",
|
|
189
|
+
...typingProps,
|
|
190
|
+
className: cn("align-middle", invertDots && "[&>div>div]:bg-current")
|
|
191
|
+
}
|
|
192
|
+
) : children
|
|
193
|
+
);
|
|
194
|
+
if (!actions) return bubble;
|
|
195
|
+
return /* @__PURE__ */ React.createElement("div", { className: cn("flex items-end gap-1.5", role === "user" && variant !== "flat" ? "flex-row-reverse" : "flex-row") }, bubble, /* @__PURE__ */ React.createElement("div", { className: cn(
|
|
196
|
+
"shrink-0 flex items-center gap-1 pb-0.5",
|
|
197
|
+
"opacity-0 group-hover/message:opacity-100",
|
|
198
|
+
"transition-opacity duration-normal"
|
|
199
|
+
) }, actions));
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
ChatMessageContent.displayName = "ChatMessageContent";
|
|
203
|
+
var ChatMessageFooter = React.forwardRef(
|
|
204
|
+
({
|
|
205
|
+
className,
|
|
206
|
+
timestamp,
|
|
207
|
+
status,
|
|
208
|
+
role: roleProp,
|
|
209
|
+
size: sizeProp,
|
|
210
|
+
children,
|
|
211
|
+
...props
|
|
212
|
+
}, ref) => {
|
|
213
|
+
const ctx = React.useContext(ChatMessageContext);
|
|
214
|
+
const role = roleProp ?? ctx.role;
|
|
215
|
+
const size = sizeProp ?? ctx.size;
|
|
216
|
+
const variant = ctx.variant;
|
|
217
|
+
const statusContent = React.useMemo(() => {
|
|
218
|
+
if (status == null) return null;
|
|
219
|
+
if (typeof status === "string" && status in builtInStatusLabels) {
|
|
220
|
+
const { label, className: cls } = builtInStatusLabels[status];
|
|
221
|
+
return /* @__PURE__ */ React.createElement("span", { className: cls }, label);
|
|
222
|
+
}
|
|
223
|
+
return status;
|
|
224
|
+
}, [status]);
|
|
225
|
+
return /* @__PURE__ */ React.createElement(
|
|
226
|
+
"div",
|
|
227
|
+
{
|
|
228
|
+
ref,
|
|
229
|
+
className: cn(
|
|
230
|
+
"flex items-center gap-1 select-none",
|
|
231
|
+
footerTextMap[size],
|
|
232
|
+
"text-text-subtle",
|
|
233
|
+
role === "user" && variant !== "flat" ? "justify-end" : "justify-start",
|
|
234
|
+
className
|
|
235
|
+
),
|
|
236
|
+
...props
|
|
237
|
+
},
|
|
238
|
+
children,
|
|
239
|
+
statusContent,
|
|
240
|
+
timestamp && /* @__PURE__ */ React.createElement("span", null, timestamp)
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
ChatMessageFooter.displayName = "ChatMessageFooter";
|
|
245
|
+
|
|
246
|
+
export {
|
|
247
|
+
ChatMessage,
|
|
248
|
+
ChatMessageAvatar,
|
|
249
|
+
ChatMessageContent,
|
|
250
|
+
ChatMessageFooter
|
|
251
|
+
};
|
|
252
|
+
//# sourceMappingURL=chunk-R7FJEO4K.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/chat-message.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '@/lib/utils'\nimport { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'\nimport { TypingIndicator, type TypingIndicatorProps } from '@/components/ui/typing-indicator'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type ChatMessageRole = 'user' | 'assistant'\nexport type ChatMessageVariant = 'bubble' | 'flat'\nexport type ChatMessageColor = 'default' | 'muted' | 'primary' | 'dark'\nexport type ChatMessageSize = 'sm' | 'default' | 'lg'\nexport type ChatMessageRadius = 'md' | 'lg' | 'xl' | '2xl'\nexport type ChatMessageAvatarSize = 'sm' | 'md' | 'lg'\n\n/** Built-in status presets (pass as string to Footer.status for auto-rendering) */\nexport type ChatMessageStatus = 'sending' | 'sent' | 'read' | 'error'\n\n// ============================================================================\n// Context — propagates root props to sub-components\n// ============================================================================\n\ninterface ChatMessageContextValue {\n role: ChatMessageRole\n variant: ChatMessageVariant\n color: ChatMessageColor\n size: ChatMessageSize\n radius: ChatMessageRadius\n tail: boolean\n typing: boolean | Omit<TypingIndicatorProps, 'className'>\n actions?: React.ReactNode\n}\n\nconst ChatMessageContext = React.createContext<ChatMessageContextValue>({\n role: 'assistant',\n variant: 'bubble',\n color: 'default',\n size: 'default',\n radius: '2xl',\n tail: true,\n typing: false,\n actions: undefined,\n})\n\n// ============================================================================\n// Size maps\n// ============================================================================\n\n/** Bubble padding per size */\nconst bubblePaddingMap: Record<ChatMessageSize, string> = {\n sm: 'px-3 py-1.5',\n default: 'px-3.5 py-2',\n lg: 'px-4 py-2.5',\n}\n\n/** Bubble text class per size */\nconst bubbleTextMap: Record<ChatMessageSize, string> = {\n sm: 'text-sm',\n default: 'text-md',\n lg: 'text-base',\n}\n\n/** Footer text size per size */\nconst footerTextMap: Record<ChatMessageSize, string> = {\n sm: 'text-2xs',\n default: 'text-2xs',\n lg: 'text-xs',\n}\n\n/** Gap between avatar and content per message size */\nconst rowGapMap: Record<ChatMessageSize, string> = {\n sm: 'gap-2',\n default: 'gap-2.5',\n lg: 'gap-3',\n}\n\n/** Gap override when avatarSize is explicitly set */\nconst avatarGapMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'gap-1.5',\n md: 'gap-2.5',\n lg: 'gap-3',\n}\n\n// ============================================================================\n// Chat avatar sizes (independent from message size)\n// ============================================================================\n\nconst chatAvatarSizeMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'w-6 h-6', // 24px\n md: 'w-7 h-7', // 28px\n lg: 'w-8 h-8', // 32px\n}\n\nconst chatAvatarFontMap: Record<ChatMessageAvatarSize, string> = {\n sm: 'text-2xs',\n md: 'text-2xs',\n lg: 'text-xs',\n}\n\n// ============================================================================\n// Bubble radius — static maps for Tailwind JIT scanner compatibility\n// ============================================================================\n\n/**\n * Asymmetric with tail: tail corner = rounded-none (0px).\n * assistant → tail at bottom-left | user → tail at bottom-right\n */\nconst bubbleRadiusTailMap: Record<ChatMessageRadius, Record<ChatMessageRole, string>> = {\n md: { assistant: 'rounded-tl-md rounded-tr-md rounded-br-md rounded-bl-none', user: 'rounded-tl-md rounded-tr-md rounded-br-none rounded-bl-md' },\n lg: { assistant: 'rounded-tl-lg rounded-tr-lg rounded-br-lg rounded-bl-none', user: 'rounded-tl-lg rounded-tr-lg rounded-br-none rounded-bl-lg' },\n xl: { assistant: 'rounded-tl-xl rounded-tr-xl rounded-br-xl rounded-bl-none', user: 'rounded-tl-xl rounded-tr-xl rounded-br-none rounded-bl-xl' },\n '2xl': { assistant: 'rounded-tl-2xl rounded-tr-2xl rounded-br-2xl rounded-bl-none', user: 'rounded-tl-2xl rounded-tr-2xl rounded-br-none rounded-bl-2xl' },\n}\n\n/** Symmetric: all corners same radius */\nconst bubbleRadiusSymMap: Record<ChatMessageRadius, string> = {\n md: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n}\n\n// ============================================================================\n// Bubble color helper — applies to both roles uniformly\n// ============================================================================\n\nfunction getBubbleColors(color: ChatMessageColor, variant: ChatMessageVariant): string {\n if (variant === 'flat') {\n return color === 'muted' ? 'bg-background-muted text-foreground' : 'text-foreground'\n }\n switch (color) {\n case 'default': return 'bg-background-paper border border-border text-foreground'\n case 'muted': return 'bg-background-muted text-foreground'\n case 'primary': return 'bg-primary text-primary-foreground'\n case 'dark': return 'bg-foreground text-background'\n }\n}\n\n// ============================================================================\n// Built-in status labels\n// ============================================================================\n\nconst builtInStatusLabels: Record<string, { label: string; className: string }> = {\n sending: { label: 'Sending...', className: 'text-text-subtle' },\n sent: { label: 'Sent', className: 'text-text-subtle' },\n read: { label: 'Read', className: 'text-text-subtle' },\n error: { label: 'Failed', className: 'text-error' },\n}\n\n// ============================================================================\n// TypingIndicator size mapping (chat sizes → indicator sizes)\n// ============================================================================\n\nconst typingSizeMap: Record<ChatMessageSize, 'sm' | 'default' | 'lg'> = {\n sm: 'sm',\n default: 'sm',\n lg: 'default',\n}\n\n/** Minimum bubble width when typing — accounts for dot size + padding per chat size */\nconst typingMinWidthMap: Record<ChatMessageSize, string> = {\n sm: 'min-w-12',\n default: 'min-w-12',\n lg: 'min-w-16',\n}\n\n// ============================================================================\n// Props interfaces\n// ============================================================================\n\nexport interface ChatMessageRootProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Sender role — controls alignment (left=assistant, right=user) */\n role?: ChatMessageRole\n /** Bubble visual style */\n variant?: ChatMessageVariant\n /** Bubble background color */\n color?: ChatMessageColor\n /** Size scale — affects text and padding */\n size?: ChatMessageSize\n /** Bubble corner radius */\n radius?: ChatMessageRadius\n /** Asymmetric tail corner (radius=0 on the avatar side) */\n tail?: boolean\n /** Show typing indicator inside Content. Pass true for defaults, or TypingIndicatorProps for custom. */\n typing?: boolean | Omit<TypingIndicatorProps, 'className'>\n /** Avatar size — overrides default gap between avatar and bubble */\n avatarSize?: ChatMessageAvatarSize\n /** Action buttons revealed on hover */\n actions?: React.ReactNode\n}\n\nexport interface ChatMessageAvatarProps {\n /** Avatar size: sm(24px), md(28px), lg(32px) */\n size?: ChatMessageAvatarSize\n /** Image URL */\n src?: string\n /** Alt text for avatar image */\n alt?: string\n /** Initials to display when no image (1–2 characters) */\n initials?: string\n /** Custom icon or ReactNode to render inside the avatar */\n icon?: React.ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ChatMessageContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface ChatMessageFooterProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Pre-formatted timestamp string (e.g. \"12:34 PM\") */\n timestamp?: string\n /** Status: built-in preset ('sending' | 'sent' | 'read' | 'error') or custom ReactNode */\n status?: React.ReactNode\n /** Size override (defaults to context value from ChatMessage root) */\n size?: ChatMessageSize\n}\n\n// ============================================================================\n// ChatMessage Root\n// ============================================================================\n\nconst ChatMessage = React.forwardRef<HTMLDivElement, ChatMessageRootProps>(\n (\n {\n className,\n role = 'assistant',\n variant = 'bubble',\n color = 'default',\n size = 'default',\n radius = '2xl',\n tail = true,\n typing = false,\n avatarSize,\n actions,\n children,\n ...props\n },\n ref\n ) => {\n const ctx = React.useMemo<ChatMessageContextValue>(\n () => ({ role, variant, color, size, radius, tail, typing, actions }),\n [role, variant, color, size, radius, tail, typing, actions]\n )\n\n const gapClass = avatarSize ? avatarGapMap[avatarSize] : rowGapMap[size]\n\n return (\n <ChatMessageContext.Provider value={ctx}>\n <div\n ref={ref}\n className={cn(\n 'group/message flex items-end',\n gapClass,\n role === 'user' && variant !== 'flat' ? 'flex-row-reverse' : 'flex-row',\n className\n )}\n {...props}\n >\n {children}\n </div>\n </ChatMessageContext.Provider>\n )\n }\n)\nChatMessage.displayName = 'ChatMessage'\n\n// ============================================================================\n// Default AI sparkle icon\n// ============================================================================\n\nfunction DefaultAiIcon() {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className=\"w-3/5 h-3/5\" aria-hidden=\"true\">\n <path d=\"M12 3l1.8 5.4 5.4 1.8-5.4 1.8L12 17.4l-1.8-5.4L4.8 10.2l5.4-1.8z\" />\n <path d=\"M19.5 3.5l.8 2.4 2.4.8-2.4.8L19.5 10l-.8-2.5-2.4-.8 2.4-.8z\" opacity=\".6\" />\n <path d=\"M4.5 14.5l.7 2 2 .7-2 .7L4.5 20l-.7-2-2-.7 2-.7z\" opacity=\".4\" />\n </svg>\n )\n}\n\n// ============================================================================\n// ChatMessageAvatar — wraps Avatar component with chat-specific sizes\n// ============================================================================\n\nconst ChatMessageAvatar = React.forwardRef<HTMLSpanElement, ChatMessageAvatarProps>(\n ({ className, size: avatarSize = 'md', src, alt = 'Avatar', initials, icon }, ref) => (\n <Avatar\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref={ref as any}\n aria-hidden=\"true\"\n className={cn(chatAvatarSizeMap[avatarSize], 'shrink-0', className)}\n >\n {src && <AvatarImage src={src} alt={alt} />}\n <AvatarFallback className={cn('font-semibold', chatAvatarFontMap[avatarSize])}>\n {icon ?? (initials || <DefaultAiIcon />)}\n </AvatarFallback>\n </Avatar>\n )\n)\nChatMessageAvatar.displayName = 'ChatMessageAvatar'\n\n// ============================================================================\n// ChatMessageContent\n// ============================================================================\n\nconst ChatMessageContent = React.forwardRef<HTMLDivElement, ChatMessageContentProps>(\n ({ className, children, ...props }, ref) => {\n const { role, variant, color, size, radius, tail, typing, actions } = React.useContext(ChatMessageContext)\n const isTyping = !!typing\n const typingProps = typeof typing === 'object' ? typing : {}\n\n // Dark bubble backgrounds need inverted typing dot colors\n const isDarkBg = color === 'primary' || color === 'dark'\n const invertDots = variant === 'bubble' && isDarkBg\n\n // flat variant never has a tail (asymmetric corner)\n const effectiveTail = variant === 'flat' ? false : tail\n const radiusClasses = effectiveTail\n ? bubbleRadiusTailMap[radius][role]\n : bubbleRadiusSymMap[radius]\n\n const bubble = (\n <div\n ref={ref}\n className={cn(\n bubbleTextMap[size],\n variant === 'bubble' && 'max-w-[75%]',\n isTyping && [typingMinWidthMap[size], 'text-center'],\n getBubbleColors(color, variant),\n (variant === 'bubble' || variant === 'flat') && bubblePaddingMap[size],\n (variant === 'bubble' || (variant === 'flat' && color === 'muted')) && radiusClasses,\n className\n )}\n {...props}\n >\n {isTyping ? (\n <TypingIndicator\n size={typingSizeMap[size]}\n color=\"muted\"\n {...typingProps}\n className={cn('align-middle', invertDots && '[&>div>div]:bg-current')}\n />\n ) : children}\n </div>\n )\n\n if (!actions) return bubble\n\n return (\n <div className={cn('flex items-end gap-1.5', role === 'user' && variant !== 'flat' ? 'flex-row-reverse' : 'flex-row')}>\n {bubble}\n <div className={cn(\n 'shrink-0 flex items-center gap-1 pb-0.5',\n 'opacity-0 group-hover/message:opacity-100',\n 'transition-opacity duration-normal',\n )}>\n {actions}\n </div>\n </div>\n )\n }\n)\nChatMessageContent.displayName = 'ChatMessageContent'\n\n// ============================================================================\n// ChatMessageFooter\n// ============================================================================\n\nconst ChatMessageFooter = React.forwardRef<HTMLDivElement, ChatMessageFooterProps>(\n (\n {\n className,\n timestamp,\n status,\n role: roleProp,\n size: sizeProp,\n children,\n ...props\n },\n ref\n ) => {\n const ctx = React.useContext(ChatMessageContext)\n const role = roleProp ?? ctx.role\n const size = sizeProp ?? ctx.size\n const variant = ctx.variant\n\n // Resolve status: built-in preset string → label, or pass-through ReactNode\n const statusContent = React.useMemo(() => {\n if (status == null) return null\n if (typeof status === 'string' && status in builtInStatusLabels) {\n const { label, className: cls } = builtInStatusLabels[status]\n return <span className={cls}>{label}</span>\n }\n return status\n }, [status])\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center gap-1 select-none',\n footerTextMap[size],\n 'text-text-subtle',\n role === 'user' && variant !== 'flat' ? 'justify-end' : 'justify-start',\n className\n )}\n {...props}\n >\n {children}\n {statusContent}\n {timestamp && <span>{timestamp}</span>}\n </div>\n )\n }\n)\nChatMessageFooter.displayName = 'ChatMessageFooter'\n\nexport {\n ChatMessage,\n ChatMessageAvatar,\n ChatMessageContent,\n ChatMessageFooter,\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
cn
|
|
4
|
+
} from "./chunk-53MIUPSY.mjs";
|
|
5
|
+
|
|
6
|
+
// src/components/ui/segmented.tsx
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
9
|
+
import { cva } from "class-variance-authority";
|
|
10
|
+
var SegmentedContext = React.createContext({});
|
|
11
|
+
var useSegmentedContext = () => React.useContext(SegmentedContext);
|
|
12
|
+
var segmentedVariants = cva(
|
|
13
|
+
"inline-flex items-center text-text-subtle",
|
|
14
|
+
{
|
|
15
|
+
variants: {
|
|
16
|
+
variant: {
|
|
17
|
+
default: "bg-background-muted gap-1",
|
|
18
|
+
outline: "bg-background border border-border gap-1",
|
|
19
|
+
underline: "bg-transparent border-b border-border gap-0",
|
|
20
|
+
ghost: "bg-transparent gap-1"
|
|
21
|
+
},
|
|
22
|
+
size: {
|
|
23
|
+
sm: "h-8",
|
|
24
|
+
// 32px height
|
|
25
|
+
md: "h-9",
|
|
26
|
+
// 36px height
|
|
27
|
+
default: "h-10",
|
|
28
|
+
// 40px height
|
|
29
|
+
lg: "h-12"
|
|
30
|
+
// 48px height
|
|
31
|
+
},
|
|
32
|
+
radius: {
|
|
33
|
+
none: "rounded-none",
|
|
34
|
+
sm: "rounded-sm",
|
|
35
|
+
base: "rounded",
|
|
36
|
+
default: "rounded-md",
|
|
37
|
+
lg: "rounded-lg",
|
|
38
|
+
xl: "rounded-xl",
|
|
39
|
+
"2xl": "rounded-2xl",
|
|
40
|
+
"3xl": "rounded-3xl",
|
|
41
|
+
full: "rounded-full"
|
|
42
|
+
},
|
|
43
|
+
fontWeight: {
|
|
44
|
+
normal: "[&>*]:font-normal",
|
|
45
|
+
semibold: "[&>*]:font-semibold"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
compoundVariants: [
|
|
49
|
+
// Padding for default/outline/ghost variants
|
|
50
|
+
{ variant: "default", className: "p-1" },
|
|
51
|
+
{ variant: "outline", className: "p-1" },
|
|
52
|
+
{ variant: "ghost", className: "p-1" },
|
|
53
|
+
// Underline has no padding
|
|
54
|
+
{ variant: "underline", className: "p-0" }
|
|
55
|
+
],
|
|
56
|
+
defaultVariants: {
|
|
57
|
+
variant: "default",
|
|
58
|
+
size: "default",
|
|
59
|
+
radius: "default",
|
|
60
|
+
fontWeight: "normal"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
var segmentedItemVariants = cva(
|
|
65
|
+
[
|
|
66
|
+
"inline-flex items-center justify-center whitespace-nowrap h-full",
|
|
67
|
+
"transition-all duration-micro ease-out",
|
|
68
|
+
"focus-visible:focus-ring",
|
|
69
|
+
"disabled:pointer-events-none disabled:opacity-50"
|
|
70
|
+
].join(" "),
|
|
71
|
+
{
|
|
72
|
+
variants: {
|
|
73
|
+
variant: {
|
|
74
|
+
// Default: light background when selected, text emphasis on hover
|
|
75
|
+
default: [
|
|
76
|
+
"hover:text-foreground",
|
|
77
|
+
"data-[state=checked]:bg-background data-[state=checked]:text-foreground",
|
|
78
|
+
"data-[state=checked]:shadow-sm"
|
|
79
|
+
].join(" "),
|
|
80
|
+
// Outline: gray background when selected
|
|
81
|
+
outline: [
|
|
82
|
+
"data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground",
|
|
83
|
+
"hover:text-foreground hover:bg-background-muted"
|
|
84
|
+
].join(" "),
|
|
85
|
+
// Underline: bottom border indicator (Stripe/GitHub style)
|
|
86
|
+
underline: [
|
|
87
|
+
"border-b-2 border-transparent -mb-px",
|
|
88
|
+
"hover:text-foreground hover:border-border",
|
|
89
|
+
"data-[state=checked]:text-foreground data-[state=checked]:border-foreground"
|
|
90
|
+
].join(" "),
|
|
91
|
+
// Ghost: pill background only on selected (Notion/Figma style)
|
|
92
|
+
ghost: [
|
|
93
|
+
"hover:text-foreground hover:bg-background-muted",
|
|
94
|
+
"data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground"
|
|
95
|
+
].join(" ")
|
|
96
|
+
},
|
|
97
|
+
size: {
|
|
98
|
+
sm: "text-xs",
|
|
99
|
+
// 12px
|
|
100
|
+
md: "text-sm",
|
|
101
|
+
// 13px
|
|
102
|
+
default: "text-sm",
|
|
103
|
+
// 13px
|
|
104
|
+
lg: "text-md"
|
|
105
|
+
// 14px
|
|
106
|
+
},
|
|
107
|
+
radius: {
|
|
108
|
+
none: "rounded-none",
|
|
109
|
+
sm: "rounded-sm",
|
|
110
|
+
base: "rounded",
|
|
111
|
+
default: "rounded-md",
|
|
112
|
+
lg: "rounded-md",
|
|
113
|
+
xl: "rounded-lg",
|
|
114
|
+
"2xl": "rounded-xl",
|
|
115
|
+
"3xl": "rounded-2xl",
|
|
116
|
+
full: "rounded-full"
|
|
117
|
+
},
|
|
118
|
+
// Content type determines padding and aspect ratio
|
|
119
|
+
contentType: {
|
|
120
|
+
// Icon only: square aspect ratio like IconButton
|
|
121
|
+
icon: "aspect-square",
|
|
122
|
+
// Icon + text: rectangular (gap is set via compoundVariants)
|
|
123
|
+
"icon-text": "",
|
|
124
|
+
// Text only: standard button padding
|
|
125
|
+
text: ""
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
compoundVariants: [
|
|
129
|
+
// Icon + text - same padding rules as Button/Toggle
|
|
130
|
+
{ contentType: "icon-text", size: "sm", className: "px-3 gap-2" },
|
|
131
|
+
// 12px padding, 8px gap
|
|
132
|
+
{ contentType: "icon-text", size: "md", className: "px-3.5 gap-2" },
|
|
133
|
+
// 14px padding, 8px gap
|
|
134
|
+
{ contentType: "icon-text", size: "default", className: "px-4 gap-2" },
|
|
135
|
+
// 16px padding, 8px gap
|
|
136
|
+
{ contentType: "icon-text", size: "lg", className: "px-6 gap-2" },
|
|
137
|
+
// 24px padding, 8px gap
|
|
138
|
+
// Text only - same padding rules as Button/Toggle
|
|
139
|
+
{ contentType: "text", size: "sm", className: "px-3.5" },
|
|
140
|
+
// 14px
|
|
141
|
+
{ contentType: "text", size: "md", className: "px-3.5" },
|
|
142
|
+
// 14px
|
|
143
|
+
{ contentType: "text", size: "default", className: "px-4" },
|
|
144
|
+
// 16px
|
|
145
|
+
{ contentType: "text", size: "lg", className: "px-6" },
|
|
146
|
+
// 24px
|
|
147
|
+
// Underline variant has no rounded corners
|
|
148
|
+
{ variant: "underline", className: "rounded-none" }
|
|
149
|
+
],
|
|
150
|
+
defaultVariants: {
|
|
151
|
+
variant: "default",
|
|
152
|
+
size: "default",
|
|
153
|
+
radius: "default",
|
|
154
|
+
contentType: "text"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
var Segmented = React.forwardRef(({ className, variant, size, radius, fontWeight, ...props }, ref) => {
|
|
159
|
+
const resolvedFontWeight = fontWeight ?? "normal";
|
|
160
|
+
return /* @__PURE__ */ React.createElement(SegmentedContext.Provider, { value: { variant: variant || "default", size: size || "default", radius: radius || "default" } }, /* @__PURE__ */ React.createElement(
|
|
161
|
+
RadioGroupPrimitive.Root,
|
|
162
|
+
{
|
|
163
|
+
className: cn(segmentedVariants({ variant, size, radius, fontWeight: resolvedFontWeight }), className),
|
|
164
|
+
...props,
|
|
165
|
+
ref
|
|
166
|
+
}
|
|
167
|
+
));
|
|
168
|
+
});
|
|
169
|
+
Segmented.displayName = "Segmented";
|
|
170
|
+
var iconSizeClasses = {
|
|
171
|
+
sm: "[&>svg]:icon-xs",
|
|
172
|
+
// 14px
|
|
173
|
+
md: "[&>svg]:icon-sm",
|
|
174
|
+
// 16px
|
|
175
|
+
default: "[&>svg]:icon-sm",
|
|
176
|
+
// 16px
|
|
177
|
+
lg: "[&>svg]:icon-sm"
|
|
178
|
+
// 16px
|
|
179
|
+
};
|
|
180
|
+
var SegmentedItem = React.forwardRef(({ className, children, size, radius, contentType, ...props }, ref) => {
|
|
181
|
+
const { variant, size: contextSize, radius: contextRadius } = useSegmentedContext();
|
|
182
|
+
const resolvedSize = size || contextSize || "default";
|
|
183
|
+
const resolvedRadius = radius || contextRadius || "default";
|
|
184
|
+
return /* @__PURE__ */ React.createElement(
|
|
185
|
+
RadioGroupPrimitive.Item,
|
|
186
|
+
{
|
|
187
|
+
ref,
|
|
188
|
+
className: cn(
|
|
189
|
+
segmentedItemVariants({ variant, size: resolvedSize, radius: resolvedRadius, contentType }),
|
|
190
|
+
iconSizeClasses[resolvedSize],
|
|
191
|
+
className
|
|
192
|
+
),
|
|
193
|
+
...props
|
|
194
|
+
},
|
|
195
|
+
children
|
|
196
|
+
);
|
|
197
|
+
});
|
|
198
|
+
SegmentedItem.displayName = "SegmentedItem";
|
|
199
|
+
|
|
200
|
+
export {
|
|
201
|
+
segmentedVariants,
|
|
202
|
+
segmentedItemVariants,
|
|
203
|
+
Segmented,
|
|
204
|
+
SegmentedItem
|
|
205
|
+
};
|
|
206
|
+
//# sourceMappingURL=chunk-RKSB2N5L.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/segmented.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@/lib/utils'\n\n// Context to pass variant and size from Segmented to SegmentedItem\ntype SegmentedContextValue = {\n variant?: 'default' | 'outline' | 'underline' | 'ghost'\n size?: 'sm' | 'md' | 'default' | 'lg'\n radius?: 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'\n}\nconst SegmentedContext = React.createContext<SegmentedContextValue>({})\nconst useSegmentedContext = () => React.useContext(SegmentedContext)\n\nconst segmentedVariants = cva(\n 'inline-flex items-center text-text-subtle',\n {\n variants: {\n variant: {\n default: 'bg-background-muted gap-1',\n outline: 'bg-background border border-border gap-1',\n underline: 'bg-transparent border-b border-border gap-0',\n ghost: 'bg-transparent gap-1',\n },\n size: {\n sm: 'h-8', // 32px height\n md: 'h-9', // 36px height\n default: 'h-10', // 40px height\n lg: 'h-12', // 48px height\n },\n radius: {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-lg',\n xl: 'rounded-xl',\n '2xl': 'rounded-2xl',\n '3xl': 'rounded-3xl',\n full: 'rounded-full',\n },\n fontWeight: {\n normal: '[&>*]:font-normal',\n semibold: '[&>*]:font-semibold',\n },\n },\n compoundVariants: [\n // Padding for default/outline/ghost variants\n { variant: 'default', className: 'p-1' },\n { variant: 'outline', className: 'p-1' },\n { variant: 'ghost', className: 'p-1' },\n // Underline has no padding\n { variant: 'underline', className: 'p-0' },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n fontWeight: 'normal',\n },\n }\n)\n\nconst segmentedItemVariants = cva(\n [\n 'inline-flex items-center justify-center whitespace-nowrap h-full',\n 'transition-all duration-micro ease-out',\n 'focus-visible:focus-ring',\n 'disabled:pointer-events-none disabled:opacity-50',\n ].join(' '),\n {\n variants: {\n variant: {\n // Default: light background when selected, text emphasis on hover\n default: [\n 'hover:text-foreground',\n 'data-[state=checked]:bg-background data-[state=checked]:text-foreground',\n 'data-[state=checked]:shadow-sm',\n ].join(' '),\n // Outline: gray background when selected\n outline: [\n 'data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground',\n 'hover:text-foreground hover:bg-background-muted',\n ].join(' '),\n // Underline: bottom border indicator (Stripe/GitHub style)\n underline: [\n 'border-b-2 border-transparent -mb-px',\n 'hover:text-foreground hover:border-border',\n 'data-[state=checked]:text-foreground data-[state=checked]:border-foreground',\n ].join(' '),\n // Ghost: pill background only on selected (Notion/Figma style)\n ghost: [\n 'hover:text-foreground hover:bg-background-muted',\n 'data-[state=checked]:bg-background-muted data-[state=checked]:text-foreground',\n ].join(' '),\n },\n size: {\n sm: 'text-xs', // 12px\n md: 'text-sm', // 13px\n default: 'text-sm', // 13px\n lg: 'text-md', // 14px\n },\n radius: {\n none: 'rounded-none',\n sm: 'rounded-sm',\n base: 'rounded',\n default: 'rounded-md',\n lg: 'rounded-md',\n xl: 'rounded-lg',\n '2xl': 'rounded-xl',\n '3xl': 'rounded-2xl',\n full: 'rounded-full',\n },\n // Content type determines padding and aspect ratio\n contentType: {\n // Icon only: square aspect ratio like IconButton\n icon: 'aspect-square',\n // Icon + text: rectangular (gap is set via compoundVariants)\n 'icon-text': '',\n // Text only: standard button padding\n text: '',\n },\n },\n compoundVariants: [\n // Icon + text - same padding rules as Button/Toggle\n { contentType: 'icon-text', size: 'sm', className: 'px-3 gap-2' }, // 12px padding, 8px gap\n { contentType: 'icon-text', size: 'md', className: 'px-3.5 gap-2' }, // 14px padding, 8px gap\n { contentType: 'icon-text', size: 'default', className: 'px-4 gap-2' }, // 16px padding, 8px gap\n { contentType: 'icon-text', size: 'lg', className: 'px-6 gap-2' }, // 24px padding, 8px gap\n // Text only - same padding rules as Button/Toggle\n { contentType: 'text', size: 'sm', className: 'px-3.5' }, // 14px\n { contentType: 'text', size: 'md', className: 'px-3.5' }, // 14px\n { contentType: 'text', size: 'default', className: 'px-4' }, // 16px\n { contentType: 'text', size: 'lg', className: 'px-6' }, // 24px\n // Underline variant has no rounded corners\n { variant: 'underline', className: 'rounded-none' },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'default',\n radius: 'default',\n contentType: 'text',\n },\n }\n)\n\nexport interface SegmentedProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>,\n VariantProps<typeof segmentedVariants> {}\n\nconst Segmented = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n SegmentedProps\n>(({ className, variant, size, radius, fontWeight, ...props }, ref) => {\n // All variants default to normal font weight\n const resolvedFontWeight = fontWeight ?? 'normal'\n\n return (\n <SegmentedContext.Provider value={{ variant: variant || 'default', size: size || 'default', radius: radius || 'default' }}>\n <RadioGroupPrimitive.Root\n className={cn(segmentedVariants({ variant, size, radius, fontWeight: resolvedFontWeight }), className)}\n {...props}\n ref={ref}\n />\n </SegmentedContext.Provider>\n )\n})\nSegmented.displayName = 'Segmented'\n\n// Icon size for segmented control (4-step scale, Icon+Text mode)\n// sm: 14px, md~default~lg: 16px\nconst iconSizeClasses = {\n sm: '[&>svg]:icon-xs', // 14px\n md: '[&>svg]:icon-sm', // 16px\n default: '[&>svg]:icon-sm', // 16px\n lg: '[&>svg]:icon-sm', // 16px\n}\n\nexport interface SegmentedItemProps\n extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>,\n Omit<VariantProps<typeof segmentedItemVariants>, 'variant'> {}\n\nconst SegmentedItem = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n SegmentedItemProps\n>(({ className, children, size, radius, contentType, ...props }, ref) => {\n const { variant, size: contextSize, radius: contextRadius } = useSegmentedContext()\n const resolvedSize = size || contextSize || 'default'\n const resolvedRadius = radius || contextRadius || 'default'\n\n return (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n segmentedItemVariants({ variant, size: resolvedSize, radius: resolvedRadius, contentType }),\n iconSizeClasses[resolvedSize],\n className\n )}\n {...props}\n >\n {children}\n </RadioGroupPrimitive.Item>\n )\n})\nSegmentedItem.displayName = 'SegmentedItem'\n\nexport { Segmented, SegmentedItem, segmentedVariants, segmentedItemVariants }\n"],"mappings":"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","names":[]}
|