@fanvue/ui 3.19.1 → 3.20.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,44 @@
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 ButtonStack = React__namespace.forwardRef(
25
+ ({ direction = "horizontal", className, children, ...props }, ref) => {
26
+ return /* @__PURE__ */ jsxRuntime.jsx(
27
+ "div",
28
+ {
29
+ ref,
30
+ className: cn.cn(
31
+ "flex gap-2",
32
+ direction === "horizontal" && "flex-row [&>*]:min-w-0 [&>*]:flex-1",
33
+ direction === "vertical" && "flex-col [&>*]:w-full",
34
+ className
35
+ ),
36
+ ...props,
37
+ children
38
+ }
39
+ );
40
+ }
41
+ );
42
+ ButtonStack.displayName = "ButtonStack";
43
+ exports.ButtonStack = ButtonStack;
44
+ //# sourceMappingURL=ButtonStack.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonStack.cjs","sources":["../../../../src/components/ButtonStack/ButtonStack.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Layout orientation of the buttons within a {@link ButtonStack}. */\nexport type ButtonStackDirection = \"horizontal\" | \"vertical\";\n\nexport interface ButtonStackProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Layout orientation. `horizontal` places buttons side by side with equal\n * widths for primary + secondary action pairs; `vertical` stacks them\n * full-width for mobile screens and narrow panels.\n * @default \"horizontal\"\n */\n direction?: ButtonStackDirection;\n /** Buttons to arrange — typically two {@link Button} elements. */\n children: React.ReactNode;\n}\n\n/**\n * A layout helper that arranges action buttons either side by side\n * (`horizontal`) or stacked (`vertical`). Compose it with {@link Button}\n * children rather than reimplementing button styles.\n *\n * In `horizontal` mode each child stretches to an equal width; in `vertical`\n * mode each child spans the full width of the container. Buttons keep their\n * own sizing, so pass a matching `size` to each child for consistent heights.\n *\n * @example\n * ```tsx\n * <ButtonStack direction=\"horizontal\">\n * <Button variant=\"outline\">Cancel</Button>\n * <Button variant=\"primary\">Confirm</Button>\n * </ButtonStack>\n * ```\n */\nexport const ButtonStack = React.forwardRef<HTMLDivElement, ButtonStackProps>(\n ({ direction = \"horizontal\", className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex gap-2\",\n direction === \"horizontal\" && \"flex-row [&>*]:min-w-0 [&>*]:flex-1\",\n direction === \"vertical\" && \"flex-col [&>*]:w-full\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nButtonStack.displayName = \"ButtonStack\";\n"],"names":["React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmCO,MAAM,cAAcA,iBAAM;AAAA,EAC/B,CAAC,EAAE,YAAY,cAAc,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AACpE,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,cAAc,gBAAgB;AAAA,UAC9B,cAAc,cAAc;AAAA,UAC5B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,YAAY,cAAc;;"}
@@ -21,35 +21,62 @@ function _interopNamespaceDefault(e) {
21
21
  return Object.freeze(n);
22
22
  }
23
23
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
24
- const VARIANT_CLASSES = {
24
+ const CardContext = React__namespace.createContext({
25
+ hierarchy: "primary",
26
+ type: "default"
27
+ });
28
+ const useCardContext = () => React__namespace.useContext(CardContext);
29
+ const LEGACY_VARIANT_CLASSES = {
25
30
  outlined: "border border-neutral-alphas-200 bg-surface-primary shadow-sm",
26
31
  elevated: "border border-neutral-alphas-200 bg-surface-primary shadow-md",
27
32
  filled: "bg-surface-secondary",
28
33
  ghost: "bg-transparent"
29
34
  };
35
+ const HIERARCHY_CLASSES = {
36
+ primary: "rounded-lg border border-border-primary bg-surface-primary",
37
+ secondary: "rounded-md border border-border-strong bg-surface-secondary shadow-sm"
38
+ };
39
+ const INTERACTIVE_CLASSES = "isolate cursor-pointer after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-content-primary after:opacity-0 after:transition-opacity after:content-[''] hover:after:opacity-5";
30
40
  const Card = React__namespace.forwardRef(
31
- ({ className, variant = "outlined", fullWidth = true, noPadding = false, children, ...props }, ref) => {
32
- return /* @__PURE__ */ jsxRuntime.jsx(
41
+ ({
42
+ className,
43
+ hierarchy = "primary",
44
+ type = "default",
45
+ interactive = false,
46
+ variant,
47
+ fullWidth = true,
48
+ noPadding = false,
49
+ children,
50
+ ...props
51
+ }, ref) => {
52
+ const isLegacy = variant !== void 0;
53
+ const padding = noPadding ? void 0 : isLegacy ? "p-4" : hierarchy === "secondary" ? "p-4" : "p-6";
54
+ const contextValue = React__namespace.useMemo(
55
+ () => ({ hierarchy, type }),
56
+ [hierarchy, type]
57
+ );
58
+ return /* @__PURE__ */ jsxRuntime.jsx(CardContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(
33
59
  "div",
34
60
  {
35
61
  ref,
36
62
  className: cn.cn(
37
- "flex flex-col overflow-hidden rounded-md",
38
- !noPadding && "p-4",
63
+ "relative flex flex-col overflow-hidden",
64
+ isLegacy ? cn.cn("rounded-md", LEGACY_VARIANT_CLASSES[variant]) : HIERARCHY_CLASSES[hierarchy],
65
+ padding,
39
66
  fullWidth && "w-full",
40
- VARIANT_CLASSES[variant],
67
+ interactive && INTERACTIVE_CLASSES,
41
68
  className
42
69
  ),
43
70
  ...props,
44
71
  children
45
72
  }
46
- );
73
+ ) });
47
74
  }
48
75
  );
49
76
  Card.displayName = "Card";
50
77
  const CardHeader = React__namespace.forwardRef(
51
78
  ({ className, action, children, ...props }, ref) => {
52
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn.cn("flex items-start gap-3", className), ...props, children: [
79
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn.cn("flex min-h-8 items-center gap-2", className), ...props, children: [
53
80
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children }),
54
81
  action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: action })
55
82
  ] });
@@ -58,11 +85,16 @@ const CardHeader = React__namespace.forwardRef(
58
85
  CardHeader.displayName = "CardHeader";
59
86
  const CardTitle = React__namespace.forwardRef(
60
87
  ({ className, children, ...props }, ref) => {
88
+ const { hierarchy } = useCardContext();
61
89
  return /* @__PURE__ */ jsxRuntime.jsx(
62
90
  "h3",
63
91
  {
64
92
  ref,
65
- className: cn.cn("typography-body-default-16px-semibold text-content-primary", className),
93
+ className: cn.cn(
94
+ hierarchy === "secondary" ? "typography-body-small-14px-regular" : "typography-header-heading-xs",
95
+ "text-content-primary",
96
+ className
97
+ ),
66
98
  ...props,
67
99
  children
68
100
  }
@@ -86,13 +118,15 @@ const CardDescription = React__namespace.forwardRef(
86
118
  CardDescription.displayName = "CardDescription";
87
119
  const CardContent = React__namespace.forwardRef(
88
120
  ({ className, children, ...props }, ref) => {
89
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("flex-1 py-4", className), ...props, children });
121
+ const { type } = useCardContext();
122
+ const padding = type === "container" ? void 0 : type === "header-only" ? "pt-6" : "py-6";
123
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("flex-1", padding, className), ...props, children });
90
124
  }
91
125
  );
92
126
  CardContent.displayName = "CardContent";
93
127
  const CardFooter = React__namespace.forwardRef(
94
128
  ({ className, children, ...props }, ref) => {
95
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("flex items-center gap-3", className), ...props, children });
129
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("flex w-full items-center gap-2", className), ...props, children });
96
130
  }
97
131
  );
98
132
  CardFooter.displayName = "CardFooter";
