@fanvue/ui 3.21.1 → 3.23.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.
Files changed (27) hide show
  1. package/dist/charts.d.ts +15 -7
  2. package/dist/cjs/components/ButtonIconGroup/ButtonIconGroup.cjs +58 -0
  3. package/dist/cjs/components/ButtonIconGroup/ButtonIconGroup.cjs.map +1 -0
  4. package/dist/cjs/components/Chart/ChartCard.cjs +67 -42
  5. package/dist/cjs/components/Chart/ChartCard.cjs.map +1 -1
  6. package/dist/cjs/components/CreatorTile/CreatorTile.cjs +2 -1
  7. package/dist/cjs/components/CreatorTile/CreatorTile.cjs.map +1 -1
  8. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs +13 -1
  9. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs.map +1 -1
  10. package/dist/cjs/components/UserItem/UserItem.cjs +15 -1
  11. package/dist/cjs/components/UserItem/UserItem.cjs.map +1 -1
  12. package/dist/cjs/index.cjs +2 -0
  13. package/dist/cjs/index.cjs.map +1 -1
  14. package/dist/components/ButtonIconGroup/ButtonIconGroup.mjs +41 -0
  15. package/dist/components/ButtonIconGroup/ButtonIconGroup.mjs.map +1 -0
  16. package/dist/components/Chart/ChartCard.mjs +67 -42
  17. package/dist/components/Chart/ChartCard.mjs.map +1 -1
  18. package/dist/components/CreatorTile/CreatorTile.mjs +2 -1
  19. package/dist/components/CreatorTile/CreatorTile.mjs.map +1 -1
  20. package/dist/components/UserDisplayName/UserDisplayName.mjs +13 -1
  21. package/dist/components/UserDisplayName/UserDisplayName.mjs.map +1 -1
  22. package/dist/components/UserItem/UserItem.mjs +15 -1
  23. package/dist/components/UserItem/UserItem.mjs.map +1 -1
  24. package/dist/index.d.ts +77 -8
  25. package/dist/index.mjs +2 -0
  26. package/dist/index.mjs.map +1 -1
  27. package/package.json +4 -4
package/dist/charts.d.ts CHANGED
@@ -12,11 +12,12 @@ export declare type CardHierarchy = "primary" | "secondary";
12
12
 
13
13
  /**
14
14
  * Wraps any chart with a structured header containing title, subtitle,
15
- * optional trend chip, date range label, info tooltip, and a loading
15
+ * optional trend indicator, date range label, info tooltip, and a loading
16
16
  * skeleton state.
17
17
  *
18
- * The surface treatment comes from the underlying {@link Card} and is driven by
19
- * the `hierarchy` prop.
18
+ * At `hierarchy="primary"` this implements the V2 Insight Card surface, which
19
+ * differs from {@link Card}'s own primary hierarchy: a white fill, the strong
20
+ * border, and a 12px radius.
20
21
  *
21
22
  * @example
22
23
  * ```tsx
@@ -35,7 +36,11 @@ export declare const ChartCard: React_2.ForwardRefExoticComponent<ChartCardProps
35
36
 
36
37
  /** Props for {@link ChartCard}. */
37
38
  export declare interface ChartCardProps extends Omit<React_2.HTMLAttributes<HTMLDivElement>, "title"> {
38
- /** Surface treatment of the underlying {@link Card}. @default "primary" */
39
+ /**
40
+ * Surface treatment. `primary` follows the V2 Insight Card spec (white fill,
41
+ * strong border, 12px radius); `secondary` uses the {@link Card} secondary
42
+ * surface. @default "primary"
43
+ */
39
44
  hierarchy?: CardHierarchy;
40
45
  /** Card title text. Pass translated string for i18n. */
41
46
  title: React_2.ReactNode;
@@ -47,11 +52,14 @@ export declare interface ChartCardProps extends Omit<React_2.HTMLAttributes<HTML
47
52
  tooltipAriaLabel?: string;
48
53
  /** Date range or period label shown below the subtitle. */
49
54
  dateInfo?: React_2.ReactNode;
50
- /** Trend indicator chip config. Only rendered when {@link subtitle} is also provided. */
55
+ /**
56
+ * Trend indicator config. Rendered as a coloured directional arrow and label
57
+ * beside the subtitle, so it is only shown when {@link subtitle} is provided.
58
+ */
51
59
  trendChip?: {
52
- /** Display label (e.g. "12.5%"). */
60
+ /** Display label (e.g. "12.5% vs prev"). */
53
61
  label: React_2.ReactNode;
54
- /** Whether the trend is positive (green) or negative (red). */
62
+ /** Whether the trend is positive (green, arrow up) or negative (red, arrow down). */
55
63
  trend: "positive" | "negative";
56
64
  };
57
65
  /** Show loading skeleton instead of content. @default false */
@@ -0,0 +1,58 @@
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 ORIENTATION_AWARE_ROLES = /* @__PURE__ */ new Set([
25
+ "toolbar",
26
+ "menu",
27
+ "menubar",
28
+ "listbox",
29
+ "radiogroup",
30
+ "tablist",
31
+ "tree"
32
+ ]);
33
+ const ButtonIconGroup = React__namespace.forwardRef(
34
+ ({ className, orientation = "horizontal", role = "group", children, ...props }, ref) => {
35
+ const supportsOrientation = typeof role === "string" && ORIENTATION_AWARE_ROLES.has(role);
36
+ const orientationProps = supportsOrientation ? { "aria-orientation": orientation } : {};
37
+ return /* @__PURE__ */ jsxRuntime.jsx(
38
+ "div",
39
+ {
40
+ ref,
41
+ role,
42
+ ...orientationProps,
43
+ "data-testid": "button-icon-group",
44
+ "data-orientation": orientation,
45
+ className: cn.cn(
46
+ "inline-flex items-center gap-1",
47
+ orientation === "vertical" && "flex-col",
48
+ className
49
+ ),
50
+ ...props,
51
+ children
52
+ }
53
+ );
54
+ }
55
+ );
56
+ ButtonIconGroup.displayName = "ButtonIconGroup";
57
+ exports.ButtonIconGroup = ButtonIconGroup;
58
+ //# sourceMappingURL=ButtonIconGroup.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonIconGroup.cjs","sources":["../../../../src/components/ButtonIconGroup/ButtonIconGroup.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Orientation of the icon button cluster. */\nexport type ButtonIconGroupOrientation = \"horizontal\" | \"vertical\";\n\n// Roles whose ARIA semantics include an orientation. For these we mirror the\n// visual orientation so assistive tech isn't given the spec default\n// (horizontal) when the cluster is stacked vertically.\nconst ORIENTATION_AWARE_ROLES = new Set<string>([\n \"toolbar\",\n \"menu\",\n \"menubar\",\n \"listbox\",\n \"radiogroup\",\n \"tablist\",\n \"tree\",\n]);\n\nexport interface ButtonIconGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Direction the icon buttons flow in. Use `vertical` for side rails and\n * stacked media controls. @default \"horizontal\"\n */\n orientation?: ButtonIconGroupOrientation;\n /**\n * The icon buttons to cluster together. Compose {@link IconButton} elements\n * here; the group only handles layout and spacing.\n */\n children: React.ReactNode;\n}\n\n/**\n * A pre-composed cluster of {@link IconButton}s for toolbars and action rows\n * (media controls, editing tools, content action bars). Items are spaced with a\n * fixed 4px gap and stay individually rounded — this is a spaced group, not a\n * segmented/joined control.\n *\n * Exposes `role=\"group\"` by default; pass an `aria-label` or `aria-labelledby`\n * to describe the cluster for assistive technology.\n *\n * This is a presentational layout primitive: it does not implement\n * roving-tabindex / arrow-key focus management. `role` is overridable, but if\n * you set an interactive-widget role such as `role=\"toolbar\"` you own the\n * keyboard behaviour that role implies. For orientation-aware roles the\n * `aria-orientation` is synced to `orientation` automatically.\n *\n * @example\n * ```tsx\n * <ButtonIconGroup aria-label=\"Media controls\">\n * <IconButton variant=\"tertiary\" size=\"48\" icon={<PlayIcon />} aria-label=\"Play\" />\n * <IconButton variant=\"tertiary\" size=\"48\" icon={<ForwardIcon />} aria-label=\"Skip\" />\n * </ButtonIconGroup>\n * ```\n */\nexport const ButtonIconGroup = React.forwardRef<HTMLDivElement, ButtonIconGroupProps>(\n ({ className, orientation = \"horizontal\", role = \"group\", children, ...props }, ref) => {\n const supportsOrientation = typeof role === \"string\" && ORIENTATION_AWARE_ROLES.has(role);\n // Spread rather than a static attribute so the value is only present for\n // orientation-aware roles (a bare div/group role does not support it).\n const orientationProps = supportsOrientation ? { \"aria-orientation\": orientation } : {};\n return (\n <div\n ref={ref}\n role={role}\n {...orientationProps}\n data-testid=\"button-icon-group\"\n data-orientation={orientation}\n className={cn(\n \"inline-flex items-center gap-1\",\n orientation === \"vertical\" && \"flex-col\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nButtonIconGroup.displayName = \"ButtonIconGroup\";\n"],"names":["React","jsx","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AASA,MAAM,8CAA8B,IAAY;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAsCM,MAAM,kBAAkBA,iBAAM;AAAA,EACnC,CAAC,EAAE,WAAW,cAAc,cAAc,OAAO,SAAS,UAAU,GAAG,MAAA,GAAS,QAAQ;AACtF,UAAM,sBAAsB,OAAO,SAAS,YAAY,wBAAwB,IAAI,IAAI;AAGxF,UAAM,mBAAmB,sBAAsB,EAAE,oBAAoB,YAAA,IAAgB,CAAA;AACrF,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACC,GAAG;AAAA,QACJ,eAAY;AAAA,QACZ,oBAAkB;AAAA,QAClB,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,gBAAgB,cAAc;AAAA,UAC9B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,gBAAgB,cAAc;;"}
@@ -6,7 +6,8 @@ const React = require("react");
6
6
  const cn = require("../../utils/cn.cjs");
7
7
  const Card = require("../Card/Card.cjs");
8
8
  const IconButton = require("../IconButton/IconButton.cjs");
9
- const InfoCircleIcon = require("../Icons/InfoCircleIcon.cjs");
9
+ const ArrowUpRightIcon = require("../Icons/ArrowUpRightIcon.cjs");
10
+ const InfoIcon = require("../Icons/InfoIcon.cjs");
10
11
  const Skeleton = require("../Skeleton/Skeleton.cjs");
11
12
  const Tooltip = require("../Tooltip/Tooltip.cjs");
12
13
  function _interopNamespaceDefault(e) {
@@ -27,8 +28,11 @@ function _interopNamespaceDefault(e) {
27
28
  }
28
29
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
29
30
  const TREND_CLASSES = {
30
- positive: "bg-success-surface text-success-content",
31
- negative: "bg-error-surface text-error-content"
31
+ positive: "text-success-content",
32
+ negative: "text-error-content"
33
+ };
34
+ const SURFACE_CLASSES = {
35
+ primary: "rounded-sm border-border-strong bg-background-primary"
32
36
  };
33
37
  const ChartCard = React__namespace.forwardRef(
34
38
  ({
@@ -44,45 +48,66 @@ const ChartCard = React__namespace.forwardRef(
44
48
  children,
45
49
  ...props
46
50
  }, ref) => {
47
- return /* @__PURE__ */ jsxRuntime.jsx(Card.Card, { ref, hierarchy, noPadding: true, className, ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
48
- loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
49
- /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-4 w-32" }),
50
- /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-7 w-44" }),
51
- /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-3 w-24" })
52
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
53
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
54
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-small-14px-semibold text-content-primary", children: title }),
55
- tooltip && /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip.Tooltip, { children: [
56
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
57
- IconButton.IconButton,
58
- {
59
- variant: "tertiary",
60
- size: "32",
61
- "aria-label": tooltipAriaLabel,
62
- className: "text-content-tertiary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary",
63
- icon: /* @__PURE__ */ jsxRuntime.jsx(InfoCircleIcon.InfoCircleIcon, {})
64
- }
65
- ) }),
66
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipContent, { children: tooltip })
67
- ] }) })
68
- ] }),
69
- subtitle && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
70
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-header-heading-sm text-content-primary", children: subtitle }),
71
- trendChip && /* @__PURE__ */ jsxRuntime.jsx(
72
- "span",
73
- {
74
- className: cn.cn(
75
- "typography-description-12px-semibold whitespace-nowrap rounded-full px-2 py-0.5",
76
- TREND_CLASSES[trendChip.trend]
77
- ),
78
- children: trendChip.label
79
- }
80
- )
81
- ] }),
82
- dateInfo && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-description-12px-regular text-content-tertiary", children: dateInfo })
83
- ] }),
84
- children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto", children })
85
- ] }) });
51
+ return /* @__PURE__ */ jsxRuntime.jsx(
52
+ Card.Card,
53
+ {
54
+ ref,
55
+ hierarchy,
56
+ noPadding: true,
57
+ className: cn.cn(SURFACE_CLASSES[hierarchy], className),
58
+ ...props,
59
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
60
+ loading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
61
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-4 w-32" }),
62
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-7 w-44" }),
63
+ /* @__PURE__ */ jsxRuntime.jsx(Skeleton.Skeleton, { animation: "wave", variant: "rounded", className: "h-3 w-24" })
64
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
65
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
66
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-small-14px-regular text-content-secondary", children: title }),
67
+ tooltip && /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip.Tooltip, { children: [
68
+ /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
69
+ IconButton.IconButton,
70
+ {
71
+ variant: "tertiary",
72
+ size: "32",
73
+ "aria-label": tooltipAriaLabel,
74
+ className: "text-icons-primary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary",
75
+ icon: /* @__PURE__ */ jsxRuntime.jsx(InfoIcon.InfoIcon, { size: 16 })
76
+ }
77
+ ) }),
78
+ /* @__PURE__ */ jsxRuntime.jsx(Tooltip.TooltipContent, { children: tooltip })
79
+ ] }) })
80
+ ] }),
81
+ subtitle && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-end gap-2", children: [
82
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-header-heading-sm text-content-primary", children: subtitle }),
83
+ trendChip && /* @__PURE__ */ jsxRuntime.jsxs(
84
+ "span",
85
+ {
86
+ className: cn.cn(
87
+ "flex items-center gap-1 pb-px",
88
+ TREND_CLASSES[trendChip.trend]
89
+ ),
90
+ children: [
91
+ /* @__PURE__ */ jsxRuntime.jsx(
92
+ ArrowUpRightIcon.ArrowUpRightIcon,
93
+ {
94
+ className: cn.cn(
95
+ "size-4 shrink-0",
96
+ trendChip.trend === "negative" && "rotate-90"
97
+ )
98
+ }
99
+ ),
100
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-small-14px-regular whitespace-nowrap", children: trendChip.label })
101
+ ]
102
+ }
103
+ )
104
+ ] }),
105
+ dateInfo && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-description-12px-regular text-content-tertiary", children: dateInfo })
106
+ ] }),
107
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto", children })
108
+ ] })
109
+ }
110
+ );
86
111
  }
