@handled-ai/design-system 0.18.4 → 0.18.6
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/chart.d.ts +1 -1
- package/dist/charts/empty-chart-state.d.ts +11 -0
- package/dist/charts/empty-chart-state.js +70 -0
- package/dist/charts/empty-chart-state.js.map +1 -0
- package/dist/charts/index.d.ts +1 -0
- package/dist/charts/index.js +1 -0
- package/dist/charts/index.js.map +1 -1
- package/dist/charts/pipeline-overview.d.ts +2 -1
- package/dist/charts/pipeline-overview.js +32 -1
- package/dist/charts/pipeline-overview.js.map +1 -1
- package/dist/components/days-open-cell.d.ts +16 -0
- package/dist/components/days-open-cell.js +73 -0
- package/dist/components/days-open-cell.js.map +1 -0
- package/dist/components/detail-drawer.d.ts +16 -0
- package/dist/components/detail-drawer.js +45 -0
- package/dist/components/detail-drawer.js.map +1 -0
- package/dist/components/insights-filter-bar.d.ts +2 -1
- package/dist/components/insights-filter-bar.js +13 -5
- package/dist/components/insights-filter-bar.js.map +1 -1
- package/dist/components/linked-entity-cell.d.ts +14 -0
- package/dist/components/linked-entity-cell.js +96 -0
- package/dist/components/linked-entity-cell.js.map +1 -0
- package/dist/components/metric-card.d.ts +14 -1
- package/dist/components/metric-card.js +97 -0
- package/dist/components/metric-card.js.map +1 -1
- package/dist/components/pill.d.ts +26 -0
- package/dist/components/pill.js +77 -0
- package/dist/components/pill.js.map +1 -0
- package/dist/components/quick-segment.d.ts +13 -0
- package/dist/components/quick-segment.js +96 -0
- package/dist/components/quick-segment.js.map +1 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -3
- package/src/charts/__tests__/insights-charts.test.tsx +62 -0
- package/src/charts/empty-chart-state.tsx +44 -0
- package/src/charts/index.ts +1 -0
- package/src/charts/pipeline-overview.tsx +41 -1
- package/src/components/__tests__/insights-primitives.test.tsx +135 -0
- package/src/components/days-open-cell.tsx +50 -0
- package/src/components/detail-drawer.tsx +60 -0
- package/src/components/insights-filter-bar.tsx +13 -4
- package/src/components/linked-entity-cell.tsx +74 -0
- package/src/components/metric-card.tsx +98 -0
- package/src/components/pill.tsx +67 -0
- package/src/components/quick-segment.tsx +68 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defProps = Object.defineProperties;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __spreadValues = (a, b) => {
|
|
12
|
+
for (var prop in b || (b = {}))
|
|
13
|
+
if (__hasOwnProp.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
if (__getOwnPropSymbols)
|
|
16
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
+
if (__propIsEnum.call(b, prop))
|
|
18
|
+
__defNormalProp(a, prop, b[prop]);
|
|
19
|
+
}
|
|
20
|
+
return a;
|
|
21
|
+
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
var __objRest = (source, exclude) => {
|
|
24
|
+
var target = {};
|
|
25
|
+
for (var prop in source)
|
|
26
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
27
|
+
target[prop] = source[prop];
|
|
28
|
+
if (source != null && __getOwnPropSymbols)
|
|
29
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
30
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
31
|
+
target[prop] = source[prop];
|
|
32
|
+
}
|
|
33
|
+
return target;
|
|
34
|
+
};
|
|
35
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
36
|
+
import { ExternalLink } from "lucide-react";
|
|
37
|
+
import { cn } from "../lib/utils.js";
|
|
38
|
+
function LinkedEntityCell(_a) {
|
|
39
|
+
var _b = _a, {
|
|
40
|
+
name,
|
|
41
|
+
href,
|
|
42
|
+
subtitle,
|
|
43
|
+
meta,
|
|
44
|
+
icon,
|
|
45
|
+
external = false,
|
|
46
|
+
onNavigate,
|
|
47
|
+
className
|
|
48
|
+
} = _b, props = __objRest(_b, [
|
|
49
|
+
"name",
|
|
50
|
+
"href",
|
|
51
|
+
"subtitle",
|
|
52
|
+
"meta",
|
|
53
|
+
"icon",
|
|
54
|
+
"external",
|
|
55
|
+
"onNavigate",
|
|
56
|
+
"className"
|
|
57
|
+
]);
|
|
58
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
59
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: name }),
|
|
60
|
+
external ? /* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3 shrink-0 opacity-60", "aria-hidden": "true" }) : null
|
|
61
|
+
] });
|
|
62
|
+
return /* @__PURE__ */ jsxs(
|
|
63
|
+
"div",
|
|
64
|
+
__spreadProps(__spreadValues({
|
|
65
|
+
"data-slot": "linked-entity-cell",
|
|
66
|
+
className: cn("flex min-w-0 items-center gap-2", className)
|
|
67
|
+
}, props), {
|
|
68
|
+
children: [
|
|
69
|
+
icon ? /* @__PURE__ */ jsx("span", { "data-slot": "linked-entity-cell-icon", className: "shrink-0 text-muted-foreground", children: icon }) : null,
|
|
70
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
71
|
+
href ? /* @__PURE__ */ jsx(
|
|
72
|
+
"a",
|
|
73
|
+
{
|
|
74
|
+
"data-slot": "linked-entity-cell-link",
|
|
75
|
+
href,
|
|
76
|
+
target: external ? "_blank" : void 0,
|
|
77
|
+
rel: external ? "noreferrer" : void 0,
|
|
78
|
+
onClick: onNavigate,
|
|
79
|
+
className: "inline-flex max-w-full items-center gap-1 truncate font-medium text-foreground underline-offset-4 hover:text-primary hover:underline",
|
|
80
|
+
children: content
|
|
81
|
+
}
|
|
82
|
+
) : /* @__PURE__ */ jsx("span", { "data-slot": "linked-entity-cell-name", className: "block truncate font-medium text-foreground", children: name }),
|
|
83
|
+
subtitle || meta ? /* @__PURE__ */ jsxs("div", { "data-slot": "linked-entity-cell-meta", className: "mt-0.5 truncate text-xs text-muted-foreground", children: [
|
|
84
|
+
subtitle,
|
|
85
|
+
subtitle && meta ? /* @__PURE__ */ jsx("span", { className: "px-1", children: "\xB7" }) : null,
|
|
86
|
+
meta
|
|
87
|
+
] }) : null
|
|
88
|
+
] })
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
LinkedEntityCell
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=linked-entity-cell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/linked-entity-cell.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ExternalLink } from \"lucide-react\"\n\nimport { cn } from \"../lib/utils\"\n\nexport interface LinkedEntityCellProps extends React.HTMLAttributes<HTMLDivElement> {\n name: React.ReactNode\n href?: string\n subtitle?: React.ReactNode\n meta?: React.ReactNode\n icon?: React.ReactNode\n external?: boolean\n onNavigate?: () => void\n}\n\nexport function LinkedEntityCell({\n name,\n href,\n subtitle,\n meta,\n icon,\n external = false,\n onNavigate,\n className,\n ...props\n}: LinkedEntityCellProps) {\n const content = (\n <>\n <span className=\"truncate\">{name}</span>\n {external ? <ExternalLink className=\"h-3 w-3 shrink-0 opacity-60\" aria-hidden=\"true\" /> : null}\n </>\n )\n\n return (\n <div\n data-slot=\"linked-entity-cell\"\n className={cn(\"flex min-w-0 items-center gap-2\", className)}\n {...props}\n >\n {icon ? (\n <span data-slot=\"linked-entity-cell-icon\" className=\"shrink-0 text-muted-foreground\">\n {icon}\n </span>\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {href ? (\n <a\n data-slot=\"linked-entity-cell-link\"\n href={href}\n target={external ? \"_blank\" : undefined}\n rel={external ? \"noreferrer\" : undefined}\n onClick={onNavigate}\n className=\"inline-flex max-w-full items-center gap-1 truncate font-medium text-foreground underline-offset-4 hover:text-primary hover:underline\"\n >\n {content}\n </a>\n ) : (\n <span data-slot=\"linked-entity-cell-name\" className=\"block truncate font-medium text-foreground\">\n {name}\n </span>\n )}\n {subtitle || meta ? (\n <div data-slot=\"linked-entity-cell-meta\" className=\"mt-0.5 truncate text-xs text-muted-foreground\">\n {subtitle}\n {subtitle && meta ? <span className=\"px-1\">·</span> : null}\n {meta}\n </div>\n ) : null}\n </div>\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BI,mBACE,KADF;AA1BJ,SAAS,oBAAoB;AAE7B,SAAS,UAAU;AAYZ,SAAS,iBAAiB,IAUP;AAVO,eAC/B;AAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,EAzBF,IAiBiC,IAS5B,kBAT4B,IAS5B;AAAA,IARH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAM,UACJ,iCACE;AAAA,wBAAC,UAAK,WAAU,YAAY,gBAAK;AAAA,IAChC,WAAW,oBAAC,gBAAa,WAAU,+BAA8B,eAAY,QAAO,IAAK;AAAA,KAC5F;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,mCAAmC,SAAS;AAAA,OACtD,QAHL;AAAA,MAKE;AAAA,eACC,oBAAC,UAAK,aAAU,2BAA0B,WAAU,kCACjD,gBACH,IACE;AAAA,QACJ,qBAAC,SAAI,WAAU,kBACZ;AAAA,iBACC;AAAA,YAAC;AAAA;AAAA,cACC,aAAU;AAAA,cACV;AAAA,cACA,QAAQ,WAAW,WAAW;AAAA,cAC9B,KAAK,WAAW,eAAe;AAAA,cAC/B,SAAS;AAAA,cACT,WAAU;AAAA,cAET;AAAA;AAAA,UACH,IAEA,oBAAC,UAAK,aAAU,2BAA0B,WAAU,8CACjD,gBACH;AAAA,UAED,YAAY,OACX,qBAAC,SAAI,aAAU,2BAA0B,WAAU,iDAChD;AAAA;AAAA,YACA,YAAY,OAAO,oBAAC,UAAK,WAAU,QAAO,kBAAC,IAAU;AAAA,YACrD;AAAA,aACH,IACE;AAAA,WACN;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -20,6 +20,19 @@ interface MetricCardProps {
|
|
|
20
20
|
showExternalLink?: boolean;
|
|
21
21
|
showInfo?: boolean;
|
|
22
22
|
}
|
|
23
|
+
interface KpiStripItem {
|
|
24
|
+
id?: string;
|
|
25
|
+
label: React.ReactNode;
|
|
26
|
+
value: React.ReactNode;
|
|
27
|
+
unit?: React.ReactNode;
|
|
28
|
+
subtitle?: React.ReactNode;
|
|
29
|
+
change?: MetricCardProps["change"];
|
|
30
|
+
}
|
|
31
|
+
interface KpiStripProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
32
|
+
items: KpiStripItem[];
|
|
33
|
+
columns?: 2 | 3 | 4;
|
|
34
|
+
}
|
|
35
|
+
declare function KpiStrip({ items, columns, className, ...props }: KpiStripProps): React.JSX.Element;
|
|
23
36
|
declare function MetricCard({ title, value, unit, subtitle, change, footerText, dataPoints, showExternalLink, showInfo, }: MetricCardProps): React.JSX.Element;
|
|
24
37
|
|
|
25
|
-
export { MetricCard, type MetricCardProps, type MetricDataPoint };
|
|
38
|
+
export { KpiStrip, type KpiStripItem, type KpiStripProps, MetricCard, type MetricCardProps, type MetricDataPoint };
|
|
@@ -1,6 +1,102 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
1
32
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
33
|
import { ArrowUp, ArrowDown, Info, ExternalLink } from "lucide-react";
|
|
3
34
|
import { cn } from "../lib/utils.js";
|
|
35
|
+
function getChangePresentation(change) {
|
|
36
|
+
if (!change) return null;
|
|
37
|
+
if (change.direction === "neutral") {
|
|
38
|
+
return { icon: null, className: "text-muted-foreground" };
|
|
39
|
+
}
|
|
40
|
+
const isGoodDirection = change.isGood !== void 0 ? change.isGood : change.direction === "up";
|
|
41
|
+
return {
|
|
42
|
+
icon: change.direction === "down" ? ArrowDown : ArrowUp,
|
|
43
|
+
className: isGoodDirection ? "text-emerald-600" : "text-red-600"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function KpiStrip(_a) {
|
|
47
|
+
var _b = _a, { items, columns = 4, className } = _b, props = __objRest(_b, ["items", "columns", "className"]);
|
|
48
|
+
return /* @__PURE__ */ jsx(
|
|
49
|
+
"div",
|
|
50
|
+
__spreadProps(__spreadValues({
|
|
51
|
+
"data-slot": "kpi-strip",
|
|
52
|
+
className: cn(
|
|
53
|
+
"grid gap-3 rounded-xl border border-border bg-card p-3 shadow-sm",
|
|
54
|
+
columns === 2 && "sm:grid-cols-2",
|
|
55
|
+
columns === 3 && "sm:grid-cols-3",
|
|
56
|
+
columns === 4 && "sm:grid-cols-2 lg:grid-cols-4",
|
|
57
|
+
className
|
|
58
|
+
)
|
|
59
|
+
}, props), {
|
|
60
|
+
children: items.map((item, index) => {
|
|
61
|
+
var _a2;
|
|
62
|
+
const changePresentation = getChangePresentation(item.change);
|
|
63
|
+
const ChangeIcon = changePresentation == null ? void 0 : changePresentation.icon;
|
|
64
|
+
return /* @__PURE__ */ jsxs(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
"data-slot": "kpi-strip-item",
|
|
68
|
+
className: "min-w-0 rounded-lg bg-muted/40 px-3 py-2",
|
|
69
|
+
children: [
|
|
70
|
+
/* @__PURE__ */ jsx("div", { "data-slot": "kpi-strip-label", className: "truncate text-xs font-medium text-muted-foreground", children: item.label }),
|
|
71
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-baseline gap-1", children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "kpi-strip-value", className: "truncate text-2xl font-bold tracking-tight text-foreground", children: item.value }),
|
|
73
|
+
item.unit ? /* @__PURE__ */ jsx("span", { "data-slot": "kpi-strip-unit", className: "text-sm font-semibold text-muted-foreground", children: item.unit }) : null
|
|
74
|
+
] }),
|
|
75
|
+
item.subtitle || item.change ? /* @__PURE__ */ jsxs("div", { className: "mt-1 flex items-center gap-2 text-xs", children: [
|
|
76
|
+
item.change ? /* @__PURE__ */ jsxs(
|
|
77
|
+
"span",
|
|
78
|
+
{
|
|
79
|
+
"data-slot": "kpi-strip-change",
|
|
80
|
+
className: cn(
|
|
81
|
+
"inline-flex items-center gap-0.5 font-semibold",
|
|
82
|
+
changePresentation == null ? void 0 : changePresentation.className
|
|
83
|
+
),
|
|
84
|
+
children: [
|
|
85
|
+
ChangeIcon ? /* @__PURE__ */ jsx(ChangeIcon, { className: "h-3 w-3 stroke-[3]" }) : null,
|
|
86
|
+
item.change.value
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
) : null,
|
|
90
|
+
item.subtitle ? /* @__PURE__ */ jsx("span", { "data-slot": "kpi-strip-subtitle", className: "truncate text-muted-foreground", children: item.subtitle }) : null
|
|
91
|
+
] }) : null
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
(_a2 = item.id) != null ? _a2 : index
|
|
95
|
+
);
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
}
|
|
4
100
|
function MetricCard({
|
|
5
101
|
title,
|
|
6
102
|
value,
|
|
@@ -102,6 +198,7 @@ function MetricCard({
|
|
|
102
198
|
] });
|
|
103
199
|
}
|
|
104
200
|
export {
|
|
201
|
+
KpiStrip,
|
|
105
202
|
MetricCard
|
|
106
203
|
};
|
|
107
204
|
//# sourceMappingURL=metric-card.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/metric-card.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { ArrowUp, ArrowDown, Info, ExternalLink } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport interface MetricDataPoint {\n label: string\n value: number | string\n color?: string\n}\n\nexport interface MetricCardProps {\n title: string\n value?: string | number\n unit?: string\n subtitle?: string\n change?: { \n value: string\n direction: \"up\" | \"down\" | \"neutral\"\n isGood?: boolean // if true, up is green. if false, up is red (e.g. churn).\n }\n footerText?: string\n dataPoints?: MetricDataPoint[]\n showExternalLink?: boolean\n showInfo?: boolean\n}\n\nexport function MetricCard({\n title,\n value,\n unit,\n subtitle,\n change,\n footerText,\n dataPoints,\n showExternalLink,\n showInfo = true,\n}: MetricCardProps) {\n // SVG Donut Chart logic for variants with dataPoints\n const renderDonut = () => {\n if (!dataPoints || dataPoints.length === 0 || value === undefined) return null\n\n // Simple pseudo-donut chart logic assuming specific colors from the image\n // In a real prod environment we'd use recharts/visx, but for this standalone component\n // we can draw an SVG circle with stroke-dasharray based on the data\n const size = 80\n const strokeWidth = 12\n const radius = (size - strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n \n // Calculate total to distribute the circle\n const total = dataPoints.reduce((sum, dp) => sum + (typeof dp.value === 'number' ? dp.value : 0), 0)\n let currentOffset = 0\n\n return (\n <div className=\"relative\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"transform -rotate-90\">\n {dataPoints.map((dp, i) => {\n const val = typeof dp.value === 'number' ? dp.value : 0\n const percentage = val / total\n const strokeLength = percentage * circumference\n const offset = currentOffset\n currentOffset += strokeLength\n\n // Fallback colors matching the image's teal/green palette\n const colors = [\"#166534\", \"#22c55e\", \"#6ee7b7\", \"#ccfbf1\", \"#f1f5f9\"]\n const color = dp.color || colors[i % colors.length]\n\n return (\n <circle\n key={dp.label}\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={strokeWidth}\n strokeDasharray={`${Math.max(strokeLength - 2, 0)} ${circumference}`}\n strokeDashoffset={-offset}\n className=\"transition-all duration-300\"\n />\n )\n })}\n </svg>\n <div className=\"absolute inset-0 flex items-center justify-center flex-col\">\n <span className=\"text-xl font-bold text-foreground leading-none\">{value}</span>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col rounded-xl border border-border bg-card p-5 shadow-sm h-full w-full\">\n <div className={cn(\"flex justify-between items-start\", title ? \"mb-4\" : \"mb-4\")}>\n {title ? (\n <h3 className=\"font-semibold text-sm text-foreground/80\">{title}</h3>\n ) : (\n <div className=\"flex flex-col\">\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-3xl font-bold tracking-tight text-foreground\">{value}</span>\n {unit && <span className=\"text-2xl font-bold tracking-tight text-foreground\">{unit}</span>}\n </div>\n {subtitle && (\n <p className=\"text-sm font-medium text-muted-foreground mt-2\">{subtitle}</p>\n )}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 text-muted-foreground shrink-0 mt-0.5\">\n {showExternalLink && <ExternalLink className=\"w-3.5 h-3.5 cursor-pointer hover:text-foreground transition-colors\" />}\n {showInfo && <Info className=\"w-3.5 h-3.5 cursor-pointer hover:text-foreground transition-colors\" />}\n </div>\n </div>\n\n <div className=\"flex-1 flex flex-col min-w-0\">\n {dataPoints && dataPoints.length > 0 ? (\n // Donut Chart Variant\n <div className=\"flex items-center gap-4 mt-2 mb-6\">\n <div className=\"shrink-0\">\n {renderDonut()}\n </div>\n <div className=\"flex flex-col gap-2 flex-1 min-w-0\">\n {dataPoints.slice(0, 5).map((dp, i) => {\n const colors = [\"bg-[#166534]\", \"bg-[#22c55e]\", \"bg-[#6ee7b7]\", \"bg-[#ccfbf1]\", \"bg-[#f1f5f9]\"]\n return (\n <div key={dp.label} className=\"flex items-center justify-between gap-2 text-[11px] font-medium min-w-0\">\n <div className=\"flex items-center gap-1.5 text-muted-foreground min-w-0\">\n <div className={cn(\"w-1.5 h-1.5 rounded-full shrink-0\", dp.color ? \"\" : colors[i % colors.length])} style={dp.color ? { backgroundColor: dp.color } : {}} />\n <span className=\"whitespace-nowrap\">{dp.label}</span>\n </div>\n <span className=\"text-foreground font-semibold shrink-0\">{dp.value}</span>\n </div>\n )\n })}\n </div>\n </div>\n ) : title && (\n // Standard Big Number Variant (only if title exists)\n <div className=\"mb-6\">\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-4xl font-bold tracking-tight text-foreground\">{value}</span>\n {unit && <span className=\"text-2xl font-bold tracking-tight text-foreground\">{unit}</span>}\n </div>\n {subtitle && (\n <p className=\"text-sm font-medium text-muted-foreground mt-1\">{subtitle}</p>\n )}\n </div>\n )}\n\n {/* Footer section (Change indicator & extra text) */}\n <div className=\"mt-auto flex flex-col gap-1.5\">\n {change && (\n <div className=\"flex items-center gap-1\">\n {(() => {\n // Determine color based on isGood property\n // By default, up is green (good), down is red (bad)\n const isGoodDirection = change.isGood !== undefined \n ? change.isGood \n : change.direction === \"up\";\n \n const colorClass = isGoodDirection ? \"text-emerald-600\" : \"text-red-600\";\n const Icon = change.direction === \"down\" ? ArrowDown : ArrowUp;\n \n return (\n <span className={cn(\"text-xs font-semibold flex items-center gap-0.5\", colorClass)}>\n <Icon className=\"w-3 h-3 stroke-[3]\" />\n {change.value}\n </span>\n )\n })()}\n </div>\n )}\n {footerText && (\n <span className=\"text-[11px] text-muted-foreground font-medium\">{footerText}</span>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/metric-card.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { ArrowUp, ArrowDown, Info, ExternalLink } from \"lucide-react\"\nimport type { LucideIcon } from \"lucide-react\"\nimport { cn } from \"../lib/utils\"\n\nexport interface MetricDataPoint {\n label: string\n value: number | string\n color?: string\n}\n\nexport interface MetricCardProps {\n title: string\n value?: string | number\n unit?: string\n subtitle?: string\n change?: { \n value: string\n direction: \"up\" | \"down\" | \"neutral\"\n isGood?: boolean // if true, up is green. if false, up is red (e.g. churn).\n }\n footerText?: string\n dataPoints?: MetricDataPoint[]\n showExternalLink?: boolean\n showInfo?: boolean\n}\n\nexport interface KpiStripItem {\n id?: string\n label: React.ReactNode\n value: React.ReactNode\n unit?: React.ReactNode\n subtitle?: React.ReactNode\n change?: MetricCardProps[\"change\"]\n}\n\nexport interface KpiStripProps extends React.HTMLAttributes<HTMLDivElement> {\n items: KpiStripItem[]\n columns?: 2 | 3 | 4\n}\n\nfunction getChangePresentation(change: MetricCardProps[\"change\"]): {\n icon: LucideIcon | null\n className: string\n} | null {\n if (!change) return null\n if (change.direction === \"neutral\") {\n return { icon: null, className: \"text-muted-foreground\" }\n }\n\n const isGoodDirection = change.isGood !== undefined\n ? change.isGood\n : change.direction === \"up\"\n\n return {\n icon: change.direction === \"down\" ? ArrowDown : ArrowUp,\n className: isGoodDirection ? \"text-emerald-600\" : \"text-red-600\",\n }\n}\n\nexport function KpiStrip({ items, columns = 4, className, ...props }: KpiStripProps) {\n return (\n <div\n data-slot=\"kpi-strip\"\n className={cn(\n \"grid gap-3 rounded-xl border border-border bg-card p-3 shadow-sm\",\n columns === 2 && \"sm:grid-cols-2\",\n columns === 3 && \"sm:grid-cols-3\",\n columns === 4 && \"sm:grid-cols-2 lg:grid-cols-4\",\n className\n )}\n {...props}\n >\n {items.map((item, index) => {\n const changePresentation = getChangePresentation(item.change)\n const ChangeIcon = changePresentation?.icon\n\n return (\n <div\n key={item.id ?? index}\n data-slot=\"kpi-strip-item\"\n className=\"min-w-0 rounded-lg bg-muted/40 px-3 py-2\"\n >\n <div data-slot=\"kpi-strip-label\" className=\"truncate text-xs font-medium text-muted-foreground\">\n {item.label}\n </div>\n <div className=\"mt-1 flex items-baseline gap-1\">\n <span data-slot=\"kpi-strip-value\" className=\"truncate text-2xl font-bold tracking-tight text-foreground\">\n {item.value}\n </span>\n {item.unit ? (\n <span data-slot=\"kpi-strip-unit\" className=\"text-sm font-semibold text-muted-foreground\">\n {item.unit}\n </span>\n ) : null}\n </div>\n {item.subtitle || item.change ? (\n <div className=\"mt-1 flex items-center gap-2 text-xs\">\n {item.change ? (\n <span\n data-slot=\"kpi-strip-change\"\n className={cn(\n \"inline-flex items-center gap-0.5 font-semibold\",\n changePresentation?.className\n )}\n >\n {ChangeIcon ? <ChangeIcon className=\"h-3 w-3 stroke-[3]\" /> : null}\n {item.change.value}\n </span>\n ) : null}\n {item.subtitle ? (\n <span data-slot=\"kpi-strip-subtitle\" className=\"truncate text-muted-foreground\">\n {item.subtitle}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n })}\n </div>\n )\n}\n\nexport function MetricCard({\n title,\n value,\n unit,\n subtitle,\n change,\n footerText,\n dataPoints,\n showExternalLink,\n showInfo = true,\n}: MetricCardProps) {\n // SVG Donut Chart logic for variants with dataPoints\n const renderDonut = () => {\n if (!dataPoints || dataPoints.length === 0 || value === undefined) return null\n\n // Simple pseudo-donut chart logic assuming specific colors from the image\n // In a real prod environment we'd use recharts/visx, but for this standalone component\n // we can draw an SVG circle with stroke-dasharray based on the data\n const size = 80\n const strokeWidth = 12\n const radius = (size - strokeWidth) / 2\n const circumference = 2 * Math.PI * radius\n \n // Calculate total to distribute the circle\n const total = dataPoints.reduce((sum, dp) => sum + (typeof dp.value === 'number' ? dp.value : 0), 0)\n let currentOffset = 0\n\n return (\n <div className=\"relative\" style={{ width: size, height: size }}>\n <svg width={size} height={size} className=\"transform -rotate-90\">\n {dataPoints.map((dp, i) => {\n const val = typeof dp.value === 'number' ? dp.value : 0\n const percentage = val / total\n const strokeLength = percentage * circumference\n const offset = currentOffset\n currentOffset += strokeLength\n\n // Fallback colors matching the image's teal/green palette\n const colors = [\"#166534\", \"#22c55e\", \"#6ee7b7\", \"#ccfbf1\", \"#f1f5f9\"]\n const color = dp.color || colors[i % colors.length]\n\n return (\n <circle\n key={dp.label}\n cx={size / 2}\n cy={size / 2}\n r={radius}\n fill=\"none\"\n stroke={color}\n strokeWidth={strokeWidth}\n strokeDasharray={`${Math.max(strokeLength - 2, 0)} ${circumference}`}\n strokeDashoffset={-offset}\n className=\"transition-all duration-300\"\n />\n )\n })}\n </svg>\n <div className=\"absolute inset-0 flex items-center justify-center flex-col\">\n <span className=\"text-xl font-bold text-foreground leading-none\">{value}</span>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"flex flex-col rounded-xl border border-border bg-card p-5 shadow-sm h-full w-full\">\n <div className={cn(\"flex justify-between items-start\", title ? \"mb-4\" : \"mb-4\")}>\n {title ? (\n <h3 className=\"font-semibold text-sm text-foreground/80\">{title}</h3>\n ) : (\n <div className=\"flex flex-col\">\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-3xl font-bold tracking-tight text-foreground\">{value}</span>\n {unit && <span className=\"text-2xl font-bold tracking-tight text-foreground\">{unit}</span>}\n </div>\n {subtitle && (\n <p className=\"text-sm font-medium text-muted-foreground mt-2\">{subtitle}</p>\n )}\n </div>\n )}\n <div className=\"flex items-center gap-1.5 text-muted-foreground shrink-0 mt-0.5\">\n {showExternalLink && <ExternalLink className=\"w-3.5 h-3.5 cursor-pointer hover:text-foreground transition-colors\" />}\n {showInfo && <Info className=\"w-3.5 h-3.5 cursor-pointer hover:text-foreground transition-colors\" />}\n </div>\n </div>\n\n <div className=\"flex-1 flex flex-col min-w-0\">\n {dataPoints && dataPoints.length > 0 ? (\n // Donut Chart Variant\n <div className=\"flex items-center gap-4 mt-2 mb-6\">\n <div className=\"shrink-0\">\n {renderDonut()}\n </div>\n <div className=\"flex flex-col gap-2 flex-1 min-w-0\">\n {dataPoints.slice(0, 5).map((dp, i) => {\n const colors = [\"bg-[#166534]\", \"bg-[#22c55e]\", \"bg-[#6ee7b7]\", \"bg-[#ccfbf1]\", \"bg-[#f1f5f9]\"]\n return (\n <div key={dp.label} className=\"flex items-center justify-between gap-2 text-[11px] font-medium min-w-0\">\n <div className=\"flex items-center gap-1.5 text-muted-foreground min-w-0\">\n <div className={cn(\"w-1.5 h-1.5 rounded-full shrink-0\", dp.color ? \"\" : colors[i % colors.length])} style={dp.color ? { backgroundColor: dp.color } : {}} />\n <span className=\"whitespace-nowrap\">{dp.label}</span>\n </div>\n <span className=\"text-foreground font-semibold shrink-0\">{dp.value}</span>\n </div>\n )\n })}\n </div>\n </div>\n ) : title && (\n // Standard Big Number Variant (only if title exists)\n <div className=\"mb-6\">\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-4xl font-bold tracking-tight text-foreground\">{value}</span>\n {unit && <span className=\"text-2xl font-bold tracking-tight text-foreground\">{unit}</span>}\n </div>\n {subtitle && (\n <p className=\"text-sm font-medium text-muted-foreground mt-1\">{subtitle}</p>\n )}\n </div>\n )}\n\n {/* Footer section (Change indicator & extra text) */}\n <div className=\"mt-auto flex flex-col gap-1.5\">\n {change && (\n <div className=\"flex items-center gap-1\">\n {(() => {\n // Determine color based on isGood property\n // By default, up is green (good), down is red (bad)\n const isGoodDirection = change.isGood !== undefined \n ? change.isGood \n : change.direction === \"up\";\n \n const colorClass = isGoodDirection ? \"text-emerald-600\" : \"text-red-600\";\n const Icon = change.direction === \"down\" ? ArrowDown : ArrowUp;\n \n return (\n <span className={cn(\"text-xs font-semibold flex items-center gap-0.5\", colorClass)}>\n <Icon className=\"w-3 h-3 stroke-[3]\" />\n {change.value}\n </span>\n )\n })()}\n </div>\n )}\n {footerText && (\n <span className=\"text-[11px] text-muted-foreground font-medium\">{footerText}</span>\n )}\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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","names":["_a"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Insights-friendly pill convenience wrappers.
|
|
7
|
+
*
|
|
8
|
+
* Pill and StatusPill are small, rounded wrappers for dense Insights surfaces
|
|
9
|
+
* such as tables, KPI strips, and filter summaries. They intentionally wrap the
|
|
10
|
+
* existing Badge/StatusBadge visual language and are not a replacement for all
|
|
11
|
+
* Badge usage across the design system.
|
|
12
|
+
*/
|
|
13
|
+
type PillStatus = "success" | "warning" | "error" | "neutral" | "info";
|
|
14
|
+
declare const pillVariants: (props?: ({
|
|
15
|
+
variant?: "default" | "secondary" | "destructive" | "outline" | "ghost" | "error" | "neutral" | "info" | "warning" | "success" | null | undefined;
|
|
16
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
17
|
+
interface PillProps extends React.ComponentProps<"span">, VariantProps<typeof pillVariants> {
|
|
18
|
+
}
|
|
19
|
+
declare function Pill({ className, variant, ...props }: PillProps): React.JSX.Element;
|
|
20
|
+
interface StatusPillProps extends Omit<PillProps, "variant"> {
|
|
21
|
+
status: React.ReactNode;
|
|
22
|
+
intent?: PillStatus;
|
|
23
|
+
}
|
|
24
|
+
declare function StatusPill({ status, intent, children, ...props }: StatusPillProps): React.JSX.Element;
|
|
25
|
+
|
|
26
|
+
export { Pill, type PillProps, type PillStatus, StatusPill, type StatusPillProps, pillVariants };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __objRest = (source, exclude) => {
|
|
21
|
+
var target = {};
|
|
22
|
+
for (var prop in source)
|
|
23
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
24
|
+
target[prop] = source[prop];
|
|
25
|
+
if (source != null && __getOwnPropSymbols)
|
|
26
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
27
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
28
|
+
target[prop] = source[prop];
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
};
|
|
32
|
+
import { jsx } from "react/jsx-runtime";
|
|
33
|
+
import { cva } from "class-variance-authority";
|
|
34
|
+
import { cn } from "../lib/utils.js";
|
|
35
|
+
const pillVariants = cva(
|
|
36
|
+
"inline-flex w-fit shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors [&>svg]:size-3",
|
|
37
|
+
{
|
|
38
|
+
variants: {
|
|
39
|
+
variant: {
|
|
40
|
+
default: "border-transparent bg-primary text-primary-foreground",
|
|
41
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground",
|
|
42
|
+
destructive: "border-transparent bg-destructive text-white dark:bg-destructive/60",
|
|
43
|
+
outline: "border-border bg-background text-foreground",
|
|
44
|
+
ghost: "border-transparent bg-transparent text-muted-foreground",
|
|
45
|
+
success: "border-transparent bg-green-100 text-green-950 dark:bg-green-950 dark:text-green-100",
|
|
46
|
+
warning: "border-transparent bg-yellow-100 text-yellow-950 dark:bg-yellow-950 dark:text-yellow-100",
|
|
47
|
+
error: "border-transparent bg-red-100 text-red-950 dark:bg-red-950 dark:text-red-100",
|
|
48
|
+
neutral: "border-transparent bg-muted text-foreground",
|
|
49
|
+
info: "border-transparent bg-blue-100 text-blue-950 dark:bg-blue-950 dark:text-blue-100"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
defaultVariants: {
|
|
53
|
+
variant: "neutral"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
function Pill(_a) {
|
|
58
|
+
var _b = _a, { className, variant = "neutral" } = _b, props = __objRest(_b, ["className", "variant"]);
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
"span",
|
|
61
|
+
__spreadValues({
|
|
62
|
+
"data-slot": "pill",
|
|
63
|
+
"data-variant": variant,
|
|
64
|
+
className: cn(pillVariants({ variant }), className)
|
|
65
|
+
}, props)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function StatusPill(_c) {
|
|
69
|
+
var _d = _c, { status, intent = "neutral", children } = _d, props = __objRest(_d, ["status", "intent", "children"]);
|
|
70
|
+
return /* @__PURE__ */ jsx(Pill, __spreadProps(__spreadValues({ "data-slot": "status-pill", variant: intent }, props), { children: children != null ? children : status }));
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
Pill,
|
|
74
|
+
StatusPill,
|
|
75
|
+
pillVariants
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=pill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/pill.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../lib/utils\"\n\n/**\n * Insights-friendly pill convenience wrappers.\n *\n * Pill and StatusPill are small, rounded wrappers for dense Insights surfaces\n * such as tables, KPI strips, and filter summaries. They intentionally wrap the\n * existing Badge/StatusBadge visual language and are not a replacement for all\n * Badge usage across the design system.\n */\nexport type PillStatus = \"success\" | \"warning\" | \"error\" | \"neutral\" | \"info\"\n\nconst pillVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"border-transparent bg-primary text-primary-foreground\",\n secondary: \"border-transparent bg-secondary text-secondary-foreground\",\n destructive: \"border-transparent bg-destructive text-white dark:bg-destructive/60\",\n outline: \"border-border bg-background text-foreground\",\n ghost: \"border-transparent bg-transparent text-muted-foreground\",\n success: \"border-transparent bg-green-100 text-green-950 dark:bg-green-950 dark:text-green-100\",\n warning: \"border-transparent bg-yellow-100 text-yellow-950 dark:bg-yellow-950 dark:text-yellow-100\",\n error: \"border-transparent bg-red-100 text-red-950 dark:bg-red-950 dark:text-red-100\",\n neutral: \"border-transparent bg-muted text-foreground\",\n info: \"border-transparent bg-blue-100 text-blue-950 dark:bg-blue-950 dark:text-blue-100\",\n },\n },\n defaultVariants: {\n variant: \"neutral\",\n },\n }\n)\n\nexport interface PillProps\n extends React.ComponentProps<\"span\">,\n VariantProps<typeof pillVariants> {}\n\nexport function Pill({ className, variant = \"neutral\", ...props }: PillProps) {\n return (\n <span\n data-slot=\"pill\"\n data-variant={variant}\n className={cn(pillVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport interface StatusPillProps extends Omit<PillProps, \"variant\"> {\n status: React.ReactNode\n intent?: PillStatus\n}\n\nexport function StatusPill({ status, intent = \"neutral\", children, ...props }: StatusPillProps) {\n return (\n <Pill data-slot=\"status-pill\" variant={intent} {...props}>\n {children ?? status}\n </Pill>\n )\n}\n\nexport { pillVariants }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CI;AA3CJ,SAAS,WAA8B;AAEvC,SAAS,UAAU;AAYnB,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,WAAW;AAAA,QACX,aAAa;AAAA,QACb,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,OAAO;AAAA,QACP,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAMO,SAAS,KAAK,IAAyD;AAAzD,eAAE,aAAW,UAAU,UA1C5C,IA0CqB,IAAqC,kBAArC,IAAqC,CAAnC,aAAW;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAc;AAAA,MACd,WAAW,GAAG,aAAa,EAAE,QAAQ,CAAC,GAAG,SAAS;AAAA,OAC9C;AAAA,EACN;AAEJ;AAOO,SAAS,WAAW,IAAqE;AAArE,eAAE,UAAQ,SAAS,WAAW,SA1DzD,IA0D2B,IAA2C,kBAA3C,IAA2C,CAAzC,UAAQ,UAAoB;AACvD,SACE,oBAAC,qCAAK,aAAU,eAAc,SAAS,UAAY,QAAlD,EACE,wCAAY,SACf;AAEJ;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface QuickSegmentProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onSelect" | "value"> {
|
|
4
|
+
label: React.ReactNode;
|
|
5
|
+
value: string;
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
count?: number | string;
|
|
8
|
+
description?: React.ReactNode;
|
|
9
|
+
onSelect?: (value: string) => void;
|
|
10
|
+
}
|
|
11
|
+
declare function QuickSegment({ label, value, selected, count, description, onSelect, className, type, ...props }: QuickSegmentProps): React.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { QuickSegment, type QuickSegmentProps };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
"use client";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __defProps = Object.defineProperties;
|
|
6
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
10
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
11
|
+
var __spreadValues = (a, b) => {
|
|
12
|
+
for (var prop in b || (b = {}))
|
|
13
|
+
if (__hasOwnProp.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
if (__getOwnPropSymbols)
|
|
16
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
17
|
+
if (__propIsEnum.call(b, prop))
|
|
18
|
+
__defNormalProp(a, prop, b[prop]);
|
|
19
|
+
}
|
|
20
|
+
return a;
|
|
21
|
+
};
|
|
22
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
23
|
+
var __objRest = (source, exclude) => {
|
|
24
|
+
var target = {};
|
|
25
|
+
for (var prop in source)
|
|
26
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
27
|
+
target[prop] = source[prop];
|
|
28
|
+
if (source != null && __getOwnPropSymbols)
|
|
29
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
30
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
31
|
+
target[prop] = source[prop];
|
|
32
|
+
}
|
|
33
|
+
return target;
|
|
34
|
+
};
|
|
35
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
36
|
+
import { cn } from "../lib/utils.js";
|
|
37
|
+
function QuickSegment(_a) {
|
|
38
|
+
var _b = _a, {
|
|
39
|
+
label,
|
|
40
|
+
value,
|
|
41
|
+
selected = false,
|
|
42
|
+
count,
|
|
43
|
+
description,
|
|
44
|
+
onSelect,
|
|
45
|
+
className,
|
|
46
|
+
type = "button"
|
|
47
|
+
} = _b, props = __objRest(_b, [
|
|
48
|
+
"label",
|
|
49
|
+
"value",
|
|
50
|
+
"selected",
|
|
51
|
+
"count",
|
|
52
|
+
"description",
|
|
53
|
+
"onSelect",
|
|
54
|
+
"className",
|
|
55
|
+
"type"
|
|
56
|
+
]);
|
|
57
|
+
return /* @__PURE__ */ jsxs(
|
|
58
|
+
"button",
|
|
59
|
+
__spreadProps(__spreadValues({
|
|
60
|
+
"data-slot": "quick-segment",
|
|
61
|
+
"data-selected": selected ? "true" : "false",
|
|
62
|
+
type,
|
|
63
|
+
"aria-pressed": selected,
|
|
64
|
+
className: cn(
|
|
65
|
+
"inline-flex min-h-8 items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium transition-colors",
|
|
66
|
+
selected ? "border-primary bg-primary text-primary-foreground shadow-sm" : "border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
67
|
+
className
|
|
68
|
+
),
|
|
69
|
+
onClick: (event) => {
|
|
70
|
+
var _a2;
|
|
71
|
+
(_a2 = props.onClick) == null ? void 0 : _a2.call(props, event);
|
|
72
|
+
if (!event.defaultPrevented) onSelect == null ? void 0 : onSelect(value);
|
|
73
|
+
}
|
|
74
|
+
}, props), {
|
|
75
|
+
children: [
|
|
76
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "quick-segment-label", children: label }),
|
|
77
|
+
count !== void 0 ? /* @__PURE__ */ jsx(
|
|
78
|
+
"span",
|
|
79
|
+
{
|
|
80
|
+
"data-slot": "quick-segment-count",
|
|
81
|
+
className: cn(
|
|
82
|
+
"rounded-full px-1.5 py-0.5 text-[11px] leading-none",
|
|
83
|
+
selected ? "bg-primary-foreground/20 text-primary-foreground" : "bg-muted text-muted-foreground"
|
|
84
|
+
),
|
|
85
|
+
children: count
|
|
86
|
+
}
|
|
87
|
+
) : null,
|
|
88
|
+
description ? /* @__PURE__ */ jsx("span", { "data-slot": "quick-segment-description", className: "sr-only", children: description }) : null
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
QuickSegment
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=quick-segment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/quick-segment.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"../lib/utils\"\n\nexport interface QuickSegmentProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"onSelect\" | \"value\"> {\n label: React.ReactNode\n value: string\n selected?: boolean\n count?: number | string\n description?: React.ReactNode\n onSelect?: (value: string) => void\n}\n\nexport function QuickSegment({\n label,\n value,\n selected = false,\n count,\n description,\n onSelect,\n className,\n type = \"button\",\n ...props\n}: QuickSegmentProps) {\n return (\n <button\n data-slot=\"quick-segment\"\n data-selected={selected ? \"true\" : \"false\"}\n type={type}\n aria-pressed={selected}\n className={cn(\n \"inline-flex min-h-8 items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium transition-colors\",\n selected\n ? \"border-primary bg-primary text-primary-foreground shadow-sm\"\n : \"border-border bg-background text-muted-foreground hover:bg-muted hover:text-foreground\",\n className\n )}\n onClick={(event) => {\n props.onClick?.(event)\n if (!event.defaultPrevented) onSelect?.(value)\n }}\n {...props}\n >\n <span data-slot=\"quick-segment-label\">{label}</span>\n {count !== undefined ? (\n <span\n data-slot=\"quick-segment-count\"\n className={cn(\n \"rounded-full px-1.5 py-0.5 text-[11px] leading-none\",\n selected\n ? \"bg-primary-foreground/20 text-primary-foreground\"\n : \"bg-muted text-muted-foreground\"\n )}\n >\n {count}\n </span>\n ) : null}\n {description ? (\n <span data-slot=\"quick-segment-description\" className=\"sr-only\">\n {description}\n </span>\n ) : null}\n </button>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BI,SAkBE,KAlBF;AAxBJ,SAAS,UAAU;AAYZ,SAAS,aAAa,IAUP;AAVO,eAC3B;AAAA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,EAxBT,IAgB6B,IASxB,kBATwB,IASxB;AAAA,IARH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,iBAAe,WAAW,SAAS;AAAA,MACnC;AAAA,MACA,gBAAc;AAAA,MACd,WAAW;AAAA,QACT;AAAA,QACA,WACI,gEACA;AAAA,QACJ;AAAA,MACF;AAAA,MACA,SAAS,CAAC,UAAU;AAxC1B,YAAAA;AAyCQ,SAAAA,MAAA,MAAM,YAAN,gBAAAA,IAAA,YAAgB;AAChB,YAAI,CAAC,MAAM,iBAAkB,sCAAW;AAAA,MAC1C;AAAA,OACI,QAhBL;AAAA,MAkBC;AAAA,4BAAC,UAAK,aAAU,uBAAuB,iBAAM;AAAA,QAC5C,UAAU,SACT;AAAA,UAAC;AAAA;AAAA,YACC,aAAU;AAAA,YACV,WAAW;AAAA,cACT;AAAA,cACA,WACI,qDACA;AAAA,YACN;AAAA,YAEC;AAAA;AAAA,QACH,IACE;AAAA,QACH,cACC,oBAAC,UAAK,aAAU,6BAA4B,WAAU,WACnD,uBACH,IACE;AAAA;AAAA;AAAA,EACN;AAEJ;","names":["_a"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export { DataTableFilter, DataTableFilterCategory, DataTableFilterProps, FilterO
|
|
|
23
23
|
export { DataTableQuickViewValue, DataTableQuickViews } from './components/data-table-quick-views.js';
|
|
24
24
|
export { DataTableToolbar } from './components/data-table-toolbar.js';
|
|
25
25
|
export { Citation, DetailViewHeader, DetailViewSummary, DetailViewThread, SourceDef, SourceList, ThreadMessage } from './components/detail-view.js';
|
|
26
|
+
export { DetailDrawer, DetailDrawerProps } from './components/detail-drawer.js';
|
|
26
27
|
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/dialog.js';
|
|
27
28
|
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from './components/dropdown-menu.js';
|
|
28
29
|
export { EmptyState, EmptyStateProps } from './components/empty-state.js';
|
|
@@ -35,6 +36,8 @@ export { AssigneeFilter, InboxFilterCategory, InboxToolbar, InboxToolbarProps }
|
|
|
35
36
|
export { InlineBanner, InlineBannerProps } from './components/inline-banner.js';
|
|
36
37
|
export { Input } from './components/input.js';
|
|
37
38
|
export { FilterDefinition, InsightsFilterBar, InsightsFilterBarProps } from './components/insights-filter-bar.js';
|
|
39
|
+
export { DaysOpenCell, DaysOpenCellProps, getDaysOpenIntent } from './components/days-open-cell.js';
|
|
40
|
+
export { LinkedEntityCell, LinkedEntityCellProps } from './components/linked-entity-cell.js';
|
|
38
41
|
export { GroupedListGroup, GroupedListView, GroupedListViewProps, ItemList } from './components/item-list.js';
|
|
39
42
|
export { ItemListDisplay, ItemListDisplayState, ItemListGrouping, ItemListViewMode } from './components/item-list-display.js';
|
|
40
43
|
export { ItemListFilter, ItemListFilterCategory } from './components/item-list-filter.js';
|
|
@@ -42,11 +45,13 @@ export { ItemListQuickView, ItemListToolbar } from './components/item-list-toolb
|
|
|
42
45
|
export { KbdHint } from './components/kbd-hint.js';
|
|
43
46
|
export { Label } from './components/label.js';
|
|
44
47
|
export { Message, MessageAvatar, MessageAvatarProps, MessageContent, MessageContentProps, MessageProps } from './components/message.js';
|
|
45
|
-
export { MetricCard, MetricCardProps, MetricDataPoint } from './components/metric-card.js';
|
|
48
|
+
export { KpiStrip, KpiStripItem, KpiStripProps, MetricCard, MetricCardProps, MetricDataPoint } from './components/metric-card.js';
|
|
46
49
|
export { PerformanceMetricsTable, PerformanceMetricsTableRow, PerformanceMetricsTableSortOption } from './components/performance-metrics-table.js';
|
|
50
|
+
export { Pill, PillProps, PillStatus, StatusPill, StatusPillProps, pillVariants } from './components/pill.js';
|
|
47
51
|
export { PreviewList, PreviewListItem, PreviewListItemProps } from './components/preview-list.js';
|
|
48
52
|
export { Progress } from './components/progress.js';
|
|
49
53
|
export { QuickActionChatArea, QuickActionSubmitPayload } from './components/quick-action-chat-area.js';
|
|
54
|
+
export { QuickSegment, QuickSegmentProps } from './components/quick-segment.js';
|
|
50
55
|
export { QuickActionModal, QuickActionPriority, QuickActionTaskDraft, QuickActionTemplate } from './components/quick-action-modal.js';
|
|
51
56
|
export { ActiveVariant, QuickActionSidebarNav, SidebarNavItem, SidebarNavSection, SidebarUserProfile, UserMenuItem } from './components/quick-action-sidebar-nav.js';
|
|
52
57
|
export { RecommendedAction, RecommendedActionsSection } from './components/recommended-actions-section.js';
|
|
@@ -92,6 +97,7 @@ export { VolumeAnalysisChart, VolumeAnalysisChartProps, VolumeDataKey } from './
|
|
|
92
97
|
export { MetricCardData, TopLineMetrics, TopLineMetricsProps } from './charts/top-line-metrics.js';
|
|
93
98
|
export { PipelineFilterBreakdown, PipelineOverview, PipelineOverviewProps, PipelineStage, PipelineStageMetrics, PipelineStageTiming } from './charts/pipeline-overview.js';
|
|
94
99
|
export { SankeyChart, SankeyData, SankeyDropOff, SankeyHoverCardData, SankeyLink, SankeyNode, SankeyStageMetrics } from './charts/sankey-chart.js';
|
|
100
|
+
export { EmptyChartState, EmptyChartStateProps } from './charts/empty-chart-state.js';
|
|
95
101
|
export { PrototypeShell, PrototypeShellProps } from './prototype/prototype-shell.js';
|
|
96
102
|
export { DetailView, DetailViewProps, PrototypeInboxView, PrototypeInboxViewProps } from './prototype/prototype-inbox-view.js';
|
|
97
103
|
export { PrototypeInsightsView, PrototypeInsightsViewProps } from './prototype/prototype-insights-view.js';
|
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ export * from "./components/data-table-filter.js";
|
|
|
23
23
|
export * from "./components/data-table-quick-views.js";
|
|
24
24
|
export * from "./components/data-table-toolbar.js";
|
|
25
25
|
export * from "./components/detail-view.js";
|
|
26
|
+
export * from "./components/detail-drawer.js";
|
|
26
27
|
export * from "./components/dialog.js";
|
|
27
28
|
export * from "./components/dropdown-menu.js";
|
|
28
29
|
export * from "./components/empty-state.js";
|
|
@@ -35,6 +36,8 @@ export * from "./components/inbox-toolbar.js";
|
|
|
35
36
|
export * from "./components/inline-banner.js";
|
|
36
37
|
export * from "./components/input.js";
|
|
37
38
|
export * from "./components/insights-filter-bar.js";
|
|
39
|
+
export * from "./components/days-open-cell.js";
|
|
40
|
+
export * from "./components/linked-entity-cell.js";
|
|
38
41
|
export * from "./components/item-list.js";
|
|
39
42
|
export * from "./components/item-list-display.js";
|
|
40
43
|
export * from "./components/item-list-filter.js";
|
|
@@ -44,9 +47,11 @@ export * from "./components/label.js";
|
|
|
44
47
|
export * from "./components/message.js";
|
|
45
48
|
export * from "./components/metric-card.js";
|
|
46
49
|
export * from "./components/performance-metrics-table.js";
|
|
50
|
+
export * from "./components/pill.js";
|
|
47
51
|
export * from "./components/preview-list.js";
|
|
48
52
|
export * from "./components/progress.js";
|
|
49
53
|
export * from "./components/quick-action-chat-area.js";
|
|
54
|
+
export * from "./components/quick-segment.js";
|
|
50
55
|
import {
|
|
51
56
|
QuickActionModal
|
|
52
57
|
} from "./components/quick-action-modal.js";
|