@@ -1 +1 @@
1
- {"version":3,"file":"Card.cjs","sources":["../../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual style variant of the card. */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the card. @default \"outlined\" */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\n/**\n * A composable card component with multiple visual variants. Use with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * @example\n * ```tsx\n * <Card variant=\"outlined\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n { className, variant = \"outlined\", fullWidth = true, noPadding = false, children, ...props },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-col overflow-hidden rounded-md\",\n !noPadding && \"p-4\",\n fullWidth && \"w-full\",\n VARIANT_CLASSES[variant],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-start gap-3\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"typography-body-default-16px-semibold text-content-primary\", className)}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-description-12px-regular text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/** Flexible content area of a {@link Card}. Adds vertical padding between header and footer. */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex-1 py-4\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-center gap-3\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":["React","jsx","cn","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,kBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AACT;AAsBO,MAAM,OAAOA,iBAAM;AAAA,EACxB,CACE,EAAE,WAAW,UAAU,YAAY,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,CAAC,aAAa;AAAA,UACd,aAAa;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,KAAK,cAAc;AAMZ,MAAM,aAAaF,iBAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,QAAQ,UAAU,GAAG,MAAA,GAAS,QAAQ;AAClD,WACEG,gCAAC,SAAI,KAAU,WAAWD,MAAG,0BAA0B,SAAS,GAAI,GAAG,OACrE,UAAA;AAAA,MAAAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,kBAAkB,SAAA,CAAS;AAAA,MACzC,UAAUA,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAA,CAAO;AAAA,IAAA,GAC/C;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGlB,MAAM,YAAYD,iBAAM;AAAA,EAC7B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,UAAU,cAAc;AAGjB,MAAM,kBAAkBF,iBAAM;AAAA,EACnC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,gBAAgB,cAAc;AAGvB,MAAM,cAAcF,iBAAM;AAAA,EAC/B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACEC,+BAAC,OAAA,EAAI,KAAU,WAAWC,GAAAA,GAAG,eAAe,SAAS,GAAI,GAAG,OACzD,SAAA,CACH;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAGnB,MAAM,aAAaF,iBAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACEC,+BAAC,OAAA,EAAI,KAAU,WAAWC,GAAAA,GAAG,2BAA2B,SAAS,GAAI,GAAG,OACrE,SAAA,CACH;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;;;;;;;"}
1
+ {"version":3,"file":"Card.cjs","sources":["../../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual hierarchy of the card. Primary is for prominent, content-carrying cards; secondary for supporting cards within denser layouts. */\nexport type CardHierarchy = \"primary\" | \"secondary\";\n\n/** Structural type of the card. `default` has header, content and footer; `header-only` drops the footer; `container` is a bare surface. */\nexport type CardType = \"default\" | \"header-only\" | \"container\";\n\n/**\n * Legacy visual style variant.\n * @deprecated Use {@link CardHierarchy} via the `hierarchy` prop instead. Retained for backwards compatibility.\n */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\ninterface CardContextValue {\n hierarchy: CardHierarchy;\n type: CardType;\n}\n\nconst CardContext = React.createContext<CardContextValue>({\n hierarchy: \"primary\",\n type: \"default\",\n});\n\nconst useCardContext = () => React.useContext(CardContext);\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual hierarchy of the card. @default \"primary\" */\n hierarchy?: CardHierarchy;\n /** Structural type of the card. @default \"default\" */\n type?: CardType;\n /** When `true`, applies the hover treatment for clickable cards. @default false */\n interactive?: boolean;\n /**\n * Legacy visual style variant.\n * @deprecated Use `hierarchy` instead. When set, the card keeps its legacy V1 appearance for backwards compatibility.\n */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst LEGACY_VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\nconst HIERARCHY_CLASSES: Record<CardHierarchy, string> = {\n primary: \"rounded-lg border border-border-primary bg-surface-primary\",\n secondary: \"rounded-md border border-border-strong bg-surface-secondary shadow-sm\",\n};\n\nconst INTERACTIVE_CLASSES =\n \"isolate cursor-pointer after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-content-primary after:opacity-0 after:transition-opacity after:content-[''] hover:after:opacity-5\";\n\n/**\n * A composable card component built on the V2 design system. Compose it with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * The `hierarchy` prop drives the surface treatment (Primary vs Secondary) and\n * the `type` prop drives the internal spacing (Default / Header Only / Container).\n *\n * @example\n * ```tsx\n * <Card hierarchy=\"primary\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n type = \"default\",\n interactive = false,\n variant,\n fullWidth = true,\n noPadding = false,\n children,\n ...props\n },\n ref,\n ) => {\n const isLegacy = variant !== undefined;\n const padding = noPadding\n ? undefined\n : isLegacy\n ? \"p-4\"\n : hierarchy === \"secondary\"\n ? \"p-4\"\n : \"p-6\";\n\n const contextValue = React.useMemo<CardContextValue>(\n () => ({ hierarchy, type }),\n [hierarchy, type],\n );\n\n return (\n <CardContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cn(\n \"relative flex flex-col overflow-hidden\",\n isLegacy\n ? cn(\"rounded-md\", LEGACY_VARIANT_CLASSES[variant])\n : HIERARCHY_CLASSES[hierarchy],\n padding,\n fullWidth && \"w-full\",\n interactive && INTERACTIVE_CLASSES,\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </CardContext.Provider>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex min-h-8 items-center gap-2\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. Adapts its type scale to the card `hierarchy`. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { hierarchy } = useCardContext();\n return (\n <h3\n ref={ref}\n className={cn(\n hierarchy === \"secondary\"\n ? \"typography-body-small-14px-regular\"\n : \"typography-header-heading-xs\",\n \"text-content-primary\",\n className,\n )}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-description-12px-regular text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/**\n * Flexible content area of a {@link Card}. Its vertical padding follows the card\n * `type`: `default` pads top and bottom, `header-only` pads only the top, and\n * `container` removes the built-in padding entirely.\n */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n const { type } = useCardContext();\n const padding = type === \"container\" ? undefined : type === \"header-only\" ? \"pt-6\" : \"py-6\";\n return (\n <div ref={ref} className={cn(\"flex-1\", padding, className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex w-full items-center gap-2\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":["React","jsx","cn","jsxs"],"mappings":"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"}
@@ -0,0 +1,109 @@
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
+ const Button = require("../Button/Button.cjs");
8
+ const WarningIcon = require("../Icons/WarningIcon.cjs");
9
+ function _interopNamespaceDefault(e) {
10
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
11
+ if (e) {
12
+ for (const k in e) {
13
+ if (k !== "default") {
14
+ const d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: () => e[k]
18
+ });
19
+ }
20
+ }
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
26
+ function CriticalBannerCta({
27
+ ctaLabel,
28
+ ctaProps
29
+ }) {
30
+ const isDisabled = ctaProps?.disabled ?? false;
31
+ return /* @__PURE__ */ jsxRuntime.jsx(
32
+ Button.Button,
33
+ {
34
+ variant: "white",
35
+ size: "40",
36
+ ...ctaProps,
37
+ className: cn.cn(
38
+ !isDisabled && "text-alerts-critical-banner-background hover:text-alerts-critical-banner-background active:text-alerts-critical-banner-background",
39
+ ctaProps?.className
40
+ ),
41
+ children: ctaLabel
42
+ }
43
+ );
44
+ }
45
+ const CriticalBanner = React__namespace.forwardRef(
46
+ ({
47
+ className,
48
+ children,
49
+ layout = "trailing",
50
+ title,
51
+ icon,
52
+ ctaLabel,
53
+ ctaProps,
54
+ action,
55
+ role = "alert",
56
+ ...props
57
+ }, ref) => {
58
+ const isUnder = layout === "under";
59
+ const cta = action ?? (ctaLabel !== void 0 && ctaLabel !== null && ctaLabel !== false ? /* @__PURE__ */ jsxRuntime.jsx(CriticalBannerCta, { ctaLabel, ctaProps }) : null);
60
+ const iconNode = /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-alerts-critical-banner-icons", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsxRuntime.jsx(WarningIcon.WarningIcon, { filled: true, size: 32 }) });
61
+ const textColumn = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1 break-words pt-1 text-alerts-critical-banner-content", children: [
62
+ title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "typography-header-heading-xs", children: title }),
63
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "typography-body-default-16px-regular", children })
64
+ ] });
65
+ if (isUnder) {
66
+ return /* @__PURE__ */ jsxRuntime.jsxs(
67
+ "div",
68
+ {
69
+ ref,
70
+ role,
71
+ className: cn.cn(
72
+ "flex w-full min-w-[260px] items-start gap-4 rounded-md bg-alerts-critical-banner-background p-6",
73
+ className
74
+ ),
75
+ ...props,
76
+ children: [
77
+ iconNode,
78
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col items-start gap-6", children: [
79
+ textColumn,
80
+ cta !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: cta })
81
+ ] })
82
+ ]
83
+ }
84
+ );
85
+ }
86
+ return /* @__PURE__ */ jsxRuntime.jsxs(
87
+ "div",
88
+ {
89
+ ref,
90
+ role,
91
+ className: cn.cn(
92
+ "flex w-full min-w-[260px] items-center gap-6 rounded-md bg-alerts-critical-banner-background p-6",
93
+ className
94
+ ),
95
+ ...props,
96
+ children: [
97
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-4", children: [
98
+ iconNode,
99
+ textColumn
100
+ ] }),
101
+ cta !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: cta })
102
+ ]
103
+ }
104
+ );
105
+ }
106
+ );
107
+ CriticalBanner.displayName = "CriticalBanner";
108
+ exports.CriticalBanner = CriticalBanner;
109
+ //# sourceMappingURL=CriticalBanner.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CriticalBanner.cjs","sources":["../../../../src/components/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button, type ButtonProps } from \"../Button/Button\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/**\n * Placement of the call-to-action relative to the message.\n *\n * - `\"trailing\"` keeps the action inline, aligned to the end of the banner.\n * - `\"under\"` stacks the action beneath the message (use when the CTA label is\n * too long to sit comfortably on the same line).\n */\nexport type CriticalBannerLayout = \"trailing\" | \"under\";\n\nexport interface CriticalBannerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Body copy describing the blocking situation. */\n children: React.ReactNode;\n /** Placement of the call-to-action relative to the message. @default \"trailing\" */\n layout?: CriticalBannerLayout;\n /** Optional bold heading shown above the body copy. */\n title?: React.ReactNode;\n /** Leading icon. Overrides the default filled warning icon. */\n icon?: React.ReactNode;\n /** Label for the built-in white call-to-action button. Ignored when `action` is set. */\n ctaLabel?: React.ReactNode;\n /**\n * Props forwarded to the built-in call-to-action button (e.g. `onClick`).\n * `asChild` is intentionally excluded — the built-in CTA renders `ctaLabel`\n * as text; for a link or fully custom element use the `action` prop instead.\n */\n ctaProps?: Omit<ButtonProps, \"variant\" | \"size\" | \"children\" | \"asChild\">;\n /** Custom action node rendered in place of the built-in call-to-action button. */\n action?: React.ReactNode;\n}\n\nfunction CriticalBannerCta({\n ctaLabel,\n ctaProps,\n}: {\n ctaLabel: React.ReactNode;\n ctaProps?: CriticalBannerProps[\"ctaProps\"];\n}) {\n // Only tint the label red for enabled states; when disabled, let Button keep\n // its own `text-content-disabled` treatment instead of overriding it.\n const isDisabled = ctaProps?.disabled ?? false;\n return (\n <Button\n variant=\"white\"\n size=\"40\"\n {...ctaProps}\n className={cn(\n !isDisabled &&\n \"text-alerts-critical-banner-background hover:text-alerts-critical-banner-background active:text-alerts-critical-banner-background\",\n ctaProps?.className,\n )}\n >\n {ctaLabel}\n </Button>\n );\n}\n\n/**\n * A full-width, high-priority banner reserved for situations that block or\n * significantly impact a user's ability to use the platform — account\n * suspensions, blocking payment failures, identity verification requirements,\n * or critical security notices. It sits at the very top of a page and is\n * intentionally disruptive, so use it sparingly; for non-blocking messaging use\n * {@link Alert} or {@link Banner} instead.\n *\n * Renders with `role=\"alert\"` so assistive technology conveys its urgency;\n * override `role` for a less assertive treatment when appropriate.\n *\n * @example\n * ```tsx\n * <CriticalBanner\n * title=\"Payment failed\"\n * layout=\"trailing\"\n * ctaLabel=\"Update payment\"\n * ctaProps={{ onClick: handleUpdate }}\n * >\n * We couldn't process your last payment. Update your details to keep your account active.\n * </CriticalBanner>\n * ```\n */\nexport const CriticalBanner = React.forwardRef<HTMLDivElement, CriticalBannerProps>(\n (\n {\n className,\n children,\n layout = \"trailing\",\n title,\n icon,\n ctaLabel,\n ctaProps,\n action,\n role = \"alert\",\n ...props\n },\n ref,\n ) => {\n const isUnder = layout === \"under\";\n\n const cta =\n action ??\n (ctaLabel !== undefined && ctaLabel !== null && ctaLabel !== false ? (\n <CriticalBannerCta ctaLabel={ctaLabel} ctaProps={ctaProps} />\n ) : null);\n\n const iconNode = (\n <span className=\"shrink-0 text-alerts-critical-banner-icons\" aria-hidden=\"true\">\n {icon ?? <WarningIcon filled size={32} />}\n </span>\n );\n\n const textColumn = (\n <div className=\"flex min-w-0 flex-col gap-1 break-words pt-1 text-alerts-critical-banner-content\">\n {title && <div className=\"typography-header-heading-xs\">{title}</div>}\n <div className=\"typography-body-default-16px-regular\">{children}</div>\n </div>\n );\n\n if (isUnder) {\n return (\n <div\n ref={ref}\n role={role}\n className={cn(\n \"flex w-full min-w-[260px] items-start gap-4 rounded-md bg-alerts-critical-banner-background p-6\",\n className,\n )}\n {...props}\n >\n {iconNode}\n <div className=\"flex min-w-0 flex-1 flex-col items-start gap-6\">\n {textColumn}\n {cta !== null && <div className=\"shrink-0\">{cta}</div>}\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n role={role}\n className={cn(\n \"flex w-full min-w-[260px] items-center gap-6 rounded-md bg-alerts-critical-banner-background p-6\",\n className,\n )}\n {...props}\n >\n <div className=\"flex min-w-0 flex-1 items-start gap-4\">\n {iconNode}\n {textColumn}\n </div>\n {cta !== null && <div className=\"shrink-0\">{cta}</div>}\n </div>\n );\n },\n);\n\nCriticalBanner.displayName = \"CriticalBanner\";\n"],"names":["jsx","Button","cn","React","WarningIcon","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AAGD,QAAM,aAAa,UAAU,YAAY;AACzC,SACEA,2BAAAA;AAAAA,IAACC,OAAAA;AAAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACJ,GAAG;AAAA,MACJ,WAAWC,GAAAA;AAAAA,QACT,CAAC,cACC;AAAA,QACF,UAAU;AAAA,MAAA;AAAA,MAGX,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAyBO,MAAM,iBAAiBC,iBAAM;AAAA,EAClC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,UAAU,WAAW;AAE3B,UAAM,MACJ,WACC,aAAa,UAAa,aAAa,QAAQ,aAAa,QAC3DH,2BAAAA,IAAC,mBAAA,EAAkB,UAAoB,SAAA,CAAoB,IACzD;AAEN,UAAM,WACJA,2BAAAA,IAAC,QAAA,EAAK,WAAU,8CAA6C,eAAY,QACtE,UAAA,QAAQA,2BAAAA,IAACI,YAAAA,aAAA,EAAY,QAAM,MAAC,MAAM,IAAI,GACzC;AAGF,UAAM,aACJC,2BAAAA,KAAC,OAAA,EAAI,WAAU,oFACZ,UAAA;AAAA,MAAA,SAASL,2BAAAA,IAAC,OAAA,EAAI,WAAU,gCAAgC,UAAA,OAAM;AAAA,MAC/DA,2BAAAA,IAAC,OAAA,EAAI,WAAU,wCAAwC,SAAA,CAAS;AAAA,IAAA,GAClE;AAGF,QAAI,SAAS;AACX,aACEK,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,WAAWH,GAAAA;AAAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,UAED,GAAG;AAAA,UAEH,UAAA;AAAA,YAAA;AAAA,YACDG,2BAAAA,KAAC,OAAA,EAAI,WAAU,kDACZ,UAAA;AAAA,cAAA;AAAA,cACA,QAAQ,QAAQL,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,UAAA,IAAA,CAAI;AAAA,YAAA,EAAA,CAClD;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAEA,WACEK,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAWH,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAG,2BAAAA,KAAC,OAAA,EAAI,WAAU,yCACZ,UAAA;AAAA,YAAA;AAAA,YACA;AAAA,UAAA,GACH;AAAA,UACC,QAAQ,QAAQL,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,UAAA,IAAA,CAAI;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGtD;AACF;AAEA,eAAe,cAAc;;"}
@@ -19,6 +19,7 @@ const BottomNavigation = require("./components/BottomNavigation/BottomNavigation
19
19
  const BottomNavigationAction = require("./components/BottomNavigation/BottomNavigationAction.cjs");
20
20
  const Breadcrumb = require("./components/Breadcrumb/Breadcrumb.cjs");
21
21
  const Button = require("./components/Button/Button.cjs");
22
+ const ButtonStack = require("./components/ButtonStack/ButtonStack.cjs");
22
23
  const Card = require("./components/Card/Card.cjs");
23
24
  const ChatInput = require("./components/ChatInput/ChatInput.cjs");
24
25
  const ChatMessage = require("./components/ChatMessage/ChatMessage.cjs");
@@ -28,6 +29,7 @@ const Count = require("./components/Count/Count.cjs");
28
29
  const CreatorCard = require("./components/CreatorCard/CreatorCard.cjs");
29
30
  const CreatorCover = require("./components/CreatorCover/CreatorCover.cjs");
30
31
  const CreatorTile = require("./components/CreatorTile/CreatorTile.cjs");
32
+ const CriticalBanner = require("./components/CriticalBanner/CriticalBanner.cjs");
31
33
  const CyclingText = require("./components/CyclingText/CyclingText.cjs");
32
34
  const Dialog = require("./components/Dialog/Dialog.cjs");
33
35
  const Divider = require("./components/Divider/Divider.cjs");
@@ -289,6 +291,7 @@ exports.BreadcrumbList = Breadcrumb.BreadcrumbList;
289
291
  exports.BreadcrumbPage = Breadcrumb.BreadcrumbPage;
290
292
  exports.BreadcrumbSeparator = Breadcrumb.BreadcrumbSeparator;
291
293
  exports.Button = Button.Button;
294
+ exports.ButtonStack = ButtonStack.ButtonStack;
292
295
  exports.Card = Card.Card;
293
296
  exports.CardContent = Card.CardContent;
294
297
  exports.CardDescription = Card.CardDescription;
@@ -303,6 +306,7 @@ exports.Count = Count.Count;
303
306
  exports.CreatorCard = CreatorCard.CreatorCard;
304
307
  exports.CreatorCover = CreatorCover.CreatorCover;
305
308
  exports.CreatorTile = CreatorTile.CreatorTile;
309
+ exports.CriticalBanner = CriticalBanner.CriticalBanner;
306
310
  exports.CyclingText = CyclingText.CyclingText;
307
311
  exports.Dialog = Dialog.Dialog;
308
312
  exports.DialogBody = Dialog.DialogBody;
@@ -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,27 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ const ButtonStack = React.forwardRef(
6
+ ({ direction = "horizontal", className, children, ...props }, ref) => {
7
+ return /* @__PURE__ */ jsx(
8
+ "div",
9
+ {
10
+ ref,
11
+ className: cn(
12
+ "flex gap-2",
13
+ direction === "horizontal" && "flex-row [&>*]:min-w-0 [&>*]:flex-1",
14
+ direction === "vertical" && "flex-col [&>*]:w-full",
15
+ className
16
+ ),
17
+ ...props,
18
+ children
19
+ }
20
+ );
21
+ }
22
+ );
23
+ ButtonStack.displayName = "ButtonStack";
24
+ export {
25
+ ButtonStack
26
+ };
27
+ //# sourceMappingURL=ButtonStack.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonStack.mjs","sources":["../../../src/components/ButtonStack/ButtonStack.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Layout orientation of the buttons within a {@link ButtonStack}. */\nexport type ButtonStackDirection = \"horizontal\" | \"vertical\";\n\nexport interface ButtonStackProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Layout orientation. `horizontal` places buttons side by side with equal\n * widths for primary + secondary action pairs; `vertical` stacks them\n * full-width for mobile screens and narrow panels.\n * @default \"horizontal\"\n */\n direction?: ButtonStackDirection;\n /** Buttons to arrange — typically two {@link Button} elements. */\n children: React.ReactNode;\n}\n\n/**\n * A layout helper that arranges action buttons either side by side\n * (`horizontal`) or stacked (`vertical`). Compose it with {@link Button}\n * children rather than reimplementing button styles.\n *\n * In `horizontal` mode each child stretches to an equal width; in `vertical`\n * mode each child spans the full width of the container. Buttons keep their\n * own sizing, so pass a matching `size` to each child for consistent heights.\n *\n * @example\n * ```tsx\n * <ButtonStack direction=\"horizontal\">\n * <Button variant=\"outline\">Cancel</Button>\n * <Button variant=\"primary\">Confirm</Button>\n * </ButtonStack>\n * ```\n */\nexport const ButtonStack = React.forwardRef<HTMLDivElement, ButtonStackProps>(\n ({ direction = \"horizontal\", className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex gap-2\",\n direction === \"horizontal\" && \"flex-row [&>*]:min-w-0 [&>*]:flex-1\",\n direction === \"vertical\" && \"flex-col [&>*]:w-full\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nButtonStack.displayName = \"ButtonStack\";\n"],"names":[],"mappings":";;;;AAmCO,MAAM,cAAc,MAAM;AAAA,EAC/B,CAAC,EAAE,YAAY,cAAc,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AACpE,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,cAAc,gBAAgB;AAAA,UAC9B,cAAc,cAAc;AAAA,UAC5B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,YAAY,cAAc;"}
@@ -2,35 +2,62 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cn } from "../../utils/cn.mjs";
5
- const VARIANT_CLASSES = {
5
+ const CardContext = React.createContext({
6
+ hierarchy: "primary",
7
+ type: "default"
8
+ });
9
+ const useCardContext = () => React.useContext(CardContext);
10
+ const LEGACY_VARIANT_CLASSES = {
6
11
  outlined: "border border-neutral-alphas-200 bg-surface-primary shadow-sm",
7
12
  elevated: "border border-neutral-alphas-200 bg-surface-primary shadow-md",
8
13
  filled: "bg-surface-secondary",
9
14
  ghost: "bg-transparent"
10
15
  };
16
+ const HIERARCHY_CLASSES = {
17
+ primary: "rounded-lg border border-border-primary bg-surface-primary",
18
+ secondary: "rounded-md border border-border-strong bg-surface-secondary shadow-sm"
19
+ };
20
+ const INTERACTIVE_CLASSES = "isolate cursor-pointer after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-content-primary after:opacity-0 after:transition-opacity after:content-[''] hover:after:opacity-5";
11
21
  const Card = React.forwardRef(
12
- ({ className, variant = "outlined", fullWidth = true, noPadding = false, children, ...props }, ref) => {
13
- return /* @__PURE__ */ jsx(
22
+ ({
23
+ className,
24
+ hierarchy = "primary",
25
+ type = "default",
26
+ interactive = false,
27
+ variant,
28
+ fullWidth = true,
29
+ noPadding = false,
30
+ children,
31
+ ...props
32
+ }, ref) => {
33
+ const isLegacy = variant !== void 0;
34
+ const padding = noPadding ? void 0 : isLegacy ? "p-4" : hierarchy === "secondary" ? "p-4" : "p-6";
35
+ const contextValue = React.useMemo(
36
+ () => ({ hierarchy, type }),
37
+ [hierarchy, type]
38
+ );
39
+ return /* @__PURE__ */ jsx(CardContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
14
40
  "div",
15
41
  {
16
42
  ref,
17
43
  className: cn(
18
- "flex flex-col overflow-hidden rounded-md",
19
- !noPadding && "p-4",
44
+ "relative flex flex-col overflow-hidden",
45
+ isLegacy ? cn("rounded-md", LEGACY_VARIANT_CLASSES[variant]) : HIERARCHY_CLASSES[hierarchy],
46
+ padding,
20
47
  fullWidth && "w-full",
21
- VARIANT_CLASSES[variant],
48
+ interactive && INTERACTIVE_CLASSES,
22
49
  className
23
50
  ),
24
51
  ...props,
25
52
  children
26
53
  }
27
- );
54
+ ) });
28
55
  }
29
56
  );