87
112
  );
88
113
  ChartCard.displayName = "ChartCard";
@@ -1 +1 @@
1
- {"version":3,"file":"ChartCard.cjs","sources":["../../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card, type CardHierarchy } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Surface treatment of the underlying {@link Card}. @default \"primary\" */\n hierarchy?: CardHierarchy;\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /** Trend indicator chip config. Only rendered when {@link subtitle} is also provided. */\n trendChip?: {\n /** Display label (e.g. \"12.5%\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green) or negative (red). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"bg-success-surface text-success-content\",\n negative: \"bg-error-surface text-error-content\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend chip, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * The surface treatment comes from the underlying {@link Card} and is driven by\n * the `hierarchy` prop.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card ref={ref} hierarchy={hierarchy} noPadding className={className} {...props}>\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"typography-body-small-14px-semibold text-content-primary\">\n {title}\n </span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n aria-label={tooltipAriaLabel}\n className=\"text-content-tertiary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary\"\n icon={<InfoCircleIcon />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"typography-header-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"typography-description-12px-semibold whitespace-nowrap rounded-full px-2 py-0.5\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n {trendChip.label}\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-description-12px-regular text-content-tertiary\">\n {dateInfo}\n </span>\n )}\n </>\n )}\n {children && <div className=\"mt-auto\">{children}</div>}\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":["React","jsx","Card","jsxs","Fragment","Skeleton","TooltipProvider","Tooltip","TooltipTrigger","IconButton","InfoCircleIcon","TooltipContent","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAuBO,MAAM,YAAYA,iBAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA,IAACC,KAAAA,MAAA,EAAK,KAAU,WAAsB,WAAS,MAAC,WAAuB,GAAG,OACxE,UAAAC,gCAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAA,UACCA,2BAAAA,KAAAC,qBAAA,EACE,UAAA;AAAA,QAAAH,+BAACI,SAAAA,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,uCACjEA,SAAAA,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,uCACjEA,SAAAA,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,MAAA,EAAA,CACpE,IAEAF,2BAAAA,KAAAC,WAAAA,UAAA,EACE,UAAA;AAAA,QAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAAF,2BAAAA,IAAC,QAAA,EAAK,WAAU,4DACb,UAAA,OACH;AAAA,UACC,WACCA,2BAAAA,IAACK,yBAAA,EACC,UAAAH,gCAACI,QAAAA,SAAA,EACC,UAAA;AAAA,YAAAN,2BAAAA,IAACO,QAAAA,gBAAA,EAAe,SAAO,MACrB,UAAAP,2BAAAA;AAAAA,cAACQ,WAAAA;AAAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,cAAY;AAAA,gBACZ,WAAU;AAAA,gBACV,qCAAOC,eAAAA,gBAAA,CAAA,CAAe;AAAA,cAAA;AAAA,YAAA,GAE1B;AAAA,YACAT,2BAAAA,IAACU,QAAAA,kBAAgB,UAAA,QAAA,CAAQ;AAAA,UAAA,EAAA,CAC3B,EAAA,CACF;AAAA,QAAA,GAEJ;AAAA,QACC,YACCR,2BAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,UAAAF,2BAAAA,IAAC,QAAA,EAAK,WAAU,qDACb,UAAA,UACH;AAAA,UACC,aACCA,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWW,GAAAA;AAAAA,gBACT;AAAA,gBACA,cAAc,UAAU,KAAK;AAAA,cAAA;AAAA,cAG9B,UAAA,UAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb,GAEJ;AAAA,QAED,YACCX,2BAAAA,IAAC,QAAA,EAAK,WAAU,6DACb,UAAA,SAAA,CACH;AAAA,MAAA,GAEJ;AAAA,MAED,YAAYA,2BAAAA,IAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,IAAA,EAAA,CAClD,EAAA,CACF;AAAA,EAEJ;AACF;AACA,UAAU,cAAc;;"}
1
+ {"version":3,"file":"ChartCard.cjs","sources":["../../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card, type CardHierarchy } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { ArrowUpRightIcon } from \"../Icons/ArrowUpRightIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * Surface treatment. `primary` follows the V2 Insight Card spec (white fill,\n * strong border, 12px radius); `secondary` uses the {@link Card} secondary\n * surface. @default \"primary\"\n */\n hierarchy?: CardHierarchy;\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /**\n * Trend indicator config. Rendered as a coloured directional arrow and label\n * beside the subtitle, so it is only shown when {@link subtitle} is provided.\n */\n trendChip?: {\n /** Display label (e.g. \"12.5% vs prev\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green, arrow up) or negative (red, arrow down). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"text-success-content\",\n negative: \"text-error-content\",\n};\n\nconst SURFACE_CLASSES: Partial<Record<CardHierarchy, string>> = {\n primary: \"rounded-sm border-border-strong bg-background-primary\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend indicator, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * At `hierarchy=\"primary\"` this implements the V2 Insight Card surface, which\n * differs from {@link Card}'s own primary hierarchy: a white fill, the strong\n * border, and a 12px radius.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card\n ref={ref}\n hierarchy={hierarchy}\n noPadding\n className={cn(SURFACE_CLASSES[hierarchy], className)}\n {...props}\n >\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1\">\n <span className=\"typography-body-small-14px-regular text-content-secondary\">\n {title}\n </span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n aria-label={tooltipAriaLabel}\n className=\"text-icons-primary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary\"\n icon={<InfoIcon size={16} />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex flex-wrap items-end gap-2\">\n <span className=\"typography-header-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"flex items-center gap-1 pb-px\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n <ArrowUpRightIcon\n className={cn(\n \"size-4 shrink-0\",\n trendChip.trend === \"negative\" && \"rotate-90\",\n )}\n />\n <span className=\"typography-body-small-14px-regular whitespace-nowrap\">\n {trendChip.label}\n </span>\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-description-12px-regular text-content-tertiary\">\n {dateInfo}\n </span>\n )}\n </>\n )}\n {children && <div className=\"mt-auto\">{children}</div>}\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":["React","jsx","Card","cn","jsxs","Fragment","Skeleton","TooltipProvider","Tooltip","TooltipTrigger","IconButton","InfoIcon","TooltipContent","ArrowUpRightIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAEA,MAAM,kBAA0D;AAAA,EAC9D,SAAS;AACX;AAwBO,MAAM,YAAYA,iBAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAACC,KAAAA;AAAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAS;AAAA,QACT,WAAWC,GAAAA,GAAG,gBAAgB,SAAS,GAAG,SAAS;AAAA,QAClD,GAAG;AAAA,QAEJ,UAAAC,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,UAAA,UACCA,2BAAAA,KAAAC,qBAAA,EACE,UAAA;AAAA,YAAAJ,+BAACK,SAAAA,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,2CACjEA,SAAAA,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,2CACjEA,SAAAA,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,UAAA,EAAA,CACpE,IAEAF,2BAAAA,KAAAC,WAAAA,UAAA,EACE,UAAA;AAAA,YAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAAH,2BAAAA,IAAC,QAAA,EAAK,WAAU,6DACb,UAAA,OACH;AAAA,cACC,WACCA,2BAAAA,IAACM,yBAAA,EACC,UAAAH,gCAACI,QAAAA,SAAA,EACC,UAAA;AAAA,gBAAAP,2BAAAA,IAACQ,QAAAA,gBAAA,EAAe,SAAO,MACrB,UAAAR,2BAAAA;AAAAA,kBAACS,WAAAA;AAAAA,kBAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,cAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,MAAMT,2BAAAA,IAACU,SAAAA,UAAA,EAAS,MAAM,GAAA,CAAI;AAAA,kBAAA;AAAA,gBAAA,GAE9B;AAAA,gBACAV,2BAAAA,IAACW,QAAAA,kBAAgB,UAAA,QAAA,CAAQ;AAAA,cAAA,EAAA,CAC3B,EAAA,CACF;AAAA,YAAA,GAEJ;AAAA,YACC,YACCR,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,cAAAH,2BAAAA,IAAC,QAAA,EAAK,WAAU,qDACb,UAAA,UACH;AAAA,cACC,aACCG,2BAAAA;AAAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAWD,GAAAA;AAAAA,oBACT;AAAA,oBACA,cAAc,UAAU,KAAK;AAAA,kBAAA;AAAA,kBAG/B,UAAA;AAAA,oBAAAF,2BAAAA;AAAAA,sBAACY,iBAAAA;AAAAA,sBAAA;AAAA,wBACC,WAAWV,GAAAA;AAAAA,0BACT;AAAA,0BACA,UAAU,UAAU,cAAc;AAAA,wBAAA;AAAA,sBACpC;AAAA,oBAAA;AAAA,oBAEFF,2BAAAA,IAAC,QAAA,EAAK,WAAU,wDACb,oBAAU,MAAA,CACb;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF,GAEJ;AAAA,YAED,YACCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,6DACb,UAAA,SAAA,CACH;AAAA,UAAA,GAEJ;AAAA,UAED,YAAYA,2BAAAA,IAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,QAAA,EAAA,CAClD;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACA,UAAU,cAAc;;"}
@@ -25,7 +25,8 @@ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
25
  const ASPECT_RATIO_CLASSES = {
26
26
  tall: "aspect-5/4",
27
27
  medium: "aspect-3/2",
28
- short: "aspect-9/5"
28
+ short: "aspect-9/5",
29
+ banner: "aspect-5/2"
29
30
  };
30
31
  const CreatorTile = React__namespace.forwardRef(
31
32
  ({ className, background, name, tagline, avatar, action, aspectRatio = "medium", ...props }, ref) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CreatorTile.cjs","sources":["../../../../src/components/CreatorTile/CreatorTile.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\n\n/** Width-to-height ratio preset for the tile. */\nexport type CreatorTileAspectRatio = \"tall\" | \"medium\" | \"short\";\n\nconst ASPECT_RATIO_CLASSES: Record<CreatorTileAspectRatio, string> = {\n tall: \"aspect-5/4\",\n medium: \"aspect-3/2\",\n short: \"aspect-9/5\",\n};\n\nexport interface CreatorTileProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Decorative background media rendered behind the creator content. */\n background: React.ReactNode;\n /** Creator display name shown as the prominent heading. */\n name: React.ReactNode;\n /** Optional secondary line shown under the name (e.g. handle or tagline). */\n tagline?: React.ReactNode;\n /** Avatar props forwarded to the inner {@link Avatar}. */\n avatar?: React.ComponentPropsWithoutRef<typeof Avatar>;\n /**\n * Action element rendered on the right of the profile row (e.g. a `Button`\n * for following the creator).\n */\n action?: React.ReactNode;\n /**\n * Width-to-height ratio preset.\n *\n * - `tall` – 1:2 narrow portrait\n * - `medium` – 361:200 landscape banner (default)\n * - `short` – 4:5 closer to square\n *\n * @default \"medium\"\n */\n aspectRatio?: CreatorTileAspectRatio;\n}\n\n/**\n * A visual highlight tile showcasing a creator with a full-bleed background\n * media and an overlaid profile row containing an avatar, name, optional\n * tagline and an action element.\n *\n * @example\n * ```tsx\n * <CreatorTile\n * background={<img src=\"/creator.jpg\" alt=\"\" />}\n * avatar={{ src: \"/avatar.jpg\", alt: \"Aitana Lopez\", fallback: \"AL\" }}\n * name=\"Aitana Lopez\"\n * tagline=\"@fit_aitana\"\n * action={<Button variant=\"primary\">Follow</Button>}\n * />\n * ```\n */\nexport const CreatorTile = React.forwardRef<HTMLDivElement, CreatorTileProps>(\n (\n { className, background, name, tagline, avatar, action, aspectRatio = \"medium\", ...props },\n ref,\n ) => {\n const aspectClass = ASPECT_RATIO_CLASSES[aspectRatio];\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative isolate flex w-full flex-col justify-end overflow-hidden\",\n aspectClass,\n className,\n )}\n {...props}\n >\n <div className=\"pointer-events-none absolute inset-0 select-none *:h-full *:w-full [&>img]:object-cover [&>video]:object-cover\">\n {background}\n </div>\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 rounded-b-[inherit] bg-linear-to-t from-black/60 to-transparent\" />\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 overflow-hidden rounded-b-[inherit] backdrop-blur-md [-webkit-mask-image:linear-gradient(to_top,black,transparent)] [mask-image:linear-gradient(to_top,black,transparent)]\" />\n <div className=\"relative flex items-center justify-between gap-4 p-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Avatar\n size={40}\n src={avatar?.src}\n alt={avatar?.alt ?? (typeof name === \"string\" ? name : undefined)}\n fallback={avatar?.fallback}\n {...avatar}\n />\n <div className=\"flex min-w-0 flex-col\">\n <p className=\"typography-body-default-16px-semibold m-0 truncate text-white\">\n {name}\n </p>\n {tagline ? (\n <p className=\"typography-body-small-14px-semibold m-0 truncate text-white/50\">\n {tagline}\n </p>\n ) : null}\n </div>\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </div>\n );\n },\n);\n\nCreatorTile.displayName = \"CreatorTile\";\n"],"names":["React","jsxs","cn","jsx","Avatar"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAOA,MAAM,uBAA+D;AAAA,EACnE,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AA4CO,MAAM,cAAcA,iBAAM;AAAA,EAC/B,CACE,EAAE,WAAW,YAAY,MAAM,SAAS,QAAQ,QAAQ,cAAc,UAAU,GAAG,MAAA,GACnF,QACG;AACH,UAAM,cAAc,qBAAqB,WAAW;AAEpD,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,kHACZ,UAAA,YACH;AAAA,UACAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,wHAAA,CAAwH;AAAA,UACvIA,2BAAAA,IAAC,OAAA,EAAI,WAAU,mOAAA,CAAmO;AAAA,UAClPF,2BAAAA,KAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,YAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,cAAAE,2BAAAA;AAAAA,gBAACC,OAAAA;AAAAA,gBAAA;AAAA,kBACC,MAAM;AAAA,kBACN,KAAK,QAAQ;AAAA,kBACb,KAAK,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;AAAA,kBACvD,UAAU,QAAQ;AAAA,kBACjB,GAAG;AAAA,gBAAA;AAAA,cAAA;AAAA,cAENH,2BAAAA,KAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,gBAAAE,2BAAAA,IAAC,KAAA,EAAE,WAAU,iEACV,UAAA,MACH;AAAA,gBACC,UACCA,2BAAAA,IAAC,KAAA,EAAE,WAAU,kEACV,mBACH,IACE;AAAA,cAAA,EAAA,CACN;AAAA,YAAA,GACF;AAAA,YACC,SAASA,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,kBAAO,IAAS;AAAA,UAAA,EAAA,CACvD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,YAAY,cAAc;;"}
1
+ {"version":3,"file":"CreatorTile.cjs","sources":["../../../../src/components/CreatorTile/CreatorTile.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\n\n/** Width-to-height ratio preset for the tile. */\nexport type CreatorTileAspectRatio = \"tall\" | \"medium\" | \"short\" | \"banner\";\n\nconst ASPECT_RATIO_CLASSES: Record<CreatorTileAspectRatio, string> = {\n tall: \"aspect-5/4\",\n medium: \"aspect-3/2\",\n short: \"aspect-9/5\",\n banner: \"aspect-5/2\",\n};\n\nexport interface CreatorTileProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Decorative background media rendered behind the creator content. */\n background: React.ReactNode;\n /** Creator display name shown as the prominent heading. */\n name: React.ReactNode;\n /** Optional secondary line shown under the name (e.g. handle or tagline). */\n tagline?: React.ReactNode;\n /** Avatar props forwarded to the inner {@link Avatar}. */\n avatar?: React.ComponentPropsWithoutRef<typeof Avatar>;\n /**\n * Action element rendered on the right of the profile row (e.g. a `Button`\n * for following the creator).\n */\n action?: React.ReactNode;\n /**\n * Width-to-height ratio preset.\n *\n * - `tall` – 5:4, closest to square\n * - `medium` – 3:2 landscape\n * - `short` – 9:5 landscape\n * - `banner` – 5:2, the slimmest preset\n *\n * The profile row is a fixed ~74px tall, so `banner` needs at least 185px of\n * width before the ratio makes the tile shorter than its own row and the top\n * of the row is clipped. The taller presets reach that floor at widths too\n * narrow to be practical.\n *\n * @default \"medium\"\n */\n aspectRatio?: CreatorTileAspectRatio;\n}\n\n/**\n * A visual highlight tile showcasing a creator with a full-bleed background\n * media and an overlaid profile row containing an avatar, name, optional\n * tagline and an action element.\n *\n * @example\n * ```tsx\n * <CreatorTile\n * background={<img src=\"/creator.jpg\" alt=\"\" />}\n * avatar={{ src: \"/avatar.jpg\", alt: \"Aitana Lopez\", fallback: \"AL\" }}\n * name=\"Aitana Lopez\"\n * tagline=\"@fit_aitana\"\n * action={<Button variant=\"primary\">Follow</Button>}\n * />\n * ```\n */\nexport const CreatorTile = React.forwardRef<HTMLDivElement, CreatorTileProps>(\n (\n { className, background, name, tagline, avatar, action, aspectRatio = \"medium\", ...props },\n ref,\n ) => {\n const aspectClass = ASPECT_RATIO_CLASSES[aspectRatio];\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative isolate flex w-full flex-col justify-end overflow-hidden\",\n aspectClass,\n className,\n )}\n {...props}\n >\n <div className=\"pointer-events-none absolute inset-0 select-none *:h-full *:w-full [&>img]:object-cover [&>video]:object-cover\">\n {background}\n </div>\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 rounded-b-[inherit] bg-linear-to-t from-black/60 to-transparent\" />\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 overflow-hidden rounded-b-[inherit] backdrop-blur-md [-webkit-mask-image:linear-gradient(to_top,black,transparent)] [mask-image:linear-gradient(to_top,black,transparent)]\" />\n <div className=\"relative flex items-center justify-between gap-4 p-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Avatar\n size={40}\n src={avatar?.src}\n alt={avatar?.alt ?? (typeof name === \"string\" ? name : undefined)}\n fallback={avatar?.fallback}\n {...avatar}\n />\n <div className=\"flex min-w-0 flex-col\">\n <p className=\"typography-body-default-16px-semibold m-0 truncate text-white\">\n {name}\n </p>\n {tagline ? (\n <p className=\"typography-body-small-14px-semibold m-0 truncate text-white/50\">\n {tagline}\n </p>\n ) : null}\n </div>\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </div>\n );\n },\n);\n\nCreatorTile.displayName = \"CreatorTile\";\n"],"names":["React","jsxs","cn","jsx","Avatar"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAOA,MAAM,uBAA+D;AAAA,EACnE,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAkDO,MAAM,cAAcA,iBAAM;AAAA,EAC/B,CACE,EAAE,WAAW,YAAY,MAAM,SAAS,QAAQ,QAAQ,cAAc,UAAU,GAAG,MAAA,GACnF,QACG;AACH,UAAM,cAAc,qBAAqB,WAAW;AAEpD,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,2BAAAA,IAAC,OAAA,EAAI,WAAU,kHACZ,UAAA,YACH;AAAA,UACAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,wHAAA,CAAwH;AAAA,UACvIA,2BAAAA,IAAC,OAAA,EAAI,WAAU,mOAAA,CAAmO;AAAA,UAClPF,2BAAAA,KAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,YAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,cAAAE,2BAAAA;AAAAA,gBAACC,OAAAA;AAAAA,gBAAA;AAAA,kBACC,MAAM;AAAA,kBACN,KAAK,QAAQ;AAAA,kBACb,KAAK,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;AAAA,kBACvD,UAAU,QAAQ;AAAA,kBACjB,GAAG;AAAA,gBAAA;AAAA,cAAA;AAAA,cAENH,2BAAAA,KAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,gBAAAE,2BAAAA,IAAC,KAAA,EAAE,WAAU,iEACV,UAAA,MACH;AAAA,gBACC,UACCA,2BAAAA,IAAC,KAAA,EAAE,WAAU,kEACV,mBACH,IACE;AAAA,cAAA,EAAA,CACN;AAAA,YAAA,GACF;AAAA,YACC,SAASA,2BAAAA,IAAC,OAAA,EAAI,WAAU,YAAY,kBAAO,IAAS;AAAA,UAAA,EAAA,CACvD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,YAAY,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 AIDisclosureIcon = require("../Icons/AIDisclosureIcon.cjs");
7
8
  const VerifiedIcon = require("../Icons/VerifiedIcon.cjs");
8
9
  const ProfileOnlineStatus = require("../ProfileOnlineStatus/ProfileOnlineStatus.cjs");
9
10
  function _interopNamespaceDefault(e) {
@@ -25,6 +26,8 @@ function _interopNamespaceDefault(e) {
25
26
  const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
26
27
  const UserDisplayName = React__namespace.forwardRef(
27
28
  ({
29
+ aiDisclosure,
30
+ aiDisclosureLabel = "AI creator",
28
31
  ambassador,
29
32
  ambassadorLabel = "Ambassador",
30
33
  children,
@@ -38,7 +41,7 @@ const UserDisplayName = React__namespace.forwardRef(
38
41
  ...props
39
42
  }, ref) => {
40
43
  const Component = component;
41
- const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-content-primary" } : null;
44
+ const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-current" } : null;
42
45
  return /* @__PURE__ */ jsxRuntime.jsxs(
43
46
  Component,
44
47
  {
@@ -56,6 +59,15 @@ const UserDisplayName = React__namespace.forwardRef(
56
59
  children: /* @__PURE__ */ jsxRuntime.jsx(VerifiedIcon.VerifiedIcon, { size: 16 })
57
60
  }
58
61
  ),
62
+ aiDisclosure && /* @__PURE__ */ jsxRuntime.jsx(
63
+ "span",
64
+ {
65
+ role: "img",
66
+ "aria-label": aiDisclosureLabel,
67
+ className: "ml-2 inline-flex shrink-0 items-center text-current",
68
+ children: /* @__PURE__ */ jsxRuntime.jsx(AIDisclosureIcon.AIDisclosureIcon, { size: 16 })
69
+ }
70
+ ),
59
71
  showOnlineStatus && /* @__PURE__ */ jsxRuntime.jsx(ProfileOnlineStatus.ProfileOnlineStatus, { label: onlineLabel, className: "shrink-0 ml-2" })
60
72
  ]
61
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"UserDisplayName.cjs","sources":["../../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. Its tint uses `text-success-content` (not `text-icons-brand-green`)\n * so the green darkens in light mode and lightens in dark mode, matching\n * {@link ProfileOnlineStatus}; `text-icons-brand-green` is fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-content-primary\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":["React","jsxs","cn","jsx","VerifiedIcon","ProfileOnlineStatus"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA2CO,MAAM,kBAAkBA,iBAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,2BAC9B;AAEN,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,+BAAC,UAAK,WAAWD,GAAAA,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAWD,GAAAA,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAAC,2BAAAA,IAACC,aAAAA,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,oBAAoBD,2BAAAA,IAACE,yCAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;;"}
1
+ {"version":3,"file":"UserDisplayName.cjs","sources":["../../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { AIDisclosureIcon } from \"../Icons/AIDisclosureIcon\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an AI-disclosure badge after the name, alongside any status badge. */\n aiDisclosure?: boolean;\n /** Accessible label for the AI-disclosure badge. @default \"AI creator\" */\n aiDisclosureLabel?: string;\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. `aiDisclosure` is independent of both and renders after whichever\n * status badge is shown, since it discloses how the account is operated rather\n * than ranking it.\n *\n * The verified and AI-disclosure badges inherit the name's colour, so setting a\n * colour on the root tints them with it. That keeps them legible on surfaces\n * that fix their own text colour — over a cover image, for example, where a\n * theme-dependent tint would turn black against white text in light mode.\n *\n * The ambassador tint is deliberately not inherited: it uses `text-success-content`\n * (not `text-icons-brand-green`) so the green darkens in light mode and lightens\n * in dark mode, matching {@link ProfileOnlineStatus}; `text-icons-brand-green` is\n * fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n aiDisclosure,\n aiDisclosureLabel = \"AI creator\",\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-current\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {aiDisclosure && (\n <span\n role=\"img\"\n aria-label={aiDisclosureLabel}\n className=\"ml-2 inline-flex shrink-0 items-center text-current\"\n >\n <AIDisclosureIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":["React","jsxs","cn","jsx","VerifiedIcon","AIDisclosureIcon","ProfileOnlineStatus"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0DO,MAAM,kBAAkBA,iBAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,mBAC9B;AAEN,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,+BAAC,UAAK,WAAWD,GAAAA,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAWD,GAAAA,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAAC,2BAAAA,IAACC,aAAAA,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,gBACCD,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY;AAAA,cACZ,WAAU;AAAA,cAEV,UAAAA,2BAAAA,IAACE,iBAAAA,kBAAA,EAAiB,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG/B,oBAAoBF,2BAAAA,IAACG,yCAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;;"}
@@ -39,6 +39,10 @@ const UserItem = React__namespace.forwardRef(
39
39
  showOnlineStatus,
40
40
  showHandle = true,
41
41
  showAvatar = true,
42
+ aiDisclosure = false,
43
+ aiDisclosureLabel,
44
+ verified = false,
45
+ verifiedLabel,
42
46
  className,
43
47
  ...props
44
48
  }, ref) => {
@@ -61,7 +65,17 @@ const UserItem = React__namespace.forwardRef(
61
65
  }
62
66
  ),
63
67
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden pl-2", children: [
64
- /* @__PURE__ */ jsxRuntime.jsx(UserDisplayName.UserDisplayName, { className: "typography-body-small-14px-semibold", children: user.nickname || user.displayName }),
68
+ /* @__PURE__ */ jsxRuntime.jsx(
69
+ UserDisplayName.UserDisplayName,
70
+ {
71
+ aiDisclosure,
72
+ aiDisclosureLabel,
73
+ verified,
74
+ verifiedLabel,
75
+ className: "typography-body-small-14px-semibold",
76
+ children: user.nickname || user.displayName
77
+ }
78
+ ),
65
79
  showHandle && /* @__PURE__ */ jsxRuntime.jsx(UserHandle.UserHandle, { children: user.handle })
66
80
  ] })
67
81
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"UserItem.cjs","sources":["../../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName className=\"typography-body-small-14px-semibold\">\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":["React","jsxs","cn","jsx","BellOffIcon","Avatar","getInitials","UserDisplayName","UserHandle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AAoCK,MAAM,WAAWA,iBAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACCC,2BAAAA,IAAC,SAAI,WAAU,uEACb,yCAACC,YAAAA,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACCD,2BAAAA;AAAAA,YAACE,OAAAA;AAAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAUC,YAAAA,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzDL,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAAE,+BAACI,gBAAAA,mBAAgB,WAAU,uCACxB,UAAA,KAAK,YAAY,KAAK,aACzB;AAAA,YACC,cAAcJ,2BAAAA,IAACK,WAAAA,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,cAAc;;"}
1
+ {"version":3,"file":"UserItem.cjs","sources":["../../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n /** Render an AI-disclosure badge after the display name. @default false */\n aiDisclosure?: boolean;\n /** Accessible label for the AI-disclosure badge. @default \"AI creator\" */\n aiDisclosureLabel?: string;\n /** Render a verified badge after the display name. @default false */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional verified and AI-disclosure badges and online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n aiDisclosure = false,\n aiDisclosureLabel,\n verified = false,\n verifiedLabel,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName\n aiDisclosure={aiDisclosure}\n aiDisclosureLabel={aiDisclosureLabel}\n verified={verified}\n verifiedLabel={verifiedLabel}\n className=\"typography-body-small-14px-semibold\"\n >\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":["React","jsxs","cn","jsx","BellOffIcon","Avatar","getInitials","UserDisplayName","UserHandle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AA4CK,MAAM,WAAWA,iBAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACCC,2BAAAA,IAAC,SAAI,WAAU,uEACb,yCAACC,YAAAA,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACCD,2BAAAA;AAAAA,YAACE,OAAAA;AAAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAUC,YAAAA,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzDL,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAAE,2BAAAA;AAAAA,cAACI,gBAAAA;AAAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,WAAU;AAAA,gBAET,UAAA,KAAK,YAAY,KAAK;AAAA,cAAA;AAAA,YAAA;AAAA,YAExB,cAAcJ,2BAAAA,IAACK,WAAAA,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,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 ButtonIconGroup = require("./components/ButtonIconGroup/ButtonIconGroup.cjs");
22
23
  const ButtonStack = require("./components/ButtonStack/ButtonStack.cjs");
23
24
  const Card = require("./components/Card/Card.cjs");
24
25
  const ChatInput = require("./components/ChatInput/ChatInput.cjs");
@@ -291,6 +292,7 @@ exports.BreadcrumbList = Breadcrumb.BreadcrumbList;
291
292
  exports.BreadcrumbPage = Breadcrumb.BreadcrumbPage;
292
293
  exports.BreadcrumbSeparator = Breadcrumb.BreadcrumbSeparator;
293
294
  exports.Button = Button.Button;
295
+ exports.ButtonIconGroup = ButtonIconGroup.ButtonIconGroup;
294
296
  exports.ButtonStack = ButtonStack.ButtonStack;
295
297
  exports.Card = Card.Card;
296
298
  exports.CardContent = Card.CardContent;
@@ -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,41 @@
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 ORIENTATION_AWARE_ROLES = /* @__PURE__ */ new Set([
6
+ "toolbar",
7
+ "menu",
8
+ "menubar",
9
+ "listbox",
10
+ "radiogroup",
11
+ "tablist",
12
+ "tree"
13
+ ]);
14
+ const ButtonIconGroup = React.forwardRef(
15
+ ({ className, orientation = "horizontal", role = "group", children, ...props }, ref) => {
16
+ const supportsOrientation = typeof role === "string" && ORIENTATION_AWARE_ROLES.has(role);
17
+ const orientationProps = supportsOrientation ? { "aria-orientation": orientation } : {};
18
+ return /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ ref,
22
+ role,
23
+ ...orientationProps,
24
+ "data-testid": "button-icon-group",
25
+ "data-orientation": orientation,
26
+ className: cn(
27
+ "inline-flex items-center gap-1",
28
+ orientation === "vertical" && "flex-col",
29
+ className
30
+ ),
31
+ ...props,
32
+ children
33
+ }
34
+ );
35
+ }
36
+ );
37
+ ButtonIconGroup.displayName = "ButtonIconGroup";
38
+ export {
39
+ ButtonIconGroup
40
+ };
41
+ //# sourceMappingURL=ButtonIconGroup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ButtonIconGroup.mjs","sources":["../../../src/components/ButtonIconGroup/ButtonIconGroup.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** Orientation of the icon button cluster. */\nexport type ButtonIconGroupOrientation = \"horizontal\" | \"vertical\";\n\n// Roles whose ARIA semantics include an orientation. For these we mirror the\n// visual orientation so assistive tech isn't given the spec default\n// (horizontal) when the cluster is stacked vertically.\nconst ORIENTATION_AWARE_ROLES = new Set<string>([\n \"toolbar\",\n \"menu\",\n \"menubar\",\n \"listbox\",\n \"radiogroup\",\n \"tablist\",\n \"tree\",\n]);\n\nexport interface ButtonIconGroupProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Direction the icon buttons flow in. Use `vertical` for side rails and\n * stacked media controls. @default \"horizontal\"\n */\n orientation?: ButtonIconGroupOrientation;\n /**\n * The icon buttons to cluster together. Compose {@link IconButton} elements\n * here; the group only handles layout and spacing.\n */\n children: React.ReactNode;\n}\n\n/**\n * A pre-composed cluster of {@link IconButton}s for toolbars and action rows\n * (media controls, editing tools, content action bars). Items are spaced with a\n * fixed 4px gap and stay individually rounded — this is a spaced group, not a\n * segmented/joined control.\n *\n * Exposes `role=\"group\"` by default; pass an `aria-label` or `aria-labelledby`\n * to describe the cluster for assistive technology.\n *\n * This is a presentational layout primitive: it does not implement\n * roving-tabindex / arrow-key focus management. `role` is overridable, but if\n * you set an interactive-widget role such as `role=\"toolbar\"` you own the\n * keyboard behaviour that role implies. For orientation-aware roles the\n * `aria-orientation` is synced to `orientation` automatically.\n *\n * @example\n * ```tsx\n * <ButtonIconGroup aria-label=\"Media controls\">\n * <IconButton variant=\"tertiary\" size=\"48\" icon={<PlayIcon />} aria-label=\"Play\" />\n * <IconButton variant=\"tertiary\" size=\"48\" icon={<ForwardIcon />} aria-label=\"Skip\" />\n * </ButtonIconGroup>\n * ```\n */\nexport const ButtonIconGroup = React.forwardRef<HTMLDivElement, ButtonIconGroupProps>(\n ({ className, orientation = \"horizontal\", role = \"group\", children, ...props }, ref) => {\n const supportsOrientation = typeof role === \"string\" && ORIENTATION_AWARE_ROLES.has(role);\n // Spread rather than a static attribute so the value is only present for\n // orientation-aware roles (a bare div/group role does not support it).\n const orientationProps = supportsOrientation ? { \"aria-orientation\": orientation } : {};\n return (\n <div\n ref={ref}\n role={role}\n {...orientationProps}\n data-testid=\"button-icon-group\"\n data-orientation={orientation}\n className={cn(\n \"inline-flex items-center gap-1\",\n orientation === \"vertical\" && \"flex-col\",\n className,\n )}\n {...props}\n >\n {children}\n </div>\n );\n },\n);\n\nButtonIconGroup.displayName = \"ButtonIconGroup\";\n"],"names":[],"mappings":";;;;AASA,MAAM,8CAA8B,IAAY;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAsCM,MAAM,kBAAkB,MAAM;AAAA,EACnC,CAAC,EAAE,WAAW,cAAc,cAAc,OAAO,SAAS,UAAU,GAAG,MAAA,GAAS,QAAQ;AACtF,UAAM,sBAAsB,OAAO,SAAS,YAAY,wBAAwB,IAAI,IAAI;AAGxF,UAAM,mBAAmB,sBAAsB,EAAE,oBAAoB,YAAA,IAAgB,CAAA;AACrF,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACC,GAAG;AAAA,QACJ,eAAY;AAAA,QACZ,oBAAkB;AAAA,QAClB,WAAW;AAAA,UACT;AAAA,UACA,gBAAgB,cAAc;AAAA,UAC9B;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,gBAAgB,cAAc;"}
@@ -4,12 +4,16 @@ import * as React from "react";
4
4
  import { cn } from "../../utils/cn.mjs";
5
5
  import { Card } from "../Card/Card.mjs";
6
6
  import { IconButton } from "../IconButton/IconButton.mjs";
7
- import { InfoCircleIcon } from "../Icons/InfoCircleIcon.mjs";
7
+ import { ArrowUpRightIcon } from "../Icons/ArrowUpRightIcon.mjs";
8
+ import { InfoIcon } from "../Icons/InfoIcon.mjs";
8
9
  import { Skeleton } from "../Skeleton/Skeleton.mjs";
9
10
  import { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent } from "../Tooltip/Tooltip.mjs";
10
11
  const TREND_CLASSES = {
11
- positive: "bg-success-surface text-success-content",
12
- negative: "bg-error-surface text-error-content"
12
+ positive: "text-success-content",
13
+ negative: "text-error-content"
14
+ };
15
+ const SURFACE_CLASSES = {
16
+ primary: "rounded-sm border-border-strong bg-background-primary"
13
17
  };
14
18
  const ChartCard = React.forwardRef(
15
19
  ({
@@ -25,45 +29,66 @@ const ChartCard = React.forwardRef(
25
29
  children,
26
30
  ...props
27
31
  }, ref) => {
28
- return /* @__PURE__ */ jsx(Card, { ref, hierarchy, noPadding: true, className, ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
29
- loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
30
- /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-4 w-32" }),
31
- /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-7 w-44" }),
32
- /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-3 w-24" })
33
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
34
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
35
- /* @__PURE__ */ jsx("span", { className: "typography-body-small-14px-semibold text-content-primary", children: title }),
36
- tooltip && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
37
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
38
- IconButton,
39
- {
40
- variant: "tertiary",
41
- size: "32",
42
- "aria-label": tooltipAriaLabel,
43
- className: "text-content-tertiary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary",
44
- icon: /* @__PURE__ */ jsx(InfoCircleIcon, {})
45
- }
46
- ) }),
47
- /* @__PURE__ */ jsx(TooltipContent, { children: tooltip })
48
- ] }) })
49
- ] }),
50
- subtitle && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
51
- /* @__PURE__ */ jsx("span", { className: "typography-header-heading-sm text-content-primary", children: subtitle }),
52
- trendChip && /* @__PURE__ */ jsx(
53
- "span",
54
- {
55
- className: cn(
56
- "typography-description-12px-semibold whitespace-nowrap rounded-full px-2 py-0.5",
57
- TREND_CLASSES[trendChip.trend]
58
- ),
59
- children: trendChip.label
60
- }
61
- )
62
- ] }),
63
- dateInfo && /* @__PURE__ */ jsx("span", { className: "typography-description-12px-regular text-content-tertiary", children: dateInfo })
64
- ] }),
65
- children && /* @__PURE__ */ jsx("div", { className: "mt-auto", children })
66
- ] }) });
32
+ return /* @__PURE__ */ jsx(
33
+ Card,
34
+ {
35
+ ref,
36
+ hierarchy,
37
+ noPadding: true,
38
+ className: cn(SURFACE_CLASSES[hierarchy], className),
39
+ ...props,
40
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
41
+ loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
42
+ /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-4 w-32" }),
43
+ /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-7 w-44" }),
44
+ /* @__PURE__ */ jsx(Skeleton, { animation: "wave", variant: "rounded", className: "h-3 w-24" })
45
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
46
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
47
+ /* @__PURE__ */ jsx("span", { className: "typography-body-small-14px-regular text-content-secondary", children: title }),
48
+ tooltip && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
49
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
50
+ IconButton,
51
+ {
52
+ variant: "tertiary",
53
+ size: "32",
54
+ "aria-label": tooltipAriaLabel,
55
+ className: "text-icons-primary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary",
56
+ icon: /* @__PURE__ */ jsx(InfoIcon, { size: 16 })
57
+ }
58
+ ) }),
59
+ /* @__PURE__ */ jsx(TooltipContent, { children: tooltip })
60
+ ] }) })
61
+ ] }),
62
+ subtitle && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-end gap-2", children: [
63
+ /* @__PURE__ */ jsx("span", { className: "typography-header-heading-sm text-content-primary", children: subtitle }),
64
+ trendChip && /* @__PURE__ */ jsxs(
65
+ "span",
66
+ {
67
+ className: cn(
68
+ "flex items-center gap-1 pb-px",
69
+ TREND_CLASSES[trendChip.trend]
70
+ ),
71
+ children: [
72
+ /* @__PURE__ */ jsx(
73
+ ArrowUpRightIcon,
74
+ {
75
+ className: cn(
76
+ "size-4 shrink-0",
77
+ trendChip.trend === "negative" && "rotate-90"
78
+ )
79
+ }
80
+ ),
81
+ /* @__PURE__ */ jsx("span", { className: "typography-body-small-14px-regular whitespace-nowrap", children: trendChip.label })
82
+ ]
83
+ }
84
+ )
85
+ ] }),
86
+ dateInfo && /* @__PURE__ */ jsx("span", { className: "typography-description-12px-regular text-content-tertiary", children: dateInfo })
87
+ ] }),
88
+ children && /* @__PURE__ */ jsx("div", { className: "mt-auto", children })
89
+ ] })
90
+ }
91
+ );
67
92
  }
