asterui 0.12.11 → 0.12.13
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/dist/components/Anchor.d.ts +10 -0
- package/dist/components/Breadcrumb.d.ts +20 -3
- package/dist/components/ContextMenu.d.ts +39 -3
- package/dist/components/Menu.d.ts +30 -5
- package/dist/components/Steps.d.ts +42 -6
- package/dist/index.d.ts +3 -3
- package/dist/index19.js +161 -63
- package/dist/index19.js.map +1 -1
- package/dist/index3.js +81 -65
- package/dist/index3.js.map +1 -1
- package/dist/index51.js +110 -104
- package/dist/index51.js.map +1 -1
- package/dist/index78.js +91 -19
- package/dist/index78.js.map +1 -1
- package/dist/index8.js +32 -8
- package/dist/index8.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,8 +14,12 @@ export interface AnchorProps {
|
|
|
14
14
|
direction?: 'horizontal' | 'vertical';
|
|
15
15
|
/** Offset from top when calculating scroll position */
|
|
16
16
|
offsetTop?: number;
|
|
17
|
+
/** Bounding distance of anchor area */
|
|
18
|
+
bounds?: number;
|
|
17
19
|
/** Target scroll container (default: window) */
|
|
18
20
|
getContainer?: () => HTMLElement | Window;
|
|
21
|
+
/** Customize the anchor highlight */
|
|
22
|
+
getCurrentAnchor?: (activeLink: string) => string;
|
|
19
23
|
/** Callback when active link changes */
|
|
20
24
|
onChange?: (activeLink: string) => void;
|
|
21
25
|
/** Callback when link is clicked */
|
|
@@ -25,6 +29,12 @@ export interface AnchorProps {
|
|
|
25
29
|
}) => void;
|
|
26
30
|
/** Currently active link (controlled) */
|
|
27
31
|
activeLink?: string;
|
|
32
|
+
/** Whether to fix the anchor when scrolling */
|
|
33
|
+
affix?: boolean;
|
|
34
|
+
/** Pixels to offset from top when affix is true */
|
|
35
|
+
affixOffsetTop?: number;
|
|
36
|
+
/** Replace history instead of push */
|
|
37
|
+
replace?: boolean;
|
|
28
38
|
/** Custom class name */
|
|
29
39
|
className?: string;
|
|
30
40
|
/** Anchor.Link children */
|
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
+
export interface BreadcrumbItemType {
|
|
3
|
+
/** Item title/label */
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
/** Link URL */
|
|
6
|
+
href?: string;
|
|
7
|
+
/** Click handler */
|
|
8
|
+
onClick?: () => void;
|
|
9
|
+
/** Custom class name */
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
2
12
|
export interface BreadcrumbProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
-
children
|
|
13
|
+
/** Breadcrumb.Item children (compound pattern) */
|
|
14
|
+
children?: React.ReactNode;
|
|
15
|
+
/** Breadcrumb items data (data-driven pattern) */
|
|
16
|
+
items?: BreadcrumbItemType[];
|
|
17
|
+
/** Custom separator between items */
|
|
18
|
+
separator?: React.ReactNode;
|
|
4
19
|
}
|
|
5
20
|
export interface BreadcrumbItemProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'onClick'> {
|
|
6
21
|
children: React.ReactNode;
|
|
7
22
|
href?: string;
|
|
8
23
|
onClick?: () => void;
|
|
24
|
+
/** Icon to display before the label */
|
|
25
|
+
icon?: React.ReactNode;
|
|
9
26
|
}
|
|
10
|
-
declare function BreadcrumbRoot({ children, className, ...rest }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
-
declare function BreadcrumbItem({ children, href, onClick, className, ...rest }: BreadcrumbItemProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
declare function BreadcrumbRoot({ children, items, separator, className, ...rest }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
declare function BreadcrumbItem({ children, href, onClick, icon, className, ...rest }: BreadcrumbItemProps): import("react/jsx-runtime").JSX.Element;
|
|
12
29
|
export declare const Breadcrumb: typeof BreadcrumbRoot & {
|
|
13
30
|
Item: typeof BreadcrumbItem;
|
|
14
31
|
};
|
|
@@ -11,8 +11,8 @@ export interface ContextMenuItem {
|
|
|
11
11
|
export interface ContextMenuProps {
|
|
12
12
|
/** Element that triggers the context menu on right-click */
|
|
13
13
|
children: React.ReactNode;
|
|
14
|
-
/** Menu items */
|
|
15
|
-
items
|
|
14
|
+
/** Menu items (data-driven pattern) */
|
|
15
|
+
items?: ContextMenuItem[];
|
|
16
16
|
/** Callback when an item is selected */
|
|
17
17
|
onSelect?: (key: string) => void;
|
|
18
18
|
/** Whether the context menu is disabled */
|
|
@@ -20,4 +20,40 @@ export interface ContextMenuProps {
|
|
|
20
20
|
/** Additional CSS classes for the menu */
|
|
21
21
|
className?: string;
|
|
22
22
|
}
|
|
23
|
-
export
|
|
23
|
+
export interface ContextMenuItemProps {
|
|
24
|
+
/** Unique key for the item */
|
|
25
|
+
itemKey: string;
|
|
26
|
+
/** Item content */
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
/** Icon to display before label */
|
|
29
|
+
icon?: React.ReactNode;
|
|
30
|
+
/** Whether the item is disabled */
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
/** Show as danger/destructive action */
|
|
33
|
+
danger?: boolean;
|
|
34
|
+
/** Additional CSS classes */
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ContextMenuDividerProps {
|
|
38
|
+
/** Additional CSS classes */
|
|
39
|
+
className?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface ContextMenuSubMenuProps {
|
|
42
|
+
/** Unique key for the submenu */
|
|
43
|
+
itemKey: string;
|
|
44
|
+
/** Submenu label */
|
|
45
|
+
label: React.ReactNode;
|
|
46
|
+
/** Icon to display before label */
|
|
47
|
+
icon?: React.ReactNode;
|
|
48
|
+
/** Whether the submenu is disabled */
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
/** Submenu items */
|
|
51
|
+
children: React.ReactNode;
|
|
52
|
+
/** Additional CSS classes */
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare const ContextMenu: React.FC<ContextMenuProps> & {
|
|
56
|
+
Item: React.FC<ContextMenuItemProps>;
|
|
57
|
+
Divider: React.FC<ContextMenuDividerProps>;
|
|
58
|
+
SubMenu: React.FC<ContextMenuSubMenuProps>;
|
|
59
|
+
};
|
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
export type MenuMode = 'vertical' | 'horizontal' | 'inline';
|
|
3
|
+
export type MenuSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
|
+
export interface MenuItem {
|
|
5
|
+
key: string;
|
|
6
|
+
label: React.ReactNode;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
children?: MenuItem[];
|
|
10
|
+
divider?: boolean;
|
|
11
|
+
title?: boolean;
|
|
12
|
+
}
|
|
3
13
|
export interface MenuProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onSelect'> {
|
|
4
|
-
|
|
14
|
+
/** Menu items (compound pattern) */
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
/** Menu items (data-driven pattern) */
|
|
17
|
+
items?: MenuItem[];
|
|
18
|
+
/** Menu display mode */
|
|
5
19
|
mode?: MenuMode;
|
|
20
|
+
/** Menu size */
|
|
21
|
+
size?: MenuSize;
|
|
22
|
+
/** Controlled selected keys */
|
|
6
23
|
selectedKeys?: string[];
|
|
24
|
+
/** Default selected keys (uncontrolled) */
|
|
7
25
|
defaultSelectedKeys?: string[];
|
|
26
|
+
/** Controlled open submenu keys */
|
|
8
27
|
openKeys?: string[];
|
|
28
|
+
/** Default open submenu keys (uncontrolled) */
|
|
9
29
|
defaultOpenKeys?: string[];
|
|
30
|
+
/** Callback when item is selected */
|
|
10
31
|
onSelect?: (key: string) => void;
|
|
32
|
+
/** Callback when submenu open state changes */
|
|
11
33
|
onOpenChange?: (openKeys: string[]) => void;
|
|
12
34
|
}
|
|
13
35
|
export interface MenuItemProps extends Omit<React.HTMLAttributes<HTMLAnchorElement>, 'onClick'> {
|
|
@@ -19,10 +41,13 @@ export interface MenuItemProps extends Omit<React.HTMLAttributes<HTMLAnchorEleme
|
|
|
19
41
|
/** @deprecated Use itemKey and selectedKeys instead */
|
|
20
42
|
active?: boolean;
|
|
21
43
|
}
|
|
22
|
-
export interface MenuSubMenuProps extends React.HTMLAttributes<HTMLLIElement> {
|
|
44
|
+
export interface MenuSubMenuProps extends Omit<React.HTMLAttributes<HTMLLIElement>, 'title'> {
|
|
23
45
|
children: React.ReactNode;
|
|
24
46
|
itemKey: string;
|
|
25
|
-
label
|
|
47
|
+
/** Submenu label */
|
|
48
|
+
label?: React.ReactNode;
|
|
49
|
+
/** Submenu title (alias for label) */
|
|
50
|
+
title?: React.ReactNode;
|
|
26
51
|
icon?: React.ReactNode;
|
|
27
52
|
disabled?: boolean;
|
|
28
53
|
}
|
|
@@ -31,9 +56,9 @@ export interface MenuTitleProps extends React.HTMLAttributes<HTMLLIElement> {
|
|
|
31
56
|
}
|
|
32
57
|
export interface MenuDividerProps extends React.HTMLAttributes<HTMLLIElement> {
|
|
33
58
|
}
|
|
34
|
-
declare function MenuRoot({ children, mode, selectedKeys: controlledSelectedKeys, defaultSelectedKeys, openKeys: controlledOpenKeys, defaultOpenKeys, onSelect, onOpenChange, className, ...rest }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
declare function MenuRoot({ children, items, mode, size, selectedKeys: controlledSelectedKeys, defaultSelectedKeys, openKeys: controlledOpenKeys, defaultOpenKeys, onSelect, onOpenChange, className, ...rest }: MenuProps): import("react/jsx-runtime").JSX.Element;
|
|
35
60
|
declare function MenuItem({ children, itemKey, icon, disabled, onClick, active, className, ...rest }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
|
|
36
|
-
declare function MenuSubMenu({ children, itemKey, label, icon, disabled, className, ...rest }: MenuSubMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
61
|
+
declare function MenuSubMenu({ children, itemKey, label, title, icon, disabled, className, ...rest }: MenuSubMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
37
62
|
declare function MenuTitle({ children, className, ...rest }: MenuTitleProps): import("react/jsx-runtime").JSX.Element;
|
|
38
63
|
declare function MenuDivider({ className, ...rest }: MenuDividerProps): import("react/jsx-runtime").JSX.Element;
|
|
39
64
|
export declare const Menu: typeof MenuRoot & {
|
|
@@ -1,15 +1,51 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
export
|
|
3
|
-
|
|
2
|
+
export type StepsDirection = 'horizontal' | 'vertical';
|
|
3
|
+
export interface StepItem {
|
|
4
|
+
key?: string;
|
|
5
|
+
title: React.ReactNode;
|
|
6
|
+
description?: React.ReactNode;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface StepsProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onChange'> {
|
|
12
|
+
/** Step items (compound pattern) */
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
/** Step items (data-driven pattern) */
|
|
15
|
+
items?: StepItem[];
|
|
16
|
+
/** Current step index (0-based) */
|
|
17
|
+
current?: number;
|
|
18
|
+
/** Layout direction */
|
|
19
|
+
direction?: StepsDirection;
|
|
20
|
+
/** @deprecated Use direction="vertical" instead */
|
|
4
21
|
vertical?: boolean;
|
|
22
|
+
/** Callback when step is clicked */
|
|
23
|
+
onChange?: (current: number) => void;
|
|
5
24
|
}
|
|
6
|
-
export interface StepProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color'> {
|
|
7
|
-
|
|
25
|
+
export interface StepProps extends Omit<React.LiHTMLAttributes<HTMLLIElement>, 'color' | 'title'> {
|
|
26
|
+
/** Step title/label */
|
|
27
|
+
children?: React.ReactNode;
|
|
28
|
+
/** Step title (alternative to children) */
|
|
29
|
+
title?: React.ReactNode;
|
|
30
|
+
/** Step description */
|
|
31
|
+
description?: React.ReactNode;
|
|
32
|
+
/** Step icon */
|
|
33
|
+
icon?: React.ReactNode;
|
|
34
|
+
/** Step color */
|
|
8
35
|
color?: 'neutral' | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'error';
|
|
36
|
+
/** Custom content for step indicator */
|
|
9
37
|
dataContent?: string;
|
|
38
|
+
/** Whether step is disabled */
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** Internal: step index */
|
|
41
|
+
_index?: number;
|
|
42
|
+
/** Internal: whether step is clickable */
|
|
43
|
+
_clickable?: boolean;
|
|
44
|
+
/** Internal: click handler */
|
|
45
|
+
_onClick?: (index: number) => void;
|
|
10
46
|
}
|
|
11
|
-
declare function StepsRoot({ children, vertical, className, ...rest }: StepsProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
-
declare function Step({ children, color, dataContent, className, ...rest }: StepProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
declare function StepsRoot({ children, items, current, direction, vertical, onChange, className, ...rest }: StepsProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
declare function Step({ children, title, description, icon, color, dataContent, disabled, className, _index, _clickable, _onClick, ...rest }: StepProps): import("react/jsx-runtime").JSX.Element;
|
|
13
49
|
export declare const Steps: typeof StepsRoot & {
|
|
14
50
|
Step: typeof Step;
|
|
15
51
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export type { CollapseProps, CollapseTitleProps, CollapseContentProps } from './
|
|
|
33
33
|
export { Container } from './components/Container';
|
|
34
34
|
export type { ContainerProps } from './components/Container';
|
|
35
35
|
export { ContextMenu } from './components/ContextMenu';
|
|
36
|
-
export type { ContextMenuProps, ContextMenuItem } from './components/ContextMenu';
|
|
36
|
+
export type { ContextMenuProps, ContextMenuItem, ContextMenuItemProps, ContextMenuDividerProps, ContextMenuSubMenuProps } from './components/ContextMenu';
|
|
37
37
|
export { Countdown } from './components/Countdown';
|
|
38
38
|
export type { CountdownProps } from './components/Countdown';
|
|
39
39
|
export { DatePicker } from './components/DatePicker';
|
|
@@ -97,7 +97,7 @@ export type { MasonryProps } from './components/Masonry';
|
|
|
97
97
|
export { Mention } from './components/Mention';
|
|
98
98
|
export type { MentionProps, MentionOption } from './components/Mention';
|
|
99
99
|
export { Menu } from './components/Menu';
|
|
100
|
-
export type { MenuProps, MenuItemProps, MenuSubMenuProps, MenuTitleProps, MenuDividerProps, MenuMode } from './components/Menu';
|
|
100
|
+
export type { MenuProps, MenuItem, MenuItemProps, MenuSubMenuProps, MenuTitleProps, MenuDividerProps, MenuMode, MenuSize } from './components/Menu';
|
|
101
101
|
export { Browser } from './components/Browser';
|
|
102
102
|
export type { BrowserProps } from './components/Browser';
|
|
103
103
|
export { Code } from './components/Code';
|
|
@@ -151,7 +151,7 @@ export type { StatsProps, StatProps } from './components/Stat';
|
|
|
151
151
|
export { Status } from './components/Status';
|
|
152
152
|
export type { StatusProps, StatusType, StatusSize } from './components/Status';
|
|
153
153
|
export { Steps } from './components/Steps';
|
|
154
|
-
export type { StepsProps, StepProps } from './components/Steps';
|
|
154
|
+
export type { StepsProps, StepProps, StepItem, StepsDirection } from './components/Steps';
|
|
155
155
|
export { Table } from './components/Table';
|
|
156
156
|
export type { TableProps, ColumnType, PaginationConfig, FilterConfig, RowSelection } from './components/Table';
|
|
157
157
|
export { Tabs } from './components/Tabs';
|
package/dist/index19.js
CHANGED
|
@@ -1,25 +1,107 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { createPortal as
|
|
4
|
-
const
|
|
5
|
-
const
|
|
1
|
+
import { jsxs as b, Fragment as P, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import T, { useState as g, useRef as C, useCallback as M, useEffect as N, createContext as W, useContext as z } from "react";
|
|
3
|
+
import { createPortal as B } from "react-dom";
|
|
4
|
+
const E = W(null), I = () => {
|
|
5
|
+
const e = z(E);
|
|
6
|
+
if (!e)
|
|
7
|
+
throw new Error("ContextMenu compound components must be used within a ContextMenu");
|
|
8
|
+
return e;
|
|
9
|
+
}, A = ({
|
|
10
|
+
itemKey: e,
|
|
11
|
+
children: u,
|
|
12
|
+
icon: l,
|
|
13
|
+
disabled: s = !1,
|
|
14
|
+
danger: d = !1,
|
|
15
|
+
className: o = ""
|
|
16
|
+
}) => {
|
|
17
|
+
const { onSelect: h, onClose: t } = I();
|
|
18
|
+
return /* @__PURE__ */ n("li", { className: o, children: /* @__PURE__ */ b(
|
|
19
|
+
"button",
|
|
20
|
+
{
|
|
21
|
+
onClick: () => {
|
|
22
|
+
s || (h(e), t());
|
|
23
|
+
},
|
|
24
|
+
disabled: s,
|
|
25
|
+
className: `
|
|
26
|
+
flex items-center gap-2 w-full px-4 py-2 text-left text-sm
|
|
27
|
+
${s ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
|
|
28
|
+
${d ? "text-error hover:bg-error/10" : ""}
|
|
29
|
+
`,
|
|
30
|
+
children: [
|
|
31
|
+
l && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: l }),
|
|
32
|
+
/* @__PURE__ */ n("span", { className: "flex-1", children: u })
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
) });
|
|
36
|
+
}, H = ({ className: e = "" }) => /* @__PURE__ */ n("li", { className: `divider my-1 ${e}` }), K = ({
|
|
37
|
+
itemKey: e,
|
|
38
|
+
label: u,
|
|
39
|
+
icon: l,
|
|
40
|
+
disabled: s = !1,
|
|
41
|
+
children: d,
|
|
42
|
+
className: o = ""
|
|
43
|
+
}) => {
|
|
44
|
+
const [h, t] = g(!1), a = C(null), c = () => {
|
|
45
|
+
s || (a.current && clearTimeout(a.current), t(!0));
|
|
46
|
+
}, m = () => {
|
|
47
|
+
a.current = setTimeout(() => t(!1), 100);
|
|
48
|
+
};
|
|
49
|
+
return /* @__PURE__ */ b(
|
|
50
|
+
"li",
|
|
51
|
+
{
|
|
52
|
+
onMouseEnter: c,
|
|
53
|
+
onMouseLeave: m,
|
|
54
|
+
className: `relative ${o}`,
|
|
55
|
+
children: [
|
|
56
|
+
/* @__PURE__ */ b(
|
|
57
|
+
"button",
|
|
58
|
+
{
|
|
59
|
+
disabled: s,
|
|
60
|
+
className: `
|
|
61
|
+
flex items-center gap-2 w-full px-4 py-2 text-left text-sm
|
|
62
|
+
${s ? "opacity-50 cursor-not-allowed" : "hover:bg-base-200"}
|
|
63
|
+
`,
|
|
64
|
+
children: [
|
|
65
|
+
l && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: l }),
|
|
66
|
+
/* @__PURE__ */ n("span", { className: "flex-1", children: u }),
|
|
67
|
+
/* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
h && /* @__PURE__ */ n(
|
|
72
|
+
"ul",
|
|
73
|
+
{
|
|
74
|
+
className: "menu bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1",
|
|
75
|
+
onMouseEnter: c,
|
|
76
|
+
onMouseLeave: m,
|
|
77
|
+
children: d
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
}, L = ({ item: e, onSelect: u, onClose: l }) => {
|
|
84
|
+
const [s, d] = g(!1), o = C(null);
|
|
6
85
|
if (e.divider)
|
|
7
|
-
return /* @__PURE__ */
|
|
8
|
-
const
|
|
9
|
-
e.disabled || e.children && e.children.length > 0 || (
|
|
10
|
-
}, t = e.children && e.children.length > 0
|
|
11
|
-
|
|
86
|
+
return /* @__PURE__ */ n("li", { className: "divider my-1" });
|
|
87
|
+
const h = () => {
|
|
88
|
+
e.disabled || e.children && e.children.length > 0 || (u(e.key), l());
|
|
89
|
+
}, t = e.children && e.children.length > 0, a = () => {
|
|
90
|
+
t && (o.current && clearTimeout(o.current), d(!0));
|
|
91
|
+
}, c = () => {
|
|
92
|
+
t && (o.current = setTimeout(() => d(!1), 100));
|
|
93
|
+
};
|
|
94
|
+
return /* @__PURE__ */ b(
|
|
12
95
|
"li",
|
|
13
96
|
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
onMouseLeave: () => t && m(!1),
|
|
97
|
+
onMouseEnter: a,
|
|
98
|
+
onMouseLeave: c,
|
|
17
99
|
className: "relative",
|
|
18
100
|
children: [
|
|
19
|
-
/* @__PURE__ */
|
|
101
|
+
/* @__PURE__ */ b(
|
|
20
102
|
"button",
|
|
21
103
|
{
|
|
22
|
-
onClick:
|
|
104
|
+
onClick: h,
|
|
23
105
|
disabled: e.disabled,
|
|
24
106
|
className: `
|
|
25
107
|
flex items-center gap-2 w-full px-4 py-2 text-left text-sm
|
|
@@ -27,75 +109,91 @@ const C = ({ item: e, onSelect: h, onClose: c }) => {
|
|
|
27
109
|
${e.danger ? "text-error hover:bg-error/10" : ""}
|
|
28
110
|
`,
|
|
29
111
|
children: [
|
|
30
|
-
e.icon && /* @__PURE__ */
|
|
31
|
-
/* @__PURE__ */
|
|
32
|
-
t && /* @__PURE__ */
|
|
112
|
+
e.icon && /* @__PURE__ */ n("span", { className: "w-4 h-4", children: e.icon }),
|
|
113
|
+
/* @__PURE__ */ n("span", { className: "flex-1", children: e.label }),
|
|
114
|
+
t && /* @__PURE__ */ n("svg", { className: "w-4 h-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ n("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
33
115
|
]
|
|
34
116
|
}
|
|
35
117
|
),
|
|
36
|
-
t &&
|
|
118
|
+
t && s && /* @__PURE__ */ n(
|
|
119
|
+
"ul",
|
|
120
|
+
{
|
|
121
|
+
className: "menu bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1",
|
|
122
|
+
onMouseEnter: a,
|
|
123
|
+
onMouseLeave: c,
|
|
124
|
+
children: e.children.map((m) => /* @__PURE__ */ n(L, { item: m, onSelect: u, onClose: l }, m.key))
|
|
125
|
+
}
|
|
126
|
+
)
|
|
37
127
|
]
|
|
38
128
|
}
|
|
39
129
|
);
|
|
40
|
-
},
|
|
130
|
+
}, O = ({
|
|
41
131
|
children: e,
|
|
42
|
-
items:
|
|
43
|
-
onSelect:
|
|
44
|
-
disabled:
|
|
45
|
-
className:
|
|
132
|
+
items: u,
|
|
133
|
+
onSelect: l,
|
|
134
|
+
disabled: s = !1,
|
|
135
|
+
className: d = ""
|
|
46
136
|
}) => {
|
|
47
|
-
const [
|
|
48
|
-
(
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
|
|
137
|
+
const [o, h] = g(!1), [t, a] = g({ x: 0, y: 0 }), c = C(null), m = C(null), S = M(
|
|
138
|
+
(r) => {
|
|
139
|
+
if (s) return;
|
|
140
|
+
r.preventDefault(), r.stopPropagation();
|
|
141
|
+
let i = r.clientX, f = r.clientY;
|
|
142
|
+
a({ x: i, y: f }), h(!0);
|
|
53
143
|
},
|
|
54
|
-
[
|
|
55
|
-
),
|
|
56
|
-
|
|
57
|
-
}, []),
|
|
58
|
-
(
|
|
59
|
-
|
|
144
|
+
[s]
|
|
145
|
+
), x = M(() => {
|
|
146
|
+
h(!1);
|
|
147
|
+
}, []), y = M(
|
|
148
|
+
(r) => {
|
|
149
|
+
l?.(r);
|
|
60
150
|
},
|
|
61
|
-
[
|
|
151
|
+
[l]
|
|
62
152
|
);
|
|
63
|
-
|
|
64
|
-
if (
|
|
65
|
-
const
|
|
66
|
-
let { x:
|
|
67
|
-
|
|
153
|
+
N(() => {
|
|
154
|
+
if (o && c.current) {
|
|
155
|
+
const i = c.current.getBoundingClientRect(), f = window.innerWidth, p = window.innerHeight;
|
|
156
|
+
let { x: v, y: w } = t;
|
|
157
|
+
v + i.width > f && (v = f - i.width - 8), w + i.height > p && (w = p - i.height - 8), (v !== t.x || w !== t.y) && a({ x: v, y: w });
|
|
68
158
|
}
|
|
69
|
-
}, [
|
|
70
|
-
if (!
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
},
|
|
76
|
-
|
|
159
|
+
}, [o, t]), N(() => {
|
|
160
|
+
if (!o) return;
|
|
161
|
+
const r = (p) => {
|
|
162
|
+
c.current && !c.current.contains(p.target) && x();
|
|
163
|
+
}, i = (p) => {
|
|
164
|
+
p.key === "Escape" && x();
|
|
165
|
+
}, f = () => {
|
|
166
|
+
x();
|
|
77
167
|
};
|
|
78
|
-
return document.addEventListener("mousedown",
|
|
79
|
-
document.removeEventListener("mousedown",
|
|
168
|
+
return document.addEventListener("mousedown", r), document.addEventListener("keydown", i), document.addEventListener("scroll", f, !0), () => {
|
|
169
|
+
document.removeEventListener("mousedown", r), document.removeEventListener("keydown", i), document.removeEventListener("scroll", f, !0);
|
|
80
170
|
};
|
|
81
|
-
}, [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
171
|
+
}, [o, x]);
|
|
172
|
+
const k = T.Children.toArray(e), R = k[0], $ = k.slice(1), j = u && u.length > 0, D = {
|
|
173
|
+
onSelect: y,
|
|
174
|
+
onClose: x
|
|
175
|
+
};
|
|
176
|
+
return /* @__PURE__ */ b(P, { children: [
|
|
177
|
+
/* @__PURE__ */ n("div", { ref: m, onContextMenu: S, className: "inline-block", children: R }),
|
|
178
|
+
o && B(
|
|
179
|
+
/* @__PURE__ */ n(E.Provider, { value: D, children: /* @__PURE__ */ n(
|
|
85
180
|
"ul",
|
|
86
181
|
{
|
|
87
|
-
ref:
|
|
88
|
-
className: `menu bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${
|
|
182
|
+
ref: c,
|
|
183
|
+
className: `menu bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${d}`,
|
|
89
184
|
style: { left: t.x, top: t.y },
|
|
90
|
-
children:
|
|
185
|
+
children: j ? u.map((r) => /* @__PURE__ */ n(L, { item: r, onSelect: y, onClose: x }, r.key)) : $
|
|
91
186
|
}
|
|
92
|
-
),
|
|
187
|
+
) }),
|
|
93
188
|
document.body
|
|
94
189
|
)
|
|
95
190
|
] });
|
|
96
|
-
}
|
|
97
|
-
|
|
191
|
+
}, Y = Object.assign(O, {
|
|
192
|
+
Item: A,
|
|
193
|
+
Divider: H,
|
|
194
|
+
SubMenu: K
|
|
195
|
+
});
|
|
98
196
|
export {
|
|
99
|
-
|
|
197
|
+
Y as ContextMenu
|
|
100
198
|
};
|
|
101
199
|
//# sourceMappingURL=index19.js.map
|
package/dist/index19.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index19.js","sources":["../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items */\n items: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n}> = ({ item, onSelect, onClose }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const itemRef = useRef<HTMLLIElement>(null)\n\n if (item.divider) {\n return <li className=\"divider my-1\"></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n return (\n <li\n ref={itemRef}\n onMouseEnter={() => hasSubmenu && setShowSubmenu(true)}\n onMouseLeave={() => hasSubmenu && setShowSubmenu(false)}\n className=\"relative\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul className=\"menu bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50\">\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nexport const ContextMenu: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n}) => {\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n return (\n <>\n <div ref={triggerRef} onContextMenu={handleContextMenu} className=\"inline-block\">\n {children}\n </div>\n {visible &&\n createPortal(\n <ul\n ref={menuRef}\n className={`menu bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n >\n {items.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} />\n ))}\n </ul>,\n document.body\n )}\n </>\n )\n}\n\nContextMenu.displayName = 'ContextMenu'\n"],"names":["MenuItem","item","onSelect","onClose","showSubmenu","setShowSubmenu","useState","itemRef","useRef","jsx","handleClick","hasSubmenu","jsxs","child","ContextMenu","children","items","disabled","className","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","Fragment","createPortal"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index19.js","sources":["../src/components/ContextMenu.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback, createContext, useContext } from 'react'\nimport { createPortal } from 'react-dom'\n\nexport interface ContextMenuItem {\n key: string\n label: React.ReactNode\n icon?: React.ReactNode\n disabled?: boolean\n danger?: boolean\n divider?: boolean\n children?: ContextMenuItem[]\n}\n\nexport interface ContextMenuProps {\n /** Element that triggers the context menu on right-click */\n children: React.ReactNode\n /** Menu items (data-driven pattern) */\n items?: ContextMenuItem[]\n /** Callback when an item is selected */\n onSelect?: (key: string) => void\n /** Whether the context menu is disabled */\n disabled?: boolean\n /** Additional CSS classes for the menu */\n className?: string\n}\n\nexport interface ContextMenuItemProps {\n /** Unique key for the item */\n itemKey: string\n /** Item content */\n children: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Show as danger/destructive action */\n danger?: boolean\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ContextMenuDividerProps {\n /** Additional CSS classes */\n className?: string\n}\n\nexport interface ContextMenuSubMenuProps {\n /** Unique key for the submenu */\n itemKey: string\n /** Submenu label */\n label: React.ReactNode\n /** Icon to display before label */\n icon?: React.ReactNode\n /** Whether the submenu is disabled */\n disabled?: boolean\n /** Submenu items */\n children: React.ReactNode\n /** Additional CSS classes */\n className?: string\n}\n\ninterface ContextMenuContextValue {\n onSelect: (key: string) => void\n onClose: () => void\n}\n\ninterface MenuPosition {\n x: number\n y: number\n}\n\nconst ContextMenuContext = createContext<ContextMenuContextValue | null>(null)\n\nconst useContextMenuContext = () => {\n const context = useContext(ContextMenuContext)\n if (!context) {\n throw new Error('ContextMenu compound components must be used within a ContextMenu')\n }\n return context\n}\n\n// Compound pattern components\nconst ContextMenuItemComponent: React.FC<ContextMenuItemProps> = ({\n itemKey,\n children,\n icon,\n disabled = false,\n danger = false,\n className = '',\n}) => {\n const { onSelect, onClose } = useContextMenuContext()\n\n const handleClick = () => {\n if (disabled) return\n onSelect(itemKey)\n onClose()\n }\n\n return (\n <li className={className}>\n <button\n onClick={handleClick}\n disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\n <span className=\"flex-1\">{children}</span>\n </button>\n </li>\n )\n}\n\nconst ContextMenuDividerComponent: React.FC<ContextMenuDividerProps> = ({ className = '' }) => {\n return <li className={`divider my-1 ${className}`}></li>\n}\n\nconst ContextMenuSubMenuComponent: React.FC<ContextMenuSubMenuProps> = ({\n itemKey: _itemKey,\n label,\n icon,\n disabled = false,\n children,\n className = '',\n}) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const handleMouseEnter = () => {\n if (disabled) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className={`relative ${className}`}\n >\n <button\n disabled={disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n `}\n >\n {icon && <span className=\"w-4 h-4\">{icon}</span>}\n <span className=\"flex-1\">{label}</span>\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n {showSubmenu && (\n <ul\n className=\"menu bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {children}\n </ul>\n )}\n </li>\n )\n}\n\n// Data-driven pattern internal component\nconst MenuItem: React.FC<{\n item: ContextMenuItem\n onSelect: (key: string) => void\n onClose: () => void\n}> = ({ item, onSelect, onClose }) => {\n const [showSubmenu, setShowSubmenu] = useState(false)\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n if (item.divider) {\n return <li className=\"divider my-1\"></li>\n }\n\n const handleClick = () => {\n if (item.disabled) return\n if (item.children && item.children.length > 0) return\n onSelect(item.key)\n onClose()\n }\n\n const hasSubmenu = item.children && item.children.length > 0\n\n const handleMouseEnter = () => {\n if (!hasSubmenu) return\n if (timeoutRef.current) clearTimeout(timeoutRef.current)\n setShowSubmenu(true)\n }\n\n const handleMouseLeave = () => {\n if (!hasSubmenu) return\n timeoutRef.current = setTimeout(() => setShowSubmenu(false), 100)\n }\n\n return (\n <li\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n className=\"relative\"\n >\n <button\n onClick={handleClick}\n disabled={item.disabled}\n className={`\n flex items-center gap-2 w-full px-4 py-2 text-left text-sm\n ${item.disabled ? 'opacity-50 cursor-not-allowed' : 'hover:bg-base-200'}\n ${item.danger ? 'text-error hover:bg-error/10' : ''}\n `}\n >\n {item.icon && <span className=\"w-4 h-4\">{item.icon}</span>}\n <span className=\"flex-1\">{item.label}</span>\n {hasSubmenu && (\n <svg className=\"w-4 h-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n )}\n </button>\n {hasSubmenu && showSubmenu && (\n <ul\n className=\"menu bg-base-100 rounded-box shadow-lg border border-base-300 absolute left-full top-0 min-w-[160px] z-50 p-1\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n >\n {item.children!.map((child) => (\n <MenuItem key={child.key} item={child} onSelect={onSelect} onClose={onClose} />\n ))}\n </ul>\n )}\n </li>\n )\n}\n\nconst ContextMenuRoot: React.FC<ContextMenuProps> = ({\n children,\n items,\n onSelect,\n disabled = false,\n className = '',\n}) => {\n const [visible, setVisible] = useState(false)\n const [position, setPosition] = useState<MenuPosition>({ x: 0, y: 0 })\n const menuRef = useRef<HTMLUListElement>(null)\n const triggerRef = useRef<HTMLDivElement>(null)\n\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (disabled) return\n e.preventDefault()\n e.stopPropagation()\n\n // Calculate position, ensuring menu stays within viewport\n let x = e.clientX\n let y = e.clientY\n\n // We'll adjust after render when we know menu dimensions\n setPosition({ x, y })\n setVisible(true)\n },\n [disabled]\n )\n\n const handleClose = useCallback(() => {\n setVisible(false)\n }, [])\n\n const handleSelect = useCallback(\n (key: string) => {\n onSelect?.(key)\n },\n [onSelect]\n )\n\n // Adjust position after menu renders to keep it in viewport\n useEffect(() => {\n if (visible && menuRef.current) {\n const menu = menuRef.current\n const rect = menu.getBoundingClientRect()\n const viewportWidth = window.innerWidth\n const viewportHeight = window.innerHeight\n\n let { x, y } = position\n\n if (x + rect.width > viewportWidth) {\n x = viewportWidth - rect.width - 8\n }\n if (y + rect.height > viewportHeight) {\n y = viewportHeight - rect.height - 8\n }\n\n if (x !== position.x || y !== position.y) {\n setPosition({ x, y })\n }\n }\n }, [visible, position])\n\n // Close on click outside or escape\n useEffect(() => {\n if (!visible) return\n\n const handleClickOutside = (e: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n handleClose()\n }\n }\n\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n handleClose()\n }\n }\n\n const handleScroll = () => {\n handleClose()\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n document.addEventListener('keydown', handleEscape)\n document.addEventListener('scroll', handleScroll, true)\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n document.removeEventListener('keydown', handleEscape)\n document.removeEventListener('scroll', handleScroll, true)\n }\n }, [visible, handleClose])\n\n // Determine if using data-driven or compound pattern\n // Find menu content children (not the trigger element)\n const childArray = React.Children.toArray(children)\n const triggerChild = childArray[0]\n const menuChildren = childArray.slice(1)\n const useDataDriven = items && items.length > 0\n\n const contextValue: ContextMenuContextValue = {\n onSelect: handleSelect,\n onClose: handleClose,\n }\n\n return (\n <>\n <div ref={triggerRef} onContextMenu={handleContextMenu} className=\"inline-block\">\n {triggerChild}\n </div>\n {visible &&\n createPortal(\n <ContextMenuContext.Provider value={contextValue}>\n <ul\n ref={menuRef}\n className={`menu bg-base-100 rounded-box shadow-lg border border-base-300 min-w-[160px] p-1 fixed z-[9999] ${className}`}\n style={{ left: position.x, top: position.y }}\n >\n {useDataDriven\n ? items!.map((item) => (\n <MenuItem key={item.key} item={item} onSelect={handleSelect} onClose={handleClose} />\n ))\n : menuChildren}\n </ul>\n </ContextMenuContext.Provider>,\n document.body\n )}\n </>\n )\n}\n\n// Assign compound components\nexport const ContextMenu = Object.assign(ContextMenuRoot, {\n Item: ContextMenuItemComponent,\n Divider: ContextMenuDividerComponent,\n SubMenu: ContextMenuSubMenuComponent,\n})\n"],"names":["ContextMenuContext","createContext","useContextMenuContext","context","useContext","ContextMenuItemComponent","itemKey","children","icon","disabled","danger","className","onSelect","onClose","jsx","jsxs","ContextMenuDividerComponent","ContextMenuSubMenuComponent","_itemKey","label","showSubmenu","setShowSubmenu","useState","timeoutRef","useRef","handleMouseEnter","handleMouseLeave","MenuItem","item","handleClick","hasSubmenu","child","ContextMenuRoot","items","visible","setVisible","position","setPosition","menuRef","triggerRef","handleContextMenu","useCallback","e","x","y","handleClose","handleSelect","key","useEffect","rect","viewportWidth","viewportHeight","handleClickOutside","handleEscape","handleScroll","childArray","React","triggerChild","menuChildren","useDataDriven","contextValue","Fragment","createPortal","ContextMenu"],"mappings":"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"}
|