30
57
  Card.displayName = "Card";
31
58
  const CardHeader = React.forwardRef(
32
59
  ({ className, action, children, ...props }, ref) => {
33
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex items-start gap-3", className), ...props, children: [
60
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex min-h-8 items-center gap-2", className), ...props, children: [
34
61
  /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children }),
35
62
  action && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: action })
36
63
  ] });
@@ -39,11 +66,16 @@ const CardHeader = React.forwardRef(
39
66
  CardHeader.displayName = "CardHeader";
40
67
  const CardTitle = React.forwardRef(
41
68
  ({ className, children, ...props }, ref) => {
69
+ const { hierarchy } = useCardContext();
42
70
  return /* @__PURE__ */ jsx(
43
71
  "h3",
44
72
  {
45
73
  ref,
46
- className: cn("typography-body-default-16px-semibold text-content-primary", className),
74
+ className: cn(
75
+ hierarchy === "secondary" ? "typography-body-small-14px-regular" : "typography-header-heading-xs",
76
+ "text-content-primary",
77
+ className
78
+ ),
47
79
  ...props,
48
80
  children
49
81
  }
@@ -67,13 +99,15 @@ const CardDescription = React.forwardRef(
67
99
  CardDescription.displayName = "CardDescription";
68
100
  const CardContent = React.forwardRef(
69
101
  ({ className, children, ...props }, ref) => {
70
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex-1 py-4", className), ...props, children });
102
+ const { type } = useCardContext();
103
+ const padding = type === "container" ? void 0 : type === "header-only" ? "pt-6" : "py-6";
104
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("flex-1", padding, className), ...props, children });
71
105
  }
72
106
  );
73
107
  CardContent.displayName = "CardContent";
74
108
  const CardFooter = React.forwardRef(
75
109
  ({ className, children, ...props }, ref) => {
76
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center gap-3", className), ...props, children });
110
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("flex w-full items-center gap-2", className), ...props, children });
77
111
  }
78
112
  );
79
113
  CardFooter.displayName = "CardFooter";
@@ -1 +1 @@
1
- {"version":3,"file":"Card.mjs","sources":["../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual style variant of the card. */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual style variant of the card. @default \"outlined\" */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\n/**\n * A composable card component with multiple visual variants. Use with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * @example\n * ```tsx\n * <Card variant=\"outlined\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n { className, variant = \"outlined\", fullWidth = true, noPadding = false, children, ...props },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-col overflow-hidden rounded-md\",\n !noPadding && \"p-4\",\n fullWidth && \"w-full\",\n VARIANT_CLASSES[variant],\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-start gap-3\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <h3\n ref={ref}\n className={cn(\"typography-body-default-16px-semibold text-content-primary\", className)}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-description-12px-regular text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/** Flexible content area of a {@link Card}. Adds vertical padding between header and footer. */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex-1 py-4\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex items-center gap-3\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":[],"mappings":";;;;AA4BA,MAAM,kBAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,OAAO;AACT;AAsBO,MAAM,OAAO,MAAM;AAAA,EACxB,CACE,EAAE,WAAW,UAAU,YAAY,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG,MAAA,GACrF,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA,CAAC,aAAa;AAAA,UACd,aAAa;AAAA,UACb,gBAAgB,OAAO;AAAA,UACvB;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,KAAK,cAAc;AAMZ,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,QAAQ,UAAU,GAAG,MAAA,GAAS,QAAQ;AAClD,WACE,qBAAC,SAAI,KAAU,WAAW,GAAG,0BAA0B,SAAS,GAAI,GAAG,OACrE,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,kBAAkB,SAAA,CAAS;AAAA,MACzC,UAAU,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,OAAA,CAAO;AAAA,IAAA,GAC/C;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;AAGlB,MAAM,YAAY,MAAM;AAAA,EAC7B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,UAAU,cAAc;AAGjB,MAAM,kBAAkB,MAAM;AAAA,EACnC,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,8DAA8D,SAAS;AAAA,QACpF,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AACA,gBAAgB,cAAc;AAGvB,MAAM,cAAc,MAAM;AAAA,EAC/B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,eAAe,SAAS,GAAI,GAAG,OACzD,SAAA,CACH;AAAA,EAEJ;AACF;AACA,YAAY,cAAc;AAGnB,MAAM,aAAa,MAAM;AAAA,EAC9B,CAAC,EAAE,WAAW,UAAU,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACE,oBAAC,OAAA,EAAI,KAAU,WAAW,GAAG,2BAA2B,SAAS,GAAI,GAAG,OACrE,SAAA,CACH;AAAA,EAEJ;AACF;AACA,WAAW,cAAc;"}
1
+ {"version":3,"file":"Card.mjs","sources":["../../../src/components/Card/Card.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Visual hierarchy of the card. Primary is for prominent, content-carrying cards; secondary for supporting cards within denser layouts. */\nexport type CardHierarchy = \"primary\" | \"secondary\";\n\n/** Structural type of the card. `default` has header, content and footer; `header-only` drops the footer; `container` is a bare surface. */\nexport type CardType = \"default\" | \"header-only\" | \"container\";\n\n/**\n * Legacy visual style variant.\n * @deprecated Use {@link CardHierarchy} via the `hierarchy` prop instead. Retained for backwards compatibility.\n */\nexport type CardVariant = \"outlined\" | \"elevated\" | \"filled\" | \"ghost\";\n\ninterface CardContextValue {\n hierarchy: CardHierarchy;\n type: CardType;\n}\n\nconst CardContext = React.createContext<CardContextValue>({\n hierarchy: \"primary\",\n type: \"default\",\n});\n\nconst useCardContext = () => React.useContext(CardContext);\n\nexport interface CardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Visual hierarchy of the card. @default \"primary\" */\n hierarchy?: CardHierarchy;\n /** Structural type of the card. @default \"default\" */\n type?: CardType;\n /** When `true`, applies the hover treatment for clickable cards. @default false */\n interactive?: boolean;\n /**\n * Legacy visual style variant.\n * @deprecated Use `hierarchy` instead. When set, the card keeps its legacy V1 appearance for backwards compatibility.\n */\n variant?: CardVariant;\n /** When `true`, the card will take the full width of its container. @default true */\n fullWidth?: boolean;\n /** When `true`, removes all internal padding. @default false */\n noPadding?: boolean;\n}\n\nexport interface CardHeaderProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Icon element displayed at the trailing end of the header. */\n action?: React.ReactNode;\n}\n\nexport interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {}\n\nexport interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}\n\nexport interface CardContentProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nexport interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {}\n\nconst LEGACY_VARIANT_CLASSES: Record<CardVariant, string> = {\n outlined: \"border border-neutral-alphas-200 bg-surface-primary shadow-sm\",\n elevated: \"border border-neutral-alphas-200 bg-surface-primary shadow-md\",\n filled: \"bg-surface-secondary\",\n ghost: \"bg-transparent\",\n};\n\nconst HIERARCHY_CLASSES: Record<CardHierarchy, string> = {\n primary: \"rounded-lg border border-border-primary bg-surface-primary\",\n secondary: \"rounded-md border border-border-strong bg-surface-secondary shadow-sm\",\n};\n\nconst INTERACTIVE_CLASSES =\n \"isolate cursor-pointer after:pointer-events-none after:absolute after:inset-0 after:-z-10 after:bg-content-primary after:opacity-0 after:transition-opacity after:content-[''] hover:after:opacity-5\";\n\n/**\n * A composable card component built on the V2 design system. Compose it with\n * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},\n * {@link CardContent}, and {@link CardFooter} for structured layouts.\n *\n * The `hierarchy` prop drives the surface treatment (Primary vs Secondary) and\n * the `type` prop drives the internal spacing (Default / Header Only / Container).\n *\n * @example\n * ```tsx\n * <Card hierarchy=\"primary\">\n * <CardHeader action={<HomeIcon className=\"size-5\" />}>\n * <CardTitle>Card title</CardTitle>\n * <CardDescription>Card description text</CardDescription>\n * </CardHeader>\n * <CardContent>Content goes here</CardContent>\n * <CardFooter>\n * <Button variant=\"secondary\">Label</Button>\n * <Button variant=\"primary\">Label</Button>\n * </CardFooter>\n * </Card>\n * ```\n */\nexport const Card = React.forwardRef<HTMLDivElement, CardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n type = \"default\",\n interactive = false,\n variant,\n fullWidth = true,\n noPadding = false,\n children,\n ...props\n },\n ref,\n ) => {\n const isLegacy = variant !== undefined;\n const padding = noPadding\n ? undefined\n : isLegacy\n ? \"p-4\"\n : hierarchy === \"secondary\"\n ? \"p-4\"\n : \"p-6\";\n\n const contextValue = React.useMemo<CardContextValue>(\n () => ({ hierarchy, type }),\n [hierarchy, type],\n );\n\n return (\n <CardContext.Provider value={contextValue}>\n <div\n ref={ref}\n className={cn(\n \"relative flex flex-col overflow-hidden\",\n isLegacy\n ? cn(\"rounded-md\", LEGACY_VARIANT_CLASSES[variant])\n : HIERARCHY_CLASSES[hierarchy],\n padding,\n fullWidth && \"w-full\",\n interactive && INTERACTIVE_CLASSES,\n className,\n )}\n {...props}\n >\n {children}\n </div>\n </CardContext.Provider>\n );\n },\n);\nCard.displayName = \"Card\";\n\n/**\n * Header section of a {@link Card}. Renders a flex row with text content\n * on the left and an optional trailing action element (e.g. icon) on the right.\n */\nexport const CardHeader = React.forwardRef<HTMLDivElement, CardHeaderProps>(\n ({ className, action, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex min-h-8 items-center gap-2\", className)} {...props}>\n <div className=\"min-w-0 flex-1\">{children}</div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n );\n },\n);\nCardHeader.displayName = \"CardHeader\";\n\n/** Title element rendered inside a {@link CardHeader}. Adapts its type scale to the card `hierarchy`. */\nexport const CardTitle = React.forwardRef<HTMLHeadingElement, CardTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { hierarchy } = useCardContext();\n return (\n <h3\n ref={ref}\n className={cn(\n hierarchy === \"secondary\"\n ? \"typography-body-small-14px-regular\"\n : \"typography-header-heading-xs\",\n \"text-content-primary\",\n className,\n )}\n {...props}\n >\n {children}\n </h3>\n );\n },\n);\nCardTitle.displayName = \"CardTitle\";\n\n/** Description text rendered below the {@link CardTitle} inside a {@link CardHeader}. */\nexport const CardDescription = React.forwardRef<HTMLParagraphElement, CardDescriptionProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn(\"typography-description-12px-regular text-content-secondary\", className)}\n {...props}\n >\n {children}\n </p>\n );\n },\n);\nCardDescription.displayName = \"CardDescription\";\n\n/**\n * Flexible content area of a {@link Card}. Its vertical padding follows the card\n * `type`: `default` pads top and bottom, `header-only` pads only the top, and\n * `container` removes the built-in padding entirely.\n */\nexport const CardContent = React.forwardRef<HTMLDivElement, CardContentProps>(\n ({ className, children, ...props }, ref) => {\n const { type } = useCardContext();\n const padding = type === \"container\" ? undefined : type === \"header-only\" ? \"pt-6\" : \"py-6\";\n return (\n <div ref={ref} className={cn(\"flex-1\", padding, className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardContent.displayName = \"CardContent\";\n\n/** Footer section of a {@link Card}. Renders children in a horizontal row with a gap. */\nexport const CardFooter = React.forwardRef<HTMLDivElement, CardFooterProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex w-full items-center gap-2\", className)} {...props}>\n {children}\n </div>\n );\n },\n);\nCardFooter.displayName = \"CardFooter\";\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../utils/cn.mjs";
5
+ import { Button } from "../Button/Button.mjs";
6
+ import { WarningIcon } from "../Icons/WarningIcon.mjs";
7
+ function CriticalBannerCta({
8
+ ctaLabel,
9
+ ctaProps
10
+ }) {
11
+ const isDisabled = ctaProps?.disabled ?? false;
12
+ return /* @__PURE__ */ jsx(
13
+ Button,
14
+ {
15
+ variant: "white",
16
+ size: "40",
17
+ ...ctaProps,
18
+ className: cn(
19
+ !isDisabled && "text-alerts-critical-banner-background hover:text-alerts-critical-banner-background active:text-alerts-critical-banner-background",
20
+ ctaProps?.className
21
+ ),
22
+ children: ctaLabel
23
+ }
24
+ );
25
+ }
26
+ const CriticalBanner = React.forwardRef(
27
+ ({
28
+ className,
29
+ children,
30
+ layout = "trailing",
31
+ title,
32
+ icon,
33
+ ctaLabel,
34
+ ctaProps,
35
+ action,
36
+ role = "alert",
37
+ ...props
38
+ }, ref) => {
39
+ const isUnder = layout === "under";
40
+ const cta = action ?? (ctaLabel !== void 0 && ctaLabel !== null && ctaLabel !== false ? /* @__PURE__ */ jsx(CriticalBannerCta, { ctaLabel, ctaProps }) : null);
41
+ const iconNode = /* @__PURE__ */ jsx("span", { className: "shrink-0 text-alerts-critical-banner-icons", "aria-hidden": "true", children: icon ?? /* @__PURE__ */ jsx(WarningIcon, { filled: true, size: 32 }) });
42
+ const textColumn = /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1 break-words pt-1 text-alerts-critical-banner-content", children: [
43
+ title && /* @__PURE__ */ jsx("div", { className: "typography-header-heading-xs", children: title }),
44
+ /* @__PURE__ */ jsx("div", { className: "typography-body-default-16px-regular", children })
45
+ ] });
46
+ if (isUnder) {
47
+ return /* @__PURE__ */ jsxs(
48
+ "div",
49
+ {
50
+ ref,
51
+ role,
52
+ className: cn(
53
+ "flex w-full min-w-[260px] items-start gap-4 rounded-md bg-alerts-critical-banner-background p-6",
54
+ className
55
+ ),
56
+ ...props,
57
+ children: [
58
+ iconNode,
59
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col items-start gap-6", children: [
60
+ textColumn,
61
+ cta !== null && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: cta })
62
+ ] })
63
+ ]
64
+ }
65
+ );
66
+ }
67
+ return /* @__PURE__ */ jsxs(
68
+ "div",
69
+ {
70
+ ref,
71
+ role,
72
+ className: cn(
73
+ "flex w-full min-w-[260px] items-center gap-6 rounded-md bg-alerts-critical-banner-background p-6",
74
+ className
75
+ ),
76
+ ...props,
77
+ children: [
78
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-4", children: [
79
+ iconNode,
80
+ textColumn
81
+ ] }),
82
+ cta !== null && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: cta })
83
+ ]
84
+ }
85
+ );
86
+ }
87
+ );
88
+ CriticalBanner.displayName = "CriticalBanner";
89
+ export {
90
+ CriticalBanner
91
+ };
92
+ //# sourceMappingURL=CriticalBanner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CriticalBanner.mjs","sources":["../../../src/components/CriticalBanner/CriticalBanner.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Button, type ButtonProps } from \"../Button/Button\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/**\n * Placement of the call-to-action relative to the message.\n *\n * - `\"trailing\"` keeps the action inline, aligned to the end of the banner.\n * - `\"under\"` stacks the action beneath the message (use when the CTA label is\n * too long to sit comfortably on the same line).\n */\nexport type CriticalBannerLayout = \"trailing\" | \"under\";\n\nexport interface CriticalBannerProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Body copy describing the blocking situation. */\n children: React.ReactNode;\n /** Placement of the call-to-action relative to the message. @default \"trailing\" */\n layout?: CriticalBannerLayout;\n /** Optional bold heading shown above the body copy. */\n title?: React.ReactNode;\n /** Leading icon. Overrides the default filled warning icon. */\n icon?: React.ReactNode;\n /** Label for the built-in white call-to-action button. Ignored when `action` is set. */\n ctaLabel?: React.ReactNode;\n /**\n * Props forwarded to the built-in call-to-action button (e.g. `onClick`).\n * `asChild` is intentionally excluded — the built-in CTA renders `ctaLabel`\n * as text; for a link or fully custom element use the `action` prop instead.\n */\n ctaProps?: Omit<ButtonProps, \"variant\" | \"size\" | \"children\" | \"asChild\">;\n /** Custom action node rendered in place of the built-in call-to-action button. */\n action?: React.ReactNode;\n}\n\nfunction CriticalBannerCta({\n ctaLabel,\n ctaProps,\n}: {\n ctaLabel: React.ReactNode;\n ctaProps?: CriticalBannerProps[\"ctaProps\"];\n}) {\n // Only tint the label red for enabled states; when disabled, let Button keep\n // its own `text-content-disabled` treatment instead of overriding it.\n const isDisabled = ctaProps?.disabled ?? false;\n return (\n <Button\n variant=\"white\"\n size=\"40\"\n {...ctaProps}\n className={cn(\n !isDisabled &&\n \"text-alerts-critical-banner-background hover:text-alerts-critical-banner-background active:text-alerts-critical-banner-background\",\n ctaProps?.className,\n )}\n >\n {ctaLabel}\n </Button>\n );\n}\n\n/**\n * A full-width, high-priority banner reserved for situations that block or\n * significantly impact a user's ability to use the platform — account\n * suspensions, blocking payment failures, identity verification requirements,\n * or critical security notices. It sits at the very top of a page and is\n * intentionally disruptive, so use it sparingly; for non-blocking messaging use\n * {@link Alert} or {@link Banner} instead.\n *\n * Renders with `role=\"alert\"` so assistive technology conveys its urgency;\n * override `role` for a less assertive treatment when appropriate.\n *\n * @example\n * ```tsx\n * <CriticalBanner\n * title=\"Payment failed\"\n * layout=\"trailing\"\n * ctaLabel=\"Update payment\"\n * ctaProps={{ onClick: handleUpdate }}\n * >\n * We couldn't process your last payment. Update your details to keep your account active.\n * </CriticalBanner>\n * ```\n */\nexport const CriticalBanner = React.forwardRef<HTMLDivElement, CriticalBannerProps>(\n (\n {\n className,\n children,\n layout = \"trailing\",\n title,\n icon,\n ctaLabel,\n ctaProps,\n action,\n role = \"alert\",\n ...props\n },\n ref,\n ) => {\n const isUnder = layout === \"under\";\n\n const cta =\n action ??\n (ctaLabel !== undefined && ctaLabel !== null && ctaLabel !== false ? (\n <CriticalBannerCta ctaLabel={ctaLabel} ctaProps={ctaProps} />\n ) : null);\n\n const iconNode = (\n <span className=\"shrink-0 text-alerts-critical-banner-icons\" aria-hidden=\"true\">\n {icon ?? <WarningIcon filled size={32} />}\n </span>\n );\n\n const textColumn = (\n <div className=\"flex min-w-0 flex-col gap-1 break-words pt-1 text-alerts-critical-banner-content\">\n {title && <div className=\"typography-header-heading-xs\">{title}</div>}\n <div className=\"typography-body-default-16px-regular\">{children}</div>\n </div>\n );\n\n if (isUnder) {\n return (\n <div\n ref={ref}\n role={role}\n className={cn(\n \"flex w-full min-w-[260px] items-start gap-4 rounded-md bg-alerts-critical-banner-background p-6\",\n className,\n )}\n {...props}\n >\n {iconNode}\n <div className=\"flex min-w-0 flex-1 flex-col items-start gap-6\">\n {textColumn}\n {cta !== null && <div className=\"shrink-0\">{cta}</div>}\n </div>\n </div>\n );\n }\n\n return (\n <div\n ref={ref}\n role={role}\n className={cn(\n \"flex w-full min-w-[260px] items-center gap-6 rounded-md bg-alerts-critical-banner-background p-6\",\n className,\n )}\n {...props}\n >\n <div className=\"flex min-w-0 flex-1 items-start gap-4\">\n {iconNode}\n {textColumn}\n </div>\n {cta !== null && <div className=\"shrink-0\">{cta}</div>}\n </div>\n );\n },\n);\n\nCriticalBanner.displayName = \"CriticalBanner\";\n"],"names":[],"mappings":";;;;;;AAmCA,SAAS,kBAAkB;AAAA,EACzB;AAAA,EACA;AACF,GAGG;AAGD,QAAM,aAAa,UAAU,YAAY;AACzC,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAK;AAAA,MACJ,GAAG;AAAA,MACJ,WAAW;AAAA,QACT,CAAC,cACC;AAAA,QACF,UAAU;AAAA,MAAA;AAAA,MAGX,UAAA;AAAA,IAAA;AAAA,EAAA;AAGP;AAyBO,MAAM,iBAAiB,MAAM;AAAA,EAClC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,UAAU,WAAW;AAE3B,UAAM,MACJ,WACC,aAAa,UAAa,aAAa,QAAQ,aAAa,QAC3D,oBAAC,mBAAA,EAAkB,UAAoB,SAAA,CAAoB,IACzD;AAEN,UAAM,WACJ,oBAAC,QAAA,EAAK,WAAU,8CAA6C,eAAY,QACtE,UAAA,QAAQ,oBAAC,aAAA,EAAY,QAAM,MAAC,MAAM,IAAI,GACzC;AAGF,UAAM,aACJ,qBAAC,OAAA,EAAI,WAAU,oFACZ,UAAA;AAAA,MAAA,SAAS,oBAAC,OAAA,EAAI,WAAU,gCAAgC,UAAA,OAAM;AAAA,MAC/D,oBAAC,OAAA,EAAI,WAAU,wCAAwC,SAAA,CAAS;AAAA,IAAA,GAClE;AAGF,QAAI,SAAS;AACX,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA,WAAW;AAAA,YACT;AAAA,YACA;AAAA,UAAA;AAAA,UAED,GAAG;AAAA,UAEH,UAAA;AAAA,YAAA;AAAA,YACD,qBAAC,OAAA,EAAI,WAAU,kDACZ,UAAA;AAAA,cAAA;AAAA,cACA,QAAQ,QAAQ,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,IAAA,CAAI;AAAA,YAAA,EAAA,CAClD;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAGN;AAEA,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,yCACZ,UAAA;AAAA,YAAA;AAAA,YACA;AAAA,UAAA,GACH;AAAA,UACC,QAAQ,QAAQ,oBAAC,OAAA,EAAI,WAAU,YAAY,UAAA,IAAA,CAAI;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGtD;AACF;AAEA,eAAe,cAAc;"}
package/dist/index.d.ts CHANGED
@@ -998,6 +998,40 @@ export declare interface ButtonProps extends React_2.ButtonHTMLAttributes<HTMLBu
998
998
  /** Button height in pixels. */