68
93
  );
69
94
  ChartCard.displayName = "ChartCard";
@@ -1 +1 @@
1
- {"version":3,"file":"ChartCard.mjs","sources":["../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card, type CardHierarchy } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { InfoCircleIcon } from \"../Icons/InfoCircleIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Surface treatment of the underlying {@link Card}. @default \"primary\" */\n hierarchy?: CardHierarchy;\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /** Trend indicator chip config. Only rendered when {@link subtitle} is also provided. */\n trendChip?: {\n /** Display label (e.g. \"12.5%\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green) or negative (red). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"bg-success-surface text-success-content\",\n negative: \"bg-error-surface text-error-content\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend chip, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * The surface treatment comes from the underlying {@link Card} and is driven by\n * the `hierarchy` prop.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card ref={ref} hierarchy={hierarchy} noPadding className={className} {...props}>\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1.5\">\n <span className=\"typography-body-small-14px-semibold text-content-primary\">\n {title}\n </span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n aria-label={tooltipAriaLabel}\n className=\"text-content-tertiary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary\"\n icon={<InfoCircleIcon />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"typography-header-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"typography-description-12px-semibold whitespace-nowrap rounded-full px-2 py-0.5\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n {trendChip.label}\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-description-12px-regular text-content-tertiary\">\n {dateInfo}\n </span>\n )}\n </>\n )}\n {children && <div className=\"mt-auto\">{children}</div>}\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":[],"mappings":";;;;;;;;;AAmCA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAuBO,MAAM,YAAY,MAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE,oBAAC,MAAA,EAAK,KAAU,WAAsB,WAAS,MAAC,WAAuB,GAAG,OACxE,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAA,UACC,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,oBAAC,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,4BACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,MAAA,EAAA,CACpE,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,6BACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,4DACb,UAAA,OACH;AAAA,UACC,WACC,oBAAC,iBAAA,EACC,UAAA,qBAAC,SAAA,EACC,UAAA;AAAA,YAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,cAAY;AAAA,gBACZ,WAAU;AAAA,gBACV,0BAAO,gBAAA,CAAA,CAAe;AAAA,cAAA;AAAA,YAAA,GAE1B;AAAA,YACA,oBAAC,kBAAgB,UAAA,QAAA,CAAQ;AAAA,UAAA,EAAA,CAC3B,EAAA,CACF;AAAA,QAAA,GAEJ;AAAA,QACC,YACC,qBAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,qDACb,UAAA,UACH;AAAA,UACC,aACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA,cAAc,UAAU,KAAK;AAAA,cAAA;AAAA,cAG9B,UAAA,UAAU;AAAA,YAAA;AAAA,UAAA;AAAA,QACb,GAEJ;AAAA,QAED,YACC,oBAAC,QAAA,EAAK,WAAU,6DACb,UAAA,SAAA,CACH;AAAA,MAAA,GAEJ;AAAA,MAED,YAAY,oBAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,IAAA,EAAA,CAClD,EAAA,CACF;AAAA,EAEJ;AACF;AACA,UAAU,cAAc;"}
1
+ {"version":3,"file":"ChartCard.mjs","sources":["../../../src/components/Chart/ChartCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Card, type CardHierarchy } from \"../Card/Card\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { ArrowUpRightIcon } from \"../Icons/ArrowUpRightIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { Skeleton } from \"../Skeleton/Skeleton\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"../Tooltip/Tooltip\";\n\n/** Props for {@link ChartCard}. */\nexport interface ChartCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * Surface treatment. `primary` follows the V2 Insight Card spec (white fill,\n * strong border, 12px radius); `secondary` uses the {@link Card} secondary\n * surface. @default \"primary\"\n */\n hierarchy?: CardHierarchy;\n /** Card title text. Pass translated string for i18n. */\n title: React.ReactNode;\n /** Large subtitle value (e.g. formatted price or count). */\n subtitle?: React.ReactNode;\n /** Tooltip text shown next to the title. Pass translated string for i18n. */\n tooltip?: React.ReactNode;\n /** Accessible label for the info tooltip trigger. Override for i18n. @default \"More info\" */\n tooltipAriaLabel?: string;\n /** Date range or period label shown below the subtitle. */\n dateInfo?: React.ReactNode;\n /**\n * Trend indicator config. Rendered as a coloured directional arrow and label\n * beside the subtitle, so it is only shown when {@link subtitle} is provided.\n */\n trendChip?: {\n /** Display label (e.g. \"12.5% vs prev\"). */\n label: React.ReactNode;\n /** Whether the trend is positive (green, arrow up) or negative (red, arrow down). */\n trend: \"positive\" | \"negative\";\n };\n /** Show loading skeleton instead of content. @default false */\n loading?: boolean;\n /** Chart content rendered below the header. */\n children?: React.ReactNode;\n}\n\nconst TREND_CLASSES: Record<\"positive\" | \"negative\", string> = {\n positive: \"text-success-content\",\n negative: \"text-error-content\",\n};\n\nconst SURFACE_CLASSES: Partial<Record<CardHierarchy, string>> = {\n primary: \"rounded-sm border-border-strong bg-background-primary\",\n};\n\n/**\n * Wraps any chart with a structured header containing title, subtitle,\n * optional trend indicator, date range label, info tooltip, and a loading\n * skeleton state.\n *\n * At `hierarchy=\"primary\"` this implements the V2 Insight Card surface, which\n * differs from {@link Card}'s own primary hierarchy: a white fill, the strong\n * border, and a 12px radius.\n *\n * @example\n * ```tsx\n * <ChartCard\n * title=\"Revenue\"\n * subtitle=\"$4,523\"\n * trendChip={{ label: \"+12.5%\", trend: \"positive\" }}\n * dateInfo=\"Jan 1 – Mar 17\"\n * tooltip=\"Total revenue for the selected period.\"\n * >\n * <MyLineChart />\n * </ChartCard>\n * ```\n */\nexport const ChartCard = React.forwardRef<HTMLDivElement, ChartCardProps>(\n (\n {\n className,\n hierarchy = \"primary\",\n title,\n subtitle,\n tooltip,\n tooltipAriaLabel = \"More info\",\n dateInfo,\n trendChip,\n loading = false,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <Card\n ref={ref}\n hierarchy={hierarchy}\n noPadding\n className={cn(SURFACE_CLASSES[hierarchy], className)}\n {...props}\n >\n <div className=\"flex flex-col gap-2 p-4\">\n {loading ? (\n <>\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-4 w-32\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-7 w-44\" />\n <Skeleton animation=\"wave\" variant=\"rounded\" className=\"h-3 w-24\" />\n </>\n ) : (\n <>\n <div className=\"flex items-center gap-1\">\n <span className=\"typography-body-small-14px-regular text-content-secondary\">\n {title}\n </span>\n {tooltip && (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <IconButton\n variant=\"tertiary\"\n size=\"32\"\n aria-label={tooltipAriaLabel}\n className=\"text-icons-primary hover:text-content-primary focus-visible:text-content-primary active:text-content-primary\"\n icon={<InfoIcon size={16} />}\n />\n </TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )}\n </div>\n {subtitle && (\n <div className=\"flex flex-wrap items-end gap-2\">\n <span className=\"typography-header-heading-sm text-content-primary\">\n {subtitle}\n </span>\n {trendChip && (\n <span\n className={cn(\n \"flex items-center gap-1 pb-px\",\n TREND_CLASSES[trendChip.trend],\n )}\n >\n <ArrowUpRightIcon\n className={cn(\n \"size-4 shrink-0\",\n trendChip.trend === \"negative\" && \"rotate-90\",\n )}\n />\n <span className=\"typography-body-small-14px-regular whitespace-nowrap\">\n {trendChip.label}\n </span>\n </span>\n )}\n </div>\n )}\n {dateInfo && (\n <span className=\"typography-description-12px-regular text-content-tertiary\">\n {dateInfo}\n </span>\n )}\n </>\n )}\n {children && <div className=\"mt-auto\">{children}</div>}\n </div>\n </Card>\n );\n },\n);\nChartCard.displayName = \"ChartCard\";\n"],"names":[],"mappings":";;;;;;;;;;AA2CA,MAAM,gBAAyD;AAAA,EAC7D,UAAU;AAAA,EACV,UAAU;AACZ;AAEA,MAAM,kBAA0D;AAAA,EAC9D,SAAS;AACX;AAwBO,MAAM,YAAY,MAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,WAAS;AAAA,QACT,WAAW,GAAG,gBAAgB,SAAS,GAAG,SAAS;AAAA,QAClD,GAAG;AAAA,QAEJ,UAAA,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,UAAA,UACC,qBAAA,UAAA,EACE,UAAA;AAAA,YAAA,oBAAC,YAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,gCACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,YAAW;AAAA,gCACjE,UAAA,EAAS,WAAU,QAAO,SAAQ,WAAU,WAAU,WAAA,CAAW;AAAA,UAAA,EAAA,CACpE,IAEA,qBAAA,UAAA,EACE,UAAA;AAAA,YAAA,qBAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,WAAU,6DACb,UAAA,OACH;AAAA,cACC,WACC,oBAAC,iBAAA,EACC,UAAA,qBAAC,SAAA,EACC,UAAA;AAAA,gBAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAQ;AAAA,oBACR,MAAK;AAAA,oBACL,cAAY;AAAA,oBACZ,WAAU;AAAA,oBACV,MAAM,oBAAC,UAAA,EAAS,MAAM,GAAA,CAAI;AAAA,kBAAA;AAAA,gBAAA,GAE9B;AAAA,gBACA,oBAAC,kBAAgB,UAAA,QAAA,CAAQ;AAAA,cAAA,EAAA,CAC3B,EAAA,CACF;AAAA,YAAA,GAEJ;AAAA,YACC,YACC,qBAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAK,WAAU,qDACb,UAAA,UACH;AAAA,cACC,aACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAW;AAAA,oBACT;AAAA,oBACA,cAAc,UAAU,KAAK;AAAA,kBAAA;AAAA,kBAG/B,UAAA;AAAA,oBAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,WAAW;AAAA,0BACT;AAAA,0BACA,UAAU,UAAU,cAAc;AAAA,wBAAA;AAAA,sBACpC;AAAA,oBAAA;AAAA,oBAEF,oBAAC,QAAA,EAAK,WAAU,wDACb,oBAAU,MAAA,CACb;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF,GAEJ;AAAA,YAED,YACC,oBAAC,QAAA,EAAK,WAAU,6DACb,UAAA,SAAA,CACH;AAAA,UAAA,GAEJ;AAAA,UAED,YAAY,oBAAC,OAAA,EAAI,WAAU,WAAW,SAAA,CAAS;AAAA,QAAA,EAAA,CAClD;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACA,UAAU,cAAc;"}
@@ -6,7 +6,8 @@ import { Avatar } from "../Avatar/Avatar.mjs";
6
6
  const ASPECT_RATIO_CLASSES = {
7
7
  tall: "aspect-5/4",
8
8
  medium: "aspect-3/2",
9
- short: "aspect-9/5"
9
+ short: "aspect-9/5",
10
+ banner: "aspect-5/2"
10
11
  };
11
12
  const CreatorTile = React.forwardRef(
12
13
  ({ className, background, name, tagline, avatar, action, aspectRatio = "medium", ...props }, ref) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CreatorTile.mjs","sources":["../../../src/components/CreatorTile/CreatorTile.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\n\n/** Width-to-height ratio preset for the tile. */\nexport type CreatorTileAspectRatio = \"tall\" | \"medium\" | \"short\";\n\nconst ASPECT_RATIO_CLASSES: Record<CreatorTileAspectRatio, string> = {\n tall: \"aspect-5/4\",\n medium: \"aspect-3/2\",\n short: \"aspect-9/5\",\n};\n\nexport interface CreatorTileProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Decorative background media rendered behind the creator content. */\n background: React.ReactNode;\n /** Creator display name shown as the prominent heading. */\n name: React.ReactNode;\n /** Optional secondary line shown under the name (e.g. handle or tagline). */\n tagline?: React.ReactNode;\n /** Avatar props forwarded to the inner {@link Avatar}. */\n avatar?: React.ComponentPropsWithoutRef<typeof Avatar>;\n /**\n * Action element rendered on the right of the profile row (e.g. a `Button`\n * for following the creator).\n */\n action?: React.ReactNode;\n /**\n * Width-to-height ratio preset.\n *\n * - `tall` – 1:2 narrow portrait\n * - `medium` – 361:200 landscape banner (default)\n * - `short` – 4:5 closer to square\n *\n * @default \"medium\"\n */\n aspectRatio?: CreatorTileAspectRatio;\n}\n\n/**\n * A visual highlight tile showcasing a creator with a full-bleed background\n * media and an overlaid profile row containing an avatar, name, optional\n * tagline and an action element.\n *\n * @example\n * ```tsx\n * <CreatorTile\n * background={<img src=\"/creator.jpg\" alt=\"\" />}\n * avatar={{ src: \"/avatar.jpg\", alt: \"Aitana Lopez\", fallback: \"AL\" }}\n * name=\"Aitana Lopez\"\n * tagline=\"@fit_aitana\"\n * action={<Button variant=\"primary\">Follow</Button>}\n * />\n * ```\n */\nexport const CreatorTile = React.forwardRef<HTMLDivElement, CreatorTileProps>(\n (\n { className, background, name, tagline, avatar, action, aspectRatio = \"medium\", ...props },\n ref,\n ) => {\n const aspectClass = ASPECT_RATIO_CLASSES[aspectRatio];\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative isolate flex w-full flex-col justify-end overflow-hidden\",\n aspectClass,\n className,\n )}\n {...props}\n >\n <div className=\"pointer-events-none absolute inset-0 select-none *:h-full *:w-full [&>img]:object-cover [&>video]:object-cover\">\n {background}\n </div>\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 rounded-b-[inherit] bg-linear-to-t from-black/60 to-transparent\" />\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 overflow-hidden rounded-b-[inherit] backdrop-blur-md [-webkit-mask-image:linear-gradient(to_top,black,transparent)] [mask-image:linear-gradient(to_top,black,transparent)]\" />\n <div className=\"relative flex items-center justify-between gap-4 p-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Avatar\n size={40}\n src={avatar?.src}\n alt={avatar?.alt ?? (typeof name === \"string\" ? name : undefined)}\n fallback={avatar?.fallback}\n {...avatar}\n />\n <div className=\"flex min-w-0 flex-col\">\n <p className=\"typography-body-default-16px-semibold m-0 truncate text-white\">\n {name}\n </p>\n {tagline ? (\n <p className=\"typography-body-small-14px-semibold m-0 truncate text-white/50\">\n {tagline}\n </p>\n ) : null}\n </div>\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </div>\n );\n },\n);\n\nCreatorTile.displayName = \"CreatorTile\";\n"],"names":[],"mappings":";;;;;AAOA,MAAM,uBAA+D;AAAA,EACnE,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AA4CO,MAAM,cAAc,MAAM;AAAA,EAC/B,CACE,EAAE,WAAW,YAAY,MAAM,SAAS,QAAQ,QAAQ,cAAc,UAAU,GAAG,MAAA,GACnF,QACG;AACH,UAAM,cAAc,qBAAqB,WAAW;AAEpD,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,kHACZ,UAAA,YACH;AAAA,UACA,oBAAC,OAAA,EAAI,WAAU,wHAAA,CAAwH;AAAA,UACvI,oBAAC,OAAA,EAAI,WAAU,mOAAA,CAAmO;AAAA,UAClP,qBAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,YAAA,qBAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAM;AAAA,kBACN,KAAK,QAAQ;AAAA,kBACb,KAAK,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;AAAA,kBACvD,UAAU,QAAQ;AAAA,kBACjB,GAAG;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEN,qBAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,gBAAA,oBAAC,KAAA,EAAE,WAAU,iEACV,UAAA,MACH;AAAA,gBACC,UACC,oBAAC,KAAA,EAAE,WAAU,kEACV,mBACH,IACE;AAAA,cAAA,EAAA,CACN;AAAA,YAAA,GACF;AAAA,YACC,SAAS,oBAAC,OAAA,EAAI,WAAU,YAAY,kBAAO,IAAS;AAAA,UAAA,EAAA,CACvD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,YAAY,cAAc;"}
