@actioneer/ads 0.5.2 → 0.5.4
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/components/ai-elements/agent-trace.d.ts +6 -1
- package/components/ai-elements/agent-trace.js +150 -120
- package/components/ai-elements/chain-of-thought.d.ts +21 -5
- package/components/ai-elements/chain-of-thought.js +190 -140
- package/components/ai-elements/research-activity.js +100 -95
- package/components/ai-elements/task.js +11 -11
- package/components/ai-elements/tool.js +29 -29
- package/components/alert.js +7 -7
- package/components/chart.d.ts +14 -0
- package/components/chart.js +745 -612
- package/components/index.d.ts +1 -0
- package/components/index.js +373 -366
- package/components/viz-charts.d.ts +62 -0
- package/components/viz-charts.js +408 -0
- package/lib/viz-format.d.ts +25 -0
- package/lib/viz-format.js +40 -0
- package/llms.txt +15 -0
- package/manifest.json +149 -8
- package/package.json +1 -1
- package/styles.css +31 -13
- package/theme.css +20 -10
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface VizSeries {
|
|
3
|
+
name: string;
|
|
4
|
+
/** Omit to take the palette color for its index. */
|
|
5
|
+
color?: string;
|
|
6
|
+
values: number[];
|
|
7
|
+
/** Render dashed — a 2nd+ event line, not the primary. */
|
|
8
|
+
dashed?: boolean;
|
|
9
|
+
/** Faded dashed ghost — a "previous period" compare series. */
|
|
10
|
+
ghost?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SeriesChartProps {
|
|
13
|
+
type?: "line" | "area" | "bar";
|
|
14
|
+
labels: string[];
|
|
15
|
+
series: VizSeries[];
|
|
16
|
+
height?: number;
|
|
17
|
+
/** Formatter for the value axis + tooltip; defaults to abbr / commafy. */
|
|
18
|
+
formatAxis?: (v: number) => string;
|
|
19
|
+
formatValue?: (v: number) => string;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function SeriesChart({ type, labels, series, height, formatAxis, formatValue, className, }: SeriesChartProps): React.JSX.Element;
|
|
23
|
+
export interface FunnelStep {
|
|
24
|
+
label: string;
|
|
25
|
+
value: number;
|
|
26
|
+
/** Median seconds from the previous step. */
|
|
27
|
+
medianTime?: number | null;
|
|
28
|
+
avgTime?: number | null;
|
|
29
|
+
}
|
|
30
|
+
export interface FunnelVizProps {
|
|
31
|
+
steps: FunnelStep[];
|
|
32
|
+
height?: number;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function FunnelViz({ steps, height, className }: FunnelVizProps): React.JSX.Element;
|
|
36
|
+
export interface FunnelBarsHorizontalProps {
|
|
37
|
+
steps: FunnelStep[];
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function FunnelBarsHorizontal({ steps, className }: FunnelBarsHorizontalProps): React.JSX.Element;
|
|
41
|
+
export interface RetentionPoint {
|
|
42
|
+
label: string;
|
|
43
|
+
v: number;
|
|
44
|
+
}
|
|
45
|
+
export interface RetentionCurveProps {
|
|
46
|
+
points: RetentionPoint[];
|
|
47
|
+
height?: number;
|
|
48
|
+
className?: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function RetentionCurve({ points, height, className }: RetentionCurveProps): React.JSX.Element;
|
|
51
|
+
export interface RetentionCohort {
|
|
52
|
+
label: string;
|
|
53
|
+
size: number;
|
|
54
|
+
/** One per column; null = period not yet elapsed. */
|
|
55
|
+
values: (number | null)[];
|
|
56
|
+
}
|
|
57
|
+
export interface RetentionGridProps {
|
|
58
|
+
cols: string[];
|
|
59
|
+
cohorts: RetentionCohort[];
|
|
60
|
+
className?: string;
|
|
61
|
+
}
|
|
62
|
+
export declare function RetentionGrid({ cols, cohorts, className }: RetentionGridProps): React.JSX.Element;
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as r, jsxs as c, Fragment as J } from "react/jsx-runtime";
|
|
3
|
+
import * as $ from "react";
|
|
4
|
+
import { cn as D } from "../lib/cn.js";
|
|
5
|
+
import { fmtDuration as B, abbr as V, pct1 as z, commafy as H } from "../lib/viz-format.js";
|
|
6
|
+
const G = [
|
|
7
|
+
"var(--color-chart-1)",
|
|
8
|
+
"var(--color-chart-2)",
|
|
9
|
+
"var(--color-chart-3)",
|
|
10
|
+
"var(--color-chart-4)",
|
|
11
|
+
"var(--color-chart-5)",
|
|
12
|
+
"var(--color-chart-6)"
|
|
13
|
+
], O = (e) => G[e % G.length], A = "var(--color-chart-1)", E = "var(--color-ink-400)", U = "var(--border)", Q = "var(--foreground)";
|
|
14
|
+
function Y(e, s = 4) {
|
|
15
|
+
if (e <= 0) return { max: 1, ticks: [0, 1] };
|
|
16
|
+
const d = e / s, i = Math.pow(10, Math.floor(Math.log10(d))), o = ([1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10].find((w) => w * i >= d) ?? 10) * i, a = Math.ceil(e / o) * o, y = [];
|
|
17
|
+
for (let w = 0; w <= a + o / 1e6; w += o) y.push(w);
|
|
18
|
+
return { max: a, ticks: y };
|
|
19
|
+
}
|
|
20
|
+
function Z(e, s = 8) {
|
|
21
|
+
if (e.length <= s) return e;
|
|
22
|
+
const d = Math.ceil(e.length / s);
|
|
23
|
+
return e.map((i, u) => u % d === 0 || u === e.length - 1 ? i : null);
|
|
24
|
+
}
|
|
25
|
+
function P(e) {
|
|
26
|
+
if (!e.length) return "";
|
|
27
|
+
if (e.length === 1) return `M${e[0][0]},${e[0][1]}`;
|
|
28
|
+
let s = `M${e[0][0]},${e[0][1]}`;
|
|
29
|
+
for (let d = 1; d < e.length; d++) {
|
|
30
|
+
const [i, u] = e[d - 1], [o, a] = e[d], y = (i + o) / 2;
|
|
31
|
+
s += `C${y},${u} ${y},${a} ${o},${a}`;
|
|
32
|
+
}
|
|
33
|
+
return s;
|
|
34
|
+
}
|
|
35
|
+
function _({
|
|
36
|
+
x: e,
|
|
37
|
+
y: s,
|
|
38
|
+
title: d,
|
|
39
|
+
rows: i,
|
|
40
|
+
flip: u
|
|
41
|
+
}) {
|
|
42
|
+
return /* @__PURE__ */ c(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: "pointer-events-none absolute z-10 min-w-[184px] max-w-[248px] rounded-lg bg-foreground px-3 py-2.5 text-background shadow-elevation",
|
|
46
|
+
style: {
|
|
47
|
+
left: e,
|
|
48
|
+
top: s,
|
|
49
|
+
transform: `translate(${u ? "calc(-100% - 12px)" : "12px"}, -50%)`
|
|
50
|
+
},
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ r("div", { className: "mb-1.5 text-xs text-background/60", children: d }),
|
|
53
|
+
/* @__PURE__ */ r("div", { className: "flex flex-col gap-1", children: i.map((o, a) => /* @__PURE__ */ c("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
54
|
+
o.dashed ? /* @__PURE__ */ r(
|
|
55
|
+
"span",
|
|
56
|
+
{
|
|
57
|
+
"aria-hidden": !0,
|
|
58
|
+
className: "h-0 w-3 shrink-0 border-t border-dashed",
|
|
59
|
+
style: { borderColor: o.swatch ?? "currentColor" }
|
|
60
|
+
}
|
|
61
|
+
) : o.swatch ? /* @__PURE__ */ r("span", { "aria-hidden": !0, className: "size-2 shrink-0 rounded-dot", style: { background: o.swatch } }) : null,
|
|
62
|
+
/* @__PURE__ */ r("span", { className: "min-w-0 flex-1 truncate text-background/70", children: o.label }),
|
|
63
|
+
/* @__PURE__ */ r("span", { className: "shrink-0 font-semibold tabular-nums", children: o.value })
|
|
64
|
+
] }, a)) })
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
function ee({
|
|
70
|
+
items: e
|
|
71
|
+
}) {
|
|
72
|
+
return /* @__PURE__ */ r("div", { className: "mb-3 flex flex-wrap items-center justify-end gap-x-4 gap-y-1", children: e.map((s) => /* @__PURE__ */ c("span", { className: "inline-flex items-center gap-1.5 text-xs text-secondary", children: [
|
|
73
|
+
/* @__PURE__ */ r(
|
|
74
|
+
"span",
|
|
75
|
+
{
|
|
76
|
+
"aria-hidden": !0,
|
|
77
|
+
className: D("h-0 w-4 shrink-0", s.dashed ? "border-t-2 border-dashed" : "border-t-[3px]"),
|
|
78
|
+
style: { borderColor: s.color }
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
s.label
|
|
82
|
+
] }, s.label)) });
|
|
83
|
+
}
|
|
84
|
+
const b = { l: 56, r: 18, t: 18, b: 34 };
|
|
85
|
+
function ne({
|
|
86
|
+
type: e = "line",
|
|
87
|
+
labels: s,
|
|
88
|
+
series: d,
|
|
89
|
+
height: i = 300,
|
|
90
|
+
formatAxis: u = V,
|
|
91
|
+
formatValue: o = H,
|
|
92
|
+
className: a
|
|
93
|
+
}) {
|
|
94
|
+
const [y, w] = $.useState(720), N = $.useRef(null);
|
|
95
|
+
$.useEffect(() => {
|
|
96
|
+
if (!N.current) return;
|
|
97
|
+
const t = new ResizeObserver(([m]) => w(m.contentRect.width));
|
|
98
|
+
return t.observe(N.current), () => t.disconnect();
|
|
99
|
+
}, []);
|
|
100
|
+
const [h, f] = $.useState(null), x = Math.max(0, y - b.l - b.r), M = Math.max(0, i - b.t - b.b), l = d.filter((t) => !t.ghost), { max: n, ticks: p } = Y(Math.max(1, ...d.flatMap((t) => t.values))), k = (t) => b.t + M - t / n * M, R = s.length, v = (t) => e === "bar" ? b.l + (t + 0.5) / R * x : b.l + (R <= 1 ? x / 2 : t / (R - 1) * x), j = [...p].reverse(), C = l.map((t, m) => ({ label: t.name, color: t.color ?? O(m), dashed: t.dashed }));
|
|
101
|
+
return /* @__PURE__ */ c("div", { ref: N, className: D("relative w-full font-sans", a), children: [
|
|
102
|
+
C.length > 1 && /* @__PURE__ */ r(ee, { items: C }),
|
|
103
|
+
/* @__PURE__ */ c(
|
|
104
|
+
"svg",
|
|
105
|
+
{
|
|
106
|
+
width: y,
|
|
107
|
+
height: i,
|
|
108
|
+
className: "block select-none",
|
|
109
|
+
onMouseLeave: () => f(null),
|
|
110
|
+
onMouseMove: (t) => {
|
|
111
|
+
const m = t.currentTarget.getBoundingClientRect(), T = t.clientX - m.left, L = Math.round((T - b.l) / x * (R - 1));
|
|
112
|
+
f(Math.max(0, Math.min(R - 1, L)));
|
|
113
|
+
},
|
|
114
|
+
children: [
|
|
115
|
+
j.map((t, m) => /* @__PURE__ */ c("g", { children: [
|
|
116
|
+
/* @__PURE__ */ r(
|
|
117
|
+
"line",
|
|
118
|
+
{
|
|
119
|
+
x1: b.l,
|
|
120
|
+
x2: b.l + x,
|
|
121
|
+
y1: k(t),
|
|
122
|
+
y2: k(t),
|
|
123
|
+
stroke: U,
|
|
124
|
+
strokeWidth: 1,
|
|
125
|
+
strokeDasharray: t === 0 ? void 0 : "3 4",
|
|
126
|
+
opacity: t === 0 ? 0.9 : 0.6
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
/* @__PURE__ */ r("text", { x: b.l - 10, y: k(t), dy: "0.32em", textAnchor: "end", className: "fill-tertiary text-[11px] tabular-nums", children: u(t) })
|
|
130
|
+
] }, m)),
|
|
131
|
+
Z(s).map(
|
|
132
|
+
(t, m) => t == null ? null : /* @__PURE__ */ r("text", { x: v(m), y: i - 12, textAnchor: "middle", className: "fill-tertiary text-[11px] tabular-nums", children: t }, m)
|
|
133
|
+
),
|
|
134
|
+
e === "bar" && l.map((t, m) => {
|
|
135
|
+
const T = x / R, L = Math.min(T * 0.7, 64), F = (L - (l.length - 1)) / l.length;
|
|
136
|
+
return t.values.map((I, S) => {
|
|
137
|
+
const K = b.l + S * T + (T - L) / 2 + m * (F + 1), q = h != null && h !== S;
|
|
138
|
+
return /* @__PURE__ */ r(
|
|
139
|
+
"rect",
|
|
140
|
+
{
|
|
141
|
+
x: K,
|
|
142
|
+
y: k(I),
|
|
143
|
+
width: Math.max(0, F),
|
|
144
|
+
height: b.t + M - k(I),
|
|
145
|
+
rx: 2,
|
|
146
|
+
fill: t.color ?? O(m),
|
|
147
|
+
opacity: q ? 0.4 : 1
|
|
148
|
+
},
|
|
149
|
+
`${m}-${S}`
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
}),
|
|
153
|
+
e === "area" && l[0] && /* @__PURE__ */ r(
|
|
154
|
+
"path",
|
|
155
|
+
{
|
|
156
|
+
d: `${P(l[0].values.map((t, m) => [v(m), k(t)]))} L${v(R - 1)},${k(0)} L${v(0)},${k(0)} Z`,
|
|
157
|
+
fill: l[0].color ?? O(0),
|
|
158
|
+
opacity: 0.12
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
e !== "bar" && d.map((t, m) => {
|
|
162
|
+
const T = t.color ?? O(l.indexOf(t)), L = t.ghost ? "2 4" : t.dashed ? "6 5" : void 0, F = t.ghost ? 1.75 : m === 0 ? 2.5 : 2;
|
|
163
|
+
return /* @__PURE__ */ r(
|
|
164
|
+
"path",
|
|
165
|
+
{
|
|
166
|
+
d: P(t.values.map((I, S) => [v(S), k(I)])),
|
|
167
|
+
fill: "none",
|
|
168
|
+
stroke: T,
|
|
169
|
+
strokeWidth: F,
|
|
170
|
+
strokeDasharray: L,
|
|
171
|
+
strokeLinecap: "round",
|
|
172
|
+
strokeLinejoin: "round",
|
|
173
|
+
opacity: t.ghost ? 0.4 : 1
|
|
174
|
+
},
|
|
175
|
+
m
|
|
176
|
+
);
|
|
177
|
+
}),
|
|
178
|
+
h != null && e !== "bar" && /* @__PURE__ */ c(J, { children: [
|
|
179
|
+
/* @__PURE__ */ r("line", { x1: v(h), x2: v(h), y1: b.t, y2: b.t + M, stroke: Q, strokeWidth: 1, opacity: 0.18 }),
|
|
180
|
+
l.map((t, m) => /* @__PURE__ */ r(
|
|
181
|
+
"circle",
|
|
182
|
+
{
|
|
183
|
+
cx: v(h),
|
|
184
|
+
cy: k(t.values[h]),
|
|
185
|
+
r: 4.5,
|
|
186
|
+
fill: t.color ?? O(m),
|
|
187
|
+
stroke: "var(--card)",
|
|
188
|
+
strokeWidth: 2
|
|
189
|
+
},
|
|
190
|
+
m
|
|
191
|
+
))
|
|
192
|
+
] })
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
),
|
|
196
|
+
h != null && /* @__PURE__ */ r(
|
|
197
|
+
_,
|
|
198
|
+
{
|
|
199
|
+
x: v(h),
|
|
200
|
+
y: b.t + M / 2,
|
|
201
|
+
flip: v(h) > b.l + x * 0.66,
|
|
202
|
+
title: s[h],
|
|
203
|
+
rows: d.map((t) => ({
|
|
204
|
+
swatch: t.color ?? O(l.indexOf(t)),
|
|
205
|
+
dashed: t.ghost,
|
|
206
|
+
label: t.name,
|
|
207
|
+
value: o(t.values[h])
|
|
208
|
+
}))
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
] });
|
|
212
|
+
}
|
|
213
|
+
const g = { l: 22, r: 16, t: 28, b: 98 }, X = "viz-funnel-hatch";
|
|
214
|
+
function oe({ steps: e, height: s = 320, className: d }) {
|
|
215
|
+
var l;
|
|
216
|
+
const [i, u] = $.useState(720), o = $.useRef(null);
|
|
217
|
+
$.useEffect(() => {
|
|
218
|
+
if (!o.current) return;
|
|
219
|
+
const n = new ResizeObserver(([p]) => u(p.contentRect.width));
|
|
220
|
+
return n.observe(o.current), () => n.disconnect();
|
|
221
|
+
}, []);
|
|
222
|
+
const [a, y] = $.useState(null), w = Math.max(0, i - g.l - g.r), N = Math.max(0, s - g.t - g.b), h = ((l = e[0]) == null ? void 0 : l.value) || 1, f = (n) => g.t + N - n * N, x = w / Math.max(1, e.length), M = Math.min(x * 0.56, 120);
|
|
223
|
+
return /* @__PURE__ */ c("div", { ref: o, className: D("relative w-full font-sans", d), children: [
|
|
224
|
+
/* @__PURE__ */ c("svg", { width: i, height: s, className: "block select-none", children: [
|
|
225
|
+
/* @__PURE__ */ r("defs", { children: /* @__PURE__ */ c("pattern", { id: X, width: 6, height: 6, patternTransform: "rotate(45)", patternUnits: "userSpaceOnUse", children: [
|
|
226
|
+
/* @__PURE__ */ r("rect", { width: 6, height: 6, fill: E, opacity: 0.07 }),
|
|
227
|
+
/* @__PURE__ */ r("line", { x1: 0, y1: 0, x2: 0, y2: 6, stroke: E, strokeWidth: 2.5, opacity: 0.22 })
|
|
228
|
+
] }) }),
|
|
229
|
+
[1, 0.75, 0.5, 0.25, 0].map((n) => /* @__PURE__ */ c("g", { children: [
|
|
230
|
+
/* @__PURE__ */ r("line", { x1: g.l, x2: g.l + w, y1: f(n), y2: f(n), stroke: U, strokeWidth: 1, strokeDasharray: n === 0 ? void 0 : "3 4", opacity: n === 0 ? 0.9 : 0.6 }),
|
|
231
|
+
/* @__PURE__ */ r("text", { x: g.l, y: f(n) - 4, className: "fill-tertiary text-[10px] tabular-nums", children: n * 100 })
|
|
232
|
+
] }, n)),
|
|
233
|
+
e.map((n, p) => {
|
|
234
|
+
const k = n.value / h, R = p === 0 ? 1 : e[p - 1].value / h, v = g.l + p * x + x / 2, j = v - M / 2, C = f(k), t = a != null && a !== p;
|
|
235
|
+
return /* @__PURE__ */ c("g", { opacity: t ? 0.55 : 1, onMouseEnter: () => y(p), onMouseLeave: () => y(null), children: [
|
|
236
|
+
p > 0 && /* @__PURE__ */ r("rect", { x: j, y: f(R), width: M, height: Math.max(0, C - f(R)), rx: 4, fill: `url(#${X})` }),
|
|
237
|
+
/* @__PURE__ */ r("rect", { x: j, y: C, width: M, height: Math.max(0, g.t + N - C), rx: 4, fill: A }),
|
|
238
|
+
/* @__PURE__ */ r("text", { x: v, y: C + 16, textAnchor: "middle", className: "fill-[var(--card)] text-[12px] font-semibold tabular-nums", children: V(n.value) }),
|
|
239
|
+
/* @__PURE__ */ r("text", { x: v, y: g.t + N + 24, textAnchor: "middle", className: "fill-secondary text-[12.5px] font-semibold", children: n.label }),
|
|
240
|
+
/* @__PURE__ */ c("text", { x: v, y: g.t + N + 45, textAnchor: "middle", className: "fill-foreground text-[12px] font-semibold tabular-nums", children: [
|
|
241
|
+
H(n.value),
|
|
242
|
+
" ",
|
|
243
|
+
/* @__PURE__ */ r("tspan", { className: "fill-tertiary", children: p === 0 ? "entered" : `→ ${z(k * 100)}` })
|
|
244
|
+
] }),
|
|
245
|
+
p > 0 && /* @__PURE__ */ c("text", { x: v, y: g.t + N + 66, textAnchor: "middle", className: "fill-tertiary text-[12px] font-semibold tabular-nums", children: [
|
|
246
|
+
"↘ ",
|
|
247
|
+
z((1 - n.value / e[p - 1].value) * 100)
|
|
248
|
+
] }),
|
|
249
|
+
p > 0 && n.medianTime != null && /* @__PURE__ */ c("text", { x: v, y: g.t + N + 86, textAnchor: "middle", className: "fill-tertiary text-[11px] tabular-nums", children: [
|
|
250
|
+
"◷ ",
|
|
251
|
+
B(n.medianTime)
|
|
252
|
+
] })
|
|
253
|
+
] }, p);
|
|
254
|
+
})
|
|
255
|
+
] }),
|
|
256
|
+
a != null && e[a] && /* @__PURE__ */ r(
|
|
257
|
+
_,
|
|
258
|
+
{
|
|
259
|
+
x: g.l + a * x + x / 2,
|
|
260
|
+
y: g.t + N / 2,
|
|
261
|
+
flip: a >= e.length - 2,
|
|
262
|
+
title: e[a].label,
|
|
263
|
+
rows: [
|
|
264
|
+
{ swatch: A, label: "Converted", value: H(e[a].value) },
|
|
265
|
+
...a > 0 ? [
|
|
266
|
+
{ swatch: E, label: "Dropped off", value: `−${H(e[a - 1].value - e[a].value)}` },
|
|
267
|
+
{ label: "Conversion so far", value: z(e[a].value / h * 100) },
|
|
268
|
+
{ label: "From previous", value: z(e[a].value / e[a - 1].value * 100) },
|
|
269
|
+
{ label: "Median time", value: B(e[a].medianTime) }
|
|
270
|
+
] : []
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
] });
|
|
275
|
+
}
|
|
276
|
+
function ce({ steps: e, className: s }) {
|
|
277
|
+
var i;
|
|
278
|
+
const d = ((i = e[0]) == null ? void 0 : i.value) || 1;
|
|
279
|
+
return /* @__PURE__ */ r("div", { className: D("flex w-full flex-col gap-[30px] font-sans", s), children: e.map((u, o) => {
|
|
280
|
+
const a = u.value / d, y = o === 0 ? 1 : e[o - 1].value / d;
|
|
281
|
+
return /* @__PURE__ */ c("div", { className: "flex items-center gap-3", children: [
|
|
282
|
+
/* @__PURE__ */ c("div", { className: "min-w-0 flex-1", children: [
|
|
283
|
+
/* @__PURE__ */ c("div", { className: "mb-1.5 flex items-center justify-between gap-3", children: [
|
|
284
|
+
/* @__PURE__ */ c("span", { className: "truncate text-[12.5px] font-semibold text-secondary", children: [
|
|
285
|
+
/* @__PURE__ */ c("span", { className: "text-tertiary tabular-nums", children: [
|
|
286
|
+
o + 1,
|
|
287
|
+
"."
|
|
288
|
+
] }),
|
|
289
|
+
" ",
|
|
290
|
+
u.label
|
|
291
|
+
] }),
|
|
292
|
+
o > 0 && u.avgTime != null && /* @__PURE__ */ c("span", { className: "shrink-0 text-[11px] text-tertiary tabular-nums", children: [
|
|
293
|
+
"Avg time ",
|
|
294
|
+
B(u.avgTime)
|
|
295
|
+
] })
|
|
296
|
+
] }),
|
|
297
|
+
/* @__PURE__ */ c("div", { className: "relative h-[46px] overflow-hidden rounded-lg bg-muted-foreground/[0.06]", children: [
|
|
298
|
+
o > 0 && /* @__PURE__ */ r(
|
|
299
|
+
"div",
|
|
300
|
+
{
|
|
301
|
+
className: "absolute inset-y-0 left-0",
|
|
302
|
+
style: {
|
|
303
|
+
width: `${y * 100}%`,
|
|
304
|
+
backgroundImage: `repeating-linear-gradient(45deg, color-mix(in srgb, ${E} 9%, transparent) 0 4px, color-mix(in srgb, ${E} 22%, transparent) 4px 5px)`
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
),
|
|
308
|
+
/* @__PURE__ */ r("div", { className: "absolute inset-y-0 left-0 flex items-center rounded-lg", style: { width: `${a * 100}%`, background: A }, children: /* @__PURE__ */ r("span", { className: "ml-3 text-[12px] font-semibold text-[var(--card)] tabular-nums", children: V(u.value) }) })
|
|
309
|
+
] })
|
|
310
|
+
] }),
|
|
311
|
+
/* @__PURE__ */ r("span", { className: "w-[60px] shrink-0 text-right text-base font-bold text-foreground tabular-nums", children: z(a * 100) })
|
|
312
|
+
] }, o);
|
|
313
|
+
}) });
|
|
314
|
+
}
|
|
315
|
+
const W = { l: 48, r: 24, t: 34, b: 34 };
|
|
316
|
+
function se({ points: e, height: s = 300, className: d }) {
|
|
317
|
+
const [i, u] = $.useState(720), o = $.useRef(null);
|
|
318
|
+
$.useEffect(() => {
|
|
319
|
+
if (!o.current) return;
|
|
320
|
+
const l = new ResizeObserver(([n]) => u(n.contentRect.width));
|
|
321
|
+
return l.observe(o.current), () => l.disconnect();
|
|
322
|
+
}, []);
|
|
323
|
+
const [a, y] = $.useState(null), w = Math.max(0, i - W.l - W.r), N = Math.max(0, s - W.t - W.b), h = e.length, f = (l) => W.l + (h <= 1 ? w / 2 : l / (h - 1) * w), x = (l) => W.t + N - l / 100 * N, M = e.map((l, n) => [f(n), x(l.v)]);
|
|
324
|
+
return /* @__PURE__ */ c("div", { ref: o, className: D("relative w-full font-sans", d), children: [
|
|
325
|
+
/* @__PURE__ */ c(
|
|
326
|
+
"svg",
|
|
327
|
+
{
|
|
328
|
+
width: i,
|
|
329
|
+
height: s,
|
|
330
|
+
className: "block select-none",
|
|
331
|
+
onMouseLeave: () => y(null),
|
|
332
|
+
onMouseMove: (l) => {
|
|
333
|
+
const n = l.currentTarget.getBoundingClientRect(), p = Math.round((l.clientX - n.left - W.l) / w * (h - 1));
|
|
334
|
+
y(Math.max(0, Math.min(h - 1, p)));
|
|
335
|
+
},
|
|
336
|
+
children: [
|
|
337
|
+
[100, 75, 50, 25, 0].map((l) => /* @__PURE__ */ c("g", { children: [
|
|
338
|
+
/* @__PURE__ */ r("line", { x1: W.l, x2: W.l + w, y1: x(l), y2: x(l), stroke: U, strokeWidth: 1, strokeDasharray: l === 0 ? void 0 : "3 4", opacity: l === 0 ? 0.9 : 0.6 }),
|
|
339
|
+
/* @__PURE__ */ c("text", { x: W.l - 10, y: x(l), dy: "0.32em", textAnchor: "end", className: "fill-tertiary text-[11px] tabular-nums", children: [
|
|
340
|
+
l,
|
|
341
|
+
"%"
|
|
342
|
+
] })
|
|
343
|
+
] }, l)),
|
|
344
|
+
Z(e).map(
|
|
345
|
+
(l, n) => l == null ? null : /* @__PURE__ */ r("text", { x: f(n), y: s - 12, textAnchor: "middle", className: "fill-tertiary text-[11px] tabular-nums", children: l.label }, n)
|
|
346
|
+
),
|
|
347
|
+
/* @__PURE__ */ r("path", { d: `${P(M)} L${f(h - 1)},${x(0)} L${f(0)},${x(0)} Z`, fill: A, opacity: 0.12 }),
|
|
348
|
+
/* @__PURE__ */ r("path", { d: P(M), fill: "none", stroke: A, strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
349
|
+
e.map((l, n) => /* @__PURE__ */ c("g", { children: [
|
|
350
|
+
/* @__PURE__ */ c("text", { x: f(n), y: x(l.v) - 12, textAnchor: "middle", className: "fill-foreground text-[11.5px] font-semibold tabular-nums", children: [
|
|
351
|
+
l.v,
|
|
352
|
+
"%"
|
|
353
|
+
] }),
|
|
354
|
+
/* @__PURE__ */ r("circle", { cx: f(n), cy: x(l.v), r: a === n ? 5 : 3.5, fill: "var(--card)", stroke: A, strokeWidth: 2 })
|
|
355
|
+
] }, n))
|
|
356
|
+
]
|
|
357
|
+
}
|
|
358
|
+
),
|
|
359
|
+
a != null && e[a] && /* @__PURE__ */ r(
|
|
360
|
+
_,
|
|
361
|
+
{
|
|
362
|
+
x: f(a),
|
|
363
|
+
y: x(e[a].v),
|
|
364
|
+
flip: a >= h - 2,
|
|
365
|
+
title: e[a].label,
|
|
366
|
+
rows: [{ swatch: A, label: "Retention", value: `${e[a].v}%` }]
|
|
367
|
+
}
|
|
368
|
+
)
|
|
369
|
+
] });
|
|
370
|
+
}
|
|
371
|
+
function te(e) {
|
|
372
|
+
const s = 10 + Math.max(0, Math.min(100, e)) / 100 * 78;
|
|
373
|
+
return `color-mix(in srgb, ${A} ${s}%, transparent)`;
|
|
374
|
+
}
|
|
375
|
+
function ie({ cols: e, cohorts: s, className: d }) {
|
|
376
|
+
return /* @__PURE__ */ r("div", { className: D("w-full overflow-x-auto font-sans", d), children: /* @__PURE__ */ c("table", { className: "w-full border-collapse text-left", children: [
|
|
377
|
+
/* @__PURE__ */ r("thead", { children: /* @__PURE__ */ c("tr", { className: "text-xs font-semibold text-tertiary", children: [
|
|
378
|
+
/* @__PURE__ */ r("th", { className: "sticky left-0 w-[1%] bg-card py-2 pr-4 whitespace-nowrap", children: "Cohort" }),
|
|
379
|
+
/* @__PURE__ */ r("th", { className: "w-[1%] py-2 pr-4 text-right whitespace-nowrap", children: "Users" }),
|
|
380
|
+
e.map((i) => /* @__PURE__ */ r("th", { className: "px-1.5 py-2 text-center tabular-nums", children: i }, i))
|
|
381
|
+
] }) }),
|
|
382
|
+
/* @__PURE__ */ r("tbody", { children: s.map((i) => /* @__PURE__ */ c("tr", { children: [
|
|
383
|
+
/* @__PURE__ */ r("td", { className: "sticky left-0 w-[1%] bg-card py-1.5 pr-4 text-[12.5px] text-secondary whitespace-nowrap", children: i.label }),
|
|
384
|
+
/* @__PURE__ */ r("td", { className: "w-[1%] py-1.5 pr-4 text-right text-[12.5px] text-secondary tabular-nums whitespace-nowrap", children: H(i.size) }),
|
|
385
|
+
i.values.map((u, o) => /* @__PURE__ */ r("td", { className: "px-1 py-1", children: u == null ? /* @__PURE__ */ r("div", { className: "py-[9px] text-center text-[12.5px] text-tertiary/45 tabular-nums", children: "—" }) : /* @__PURE__ */ c(
|
|
386
|
+
"div",
|
|
387
|
+
{
|
|
388
|
+
className: D(
|
|
389
|
+
"rounded-md py-[9px] text-center text-[12.5px] tabular-nums",
|
|
390
|
+
u >= 50 ? "text-[var(--card)]" : "text-secondary"
|
|
391
|
+
),
|
|
392
|
+
style: { background: te(u) },
|
|
393
|
+
children: [
|
|
394
|
+
u,
|
|
395
|
+
"%"
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
) }, o))
|
|
399
|
+
] }, i.label)) })
|
|
400
|
+
] }) });
|
|
401
|
+
}
|
|
402
|
+
export {
|
|
403
|
+
ce as FunnelBarsHorizontal,
|
|
404
|
+
oe as FunnelViz,
|
|
405
|
+
se as RetentionCurve,
|
|
406
|
+
ie as RetentionGrid,
|
|
407
|
+
ne as SeriesChart
|
|
408
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Number & date formatting for the viz (segmentation) charts — India-first,
|
|
3
|
+
* per the Visualisations handoff. Kept separate from the components so both
|
|
4
|
+
* the renderers and their data tables format identically.
|
|
5
|
+
*
|
|
6
|
+
* Rule of the surface: every numeral is tabular-nums in the ADS face (never
|
|
7
|
+
* a mono font — EXTENDING §2.2), prose labels are sans. These helpers only
|
|
8
|
+
* produce the numeral strings.
|
|
9
|
+
*/
|
|
10
|
+
/** Tooltip / table grouping — lakh grouping. 1042318 → "10,42,318". */
|
|
11
|
+
export declare function commafy(n: number): string;
|
|
12
|
+
/**
|
|
13
|
+
* Axis abbreviation with the Indian ladder — capital K, then L (lakh),
|
|
14
|
+
* then Cr (crore). 145000 → "1.5L", 15000000 → "1.5Cr", 2300 → "2.3K".
|
|
15
|
+
*/
|
|
16
|
+
export declare function abbr(n: number): string;
|
|
17
|
+
/**
|
|
18
|
+
* Duration as the two most-significant units; "—" for null/0.
|
|
19
|
+
* 21310 → "5h 55m", 305 → "5m 5s", 42 → "42s".
|
|
20
|
+
*/
|
|
21
|
+
export declare function fmtDuration(seconds: number | null | undefined): string;
|
|
22
|
+
/** Percentage to one decimal place, the surface default. 12.83 → "12.8%". */
|
|
23
|
+
export declare function pct1(x: number): string;
|
|
24
|
+
/** Percentage to two decimals — funnel-trends tooltip. 12.8 → "12.80%". */
|
|
25
|
+
export declare function pct2(x: number): string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
function s(t) {
|
|
3
|
+
return t.toLocaleString("en-IN");
|
|
4
|
+
}
|
|
5
|
+
function o(t, n) {
|
|
6
|
+
return t.toFixed(n).replace(/\.?0+$/, "");
|
|
7
|
+
}
|
|
8
|
+
function l(t) {
|
|
9
|
+
const n = t < 0 ? "-" : "", r = Math.abs(t);
|
|
10
|
+
return r >= 1e7 ? `${n}${o(r / 1e7, 1)}Cr` : r >= 1e5 ? `${n}${o(r / 1e5, 1)}L` : r >= 1e3 ? `${n}${o(r / 1e3, 1)}K` : `${n}${r}`;
|
|
11
|
+
}
|
|
12
|
+
function $(t) {
|
|
13
|
+
if (t == null || t === 0) return "—";
|
|
14
|
+
const n = Math.floor(t), r = [
|
|
15
|
+
[86400, "d"],
|
|
16
|
+
[3600, "h"],
|
|
17
|
+
[60, "m"],
|
|
18
|
+
[1, "s"]
|
|
19
|
+
], e = [];
|
|
20
|
+
let i = n;
|
|
21
|
+
for (const [u, c] of r)
|
|
22
|
+
if (i >= u || e.length) {
|
|
23
|
+
const f = Math.floor(i / u);
|
|
24
|
+
if ((e.length || f > 0) && (e.push(`${f}${c}`), i -= f * u), e.length === 2) break;
|
|
25
|
+
}
|
|
26
|
+
return e.slice(0, 2).join(" ") || `${n}s`;
|
|
27
|
+
}
|
|
28
|
+
function a(t) {
|
|
29
|
+
return `${o(t, 1)}%`;
|
|
30
|
+
}
|
|
31
|
+
function h(t) {
|
|
32
|
+
return `${t.toFixed(2)}%`;
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
l as abbr,
|
|
36
|
+
s as commafy,
|
|
37
|
+
$ as fmtDuration,
|
|
38
|
+
a as pct1,
|
|
39
|
+
h as pct2
|
|
40
|
+
};
|
package/llms.txt
CHANGED
|
@@ -332,7 +332,9 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
332
332
|
- [ConnectorCard] — Use ConnectorCard to represent one data source/destination on an integrations screen — identity, connection status, health strip, and a usage/action footer. [docs](https://ads.actioneer.dev/#/connector-card)
|
|
333
333
|
- [EdgeLabelRenderer] — component [docs](https://ads.actioneer.dev/#/infinite-canvas)
|
|
334
334
|
- [ExplanationAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
|
|
335
|
+
- [FunnelBarsHorizontal] — component [docs](https://ads.actioneer.dev/#/viz-charts)
|
|
335
336
|
- [FunnelChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
|
|
337
|
+
- [FunnelViz] — component [docs](https://ads.actioneer.dev/#/viz-charts)
|
|
336
338
|
- [Handle] — component [docs](https://ads.actioneer.dev/#/infinite-canvas)
|
|
337
339
|
- [InfiniteCanvas] — Lay out a node graph or workflow on a pan/zoom surface — pass nodes, edges, and your own nodeTypes; the canvas owns the grid, edges, zoom cluster, snap toggle, and toolbar slots. Use readOnly for a canvas that explains rather than edits. [docs](https://ads.actioneer.dev/#/infinite-canvas)
|
|
338
340
|
- [LineChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
|
|
@@ -342,7 +344,10 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
342
344
|
- [RadarChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
|
|
343
345
|
- [RadialBarChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
|
|
344
346
|
- [ReactFlowProvider] — component [docs](https://ads.actioneer.dev/#/infinite-canvas)
|
|
347
|
+
- [RetentionCurve] — component [docs](https://ads.actioneer.dev/#/viz-charts)
|
|
348
|
+
- [RetentionGrid] — component [docs](https://ads.actioneer.dev/#/viz-charts)
|
|
345
349
|
- [ScatterChart] — component [docs](https://ads.actioneer.dev/#/ai/chart)
|
|
350
|
+
- [SeriesChart] — component [docs](https://ads.actioneer.dev/#/viz-charts)
|
|
346
351
|
- [StatusAnswer] — component (variants: tone: default|primary|success|warning|danger|info) [docs](https://ads.actioneer.dev/#/ai/answer)
|
|
347
352
|
- [Tab] — component (variants: variant: primary|secondary; orientation: horizontal|vertical; size: sm|md|lg; selected: true|false) [docs](https://ads.actioneer.dev/#/tabs)
|
|
348
353
|
- [Table] — Use Table for structured tabular data that may need row selection, column sorting, sticky columns, or a paginated footer — not for simple key-value lists. Interactive rows inherit the shared soft neutral hover/focus sink and keep their normal table geometry; do not add a brand tint or hover-only corner rounding. Primary record links stay text-only in every state: never reveal an arrow, chevron, or other directional icon only on hover. Persistent row actions use a final sticky-right column plus elevatedActionColumn so one body-column shadow lifts the action surface instead of repeating on individual cells. The empty matching header cell remains transparent and non-sticky. [docs](https://ads.actioneer.dev/#/table)
|
|
@@ -410,9 +415,12 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
410
415
|
- [EdgeTypes] — TypeScript type
|
|
411
416
|
- [ExplanationAnswerProps] — TypeScript type
|
|
412
417
|
- [ExplanationAnswerSpec] — TypeScript type
|
|
418
|
+
- [FunnelBarsHorizontalProps] — TypeScript type
|
|
413
419
|
- [FunnelChartProps] — TypeScript type
|
|
414
420
|
- [FunnelLabelContext] — TypeScript type
|
|
415
421
|
- [FunnelLabelRenderer] — TypeScript type
|
|
422
|
+
- [FunnelStep] — TypeScript type
|
|
423
|
+
- [FunnelVizProps] — TypeScript type
|
|
416
424
|
- [InfiniteCanvasProps] — TypeScript type
|
|
417
425
|
- [LineChartProps] — TypeScript type
|
|
418
426
|
- [Node] — TypeScript type
|
|
@@ -424,9 +432,14 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
424
432
|
- [RadarChartProps] — TypeScript type
|
|
425
433
|
- [RadialBarChartProps] — TypeScript type
|
|
426
434
|
- [ReactFlowInstance] — TypeScript type
|
|
435
|
+
- [RetentionCohort] — TypeScript type
|
|
436
|
+
- [RetentionCurveProps] — TypeScript type
|
|
437
|
+
- [RetentionGridProps] — TypeScript type
|
|
438
|
+
- [RetentionPoint] — TypeScript type
|
|
427
439
|
- [ScatterChartProps] — TypeScript type
|
|
428
440
|
- [Selection] — TypeScript type
|
|
429
441
|
- [SelectionMode] — TypeScript type
|
|
442
|
+
- [SeriesChartProps] — TypeScript type
|
|
430
443
|
- [SortDescriptor] — TypeScript type
|
|
431
444
|
- [SortDirection] — TypeScript type
|
|
432
445
|
- [StatusAnswerProps] — TypeScript type
|
|
@@ -447,6 +460,7 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
447
460
|
- [TrendAnswerProps] — TypeScript type
|
|
448
461
|
- [TrendAnswerSpec] — TypeScript type
|
|
449
462
|
- [Viewport] — TypeScript type
|
|
463
|
+
- [VizSeries] — TypeScript type
|
|
450
464
|
- [useEdgesState] — React hook
|
|
451
465
|
- [useNodesState] — React hook
|
|
452
466
|
- [useReactFlow] — React hook
|
|
@@ -466,6 +480,7 @@ When tabs and a search field control the same content, they share one responsive
|
|
|
466
480
|
- [getBezierPath] — utility
|
|
467
481
|
- [getSmoothStepPath] — utility
|
|
468
482
|
- [getStraightPath] — utility
|
|
483
|
+
- [MIN_HEIGHT] — utility
|
|
469
484
|
- [StatusAnswerSchema] — utility
|
|
470
485
|
- [TrendAnswerSchema] — utility
|
|
471
486
|
|