@fanvue/ui 3.21.1 → 3.22.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.
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
|
|
15
|
+
* optional trend indicator, date range label, info tooltip, and a loading
|
|
16
16
|
* skeleton state.
|
|
17
17
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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 */
|
|
@@ -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
|
|
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: "
|
|
31
|
-
negative: "
|
|
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(
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
children:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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 {
|
|
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;;"}
|
|
@@ -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 {
|
|
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: "
|
|
12
|
-
negative: "
|
|
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(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
children:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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 {
|
|
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;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fanvue/ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.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.
|
|
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.
|
|
169
|
+
"brace-expansion": ">=5.0.8",
|
|
170
170
|
"yaml": ">=2.8.3",
|
|
171
|
-
"postcss": ">=8.5.
|
|
171
|
+
"postcss": ">=8.5.18",
|
|
172
172
|
"tmp": ">=0.2.7",
|
|
173
173
|
"ws": ">=8.20.1",
|
|
174
174
|
"qs": ">=6.15.2",
|