1
+ {"version":3,"file":"CreatorTile.mjs","sources":["../../../src/components/CreatorTile/CreatorTile.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\n\n/** Width-to-height ratio preset for the tile. */\nexport type CreatorTileAspectRatio = \"tall\" | \"medium\" | \"short\" | \"banner\";\n\nconst ASPECT_RATIO_CLASSES: Record<CreatorTileAspectRatio, string> = {\n tall: \"aspect-5/4\",\n medium: \"aspect-3/2\",\n short: \"aspect-9/5\",\n banner: \"aspect-5/2\",\n};\n\nexport interface CreatorTileProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Decorative background media rendered behind the creator content. */\n background: React.ReactNode;\n /** Creator display name shown as the prominent heading. */\n name: React.ReactNode;\n /** Optional secondary line shown under the name (e.g. handle or tagline). */\n tagline?: React.ReactNode;\n /** Avatar props forwarded to the inner {@link Avatar}. */\n avatar?: React.ComponentPropsWithoutRef<typeof Avatar>;\n /**\n * Action element rendered on the right of the profile row (e.g. a `Button`\n * for following the creator).\n */\n action?: React.ReactNode;\n /**\n * Width-to-height ratio preset.\n *\n * - `tall` – 5:4, closest to square\n * - `medium` – 3:2 landscape\n * - `short` – 9:5 landscape\n * - `banner` – 5:2, the slimmest preset\n *\n * The profile row is a fixed ~74px tall, so `banner` needs at least 185px of\n * width before the ratio makes the tile shorter than its own row and the top\n * of the row is clipped. The taller presets reach that floor at widths too\n * narrow to be practical.\n *\n * @default \"medium\"\n */\n aspectRatio?: CreatorTileAspectRatio;\n}\n\n/**\n * A visual highlight tile showcasing a creator with a full-bleed background\n * media and an overlaid profile row containing an avatar, name, optional\n * tagline and an action element.\n *\n * @example\n * ```tsx\n * <CreatorTile\n * background={<img src=\"/creator.jpg\" alt=\"\" />}\n * avatar={{ src: \"/avatar.jpg\", alt: \"Aitana Lopez\", fallback: \"AL\" }}\n * name=\"Aitana Lopez\"\n * tagline=\"@fit_aitana\"\n * action={<Button variant=\"primary\">Follow</Button>}\n * />\n * ```\n */\nexport const CreatorTile = React.forwardRef<HTMLDivElement, CreatorTileProps>(\n (\n { className, background, name, tagline, avatar, action, aspectRatio = \"medium\", ...props },\n ref,\n ) => {\n const aspectClass = ASPECT_RATIO_CLASSES[aspectRatio];\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative isolate flex w-full flex-col justify-end overflow-hidden\",\n aspectClass,\n className,\n )}\n {...props}\n >\n <div className=\"pointer-events-none absolute inset-0 select-none *:h-full *:w-full [&>img]:object-cover [&>video]:object-cover\">\n {background}\n </div>\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 rounded-b-[inherit] bg-linear-to-t from-black/60 to-transparent\" />\n <div className=\"pointer-events-none absolute inset-x-0 bottom-0 h-1/2 overflow-hidden rounded-b-[inherit] backdrop-blur-md [-webkit-mask-image:linear-gradient(to_top,black,transparent)] [mask-image:linear-gradient(to_top,black,transparent)]\" />\n <div className=\"relative flex items-center justify-between gap-4 p-4\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <Avatar\n size={40}\n src={avatar?.src}\n alt={avatar?.alt ?? (typeof name === \"string\" ? name : undefined)}\n fallback={avatar?.fallback}\n {...avatar}\n />\n <div className=\"flex min-w-0 flex-col\">\n <p className=\"typography-body-default-16px-semibold m-0 truncate text-white\">\n {name}\n </p>\n {tagline ? (\n <p className=\"typography-body-small-14px-semibold m-0 truncate text-white/50\">\n {tagline}\n </p>\n ) : null}\n </div>\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </div>\n );\n },\n);\n\nCreatorTile.displayName = \"CreatorTile\";\n"],"names":[],"mappings":";;;;;AAOA,MAAM,uBAA+D;AAAA,EACnE,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AACV;AAkDO,MAAM,cAAc,MAAM;AAAA,EAC/B,CACE,EAAE,WAAW,YAAY,MAAM,SAAS,QAAQ,QAAQ,cAAc,UAAU,GAAG,MAAA,GACnF,QACG;AACH,UAAM,cAAc,qBAAqB,WAAW;AAEpD,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,oBAAC,OAAA,EAAI,WAAU,kHACZ,UAAA,YACH;AAAA,UACA,oBAAC,OAAA,EAAI,WAAU,wHAAA,CAAwH;AAAA,UACvI,oBAAC,OAAA,EAAI,WAAU,mOAAA,CAAmO;AAAA,UAClP,qBAAC,OAAA,EAAI,WAAU,wDACb,UAAA;AAAA,YAAA,qBAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,cAAA;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAM;AAAA,kBACN,KAAK,QAAQ;AAAA,kBACb,KAAK,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;AAAA,kBACvD,UAAU,QAAQ;AAAA,kBACjB,GAAG;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEN,qBAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,gBAAA,oBAAC,KAAA,EAAE,WAAU,iEACV,UAAA,MACH;AAAA,gBACC,UACC,oBAAC,KAAA,EAAE,WAAU,kEACV,mBACH,IACE;AAAA,cAAA,EAAA,CACN;AAAA,YAAA,GACF;AAAA,YACC,SAAS,oBAAC,OAAA,EAAI,WAAU,YAAY,kBAAO,IAAS;AAAA,UAAA,EAAA,CACvD;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,YAAY,cAAc;"}
@@ -2,10 +2,13 @@
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cn } from "../../utils/cn.mjs";
5
+ import { AIDisclosureIcon } from "../Icons/AIDisclosureIcon.mjs";
5
6
  import { VerifiedIcon } from "../Icons/VerifiedIcon.mjs";
