@edux-design/popovers 1.0.6 → 1.1.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.
@@ -1,156 +0,0 @@
1
- import React, { forwardRef } from "react";
2
- import * as PopoverPrimitive from "@radix-ui/react-popover";
3
- import { cx } from "@edux-design/utils";
4
-
5
- const POPOVER_Z_INDEX = 2147483646;
6
-
7
- /**
8
- * Root Popover component.
9
- *
10
- * Wraps a `PopoverTrigger` (or `Popover.Anchor + Trigger`) and a `PopoverContent`.
11
- * Supports both controlled and uncontrolled modes.
12
- *
13
- * @component
14
- * @param {Object} props
15
- * @param {boolean} [props.defaultOpen] – whether popover is open by default (uncontrolled mode)
16
- * @param {boolean} [props.open] – controlled open state
17
- * @param {(open: boolean) => void} [props.onOpenChange] – change handler for controlled mode
18
- * @param {boolean} [props.modal=false] – whether to render modal behavior (blocking outside interactions) :contentReference[oaicite:1]{index=1}
19
- * @param {React.ReactNode} props.children
20
- * @returns JSX.Element
21
- */
22
- export const Popover = PopoverPrimitive.Root;
23
-
24
- /**
25
- * PopoverTrigger
26
- *
27
- * The interactive element that toggles opening/closing the popover.
28
- *
29
- * @component
30
- * @param {React.ComponentProps<typeof PopoverPrimitive.Trigger>} props
31
- * @example
32
- * ```jsx
33
- * <PopoverTrigger asChild>
34
- * <button>Open Popover</button>
35
- * </PopoverTrigger>
36
- * ```
37
- */
38
- export const PopoverTrigger = PopoverPrimitive.Trigger;
39
-
40
- /**
41
- * PopoverAnchor
42
- *
43
- * Optional anchor component: if you want the PopoverContent positioned against an element
44
- * other than the trigger. (Matches Radix’s `Popover.Anchor`) :contentReference[oaicite:2]{index=2}
45
- *
46
- * @component
47
- * @param {React.ComponentProps<typeof PopoverPrimitive.Anchor>} props
48
- */
49
- export const PopoverAnchor = PopoverPrimitive.Anchor;
50
-
51
- /**
52
- * PopoverPortal
53
- *
54
- * Portal wrapper. You can use this if you need to override portal container or force mount.
55
- *
56
- * @component
57
- * @param {React.ComponentProps<typeof PopoverPrimitive.Portal>} props
58
- */
59
- export const PopoverPortal = PopoverPrimitive.Portal;
60
-
61
- /**
62
- * Props for PopoverContent component.
63
- *
64
- * @typedef {Object} PopoverContentProps
65
- * @property {React.ReactNode} children – content inside the popover
66
- * @property {"top"|"right"|"bottom"|"left"} [side="bottom"] – preferred side for popover placement
67
- * @property {number} [sideOffset=8] – gap between trigger (or anchor) and the popover
68
- * @property {"start"|"center"|"end"} [align="center"] – alignment along the cross-axis
69
- * @property {number} [alignOffset=0] – offset for the alignment axis
70
- * @property {boolean} [avoidCollisions=true] – whether to auto-adjust position to avoid clipping :contentReference[oaicite:3]{index=3}
71
- * @property {boolean} [forceMount=false] – whether to always mount the content into the DOM
72
- * @property {string} [className] – additional CSS / Tailwind classes
73
- * @property {Object} [style] – inline style overrides
74
- * @property {React.ComponentProps<typeof PopoverPrimitive.Content>} [contentProps] – any extra props forwarded to Radix’s Content
75
- */
76
-
77
- /**
78
- * PopoverContent
79
- *
80
- * The popover surface that appears. Renders in a Portal by default.
81
- * You can override animation, styling, arrow, etc.
82
- *
83
- * @component
84
- * @param {PopoverContentProps & React.RefAttributes<HTMLDivElement>} props
85
- */
86
- export const PopoverContent = forwardRef(
87
- (
88
- {
89
- children,
90
- className,
91
- style,
92
- container,
93
- portalProps = {},
94
- side = "bottom",
95
- sideOffset = 8,
96
- align = "center",
97
- alignOffset = 0,
98
- avoidCollisions = true,
99
- forceMount = false,
100
- showArrow = false,
101
- contentProps = {},
102
- ...restProps
103
- },
104
- ref
105
- ) => {
106
- // Base styling; consuming apps can override via className or wrapping
107
- const base =
108
- "bg-fg-base text-fg-invert text-sm font-normal rounded-xl shadow-lg px-12 py-8 animate-fade-in";
109
- // A transform to “nudge” content initially
110
- const positioning = {
111
- top: "translate-y-[-4px]",
112
- right: "translate-x-[4px]",
113
- bottom: "translate-y-[4px]",
114
- left: "translate-x-[-4px]",
115
- }[side];
116
-
117
- return (
118
- <PopoverPortal container={container} {...portalProps}>
119
- <PopoverPrimitive.Content
120
- ref={ref}
121
- side={side}
122
- sideOffset={sideOffset}
123
- align={align}
124
- alignOffset={alignOffset}
125
- avoidCollisions={avoidCollisions}
126
- forceMount={forceMount}
127
- className={cx(positioning, className, "relative")}
128
- style={{ zIndex: POPOVER_Z_INDEX, ...style }}
129
- {...contentProps}
130
- {...restProps}
131
- >
132
- {children}
133
- {showArrow && (
134
- <PopoverPrimitive.Arrow
135
- className="fill-fg-base"
136
- width={12}
137
- height={8}
138
- />
139
- )}
140
- </PopoverPrimitive.Content>
141
- </PopoverPortal>
142
- );
143
- }
144
- );
145
-
146
- PopoverContent.displayName = "PopoverContent";
147
-
148
- /**
149
- * PopoverClose
150
- *
151
- * A button or element inside the PopoverContent that triggers closing action.
152
- *
153
- * @component
154
- * @param {React.ComponentProps<typeof PopoverPrimitive.Close>} props
155
- */
156
- export const PopoverClose = PopoverPrimitive.Close;
@@ -1,63 +0,0 @@
1
- import React from "react";
2
- import { render, screen } from "@testing-library/react";
3
- import {
4
- Popover,
5
- PopoverTrigger,
6
- PopoverContent,
7
- PopoverClose,
8
- } from "./Popover";
9
-
10
- vi.mock("@radix-ui/react-popover", () => {
11
- const Passthrough = ({ children, ...props }) => (
12
- <div {...props}>{children}</div>
13
- );
14
- const Buttonish = ({ children, ...props }) => (
15
- <button type="button" {...props}>
16
- {children}
17
- </button>
18
- );
19
- const Content = React.forwardRef(
20
- ({ sideOffset, alignOffset, avoidCollisions, forceMount, ...props }, ref) => (
21
- <div ref={ref} data-testid="radix-content" {...props} />
22
- )
23
- );
24
- Content.displayName = "RadixContent";
25
- const Arrow = (props) => <div data-testid="popover-arrow" {...props} />;
26
-
27
- return {
28
- Provider: Passthrough,
29
- Root: Passthrough,
30
- Trigger: Buttonish,
31
- Anchor: Passthrough,
32
- Portal: Passthrough,
33
- Content,
34
- Close: Buttonish,
35
- Arrow,
36
- };
37
- });
38
-
39
- describe("PopoverContent", () => {
40
- it("merges Tailwind classes and optionally renders arrow", () => {
41
- render(
42
- <PopoverContent className="custom" showArrow side="top" data-testid="content">
43
- Body
44
- </PopoverContent>
45
- );
46
- const content = screen.getByTestId("content");
47
- expect(content).toHaveClass("custom");
48
- expect(content).toHaveStyle({ zIndex: "2147483646" });
49
- expect(screen.getByTestId("popover-arrow")).toBeInTheDocument();
50
- });
51
-
52
- it("plays nicely with Popover + Trigger exports", () => {
53
- render(
54
- <Popover>
55
- <PopoverTrigger>Open</PopoverTrigger>
56
- <PopoverContent>Panel</PopoverContent>
57
- <PopoverClose>Close</PopoverClose>
58
- </Popover>
59
- );
60
- expect(screen.getByText("Open")).toBeInTheDocument();
61
- expect(screen.getAllByText(/close|panel/i).length).toBeGreaterThan(0);
62
- });
63
- });
package/src/index.js DELETED
@@ -1,8 +0,0 @@
1
- export {
2
- Popover,
3
- PopoverTrigger,
4
- PopoverAnchor,
5
- PopoverPortal,
6
- PopoverContent,
7
- PopoverClose,
8
- } from "./elements/Popover";