@fanvue/ui 2.1.2 → 2.2.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.
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ function _interopNamespaceDefault(e) {
8
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
9
+ if (e) {
10
+ for (const k in e) {
11
+ if (k !== "default") {
12
+ const d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: () => e[k]
16
+ });
17
+ }
18
+ }
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
24
+ const PeopleIcon = React__namespace.forwardRef(
25
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
26
+ "svg",
27
+ {
28
+ ref,
29
+ viewBox: "0 0 20 20",
30
+ fill: "none",
31
+ "aria-hidden": "true",
32
+ className: cn.cn("size-5", className),
33
+ ...props,
34
+ children: [
35
+ /* @__PURE__ */ jsxRuntime.jsx(
36
+ "path",
37
+ {
38
+ fill: "currentColor",
39
+ d: "M7.82051 9.46722C8.47833 9.46722 9.12138 9.27758 9.66833 8.92226C10.2153 8.56695 10.6416 8.06193 10.8933 7.47106C11.1451 6.8802 11.2109 6.23003 11.0826 5.60277C10.9543 4.97551 10.6375 4.39933 10.1723 3.9471C9.70719 3.49488 9.11456 3.1869 8.46938 3.06213C7.8242 2.93736 7.15545 3.0014 6.5477 3.24615C5.93995 3.49089 5.4205 3.90535 5.05504 4.43711C4.68957 4.96888 4.49451 5.59406 4.49451 6.23361C4.49451 7.09122 4.84492 7.9137 5.46867 8.52012C6.09242 9.12654 6.9384 9.46722 7.82051 9.46722ZM7.82051 4.61681C8.14942 4.61681 8.47094 4.71163 8.74442 4.88929C9.0179 5.06694 9.23105 5.31945 9.35692 5.61489C9.48279 5.91032 9.51572 6.23541 9.45155 6.54904C9.38739 6.86266 9.229 7.15075 8.99643 7.37687C8.76385 7.60298 8.46753 7.75697 8.14494 7.81935C7.82235 7.88174 7.48798 7.84972 7.1841 7.72735C6.88023 7.60497 6.62051 7.39774 6.43777 7.13186C6.25504 6.86598 6.15751 6.55339 6.15751 6.23361C6.15751 5.80481 6.33272 5.39357 6.64459 5.09036C6.95646 4.78715 7.37945 4.61681 7.82051 4.61681Z"
40
+ }
41
+ ),
42
+ /* @__PURE__ */ jsxRuntime.jsx(
43
+ "path",
44
+ {
45
+ fill: "currentColor",
46
+ d: "M14.4725 11.0841C14.9659 11.0841 15.4482 10.9418 15.8584 10.6753C16.2686 10.4088 16.5883 10.0301 16.7771 9.58693C16.9659 9.14378 17.0153 8.65615 16.9191 8.18571C16.8228 7.71527 16.5853 7.28313 16.2364 6.94396C15.8875 6.60479 15.4431 6.37381 14.9592 6.28024C14.4753 6.18666 13.9737 6.23469 13.5179 6.41824C13.0621 6.6018 12.6725 6.91265 12.3984 7.31147C12.1243 7.71029 11.978 8.17918 11.978 8.65884C11.978 9.30205 12.2408 9.91891 12.7086 10.3737C13.1765 10.8285 13.8109 11.0841 14.4725 11.0841ZM14.4725 7.85044C14.637 7.85044 14.7977 7.89785 14.9345 7.98668C15.0712 8.07551 15.1778 8.20177 15.2407 8.34948C15.3037 8.4972 15.3201 8.65974 15.2881 8.81656C15.256 8.97337 15.1768 9.11741 15.0605 9.23047C14.9442 9.34353 14.796 9.42052 14.6347 9.45171C14.4735 9.48291 14.3063 9.4669 14.1543 9.40571C14.0024 9.34452 13.8725 9.24091 13.7812 9.10797C13.6898 8.97503 13.641 8.81873 13.641 8.65884C13.641 8.44444 13.7286 8.23882 13.8846 8.08722C14.0405 7.93561 14.252 7.85044 14.4725 7.85044Z"
47
+ }
48
+ ),
49
+ /* @__PURE__ */ jsxRuntime.jsx(
50
+ "path",
51
+ {
52
+ fill: "currentColor",
53
+ d: "M14.4725 11.8924C13.5511 11.8934 12.6561 12.192 11.9281 12.7413C11.1137 11.9526 10.0772 11.416 8.94953 11.1992C7.82182 10.9824 6.65334 11.0951 5.59144 11.5231C4.52953 11.9511 3.62177 12.6753 2.98262 13.6042C2.34347 14.5331 2.00156 15.6253 2 16.7429C2 16.9573 2.0876 17.1629 2.24354 17.3145C2.39948 17.4661 2.61097 17.5513 2.8315 17.5513C3.05203 17.5513 3.26352 17.4661 3.41946 17.3145C3.5754 17.1629 3.663 16.9573 3.663 16.7429C3.663 15.6709 4.10102 14.6428 4.8807 13.8847C5.66039 13.1267 6.71786 12.7009 7.8205 12.7009C8.92314 12.7009 9.98061 13.1267 10.7603 13.8847C11.54 14.6428 11.978 15.6709 11.978 16.7429C11.978 16.9573 12.0656 17.1629 12.2215 17.3145C12.3775 17.4661 12.589 17.5513 12.8095 17.5513C13.03 17.5513 13.2415 17.4661 13.3975 17.3145C13.5534 17.1629 13.641 16.9573 13.641 16.7429C13.643 15.7958 13.3969 14.8638 12.9259 14.0347C13.2934 13.7524 13.7352 13.5764 14.2007 13.5268C14.6663 13.4772 15.1368 13.556 15.5584 13.7542C15.98 13.9524 16.3358 14.262 16.5849 14.6476C16.834 15.0332 16.9664 15.4791 16.967 15.9345C16.967 16.1489 17.0546 16.3545 17.2105 16.5061C17.3665 16.6577 17.578 16.7429 17.7985 16.7429C18.019 16.7429 18.2305 16.6577 18.3865 16.5061C18.5424 16.3545 18.63 16.1489 18.63 15.9345C18.63 14.8625 18.192 13.8344 17.4123 13.0763C16.6326 12.3183 15.5751 11.8924 14.4725 11.8924Z"
54
+ }
55
+ )
56
+ ]
57
+ }
58
+ )
59
+ );
60
+ PeopleIcon.displayName = "PeopleIcon";
61
+ exports.PeopleIcon = PeopleIcon;
62
+ //# sourceMappingURL=PeopleIcon.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeopleIcon.cjs","sources":["../../../../src/components/Icons/PeopleIcon.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport type { IconProps } from \"./types\";\n\n/** Two-person silhouette (20 × 20). */\nexport const PeopleIcon = React.forwardRef<SVGSVGElement, IconProps>(\n ({ className, ...props }, ref) => (\n <svg\n ref={ref}\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n aria-hidden=\"true\"\n className={cn(\"size-5\", className)}\n {...props}\n >\n <path\n fill=\"currentColor\"\n d=\"M7.82051 9.46722C8.47833 9.46722 9.12138 9.27758 9.66833 8.92226C10.2153 8.56695 10.6416 8.06193 10.8933 7.47106C11.1451 6.8802 11.2109 6.23003 11.0826 5.60277C10.9543 4.97551 10.6375 4.39933 10.1723 3.9471C9.70719 3.49488 9.11456 3.1869 8.46938 3.06213C7.8242 2.93736 7.15545 3.0014 6.5477 3.24615C5.93995 3.49089 5.4205 3.90535 5.05504 4.43711C4.68957 4.96888 4.49451 5.59406 4.49451 6.23361C4.49451 7.09122 4.84492 7.9137 5.46867 8.52012C6.09242 9.12654 6.9384 9.46722 7.82051 9.46722ZM7.82051 4.61681C8.14942 4.61681 8.47094 4.71163 8.74442 4.88929C9.0179 5.06694 9.23105 5.31945 9.35692 5.61489C9.48279 5.91032 9.51572 6.23541 9.45155 6.54904C9.38739 6.86266 9.229 7.15075 8.99643 7.37687C8.76385 7.60298 8.46753 7.75697 8.14494 7.81935C7.82235 7.88174 7.48798 7.84972 7.1841 7.72735C6.88023 7.60497 6.62051 7.39774 6.43777 7.13186C6.25504 6.86598 6.15751 6.55339 6.15751 6.23361C6.15751 5.80481 6.33272 5.39357 6.64459 5.09036C6.95646 4.78715 7.37945 4.61681 7.82051 4.61681Z\"\n />\n <path\n fill=\"currentColor\"\n d=\"M14.4725 11.0841C14.9659 11.0841 15.4482 10.9418 15.8584 10.6753C16.2686 10.4088 16.5883 10.0301 16.7771 9.58693C16.9659 9.14378 17.0153 8.65615 16.9191 8.18571C16.8228 7.71527 16.5853 7.28313 16.2364 6.94396C15.8875 6.60479 15.4431 6.37381 14.9592 6.28024C14.4753 6.18666 13.9737 6.23469 13.5179 6.41824C13.0621 6.6018 12.6725 6.91265 12.3984 7.31147C12.1243 7.71029 11.978 8.17918 11.978 8.65884C11.978 9.30205 12.2408 9.91891 12.7086 10.3737C13.1765 10.8285 13.8109 11.0841 14.4725 11.0841ZM14.4725 7.85044C14.637 7.85044 14.7977 7.89785 14.9345 7.98668C15.0712 8.07551 15.1778 8.20177 15.2407 8.34948C15.3037 8.4972 15.3201 8.65974 15.2881 8.81656C15.256 8.97337 15.1768 9.11741 15.0605 9.23047C14.9442 9.34353 14.796 9.42052 14.6347 9.45171C14.4735 9.48291 14.3063 9.4669 14.1543 9.40571C14.0024 9.34452 13.8725 9.24091 13.7812 9.10797C13.6898 8.97503 13.641 8.81873 13.641 8.65884C13.641 8.44444 13.7286 8.23882 13.8846 8.08722C14.0405 7.93561 14.252 7.85044 14.4725 7.85044Z\"\n />\n <path\n fill=\"currentColor\"\n d=\"M14.4725 11.8924C13.5511 11.8934 12.6561 12.192 11.9281 12.7413C11.1137 11.9526 10.0772 11.416 8.94953 11.1992C7.82182 10.9824 6.65334 11.0951 5.59144 11.5231C4.52953 11.9511 3.62177 12.6753 2.98262 13.6042C2.34347 14.5331 2.00156 15.6253 2 16.7429C2 16.9573 2.0876 17.1629 2.24354 17.3145C2.39948 17.4661 2.61097 17.5513 2.8315 17.5513C3.05203 17.5513 3.26352 17.4661 3.41946 17.3145C3.5754 17.1629 3.663 16.9573 3.663 16.7429C3.663 15.6709 4.10102 14.6428 4.8807 13.8847C5.66039 13.1267 6.71786 12.7009 7.8205 12.7009C8.92314 12.7009 9.98061 13.1267 10.7603 13.8847C11.54 14.6428 11.978 15.6709 11.978 16.7429C11.978 16.9573 12.0656 17.1629 12.2215 17.3145C12.3775 17.4661 12.589 17.5513 12.8095 17.5513C13.03 17.5513 13.2415 17.4661 13.3975 17.3145C13.5534 17.1629 13.641 16.9573 13.641 16.7429C13.643 15.7958 13.3969 14.8638 12.9259 14.0347C13.2934 13.7524 13.7352 13.5764 14.2007 13.5268C14.6663 13.4772 15.1368 13.556 15.5584 13.7542C15.98 13.9524 16.3358 14.262 16.5849 14.6476C16.834 15.0332 16.9664 15.4791 16.967 15.9345C16.967 16.1489 17.0546 16.3545 17.2105 16.5061C17.3665 16.6577 17.578 16.7429 17.7985 16.7429C18.019 16.7429 18.2305 16.6577 18.3865 16.5061C18.5424 16.3545 18.63 16.1489 18.63 15.9345C18.63 14.8625 18.192 13.8344 17.4123 13.0763C16.6326 12.3183 15.5751 11.8924 14.4725 11.8924Z\"\n />\n </svg>\n ),\n);\n\nPeopleIcon.displayName = \"PeopleIcon\";\n"],"names":["React","jsxs","cn","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKO,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxBC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,eAAY;AAAA,MACZ,WAAWC,GAAAA,GAAG,UAAU,SAAS;AAAA,MAChC,GAAG;AAAA,MAEJ,UAAA;AAAA,QAAAC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,GAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAEJA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,GAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAEJA,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,GAAE;AAAA,UAAA;AAAA,QAAA;AAAA,MACJ;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,WAAW,cAAc;;"}
@@ -11,6 +11,7 @@ const useAudioRecorder = require("./components/AudioUpload/useAudioRecorder.cjs"
11
11
  const Autocomplete = require("./components/Autocomplete/Autocomplete.cjs");
12
12
  const Avatar = require("./components/Avatar/Avatar.cjs");
13
13
  const Badge = require("./components/Badge/Badge.cjs");
14
+ const Banner = require("./components/Banner/Banner.cjs");
14
15
  const BottomNavigation = require("./components/BottomNavigation/BottomNavigation.cjs");
15
16
  const BottomNavigationAction = require("./components/BottomNavigation/BottomNavigationAction.cjs");
16
17
  const Breadcrumb = require("./components/Breadcrumb/Breadcrumb.cjs");
@@ -100,7 +101,9 @@ const MoonIcon = require("./components/Icons/MoonIcon.cjs");
100
101
  const MoreIcon = require("./components/Icons/MoreIcon.cjs");
101
102
  const MoreVerticalIcon = require("./components/Icons/MoreVerticalIcon.cjs");
102
103
  const NewMessageIcon = require("./components/Icons/NewMessageIcon.cjs");
104
+ const OpenIcon = require("./components/Icons/OpenIcon.cjs");
103
105
  const PauseIcon = require("./components/Icons/PauseIcon.cjs");
106
+ const PeopleIcon = require("./components/Icons/PeopleIcon.cjs");
104
107
  const PhoneIcon = require("./components/Icons/PhoneIcon.cjs");
105
108
  const PhoneOffIcon = require("./components/Icons/PhoneOffIcon.cjs");
106
109
  const PinIcon = require("./components/Icons/PinIcon.cjs");
@@ -187,6 +190,7 @@ exports.AvatarFallback = Avatar.AvatarFallback;
187
190
  exports.AvatarImage = Avatar.AvatarImage;
188
191
  exports.AvatarRoot = Avatar.AvatarRoot;
189
192
  exports.Badge = Badge.Badge;
193
+ exports.Banner = Banner.Banner;
190
194
  exports.BottomNavigation = BottomNavigation.BottomNavigation;
191
195
  exports.BottomNavigationAction = BottomNavigationAction.BottomNavigationAction;
192
196
  exports.Breadcrumb = Breadcrumb.Breadcrumb;
@@ -309,7 +313,9 @@ exports.MoonIcon = MoonIcon.MoonIcon;
309
313
  exports.MoreIcon = MoreIcon.MoreIcon;
310
314
  exports.MoreVerticalIcon = MoreVerticalIcon.MoreVerticalIcon;
311
315
  exports.NewMessageIcon = NewMessageIcon.NewMessageIcon;
316
+ exports.OpenIcon = OpenIcon.OpenIcon;
312
317
  exports.PauseIcon = PauseIcon.PauseIcon;
318
+ exports.PeopleIcon = PeopleIcon.PeopleIcon;
313
319
  exports.PhoneIcon = PhoneIcon.PhoneIcon;
314
320
  exports.PhoneOffIcon = PhoneOffIcon.PhoneOffIcon;
315
321
  exports.PinIcon = PinIcon.PinIcon;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,293 @@
1
+ "use client";
2
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ import { Badge } from "../Badge/Badge.mjs";
6
+ import { IconButton } from "../IconButton/IconButton.mjs";
7
+ import { CrossIcon } from "../Icons/CrossIcon.mjs";
8
+ const APP_STORE_VARIANTS = ["appStore1", "appStore2", "appStore3"];
9
+ function isAppStoreVariant(variant) {
10
+ return APP_STORE_VARIANTS.includes(variant);
11
+ }
12
+ const GUIDE_BADGE_VARIANT = {
13
+ appStore1: "dark",
14
+ appStore2: "default",
15
+ appStore3: "default"
16
+ };
17
+ const BANNER_SHADOW = "shadow-sm";
18
+ const guideGradient = {
19
+ appStore1: {
20
+ backgroundImage: "linear-gradient(125.54deg, var(--color-brand-primary-muted) 0%, var(--color-neutral-alphas-50) 100%)"
21
+ },
22
+ appStore2: {
23
+ backgroundImage: "linear-gradient(125.54deg, var(--color-brand-secondary-muted) 0%, var(--color-brand-secondary-muted) 100%)"
24
+ },
25
+ appStore3: {
26
+ backgroundImage: "linear-gradient(125.54deg, var(--color-brand-secondary-muted) 0%, color-mix(in srgb, var(--color-info-surface) 80%, transparent) 100%)"
27
+ }
28
+ };
29
+ function BannerDismiss({
30
+ onDismiss,
31
+ dismissLabel
32
+ }) {
33
+ return /* @__PURE__ */ jsx(
34
+ IconButton,
35
+ {
36
+ variant: "contrast",
37
+ size: "24",
38
+ icon: /* @__PURE__ */ jsx(CrossIcon, {}),
39
+ onClick: onDismiss,
40
+ "aria-label": dismissLabel,
41
+ className: "hover:bg-white/10 active:bg-white/15"
42
+ }
43
+ );
44
+ }
45
+ function resolveLayout(variant, layoutProp) {
46
+ if (variant === "Subtle") {
47
+ return "horizontal";
48
+ }
49
+ if (isAppStoreVariant(variant)) {
50
+ return "vertical";
51
+ }
52
+ if (variant === "whatsNew") {
53
+ return layoutProp ?? "horizontal";
54
+ }
55
+ return layoutProp ?? "vertical";
56
+ }
57
+ function bannerRootClass(variant, layout, className) {
58
+ return cn(
59
+ "flex rounded-md",
60
+ BANNER_SHADOW,
61
+ variant === "Default" && "gap-3 bg-surface-primary-inverted p-4 text-content-primary-inverted",
62
+ variant === "Subtle" && "w-full max-w-[600px] items-start gap-3 border border-border-primary bg-surface-secondary p-4 text-content-primary",
63
+ variant === "whatsNew" && layout === "horizontal" && "w-full max-w-[446px] items-center gap-4 bg-surface-purple-muted p-4 text-content-primary",
64
+ variant === "whatsNew" && layout === "vertical" && "w-full max-w-[220px] flex-col items-stretch gap-4 border border-border-primary bg-surface-secondary p-4 text-content-primary",
65
+ variant === "whatsNew" && layout === "compact" && "w-full max-w-[446px] items-start gap-4 bg-surface-purple-muted p-4 text-content-primary",
66
+ isAppStoreVariant(variant) && "w-full max-w-[280px] flex-col gap-4 p-6",
67
+ layout === "vertical" && variant === "Default" && "max-w-[360px]",
68
+ layout === "horizontal" && variant === "Default" && "w-full max-w-[600px] items-start",
69
+ className
70
+ );
71
+ }
72
+ const BannerSection = React.forwardRef(
73
+ ({ className, labelledBy, children, ...rest }, ref) => /* @__PURE__ */ jsx(
74
+ "section",
75
+ {
76
+ ref,
77
+ "aria-labelledby": labelledBy,
78
+ "data-testid": "banner",
79
+ className,
80
+ ...rest,
81
+ children
82
+ }
83
+ )
84
+ );
85
+ BannerSection.displayName = "BannerSection";
86
+ function BannerGuideBody({
87
+ appStoreVariant,
88
+ eyebrow,
89
+ title,
90
+ description,
91
+ textAction,
92
+ labelledBy
93
+ }) {
94
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
95
+ eyebrow !== void 0 && eyebrow !== null && eyebrow !== false && /* @__PURE__ */ jsx(
96
+ Badge,
97
+ {
98
+ variant: GUIDE_BADGE_VARIANT[appStoreVariant],
99
+ leftDot: false,
100
+ className: "typography-semibold-badge self-start",
101
+ children: eyebrow
102
+ }
103
+ ),
104
+ title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsx("p", { id: labelledBy, className: "typography-semibold-body-lg text-content-primary", children: title }),
105
+ description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-md text-content-secondary", children: description }),
106
+ textAction
107
+ ] });
108
+ }
109
+ function BannerFeatureBody({
110
+ layout,
111
+ media,
112
+ title,
113
+ description,
114
+ textAction,
115
+ labelledBy
116
+ }) {
117
+ const titleClass = layout === "vertical" ? "typography-semibold-body-lg text-content-primary" : "typography-semibold-body-lg text-[18px] leading-6 text-content-primary";
118
+ const mediaWrap = layout === "compact" ? "size-20 shrink-0 overflow-hidden rounded-sm" : "size-[132px] shrink-0 overflow-hidden rounded-sm";
119
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
120
+ media !== void 0 && media !== null && /* @__PURE__ */ jsx("div", { className: cn(mediaWrap, layout === "vertical" && "w-full [&>*]:mx-auto"), children: media }),
121
+ /* @__PURE__ */ jsxs(
122
+ "div",
123
+ {
124
+ className: cn(
125
+ "flex min-w-0 flex-col gap-2",
126
+ layout === "horizontal" || layout === "compact" ? "flex-1 justify-end" : "w-full"
127
+ ),
128
+ children: [
129
+ title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsx("div", { id: labelledBy, className: titleClass, children: title }),
130
+ description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-md text-content-secondary", children: description }),
131
+ textAction
132
+ ]
133
+ }
134
+ )
135
+ ] });
136
+ }
137
+ function BannerSubtleBody({
138
+ media,
139
+ leadBadge,
140
+ title,
141
+ description,
142
+ secondaryLine,
143
+ stackedAction,
144
+ statusRow,
145
+ primaryAction,
146
+ labelledBy
147
+ }) {
148
+ const mediaSizeDefault = "size-12 shrink-0 overflow-hidden rounded-xl";
149
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
150
+ media !== void 0 && media !== null && /* @__PURE__ */ jsx("div", { className: mediaSizeDefault, children: media }),
151
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-end gap-3", children: [
152
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: [
153
+ leadBadge !== void 0 && leadBadge !== null && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: leadBadge }),
154
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
155
+ title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsx("div", { id: labelledBy, className: "typography-bold-heading-xs text-content-primary", children: title }),
156
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
157
+ description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-md text-content-primary", children: description }),
158
+ secondaryLine !== void 0 && secondaryLine !== null && secondaryLine !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-sm text-content-primary", children: secondaryLine })
159
+ ] })
160
+ ] }),
161
+ stackedAction !== void 0 && stackedAction !== null && /* @__PURE__ */ jsx("div", { className: "flex flex-col items-end self-start", children: stackedAction }),
162
+ statusRow !== void 0 && statusRow !== null && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: statusRow })
163
+ ] }),
164
+ primaryAction !== void 0 && primaryAction !== null && /* @__PURE__ */ jsx("div", { className: "shrink-0 self-center", children: primaryAction })
165
+ ] })
166
+ ] });
167
+ }
168
+ function BannerInverseBody({
169
+ layout,
170
+ media,
171
+ eyebrow,
172
+ title,
173
+ description,
174
+ primaryAction,
175
+ labelledBy,
176
+ dismissSlot
177
+ }) {
178
+ const mediaSizeDefault = "size-12 shrink-0 overflow-hidden rounded-xl";
179
+ const titleClassInverse = "typography-bold-heading-xs text-content-primary-inverted";
180
+ const textColumn = /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
181
+ eyebrow !== void 0 && eyebrow !== null && eyebrow !== false && /* @__PURE__ */ jsx("p", { className: "typography-semibold-body-sm text-content-primary-inverted", children: eyebrow }),
182
+ title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsx("div", { id: labelledBy, className: titleClassInverse, children: title }),
183
+ description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-md text-content-primary-inverted", children: description })
184
+ ] });
185
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
186
+ media !== void 0 && media !== null && /* @__PURE__ */ jsx("div", { className: mediaSizeDefault, children: media }),
187
+ layout === "horizontal" ? /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-end gap-3", children: [
188
+ textColumn,
189
+ primaryAction !== void 0 && primaryAction !== null && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: primaryAction })
190
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-3", children: [
191
+ textColumn,
192
+ primaryAction !== void 0 && primaryAction !== null && /* @__PURE__ */ jsx("div", { children: primaryAction })
193
+ ] }),
194
+ dismissSlot
195
+ ] });
196
+ }
197
+ const Banner = React.forwardRef(
198
+ ({
199
+ className,
200
+ variant,
201
+ layout: layoutProp,
202
+ media,
203
+ eyebrow,
204
+ leadBadge,
205
+ title,
206
+ description,
207
+ secondaryLine,
208
+ stackedAction,
209
+ statusRow,
210
+ primaryAction,
211
+ textAction,
212
+ onDismiss,
213
+ dismissLabel = "Dismiss banner",
214
+ ...props
215
+ }, ref) => {
216
+ const layout = resolveLayout(variant, layoutProp);
217
+ const showDismiss = onDismiss !== void 0 && variant === "Default";
218
+ const titleId = React.useId();
219
+ const regionLabelledBy = title !== void 0 && title !== null && title !== false ? titleId : void 0;
220
+ const rootClass = bannerRootClass(variant, layout, className);
221
+ if (isAppStoreVariant(variant)) {
222
+ return /* @__PURE__ */ jsx(
223
+ BannerSection,
224
+ {
225
+ ref,
226
+ labelledBy: regionLabelledBy,
227
+ style: guideGradient[variant],
228
+ className: rootClass,
229
+ ...props,
230
+ children: /* @__PURE__ */ jsx(
231
+ BannerGuideBody,
232
+ {
233
+ appStoreVariant: variant,
234
+ eyebrow,
235
+ title,
236
+ description,
237
+ textAction,
238
+ labelledBy: regionLabelledBy
239
+ }
240
+ )
241
+ }
242
+ );
243
+ }
244
+ if (variant === "whatsNew") {
245
+ return /* @__PURE__ */ jsx(BannerSection, { ref, labelledBy: regionLabelledBy, className: rootClass, ...props, children: /* @__PURE__ */ jsx(
246
+ BannerFeatureBody,
247
+ {
248
+ layout,
249
+ media,
250
+ title,
251
+ description,
252
+ textAction,
253
+ labelledBy: regionLabelledBy
254
+ }
255
+ ) });
256
+ }
257
+ if (variant === "Subtle") {
258
+ return /* @__PURE__ */ jsx(BannerSection, { ref, labelledBy: regionLabelledBy, className: rootClass, ...props, children: /* @__PURE__ */ jsx(
259
+ BannerSubtleBody,
260
+ {
261
+ media,
262
+ leadBadge,
263
+ title,
264
+ description,
265
+ secondaryLine,
266
+ stackedAction,
267
+ statusRow,
268
+ primaryAction,
269
+ labelledBy: regionLabelledBy
270
+ }
271
+ ) });
272
+ }
273
+ const dismissSlot = showDismiss && onDismiss !== void 0 ? /* @__PURE__ */ jsx(BannerDismiss, { onDismiss, dismissLabel }) : null;
274
+ return /* @__PURE__ */ jsx(BannerSection, { ref, labelledBy: regionLabelledBy, className: rootClass, ...props, children: /* @__PURE__ */ jsx("div", { className: "flex w-full items-start gap-3", children: /* @__PURE__ */ jsx(
275
+ BannerInverseBody,
276
+ {
277
+ layout,
278
+ media,
279
+ eyebrow,
280
+ title,
281
+ description,
282
+ primaryAction,
283
+ labelledBy: regionLabelledBy,
284
+ dismissSlot
285
+ }
286
+ ) }) });
287
+ }
288
+ );
289
+ Banner.displayName = "Banner";
290
+ export {
291
+ Banner
292
+ };
293
+ //# sourceMappingURL=Banner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Banner.mjs","sources":["../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Badge, type BadgeVariant } from \"../Badge/Badge\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CrossIcon } from \"../Icons/CrossIcon\";\n\n/**\n * Matches the Fanvue Library Banner Figma component property `Type`\n * (`Default`, `Subtle`, `whatsNew`, `appStore1`, `appStore2`, `appStore3`).\n */\nexport type BannerVariant =\n | \"Default\"\n | \"Subtle\"\n | \"whatsNew\"\n | \"appStore1\"\n | \"appStore2\"\n | \"appStore3\";\n\n/** Layout (`Vertical` / `Horizontal` / `HorizontalSmall` in Figma). Ignored for `Subtle` and app store types. */\nexport type BannerLayout = \"vertical\" | \"horizontal\" | \"compact\";\n\ntype AppStoreVariant = \"appStore1\" | \"appStore2\" | \"appStore3\";\n\nconst APP_STORE_VARIANTS: readonly AppStoreVariant[] = [\"appStore1\", \"appStore2\", \"appStore3\"];\n\nfunction isAppStoreVariant(variant: BannerVariant): variant is AppStoreVariant {\n return (APP_STORE_VARIANTS as readonly string[]).includes(variant);\n}\n\nconst GUIDE_BADGE_VARIANT: Record<AppStoreVariant, BadgeVariant> = {\n appStore1: \"dark\",\n appStore2: \"default\",\n appStore3: \"default\",\n};\n\nconst BANNER_SHADOW = \"shadow-sm\";\n\nconst guideGradient: Record<AppStoreVariant, React.CSSProperties> = {\n appStore1: {\n backgroundImage:\n \"linear-gradient(125.54deg, var(--color-brand-primary-muted) 0%, var(--color-neutral-alphas-50) 100%)\",\n },\n appStore2: {\n backgroundImage:\n \"linear-gradient(125.54deg, var(--color-brand-secondary-muted) 0%, var(--color-brand-secondary-muted) 100%)\",\n },\n appStore3: {\n backgroundImage:\n \"linear-gradient(125.54deg, var(--color-brand-secondary-muted) 0%, color-mix(in srgb, var(--color-info-surface) 80%, transparent) 100%)\",\n },\n};\n\nexport interface BannerProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /** Figma `Type` — selects structure, surfaces, and app store gradient. */\n variant: BannerVariant;\n /**\n * Figma `Orientation`. Ignored when `variant` is `Subtle` (horizontal) or an app store type (vertical).\n * @default `\"vertical\"` for `Default`, `\"horizontal\"` for `whatsNew`\n */\n layout?: BannerLayout;\n /** Leading visual (image, illustration, or composite). */\n media?: React.ReactNode;\n /** Small uppercase label (e.g. HOW TO). */\n eyebrow?: React.ReactNode;\n /** Top badge row (e.g. NEW pill) — mainly for `Subtle`. */\n leadBadge?: React.ReactNode;\n /** Main heading. */\n title?: React.ReactNode;\n /** Primary body copy. */\n description?: React.ReactNode;\n /** Extra line under description (`Subtle`). */\n secondaryLine?: React.ReactNode;\n /** Left-stacked pill action (`Subtle`). */\n stackedAction?: React.ReactNode;\n /** Row under stacked action (`Subtle`). */\n statusRow?: React.ReactNode;\n /** Primary button (e.g. Learn more). */\n primaryAction?: React.ReactNode;\n /** Text-style CTA (`whatsNew` / app store). */\n textAction?: React.ReactNode;\n /** When set, shows a dismiss control (`Default` only). */\n onDismiss?: () => void;\n /** Accessible label for dismiss. @default \"Dismiss banner\" */\n dismissLabel?: string;\n}\n\nfunction BannerDismiss({\n onDismiss,\n dismissLabel,\n}: {\n onDismiss: () => void;\n dismissLabel: string;\n}) {\n return (\n <IconButton\n variant=\"contrast\"\n size=\"24\"\n icon={<CrossIcon />}\n onClick={onDismiss}\n aria-label={dismissLabel}\n className=\"hover:bg-white/10 active:bg-white/15\"\n />\n );\n}\n\nfunction resolveLayout(variant: BannerVariant, layoutProp: BannerLayout | undefined): BannerLayout {\n if (variant === \"Subtle\") {\n return \"horizontal\";\n }\n if (isAppStoreVariant(variant)) {\n return \"vertical\";\n }\n if (variant === \"whatsNew\") {\n return layoutProp ?? \"horizontal\";\n }\n return layoutProp ?? \"vertical\";\n}\n\nfunction bannerRootClass(variant: BannerVariant, layout: BannerLayout, className?: string): string {\n return cn(\n \"flex rounded-md\",\n BANNER_SHADOW,\n variant === \"Default\" && \"gap-3 bg-surface-primary-inverted p-4 text-content-primary-inverted\",\n variant === \"Subtle\" &&\n \"w-full max-w-[600px] items-start gap-3 border border-border-primary bg-surface-secondary p-4 text-content-primary\",\n variant === \"whatsNew\" &&\n layout === \"horizontal\" &&\n \"w-full max-w-[446px] items-center gap-4 bg-surface-purple-muted p-4 text-content-primary\",\n variant === \"whatsNew\" &&\n layout === \"vertical\" &&\n \"w-full max-w-[220px] flex-col items-stretch gap-4 border border-border-primary bg-surface-secondary p-4 text-content-primary\",\n variant === \"whatsNew\" &&\n layout === \"compact\" &&\n \"w-full max-w-[446px] items-start gap-4 bg-surface-purple-muted p-4 text-content-primary\",\n isAppStoreVariant(variant) && \"w-full max-w-[280px] flex-col gap-4 p-6\",\n layout === \"vertical\" && variant === \"Default\" && \"max-w-[360px]\",\n layout === \"horizontal\" && variant === \"Default\" && \"w-full max-w-[600px] items-start\",\n className,\n );\n}\n\ntype BannerSectionProps = React.ComponentPropsWithoutRef<\"section\"> & {\n labelledBy?: string;\n};\n\nconst BannerSection = React.forwardRef<HTMLElement, BannerSectionProps>(\n ({ className, labelledBy, children, ...rest }, ref) => (\n <section\n ref={ref}\n aria-labelledby={labelledBy}\n data-testid=\"banner\"\n className={className}\n {...rest}\n >\n {children}\n </section>\n ),\n);\nBannerSection.displayName = \"BannerSection\";\n\ntype GuideBodyProps = Pick<BannerProps, \"eyebrow\" | \"title\" | \"description\" | \"textAction\"> & {\n appStoreVariant: AppStoreVariant;\n labelledBy?: string;\n};\n\nfunction BannerGuideBody({\n appStoreVariant,\n eyebrow,\n title,\n description,\n textAction,\n labelledBy,\n}: GuideBodyProps) {\n return (\n <>\n {eyebrow !== undefined && eyebrow !== null && eyebrow !== false && (\n <Badge\n variant={GUIDE_BADGE_VARIANT[appStoreVariant]}\n leftDot={false}\n className=\"typography-semibold-badge self-start\"\n >\n {eyebrow}\n </Badge>\n )}\n {title !== undefined && title !== null && title !== false && (\n <p id={labelledBy} className=\"typography-semibold-body-lg text-content-primary\">\n {title}\n </p>\n )}\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-md text-content-secondary\">{description}</p>\n )}\n {textAction}\n </>\n );\n}\n\ntype FeatureBodyProps = Pick<BannerProps, \"title\" | \"description\" | \"textAction\" | \"media\"> & {\n layout: BannerLayout;\n labelledBy?: string;\n};\n\nfunction BannerFeatureBody({\n layout,\n media,\n title,\n description,\n textAction,\n labelledBy,\n}: FeatureBodyProps) {\n const titleClass =\n layout === \"vertical\"\n ? \"typography-semibold-body-lg text-content-primary\"\n : \"typography-semibold-body-lg text-[18px] leading-6 text-content-primary\";\n const mediaWrap =\n layout === \"compact\"\n ? \"size-20 shrink-0 overflow-hidden rounded-sm\"\n : \"size-[132px] shrink-0 overflow-hidden rounded-sm\";\n\n return (\n <>\n {media !== undefined && media !== null && (\n <div className={cn(mediaWrap, layout === \"vertical\" && \"w-full [&>*]:mx-auto\")}>\n {media}\n </div>\n )}\n <div\n className={cn(\n \"flex min-w-0 flex-col gap-2\",\n layout === \"horizontal\" || layout === \"compact\" ? \"flex-1 justify-end\" : \"w-full\",\n )}\n >\n {title !== undefined && title !== null && title !== false && (\n <div id={labelledBy} className={titleClass}>\n {title}\n </div>\n )}\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-md text-content-secondary\">{description}</p>\n )}\n {textAction}\n </div>\n </>\n );\n}\n\ntype SubtleBodyProps = Pick<\n BannerProps,\n | \"media\"\n | \"leadBadge\"\n | \"title\"\n | \"description\"\n | \"secondaryLine\"\n | \"stackedAction\"\n | \"statusRow\"\n | \"primaryAction\"\n> & { labelledBy?: string };\n\nfunction BannerSubtleBody({\n media,\n leadBadge,\n title,\n description,\n secondaryLine,\n stackedAction,\n statusRow,\n primaryAction,\n labelledBy,\n}: SubtleBodyProps) {\n const mediaSizeDefault = \"size-12 shrink-0 overflow-hidden rounded-xl\";\n return (\n <>\n {media !== undefined && media !== null && <div className={mediaSizeDefault}>{media}</div>}\n <div className=\"flex min-w-0 flex-1 items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-4\">\n {leadBadge !== undefined && leadBadge !== null && (\n <div className=\"flex flex-wrap items-center gap-2\">{leadBadge}</div>\n )}\n <div className=\"flex flex-col gap-1\">\n {title !== undefined && title !== null && title !== false && (\n <div id={labelledBy} className=\"typography-bold-heading-xs text-content-primary\">\n {title}\n </div>\n )}\n <div className=\"flex flex-col gap-2\">\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-md text-content-primary\">{description}</p>\n )}\n {secondaryLine !== undefined && secondaryLine !== null && secondaryLine !== false && (\n <p className=\"typography-regular-body-sm text-content-primary\">{secondaryLine}</p>\n )}\n </div>\n </div>\n {stackedAction !== undefined && stackedAction !== null && (\n <div className=\"flex flex-col items-end self-start\">{stackedAction}</div>\n )}\n {statusRow !== undefined && statusRow !== null && (\n <div className=\"flex flex-wrap items-center gap-2\">{statusRow}</div>\n )}\n </div>\n {primaryAction !== undefined && primaryAction !== null && (\n <div className=\"shrink-0 self-center\">{primaryAction}</div>\n )}\n </div>\n </>\n );\n}\n\ntype InverseBodyProps = Pick<\n BannerProps,\n \"media\" | \"eyebrow\" | \"title\" | \"description\" | \"primaryAction\"\n> & {\n layout: BannerLayout;\n labelledBy?: string;\n dismissSlot: React.ReactNode;\n};\n\nfunction BannerInverseBody({\n layout,\n media,\n eyebrow,\n title,\n description,\n primaryAction,\n labelledBy,\n dismissSlot,\n}: InverseBodyProps) {\n const mediaSizeDefault = \"size-12 shrink-0 overflow-hidden rounded-xl\";\n const titleClassInverse = \"typography-bold-heading-xs text-content-primary-inverted\";\n const textColumn = (\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n {eyebrow !== undefined && eyebrow !== null && eyebrow !== false && (\n <p className=\"typography-semibold-body-sm text-content-primary-inverted\">{eyebrow}</p>\n )}\n {title !== undefined && title !== null && title !== false && (\n <div id={labelledBy} className={titleClassInverse}>\n {title}\n </div>\n )}\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-md text-content-primary-inverted\">{description}</p>\n )}\n </div>\n );\n\n return (\n <>\n {media !== undefined && media !== null && <div className={mediaSizeDefault}>{media}</div>}\n {layout === \"horizontal\" ? (\n <div className=\"flex min-w-0 flex-1 items-end gap-3\">\n {textColumn}\n {primaryAction !== undefined && primaryAction !== null && (\n <div className=\"shrink-0\">{primaryAction}</div>\n )}\n </div>\n ) : (\n <div className=\"flex min-w-0 flex-1 flex-col gap-3\">\n {textColumn}\n {primaryAction !== undefined && primaryAction !== null && <div>{primaryAction}</div>}\n </div>\n )}\n {dismissSlot}\n </>\n );\n}\n\nexport const Banner = React.forwardRef<HTMLElement, BannerProps>(\n (\n {\n className,\n variant,\n layout: layoutProp,\n media,\n eyebrow,\n leadBadge,\n title,\n description,\n secondaryLine,\n stackedAction,\n statusRow,\n primaryAction,\n textAction,\n onDismiss,\n dismissLabel = \"Dismiss banner\",\n ...props\n },\n ref,\n ) => {\n const layout = resolveLayout(variant, layoutProp);\n const showDismiss = onDismiss !== undefined && variant === \"Default\";\n const titleId = React.useId();\n const regionLabelledBy =\n title !== undefined && title !== null && title !== false ? titleId : undefined;\n\n const rootClass = bannerRootClass(variant, layout, className);\n\n if (isAppStoreVariant(variant)) {\n return (\n <BannerSection\n ref={ref}\n labelledBy={regionLabelledBy}\n style={guideGradient[variant]}\n className={rootClass}\n {...props}\n >\n <BannerGuideBody\n appStoreVariant={variant}\n eyebrow={eyebrow}\n title={title}\n description={description}\n textAction={textAction}\n labelledBy={regionLabelledBy}\n />\n </BannerSection>\n );\n }\n\n if (variant === \"whatsNew\") {\n return (\n <BannerSection ref={ref} labelledBy={regionLabelledBy} className={rootClass} {...props}>\n <BannerFeatureBody\n layout={layout}\n media={media}\n title={title}\n description={description}\n textAction={textAction}\n labelledBy={regionLabelledBy}\n />\n </BannerSection>\n );\n }\n\n if (variant === \"Subtle\") {\n return (\n <BannerSection ref={ref} labelledBy={regionLabelledBy} className={rootClass} {...props}>\n <BannerSubtleBody\n media={media}\n leadBadge={leadBadge}\n title={title}\n description={description}\n secondaryLine={secondaryLine}\n stackedAction={stackedAction}\n statusRow={statusRow}\n primaryAction={primaryAction}\n labelledBy={regionLabelledBy}\n />\n </BannerSection>\n );\n }\n\n const dismissSlot =\n showDismiss && onDismiss !== undefined ? (\n <BannerDismiss onDismiss={onDismiss} dismissLabel={dismissLabel} />\n ) : null;\n\n return (\n <BannerSection ref={ref} labelledBy={regionLabelledBy} className={rootClass} {...props}>\n <div className=\"flex w-full items-start gap-3\">\n <BannerInverseBody\n layout={layout}\n media={media}\n eyebrow={eyebrow}\n title={title}\n description={description}\n primaryAction={primaryAction}\n labelledBy={regionLabelledBy}\n dismissSlot={dismissSlot}\n />\n </div>\n </BannerSection>\n );\n },\n);\n\nBanner.displayName = \"Banner\";\n"],"names":[],"mappings":"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"}
@@ -27,13 +27,21 @@ const SIZE_CLASSES = {
27
27
  md: "sm:max-w-[440px]",
28
28
  lg: "sm:max-w-[600px]"
29
29
  };