6
7
  import { ProfileOnlineStatus } from "../ProfileOnlineStatus/ProfileOnlineStatus.mjs";
7
8
  const UserDisplayName = React.forwardRef(
8
9
  ({
10
+ aiDisclosure,
11
+ aiDisclosureLabel = "AI creator",
9
12
  ambassador,
10
13
  ambassadorLabel = "Ambassador",
11
14
  children,
@@ -19,7 +22,7 @@ const UserDisplayName = React.forwardRef(
19
22
  ...props
20
23
  }, ref) => {
21
24
  const Component = component;
22
- const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-content-primary" } : null;
25
+ const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-current" } : null;
23
26
  return /* @__PURE__ */ jsxs(
24
27
  Component,
25
28
  {
@@ -37,6 +40,15 @@ const UserDisplayName = React.forwardRef(
37
40
  children: /* @__PURE__ */ jsx(VerifiedIcon, { size: 16 })
38
41
  }
39
42
  ),
43
+ aiDisclosure && /* @__PURE__ */ jsx(
44
+ "span",
45
+ {
46
+ role: "img",
47
+ "aria-label": aiDisclosureLabel,
48
+ className: "ml-2 inline-flex shrink-0 items-center text-current",
49
+ children: /* @__PURE__ */ jsx(AIDisclosureIcon, { size: 16 })
50
+ }
51
+ ),
40
52
  showOnlineStatus && /* @__PURE__ */ jsx(ProfileOnlineStatus, { label: onlineLabel, className: "shrink-0 ml-2" })
41
53
  ]
42
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"UserDisplayName.mjs","sources":["../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. Its tint uses `text-success-content` (not `text-icons-brand-green`)\n * so the green darkens in light mode and lightens in dark mode, matching\n * {@link ProfileOnlineStatus}; `text-icons-brand-green` is fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-content-primary\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":[],"mappings":";;;;;;AA2CO,MAAM,kBAAkB,MAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,2BAC9B;AAEN,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,oBAAC,UAAK,WAAW,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAW,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAA,oBAAC,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,oBAAoB,oBAAC,qBAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;"}
1
+ {"version":3,"file":"UserDisplayName.mjs","sources":["../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { AIDisclosureIcon } from \"../Icons/AIDisclosureIcon\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an AI-disclosure badge after the name, alongside any status badge. */\n aiDisclosure?: boolean;\n /** Accessible label for the AI-disclosure badge. @default \"AI creator\" */\n aiDisclosureLabel?: string;\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. `aiDisclosure` is independent of both and renders after whichever\n * status badge is shown, since it discloses how the account is operated rather\n * than ranking it.\n *\n * The verified and AI-disclosure badges inherit the name's colour, so setting a\n * colour on the root tints them with it. That keeps them legible on surfaces\n * that fix their own text colour — over a cover image, for example, where a\n * theme-dependent tint would turn black against white text in light mode.\n *\n * The ambassador tint is deliberately not inherited: it uses `text-success-content`\n * (not `text-icons-brand-green`) so the green darkens in light mode and lightens\n * in dark mode, matching {@link ProfileOnlineStatus}; `text-icons-brand-green` is\n * fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n aiDisclosure,\n aiDisclosureLabel = \"AI creator\",\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-current\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {aiDisclosure && (\n <span\n role=\"img\"\n aria-label={aiDisclosureLabel}\n className=\"ml-2 inline-flex shrink-0 items-center text-current\"\n >\n <AIDisclosureIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":[],"mappings":";;;;;;;AA0DO,MAAM,kBAAkB,MAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,oBAAoB;AAAA,IACpB;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,mBAC9B;AAEN,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAA,oBAAC,UAAK,WAAW,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAW,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAA,oBAAC,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,gBACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY;AAAA,cACZ,WAAU;AAAA,cAEV,UAAA,oBAAC,kBAAA,EAAiB,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG/B,oBAAoB,oBAAC,qBAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;"}
@@ -20,6 +20,10 @@ const UserItem = React.forwardRef(
20
20
  showOnlineStatus,
21
21
  showHandle = true,
22
22
  showAvatar = true,
23
+ aiDisclosure = false,
24
+ aiDisclosureLabel,
25
+ verified = false,
26
+ verifiedLabel,
23
27
  className,
24
28
  ...props
25
29
  }, ref) => {
@@ -42,7 +46,17 @@ const UserItem = React.forwardRef(
42
46
  }
43
47
  ),
44
48
  /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-hidden pl-2", children: [
45
- /* @__PURE__ */ jsx(UserDisplayName, { className: "typography-body-small-14px-semibold", children: user.nickname || user.displayName }),
49
+ /* @__PURE__ */ jsx(
50
+ UserDisplayName,
51
+ {
52
+ aiDisclosure,
53
+ aiDisclosureLabel,
54
+ verified,
55
+ verifiedLabel,
56
+ className: "typography-body-small-14px-semibold",
57
+ children: user.nickname || user.displayName
58
+ }
59
+ ),
46
60
  showHandle && /* @__PURE__ */ jsx(UserHandle, { children: user.handle })
47
61
  ] })
