@nocoo/basalt 2.0.2 → 2.0.3
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-dialog.js +1 -1
- package/dist/components/alert-dialog.js.map +1 -1
- package/dist/components/chat-bubble.d.ts +17 -0
- package/dist/components/chat-bubble.js +25 -0
- package/dist/components/chat-bubble.js.map +1 -0
- package/dist/components/chat-composer.d.ts +41 -0
- package/dist/components/chat-composer.js +74 -0
- package/dist/components/chat-composer.js.map +1 -0
- package/dist/components/chat-header.d.ts +20 -0
- package/dist/components/chat-header.js +33 -0
- package/dist/components/chat-header.js.map +1 -0
- package/dist/components/chat-inbox.d.ts +28 -0
- package/dist/components/chat-inbox.js +44 -0
- package/dist/components/chat-inbox.js.map +1 -0
- package/dist/components/dialog.js +2 -2
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/dock.d.ts +39 -0
- package/dist/components/dock.js +116 -0
- package/dist/components/dock.js.map +1 -0
- package/dist/components/fab.d.ts +23 -0
- package/dist/components/fab.js +25 -0
- package/dist/components/fab.js.map +1 -0
- package/dist/styles/standalone.css +109 -0
- package/dist/styles/tokens.css +1 -0
- package/package.json +1 -1
|
@@ -52,7 +52,7 @@ var _ = ({ className: t, ...n }) => /* @__PURE__ */ o("div", {
|
|
|
52
52
|
});
|
|
53
53
|
_.displayName = "AlertDialogHeader";
|
|
54
54
|
var v = ({ className: t, ...n }) => /* @__PURE__ */ o("div", {
|
|
55
|
-
className: e("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", t),
|
|
55
|
+
className: e("mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", t),
|
|
56
56
|
...n
|
|
57
57
|
});
|
|
58
58
|
v.displayName = "AlertDialogFooter";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alert-dialog.js","names":[],"sources":["../../src/components/alert-dialog.tsx"],"sourcesContent":["import * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { buttonVariants } from \"./button\";\nimport { type DialogSize, dialogOverlayClass, dialogPanelClass } from \"./dialog\";\n\nexport const AlertDialog = AlertDialogPrimitive.Root;\nexport const AlertDialogTrigger = AlertDialogPrimitive.Trigger;\nexport const AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nexport const AlertDialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nexport type AlertDialogContentProps = React.ComponentPropsWithoutRef<\n\ttypeof AlertDialogPrimitive.Content\n> & {\n\tsize?: DialogSize;\n};\n\nexport const AlertDialogContent = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Content>,\n\tAlertDialogContentProps\n>(({ className, size = \"base\", ...props }, ref) => (\n\t<AlertDialogPortal>\n\t\t<AlertDialogOverlay />\n\t\t<AlertDialogPrimitive.Content\n\t\t\tref={ref}\n\t\t\tdata-basalt-surface-root=\"\"\n\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t{...props}\n\t\t/>\n\t</AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nexport const AlertDialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-2xl font-semibold tracking-tight\", className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nexport const AlertDialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-base text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;\n\nexport const AlertDialogCancel = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Cancel\n\t\tref={ref}\n\t\tclassName={cn(buttonVariants({ variant: \"outline\" }), className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport const AlertDialogAction = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Action>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Action\n\t\tref={ref}\n\t\tclassName={cn(buttonVariants({ variant: \"destructive\" }), className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nexport const AlertDialogHeader = ({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div className={cn(\"flex flex-col space-y-2 text-left\", className)} {...props} />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nexport const AlertDialogFooter = ({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tclassName={cn(\"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n\t\t{...props}\n\t/>\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAa,IAAc,EAAqB,MACnC,IAAqB,EAAqB,SAC1C,IAAoB,EAAqB,QAEzC,IAAqB,EAAM,YAGrC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,SAAtB;CAAmC;CAAK,WAAW,EAAmB,CAAS;CAAG,GAAI;AAAQ,CAAA,CAC9F;AACD,EAAmB,cAAc,EAAqB,QAAQ;AAQ9D,IAAa,IAAqB,EAAM,YAGrC,EAAE,cAAW,UAAO,QAAQ,GAAG,KAAS,MAC1C,kBAAC,GAAD,EAAA,UAAA,CACC,kBAAC,GAAD,CAAqB,CAAA,GACrB,kBAAC,EAAqB,SAAtB;CACM;CACL,4BAAyB;CACzB,WAAW,EAAiB;EAAE;EAAM;CAAU,CAAC;CAC/C,GAAI;AACJ,CAAA,CACiB,EAAA,CAAA,CACnB;AACD,EAAmB,cAAc,EAAqB,QAAQ;AAE9D,IAAa,IAAmB,EAAM,YAGnC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,OAAtB;CACM;CACL,WAAW,EAAG,yCAAyC,CAAS;CAChE,GAAI;AACJ,CAAA,CACD;AACD,EAAiB,cAAc,EAAqB,MAAM;AAE1D,IAAa,IAAyB,EAAM,YAGzC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,aAAtB;CACM;CACL,WAAW,EAAG,0CAA0C,CAAS;CACjE,GAAI;AACJ,CAAA,CACD;AACD,EAAuB,cAAc,EAAqB,YAAY;AAEtE,IAAa,IAAoB,EAAM,YAGpC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,QAAtB;CACM;CACL,WAAW,EAAG,EAAe,EAAE,SAAS,UAAU,CAAC,GAAG,CAAS;CAC/D,GAAI;AACJ,CAAA,CACD;AACD,EAAkB,cAAc,EAAqB,OAAO;AAE5D,IAAa,IAAoB,EAAM,YAGpC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,QAAtB;CACM;CACL,WAAW,EAAG,EAAe,EAAE,SAAS,cAAc,CAAC,GAAG,CAAS;CACnE,GAAI;AACJ,CAAA,CACD;AACD,EAAkB,cAAc,EAAqB,OAAO;AAE5D,IAAa,KAAqB,EACjC,cACA,GAAG,QAEH,kBAAC,OAAD;CAAK,WAAW,EAAG,qCAAqC,CAAS;CAAG,GAAI;AAAQ,CAAA;AAEjF,EAAkB,cAAc;AAEhC,IAAa,KAAqB,EACjC,cACA,GAAG,QAEH,kBAAC,OAAD;CACC,WAAW,EAAG,
|
|
1
|
+
{"version":3,"file":"alert-dialog.js","names":[],"sources":["../../src/components/alert-dialog.tsx"],"sourcesContent":["import * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { buttonVariants } from \"./button\";\nimport { type DialogSize, dialogOverlayClass, dialogPanelClass } from \"./dialog\";\n\nexport const AlertDialog = AlertDialogPrimitive.Root;\nexport const AlertDialogTrigger = AlertDialogPrimitive.Trigger;\nexport const AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nexport const AlertDialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nexport type AlertDialogContentProps = React.ComponentPropsWithoutRef<\n\ttypeof AlertDialogPrimitive.Content\n> & {\n\tsize?: DialogSize;\n};\n\nexport const AlertDialogContent = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Content>,\n\tAlertDialogContentProps\n>(({ className, size = \"base\", ...props }, ref) => (\n\t<AlertDialogPortal>\n\t\t<AlertDialogOverlay />\n\t\t<AlertDialogPrimitive.Content\n\t\t\tref={ref}\n\t\t\tdata-basalt-surface-root=\"\"\n\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t{...props}\n\t\t/>\n\t</AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nexport const AlertDialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-2xl font-semibold tracking-tight\", className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nexport const AlertDialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-base text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;\n\nexport const AlertDialogCancel = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Cancel\n\t\tref={ref}\n\t\tclassName={cn(buttonVariants({ variant: \"outline\" }), className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport const AlertDialogAction = React.forwardRef<\n\tReact.ElementRef<typeof AlertDialogPrimitive.Action>,\n\tReact.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n\t<AlertDialogPrimitive.Action\n\t\tref={ref}\n\t\tclassName={cn(buttonVariants({ variant: \"destructive\" }), className)}\n\t\t{...props}\n\t/>\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nexport const AlertDialogHeader = ({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div className={cn(\"flex flex-col space-y-2 text-left\", className)} {...props} />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nexport const AlertDialogFooter = ({\n\tclassName,\n\t...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tclassName={cn(\"mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n\t\t{...props}\n\t/>\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n"],"mappings":";;;;;;;;AAMA,IAAa,IAAc,EAAqB,MACnC,IAAqB,EAAqB,SAC1C,IAAoB,EAAqB,QAEzC,IAAqB,EAAM,YAGrC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,SAAtB;CAAmC;CAAK,WAAW,EAAmB,CAAS;CAAG,GAAI;AAAQ,CAAA,CAC9F;AACD,EAAmB,cAAc,EAAqB,QAAQ;AAQ9D,IAAa,IAAqB,EAAM,YAGrC,EAAE,cAAW,UAAO,QAAQ,GAAG,KAAS,MAC1C,kBAAC,GAAD,EAAA,UAAA,CACC,kBAAC,GAAD,CAAqB,CAAA,GACrB,kBAAC,EAAqB,SAAtB;CACM;CACL,4BAAyB;CACzB,WAAW,EAAiB;EAAE;EAAM;CAAU,CAAC;CAC/C,GAAI;AACJ,CAAA,CACiB,EAAA,CAAA,CACnB;AACD,EAAmB,cAAc,EAAqB,QAAQ;AAE9D,IAAa,IAAmB,EAAM,YAGnC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,OAAtB;CACM;CACL,WAAW,EAAG,yCAAyC,CAAS;CAChE,GAAI;AACJ,CAAA,CACD;AACD,EAAiB,cAAc,EAAqB,MAAM;AAE1D,IAAa,IAAyB,EAAM,YAGzC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,aAAtB;CACM;CACL,WAAW,EAAG,0CAA0C,CAAS;CACjE,GAAI;AACJ,CAAA,CACD;AACD,EAAuB,cAAc,EAAqB,YAAY;AAEtE,IAAa,IAAoB,EAAM,YAGpC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,QAAtB;CACM;CACL,WAAW,EAAG,EAAe,EAAE,SAAS,UAAU,CAAC,GAAG,CAAS;CAC/D,GAAI;AACJ,CAAA,CACD;AACD,EAAkB,cAAc,EAAqB,OAAO;AAE5D,IAAa,IAAoB,EAAM,YAGpC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAqB,QAAtB;CACM;CACL,WAAW,EAAG,EAAe,EAAE,SAAS,cAAc,CAAC,GAAG,CAAS;CACnE,GAAI;AACJ,CAAA,CACD;AACD,EAAkB,cAAc,EAAqB,OAAO;AAE5D,IAAa,KAAqB,EACjC,cACA,GAAG,QAEH,kBAAC,OAAD;CAAK,WAAW,EAAG,qCAAqC,CAAS;CAAG,GAAI;AAAQ,CAAA;AAEjF,EAAkB,cAAc;AAEhC,IAAa,KAAqB,EACjC,cACA,GAAG,QAEH,kBAAC,OAAD;CACC,WAAW,EAAG,+DAA+D,CAAS;CACtF,GAAI;AACJ,CAAA;AAEF,EAAkB,cAAc"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export type ChatBubbleVariant = "assistant" | "system" | "user";
|
|
3
|
+
export interface ChatBubbleProps {
|
|
4
|
+
/**
|
|
5
|
+
* Alignment and fill.
|
|
6
|
+
* @default "assistant"
|
|
7
|
+
*/
|
|
8
|
+
variant?: ChatBubbleVariant;
|
|
9
|
+
/**
|
|
10
|
+
* Show a streaming caret after the body.
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
streaming?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare function ChatBubble({ variant, streaming, className, children, }: ChatBubbleProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/chat-bubble.tsx
|
|
5
|
+
function r({ variant: r = "assistant", streaming: i = !1, className: a, children: o }) {
|
|
6
|
+
if (r === "system") return /* @__PURE__ */ t("p", {
|
|
7
|
+
className: e("px-1 text-center text-[11px] text-basalt-muted-foreground", a),
|
|
8
|
+
children: o
|
|
9
|
+
});
|
|
10
|
+
let s = r === "user";
|
|
11
|
+
return /* @__PURE__ */ t("div", {
|
|
12
|
+
className: e("flex w-full", s ? "justify-end" : "justify-start"),
|
|
13
|
+
children: /* @__PURE__ */ n("div", {
|
|
14
|
+
className: e("max-w-[92%] px-3.5 py-2 text-sm leading-5 shadow-sm", s ? "rounded-2xl rounded-br-md bg-basalt-primary text-basalt-primary-foreground" : "rounded-2xl rounded-bl-md bg-basalt-secondary text-basalt-foreground ring-1 ring-basalt-border/50", a),
|
|
15
|
+
children: [o, i ? /* @__PURE__ */ t("span", {
|
|
16
|
+
className: "mt-1 inline-block h-3 w-1.5 animate-pulse rounded-sm bg-basalt-primary/70 align-middle",
|
|
17
|
+
"aria-hidden": !0
|
|
18
|
+
}) : null]
|
|
19
|
+
})
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { r as ChatBubble };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=chat-bubble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-bubble.js","names":[],"sources":["../../src/components/chat-bubble.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport type ChatBubbleVariant = \"assistant\" | \"system\" | \"user\";\n\nexport interface ChatBubbleProps {\n\t/**\n\t * Alignment and fill.\n\t * @default \"assistant\"\n\t */\n\tvariant?: ChatBubbleVariant;\n\t/**\n\t * Show a streaming caret after the body.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nexport function ChatBubble({\n\tvariant = \"assistant\",\n\tstreaming = false,\n\tclassName,\n\tchildren,\n}: ChatBubbleProps) {\n\tif (variant === \"system\") {\n\t\treturn (\n\t\t\t<p className={cn(\"px-1 text-center text-[11px] text-basalt-muted-foreground\", className)}>\n\t\t\t\t{children}\n\t\t\t</p>\n\t\t);\n\t}\n\tconst user = variant === \"user\";\n\treturn (\n\t\t<div className={cn(\"flex w-full\", user ? \"justify-end\" : \"justify-start\")}>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t\"max-w-[92%] px-3.5 py-2 text-sm leading-5 shadow-sm\",\n\t\t\t\t\tuser\n\t\t\t\t\t\t? \"rounded-2xl rounded-br-md bg-basalt-primary text-basalt-primary-foreground\"\n\t\t\t\t\t\t: \"rounded-2xl rounded-bl-md bg-basalt-secondary text-basalt-foreground ring-1 ring-basalt-border/50\",\n\t\t\t\t\tclassName,\n\t\t\t\t)}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName=\"mt-1 inline-block h-3 w-1.5 animate-pulse rounded-sm bg-basalt-primary/70 align-middle\"\n\t\t\t\t\t\taria-hidden\n\t\t\t\t\t/>\n\t\t\t\t) : null}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;AAoBA,SAAgB,EAAW,EAC1B,aAAU,aACV,eAAY,IACZ,cACA,eACmB;CACnB,IAAI,MAAY,UACf,OACC,kBAAC,KAAD;EAAG,WAAW,EAAG,6DAA6D,CAAS;EACrF;CACC,CAAA;CAGL,IAAM,IAAO,MAAY;CACzB,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,eAAe,IAAO,gBAAgB,eAAe;EACvE,UAAA,kBAAC,OAAD;GACC,WAAW,EACV,uDACA,IACG,+EACA,qGACH,CACD;GAPD,UAAA,CASE,GACA,IACA,kBAAC,QAAD;IACC,WAAU;IACV,eAAA;GACA,CAAA,IACE,IACA;;CACD,CAAA;AAEP"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface ChatComposerProps {
|
|
2
|
+
/**
|
|
3
|
+
* Disable the field and send.
|
|
4
|
+
* @default false
|
|
5
|
+
*/
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Replace send with stop.
|
|
9
|
+
* @default false
|
|
10
|
+
*/
|
|
11
|
+
streaming?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Field accessible name.
|
|
14
|
+
* @default "Message"
|
|
15
|
+
*/
|
|
16
|
+
label?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Placeholder when empty.
|
|
19
|
+
*/
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Called with trimmed text on send.
|
|
23
|
+
*/
|
|
24
|
+
onSend: (text: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Called when the stop control is pressed.
|
|
27
|
+
*/
|
|
28
|
+
onCancel?: () => void;
|
|
29
|
+
/**
|
|
30
|
+
* Send control accessible name.
|
|
31
|
+
* @default "Send message"
|
|
32
|
+
*/
|
|
33
|
+
sendLabel?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Stop control accessible name.
|
|
36
|
+
* @default "Stop generating"
|
|
37
|
+
*/
|
|
38
|
+
cancelLabel?: string;
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function ChatComposer({ disabled, streaming, label, placeholder, onSend, onCancel, sendLabel, cancelLabel, className, }: ChatComposerProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { Button as t } from "./button.js";
|
|
4
|
+
import { InputArea as n } from "./input-area.js";
|
|
5
|
+
import { useRef as r, useState as i } from "react";
|
|
6
|
+
import { ArrowUp as a, Square as o } from "lucide-react";
|
|
7
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
8
|
+
//#region src/components/chat-composer.tsx
|
|
9
|
+
function l({ disabled: l = !1, streaming: u = !1, label: d = "Message", placeholder: f, onSend: p, onCancel: m, sendLabel: h = "Send message", cancelLabel: g = "Stop generating", className: _ }) {
|
|
10
|
+
let [v, y] = i(""), b = r(null), x = r(!1), S = () => {
|
|
11
|
+
let e = b.current;
|
|
12
|
+
e && (e.style.height = "0px", e.style.height = `${Math.min(e.scrollHeight, 160)}px`);
|
|
13
|
+
}, C = () => {
|
|
14
|
+
let e = v.trim();
|
|
15
|
+
!e || l || u || (p(e), y(""), requestAnimationFrame(() => {
|
|
16
|
+
let e = b.current;
|
|
17
|
+
e && (e.style.height = "0px", e.style.height = `${Math.min(e.scrollHeight, 160)}px`, e.focus());
|
|
18
|
+
}));
|
|
19
|
+
};
|
|
20
|
+
return /* @__PURE__ */ s("form", {
|
|
21
|
+
className: e("border-t border-basalt-border/50 bg-basalt-card p-3", _),
|
|
22
|
+
onSubmit: (e) => {
|
|
23
|
+
e.preventDefault(), C();
|
|
24
|
+
},
|
|
25
|
+
children: /* @__PURE__ */ c("div", {
|
|
26
|
+
className: "flex items-end gap-2 rounded-2xl bg-basalt-secondary p-2 ring-1 ring-basalt-border/50",
|
|
27
|
+
children: [/* @__PURE__ */ s(n, {
|
|
28
|
+
ref: b,
|
|
29
|
+
value: v,
|
|
30
|
+
onChange: (e) => {
|
|
31
|
+
y(e.target.value), requestAnimationFrame(S);
|
|
32
|
+
},
|
|
33
|
+
onCompositionStart: () => {
|
|
34
|
+
x.current = !0;
|
|
35
|
+
},
|
|
36
|
+
onCompositionEnd: () => {
|
|
37
|
+
x.current = !1;
|
|
38
|
+
},
|
|
39
|
+
onKeyDown: (e) => {
|
|
40
|
+
x.current || e.nativeEvent.isComposing || e.key !== "Enter" || e.shiftKey || (e.preventDefault(), C());
|
|
41
|
+
},
|
|
42
|
+
rows: 1,
|
|
43
|
+
placeholder: f,
|
|
44
|
+
disabled: l,
|
|
45
|
+
"aria-label": d,
|
|
46
|
+
className: "max-h-40 min-h-[40px] flex-1 resize-none border-0 bg-transparent p-2 shadow-none ring-0"
|
|
47
|
+
}), u ? /* @__PURE__ */ s(t, {
|
|
48
|
+
type: "button",
|
|
49
|
+
size: "icon",
|
|
50
|
+
variant: "secondary",
|
|
51
|
+
onClick: m,
|
|
52
|
+
disabled: !m,
|
|
53
|
+
"aria-label": g,
|
|
54
|
+
children: /* @__PURE__ */ s(o, {
|
|
55
|
+
className: "h-3.5 w-3.5 fill-current",
|
|
56
|
+
strokeWidth: 0
|
|
57
|
+
})
|
|
58
|
+
}) : /* @__PURE__ */ s(t, {
|
|
59
|
+
type: "submit",
|
|
60
|
+
size: "icon",
|
|
61
|
+
disabled: l || !v.trim(),
|
|
62
|
+
"aria-label": h,
|
|
63
|
+
children: /* @__PURE__ */ s(a, {
|
|
64
|
+
className: "h-4 w-4",
|
|
65
|
+
strokeWidth: 2.25
|
|
66
|
+
})
|
|
67
|
+
})]
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//#endregion
|
|
72
|
+
export { l as ChatComposer };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=chat-composer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-composer.js","names":[],"sources":["../../src/components/chat-composer.tsx"],"sourcesContent":["import { ArrowUp, Square } from \"lucide-react\";\nimport { type FormEvent, type KeyboardEvent, useRef, useState } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { InputArea } from \"./input-area\";\n\nexport interface ChatComposerProps {\n\t/**\n\t * Disable the field and send.\n\t * @default false\n\t */\n\tdisabled?: boolean;\n\t/**\n\t * Replace send with stop.\n\t * @default false\n\t */\n\tstreaming?: boolean;\n\t/**\n\t * Field accessible name.\n\t * @default \"Message\"\n\t */\n\tlabel?: string;\n\t/**\n\t * Placeholder when empty.\n\t */\n\tplaceholder?: string;\n\t/**\n\t * Called with trimmed text on send.\n\t */\n\tonSend: (text: string) => void;\n\t/**\n\t * Called when the stop control is pressed.\n\t */\n\tonCancel?: () => void;\n\t/**\n\t * Send control accessible name.\n\t * @default \"Send message\"\n\t */\n\tsendLabel?: string;\n\t/**\n\t * Stop control accessible name.\n\t * @default \"Stop generating\"\n\t */\n\tcancelLabel?: string;\n\tclassName?: string;\n}\n\nexport function ChatComposer({\n\tdisabled = false,\n\tstreaming = false,\n\tlabel = \"Message\",\n\tplaceholder,\n\tonSend,\n\tonCancel,\n\tsendLabel = \"Send message\",\n\tcancelLabel = \"Stop generating\",\n\tclassName,\n}: ChatComposerProps) {\n\tconst [value, setValue] = useState(\"\");\n\tconst ref = useRef<HTMLTextAreaElement>(null);\n\tconst composingRef = useRef(false);\n\n\tconst resize = () => {\n\t\tconst el = ref.current;\n\t\tif (!el) {\n\t\t\treturn;\n\t\t}\n\t\tel.style.height = \"0px\";\n\t\tel.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n\t};\n\n\tconst submit = () => {\n\t\tconst text = value.trim();\n\t\tif (!text || disabled || streaming) {\n\t\t\treturn;\n\t\t}\n\t\tonSend(text);\n\t\tsetValue(\"\");\n\t\trequestAnimationFrame(() => {\n\t\t\tconst el = ref.current;\n\t\t\tif (el) {\n\t\t\t\tel.style.height = \"0px\";\n\t\t\t\tel.style.height = `${Math.min(el.scrollHeight, 160)}px`;\n\t\t\t\tel.focus();\n\t\t\t}\n\t\t});\n\t};\n\n\tconst onSubmit = (event: FormEvent) => {\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\tconst onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n\t\tif (composingRef.current || event.nativeEvent.isComposing) {\n\t\t\treturn;\n\t\t}\n\t\tif (event.key !== \"Enter\" || event.shiftKey) {\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tsubmit();\n\t};\n\n\treturn (\n\t\t<form\n\t\t\tclassName={cn(\"border-t border-basalt-border/50 bg-basalt-card p-3\", className)}\n\t\t\tonSubmit={onSubmit}\n\t\t>\n\t\t\t<div className=\"flex items-end gap-2 rounded-2xl bg-basalt-secondary p-2 ring-1 ring-basalt-border/50\">\n\t\t\t\t<InputArea\n\t\t\t\t\tref={ref}\n\t\t\t\t\tvalue={value}\n\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\tsetValue(event.target.value);\n\t\t\t\t\t\trequestAnimationFrame(resize);\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionStart={() => {\n\t\t\t\t\t\tcomposingRef.current = true;\n\t\t\t\t\t}}\n\t\t\t\t\tonCompositionEnd={() => {\n\t\t\t\t\t\tcomposingRef.current = false;\n\t\t\t\t\t}}\n\t\t\t\t\tonKeyDown={onKeyDown}\n\t\t\t\t\trows={1}\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\taria-label={label}\n\t\t\t\t\tclassName=\"max-h-40 min-h-[40px] flex-1 resize-none border-0 bg-transparent p-2 shadow-none ring-0\"\n\t\t\t\t/>\n\t\t\t\t{streaming ? (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\t\tonClick={onCancel}\n\t\t\t\t\t\tdisabled={!onCancel}\n\t\t\t\t\t\taria-label={cancelLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<Square className=\"h-3.5 w-3.5 fill-current\" strokeWidth={0} />\n\t\t\t\t\t</Button>\n\t\t\t\t) : (\n\t\t\t\t\t<Button\n\t\t\t\t\t\ttype=\"submit\"\n\t\t\t\t\t\tsize=\"icon\"\n\t\t\t\t\t\tdisabled={disabled || !value.trim()}\n\t\t\t\t\t\taria-label={sendLabel}\n\t\t\t\t\t>\n\t\t\t\t\t\t<ArrowUp className=\"h-4 w-4\" strokeWidth={2.25} />\n\t\t\t\t\t</Button>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n"],"mappings":";;;;;;;;AA+CA,SAAgB,EAAa,EAC5B,cAAW,IACX,eAAY,IACZ,WAAQ,WACR,gBACA,WACA,aACA,eAAY,gBACZ,iBAAc,mBACd,gBACqB;CACrB,IAAM,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,IAAM,EAA4B,IAAI,GACtC,IAAe,EAAO,EAAK,GAE3B,UAAe;EACpB,IAAM,IAAK,EAAI;EACV,MAGL,EAAG,MAAM,SAAS,OAClB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,GAAG,EAAE;CACrD,GAEM,UAAe;EACpB,IAAM,IAAO,EAAM,KAAK;EACpB,CAAC,KAAQ,KAAY,MAGzB,EAAO,CAAI,GACX,EAAS,EAAE,GACX,4BAA4B;GAC3B,IAAM,IAAK,EAAI;GACf,AAAI,MACH,EAAG,MAAM,SAAS,OAClB,EAAG,MAAM,SAAS,GAAG,KAAK,IAAI,EAAG,cAAc,GAAG,EAAE,KACpD,EAAG,MAAM;EAEX,CAAC;CACF;CAkBA,OACC,kBAAC,QAAD;EACC,WAAW,EAAG,uDAAuD,CAAS;EACpE,WAnBM,MAAqB;GAEtC,AADA,EAAM,eAAe,GACrB,EAAO;EACR;EAkBE,UAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACC,kBAAC,GAAD;IACM;IACE;IACP,WAAW,MAAU;KAEpB,AADA,EAAS,EAAM,OAAO,KAAK,GAC3B,sBAAsB,CAAM;IAC7B;IACA,0BAA0B;KACzB,EAAa,UAAU;IACxB;IACA,wBAAwB;KACvB,EAAa,UAAU;IACxB;IACW,YA9BI,MAA8C;KAC5D,EAAa,WAAW,EAAM,YAAY,eAG1C,EAAM,QAAQ,WAAW,EAAM,aAGnC,EAAM,eAAe,GACrB,EAAO;IACR;IAsBI,MAAM;IACO;IACH;IACV,cAAY;IACZ,WAAU;GACV,CAAA,GACA,IACA,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,SAAQ;IACR,SAAS;IACT,UAAU,CAAC;IACX,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAQ,WAAU;KAA2B,aAAa;IAAI,CAAA;GACvD,CAAA,IAER,kBAAC,GAAD;IACC,MAAK;IACL,MAAK;IACL,UAAU,KAAY,CAAC,EAAM,KAAK;IAClC,cAAY;IAEZ,UAAA,kBAAC,GAAD;KAAS,WAAU;KAAU,aAAa;IAAO,CAAA;GAC1C,CAAA,CAEL;;CACA,CAAA;AAER"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
export interface ChatHeaderProps extends Omit<HTMLAttributes<HTMLElement>, "title"> {
|
|
3
|
+
/**
|
|
4
|
+
* Conversation title.
|
|
5
|
+
*/
|
|
6
|
+
title: ReactNode;
|
|
7
|
+
/**
|
|
8
|
+
* Secondary line under the title.
|
|
9
|
+
*/
|
|
10
|
+
subtitle?: ReactNode;
|
|
11
|
+
/**
|
|
12
|
+
* Leading mark, usually an icon.
|
|
13
|
+
*/
|
|
14
|
+
leading?: ReactNode;
|
|
15
|
+
/**
|
|
16
|
+
* Trailing actions.
|
|
17
|
+
*/
|
|
18
|
+
children?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
export declare function ChatHeader({ title, subtitle, leading, children, className, ...props }: ChatHeaderProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { jsx as t, jsxs as n } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/chat-header.tsx
|
|
5
|
+
function r({ title: r, subtitle: i, leading: a, children: o, className: s, ...c }) {
|
|
6
|
+
return /* @__PURE__ */ n("header", {
|
|
7
|
+
className: e("flex items-center justify-between gap-2 border-b border-basalt-border/50 px-3 py-2.5", s),
|
|
8
|
+
...c,
|
|
9
|
+
children: [/* @__PURE__ */ n("div", {
|
|
10
|
+
className: "flex min-w-0 items-center gap-2",
|
|
11
|
+
children: [a ? /* @__PURE__ */ t("span", {
|
|
12
|
+
className: "flex h-8 w-8 items-center justify-center",
|
|
13
|
+
children: a
|
|
14
|
+
}) : null, /* @__PURE__ */ n("div", {
|
|
15
|
+
className: "min-w-0",
|
|
16
|
+
children: [/* @__PURE__ */ t("p", {
|
|
17
|
+
className: "truncate text-sm font-semibold tracking-tight",
|
|
18
|
+
children: r
|
|
19
|
+
}), i ? /* @__PURE__ */ t("p", {
|
|
20
|
+
className: "truncate text-[11px] text-basalt-muted-foreground",
|
|
21
|
+
children: i
|
|
22
|
+
}) : null]
|
|
23
|
+
})]
|
|
24
|
+
}), o ? /* @__PURE__ */ t("div", {
|
|
25
|
+
className: "flex items-center gap-1",
|
|
26
|
+
children: o
|
|
27
|
+
}) : null]
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { r as ChatHeader };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=chat-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-header.js","names":[],"sources":["../../src/components/chat-header.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\nexport interface ChatHeaderProps extends Omit<HTMLAttributes<HTMLElement>, \"title\"> {\n\t/**\n\t * Conversation title.\n\t */\n\ttitle: ReactNode;\n\t/**\n\t * Secondary line under the title.\n\t */\n\tsubtitle?: ReactNode;\n\t/**\n\t * Leading mark, usually an icon.\n\t */\n\tleading?: ReactNode;\n\t/**\n\t * Trailing actions.\n\t */\n\tchildren?: ReactNode;\n}\n\nexport function ChatHeader({\n\ttitle,\n\tsubtitle,\n\tleading,\n\tchildren,\n\tclassName,\n\t...props\n}: ChatHeaderProps) {\n\treturn (\n\t\t<header\n\t\t\tclassName={cn(\n\t\t\t\t\"flex items-center justify-between gap-2 border-b border-basalt-border/50 px-3 py-2.5\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t\t{...props}\n\t\t>\n\t\t\t<div className=\"flex min-w-0 items-center gap-2\">\n\t\t\t\t{leading ? (\n\t\t\t\t\t<span className=\"flex h-8 w-8 items-center justify-center\">{leading}</span>\n\t\t\t\t) : null}\n\t\t\t\t<div className=\"min-w-0\">\n\t\t\t\t\t<p className=\"truncate text-sm font-semibold tracking-tight\">{title}</p>\n\t\t\t\t\t{subtitle ? (\n\t\t\t\t\t\t<p className=\"truncate text-[11px] text-basalt-muted-foreground\">{subtitle}</p>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{children ? <div className=\"flex items-center gap-1\">{children}</div> : null}\n\t\t</header>\n\t);\n}\n"],"mappings":";;;;AAsBA,SAAgB,EAAW,EAC1B,UACA,aACA,YACA,aACA,cACA,GAAG,KACgB;CACnB,OACC,kBAAC,UAAD;EACC,WAAW,EACV,wFACA,CACD;EACA,GAAI;EALL,UAAA,CAOC,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,IACA,kBAAC,QAAD;IAAM,WAAU;IAA4C,UAAA;GAAc,CAAA,IACvE,MACJ,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACC,kBAAC,KAAD;KAAG,WAAU;KAAiD,UAAA;IAAS,CAAA,GACtE,IACA,kBAAC,KAAD;KAAG,WAAU;KAAqD,UAAA;IAAY,CAAA,IAC3E,IACA;GACD,CAAA,CAAA;EACJ,CAAA,GAAA,IAAW,kBAAC,OAAD;GAAK,WAAU;GAA2B;EAAc,CAAA,IAAI,IACjE;;AAEV"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
export interface ChatInboxItem {
|
|
3
|
+
/** Stable id for selection. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Thread title. */
|
|
6
|
+
title: string;
|
|
7
|
+
/** Last-message preview. */
|
|
8
|
+
preview?: string;
|
|
9
|
+
/** Timestamp label. */
|
|
10
|
+
time?: string;
|
|
11
|
+
/** Optional leading mark. */
|
|
12
|
+
leading?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export interface ChatInboxProps extends Omit<HTMLAttributes<HTMLElement>, "onSelect"> {
|
|
15
|
+
/**
|
|
16
|
+
* Threads to list.
|
|
17
|
+
*/
|
|
18
|
+
items: readonly ChatInboxItem[];
|
|
19
|
+
/**
|
|
20
|
+
* Selected thread id.
|
|
21
|
+
*/
|
|
22
|
+
activeId?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Called when a thread is chosen.
|
|
25
|
+
*/
|
|
26
|
+
onSelect: (id: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export declare function ChatInbox({ items, activeId, onSelect, className, ...props }: ChatInboxProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { Button as t } from "./button.js";
|
|
4
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
5
|
+
//#region src/components/chat-inbox.tsx
|
|
6
|
+
function i({ items: i, activeId: a, onSelect: o, className: s, ...c }) {
|
|
7
|
+
return /* @__PURE__ */ n("nav", {
|
|
8
|
+
className: e("flex min-h-0 flex-col gap-0.5 overflow-y-auto p-2", s),
|
|
9
|
+
...c,
|
|
10
|
+
children: i.map((i) => {
|
|
11
|
+
let s = i.id === a;
|
|
12
|
+
return /* @__PURE__ */ r(t, {
|
|
13
|
+
type: "button",
|
|
14
|
+
variant: "ghost",
|
|
15
|
+
"aria-current": s ? "true" : void 0,
|
|
16
|
+
onClick: () => o(i.id),
|
|
17
|
+
className: e("h-auto w-full justify-start gap-2 rounded-basalt-md px-2 py-2 text-left", s ? "bg-basalt-accent" : ""),
|
|
18
|
+
children: [i.leading ? /* @__PURE__ */ n("span", {
|
|
19
|
+
className: "flex h-8 w-8 shrink-0 items-center justify-center",
|
|
20
|
+
children: i.leading
|
|
21
|
+
}) : null, /* @__PURE__ */ r("span", {
|
|
22
|
+
className: "min-w-0 flex-1",
|
|
23
|
+
children: [/* @__PURE__ */ r("span", {
|
|
24
|
+
className: "flex items-baseline justify-between gap-2",
|
|
25
|
+
children: [/* @__PURE__ */ n("span", {
|
|
26
|
+
className: "truncate text-sm font-medium text-basalt-foreground",
|
|
27
|
+
children: i.title
|
|
28
|
+
}), i.time ? /* @__PURE__ */ n("span", {
|
|
29
|
+
className: "shrink-0 text-[11px] text-basalt-muted-foreground",
|
|
30
|
+
children: i.time
|
|
31
|
+
}) : null]
|
|
32
|
+
}), i.preview ? /* @__PURE__ */ n("span", {
|
|
33
|
+
className: "mt-0.5 block truncate text-xs text-basalt-muted-foreground",
|
|
34
|
+
children: i.preview
|
|
35
|
+
}) : null]
|
|
36
|
+
})]
|
|
37
|
+
}, i.id);
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { i as ChatInbox };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=chat-inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-inbox.js","names":[],"sources":["../../src/components/chat-inbox.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\n\nexport interface ChatInboxItem {\n\t/** Stable id for selection. */\n\tid: string;\n\t/** Thread title. */\n\ttitle: string;\n\t/** Last-message preview. */\n\tpreview?: string;\n\t/** Timestamp label. */\n\ttime?: string;\n\t/** Optional leading mark. */\n\tleading?: ReactNode;\n}\n\nexport interface ChatInboxProps extends Omit<HTMLAttributes<HTMLElement>, \"onSelect\"> {\n\t/**\n\t * Threads to list.\n\t */\n\titems: readonly ChatInboxItem[];\n\t/**\n\t * Selected thread id.\n\t */\n\tactiveId?: string;\n\t/**\n\t * Called when a thread is chosen.\n\t */\n\tonSelect: (id: string) => void;\n}\n\nexport function ChatInbox({ items, activeId, onSelect, className, ...props }: ChatInboxProps) {\n\treturn (\n\t\t<nav className={cn(\"flex min-h-0 flex-col gap-0.5 overflow-y-auto p-2\", className)} {...props}>\n\t\t\t{items.map((item) => {\n\t\t\t\tconst active = item.id === activeId;\n\t\t\t\treturn (\n\t\t\t\t\t<Button\n\t\t\t\t\t\tkey={item.id}\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\taria-current={active ? \"true\" : undefined}\n\t\t\t\t\t\tonClick={() => onSelect(item.id)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"h-auto w-full justify-start gap-2 rounded-basalt-md px-2 py-2 text-left\",\n\t\t\t\t\t\t\tactive ? \"bg-basalt-accent\" : \"\",\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{item.leading ? (\n\t\t\t\t\t\t\t<span className=\"flex h-8 w-8 shrink-0 items-center justify-center\">\n\t\t\t\t\t\t\t\t{item.leading}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t<span className=\"min-w-0 flex-1\">\n\t\t\t\t\t\t\t<span className=\"flex items-baseline justify-between gap-2\">\n\t\t\t\t\t\t\t\t<span className=\"truncate text-sm font-medium text-basalt-foreground\">\n\t\t\t\t\t\t\t\t\t{item.title}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t{item.time ? (\n\t\t\t\t\t\t\t\t\t<span className=\"shrink-0 text-[11px] text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t\t{item.time}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t{item.preview ? (\n\t\t\t\t\t\t\t\t<span className=\"mt-0.5 block truncate text-xs text-basalt-muted-foreground\">\n\t\t\t\t\t\t\t\t\t{item.preview}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Button>\n\t\t\t\t);\n\t\t\t})}\n\t\t</nav>\n\t);\n}\n"],"mappings":";;;;;AAgCA,SAAgB,EAAU,EAAE,UAAO,aAAU,aAAU,cAAW,GAAG,KAAyB;CAC7F,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,qDAAqD,CAAS;EAAG,GAAI;EACtF,UAAA,EAAM,KAAK,MAAS;GACpB,IAAM,IAAS,EAAK,OAAO;GAC3B,OACC,kBAAC,GAAD;IAEC,MAAK;IACL,SAAQ;IACR,gBAAc,IAAS,SAAS,KAAA;IAChC,eAAe,EAAS,EAAK,EAAE;IAC/B,WAAW,EACV,2EACA,IAAS,qBAAqB,EAC/B;IATD,UAAA,CAWE,EAAK,UACL,kBAAC,QAAD;KAAM,WAAU;KACd,UAAA,EAAK;IACD,CAAA,IACH,MACJ,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACC,kBAAC,QAAD;MAAM,WAAU;MAAhB,UAAA,CACC,kBAAC,QAAD;OAAM,WAAU;OACd,UAAA,EAAK;MACD,CAAA,GACL,EAAK,OACL,kBAAC,QAAD;OAAM,WAAU;OACd,UAAA,EAAK;MACD,CAAA,IACH,IACC;KACL,CAAA,GAAA,EAAK,UACL,kBAAC,QAAD;MAAM,WAAU;MACd,UAAA,EAAK;KACD,CAAA,IACH,IACC;IACC,CAAA,CAAA;GAhCF,GAAA,EAAK,EAgCH;EAEV,CAAC;CACG,CAAA;AAEP"}
|
|
@@ -15,7 +15,7 @@ function c(r) {
|
|
|
15
15
|
return e("fixed inset-0 bg-black/40 backdrop-blur-md", t, "data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out", n, r);
|
|
16
16
|
}
|
|
17
17
|
function l({ size: r = "base", className: i } = {}) {
|
|
18
|
-
return e("fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-
|
|
18
|
+
return e("fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-6 text-basalt-foreground shadow-lg ring-1 ring-basalt-border", t, "data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out", n, s[r], i);
|
|
19
19
|
}
|
|
20
20
|
var u = o.Root, d = o.Trigger, f = o.Close, p = o.Portal, m = r.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ i(o.Overlay, {
|
|
21
21
|
ref: n,
|
|
@@ -58,7 +58,7 @@ var v = ({ className: t, ...n }) => /* @__PURE__ */ i("div", {
|
|
|
58
58
|
});
|
|
59
59
|
v.displayName = "DialogHeader";
|
|
60
60
|
var y = ({ className: t, ...n }) => /* @__PURE__ */ i("div", {
|
|
61
|
-
className: e("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", t),
|
|
61
|
+
className: e("mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", t),
|
|
62
62
|
...n
|
|
63
63
|
});
|
|
64
64
|
y.displayName = "DialogFooter";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialog.js","names":[],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-72\",\n\tbase: \"sm:w-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-black/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-
|
|
1
|
+
{"version":3,"file":"dialog.js","names":[],"sources":["../../src/components/dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport const DIALOG_SIZES = {\n\tsm: \"sm:w-72\",\n\tbase: \"sm:w-96\",\n\tlg: \"sm:w-[32rem]\",\n\txl: \"sm:w-[48rem]\",\n} as const;\n\nexport type DialogSize = keyof typeof DIALOG_SIZES;\n\nexport function dialogOverlayClass(className?: string) {\n\treturn cn(\n\t\t\"fixed inset-0 bg-black/40 backdrop-blur-md\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-overlay-in data-[state=closed]:animate-basalt-overlay-out\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n}\n\nexport function dialogPanelClass({\n\tsize = \"base\",\n\tclassName,\n}: {\n\tsize?: DialogSize;\n\tclassName?: string;\n} = {}) {\n\treturn cn(\n\t\t\"fixed top-1/2 left-1/2 w-full max-h-[calc(100vh-2rem)] max-w-[calc(100vw-2rem)] origin-center -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-basalt-lg p-6 text-basalt-foreground shadow-lg ring-1 ring-basalt-border\",\n\t\tOVERLAY_LAYER,\n\t\t\"data-[state=open]:animate-basalt-dialog-in data-[state=closed]:animate-basalt-dialog-out\",\n\t\tOVERLAY_MOTION,\n\t\tDIALOG_SIZES[size],\n\t\tclassName,\n\t);\n}\n\nexport const Dialog = DialogPrimitive.Root;\nexport const DialogTrigger = DialogPrimitive.Trigger;\nexport const DialogClose = DialogPrimitive.Close;\nexport const DialogPortal = DialogPrimitive.Portal;\n\nexport const DialogOverlay = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Overlay>,\n\tReact.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Overlay ref={ref} className={dialogOverlayClass(className)} {...props} />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nexport type DialogContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {\n\tsize?: DialogSize;\n\tdisablePointerDismissal?: boolean;\n};\n\nexport const DialogContent = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Content>,\n\tDialogContentProps\n>(\n\t(\n\t\t{\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tsize = \"base\",\n\t\t\tdisablePointerDismissal = false,\n\t\t\tonPointerDownOutside,\n\t\t\tonInteractOutside,\n\t\t\t...props\n\t\t},\n\t\tref,\n\t) => (\n\t\t<DialogPortal>\n\t\t\t<DialogOverlay />\n\t\t\t<DialogPrimitive.Content\n\t\t\t\tref={ref}\n\t\t\t\tdata-basalt-surface-root=\"\"\n\t\t\t\tclassName={dialogPanelClass({ size, className })}\n\t\t\t\tonPointerDownOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonPointerDownOutside?.(event);\n\t\t\t\t}}\n\t\t\t\tonInteractOutside={(event) => {\n\t\t\t\t\tif (disablePointerDismissal) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t}\n\t\t\t\t\tonInteractOutside?.(event);\n\t\t\t\t}}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</DialogPrimitive.Content>\n\t\t</DialogPortal>\n\t),\n);\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nexport const DialogTitle = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Title>,\n\tReact.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Title\n\t\tref={ref}\n\t\tclassName={cn(\"text-2xl font-semibold tracking-tight\", className)}\n\t\t{...props}\n\t/>\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nexport const DialogDescription = React.forwardRef<\n\tReact.ElementRef<typeof DialogPrimitive.Description>,\n\tReact.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n\t<DialogPrimitive.Description\n\t\tref={ref}\n\t\tclassName={cn(\"text-base text-basalt-muted-foreground\", className)}\n\t\t{...props}\n\t/>\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div className={cn(\"flex flex-col space-y-1.5 text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nexport const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n\t<div\n\t\tclassName={cn(\"mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end\", className)}\n\t\t{...props}\n\t/>\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"mappings":";;;;;;;AAKA,IAAa,IAAe;CAC3B,IAAI;CACJ,MAAM;CACN,IAAI;CACJ,IAAI;AACL;AAIA,SAAgB,EAAmB,GAAoB;CACtD,OAAO,EACN,8CACA,GACA,8FACA,GACA,CACD;AACD;AAEA,SAAgB,EAAiB,EAChC,UAAO,QACP,iBAIG,CAAC,GAAG;CACP,OAAO,EACN,oOACA,GACA,4FACA,GACA,EAAa,IACb,CACD;AACD;AAEA,IAAa,IAAS,EAAgB,MACzB,IAAgB,EAAgB,SAChC,IAAc,EAAgB,OAC9B,IAAe,EAAgB,QAE/B,IAAgB,EAAM,YAGhC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAgB,SAAjB;CAA8B;CAAK,WAAW,EAAmB,CAAS;CAAG,GAAI;AAAQ,CAAA,CACzF;AACD,EAAc,cAAc,EAAgB,QAAQ;AAOpD,IAAa,IAAgB,EAAM,YAKjC,EACC,cACA,aACA,UAAO,QACP,6BAA0B,IAC1B,yBACA,sBACA,GAAG,KAEJ,MAEA,kBAAC,GAAD,EAAA,UAAA,CACC,kBAAC,GAAD,CAAgB,CAAA,GAChB,kBAAC,EAAgB,SAAjB;CACM;CACL,4BAAyB;CACzB,WAAW,EAAiB;EAAE;EAAM;CAAU,CAAC;CAC/C,uBAAuB,MAAU;EAIhC,AAHI,KACH,EAAM,eAAe,GAEtB,IAAuB,CAAK;CAC7B;CACA,oBAAoB,MAAU;EAI7B,AAHI,KACH,EAAM,eAAe,GAEtB,IAAoB,CAAK;CAC1B;CACA,GAAI;CAEH;AACuB,CAAA,CACZ,EAAA,CAAA,CAEhB;AACA,EAAc,cAAc,EAAgB,QAAQ;AAEpD,IAAa,IAAc,EAAM,YAG9B,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAgB,OAAjB;CACM;CACL,WAAW,EAAG,yCAAyC,CAAS;CAChE,GAAI;AACJ,CAAA,CACD;AACD,EAAY,cAAc,EAAgB,MAAM;AAEhD,IAAa,IAAoB,EAAM,YAGpC,EAAE,cAAW,GAAG,KAAS,MAC3B,kBAAC,EAAgB,aAAjB;CACM;CACL,WAAW,EAAG,0CAA0C,CAAS;CACjE,GAAI;AACJ,CAAA,CACD;AACD,EAAkB,cAAc,EAAgB,YAAY;AAE5D,IAAa,KAAgB,EAAE,cAAW,GAAG,QAC5C,kBAAC,OAAD;CAAK,WAAW,EAAG,uCAAuC,CAAS;CAAG,GAAI;AAAQ,CAAA;AAEnF,EAAa,cAAc;AAE3B,IAAa,KAAgB,EAAE,cAAW,GAAG,QAC5C,kBAAC,OAAD;CACC,WAAW,EAAG,+DAA+D,CAAS;CACtF,GAAI;AACJ,CAAA;AAEF,EAAa,cAAc"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type DockMode = "overlay" | "push";
|
|
3
|
+
export interface DockProps {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the dock occupies its width.
|
|
6
|
+
*/
|
|
7
|
+
open: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* `push` shrinks the main column. `overlay` covers it with a Dialog scrim.
|
|
10
|
+
* @default "push"
|
|
11
|
+
*/
|
|
12
|
+
mode?: DockMode;
|
|
13
|
+
/**
|
|
14
|
+
* Width when open.
|
|
15
|
+
* @default "clamp(300px, 32.5vw, 546px)"
|
|
16
|
+
*/
|
|
17
|
+
width?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Overlay scrim click. Ignored in push mode.
|
|
20
|
+
*/
|
|
21
|
+
onDismiss?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Overlay scrim accessible name.
|
|
24
|
+
* @default "Dismiss"
|
|
25
|
+
*/
|
|
26
|
+
dismissLabel?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Accessible name.
|
|
29
|
+
*/
|
|
30
|
+
"aria-label": string;
|
|
31
|
+
className?: string;
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
export interface DockBodyProps {
|
|
35
|
+
className?: string;
|
|
36
|
+
children: ReactNode;
|
|
37
|
+
}
|
|
38
|
+
export declare function DockBody({ className, children }: DockBodyProps): import("react").JSX.Element;
|
|
39
|
+
export declare function Dock({ open, mode, width, onDismiss, dismissLabel, className, children, "aria-label": ariaLabel, }: DockProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { OVERLAY_LAYER as t, OVERLAY_MOTION as n } from "./overlay.js";
|
|
4
|
+
import { dialogOverlayClass as r } from "./dialog.js";
|
|
5
|
+
import { useEffect as i, useRef as a } from "react";
|
|
6
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/dock.tsx
|
|
8
|
+
var c = "button:not([disabled]), [href], input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])", l = "[data-radix-popper-content-wrapper], [data-radix-select-viewport]";
|
|
9
|
+
function u(e) {
|
|
10
|
+
return e ? [...e.querySelectorAll(c)].filter((e) => {
|
|
11
|
+
if (e.closest("[inert], [hidden]") || e.tabIndex < 0 || window.getComputedStyle(e).visibility === "hidden") return !1;
|
|
12
|
+
for (let t = e; t; t = t.parentElement) if (window.getComputedStyle(t).display === "none") return !1;
|
|
13
|
+
return !0;
|
|
14
|
+
}) : [];
|
|
15
|
+
}
|
|
16
|
+
function d({ className: t, children: n }) {
|
|
17
|
+
return /* @__PURE__ */ o("div", {
|
|
18
|
+
className: e("flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto px-3 py-3", t),
|
|
19
|
+
children: n
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function f({ open: c, mode: d = "push", width: f = "clamp(300px, 32.5vw, 546px)", onDismiss: p, dismissLabel: m = "Dismiss", className: h, children: g, "aria-label": _ }) {
|
|
23
|
+
let v = d === "overlay", y = a(null), b = a(null), x = (e) => {
|
|
24
|
+
y.current = e;
|
|
25
|
+
}, S = a(!v && c), C = a(null);
|
|
26
|
+
i(() => {
|
|
27
|
+
if (c) {
|
|
28
|
+
if (S.current) return;
|
|
29
|
+
C.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
30
|
+
let e = window.setTimeout(() => {
|
|
31
|
+
let e = y.current;
|
|
32
|
+
(u(e)[0] ?? e)?.focus(), S.current = !0;
|
|
33
|
+
}, 0);
|
|
34
|
+
return () => window.clearTimeout(e);
|
|
35
|
+
}
|
|
36
|
+
S.current &&= (C.current?.focus?.(), C.current = null, !1);
|
|
37
|
+
}, [c]), i(() => {
|
|
38
|
+
if (!v || !c) return;
|
|
39
|
+
let e = (e) => {
|
|
40
|
+
if (e.key === "Escape") {
|
|
41
|
+
if (e.defaultPrevented || !p) return;
|
|
42
|
+
e.preventDefault(), p();
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (e.key !== "Tab") return;
|
|
46
|
+
let t = b.current;
|
|
47
|
+
if (!t) return;
|
|
48
|
+
let n = u(t);
|
|
49
|
+
if (n.length === 0) {
|
|
50
|
+
e.preventDefault(), y.current?.focus();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let r = n[0], i = n[n.length - 1], a = document.activeElement;
|
|
54
|
+
if (a instanceof Element) {
|
|
55
|
+
let e = a.closest("[role='dialog'], [role='alertdialog']");
|
|
56
|
+
if (e && e !== y.current && !t.contains(e) || a.closest(l)) return;
|
|
57
|
+
}
|
|
58
|
+
if (!(a instanceof Node) || !t.contains(a) || !e.shiftKey && a === i) {
|
|
59
|
+
e.preventDefault(), r?.focus();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
e.shiftKey && a === r && (e.preventDefault(), i?.focus());
|
|
63
|
+
};
|
|
64
|
+
return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
|
|
65
|
+
}, [
|
|
66
|
+
v,
|
|
67
|
+
c,
|
|
68
|
+
p
|
|
69
|
+
]);
|
|
70
|
+
let w = e("overflow-hidden bg-basalt-background transition-[width] duration-300 ease-in-out", v ? e("absolute top-0 right-0 h-full", t) : "sticky top-0 h-screen shrink-0", n, h), T = { width: c ? f : 0 }, E = /* @__PURE__ */ o("div", {
|
|
71
|
+
className: "flex h-full flex-col bg-basalt-card shadow-lg ring-1 ring-basalt-border/40",
|
|
72
|
+
style: { width: f },
|
|
73
|
+
children: g
|
|
74
|
+
});
|
|
75
|
+
return v ? /* @__PURE__ */ s("div", {
|
|
76
|
+
ref: b,
|
|
77
|
+
className: e("absolute inset-0", t, !c && "pointer-events-none"),
|
|
78
|
+
children: [p ? /* @__PURE__ */ o("button", {
|
|
79
|
+
type: "button",
|
|
80
|
+
tabIndex: c ? 0 : -1,
|
|
81
|
+
"aria-label": m,
|
|
82
|
+
"aria-hidden": !c,
|
|
83
|
+
"data-state": c ? "open" : "closed",
|
|
84
|
+
className: e(r("absolute"), !c && "opacity-0"),
|
|
85
|
+
onClick: c ? p : void 0
|
|
86
|
+
}) : /* @__PURE__ */ o("div", {
|
|
87
|
+
"aria-hidden": !0,
|
|
88
|
+
"data-state": c ? "open" : "closed",
|
|
89
|
+
className: e(r("absolute"), !c && "opacity-0")
|
|
90
|
+
}), /* @__PURE__ */ o("div", {
|
|
91
|
+
ref: x,
|
|
92
|
+
role: "dialog",
|
|
93
|
+
"aria-modal": c ? !0 : void 0,
|
|
94
|
+
"aria-label": _,
|
|
95
|
+
className: w,
|
|
96
|
+
style: T,
|
|
97
|
+
"aria-hidden": !c,
|
|
98
|
+
inert: !c || void 0,
|
|
99
|
+
tabIndex: c ? -1 : void 0,
|
|
100
|
+
children: E
|
|
101
|
+
})]
|
|
102
|
+
}) : /* @__PURE__ */ o("aside", {
|
|
103
|
+
ref: x,
|
|
104
|
+
className: w,
|
|
105
|
+
style: T,
|
|
106
|
+
"aria-label": _,
|
|
107
|
+
"aria-hidden": !c,
|
|
108
|
+
inert: !c || void 0,
|
|
109
|
+
tabIndex: c ? -1 : void 0,
|
|
110
|
+
children: E
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { f as Dock, d as DockBody };
|
|
115
|
+
|
|
116
|
+
//# sourceMappingURL=dock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dock.js","names":[],"sources":["../../src/components/dock.tsx"],"sourcesContent":["import { type ReactNode, useEffect, useRef } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { dialogOverlayClass } from \"./dialog\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nconst FOCUSABLE =\n\t'button:not([disabled]), [href], input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\nconst PORTAL_FOCUS = \"[data-radix-popper-content-wrapper], [data-radix-select-viewport]\";\n\nfunction tabbables(root: HTMLElement | null) {\n\tif (!root) {\n\t\treturn [];\n\t}\n\treturn [...root.querySelectorAll<HTMLElement>(FOCUSABLE)].filter((node) => {\n\t\tif (node.closest(\"[inert], [hidden]\")) {\n\t\t\treturn false;\n\t\t}\n\t\tif (node.tabIndex < 0) {\n\t\t\treturn false;\n\t\t}\n\t\tif (window.getComputedStyle(node).visibility === \"hidden\") {\n\t\t\treturn false;\n\t\t}\n\t\tfor (let current: HTMLElement | null = node; current; current = current.parentElement) {\n\t\t\tif (window.getComputedStyle(current).display === \"none\") {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t});\n}\n\nexport type DockMode = \"overlay\" | \"push\";\n\nexport interface DockProps {\n\t/**\n\t * Whether the dock occupies its width.\n\t */\n\topen: boolean;\n\t/**\n\t * `push` shrinks the main column. `overlay` covers it with a Dialog scrim.\n\t * @default \"push\"\n\t */\n\tmode?: DockMode;\n\t/**\n\t * Width when open.\n\t * @default \"clamp(300px, 32.5vw, 546px)\"\n\t */\n\twidth?: string;\n\t/**\n\t * Overlay scrim click. Ignored in push mode.\n\t */\n\tonDismiss?: () => void;\n\t/**\n\t * Overlay scrim accessible name.\n\t * @default \"Dismiss\"\n\t */\n\tdismissLabel?: string;\n\t/**\n\t * Accessible name.\n\t */\n\t\"aria-label\": string;\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nexport interface DockBodyProps {\n\tclassName?: string;\n\tchildren: ReactNode;\n}\n\nexport function DockBody({ className, children }: DockBodyProps) {\n\treturn (\n\t\t<div className={cn(\"flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto px-3 py-3\", className)}>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\nexport function Dock({\n\topen,\n\tmode = \"push\",\n\twidth = \"clamp(300px, 32.5vw, 546px)\",\n\tonDismiss,\n\tdismissLabel = \"Dismiss\",\n\tclassName,\n\tchildren,\n\t\"aria-label\": ariaLabel,\n}: DockProps) {\n\tconst overlay = mode === \"overlay\";\n\tconst panelRef = useRef<HTMLElement | null>(null);\n\tconst overlayRootRef = useRef<HTMLDivElement>(null);\n\tconst setPanel = (node: HTMLElement | null) => {\n\t\tpanelRef.current = node;\n\t};\n\tconst wasOpen = useRef(!overlay && open);\n\tconst previousFocus = useRef<HTMLElement | null>(null);\n\n\tuseEffect(() => {\n\t\tif (open) {\n\t\t\tif (wasOpen.current) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpreviousFocus.current =\n\t\t\t\tdocument.activeElement instanceof HTMLElement ? document.activeElement : null;\n\t\t\tconst timer = window.setTimeout(() => {\n\t\t\t\tconst root = panelRef.current;\n\t\t\t\tconst nodes = tabbables(root);\n\t\t\t\t(nodes[0] ?? root)?.focus();\n\t\t\t\twasOpen.current = true;\n\t\t\t}, 0);\n\t\t\treturn () => window.clearTimeout(timer);\n\t\t}\n\t\tif (wasOpen.current) {\n\t\t\tpreviousFocus.current?.focus?.();\n\t\t\tpreviousFocus.current = null;\n\t\t\twasOpen.current = false;\n\t\t}\n\t}, [open]);\n\n\tuseEffect(() => {\n\t\tif (!overlay || !open) {\n\t\t\treturn;\n\t\t}\n\t\tconst onKeyDown = (event: KeyboardEvent) => {\n\t\t\tif (event.key === \"Escape\") {\n\t\t\t\tif (event.defaultPrevented || !onDismiss) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tevent.preventDefault();\n\t\t\t\tonDismiss();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.key !== \"Tab\") {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst root = overlayRootRef.current;\n\t\t\tif (!root) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst nodes = tabbables(root);\n\t\t\tif (nodes.length === 0) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tpanelRef.current?.focus();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst first = nodes[0];\n\t\t\tconst last = nodes[nodes.length - 1];\n\t\t\tconst active = document.activeElement;\n\t\t\tif (active instanceof Element) {\n\t\t\t\tconst nestedModal = active.closest(\"[role='dialog'], [role='alertdialog']\");\n\t\t\t\tif (nestedModal && nestedModal !== panelRef.current && !root.contains(nestedModal)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (active.closest(PORTAL_FOCUS)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!(active instanceof Node) ||\n\t\t\t\t!root.contains(active) ||\n\t\t\t\t(!event.shiftKey && active === last)\n\t\t\t) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tfirst?.focus();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (event.shiftKey && active === first) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tlast?.focus();\n\t\t\t}\n\t\t};\n\t\twindow.addEventListener(\"keydown\", onKeyDown);\n\t\treturn () => window.removeEventListener(\"keydown\", onKeyDown);\n\t}, [overlay, open, onDismiss]);\n\tconst panelClass = cn(\n\t\t\"overflow-hidden bg-basalt-background transition-[width] duration-300 ease-in-out\",\n\t\toverlay ? cn(\"absolute top-0 right-0 h-full\", OVERLAY_LAYER) : \"sticky top-0 h-screen shrink-0\",\n\t\tOVERLAY_MOTION,\n\t\tclassName,\n\t);\n\tconst panelStyle = { width: open ? width : 0 };\n\tconst inner = (\n\t\t<div\n\t\t\tclassName=\"flex h-full flex-col bg-basalt-card shadow-lg ring-1 ring-basalt-border/40\"\n\t\t\tstyle={{ width }}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n\n\tif (!overlay) {\n\t\treturn (\n\t\t\t<aside\n\t\t\t\tref={setPanel}\n\t\t\t\tclassName={panelClass}\n\t\t\t\tstyle={panelStyle}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\taria-hidden={!open}\n\t\t\t\tinert={!open || undefined}\n\t\t\t\ttabIndex={open ? -1 : undefined}\n\t\t\t>\n\t\t\t\t{inner}\n\t\t\t</aside>\n\t\t);\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tref={overlayRootRef}\n\t\t\tclassName={cn(\"absolute inset-0\", OVERLAY_LAYER, !open && \"pointer-events-none\")}\n\t\t>\n\t\t\t{onDismiss ? (\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\ttabIndex={open ? 0 : -1}\n\t\t\t\t\taria-label={dismissLabel}\n\t\t\t\t\taria-hidden={!open}\n\t\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\t\tclassName={cn(dialogOverlayClass(\"absolute\"), !open && \"opacity-0\")}\n\t\t\t\t\tonClick={open ? onDismiss : undefined}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<div\n\t\t\t\t\taria-hidden\n\t\t\t\t\tdata-state={open ? \"open\" : \"closed\"}\n\t\t\t\t\tclassName={cn(dialogOverlayClass(\"absolute\"), !open && \"opacity-0\")}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<div\n\t\t\t\tref={setPanel}\n\t\t\t\trole=\"dialog\"\n\t\t\t\taria-modal={open ? true : undefined}\n\t\t\t\taria-label={ariaLabel}\n\t\t\t\tclassName={panelClass}\n\t\t\t\tstyle={panelStyle}\n\t\t\t\taria-hidden={!open}\n\t\t\t\tinert={!open || undefined}\n\t\t\t\ttabIndex={open ? -1 : undefined}\n\t\t\t>\n\t\t\t\t{inner}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n"],"mappings":";;;;;;;AAKA,IAAM,IACL,qKACK,IAAe;AAErB,SAAS,EAAU,GAA0B;CAI5C,OAHK,IAGE,CAAC,GAAG,EAAK,iBAA8B,CAAS,CAAC,CAAC,CAAC,QAAQ,MAAS;EAO1E,IANI,EAAK,QAAQ,mBAAmB,KAGhC,EAAK,WAAW,KAGhB,OAAO,iBAAiB,CAAI,CAAC,CAAC,eAAe,UAChD,OAAO;EAER,KAAK,IAAI,IAA8B,GAAM,GAAS,IAAU,EAAQ,eACvE,IAAI,OAAO,iBAAiB,CAAO,CAAC,CAAC,YAAY,QAChD,OAAO;EAGT,OAAO;CACR,CAAC,IAlBO,CAAC;AAmBV;AAyCA,SAAgB,EAAS,EAAE,cAAW,eAA2B;CAChE,OACC,kBAAC,OAAD;EAAK,WAAW,EAAG,gEAAgE,CAAS;EAC1F;CACG,CAAA;AAEP;AAEA,SAAgB,EAAK,EACpB,SACA,UAAO,QACP,WAAQ,+BACR,cACA,kBAAe,WACf,cACA,aACA,cAAc,KACD;CACb,IAAM,IAAU,MAAS,WACnB,IAAW,EAA2B,IAAI,GAC1C,IAAiB,EAAuB,IAAI,GAC5C,KAAY,MAA6B;EAC9C,EAAS,UAAU;CACpB,GACM,IAAU,EAAO,CAAC,KAAW,CAAI,GACjC,IAAgB,EAA2B,IAAI;CAwBrD,AAtBA,QAAgB;EACf,IAAI,GAAM;GACT,IAAI,EAAQ,SACX;GAED,EAAc,UACb,SAAS,yBAAyB,cAAc,SAAS,gBAAgB;GAC1E,IAAM,IAAQ,OAAO,iBAAiB;IACrC,IAAM,IAAO,EAAS;IAGtB,CAFc,EAAU,CACvB,CAAA,CAAM,MAAM,EAAA,EAAO,MAAM,GAC1B,EAAQ,UAAU;GACnB,GAAG,CAAC;GACJ,aAAa,OAAO,aAAa,CAAK;EACvC;EACA,AAGC,EAAQ,aAFR,EAAc,SAAS,QAAQ,GAC/B,EAAc,UAAU,MACN;CAEpB,GAAG,CAAC,CAAI,CAAC,GAET,QAAgB;EACf,IAAI,CAAC,KAAW,CAAC,GAChB;EAED,IAAM,KAAa,MAAyB;GAC3C,IAAI,EAAM,QAAQ,UAAU;IAC3B,IAAI,EAAM,oBAAoB,CAAC,GAC9B;IAGD,AADA,EAAM,eAAe,GACrB,EAAU;IACV;GACD;GACA,IAAI,EAAM,QAAQ,OACjB;GAED,IAAM,IAAO,EAAe;GAC5B,IAAI,CAAC,GACJ;GAED,IAAM,IAAQ,EAAU,CAAI;GAC5B,IAAI,EAAM,WAAW,GAAG;IAEvB,AADA,EAAM,eAAe,GACrB,EAAS,SAAS,MAAM;IACxB;GACD;GACA,IAAM,IAAQ,EAAM,IACd,IAAO,EAAM,EAAM,SAAS,IAC5B,IAAS,SAAS;GACxB,IAAI,aAAkB,SAAS;IAC9B,IAAM,IAAc,EAAO,QAAQ,uCAAuC;IAI1E,IAHI,KAAe,MAAgB,EAAS,WAAW,CAAC,EAAK,SAAS,CAAW,KAG7E,EAAO,QAAQ,CAAY,GAC9B;GAEF;GACA,IACC,EAAE,aAAkB,SACpB,CAAC,EAAK,SAAS,CAAM,KACpB,CAAC,EAAM,YAAY,MAAW,GAC9B;IAED,AADA,EAAM,eAAe,GACrB,GAAO,MAAM;IACb;GACD;GACA,AAAI,EAAM,YAAY,MAAW,MAChC,EAAM,eAAe,GACrB,GAAM,MAAM;EAEd;EAEA,OADA,OAAO,iBAAiB,WAAW,CAAS,SAC/B,OAAO,oBAAoB,WAAW,CAAS;CAC7D,GAAG;EAAC;EAAS;EAAM;CAAS,CAAC;CAC7B,IAAM,IAAa,EAClB,oFACA,IAAU,EAAG,iCAAiC,CAAa,IAAI,kCAC/D,GACA,CACD,GACM,IAAa,EAAE,OAAO,IAAO,IAAQ,EAAE,GACvC,IACL,kBAAC,OAAD;EACC,WAAU;EACV,OAAO,EAAE,SAAM;EAEd;CACG,CAAA;CAmBN,OAhBK,IAiBJ,kBAAC,OAAD;EACC,KAAK;EACL,WAAW,EAAG,oBAAoB,GAAe,CAAC,KAAQ,qBAAqB;EAFhF,UAAA,CAIE,IACA,kBAAC,UAAD;GACC,MAAK;GACL,UAAU,IAAO,IAAI;GACrB,cAAY;GACZ,eAAa,CAAC;GACd,cAAY,IAAO,SAAS;GAC5B,WAAW,EAAG,EAAmB,UAAU,GAAG,CAAC,KAAQ,WAAW;GAClE,SAAS,IAAO,IAAY,KAAA;EAC5B,CAAA,IAED,kBAAC,OAAD;GACC,eAAA;GACA,cAAY,IAAO,SAAS;GAC5B,WAAW,EAAG,EAAmB,UAAU,GAAG,CAAC,KAAQ,WAAW;EAClE,CAAA,GAEF,kBAAC,OAAD;GACC,KAAK;GACL,MAAK;GACL,cAAY,IAAO,KAAO,KAAA;GAC1B,cAAY;GACZ,WAAW;GACX,OAAO;GACP,eAAa,CAAC;GACd,OAAO,CAAC,KAAQ,KAAA;GAChB,UAAU,IAAO,KAAK,KAAA;GAErB,UAAA;EACG,CAAA,CACD;MAjDJ,kBAAC,SAAD;EACC,KAAK;EACL,WAAW;EACX,OAAO;EACP,cAAY;EACZ,eAAa,CAAC;EACd,OAAO,CAAC,KAAQ,KAAA;EAChB,UAAU,IAAO,KAAK,KAAA;EAErB,UAAA;CACK,CAAA;AAyCV"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type FabPlacement = "absolute" | "fixed";
|
|
3
|
+
export interface FabProps {
|
|
4
|
+
/**
|
|
5
|
+
* When true, the launcher hides so a dock can take the corner.
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
8
|
+
open?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Viewport pin versus containing frame.
|
|
11
|
+
* @default "fixed"
|
|
12
|
+
*/
|
|
13
|
+
placement?: FabPlacement;
|
|
14
|
+
/**
|
|
15
|
+
* Accessible name.
|
|
16
|
+
*/
|
|
17
|
+
"aria-label": string;
|
|
18
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
19
|
+
children?: React.ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare const Fab: React.ForwardRefExoticComponent<FabProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn as e } from "../utils/cn.js";
|
|
3
|
+
import { OVERLAY_LAYER as t, OVERLAY_MOTION as n } from "./overlay.js";
|
|
4
|
+
import { Button as r } from "./button.js";
|
|
5
|
+
import * as i from "react";
|
|
6
|
+
import { jsx as a } from "react/jsx-runtime";
|
|
7
|
+
//#region src/components/fab.tsx
|
|
8
|
+
var o = i.forwardRef(({ open: i = !1, placement: o = "fixed", className: s, children: c, onClick: l, "aria-label": u, disabled: d }, f) => /* @__PURE__ */ a(r, {
|
|
9
|
+
ref: f,
|
|
10
|
+
size: "icon",
|
|
11
|
+
"aria-label": u,
|
|
12
|
+
"aria-expanded": i,
|
|
13
|
+
"aria-hidden": i || void 0,
|
|
14
|
+
tabIndex: i ? -1 : 0,
|
|
15
|
+
inert: i || void 0,
|
|
16
|
+
disabled: d,
|
|
17
|
+
onClick: i ? void 0 : l,
|
|
18
|
+
className: e(o === "absolute" ? "absolute" : "fixed", "right-4 bottom-4 h-16 w-16 rounded-full shadow-lg", t, "transition-[transform,opacity] duration-300 ease-in-out", n, i ? "pointer-events-none scale-75 opacity-0" : "hover:scale-[1.03] active:scale-[0.98]", s),
|
|
19
|
+
children: c
|
|
20
|
+
}));
|
|
21
|
+
o.displayName = "Fab";
|
|
22
|
+
//#endregion
|
|
23
|
+
export { o as Fab };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=fab.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fab.js","names":[],"sources":["../../src/components/fab.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"./button\";\nimport { OVERLAY_LAYER, OVERLAY_MOTION } from \"./overlay\";\n\nexport type FabPlacement = \"absolute\" | \"fixed\";\n\nexport interface FabProps {\n\t/**\n\t * When true, the launcher hides so a dock can take the corner.\n\t * @default false\n\t */\n\topen?: boolean;\n\t/**\n\t * Viewport pin versus containing frame.\n\t * @default \"fixed\"\n\t */\n\tplacement?: FabPlacement;\n\t/**\n\t * Accessible name.\n\t */\n\t\"aria-label\": string;\n\tonClick?: React.MouseEventHandler<HTMLButtonElement>;\n\tchildren?: React.ReactNode;\n\tclassName?: string;\n\tdisabled?: boolean;\n}\n\nexport const Fab = React.forwardRef<HTMLButtonElement, FabProps>(\n\t(\n\t\t{\n\t\t\topen = false,\n\t\t\tplacement = \"fixed\",\n\t\t\tclassName,\n\t\t\tchildren,\n\t\t\tonClick,\n\t\t\t\"aria-label\": ariaLabel,\n\t\t\tdisabled,\n\t\t},\n\t\tref,\n\t) => (\n\t\t<Button\n\t\t\tref={ref}\n\t\t\tsize=\"icon\"\n\t\t\taria-label={ariaLabel}\n\t\t\taria-expanded={open}\n\t\t\taria-hidden={open || undefined}\n\t\t\ttabIndex={open ? -1 : 0}\n\t\t\tinert={open || undefined}\n\t\t\tdisabled={disabled}\n\t\t\tonClick={open ? undefined : onClick}\n\t\t\tclassName={cn(\n\t\t\t\tplacement === \"absolute\" ? \"absolute\" : \"fixed\",\n\t\t\t\t\"right-4 bottom-4 h-16 w-16 rounded-full shadow-lg\",\n\t\t\t\tOVERLAY_LAYER,\n\t\t\t\t\"transition-[transform,opacity] duration-300 ease-in-out\",\n\t\t\t\tOVERLAY_MOTION,\n\t\t\t\topen ? \"pointer-events-none scale-75 opacity-0\" : \"hover:scale-[1.03] active:scale-[0.98]\",\n\t\t\t\tclassName,\n\t\t\t)}\n\t\t>\n\t\t\t{children}\n\t\t</Button>\n\t),\n);\nFab.displayName = \"Fab\";\n"],"mappings":";;;;;;;AA4BA,IAAa,IAAM,EAAM,YAEvB,EACC,UAAO,IACP,eAAY,SACZ,cACA,aACA,YACA,cAAc,GACd,eAED,MAEA,kBAAC,GAAD;CACM;CACL,MAAK;CACL,cAAY;CACZ,iBAAe;CACf,eAAa,KAAQ,KAAA;CACrB,UAAU,IAAO,KAAK;CACtB,OAAO,KAAQ,KAAA;CACL;CACV,SAAS,IAAO,KAAA,IAAY;CAC5B,WAAW,EACV,MAAc,aAAa,aAAa,SACxC,qDACA,GACA,2DACA,GACA,IAAO,2CAA2C,0CAClD,CACD;CAEC;AACM,CAAA,CAEV;AACA,EAAI,cAAc"}
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
--radius-sm: 0.25rem;
|
|
32
32
|
--radius-md: 0.375rem;
|
|
33
33
|
--radius-lg: 0.5rem;
|
|
34
|
+
--radius-2xl: 1rem;
|
|
34
35
|
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
35
36
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
36
37
|
--blur-xs: 4px;
|
|
@@ -415,9 +416,15 @@
|
|
|
415
416
|
.right-2 {
|
|
416
417
|
right: calc(var(--spacing) * 2);
|
|
417
418
|
}
|
|
419
|
+
.right-4 {
|
|
420
|
+
right: calc(var(--spacing) * 4);
|
|
421
|
+
}
|
|
418
422
|
.bottom-0 {
|
|
419
423
|
bottom: 0px;
|
|
420
424
|
}
|
|
425
|
+
.bottom-4 {
|
|
426
|
+
bottom: calc(var(--spacing) * 4);
|
|
427
|
+
}
|
|
421
428
|
.-left-\[5px\] {
|
|
422
429
|
left: calc(5px * -1);
|
|
423
430
|
}
|
|
@@ -466,6 +473,9 @@
|
|
|
466
473
|
.mt-3 {
|
|
467
474
|
margin-top: calc(var(--spacing) * 3);
|
|
468
475
|
}
|
|
476
|
+
.mt-6 {
|
|
477
|
+
margin-top: calc(var(--spacing) * 6);
|
|
478
|
+
}
|
|
469
479
|
.mr-1 {
|
|
470
480
|
margin-right: var(--spacing);
|
|
471
481
|
}
|
|
@@ -583,6 +593,9 @@
|
|
|
583
593
|
.h-14 {
|
|
584
594
|
height: calc(var(--spacing) * 14);
|
|
585
595
|
}
|
|
596
|
+
.h-16 {
|
|
597
|
+
height: calc(var(--spacing) * 16);
|
|
598
|
+
}
|
|
586
599
|
.h-36 {
|
|
587
600
|
height: calc(var(--spacing) * 36);
|
|
588
601
|
}
|
|
@@ -601,6 +614,9 @@
|
|
|
601
614
|
.h-screen {
|
|
602
615
|
height: 100vh;
|
|
603
616
|
}
|
|
617
|
+
.max-h-40 {
|
|
618
|
+
max-height: calc(var(--spacing) * 40);
|
|
619
|
+
}
|
|
604
620
|
.max-h-\[300px\] {
|
|
605
621
|
max-height: 300px;
|
|
606
622
|
}
|
|
@@ -616,6 +632,9 @@
|
|
|
616
632
|
.min-h-\[24px\] {
|
|
617
633
|
min-height: 24px;
|
|
618
634
|
}
|
|
635
|
+
.min-h-\[40px\] {
|
|
636
|
+
min-height: 40px;
|
|
637
|
+
}
|
|
619
638
|
.min-h-\[64px\] {
|
|
620
639
|
min-height: 64px;
|
|
621
640
|
}
|
|
@@ -667,6 +686,9 @@
|
|
|
667
686
|
.w-12 {
|
|
668
687
|
width: calc(var(--spacing) * 12);
|
|
669
688
|
}
|
|
689
|
+
.w-16 {
|
|
690
|
+
width: calc(var(--spacing) * 16);
|
|
691
|
+
}
|
|
670
692
|
.w-28 {
|
|
671
693
|
width: calc(var(--spacing) * 28);
|
|
672
694
|
}
|
|
@@ -706,6 +728,9 @@
|
|
|
706
728
|
.w-px {
|
|
707
729
|
width: 1px;
|
|
708
730
|
}
|
|
731
|
+
.max-w-\[92\%\] {
|
|
732
|
+
max-width: 92%;
|
|
733
|
+
}
|
|
709
734
|
.max-w-\[calc\(100vw-2rem\)\] {
|
|
710
735
|
max-width: calc(100vw - 2rem);
|
|
711
736
|
}
|
|
@@ -759,6 +784,12 @@
|
|
|
759
784
|
--tw-translate-y: calc(calc(1 / 2 * 100%) * -1);
|
|
760
785
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
761
786
|
}
|
|
787
|
+
.scale-75 {
|
|
788
|
+
--tw-scale-x: 75%;
|
|
789
|
+
--tw-scale-y: 75%;
|
|
790
|
+
--tw-scale-z: 75%;
|
|
791
|
+
scale: var(--tw-scale-x) var(--tw-scale-y);
|
|
792
|
+
}
|
|
762
793
|
.rotate-180 {
|
|
763
794
|
rotate: 180deg;
|
|
764
795
|
}
|
|
@@ -771,6 +802,9 @@
|
|
|
771
802
|
.animate-basalt-spin {
|
|
772
803
|
animation: basalt-spin 1s linear infinite;
|
|
773
804
|
}
|
|
805
|
+
.animate-pulse {
|
|
806
|
+
animation: basalt-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
807
|
+
}
|
|
774
808
|
.cursor-col-resize {
|
|
775
809
|
cursor: col-resize;
|
|
776
810
|
}
|
|
@@ -786,6 +820,9 @@
|
|
|
786
820
|
.touch-none {
|
|
787
821
|
touch-action: none;
|
|
788
822
|
}
|
|
823
|
+
.resize-none {
|
|
824
|
+
resize: none;
|
|
825
|
+
}
|
|
789
826
|
.appearance-none {
|
|
790
827
|
appearance: none;
|
|
791
828
|
}
|
|
@@ -807,6 +844,9 @@
|
|
|
807
844
|
.flex-wrap {
|
|
808
845
|
flex-wrap: wrap;
|
|
809
846
|
}
|
|
847
|
+
.items-baseline {
|
|
848
|
+
align-items: baseline;
|
|
849
|
+
}
|
|
810
850
|
.items-center {
|
|
811
851
|
align-items: center;
|
|
812
852
|
}
|
|
@@ -920,6 +960,9 @@
|
|
|
920
960
|
.overflow-y-hidden\! {
|
|
921
961
|
overflow-y: hidden !important;
|
|
922
962
|
}
|
|
963
|
+
.rounded-2xl {
|
|
964
|
+
border-radius: var(--radius-2xl);
|
|
965
|
+
}
|
|
923
966
|
.rounded-\[4px\] {
|
|
924
967
|
border-radius: 4px;
|
|
925
968
|
}
|
|
@@ -961,6 +1004,12 @@
|
|
|
961
1004
|
border-top-right-radius: calc(var(--basalt-radius) - 2px);
|
|
962
1005
|
border-bottom-right-radius: calc(var(--basalt-radius) - 2px);
|
|
963
1006
|
}
|
|
1007
|
+
.rounded-br-md {
|
|
1008
|
+
border-bottom-right-radius: var(--radius-md);
|
|
1009
|
+
}
|
|
1010
|
+
.rounded-bl-md {
|
|
1011
|
+
border-bottom-left-radius: var(--radius-md);
|
|
1012
|
+
}
|
|
964
1013
|
.border {
|
|
965
1014
|
border-style: var(--tw-border-style);
|
|
966
1015
|
border-width: 1px;
|
|
@@ -1004,6 +1053,12 @@
|
|
|
1004
1053
|
.border-basalt-border {
|
|
1005
1054
|
border-color: hsl(var(--basalt-border));
|
|
1006
1055
|
}
|
|
1056
|
+
.border-basalt-border\/50 {
|
|
1057
|
+
border-color: hsl(var(--basalt-border));
|
|
1058
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1059
|
+
border-color: color-mix(in oklab, hsl(var(--basalt-border)) 50%, transparent);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1007
1062
|
.border-basalt-primary {
|
|
1008
1063
|
border-color: hsl(var(--basalt-primary));
|
|
1009
1064
|
}
|
|
@@ -1067,6 +1122,12 @@
|
|
|
1067
1122
|
.bg-basalt-primary {
|
|
1068
1123
|
background-color: hsl(var(--basalt-primary));
|
|
1069
1124
|
}
|
|
1125
|
+
.bg-basalt-primary\/70 {
|
|
1126
|
+
background-color: hsl(var(--basalt-primary));
|
|
1127
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1128
|
+
background-color: color-mix(in oklab, hsl(var(--basalt-primary)) 70%, transparent);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1070
1131
|
.bg-basalt-secondary {
|
|
1071
1132
|
background-color: hsl(var(--basalt-secondary));
|
|
1072
1133
|
}
|
|
@@ -1168,6 +1229,9 @@
|
|
|
1168
1229
|
.px-3 {
|
|
1169
1230
|
padding-inline: calc(var(--spacing) * 3);
|
|
1170
1231
|
}
|
|
1232
|
+
.px-3\.5 {
|
|
1233
|
+
padding-inline: calc(var(--spacing) * 3.5);
|
|
1234
|
+
}
|
|
1171
1235
|
.px-4 {
|
|
1172
1236
|
padding-inline: calc(var(--spacing) * 4);
|
|
1173
1237
|
}
|
|
@@ -1240,6 +1304,9 @@
|
|
|
1240
1304
|
.text-right {
|
|
1241
1305
|
text-align: right;
|
|
1242
1306
|
}
|
|
1307
|
+
.align-middle {
|
|
1308
|
+
vertical-align: middle;
|
|
1309
|
+
}
|
|
1243
1310
|
.font-mono {
|
|
1244
1311
|
font-family: var(--font-mono);
|
|
1245
1312
|
}
|
|
@@ -1273,6 +1340,10 @@
|
|
|
1273
1340
|
.text-\[11px\] {
|
|
1274
1341
|
font-size: 11px;
|
|
1275
1342
|
}
|
|
1343
|
+
.leading-5 {
|
|
1344
|
+
--tw-leading: calc(var(--spacing) * 5);
|
|
1345
|
+
line-height: calc(var(--spacing) * 5);
|
|
1346
|
+
}
|
|
1276
1347
|
.leading-6 {
|
|
1277
1348
|
--tw-leading: calc(var(--spacing) * 6);
|
|
1278
1349
|
line-height: calc(var(--spacing) * 6);
|
|
@@ -1380,6 +1451,9 @@
|
|
|
1380
1451
|
.underline-offset-4 {
|
|
1381
1452
|
text-underline-offset: 4px;
|
|
1382
1453
|
}
|
|
1454
|
+
.opacity-0 {
|
|
1455
|
+
opacity: 0%;
|
|
1456
|
+
}
|
|
1383
1457
|
.opacity-50 {
|
|
1384
1458
|
opacity: 50%;
|
|
1385
1459
|
}
|
|
@@ -1424,6 +1498,12 @@
|
|
|
1424
1498
|
--tw-ring-color: color-mix(in oklab, hsl(var(--basalt-border)) 40%, transparent);
|
|
1425
1499
|
}
|
|
1426
1500
|
}
|
|
1501
|
+
.ring-basalt-border\/50 {
|
|
1502
|
+
--tw-ring-color: hsl(var(--basalt-border));
|
|
1503
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1504
|
+
--tw-ring-color: color-mix(in oklab, hsl(var(--basalt-border)) 50%, transparent);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1427
1507
|
.ring-basalt-border\/70 {
|
|
1428
1508
|
--tw-ring-color: hsl(var(--basalt-border));
|
|
1429
1509
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -1457,6 +1537,11 @@
|
|
|
1457
1537
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
1458
1538
|
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
1459
1539
|
}
|
|
1540
|
+
.transition-\[transform\,opacity\] {
|
|
1541
|
+
transition-property: transform,opacity;
|
|
1542
|
+
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
1543
|
+
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
1544
|
+
}
|
|
1460
1545
|
.transition-\[width\] {
|
|
1461
1546
|
transition-property: width;
|
|
1462
1547
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
@@ -1549,6 +1634,9 @@
|
|
|
1549
1634
|
border-color: hsl(var(--basalt-ring));
|
|
1550
1635
|
}
|
|
1551
1636
|
@media (hover: hover) {
|
|
1637
|
+
.hover\:scale-\[1\.03\]:hover {
|
|
1638
|
+
scale: 1.03;
|
|
1639
|
+
}
|
|
1552
1640
|
.hover\:bg-basalt-accent:hover {
|
|
1553
1641
|
background-color: hsl(var(--basalt-accent));
|
|
1554
1642
|
}
|
|
@@ -1673,6 +1761,9 @@
|
|
|
1673
1761
|
.focus-visible\:ring-inset:focus-visible {
|
|
1674
1762
|
--tw-ring-inset: inset;
|
|
1675
1763
|
}
|
|
1764
|
+
.active\:scale-\[0\.98\]:active {
|
|
1765
|
+
scale: 0.98;
|
|
1766
|
+
}
|
|
1676
1767
|
.active\:bg-basalt-accent:active {
|
|
1677
1768
|
background-color: hsl(var(--basalt-accent));
|
|
1678
1769
|
}
|
|
@@ -2140,6 +2231,21 @@
|
|
|
2140
2231
|
inherits: false;
|
|
2141
2232
|
initial-value: 0;
|
|
2142
2233
|
}
|
|
2234
|
+
@property --tw-scale-x {
|
|
2235
|
+
syntax: "*";
|
|
2236
|
+
inherits: false;
|
|
2237
|
+
initial-value: 1;
|
|
2238
|
+
}
|
|
2239
|
+
@property --tw-scale-y {
|
|
2240
|
+
syntax: "*";
|
|
2241
|
+
inherits: false;
|
|
2242
|
+
initial-value: 1;
|
|
2243
|
+
}
|
|
2244
|
+
@property --tw-scale-z {
|
|
2245
|
+
syntax: "*";
|
|
2246
|
+
inherits: false;
|
|
2247
|
+
initial-value: 1;
|
|
2248
|
+
}
|
|
2143
2249
|
@property --tw-space-y-reverse {
|
|
2144
2250
|
syntax: "*";
|
|
2145
2251
|
inherits: false;
|
|
@@ -2346,6 +2452,9 @@
|
|
|
2346
2452
|
--tw-translate-x: 0;
|
|
2347
2453
|
--tw-translate-y: 0;
|
|
2348
2454
|
--tw-translate-z: 0;
|
|
2455
|
+
--tw-scale-x: 1;
|
|
2456
|
+
--tw-scale-y: 1;
|
|
2457
|
+
--tw-scale-z: 1;
|
|
2349
2458
|
--tw-space-y-reverse: 0;
|
|
2350
2459
|
--tw-border-style: solid;
|
|
2351
2460
|
--tw-gradient-position: initial;
|
package/dist/styles/tokens.css
CHANGED
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
--basalt-zebra-fill: hsl(var(--basalt-secondary));
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
/* biome-ignore lint/style/noDescendingSpecificity: Rootless surface trees cannot overlap a surface-root tree. */
|
|
186
187
|
[data-basalt-surface]:not([data-basalt-surface-root] *) [data-basalt-surface] {
|
|
187
188
|
background: hsl(var(--basalt-secondary));
|
|
188
189
|
--basalt-control-fill: hsl(var(--basalt-secondary));
|