@cronus-ui/ui 0.6.0 → 0.6.1
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.
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type ComponentPropsWithoutRef, type ReactNode, type Ref } from "react";
|
|
2
|
+
import { DialogContent } from "./dialog.js";
|
|
3
|
+
export interface InviteDialogLabels {
|
|
4
|
+
title?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
emailPlaceholder?: string;
|
|
8
|
+
role?: string;
|
|
9
|
+
send?: string;
|
|
10
|
+
cancel?: string;
|
|
11
|
+
sending?: string;
|
|
12
|
+
errorFallback?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface InviteRole {
|
|
15
|
+
value: string;
|
|
16
|
+
label: string;
|
|
17
|
+
}
|
|
18
|
+
export interface InviteDialogProps extends Omit<ComponentPropsWithoutRef<typeof DialogContent>, "title" | "children"> {
|
|
19
|
+
/** Element that opens the dialog. Rendered inside a `DialogTrigger asChild`. Omit when driving the dialog purely via `open`. */
|
|
20
|
+
trigger?: ReactNode;
|
|
21
|
+
/** Controlled open state. Provide alongside `onOpenChange` to control the dialog externally. */
|
|
22
|
+
open?: boolean;
|
|
23
|
+
/** Uncontrolled initial open state. @default false */
|
|
24
|
+
defaultOpen?: boolean;
|
|
25
|
+
/** Called whenever the open state changes. Dismissal is suppressed while an invite promise is pending. */
|
|
26
|
+
onOpenChange?: (open: boolean) => void;
|
|
27
|
+
/** Roles offered in the select. Defaults to Member and Admin. */
|
|
28
|
+
roles?: readonly InviteRole[];
|
|
29
|
+
/** Initially selected role `value`. Falls back to the first role. */
|
|
30
|
+
defaultRole?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Invoked with the submitted email and role. If it returns a promise, the send
|
|
33
|
+
* button shows a spinner and actions are disabled until it settles; on resolve
|
|
34
|
+
* the dialog closes, on reject it stays open and surfaces the error.
|
|
35
|
+
*/
|
|
36
|
+
onInvite?: (payload: {
|
|
37
|
+
email: string;
|
|
38
|
+
role: string;
|
|
39
|
+
}) => void | Promise<void>;
|
|
40
|
+
/** Override any subset of the built-in English strings. */
|
|
41
|
+
labels?: InviteDialogLabels;
|
|
42
|
+
/** Forwarded to the dialog content surface. */
|
|
43
|
+
ref?: Ref<HTMLDivElement>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* An ergonomic invite dialog for adding a member by email and role, composed
|
|
47
|
+
* on top of the accessible `Dialog` primitive (focus trap, overlay, Escape).
|
|
48
|
+
*
|
|
49
|
+
* Behavior: `onInvite` may be async — while its promise is pending the send
|
|
50
|
+
* button shows a `Spinner`, both actions are disabled, and the dialog cannot be
|
|
51
|
+
* dismissed so the operation can't be interrupted mid-flight. On resolve the
|
|
52
|
+
* dialog closes; on reject it stays open and renders the error in a
|
|
53
|
+
* `role="alert"` region. Works controlled (`open`/`onOpenChange`) or
|
|
54
|
+
* uncontrolled (`defaultOpen`).
|
|
55
|
+
*
|
|
56
|
+
* Performance/a11y: late promise settlements are ignored after unmount via a
|
|
57
|
+
* mounted ref. The spinner is decorative (`aria-hidden`) with loading state
|
|
58
|
+
* conveyed through `aria-busy`. All entrance/exit motion is owned by the
|
|
59
|
+
* underlying primitive and degrades under `prefers-reduced-motion`.
|
|
60
|
+
*/
|
|
61
|
+
export declare function InviteDialog({ trigger, open, defaultOpen, onOpenChange, roles, defaultRole, onInvite, labels, className, ref, ...contentProps }: InviteDialogProps): import("react").JSX.Element;
|
|
62
|
+
//# sourceMappingURL=invite-dialog.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { CircleAlert } from "lucide-react";
|
|
4
|
+
import { useCallback, useEffect, useId, useRef, useState, } from "react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Button } from "./button.js";
|
|
7
|
+
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "./dialog.js";
|
|
8
|
+
import { Field, FieldLabel } from "./field.js";
|
|
9
|
+
import { Input } from "./input.js";
|
|
10
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select.js";
|
|
11
|
+
import { Spinner } from "./spinner.js";
|
|
12
|
+
const DEFAULT_LABELS = {
|
|
13
|
+
title: "Invite member",
|
|
14
|
+
description: "Send an invitation to join this workspace.",
|
|
15
|
+
email: "Email",
|
|
16
|
+
emailPlaceholder: "name@example.com",
|
|
17
|
+
role: "Role",
|
|
18
|
+
send: "Send invite",
|
|
19
|
+
cancel: "Cancel",
|
|
20
|
+
sending: "Sending",
|
|
21
|
+
errorFallback: "Something went wrong. Please try again.",
|
|
22
|
+
};
|
|
23
|
+
const DEFAULT_ROLES = [
|
|
24
|
+
{ value: "member", label: "Member" },
|
|
25
|
+
{ value: "admin", label: "Admin" },
|
|
26
|
+
];
|
|
27
|
+
function resolveErrorMessage(error, fallback) {
|
|
28
|
+
if (error instanceof Error && error.message) {
|
|
29
|
+
return error.message;
|
|
30
|
+
}
|
|
31
|
+
if (typeof error === "string" && error) {
|
|
32
|
+
return error;
|
|
33
|
+
}
|
|
34
|
+
return fallback;
|
|
35
|
+
}
|
|
36
|
+
function resolveRoles(roles) {
|
|
37
|
+
return roles && roles.length > 0 ? roles : DEFAULT_ROLES;
|
|
38
|
+
}
|
|
39
|
+
function resolveDefaultRole(roles, defaultRole) {
|
|
40
|
+
if (defaultRole && roles.some((role) => role.value === defaultRole)) {
|
|
41
|
+
return defaultRole;
|
|
42
|
+
}
|
|
43
|
+
return roles[0]?.value ?? "";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* An ergonomic invite dialog for adding a member by email and role, composed
|
|
47
|
+
* on top of the accessible `Dialog` primitive (focus trap, overlay, Escape).
|
|
48
|
+
*
|
|
49
|
+
* Behavior: `onInvite` may be async — while its promise is pending the send
|
|
50
|
+
* button shows a `Spinner`, both actions are disabled, and the dialog cannot be
|
|
51
|
+
* dismissed so the operation can't be interrupted mid-flight. On resolve the
|
|
52
|
+
* dialog closes; on reject it stays open and renders the error in a
|
|
53
|
+
* `role="alert"` region. Works controlled (`open`/`onOpenChange`) or
|
|
54
|
+
* uncontrolled (`defaultOpen`).
|
|
55
|
+
*
|
|
56
|
+
* Performance/a11y: late promise settlements are ignored after unmount via a
|
|
57
|
+
* mounted ref. The spinner is decorative (`aria-hidden`) with loading state
|
|
58
|
+
* conveyed through `aria-busy`. All entrance/exit motion is owned by the
|
|
59
|
+
* underlying primitive and degrades under `prefers-reduced-motion`.
|
|
60
|
+
*/
|
|
61
|
+
export function InviteDialog({ trigger, open, defaultOpen, onOpenChange, roles, defaultRole, onInvite, labels, className, ref, ...contentProps }) {
|
|
62
|
+
const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
|
|
63
|
+
const resolvedRoles = resolveRoles(roles);
|
|
64
|
+
const initialRole = resolveDefaultRole(resolvedRoles, defaultRole);
|
|
65
|
+
const isControlled = open !== undefined;
|
|
66
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen ?? false);
|
|
67
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
68
|
+
const [email, setEmail] = useState("");
|
|
69
|
+
const [role, setRole] = useState(initialRole);
|
|
70
|
+
const [loading, setLoading] = useState(false);
|
|
71
|
+
const [error, setError] = useState(null);
|
|
72
|
+
const loadingRef = useRef(false);
|
|
73
|
+
const mountedRef = useRef(true);
|
|
74
|
+
const emailId = useId();
|
|
75
|
+
const roleId = useId();
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
mountedRef.current = true;
|
|
78
|
+
return () => {
|
|
79
|
+
mountedRef.current = false;
|
|
80
|
+
};
|
|
81
|
+
}, []);
|
|
82
|
+
const setOpen = useCallback((next) => {
|
|
83
|
+
if (!isControlled) {
|
|
84
|
+
setUncontrolledOpen(next);
|
|
85
|
+
}
|
|
86
|
+
onOpenChange?.(next);
|
|
87
|
+
}, [isControlled, onOpenChange]);
|
|
88
|
+
const handleOpenChange = useCallback((next) => {
|
|
89
|
+
if (loadingRef.current && !next) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (next) {
|
|
93
|
+
setError(null);
|
|
94
|
+
setEmail("");
|
|
95
|
+
setRole(initialRole);
|
|
96
|
+
}
|
|
97
|
+
setOpen(next);
|
|
98
|
+
}, [initialRole, setOpen]);
|
|
99
|
+
const beginLoading = useCallback((value) => {
|
|
100
|
+
loadingRef.current = value;
|
|
101
|
+
setLoading(value);
|
|
102
|
+
}, []);
|
|
103
|
+
const handleSubmit = useCallback(async (event) => {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
if (loadingRef.current) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const trimmed = email.trim();
|
|
109
|
+
if (!trimmed) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setError(null);
|
|
113
|
+
if (!onInvite) {
|
|
114
|
+
setOpen(false);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const result = onInvite({ email: trimmed, role });
|
|
118
|
+
if (!(result instanceof Promise)) {
|
|
119
|
+
setOpen(false);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
beginLoading(true);
|
|
123
|
+
try {
|
|
124
|
+
await result;
|
|
125
|
+
if (!mountedRef.current) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
beginLoading(false);
|
|
129
|
+
setOpen(false);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
if (!mountedRef.current) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
beginLoading(false);
|
|
136
|
+
setError(resolveErrorMessage(err, resolvedLabels.errorFallback));
|
|
137
|
+
}
|
|
138
|
+
}, [beginLoading, email, onInvite, resolvedLabels.errorFallback, role, setOpen]);
|
|
139
|
+
return (_jsxs(Dialog, { open: isOpen, onOpenChange: handleOpenChange, children: [trigger ? _jsx(DialogTrigger, { asChild: true, children: trigger }) : null, _jsxs(DialogContent, { ref: ref, "data-slot": "invite-dialog", className: cn("max-w-md", className), ...contentProps, children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: resolvedLabels.title }), resolvedLabels.description ? (_jsx(DialogDescription, { children: resolvedLabels.description })) : null] }), _jsxs("form", { className: "flex flex-col gap-4", onSubmit: handleSubmit, children: [_jsxs(Field, { children: [_jsx(FieldLabel, { htmlFor: emailId, children: resolvedLabels.email }), _jsx(Input, { id: emailId, type: "email", name: "email", autoComplete: "email", required: true, value: email, onChange: (event) => setEmail(event.target.value), placeholder: resolvedLabels.emailPlaceholder, disabled: loading })] }), _jsxs(Field, { children: [_jsx(FieldLabel, { htmlFor: roleId, children: resolvedLabels.role }), _jsxs(Select, { value: role, onValueChange: setRole, disabled: loading, children: [_jsx(SelectTrigger, { id: roleId, children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: resolvedRoles.map((item) => (_jsx(SelectItem, { value: item.value, children: item.label }, item.value))) })] })] }), error ? (_jsxs("div", { role: "alert", "data-slot": "invite-dialog-error", className: "flex items-start gap-2 rounded-lg border border-error/30 bg-error/10 px-3 py-2 text-start text-sm text-error-strong", children: [_jsx(CircleAlert, { "aria-hidden": true, className: "mt-0.5 size-4 shrink-0" }), _jsx("span", { children: error })] })) : null, _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", disabled: loading, onClick: () => handleOpenChange(false), children: resolvedLabels.cancel }), _jsxs(Button, { type: "submit", "data-slot": "invite-dialog-send", disabled: loading, "aria-busy": loading, className: "min-w-24", children: [loading ? _jsx(Spinner, { size: "sm", "aria-hidden": true }) : null, loading ? resolvedLabels.sending : resolvedLabels.send] })] })] })] })] }));
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=invite-dialog.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Ref } from "react";
|
|
2
|
+
export interface WorkspaceItem {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
initials?: string;
|
|
6
|
+
image?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkspaceSwitcherLabels {
|
|
9
|
+
/** Accessible name for the trigger. @default "Switch workspace" */
|
|
10
|
+
label?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface WorkspaceSwitcherProps {
|
|
13
|
+
workspaces: readonly WorkspaceItem[];
|
|
14
|
+
/** Controlled selected workspace id. Pair with `onValueChange`. */
|
|
15
|
+
value?: string;
|
|
16
|
+
/** Uncontrolled initial workspace id. Defaults to the first workspace. */
|
|
17
|
+
defaultValue?: string;
|
|
18
|
+
/** Called with the selected workspace id. */
|
|
19
|
+
onValueChange?: (id: string) => void;
|
|
20
|
+
/** Override any subset of the built-in English strings. */
|
|
21
|
+
labels?: WorkspaceSwitcherLabels;
|
|
22
|
+
className?: string;
|
|
23
|
+
/** Forwarded to the trigger button. */
|
|
24
|
+
ref?: Ref<HTMLButtonElement>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Compact workspace/org switcher for app chrome. The trigger shows the current
|
|
28
|
+
* workspace avatar, name, and a chevron; the menu lists every workspace with
|
|
29
|
+
* the selected row marked as a radio item (`menuitemradio`).
|
|
30
|
+
*
|
|
31
|
+
* Controlled via `value`/`onValueChange` or uncontrolled via `defaultValue`.
|
|
32
|
+
* Renders nothing when `workspaces` is empty. Keyboard access is owned by the
|
|
33
|
+
* underlying (non-modal) dropdown menu.
|
|
34
|
+
*/
|
|
35
|
+
export declare function WorkspaceSwitcher({ workspaces, value, defaultValue, onValueChange, labels, className, ref, }: WorkspaceSwitcherProps): import("react").JSX.Element | null;
|
|
36
|
+
//# sourceMappingURL=workspace-switcher.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronsUpDown } from "lucide-react";
|
|
4
|
+
import { useCallback, useState } from "react";
|
|
5
|
+
import { cn } from "../lib/cn.js";
|
|
6
|
+
import { Avatar, AvatarFallback, AvatarImage } from "./avatar.js";
|
|
7
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuTrigger, } from "./dropdown-menu.js";
|
|
8
|
+
const DEFAULT_LABELS = {
|
|
9
|
+
label: "Switch workspace",
|
|
10
|
+
};
|
|
11
|
+
function workspaceInitials(workspace) {
|
|
12
|
+
if (workspace.initials) {
|
|
13
|
+
return workspace.initials;
|
|
14
|
+
}
|
|
15
|
+
const parts = workspace.name.trim().split(/\s+/).filter(Boolean);
|
|
16
|
+
if (parts.length >= 2) {
|
|
17
|
+
const first = parts[0]?.[0] ?? "";
|
|
18
|
+
const second = parts[1]?.[0] ?? "";
|
|
19
|
+
return `${first}${second}`.toUpperCase();
|
|
20
|
+
}
|
|
21
|
+
return workspace.name.slice(0, 2).toUpperCase();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Compact workspace/org switcher for app chrome. The trigger shows the current
|
|
25
|
+
* workspace avatar, name, and a chevron; the menu lists every workspace with
|
|
26
|
+
* the selected row marked as a radio item (`menuitemradio`).
|
|
27
|
+
*
|
|
28
|
+
* Controlled via `value`/`onValueChange` or uncontrolled via `defaultValue`.
|
|
29
|
+
* Renders nothing when `workspaces` is empty. Keyboard access is owned by the
|
|
30
|
+
* underlying (non-modal) dropdown menu.
|
|
31
|
+
*/
|
|
32
|
+
export function WorkspaceSwitcher({ workspaces, value, defaultValue, onValueChange, labels, className, ref, }) {
|
|
33
|
+
const resolvedLabels = { ...DEFAULT_LABELS, ...labels };
|
|
34
|
+
const isControlled = value !== undefined;
|
|
35
|
+
const [uncontrolled, setUncontrolled] = useState(() => defaultValue ?? workspaces[0]?.id ?? "");
|
|
36
|
+
const selectedId = isControlled ? value : uncontrolled;
|
|
37
|
+
const handleChange = useCallback((id) => {
|
|
38
|
+
if (!isControlled) {
|
|
39
|
+
setUncontrolled(id);
|
|
40
|
+
}
|
|
41
|
+
onValueChange?.(id);
|
|
42
|
+
}, [isControlled, onValueChange]);
|
|
43
|
+
if (workspaces.length === 0) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const current = workspaces.find((workspace) => workspace.id === selectedId) ?? workspaces[0];
|
|
47
|
+
if (!current) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const triggerLabel = `${resolvedLabels.label}, ${current.name}`;
|
|
51
|
+
return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs("button", { ref: ref, type: "button", "data-slot": "workspace-switcher", "aria-label": triggerLabel, className: cn("flex w-full min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-sm text-fg outline-none hover:bg-surface-overlay focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-surface-base disabled:pointer-events-none disabled:opacity-50", className), children: [_jsx(WorkspaceAvatar, { workspace: current }), _jsx("span", { className: "min-w-0 flex-1 truncate text-start font-medium", children: current.name }), _jsx(ChevronsUpDown, { className: "size-4 shrink-0 text-fg-tertiary", "aria-hidden": true })] }) }), _jsx(DropdownMenuContent, { "data-slot": "workspace-switcher-content", align: "start", className: "min-w-56", children: _jsx(DropdownMenuRadioGroup, { value: current.id, onValueChange: handleChange, children: workspaces.map((workspace) => (_jsxs(DropdownMenuRadioItem, { value: workspace.id, className: "gap-2", children: [_jsx(WorkspaceAvatar, { workspace: workspace }), _jsx("span", { className: "min-w-0 flex-1 truncate text-start", children: workspace.name })] }, workspace.id))) }) })] }));
|
|
52
|
+
}
|
|
53
|
+
function WorkspaceAvatar({ workspace }) {
|
|
54
|
+
return (_jsxs(Avatar, { className: "size-6", children: [workspace.image ? _jsx(AvatarImage, { src: workspace.image, alt: "" }) : null, _jsx(AvatarFallback, { className: "text-xs", children: workspaceInitials(workspace) })] }));
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=workspace-switcher.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -142,6 +142,8 @@ export { Input } from "./components/input.js";
|
|
|
142
142
|
export type { InputGroupAddonProps, InputGroupProps } from "./components/input-group.js";
|
|
143
143
|
export { InputGroup, InputGroupAddon } from "./components/input-group.js";
|
|
144
144
|
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, } from "./components/input-otp.js";
|
|
145
|
+
export type { InviteDialogLabels, InviteDialogProps, InviteRole, } from "./components/invite-dialog.js";
|
|
146
|
+
export { InviteDialog } from "./components/invite-dialog.js";
|
|
145
147
|
export type { JsonViewerProps } from "./components/json-viewer.js";
|
|
146
148
|
export { JsonViewer } from "./components/json-viewer.js";
|
|
147
149
|
export type { KanbanColumn, KanbanItem, KanbanProps } from "./components/kanban.js";
|
|
@@ -302,5 +304,7 @@ export type { VideoPlayerLabels, VideoPlayerProps } from "./components/video-pla
|
|
|
302
304
|
export { VideoPlayer, videoPlayerVariants } from "./components/video-player.js";
|
|
303
305
|
export type { WordRotateProps } from "./components/word-rotate.js";
|
|
304
306
|
export { WordRotate } from "./components/word-rotate.js";
|
|
307
|
+
export type { WorkspaceItem, WorkspaceSwitcherLabels, WorkspaceSwitcherProps, } from "./components/workspace-switcher.js";
|
|
308
|
+
export { WorkspaceSwitcher } from "./components/workspace-switcher.js";
|
|
305
309
|
export { cn } from "./lib/cn.js";
|
|
306
310
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -85,6 +85,7 @@ export { ImageZoom, imageZoomVariants } from "./components/image-zoom.js";
|
|
|
85
85
|
export { Input } from "./components/input.js";
|
|
86
86
|
export { InputGroup, InputGroupAddon } from "./components/input-group.js";
|
|
87
87
|
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, } from "./components/input-otp.js";
|
|
88
|
+
export { InviteDialog } from "./components/invite-dialog.js";
|
|
88
89
|
export { JsonViewer } from "./components/json-viewer.js";
|
|
89
90
|
export { Kanban } from "./components/kanban.js";
|
|
90
91
|
export { Kbd } from "./components/kbd.js";
|
|
@@ -175,5 +176,6 @@ export { TypingText } from "./components/typing-text.js";
|
|
|
175
176
|
export { UsageMeter, UsageMeterCircular, UsageMeterLinear } from "./components/usage-meter.js";
|
|
176
177
|
export { VideoPlayer, videoPlayerVariants } from "./components/video-player.js";
|
|
177
178
|
export { WordRotate } from "./components/word-rotate.js";
|
|
179
|
+
export { WorkspaceSwitcher } from "./components/workspace-switcher.js";
|
|
178
180
|
export { cn } from "./lib/cn.js";
|
|
179
181
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cronus-ui/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Cronus UI — themeable, accessible React components (Radix + CVA + Tailwind v4).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -316,6 +316,10 @@
|
|
|
316
316
|
"types": "./dist/components/input-otp.d.ts",
|
|
317
317
|
"import": "./dist/components/input-otp.js"
|
|
318
318
|
},
|
|
319
|
+
"./invite-dialog": {
|
|
320
|
+
"types": "./dist/components/invite-dialog.d.ts",
|
|
321
|
+
"import": "./dist/components/invite-dialog.js"
|
|
322
|
+
},
|
|
319
323
|
"./json-viewer": {
|
|
320
324
|
"types": "./dist/components/json-viewer.d.ts",
|
|
321
325
|
"import": "./dist/components/json-viewer.js"
|
|
@@ -668,6 +672,10 @@
|
|
|
668
672
|
"types": "./dist/components/word-rotate.d.ts",
|
|
669
673
|
"import": "./dist/components/word-rotate.js"
|
|
670
674
|
},
|
|
675
|
+
"./workspace-switcher": {
|
|
676
|
+
"types": "./dist/components/workspace-switcher.d.ts",
|
|
677
|
+
"import": "./dist/components/workspace-switcher.js"
|
|
678
|
+
},
|
|
671
679
|
"./package.json": "./package.json"
|
|
672
680
|
},
|
|
673
681
|
"main": "./dist/index.js",
|
|
@@ -747,7 +755,7 @@
|
|
|
747
755
|
"vaul": "^1.1.2"
|
|
748
756
|
},
|
|
749
757
|
"peerDependencies": {
|
|
750
|
-
"@cronus-ui/theme": "0.6.
|
|
758
|
+
"@cronus-ui/theme": "0.6.1",
|
|
751
759
|
"@dnd-kit/core": "^6.3.1",
|
|
752
760
|
"@dnd-kit/sortable": "^10.0.0",
|
|
753
761
|
"@dnd-kit/utilities": "^3.2.2",
|
|
@@ -891,7 +899,7 @@
|
|
|
891
899
|
}
|
|
892
900
|
},
|
|
893
901
|
"devDependencies": {
|
|
894
|
-
"@cronus-ui/theme": "0.6.
|
|
902
|
+
"@cronus-ui/theme": "0.6.1",
|
|
895
903
|
"@dnd-kit/core": "^6.3.1",
|
|
896
904
|
"@dnd-kit/sortable": "^10.0.0",
|
|
897
905
|
"@dnd-kit/utilities": "^3.2.2",
|