48
62
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"UserItem.mjs","sources":["../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName className=\"typography-body-small-14px-semibold\">\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":[],"mappings":";;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AAoCK,MAAM,WAAW,MAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACC,oBAAC,SAAI,WAAU,uEACb,8BAAC,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAU,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzD,qBAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAA,oBAAC,mBAAgB,WAAU,uCACxB,UAAA,KAAK,YAAY,KAAK,aACzB;AAAA,YACC,cAAc,oBAAC,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,cAAc;"}
1
+ {"version":3,"file":"UserItem.mjs","sources":["../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n /** Render an AI-disclosure badge after the display name. @default false */\n aiDisclosure?: boolean;\n /** Accessible label for the AI-disclosure badge. @default \"AI creator\" */\n aiDisclosureLabel?: string;\n /** Render a verified badge after the display name. @default false */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional verified and AI-disclosure badges and online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n aiDisclosure = false,\n aiDisclosureLabel,\n verified = false,\n verifiedLabel,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName\n aiDisclosure={aiDisclosure}\n aiDisclosureLabel={aiDisclosureLabel}\n verified={verified}\n verifiedLabel={verifiedLabel}\n className=\"typography-body-small-14px-semibold\"\n >\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":[],"mappings":";;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AA4CK,MAAM,WAAW,MAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACC,oBAAC,SAAI,WAAU,uEACb,8BAAC,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAU,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzD,qBAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,WAAU;AAAA,gBAET,UAAA,KAAK,YAAY,KAAK;AAAA,cAAA;AAAA,YAAA;AAAA,YAExB,cAAc,oBAAC,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,cAAc;"}
package/dist/index.d.ts CHANGED
@@ -966,6 +966,47 @@ export declare type BulbIconProps = BaseIconProps;
966
966
  */
967
967
  export declare const Button: React_2.ForwardRefExoticComponent<ButtonProps & React_2.RefAttributes<HTMLButtonElement>>;
968
968
 
969
+ /**
970
+ * A pre-composed cluster of {@link IconButton}s for toolbars and action rows
971
+ * (media controls, editing tools, content action bars). Items are spaced with a
972
+ * fixed 4px gap and stay individually rounded — this is a spaced group, not a
973
+ * segmented/joined control.
974
+ *
975
+ * Exposes `role="group"` by default; pass an `aria-label` or `aria-labelledby`
976
+ * to describe the cluster for assistive technology.
977
+ *
978
+ * This is a presentational layout primitive: it does not implement
979
+ * roving-tabindex / arrow-key focus management. `role` is overridable, but if
980
+ * you set an interactive-widget role such as `role="toolbar"` you own the
981
+ * keyboard behaviour that role implies. For orientation-aware roles the
982
+ * `aria-orientation` is synced to `orientation` automatically.
983
+ *
984
+ * @example
985
+ * ```tsx
986
+ * <ButtonIconGroup aria-label="Media controls">
987
+ * <IconButton variant="tertiary" size="48" icon={<PlayIcon />} aria-label="Play" />
988
+ * <IconButton variant="tertiary" size="48" icon={<ForwardIcon />} aria-label="Skip" />
989
+ * </ButtonIconGroup>
990
+ * ```
991
+ */
992
+ export declare const ButtonIconGroup: React_2.ForwardRefExoticComponent<ButtonIconGroupProps & React_2.RefAttributes<HTMLDivElement>>;
993
+
994
+ /** Orientation of the icon button cluster. */
995
+ export declare type ButtonIconGroupOrientation = "horizontal" | "vertical";
996
+
997
+ export declare interface ButtonIconGroupProps extends React_2.HTMLAttributes<HTMLDivElement> {
998
+ /**
999
+ * Direction the icon buttons flow in. Use `vertical` for side rails and
1000
+ * stacked media controls. @default "horizontal"
1001
+ */
1002
+ orientation?: ButtonIconGroupOrientation;
1003
+ /**
1004
+ * The icon buttons to cluster together. Compose {@link IconButton} elements
1005
+ * here; the group only handles layout and spacing.
1006
+ */
1007
+ children: React_2.ReactNode;
1008
+ }
1009
+
969
1010
  export declare interface ButtonProps extends React_2.ButtonHTMLAttributes<HTMLButtonElement> {
970
1011
  /** Visual style variant of the button. @default "primary" */
971
1012
  variant?: ButtonVariant;
@@ -1850,7 +1891,7 @@ export declare type CreatorCoverSlot = string | React_2.ReactNode;
1850
1891
  export declare const CreatorTile: React_2.ForwardRefExoticComponent<CreatorTileProps & React_2.RefAttributes<HTMLDivElement>>;
1851
1892
 
1852
1893
  /** Width-to-height ratio preset for the tile. */
1853
- export declare type CreatorTileAspectRatio = "tall" | "medium" | "short";
1894
+ export declare type CreatorTileAspectRatio = "tall" | "medium" | "short" | "banner";
1854
1895
 
1855
1896
  export declare interface CreatorTileProps extends React_2.HTMLAttributes<HTMLDivElement> {
1856
1897
  /** Decorative background media rendered behind the creator content. */
@@ -1869,9 +1910,15 @@ export declare interface CreatorTileProps extends React_2.HTMLAttributes<HTMLDiv
1869
1910
  /**
1870
1911
  * Width-to-height ratio preset.
1871
1912
  *
1872
- * - `tall` – 1:2 narrow portrait
1873
- * - `medium` – 361:200 landscape banner (default)
1874
- * - `short` – 4:5 closer to square
1913
+ * - `tall` – 5:4, closest to square
1914
+ * - `medium` – 3:2 landscape
1915
+ * - `short` – 9:5 landscape
1916
+ * - `banner` – 5:2, the slimmest preset
1917
+ *
1918
+ * The profile row is a fixed ~74px tall, so `banner` needs at least 185px of
1919
+ * width before the ratio makes the tile shorter than its own row and the top
1920
+ * of the row is clipped. The taller presets reach that floor at widths too
1921
+ * narrow to be practical.
1875
1922
  *
1876
1923
  * @default "medium"
1877
1924
  */
@@ -6085,9 +6132,19 @@ export declare const UserCircleIcon: React_2.ForwardRefExoticComponent<React_2.S
6085
6132
  * for the standard display-name scale.
6086
6133
  *
6087
6134
  * When both `ambassador` and `verified` are set, the ambassador badge takes
6088
- * precedence. Its tint uses `text-success-content` (not `text-icons-brand-green`)
6089
- * so the green darkens in light mode and lightens in dark mode, matching
6090
- * {@link ProfileOnlineStatus}; `text-icons-brand-green` is fixed across modes.
6135
+ * precedence. `aiDisclosure` is independent of both and renders after whichever
6136
+ * status badge is shown, since it discloses how the account is operated rather
6137
+ * than ranking it.
6138
+ *
6139
+ * The verified and AI-disclosure badges inherit the name's colour, so setting a
6140
+ * colour on the root tints them with it. That keeps them legible on surfaces
6141
+ * that fix their own text colour — over a cover image, for example, where a
6142
+ * theme-dependent tint would turn black against white text in light mode.
6143
+ *
6144
+ * The ambassador tint is deliberately not inherited: it uses `text-success-content`
6145
+ * (not `text-icons-brand-green`) so the green darkens in light mode and lightens
6146
+ * in dark mode, matching {@link ProfileOnlineStatus}; `text-icons-brand-green` is
6147
+ * fixed across modes.
6091
6148
  *
6092
6149
  * @example
6093
6150
  * ```tsx
@@ -6097,6 +6154,10 @@ export declare const UserCircleIcon: React_2.ForwardRefExoticComponent<React_2.S
6097
6154
  export declare const UserDisplayName: React_2.ForwardRefExoticComponent<UserDisplayNameProps & React_2.RefAttributes<HTMLElement>>;
6098
6155
 
6099
6156
  export declare interface UserDisplayNameProps extends React_2.HTMLAttributes<HTMLElement> {
6157
+ /** Render an AI-disclosure badge after the name, alongside any status badge. */
6158
+ aiDisclosure?: boolean;
6159
+ /** Accessible label for the AI-disclosure badge. @default "AI creator" */
6160
+ aiDisclosureLabel?: string;
6100
6161
  /** Render an ambassador badge after the name. */
6101
6162
  ambassador?: boolean;
6102
6163
  /** Accessible label for the ambassador badge. @default "Ambassador" */
@@ -6144,7 +6205,7 @@ export declare type UserIconProps = BaseIconProps;
6144
6205
 
6145
6206
  /**
6146
6207
  * A compact user row showing an avatar, display name (or nickname) and handle,
6147
- * with optional online and muted indicators.
6208
+ * with optional verified and AI-disclosure badges and online and muted indicators.
6148
6209
  *
6149
6210
  * @example
6150
6211
  * ```tsx
@@ -6168,6 +6229,14 @@ export declare interface UserItemProps extends React_2.HTMLAttributes<HTMLDivEle
6168
6229
  showHandle?: boolean;
6169
6230
  /** Enable the avatar online indicator (combined with `isOnline`). */
6170
6231
  showOnlineStatus?: boolean;
6232
+ /** Render an AI-disclosure badge after the display name. @default false */
6233
+ aiDisclosure?: boolean;
6234
+ /** Accessible label for the AI-disclosure badge. @default "AI creator" */
6235
+ aiDisclosureLabel?: string;
6236
+ /** Render a verified badge after the display name. @default false */
6237
+ verified?: boolean;
6238
+ /** Accessible label for the verified badge. @default "Verified" */
6239
+ verifiedLabel?: string;
6171
6240
  }
6172
6241
 
6173
6242
  /** Minimal user shape consumed by {@link UserItem}. */
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 { ButtonIconGroup } from "./components/ButtonIconGroup/ButtonIconGroup.mjs";
20
21
  import { ButtonStack } from "./components/ButtonStack/ButtonStack.mjs";
21
22
  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "./components/Card/Card.mjs";
22
23
  import { ChatInput } from "./components/ChatInput/ChatInput.mjs";
@@ -301,6 +302,7 @@ export {
301
302
  BreadcrumbSeparator,
302
303
  BulbIcon,
303
304
  Button,
305
+ ButtonIconGroup,
304
306
  ButtonStack,
305
307
  Calendar2Icon,
306
308
  CalendarIcon,
@@ -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.21.1",
3
+ "version": "3.23.0",
4
4
  "description": "React component library built with Tailwind CSS for Fanvue ecosystem",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",
@@ -142,7 +142,7 @@
142
142
  "jsdom": "27.4.0",
143
143
  "lint-staged": "16.2.7",
144
144
  "playwright": "^1.58.1",
145
- "postcss": "8.5.12",
145
+ "postcss": "8.5.20",
146
146
  "react": "19.2.3",
147
147
  "react-day-picker": "9.13.1",
148
148
  "react-dom": "19.2.3",
@@ -166,9 +166,9 @@
166
166
  "minimatch": ">=10.2.3",
167
167
  "ajv": ">=8.18.0",
168
168
  "fast-uri": ">=3.1.4",
169
- "brace-expansion": ">=5.0.7",
169
+ "brace-expansion": ">=5.0.8",
170
170
  "yaml": ">=2.8.3",
171
- "postcss": ">=8.5.10",
171
+ "postcss": ">=8.5.18",
172
172
  "tmp": ">=0.2.7",
173
173
  "ws": ">=8.20.1",
174
174
  "qs": ">=6.15.2",