@cronus-ui/ui 0.6.0 → 0.6.2

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
@@ -0,0 +1,26 @@
1
+ /**
2
+ * DEMO auth adapter. Gold-path apps replace `lib/auth-adapter.ts` with a
3
+ * Better-Auth implementation that keeps the same named exports
4
+ * (`signInEmail`, `signUpEmail`, `requestPasswordReset`).
5
+ *
6
+ * PURE TS (zero React / hooks / DOM). Gallery and store demos fake success
7
+ * after client-side validation — no network.
8
+ */
9
+ /** Email + password used by sign-in (and as the base of sign-up). */
10
+ export interface AuthCredentials {
11
+ email: string;
12
+ password: string;
13
+ }
14
+ /** Sign-up payload — same credentials, optional display name. */
15
+ export interface SignUpInput extends AuthCredentials {
16
+ name?: string;
17
+ }
18
+ /** Demo sign-in: validate, wait briefly, resolve. No network. */
19
+ export declare function signInEmail(input: AuthCredentials): Promise<void>;
20
+ /** Demo sign-up: validate, wait briefly, resolve. No network. */
21
+ export declare function signUpEmail(input: SignUpInput): Promise<void>;
22
+ /** Demo password-reset request: validate email, wait briefly, resolve. No network. */
23
+ export declare function requestPasswordReset(input: {
24
+ email: string;
25
+ }): Promise<void>;
26
+ //# sourceMappingURL=auth-adapter.d.ts.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * DEMO auth adapter. Gold-path apps replace `lib/auth-adapter.ts` with a
3
+ * Better-Auth implementation that keeps the same named exports
4
+ * (`signInEmail`, `signUpEmail`, `requestPasswordReset`).
5
+ *
6
+ * PURE TS (zero React / hooks / DOM). Gallery and store demos fake success
7
+ * after client-side validation — no network.
8
+ */
9
+ const DEMO_LATENCY_MS = 200;
10
+ function wait(ms) {
11
+ return new Promise((resolve) => {
12
+ setTimeout(resolve, ms);
13
+ });
14
+ }
15
+ function requireEmail(email) {
16
+ const trimmed = email.trim();
17
+ if (!trimmed) {
18
+ throw new Error("Email is required.");
19
+ }
20
+ if (!trimmed.includes("@")) {
21
+ throw new Error("Enter a valid email address.");
22
+ }
23
+ }
24
+ function requirePassword(password) {
25
+ if (password.length < 8) {
26
+ throw new Error("Password must be at least 8 characters.");
27
+ }
28
+ }
29
+ /** Demo sign-in: validate, wait briefly, resolve. No network. */
30
+ export async function signInEmail(input) {
31
+ requireEmail(input.email);
32
+ requirePassword(input.password);
33
+ await wait(DEMO_LATENCY_MS);
34
+ }
35
+ /** Demo sign-up: validate, wait briefly, resolve. No network. */
36
+ export async function signUpEmail(input) {
37
+ requireEmail(input.email);
38
+ requirePassword(input.password);
39
+ await wait(DEMO_LATENCY_MS);
40
+ }
41
+ /** Demo password-reset request: validate email, wait briefly, resolve. No network. */
42
+ export async function requestPasswordReset(input) {
43
+ requireEmail(input.email);
44
+ await wait(DEMO_LATENCY_MS);
45
+ }
46
+ //# sourceMappingURL=auth-adapter.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cronus-ui/ui",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Cronus UI — themeable, accessible React components (Radix + CVA + Tailwind v4).",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,6 +20,10 @@
20
20
  "types": "./dist/lib/demo-saas.d.ts",
21
21
  "import": "./dist/lib/demo-saas.js"
22
22
  },
23
+ "./auth-adapter": {
24
+ "types": "./dist/lib/auth-adapter.d.ts",
25
+ "import": "./dist/lib/auth-adapter.js"
26
+ },
23
27
  "./testing": {
24
28
  "types": "./dist/testing/index.d.ts",
25
29
  "import": "./dist/testing/index.js"
@@ -316,6 +320,10 @@
316
320
  "types": "./dist/components/input-otp.d.ts",
317
321
  "import": "./dist/components/input-otp.js"
318
322
  },
323
+ "./invite-dialog": {
324
+ "types": "./dist/components/invite-dialog.d.ts",
325
+ "import": "./dist/components/invite-dialog.js"
326
+ },
319
327
  "./json-viewer": {
320
328
  "types": "./dist/components/json-viewer.d.ts",
321
329
  "import": "./dist/components/json-viewer.js"
@@ -668,6 +676,10 @@
668
676
  "types": "./dist/components/word-rotate.d.ts",
669
677
  "import": "./dist/components/word-rotate.js"
670
678
  },
679
+ "./workspace-switcher": {
680
+ "types": "./dist/components/workspace-switcher.d.ts",
681
+ "import": "./dist/components/workspace-switcher.js"
682
+ },
671
683
  "./package.json": "./package.json"
672
684
  },
673
685
  "main": "./dist/index.js",
@@ -747,7 +759,7 @@
747
759
  "vaul": "^1.1.2"
748
760
  },
749
761
  "peerDependencies": {
750
- "@cronus-ui/theme": "0.6.0",
762
+ "@cronus-ui/theme": "0.6.2",
751
763
  "@dnd-kit/core": "^6.3.1",
752
764
  "@dnd-kit/sortable": "^10.0.0",
753
765
  "@dnd-kit/utilities": "^3.2.2",
@@ -891,7 +903,7 @@
891
903
  }
892
904
  },
893
905
  "devDependencies": {
894
- "@cronus-ui/theme": "0.6.0",
906
+ "@cronus-ui/theme": "0.6.2",
895
907
  "@dnd-kit/core": "^6.3.1",
896
908
  "@dnd-kit/sortable": "^10.0.0",
897
909
  "@dnd-kit/utilities": "^3.2.2",