999
999
  export declare type ButtonSize = "48" | "40" | "32" | "24";
1000
1000
 
1001
+ /**
1002
+ * A layout helper that arranges action buttons either side by side
1003
+ * (`horizontal`) or stacked (`vertical`). Compose it with {@link Button}
1004
+ * children rather than reimplementing button styles.
1005
+ *
1006
+ * In `horizontal` mode each child stretches to an equal width; in `vertical`
1007
+ * mode each child spans the full width of the container. Buttons keep their
1008
+ * own sizing, so pass a matching `size` to each child for consistent heights.
1009
+ *
1010
+ * @example
1011
+ * ```tsx
1012
+ * <ButtonStack direction="horizontal">
1013
+ * <Button variant="outline">Cancel</Button>
1014
+ * <Button variant="primary">Confirm</Button>
1015
+ * </ButtonStack>
1016
+ * ```
1017
+ */
1018
+ export declare const ButtonStack: React_2.ForwardRefExoticComponent<ButtonStackProps & React_2.RefAttributes<HTMLDivElement>>;
1019
+
1020
+ /** Layout orientation of the buttons within a {@link ButtonStack}. */
1021
+ export declare type ButtonStackDirection = "horizontal" | "vertical";
1022
+
1023
+ export declare interface ButtonStackProps extends React_2.HTMLAttributes<HTMLDivElement> {
1024
+ /**
1025
+ * Layout orientation. `horizontal` places buttons side by side with equal
1026
+ * widths for primary + secondary action pairs; `vertical` stacks them
1027
+ * full-width for mobile screens and narrow panels.
1028
+ * @default "horizontal"
1029
+ */
1030
+ direction?: ButtonStackDirection;
1031
+ /** Buttons to arrange — typically two {@link Button} elements. */
1032
+ children: React_2.ReactNode;
1033
+ }
1034
+
1001
1035
  /** Visual style variant of the button. */