30
- const DialogContent = React.forwardRef(({ className, children, size = "md", overlay = true, style, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
30
+ const DialogContent = React.forwardRef(({ className, children, size = "md", overlay = true, style, onOpenAutoFocus, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
31
31
  overlay && /* @__PURE__ */ jsx(DialogOverlay, {}),
32
32
  /* @__PURE__ */ jsx(
33
33
  DialogPrimitive.Content,
34
34
  {
35
35
  ref,
36
36
  style: { zIndex: "var(--fanvue-ui-portal-z-index, 50)", ...style },
37
+ onOpenAutoFocus: (e) => {
38
+ if (onOpenAutoFocus) {
39
+ onOpenAutoFocus(e);
40
+ return;
41
+ }
42
+ e.preventDefault();
43
+ e.currentTarget.focus();
44
+ },
37
45
  className: cn(
38
46
  // Base
39
47
  "fixed flex flex-col overflow-hidden bg-bg-primary shadow-lg focus:outline-none dark:bg-surface-primary",
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.mjs","sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { ArrowLeftIcon } from \"../Icons/ArrowLeftIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** Props for the {@link Dialog} root component. */\nexport interface DialogProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root> {\n /** Controlled open state. When provided, you must also supply `onOpenChange`. */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the dialog when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a dialog. */\nexport const Dialog = DialogPrimitive.Root;\n\n/** Props for the {@link DialogTrigger} component. */\nexport type DialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\n\n/** The element that opens the dialog when clicked. */\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\n/** Convenience alias for Radix `Dialog.Close`. Closes the dialog when clicked. */\nexport const DialogClose = DialogPrimitive.Close;\n\n/** Props for the {@link DialogClose} component. */\nexport type DialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogOverlayProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> {}\n\n/**\n * Semi-transparent backdrop rendered behind the dialog content.\n * Rendered inside a portal automatically by {@link DialogContent}.\n */\nexport const DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n DialogOverlayProps\n>(({ className, style, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 fixed inset-0 bg-bg-overlay data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className,\n )}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n {...props}\n />\n));\nDialogOverlay.displayName = \"DialogOverlay\";\n\nexport interface DialogContentProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {\n /**\n * Width preset for the dialog.\n * - `\"sm\"` — 400px max-width (confirmations, simple forms)\n * - `\"md\"` — 440px max-width (default, standard dialogs)\n * - `\"lg\"` — 600px max-width (complex content, tables)\n *\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** When true, renders overlay automatically. @default true */\n overlay?: boolean;\n}\n\nconst SIZE_CLASSES: Record<NonNullable<DialogContentProps[\"size\"]>, string> = {\n sm: \"sm:max-w-[400px]\",\n md: \"sm:max-w-[440px]\",\n lg: \"sm:max-w-[600px]\",\n};\n\n/**\n * The dialog panel rendered inside a portal. Includes the overlay by default.\n *\n * On mobile viewports (<640px), the dialog slides up from the bottom as a sheet\n * with top-only border radius. On larger viewports it renders centered with\n * full border radius.\n *\n * @example\n * ```tsx\n * <Dialog>\n * <DialogTrigger asChild>\n * <Button>Open</Button>\n * </DialogTrigger>\n * <DialogContent>\n * <DialogHeader>\n * <DialogTitle>Title</DialogTitle>\n * </DialogHeader>\n * <DialogBody>Content here</DialogBody>\n * <DialogFooter>\n * <DialogClose asChild>\n * <Button variant=\"secondary\">Cancel</Button>\n * </DialogClose>\n * <Button>Accept</Button>\n * </DialogFooter>\n * </DialogContent>\n * </Dialog>\n * ```\n */\nexport const DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n DialogContentProps\n>(({ className, children, size = \"md\", overlay = true, style, ...props }, ref) => (\n <DialogPrimitive.Portal>\n {overlay && <DialogOverlay />}\n <DialogPrimitive.Content\n ref={ref}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n className={cn(\n // Base\n \"fixed flex flex-col overflow-hidden bg-bg-primary shadow-lg focus:outline-none dark:bg-surface-primary\",\n // Mobile: bottom sheet\n \"inset-x-0 bottom-0 max-h-[85vh] w-full rounded-t-lg\",\n // Animation (shared)\n \"data-[state=open]:fade-in-0 data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:animate-out\",\n // Mobile: slide up from bottom\n \"data-[state=open]:slide-in-from-bottom-full\",\n \"data-[state=closed]:slide-out-to-bottom-full\",\n // Desktop: centered dialog\n \"sm:inset-auto sm:top-1/2 sm:left-1/2 sm:max-h-[85vh] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-lg\",\n // Desktop: scale in/out (cancel mobile slide)\n \"sm:data-[state=open]:slide-in-from-bottom-0 sm:data-[state=open]:zoom-in-95\",\n \"sm:data-[state=closed]:slide-out-to-bottom-0 sm:data-[state=closed]:zoom-out-95\",\n // Duration\n \"duration-200\",\n // Size\n SIZE_CLASSES[size],\n className,\n )}\n {...props}\n >\n {children}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n));\nDialogContent.displayName = \"DialogContent\";\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Show the close (X) button in the header. @default true */\n showClose?: boolean;\n /** Show a back arrow button on the left side. Defaults to `true` when `onBack` is provided. */\n showBack?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Accessible label for the back button. @default \"Go back\" */\n backLabel?: string;\n /** Accessible label for the close button. @default \"Close\" */\n closeLabel?: string;\n}\n\n/**\n * Header bar for the dialog. Renders the title with an optional back arrow\n * and close button.\n *\n * @example\n * ```tsx\n * <DialogHeader>\n * <DialogTitle>Settings</DialogTitle>\n * </DialogHeader>\n *\n * <DialogHeader showBack onBack={() => setStep(0)}>\n * <DialogTitle>Step 2</DialogTitle>\n * </DialogHeader>\n * ```\n */\nexport const DialogHeader = React.forwardRef<HTMLDivElement, DialogHeaderProps>(\n (\n {\n className,\n children,\n showClose = true,\n showBack,\n onBack,\n backLabel = \"Go back\",\n closeLabel = \"Close\",\n ...props\n },\n ref,\n ) => {\n const shouldShowBack = showBack ?? !!onBack;\n\n return (\n <div\n ref={ref}\n className={cn(\"flex h-16 shrink-0 items-center gap-2 px-6 py-4\", className)}\n {...props}\n >\n {shouldShowBack && (\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n icon={<ArrowLeftIcon />}\n onClick={onBack}\n disabled={!onBack}\n aria-label={backLabel}\n />\n )}\n <div className=\"min-w-0 flex-1\">{children}</div>\n {showClose && (\n <DialogPrimitive.Close asChild>\n <IconButton variant=\"tertiary\" size=\"32\" icon={<CloseIcon />} aria-label={closeLabel} />\n </DialogPrimitive.Close>\n )}\n </div>\n );\n },\n);\nDialogHeader.displayName = \"DialogHeader\";\n\n/** Props for the {@link DialogTitle} component. */\nexport type DialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\n\n/**\n * Accessible title for the dialog. Must be rendered inside {@link DialogHeader}\n * or directly within {@link DialogContent}.\n */\nexport const DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n DialogTitleProps\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\"typography-bold-heading-xs truncate text-content-primary\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = \"DialogTitle\";\n\n/** Props for the {@link DialogDescription} component. */\nexport type DialogDescriptionProps = React.ComponentPropsWithoutRef<\n typeof DialogPrimitive.Description\n>;\n\n/** Accessible description for the dialog. Rendered as secondary text. */\nexport const DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n DialogDescriptionProps\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"typography-regular-body-lg text-content-secondary\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = \"DialogDescription\";\n\nexport interface DialogBodyProps extends React.HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Scrollable content area (slot) between the header and footer.\n * Grows to fill available space and scrolls when content overflows.\n */\nexport const DialogBody = React.forwardRef<HTMLDivElement, DialogBodyProps>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex-1 overflow-y-auto px-6 py-4\", className)} {...props} />\n ),\n);\nDialogBody.displayName = \"DialogBody\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Footer bar for the dialog. Typically contains action buttons.\n * Children are laid out in a horizontal row with equal flex-basis.\n */\nexport const DialogFooter = React.forwardRef<HTMLDivElement, DialogFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"flex shrink-0 items-center gap-3 px-6 pt-3 pb-6\",\n \"[&>*]:min-w-0 [&>*]:flex-1\",\n className,\n )}\n {...props}\n />\n ),\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Dialog.mjs","sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { ArrowLeftIcon } from \"../Icons/ArrowLeftIcon\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\n\n/** Props for the {@link Dialog} root component. */\nexport interface DialogProps extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Root> {\n /** Controlled open state. When provided, you must also supply `onOpenChange`. */\n open?: boolean;\n /** Called when the open state changes. Required when `open` is controlled. */\n onOpenChange?: (open: boolean) => void;\n /** The open state of the dialog when it is initially rendered (uncontrolled). */\n defaultOpen?: boolean;\n}\n\n/** Root component that manages open/close state for a dialog. */\nexport const Dialog = DialogPrimitive.Root;\n\n/** Props for the {@link DialogTrigger} component. */\nexport type DialogTriggerProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger>;\n\n/** The element that opens the dialog when clicked. */\nexport const DialogTrigger = DialogPrimitive.Trigger;\n\n/** Convenience alias for Radix `Dialog.Close`. Closes the dialog when clicked. */\nexport const DialogClose = DialogPrimitive.Close;\n\n/** Props for the {@link DialogClose} component. */\nexport type DialogCloseProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close>;\n\nexport interface DialogOverlayProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> {}\n\n/**\n * Semi-transparent backdrop rendered behind the dialog content.\n * Rendered inside a portal automatically by {@link DialogContent}.\n */\nexport const DialogOverlay = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Overlay>,\n DialogOverlayProps\n>(({ className, style, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 fixed inset-0 bg-bg-overlay data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className,\n )}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n {...props}\n />\n));\nDialogOverlay.displayName = \"DialogOverlay\";\n\nexport interface DialogContentProps\n extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {\n /**\n * Width preset for the dialog.\n * - `\"sm\"` — 400px max-width (confirmations, simple forms)\n * - `\"md\"` — 440px max-width (default, standard dialogs)\n * - `\"lg\"` — 600px max-width (complex content, tables)\n *\n * @default \"md\"\n */\n size?: \"sm\" | \"md\" | \"lg\";\n /** When true, renders overlay automatically. @default true */\n overlay?: boolean;\n}\n\nconst SIZE_CLASSES: Record<NonNullable<DialogContentProps[\"size\"]>, string> = {\n sm: \"sm:max-w-[400px]\",\n md: \"sm:max-w-[440px]\",\n lg: \"sm:max-w-[600px]\",\n};\n\n/**\n * The dialog panel rendered inside a portal. Includes the overlay by default.\n *\n * On mobile viewports (<640px), the dialog slides up from the bottom as a sheet\n * with top-only border radius. On larger viewports it renders centered with\n * full border radius.\n *\n * @example\n * ```tsx\n * <Dialog>\n * <DialogTrigger asChild>\n * <Button>Open</Button>\n * </DialogTrigger>\n * <DialogContent>\n * <DialogHeader>\n * <DialogTitle>Title</DialogTitle>\n * </DialogHeader>\n * <DialogBody>Content here</DialogBody>\n * <DialogFooter>\n * <DialogClose asChild>\n * <Button variant=\"secondary\">Cancel</Button>\n * </DialogClose>\n * <Button>Accept</Button>\n * </DialogFooter>\n * </DialogContent>\n * </Dialog>\n * ```\n */\nexport const DialogContent = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Content>,\n DialogContentProps\n>(({ className, children, size = \"md\", overlay = true, style, onOpenAutoFocus, ...props }, ref) => (\n <DialogPrimitive.Portal>\n {overlay && <DialogOverlay />}\n <DialogPrimitive.Content\n ref={ref}\n style={{ zIndex: \"var(--fanvue-ui-portal-z-index, 50)\", ...style }}\n onOpenAutoFocus={(e) => {\n if (onOpenAutoFocus) {\n onOpenAutoFocus(e);\n return;\n }\n e.preventDefault();\n (e.currentTarget as HTMLElement).focus();\n }}\n className={cn(\n // Base\n \"fixed flex flex-col overflow-hidden bg-bg-primary shadow-lg focus:outline-none dark:bg-surface-primary\",\n // Mobile: bottom sheet\n \"inset-x-0 bottom-0 max-h-[85vh] w-full rounded-t-lg\",\n // Animation (shared)\n \"data-[state=open]:fade-in-0 data-[state=open]:animate-in\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:animate-out\",\n // Mobile: slide up from bottom\n \"data-[state=open]:slide-in-from-bottom-full\",\n \"data-[state=closed]:slide-out-to-bottom-full\",\n // Desktop: centered dialog\n \"sm:inset-auto sm:top-1/2 sm:left-1/2 sm:max-h-[85vh] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-lg\",\n // Desktop: scale in/out (cancel mobile slide)\n \"sm:data-[state=open]:slide-in-from-bottom-0 sm:data-[state=open]:zoom-in-95\",\n \"sm:data-[state=closed]:slide-out-to-bottom-0 sm:data-[state=closed]:zoom-out-95\",\n // Duration\n \"duration-200\",\n // Size\n SIZE_CLASSES[size],\n className,\n )}\n {...props}\n >\n {children}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n));\nDialogContent.displayName = \"DialogContent\";\n\nexport interface DialogHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Show the close (X) button in the header. @default true */\n showClose?: boolean;\n /** Show a back arrow button on the left side. Defaults to `true` when `onBack` is provided. */\n showBack?: boolean;\n /** Called when the back button is clicked. */\n onBack?: () => void;\n /** Accessible label for the back button. @default \"Go back\" */\n backLabel?: string;\n /** Accessible label for the close button. @default \"Close\" */\n closeLabel?: string;\n}\n\n/**\n * Header bar for the dialog. Renders the title with an optional back arrow\n * and close button.\n *\n * @example\n * ```tsx\n * <DialogHeader>\n * <DialogTitle>Settings</DialogTitle>\n * </DialogHeader>\n *\n * <DialogHeader showBack onBack={() => setStep(0)}>\n * <DialogTitle>Step 2</DialogTitle>\n * </DialogHeader>\n * ```\n */\nexport const DialogHeader = React.forwardRef<HTMLDivElement, DialogHeaderProps>(\n (\n {\n className,\n children,\n showClose = true,\n showBack,\n onBack,\n backLabel = \"Go back\",\n closeLabel = \"Close\",\n ...props\n },\n ref,\n ) => {\n const shouldShowBack = showBack ?? !!onBack;\n\n return (\n <div\n ref={ref}\n className={cn(\"flex h-16 shrink-0 items-center gap-2 px-6 py-4\", className)}\n {...props}\n >\n {shouldShowBack && (\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n icon={<ArrowLeftIcon />}\n onClick={onBack}\n disabled={!onBack}\n aria-label={backLabel}\n />\n )}\n <div className=\"min-w-0 flex-1\">{children}</div>\n {showClose && (\n <DialogPrimitive.Close asChild>\n <IconButton variant=\"tertiary\" size=\"32\" icon={<CloseIcon />} aria-label={closeLabel} />\n </DialogPrimitive.Close>\n )}\n </div>\n );\n },\n);\nDialogHeader.displayName = \"DialogHeader\";\n\n/** Props for the {@link DialogTitle} component. */\nexport type DialogTitleProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>;\n\n/**\n * Accessible title for the dialog. Must be rendered inside {@link DialogHeader}\n * or directly within {@link DialogContent}.\n */\nexport const DialogTitle = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Title>,\n DialogTitleProps\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\"typography-bold-heading-xs truncate text-content-primary\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = \"DialogTitle\";\n\n/** Props for the {@link DialogDescription} component. */\nexport type DialogDescriptionProps = React.ComponentPropsWithoutRef<\n typeof DialogPrimitive.Description\n>;\n\n/** Accessible description for the dialog. Rendered as secondary text. */\nexport const DialogDescription = React.forwardRef<\n React.ComponentRef<typeof DialogPrimitive.Description>,\n DialogDescriptionProps\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"typography-regular-body-lg text-content-secondary\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = \"DialogDescription\";\n\nexport interface DialogBodyProps extends React.HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Scrollable content area (slot) between the header and footer.\n * Grows to fill available space and scrolls when content overflows.\n */\nexport const DialogBody = React.forwardRef<HTMLDivElement, DialogBodyProps>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex-1 overflow-y-auto px-6 py-4\", className)} {...props} />\n ),\n);\nDialogBody.displayName = \"DialogBody\";\n\nexport interface DialogFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Footer bar for the dialog. Typically contains action buttons.\n * Children are laid out in a horizontal row with equal flex-basis.\n */\nexport const DialogFooter = React.forwardRef<HTMLDivElement, DialogFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"flex shrink-0 items-center gap-3 px-6 pt-3 pb-6\",\n \"[&>*]:min-w-0 [&>*]:flex-1\",\n className,\n )}\n {...props}\n />\n ),\n);\nDialogFooter.displayName = \"DialogFooter\";\n"],"names":[],"mappings":";;;;;;;;AAkBO,MAAM,SAAS,gBAAgB;AAM/B,MAAM,gBAAgB,gBAAgB;AAGtC,MAAM,cAAc,gBAAgB;AAYpC,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,OAAO,GAAG,SAAS,QACjC;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,IAC1D,GAAG;AAAA,EAAA;AACN,CACD;AACD,cAAc,cAAc;AAiB5B,MAAM,eAAwE;AAAA,EAC5E,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AA8BO,MAAM,gBAAgB,MAAM,WAGjC,CAAC,EAAE,WAAW,UAAU,OAAO,MAAM,UAAU,MAAM,OAAO,iBAAiB,GAAG,SAAS,QACzF,qBAAC,gBAAgB,QAAhB,EACE,UAAA;AAAA,EAAA,+BAAY,eAAA,EAAc;AAAA,EAC3B;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACC;AAAA,MACA,OAAO,EAAE,QAAQ,uCAAuC,GAAG,MAAA;AAAA,MAC3D,iBAAiB,CAAC,MAAM;AACtB,YAAI,iBAAiB;AACnB,0BAAgB,CAAC;AACjB;AAAA,QACF;AACA,UAAE,eAAA;AACD,UAAE,cAA8B,MAAA;AAAA,MACnC;AAAA,MACA,WAAW;AAAA;AAAA,QAET;AAAA;AAAA,QAEA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA;AAAA,QAEA;AAAA,QACA;AAAA;AAAA,QAEA;AAAA;AAAA,QAEA,aAAa,IAAI;AAAA,QACjB;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,MAEH;AAAA,IAAA;AAAA,EAAA;AACH,GACF,CACD;AACD,cAAc,cAAc;AA8BrB,MAAM,eAAe,MAAM;AAAA,EAChC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,iBAAiB,YAAY,CAAC,CAAC;AAErC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,mDAAmD,SAAS;AAAA,QACzE,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,kBACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,0BAAO,eAAA,EAAc;AAAA,cACrB,SAAS;AAAA,cACT,UAAU,CAAC;AAAA,cACX,cAAY;AAAA,YAAA;AAAA,UAAA;AAAA,UAGhB,oBAAC,OAAA,EAAI,WAAU,kBAAkB,SAAA,CAAS;AAAA,UACzC,aACC,oBAAC,gBAAgB,OAAhB,EAAsB,SAAO,MAC5B,UAAA,oBAAC,YAAA,EAAW,SAAQ,YAAW,MAAK,MAAK,MAAM,oBAAC,aAAU,GAAI,cAAY,YAAY,EAAA,CACxF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AACA,aAAa,cAAc;AASpB,MAAM,cAAc,MAAM,WAG/B,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,4DAA4D,SAAS;AAAA,IAClF,GAAG;AAAA,EAAA;AACN,CACD;AACD,YAAY,cAAc;AAQnB,MAAM,oBAAoB,MAAM,WAGrC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,gBAAgB;AAAA,EAAhB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,qDAAqD,SAAS;AAAA,IAC3E,GAAG;AAAA,EAAA;AACN,CACD;AACD,kBAAkB,cAAc;AAQzB,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,oCAAoC,SAAS,GAAI,GAAG,MAAA,CAAO;AAE5F;AACA,WAAW,cAAc;AAQlB,MAAM,eAAe,MAAM;AAAA,EAChC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QACxB;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AACA,aAAa,cAAc;"}
@@ -21,7 +21,7 @@ const DropdownMenuContent = React.forwardRef(
21
21
  sideOffset,
22
22
  collisionPadding,
23
23
  className: cn(
24
- "w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
24
+ "w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-xs border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg",
25
25
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
26
26
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
27
27
  "data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2",
@@ -1 +1 @@
1
- {"version":3,"file":"DropdownMenu.mjs","sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n style,\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n className={cn(\n \"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-sm border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\",\n \"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2\",\n \"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2\",\n className,\n )}\n style={{\n zIndex: \"var(--fanvue-ui-portal-z-index, 50)\",\n maxHeight: \"var(--radix-dropdown-menu-content-available-height)\",\n ...style,\n }}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n ),\n);\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\n/** Props for the {@link DropdownMenuGroup} component. */\nexport type DropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Group\n>;\n\n/** Groups related menu items. Accepts an optional `DropdownMenuLabel`. */\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nDropdownMenuGroup.displayName = \"DropdownMenuGroup\";\n\n/** Props for the {@link DropdownMenuLabel} component. */\nexport interface DropdownMenuLabelProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> {}\n\n/** A label for a group of items. Not focusable or selectable. */\nexport const DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n DropdownMenuLabelProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"typography-medium-body-xs px-2 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\n/** Available sizes for a dropdown menu item. */\nexport type DropdownMenuItemSize = \"sm\" | \"md\";\n\nexport interface DropdownMenuItemProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> {\n /** Height of the menu item row. @default \"sm\" */\n size?: DropdownMenuItemSize;\n /** Whether the item uses destructive (error) styling. */\n destructive?: boolean;\n /** Icon rendered before the label. */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after the label. */\n trailingIcon?: React.ReactNode;\n /** Whether the item is in a selected state. */\n selected?: boolean;\n}\n\n/**\n * An individual item within a {@link DropdownMenuContent}.\n *\n * @example\n * ```tsx\n * <DropdownMenuItem>Edit profile</DropdownMenuItem>\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * <DropdownMenuItem leadingIcon={<EditIcon />}>Edit</DropdownMenuItem>\n *\n * // As a link\n * <DropdownMenuItem asChild>\n * <a href=\"/settings\">Settings</a>\n * </DropdownMenuItem>\n * ```\n */\nexport const DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n {\n size = \"sm\",\n destructive,\n leadingIcon,\n trailingIcon,\n selected,\n className,\n children,\n asChild,\n ...props\n },\n ref,\n ) => {\n const itemClassName = cn(\n \"flex w-full cursor-pointer items-center gap-1 rounded px-2 outline-none\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"data-[highlighted]:bg-neutral-alphas-100\",\n size === \"sm\" ? \"min-h-[34px] py-1\" : \"min-h-[40px] py-1.5\",\n size === \"sm\" ? \"typography-medium-body-sm\" : \"typography-medium-body-md\",\n destructive && \"text-error-content\",\n selected && \"bg-success-surface\",\n className,\n );\n\n if (asChild) {\n return (\n <DropdownMenuPrimitive.Item ref={ref} asChild className={itemClassName} {...props}>\n {children}\n </DropdownMenuPrimitive.Item>\n );\n }\n\n return (\n <DropdownMenuPrimitive.Item ref={ref} className={itemClassName} {...props}>\n {leadingIcon}\n <span className=\"flex-1\">{children}</span>\n {trailingIcon}\n </DropdownMenuPrimitive.Item>\n );\n },\n);\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\n/** Props for the {@link DropdownMenuSeparator} component. */\nexport interface DropdownMenuSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> {}\n\n/** Visual separator between groups of items. */\nexport const DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n DropdownMenuSeparatorProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n"],"names":[],"mappings":";;;;;;AAUO,MAAM,eAAe,sBAAsB;AAQ3C,MAAM,sBAAsB,sBAAsB;AACzD,oBAAoB,cAAc;AAyB3B,MAAM,sBAAsB,MAAM;AAAA,EAIvC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QAEA,oBAAC,sBAAsB,QAAtB,EACC,UAAA;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,GAAG;AAAA,MAAA;AAAA,MAEJ,GAAG;AAAA,IAAA;AAAA,EAAA,EACN,CACF;AAEJ;AACA,oBAAoB,cAAc;AAQ3B,MAAM,oBAAoB,sBAAsB;AACvD,kBAAkB,cAAc;AAOzB,MAAM,oBAAoB,MAAM,WAGrC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,gEAAgE,SAAS;AAAA,IACtF,GAAG;AAAA,EAAA;AACN,CACD;AACD,kBAAkB,cAAc;AAkCzB,MAAM,mBAAmB,MAAM;AAAA,EAIpC,CACE;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO,sBAAsB;AAAA,MACtC,SAAS,OAAO,8BAA8B;AAAA,MAC9C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,IAAA;AAGF,QAAI,SAAS;AACX,aACE,oBAAC,sBAAsB,MAAtB,EAA2B,KAAU,SAAO,MAAC,WAAW,eAAgB,GAAG,OACzE,SAAA,CACH;AAAA,IAEJ;AAEA,WACE,qBAAC,sBAAsB,MAAtB,EAA2B,KAAU,WAAW,eAAgB,GAAG,OACjE,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAA,EAAK,WAAU,UAAU,SAAA,CAAS;AAAA,MAClC;AAAA,IAAA,GACH;AAAA,EAEJ;AACF;AACA,iBAAiB,cAAc;AAOxB,MAAM,wBAAwB,MAAM,WAGzC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,mCAAmC,SAAS;AAAA,IACzD,GAAG;AAAA,EAAA;AACN,CACD;AACD,sBAAsB,cAAc;"}
1
+ {"version":3,"file":"DropdownMenu.mjs","sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FLOATING_CONTENT_COLLISION_PADDING } from \"../../utils/floatingContentCollisionPadding\";\n\n/** Props for the {@link DropdownMenu} root component. */\nexport interface DropdownMenuProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root> {}\n\n/** Root component that manages open/close state for a dropdown menu. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root;\n\n/** Props for the {@link DropdownMenuTrigger} component. */\nexport type DropdownMenuTriggerProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Trigger\n>;\n\n/** The element that toggles the dropdown menu when clicked. */\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nDropdownMenuTrigger.displayName = \"DropdownMenuTrigger\";\n\n/** Props for the {@link DropdownMenuContent} component. */\nexport interface DropdownMenuContentProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> {}\n\n/**\n * The positioned content panel rendered inside a portal.\n *\n * Override the portal z-index per-instance via `style={{ zIndex: 1500 }}` or\n * globally with the `--fanvue-ui-portal-z-index` CSS custom property.\n *\n * @example\n * ```tsx\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild>\n * <Button>Open</Button>\n * </DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuItem>Option 1</DropdownMenuItem>\n * <DropdownMenuItem>Option 2</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n * ```\n */\nexport const DropdownMenuContent = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n DropdownMenuContentProps\n>(\n (\n {\n className,\n style,\n sideOffset = 4,\n collisionPadding = FLOATING_CONTENT_COLLISION_PADDING,\n ...props\n },\n ref,\n ) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n collisionPadding={collisionPadding}\n className={cn(\n \"w-max min-w-(--radix-dropdown-menu-trigger-width) max-w-(--radix-dropdown-menu-content-available-width) overflow-y-auto rounded-xs border border-neutral-alphas-200 bg-bg-primary p-1 shadow-lg\",\n \"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95\",\n \"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95\",\n \"data-[side=top]:slide-in-from-bottom-2 data-[side=bottom]:slide-in-from-top-2\",\n \"data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2\",\n className,\n )}\n style={{\n zIndex: \"var(--fanvue-ui-portal-z-index, 50)\",\n maxHeight: \"var(--radix-dropdown-menu-content-available-height)\",\n ...style,\n }}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n ),\n);\nDropdownMenuContent.displayName = \"DropdownMenuContent\";\n\n/** Props for the {@link DropdownMenuGroup} component. */\nexport type DropdownMenuGroupProps = React.ComponentPropsWithoutRef<\n typeof DropdownMenuPrimitive.Group\n>;\n\n/** Groups related menu items. Accepts an optional `DropdownMenuLabel`. */\nexport const DropdownMenuGroup = DropdownMenuPrimitive.Group;\nDropdownMenuGroup.displayName = \"DropdownMenuGroup\";\n\n/** Props for the {@link DropdownMenuLabel} component. */\nexport interface DropdownMenuLabelProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> {}\n\n/** A label for a group of items. Not focusable or selectable. */\nexport const DropdownMenuLabel = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n DropdownMenuLabelProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"typography-medium-body-xs px-2 py-1.5 text-content-secondary\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = \"DropdownMenuLabel\";\n\n/** Available sizes for a dropdown menu item. */\nexport type DropdownMenuItemSize = \"sm\" | \"md\";\n\nexport interface DropdownMenuItemProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> {\n /** Height of the menu item row. @default \"sm\" */\n size?: DropdownMenuItemSize;\n /** Whether the item uses destructive (error) styling. */\n destructive?: boolean;\n /** Icon rendered before the label. */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after the label. */\n trailingIcon?: React.ReactNode;\n /** Whether the item is in a selected state. */\n selected?: boolean;\n}\n\n/**\n * An individual item within a {@link DropdownMenuContent}.\n *\n * @example\n * ```tsx\n * <DropdownMenuItem>Edit profile</DropdownMenuItem>\n * <DropdownMenuItem destructive>Delete</DropdownMenuItem>\n * <DropdownMenuItem leadingIcon={<EditIcon />}>Edit</DropdownMenuItem>\n *\n * // As a link\n * <DropdownMenuItem asChild>\n * <a href=\"/settings\">Settings</a>\n * </DropdownMenuItem>\n * ```\n */\nexport const DropdownMenuItem = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n DropdownMenuItemProps\n>(\n (\n {\n size = \"sm\",\n destructive,\n leadingIcon,\n trailingIcon,\n selected,\n className,\n children,\n asChild,\n ...props\n },\n ref,\n ) => {\n const itemClassName = cn(\n \"flex w-full cursor-pointer items-center gap-1 rounded px-2 outline-none\",\n \"data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\",\n \"data-[highlighted]:bg-neutral-alphas-100\",\n size === \"sm\" ? \"min-h-[34px] py-1\" : \"min-h-[40px] py-1.5\",\n size === \"sm\" ? \"typography-medium-body-sm\" : \"typography-medium-body-md\",\n destructive && \"text-error-content\",\n selected && \"bg-success-surface\",\n className,\n );\n\n if (asChild) {\n return (\n <DropdownMenuPrimitive.Item ref={ref} asChild className={itemClassName} {...props}>\n {children}\n </DropdownMenuPrimitive.Item>\n );\n }\n\n return (\n <DropdownMenuPrimitive.Item ref={ref} className={itemClassName} {...props}>\n {leadingIcon}\n <span className=\"flex-1\">{children}</span>\n {trailingIcon}\n </DropdownMenuPrimitive.Item>\n );\n },\n);\nDropdownMenuItem.displayName = \"DropdownMenuItem\";\n\n/** Props for the {@link DropdownMenuSeparator} component. */\nexport interface DropdownMenuSeparatorProps\n extends React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> {}\n\n/** Visual separator between groups of items. */\nexport const DropdownMenuSeparator = React.forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n DropdownMenuSeparatorProps\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"my-1 h-px bg-neutral-alphas-200\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = \"DropdownMenuSeparator\";\n"],"names":[],"mappings":";;;;;;AAUO,MAAM,eAAe,sBAAsB;AAQ3C,MAAM,sBAAsB,sBAAsB;AACzD,oBAAoB,cAAc;AAyB3B,MAAM,sBAAsB,MAAM;AAAA,EAIvC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,GAEL,QAEA,oBAAC,sBAAsB,QAAtB,EACC,UAAA;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,GAAG;AAAA,MAAA;AAAA,MAEJ,GAAG;AAAA,IAAA;AAAA,EAAA,EACN,CACF;AAEJ;AACA,oBAAoB,cAAc;AAQ3B,MAAM,oBAAoB,sBAAsB;AACvD,kBAAkB,cAAc;AAOzB,MAAM,oBAAoB,MAAM,WAGrC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,gEAAgE,SAAS;AAAA,IACtF,GAAG;AAAA,EAAA;AACN,CACD;AACD,kBAAkB,cAAc;AAkCzB,MAAM,mBAAmB,MAAM;AAAA,EAIpC,CACE;AAAA,IACE,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,OAAO,sBAAsB;AAAA,MACtC,SAAS,OAAO,8BAA8B;AAAA,MAC9C,eAAe;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,IAAA;AAGF,QAAI,SAAS;AACX,aACE,oBAAC,sBAAsB,MAAtB,EAA2B,KAAU,SAAO,MAAC,WAAW,eAAgB,GAAG,OACzE,SAAA,CACH;AAAA,IAEJ;AAEA,WACE,qBAAC,sBAAsB,MAAtB,EAA2B,KAAU,WAAW,eAAgB,GAAG,OACjE,UAAA;AAAA,MAAA;AAAA,MACD,oBAAC,QAAA,EAAK,WAAU,UAAU,SAAA,CAAS;AAAA,MAClC;AAAA,IAAA,GACH;AAAA,EAEJ;AACF;AACA,iBAAiB,cAAc;AAOxB,MAAM,wBAAwB,MAAM,WAGzC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1B;AAAA,EAAC,sBAAsB;AAAA,EAAtB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,mCAAmC,SAAS;AAAA,IACzD,GAAG;AAAA,EAAA;AACN,CACD;AACD,sBAAsB,cAAc;"}