@fanvue/ui 2.9.1 → 2.9.3

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.
@@ -62,7 +62,7 @@ const BottomNavigationAction = React__namespace.forwardRef(({ className, value,
62
62
  "span",
63
63
  {
64
64
  className: cn.cn(
65
- "typography-medium-caption-xs truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out",
65
+ "typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out",
66
66
  isActive ? "text-content-primary" : "text-content-tertiary"
67
67
  ),
68
68
  children: label
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigationAction.cjs","sources":["../../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":["React","useBottomNavigationContext","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAyBA,iBAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACEC,4CAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAWC,2BAAAA,IAACC,uBAAW,SAAA,CAAS;AAAA,UACjCH,2BAAAA,KAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAAE,+BAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAASA,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA;AAAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACED,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAWC,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAWC,2BAAAA,IAACC,uBAAW,SAAA,CAAS;AAAA,QACjCH,2BAAAA,KAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAAE,+BAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAASA,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;;"}
1
+ {"version":3,"file":"BottomNavigationAction.cjs","sources":["../../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":["React","useBottomNavigationContext","Slot","jsxs","cn","jsx","Slottable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmBO,MAAM,yBAAyBA,iBAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACEC,4CAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAUC,UAAAA,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAWC,2BAAAA,IAACC,uBAAW,SAAA,CAAS;AAAA,UACjCH,2BAAAA,KAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAAE,+BAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAASA,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWD,GAAAA;AAAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACED,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAWC,GAAAA;AAAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAWC,2BAAAA,IAACC,uBAAW,SAAA,CAAS;AAAA,QACjCH,2BAAAA,KAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAAE,+BAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAASA,2BAAAA,IAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;;"}
@@ -4,6 +4,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  const jsxRuntime = require("react/jsx-runtime");
5
5
  const React = require("react");
6
6
  const cn = require("../../utils/cn.cjs");
7
+ const Button = require("../Button/Button.cjs");
7
8
  function _interopNamespaceDefault(e) {
8
9
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
9
10
  if (e) {
@@ -21,6 +22,18 @@ function _interopNamespaceDefault(e) {
21
22
  return Object.freeze(n);
22
23
  }
23
24
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
+ function isNonEmptyString(value) {
26
+ return typeof value === "string" && value.length > 0;
27
+ }
28
+ function hasSlotContent(value) {
29
+ if (value === void 0 || value === null || value === false) {
30
+ return false;
31
+ }
32
+ if (typeof value === "string") {
33
+ return value.length > 0;
34
+ }
35
+ return true;
36
+ }
24
37
  const EmptyState = React__namespace.forwardRef(
25
38
  ({
26
39
  className,
@@ -34,7 +47,29 @@ const EmptyState = React__namespace.forwardRef(
34
47
  }, ref) => {
35
48
  const isCentered = variant === "centered";
36
49
  const titleId = React__namespace.useId();
37
- const regionLabelledBy = title !== void 0 && title !== null && title !== false ? titleId : void 0;
50
+ const regionLabelledBy = hasSlotContent(title) ? titleId : void 0;
51
+ const renderedPrimary = primaryAction === void 0 || primaryAction === null || primaryAction === false || primaryAction === "" ? null : isNonEmptyString(primaryAction) ? /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "brand", fullWidth: true, children: primaryAction }) : primaryAction;
52
+ const renderedSecondary = secondaryAction === void 0 || secondaryAction === null || secondaryAction === false || secondaryAction === "" ? null : isNonEmptyString(secondaryAction) ? /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "secondary", fullWidth: true, children: secondaryAction }) : secondaryAction;
53
+ const renderedTitle = title === void 0 || title === null || title === false || title === "" ? null : isNonEmptyString(title) ? /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "m-0 typography-bold-heading-lg text-content-primary", children: title }) : /* @__PURE__ */ jsxRuntime.jsx(
54
+ "div",
55
+ {
56
+ id: titleId,
57
+ className: "typography-bold-heading-lg text-content-primary min-w-0 w-full",
58
+ children: title
59
+ }
60
+ );
61
+ const renderedDescription = description === void 0 || description === null || description === false || description === "" ? null : isNonEmptyString(description) ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 typography-regular-body-lg text-content-secondary", children: description }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "typography-regular-body-lg text-content-secondary min-w-0 w-full", children: description });
62
+ const renderedMedia = media === void 0 || media === null || media === false || media === "" ? null : isNonEmptyString(media) ? /* @__PURE__ */ jsxRuntime.jsx(
63
+ "img",
64
+ {
65
+ src: media,
66
+ alt: "",
67
+ decoding: "async",
68
+ className: "block h-full w-full object-contain object-center"
69
+ }
70
+ ) : media;
71
+ const showMedia = renderedMedia !== null;
72
+ const showActions = renderedPrimary !== null || renderedSecondary !== null;
38
73
  return /* @__PURE__ */ jsxRuntime.jsxs(
39
74
  "section",
40
75
  {
@@ -48,7 +83,7 @@ const EmptyState = React__namespace.forwardRef(
48
83
  ),
49
84
  ...props,
50
85
  children: [
51
- media !== void 0 && media !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[280px] w-full overflow-hidden rounded-md", children: media }),
86
+ showMedia && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[280px] w-full overflow-hidden rounded-md", children: renderedMedia }),
52
87
  /* @__PURE__ */ jsxRuntime.jsxs(
53
88
  "div",
54
89
  {
@@ -62,14 +97,14 @@ const EmptyState = React__namespace.forwardRef(
62
97
  isCentered ? "items-center" : "items-start"
63
98
  ),
64
99
  children: [
65
- title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsxRuntime.jsx("div", { id: titleId, className: "typography-bold-heading-lg text-content-primary", children: title }),
66
- description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-regular-body-lg text-content-secondary", children: description })
100
+ renderedTitle,
101
+ renderedDescription
67
102
  ]
68
103
  }
69
104
  ),
70
- primaryAction !== void 0 && primaryAction !== null || secondaryAction !== void 0 && secondaryAction !== null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn.cn("flex flex-col gap-4", isCentered ? "items-center" : "items-start"), children: [
71
- primaryAction,
72
- secondaryAction
105
+ showActions ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn.cn("flex flex-col gap-4", isCentered ? "items-center" : "items-start"), children: [
106
+ renderedPrimary,
107
+ renderedSecondary
73
108
  ] }) : null
74
109
  ]
75
110
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.cjs","sources":["../../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. */\n title?: React.ReactNode;\n /** Supporting body copy. */\n description?: React.ReactNode;\n /** Top visual/illustration slot. */\n media?: React.ReactNode;\n /** Primary call-to-action node. */\n primaryAction?: React.ReactNode;\n /** Optional secondary action rendered below primary. */\n secondaryAction?: React.ReactNode;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n description,\n media,\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy =\n title !== undefined && title !== null && title !== false ? titleId : undefined;\n\n return (\n <section\n ref={ref}\n aria-labelledby={regionLabelledBy}\n data-testid=\"empty-state\"\n className={cn(\n \"flex w-full max-w-[375px] flex-col gap-6\",\n isCentered ? \"items-center text-center\" : \"items-start text-left\",\n className,\n )}\n {...props}\n >\n {media !== undefined && media !== null && (\n <div className=\"h-[280px] w-full overflow-hidden rounded-md\">{media}</div>\n )}\n\n <div\n className={cn(\"flex w-full flex-col gap-6\", isCentered ? \"items-center\" : \"items-start\")}\n >\n <div\n className={cn(\n \"flex w-full flex-col gap-4\",\n isCentered ? \"items-center\" : \"items-start\",\n )}\n >\n {title !== undefined && title !== null && title !== false && (\n <div id={titleId} className=\"typography-bold-heading-lg text-content-primary\">\n {title}\n </div>\n )}\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-lg text-content-secondary\">{description}</p>\n )}\n </div>\n\n {(primaryAction !== undefined && primaryAction !== null) ||\n (secondaryAction !== undefined && secondaryAction !== null) ? (\n <div className={cn(\"flex flex-col gap-4\", isCentered ? \"items-center\" : \"items-start\")}>\n {primaryAction}\n {secondaryAction}\n </div>\n ) : null}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = \"EmptyState\";\n"],"names":["React","jsxs","cn","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBO,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,aAAa,YAAY;AAC/B,UAAM,UAAUA,iBAAM,MAAA;AACtB,UAAM,mBACJ,UAAU,UAAa,UAAU,QAAQ,UAAU,QAAQ,UAAU;AAEvE,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,mBAAiB;AAAA,QACjB,eAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,aAAa,6BAA6B;AAAA,UAC1C;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,UAAU,UAAa,UAAU,uCAC/B,OAAA,EAAI,WAAU,+CAA+C,UAAA,MAAA,CAAM;AAAA,UAGtED,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWC,GAAAA,GAAG,8BAA8B,aAAa,iBAAiB,aAAa;AAAA,cAEvF,UAAA;AAAA,gBAAAD,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAWC,GAAAA;AAAAA,sBACT;AAAA,sBACA,aAAa,iBAAiB;AAAA,oBAAA;AAAA,oBAG/B,UAAA;AAAA,sBAAA,UAAU,UAAa,UAAU,QAAQ,UAAU,SAClDC,2BAAAA,IAAC,OAAA,EAAI,IAAI,SAAS,WAAU,mDACzB,UAAA,OACH;AAAA,sBAED,gBAAgB,UAAa,gBAAgB,QAAQ,gBAAgB,SACpEA,+BAAC,KAAA,EAAE,WAAU,qDAAqD,UAAA,YAAA,CAAY;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAIhF,kBAAkB,UAAa,kBAAkB,QAClD,oBAAoB,UAAa,oBAAoB,OACpDF,2BAAAA,KAAC,OAAA,EAAI,WAAWC,GAAAA,GAAG,uBAAuB,aAAa,iBAAiB,aAAa,GAClF,UAAA;AAAA,kBAAA;AAAA,kBACA;AAAA,gBAAA,EAAA,CACH,IACE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACN;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,WAAW,cAAc;;"}
1
+ {"version":3,"file":"EmptyState.cjs","sources":["../../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\n/** Slot that can be plain copy (styled by `EmptyState`) or custom markup. */\nexport type EmptyStateSlot = string | React.ReactNode;\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction hasSlotContent(value: EmptyStateSlot | undefined): boolean {\n if (value === undefined || value === null || value === false) {\n return false;\n }\n if (typeof value === \"string\") {\n return value.length > 0;\n }\n return true;\n}\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. Strings use library heading styles; pass a node for full control. */\n title?: EmptyStateSlot;\n /** Supporting body copy. Strings use library body styles; pass a node for rich text. */\n description?: EmptyStateSlot;\n /**\n * Top visual / illustration slot.\n * A string is treated as an image URL (`<img src={…}>`); pass a node for custom layout.\n */\n media?: EmptyStateSlot;\n /**\n * Primary call to action.\n * A string renders a brand `Button` with that label; pass a node for links, loading, etc.\n */\n primaryAction?: EmptyStateSlot;\n /**\n * Secondary action below the primary.\n * A string renders a secondary `Button` with that label; pass a node when you need more control.\n */\n secondaryAction?: EmptyStateSlot;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n description,\n media,\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy = hasSlotContent(title) ? titleId : undefined;\n\n const renderedPrimary =\n primaryAction === undefined ||\n primaryAction === null ||\n primaryAction === false ||\n primaryAction === \"\" ? null : isNonEmptyString(primaryAction) ? (\n <Button variant=\"brand\" fullWidth>\n {primaryAction}\n </Button>\n ) : (\n primaryAction\n );\n\n const renderedSecondary =\n secondaryAction === undefined ||\n secondaryAction === null ||\n secondaryAction === false ||\n secondaryAction === \"\" ? null : isNonEmptyString(secondaryAction) ? (\n <Button variant=\"secondary\" fullWidth>\n {secondaryAction}\n </Button>\n ) : (\n secondaryAction\n );\n\n const renderedTitle =\n title === undefined ||\n title === null ||\n title === false ||\n title === \"\" ? null : isNonEmptyString(title) ? (\n <h2 id={titleId} className=\"m-0 typography-bold-heading-lg text-content-primary\">\n {title}\n </h2>\n ) : (\n <div\n id={titleId}\n className=\"typography-bold-heading-lg text-content-primary min-w-0 w-full\"\n >\n {title}\n </div>\n );\n\n const renderedDescription =\n description === undefined ||\n description === null ||\n description === false ||\n description === \"\" ? null : isNonEmptyString(description) ? (\n <p className=\"m-0 typography-regular-body-lg text-content-secondary\">{description}</p>\n ) : (\n <div className=\"typography-regular-body-lg text-content-secondary min-w-0 w-full\">\n {description}\n </div>\n );\n\n const renderedMedia =\n media === undefined ||\n media === null ||\n media === false ||\n media === \"\" ? null : isNonEmptyString(media) ? (\n <img\n src={media}\n alt=\"\"\n decoding=\"async\"\n className=\"block h-full w-full object-contain object-center\"\n />\n ) : (\n media\n );\n\n const showMedia = renderedMedia !== null;\n const showActions = renderedPrimary !== null || renderedSecondary !== null;\n\n return (\n <section\n ref={ref}\n aria-labelledby={regionLabelledBy}\n data-testid=\"empty-state\"\n className={cn(\n \"flex w-full max-w-[375px] flex-col gap-6\",\n isCentered ? \"items-center text-center\" : \"items-start text-left\",\n className,\n )}\n {...props}\n >\n {showMedia && (\n <div className=\"h-[280px] w-full overflow-hidden rounded-md\">{renderedMedia}</div>\n )}\n\n <div\n className={cn(\"flex w-full flex-col gap-6\", isCentered ? \"items-center\" : \"items-start\")}\n >\n <div\n className={cn(\n \"flex w-full flex-col gap-4\",\n isCentered ? \"items-center\" : \"items-start\",\n )}\n >\n {renderedTitle}\n {renderedDescription}\n </div>\n\n {showActions ? (\n <div className={cn(\"flex flex-col gap-4\", isCentered ? \"items-center\" : \"items-start\")}>\n {renderedPrimary}\n {renderedSecondary}\n </div>\n ) : null}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = \"EmptyState\";\n"],"names":["React","Button","jsx","jsxs","cn"],"mappings":"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"}
@@ -43,7 +43,7 @@ const BottomNavigationAction = React.forwardRef(({ className, value, icon, label
43
43
  "span",
44
44
  {
45
45
  className: cn(
46
- "typography-medium-caption-xs truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out",
46
+ "typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out",
47
47
  isActive ? "text-content-primary" : "text-content-tertiary"
48
48
  ),
49
49
  children: label
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigationAction.mjs","sources":["../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":[],"mappings":";;;;;;AAmBO,MAAM,yBAAyB,MAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACE,2BAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAU,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAW;AAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,UACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,QACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;"}
1
+ {"version":3,"file":"BottomNavigationAction.mjs","sources":["../../../src/components/BottomNavigation/BottomNavigationAction.tsx"],"sourcesContent":["import { Slot, Slottable } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useBottomNavigationContext } from \"./BottomNavigation\";\n\nexport interface BottomNavigationActionProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"value\"> {\n /** Unique value that identifies this action. */\n value: string;\n /** Icon element displayed in the action. */\n icon: React.ReactElement;\n /** Accessible label applied as `aria-label`. */\n label?: string;\n /** Optional badge element (e.g. {@link Count}) rendered at the top-end corner of the icon. */\n badge?: React.ReactNode;\n /** Merge props onto a child element instead of rendering a `<button>`. @default false */\n asChild?: boolean;\n}\n\nexport const BottomNavigationAction = React.forwardRef<\n HTMLButtonElement,\n BottomNavigationActionProps\n>(({ className, value, icon, label, badge, onClick, asChild = false, children, ...props }, ref) => {\n const {\n value: selectedValue,\n onValueChange,\n hasInformationArchitectureNav,\n } = useBottomNavigationContext();\n\n const isActive = selectedValue === value;\n\n const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onValueChange?.(value);\n onClick?.(e);\n };\n\n const Comp = asChild ? Slot : \"button\";\n\n if (hasInformationArchitectureNav) {\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? (\"page\" as const) : undefined}\n data-state={isActive ? \"active\" : \"inactive\"}\n onClick={handleClick}\n {...props}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-1\",\n isActive ? \"text-icons-primary\" : \"text-icons-tertiary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-6\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n {label && (\n <span\n className={cn(\n \"typography-medium-caption-xs max-w-full truncate text-center motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n isActive ? \"text-content-primary\" : \"text-content-tertiary\",\n )}\n >\n {label}\n </span>\n )}\n </Comp>\n );\n }\n\n return (\n <Comp\n ref={ref}\n {...(!asChild && { type: \"button\" as const })}\n aria-current={isActive ? \"page\" : undefined}\n aria-label={label}\n data-state={isActive ? \"active\" : \"inactive\"}\n className={cn(\n \"relative flex min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 overflow-hidden px-2 py-2\",\n \"text-content-primary\",\n \"motion-safe:transition-colors motion-safe:duration-150 motion-safe:ease-in-out\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-interaction-focus focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary\",\n className,\n )}\n onClick={handleClick}\n {...props}\n >\n {asChild && <Slottable>{children}</Slottable>}\n <span className=\"relative inline-flex\">\n <span className=\"flex items-center justify-center [&>svg]:size-7\" aria-hidden=\"true\">\n {icon}\n </span>\n {badge && <span className=\"absolute -end-1 -top-2.5\">{badge}</span>}\n </span>\n </Comp>\n );\n});\n\nBottomNavigationAction.displayName = \"BottomNavigationAction\";\n"],"names":[],"mappings":";;;;;;AAmBO,MAAM,yBAAyB,MAAM,WAG1C,CAAC,EAAE,WAAW,OAAO,MAAM,OAAO,OAAO,SAAS,UAAU,OAAO,UAAU,GAAG,MAAA,GAAS,QAAQ;AACjG,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,EAAA,IACE,2BAAA;AAEJ,QAAM,WAAW,kBAAkB;AAEnC,QAAM,cAAc,CAAC,MAA2C;AAC9D,oBAAgB,KAAK;AACrB,cAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAO,UAAU,OAAO;AAE9B,MAAI,+BAA+B;AACjC,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,QACzB,gBAAc,WAAY,SAAmB;AAAA,QAC7C,cAAY,WAAW,WAAW;AAAA,QAClC,SAAS;AAAA,QACR,GAAG;AAAA,QACJ,WAAW;AAAA,UACT;AAAA,UACA,WAAW,uBAAuB;AAAA,UAClC;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAGD,UAAA;AAAA,UAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,UACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,YAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,YACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,UAAA,GAC9D;AAAA,UACC,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,WAAW,yBAAyB;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAI,CAAC,WAAW,EAAE,MAAM,SAAA;AAAA,MACzB,gBAAc,WAAW,SAAS;AAAA,MAClC,cAAY;AAAA,MACZ,cAAY,WAAW,WAAW;AAAA,MAClC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,SAAS;AAAA,MACR,GAAG;AAAA,MAEH,UAAA;AAAA,QAAA,WAAW,oBAAC,aAAW,SAAA,CAAS;AAAA,QACjC,qBAAC,QAAA,EAAK,WAAU,wBACd,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,mDAAkD,eAAY,QAC3E,UAAA,MACH;AAAA,UACC,SAAS,oBAAC,QAAA,EAAK,WAAU,4BAA4B,UAAA,MAAA,CAAM;AAAA,QAAA,EAAA,CAC9D;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN,CAAC;AAED,uBAAuB,cAAc;"}
@@ -1,7 +1,20 @@
1
1
  "use client";
2
- import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cn } from "../../utils/cn.mjs";
5
+ import { Button } from "../Button/Button.mjs";
6
+ function isNonEmptyString(value) {
7
+ return typeof value === "string" && value.length > 0;
8
+ }
9
+ function hasSlotContent(value) {
10
+ if (value === void 0 || value === null || value === false) {
11
+ return false;
12
+ }
13
+ if (typeof value === "string") {
14
+ return value.length > 0;
15
+ }
16
+ return true;
17
+ }
5
18
  const EmptyState = React.forwardRef(
6
19
  ({
7
20
  className,
@@ -15,7 +28,29 @@ const EmptyState = React.forwardRef(
15
28
  }, ref) => {
16
29
  const isCentered = variant === "centered";
17
30
  const titleId = React.useId();
18
- const regionLabelledBy = title !== void 0 && title !== null && title !== false ? titleId : void 0;
31
+ const regionLabelledBy = hasSlotContent(title) ? titleId : void 0;
32
+ const renderedPrimary = primaryAction === void 0 || primaryAction === null || primaryAction === false || primaryAction === "" ? null : isNonEmptyString(primaryAction) ? /* @__PURE__ */ jsx(Button, { variant: "brand", fullWidth: true, children: primaryAction }) : primaryAction;
33
+ const renderedSecondary = secondaryAction === void 0 || secondaryAction === null || secondaryAction === false || secondaryAction === "" ? null : isNonEmptyString(secondaryAction) ? /* @__PURE__ */ jsx(Button, { variant: "secondary", fullWidth: true, children: secondaryAction }) : secondaryAction;
34
+ const renderedTitle = title === void 0 || title === null || title === false || title === "" ? null : isNonEmptyString(title) ? /* @__PURE__ */ jsx("h2", { id: titleId, className: "m-0 typography-bold-heading-lg text-content-primary", children: title }) : /* @__PURE__ */ jsx(
35
+ "div",
36
+ {
37
+ id: titleId,
38
+ className: "typography-bold-heading-lg text-content-primary min-w-0 w-full",
39
+ children: title
40
+ }
41
+ );
42
+ const renderedDescription = description === void 0 || description === null || description === false || description === "" ? null : isNonEmptyString(description) ? /* @__PURE__ */ jsx("p", { className: "m-0 typography-regular-body-lg text-content-secondary", children: description }) : /* @__PURE__ */ jsx("div", { className: "typography-regular-body-lg text-content-secondary min-w-0 w-full", children: description });
43
+ const renderedMedia = media === void 0 || media === null || media === false || media === "" ? null : isNonEmptyString(media) ? /* @__PURE__ */ jsx(
44
+ "img",
45
+ {
46
+ src: media,
47
+ alt: "",
48
+ decoding: "async",
49
+ className: "block h-full w-full object-contain object-center"
50
+ }
51
+ ) : media;
52
+ const showMedia = renderedMedia !== null;
53
+ const showActions = renderedPrimary !== null || renderedSecondary !== null;
19
54
  return /* @__PURE__ */ jsxs(
20
55
  "section",
21
56
  {
@@ -29,7 +64,7 @@ const EmptyState = React.forwardRef(
29
64
  ),
30
65
  ...props,
31
66
  children: [
32
- media !== void 0 && media !== null && /* @__PURE__ */ jsx("div", { className: "h-[280px] w-full overflow-hidden rounded-md", children: media }),
67
+ showMedia && /* @__PURE__ */ jsx("div", { className: "h-[280px] w-full overflow-hidden rounded-md", children: renderedMedia }),
33
68
  /* @__PURE__ */ jsxs(
34
69
  "div",
35
70
  {
@@ -43,14 +78,14 @@ const EmptyState = React.forwardRef(
43
78
  isCentered ? "items-center" : "items-start"
44
79
  ),
45
80
  children: [
46
- title !== void 0 && title !== null && title !== false && /* @__PURE__ */ jsx("div", { id: titleId, className: "typography-bold-heading-lg text-content-primary", children: title }),
47
- description !== void 0 && description !== null && description !== false && /* @__PURE__ */ jsx("p", { className: "typography-regular-body-lg text-content-secondary", children: description })
81
+ renderedTitle,
82
+ renderedDescription
48
83
  ]
49
84
  }
50
85
  ),
51
- primaryAction !== void 0 && primaryAction !== null || secondaryAction !== void 0 && secondaryAction !== null ? /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", isCentered ? "items-center" : "items-start"), children: [
52
- primaryAction,
53
- secondaryAction
86
+ showActions ? /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", isCentered ? "items-center" : "items-start"), children: [
87
+ renderedPrimary,
88
+ renderedSecondary
54
89
  ] }) : null
55
90
  ]
56
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.mjs","sources":["../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. */\n title?: React.ReactNode;\n /** Supporting body copy. */\n description?: React.ReactNode;\n /** Top visual/illustration slot. */\n media?: React.ReactNode;\n /** Primary call-to-action node. */\n primaryAction?: React.ReactNode;\n /** Optional secondary action rendered below primary. */\n secondaryAction?: React.ReactNode;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n description,\n media,\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy =\n title !== undefined && title !== null && title !== false ? titleId : undefined;\n\n return (\n <section\n ref={ref}\n aria-labelledby={regionLabelledBy}\n data-testid=\"empty-state\"\n className={cn(\n \"flex w-full max-w-[375px] flex-col gap-6\",\n isCentered ? \"items-center text-center\" : \"items-start text-left\",\n className,\n )}\n {...props}\n >\n {media !== undefined && media !== null && (\n <div className=\"h-[280px] w-full overflow-hidden rounded-md\">{media}</div>\n )}\n\n <div\n className={cn(\"flex w-full flex-col gap-6\", isCentered ? \"items-center\" : \"items-start\")}\n >\n <div\n className={cn(\n \"flex w-full flex-col gap-4\",\n isCentered ? \"items-center\" : \"items-start\",\n )}\n >\n {title !== undefined && title !== null && title !== false && (\n <div id={titleId} className=\"typography-bold-heading-lg text-content-primary\">\n {title}\n </div>\n )}\n {description !== undefined && description !== null && description !== false && (\n <p className=\"typography-regular-body-lg text-content-secondary\">{description}</p>\n )}\n </div>\n\n {(primaryAction !== undefined && primaryAction !== null) ||\n (secondaryAction !== undefined && secondaryAction !== null) ? (\n <div className={cn(\"flex flex-col gap-4\", isCentered ? \"items-center\" : \"items-start\")}>\n {primaryAction}\n {secondaryAction}\n </div>\n ) : null}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = \"EmptyState\";\n"],"names":[],"mappings":";;;;AAuBO,MAAM,aAAa,MAAM;AAAA,EAC9B,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,aAAa,YAAY;AAC/B,UAAM,UAAU,MAAM,MAAA;AACtB,UAAM,mBACJ,UAAU,UAAa,UAAU,QAAQ,UAAU,QAAQ,UAAU;AAEvE,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,mBAAiB;AAAA,QACjB,eAAY;AAAA,QACZ,WAAW;AAAA,UACT;AAAA,UACA,aAAa,6BAA6B;AAAA,UAC1C;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,UAAU,UAAa,UAAU,4BAC/B,OAAA,EAAI,WAAU,+CAA+C,UAAA,MAAA,CAAM;AAAA,UAGtE;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW,GAAG,8BAA8B,aAAa,iBAAiB,aAAa;AAAA,cAEvF,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW;AAAA,sBACT;AAAA,sBACA,aAAa,iBAAiB;AAAA,oBAAA;AAAA,oBAG/B,UAAA;AAAA,sBAAA,UAAU,UAAa,UAAU,QAAQ,UAAU,SAClD,oBAAC,OAAA,EAAI,IAAI,SAAS,WAAU,mDACzB,UAAA,OACH;AAAA,sBAED,gBAAgB,UAAa,gBAAgB,QAAQ,gBAAgB,SACpE,oBAAC,KAAA,EAAE,WAAU,qDAAqD,UAAA,YAAA,CAAY;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAIhF,kBAAkB,UAAa,kBAAkB,QAClD,oBAAoB,UAAa,oBAAoB,OACpD,qBAAC,OAAA,EAAI,WAAW,GAAG,uBAAuB,aAAa,iBAAiB,aAAa,GAClF,UAAA;AAAA,kBAAA;AAAA,kBACA;AAAA,gBAAA,EAAA,CACH,IACE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACN;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,WAAW,cAAc;"}
1
+ {"version":3,"file":"EmptyState.mjs","sources":["../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../Button/Button\";\n\nexport type EmptyStateVariant = \"default\" | \"centered\";\n\n/** Slot that can be plain copy (styled by `EmptyState`) or custom markup. */\nexport type EmptyStateSlot = string | React.ReactNode;\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === \"string\" && value.length > 0;\n}\n\nfunction hasSlotContent(value: EmptyStateSlot | undefined): boolean {\n if (value === undefined || value === null || value === false) {\n return false;\n }\n if (typeof value === \"string\") {\n return value.length > 0;\n }\n return true;\n}\n\nexport interface EmptyStateProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n /**\n * Matches Figma property `Property 1` (`Default` / `centered`).\n * @default \"default\"\n */\n variant?: EmptyStateVariant;\n /** Main heading. Strings use library heading styles; pass a node for full control. */\n title?: EmptyStateSlot;\n /** Supporting body copy. Strings use library body styles; pass a node for rich text. */\n description?: EmptyStateSlot;\n /**\n * Top visual / illustration slot.\n * A string is treated as an image URL (`<img src={…}>`); pass a node for custom layout.\n */\n media?: EmptyStateSlot;\n /**\n * Primary call to action.\n * A string renders a brand `Button` with that label; pass a node for links, loading, etc.\n */\n primaryAction?: EmptyStateSlot;\n /**\n * Secondary action below the primary.\n * A string renders a secondary `Button` with that label; pass a node when you need more control.\n */\n secondaryAction?: EmptyStateSlot;\n}\n\nexport const EmptyState = React.forwardRef<HTMLElement, EmptyStateProps>(\n (\n {\n className,\n variant = \"default\",\n title,\n description,\n media,\n primaryAction,\n secondaryAction,\n ...props\n },\n ref,\n ) => {\n const isCentered = variant === \"centered\";\n const titleId = React.useId();\n const regionLabelledBy = hasSlotContent(title) ? titleId : undefined;\n\n const renderedPrimary =\n primaryAction === undefined ||\n primaryAction === null ||\n primaryAction === false ||\n primaryAction === \"\" ? null : isNonEmptyString(primaryAction) ? (\n <Button variant=\"brand\" fullWidth>\n {primaryAction}\n </Button>\n ) : (\n primaryAction\n );\n\n const renderedSecondary =\n secondaryAction === undefined ||\n secondaryAction === null ||\n secondaryAction === false ||\n secondaryAction === \"\" ? null : isNonEmptyString(secondaryAction) ? (\n <Button variant=\"secondary\" fullWidth>\n {secondaryAction}\n </Button>\n ) : (\n secondaryAction\n );\n\n const renderedTitle =\n title === undefined ||\n title === null ||\n title === false ||\n title === \"\" ? null : isNonEmptyString(title) ? (\n <h2 id={titleId} className=\"m-0 typography-bold-heading-lg text-content-primary\">\n {title}\n </h2>\n ) : (\n <div\n id={titleId}\n className=\"typography-bold-heading-lg text-content-primary min-w-0 w-full\"\n >\n {title}\n </div>\n );\n\n const renderedDescription =\n description === undefined ||\n description === null ||\n description === false ||\n description === \"\" ? null : isNonEmptyString(description) ? (\n <p className=\"m-0 typography-regular-body-lg text-content-secondary\">{description}</p>\n ) : (\n <div className=\"typography-regular-body-lg text-content-secondary min-w-0 w-full\">\n {description}\n </div>\n );\n\n const renderedMedia =\n media === undefined ||\n media === null ||\n media === false ||\n media === \"\" ? null : isNonEmptyString(media) ? (\n <img\n src={media}\n alt=\"\"\n decoding=\"async\"\n className=\"block h-full w-full object-contain object-center\"\n />\n ) : (\n media\n );\n\n const showMedia = renderedMedia !== null;\n const showActions = renderedPrimary !== null || renderedSecondary !== null;\n\n return (\n <section\n ref={ref}\n aria-labelledby={regionLabelledBy}\n data-testid=\"empty-state\"\n className={cn(\n \"flex w-full max-w-[375px] flex-col gap-6\",\n isCentered ? \"items-center text-center\" : \"items-start text-left\",\n className,\n )}\n {...props}\n >\n {showMedia && (\n <div className=\"h-[280px] w-full overflow-hidden rounded-md\">{renderedMedia}</div>\n )}\n\n <div\n className={cn(\"flex w-full flex-col gap-6\", isCentered ? \"items-center\" : \"items-start\")}\n >\n <div\n className={cn(\n \"flex w-full flex-col gap-4\",\n isCentered ? \"items-center\" : \"items-start\",\n )}\n >\n {renderedTitle}\n {renderedDescription}\n </div>\n\n {showActions ? (\n <div className={cn(\"flex flex-col gap-4\", isCentered ? \"items-center\" : \"items-start\")}>\n {renderedPrimary}\n {renderedSecondary}\n </div>\n ) : null}\n </div>\n </section>\n );\n },\n);\n\nEmptyState.displayName = \"EmptyState\";\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1354,18 +1354,30 @@ export declare interface EmptyStateProps extends Omit<React_2.HTMLAttributes<HTM
1354
1354
  * @default "default"
1355
1355
  */
1356
1356
  variant?: EmptyStateVariant;
1357
- /** Main heading. */
1358
- title?: React_2.ReactNode;
1359
- /** Supporting body copy. */
1360
- description?: React_2.ReactNode;
1361
- /** Top visual/illustration slot. */
1362
- media?: React_2.ReactNode;
1363
- /** Primary call-to-action node. */
1364
- primaryAction?: React_2.ReactNode;
1365
- /** Optional secondary action rendered below primary. */
1366
- secondaryAction?: React_2.ReactNode;
1357
+ /** Main heading. Strings use library heading styles; pass a node for full control. */
1358
+ title?: EmptyStateSlot;
1359
+ /** Supporting body copy. Strings use library body styles; pass a node for rich text. */
1360
+ description?: EmptyStateSlot;
1361
+ /**
1362
+ * Top visual / illustration slot.
1363
+ * A string is treated as an image URL (`<img src={…}>`); pass a node for custom layout.
1364
+ */
1365
+ media?: EmptyStateSlot;
1366
+ /**
1367
+ * Primary call to action.
1368
+ * A string renders a brand `Button` with that label; pass a node for links, loading, etc.
1369
+ */
1370
+ primaryAction?: EmptyStateSlot;
1371
+ /**
1372
+ * Secondary action below the primary.
1373
+ * A string renders a secondary `Button` with that label; pass a node when you need more control.
1374
+ */
1375
+ secondaryAction?: EmptyStateSlot;
1367
1376
  }
1368
1377
 
1378
+ /** Slot that can be plain copy (styled by `EmptyState`) or custom markup. */
1379
+ export declare type EmptyStateSlot = string | React_2.ReactNode;
1380
+
1369
1381
  export declare type EmptyStateVariant = "default" | "centered";
1370
1382
 
1371
1383
  /** An "×" inside a filled circle icon for error states (20 × 20). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanvue/ui",
3
- "version": "2.9.1",
3
+ "version": "2.9.3",
4
4
  "description": "React component library built with Tailwind CSS for Fanvue ecosystem",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",