1002
1036
  export declare type ButtonVariant = "primary" | "secondary" | "tertiary" | "outline" | "link" | "brand" | "destructive" | "white" | "alwaysBlack" | "ai" | "tertiaryDestructive" | "text";
1003
1037
 
@@ -1032,13 +1066,16 @@ export declare const CameraIcon: React_2.ForwardRefExoticComponent<React_2.SVGAt
1032
1066
  } & React_2.RefAttributes<SVGSVGElement>>;
1033
1067
 
1034
1068
  /**
1035
- * A composable card component with multiple visual variants. Use with
1069
+ * A composable card component built on the V2 design system. Compose it with
1036
1070
  * {@link CardHeader}, {@link CardTitle}, {@link CardDescription},
1037
1071
  * {@link CardContent}, and {@link CardFooter} for structured layouts.
1038
1072
  *
1073
+ * The `hierarchy` prop drives the surface treatment (Primary vs Secondary) and
1074
+ * the `type` prop drives the internal spacing (Default / Header Only / Container).
1075
+ *
1039
1076
  * @example
1040
1077
  * ```tsx
1041
- * <Card variant="outlined">
1078
+ * <Card hierarchy="primary">
1042
1079
  * <CardHeader action={<HomeIcon className="size-5" />}>
1043
1080
  * <CardTitle>Card title</CardTitle>
1044
1081
  * <CardDescription>Card description text</CardDescription>
@@ -1053,7 +1090,11 @@ export declare const CameraIcon: React_2.ForwardRefExoticComponent<React_2.SVGAt
1053
1090
  */
