@tangle-network/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/dist/active-sessions-store-CeOmXgv5.d.ts +85 -0
- package/dist/artifact-pane-DvJyPWV4.d.ts +24 -0
- package/dist/auth.d.ts +74 -0
- package/dist/auth.js +15 -0
- package/dist/button-CMQuQEW_.d.ts +17 -0
- package/dist/chat.d.ts +232 -0
- package/dist/chat.js +30 -0
- package/dist/chunk-2NFQRQOD.js +1009 -0
- package/dist/chunk-2VH6PUXD.js +186 -0
- package/dist/chunk-34A66VBG.js +214 -0
- package/dist/chunk-3OI2QKFD.js +0 -0
- package/dist/chunk-4CLN43XT.js +45 -0
- package/dist/chunk-54SQQMMM.js +156 -0
- package/dist/chunk-5Z5ZYMOJ.js +0 -0
- package/dist/chunk-66BNMOVT.js +167 -0
- package/dist/chunk-6BGQA4BQ.js +0 -0
- package/dist/chunk-7UO2ZMRQ.js +133 -0
- package/dist/chunk-BX6AQMUS.js +183 -0
- package/dist/chunk-CD53GZOM.js +59 -0
- package/dist/chunk-CSAIKY36.js +54 -0
- package/dist/chunk-EEE55AVS.js +1201 -0
- package/dist/chunk-GYPQXTJU.js +230 -0
- package/dist/chunk-HFL6R6IF.js +37 -0
- package/dist/chunk-HJKCSXCH.js +737 -0
- package/dist/chunk-LISXUB4D.js +1222 -0
- package/dist/chunk-LQS34IGP.js +0 -0
- package/dist/chunk-MKTSMWVD.js +109 -0
- package/dist/chunk-NKDZ7GZE.js +192 -0
- package/dist/chunk-OEX7NZE3.js +321 -0
- package/dist/chunk-Q56BYXQF.js +61 -0
- package/dist/chunk-Q7EIIWTC.js +0 -0
- package/dist/chunk-REJESC5U.js +117 -0
- package/dist/chunk-RQGKSCEZ.js +0 -0
- package/dist/chunk-RQHJBTEU.js +10 -0
- package/dist/chunk-TMFOPHHN.js +299 -0
- package/dist/chunk-XGKULLYE.js +40 -0
- package/dist/chunk-XIHMJ7ZQ.js +614 -0
- package/dist/chunk-YJ2G3XO5.js +1048 -0
- package/dist/chunk-YNN4O57I.js +754 -0
- package/dist/code-block-DjXf8eOG.d.ts +19 -0
- package/dist/document-editor-pane-A5LT5H4N.js +12 -0
- package/dist/document-editor-pane-DyDEX_Zm.d.ts +124 -0
- package/dist/editor.d.ts +120 -0
- package/dist/editor.js +34 -0
- package/dist/files.d.ts +175 -0
- package/dist/files.js +20 -0
- package/dist/hooks.d.ts +56 -0
- package/dist/hooks.js +41 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +446 -0
- package/dist/markdown.d.ts +15 -0
- package/dist/markdown.js +14 -0
- package/dist/message-BHWbxBtT.d.ts +15 -0
- package/dist/openui.d.ts +115 -0
- package/dist/openui.js +12 -0
- package/dist/parts-dj7AcUg0.d.ts +36 -0
- package/dist/primitives.d.ts +332 -0
- package/dist/primitives.js +191 -0
- package/dist/run-PfLmDAox.d.ts +41 -0
- package/dist/run.d.ts +69 -0
- package/dist/run.js +36 -0
- package/dist/sdk-hooks.d.ts +285 -0
- package/dist/sdk-hooks.js +31 -0
- package/dist/stores.d.ts +17 -0
- package/dist/stores.js +76 -0
- package/dist/tool-call-feed-Bs3MyQMT.d.ts +68 -0
- package/dist/tool-display-z4JcDmMQ.d.ts +32 -0
- package/dist/tool-previews.d.ts +48 -0
- package/dist/tool-previews.js +21 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +45 -0
- package/dist/utils.js +32 -0
- package/package.json +193 -0
- package/src/auth/auth.tsx +228 -0
- package/src/auth/index.ts +13 -0
- package/src/auth/login-layout.tsx +46 -0
- package/src/chat/agent-timeline.stories.tsx +429 -0
- package/src/chat/agent-timeline.tsx +360 -0
- package/src/chat/chat-container.tsx +486 -0
- package/src/chat/chat-input.stories.tsx +142 -0
- package/src/chat/chat-input.tsx +389 -0
- package/src/chat/chat-message.stories.tsx +237 -0
- package/src/chat/chat-message.tsx +129 -0
- package/src/chat/index.ts +18 -0
- package/src/chat/message-list.stories.tsx +336 -0
- package/src/chat/message-list.tsx +79 -0
- package/src/chat/thinking-indicator.stories.tsx +56 -0
- package/src/chat/thinking-indicator.tsx +30 -0
- package/src/chat/user-message.stories.tsx +92 -0
- package/src/chat/user-message.tsx +43 -0
- package/src/editor/document-editor-pane.tsx +351 -0
- package/src/editor/editor-provider.tsx +428 -0
- package/src/editor/editor-toolbar.tsx +130 -0
- package/src/editor/index.ts +31 -0
- package/src/editor/markdown-conversion.ts +21 -0
- package/src/editor/markdown-document-editor.tsx +137 -0
- package/src/editor/tiptap-editor.tsx +331 -0
- package/src/editor/use-editor.ts +221 -0
- package/src/files/file-artifact-pane.tsx +183 -0
- package/src/files/file-preview.tsx +342 -0
- package/src/files/file-tabs.tsx +71 -0
- package/src/files/file-tree.tsx +258 -0
- package/src/files/index.ts +17 -0
- package/src/files/rich-file-tree.stories.tsx +104 -0
- package/src/files/rich-file-tree.test.tsx +42 -0
- package/src/files/rich-file-tree.tsx +232 -0
- package/src/hooks/index.ts +10 -0
- package/src/hooks/use-auth.ts +153 -0
- package/src/hooks/use-auto-scroll.ts +59 -0
- package/src/hooks/use-dropdown-menu.ts +40 -0
- package/src/hooks/use-live-time.test.tsx +40 -0
- package/src/hooks/use-live-time.ts +27 -0
- package/src/hooks/use-realtime-session.ts +319 -0
- package/src/hooks/use-run-collapse-state.ts +25 -0
- package/src/hooks/use-run-groups.ts +111 -0
- package/src/hooks/use-sdk-session.ts +575 -0
- package/src/hooks/use-sse-stream.ts +475 -0
- package/src/hooks/use-tool-call-stream.ts +96 -0
- package/src/index.ts +14 -0
- package/src/lib/utils.ts +6 -0
- package/src/markdown/code-block.tsx +198 -0
- package/src/markdown/index.ts +2 -0
- package/src/markdown/markdown.stories.tsx +190 -0
- package/src/markdown/markdown.tsx +62 -0
- package/src/openui/index.ts +20 -0
- package/src/openui/openui-artifact-renderer.tsx +542 -0
- package/src/primitives/artifact-pane.tsx +91 -0
- package/src/primitives/avatar.stories.tsx +95 -0
- package/src/primitives/avatar.tsx +47 -0
- package/src/primitives/badge.stories.tsx +57 -0
- package/src/primitives/badge.tsx +97 -0
- package/src/primitives/button.stories.tsx +48 -0
- package/src/primitives/button.tsx +115 -0
- package/src/primitives/card.stories.tsx +53 -0
- package/src/primitives/card.tsx +98 -0
- package/src/primitives/code-block.stories.tsx +115 -0
- package/src/primitives/code-block.tsx +22 -0
- package/src/primitives/design-tokens.stories.tsx +162 -0
- package/src/primitives/dialog.stories.tsx +176 -0
- package/src/primitives/dialog.tsx +137 -0
- package/src/primitives/drop-zone.stories.tsx +123 -0
- package/src/primitives/drop-zone.tsx +131 -0
- package/src/primitives/dropdown-menu.stories.tsx +122 -0
- package/src/primitives/dropdown-menu.tsx +214 -0
- package/src/primitives/empty-state.stories.tsx +81 -0
- package/src/primitives/empty-state.tsx +40 -0
- package/src/primitives/index.ts +118 -0
- package/src/primitives/input.stories.tsx +113 -0
- package/src/primitives/input.tsx +136 -0
- package/src/primitives/label.stories.tsx +84 -0
- package/src/primitives/label.tsx +24 -0
- package/src/primitives/progress.stories.tsx +93 -0
- package/src/primitives/progress.tsx +50 -0
- package/src/primitives/segmented-control.test.tsx +328 -0
- package/src/primitives/segmented-control.tsx +154 -0
- package/src/primitives/select.stories.tsx +164 -0
- package/src/primitives/select.tsx +158 -0
- package/src/primitives/sidebar-drop-zone.stories.tsx +100 -0
- package/src/primitives/sidebar-drop-zone.tsx +149 -0
- package/src/primitives/skeleton.stories.tsx +79 -0
- package/src/primitives/skeleton.tsx +55 -0
- package/src/primitives/stat-card.stories.tsx +137 -0
- package/src/primitives/stat-card.tsx +97 -0
- package/src/primitives/switch.stories.tsx +85 -0
- package/src/primitives/switch.tsx +28 -0
- package/src/primitives/table.stories.tsx +170 -0
- package/src/primitives/table.tsx +116 -0
- package/src/primitives/tabs.stories.tsx +180 -0
- package/src/primitives/tabs.tsx +71 -0
- package/src/primitives/terminal-display.stories.tsx +191 -0
- package/src/primitives/terminal-display.tsx +189 -0
- package/src/primitives/theme-toggle.stories.tsx +32 -0
- package/src/primitives/theme-toggle.tsx +96 -0
- package/src/primitives/toast.stories.tsx +155 -0
- package/src/primitives/toast.tsx +190 -0
- package/src/primitives/upload-progress.stories.tsx +120 -0
- package/src/primitives/upload-progress.tsx +110 -0
- package/src/run/expanded-tool-detail.stories.tsx +182 -0
- package/src/run/expanded-tool-detail.tsx +186 -0
- package/src/run/index.ts +13 -0
- package/src/run/inline-thinking-item.stories.tsx +136 -0
- package/src/run/inline-thinking-item.tsx +120 -0
- package/src/run/inline-tool-item.stories.tsx +222 -0
- package/src/run/inline-tool-item.tsx +190 -0
- package/src/run/run-group.stories.tsx +322 -0
- package/src/run/run-group.tsx +569 -0
- package/src/run/run-item-primitives.tsx +17 -0
- package/src/run/tool-call-feed.stories.tsx +294 -0
- package/src/run/tool-call-feed.tsx +192 -0
- package/src/run/tool-call-step.stories.tsx +198 -0
- package/src/run/tool-call-step.tsx +240 -0
- package/src/sdk-hooks.ts +38 -0
- package/src/stores/active-sessions-store.ts +455 -0
- package/src/stores/chat-store.ts +43 -0
- package/src/stores/index.ts +2 -0
- package/src/tool-previews/command-preview.tsx +116 -0
- package/src/tool-previews/diff-preview.tsx +85 -0
- package/src/tool-previews/glob-results-preview.tsx +98 -0
- package/src/tool-previews/grep-results-preview.tsx +157 -0
- package/src/tool-previews/index.ts +22 -0
- package/src/tool-previews/preview-primitives.tsx +84 -0
- package/src/tool-previews/question-preview.tsx +101 -0
- package/src/tool-previews/web-search-preview.tsx +117 -0
- package/src/tool-previews/write-file-preview.tsx +80 -0
- package/src/types/branding.ts +11 -0
- package/src/types/index.ts +5 -0
- package/src/types/message.ts +13 -0
- package/src/types/parts.ts +51 -0
- package/src/types/run.ts +56 -0
- package/src/types/tool-display.ts +41 -0
- package/src/utils/copy-text.ts +30 -0
- package/src/utils/format.test.ts +43 -0
- package/src/utils/format.ts +56 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/time-ago.ts +9 -0
- package/src/utils/tool-display.ts +238 -0
|
File without changes
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-RQHJBTEU.js";
|
|
4
|
+
|
|
5
|
+
// src/primitives/button.tsx
|
|
6
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
7
|
+
import { cva } from "class-variance-authority";
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var buttonVariants = cva(
|
|
11
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg font-medium text-sm transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
variant: {
|
|
15
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90 active:scale-[0.97] duration-[var(--transition-fast)]",
|
|
16
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90 active:scale-[0.97] duration-[var(--transition-fast)]",
|
|
17
|
+
outline: "border border-border bg-card hover:bg-muted active:scale-[0.97] duration-[var(--transition-fast)] text-foreground",
|
|
18
|
+
secondary: "bg-muted border border-border text-foreground hover:bg-muted/80 active:scale-[0.97] duration-[var(--transition-fast)]",
|
|
19
|
+
ghost: "hover:bg-muted hover:text-foreground duration-[var(--transition-fast)] text-muted-foreground border border-transparent",
|
|
20
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
21
|
+
sandbox: "bg-[var(--btn-primary-bg)] text-[var(--btn-primary-text)] border border-[var(--border-accent)] hover:bg-[var(--btn-primary-hover)] active:scale-[0.97] duration-[var(--transition-fast)]"
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
default: "h-[var(--control-height)] px-4 py-2",
|
|
25
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
26
|
+
lg: "h-11 rounded-lg px-7 text-sm",
|
|
27
|
+
xl: "h-13 rounded-xl px-9 text-base",
|
|
28
|
+
icon: "h-[var(--control-height)] w-[var(--control-height)]"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
defaultVariants: {
|
|
32
|
+
variant: "default",
|
|
33
|
+
size: "default"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
var Button = React.forwardRef(
|
|
38
|
+
({
|
|
39
|
+
className,
|
|
40
|
+
variant,
|
|
41
|
+
size,
|
|
42
|
+
asChild = false,
|
|
43
|
+
loading = false,
|
|
44
|
+
disabled,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
}, ref) => {
|
|
48
|
+
const Comp = asChild ? Slot : "button";
|
|
49
|
+
if (asChild) {
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
Comp,
|
|
52
|
+
{
|
|
53
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
54
|
+
ref,
|
|
55
|
+
...props,
|
|
56
|
+
children
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return /* @__PURE__ */ jsxs(
|
|
61
|
+
Comp,
|
|
62
|
+
{
|
|
63
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
64
|
+
ref,
|
|
65
|
+
disabled: disabled || loading,
|
|
66
|
+
...props,
|
|
67
|
+
children: [
|
|
68
|
+
loading && /* @__PURE__ */ jsxs(
|
|
69
|
+
"svg",
|
|
70
|
+
{
|
|
71
|
+
className: "mr-2 -ml-1 h-4 w-4 animate-spin",
|
|
72
|
+
fill: "none",
|
|
73
|
+
viewBox: "0 0 24 24",
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ jsx("title", { children: "Loading spinner" }),
|
|
76
|
+
/* @__PURE__ */ jsx(
|
|
77
|
+
"circle",
|
|
78
|
+
{
|
|
79
|
+
className: "opacity-25",
|
|
80
|
+
cx: "12",
|
|
81
|
+
cy: "12",
|
|
82
|
+
r: "10",
|
|
83
|
+
stroke: "currentColor",
|
|
84
|
+
strokeWidth: "4"
|
|
85
|
+
}
|
|
86
|
+
),
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
"path",
|
|
89
|
+
{
|
|
90
|
+
className: "opacity-75",
|
|
91
|
+
fill: "currentColor",
|
|
92
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
children
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
);
|
|
104
|
+
Button.displayName = "Button";
|
|
105
|
+
|
|
106
|
+
export {
|
|
107
|
+
buttonVariants,
|
|
108
|
+
Button
|
|
109
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Avatar,
|
|
3
|
+
AvatarFallback,
|
|
4
|
+
AvatarImage,
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuItem,
|
|
8
|
+
DropdownMenuLabel,
|
|
9
|
+
DropdownMenuSeparator,
|
|
10
|
+
DropdownMenuTrigger
|
|
11
|
+
} from "./chunk-34A66VBG.js";
|
|
12
|
+
import {
|
|
13
|
+
Button
|
|
14
|
+
} from "./chunk-MKTSMWVD.js";
|
|
15
|
+
import {
|
|
16
|
+
cn
|
|
17
|
+
} from "./chunk-RQHJBTEU.js";
|
|
18
|
+
|
|
19
|
+
// src/auth/auth.tsx
|
|
20
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
+
function GitHubIcon({ className }) {
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
"svg",
|
|
24
|
+
{
|
|
25
|
+
className,
|
|
26
|
+
viewBox: "0 0 24 24",
|
|
27
|
+
fill: "currentColor",
|
|
28
|
+
"aria-hidden": "true",
|
|
29
|
+
children: /* @__PURE__ */ jsx(
|
|
30
|
+
"path",
|
|
31
|
+
{
|
|
32
|
+
fillRule: "evenodd",
|
|
33
|
+
clipRule: "evenodd",
|
|
34
|
+
d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
function GitHubLoginButton({
|
|
41
|
+
authUrl = "/auth/github",
|
|
42
|
+
variant = "default",
|
|
43
|
+
className,
|
|
44
|
+
children,
|
|
45
|
+
...props
|
|
46
|
+
}) {
|
|
47
|
+
return /* @__PURE__ */ jsxs(
|
|
48
|
+
Button,
|
|
49
|
+
{
|
|
50
|
+
variant,
|
|
51
|
+
className: cn("gap-2", className),
|
|
52
|
+
onClick: () => {
|
|
53
|
+
window.location.href = authUrl;
|
|
54
|
+
},
|
|
55
|
+
...props,
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ jsx(GitHubIcon, { className: "h-5 w-5" }),
|
|
58
|
+
children ?? "Sign in with GitHub"
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
function UserMenu({
|
|
64
|
+
user,
|
|
65
|
+
logoutUrl = "/auth/logout",
|
|
66
|
+
links = [],
|
|
67
|
+
variant = "sandbox",
|
|
68
|
+
onLogout
|
|
69
|
+
}) {
|
|
70
|
+
const initials = user.name ? user.name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : user.email.slice(0, 2).toUpperCase();
|
|
71
|
+
const avatarGradient = {
|
|
72
|
+
sandbox: "bg-[image:var(--accent-gradient-strong)]"
|
|
73
|
+
}[variant];
|
|
74
|
+
const handleLogout = () => {
|
|
75
|
+
if (onLogout) {
|
|
76
|
+
onLogout();
|
|
77
|
+
}
|
|
78
|
+
window.location.href = logoutUrl;
|
|
79
|
+
};
|
|
80
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
81
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
82
|
+
"button",
|
|
83
|
+
{
|
|
84
|
+
type: "button",
|
|
85
|
+
className: "flex items-center gap-2 rounded-lg p-1.5 transition-colors hover:bg-accent focus:outline-none focus:ring-2 focus:ring-ring",
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "h-8 w-8", children: [
|
|
88
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: void 0, alt: user.name ?? user.email }),
|
|
89
|
+
/* @__PURE__ */ jsx(
|
|
90
|
+
AvatarFallback,
|
|
91
|
+
{
|
|
92
|
+
className: cn(
|
|
93
|
+
"text-white text-xs",
|
|
94
|
+
avatarGradient
|
|
95
|
+
),
|
|
96
|
+
children: initials
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
] }),
|
|
100
|
+
/* @__PURE__ */ jsxs("div", { className: "hidden text-left md:block", children: [
|
|
101
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: user.name ?? user.email }),
|
|
102
|
+
user.tier && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-xs capitalize", children: [
|
|
103
|
+
user.tier,
|
|
104
|
+
" Plan"
|
|
105
|
+
] })
|
|
106
|
+
] })
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
) }),
|
|
110
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56", children: [
|
|
111
|
+
/* @__PURE__ */ jsx(DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-1", children: [
|
|
112
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-sm", children: user.name ?? "Account" }),
|
|
113
|
+
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: user.email })
|
|
114
|
+
] }) }),
|
|
115
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
116
|
+
links.map((link) => /* @__PURE__ */ jsx(DropdownMenuItem, { asChild: true, children: /* @__PURE__ */ jsxs("a", { href: link.href, className: "flex items-center gap-2", children: [
|
|
117
|
+
link.icon,
|
|
118
|
+
link.label
|
|
119
|
+
] }) }, link.href)),
|
|
120
|
+
links.length > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
121
|
+
/* @__PURE__ */ jsx(
|
|
122
|
+
DropdownMenuItem,
|
|
123
|
+
{
|
|
124
|
+
onClick: handleLogout,
|
|
125
|
+
className: "text-[var(--surface-danger-text)] focus:text-[var(--surface-danger-text)]",
|
|
126
|
+
children: "Sign out"
|
|
127
|
+
}
|
|
128
|
+
)
|
|
129
|
+
] })
|
|
130
|
+
] });
|
|
131
|
+
}
|
|
132
|
+
function AuthHeader({
|
|
133
|
+
user,
|
|
134
|
+
loading = false,
|
|
135
|
+
variant = "sandbox",
|
|
136
|
+
apiBaseUrl = "",
|
|
137
|
+
menuLinks,
|
|
138
|
+
className
|
|
139
|
+
}) {
|
|
140
|
+
if (loading) {
|
|
141
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", className), children: [
|
|
142
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 w-8 animate-pulse rounded-full bg-muted" }),
|
|
143
|
+
/* @__PURE__ */ jsx("div", { className: "hidden md:block", children: /* @__PURE__ */ jsx("div", { className: "h-4 w-20 animate-pulse rounded bg-muted" }) })
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
if (!user) {
|
|
147
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-2", className), children: /* @__PURE__ */ jsx(
|
|
148
|
+
GitHubLoginButton,
|
|
149
|
+
{
|
|
150
|
+
authUrl: `${apiBaseUrl}/auth/github`,
|
|
151
|
+
variant,
|
|
152
|
+
size: "sm"
|
|
153
|
+
}
|
|
154
|
+
) });
|
|
155
|
+
}
|
|
156
|
+
return /* @__PURE__ */ jsx(
|
|
157
|
+
UserMenu,
|
|
158
|
+
{
|
|
159
|
+
user,
|
|
160
|
+
variant,
|
|
161
|
+
logoutUrl: `${apiBaseUrl}/auth/logout`,
|
|
162
|
+
links: menuLinks
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// src/auth/login-layout.tsx
|
|
168
|
+
import { Terminal } from "lucide-react";
|
|
169
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
170
|
+
function LoginLayout({
|
|
171
|
+
title = "Welcome Back",
|
|
172
|
+
subtitle = "Sign in to your workspace.",
|
|
173
|
+
brandIcon,
|
|
174
|
+
children,
|
|
175
|
+
className
|
|
176
|
+
}) {
|
|
177
|
+
return /* @__PURE__ */ jsx2("div", { className: cn("relative flex min-h-screen items-center justify-center bg-background overflow-hidden antialiased font-sans flex-col", className), children: /* @__PURE__ */ jsxs2("div", { className: "z-10 w-full max-w-md px-6 animate-in flex flex-col items-center", children: [
|
|
178
|
+
/* @__PURE__ */ jsxs2("div", { className: "mb-10 text-center flex flex-col items-center", children: [
|
|
179
|
+
/* @__PURE__ */ jsx2("div", { className: "inline-flex h-14 w-14 mb-4 items-center justify-center rounded-lg bg-muted border border-border", children: brandIcon || /* @__PURE__ */ jsx2(Terminal, { className: "h-7 w-7 text-foreground" }) }),
|
|
180
|
+
/* @__PURE__ */ jsx2("h1", { className: "text-2xl font-bold tracking-tight text-foreground font-display", children: title }),
|
|
181
|
+
/* @__PURE__ */ jsx2("p", { className: "mt-2 text-sm text-muted-foreground", children: subtitle })
|
|
182
|
+
] }),
|
|
183
|
+
/* @__PURE__ */ jsx2("div", { className: "w-full bg-card p-8 border border-border rounded-lg", children })
|
|
184
|
+
] }) });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export {
|
|
188
|
+
GitHubLoginButton,
|
|
189
|
+
UserMenu,
|
|
190
|
+
AuthHeader,
|
|
191
|
+
LoginLayout
|
|
192
|
+
};
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
// src/stores/active-sessions-store.ts
|
|
2
|
+
import { useStore } from "@nanostores/react";
|
|
3
|
+
import { atom } from "nanostores";
|
|
4
|
+
import { useMemo } from "react";
|
|
5
|
+
var INITIAL_STATE = {
|
|
6
|
+
sessions: {},
|
|
7
|
+
lastUpdatedAt: 0
|
|
8
|
+
};
|
|
9
|
+
var STATUS_PRIORITY = {
|
|
10
|
+
running: 0,
|
|
11
|
+
error: 1,
|
|
12
|
+
"attention-needed": 2,
|
|
13
|
+
idle: 3
|
|
14
|
+
};
|
|
15
|
+
var DEFAULT_RECORD = {
|
|
16
|
+
status: "idle",
|
|
17
|
+
isRunning: false,
|
|
18
|
+
isForeground: false,
|
|
19
|
+
needsAttention: false,
|
|
20
|
+
connectionState: "disconnected",
|
|
21
|
+
reconnectState: "idle",
|
|
22
|
+
transportMode: null,
|
|
23
|
+
lastError: null,
|
|
24
|
+
lastEventAt: null
|
|
25
|
+
};
|
|
26
|
+
var activeSessionsAtom = atom(INITIAL_STATE);
|
|
27
|
+
var foregroundSessionId = null;
|
|
28
|
+
function createRecord(options, now) {
|
|
29
|
+
return {
|
|
30
|
+
sessionId: options.sessionId,
|
|
31
|
+
projectId: options.projectId ?? null,
|
|
32
|
+
projectLabel: options.projectLabel,
|
|
33
|
+
title: options.title,
|
|
34
|
+
href: options.href,
|
|
35
|
+
registeredAt: now,
|
|
36
|
+
lastActivityAt: now,
|
|
37
|
+
metadata: options.metadata,
|
|
38
|
+
...DEFAULT_RECORD,
|
|
39
|
+
isForeground: options.sessionId === foregroundSessionId
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function resolveStatus(session) {
|
|
43
|
+
if (session.isRunning) return "running";
|
|
44
|
+
if (session.lastError || session.reconnectState === "failed") return "error";
|
|
45
|
+
if (session.needsAttention) return "attention-needed";
|
|
46
|
+
return "idle";
|
|
47
|
+
}
|
|
48
|
+
function normalizeSession(session) {
|
|
49
|
+
return {
|
|
50
|
+
...session,
|
|
51
|
+
status: resolveStatus(session)
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function updateSession(sessionId, updater) {
|
|
55
|
+
const current = activeSessionsAtom.get();
|
|
56
|
+
const existing = current.sessions[sessionId];
|
|
57
|
+
if (!existing) return;
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
activeSessionsAtom.set({
|
|
60
|
+
sessions: {
|
|
61
|
+
...current.sessions,
|
|
62
|
+
[sessionId]: normalizeSession(updater(existing, now))
|
|
63
|
+
},
|
|
64
|
+
lastUpdatedAt: now
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function registerActiveSession(options) {
|
|
68
|
+
const now = Date.now();
|
|
69
|
+
const current = activeSessionsAtom.get();
|
|
70
|
+
const existing = current.sessions[options.sessionId];
|
|
71
|
+
activeSessionsAtom.set({
|
|
72
|
+
sessions: {
|
|
73
|
+
...current.sessions,
|
|
74
|
+
[options.sessionId]: normalizeSession(
|
|
75
|
+
existing ? {
|
|
76
|
+
...existing,
|
|
77
|
+
projectId: existing.projectId ?? options.projectId ?? null,
|
|
78
|
+
projectLabel: options.projectLabel ?? existing.projectLabel,
|
|
79
|
+
title: options.title ?? existing.title,
|
|
80
|
+
href: options.href ?? existing.href,
|
|
81
|
+
metadata: options.metadata ?? existing.metadata,
|
|
82
|
+
lastActivityAt: now,
|
|
83
|
+
isForeground: options.sessionId === foregroundSessionId || existing.isForeground
|
|
84
|
+
} : createRecord(options, now)
|
|
85
|
+
)
|
|
86
|
+
},
|
|
87
|
+
lastUpdatedAt: now
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function unregisterActiveSession(sessionId) {
|
|
91
|
+
const current = activeSessionsAtom.get();
|
|
92
|
+
if (!current.sessions[sessionId]) return;
|
|
93
|
+
const { [sessionId]: _removed, ...remaining } = current.sessions;
|
|
94
|
+
if (foregroundSessionId === sessionId) {
|
|
95
|
+
foregroundSessionId = null;
|
|
96
|
+
}
|
|
97
|
+
activeSessionsAtom.set({
|
|
98
|
+
sessions: remaining,
|
|
99
|
+
lastUpdatedAt: Date.now()
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function setForegroundActiveSession(sessionId) {
|
|
103
|
+
foregroundSessionId = sessionId;
|
|
104
|
+
const current = activeSessionsAtom.get();
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
let changed = false;
|
|
107
|
+
const sessions = Object.fromEntries(
|
|
108
|
+
Object.entries(current.sessions).map(([id, session]) => {
|
|
109
|
+
const isForeground = id === sessionId;
|
|
110
|
+
if (session.isForeground !== isForeground) {
|
|
111
|
+
changed = true;
|
|
112
|
+
}
|
|
113
|
+
return [
|
|
114
|
+
id,
|
|
115
|
+
{
|
|
116
|
+
...session,
|
|
117
|
+
isForeground,
|
|
118
|
+
lastActivityAt: isForeground ? now : session.lastActivityAt
|
|
119
|
+
}
|
|
120
|
+
];
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
if (!changed) return;
|
|
124
|
+
activeSessionsAtom.set({
|
|
125
|
+
sessions,
|
|
126
|
+
lastUpdatedAt: now
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function updateActiveSessionMeta(sessionId, meta) {
|
|
130
|
+
updateSession(sessionId, (session, now) => ({
|
|
131
|
+
...session,
|
|
132
|
+
...meta,
|
|
133
|
+
lastActivityAt: now
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
function setActiveSessionConnection(sessionId, options) {
|
|
137
|
+
updateSession(sessionId, (session, now) => ({
|
|
138
|
+
...session,
|
|
139
|
+
connectionState: options.connectionState,
|
|
140
|
+
reconnectState: options.reconnectState ?? session.reconnectState,
|
|
141
|
+
transportMode: options.transportMode ?? session.transportMode,
|
|
142
|
+
lastError: options.lastError === void 0 ? session.lastError : options.lastError,
|
|
143
|
+
lastEventAt: options.lastEventAt ?? session.lastEventAt,
|
|
144
|
+
lastActivityAt: now
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
function setActiveSessionRunning(sessionId, isRunning, options) {
|
|
148
|
+
updateSession(sessionId, (session, now) => ({
|
|
149
|
+
...session,
|
|
150
|
+
isRunning,
|
|
151
|
+
needsAttention: isRunning ? false : session.needsAttention,
|
|
152
|
+
lastError: isRunning ? null : session.lastError,
|
|
153
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt,
|
|
154
|
+
lastActivityAt: now
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
function setActiveSessionAttention(sessionId, needsAttention, options) {
|
|
158
|
+
updateSession(sessionId, (session, now) => ({
|
|
159
|
+
...session,
|
|
160
|
+
needsAttention,
|
|
161
|
+
isRunning: needsAttention ? false : session.isRunning,
|
|
162
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt,
|
|
163
|
+
lastActivityAt: now
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
function setActiveSessionError(sessionId, error) {
|
|
167
|
+
updateSession(sessionId, (session, now) => ({
|
|
168
|
+
...session,
|
|
169
|
+
isRunning: false,
|
|
170
|
+
needsAttention: false,
|
|
171
|
+
lastError: error,
|
|
172
|
+
reconnectState: error ? "failed" : "idle",
|
|
173
|
+
connectionState: error ? "error" : session.connectionState,
|
|
174
|
+
lastEventAt: now,
|
|
175
|
+
lastActivityAt: now
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
function bumpActiveSessionActivity(sessionId, options) {
|
|
179
|
+
updateSession(sessionId, (session, now) => ({
|
|
180
|
+
...session,
|
|
181
|
+
lastEventAt: options?.lastEventAt ?? session.lastEventAt ?? now,
|
|
182
|
+
lastActivityAt: now
|
|
183
|
+
}));
|
|
184
|
+
}
|
|
185
|
+
function resetActiveSessions() {
|
|
186
|
+
foregroundSessionId = null;
|
|
187
|
+
activeSessionsAtom.set(INITIAL_STATE);
|
|
188
|
+
}
|
|
189
|
+
function getAllActiveSessions(state) {
|
|
190
|
+
return Object.values(state.sessions);
|
|
191
|
+
}
|
|
192
|
+
function getActiveSession(state, sessionId) {
|
|
193
|
+
return state.sessions[sessionId] ?? null;
|
|
194
|
+
}
|
|
195
|
+
function getSessionsForProject(state, projectId) {
|
|
196
|
+
return Object.values(state.sessions).filter((session) => session.projectId === projectId);
|
|
197
|
+
}
|
|
198
|
+
function getSessionsForNavbar(state, projectId) {
|
|
199
|
+
const sessions = projectId == null ? Object.values(state.sessions) : getSessionsForProject(state, projectId);
|
|
200
|
+
return [...sessions].sort((left, right) => {
|
|
201
|
+
if (left.isForeground !== right.isForeground) {
|
|
202
|
+
return Number(right.isForeground) - Number(left.isForeground);
|
|
203
|
+
}
|
|
204
|
+
const statusDiff = STATUS_PRIORITY[left.status] - STATUS_PRIORITY[right.status];
|
|
205
|
+
if (statusDiff !== 0) {
|
|
206
|
+
return statusDiff;
|
|
207
|
+
}
|
|
208
|
+
return right.lastActivityAt - left.lastActivityAt;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function getSessionsByActivity(state) {
|
|
212
|
+
return [...Object.values(state.sessions)].sort(
|
|
213
|
+
(left, right) => right.lastActivityAt - left.lastActivityAt
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
function getTotalRunningSessionCount(state) {
|
|
217
|
+
return Object.values(state.sessions).filter((session) => session.isRunning).length;
|
|
218
|
+
}
|
|
219
|
+
function hasBackgroundRunningSessions(state) {
|
|
220
|
+
return Object.values(state.sessions).some(
|
|
221
|
+
(session) => session.isRunning && !session.isForeground
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
function getAllProjectActivity(state) {
|
|
225
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
226
|
+
for (const session of Object.values(state.sessions)) {
|
|
227
|
+
if (session.projectId == null) continue;
|
|
228
|
+
const existing = grouped.get(session.projectId);
|
|
229
|
+
if (existing) {
|
|
230
|
+
existing.activeSessionCount += 1;
|
|
231
|
+
existing.lastActivityAt = Math.max(existing.lastActivityAt, session.lastActivityAt);
|
|
232
|
+
if (session.isRunning) {
|
|
233
|
+
existing.runningSessionIds.push(session.sessionId);
|
|
234
|
+
}
|
|
235
|
+
if (!existing.projectLabel && session.projectLabel) {
|
|
236
|
+
existing.projectLabel = session.projectLabel;
|
|
237
|
+
}
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
grouped.set(session.projectId, {
|
|
241
|
+
projectId: session.projectId,
|
|
242
|
+
projectLabel: session.projectLabel,
|
|
243
|
+
activeSessionCount: 1,
|
|
244
|
+
runningSessionIds: session.isRunning ? [session.sessionId] : [],
|
|
245
|
+
lastActivityAt: session.lastActivityAt
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
return [...grouped.values()].sort((left, right) => right.lastActivityAt - left.lastActivityAt);
|
|
249
|
+
}
|
|
250
|
+
function useActiveSessionsState() {
|
|
251
|
+
return useStore(activeSessionsAtom);
|
|
252
|
+
}
|
|
253
|
+
function useActiveSessions() {
|
|
254
|
+
const state = useStore(activeSessionsAtom);
|
|
255
|
+
return useMemo(() => getAllActiveSessions(state), [state]);
|
|
256
|
+
}
|
|
257
|
+
function useActiveSession(sessionId) {
|
|
258
|
+
const state = useStore(activeSessionsAtom);
|
|
259
|
+
return useMemo(
|
|
260
|
+
() => sessionId ? getActiveSession(state, sessionId) : null,
|
|
261
|
+
[sessionId, state]
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
function useProjectSessions(projectId) {
|
|
265
|
+
const state = useStore(activeSessionsAtom);
|
|
266
|
+
return useMemo(
|
|
267
|
+
() => projectId == null ? [] : getSessionsForProject(state, projectId),
|
|
268
|
+
[projectId, state]
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
function useNavbarSessions(projectId) {
|
|
272
|
+
const state = useStore(activeSessionsAtom);
|
|
273
|
+
return useMemo(() => getSessionsForNavbar(state, projectId), [projectId, state]);
|
|
274
|
+
}
|
|
275
|
+
function useSessionsByActivity() {
|
|
276
|
+
const state = useStore(activeSessionsAtom);
|
|
277
|
+
return useMemo(() => getSessionsByActivity(state), [state]);
|
|
278
|
+
}
|
|
279
|
+
function useProjectActivity() {
|
|
280
|
+
const state = useStore(activeSessionsAtom);
|
|
281
|
+
return useMemo(() => getAllProjectActivity(state), [state]);
|
|
282
|
+
}
|
|
283
|
+
function useTotalRunningSessions() {
|
|
284
|
+
const state = useStore(activeSessionsAtom);
|
|
285
|
+
return useMemo(() => getTotalRunningSessionCount(state), [state]);
|
|
286
|
+
}
|
|
287
|
+
function useHasBackgroundRunningSessions() {
|
|
288
|
+
const state = useStore(activeSessionsAtom);
|
|
289
|
+
return useMemo(() => hasBackgroundRunningSessions(state), [state]);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export {
|
|
293
|
+
activeSessionsAtom,
|
|
294
|
+
registerActiveSession,
|
|
295
|
+
unregisterActiveSession,
|
|
296
|
+
setForegroundActiveSession,
|
|
297
|
+
updateActiveSessionMeta,
|
|
298
|
+
setActiveSessionConnection,
|
|
299
|
+
setActiveSessionRunning,
|
|
300
|
+
setActiveSessionAttention,
|
|
301
|
+
setActiveSessionError,
|
|
302
|
+
bumpActiveSessionActivity,
|
|
303
|
+
resetActiveSessions,
|
|
304
|
+
getAllActiveSessions,
|
|
305
|
+
getActiveSession,
|
|
306
|
+
getSessionsForProject,
|
|
307
|
+
getSessionsForNavbar,
|
|
308
|
+
getSessionsByActivity,
|
|
309
|
+
getTotalRunningSessionCount,
|
|
310
|
+
hasBackgroundRunningSessions,
|
|
311
|
+
getAllProjectActivity,
|
|
312
|
+
useActiveSessionsState,
|
|
313
|
+
useActiveSessions,
|
|
314
|
+
useActiveSession,
|
|
315
|
+
useProjectSessions,
|
|
316
|
+
useNavbarSessions,
|
|
317
|
+
useSessionsByActivity,
|
|
318
|
+
useProjectActivity,
|
|
319
|
+
useTotalRunningSessions,
|
|
320
|
+
useHasBackgroundRunningSessions
|
|
321
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cn
|
|
3
|
+
} from "./chunk-RQHJBTEU.js";
|
|
4
|
+
|
|
5
|
+
// src/primitives/tabs.tsx
|
|
6
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs";
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var Tabs = TabsPrimitive.Root;
|
|
10
|
+
var TabsList = React.forwardRef(({ className, variant = "default", ...props }, ref) => {
|
|
11
|
+
const variants = {
|
|
12
|
+
default: "inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
13
|
+
pills: "inline-flex items-center gap-2",
|
|
14
|
+
underline: "inline-flex items-center gap-4 border-b border-border"
|
|
15
|
+
};
|
|
16
|
+
return /* @__PURE__ */ jsx(
|
|
17
|
+
TabsPrimitive.List,
|
|
18
|
+
{
|
|
19
|
+
ref,
|
|
20
|
+
className: cn(variants[variant], className),
|
|
21
|
+
...props
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
});
|
|
25
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
26
|
+
var TabsTrigger = React.forwardRef(({ className, variant = "default", ...props }, ref) => {
|
|
27
|
+
const variants = {
|
|
28
|
+
default: "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
|
|
29
|
+
pills: "inline-flex items-center justify-center whitespace-nowrap rounded-full px-4 py-2 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-primary data-[state=active]:text-primary-foreground data-[state=inactive]:text-muted-foreground data-[state=inactive]:hover:bg-muted",
|
|
30
|
+
underline: "inline-flex items-center justify-center whitespace-nowrap pb-3 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border-b-2 border-transparent data-[state=active]:border-primary data-[state=active]:text-foreground data-[state=inactive]:text-muted-foreground"
|
|
31
|
+
};
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
TabsPrimitive.Trigger,
|
|
34
|
+
{
|
|
35
|
+
ref,
|
|
36
|
+
className: cn(variants[variant], className),
|
|
37
|
+
...props
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
42
|
+
var TabsContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
43
|
+
TabsPrimitive.Content,
|
|
44
|
+
{
|
|
45
|
+
ref,
|
|
46
|
+
className: cn(
|
|
47
|
+
"mt-4 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
48
|
+
"data-[state=active]:fade-in-0 data-[state=active]:slide-in-from-bottom-2 data-[state=active]:animate-in",
|
|
49
|
+
className
|
|
50
|
+
),
|
|
51
|
+
...props
|
|
52
|
+
}
|
|
53
|
+
));
|
|
54
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
Tabs,
|
|
58
|
+
TabsList,
|
|
59
|
+
TabsTrigger,
|
|
60
|
+
TabsContent
|
|
61
|
+
};
|
|
File without changes
|