@zentauri-ui/zentauri-components 1.7.1 → 1.7.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/README.md +9 -5
- package/cli/registry.json +2 -0
- package/dist/chunk-BC6M42HQ.mjs +251 -0
- package/dist/chunk-BC6M42HQ.mjs.map +1 -0
- package/dist/chunk-KEKMMNL5.mjs +600 -0
- package/dist/chunk-KEKMMNL5.mjs.map +1 -0
- package/dist/chunk-NZDHSIIC.js +616 -0
- package/dist/chunk-NZDHSIIC.js.map +1 -0
- package/dist/chunk-QSPXPU72.js +259 -0
- package/dist/chunk-QSPXPU72.js.map +1 -0
- package/dist/design-system/command.d.ts +41 -0
- package/dist/design-system/command.d.ts.map +1 -0
- package/dist/design-system/index.d.ts +2 -0
- package/dist/design-system/index.d.ts.map +1 -1
- package/dist/design-system/popover.d.ts +40 -0
- package/dist/design-system/popover.d.ts.map +1 -0
- package/dist/ui/command/animated/animations.d.ts +3 -0
- package/dist/ui/command/animated/animations.d.ts.map +1 -0
- package/dist/ui/command/animated/command-content-animated.d.ts +6 -0
- package/dist/ui/command/animated/command-content-animated.d.ts.map +1 -0
- package/dist/ui/command/animated/index.d.ts +4 -0
- package/dist/ui/command/animated/index.d.ts.map +1 -0
- package/dist/ui/command/animated/types.d.ts +9 -0
- package/dist/ui/command/animated/types.d.ts.map +1 -0
- package/dist/ui/command/animated.js +92 -0
- package/dist/ui/command/animated.js.map +1 -0
- package/dist/ui/command/animated.mjs +89 -0
- package/dist/ui/command/animated.mjs.map +1 -0
- package/dist/ui/command/command-base.d.ts +53 -0
- package/dist/ui/command/command-base.d.ts.map +1 -0
- package/dist/ui/command/command.d.ts +6 -0
- package/dist/ui/command/command.d.ts.map +1 -0
- package/dist/ui/command/index.d.ts +5 -0
- package/dist/ui/command/index.d.ts.map +1 -0
- package/dist/ui/command/types.d.ts +111 -0
- package/dist/ui/command/types.d.ts.map +1 -0
- package/dist/ui/command/variants.d.ts +15 -0
- package/dist/ui/command/variants.d.ts.map +1 -0
- package/dist/ui/command.js +69 -0
- package/dist/ui/command.js.map +1 -0
- package/dist/ui/command.mjs +16 -0
- package/dist/ui/command.mjs.map +1 -0
- package/dist/ui/popover/animated/animations.d.ts +3 -0
- package/dist/ui/popover/animated/animations.d.ts.map +1 -0
- package/dist/ui/popover/animated/index.d.ts +4 -0
- package/dist/ui/popover/animated/index.d.ts.map +1 -0
- package/dist/ui/popover/animated/popover-content-animated.d.ts +3 -0
- package/dist/ui/popover/animated/popover-content-animated.d.ts.map +1 -0
- package/dist/ui/popover/animated/types.d.ts +9 -0
- package/dist/ui/popover/animated/types.d.ts.map +1 -0
- package/dist/ui/popover/animated.js +67 -0
- package/dist/ui/popover/animated.js.map +1 -0
- package/dist/ui/popover/animated.mjs +64 -0
- package/dist/ui/popover/animated.mjs.map +1 -0
- package/dist/ui/popover/index.d.ts +4 -0
- package/dist/ui/popover/index.d.ts.map +1 -0
- package/dist/ui/popover/popover-base.d.ts +8 -0
- package/dist/ui/popover/popover-base.d.ts.map +1 -0
- package/dist/ui/popover/popover.d.ts +2 -0
- package/dist/ui/popover/popover.d.ts.map +1 -0
- package/dist/ui/popover/types.d.ts +34 -0
- package/dist/ui/popover/types.d.ts.map +1 -0
- package/dist/ui/popover/variants.d.ts +6 -0
- package/dist/ui/popover/variants.d.ts.map +1 -0
- package/dist/ui/popover.js +34 -0
- package/dist/ui/popover.js.map +1 -0
- package/dist/ui/popover.mjs +5 -0
- package/dist/ui/popover.mjs.map +1 -0
- package/package.json +1 -1
- package/src/design-system/command.ts +80 -0
- package/src/design-system/index.ts +2 -0
- package/src/design-system/popover.ts +66 -0
- package/src/ui/command/animated/animations.ts +29 -0
- package/src/ui/command/animated/command-content-animated.tsx +58 -0
- package/src/ui/command/animated/index.ts +10 -0
- package/src/ui/command/animated/types.ts +23 -0
- package/src/ui/command/command-base.tsx +660 -0
- package/src/ui/command/command.test.tsx +130 -0
- package/src/ui/command/command.tsx +8 -0
- package/src/ui/command/index.ts +34 -0
- package/src/ui/command/types.ts +129 -0
- package/src/ui/command/variants.ts +41 -0
- package/src/ui/popover/animated/animations.ts +15 -0
- package/src/ui/popover/animated/index.ts +10 -0
- package/src/ui/popover/animated/popover-content-animated.tsx +54 -0
- package/src/ui/popover/animated/types.ts +18 -0
- package/src/ui/popover/index.ts +18 -0
- package/src/ui/popover/popover-base.tsx +261 -0
- package/src/ui/popover/popover.test.tsx +84 -0
- package/src/ui/popover/popover.tsx +8 -0
- package/src/ui/popover/types.ts +38 -0
- package/src/ui/popover/variants.ts +21 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { render, screen, waitFor } from "@testing-library/react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { describe, expect, it, vi } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { Command } from "./command";
|
|
6
|
+
import {
|
|
7
|
+
CommandContent,
|
|
8
|
+
CommandEmpty,
|
|
9
|
+
CommandGroup,
|
|
10
|
+
CommandInput,
|
|
11
|
+
CommandItem,
|
|
12
|
+
CommandList,
|
|
13
|
+
CommandSeparator,
|
|
14
|
+
CommandTrigger,
|
|
15
|
+
} from "./command-base";
|
|
16
|
+
|
|
17
|
+
function Palette({
|
|
18
|
+
open,
|
|
19
|
+
onOpenChange,
|
|
20
|
+
onSelectHome,
|
|
21
|
+
}: {
|
|
22
|
+
open?: boolean;
|
|
23
|
+
onOpenChange?: (next: boolean) => void;
|
|
24
|
+
onSelectHome?: (value: string) => void;
|
|
25
|
+
} = {}) {
|
|
26
|
+
return (
|
|
27
|
+
<Command open={open} onOpenChange={onOpenChange}>
|
|
28
|
+
<CommandTrigger>Open palette</CommandTrigger>
|
|
29
|
+
<CommandContent>
|
|
30
|
+
<CommandInput placeholder="Search…" />
|
|
31
|
+
<CommandList>
|
|
32
|
+
<CommandEmpty>No results found.</CommandEmpty>
|
|
33
|
+
<CommandGroup heading="Navigation">
|
|
34
|
+
<CommandItem value="home" onSelect={onSelectHome}>
|
|
35
|
+
Home
|
|
36
|
+
</CommandItem>
|
|
37
|
+
<CommandItem value="settings">Settings</CommandItem>
|
|
38
|
+
</CommandGroup>
|
|
39
|
+
<CommandSeparator />
|
|
40
|
+
<CommandGroup heading="Actions">
|
|
41
|
+
<CommandItem value="new-project">Create project</CommandItem>
|
|
42
|
+
</CommandGroup>
|
|
43
|
+
</CommandList>
|
|
44
|
+
</CommandContent>
|
|
45
|
+
</Command>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe("Command", () => {
|
|
50
|
+
it("should open from the trigger and render a dialog", async () => {
|
|
51
|
+
const user = userEvent.setup();
|
|
52
|
+
render(<Palette />);
|
|
53
|
+
await user.click(screen.getByRole("button", { name: "Open palette" }));
|
|
54
|
+
await waitFor(() =>
|
|
55
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
56
|
+
);
|
|
57
|
+
expect(screen.getByText("Home")).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("should respect controlled open state", async () => {
|
|
61
|
+
const { rerender } = render(<Palette open={false} />);
|
|
62
|
+
expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
|
|
63
|
+
rerender(<Palette open />);
|
|
64
|
+
await waitFor(() =>
|
|
65
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should filter items as the user types", async () => {
|
|
70
|
+
const user = userEvent.setup();
|
|
71
|
+
render(<Palette open />);
|
|
72
|
+
await waitFor(() =>
|
|
73
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
74
|
+
);
|
|
75
|
+
await user.type(screen.getByRole("combobox"), "settings");
|
|
76
|
+
await waitFor(() => {
|
|
77
|
+
expect(screen.getByText("Settings")).toBeVisible();
|
|
78
|
+
expect(screen.getByText("Home").closest("[data-slot=command-item]")).toHaveAttribute(
|
|
79
|
+
"hidden",
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("should show the empty state when nothing matches", async () => {
|
|
85
|
+
const user = userEvent.setup();
|
|
86
|
+
render(<Palette open />);
|
|
87
|
+
await user.type(screen.getByRole("combobox"), "zzzzzz");
|
|
88
|
+
await waitFor(() =>
|
|
89
|
+
expect(screen.getByText("No results found.")).toBeInTheDocument(),
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should select the active item with arrow keys and Enter", async () => {
|
|
94
|
+
const user = userEvent.setup();
|
|
95
|
+
const onSelectHome = vi.fn();
|
|
96
|
+
render(<Palette open onSelectHome={onSelectHome} />);
|
|
97
|
+
await waitFor(() =>
|
|
98
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
99
|
+
);
|
|
100
|
+
const input = screen.getByRole("combobox");
|
|
101
|
+
input.focus();
|
|
102
|
+
await user.keyboard("{Enter}");
|
|
103
|
+
expect(onSelectHome).toHaveBeenCalledWith("home");
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("should close when Escape is pressed", async () => {
|
|
107
|
+
const user = userEvent.setup();
|
|
108
|
+
const onOpenChange = vi.fn();
|
|
109
|
+
render(<Palette open onOpenChange={onOpenChange} />);
|
|
110
|
+
await waitFor(() =>
|
|
111
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
112
|
+
);
|
|
113
|
+
await user.keyboard("{Escape}");
|
|
114
|
+
await waitFor(() =>
|
|
115
|
+
expect(onOpenChange).toHaveBeenLastCalledWith(false),
|
|
116
|
+
);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should render group headings and a separator", async () => {
|
|
120
|
+
render(<Palette open />);
|
|
121
|
+
await waitFor(() =>
|
|
122
|
+
expect(screen.getByRole("dialog")).toBeInTheDocument(),
|
|
123
|
+
);
|
|
124
|
+
expect(screen.getByText("Navigation")).toBeInTheDocument();
|
|
125
|
+
expect(screen.getByText("Actions")).toBeInTheDocument();
|
|
126
|
+
expect(
|
|
127
|
+
document.querySelector('[data-slot="command-separator"]'),
|
|
128
|
+
).toBeTruthy();
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export { Command } from "./command";
|
|
4
|
+
export {
|
|
5
|
+
CommandTrigger,
|
|
6
|
+
CommandContent,
|
|
7
|
+
CommandInput,
|
|
8
|
+
CommandList,
|
|
9
|
+
CommandGroup,
|
|
10
|
+
CommandItem,
|
|
11
|
+
CommandSeparator,
|
|
12
|
+
CommandEmpty,
|
|
13
|
+
CommandFooter,
|
|
14
|
+
useCommandContext,
|
|
15
|
+
} from "./command-base";
|
|
16
|
+
export type {
|
|
17
|
+
CommandProps,
|
|
18
|
+
CommandTriggerProps,
|
|
19
|
+
CommandContentProps,
|
|
20
|
+
CommandContentVariantProps,
|
|
21
|
+
CommandInputProps,
|
|
22
|
+
CommandListProps,
|
|
23
|
+
CommandGroupProps,
|
|
24
|
+
CommandItemProps,
|
|
25
|
+
CommandSectionProps,
|
|
26
|
+
CommandCtx,
|
|
27
|
+
ItemMeta,
|
|
28
|
+
RegisteredItem
|
|
29
|
+
} from "./types";
|
|
30
|
+
export {
|
|
31
|
+
commandContentVariants,
|
|
32
|
+
commandOverlayVariants,
|
|
33
|
+
commandItemVariants,
|
|
34
|
+
} from "./variants";
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { VariantProps } from "class-variance-authority";
|
|
2
|
+
import type { CSSProperties, ReactNode, Ref, RefObject } from "react";
|
|
3
|
+
|
|
4
|
+
import type { commandContentVariants } from "./variants";
|
|
5
|
+
|
|
6
|
+
export type CommandContentVariantProps = VariantProps<
|
|
7
|
+
typeof commandContentVariants
|
|
8
|
+
>;
|
|
9
|
+
|
|
10
|
+
export type CommandProps = {
|
|
11
|
+
open?: boolean;
|
|
12
|
+
defaultOpen?: boolean;
|
|
13
|
+
onOpenChange?: (open: boolean) => void;
|
|
14
|
+
/**
|
|
15
|
+
* When set, binds a global shortcut that toggles the palette: this key plus
|
|
16
|
+
* meta (⌘) or ctrl. Defaults to "k" when `hotkey` is `true`.
|
|
17
|
+
*/
|
|
18
|
+
hotkey?: string | boolean;
|
|
19
|
+
/** Accessible label for the dialog. */
|
|
20
|
+
label?: string;
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type CommandTriggerProps = {
|
|
25
|
+
className?: string;
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
ref?: Ref<HTMLButtonElement>;
|
|
28
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type CommandContentProps = CommandContentVariantProps & {
|
|
32
|
+
className?: string;
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
ref?: Ref<HTMLDivElement>;
|
|
35
|
+
id?: string;
|
|
36
|
+
style?: CSSProperties;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type CommandInputProps = {
|
|
40
|
+
className?: string;
|
|
41
|
+
placeholder?: string;
|
|
42
|
+
ref?: Ref<HTMLInputElement>;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export type CommandListProps = {
|
|
46
|
+
className?: string;
|
|
47
|
+
children?: ReactNode;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type CommandGroupProps = {
|
|
51
|
+
className?: string;
|
|
52
|
+
heading?: ReactNode;
|
|
53
|
+
children?: ReactNode;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type CommandItemProps = {
|
|
57
|
+
className?: string;
|
|
58
|
+
/** Stable identifier used for filtering, keyboard nav, and onSelect. */
|
|
59
|
+
value: string;
|
|
60
|
+
/** Extra terms used by the filter in addition to the rendered text. */
|
|
61
|
+
keywords?: string[];
|
|
62
|
+
disabled?: boolean;
|
|
63
|
+
onSelect?: (value: string) => void;
|
|
64
|
+
children?: ReactNode;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type CommandSectionProps = {
|
|
68
|
+
className?: string;
|
|
69
|
+
children?: ReactNode;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type ItemMeta = {
|
|
73
|
+
keywords?: string[];
|
|
74
|
+
disabled?: boolean;
|
|
75
|
+
onSelect?: (value: string) => void;
|
|
76
|
+
searchText?: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type RegisteredItem = {
|
|
80
|
+
value: string;
|
|
81
|
+
metaRef: RefObject<ItemMeta>;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export type CommandCtx = {
|
|
85
|
+
open: boolean;
|
|
86
|
+
setOpen: (next: boolean) => void;
|
|
87
|
+
labelId: string;
|
|
88
|
+
listId: string;
|
|
89
|
+
query: string;
|
|
90
|
+
setQuery: (next: string) => void;
|
|
91
|
+
activeValue: string | null;
|
|
92
|
+
setActiveValue: (next: string | null) => void;
|
|
93
|
+
visibleValues: string[];
|
|
94
|
+
isVisible: (value: string) => boolean;
|
|
95
|
+
registerItem: (item: RegisteredItem) => () => void;
|
|
96
|
+
invalidateRegistry: () => void;
|
|
97
|
+
selectValue: (value: string) => boolean;
|
|
98
|
+
contentRef: RefObject<HTMLDivElement | null>;
|
|
99
|
+
triggerRef: RefObject<HTMLElement | null>;
|
|
100
|
+
inputRef: RefObject<HTMLInputElement | null>;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
export type CommandContentOverlayRenderProps = {
|
|
105
|
+
role: "presentation";
|
|
106
|
+
"data-slot": "command-overlay";
|
|
107
|
+
className: string;
|
|
108
|
+
onClick: () => void;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export type CommandContentPanelRenderProps = {
|
|
112
|
+
ref: (node: HTMLDivElement | null) => void;
|
|
113
|
+
role: "dialog";
|
|
114
|
+
"aria-modal": true;
|
|
115
|
+
"aria-labelledby": string;
|
|
116
|
+
"data-slot": "command-content";
|
|
117
|
+
tabIndex: -1;
|
|
118
|
+
className: string;
|
|
119
|
+
id?: string;
|
|
120
|
+
style?: CommandContentProps["style"];
|
|
121
|
+
children: ReactNode;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export type CommandContentLayerProps = CommandContentProps & {
|
|
125
|
+
componentName: string;
|
|
126
|
+
renderPresence?: (children: ReactNode) => ReactNode;
|
|
127
|
+
renderOverlay?: (props: CommandContentOverlayRenderProps) => ReactNode;
|
|
128
|
+
renderPanel?: (props: CommandContentPanelRenderProps) => ReactNode;
|
|
129
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
zuiCommandContentAppearances,
|
|
5
|
+
zuiCommandContentBase,
|
|
6
|
+
zuiCommandContentSizes,
|
|
7
|
+
zuiCommandEmptyBase,
|
|
8
|
+
zuiCommandFooterBase,
|
|
9
|
+
zuiCommandGroupHeadingBase,
|
|
10
|
+
zuiCommandInputBase,
|
|
11
|
+
zuiCommandInputRowBase,
|
|
12
|
+
zuiCommandItemBase,
|
|
13
|
+
zuiCommandListBase,
|
|
14
|
+
zuiCommandOverlayBase,
|
|
15
|
+
zuiCommandSeparatorBase,
|
|
16
|
+
zuiCommandTriggerBase,
|
|
17
|
+
} from "../../design-system/command";
|
|
18
|
+
|
|
19
|
+
export const commandOverlayVariants = cva(zuiCommandOverlayBase);
|
|
20
|
+
|
|
21
|
+
export const commandTriggerVariants = cva(zuiCommandTriggerBase);
|
|
22
|
+
|
|
23
|
+
export const commandContentVariants = cva(zuiCommandContentBase, {
|
|
24
|
+
variants: {
|
|
25
|
+
size: zuiCommandContentSizes,
|
|
26
|
+
appearance: zuiCommandContentAppearances,
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: {
|
|
29
|
+
size: "md",
|
|
30
|
+
appearance: "default",
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
export const commandInputRowVariants = cva(zuiCommandInputRowBase);
|
|
35
|
+
export const commandInputVariants = cva(zuiCommandInputBase);
|
|
36
|
+
export const commandListVariants = cva(zuiCommandListBase);
|
|
37
|
+
export const commandGroupHeadingVariants = cva(zuiCommandGroupHeadingBase);
|
|
38
|
+
export const commandItemVariants = cva(zuiCommandItemBase);
|
|
39
|
+
export const commandSeparatorVariants = cva(zuiCommandSeparatorBase);
|
|
40
|
+
export const commandEmptyVariants = cva(zuiCommandEmptyBase);
|
|
41
|
+
export const commandFooterVariants = cva(zuiCommandFooterBase);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PopoverAnimationPresets } from "./types";
|
|
2
|
+
|
|
3
|
+
export const popoverAnimationPresets: PopoverAnimationPresets = {
|
|
4
|
+
none: {},
|
|
5
|
+
fade: {
|
|
6
|
+
initial: { opacity: 0, y: -4 },
|
|
7
|
+
animate: { opacity: 1, y: 0 },
|
|
8
|
+
transition: { duration: 0.16, ease: "easeOut" },
|
|
9
|
+
},
|
|
10
|
+
scale: {
|
|
11
|
+
initial: { opacity: 0, scale: 0.96 },
|
|
12
|
+
animate: { opacity: 1, scale: 1 },
|
|
13
|
+
transition: { duration: 0.16, ease: "easeOut" },
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export { PopoverContentAnimated } from "./popover-content-animated";
|
|
4
|
+
export { popoverAnimationPresets } from "./animations";
|
|
5
|
+
export type {
|
|
6
|
+
PopoverAnimation,
|
|
7
|
+
PopoverAnimationPresets,
|
|
8
|
+
PopoverContentAnimatedProps,
|
|
9
|
+
PopoverPresetMotionProps,
|
|
10
|
+
} from "./types";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../../lib/utils";
|
|
6
|
+
|
|
7
|
+
import { popoverAnimationPresets } from "./animations";
|
|
8
|
+
import type { PopoverContentAnimatedProps } from "./types";
|
|
9
|
+
import { sideAlignClass, usePopover } from "../popover-base";
|
|
10
|
+
import { popoverContentVariants } from "../variants";
|
|
11
|
+
|
|
12
|
+
export const PopoverContentAnimated = ({
|
|
13
|
+
children,
|
|
14
|
+
className,
|
|
15
|
+
variant,
|
|
16
|
+
size,
|
|
17
|
+
width,
|
|
18
|
+
side = "bottom",
|
|
19
|
+
align = "center",
|
|
20
|
+
role = "dialog",
|
|
21
|
+
animation = "none",
|
|
22
|
+
onDrag: _onDrag,
|
|
23
|
+
onDragStart: _onDragStart,
|
|
24
|
+
onDragEnd: _onDragEnd,
|
|
25
|
+
onAnimationStart: _onAnimationStart,
|
|
26
|
+
...props
|
|
27
|
+
}: PopoverContentAnimatedProps) => {
|
|
28
|
+
const { open, contentId, contentRef } = usePopover();
|
|
29
|
+
|
|
30
|
+
if (!open) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const motionProps = popoverAnimationPresets[animation];
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<motion.div
|
|
38
|
+
ref={contentRef}
|
|
39
|
+
id={contentId}
|
|
40
|
+
data-open={open}
|
|
41
|
+
role={role}
|
|
42
|
+
tabIndex={-1}
|
|
43
|
+
{...motionProps}
|
|
44
|
+
className={cn(
|
|
45
|
+
popoverContentVariants({ variant, size, width }),
|
|
46
|
+
sideAlignClass(side, align),
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
{...props}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
</motion.div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HTMLMotionProps } from "framer-motion";
|
|
2
|
+
import type { PopoverContentProps } from "../types";
|
|
3
|
+
|
|
4
|
+
export type PopoverAnimation = "none" | "fade" | "scale";
|
|
5
|
+
|
|
6
|
+
export type PopoverPresetMotionProps = Pick<
|
|
7
|
+
HTMLMotionProps<"div">,
|
|
8
|
+
"initial" | "animate" | "style" | "transition"
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
export type PopoverAnimationPresets = Record<
|
|
12
|
+
PopoverAnimation,
|
|
13
|
+
PopoverPresetMotionProps
|
|
14
|
+
>;
|
|
15
|
+
|
|
16
|
+
export type PopoverContentAnimatedProps = PopoverContentProps & {
|
|
17
|
+
animation?: PopoverAnimation;
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export {
|
|
4
|
+
Popover,
|
|
5
|
+
PopoverTrigger,
|
|
6
|
+
PopoverContent,
|
|
7
|
+
PopoverContext,
|
|
8
|
+
usePopover,
|
|
9
|
+
} from "./popover";
|
|
10
|
+
export { popoverContentVariants } from "./variants";
|
|
11
|
+
export type {
|
|
12
|
+
PopoverAlign,
|
|
13
|
+
PopoverContentProps,
|
|
14
|
+
PopoverContextType,
|
|
15
|
+
PopoverProps,
|
|
16
|
+
PopoverSide,
|
|
17
|
+
PopoverTriggerProps,
|
|
18
|
+
} from "./types";
|