1054
1091
  export declare const Card: React_2.ForwardRefExoticComponent<CardProps & React_2.RefAttributes<HTMLDivElement>>;
1055
1092
 
1056
- /** Flexible content area of a {@link Card}. Adds vertical padding between header and footer. */
1093
+ /**
1094
+ * Flexible content area of a {@link Card}. Its vertical padding follows the card
1095
+ * `type`: `default` pads top and bottom, `header-only` pads only the top, and
1096
+ * `container` removes the built-in padding entirely.
1097
+ */
1057
1098
  export declare const CardContent: React_2.ForwardRefExoticComponent<CardContentProps & React_2.RefAttributes<HTMLDivElement>>;
1058
1099
 
1059
1100
  export declare interface CardContentProps extends React_2.HTMLAttributes<HTMLDivElement> {
@@ -1082,6 +1123,9 @@ export declare interface CardHeaderProps extends React_2.HTMLAttributes<HTMLDivE
1082
1123
  action?: React_2.ReactNode;
1083
1124
  }
1084
1125
 
1126
+ /** Visual hierarchy of the card. Primary is for prominent, content-carrying cards; secondary for supporting cards within denser layouts. */
1127
+ export declare type CardHierarchy = "primary" | "secondary";
1128
+
1085
1129
  /**
1086
1130
  * Card icon. Renders at sizes 16, 24, or 32 px with outlined and filled variants.
1087
1131
  *
@@ -1096,7 +1140,16 @@ export declare const CardIcon: React_2.ForwardRefExoticComponent<BaseIconProps &
1096
1140
  export declare type CardIconProps = BaseIconProps;
1097
1141
 
1098
1142
  export declare interface CardProps extends React_2.HTMLAttributes<HTMLDivElement> {
1099
- /** Visual style variant of the card. @default "outlined" */
1143
+ /** Visual hierarchy of the card. @default "primary" */
1144
+ hierarchy?: CardHierarchy;
1145
+ /** Structural type of the card. @default "default" */
1146
+ type?: CardType;
1147
+ /** When `true`, applies the hover treatment for clickable cards. @default false */
1148
+ interactive?: boolean;
1149
+ /**
1150
+ * Legacy visual style variant.
1151
+ * @deprecated Use `hierarchy` instead. When set, the card keeps its legacy V1 appearance for backwards compatibility.
1152
+ */
1100
1153
  variant?: CardVariant;
