@stackone/malachite 2.38.0 → 2.39.0
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/COMPONENTS.md +1 -1
- package/dist/ShadowRootWrapper.js +33 -59
- package/dist/ShadowRootWrapper.js.map +1 -1
- package/dist/components/ActionMenu.js +78 -76
- package/dist/components/ActionMenu.js.map +1 -1
- package/dist/components/ActionMenuTagHost.js +19 -0
- package/dist/components/ActionMenuTagHost.js.map +1 -0
- package/dist/components/Breadcrumbs.js +7 -7
- package/dist/components/Breadcrumbs.js.map +1 -1
- package/dist/components/actionMenuStyles.js +29 -24
- package/dist/components/actionMenuStyles.js.map +1 -1
- package/dist/components/useActionMenuPosition.js +59 -52
- package/dist/components/useActionMenuPosition.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/tailwind.css.js +1 -1
- package/dist/tailwindSheet.js +35 -0
- package/dist/tailwindSheet.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumbs.js","sources":["../../src/components/Breadcrumbs.tsx"],"sourcesContent":["import React from 'react';\nimport Button from './Button';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport CaretRightIcon from './CustomIcons/CaretRightIcon';\nimport type { BreadcrumbLink, PageAction, RenderBreadcrumbLink } from './PageLayout/types';\nimport Text, { type TextColor } from './Typography/Text';\nimport { hasBackButton } from './breadcrumbsNav';\nimport { FOCUS_RING } from './focusRing';\nimport { isSafeHref, safeHref } from './safeHref';\n\nexport interface BreadcrumbsProps {\n links: BreadcrumbLink[];\n actions?: PageAction[];\n renderLink?: RenderBreadcrumbLink;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst CRUMB_LINK_CLASSES = `no-underline rounded-xs cursor-pointer transition-colors duration-200 ease-in-out hover:text-[var(--malachite-accent-foreground)] ${FOCUS_RING}`;\n\nconst BACK_BUTTON_CLASSES = `flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--malachite-radius-10,10px)] no-underline bg-[var(--malachite-number-tag-background)] text-[var(--malachite-text-primary)] transition-colors duration-200 ease-in-out hover:bg-[var(--malachite-number-tag-emphasis-background)] ${FOCUS_RING}`;\n\ntype LinkProps = Parameters<RenderBreadcrumbLink>[0];\n\nconst renderCrumbLink = (props: LinkProps, renderLink?: RenderBreadcrumbLink): React.ReactNode => {\n // An unsafe url degrades to plain text rather than a link that could run a script.\n if (!isSafeHref(props.href)) {\n return props.children;\n }\n return renderLink ? renderLink(props) : <a {...props} />;\n};\n\nconst renderCrumbName = (name: React.ReactNode, color: TextColor): React.ReactNode =>\n typeof name === 'string' ? (\n <Text size=\"medium\" fontWeight=\"semi-bold\" color={color}>\n {name}\n </Text>\n ) : (\n name\n );\n\nconst renderAction = (\n {\n label,\n onClick,\n disabled,\n variant,\n icon,\n href,\n target,\n tooltip,\n tooltipPlacement,\n }: PageAction,\n index: number,\n) => {\n const safe = safeHref(href);\n return (\n <Button\n key={`${index}-${label}`}\n size=\"small\"\n variant={variant ?? 'outline'}\n disabled={disabled}\n icon={icon}\n tooltip={tooltip}\n tooltipPlacement={tooltipPlacement}\n href={safe}\n target={safe ? (target ?? '_blank') : undefined}\n onClick={safe ? undefined : onClick}\n >\n {label}\n </Button>\n );\n};\n\nconst Breadcrumbs: React.FC<BreadcrumbsProps> = ({\n links,\n actions,\n renderLink,\n className = '',\n style,\n}) => {\n // PageLayout mounts this unconditionally, so returning markup would leave an empty\n // navigation landmark on every page without crumbs.\n if (links.length === 0 && !actions?.length) {\n return null;\n }\n\n const isTitle = links.length === 1 && Boolean(links[0].isRoot);\n const parentCrumb = hasBackButton(links) ? links[links.length - 2] : undefined;\n const parentName = parentCrumb?.name;\n const hasActions = Boolean(actions?.length);\n\n return (\n <div\n className={`flex items-center ${hasActions ? 'justify-between' : ''} ${className}`}\n style={style}\n >\n {isTitle ? (\n renderCrumbName(links[0].name, 'primary')\n ) : (\n <div className=\"flex items-center gap-4\">\n {parentCrumb?.url &&\n renderCrumbLink(\n {\n href: parentCrumb.url,\n 'aria-label':\n typeof parentName === 'string'\n ? `Back to ${parentName}`\n : 'Go back',\n className: BACK_BUTTON_CLASSES,\n children: <ArrowLeftIcon size={12} />,\n },\n renderLink,\n )}\n {links.length > 0 && (\n <nav aria-label=\"Breadcrumb\">\n <ol className=\"flex flex-wrap items-center gap-2 m-0 p-0 list-none\">\n {links.map((link, index) => {\n const isLast = index === links.length - 1;\n const color: TextColor = isLast ? 'primary' : 'muted';\n\n return (\n <li\n key={`${link.url ?? ''}-${index}`}\n className=\"flex items-center gap-2\"\n aria-current={isLast && !link.url ? 'page' : undefined}\n >\n {link.url\n ? renderCrumbLink(\n {\n href: link.url,\n 'aria-current': isLast\n ? 'page'\n : undefined,\n className: `${CRUMB_LINK_CLASSES} ${\n isLast\n ? 'text-[var(--malachite-text-primary)]'\n : 'text-[var(--malachite-text-muted)]'\n }`,\n children: renderCrumbName(\n link.name,\n 'inherit',\n ),\n },\n renderLink,\n )\n : renderCrumbName(link.name, color)}\n {!isLast && (\n <span\n aria-hidden=\"true\"\n className=\"flex items-center text-[var(--malachite-text-dimmed)]\"\n >\n <CaretRightIcon size={13} />\n </span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n )}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-2\">{actions?.map(renderAction)}</div>\n )}\n </div>\n );\n};\n\nexport { Breadcrumbs };\nexport default Breadcrumbs;\n"],"names":["CRUMB_LINK_CLASSES","FOCUS_RING","BACK_BUTTON_CLASSES","renderCrumbLink","props","renderLink","isSafeHref","jsx","renderCrumbName","name","color","Text","renderAction","label","onClick","disabled","variant","icon","href","target","tooltip","tooltipPlacement","index","safe","safeHref","Button","Breadcrumbs","links","actions","className","style","isTitle","parentCrumb","hasBackButton","parentName","hasActions","jsxs","ArrowLeftIcon","link","isLast","CaretRightIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.js","sources":["../../src/components/Breadcrumbs.tsx"],"sourcesContent":["import React from 'react';\nimport Button from './Button';\nimport ArrowLeftIcon from './CustomIcons/ArrowLeftIcon';\nimport CaretRightIcon from './CustomIcons/CaretRightIcon';\nimport type { BreadcrumbLink, PageAction, RenderBreadcrumbLink } from './PageLayout/types';\nimport Text, { type TextColor } from './Typography/Text';\nimport { hasBackButton } from './breadcrumbsNav';\nimport { FOCUS_RING } from './focusRing';\nimport { isSafeHref, safeHref } from './safeHref';\n\nexport interface BreadcrumbsProps {\n links: BreadcrumbLink[];\n actions?: PageAction[];\n renderLink?: RenderBreadcrumbLink;\n className?: string;\n style?: React.CSSProperties;\n}\n\nconst CRUMB_LINK_CLASSES = `no-underline rounded-xs cursor-pointer transition-colors duration-200 ease-in-out hover:text-[var(--malachite-accent-foreground,rgb(2,122,66))] ${FOCUS_RING}`;\n\nconst BACK_BUTTON_CLASSES = `flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--malachite-radius-10,10px)] no-underline bg-[var(--malachite-number-tag-background,rgba(0,0,0,0.08))] text-[var(--malachite-text-primary,rgb(10,10,10))] transition-colors duration-200 ease-in-out hover:bg-[var(--malachite-number-tag-emphasis-background,rgba(0,0,0,0.15))] ${FOCUS_RING}`;\n\ntype LinkProps = Parameters<RenderBreadcrumbLink>[0];\n\nconst renderCrumbLink = (props: LinkProps, renderLink?: RenderBreadcrumbLink): React.ReactNode => {\n // An unsafe url degrades to plain text rather than a link that could run a script.\n if (!isSafeHref(props.href)) {\n return props.children;\n }\n return renderLink ? renderLink(props) : <a {...props} />;\n};\n\nconst renderCrumbName = (name: React.ReactNode, color: TextColor): React.ReactNode =>\n typeof name === 'string' ? (\n <Text size=\"medium\" fontWeight=\"semi-bold\" color={color}>\n {name}\n </Text>\n ) : (\n name\n );\n\nconst renderAction = (\n {\n label,\n onClick,\n disabled,\n variant,\n icon,\n href,\n target,\n tooltip,\n tooltipPlacement,\n }: PageAction,\n index: number,\n) => {\n const safe = safeHref(href);\n return (\n <Button\n key={`${index}-${label}`}\n size=\"small\"\n variant={variant ?? 'outline'}\n disabled={disabled}\n icon={icon}\n tooltip={tooltip}\n tooltipPlacement={tooltipPlacement}\n href={safe}\n target={safe ? (target ?? '_blank') : undefined}\n onClick={safe ? undefined : onClick}\n >\n {label}\n </Button>\n );\n};\n\nconst Breadcrumbs: React.FC<BreadcrumbsProps> = ({\n links,\n actions,\n renderLink,\n className = '',\n style,\n}) => {\n // PageLayout mounts this unconditionally, so returning markup would leave an empty\n // navigation landmark on every page without crumbs.\n if (links.length === 0 && !actions?.length) {\n return null;\n }\n\n const isTitle = links.length === 1 && Boolean(links[0].isRoot);\n const parentCrumb = hasBackButton(links) ? links[links.length - 2] : undefined;\n const parentName = parentCrumb?.name;\n const hasActions = Boolean(actions?.length);\n\n return (\n <div\n className={`flex items-center ${hasActions ? 'justify-between' : ''} ${className}`}\n style={style}\n >\n {isTitle ? (\n renderCrumbName(links[0].name, 'primary')\n ) : (\n <div className=\"flex items-center gap-4\">\n {parentCrumb?.url &&\n renderCrumbLink(\n {\n href: parentCrumb.url,\n 'aria-label':\n typeof parentName === 'string'\n ? `Back to ${parentName}`\n : 'Go back',\n className: BACK_BUTTON_CLASSES,\n children: <ArrowLeftIcon size={12} />,\n },\n renderLink,\n )}\n {links.length > 0 && (\n <nav aria-label=\"Breadcrumb\">\n <ol className=\"flex flex-wrap items-center gap-2 m-0 p-0 list-none\">\n {links.map((link, index) => {\n const isLast = index === links.length - 1;\n const color: TextColor = isLast ? 'primary' : 'muted';\n\n return (\n <li\n key={`${link.url ?? ''}-${index}`}\n className=\"flex items-center gap-2\"\n aria-current={isLast && !link.url ? 'page' : undefined}\n >\n {link.url\n ? renderCrumbLink(\n {\n href: link.url,\n 'aria-current': isLast\n ? 'page'\n : undefined,\n className: `${CRUMB_LINK_CLASSES} ${\n isLast\n ? 'text-[var(--malachite-text-primary,rgb(10,10,10))]'\n : 'text-[var(--malachite-text-muted,rgb(76,75,75))]'\n }`,\n children: renderCrumbName(\n link.name,\n 'inherit',\n ),\n },\n renderLink,\n )\n : renderCrumbName(link.name, color)}\n {!isLast && (\n <span\n aria-hidden=\"true\"\n className=\"flex items-center text-[var(--malachite-text-dimmed,rgb(161,161,161))]\"\n >\n <CaretRightIcon size={13} />\n </span>\n )}\n </li>\n );\n })}\n </ol>\n </nav>\n )}\n </div>\n )}\n {hasActions && (\n <div className=\"flex items-center gap-2\">{actions?.map(renderAction)}</div>\n )}\n </div>\n );\n};\n\nexport { Breadcrumbs };\nexport default Breadcrumbs;\n"],"names":["CRUMB_LINK_CLASSES","FOCUS_RING","BACK_BUTTON_CLASSES","renderCrumbLink","props","renderLink","isSafeHref","jsx","renderCrumbName","name","color","Text","renderAction","label","onClick","disabled","variant","icon","href","target","tooltip","tooltipPlacement","index","safe","safeHref","Button","Breadcrumbs","links","actions","className","style","isTitle","parentCrumb","hasBackButton","parentName","hasActions","jsxs","ArrowLeftIcon","link","isLast","CaretRightIcon"],"mappings":"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"}
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import { MENU_SPECS as t } from "./floatingMenuGeometry.js";
|
|
2
2
|
import { injectStyleSheet as l } from "./injectStyleSheet.js";
|
|
3
|
-
import { ensureOverlayStyles as
|
|
4
|
-
|
|
3
|
+
import { ensureOverlayStyles as n } from "./portalOverlay.js";
|
|
4
|
+
import { SELECTED_ROW_BACKGROUND as o, SELECTED_ROW_FOREGROUND as d } from "./selectedRow.js";
|
|
5
|
+
const b = {
|
|
5
6
|
small: { icon: 16, iconBox: "text-[16px] [&_svg]:size-[16px]!" },
|
|
6
7
|
xsmall: { icon: 11, iconBox: "text-[11px] [&_svg]:size-[11px]!" }
|
|
7
|
-
},
|
|
8
|
+
}, p = {
|
|
8
9
|
minWidth: 0,
|
|
9
10
|
overflow: "hidden",
|
|
10
11
|
textOverflow: "ellipsis"
|
|
11
|
-
},
|
|
12
|
+
}, c = {
|
|
12
13
|
padding: "6px 10px",
|
|
13
14
|
fontSize: "var(--malachite-font-size-small, 13px)",
|
|
14
15
|
color: "var(--malachite-text-dimmed, rgb(161, 161, 161))",
|
|
15
16
|
userSelect: "none"
|
|
16
|
-
},
|
|
17
|
-
...
|
|
17
|
+
}, i = {
|
|
18
|
+
...c,
|
|
18
19
|
color: "var(--malachite-text-secondary, rgb(123, 123, 123))",
|
|
19
20
|
overflow: "hidden",
|
|
20
21
|
textOverflow: "ellipsis",
|
|
21
22
|
whiteSpace: "nowrap"
|
|
22
|
-
},
|
|
23
|
+
}, v = {
|
|
23
24
|
display: "inline-flex",
|
|
24
25
|
flexShrink: 0,
|
|
25
26
|
color: "var(--malachite-text-dimmed, rgb(161, 161, 161))"
|
|
26
|
-
},
|
|
27
|
-
`.${
|
|
28
|
-
`.${
|
|
29
|
-
`.${
|
|
30
|
-
],
|
|
27
|
+
}, a = "malachite-actionmenu-item", s = "data-malachite-actionmenu-tag", E = { display: "inline-flex", flexShrink: 0 }, T = { [s]: "" }, m = [
|
|
28
|
+
`.${a} { background: transparent; }`,
|
|
29
|
+
`.${a}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,
|
|
30
|
+
`.${a}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`
|
|
31
|
+
], _ = () => (n(), l("malachite-actionmenu-item-styles", m)), x = {
|
|
31
32
|
default: "var(--malachite-text-primary, rgb(10, 10, 10))",
|
|
32
33
|
muted: "var(--malachite-text-secondary, rgb(123, 123, 123))"
|
|
33
|
-
},
|
|
34
|
+
}, u = (e, r) => e.danger ? "var(--malachite-text-destructive, rgb(237, 53, 54))" : e.current ? d : x[r], y = (e, r = "default") => e.type === "text" ? i : e.type === "divider" ? {
|
|
34
35
|
height: 1,
|
|
35
36
|
background: "var(--malachite-card-border, rgb(232, 232, 232))",
|
|
36
37
|
margin: "4px 0"
|
|
@@ -42,7 +43,8 @@ const h = {
|
|
|
42
43
|
borderRadius: 8,
|
|
43
44
|
fontSize: "var(--malachite-font-size-small, 13px)",
|
|
44
45
|
fontWeight: 400,
|
|
45
|
-
color: e
|
|
46
|
+
color: u(e, r),
|
|
47
|
+
background: e.current ? o : void 0,
|
|
46
48
|
cursor: e.disabled ? "not-allowed" : "pointer",
|
|
47
49
|
opacity: e.disabled ? 0.5 : 1,
|
|
48
50
|
userSelect: "none",
|
|
@@ -51,7 +53,7 @@ const h = {
|
|
|
51
53
|
border: "none",
|
|
52
54
|
textAlign: "left",
|
|
53
55
|
width: "100%"
|
|
54
|
-
},
|
|
56
|
+
}, w = (e) => ({
|
|
55
57
|
position: "fixed",
|
|
56
58
|
top: (e == null ? void 0 : e.top) ?? 0,
|
|
57
59
|
left: (e == null ? void 0 : e.left) ?? 0,
|
|
@@ -70,14 +72,17 @@ const h = {
|
|
|
70
72
|
opacity: e ? 1 : 0
|
|
71
73
|
});
|
|
72
74
|
export {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
c as EMPTY_ITEM_STYLE,
|
|
76
|
+
a as ITEM_CLASS,
|
|
77
|
+
v as ITEM_ICON_STYLE,
|
|
78
|
+
p as LABEL_STYLE,
|
|
79
|
+
s as TAG_HOST_ATTR,
|
|
80
|
+
T as TAG_HOST_PROPS,
|
|
81
|
+
E as TAG_HOST_STYLE,
|
|
82
|
+
i as TEXT_ITEM_STYLE,
|
|
83
|
+
b as TRIGGER_SIZES,
|
|
84
|
+
_ as ensureActionMenuStyles,
|
|
85
|
+
y as itemStyle,
|
|
86
|
+
w as menuStyle
|
|
82
87
|
};
|
|
83
88
|
//# sourceMappingURL=actionMenuStyles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actionMenuStyles.js","sources":["../../src/components/actionMenuStyles.ts"],"sourcesContent":["import type React from 'react';\nimport type { ActionMenuItem } from './actionMenuTypes';\nimport { MENU_SPECS, type MenuGeometry } from './floatingMenuGeometry';\nimport { injectStyleSheet } from './injectStyleSheet';\nimport { ensureOverlayStyles } from './portalOverlay';\n\nexport const TRIGGER_SIZES: Record<'small' | 'xsmall', { icon: number; iconBox: string }> = {\n small: { icon: 16, iconBox: 'text-[16px] [&_svg]:size-[16px]!' },\n xsmall: { icon: 11, iconBox: 'text-[11px] [&_svg]:size-[11px]!' },\n};\n\nexport const LABEL_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n};\n\nexport const EMPTY_ITEM_STYLE: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 'var(--malachite-font-size-small, 13px)',\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n userSelect: 'none',\n};\n\nexport const TEXT_ITEM_STYLE: React.CSSProperties = {\n ...EMPTY_ITEM_STYLE,\n color: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nexport const ITEM_ICON_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n flexShrink: 0,\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n};\n\nexport const ITEM_CLASS = 'malachite-actionmenu-item';\n\nconst ITEM_RULES = [\n `.${ITEM_CLASS} { background: transparent; }`,\n `.${ITEM_CLASS}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,\n `.${ITEM_CLASS}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`,\n];\n\nexport const ensureActionMenuStyles = (): CSSStyleSheet | null => {\n ensureOverlayStyles();\n return injectStyleSheet('malachite-actionmenu-item-styles', ITEM_RULES);\n};\n\nexport type ActionMenuTone = 'default' | 'muted';\n\nconst ITEM_TEXT: Record<ActionMenuTone, string> = {\n default: 'var(--malachite-text-primary, rgb(10, 10, 10))',\n muted: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n};\n\nexport const itemStyle = (\n item: ActionMenuItem,\n tone: ActionMenuTone = 'default',\n): React.CSSProperties => {\n if (item.type === 'text') {\n return TEXT_ITEM_STYLE;\n }\n if (item.type === 'divider') {\n return {\n height: 1,\n background: 'var(--malachite-card-border, rgb(232, 232, 232))',\n margin: '4px 0',\n };\n }\n return {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 10px',\n borderRadius: 8,\n fontSize: 'var(--malachite-font-size-small, 13px)',\n fontWeight: 400,\n color: item.
|
|
1
|
+
{"version":3,"file":"actionMenuStyles.js","sources":["../../src/components/actionMenuStyles.ts"],"sourcesContent":["import type React from 'react';\nimport type { ActionMenuItem } from './actionMenuTypes';\nimport { MENU_SPECS, type MenuGeometry } from './floatingMenuGeometry';\nimport { injectStyleSheet } from './injectStyleSheet';\nimport { ensureOverlayStyles } from './portalOverlay';\nimport { SELECTED_ROW_BACKGROUND, SELECTED_ROW_FOREGROUND } from './selectedRow';\n\nexport const TRIGGER_SIZES: Record<'small' | 'xsmall', { icon: number; iconBox: string }> = {\n small: { icon: 16, iconBox: 'text-[16px] [&_svg]:size-[16px]!' },\n xsmall: { icon: 11, iconBox: 'text-[11px] [&_svg]:size-[11px]!' },\n};\n\nexport const LABEL_STYLE: React.CSSProperties = {\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n};\n\nexport const EMPTY_ITEM_STYLE: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 'var(--malachite-font-size-small, 13px)',\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n userSelect: 'none',\n};\n\nexport const TEXT_ITEM_STYLE: React.CSSProperties = {\n ...EMPTY_ITEM_STYLE,\n color: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nexport const ITEM_ICON_STYLE: React.CSSProperties = {\n display: 'inline-flex',\n flexShrink: 0,\n color: 'var(--malachite-text-dimmed, rgb(161, 161, 161))',\n};\n\nexport const ITEM_CLASS = 'malachite-actionmenu-item';\n\nexport const TAG_HOST_ATTR = 'data-malachite-actionmenu-tag' as const;\n\nexport const TAG_HOST_STYLE: React.CSSProperties = { display: 'inline-flex', flexShrink: 0 };\n\nexport const TAG_HOST_PROPS = { [TAG_HOST_ATTR]: '' };\n\nconst ITEM_RULES = [\n `.${ITEM_CLASS} { background: transparent; }`,\n `.${ITEM_CLASS}:not(:disabled):hover { background: var(--malachite-card-dimmed-background, rgb(247, 247, 247)); }`,\n `.${ITEM_CLASS}:focus-visible { outline: 2px solid var(--malachite-text-primary, rgb(10, 10, 10)); outline-offset: -2px; }`,\n];\n\nexport const ensureActionMenuStyles = (): CSSStyleSheet | null => {\n ensureOverlayStyles();\n return injectStyleSheet('malachite-actionmenu-item-styles', ITEM_RULES);\n};\n\nexport type ActionMenuTone = 'default' | 'muted';\n\nconst ITEM_TEXT: Record<ActionMenuTone, string> = {\n default: 'var(--malachite-text-primary, rgb(10, 10, 10))',\n muted: 'var(--malachite-text-secondary, rgb(123, 123, 123))',\n};\n\ntype ActionItem = Exclude<ActionMenuItem, { type: 'text' } | { type: 'divider' }>;\n\nconst actionItemColor = (item: ActionItem, tone: ActionMenuTone): string => {\n if (item.danger) {\n return 'var(--malachite-text-destructive, rgb(237, 53, 54))';\n }\n if (item.current) {\n return SELECTED_ROW_FOREGROUND;\n }\n return ITEM_TEXT[tone];\n};\n\nexport const itemStyle = (\n item: ActionMenuItem,\n tone: ActionMenuTone = 'default',\n): React.CSSProperties => {\n if (item.type === 'text') {\n return TEXT_ITEM_STYLE;\n }\n if (item.type === 'divider') {\n return {\n height: 1,\n background: 'var(--malachite-card-border, rgb(232, 232, 232))',\n margin: '4px 0',\n };\n }\n return {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 10px',\n borderRadius: 8,\n fontSize: 'var(--malachite-font-size-small, 13px)',\n fontWeight: 400,\n color: actionItemColor(item, tone),\n background: item.current ? SELECTED_ROW_BACKGROUND : undefined,\n cursor: item.disabled ? 'not-allowed' : 'pointer',\n opacity: item.disabled ? 0.5 : 1,\n userSelect: 'none',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n border: 'none',\n textAlign: 'left',\n width: '100%',\n };\n};\n\nexport const menuStyle = (position: MenuGeometry | null): React.CSSProperties => ({\n position: 'fixed',\n top: position?.top ?? 0,\n left: position?.left ?? 0,\n width: position?.width,\n maxHeight: position?.maxHeight,\n overflowY: 'auto',\n background: MENU_SPECS.options.background,\n border: MENU_SPECS.options.border,\n borderRadius: MENU_SPECS.options.radius,\n boxShadow: MENU_SPECS.options.shadow,\n padding: MENU_SPECS.options.padding,\n display: 'flex',\n flexDirection: 'column',\n gap: 2,\n visibility: position ? 'visible' : 'hidden',\n opacity: position ? 1 : 0,\n});\n"],"names":["TRIGGER_SIZES","LABEL_STYLE","EMPTY_ITEM_STYLE","TEXT_ITEM_STYLE","ITEM_ICON_STYLE","ITEM_CLASS","TAG_HOST_ATTR","TAG_HOST_STYLE","TAG_HOST_PROPS","ITEM_RULES","ensureActionMenuStyles","ensureOverlayStyles","injectStyleSheet","ITEM_TEXT","actionItemColor","item","tone","SELECTED_ROW_FOREGROUND","itemStyle","SELECTED_ROW_BACKGROUND","menuStyle","position","MENU_SPECS"],"mappings":";;;;AAOO,MAAMA,IAA+E;AAAA,EACxF,OAAO,EAAE,MAAM,IAAI,SAAS,mCAAA;AAAA,EAC5B,QAAQ,EAAE,MAAM,IAAI,SAAS,mCAAA;AACjC,GAEaC,IAAmC;AAAA,EAC5C,UAAU;AAAA,EACV,UAAU;AAAA,EACV,cAAc;AAClB,GAEaC,IAAwC;AAAA,EACjD,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,YAAY;AAChB,GAEaC,IAAuC;AAAA,EAChD,GAAGD;AAAA,EACH,OAAO;AAAA,EACP,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AAChB,GAEaE,IAAuC;AAAA,EAChD,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,OAAO;AACX,GAEaC,IAAa,6BAEbC,IAAgB,iCAEhBC,IAAsC,EAAE,SAAS,eAAe,YAAY,EAAA,GAE5EC,IAAiB,EAAE,CAACF,CAAa,GAAG,GAAA,GAE3CG,IAAa;AAAA,EACf,IAAIJ,CAAU;AAAA,EACd,IAAIA,CAAU;AAAA,EACd,IAAIA,CAAU;AAClB,GAEaK,IAAyB,OAClCC,EAAA,GACOC,EAAiB,oCAAoCH,CAAU,IAKpEI,IAA4C;AAAA,EAC9C,SAAS;AAAA,EACT,OAAO;AACX,GAIMC,IAAkB,CAACC,GAAkBC,MACnCD,EAAK,SACE,wDAEPA,EAAK,UACEE,IAEJJ,EAAUG,CAAI,GAGZE,IAAY,CACrBH,GACAC,IAAuB,cAEnBD,EAAK,SAAS,SACPZ,IAEPY,EAAK,SAAS,YACP;AAAA,EACH,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,QAAQ;AAAA,IAGT;AAAA,EACH,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,KAAK;AAAA,EACL,SAAS;AAAA,EACT,cAAc;AAAA,EACd,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAOD,EAAgBC,GAAMC,CAAI;AAAA,EACjC,YAAYD,EAAK,UAAUI,IAA0B;AAAA,EACrD,QAAQJ,EAAK,WAAW,gBAAgB;AAAA,EACxC,SAASA,EAAK,WAAW,MAAM;AAAA,EAC/B,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,OAAO;AAAA,GAIFK,IAAY,CAACC,OAAwD;AAAA,EAC9E,UAAU;AAAA,EACV,MAAKA,KAAA,gBAAAA,EAAU,QAAO;AAAA,EACtB,OAAMA,KAAA,gBAAAA,EAAU,SAAQ;AAAA,EACxB,OAAOA,KAAA,gBAAAA,EAAU;AAAA,EACjB,WAAWA,KAAA,gBAAAA,EAAU;AAAA,EACrB,WAAW;AAAA,EACX,YAAYC,EAAW,QAAQ;AAAA,EAC/B,QAAQA,EAAW,QAAQ;AAAA,EAC3B,cAAcA,EAAW,QAAQ;AAAA,EACjC,WAAWA,EAAW,QAAQ;AAAA,EAC9B,SAASA,EAAW,QAAQ;AAAA,EAC5B,SAAS;AAAA,EACT,eAAe;AAAA,EACf,KAAK;AAAA,EACL,YAAYD,IAAW,YAAY;AAAA,EACnC,SAASA,IAAW,IAAI;AAC5B;"}
|
|
@@ -1,73 +1,80 @@
|
|
|
1
|
-
import { useState as L, useRef as
|
|
2
|
-
import { ensureActionMenuStyles as
|
|
3
|
-
import { measureContentWidth as
|
|
4
|
-
import { useTopLayer as
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { useState as L, useRef as T, useInsertionEffect as S, useCallback as F, useLayoutEffect as O } from "react";
|
|
2
|
+
import { ensureActionMenuStyles as _, TAG_HOST_ATTR as z } from "./actionMenuStyles.js";
|
|
3
|
+
import { measureContentWidth as C, measureMenuGeometry as G, computeFloatingGeometry as P, fullPanelHeight as W, MENU_MAX_HEIGHT_PX as E, rectSignature as A, FLOATING_OFFSET_PX as q } from "./floatingMenuGeometry.js";
|
|
4
|
+
import { useTopLayer as x } from "./topLayer.js";
|
|
5
|
+
const B = (s, t, r) => {
|
|
6
|
+
const w = new Set(s ? s.querySelectorAll(`[${z}]`) : []);
|
|
7
|
+
r.forEach((i) => {
|
|
8
|
+
w.has(i) || (r.delete(i), t == null || t.unobserve(i));
|
|
9
|
+
}), w.forEach((i) => {
|
|
10
|
+
r.has(i) || (r.add(i), t == null || t.observe(i));
|
|
11
|
+
});
|
|
12
|
+
}, U = (s, t, r, { minWidth: w, placement: i, offset: p }) => {
|
|
13
|
+
const [v, y] = L(null), g = T(void 0), c = T(!0);
|
|
14
|
+
x(r, s), S(() => {
|
|
15
|
+
s && _();
|
|
16
|
+
}, [s]);
|
|
17
|
+
const u = F(() => {
|
|
18
|
+
const l = t.current;
|
|
19
|
+
if (!l)
|
|
13
20
|
return;
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
16
|
-
const
|
|
17
|
-
|
|
21
|
+
const e = r.current;
|
|
22
|
+
if (e && c.current) {
|
|
23
|
+
const o = e.style.width;
|
|
24
|
+
e.style.width = "", g.current = C(e) ?? g.current, e.style.width = o, c.current = !1;
|
|
18
25
|
}
|
|
19
|
-
const
|
|
20
|
-
triggerRect:
|
|
26
|
+
const m = l.getBoundingClientRect(), a = G(e, {
|
|
27
|
+
triggerRect: m,
|
|
21
28
|
preset: "options",
|
|
22
|
-
minWidth:
|
|
23
|
-
contentWidth:
|
|
29
|
+
minWidth: w,
|
|
30
|
+
contentWidth: g.current,
|
|
24
31
|
viewportWidth: window.innerWidth,
|
|
25
32
|
viewportHeight: window.innerHeight
|
|
26
33
|
});
|
|
27
|
-
if (
|
|
28
|
-
|
|
34
|
+
if (i === "bottom-end" && p === void 0 || !e) {
|
|
35
|
+
y(a);
|
|
29
36
|
return;
|
|
30
37
|
}
|
|
31
|
-
const
|
|
32
|
-
triggerRect:
|
|
33
|
-
placement:
|
|
34
|
-
panelWidth:
|
|
35
|
-
panelHeight: Math.min(
|
|
36
|
-
gap:
|
|
38
|
+
const n = P({
|
|
39
|
+
triggerRect: m,
|
|
40
|
+
placement: i,
|
|
41
|
+
panelWidth: a.width,
|
|
42
|
+
panelHeight: Math.min(W(e), E),
|
|
43
|
+
gap: q[p ?? "small"],
|
|
37
44
|
viewportWidth: window.innerWidth,
|
|
38
45
|
viewportHeight: window.innerHeight
|
|
39
46
|
});
|
|
40
|
-
|
|
41
|
-
...
|
|
42
|
-
top:
|
|
43
|
-
left:
|
|
44
|
-
maxHeight: Math.min(
|
|
45
|
-
openUp:
|
|
47
|
+
y({
|
|
48
|
+
...a,
|
|
49
|
+
top: n.top,
|
|
50
|
+
left: n.left,
|
|
51
|
+
maxHeight: Math.min(E, n.maxHeight),
|
|
52
|
+
openUp: n.side === "top"
|
|
46
53
|
});
|
|
47
|
-
}, [
|
|
48
|
-
return
|
|
49
|
-
if (!
|
|
50
|
-
|
|
54
|
+
}, [t, r, w, i, p]);
|
|
55
|
+
return O(() => {
|
|
56
|
+
if (!s) {
|
|
57
|
+
y(null), g.current = void 0, c.current = !0;
|
|
51
58
|
return;
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
let
|
|
55
|
-
const
|
|
56
|
-
const f =
|
|
57
|
-
(
|
|
60
|
+
c.current = !0, u();
|
|
61
|
+
let l = 0, e = !1, m = t.current ? A(t.current.getBoundingClientRect()) : "";
|
|
62
|
+
const a = () => {
|
|
63
|
+
const f = t.current, h = f ? A(f.getBoundingClientRect()) : "";
|
|
64
|
+
(h !== m || e) && (m = h, e = !1, u()), l = requestAnimationFrame(a);
|
|
58
65
|
};
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
}) : null,
|
|
63
|
-
|
|
66
|
+
l = requestAnimationFrame(a), window.addEventListener("scroll", u, !0), window.addEventListener("resize", u);
|
|
67
|
+
const n = r.current, o = n && typeof ResizeObserver < "u" ? new ResizeObserver((f) => {
|
|
68
|
+
f.some((h) => h.target !== n) && (c.current = !0), e = !0;
|
|
69
|
+
}) : null, M = /* @__PURE__ */ new Set(), H = () => B(n, o, M), d = n && typeof MutationObserver < "u" ? new MutationObserver(() => {
|
|
70
|
+
c.current = !0, e = !0, H();
|
|
64
71
|
}) : null;
|
|
65
|
-
return
|
|
66
|
-
cancelAnimationFrame(
|
|
72
|
+
return n && (o == null || o.observe(n), H(), d == null || d.observe(n, { childList: !0, subtree: !0, characterData: !0 })), () => {
|
|
73
|
+
cancelAnimationFrame(l), o == null || o.disconnect(), d == null || d.disconnect(), window.removeEventListener("scroll", u, !0), window.removeEventListener("resize", u);
|
|
67
74
|
};
|
|
68
|
-
}, [
|
|
75
|
+
}, [s, u, t, r]), v;
|
|
69
76
|
};
|
|
70
77
|
export {
|
|
71
|
-
|
|
78
|
+
U as useActionMenuPosition
|
|
72
79
|
};
|
|
73
80
|
//# sourceMappingURL=useActionMenuPosition.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useActionMenuPosition.js","sources":["../../src/components/useActionMenuPosition.ts"],"sourcesContent":["import {\n type RefObject,\n useCallback,\n useInsertionEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { ensureActionMenuStyles } from './actionMenuStyles';\nimport type { ActionMenuPlacement } from './actionMenuTypes';\nimport {\n FLOATING_OFFSET_PX,\n type FloatingOffset,\n MENU_MAX_HEIGHT_PX,\n type MenuGeometry,\n computeFloatingGeometry,\n fullPanelHeight,\n measureContentWidth,\n measureMenuGeometry,\n rectSignature,\n} from './floatingMenuGeometry';\nimport { useTopLayer } from './topLayer';\n\ninterface PositionOptions {\n minWidth?: number;\n placement: ActionMenuPlacement;\n offset?: FloatingOffset;\n}\n\nexport const useActionMenuPosition = (\n open: boolean,\n triggerRef: RefObject<HTMLElement | null>,\n menuRef: RefObject<HTMLDivElement | null>,\n { minWidth, placement, offset }: PositionOptions,\n): MenuGeometry | null => {\n const [position, setPosition] = useState<MenuGeometry | null>(null);\n const contentWidth = useRef<number | undefined>(undefined);\n const contentDirty = useRef(true);\n\n useTopLayer(menuRef, open);\n\n useInsertionEffect(() => {\n if (open) {\n ensureActionMenuStyles();\n }\n }, [open]);\n\n const update = useCallback(() => {\n const trigger = triggerRef.current;\n if (!trigger) {\n return;\n }\n const menu = menuRef.current;\n if (menu && contentDirty.current) {\n const inlineWidth = menu.style.width;\n menu.style.width = '';\n contentWidth.current = measureContentWidth(menu) ?? contentWidth.current;\n menu.style.width = inlineWidth;\n contentDirty.current = false;\n }\n const triggerRect = trigger.getBoundingClientRect();\n const geometry = measureMenuGeometry(menu, {\n triggerRect,\n preset: 'options',\n minWidth,\n contentWidth: contentWidth.current,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n if ((placement === 'bottom-end' && offset === undefined) || !menu) {\n setPosition(geometry);\n return;\n }\n const floating = computeFloatingGeometry({\n triggerRect,\n placement,\n panelWidth: geometry.width,\n panelHeight: Math.min(fullPanelHeight(menu), MENU_MAX_HEIGHT_PX),\n gap: FLOATING_OFFSET_PX[offset ?? 'small'],\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n setPosition({\n ...geometry,\n top: floating.top,\n left: floating.left,\n maxHeight: Math.min(MENU_MAX_HEIGHT_PX, floating.maxHeight),\n openUp: floating.side === 'top',\n });\n }, [triggerRef, menuRef, minWidth, placement, offset]);\n\n useLayoutEffect(() => {\n if (!open) {\n setPosition(null);\n contentWidth.current = undefined;\n contentDirty.current = true;\n return;\n }\n contentDirty.current = true;\n update();\n let frame = 0;\n let menuResized = false;\n let lastRect = triggerRef.current\n ? rectSignature(triggerRef.current.getBoundingClientRect())\n : '';\n const followTrigger = () => {\n const trigger = triggerRef.current;\n const signature = trigger ? rectSignature(trigger.getBoundingClientRect()) : '';\n if (signature !== lastRect || menuResized) {\n lastRect = signature;\n menuResized = false;\n update();\n }\n frame = requestAnimationFrame(followTrigger);\n };\n frame = requestAnimationFrame(followTrigger);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n const menu = menuRef.current;\n const observer =\n menu && typeof ResizeObserver !== 'undefined'\n ? new ResizeObserver(() => {\n menuResized = true;\n })\n : null;\n const contentWatcher =\n menu && typeof MutationObserver !== 'undefined'\n ? new MutationObserver(() => {\n contentDirty.current = true;\n menuResized = true;\n })\n : null;\n if (menu) {\n observer?.observe(menu);\n contentWatcher?.observe(menu, { childList: true, subtree: true, characterData: true });\n }\n return () => {\n cancelAnimationFrame(frame);\n observer?.disconnect();\n contentWatcher?.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, update, triggerRef, menuRef]);\n\n return position;\n};\n"],"names":["useActionMenuPosition","open","triggerRef","menuRef","minWidth","placement","offset","position","setPosition","useState","contentWidth","useRef","contentDirty","useTopLayer","useInsertionEffect","ensureActionMenuStyles","update","useCallback","trigger","
|
|
1
|
+
{"version":3,"file":"useActionMenuPosition.js","sources":["../../src/components/useActionMenuPosition.ts"],"sourcesContent":["import {\n type RefObject,\n useCallback,\n useInsertionEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from 'react';\nimport { TAG_HOST_ATTR, ensureActionMenuStyles } from './actionMenuStyles';\nimport type { ActionMenuPlacement } from './actionMenuTypes';\nimport {\n FLOATING_OFFSET_PX,\n type FloatingOffset,\n MENU_MAX_HEIGHT_PX,\n type MenuGeometry,\n computeFloatingGeometry,\n fullPanelHeight,\n measureContentWidth,\n measureMenuGeometry,\n rectSignature,\n} from './floatingMenuGeometry';\nimport { useTopLayer } from './topLayer';\n\ninterface PositionOptions {\n minWidth?: number;\n placement: ActionMenuPlacement;\n offset?: FloatingOffset;\n}\n\n// A tag renders inside its own shadow root, which neither observer on the menu can see grow.\nconst syncTagHosts = (\n menu: HTMLElement | null,\n observer: ResizeObserver | null,\n watched: Set<Element>,\n) => {\n const present = new Set(menu ? menu.querySelectorAll(`[${TAG_HOST_ATTR}]`) : []);\n watched.forEach((host) => {\n if (!present.has(host)) {\n watched.delete(host);\n observer?.unobserve(host);\n }\n });\n present.forEach((host) => {\n if (!watched.has(host)) {\n watched.add(host);\n observer?.observe(host);\n }\n });\n};\n\nexport const useActionMenuPosition = (\n open: boolean,\n triggerRef: RefObject<HTMLElement | null>,\n menuRef: RefObject<HTMLDivElement | null>,\n { minWidth, placement, offset }: PositionOptions,\n): MenuGeometry | null => {\n const [position, setPosition] = useState<MenuGeometry | null>(null);\n const contentWidth = useRef<number | undefined>(undefined);\n const contentDirty = useRef(true);\n\n useTopLayer(menuRef, open);\n\n useInsertionEffect(() => {\n if (open) {\n ensureActionMenuStyles();\n }\n }, [open]);\n\n const update = useCallback(() => {\n const trigger = triggerRef.current;\n if (!trigger) {\n return;\n }\n const menu = menuRef.current;\n if (menu && contentDirty.current) {\n const inlineWidth = menu.style.width;\n menu.style.width = '';\n contentWidth.current = measureContentWidth(menu) ?? contentWidth.current;\n menu.style.width = inlineWidth;\n contentDirty.current = false;\n }\n const triggerRect = trigger.getBoundingClientRect();\n const geometry = measureMenuGeometry(menu, {\n triggerRect,\n preset: 'options',\n minWidth,\n contentWidth: contentWidth.current,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n if ((placement === 'bottom-end' && offset === undefined) || !menu) {\n setPosition(geometry);\n return;\n }\n const floating = computeFloatingGeometry({\n triggerRect,\n placement,\n panelWidth: geometry.width,\n panelHeight: Math.min(fullPanelHeight(menu), MENU_MAX_HEIGHT_PX),\n gap: FLOATING_OFFSET_PX[offset ?? 'small'],\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n });\n setPosition({\n ...geometry,\n top: floating.top,\n left: floating.left,\n maxHeight: Math.min(MENU_MAX_HEIGHT_PX, floating.maxHeight),\n openUp: floating.side === 'top',\n });\n }, [triggerRef, menuRef, minWidth, placement, offset]);\n\n useLayoutEffect(() => {\n if (!open) {\n setPosition(null);\n contentWidth.current = undefined;\n contentDirty.current = true;\n return;\n }\n contentDirty.current = true;\n update();\n let frame = 0;\n let menuResized = false;\n let lastRect = triggerRef.current\n ? rectSignature(triggerRef.current.getBoundingClientRect())\n : '';\n const followTrigger = () => {\n const trigger = triggerRef.current;\n const signature = trigger ? rectSignature(trigger.getBoundingClientRect()) : '';\n if (signature !== lastRect || menuResized) {\n lastRect = signature;\n menuResized = false;\n update();\n }\n frame = requestAnimationFrame(followTrigger);\n };\n frame = requestAnimationFrame(followTrigger);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n const menu = menuRef.current;\n const observer =\n menu && typeof ResizeObserver !== 'undefined'\n ? new ResizeObserver((entries) => {\n if (entries.some((entry) => entry.target !== menu)) {\n contentDirty.current = true;\n }\n menuResized = true;\n })\n : null;\n const watchedTagHosts = new Set<Element>();\n const watchTagHosts = () => syncTagHosts(menu, observer, watchedTagHosts);\n const contentWatcher =\n menu && typeof MutationObserver !== 'undefined'\n ? new MutationObserver(() => {\n contentDirty.current = true;\n menuResized = true;\n watchTagHosts();\n })\n : null;\n if (menu) {\n observer?.observe(menu);\n watchTagHosts();\n contentWatcher?.observe(menu, { childList: true, subtree: true, characterData: true });\n }\n return () => {\n cancelAnimationFrame(frame);\n observer?.disconnect();\n contentWatcher?.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, update, triggerRef, menuRef]);\n\n return position;\n};\n"],"names":["syncTagHosts","menu","observer","watched","present","TAG_HOST_ATTR","host","useActionMenuPosition","open","triggerRef","menuRef","minWidth","placement","offset","position","setPosition","useState","contentWidth","useRef","contentDirty","useTopLayer","useInsertionEffect","ensureActionMenuStyles","update","useCallback","trigger","inlineWidth","measureContentWidth","triggerRect","geometry","measureMenuGeometry","floating","computeFloatingGeometry","fullPanelHeight","MENU_MAX_HEIGHT_PX","FLOATING_OFFSET_PX","useLayoutEffect","frame","menuResized","lastRect","rectSignature","followTrigger","signature","entries","entry","watchedTagHosts","watchTagHosts","contentWatcher"],"mappings":";;;;AA8BA,MAAMA,IAAe,CACjBC,GACAC,GACAC,MACC;AACD,QAAMC,IAAU,IAAI,IAAIH,IAAOA,EAAK,iBAAiB,IAAII,CAAa,GAAG,IAAI,CAAA,CAAE;AAC/E,EAAAF,EAAQ,QAAQ,CAACG,MAAS;AACtB,IAAKF,EAAQ,IAAIE,CAAI,MACjBH,EAAQ,OAAOG,CAAI,GACnBJ,KAAA,QAAAA,EAAU,UAAUI;AAAA,EAE5B,CAAC,GACDF,EAAQ,QAAQ,CAACE,MAAS;AACtB,IAAKH,EAAQ,IAAIG,CAAI,MACjBH,EAAQ,IAAIG,CAAI,GAChBJ,KAAA,QAAAA,EAAU,QAAQI;AAAA,EAE1B,CAAC;AACL,GAEaC,IAAwB,CACjCC,GACAC,GACAC,GACA,EAAE,UAAAC,GAAU,WAAAC,GAAW,QAAAC,QACD;AACtB,QAAM,CAACC,GAAUC,CAAW,IAAIC,EAA8B,IAAI,GAC5DC,IAAeC,EAA2B,MAAS,GACnDC,IAAeD,EAAO,EAAI;AAEhC,EAAAE,EAAYV,GAASF,CAAI,GAEzBa,EAAmB,MAAM;AACrB,IAAIb,KACAc,EAAA;AAAA,EAER,GAAG,CAACd,CAAI,CAAC;AAET,QAAMe,IAASC,EAAY,MAAM;AAC7B,UAAMC,IAAUhB,EAAW;AAC3B,QAAI,CAACgB;AACD;AAEJ,UAAMxB,IAAOS,EAAQ;AACrB,QAAIT,KAAQkB,EAAa,SAAS;AAC9B,YAAMO,IAAczB,EAAK,MAAM;AAC/B,MAAAA,EAAK,MAAM,QAAQ,IACnBgB,EAAa,UAAUU,EAAoB1B,CAAI,KAAKgB,EAAa,SACjEhB,EAAK,MAAM,QAAQyB,GACnBP,EAAa,UAAU;AAAA,IAC3B;AACA,UAAMS,IAAcH,EAAQ,sBAAA,GACtBI,IAAWC,EAAoB7B,GAAM;AAAA,MACvC,aAAA2B;AAAA,MACA,QAAQ;AAAA,MACR,UAAAjB;AAAA,MACA,cAAcM,EAAa;AAAA,MAC3B,eAAe,OAAO;AAAA,MACtB,gBAAgB,OAAO;AAAA,IAAA,CAC1B;AACD,QAAKL,MAAc,gBAAgBC,MAAW,UAAc,CAACZ,GAAM;AAC/D,MAAAc,EAAYc,CAAQ;AACpB;AAAA,IACJ;AACA,UAAME,IAAWC,EAAwB;AAAA,MACrC,aAAAJ;AAAA,MACA,WAAAhB;AAAA,MACA,YAAYiB,EAAS;AAAA,MACrB,aAAa,KAAK,IAAII,EAAgBhC,CAAI,GAAGiC,CAAkB;AAAA,MAC/D,KAAKC,EAAmBtB,KAAU,OAAO;AAAA,MACzC,eAAe,OAAO;AAAA,MACtB,gBAAgB,OAAO;AAAA,IAAA,CAC1B;AACD,IAAAE,EAAY;AAAA,MACR,GAAGc;AAAA,MACH,KAAKE,EAAS;AAAA,MACd,MAAMA,EAAS;AAAA,MACf,WAAW,KAAK,IAAIG,GAAoBH,EAAS,SAAS;AAAA,MAC1D,QAAQA,EAAS,SAAS;AAAA,IAAA,CAC7B;AAAA,EACL,GAAG,CAACtB,GAAYC,GAASC,GAAUC,GAAWC,CAAM,CAAC;AAErD,SAAAuB,EAAgB,MAAM;AAClB,QAAI,CAAC5B,GAAM;AACP,MAAAO,EAAY,IAAI,GAChBE,EAAa,UAAU,QACvBE,EAAa,UAAU;AACvB;AAAA,IACJ;AACA,IAAAA,EAAa,UAAU,IACvBI,EAAA;AACA,QAAIc,IAAQ,GACRC,IAAc,IACdC,IAAW9B,EAAW,UACpB+B,EAAc/B,EAAW,QAAQ,sBAAA,CAAuB,IACxD;AACN,UAAMgC,IAAgB,MAAM;AACxB,YAAMhB,IAAUhB,EAAW,SACrBiC,IAAYjB,IAAUe,EAAcf,EAAQ,sBAAA,CAAuB,IAAI;AAC7E,OAAIiB,MAAcH,KAAYD,OAC1BC,IAAWG,GACXJ,IAAc,IACdf,EAAA,IAEJc,IAAQ,sBAAsBI,CAAa;AAAA,IAC/C;AACA,IAAAJ,IAAQ,sBAAsBI,CAAa,GAC3C,OAAO,iBAAiB,UAAUlB,GAAQ,EAAI,GAC9C,OAAO,iBAAiB,UAAUA,CAAM;AACxC,UAAMtB,IAAOS,EAAQ,SACfR,IACFD,KAAQ,OAAO,iBAAmB,MAC5B,IAAI,eAAe,CAAC0C,MAAY;AAC5B,MAAIA,EAAQ,KAAK,CAACC,MAAUA,EAAM,WAAW3C,CAAI,MAC7CkB,EAAa,UAAU,KAE3BmB,IAAc;AAAA,IAClB,CAAC,IACD,MACJO,wBAAsB,IAAA,GACtBC,IAAgB,MAAM9C,EAAaC,GAAMC,GAAU2C,CAAe,GAClEE,IACF9C,KAAQ,OAAO,mBAAqB,MAC9B,IAAI,iBAAiB,MAAM;AACvB,MAAAkB,EAAa,UAAU,IACvBmB,IAAc,IACdQ,EAAA;AAAA,IACJ,CAAC,IACD;AACV,WAAI7C,MACAC,KAAA,QAAAA,EAAU,QAAQD,IAClB6C,EAAA,GACAC,KAAA,QAAAA,EAAgB,QAAQ9C,GAAM,EAAE,WAAW,IAAM,SAAS,IAAM,eAAe,QAE5E,MAAM;AACT,2BAAqBoC,CAAK,GAC1BnC,KAAA,QAAAA,EAAU,cACV6C,KAAA,QAAAA,EAAgB,cAChB,OAAO,oBAAoB,UAAUxB,GAAQ,EAAI,GACjD,OAAO,oBAAoB,UAAUA,CAAM;AAAA,IAC/C;AAAA,EACJ,GAAG,CAACf,GAAMe,GAAQd,GAAYC,CAAO,CAAC,GAE/BI;AACX;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -105,6 +105,13 @@ export declare type ActionMenuItem = {
|
|
|
105
105
|
danger?: boolean;
|
|
106
106
|
tooltip?: string;
|
|
107
107
|
icon?: default_2.ReactNode;
|
|
108
|
+
/** Rendered after the label in its own styled host, e.g. a malachite `Tag`. Its text
|
|
109
|
+
* joins the item's accessible name. Non-interactive content only: the item is a
|
|
110
|
+
* `<button>`, so a control inside it (a removable `Tag`'s button) would be nested. */
|
|
111
|
+
tag?: default_2.ReactNode;
|
|
112
|
+
/** Marks the item for the page the user is on: `aria-current="page"` and the selected
|
|
113
|
+
* row paint. A `danger` item keeps its red text. */
|
|
114
|
+
current?: boolean;
|
|
108
115
|
} | {
|
|
109
116
|
type: 'text';
|
|
110
117
|
key: string;
|