@actioneer/ads 0.5.0 → 0.5.2
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/chart.d.ts +1 -1
- package/components/ai-elements/index.d.ts +1 -0
- package/components/ai-elements/transcript.d.ts +37 -0
- package/components/ai-elements/transcript.js +46 -0
- package/components/assistant-ui/composer-harness.js +2 -2
- package/components/audio-waveform.d.ts +30 -0
- package/components/audio-waveform.js +147 -0
- package/components/breadcrumbs.js +36 -24
- package/components/button.js +10 -10
- package/components/chart.d.ts +4 -2
- package/components/chart.js +596 -513
- package/components/index.d.ts +1 -0
- package/components/index.js +456 -452
- package/components/resizable-panel.js +1 -1
- package/components/table.d.ts +10 -0
- package/components/table.js +217 -154
- package/lib/icons.d.ts +8 -0
- package/lib/icons.js +103 -101
- package/llms.txt +10 -4
- package/manifest.json +70 -8
- package/package.json +1 -1
- package/styles.css +39 -5
- package/theme.css +39 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
export declare const aiChartVariants: (props?: ({
|
|
4
|
-
status?: "error" | "
|
|
4
|
+
status?: "error" | "ready" | "pending" | "querying" | "partial" | "rendering" | "cancelled" | null | undefined;
|
|
5
5
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
6
|
export type AIChartStatus = NonNullable<VariantProps<typeof aiChartVariants>["status"]>;
|
|
7
7
|
export interface AIChartProgress {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Transcript — the ADS conversation-transcript element (ported from the voice
|
|
4
|
+
* product's call panel). A props-driven turn list for reviewing a finished
|
|
5
|
+
* agent↔user exchange: agent turns sit left on a whisper fill, user turns sit
|
|
6
|
+
* right on a muted fill, each headed by an uppercase role label and an
|
|
7
|
+
* optional time.
|
|
8
|
+
*
|
|
9
|
+
* Sentiment scanning: pass `tone` on a user turn ("positive" | "negative")
|
|
10
|
+
* to tint that bubble with the semantic success/danger fill and prefix the
|
|
11
|
+
* role label with a square `rounded-dot` marker — reviewers jump straight to
|
|
12
|
+
* the reactions that mattered. The component renders tones; the CALLER owns
|
|
13
|
+
* the analysis (lexicon, model, or human tags). Agent turns stay neutral:
|
|
14
|
+
* the agent reads a script, so only the user's reaction carries signal.
|
|
15
|
+
*
|
|
16
|
+
* No runtime dependency — compose it under any transport, and place it as a
|
|
17
|
+
* SIBLING of `MessageResponse`, never inside it (prose wrapper clobbers
|
|
18
|
+
* composed components).
|
|
19
|
+
*/
|
|
20
|
+
export type TranscriptTone = "positive" | "negative" | "neutral";
|
|
21
|
+
export interface TranscriptTurn {
|
|
22
|
+
id: string;
|
|
23
|
+
role: "agent" | "user";
|
|
24
|
+
text: string;
|
|
25
|
+
/** Short time label shown beside the role, e.g. "0:12". */
|
|
26
|
+
timeLabel?: string;
|
|
27
|
+
/** Sentiment tint — meaningful on user turns; ignored for agents. */
|
|
28
|
+
tone?: TranscriptTone;
|
|
29
|
+
}
|
|
30
|
+
export interface TranscriptProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
31
|
+
turns: TranscriptTurn[];
|
|
32
|
+
/** Role heading overrides (defaults: Agent / User). */
|
|
33
|
+
agentLabel?: string;
|
|
34
|
+
userLabel?: string;
|
|
35
|
+
emptyMessage?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function Transcript({ turns, agentLabel, userLabel, emptyMessage, className, ...props }: TranscriptProps): React.JSX.Element;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as e, jsxs as l } from "react/jsx-runtime";
|
|
3
|
+
import { cn as t } from "../../lib/cn.js";
|
|
4
|
+
function g({
|
|
5
|
+
turns: i,
|
|
6
|
+
agentLabel: c = "Agent",
|
|
7
|
+
userLabel: o = "User",
|
|
8
|
+
emptyMessage: m = "No transcript captured yet.",
|
|
9
|
+
className: n,
|
|
10
|
+
...d
|
|
11
|
+
}) {
|
|
12
|
+
return i.length === 0 ? /* @__PURE__ */ e("p", { className: t("text-sm text-muted-foreground", n), "data-slot": "transcript", ...d, children: m }) : /* @__PURE__ */ e("div", { className: t("space-y-3", n), "data-slot": "transcript", ...d, children: i.map((s) => {
|
|
13
|
+
const r = s.role === "user", a = r ? s.tone ?? "neutral" : "neutral";
|
|
14
|
+
return /* @__PURE__ */ e("div", { className: t("flex w-full", r ? "justify-end" : "justify-start"), children: /* @__PURE__ */ l(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
className: t(
|
|
18
|
+
"max-w-[84%] rounded-lg px-3 py-2.5",
|
|
19
|
+
r ? "bg-muted" : "bg-muted/25",
|
|
20
|
+
a === "positive" && "bg-success-100/70",
|
|
21
|
+
a === "negative" && "bg-danger-100/70"
|
|
22
|
+
),
|
|
23
|
+
children: [
|
|
24
|
+
/* @__PURE__ */ l("div", { className: t("mb-1 flex items-center gap-3", r && "justify-end"), children: [
|
|
25
|
+
a !== "neutral" && /* @__PURE__ */ e(
|
|
26
|
+
"span",
|
|
27
|
+
{
|
|
28
|
+
"aria-label": a === "positive" ? "Positive response" : "Negative response",
|
|
29
|
+
className: t(
|
|
30
|
+
"size-1.5 rounded-dot",
|
|
31
|
+
a === "positive" ? "bg-success-600" : "bg-danger-600"
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
),
|
|
35
|
+
/* @__PURE__ */ e("p", { className: "text-xs font-medium uppercase text-muted-foreground", children: r ? o : c }),
|
|
36
|
+
s.timeLabel && /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: s.timeLabel })
|
|
37
|
+
] }),
|
|
38
|
+
/* @__PURE__ */ e("p", { className: t("whitespace-pre-wrap break-words text-sm leading-relaxed", r && "text-right"), children: s.text })
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
) }, s.id);
|
|
42
|
+
}) });
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
g as Transcript
|
|
46
|
+
};
|
|
@@ -22,6 +22,8 @@ import "../file-dropzone.js";
|
|
|
22
22
|
import "../scroll-area.js";
|
|
23
23
|
import "../stepper.js";
|
|
24
24
|
import "../resizable-panel.js";
|
|
25
|
+
import "react";
|
|
26
|
+
import { Bolt as a, ChevronDown as f, CheckList as h, Sparkles as g } from "../../lib/icons.js";
|
|
25
27
|
import "../input.js";
|
|
26
28
|
import "../input-field.js";
|
|
27
29
|
import "../textarea.js";
|
|
@@ -34,9 +36,7 @@ import "../autocomplete.js";
|
|
|
34
36
|
import "../slider.js";
|
|
35
37
|
import "../segmented.js";
|
|
36
38
|
import "../modal.js";
|
|
37
|
-
import "react";
|
|
38
39
|
import "react-dom";
|
|
39
|
-
import { Bolt as a, ChevronDown as f, CheckList as h, Sparkles as g } from "../../lib/icons.js";
|
|
40
40
|
import "../drawer.js";
|
|
41
41
|
import "../popover.js";
|
|
42
42
|
import "motion/react";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* AudioWaveform — the ADS recording player (ported from the voice product's
|
|
4
|
+
* call panel). One waveform with play/seek, hover scrubbing, and a download
|
|
5
|
+
* action; controls are ADS Buttons and the elapsed time lives ON the play
|
|
6
|
+
* control (0:00 at rest — no separate time strip).
|
|
7
|
+
*
|
|
8
|
+
* Speaker-split mode: for two-channel conversation audio (channel 0 = agent,
|
|
9
|
+
* channel 1 = the caller) the agent's energy draws ABOVE the centerline and
|
|
10
|
+
* the caller's BELOW it, so turn-taking reads at a glance — one waveform,
|
|
11
|
+
* never two stacked lanes. Enabled automatically when `channels > 1`;
|
|
12
|
+
* label the halves with `topLabel` / `bottomLabel` (default Agent / User).
|
|
13
|
+
*
|
|
14
|
+
* Colors ride the theme tokens (waveform = muted-foreground, progress =
|
|
15
|
+
* foreground) — never hardcoded.
|
|
16
|
+
*/
|
|
17
|
+
export interface AudioWaveformProps {
|
|
18
|
+
/** Audio source URL (same-origin or CORS-served). */
|
|
19
|
+
src: string;
|
|
20
|
+
/** Known duration — lets the waveform render its scale before decode. */
|
|
21
|
+
durationSeconds?: number;
|
|
22
|
+
contentType?: string;
|
|
23
|
+
/** >1 enables speaker-split rendering (ch0 above, ch1 below). */
|
|
24
|
+
channels?: number;
|
|
25
|
+
topLabel?: string;
|
|
26
|
+
bottomLabel?: string;
|
|
27
|
+
downloadName?: string;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function AudioWaveform({ src, durationSeconds, contentType, channels, topLabel, bottomLabel, downloadName, className, }: AudioWaveformProps): React.JSX.Element;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as l, jsx as r } from "react/jsx-runtime";
|
|
3
|
+
import * as u from "react";
|
|
4
|
+
import { Button as ee, buttonVariants as re } from "./button.js";
|
|
5
|
+
import { Loader as te, Warning as ae, Pause as ne, Play as oe, Download as ie } from "../lib/icons.js";
|
|
6
|
+
import { cn as se } from "../lib/cn.js";
|
|
7
|
+
function A(t) {
|
|
8
|
+
if (!t || !Number.isFinite(t) || t < 0) return "0:00";
|
|
9
|
+
const e = Math.floor(t), a = Math.floor(e / 3600), c = Math.floor(e % 3600 / 60), d = e % 60;
|
|
10
|
+
return a > 0 ? `${a}:${String(c).padStart(2, "0")}:${String(d).padStart(2, "0")}` : `${c}:${String(d).padStart(2, "0")}`;
|
|
11
|
+
}
|
|
12
|
+
function B(t, e, a) {
|
|
13
|
+
return getComputedStyle(t).getPropertyValue(e).trim() || a;
|
|
14
|
+
}
|
|
15
|
+
function le(t, e, a) {
|
|
16
|
+
var m;
|
|
17
|
+
if (a) return a;
|
|
18
|
+
const c = e != null && e.includes("wav") ? "wav" : e != null && e.includes("mpeg") ? "mp3" : "audio", d = ((m = t.split("/").filter(Boolean).at(-1)) == null ? void 0 : m.split("?")[0]) || "recording";
|
|
19
|
+
return `${decodeURIComponent(d)}.${c}`;
|
|
20
|
+
}
|
|
21
|
+
function fe({
|
|
22
|
+
src: t,
|
|
23
|
+
durationSeconds: e,
|
|
24
|
+
contentType: a,
|
|
25
|
+
channels: c,
|
|
26
|
+
topLabel: d = "Agent",
|
|
27
|
+
bottomLabel: m = "User",
|
|
28
|
+
downloadName: U,
|
|
29
|
+
className: V
|
|
30
|
+
}) {
|
|
31
|
+
const F = u.useRef(null), p = u.useRef(null), [G, b] = u.useState(0), [L, D] = u.useState(e ?? 0), [k, C] = u.useState(!1), [E, x] = u.useState(!1), [f, R] = u.useState(null), v = (c ?? 0) > 1, q = le(t, a, U);
|
|
32
|
+
u.useEffect(() => {
|
|
33
|
+
const o = F.current;
|
|
34
|
+
if (!o) return;
|
|
35
|
+
let M = !1;
|
|
36
|
+
return b(0), D(e ?? 0), C(!1), x(!1), R(null), o.replaceChildren(), (async () => {
|
|
37
|
+
try {
|
|
38
|
+
const [{ default: w }, { default: K }] = await Promise.all([
|
|
39
|
+
import("wavesurfer.js"),
|
|
40
|
+
import("wavesurfer.js/dist/plugins/hover.esm.js")
|
|
41
|
+
]);
|
|
42
|
+
if (M) return;
|
|
43
|
+
const N = B(o, "--foreground", "currentColor"), O = B(o, "--muted-foreground", "currentColor"), Q = B(o, "--background", "Canvas"), X = (s, P) => {
|
|
44
|
+
const Y = s[0] ?? [], Z = s[1] ?? s[0] ?? [], { width: _, height: T } = P.canvas, y = T / 2, S = 4, I = 2, $ = Math.max(1, Math.floor(_ / (S + I))), H = (n, g) => {
|
|
45
|
+
if (!n.length) return 0;
|
|
46
|
+
const h = Math.floor(g / $ * n.length), j = Math.max(h + 1, Math.floor((g + 1) / $ * n.length));
|
|
47
|
+
let W = 0;
|
|
48
|
+
for (let z = h; z < j; z++) W = Math.max(W, Math.abs(Number(n[z]) || 0));
|
|
49
|
+
return W;
|
|
50
|
+
};
|
|
51
|
+
for (let n = 0; n < $; n++) {
|
|
52
|
+
const g = n * (S + I), h = Math.max(1, H(Y, n) * (y - 2)), j = Math.max(1, H(Z, n) * (y - 2));
|
|
53
|
+
P.fillRect(g, y - h, S, h), P.fillRect(g, y + 1, S, j);
|
|
54
|
+
}
|
|
55
|
+
}, i = w.create({
|
|
56
|
+
container: o,
|
|
57
|
+
url: t,
|
|
58
|
+
duration: e,
|
|
59
|
+
height: 92,
|
|
60
|
+
normalize: !0,
|
|
61
|
+
waveColor: O,
|
|
62
|
+
progressColor: N,
|
|
63
|
+
cursorColor: N,
|
|
64
|
+
cursorWidth: 1,
|
|
65
|
+
barWidth: 2,
|
|
66
|
+
barGap: 1,
|
|
67
|
+
barRadius: 2,
|
|
68
|
+
barMinHeight: 1,
|
|
69
|
+
dragToSeek: !0,
|
|
70
|
+
hideScrollbar: !0,
|
|
71
|
+
renderFunction: v ? X : void 0,
|
|
72
|
+
plugins: [
|
|
73
|
+
K.create({
|
|
74
|
+
lineColor: N,
|
|
75
|
+
labelColor: Q,
|
|
76
|
+
labelBackground: N,
|
|
77
|
+
labelSize: 11,
|
|
78
|
+
formatTimeCallback: A
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
});
|
|
82
|
+
p.current = i, i.on("ready", (s) => {
|
|
83
|
+
D(s), C(!0);
|
|
84
|
+
}), i.on("timeupdate", (s) => b(s)), i.on("seeking", (s) => b(s)), i.on("play", () => x(!0)), i.on("pause", () => x(!1)), i.on("finish", () => {
|
|
85
|
+
x(!1), b(i.getDuration());
|
|
86
|
+
}), i.on("error", () => {
|
|
87
|
+
R("Recording could not be loaded."), C(!1);
|
|
88
|
+
});
|
|
89
|
+
} catch {
|
|
90
|
+
M || R("Recording could not be loaded.");
|
|
91
|
+
}
|
|
92
|
+
})(), () => {
|
|
93
|
+
var w;
|
|
94
|
+
M = !0, (w = p.current) == null || w.destroy(), p.current = null;
|
|
95
|
+
};
|
|
96
|
+
}, [t, e, v]);
|
|
97
|
+
const J = () => {
|
|
98
|
+
var o;
|
|
99
|
+
!k || f || (o = p.current) == null || o.playPause();
|
|
100
|
+
};
|
|
101
|
+
return /* @__PURE__ */ l("div", { className: se("space-y-3", V), "data-slot": "audio-waveform", children: [
|
|
102
|
+
/* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-3", children: [
|
|
103
|
+
/* @__PURE__ */ l("div", { className: "min-w-0", children: [
|
|
104
|
+
/* @__PURE__ */ r("p", { className: "text-base font-medium", children: "Recording" }),
|
|
105
|
+
/* @__PURE__ */ r("p", { className: "mt-0.5 truncate text-xs text-muted-foreground", children: v ? `${d} above · ${m.toLowerCase()} below` : a ?? "Audio" })
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ r("p", { className: "font-mono text-xs tabular-nums text-muted-foreground", children: A(L) })
|
|
108
|
+
] }),
|
|
109
|
+
/* @__PURE__ */ l("div", { className: "relative overflow-hidden py-2", children: [
|
|
110
|
+
v && /* @__PURE__ */ l("div", { className: "pointer-events-none absolute inset-x-0 top-2 z-10 flex h-[92px] flex-col items-center justify-between text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: [
|
|
111
|
+
/* @__PURE__ */ r("span", { className: "rounded-sm bg-card/85 px-1.5 py-0.5", children: d }),
|
|
112
|
+
/* @__PURE__ */ r("span", { className: "rounded-sm bg-card/85 px-1.5 py-0.5", children: m })
|
|
113
|
+
] }),
|
|
114
|
+
/* @__PURE__ */ r("div", { ref: F, className: "min-h-[92px]" }),
|
|
115
|
+
!k && !f && /* @__PURE__ */ r("div", { className: "absolute inset-0 flex items-center justify-center bg-background/70", children: /* @__PURE__ */ l("div", { className: "inline-flex items-center gap-2 rounded-md bg-background px-3 py-1.5 text-xs text-muted-foreground", children: [
|
|
116
|
+
/* @__PURE__ */ r(te, { className: "size-3.5 animate-spin motion-reduce:animate-none", "aria-hidden": "true" }),
|
|
117
|
+
"Loading waveform"
|
|
118
|
+
] }) }),
|
|
119
|
+
f && /* @__PURE__ */ r("div", { className: "absolute inset-0 flex items-center justify-center bg-background/80", children: /* @__PURE__ */ l("div", { className: "inline-flex items-center gap-2 rounded-md bg-background px-3 py-1.5 text-xs text-muted-foreground", children: [
|
|
120
|
+
/* @__PURE__ */ r(ae, { className: "size-3.5", "aria-hidden": "true" }),
|
|
121
|
+
f
|
|
122
|
+
] }) })
|
|
123
|
+
] }),
|
|
124
|
+
/* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-3", children: [
|
|
125
|
+
/* @__PURE__ */ r(
|
|
126
|
+
ee,
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
variant: "secondary",
|
|
130
|
+
onClick: J,
|
|
131
|
+
disabled: !k || !!f,
|
|
132
|
+
"aria-label": E ? "Pause recording" : "Play recording",
|
|
133
|
+
startContent: E ? /* @__PURE__ */ r(ne, { "aria-hidden": "true" }) : /* @__PURE__ */ r(oe, { "aria-hidden": "true" }),
|
|
134
|
+
className: "font-mono tabular-nums",
|
|
135
|
+
children: A(G)
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
/* @__PURE__ */ l("a", { href: t, download: q, className: re({ variant: "ghost" }), children: [
|
|
139
|
+
/* @__PURE__ */ r(ie, { "aria-hidden": "true", className: "size-4" }),
|
|
140
|
+
"Audio"
|
|
141
|
+
] })
|
|
142
|
+
] })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
export {
|
|
146
|
+
fe as AudioWaveform
|
|
147
|
+
};
|
|
@@ -1,50 +1,62 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as e, jsxs as
|
|
3
|
-
import * as
|
|
2
|
+
import { jsx as e, jsxs as b } from "react/jsx-runtime";
|
|
3
|
+
import * as r from "react";
|
|
4
4
|
import { ChevronRight as g } from "../lib/icons.js";
|
|
5
|
-
import { cn as
|
|
6
|
-
const
|
|
5
|
+
import { cn as n } from "../lib/cn.js";
|
|
6
|
+
const l = r.createContext({
|
|
7
7
|
count: 0
|
|
8
|
-
}),
|
|
9
|
-
({ className: i, children:
|
|
10
|
-
const
|
|
11
|
-
return /* @__PURE__ */ e(
|
|
8
|
+
}), u = r.createContext(0), p = r.forwardRef(
|
|
9
|
+
({ className: i, children: o, ...c }, t) => {
|
|
10
|
+
const s = r.Children.toArray(o);
|
|
11
|
+
return /* @__PURE__ */ e(
|
|
12
|
+
"nav",
|
|
13
|
+
{
|
|
14
|
+
ref: t,
|
|
15
|
+
"aria-label": "Breadcrumb",
|
|
16
|
+
className: n(
|
|
17
|
+
"flex min-h-12 w-full items-center border-b border-border",
|
|
18
|
+
i
|
|
19
|
+
),
|
|
20
|
+
...c,
|
|
21
|
+
children: /* @__PURE__ */ e("ol", { className: "flex min-w-0 items-center gap-1.5 text-xs", children: /* @__PURE__ */ e(l.Provider, { value: { count: s.length }, children: s.map((m, a) => /* @__PURE__ */ e(u.Provider, { value: a, children: m }, a)) }) })
|
|
22
|
+
}
|
|
23
|
+
);
|
|
12
24
|
}
|
|
13
25
|
);
|
|
14
|
-
|
|
15
|
-
const h =
|
|
16
|
-
const { count:
|
|
26
|
+
p.displayName = "Breadcrumbs";
|
|
27
|
+
const h = r.forwardRef(({ className: i, href: o, isCurrent: c, children: t, ...s }, m) => {
|
|
28
|
+
const { count: a } = r.useContext(l), x = r.useContext(u) === a - 1, d = "inline-flex items-center", f = c ? /* @__PURE__ */ e(
|
|
17
29
|
"span",
|
|
18
30
|
{
|
|
19
31
|
"aria-current": "page",
|
|
20
|
-
className:
|
|
21
|
-
children:
|
|
32
|
+
className: n(d, "font-medium text-foreground"),
|
|
33
|
+
children: t
|
|
22
34
|
}
|
|
23
|
-
) :
|
|
35
|
+
) : o ? /* @__PURE__ */ e(
|
|
24
36
|
"a",
|
|
25
37
|
{
|
|
26
|
-
href:
|
|
27
|
-
className:
|
|
38
|
+
href: o,
|
|
39
|
+
className: n(
|
|
28
40
|
d,
|
|
29
|
-
"font-medium text-foreground transition-colors hover:underline",
|
|
41
|
+
"font-medium text-muted-foreground transition-colors hover:text-foreground hover:underline",
|
|
30
42
|
"outline-none focus-visible:ring-3 focus-visible:ring-ring rounded-sm"
|
|
31
43
|
),
|
|
32
|
-
children:
|
|
44
|
+
children: t
|
|
33
45
|
}
|
|
34
|
-
) : /* @__PURE__ */ e("span", { className:
|
|
35
|
-
return /* @__PURE__ */
|
|
46
|
+
) : /* @__PURE__ */ e("span", { className: n(d, "text-muted-foreground"), children: t });
|
|
47
|
+
return /* @__PURE__ */ b(
|
|
36
48
|
"li",
|
|
37
49
|
{
|
|
38
50
|
ref: m,
|
|
39
|
-
className:
|
|
40
|
-
...
|
|
51
|
+
className: n("flex items-center gap-1.5", i),
|
|
52
|
+
...s,
|
|
41
53
|
children: [
|
|
42
54
|
f,
|
|
43
55
|
!x && /* @__PURE__ */ e(
|
|
44
56
|
g,
|
|
45
57
|
{
|
|
46
58
|
"aria-hidden": !0,
|
|
47
|
-
className: "size-3.5 shrink-0 text-
|
|
59
|
+
className: "size-3.5 shrink-0 text-border-strong"
|
|
48
60
|
}
|
|
49
61
|
)
|
|
50
62
|
]
|
|
@@ -54,5 +66,5 @@ const h = t.forwardRef(({ className: i, href: n, isCurrent: c, children: r, ...o
|
|
|
54
66
|
h.displayName = "BreadcrumbItem";
|
|
55
67
|
export {
|
|
56
68
|
h as BreadcrumbItem,
|
|
57
|
-
|
|
69
|
+
p as Breadcrumbs
|
|
58
70
|
};
|
package/components/button.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as r, jsx as
|
|
2
|
+
import { jsxs as r, jsx as u } from "react/jsx-runtime";
|
|
3
3
|
import * as c from "react";
|
|
4
4
|
import { cva as v } from "class-variance-authority";
|
|
5
5
|
import { cn as t } from "../lib/cn.js";
|
|
@@ -22,7 +22,7 @@ const p = v(
|
|
|
22
22
|
variant: {
|
|
23
23
|
solid: "bg-brand text-brand-foreground shadow-[var(--inner-glow-cta)] hover:bg-brand-hover",
|
|
24
24
|
secondary: "bg-fill text-fill-foreground shadow-[var(--inner-glow-fill)] hover:bg-fill/70",
|
|
25
|
-
outline: "border-border
|
|
25
|
+
outline: "border-border bg-transparent text-foreground hover:border-border-strong hover:bg-muted",
|
|
26
26
|
ghost: "bg-transparent text-foreground hover:bg-muted",
|
|
27
27
|
soft: "bg-muted text-foreground shadow-[var(--inner-glow-fill)] hover:bg-fill",
|
|
28
28
|
link: "bg-transparent text-foreground underline-offset-4 hover:underline active:scale-none",
|
|
@@ -43,31 +43,31 @@ const p = v(
|
|
|
43
43
|
), x = c.forwardRef(
|
|
44
44
|
({
|
|
45
45
|
className: n,
|
|
46
|
-
variant:
|
|
47
|
-
size:
|
|
46
|
+
variant: o,
|
|
47
|
+
size: s,
|
|
48
48
|
isLoading: e = !1,
|
|
49
49
|
startContent: i,
|
|
50
50
|
endContent: a,
|
|
51
51
|
fullWidth: d,
|
|
52
52
|
disabled: l,
|
|
53
53
|
children: g,
|
|
54
|
-
...
|
|
55
|
-
},
|
|
54
|
+
...b
|
|
55
|
+
}, f) => /* @__PURE__ */ r(
|
|
56
56
|
"button",
|
|
57
57
|
{
|
|
58
|
-
ref:
|
|
58
|
+
ref: f,
|
|
59
59
|
disabled: l || e,
|
|
60
60
|
"aria-busy": e || void 0,
|
|
61
61
|
className: t(
|
|
62
|
-
p({ variant:
|
|
62
|
+
p({ variant: o, size: s }),
|
|
63
63
|
d && "w-full",
|
|
64
64
|
// Real disabled fades; loading keeps the brand color
|
|
65
65
|
e ? "opacity-100" : "disabled:opacity-50",
|
|
66
66
|
n
|
|
67
67
|
),
|
|
68
|
-
...
|
|
68
|
+
...b,
|
|
69
69
|
children: [
|
|
70
|
-
e && /* @__PURE__ */
|
|
70
|
+
e && /* @__PURE__ */ u(
|
|
71
71
|
m,
|
|
72
72
|
{
|
|
73
73
|
size: "sm",
|
package/components/chart.d.ts
CHANGED
|
@@ -203,9 +203,11 @@ export interface FunnelChartProps {
|
|
|
203
203
|
valueKey: string;
|
|
204
204
|
height?: number;
|
|
205
205
|
formatValue?: (value: number) => string;
|
|
206
|
-
/** Custom
|
|
206
|
+
/** Custom per-stage metric label (default: % of the first stage, above the
|
|
207
|
+
* bar), or false to hide it. Stage name + value under each column are
|
|
208
|
+
* structural and always render. */
|
|
207
209
|
label?: FunnelLabelRenderer | false;
|
|
208
|
-
/**
|
|
210
|
+
/** @deprecated The stepped funnel has no right-hand label channel; ignored. */
|
|
209
211
|
labelWidth?: number;
|
|
210
212
|
tooltip?: ChartTooltipRenderer | false;
|
|
211
213
|
className?: string;
|