1101
1154
  /** When `true`, the card will take the full width of its container. @default true */
1102
1155
  fullWidth?: boolean;
@@ -1104,13 +1157,19 @@ export declare interface CardProps extends React_2.HTMLAttributes<HTMLDivElement
1104
1157
  noPadding?: boolean;
1105
1158
  }
1106
1159
 
1107
- /** Title element rendered inside a {@link CardHeader}. */
1160
+ /** Title element rendered inside a {@link CardHeader}. Adapts its type scale to the card `hierarchy`. */
1108
1161
  export declare const CardTitle: React_2.ForwardRefExoticComponent<CardTitleProps & React_2.RefAttributes<HTMLHeadingElement>>;
1109
1162
 
1110
1163
  export declare interface CardTitleProps extends React_2.HTMLAttributes<HTMLHeadingElement> {
1111
1164
  }
1112
1165
 
1113
- /** Visual style variant of the card. */
1166
+ /** Structural type of the card. `default` has header, content and footer; `header-only` drops the footer; `container` is a bare surface. */
1167
+ export declare type CardType = "default" | "header-only" | "container";
1168
+
1169
+ /**
1170
+ * Legacy visual style variant.
1171
+ * @deprecated Use {@link CardHierarchy} via the `hierarchy` prop instead. Retained for backwards compatibility.
1172
+ */
1114
1173
  export declare type CardVariant = "outlined" | "elevated" | "filled" | "ghost";
