@fanvue/ui 1.18.2 → 1.19.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 (54) hide show
  1. package/dist/charts.d.ts +372 -0
  2. package/dist/charts.mjs +28 -0
  3. package/dist/charts.mjs.map +1 -0
  4. package/dist/cjs/charts.cjs +28 -0
  5. package/dist/cjs/charts.cjs.map +1 -0
  6. package/dist/cjs/components/Chart/ChartCard.cjs +88 -0
  7. package/dist/cjs/components/Chart/ChartCard.cjs.map +1 -0
  8. package/dist/cjs/components/Chart/ChartCenterLabel.cjs +51 -0
  9. package/dist/cjs/components/Chart/ChartCenterLabel.cjs.map +1 -0
  10. package/dist/cjs/components/Chart/ChartContainer.cjs +64 -0
  11. package/dist/cjs/components/Chart/ChartContainer.cjs.map +1 -0
  12. package/dist/cjs/components/Chart/ChartLegend.cjs +69 -0
  13. package/dist/cjs/components/Chart/ChartLegend.cjs.map +1 -0
  14. package/dist/cjs/components/Chart/ChartLoadingOverlay.cjs +35 -0
  15. package/dist/cjs/components/Chart/ChartLoadingOverlay.cjs.map +1 -0
  16. package/dist/cjs/components/Chart/ChartPieLegend.cjs +54 -0
  17. package/dist/cjs/components/Chart/ChartPieLegend.cjs.map +1 -0
  18. package/dist/cjs/components/Chart/ChartSeriesToggle.cjs +65 -0
  19. package/dist/cjs/components/Chart/ChartSeriesToggle.cjs.map +1 -0
  20. package/dist/cjs/components/Chart/ChartStyle.cjs +40 -0
  21. package/dist/cjs/components/Chart/ChartStyle.cjs.map +1 -0
  22. package/dist/cjs/components/Chart/ChartTooltip.cjs +147 -0
  23. package/dist/cjs/components/Chart/ChartTooltip.cjs.map +1 -0
  24. package/dist/cjs/components/Chart/chartUtils.cjs +23 -0
  25. package/dist/cjs/components/Chart/chartUtils.cjs.map +1 -0
  26. package/dist/cjs/components/Chart/useChart.cjs +32 -0
  27. package/dist/cjs/components/Chart/useChart.cjs.map +1 -0
  28. package/dist/cjs/components/TextField/TextField.cjs +0 -4
  29. package/dist/cjs/components/TextField/TextField.cjs.map +1 -1
  30. package/dist/components/Chart/ChartCard.mjs +71 -0
  31. package/dist/components/Chart/ChartCard.mjs.map +1 -0
  32. package/dist/components/Chart/ChartCenterLabel.mjs +34 -0
  33. package/dist/components/Chart/ChartCenterLabel.mjs.map +1 -0
  34. package/dist/components/Chart/ChartContainer.mjs +47 -0
  35. package/dist/components/Chart/ChartContainer.mjs.map +1 -0
  36. package/dist/components/Chart/ChartLegend.mjs +52 -0
  37. package/dist/components/Chart/ChartLegend.mjs.map +1 -0
  38. package/dist/components/Chart/ChartLoadingOverlay.mjs +18 -0
  39. package/dist/components/Chart/ChartLoadingOverlay.mjs.map +1 -0
  40. package/dist/components/Chart/ChartPieLegend.mjs +37 -0
  41. package/dist/components/Chart/ChartPieLegend.mjs.map +1 -0
  42. package/dist/components/Chart/ChartSeriesToggle.mjs +48 -0
  43. package/dist/components/Chart/ChartSeriesToggle.mjs.map +1 -0
  44. package/dist/components/Chart/ChartStyle.mjs +23 -0
  45. package/dist/components/Chart/ChartStyle.mjs.map +1 -0
  46. package/dist/components/Chart/ChartTooltip.mjs +130 -0
  47. package/dist/components/Chart/ChartTooltip.mjs.map +1 -0
  48. package/dist/components/Chart/chartUtils.mjs +23 -0
  49. package/dist/components/Chart/chartUtils.mjs.map +1 -0
  50. package/dist/components/Chart/useChart.mjs +15 -0
  51. package/dist/components/Chart/useChart.mjs.map +1 -0
  52. package/dist/components/TextField/TextField.mjs +0 -4
  53. package/dist/components/TextField/TextField.mjs.map +1 -1
  54. package/package.json +18 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartContainer.cjs","sources":["../../../../src/components/Chart/ChartContainer.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { ResponsiveContainer } from \"recharts\";\nimport { cn } from \"../../utils/cn\";\nimport { ChartStyle } from \"./ChartStyle\";\nimport type { ChartConfig } from \"./types\";\nimport { ChartContext } from \"./useChart\";\n\n/** Props for {@link ChartContainer}. */\nexport interface ChartContainerProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Series configuration mapping data keys to labels, colors, and icons. */\n config: ChartConfig;\n /**\n * Recharts chart element(s) to render inside the responsive container.\n * Typically a single `<AreaChart>`, `<BarChart>`, `<LineChart>`, etc.\n */\n children: React.ComponentProps<typeof ResponsiveContainer>[\"children\"];\n}\n\n/**\n * Wraps a Recharts chart with responsive sizing, design-token theming, and\n * accessible config context for tooltips and legends.\n *\n * @example\n * ```tsx\n * <ChartContainer config={chartConfig} className=\"min-h-48\">\n * <LineChart data={data} accessibilityLayer>\n * <Line dataKey=\"revenue\" stroke=\"var(--color-revenue)\" />\n * </LineChart>\n * </ChartContainer>\n * ```\n */\nexport const ChartContainer = React.forwardRef<HTMLDivElement, ChartContainerProps>(\n ({ id, className, children, config, ...props }, ref) => {\n const uniqueId = React.useId();\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`;\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n ref={ref}\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"flex aspect-video justify-center text-xs\",\n \"[&_.recharts-cartesian-axis-tick_text]:fill-foreground-tertiary\",\n \"[&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-neutral-200\",\n \"[&_.recharts-curve.recharts-tooltip-cursor]:stroke-neutral-200\",\n \"[&_.recharts-dot[stroke='#fff']]:stroke-transparent\",\n \"[&_.recharts-layer]:outline-hidden\",\n \"[&_.recharts-polar-grid_[stroke='#ccc']]:stroke-neutral-200\",\n \"[&_.recharts-radial-bar-background-sector]:fill-neutral-100\",\n \"[&_.recharts-rectangle.recharts-tooltip-cursor]:fill-neutral-100\",\n \"[&_.recharts-reference-line_[stroke='#ccc']]:stroke-neutral-200\",\n \"[&_.recharts-sector]:outline-hidden\",\n \"[&_.recharts-sector[stroke='#fff']]:stroke-transparent\",\n \"[&_.recharts-surface]:outline-hidden\",\n className,\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <ResponsiveContainer>{children}</ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n );\n },\n);\nChartContainer.displayName = \"ChartContainer\";\n"],"names":["React","ChartContext","jsxs","cn","jsx","ChartStyle","ResponsiveContainer"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,iBAAiBA,iBAAM;AAAA,EAClC,CAAC,EAAE,IAAI,WAAW,UAAU,QAAQ,GAAG,MAAA,GAAS,QAAQ;AACtD,UAAM,WAAWA,iBAAM,MAAA;AACvB,UAAM,UAAU,SAAS,MAAM,SAAS,QAAQ,MAAM,EAAE,CAAC;AAEzD,0CACGC,SAAAA,aAAa,UAAb,EAAsB,OAAO,EAAE,UAC9B,UAAAC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,aAAU;AAAA,QACV,cAAY;AAAA,QACZ,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,2BAAAA,IAACC,WAAAA,YAAA,EAAW,IAAI,SAAS,OAAA,CAAgB;AAAA,UACzCD,+BAACE,SAAAA,uBAAqB,SAAA,CAAS;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAEnC;AAAA,EAEJ;AACF;AACA,eAAe,cAAc;;"}
@@ -0,0 +1,69 @@
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 recharts = require("recharts");
7
+ const cn = require("../../utils/cn.cjs");
8
+ const chartUtils = require("./chartUtils.cjs");
9
+ const useChart = require("./useChart.cjs");
10
+ function _interopNamespaceDefault(e) {
11
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
12
+ if (e) {
13
+ for (const k in e) {
14
+ if (k !== "default") {
15
+ const d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: () => e[k]
19
+ });
20
+ }
21
+ }
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
27
+ const ChartLegend = recharts.Legend;
28
+ const ChartLegendContent = React__namespace.forwardRef(
29
+ ({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => {
30
+ const { config } = useChart.useChart();
31
+ if (!payload?.length) return null;
32
+ return /* @__PURE__ */ jsxRuntime.jsx(
33
+ "div",
34
+ {
35
+ ref,
36
+ className: cn.cn(
37
+ "flex items-center justify-center gap-4",
38
+ verticalAlign === "top" ? "pb-3" : "pt-3",
39
+ className
40
+ ),
41
+ children: chartUtils.filterVisiblePayload(payload).map((item) => {
42
+ const key = String(nameKey || item.dataKey || "value");
43
+ const itemConfig = chartUtils.resolveConfigEntry(config, item, key);
44
+ return /* @__PURE__ */ jsxRuntime.jsxs(
45
+ "div",
46
+ {
47
+ className: "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-foreground-tertiary",
48
+ children: [
49
+ itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsxRuntime.jsx(itemConfig.icon, {}) : /* @__PURE__ */ jsxRuntime.jsx(
50
+ "div",
51
+ {
52
+ className: "h-2 w-2 shrink-0 rounded-[2px]",
53
+ style: { backgroundColor: item.color }
54
+ }
55
+ ),
56
+ itemConfig?.label
57
+ ]
58
+ },
59
+ item.value
60
+ );
61
+ })
62
+ }
63
+ );
64
+ }
65
+ );
66
+ ChartLegendContent.displayName = "ChartLegendContent";
67
+ exports.ChartLegend = ChartLegend;
68
+ exports.ChartLegendContent = ChartLegendContent;
69
+ //# sourceMappingURL=ChartLegend.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartLegend.cjs","sources":["../../../../src/components/Chart/ChartLegend.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Legend as RechartsLegend } from \"recharts\";\nimport type { LegendPayload } from \"recharts/types/component/DefaultLegendContent\";\nimport { cn } from \"../../utils/cn\";\nimport { filterVisiblePayload, resolveConfigEntry } from \"./chartUtils\";\nimport { useChart } from \"./useChart\";\n\n/** Re-export of Recharts `Legend` — use with `content={<ChartLegendContent />}`. */\nexport const ChartLegend = RechartsLegend;\n\n/** Props for {@link ChartLegendContent}. */\nexport interface ChartLegendContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Legend payload data. Passed by Recharts. */\n payload?: readonly LegendPayload[];\n /** Vertical alignment — controls padding direction. @default \"bottom\" */\n verticalAlign?: \"top\" | \"bottom\";\n /** Hide the color/icon indicator. @default false */\n hideIcon?: boolean;\n /** Data key used to resolve the display name from config. */\n nameKey?: string;\n}\n\n/**\n * Styled legend content for use with `<ChartLegend content={<ChartLegendContent />} />`.\n *\n * Reads chart config from context to resolve labels and icons.\n *\n * @example\n * ```tsx\n * <ChartLegend content={<ChartLegendContent />} />\n * ```\n */\nexport const ChartLegendContent = React.forwardRef<HTMLDivElement, ChartLegendContentProps>(\n ({ className, hideIcon = false, payload, verticalAlign = \"bottom\", nameKey }, ref) => {\n const { config } = useChart();\n\n if (!payload?.length) return null;\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className,\n )}\n >\n {filterVisiblePayload(payload).map((item) => {\n const key = String(nameKey || item.dataKey || \"value\");\n const itemConfig = resolveConfigEntry(config, item, key);\n\n return (\n <div\n key={item.value}\n className=\"flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-foreground-tertiary\"\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{ backgroundColor: item.color }}\n />\n )}\n {itemConfig?.label}\n </div>\n );\n })}\n </div>\n );\n },\n);\n\nChartLegendContent.displayName = \"ChartLegendContent\";\n"],"names":["RechartsLegend","React","useChart","jsx","cn","filterVisiblePayload","resolveConfigEntry","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,cAAcA,SAAAA;AAwBpB,MAAM,qBAAqBC,iBAAM;AAAA,EACtC,CAAC,EAAE,WAAW,WAAW,OAAO,SAAS,gBAAgB,UAAU,QAAA,GAAW,QAAQ;AACpF,UAAM,EAAE,OAAA,IAAWC,kBAAA;AAEnB,QAAI,CAAC,SAAS,OAAQ,QAAO;AAE7B,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA,kBAAkB,QAAQ,SAAS;AAAA,UACnC;AAAA,QAAA;AAAA,QAGD,UAAAC,WAAAA,qBAAqB,OAAO,EAAE,IAAI,CAAC,SAAS;AAC3C,gBAAM,MAAM,OAAO,WAAW,KAAK,WAAW,OAAO;AACrD,gBAAM,aAAaC,WAAAA,mBAAmB,QAAQ,MAAM,GAAG;AAEvD,iBACEC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cAEC,WAAU;AAAA,cAET,UAAA;AAAA,gBAAA,YAAY,QAAQ,CAAC,0CACnB,WAAW,MAAX,CAAA,CAAgB,IAEjBJ,2BAAAA;AAAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAU;AAAA,oBACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,kBAAM;AAAA,gBAAA;AAAA,gBAGxC,YAAY;AAAA,cAAA;AAAA,YAAA;AAAA,YAXR,KAAK;AAAA,UAAA;AAAA,QAchB,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,mBAAmB,cAAc;;;"}
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ const Loader = require("../Loader/Loader.cjs");
8
+ function _interopNamespaceDefault(e) {
9
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
10
+ if (e) {
11
+ for (const k in e) {
12
+ if (k !== "default") {
13
+ const d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: () => e[k]
17
+ });
18
+ }
19
+ }
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
+ const ChartLoadingOverlay = React__namespace.forwardRef(
26
+ ({ loading = false, children, className, ...props }, ref) => {
27
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn.cn("relative", className), ...props, children: [
28
+ children,
29
+ loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-surface-container/60", children: /* @__PURE__ */ jsxRuntime.jsx(Loader.Loader, { show: true, center: true }) })
30
+ ] });
31
+ }
32
+ );
33
+ ChartLoadingOverlay.displayName = "ChartLoadingOverlay";
34
+ exports.ChartLoadingOverlay = ChartLoadingOverlay;
35
+ //# sourceMappingURL=ChartLoadingOverlay.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartLoadingOverlay.cjs","sources":["../../../../src/components/Chart/ChartLoadingOverlay.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Loader } from \"../Loader/Loader\";\n\n/** Props for {@link ChartLoadingOverlay}. */\nexport interface ChartLoadingOverlayProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Whether to show the loading overlay. @default false */\n loading?: boolean;\n /** Chart content to render underneath the overlay. */\n children: React.ReactNode;\n}\n\n/**\n * A positioned overlay that displays a loading spinner on top of chart content.\n * The children are always rendered to maintain layout dimensions; the overlay\n * covers them with a semi-transparent background and a centered spinner.\n *\n * @example\n * ```tsx\n * <ChartLoadingOverlay loading={isFetching}>\n * <ChartContainer config={config} className=\"min-h-48\">\n * <LineChart data={data}>...</LineChart>\n * </ChartContainer>\n * </ChartLoadingOverlay>\n * ```\n */\nexport const ChartLoadingOverlay = React.forwardRef<HTMLDivElement, ChartLoadingOverlayProps>(\n ({ loading = false, children, className, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"relative\", className)} {...props}>\n {children}\n {loading && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center bg-surface-container/60\">\n <Loader show center />\n </div>\n )}\n </div>\n );\n },\n);\n\nChartLoadingOverlay.displayName = \"ChartLoadingOverlay\";\n"],"names":["React","jsxs","cn","jsx","Loader"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA0BO,MAAM,sBAAsBA,iBAAM;AAAA,EACvC,CAAC,EAAE,UAAU,OAAO,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AAC3D,WACEC,gCAAC,SAAI,KAAU,WAAWC,MAAG,YAAY,SAAS,GAAI,GAAG,OACtD,UAAA;AAAA,MAAA;AAAA,MACA,WACCC,2BAAAA,IAAC,OAAA,EAAI,WAAU,kFACb,UAAAA,2BAAAA,IAACC,OAAAA,QAAA,EAAO,MAAI,MAAC,QAAM,KAAA,CAAC,EAAA,CACtB;AAAA,IAAA,GAEJ;AAAA,EAEJ;AACF;AAEA,oBAAoB,cAAc;;"}
@@ -0,0 +1,54 @@
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 ChartPieLegend = React__namespace.forwardRef(
25
+ ({ items, className, ...props }, ref) => {
26
+ const total = items.reduce((sum, item) => sum + item.value, 0);
27
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("flex flex-col gap-3", className), ...props, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
28
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
29
+ item.icon ?? /* @__PURE__ */ jsxRuntime.jsx(
30
+ "span",
31
+ {
32
+ className: "size-2 shrink-0 rounded-full",
33
+ style: { backgroundColor: item.color }
34
+ }
35
+ ),
36
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-regular-body-sm min-w-0 flex-1 truncate text-foreground-secondary", children: item.label }),
37
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-semibold-body-md text-foreground-default tabular-nums", children: item.formattedValue ?? item.value.toLocaleString() })
38
+ ] }),
39
+ /* @__PURE__ */ jsxRuntime.jsx(
40
+ "div",
41
+ {
42
+ className: "h-1.5 rounded-full",
43
+ style: {
44
+ backgroundColor: item.color,
45
+ width: total > 0 ? `${item.value / total * 100}%` : "0%"
46
+ }
47
+ }
48
+ )
49
+ ] }, `${item.color}-${item.value}`)) });
50
+ }
51
+ );
52
+ ChartPieLegend.displayName = "ChartPieLegend";
53
+ exports.ChartPieLegend = ChartPieLegend;
54
+ //# sourceMappingURL=ChartPieLegend.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartPieLegend.cjs","sources":["../../../../src/components/Chart/ChartPieLegend.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single item in a {@link ChartPieLegend}. */\nexport interface ChartPieLegendItem {\n /** Display label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Numeric value for this slice. Used to calculate the proportional bar width. */\n value: number;\n /** Formatted display value (e.g. \"$4,500\"). If omitted, `value.toLocaleString()` is used. */\n formattedValue?: React.ReactNode;\n /** Slice color (CSS value). */\n color: string;\n /** Optional icon to show instead of the color dot. */\n icon?: React.ReactNode;\n}\n\n/** Props for {@link ChartPieLegend}. */\nexport interface ChartPieLegendProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Legend items to display. */\n items: ChartPieLegendItem[];\n}\n\n/**\n * A side legend for pie/donut charts that shows each slice's label,\n * formatted value, and a proportional progress bar.\n *\n * @example\n * ```tsx\n * <ChartPieLegend\n * items={[\n * { label: \"Subscriptions\", value: 4500, formattedValue: \"$4,500\", color: \"var(--color-special-chart-teal)\" },\n * { label: \"Messages\", value: 2100, formattedValue: \"$2,100\", color: \"var(--color-special-chart-sky)\" },\n * { label: \"Tips\", value: 1200, formattedValue: \"$1,200\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * />\n * ```\n */\nexport const ChartPieLegend = React.forwardRef<HTMLDivElement, ChartPieLegendProps>(\n ({ items, className, ...props }, ref) => {\n const total = items.reduce((sum, item) => sum + item.value, 0);\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-3\", className)} {...props}>\n {items.map((item) => (\n <div key={`${item.color}-${item.value}`} className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center gap-2\">\n {item.icon ?? (\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className=\"typography-regular-body-sm min-w-0 flex-1 truncate text-foreground-secondary\">\n {item.label}\n </span>\n <span className=\"typography-semibold-body-md text-foreground-default tabular-nums\">\n {item.formattedValue ?? item.value.toLocaleString()}\n </span>\n </div>\n <div\n className=\"h-1.5 rounded-full\"\n style={{\n backgroundColor: item.color,\n width: total > 0 ? `${(item.value / total) * 100}%` : \"0%\",\n }}\n />\n </div>\n ))}\n </div>\n );\n },\n);\n\nChartPieLegend.displayName = \"ChartPieLegend\";\n"],"names":["React","cn","jsxs","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsCO,MAAM,iBAAiBA,iBAAM;AAAA,EAClC,CAAC,EAAE,OAAO,WAAW,GAAG,MAAA,GAAS,QAAQ;AACvC,UAAM,QAAQ,MAAM,OAAO,CAAC,KAAK,SAAS,MAAM,KAAK,OAAO,CAAC;AAE7D,0CACG,OAAA,EAAI,KAAU,WAAWC,MAAG,uBAAuB,SAAS,GAAI,GAAG,OACjE,gBAAM,IAAI,CAAC,SACVC,2BAAAA,KAAC,OAAA,EAAwC,WAAU,yBACjD,UAAA;AAAA,MAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAA,KAAK,QACJC,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,UAAM;AAAA,QAAA;AAAA,QAGzCA,2BAAAA,IAAC,QAAA,EAAK,WAAU,gFACb,eAAK,OACR;AAAA,QACAA,2BAAAA,IAAC,UAAK,WAAU,oEACb,eAAK,kBAAkB,KAAK,MAAM,eAAA,EAAe,CACpD;AAAA,MAAA,GACF;AAAA,MACAA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO;AAAA,YACL,iBAAiB,KAAK;AAAA,YACtB,OAAO,QAAQ,IAAI,GAAI,KAAK,QAAQ,QAAS,GAAG,MAAM;AAAA,UAAA;AAAA,QACxD;AAAA,MAAA;AAAA,IACF,KArBQ,GAAG,KAAK,KAAK,IAAI,KAAK,KAAK,EAsBrC,CACD,GACH;AAAA,EAEJ;AACF;AAEA,eAAe,cAAc;;"}
@@ -0,0 +1,65 @@
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 ChartSeriesToggle = React__namespace.forwardRef(
25
+ ({ className, items, value, onValueChange, ...props }, ref) => {
26
+ const toggle = (key) => {
27
+ const next = new Set(value);
28
+ if (next.has(key)) {
29
+ next.delete(key);
30
+ } else {
31
+ next.add(key);
32
+ }
33
+ onValueChange(next);
34
+ };
35
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn.cn("grid grid-cols-2 gap-2 sm:grid-cols-3", className), ...props, children: items.map((item) => {
36
+ const isActive = value.has(item.key);
37
+ return /* @__PURE__ */ jsxRuntime.jsxs(
38
+ "button",
39
+ {
40
+ type: "button",
41
+ "aria-pressed": isActive,
42
+ className: cn.cn(
43
+ "typography-regular-body-sm flex items-center gap-2 rounded-full border px-3 py-1.5 text-foreground-default transition-opacity hover:opacity-100",
44
+ isActive ? "border-neutral-200 bg-surface-container" : "border-transparent bg-transparent opacity-50"
45
+ ),
46
+ onClick: () => toggle(item.key),
47
+ children: [
48
+ /* @__PURE__ */ jsxRuntime.jsx(
49
+ "span",
50
+ {
51
+ className: "size-2 shrink-0 rounded-full",
52
+ style: { backgroundColor: item.color }
53
+ }
54
+ ),
55
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label })
56
+ ]
57
+ },
58
+ item.key
59
+ );
60
+ }) });
61
+ }
62
+ );
63
+ ChartSeriesToggle.displayName = "ChartSeriesToggle";
64
+ exports.ChartSeriesToggle = ChartSeriesToggle;
65
+ //# sourceMappingURL=ChartSeriesToggle.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartSeriesToggle.cjs","sources":["../../../../src/components/Chart/ChartSeriesToggle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n/** A single toggleable series in a {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleItem {\n /** Unique key matching the data series key and ChartConfig key. */\n key: string;\n /** Human-readable label. Pass translated string for i18n. */\n label: React.ReactNode;\n /** Series color (CSS value). Shown as indicator dot. */\n color: string;\n}\n\n/** Props for {@link ChartSeriesToggle}. */\nexport interface ChartSeriesToggleProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Available series that can be toggled. */\n items: ChartSeriesToggleItem[];\n /** Set of currently visible series keys. */\n value: Set<string>;\n /** Called when a series is toggled. Receives the updated Set. */\n onValueChange: (value: Set<string>) => void;\n}\n\n/**\n * Renders a grid of toggleable chips that control which series are visible\n * on a multi-series chart. Each toggle shows a color indicator dot and a label.\n *\n * @example\n * ```tsx\n * const [visible, setVisible] = useState(new Set([\"subscription\", \"message\", \"tip\"]));\n *\n * <ChartSeriesToggle\n * items={[\n * { key: \"subscription\", label: \"Subscription\", color: \"var(--color-special-chart-teal)\" },\n * { key: \"message\", label: \"Message\", color: \"var(--color-special-chart-sky)\" },\n * { key: \"tip\", label: \"Tip\", color: \"var(--color-special-chart-orange)\" },\n * ]}\n * value={visible}\n * onValueChange={setVisible}\n * />\n * ```\n */\nexport const ChartSeriesToggle = React.forwardRef<HTMLDivElement, ChartSeriesToggleProps>(\n ({ className, items, value, onValueChange, ...props }, ref) => {\n const toggle = (key: string) => {\n const next = new Set(value);\n if (next.has(key)) {\n next.delete(key);\n } else {\n next.add(key);\n }\n onValueChange(next);\n };\n\n return (\n <div ref={ref} className={cn(\"grid grid-cols-2 gap-2 sm:grid-cols-3\", className)} {...props}>\n {items.map((item) => {\n const isActive = value.has(item.key);\n return (\n <button\n key={item.key}\n type=\"button\"\n aria-pressed={isActive}\n className={cn(\n \"typography-regular-body-sm flex items-center gap-2 rounded-full border px-3 py-1.5 text-foreground-default transition-opacity hover:opacity-100\",\n isActive\n ? \"border-neutral-200 bg-surface-container\"\n : \"border-transparent bg-transparent opacity-50\",\n )}\n onClick={() => toggle(item.key)}\n >\n <span\n className=\"size-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n <span>{item.label}</span>\n </button>\n );\n })}\n </div>\n );\n },\n);\n\nChartSeriesToggle.displayName = \"ChartSeriesToggle\";\n"],"names":["React","jsx","cn","jsxs"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA0CO,MAAM,oBAAoBA,iBAAM;AAAA,EACrC,CAAC,EAAE,WAAW,OAAO,OAAO,eAAe,GAAG,MAAA,GAAS,QAAQ;AAC7D,UAAM,SAAS,CAAC,QAAgB;AAC9B,YAAM,OAAO,IAAI,IAAI,KAAK;AAC1B,UAAI,KAAK,IAAI,GAAG,GAAG;AACjB,aAAK,OAAO,GAAG;AAAA,MACjB,OAAO;AACL,aAAK,IAAI,GAAG;AAAA,MACd;AACA,oBAAc,IAAI;AAAA,IACpB;AAEA,WACEC,2BAAAA,IAAC,OAAA,EAAI,KAAU,WAAWC,GAAAA,GAAG,yCAAyC,SAAS,GAAI,GAAG,OACnF,UAAA,MAAM,IAAI,CAAC,SAAS;AACnB,YAAM,WAAW,MAAM,IAAI,KAAK,GAAG;AACnC,aACEC,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,gBAAc;AAAA,UACd,WAAWD,GAAAA;AAAAA,YACT;AAAA,YACA,WACI,4CACA;AAAA,UAAA;AAAA,UAEN,SAAS,MAAM,OAAO,KAAK,GAAG;AAAA,UAE9B,UAAA;AAAA,YAAAD,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,iBAAiB,KAAK,MAAA;AAAA,cAAM;AAAA,YAAA;AAAA,YAEvCA,2BAAAA,IAAC,QAAA,EAAM,UAAA,KAAK,MAAA,CAAM;AAAA,UAAA;AAAA,QAAA;AAAA,QAfb,KAAK;AAAA,MAAA;AAAA,IAkBhB,CAAC,EAAA,CACH;AAAA,EAEJ;AACF;AAEA,kBAAkB,cAAc;;"}
@@ -0,0 +1,40 @@
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 chartUtils = require("./chartUtils.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 ChartStyle = React__namespace.memo(function ChartStyle2({ id, config }) {
25
+ const colorEntries = Object.entries(config).filter(([, entry]) => entry.theme || entry.color);
26
+ if (colorEntries.length === 0) return null;
27
+ const css = Object.entries(chartUtils.THEMES).map(([theme, prefix]) => {
28
+ const vars = colorEntries.map(([key, entry]) => {
29
+ const color = entry.theme?.[theme] || entry.color;
30
+ return color ? ` --color-${key}: ${color};` : null;
31
+ }).filter(Boolean).join("\n");
32
+ return `${prefix} [data-chart=${id}] {
33
+ ${vars}
34
+ }`;
35
+ }).join("\n");
36
+ return /* @__PURE__ */ jsxRuntime.jsx("style", { children: css });
37
+ });
38
+ ChartStyle.displayName = "ChartStyle";
39
+ exports.ChartStyle = ChartStyle;
40
+ //# sourceMappingURL=ChartStyle.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartStyle.cjs","sources":["../../../../src/components/Chart/ChartStyle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { THEMES } from \"./chartUtils\";\nimport type { ChartConfig } from \"./types\";\n\n/** Props for the scoped CSS variable injector used by {@link ChartContainer}. */\nexport interface ChartStyleProps {\n /** Unique identifier scoped to the chart instance. */\n id: string;\n /** Chart configuration mapping data keys to colors and themes. */\n config: ChartConfig;\n}\n\n/**\n * Injects a scoped `<style>` tag that maps each config entry to a\n * `--color-{key}` CSS custom property, with light/dark theme support.\n *\n * Rendered automatically by {@link ChartContainer} — you rarely need this directly.\n */\nexport const ChartStyle = React.memo(function ChartStyle({ id, config }: ChartStyleProps) {\n const colorEntries = Object.entries(config).filter(([, entry]) => entry.theme || entry.color);\n\n if (colorEntries.length === 0) return null;\n\n const css = Object.entries(THEMES)\n .map(([theme, prefix]) => {\n const vars = colorEntries\n .map(([key, entry]) => {\n const color = entry.theme?.[theme as keyof typeof entry.theme] || entry.color;\n return color ? ` --color-${key}: ${color};` : null;\n })\n .filter(Boolean)\n .join(\"\\n\");\n return `${prefix} [data-chart=${id}] {\\n${vars}\\n}`;\n })\n .join(\"\\n\");\n\n return <style>{css}</style>;\n});\n\nChartStyle.displayName = \"ChartStyle\";\n"],"names":["React","ChartStyle","THEMES","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAkBO,MAAM,aAAaA,iBAAM,KAAK,SAASC,YAAW,EAAE,IAAI,UAA2B;AACxF,QAAM,eAAe,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAA,EAAG,KAAK,MAAM,MAAM,SAAS,MAAM,KAAK;AAE5F,MAAI,aAAa,WAAW,EAAG,QAAO;AAEtC,QAAM,MAAM,OAAO,QAAQC,WAAAA,MAAM,EAC9B,IAAI,CAAC,CAAC,OAAO,MAAM,MAAM;AACxB,UAAM,OAAO,aACV,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AACrB,YAAM,QAAQ,MAAM,QAAQ,KAAiC,KAAK,MAAM;AACxE,aAAO,QAAQ,aAAa,GAAG,KAAK,KAAK,MAAM;AAAA,IACjD,CAAC,EACA,OAAO,OAAO,EACd,KAAK,IAAI;AACZ,WAAO,GAAG,MAAM,gBAAgB,EAAE;AAAA,EAAQ,IAAI;AAAA;AAAA,EAChD,CAAC,EACA,KAAK,IAAI;AAEZ,SAAOC,2BAAAA,IAAC,WAAO,UAAA,IAAA,CAAI;AACrB,CAAC;AAED,WAAW,cAAc;;"}
@@ -0,0 +1,147 @@
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 recharts = require("recharts");
7
+ const cn = require("../../utils/cn.cjs");
8
+ const chartUtils = require("./chartUtils.cjs");
9
+ const useChart = require("./useChart.cjs");
10
+ function _interopNamespaceDefault(e) {
11
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
12
+ if (e) {
13
+ for (const k in e) {
14
+ if (k !== "default") {
15
+ const d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: () => e[k]
19
+ });
20
+ }
21
+ }
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
27
+ const ChartTooltip = recharts.Tooltip;
28
+ function TooltipRow({
29
+ item,
30
+ itemConfig,
31
+ indicator,
32
+ indicatorColor,
33
+ hideIndicator,
34
+ nestLabel,
35
+ tooltipLabel
36
+ }) {
37
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
38
+ itemConfig?.icon ? /* @__PURE__ */ jsxRuntime.jsx(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsxRuntime.jsx(
39
+ "div",
40
+ {
41
+ className: cn.cn("shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)", {
42
+ "h-2.5 w-2.5": indicator === "dot",
43
+ "w-1": indicator === "line",
44
+ "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
45
+ "my-0.5": nestLabel && indicator === "dashed"
46
+ }),
47
+ style: {
48
+ "--color-bg": indicatorColor,
49
+ "--color-border": indicatorColor
50
+ }
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsxRuntime.jsxs(
54
+ "div",
55
+ {
56
+ className: cn.cn(
57
+ "flex flex-1 justify-between leading-none",
58
+ nestLabel ? "items-end" : "items-center"
59
+ ),
60
+ children: [
61
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-1.5", children: [
62
+ nestLabel ? tooltipLabel : null,
63
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground-tertiary", children: itemConfig?.label || item.name })
64
+ ] }),
65
+ item.value !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium font-mono text-foreground-default tabular-nums", children: typeof item.value === "number" ? item.value.toLocaleString() : item.value })
66
+ ]
67
+ }
68
+ )
69
+ ] });
70
+ }
71
+ const ChartTooltipContent = React__namespace.forwardRef(
72
+ ({
73
+ active,
74
+ payload,
75
+ className,
76
+ indicator = "dot",
77
+ hideLabel = false,
78
+ hideIndicator = false,
79
+ label,
80
+ labelFormatter,
81
+ labelClassName,
82
+ formatter,
83
+ color,
84
+ nameKey,
85
+ labelKey
86
+ }, ref) => {
87
+ const { config } = useChart.useChart();
88
+ const tooltipLabel = React__namespace.useMemo(() => {
89
+ if (hideLabel || !payload?.length) return null;
90
+ const [item] = payload;
91
+ const key = String(labelKey || item?.dataKey || item?.name || "value");
92
+ const itemConfig = chartUtils.resolveConfigEntry(config, item, key);
93
+ const value = !labelKey && typeof label === "string" ? config[label]?.label || label : itemConfig?.label;
94
+ if (labelFormatter && payload) {
95
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn.cn("font-medium", labelClassName), children: labelFormatter(value, payload) });
96
+ }
97
+ if (!value) return null;
98
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn.cn("font-medium", labelClassName), children: value });
99
+ }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
100
+ if (!active || !payload?.length) return null;
101
+ const nestLabel = payload.length === 1 && indicator !== "dot";
102
+ return /* @__PURE__ */ jsxRuntime.jsxs(
103
+ "div",
104
+ {
105
+ ref,
106
+ className: cn.cn(
107
+ "grid min-w-32 items-start gap-1.5 rounded-lg border border-neutral-200 bg-surface-container px-2.5 py-1.5 text-xs shadow-float",
108
+ className
109
+ ),
110
+ children: [
111
+ !nestLabel ? tooltipLabel : null,
112
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-1.5", children: chartUtils.filterVisiblePayload(payload).map((item, index) => {
113
+ const key = String(nameKey || item.dataKey || item.name || "value");
114
+ const itemConfig = chartUtils.resolveConfigEntry(config, item, key);
115
+ const indicatorColor = color || item.payload?.fill || item.color;
116
+ return /* @__PURE__ */ jsxRuntime.jsx(
117
+ "div",
118
+ {
119
+ className: cn.cn(
120
+ "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-foreground-tertiary",
121
+ indicator === "dot" && "items-center"
122
+ ),
123
+ children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, payload) : /* @__PURE__ */ jsxRuntime.jsx(
124
+ TooltipRow,
125
+ {
126
+ item,
127
+ itemConfig,
128
+ indicator,
129
+ indicatorColor,
130
+ hideIndicator,
131
+ nestLabel,
132
+ tooltipLabel
133
+ }
134
+ )
135
+ },
136
+ `${item.dataKey ?? item.name ?? index}`
137
+ );
138
+ }) })
139
+ ]
140
+ }
141
+ );
142
+ }
143
+ );
144
+ ChartTooltipContent.displayName = "ChartTooltipContent";
145
+ exports.ChartTooltip = ChartTooltip;
146
+ exports.ChartTooltipContent = ChartTooltipContent;
147
+ //# sourceMappingURL=ChartTooltip.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartTooltip.cjs","sources":["../../../../src/components/Chart/ChartTooltip.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Tooltip as RechartsTooltip } from \"recharts\";\nimport type { NameType, Payload, ValueType } from \"recharts/types/component/DefaultTooltipContent\";\nimport { cn } from \"../../utils/cn\";\nimport { filterVisiblePayload, resolveConfigEntry } from \"./chartUtils\";\nimport type { ChartConfigEntry } from \"./types\";\nimport { useChart } from \"./useChart\";\n\n/** Re-export of Recharts `Tooltip` — use with `content={<ChartTooltipContent />}`. */\nexport const ChartTooltip = RechartsTooltip;\n\n/** Indicator shape rendered beside each tooltip row. */\nexport type ChartTooltipIndicator = \"dot\" | \"line\" | \"dashed\";\n\n/** Props for {@link ChartTooltipContent}. */\nexport interface ChartTooltipContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Whether the tooltip is currently active/visible. Passed by Recharts. */\n active?: boolean;\n /** Tooltip payload data. Passed by Recharts. */\n payload?: Payload<ValueType, NameType>[];\n /** Axis label. Passed by Recharts. */\n label?: string | number;\n /** Custom label formatter. */\n labelFormatter?: (\n label: string | number,\n payload: Payload<ValueType, NameType>[],\n ) => React.ReactNode;\n /** Custom value formatter. */\n formatter?: (\n value: ValueType,\n name: NameType,\n item: Payload<ValueType, NameType>,\n index: number,\n payload: Payload<ValueType, NameType>[],\n ) => React.ReactNode;\n /** CSS class for the label element. */\n labelClassName?: string;\n /** Hide the tooltip header label. @default false */\n hideLabel?: boolean;\n /** Hide the color indicator beside each row. @default false */\n hideIndicator?: boolean;\n /** Visual style of the color indicator. @default \"dot\" */\n indicator?: ChartTooltipIndicator;\n /**\n * Data key used to resolve the display name from config.\n * Useful when the payload `name` differs from the config key.\n */\n nameKey?: string;\n /**\n * Data key used to resolve the header label from config.\n * Falls back to the first payload item's `dataKey`.\n */\n labelKey?: string;\n /** Override indicator color for all rows. */\n color?: string;\n}\n\nfunction TooltipRow({\n item,\n itemConfig,\n indicator,\n indicatorColor,\n hideIndicator,\n nestLabel,\n tooltipLabel,\n}: {\n item: Payload<ValueType, NameType>;\n itemConfig: ChartConfigEntry | undefined;\n indicator: ChartTooltipIndicator;\n indicatorColor: unknown;\n hideIndicator: boolean;\n nestLabel: boolean;\n tooltipLabel: React.ReactNode;\n}) {\n return (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\", {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\": indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n })}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\",\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-foreground-tertiary\">{itemConfig?.label || item.name}</span>\n </div>\n {item.value !== undefined && (\n <span className=\"font-medium font-mono text-foreground-default tabular-nums\">\n {typeof item.value === \"number\" ? item.value.toLocaleString() : item.value}\n </span>\n )}\n </div>\n </>\n );\n}\n\n/**\n * Styled tooltip content for use with `<ChartTooltip content={<ChartTooltipContent />} />`.\n *\n * Reads chart config from context to resolve labels, colors, and icons.\n * Supports dot/line/dashed indicators. Pass translated `label`s in config for i18n.\n *\n * @example\n * ```tsx\n * <ChartTooltip\n * content={<ChartTooltipContent indicator=\"line\" />}\n * />\n * ```\n */\nexport const ChartTooltipContent = React.forwardRef<HTMLDivElement, ChartTooltipContentProps>(\n (\n {\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n },\n ref,\n ) => {\n const { config } = useChart();\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) return null;\n\n const [item] = payload;\n const key = String(labelKey || item?.dataKey || item?.name || \"value\");\n const itemConfig = resolveConfigEntry(config, item, key);\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label;\n\n if (labelFormatter && payload) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>\n {labelFormatter(value as string | number, payload)}\n </div>\n );\n }\n\n if (!value) return null;\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>;\n }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);\n\n if (!active || !payload?.length) return null;\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\";\n\n return (\n <div\n ref={ref}\n className={cn(\n \"grid min-w-32 items-start gap-1.5 rounded-lg border border-neutral-200 bg-surface-container px-2.5 py-1.5 text-xs shadow-float\",\n className,\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {filterVisiblePayload(payload).map((item, index) => {\n const key = String(nameKey || item.dataKey || item.name || \"value\");\n const itemConfig = resolveConfigEntry(config, item, key);\n const indicatorColor =\n color || (item.payload as Record<string, unknown>)?.fill || item.color;\n\n return (\n <div\n key={`${item.dataKey ?? item.name ?? index}`}\n className={cn(\n \"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-foreground-tertiary\",\n indicator === \"dot\" && \"items-center\",\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, payload)\n ) : (\n <TooltipRow\n item={item}\n itemConfig={itemConfig}\n indicator={indicator}\n indicatorColor={indicatorColor}\n hideIndicator={hideIndicator}\n nestLabel={nestLabel}\n tooltipLabel={tooltipLabel}\n />\n )}\n </div>\n );\n })}\n </div>\n </div>\n );\n },\n);\n\nChartTooltipContent.displayName = \"ChartTooltipContent\";\n"],"names":["RechartsTooltip","jsxs","Fragment","jsx","cn","React","useChart","resolveConfigEntry","filterVisiblePayload"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const THEMES = { light: "", dark: ".dark" };
5
+ function filterVisiblePayload(items) {
6
+ return items.filter((item) => item.type !== "none");
7
+ }
8
+ function resolveConfigEntry(config, payload, key) {
9
+ if (typeof payload !== "object" || payload === null) return void 0;
10
+ const p = payload;
11
+ const nested = typeof p.payload === "object" && p.payload !== null ? p.payload : void 0;
12
+ let configKey = key;
13
+ if (key in p && typeof p[key] === "string") {
14
+ configKey = p[key];
15
+ } else if (nested && key in nested && typeof nested[key] === "string") {
16
+ configKey = nested[key];
17
+ }
18
+ return config[configKey] ?? config[key];
19
+ }
20
+ exports.THEMES = THEMES;
21
+ exports.filterVisiblePayload = filterVisiblePayload;
22
+ exports.resolveConfigEntry = resolveConfigEntry;
23
+ //# sourceMappingURL=chartUtils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chartUtils.cjs","sources":["../../../../src/components/Chart/chartUtils.ts"],"sourcesContent":["import type { ChartConfig, ChartThemeKey } from \"./types\";\n\nexport const THEMES: Record<ChartThemeKey, string> = { light: \"\", dark: \".dark\" };\n\nexport function filterVisiblePayload<T extends { type?: string }>(items: readonly T[]): T[] {\n return items.filter((item) => item.type !== \"none\");\n}\n\n/**\n * Resolves the {@link ChartConfig} entry for a given tooltip/legend payload\n * item. Recharts wraps the original data point inside `payload.payload` —\n * this function checks both levels before falling back to a direct `key` lookup.\n */\nexport function resolveConfigEntry(config: ChartConfig, payload: unknown, key: string) {\n if (typeof payload !== \"object\" || payload === null) return undefined;\n\n const p = payload as Record<string, unknown>;\n const nested =\n typeof p.payload === \"object\" && p.payload !== null\n ? (p.payload as Record<string, unknown>)\n : undefined;\n\n let configKey = key;\n\n if (key in p && typeof p[key] === \"string\") {\n configKey = p[key] as string;\n } else if (nested && key in nested && typeof nested[key] === \"string\") {\n configKey = nested[key] as string;\n }\n\n return config[configKey] ?? config[key];\n}\n"],"names":[],"mappings":";;;AAEO,MAAM,SAAwC,EAAE,OAAO,IAAI,MAAM,QAAA;AAEjE,SAAS,qBAAkD,OAA0B;AAC1F,SAAO,MAAM,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM;AACpD;AAOO,SAAS,mBAAmB,QAAqB,SAAkB,KAAa;AACrF,MAAI,OAAO,YAAY,YAAY,YAAY,KAAM,QAAO;AAE5D,QAAM,IAAI;AACV,QAAM,SACJ,OAAO,EAAE,YAAY,YAAY,EAAE,YAAY,OAC1C,EAAE,UACH;AAEN,MAAI,YAAY;AAEhB,MAAI,OAAO,KAAK,OAAO,EAAE,GAAG,MAAM,UAAU;AAC1C,gBAAY,EAAE,GAAG;AAAA,EACnB,WAAW,UAAU,OAAO,UAAU,OAAO,OAAO,GAAG,MAAM,UAAU;AACrE,gBAAY,OAAO,GAAG;AAAA,EACxB;AAEA,SAAO,OAAO,SAAS,KAAK,OAAO,GAAG;AACxC;;;;"}
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const React = require("react");
5
+ function _interopNamespaceDefault(e) {
6
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
7
+ if (e) {
8
+ for (const k in e) {
9
+ if (k !== "default") {
10
+ const d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: () => e[k]
14
+ });
15
+ }
16
+ }
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
22
+ const ChartContext = React__namespace.createContext(null);
23
+ function useChart() {
24
+ const ctx = React__namespace.useContext(ChartContext);
25
+ if (!ctx) {
26
+ throw new Error("useChart must be used within a <ChartContainer />");
27
+ }
28
+ return ctx;
29
+ }
30
+ exports.ChartContext = ChartContext;
31
+ exports.useChart = useChart;
32
+ //# sourceMappingURL=useChart.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChart.cjs","sources":["../../../../src/components/Chart/useChart.ts"],"sourcesContent":["import * as React from \"react\";\nimport type { ChartConfig } from \"./types\";\n\ntype ChartContextValue = {\n config: ChartConfig;\n};\n\nexport const ChartContext = React.createContext<ChartContextValue | null>(null);\n\n/** Access the nearest {@link ChartContainer}'s config. Throws if used outside a chart. */\nexport function useChart(): ChartContextValue {\n const ctx = React.useContext(ChartContext);\n if (!ctx) {\n throw new Error(\"useChart must be used within a <ChartContainer />\");\n }\n return ctx;\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAOO,MAAM,eAAeA,iBAAM,cAAwC,IAAI;AAGvE,SAAS,WAA8B;AAC5C,QAAM,MAAMA,iBAAM,WAAW,YAAY;AACzC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,SAAO;AACT;;;"}
@@ -56,10 +56,6 @@ function getContainerClassName(size, error, disabled) {
56
56
  function getInputClassName(size) {
57
57
  return cn.cn(
58
58
  "h-full min-w-0 flex-1 rounded-xl bg-transparent text-foreground-default no-underline placeholder:text-foreground-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed",
59
- // Override browser autofill background so it fills the full container consistently
60
- "[&:-webkit-autofill]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)] [&:-webkit-autofill]:[-webkit-text-fill-color:var(--color-foreground-default)]",
61
- "[&:-webkit-autofill:hover]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)]",
62
- "[&:-webkit-autofill:focus]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)]",
63
59
  INPUT_SIZE_CLASSES[size]
64
60
  );
65
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.cjs","sources":["../../../../src/components/TextField/TextField.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CheckOutlineIcon } from \"@/index\";\nimport { cn } from \"../../utils/cn\";\n\n/** Text field height in pixels. */\nexport type TextFieldSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> {\n /** Label text displayed above the input. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the input. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the text field in pixels. @default \"48\" */\n size?: TextFieldSize;\n /** Whether the text field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the input. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text field is validated. @default false */\n validated?: boolean;\n /** Icon element displayed at the left side of the input. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed at the right side of the input. */\n rightIcon?: React.ReactNode;\n /** Whether the text field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n}\n\nconst CONTAINER_HEIGHT: Record<TextFieldSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<TextFieldSize, string> = {\n \"48\": \"py-3 typography-regular-body-lg\",\n \"40\": \"py-2 typography-regular-body-lg\",\n \"32\": \"py-2 typography-regular-body-md\",\n};\n\nconst PADDING_HORIZONTAL: Record<TextFieldSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst ICON_SPACING: Record<TextFieldSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nfunction getContainerClassName(size: TextFieldSize, error: boolean, disabled?: boolean) {\n return cn(\n \"flex items-center rounded-xl border bg-neutral-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-default\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-400\",\n CONTAINER_HEIGHT[size],\n PADDING_HORIZONTAL[size],\n ICON_SPACING[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getInputClassName(size: TextFieldSize) {\n return cn(\n \"h-full min-w-0 flex-1 rounded-xl bg-transparent text-foreground-default no-underline placeholder:text-foreground-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n // Override browser autofill background so it fills the full container consistently\n \"[&:-webkit-autofill]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)] [&:-webkit-autofill]:[-webkit-text-fill-color:var(--color-foreground-default)]\",\n \"[&:-webkit-autofill:hover]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)]\",\n \"[&:-webkit-autofill:focus]:[box-shadow:inset_0_0_0_1000px_var(--color-neutral-100)]\",\n INPUT_SIZE_CLASSES[size],\n );\n}\n\nfunction TextFieldIcon({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-foreground-secondary\">\n {children}\n </div>\n );\n}\n\nfunction TextFieldHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-default\" : \"text-foreground-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextField: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n/**\n * A text input field with optional label, helper/error text, and icon slots.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextField\n * label=\"Email\"\n * placeholder=\"you@example.com\"\n * error={!!emailError}\n * errorMessage={emailError}\n * />\n * ```\n */\nexport const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n leftIcon,\n rightIcon,\n className,\n id,\n disabled,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-foreground-default\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n {leftIcon && <TextFieldIcon>{leftIcon}</TextFieldIcon>}\n\n <input\n ref={ref}\n id={inputId}\n disabled={disabled}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n getInputClassName(size),\n // Hide native clear button for input[type=\"search\"] in WebKit browsers (Safari/Chrome)\n \"[&[type='search']::-webkit-search-cancel-button]:hidden [&[type='search']::-webkit-search-cancel-button]:appearance-none\",\n )}\n {...props}\n />\n\n {rightIcon && <TextFieldIcon>{rightIcon}</TextFieldIcon>}\n {validated && (\n <TextFieldIcon>\n <CheckOutlineIcon className=\"text-success-default\" />\n </TextFieldIcon>\n )}\n </div>\n\n {bottomText && (\n <TextFieldHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextFieldHelperText>\n )}\n </div>\n );\n },\n);\n\nTextField.displayName = \"TextField\";\n"],"names":["cn","jsx","React","jsxs","CheckOutlineIcon"],"mappings":"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"}
1
+ {"version":3,"file":"TextField.cjs","sources":["../../../../src/components/TextField/TextField.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CheckOutlineIcon } from \"@/index\";\nimport { cn } from \"../../utils/cn\";\n\n/** Text field height in pixels. */\nexport type TextFieldSize = \"48\" | \"40\" | \"32\";\n\nexport interface TextFieldProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"size\" | \"prefix\"> {\n /** Label text displayed above the input. Also used as the accessible name. */\n label?: string;\n /** Helper text displayed below the input. Replaced by `errorMessage` when `error` is `true`. */\n helperText?: string;\n /** Height of the text field in pixels. @default \"48\" */\n size?: TextFieldSize;\n /** Whether the text field is in an error state. @default false */\n error?: boolean;\n /** Error message displayed below the input. Shown instead of `helperText` when `error` is `true`. */\n errorMessage?: string;\n /** Whether the text field is validated. @default false */\n validated?: boolean;\n /** Icon element displayed at the left side of the input. */\n leftIcon?: React.ReactNode;\n /** Icon element displayed at the right side of the input. */\n rightIcon?: React.ReactNode;\n /** Whether the text field stretches to fill its container width. @default false */\n fullWidth?: boolean;\n}\n\nconst CONTAINER_HEIGHT: Record<TextFieldSize, string> = {\n \"48\": \"h-12\",\n \"40\": \"h-10\",\n \"32\": \"h-8\",\n};\n\nconst INPUT_SIZE_CLASSES: Record<TextFieldSize, string> = {\n \"48\": \"py-3 typography-regular-body-lg\",\n \"40\": \"py-2 typography-regular-body-lg\",\n \"32\": \"py-2 typography-regular-body-md\",\n};\n\nconst PADDING_HORIZONTAL: Record<TextFieldSize, string> = {\n \"48\": \"px-4\",\n \"40\": \"px-4\",\n \"32\": \"px-3\",\n};\n\nconst ICON_SPACING: Record<TextFieldSize, string> = {\n \"48\": \"gap-3\",\n \"40\": \"gap-3\",\n \"32\": \"gap-2\",\n};\n\nfunction getContainerClassName(size: TextFieldSize, error: boolean, disabled?: boolean) {\n return cn(\n \"flex items-center rounded-xl border bg-neutral-100 has-focus-visible:outline-none motion-safe:transition-colors\",\n error ? \"border-error-default\" : \"border-transparent\",\n !disabled && !error && \"hover:border-neutral-400\",\n CONTAINER_HEIGHT[size],\n PADDING_HORIZONTAL[size],\n ICON_SPACING[size],\n disabled && \"opacity-50\",\n );\n}\n\nfunction getInputClassName(size: TextFieldSize) {\n return cn(\n \"h-full min-w-0 flex-1 rounded-xl bg-transparent text-foreground-default no-underline placeholder:text-foreground-secondary placeholder:opacity-40 focus:outline-none disabled:cursor-not-allowed\",\n INPUT_SIZE_CLASSES[size],\n );\n}\n\nfunction TextFieldIcon({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"flex size-5 shrink-0 items-center justify-center text-foreground-secondary\">\n {children}\n </div>\n );\n}\n\nfunction TextFieldHelperText({\n id,\n error,\n children,\n}: {\n id: string;\n error: boolean;\n children: React.ReactNode;\n}) {\n return (\n <p\n id={id}\n className={cn(\n \"typography-regular-body-sm px-2 pt-1 pb-0.5\",\n error ? \"text-error-default\" : \"text-foreground-secondary\",\n )}\n >\n {children}\n </p>\n );\n}\n\nfunction warnMissingAccessibleName(label?: string, ariaLabel?: string, ariaLabelledBy?: string) {\n if (process.env.NODE_ENV !== \"production\") {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n \"TextField: no accessible name provided. Pass a `label`, `aria-label`, or `aria-labelledby` prop.\",\n );\n }\n }\n}\n\n/**\n * A text input field with optional label, helper/error text, and icon slots.\n *\n * Provide at least one of `label`, `aria-label`, or `aria-labelledby` for\n * accessibility — a console warning is emitted in development if none are set.\n *\n * @example\n * ```tsx\n * <TextField\n * label=\"Email\"\n * placeholder=\"you@example.com\"\n * error={!!emailError}\n * errorMessage={emailError}\n * />\n * ```\n */\nexport const TextField = React.forwardRef<HTMLInputElement, TextFieldProps>(\n (\n {\n label,\n helperText,\n size = \"48\",\n error = false,\n errorMessage,\n validated = false,\n leftIcon,\n rightIcon,\n className,\n id,\n disabled,\n fullWidth = false,\n ...props\n },\n ref,\n ) => {\n const generatedId = React.useId();\n const inputId = id || generatedId;\n const helperTextId = `${inputId}-helper`;\n const bottomText = error && errorMessage ? errorMessage : helperText;\n\n warnMissingAccessibleName(label, props[\"aria-label\"], props[\"aria-labelledby\"]);\n\n return (\n <div\n className={cn(\"flex flex-col\", fullWidth && \"w-full\", className)}\n data-disabled={disabled ? \"\" : undefined}\n data-error={error ? \"\" : undefined}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"typography-semibold-body-sm px-1 pt-1 pb-2 text-foreground-default\"\n >\n {label}\n </label>\n )}\n\n <div className={getContainerClassName(size, error, disabled)}>\n {leftIcon && <TextFieldIcon>{leftIcon}</TextFieldIcon>}\n\n <input\n ref={ref}\n id={inputId}\n disabled={disabled}\n aria-describedby={bottomText ? helperTextId : undefined}\n aria-invalid={error || undefined}\n className={cn(\n getInputClassName(size),\n // Hide native clear button for input[type=\"search\"] in WebKit browsers (Safari/Chrome)\n \"[&[type='search']::-webkit-search-cancel-button]:hidden [&[type='search']::-webkit-search-cancel-button]:appearance-none\",\n )}\n {...props}\n />\n\n {rightIcon && <TextFieldIcon>{rightIcon}</TextFieldIcon>}\n {validated && (\n <TextFieldIcon>\n <CheckOutlineIcon className=\"text-success-default\" />\n </TextFieldIcon>\n )}\n </div>\n\n {bottomText && (\n <TextFieldHelperText id={helperTextId} error={error}>\n {bottomText}\n </TextFieldHelperText>\n )}\n </div>\n );\n },\n);\n\nTextField.displayName = \"TextField\";\n"],"names":["cn","jsx","React","jsxs","CheckOutlineIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA6BA,MAAM,mBAAkD;AAAA,EACtD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,qBAAoD;AAAA,EACxD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,qBAAoD;AAAA,EACxD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,eAA8C;AAAA,EAClD,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAEA,SAAS,sBAAsB,MAAqB,OAAgB,UAAoB;AACtF,SAAOA,GAAAA;AAAAA,IACL;AAAA,IACA,QAAQ,yBAAyB;AAAA,IACjC,CAAC,YAAY,CAAC,SAAS;AAAA,IACvB,iBAAiB,IAAI;AAAA,IACrB,mBAAmB,IAAI;AAAA,IACvB,aAAa,IAAI;AAAA,IACjB,YAAY;AAAA,EAAA;AAEhB;AAEA,SAAS,kBAAkB,MAAqB;AAC9C,SAAOA,GAAAA;AAAAA,IACL;AAAA,IACA,mBAAmB,IAAI;AAAA,EAAA;AAE3B;AAEA,SAAS,cAAc,EAAE,YAA2C;AAClE,SACEC,2BAAAA,IAAC,OAAA,EAAI,WAAU,8EACZ,SAAA,CACH;AAEJ;AAEA,SAAS,oBAAoB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,SACEA,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACA,WAAWD,GAAAA;AAAAA,QACT;AAAA,QACA,QAAQ,uBAAuB;AAAA,MAAA;AAAA,MAGhC;AAAA,IAAA;AAAA,EAAA;AAGP;AAEA,SAAS,0BAA0B,OAAgB,WAAoB,gBAAyB;AAC9F,MAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,QAAI,CAAC,SAAS,CAAC,aAAa,CAAC,gBAAgB;AAC3C,cAAQ;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAkBO,MAAM,YAAYE,iBAAM;AAAA,EAC7B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,cAAcA,iBAAM,MAAA;AAC1B,UAAM,UAAU,MAAM;AACtB,UAAM,eAAe,GAAG,OAAO;AAC/B,UAAM,aAAa,SAAS,eAAe,eAAe;AAE1D,8BAA0B,OAAO,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC;AAE9E,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAWH,GAAAA,GAAG,iBAAiB,aAAa,UAAU,SAAS;AAAA,QAC/D,iBAAe,WAAW,KAAK;AAAA,QAC/B,cAAY,QAAQ,KAAK;AAAA,QAExB,UAAA;AAAA,UAAA,SACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS;AAAA,cACT,WAAU;AAAA,cAET,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,0CAIJ,OAAA,EAAI,WAAW,sBAAsB,MAAM,OAAO,QAAQ,GACxD,UAAA;AAAA,YAAA,YAAYA,2BAAAA,IAAC,iBAAe,UAAA,SAAA,CAAS;AAAA,YAEtCA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA,IAAI;AAAA,gBACJ;AAAA,gBACA,oBAAkB,aAAa,eAAe;AAAA,gBAC9C,gBAAc,SAAS;AAAA,gBACvB,WAAWD,GAAAA;AAAAA,kBACT,kBAAkB,IAAI;AAAA;AAAA,kBAEtB;AAAA,gBAAA;AAAA,gBAED,GAAG;AAAA,cAAA;AAAA,YAAA;AAAA,YAGL,aAAaC,2BAAAA,IAAC,eAAA,EAAe,UAAA,UAAA,CAAU;AAAA,YACvC,aACCA,2BAAAA,IAAC,eAAA,EACC,yCAACG,iBAAAA,kBAAA,EAAiB,WAAU,wBAAuB,EAAA,CACrD;AAAA,UAAA,GAEJ;AAAA,UAEC,cACCH,2BAAAA,IAAC,qBAAA,EAAoB,IAAI,cAAc,OACpC,UAAA,WAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,UAAU,cAAc;;"}