@brycks/core-front 0.3.2 → 0.3.4
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/feedback/Alert/Alert.cjs +1 -1
- package/dist/components/feedback/Alert/Alert.cjs.map +1 -1
- package/dist/components/feedback/Alert/Alert.js +52 -177
- package/dist/components/feedback/Alert/Alert.js.map +1 -1
- package/dist/components/feedback/Modal/Modal.cjs +1 -1
- package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
- package/dist/components/feedback/Modal/Modal.js +7 -6
- package/dist/components/feedback/Modal/Modal.js.map +1 -1
- package/dist/components/form/Checkbox/Checkbox.cjs +1 -1
- package/dist/components/form/Checkbox/Checkbox.js +12 -12
- package/dist/components/form/Input/Input.cjs +1 -1
- package/dist/components/form/Input/Input.js +13 -13
- package/dist/components/form/Slider/Slider.cjs +1 -1
- package/dist/components/form/Slider/Slider.js +1 -1
- package/dist/components/form/Switch/Switch.cjs +1 -1
- package/dist/components/form/Switch/Switch.cjs.map +1 -1
- package/dist/components/form/Switch/Switch.js +70 -105
- package/dist/components/form/Switch/Switch.js.map +1 -1
- package/dist/components/layout/Card/Card.cjs +1 -1
- package/dist/components/layout/Card/Card.cjs.map +1 -1
- package/dist/components/layout/Card/Card.js +59 -121
- package/dist/components/layout/Card/Card.js.map +1 -1
- package/dist/components/navigation/Dropdown/Dropdown.cjs +1 -6
- package/dist/components/navigation/Dropdown/Dropdown.cjs.map +1 -1
- package/dist/components/navigation/Dropdown/Dropdown.js +118 -183
- package/dist/components/navigation/Dropdown/Dropdown.js.map +1 -1
- package/dist/components/navigation/Menu/Menu.cjs +1 -1
- package/dist/components/navigation/Menu/Menu.js +5 -5
- package/dist/components/navigation/Tabs/Tabs.cjs +1 -6
- package/dist/components/navigation/Tabs/Tabs.cjs.map +1 -1
- package/dist/components/navigation/Tabs/Tabs.js +92 -162
- package/dist/components/navigation/Tabs/Tabs.js.map +1 -1
- package/dist/components/primitives/Button/Button.cjs +1 -1
- package/dist/components/primitives/Button/Button.cjs.map +1 -1
- package/dist/components/primitives/Button/Button.js +72 -96
- package/dist/components/primitives/Button/Button.js.map +1 -1
- package/dist/components/primitives/Button/Button.styles.cjs +1 -1
- package/dist/components/primitives/Button/Button.styles.cjs.map +1 -1
- package/dist/components/primitives/Button/Button.styles.js +8 -317
- package/dist/components/primitives/Button/Button.styles.js.map +1 -1
- package/dist/components/utility/Badge/Badge.cjs +1 -1
- package/dist/components/utility/Badge/Badge.cjs.map +1 -1
- package/dist/components/utility/Badge/Badge.js +23 -80
- package/dist/components/utility/Badge/Badge.js.map +1 -1
- package/dist/feedback.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.cjs","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n */\n\nimport { forwardRef, useCallback, type CSSProperties, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, durations, easings } from '../../../design-system'\nimport { componentGap } from '../../../design-system/primitives'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nconst paddingMap: Record<CardPadding, number> = {\n none: 0,\n sm: spacing[3],\n md: spacing[4],\n lg: spacing[6],\n xl: spacing[8],\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'elevated',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const getVariantStyles = (): CSSProperties => {\n const transitionValue = `transform ${durations.quick}ms ${easings.easeOut}, box-shadow ${durations.quick}ms ${easings.easeOut}, border-color ${durations.quick}ms ${easings.easeOut}`\n const base: CSSProperties = {\n borderRadius: 'var(--brycks-radius-lg)',\n transition: transitionValue,\n }\n\n switch (variant) {\n case 'elevated':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-elevated)',\n boxShadow: selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)'\n : 'var(--brycks-shadow-md)',\n border: '1px solid var(--brycks-border-subtle)',\n }\n case 'outline':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-default)',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid var(--brycks-border-default)',\n }\n case 'filled':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-muted)',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid transparent',\n }\n case 'ghost':\n return {\n ...base,\n backgroundColor: 'transparent',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid transparent',\n }\n }\n }\n\n const cardStyle: CSSProperties = {\n ...getVariantStyles(),\n padding: paddingMap[padding],\n display: 'flex',\n flexDirection: 'column',\n cursor: interactive ? 'pointer' : undefined,\n ...style,\n }\n\n const handleMouseEnter = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.currentTarget\n if (variant === 'elevated') {\n target.style.boxShadow = selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-lg)'\n : 'var(--brycks-shadow-lg)'\n target.style.transform = 'translateY(-2px)'\n } else if (variant !== 'ghost') {\n target.style.borderColor = 'var(--brycks-border-strong)'\n }\n }, [variant, selected])\n\n const handleMouseLeave = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.currentTarget\n if (variant === 'elevated') {\n target.style.boxShadow = selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)'\n : 'var(--brycks-shadow-md)'\n target.style.transform = 'translateY(0)'\n } else if (variant !== 'ghost') {\n target.style.borderColor = selected\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-border-default)'\n }\n }, [variant, selected])\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={cardStyle}\n data-testid={testId}\n onMouseEnter={\n interactive\n ? handleMouseEnter\n : undefined\n }\n onMouseLeave={\n interactive\n ? handleMouseLeave\n : undefined\n }\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: componentGap.xl,\n paddingBottom: divider ? spacing[4] : 0,\n marginBottom: divider ? spacing[4] : spacing[3],\n borderBottom: divider ? '1px solid var(--brycks-border-muted)' : undefined,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-header', className)} style={headerStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n const bodyStyle: CSSProperties = {\n flex: 1,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-body', className)} style={bodyStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n const alignMap: Record<string, CSSProperties['justifyContent']> = {\n left: 'flex-start',\n center: 'center',\n right: 'flex-end',\n between: 'space-between',\n }\n\n const footerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: alignMap[align],\n gap: componentGap.xl,\n paddingTop: divider ? spacing[4] : 0,\n marginTop: divider ? spacing[4] : spacing[3],\n borderTop: divider ? '1px solid var(--brycks-border-muted)' : undefined,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-footer', className)} style={footerStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["paddingMap","spacing","Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","cardStyle","base","durations","easings","handleMouseEnter","useCallback","e","target","handleMouseLeave","jsx","cx","CardHeader","divider","headerStyle","componentGap","CardBody","bodyStyle","CardFooter","align","footerStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Card.cjs","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n *\n * All color styles are handled via CSS classes for easy customization.\n */\n\nimport { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'elevated',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n `brycks-card--padding-${padding}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={style}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx('brycks-card__header', divider && 'brycks-card__header--divider', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n return (\n <div ref={ref} className={cx('brycks-card__body', className)} style={style} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card__footer',\n divider && 'brycks-card__footer--divider',\n `brycks-card__footer--${align}`,\n className\n )}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","jsx","cx","CardHeader","divider","CardBody","CardFooter","align"],"mappings":"+KAmDaA,EAAOC,EAAAA,WAAsC,SACxD,CACE,QAAAC,EAAU,WACV,QAAAC,EAAU,KACV,YAAAC,EAAc,GACd,SAAAC,EAAW,GACX,UAAAC,EACA,MAAAC,EACA,SAAAC,EACA,OAAAC,EACA,GAAGC,CACL,EACAC,EACA,CACA,OACEC,EAAAA,IAAC,MAAA,CACC,IAAAD,EACA,UAAWE,EAAAA,GACT,cACA,gBAAgBX,CAAO,GACvB,wBAAwBC,CAAO,GAC/BC,GAAe,2BACfC,GAAY,wBACZC,CAAA,EAEF,MAAAC,EACA,cAAaE,EACZ,GAAGC,EAEH,SAAAF,CAAA,CAAA,CAGP,CAAC,EAEDR,EAAK,YAAc,OAEZ,MAAMc,EAAab,EAAAA,WAA4C,SACpE,CAAE,QAAAc,EAAU,GAAO,UAAAT,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAGE,CAAA,EAClDC,EACA,CACA,OACEC,EAAAA,IAAC,MAAA,CACC,IAAAD,EACA,UAAWE,EAAAA,GAAG,sBAAuBE,GAAW,+BAAgCT,CAAS,EACzF,MAAAC,EACC,GAAGG,EAEH,SAAAF,CAAA,CAAA,CAGP,CAAC,EAEDM,EAAW,YAAc,aAElB,MAAME,EAAWf,EAAAA,WAA0C,SAChE,CAAE,UAAAK,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAGE,CAAA,EACjCC,EACA,CACA,OACEC,EAAAA,IAAC,MAAA,CAAI,IAAAD,EAAU,UAAWE,EAAAA,GAAG,oBAAqBP,CAAS,EAAG,MAAAC,EAAe,GAAGG,EAC7E,SAAAF,CAAA,CACH,CAEJ,CAAC,EAEDQ,EAAS,YAAc,WAEhB,MAAMC,EAAahB,EAAAA,WAA4C,SACpE,CAAE,QAAAc,EAAU,GAAO,MAAAG,EAAQ,QAAS,UAAAZ,EAAW,MAAAC,EAAO,SAAAC,EAAU,GAAGE,CAAA,EACnEC,EACA,CACA,OACEC,EAAAA,IAAC,MAAA,CACC,IAAAD,EACA,UAAWE,EAAAA,GACT,sBACAE,GAAW,+BACX,wBAAwBG,CAAK,GAC7BZ,CAAA,EAEF,MAAAC,EACC,GAAGG,EAEH,SAAAF,CAAA,CAAA,CAGP,CAAC,EAEDS,EAAW,YAAc"}
|
|
@@ -1,138 +1,76 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { forwardRef as
|
|
1
|
+
import { jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as t } from "react";
|
|
3
3
|
import { cx as i } from "../../../utils/styles.js";
|
|
4
|
-
|
|
5
|
-
import { durations as m, easings as f } from "../../../design-system/tokens/motion.js";
|
|
6
|
-
import { spacing as s } from "../../../design-system/tokens/spacing.js";
|
|
7
|
-
const S = {
|
|
8
|
-
none: 0,
|
|
9
|
-
sm: s[3],
|
|
10
|
-
md: s[4],
|
|
11
|
-
lg: s[6],
|
|
12
|
-
xl: s[8]
|
|
13
|
-
}, N = b(function({
|
|
4
|
+
const b = t(function({
|
|
14
5
|
variant: r = "elevated",
|
|
15
|
-
padding:
|
|
16
|
-
interactive:
|
|
17
|
-
selected:
|
|
18
|
-
className:
|
|
19
|
-
style:
|
|
20
|
-
children:
|
|
21
|
-
testId:
|
|
22
|
-
...
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
...(() => {
|
|
26
|
-
const o = {
|
|
27
|
-
borderRadius: "var(--brycks-radius-lg)",
|
|
28
|
-
transition: `transform ${m.quick}ms ${f.easeOut}, box-shadow ${m.quick}ms ${f.easeOut}, border-color ${m.quick}ms ${f.easeOut}`
|
|
29
|
-
};
|
|
30
|
-
switch (r) {
|
|
31
|
-
case "elevated":
|
|
32
|
-
return {
|
|
33
|
-
...o,
|
|
34
|
-
backgroundColor: "var(--brycks-background-elevated)",
|
|
35
|
-
boxShadow: a ? "0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)" : "var(--brycks-shadow-md)",
|
|
36
|
-
border: "1px solid var(--brycks-border-subtle)"
|
|
37
|
-
};
|
|
38
|
-
case "outline":
|
|
39
|
-
return {
|
|
40
|
-
...o,
|
|
41
|
-
backgroundColor: "var(--brycks-background-default)",
|
|
42
|
-
border: a ? "2px solid var(--brycks-primary-default)" : "1px solid var(--brycks-border-default)"
|
|
43
|
-
};
|
|
44
|
-
case "filled":
|
|
45
|
-
return {
|
|
46
|
-
...o,
|
|
47
|
-
backgroundColor: "var(--brycks-background-muted)",
|
|
48
|
-
border: a ? "2px solid var(--brycks-primary-default)" : "1px solid transparent"
|
|
49
|
-
};
|
|
50
|
-
case "ghost":
|
|
51
|
-
return {
|
|
52
|
-
...o,
|
|
53
|
-
backgroundColor: "transparent",
|
|
54
|
-
border: a ? "2px solid var(--brycks-primary-default)" : "1px solid transparent"
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
})(),
|
|
58
|
-
padding: S[t],
|
|
59
|
-
display: "flex",
|
|
60
|
-
flexDirection: "column",
|
|
61
|
-
cursor: e ? "pointer" : void 0,
|
|
62
|
-
...n
|
|
63
|
-
}, h = g((c) => {
|
|
64
|
-
const o = c.currentTarget;
|
|
65
|
-
r === "elevated" ? (o.style.boxShadow = a ? "0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-lg)" : "var(--brycks-shadow-lg)", o.style.transform = "translateY(-2px)") : r !== "ghost" && (o.style.borderColor = "var(--brycks-border-strong)");
|
|
66
|
-
}, [r, a]), w = g((c) => {
|
|
67
|
-
const o = c.currentTarget;
|
|
68
|
-
r === "elevated" ? (o.style.boxShadow = a ? "0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)" : "var(--brycks-shadow-md)", o.style.transform = "translateY(0)") : r !== "ghost" && (o.style.borderColor = a ? "var(--brycks-primary-default)" : "var(--brycks-border-default)");
|
|
69
|
-
}, [r, a]);
|
|
70
|
-
return /* @__PURE__ */ y(
|
|
6
|
+
padding: a = "md",
|
|
7
|
+
interactive: d = !1,
|
|
8
|
+
selected: e = !1,
|
|
9
|
+
className: c,
|
|
10
|
+
style: s,
|
|
11
|
+
children: n,
|
|
12
|
+
testId: f,
|
|
13
|
+
...m
|
|
14
|
+
}, l) {
|
|
15
|
+
return /* @__PURE__ */ o(
|
|
71
16
|
"div",
|
|
72
17
|
{
|
|
73
|
-
ref:
|
|
18
|
+
ref: l,
|
|
74
19
|
className: i(
|
|
75
20
|
"brycks-card",
|
|
76
21
|
`brycks-card--${r}`,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
22
|
+
`brycks-card--padding-${a}`,
|
|
23
|
+
d && "brycks-card--interactive",
|
|
24
|
+
e && "brycks-card--selected",
|
|
25
|
+
c
|
|
80
26
|
),
|
|
81
|
-
style:
|
|
82
|
-
"data-testid":
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
...p,
|
|
86
|
-
children: l
|
|
27
|
+
style: s,
|
|
28
|
+
"data-testid": f,
|
|
29
|
+
...m,
|
|
30
|
+
children: n
|
|
87
31
|
}
|
|
88
32
|
);
|
|
89
33
|
});
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return /* @__PURE__ */ y("div", { ref: n, className: i("brycks-card-header", t), style: l, ...d, children: a });
|
|
34
|
+
b.displayName = "Card";
|
|
35
|
+
const C = t(function({ divider: r = !1, className: a, style: d, children: e, ...c }, s) {
|
|
36
|
+
return /* @__PURE__ */ o(
|
|
37
|
+
"div",
|
|
38
|
+
{
|
|
39
|
+
ref: s,
|
|
40
|
+
className: i("brycks-card__header", r && "brycks-card__header--divider", a),
|
|
41
|
+
style: d,
|
|
42
|
+
...c,
|
|
43
|
+
children: e
|
|
44
|
+
}
|
|
45
|
+
);
|
|
103
46
|
});
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
flex: 1,
|
|
108
|
-
...t
|
|
109
|
-
};
|
|
110
|
-
return /* @__PURE__ */ y("div", { ref: d, className: i("brycks-card-body", r), style: n, ...a, children: e });
|
|
47
|
+
C.displayName = "CardHeader";
|
|
48
|
+
const _ = t(function({ className: r, style: a, children: d, ...e }, c) {
|
|
49
|
+
return /* @__PURE__ */ o("div", { ref: c, className: i("brycks-card__body", r), style: a, ...e, children: d });
|
|
111
50
|
});
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return /* @__PURE__ */ y("div", { ref: l, className: i("brycks-card-footer", e), style: p, ...n, children: d });
|
|
51
|
+
_.displayName = "CardBody";
|
|
52
|
+
const k = t(function({ divider: r = !1, align: a = "right", className: d, style: e, children: c, ...s }, n) {
|
|
53
|
+
return /* @__PURE__ */ o(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
ref: n,
|
|
57
|
+
className: i(
|
|
58
|
+
"brycks-card__footer",
|
|
59
|
+
r && "brycks-card__footer--divider",
|
|
60
|
+
`brycks-card__footer--${a}`,
|
|
61
|
+
d
|
|
62
|
+
),
|
|
63
|
+
style: e,
|
|
64
|
+
...s,
|
|
65
|
+
children: c
|
|
66
|
+
}
|
|
67
|
+
);
|
|
130
68
|
});
|
|
131
|
-
|
|
69
|
+
k.displayName = "CardFooter";
|
|
132
70
|
export {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
71
|
+
b as Card,
|
|
72
|
+
_ as CardBody,
|
|
73
|
+
k as CardFooter,
|
|
74
|
+
C as CardHeader
|
|
137
75
|
};
|
|
138
76
|
//# sourceMappingURL=Card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.js","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n */\n\nimport { forwardRef, useCallback, type CSSProperties, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, durations, easings } from '../../../design-system'\nimport { componentGap } from '../../../design-system/primitives'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nconst paddingMap: Record<CardPadding, number> = {\n none: 0,\n sm: spacing[3],\n md: spacing[4],\n lg: spacing[6],\n xl: spacing[8],\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'elevated',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const getVariantStyles = (): CSSProperties => {\n const transitionValue = `transform ${durations.quick}ms ${easings.easeOut}, box-shadow ${durations.quick}ms ${easings.easeOut}, border-color ${durations.quick}ms ${easings.easeOut}`\n const base: CSSProperties = {\n borderRadius: 'var(--brycks-radius-lg)',\n transition: transitionValue,\n }\n\n switch (variant) {\n case 'elevated':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-elevated)',\n boxShadow: selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)'\n : 'var(--brycks-shadow-md)',\n border: '1px solid var(--brycks-border-subtle)',\n }\n case 'outline':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-default)',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid var(--brycks-border-default)',\n }\n case 'filled':\n return {\n ...base,\n backgroundColor: 'var(--brycks-background-muted)',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid transparent',\n }\n case 'ghost':\n return {\n ...base,\n backgroundColor: 'transparent',\n border: selected\n ? '2px solid var(--brycks-primary-default)'\n : '1px solid transparent',\n }\n }\n }\n\n const cardStyle: CSSProperties = {\n ...getVariantStyles(),\n padding: paddingMap[padding],\n display: 'flex',\n flexDirection: 'column',\n cursor: interactive ? 'pointer' : undefined,\n ...style,\n }\n\n const handleMouseEnter = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.currentTarget\n if (variant === 'elevated') {\n target.style.boxShadow = selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-lg)'\n : 'var(--brycks-shadow-lg)'\n target.style.transform = 'translateY(-2px)'\n } else if (variant !== 'ghost') {\n target.style.borderColor = 'var(--brycks-border-strong)'\n }\n }, [variant, selected])\n\n const handleMouseLeave = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const target = e.currentTarget\n if (variant === 'elevated') {\n target.style.boxShadow = selected\n ? '0 0 0 2px var(--brycks-primary-default), var(--brycks-shadow-md)'\n : 'var(--brycks-shadow-md)'\n target.style.transform = 'translateY(0)'\n } else if (variant !== 'ghost') {\n target.style.borderColor = selected\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-border-default)'\n }\n }, [variant, selected])\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={cardStyle}\n data-testid={testId}\n onMouseEnter={\n interactive\n ? handleMouseEnter\n : undefined\n }\n onMouseLeave={\n interactive\n ? handleMouseLeave\n : undefined\n }\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: componentGap.xl,\n paddingBottom: divider ? spacing[4] : 0,\n marginBottom: divider ? spacing[4] : spacing[3],\n borderBottom: divider ? '1px solid var(--brycks-border-muted)' : undefined,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-header', className)} style={headerStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n const bodyStyle: CSSProperties = {\n flex: 1,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-body', className)} style={bodyStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n const alignMap: Record<string, CSSProperties['justifyContent']> = {\n left: 'flex-start',\n center: 'center',\n right: 'flex-end',\n between: 'space-between',\n }\n\n const footerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: alignMap[align],\n gap: componentGap.xl,\n paddingTop: divider ? spacing[4] : 0,\n marginTop: divider ? spacing[4] : spacing[3],\n borderTop: divider ? '1px solid var(--brycks-border-muted)' : undefined,\n ...style,\n }\n\n return (\n <div ref={ref} className={cx('brycks-card-footer', className)} style={footerStyle} {...props}>\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["paddingMap","spacing","Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","cardStyle","base","durations","easings","handleMouseEnter","useCallback","e","target","handleMouseLeave","jsx","cx","CardHeader","divider","headerStyle","componentGap","CardBody","bodyStyle","CardFooter","align","footerStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Card.js","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n *\n * All color styles are handled via CSS classes for easy customization.\n */\n\nimport { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'elevated',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n `brycks-card--padding-${padding}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={style}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx('brycks-card__header', divider && 'brycks-card__header--divider', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n return (\n <div ref={ref} className={cx('brycks-card__body', className)} style={style} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card__footer',\n divider && 'brycks-card__footer--divider',\n `brycks-card__footer--${align}`,\n className\n )}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","jsx","cx","CardHeader","divider","CardBody","CardFooter","align"],"mappings":";;;AAmDO,MAAMA,IAAOC,EAAsC,SACxD;AAAA,EACE,SAAAC,IAAU;AAAA,EACV,SAAAC,IAAU;AAAA,EACV,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACA,gBAAgBX,CAAO;AAAA,QACvB,wBAAwBC,CAAO;AAAA,QAC/BC,KAAe;AAAA,QACfC,KAAY;AAAA,QACZC;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACA,eAAaE;AAAA,MACZ,GAAGC;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDR,EAAK,cAAc;AAEZ,MAAMc,IAAab,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,WAAAT,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GAClDC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE,EAAG,uBAAuBE,KAAW,gCAAgCT,CAAS;AAAA,MACzF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDM,EAAW,cAAc;AAElB,MAAME,IAAWf,EAA0C,SAChE,EAAE,WAAAK,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACjCC,GACA;AACA,SACE,gBAAAC,EAAC,OAAA,EAAI,KAAAD,GAAU,WAAWE,EAAG,qBAAqBP,CAAS,GAAG,OAAAC,GAAe,GAAGG,GAC7E,UAAAF,EAAA,CACH;AAEJ,CAAC;AAEDQ,EAAS,cAAc;AAEhB,MAAMC,IAAahB,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,OAAAG,IAAQ,SAAS,WAAAZ,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACnEC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACAE,KAAW;AAAA,QACX,wBAAwBG,CAAK;AAAA,QAC7BZ;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDS,EAAW,cAAc;"}
|
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
-
@keyframes brycks-dropdown-in {
|
|
3
|
-
from { opacity: 0; transform: translateY(-4px); }
|
|
4
|
-
to { opacity: 1; transform: translateY(0); }
|
|
5
|
-
}
|
|
6
|
-
`}),a.jsx("div",{ref:k,role:"menu",style:J,onKeyDown:A,tabIndex:-1,children:C})]}),document.body)]})})});K.displayName="Dropdown";const M=r.forwardRef(function({disabled:t=!1,icon:c,shortcut:l,destructive:d=!1,className:i,style:m,children:D,onClick:h,...S},C){const{close:E}=V(),j=n=>{t||(h?.(n),E())},z={display:"flex",alignItems:"center",gap:f.componentGap.lg,padding:`${f.componentPaddingY.md}px ${f.componentPaddingX.sm}px`,fontSize:$.fontSizes.base,color:t?"var(--brycks-foreground-disabled)":d?"var(--brycks-error-default)":"var(--brycks-foreground-default)",backgroundColor:"transparent",borderRadius:"var(--brycks-radius-md)",cursor:t?"not-allowed":"pointer",transition:`background-color ${v.durations.fast}ms ${v.easings.easeOut}`,outline:"none",...m},R={width:f.iconSizes.sm,height:f.iconSizes.sm,color:t?"var(--brycks-foreground-disabled)":d?"var(--brycks-error-default)":"var(--brycks-foreground-muted)",flexShrink:0},I={marginLeft:"auto",fontSize:$.fontSizes.sm,color:"var(--brycks-foreground-muted)",fontFamily:"var(--brycks-font-mono)"};return a.jsxs("div",{ref:C,role:"menuitem","aria-disabled":t,tabIndex:t?-1:0,className:x.cx("brycks-dropdown-item",t&&"brycks-dropdown-item--disabled",i),style:z,onClick:j,onMouseEnter:n=>{t||(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},onFocus:n=>{n.currentTarget.style.backgroundColor="var(--brycks-background-muted)"},onBlur:n=>{n.currentTarget.style.backgroundColor="transparent"},...S,children:[c&&a.jsx("span",{style:R,children:c}),a.jsx("span",{style:{flex:1},children:D}),l&&a.jsx("span",{style:I,children:l})]})});M.displayName="DropdownItem";const F=r.forwardRef(function({className:t,style:c,...l},d){const i={height:1,backgroundColor:"var(--brycks-border-muted)",margin:`${N.spacing[1]}px 0`,...c};return a.jsx("div",{ref:d,role:"separator",className:x.cx("brycks-dropdown-divider",t),style:i,...l})});F.displayName="DropdownDivider";const B=r.forwardRef(function({className:t,style:c,children:l,...d},i){const m={padding:`${f.componentPaddingY.md}px ${f.componentPaddingX.sm}px ${N.spacing[1]}px ${f.componentPaddingX.sm}px`,fontSize:$.fontSizes.xs,fontWeight:600,color:"var(--brycks-foreground-muted)",textTransform:"uppercase",letterSpacing:"0.05em",...c};return a.jsx("div",{ref:i,className:x.cx("brycks-dropdown-label",t),style:m,...d,children:l})});B.displayName="DropdownLabel";exports.Dropdown=K;exports.DropdownDivider=F;exports.DropdownItem=M;exports.DropdownLabel=B;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),t=require("react"),U=require("react-dom"),v=require("../../../utils/styles.cjs"),A=t.createContext(null);function F(){const w=t.useContext(A);if(!w)throw new Error("Dropdown components must be used within a Dropdown");return w}const P=t.forwardRef(function({trigger:o,isOpen:s,defaultOpen:a=!1,onOpenChange:d,placement:i="bottom-start",offset:D=4,closeOnSelect:y=!0,className:k,style:h,children:x,testId:g,...E},C){const[M,X]=t.useState(a),[N,Y]=t.useState({top:0,left:0}),[f,p]=t.useState(-1),[j,L]=t.useState(!1),m=t.useRef(null),b=t.useRef(null),n=s??M;t.useEffect(()=>(L(!0),()=>L(!1)),[]);const l=t.useCallback(e=>{s===void 0&&X(e),d?.(e),e||p(-1)},[s,d]),B=t.useCallback(()=>l(!1),[l]);t.useEffect(()=>{if(!n||!m.current||!j)return;const e=()=>{const r=m.current;if(!r)return;const u=r.getBoundingClientRect(),W=window.scrollX,q=window.scrollY;let R=0,I=0;i.startsWith("bottom")?R=u.bottom+q+D:R=u.top+q-D,i.endsWith("start")?I=u.left+W:I=u.right+W,Y({top:R,left:I})};return e(),window.addEventListener("resize",e),window.addEventListener("scroll",e,!0),()=>{window.removeEventListener("resize",e),window.removeEventListener("scroll",e,!0)}},[n,i,D,j]),t.useEffect(()=>{if(!n)return;const e=r=>{m.current?.contains(r.target)||b.current?.contains(r.target)||l(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[n,l]);const S=t.useCallback(e=>{if(!n){(e.key==="ArrowDown"||e.key==="Enter"||e.key===" ")&&(e.preventDefault(),l(!0));return}const r=b.current?.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])');if(r?.length)switch(e.key){case"ArrowDown":e.preventDefault(),p(u=>(u+1)%r.length);break;case"ArrowUp":e.preventDefault(),p(u=>(u-1+r.length)%r.length);break;case"Home":e.preventDefault(),p(0);break;case"End":e.preventDefault(),p(r.length-1);break;case"Escape":e.preventDefault(),l(!1),m.current?.focus();break;case"Enter":case" ":e.preventDefault(),f>=0&&r[f]?.click();break}},[n,f,l]);t.useEffect(()=>{if(!n||f<0)return;b.current?.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])')?.[f]?.focus()},[n,f]);const _=o.props,H=t.cloneElement(o,{ref:m,"aria-haspopup":"menu","aria-expanded":n,onClick:e=>{_.onClick?.(e),l(!n)},onKeyDown:e=>{_.onKeyDown?.(e),S(e)}}),T={position:"absolute",top:N.top,left:i.endsWith("end")?"auto":N.left,right:i.endsWith("end")?window.innerWidth-N.left:"auto",minWidth:m.current?.offsetWidth??160,...h};return c.jsx(A.Provider,{value:{isOpen:n,close:y?B:()=>{},activeIndex:f,setActiveIndex:p},children:c.jsxs("div",{ref:C,className:v.cx("brycks-dropdown",k),"data-testid":g,...E,children:[H,n&&j&&U.createPortal(c.jsx("div",{ref:b,role:"menu",className:"brycks-dropdown__menu",style:T,onKeyDown:S,tabIndex:-1,children:x}),document.body)]})})});P.displayName="Dropdown";const K=t.forwardRef(function({disabled:o=!1,icon:s,shortcut:a,destructive:d=!1,className:i,style:D,children:y,onClick:k,...h},x){const{close:g}=F(),E=C=>{o||(k?.(C),g())};return c.jsxs("div",{ref:x,role:"menuitem","aria-disabled":o,tabIndex:o?-1:0,className:v.cx("brycks-dropdown-item",o&&"brycks-dropdown-item--disabled",d&&"brycks-dropdown-item--destructive",i),style:D,onClick:E,...h,children:[s&&c.jsx("span",{className:"brycks-dropdown-item__icon",children:s}),c.jsx("span",{className:"brycks-dropdown-item__label",children:y}),a&&c.jsx("span",{className:"brycks-dropdown-item__shortcut",children:a})]})});K.displayName="DropdownItem";const O=t.forwardRef(function({className:o,style:s,...a},d){return c.jsx("div",{ref:d,role:"separator",className:v.cx("brycks-dropdown-divider",o),style:s,...a})});O.displayName="DropdownDivider";const z=t.forwardRef(function({className:o,style:s,children:a,...d},i){return c.jsx("div",{ref:i,className:v.cx("brycks-dropdown-label",o),style:s,...d,children:a})});z.displayName="DropdownLabel";exports.Dropdown=P;exports.DropdownDivider=O;exports.DropdownItem=K;exports.DropdownLabel=z;
|
|
7
2
|
//# sourceMappingURL=Dropdown.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dropdown.cjs","sources":["../../../../src/components/navigation/Dropdown/Dropdown.tsx"],"sourcesContent":["/**\n * Dropdown Component\n *\n * A dropdown menu with keyboard navigation support.\n * Can be used for actions, navigation, or selection.\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n cloneElement,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type ReactElement,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type DropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'\n\ninterface DropdownContextValue {\n isOpen: boolean\n close: () => void\n activeIndex: number\n setActiveIndex: (index: number) => void\n}\n\nconst DropdownContext = createContext<DropdownContextValue | null>(null)\n\nfunction useDropdownContext() {\n const context = useContext(DropdownContext)\n if (!context) {\n throw new Error('Dropdown components must be used within a Dropdown')\n }\n return context\n}\n\nexport interface DropdownProps extends HTMLAttributes<HTMLDivElement> {\n /** Trigger element */\n trigger: ReactElement\n /** Whether the dropdown is open (controlled) */\n isOpen?: boolean\n /** Default open state (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void\n /** Dropdown placement */\n placement?: DropdownPlacement\n /** Offset from trigger */\n offset?: number\n /** Whether to close on item select */\n closeOnSelect?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(function Dropdown(\n {\n trigger,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n placement = 'bottom-start',\n offset = 4,\n closeOnSelect = true,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultOpen)\n const [position, setPosition] = useState({ top: 0, left: 0 })\n const [activeIndex, setActiveIndex] = useState(-1)\n const [mounted, setMounted] = useState(false)\n const triggerRef = useRef<HTMLElement>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n\n const isOpen = controlledIsOpen ?? internalIsOpen\n\n useEffect(() => {\n setMounted(true)\n return () => setMounted(false)\n }, [])\n\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open)\n }\n onOpenChange?.(open)\n if (!open) {\n setActiveIndex(-1)\n }\n },\n [controlledIsOpen, onOpenChange]\n )\n\n const close = useCallback(() => setIsOpen(false), [setIsOpen])\n\n // Calculate position\n useEffect(() => {\n if (!isOpen || !triggerRef.current || !mounted) return\n\n const updatePosition = () => {\n const trigger = triggerRef.current\n if (!trigger) return\n\n const rect = trigger.getBoundingClientRect()\n const scrollX = window.scrollX\n const scrollY = window.scrollY\n\n let top = 0\n let left = 0\n\n if (placement.startsWith('bottom')) {\n top = rect.bottom + scrollY + offset\n } else {\n top = rect.top + scrollY - offset\n }\n\n if (placement.endsWith('start')) {\n left = rect.left + scrollX\n } else {\n left = rect.right + scrollX\n }\n\n setPosition({ top, left })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen, placement, offset, mounted])\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return\n\n const handleClick = (e: MouseEvent) => {\n if (\n triggerRef.current?.contains(e.target as Node) ||\n menuRef.current?.contains(e.target as Node)\n ) {\n return\n }\n setIsOpen(false)\n }\n\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, setIsOpen])\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setIsOpen(true)\n }\n return\n }\n\n const items = menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')\n if (!items?.length) return\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setActiveIndex((prev) => (prev + 1) % items.length)\n break\n case 'ArrowUp':\n e.preventDefault()\n setActiveIndex((prev) => (prev - 1 + items.length) % items.length)\n break\n case 'Home':\n e.preventDefault()\n setActiveIndex(0)\n break\n case 'End':\n e.preventDefault()\n setActiveIndex(items.length - 1)\n break\n case 'Escape':\n e.preventDefault()\n setIsOpen(false)\n triggerRef.current?.focus()\n break\n case 'Enter':\n case ' ':\n e.preventDefault()\n if (activeIndex >= 0) {\n items[activeIndex]?.click()\n }\n break\n }\n },\n [isOpen, activeIndex, setIsOpen]\n )\n\n // Focus active item\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return\n const items = menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')\n items?.[activeIndex]?.focus()\n }, [isOpen, activeIndex])\n\n const triggerProps = trigger.props as Record<string, unknown>\n const triggerElement = cloneElement(trigger as ReactElement<Record<string, unknown>>, {\n ref: triggerRef,\n 'aria-haspopup': 'menu',\n 'aria-expanded': isOpen,\n onClick: (e: React.MouseEvent) => {\n (triggerProps.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e)\n setIsOpen(!isOpen)\n },\n onKeyDown: (e: KeyboardEvent) => {\n (triggerProps.onKeyDown as ((e: KeyboardEvent) => void) | undefined)?.(e)\n handleKeyDown(e)\n },\n })\n\n const menuStyle: CSSProperties = {\n position: 'absolute',\n top: position.top,\n left: placement.endsWith('end') ? 'auto' : position.left,\n right: placement.endsWith('end') ? window.innerWidth - position.left : 'auto',\n zIndex: 'var(--brycks-z-dropdown)' as unknown as number,\n minWidth: triggerRef.current?.offsetWidth ?? 160,\n backgroundColor: 'var(--brycks-background-elevated)',\n border: '1px solid var(--brycks-border-default)',\n borderRadius: 'var(--brycks-radius-lg)',\n boxShadow: 'var(--brycks-shadow-lg)',\n padding: spacing[1],\n animation: `brycks-dropdown-in ${durations.quick}ms ${easings.easeOut}`,\n outline: 'none',\n ...style,\n }\n\n return (\n <DropdownContext.Provider value={{ isOpen, close: closeOnSelect ? close : () => {}, activeIndex, setActiveIndex }}>\n <div\n ref={ref}\n className={cx('brycks-dropdown', className)}\n style={{ display: 'inline-block' }}\n data-testid={testId}\n {...props}\n >\n {triggerElement}\n {isOpen && mounted && createPortal(\n <>\n <style>\n {`\n @keyframes brycks-dropdown-in {\n from { opacity: 0; transform: translateY(-4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n `}\n </style>\n <div\n ref={menuRef}\n role=\"menu\"\n style={menuStyle}\n onKeyDown={handleKeyDown}\n tabIndex={-1}\n >\n {children}\n </div>\n </>,\n document.body\n )}\n </div>\n </DropdownContext.Provider>\n )\n})\n\nDropdown.displayName = 'Dropdown'\n\n// DropdownItem\nexport interface DropdownItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether the item is disabled */\n disabled?: boolean\n /** Icon before the label */\n icon?: ReactNode\n /** Shortcut text */\n shortcut?: string\n /** Whether the item is destructive */\n destructive?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownItem = forwardRef<HTMLDivElement, DropdownItemProps>(function DropdownItem(\n { disabled = false, icon, shortcut, destructive = false, className, style, children, onClick, ...props },\n ref\n) {\n const { close } = useDropdownContext()\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n onClick?.(e)\n close()\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n padding: `${componentPaddingY.md}px ${componentPaddingX.sm}px`,\n fontSize: fontSizes.base,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : destructive\n ? 'var(--brycks-error-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: 'transparent',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `background-color ${durations.fast}ms ${easings.easeOut}`,\n outline: 'none',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: iconSizes.sm,\n height: iconSizes.sm,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : destructive\n ? 'var(--brycks-error-default)'\n : 'var(--brycks-foreground-muted)',\n flexShrink: 0,\n }\n\n const shortcutStyle: CSSProperties = {\n marginLeft: 'auto',\n fontSize: fontSizes.sm,\n color: 'var(--brycks-foreground-muted)',\n fontFamily: 'var(--brycks-font-mono)',\n }\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cx('brycks-dropdown-item', disabled && 'brycks-dropdown-item--disabled', className)}\n style={itemStyle}\n onClick={handleClick}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n onFocus={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }}\n onBlur={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n <span style={{ flex: 1 }}>{children}</span>\n {shortcut && <span style={shortcutStyle}>{shortcut}</span>}\n </div>\n )\n})\n\nDropdownItem.displayName = 'DropdownItem'\n\n// DropdownDivider\nexport interface DropdownDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownDivider = forwardRef<HTMLDivElement, DropdownDividerProps>(function DropdownDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[1]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-dropdown-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nDropdownDivider.displayName = 'DropdownDivider'\n\n// DropdownLabel\nexport interface DropdownLabelProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownLabel = forwardRef<HTMLDivElement, DropdownLabelProps>(function DropdownLabel(\n { className, style, children, ...props },\n ref\n) {\n const labelStyle: CSSProperties = {\n padding: `${componentPaddingY.md}px ${componentPaddingX.sm}px ${spacing[1]}px ${componentPaddingX.sm}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n ...style,\n }\n\n return (\n <div\n ref={ref}\n className={cx('brycks-dropdown-label', className)}\n style={labelStyle}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nDropdownLabel.displayName = 'DropdownLabel'\n"],"names":["DropdownContext","createContext","useDropdownContext","context","useContext","Dropdown","forwardRef","trigger","controlledIsOpen","defaultOpen","onOpenChange","placement","offset","closeOnSelect","className","style","children","testId","props","ref","internalIsOpen","setInternalIsOpen","useState","position","setPosition","activeIndex","setActiveIndex","mounted","setMounted","triggerRef","useRef","menuRef","isOpen","useEffect","setIsOpen","useCallback","open","close","updatePosition","rect","scrollX","scrollY","top","left","handleClick","e","handleKeyDown","items","prev","triggerProps","triggerElement","cloneElement","menuStyle","spacing","durations","easings","jsx","jsxs","cx","createPortal","Fragment","DropdownItem","disabled","icon","shortcut","destructive","onClick","itemStyle","componentGap","componentPaddingY","componentPaddingX","fontSizes","iconStyle","iconSizes","shortcutStyle","DropdownDivider","dividerStyle","DropdownLabel","labelStyle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Dropdown.cjs","sources":["../../../../src/components/navigation/Dropdown/Dropdown.tsx"],"sourcesContent":["/**\n * Dropdown Component\n *\n * A dropdown menu with keyboard navigation support.\n * Can be used for actions, navigation, or selection.\n *\n * All color styles are handled via CSS classes for easy customization.\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n cloneElement,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type ReactElement,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { createPortal } from 'react-dom'\nimport { cx } from '../../../utils/styles'\n\nexport type DropdownPlacement = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'\n\ninterface DropdownContextValue {\n isOpen: boolean\n close: () => void\n activeIndex: number\n setActiveIndex: (index: number) => void\n}\n\nconst DropdownContext = createContext<DropdownContextValue | null>(null)\n\nfunction useDropdownContext() {\n const context = useContext(DropdownContext)\n if (!context) {\n throw new Error('Dropdown components must be used within a Dropdown')\n }\n return context\n}\n\nexport interface DropdownProps extends HTMLAttributes<HTMLDivElement> {\n /** Trigger element */\n trigger: ReactElement\n /** Whether the dropdown is open (controlled) */\n isOpen?: boolean\n /** Default open state (uncontrolled) */\n defaultOpen?: boolean\n /** Callback when open state changes */\n onOpenChange?: (isOpen: boolean) => void\n /** Dropdown placement */\n placement?: DropdownPlacement\n /** Offset from trigger */\n offset?: number\n /** Whether to close on item select */\n closeOnSelect?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(function Dropdown(\n {\n trigger,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n placement = 'bottom-start',\n offset = 4,\n closeOnSelect = true,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultOpen)\n const [position, setPosition] = useState({ top: 0, left: 0 })\n const [activeIndex, setActiveIndex] = useState(-1)\n const [mounted, setMounted] = useState(false)\n const triggerRef = useRef<HTMLElement>(null)\n const menuRef = useRef<HTMLDivElement>(null)\n\n const isOpen = controlledIsOpen ?? internalIsOpen\n\n useEffect(() => {\n setMounted(true)\n return () => setMounted(false)\n }, [])\n\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open)\n }\n onOpenChange?.(open)\n if (!open) {\n setActiveIndex(-1)\n }\n },\n [controlledIsOpen, onOpenChange]\n )\n\n const close = useCallback(() => setIsOpen(false), [setIsOpen])\n\n // Calculate position\n useEffect(() => {\n if (!isOpen || !triggerRef.current || !mounted) return\n\n const updatePosition = () => {\n const trigger = triggerRef.current\n if (!trigger) return\n\n const rect = trigger.getBoundingClientRect()\n const scrollX = window.scrollX\n const scrollY = window.scrollY\n\n let top = 0\n let left = 0\n\n if (placement.startsWith('bottom')) {\n top = rect.bottom + scrollY + offset\n } else {\n top = rect.top + scrollY - offset\n }\n\n if (placement.endsWith('start')) {\n left = rect.left + scrollX\n } else {\n left = rect.right + scrollX\n }\n\n setPosition({ top, left })\n }\n\n updatePosition()\n window.addEventListener('resize', updatePosition)\n window.addEventListener('scroll', updatePosition, true)\n\n return () => {\n window.removeEventListener('resize', updatePosition)\n window.removeEventListener('scroll', updatePosition, true)\n }\n }, [isOpen, placement, offset, mounted])\n\n // Close on outside click\n useEffect(() => {\n if (!isOpen) return\n\n const handleClick = (e: MouseEvent) => {\n if (\n triggerRef.current?.contains(e.target as Node) ||\n menuRef.current?.contains(e.target as Node)\n ) {\n return\n }\n setIsOpen(false)\n }\n\n document.addEventListener('mousedown', handleClick)\n return () => document.removeEventListener('mousedown', handleClick)\n }, [isOpen, setIsOpen])\n\n // Keyboard navigation\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n setIsOpen(true)\n }\n return\n }\n\n const items = menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')\n if (!items?.length) return\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n setActiveIndex((prev) => (prev + 1) % items.length)\n break\n case 'ArrowUp':\n e.preventDefault()\n setActiveIndex((prev) => (prev - 1 + items.length) % items.length)\n break\n case 'Home':\n e.preventDefault()\n setActiveIndex(0)\n break\n case 'End':\n e.preventDefault()\n setActiveIndex(items.length - 1)\n break\n case 'Escape':\n e.preventDefault()\n setIsOpen(false)\n triggerRef.current?.focus()\n break\n case 'Enter':\n case ' ':\n e.preventDefault()\n if (activeIndex >= 0) {\n items[activeIndex]?.click()\n }\n break\n }\n },\n [isOpen, activeIndex, setIsOpen]\n )\n\n // Focus active item\n useEffect(() => {\n if (!isOpen || activeIndex < 0) return\n const items = menuRef.current?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]:not([aria-disabled=\"true\"])')\n items?.[activeIndex]?.focus()\n }, [isOpen, activeIndex])\n\n const triggerProps = trigger.props as Record<string, unknown>\n const triggerElement = cloneElement(trigger as ReactElement<Record<string, unknown>>, {\n ref: triggerRef,\n 'aria-haspopup': 'menu',\n 'aria-expanded': isOpen,\n onClick: (e: React.MouseEvent) => {\n (triggerProps.onClick as ((e: React.MouseEvent) => void) | undefined)?.(e)\n setIsOpen(!isOpen)\n },\n onKeyDown: (e: KeyboardEvent) => {\n (triggerProps.onKeyDown as ((e: KeyboardEvent) => void) | undefined)?.(e)\n handleKeyDown(e)\n },\n })\n\n // Only layout-related inline styles (position is dynamic)\n const menuStyle: CSSProperties = {\n position: 'absolute',\n top: position.top,\n left: placement.endsWith('end') ? 'auto' : position.left,\n right: placement.endsWith('end') ? window.innerWidth - position.left : 'auto',\n minWidth: triggerRef.current?.offsetWidth ?? 160,\n ...style,\n }\n\n return (\n <DropdownContext.Provider value={{ isOpen, close: closeOnSelect ? close : () => {}, activeIndex, setActiveIndex }}>\n <div\n ref={ref}\n className={cx('brycks-dropdown', className)}\n data-testid={testId}\n {...props}\n >\n {triggerElement}\n {isOpen && mounted && createPortal(\n <div\n ref={menuRef}\n role=\"menu\"\n className=\"brycks-dropdown__menu\"\n style={menuStyle}\n onKeyDown={handleKeyDown}\n tabIndex={-1}\n >\n {children}\n </div>,\n document.body\n )}\n </div>\n </DropdownContext.Provider>\n )\n})\n\nDropdown.displayName = 'Dropdown'\n\n// DropdownItem\nexport interface DropdownItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether the item is disabled */\n disabled?: boolean\n /** Icon before the label */\n icon?: ReactNode\n /** Shortcut text */\n shortcut?: string\n /** Whether the item is destructive */\n destructive?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownItem = forwardRef<HTMLDivElement, DropdownItemProps>(function DropdownItem(\n { disabled = false, icon, shortcut, destructive = false, className, style, children, onClick, ...props },\n ref\n) {\n const { close } = useDropdownContext()\n\n const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n onClick?.(e)\n close()\n }\n\n return (\n <div\n ref={ref}\n role=\"menuitem\"\n aria-disabled={disabled}\n tabIndex={disabled ? -1 : 0}\n className={cx(\n 'brycks-dropdown-item',\n disabled && 'brycks-dropdown-item--disabled',\n destructive && 'brycks-dropdown-item--destructive',\n className\n )}\n style={style}\n onClick={handleClick}\n {...props}\n >\n {icon && <span className=\"brycks-dropdown-item__icon\">{icon}</span>}\n <span className=\"brycks-dropdown-item__label\">{children}</span>\n {shortcut && <span className=\"brycks-dropdown-item__shortcut\">{shortcut}</span>}\n </div>\n )\n})\n\nDropdownItem.displayName = 'DropdownItem'\n\n// DropdownDivider\nexport interface DropdownDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownDivider = forwardRef<HTMLDivElement, DropdownDividerProps>(function DropdownDivider(\n { className, style, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-dropdown-divider', className)}\n style={style}\n {...props}\n />\n )\n})\n\nDropdownDivider.displayName = 'DropdownDivider'\n\n// DropdownLabel\nexport interface DropdownLabelProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const DropdownLabel = forwardRef<HTMLDivElement, DropdownLabelProps>(function DropdownLabel(\n { className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx('brycks-dropdown-label', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nDropdownLabel.displayName = 'DropdownLabel'\n"],"names":["DropdownContext","createContext","useDropdownContext","context","useContext","Dropdown","forwardRef","trigger","controlledIsOpen","defaultOpen","onOpenChange","placement","offset","closeOnSelect","className","style","children","testId","props","ref","internalIsOpen","setInternalIsOpen","useState","position","setPosition","activeIndex","setActiveIndex","mounted","setMounted","triggerRef","useRef","menuRef","isOpen","useEffect","setIsOpen","useCallback","open","close","updatePosition","rect","scrollX","scrollY","top","left","handleClick","e","handleKeyDown","items","prev","triggerProps","triggerElement","cloneElement","menuStyle","jsx","jsxs","cx","createPortal","DropdownItem","disabled","icon","shortcut","destructive","onClick","DropdownDivider","DropdownLabel"],"mappings":"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"}
|