1115
1174
 
1116
1175
  /**
@@ -1819,6 +1878,61 @@ export declare interface CreatorTileProps extends React_2.HTMLAttributes<HTMLDiv
1819
1878
  aspectRatio?: CreatorTileAspectRatio;
1820
1879
  }
1821
1880
 
1881
+ /**
1882
+ * A full-width, high-priority banner reserved for situations that block or
1883
+ * significantly impact a user's ability to use the platform — account
1884
+ * suspensions, blocking payment failures, identity verification requirements,
1885
+ * or critical security notices. It sits at the very top of a page and is
1886
+ * intentionally disruptive, so use it sparingly; for non-blocking messaging use
1887
+ * {@link Alert} or {@link Banner} instead.
1888
+ *
1889
+ * Renders with `role="alert"` so assistive technology conveys its urgency;
1890
+ * override `role` for a less assertive treatment when appropriate.
1891
+ *
1892
+ * @example
1893
+ * ```tsx
1894
+ * <CriticalBanner
1895
+ * title="Payment failed"
1896
+ * layout="trailing"
1897
+ * ctaLabel="Update payment"
1898
+ * ctaProps={{ onClick: handleUpdate }}
1899
+ * >
1900
+ * We couldn't process your last payment. Update your details to keep your account active.
1901
+ * </CriticalBanner>
1902
+ * ```
1903
+ */
1904
+ export declare const CriticalBanner: React_2.ForwardRefExoticComponent<CriticalBannerProps & React_2.RefAttributes<HTMLDivElement>>;
1905
+
1906
+ /**
1907
+ * Placement of the call-to-action relative to the message.
1908
+ *
1909
+ * - `"trailing"` keeps the action inline, aligned to the end of the banner.
1910
+ * - `"under"` stacks the action beneath the message (use when the CTA label is
1911
+ * too long to sit comfortably on the same line).
1912
+ */
1913
+ export declare type CriticalBannerLayout = "trailing" | "under";
1914
+
1915
+ export declare interface CriticalBannerProps extends Omit<React_2.HTMLAttributes<HTMLDivElement>, "title"> {
1916
+ /** Body copy describing the blocking situation. */
1917
+ children: React_2.ReactNode;
1918
+ /** Placement of the call-to-action relative to the message. @default "trailing" */
1919
+ layout?: CriticalBannerLayout;
1920
+ /** Optional bold heading shown above the body copy. */
1921
+ title?: React_2.ReactNode;
1922
+ /** Leading icon. Overrides the default filled warning icon. */
1923
+ icon?: React_2.ReactNode;
1924
+ /** Label for the built-in white call-to-action button. Ignored when `action` is set. */
1925
+ ctaLabel?: React_2.ReactNode;
1926
+ /**
1927
+ * Props forwarded to the built-in call-to-action button (e.g. `onClick`).
1928
+ * `asChild` is intentionally excluded — the built-in CTA renders `ctaLabel`
1929
+ * as text; for a link or fully custom element use the `action` prop instead.
1930
+ */
1931
+ ctaProps?: Omit<ButtonProps, "variant" | "size" | "children" | "asChild">;
1932
+ /** Custom action node rendered in place of the built-in call-to-action button. */
1933
+ action?: React_2.ReactNode;
1934
+ }
1935
+
1822
1936
  /**
1823
1937
  * Cross Circle icon. Renders at sizes 16, 24, or 32 px with outlined and filled variants.
1824
1938
  *
package/dist/index.mjs CHANGED
@@ -17,6 +17,7 @@ import { BottomNavigation } from "./components/BottomNavigation/BottomNavigation
17
17
  import { BottomNavigationAction } from "./components/BottomNavigation/BottomNavigationAction.mjs";
18
18
  import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "./components/Breadcrumb/Breadcrumb.mjs";
19
19
  import { Button } from "./components/Button/Button.mjs";
20
+ import { ButtonStack } from "./components/ButtonStack/ButtonStack.mjs";
20
21
  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./components/Card/Card.mjs";
21
22
  import { ChatInput } from "./components/ChatInput/ChatInput.mjs";
22
23
  import { ChatMessage } from "./components/ChatMessage/ChatMessage.mjs";
@@ -26,6 +27,7 @@ import { Count } from "./components/Count/Count.mjs";
26
27
  import { CreatorCard } from "./components/CreatorCard/CreatorCard.mjs";
27
28
  import { CreatorCover } from "./components/CreatorCover/CreatorCover.mjs";
28
29
  import { CreatorTile } from "./components/CreatorTile/CreatorTile.mjs";
30
+ import { CriticalBanner } from "./components/CriticalBanner/CriticalBanner.mjs";
29
31
  import { CyclingText } from "./components/CyclingText/CyclingText.mjs";
30
32
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogTitle, DialogTrigger } from "./components/Dialog/Dialog.mjs";
31
33
  import { Divider } from "./components/Divider/Divider.mjs";
@@ -299,6 +301,7 @@ export {
299
301
  BreadcrumbSeparator,
300
302
  BulbIcon,
301
303
  Button,
304
+ ButtonStack,
302
305
  Calendar2Icon,
303
306
  CalendarIcon,
304
307
  CameraIcon,
@@ -334,6 +337,7 @@ export {
334
337
  CreatorCard,
335
338
  CreatorCover,
336
339
  CreatorTile,
340
+ CriticalBanner,
337
341
  CrossCircleIcon,
338
342
  CrossIcon,
339
343
  CrownIcon,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanvue/ui",
3
- "version": "3.19.1",
3
+ "version": "3.20.0",
4
4
  "description": "React component library built with Tailwind CSS for Fanvue ecosystem",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",
@@ -133,8 +133,8 @@
133
133
  "@types/react": "19.2.9",
134
134
  "@types/react-dom": "19.2.3",
135
135
  "@vitejs/plugin-react": "5.1.2",
136
- "@vitest/browser-playwright": "4.1.8",
137
- "@vitest/coverage-v8": "4.1.8",
136
+ "@vitest/browser-playwright": "4.1.10",
137
+ "@vitest/coverage-v8": "4.1.10",
138
138
  "autoprefixer": "10.4.23",
139
139
  "axe-core": "4.11.1",
140
140
  "chromatic": "13.3.5",
@@ -151,12 +151,12 @@
151
151
  "size-limit": "12.0.0",
152
152
  "storybook": "10.2.13",
153
153
  "style-dictionary": "4.2.0",
154
- "svgo": "4.0.1",
154
+ "svgo": "4.0.2",
155
155
  "tailwindcss": "4.1.18",
156
156
  "typescript": "5.9.3",
157
157
  "vite": "7.3.5",
158
158
  "vite-plugin-dts": "4.5.4",
159
- "vitest": "4.1.8",
159
+ "vitest": "4.1.10",
160
160
  "vitest-axe": "1.0.0-pre.3"
161
161
  },
162
162
  "pnpm": {
@@ -165,6 +165,7 @@
165
165
  "lodash-es": ">=4.18.0",
166
166
  "minimatch": ">=10.2.3",
167
167
  "ajv": ">=8.18.0",
168
+ "fast-uri": ">=3.1.4",
168
169
  "brace-expansion": ">=5.0.7",
169
170
  "yaml": ">=2.8.3",
170
171
  "postcss": ">=8.5.10",