hazo_ui 3.4.1 → 4.1.1
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/CHANGE_LOG.md +44 -0
- package/README.md +106 -0
- package/SETUP_CHECKLIST.md +8 -1
- package/dist/index.cjs +279 -579
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -63
- package/dist/index.d.ts +53 -63
- package/dist/index.js +276 -578
- package/dist/index.js.map +1 -1
- package/package.json +4 -8
package/dist/index.js
CHANGED
|
@@ -72,6 +72,7 @@ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
|
72
72
|
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
73
73
|
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
74
74
|
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
75
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
75
76
|
import { Toaster, toast } from 'sonner';
|
|
76
77
|
export { toast as rawToast } from 'sonner';
|
|
77
78
|
import { useHazoState } from 'hazo_state/client';
|
|
@@ -7390,6 +7391,51 @@ function ButtonGroupText({ className, asChild = false, ...props }) {
|
|
|
7390
7391
|
function ButtonGroupSeparator({ className, orientation = "vertical", ...props }) {
|
|
7391
7392
|
return /* @__PURE__ */ jsx(Separator3, { orientation, className: cn("bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto", className), ...props });
|
|
7392
7393
|
}
|
|
7394
|
+
var Slider = React26.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
7395
|
+
SliderPrimitive.Root,
|
|
7396
|
+
{
|
|
7397
|
+
ref,
|
|
7398
|
+
className: cn("relative flex w-full touch-none select-none items-center", className),
|
|
7399
|
+
...props,
|
|
7400
|
+
children: [
|
|
7401
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Track, { className: "relative h-2 w-full grow overflow-hidden rounded-full bg-secondary", children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }),
|
|
7402
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Thumb, { className: "block h-5 w-5 rounded-full border-2 border-primary bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" })
|
|
7403
|
+
]
|
|
7404
|
+
}
|
|
7405
|
+
));
|
|
7406
|
+
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
7407
|
+
var InputAffix = React26.forwardRef(
|
|
7408
|
+
({ className, containerClassName, prefix, suffix, type = "text", ...props }, ref) => {
|
|
7409
|
+
return /* @__PURE__ */ jsxs(
|
|
7410
|
+
"div",
|
|
7411
|
+
{
|
|
7412
|
+
className: cn(
|
|
7413
|
+
"flex h-10 w-full items-center rounded-md border border-input bg-background text-sm ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
|
7414
|
+
containerClassName
|
|
7415
|
+
),
|
|
7416
|
+
children: [
|
|
7417
|
+
prefix != null && /* @__PURE__ */ jsx("span", { className: "flex select-none items-center pl-3 text-muted-foreground", children: prefix }),
|
|
7418
|
+
/* @__PURE__ */ jsx(
|
|
7419
|
+
"input",
|
|
7420
|
+
{
|
|
7421
|
+
type,
|
|
7422
|
+
ref,
|
|
7423
|
+
className: cn(
|
|
7424
|
+
"h-full w-full bg-transparent px-3 py-2 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
7425
|
+
prefix != null && "pl-2",
|
|
7426
|
+
suffix != null && "pr-2",
|
|
7427
|
+
className
|
|
7428
|
+
),
|
|
7429
|
+
...props
|
|
7430
|
+
}
|
|
7431
|
+
),
|
|
7432
|
+
suffix != null && /* @__PURE__ */ jsx("span", { className: "flex select-none items-center pr-3 text-muted-foreground", children: suffix })
|
|
7433
|
+
]
|
|
7434
|
+
}
|
|
7435
|
+
);
|
|
7436
|
+
}
|
|
7437
|
+
);
|
|
7438
|
+
InputAffix.displayName = "InputAffix";
|
|
7393
7439
|
var SkeletonBase = React26.forwardRef(
|
|
7394
7440
|
({ className, ...rest }, ref) => /* @__PURE__ */ jsx(
|
|
7395
7441
|
"div",
|
|
@@ -9668,573 +9714,12 @@ function pick_x_label_indices(length) {
|
|
|
9668
9714
|
if (length === 2) return [0, 0, 1];
|
|
9669
9715
|
return [0, Math.floor(length / 2), length - 1];
|
|
9670
9716
|
}
|
|
9671
|
-
var PAD_LEFT =
|
|
9672
|
-
var PAD_RIGHT =
|
|
9673
|
-
var PAD_TOP =
|
|
9717
|
+
var PAD_LEFT = 32;
|
|
9718
|
+
var PAD_RIGHT = 8;
|
|
9719
|
+
var PAD_TOP = 10;
|
|
9674
9720
|
var PAD_BOTTOM = 22;
|
|
9675
|
-
var AXIS_LABEL_COLOR = "#8b949e";
|
|
9676
|
-
var GRIDLINE_COLOR = "#2a3441";
|
|
9677
|
-
function compute_geometry(data, width, height) {
|
|
9678
|
-
const vals = data.filter((v) => v !== null && !Number.isNaN(v));
|
|
9679
|
-
if (vals.length === 0) return null;
|
|
9680
|
-
const mn = Math.min(...vals);
|
|
9681
|
-
const mx = Math.max(...vals);
|
|
9682
|
-
const rng = mx - mn || mx * 0.1 + 1;
|
|
9683
|
-
const y_min = Math.max(0, mn - rng * 0.1);
|
|
9684
|
-
const y_max = mx + rng * 0.1;
|
|
9685
|
-
const y_rng = y_max - y_min || 1;
|
|
9686
|
-
const plot_w = width - PAD_LEFT - PAD_RIGHT;
|
|
9687
|
-
const plot_h = height - PAD_TOP - PAD_BOTTOM;
|
|
9688
|
-
return {
|
|
9689
|
-
vbox_w: width,
|
|
9690
|
-
vbox_h: height,
|
|
9691
|
-
y_min,
|
|
9692
|
-
y_max,
|
|
9693
|
-
cx: (i) => data.length <= 1 ? PAD_LEFT + plot_w / 2 : PAD_LEFT + i * plot_w / (data.length - 1),
|
|
9694
|
-
cy: (v) => PAD_TOP + (1 - (v - y_min) / y_rng) * plot_h
|
|
9695
|
-
};
|
|
9696
|
-
}
|
|
9697
|
-
function build_paths(data, g) {
|
|
9698
|
-
let line_d = "";
|
|
9699
|
-
let first_idx = -1;
|
|
9700
|
-
data.forEach((v, i) => {
|
|
9701
|
-
if (v === null || Number.isNaN(v)) return;
|
|
9702
|
-
if (first_idx === -1) first_idx = i;
|
|
9703
|
-
line_d += `${line_d ? " L" : "M"}${g.cx(i).toFixed(1)},${g.cy(v).toFixed(1)}`;
|
|
9704
|
-
});
|
|
9705
|
-
const last_idx = data.length - 1;
|
|
9706
|
-
const last_v = data[last_idx];
|
|
9707
|
-
const area_d = line_d && last_v !== null && last_v !== void 0 && !Number.isNaN(last_v) ? `${line_d} L${g.cx(last_idx).toFixed(1)},${g.vbox_h - PAD_BOTTOM} L${g.cx(first_idx).toFixed(1)},${g.vbox_h - PAD_BOTTOM} Z` : "";
|
|
9708
|
-
return { line_d, area_d };
|
|
9709
|
-
}
|
|
9710
|
-
function LineChart({
|
|
9711
|
-
data,
|
|
9712
|
-
dates,
|
|
9713
|
-
color: color2,
|
|
9714
|
-
width = 360,
|
|
9715
|
-
height = 130,
|
|
9716
|
-
unit = "",
|
|
9717
|
-
showTooltip = true,
|
|
9718
|
-
className
|
|
9719
|
-
}) {
|
|
9720
|
-
const geo = compute_geometry(data, width, height);
|
|
9721
|
-
const svg_ref = React26.useRef(null);
|
|
9722
|
-
const [hover_idx, set_hover_idx] = React26.useState(null);
|
|
9723
|
-
const handle_mouse_move = React26.useCallback(
|
|
9724
|
-
(e) => {
|
|
9725
|
-
if (!geo) return;
|
|
9726
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
9727
|
-
if (rect.width === 0) return;
|
|
9728
|
-
const vbox_x = (e.clientX - rect.left) / rect.width * geo.vbox_w;
|
|
9729
|
-
const plot_w = geo.vbox_w - PAD_LEFT - PAD_RIGHT;
|
|
9730
|
-
if (vbox_x < PAD_LEFT || vbox_x > geo.vbox_w - PAD_RIGHT) {
|
|
9731
|
-
set_hover_idx(null);
|
|
9732
|
-
return;
|
|
9733
|
-
}
|
|
9734
|
-
const ratio = (vbox_x - PAD_LEFT) / plot_w;
|
|
9735
|
-
const idx = Math.round(ratio * (data.length - 1));
|
|
9736
|
-
const clamped = Math.max(0, Math.min(data.length - 1, idx));
|
|
9737
|
-
let resolved = clamped;
|
|
9738
|
-
if (data[resolved] === null || Number.isNaN(data[resolved])) {
|
|
9739
|
-
for (let step = 1; step < data.length; step += 1) {
|
|
9740
|
-
const left_i = clamped - step;
|
|
9741
|
-
const right_i = clamped + step;
|
|
9742
|
-
if (left_i >= 0 && data[left_i] !== null && !Number.isNaN(data[left_i])) {
|
|
9743
|
-
resolved = left_i;
|
|
9744
|
-
break;
|
|
9745
|
-
}
|
|
9746
|
-
if (right_i < data.length && data[right_i] !== null && !Number.isNaN(data[right_i])) {
|
|
9747
|
-
resolved = right_i;
|
|
9748
|
-
break;
|
|
9749
|
-
}
|
|
9750
|
-
}
|
|
9751
|
-
}
|
|
9752
|
-
set_hover_idx(resolved);
|
|
9753
|
-
},
|
|
9754
|
-
[geo, data]
|
|
9755
|
-
);
|
|
9756
|
-
const handle_mouse_leave = React26.useCallback(() => set_hover_idx(null), []);
|
|
9757
|
-
if (!geo) {
|
|
9758
|
-
return /* @__PURE__ */ jsx(
|
|
9759
|
-
"svg",
|
|
9760
|
-
{
|
|
9761
|
-
viewBox: `0 0 ${width} ${height}`,
|
|
9762
|
-
className: cn("cls_hazo_chart cls_hazo_chart_empty", className),
|
|
9763
|
-
style: { width: "100%", height: "auto", display: "block", maxHeight: `${height + 10}px` }
|
|
9764
|
-
}
|
|
9765
|
-
);
|
|
9766
|
-
}
|
|
9767
|
-
const { line_d, area_d } = build_paths(data, geo);
|
|
9768
|
-
const x_label_idx = pick_x_label_indices(data.length);
|
|
9769
|
-
const last_idx = data.length - 1;
|
|
9770
|
-
const last_v = data[last_idx];
|
|
9771
|
-
const has_last = last_v !== null && last_v !== void 0 && !Number.isNaN(last_v);
|
|
9772
|
-
const hover_v = hover_idx !== null ? data[hover_idx] : null;
|
|
9773
|
-
const hover_has_v = hover_v !== null && hover_v !== void 0 && !Number.isNaN(hover_v);
|
|
9774
|
-
return /* @__PURE__ */ jsxs(
|
|
9775
|
-
"svg",
|
|
9776
|
-
{
|
|
9777
|
-
ref: svg_ref,
|
|
9778
|
-
viewBox: `0 0 ${width} ${height}`,
|
|
9779
|
-
onMouseMove: showTooltip ? handle_mouse_move : void 0,
|
|
9780
|
-
onMouseLeave: showTooltip ? handle_mouse_leave : void 0,
|
|
9781
|
-
className: cn("cls_hazo_chart", className),
|
|
9782
|
-
style: {
|
|
9783
|
-
width: "100%",
|
|
9784
|
-
height: "auto",
|
|
9785
|
-
display: "block",
|
|
9786
|
-
maxHeight: `${height + 10}px`,
|
|
9787
|
-
cursor: showTooltip ? "crosshair" : "default"
|
|
9788
|
-
},
|
|
9789
|
-
children: [
|
|
9790
|
-
[0, 1, 2].map((i) => {
|
|
9791
|
-
const y = PAD_TOP + i / 2 * (geo.vbox_h - PAD_TOP - PAD_BOTTOM);
|
|
9792
|
-
return /* @__PURE__ */ jsx(
|
|
9793
|
-
"line",
|
|
9794
|
-
{
|
|
9795
|
-
x1: PAD_LEFT,
|
|
9796
|
-
x2: geo.vbox_w - PAD_RIGHT,
|
|
9797
|
-
y1: y,
|
|
9798
|
-
y2: y,
|
|
9799
|
-
stroke: GRIDLINE_COLOR,
|
|
9800
|
-
strokeWidth: 0.5,
|
|
9801
|
-
strokeDasharray: "2,3"
|
|
9802
|
-
},
|
|
9803
|
-
i
|
|
9804
|
-
);
|
|
9805
|
-
}),
|
|
9806
|
-
area_d && /* @__PURE__ */ jsx("path", { d: area_d, fill: color2, fillOpacity: 0.12, stroke: "none" }),
|
|
9807
|
-
line_d && /* @__PURE__ */ jsx("path", { d: line_d, stroke: color2, strokeWidth: 1.8, fill: "none" }),
|
|
9808
|
-
/* @__PURE__ */ jsx("text", { x: PAD_LEFT - 4, y: PAD_TOP + 3, textAnchor: "end", fill: AXIS_LABEL_COLOR, fontSize: 9, children: format_num(geo.y_max) }),
|
|
9809
|
-
/* @__PURE__ */ jsx(
|
|
9810
|
-
"text",
|
|
9811
|
-
{
|
|
9812
|
-
x: PAD_LEFT - 4,
|
|
9813
|
-
y: PAD_TOP + (geo.vbox_h - PAD_TOP - PAD_BOTTOM) / 2 + 3,
|
|
9814
|
-
textAnchor: "end",
|
|
9815
|
-
fill: AXIS_LABEL_COLOR,
|
|
9816
|
-
fontSize: 9,
|
|
9817
|
-
children: format_num((geo.y_max + geo.y_min) / 2)
|
|
9818
|
-
}
|
|
9819
|
-
),
|
|
9820
|
-
/* @__PURE__ */ jsx(
|
|
9821
|
-
"text",
|
|
9822
|
-
{
|
|
9823
|
-
x: PAD_LEFT - 4,
|
|
9824
|
-
y: geo.vbox_h - PAD_BOTTOM + 3,
|
|
9825
|
-
textAnchor: "end",
|
|
9826
|
-
fill: AXIS_LABEL_COLOR,
|
|
9827
|
-
fontSize: 9,
|
|
9828
|
-
children: format_num(geo.y_min)
|
|
9829
|
-
}
|
|
9830
|
-
),
|
|
9831
|
-
x_label_idx.map((idx, k) => {
|
|
9832
|
-
const anchor = k === 0 ? "start" : k === 1 ? "middle" : "end";
|
|
9833
|
-
const x_pos = geo.cx(idx);
|
|
9834
|
-
return /* @__PURE__ */ jsx(
|
|
9835
|
-
"text",
|
|
9836
|
-
{
|
|
9837
|
-
x: x_pos,
|
|
9838
|
-
y: geo.vbox_h - 6,
|
|
9839
|
-
textAnchor: anchor,
|
|
9840
|
-
fill: AXIS_LABEL_COLOR,
|
|
9841
|
-
fontSize: 9,
|
|
9842
|
-
children: dates[idx] ?? ""
|
|
9843
|
-
},
|
|
9844
|
-
`x_${k}`
|
|
9845
|
-
);
|
|
9846
|
-
}),
|
|
9847
|
-
has_last && hover_idx === null && (() => {
|
|
9848
|
-
const x = geo.cx(last_idx);
|
|
9849
|
-
const y = geo.cy(last_v);
|
|
9850
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
9851
|
-
/* @__PURE__ */ jsx(
|
|
9852
|
-
"line",
|
|
9853
|
-
{
|
|
9854
|
-
x1: x,
|
|
9855
|
-
x2: PAD_LEFT,
|
|
9856
|
-
y1: y,
|
|
9857
|
-
y2: y,
|
|
9858
|
-
stroke: color2,
|
|
9859
|
-
strokeWidth: 0.5,
|
|
9860
|
-
strokeDasharray: "2,2",
|
|
9861
|
-
opacity: 0.4
|
|
9862
|
-
}
|
|
9863
|
-
),
|
|
9864
|
-
/* @__PURE__ */ jsx("circle", { cx: x, cy: y, r: 3.5, fill: color2, stroke: color2, strokeWidth: 2, fillOpacity: 0.3 }),
|
|
9865
|
-
/* @__PURE__ */ jsx("circle", { cx: x, cy: y, r: 2, fill: color2 }),
|
|
9866
|
-
/* @__PURE__ */ jsxs("text", { x: x - 6, y: y - 6, textAnchor: "end", fill: color2, fontSize: 10, fontWeight: 700, children: [
|
|
9867
|
-
format_num(last_v),
|
|
9868
|
-
unit
|
|
9869
|
-
] })
|
|
9870
|
-
] });
|
|
9871
|
-
})(),
|
|
9872
|
-
showTooltip && hover_idx !== null && hover_has_v && (() => {
|
|
9873
|
-
const x = geo.cx(hover_idx);
|
|
9874
|
-
const y = geo.cy(hover_v);
|
|
9875
|
-
const label = `${format_num(hover_v)}${unit}`;
|
|
9876
|
-
const date = dates[hover_idx] ?? "";
|
|
9877
|
-
const bubble_text_w = Math.max(label.length, date.length) * 5.5 + 12;
|
|
9878
|
-
const bubble_w = Math.max(bubble_text_w, 40);
|
|
9879
|
-
const bubble_h = 26;
|
|
9880
|
-
const flip = x + bubble_w + 6 > geo.vbox_w - PAD_RIGHT;
|
|
9881
|
-
const bubble_x = flip ? x - bubble_w - 6 : x + 6;
|
|
9882
|
-
const bubble_y = Math.max(PAD_TOP, Math.min(y - bubble_h / 2, geo.vbox_h - PAD_BOTTOM - bubble_h));
|
|
9883
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
9884
|
-
/* @__PURE__ */ jsx(
|
|
9885
|
-
"line",
|
|
9886
|
-
{
|
|
9887
|
-
x1: x,
|
|
9888
|
-
x2: x,
|
|
9889
|
-
y1: PAD_TOP,
|
|
9890
|
-
y2: geo.vbox_h - PAD_BOTTOM,
|
|
9891
|
-
stroke: color2,
|
|
9892
|
-
strokeWidth: 0.5,
|
|
9893
|
-
strokeDasharray: "2,2",
|
|
9894
|
-
opacity: 0.6
|
|
9895
|
-
}
|
|
9896
|
-
),
|
|
9897
|
-
/* @__PURE__ */ jsx("circle", { cx: x, cy: y, r: 3, fill: color2 }),
|
|
9898
|
-
/* @__PURE__ */ jsx(
|
|
9899
|
-
"rect",
|
|
9900
|
-
{
|
|
9901
|
-
x: bubble_x,
|
|
9902
|
-
y: bubble_y,
|
|
9903
|
-
width: bubble_w,
|
|
9904
|
-
height: bubble_h,
|
|
9905
|
-
rx: 3,
|
|
9906
|
-
fill: "#0d1117",
|
|
9907
|
-
stroke: color2,
|
|
9908
|
-
strokeWidth: 0.5,
|
|
9909
|
-
fillOpacity: 0.92
|
|
9910
|
-
}
|
|
9911
|
-
),
|
|
9912
|
-
/* @__PURE__ */ jsx(
|
|
9913
|
-
"text",
|
|
9914
|
-
{
|
|
9915
|
-
x: bubble_x + bubble_w / 2,
|
|
9916
|
-
y: bubble_y + 11,
|
|
9917
|
-
textAnchor: "middle",
|
|
9918
|
-
fill: color2,
|
|
9919
|
-
fontSize: 10,
|
|
9920
|
-
fontWeight: 700,
|
|
9921
|
-
children: label
|
|
9922
|
-
}
|
|
9923
|
-
),
|
|
9924
|
-
/* @__PURE__ */ jsx(
|
|
9925
|
-
"text",
|
|
9926
|
-
{
|
|
9927
|
-
x: bubble_x + bubble_w / 2,
|
|
9928
|
-
y: bubble_y + 22,
|
|
9929
|
-
textAnchor: "middle",
|
|
9930
|
-
fill: AXIS_LABEL_COLOR,
|
|
9931
|
-
fontSize: 8,
|
|
9932
|
-
children: date
|
|
9933
|
-
}
|
|
9934
|
-
)
|
|
9935
|
-
] });
|
|
9936
|
-
})()
|
|
9937
|
-
]
|
|
9938
|
-
}
|
|
9939
|
-
);
|
|
9940
|
-
}
|
|
9941
|
-
var PAD_LEFT2 = 38;
|
|
9942
|
-
var PAD_RIGHT2 = 14;
|
|
9943
|
-
var PAD_TOP2 = 12;
|
|
9944
|
-
var PAD_BOTTOM2 = 22;
|
|
9945
|
-
var AXIS_LABEL_COLOR2 = "#8b949e";
|
|
9946
|
-
var GRIDLINE_COLOR2 = "#2a3441";
|
|
9947
|
-
function compute_geometry2(series, width, height) {
|
|
9948
|
-
const all_vals = [];
|
|
9949
|
-
let n = 0;
|
|
9950
|
-
for (const s of series) {
|
|
9951
|
-
n = Math.max(n, s.data.length);
|
|
9952
|
-
for (const v of s.data) if (v !== null && !Number.isNaN(v)) all_vals.push(v);
|
|
9953
|
-
}
|
|
9954
|
-
if (all_vals.length === 0 || n === 0) return null;
|
|
9955
|
-
const mn = Math.min(...all_vals);
|
|
9956
|
-
const mx = Math.max(...all_vals);
|
|
9957
|
-
const rng = mx - mn || mx * 0.1 + 1;
|
|
9958
|
-
const y_min = Math.max(0, mn - rng * 0.05);
|
|
9959
|
-
const y_max = mx + rng * 0.05;
|
|
9960
|
-
const y_rng = y_max - y_min || 1;
|
|
9961
|
-
const plot_w = width - PAD_LEFT2 - PAD_RIGHT2;
|
|
9962
|
-
const plot_h = height - PAD_TOP2 - PAD_BOTTOM2;
|
|
9963
|
-
return {
|
|
9964
|
-
vbox_w: width,
|
|
9965
|
-
vbox_h: height,
|
|
9966
|
-
y_min,
|
|
9967
|
-
y_max,
|
|
9968
|
-
point_count: n,
|
|
9969
|
-
cx: (i) => n <= 1 ? PAD_LEFT2 + plot_w / 2 : PAD_LEFT2 + i * plot_w / (n - 1),
|
|
9970
|
-
cy: (v) => PAD_TOP2 + (1 - (v - y_min) / y_rng) * plot_h
|
|
9971
|
-
};
|
|
9972
|
-
}
|
|
9973
|
-
function MultiLineChart({
|
|
9974
|
-
series,
|
|
9975
|
-
dates,
|
|
9976
|
-
width = 360,
|
|
9977
|
-
height = 140,
|
|
9978
|
-
showTooltip = true,
|
|
9979
|
-
showLegend = true,
|
|
9980
|
-
className
|
|
9981
|
-
}) {
|
|
9982
|
-
const geo = compute_geometry2(series, width, height);
|
|
9983
|
-
const [hover_idx, set_hover_idx] = React26.useState(null);
|
|
9984
|
-
const handle_mouse_move = React26.useCallback(
|
|
9985
|
-
(e) => {
|
|
9986
|
-
if (!geo) return;
|
|
9987
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
9988
|
-
if (rect.width === 0) return;
|
|
9989
|
-
const vbox_x = (e.clientX - rect.left) / rect.width * geo.vbox_w;
|
|
9990
|
-
const plot_w = geo.vbox_w - PAD_LEFT2 - PAD_RIGHT2;
|
|
9991
|
-
if (vbox_x < PAD_LEFT2 || vbox_x > geo.vbox_w - PAD_RIGHT2) {
|
|
9992
|
-
set_hover_idx(null);
|
|
9993
|
-
return;
|
|
9994
|
-
}
|
|
9995
|
-
const ratio = (vbox_x - PAD_LEFT2) / plot_w;
|
|
9996
|
-
const idx = Math.round(ratio * (geo.point_count - 1));
|
|
9997
|
-
set_hover_idx(Math.max(0, Math.min(geo.point_count - 1, idx)));
|
|
9998
|
-
},
|
|
9999
|
-
[geo]
|
|
10000
|
-
);
|
|
10001
|
-
const handle_mouse_leave = React26.useCallback(() => set_hover_idx(null), []);
|
|
10002
|
-
if (!geo) {
|
|
10003
|
-
return /* @__PURE__ */ jsx(
|
|
10004
|
-
"svg",
|
|
10005
|
-
{
|
|
10006
|
-
viewBox: `0 0 ${width} ${height}`,
|
|
10007
|
-
className: cn("cls_hazo_chart cls_hazo_chart_empty", className),
|
|
10008
|
-
style: { width: "100%", height: "auto", display: "block", maxHeight: `${height + 10}px` }
|
|
10009
|
-
}
|
|
10010
|
-
);
|
|
10011
|
-
}
|
|
10012
|
-
const x_label_idx = pick_x_label_indices(geo.point_count);
|
|
10013
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("cls_hazo_chart_wrapper", className), children: [
|
|
10014
|
-
/* @__PURE__ */ jsxs(
|
|
10015
|
-
"svg",
|
|
10016
|
-
{
|
|
10017
|
-
viewBox: `0 0 ${width} ${height}`,
|
|
10018
|
-
onMouseMove: showTooltip ? handle_mouse_move : void 0,
|
|
10019
|
-
onMouseLeave: showTooltip ? handle_mouse_leave : void 0,
|
|
10020
|
-
className: "cls_hazo_chart cls_hazo_chart_multi",
|
|
10021
|
-
style: {
|
|
10022
|
-
width: "100%",
|
|
10023
|
-
height: "auto",
|
|
10024
|
-
display: "block",
|
|
10025
|
-
maxHeight: `${height + 10}px`,
|
|
10026
|
-
cursor: showTooltip ? "crosshair" : "default"
|
|
10027
|
-
},
|
|
10028
|
-
children: [
|
|
10029
|
-
[0, 1, 2].map((i) => {
|
|
10030
|
-
const y = PAD_TOP2 + i / 2 * (geo.vbox_h - PAD_TOP2 - PAD_BOTTOM2);
|
|
10031
|
-
return /* @__PURE__ */ jsx(
|
|
10032
|
-
"line",
|
|
10033
|
-
{
|
|
10034
|
-
x1: PAD_LEFT2,
|
|
10035
|
-
x2: geo.vbox_w - PAD_RIGHT2,
|
|
10036
|
-
y1: y,
|
|
10037
|
-
y2: y,
|
|
10038
|
-
stroke: GRIDLINE_COLOR2,
|
|
10039
|
-
strokeWidth: 0.5,
|
|
10040
|
-
strokeDasharray: "2,3"
|
|
10041
|
-
},
|
|
10042
|
-
i
|
|
10043
|
-
);
|
|
10044
|
-
}),
|
|
10045
|
-
/* @__PURE__ */ jsx("text", { x: PAD_LEFT2 - 4, y: PAD_TOP2 + 3, textAnchor: "end", fill: AXIS_LABEL_COLOR2, fontSize: 9, children: format_num(geo.y_max) }),
|
|
10046
|
-
/* @__PURE__ */ jsx(
|
|
10047
|
-
"text",
|
|
10048
|
-
{
|
|
10049
|
-
x: PAD_LEFT2 - 4,
|
|
10050
|
-
y: PAD_TOP2 + (geo.vbox_h - PAD_TOP2 - PAD_BOTTOM2) / 2 + 3,
|
|
10051
|
-
textAnchor: "end",
|
|
10052
|
-
fill: AXIS_LABEL_COLOR2,
|
|
10053
|
-
fontSize: 9,
|
|
10054
|
-
children: format_num((geo.y_max + geo.y_min) / 2)
|
|
10055
|
-
}
|
|
10056
|
-
),
|
|
10057
|
-
/* @__PURE__ */ jsx("text", { x: PAD_LEFT2 - 4, y: geo.vbox_h - PAD_BOTTOM2 + 3, textAnchor: "end", fill: AXIS_LABEL_COLOR2, fontSize: 9, children: format_num(geo.y_min) }),
|
|
10058
|
-
x_label_idx.map((idx, k) => {
|
|
10059
|
-
const anchor = k === 0 ? "start" : k === 1 ? "middle" : "end";
|
|
10060
|
-
return /* @__PURE__ */ jsx(
|
|
10061
|
-
"text",
|
|
10062
|
-
{
|
|
10063
|
-
x: geo.cx(idx),
|
|
10064
|
-
y: geo.vbox_h - 6,
|
|
10065
|
-
textAnchor: anchor,
|
|
10066
|
-
fill: AXIS_LABEL_COLOR2,
|
|
10067
|
-
fontSize: 9,
|
|
10068
|
-
children: dates[idx] ?? ""
|
|
10069
|
-
},
|
|
10070
|
-
`x_${k}`
|
|
10071
|
-
);
|
|
10072
|
-
}),
|
|
10073
|
-
series.map((s, s_idx) => {
|
|
10074
|
-
let d = "";
|
|
10075
|
-
s.data.forEach((v, i) => {
|
|
10076
|
-
if (v === null || Number.isNaN(v)) return;
|
|
10077
|
-
d += `${d ? " L" : "M"}${geo.cx(i).toFixed(1)},${geo.cy(v).toFixed(1)}`;
|
|
10078
|
-
});
|
|
10079
|
-
const last_idx = s.data.length - 1;
|
|
10080
|
-
const last_v = s.data[last_idx];
|
|
10081
|
-
const has_last = last_v !== null && last_v !== void 0 && !Number.isNaN(last_v);
|
|
10082
|
-
return /* @__PURE__ */ jsxs("g", { children: [
|
|
10083
|
-
d && /* @__PURE__ */ jsx("path", { d, stroke: s.color, strokeWidth: 1.7, fill: "none" }),
|
|
10084
|
-
has_last && hover_idx === null && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10085
|
-
/* @__PURE__ */ jsx(
|
|
10086
|
-
"circle",
|
|
10087
|
-
{
|
|
10088
|
-
cx: geo.cx(last_idx),
|
|
10089
|
-
cy: geo.cy(last_v),
|
|
10090
|
-
r: 3,
|
|
10091
|
-
fill: s.color,
|
|
10092
|
-
fillOpacity: 0.3,
|
|
10093
|
-
stroke: s.color,
|
|
10094
|
-
strokeWidth: 1.5
|
|
10095
|
-
}
|
|
10096
|
-
),
|
|
10097
|
-
/* @__PURE__ */ jsx(
|
|
10098
|
-
"text",
|
|
10099
|
-
{
|
|
10100
|
-
x: geo.cx(last_idx) - 5,
|
|
10101
|
-
y: geo.cy(last_v) - 5,
|
|
10102
|
-
textAnchor: "end",
|
|
10103
|
-
fill: s.color,
|
|
10104
|
-
fontSize: 9,
|
|
10105
|
-
fontWeight: 700,
|
|
10106
|
-
children: format_num(last_v)
|
|
10107
|
-
}
|
|
10108
|
-
)
|
|
10109
|
-
] })
|
|
10110
|
-
] }, `series_${s_idx}`);
|
|
10111
|
-
}),
|
|
10112
|
-
showTooltip && hover_idx !== null && (() => {
|
|
10113
|
-
const x = geo.cx(hover_idx);
|
|
10114
|
-
const items = series.map((s) => ({
|
|
10115
|
-
label: s.label,
|
|
10116
|
-
color: s.color,
|
|
10117
|
-
value: s.data[hover_idx] ?? null
|
|
10118
|
-
})).filter((it) => it.value !== null && !Number.isNaN(it.value));
|
|
10119
|
-
if (items.length === 0) return null;
|
|
10120
|
-
const bubble_w = 70;
|
|
10121
|
-
const row_h = 12;
|
|
10122
|
-
const bubble_h = items.length * row_h + 18;
|
|
10123
|
-
const flip = x + bubble_w + 6 > geo.vbox_w - PAD_RIGHT2;
|
|
10124
|
-
const bubble_x = flip ? x - bubble_w - 6 : x + 6;
|
|
10125
|
-
const bubble_y = Math.max(PAD_TOP2, Math.min(PAD_TOP2 + 5, geo.vbox_h - PAD_BOTTOM2 - bubble_h));
|
|
10126
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10127
|
-
/* @__PURE__ */ jsx(
|
|
10128
|
-
"line",
|
|
10129
|
-
{
|
|
10130
|
-
x1: x,
|
|
10131
|
-
x2: x,
|
|
10132
|
-
y1: PAD_TOP2,
|
|
10133
|
-
y2: geo.vbox_h - PAD_BOTTOM2,
|
|
10134
|
-
stroke: AXIS_LABEL_COLOR2,
|
|
10135
|
-
strokeWidth: 0.5,
|
|
10136
|
-
strokeDasharray: "2,2",
|
|
10137
|
-
opacity: 0.6
|
|
10138
|
-
}
|
|
10139
|
-
),
|
|
10140
|
-
items.map((it) => /* @__PURE__ */ jsx(
|
|
10141
|
-
"circle",
|
|
10142
|
-
{
|
|
10143
|
-
cx: x,
|
|
10144
|
-
cy: geo.cy(it.value),
|
|
10145
|
-
r: 3,
|
|
10146
|
-
fill: it.color
|
|
10147
|
-
},
|
|
10148
|
-
`hd_${it.label}`
|
|
10149
|
-
)),
|
|
10150
|
-
/* @__PURE__ */ jsx(
|
|
10151
|
-
"rect",
|
|
10152
|
-
{
|
|
10153
|
-
x: bubble_x,
|
|
10154
|
-
y: bubble_y,
|
|
10155
|
-
width: bubble_w,
|
|
10156
|
-
height: bubble_h,
|
|
10157
|
-
rx: 3,
|
|
10158
|
-
fill: "#0d1117",
|
|
10159
|
-
stroke: AXIS_LABEL_COLOR2,
|
|
10160
|
-
strokeWidth: 0.5,
|
|
10161
|
-
fillOpacity: 0.92
|
|
10162
|
-
}
|
|
10163
|
-
),
|
|
10164
|
-
/* @__PURE__ */ jsx("text", { x: bubble_x + 6, y: bubble_y + 10, fill: AXIS_LABEL_COLOR2, fontSize: 8, children: dates[hover_idx] ?? "" }),
|
|
10165
|
-
items.map((it, i) => /* @__PURE__ */ jsxs("g", { children: [
|
|
10166
|
-
/* @__PURE__ */ jsx(
|
|
10167
|
-
"rect",
|
|
10168
|
-
{
|
|
10169
|
-
x: bubble_x + 6,
|
|
10170
|
-
y: bubble_y + 14 + i * row_h,
|
|
10171
|
-
width: 6,
|
|
10172
|
-
height: 6,
|
|
10173
|
-
fill: it.color
|
|
10174
|
-
}
|
|
10175
|
-
),
|
|
10176
|
-
/* @__PURE__ */ jsx(
|
|
10177
|
-
"text",
|
|
10178
|
-
{
|
|
10179
|
-
x: bubble_x + 16,
|
|
10180
|
-
y: bubble_y + 20 + i * row_h,
|
|
10181
|
-
fill: it.color,
|
|
10182
|
-
fontSize: 9,
|
|
10183
|
-
fontWeight: 600,
|
|
10184
|
-
children: format_num(it.value)
|
|
10185
|
-
}
|
|
10186
|
-
)
|
|
10187
|
-
] }, `row_${i}`))
|
|
10188
|
-
] });
|
|
10189
|
-
})()
|
|
10190
|
-
]
|
|
10191
|
-
}
|
|
10192
|
-
),
|
|
10193
|
-
showLegend && /* @__PURE__ */ jsx(
|
|
10194
|
-
"div",
|
|
10195
|
-
{
|
|
10196
|
-
className: "cls_hazo_chart_legend",
|
|
10197
|
-
style: {
|
|
10198
|
-
display: "flex",
|
|
10199
|
-
gap: "12px",
|
|
10200
|
-
justifyContent: "center",
|
|
10201
|
-
marginTop: "4px",
|
|
10202
|
-
fontSize: "10px",
|
|
10203
|
-
color: AXIS_LABEL_COLOR2,
|
|
10204
|
-
flexWrap: "wrap"
|
|
10205
|
-
},
|
|
10206
|
-
children: series.map((s) => /* @__PURE__ */ jsxs(
|
|
10207
|
-
"span",
|
|
10208
|
-
{
|
|
10209
|
-
style: { display: "inline-flex", alignItems: "center", gap: "4px" },
|
|
10210
|
-
children: [
|
|
10211
|
-
/* @__PURE__ */ jsx(
|
|
10212
|
-
"i",
|
|
10213
|
-
{
|
|
10214
|
-
style: {
|
|
10215
|
-
display: "inline-block",
|
|
10216
|
-
width: "8px",
|
|
10217
|
-
height: "8px",
|
|
10218
|
-
background: s.color,
|
|
10219
|
-
borderRadius: "1px"
|
|
10220
|
-
}
|
|
10221
|
-
}
|
|
10222
|
-
),
|
|
10223
|
-
s.label
|
|
10224
|
-
]
|
|
10225
|
-
},
|
|
10226
|
-
s.label
|
|
10227
|
-
))
|
|
10228
|
-
}
|
|
10229
|
-
)
|
|
10230
|
-
] });
|
|
10231
|
-
}
|
|
10232
|
-
var PAD_LEFT3 = 32;
|
|
10233
|
-
var PAD_RIGHT3 = 8;
|
|
10234
|
-
var PAD_TOP3 = 10;
|
|
10235
|
-
var PAD_BOTTOM3 = 22;
|
|
10236
9721
|
var BAR_GAP_RATIO = 0.25;
|
|
10237
|
-
var
|
|
9722
|
+
var AXIS_LABEL_COLOR = "#8b949e";
|
|
10238
9723
|
function StackedBars({
|
|
10239
9724
|
bars,
|
|
10240
9725
|
width = 360,
|
|
@@ -10244,11 +9729,11 @@ function StackedBars({
|
|
|
10244
9729
|
}) {
|
|
10245
9730
|
const totals = bars.map((b) => b.segments.reduce((sum, s) => sum + s.value, 0));
|
|
10246
9731
|
const y_max = Math.max(0, ...totals) || 1;
|
|
10247
|
-
const plot_w = width -
|
|
10248
|
-
const plot_h = height -
|
|
9732
|
+
const plot_w = width - PAD_LEFT - PAD_RIGHT;
|
|
9733
|
+
const plot_h = height - PAD_TOP - PAD_BOTTOM;
|
|
10249
9734
|
const slot_w = bars.length > 0 ? plot_w / bars.length : 0;
|
|
10250
9735
|
const bar_w = slot_w * (1 - BAR_GAP_RATIO);
|
|
10251
|
-
const x_for = (i) =>
|
|
9736
|
+
const x_for = (i) => PAD_LEFT + i * slot_w + (slot_w - bar_w) / 2;
|
|
10252
9737
|
const x_label_idx = pick_x_label_indices(bars.length);
|
|
10253
9738
|
return /* @__PURE__ */ jsxs(
|
|
10254
9739
|
"svg",
|
|
@@ -10258,14 +9743,14 @@ function StackedBars({
|
|
|
10258
9743
|
style: { width: "100%", height: "auto", display: "block", maxHeight: `${height + 10}px` },
|
|
10259
9744
|
children: [
|
|
10260
9745
|
showYAxis && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
10261
|
-
/* @__PURE__ */ jsx("text", { x:
|
|
9746
|
+
/* @__PURE__ */ jsx("text", { x: PAD_LEFT - 4, y: PAD_TOP + 3, textAnchor: "end", fill: AXIS_LABEL_COLOR, fontSize: 9, children: format_num(y_max) }),
|
|
10262
9747
|
/* @__PURE__ */ jsx(
|
|
10263
9748
|
"text",
|
|
10264
9749
|
{
|
|
10265
|
-
x:
|
|
10266
|
-
y:
|
|
9750
|
+
x: PAD_LEFT - 4,
|
|
9751
|
+
y: PAD_TOP + plot_h / 2 + 3,
|
|
10267
9752
|
textAnchor: "end",
|
|
10268
|
-
fill:
|
|
9753
|
+
fill: AXIS_LABEL_COLOR,
|
|
10269
9754
|
fontSize: 9,
|
|
10270
9755
|
children: format_num(y_max / 2)
|
|
10271
9756
|
}
|
|
@@ -10273,17 +9758,17 @@ function StackedBars({
|
|
|
10273
9758
|
/* @__PURE__ */ jsx(
|
|
10274
9759
|
"text",
|
|
10275
9760
|
{
|
|
10276
|
-
x:
|
|
10277
|
-
y: height -
|
|
9761
|
+
x: PAD_LEFT - 4,
|
|
9762
|
+
y: height - PAD_BOTTOM + 3,
|
|
10278
9763
|
textAnchor: "end",
|
|
10279
|
-
fill:
|
|
9764
|
+
fill: AXIS_LABEL_COLOR,
|
|
10280
9765
|
fontSize: 9,
|
|
10281
9766
|
children: "0"
|
|
10282
9767
|
}
|
|
10283
9768
|
)
|
|
10284
9769
|
] }),
|
|
10285
9770
|
bars.map((bar, i) => {
|
|
10286
|
-
let cursor_y = height -
|
|
9771
|
+
let cursor_y = height - PAD_BOTTOM;
|
|
10287
9772
|
return /* @__PURE__ */ jsx("g", { children: bar.segments.map((seg, s_idx) => {
|
|
10288
9773
|
if (seg.value <= 0) return null;
|
|
10289
9774
|
const seg_h = seg.value / y_max * plot_h;
|
|
@@ -10311,7 +9796,7 @@ function StackedBars({
|
|
|
10311
9796
|
x: x_pos,
|
|
10312
9797
|
y: height - 6,
|
|
10313
9798
|
textAnchor: anchor,
|
|
10314
|
-
fill:
|
|
9799
|
+
fill: AXIS_LABEL_COLOR,
|
|
10315
9800
|
fontSize: 9,
|
|
10316
9801
|
children: bars[idx]?.label ?? ""
|
|
10317
9802
|
},
|
|
@@ -10360,6 +9845,219 @@ function DateRangeSelector({
|
|
|
10360
9845
|
}
|
|
10361
9846
|
);
|
|
10362
9847
|
}
|
|
9848
|
+
var PAD_LEFT2 = 80;
|
|
9849
|
+
var PAD_RIGHT2 = 72;
|
|
9850
|
+
var PAD_TOP2 = 12;
|
|
9851
|
+
var PAD_BOTTOM2 = 12;
|
|
9852
|
+
var ROW_H = 44;
|
|
9853
|
+
var LABEL_H = 14;
|
|
9854
|
+
var BAR_H = 22;
|
|
9855
|
+
var AXIS_LABEL_COLOR2 = "#8b949e";
|
|
9856
|
+
var GRIDLINE_COLOR = "#2a3441";
|
|
9857
|
+
function step_total(step) {
|
|
9858
|
+
if (step.value !== void 0) return step.value;
|
|
9859
|
+
if (step.segments) return step.segments.reduce((s, g) => s + g.value, 0);
|
|
9860
|
+
return 0;
|
|
9861
|
+
}
|
|
9862
|
+
function FunnelChart({
|
|
9863
|
+
steps,
|
|
9864
|
+
width = 360,
|
|
9865
|
+
height,
|
|
9866
|
+
color: color2 = "#3b82f6",
|
|
9867
|
+
valueFormat,
|
|
9868
|
+
showDropoff = true,
|
|
9869
|
+
showTooltip = true,
|
|
9870
|
+
className
|
|
9871
|
+
}) {
|
|
9872
|
+
const [hover_idx, set_hover_idx] = React26.useState(null);
|
|
9873
|
+
const fmt = valueFormat ?? format_num;
|
|
9874
|
+
const totals = steps.map(step_total);
|
|
9875
|
+
const value_max = Math.max(1, ...totals);
|
|
9876
|
+
const plot_w = width - PAD_LEFT2 - PAD_RIGHT2;
|
|
9877
|
+
const vbox_h = height ?? PAD_TOP2 + steps.length * ROW_H + PAD_BOTTOM2;
|
|
9878
|
+
const handle_mouse_move = React26.useCallback(
|
|
9879
|
+
(e) => {
|
|
9880
|
+
if (steps.length === 0) return;
|
|
9881
|
+
const rect = e.currentTarget.getBoundingClientRect();
|
|
9882
|
+
if (rect.height === 0) return;
|
|
9883
|
+
const vbox_y = (e.clientY - rect.top) / rect.height * vbox_h;
|
|
9884
|
+
const row_idx = Math.floor((vbox_y - PAD_TOP2) / ROW_H);
|
|
9885
|
+
if (row_idx < 0 || row_idx >= steps.length) {
|
|
9886
|
+
set_hover_idx(null);
|
|
9887
|
+
return;
|
|
9888
|
+
}
|
|
9889
|
+
set_hover_idx(row_idx);
|
|
9890
|
+
},
|
|
9891
|
+
[steps.length, vbox_h]
|
|
9892
|
+
);
|
|
9893
|
+
const handle_mouse_leave = React26.useCallback(() => set_hover_idx(null), []);
|
|
9894
|
+
return /* @__PURE__ */ jsxs(
|
|
9895
|
+
"svg",
|
|
9896
|
+
{
|
|
9897
|
+
viewBox: `0 0 ${width} ${vbox_h}`,
|
|
9898
|
+
onMouseMove: showTooltip ? handle_mouse_move : void 0,
|
|
9899
|
+
onMouseLeave: showTooltip ? handle_mouse_leave : void 0,
|
|
9900
|
+
className: cn("cls_hazo_chart cls_hazo_chart_funnel", className),
|
|
9901
|
+
style: {
|
|
9902
|
+
width: "100%",
|
|
9903
|
+
height: "auto",
|
|
9904
|
+
display: "block",
|
|
9905
|
+
cursor: showTooltip ? "crosshair" : "default"
|
|
9906
|
+
},
|
|
9907
|
+
children: [
|
|
9908
|
+
steps.length > 0 && /* @__PURE__ */ jsx(
|
|
9909
|
+
"line",
|
|
9910
|
+
{
|
|
9911
|
+
x1: PAD_LEFT2 + plot_w / 2,
|
|
9912
|
+
x2: PAD_LEFT2 + plot_w / 2,
|
|
9913
|
+
y1: PAD_TOP2,
|
|
9914
|
+
y2: PAD_TOP2 + steps.length * ROW_H,
|
|
9915
|
+
stroke: GRIDLINE_COLOR,
|
|
9916
|
+
strokeWidth: 0.5,
|
|
9917
|
+
strokeDasharray: "2,3"
|
|
9918
|
+
}
|
|
9919
|
+
),
|
|
9920
|
+
steps.map((step, i) => {
|
|
9921
|
+
const total = totals[i];
|
|
9922
|
+
const bar_w = total / value_max * plot_w;
|
|
9923
|
+
const bar_x = PAD_LEFT2 + (plot_w - bar_w) / 2;
|
|
9924
|
+
const bar_y = PAD_TOP2 + i * ROW_H + LABEL_H;
|
|
9925
|
+
const pct_first = i === 0 ? 100 : Math.round(total / (totals[0] || 1) * 100);
|
|
9926
|
+
const value_label = i === 0 ? `${fmt(total)} (100%)` : `${fmt(total)} (${pct_first}%)`;
|
|
9927
|
+
const dropoff = i > 0 ? totals[i - 1] - total : 0;
|
|
9928
|
+
const label_x = bar_x + bar_w + 6;
|
|
9929
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
9930
|
+
/* @__PURE__ */ jsx(
|
|
9931
|
+
"text",
|
|
9932
|
+
{
|
|
9933
|
+
x: PAD_LEFT2 - 6,
|
|
9934
|
+
y: bar_y + BAR_H / 2 + 4,
|
|
9935
|
+
textAnchor: "end",
|
|
9936
|
+
fill: AXIS_LABEL_COLOR2,
|
|
9937
|
+
fontSize: 9,
|
|
9938
|
+
children: step.label
|
|
9939
|
+
}
|
|
9940
|
+
),
|
|
9941
|
+
step.segments ? (() => {
|
|
9942
|
+
let cursor_x = bar_x;
|
|
9943
|
+
return step.segments.map((seg, s_idx) => {
|
|
9944
|
+
const seg_w = seg.value / value_max * plot_w;
|
|
9945
|
+
const x = cursor_x;
|
|
9946
|
+
cursor_x += seg_w;
|
|
9947
|
+
return /* @__PURE__ */ jsx(
|
|
9948
|
+
"rect",
|
|
9949
|
+
{
|
|
9950
|
+
x,
|
|
9951
|
+
y: bar_y,
|
|
9952
|
+
width: seg_w,
|
|
9953
|
+
height: BAR_H,
|
|
9954
|
+
fill: seg.color
|
|
9955
|
+
},
|
|
9956
|
+
`seg_${s_idx}`
|
|
9957
|
+
);
|
|
9958
|
+
});
|
|
9959
|
+
})() : /* @__PURE__ */ jsx("rect", { x: bar_x, y: bar_y, width: bar_w, height: BAR_H, fill: color2 }),
|
|
9960
|
+
/* @__PURE__ */ jsx(
|
|
9961
|
+
"text",
|
|
9962
|
+
{
|
|
9963
|
+
x: label_x,
|
|
9964
|
+
y: bar_y + BAR_H / 2,
|
|
9965
|
+
textAnchor: "start",
|
|
9966
|
+
fill: color2,
|
|
9967
|
+
fontSize: 9,
|
|
9968
|
+
dominantBaseline: "middle",
|
|
9969
|
+
children: value_label
|
|
9970
|
+
}
|
|
9971
|
+
),
|
|
9972
|
+
showDropoff && i > 0 && /* @__PURE__ */ jsx(
|
|
9973
|
+
"text",
|
|
9974
|
+
{
|
|
9975
|
+
x: label_x,
|
|
9976
|
+
y: bar_y + BAR_H / 2 + 10,
|
|
9977
|
+
textAnchor: "start",
|
|
9978
|
+
fill: AXIS_LABEL_COLOR2,
|
|
9979
|
+
fontSize: 8,
|
|
9980
|
+
children: `\u2212${fmt(dropoff)}`
|
|
9981
|
+
}
|
|
9982
|
+
)
|
|
9983
|
+
] }, `step_${i}`);
|
|
9984
|
+
}),
|
|
9985
|
+
showTooltip && hover_idx !== null && (() => {
|
|
9986
|
+
const i = hover_idx;
|
|
9987
|
+
const step = steps[i];
|
|
9988
|
+
const total = totals[i];
|
|
9989
|
+
const pct_first = i === 0 ? 100 : Math.round(total / (totals[0] || 1) * 100);
|
|
9990
|
+
const pct_prev = i === 0 ? 100 : Math.round(total / (totals[i - 1] || 1) * 100);
|
|
9991
|
+
const dropoff = i > 0 ? totals[i - 1] - total : 0;
|
|
9992
|
+
const bar_w = total / value_max * plot_w;
|
|
9993
|
+
const bar_x = PAD_LEFT2 + (plot_w - bar_w) / 2;
|
|
9994
|
+
const bar_y = PAD_TOP2 + i * ROW_H + LABEL_H;
|
|
9995
|
+
const bubble_anchor_y = bar_y + BAR_H / 2;
|
|
9996
|
+
const lines = [
|
|
9997
|
+
{ text: step.label, accent: true },
|
|
9998
|
+
{ text: `Total: ${fmt(total)}`, accent: false },
|
|
9999
|
+
{ text: `% of first: ${pct_first}%`, accent: false }
|
|
10000
|
+
];
|
|
10001
|
+
if (i > 0) {
|
|
10002
|
+
lines.push({ text: `% of prev: ${pct_prev}%`, accent: false });
|
|
10003
|
+
lines.push({ text: `Drop-off: \u2212${fmt(dropoff)}`, accent: false });
|
|
10004
|
+
}
|
|
10005
|
+
if (step.segments) {
|
|
10006
|
+
step.segments.forEach((seg) => {
|
|
10007
|
+
lines.push({ text: `${seg.label}: ${fmt(seg.value)}`, accent: false });
|
|
10008
|
+
});
|
|
10009
|
+
}
|
|
10010
|
+
const line_h = 13;
|
|
10011
|
+
const pad_v = 8;
|
|
10012
|
+
const bubble_w = 120;
|
|
10013
|
+
const bubble_h = lines.length * line_h + pad_v * 2;
|
|
10014
|
+
const right_x = bar_x + bar_w + 6;
|
|
10015
|
+
const left_x = bar_x - bubble_w - 6;
|
|
10016
|
+
const fits_right = right_x + bubble_w <= width - 4;
|
|
10017
|
+
const fits_left = left_x >= 4;
|
|
10018
|
+
let bubble_x;
|
|
10019
|
+
let bubble_y;
|
|
10020
|
+
if (fits_right || fits_left) {
|
|
10021
|
+
bubble_x = fits_right ? right_x : left_x;
|
|
10022
|
+
bubble_y = Math.max(4, Math.min(bubble_anchor_y - bubble_h / 2, vbox_h - bubble_h - 4));
|
|
10023
|
+
} else {
|
|
10024
|
+
bubble_x = Math.min(Math.max(bar_x + bar_w / 2 - bubble_w / 2, 4), width - bubble_w - 4);
|
|
10025
|
+
const below_y = bar_y + BAR_H + 6;
|
|
10026
|
+
bubble_y = below_y + bubble_h <= vbox_h - 4 ? below_y : Math.max(4, bar_y - bubble_h - 6);
|
|
10027
|
+
}
|
|
10028
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
10029
|
+
/* @__PURE__ */ jsx(
|
|
10030
|
+
"rect",
|
|
10031
|
+
{
|
|
10032
|
+
x: bubble_x,
|
|
10033
|
+
y: bubble_y,
|
|
10034
|
+
width: bubble_w,
|
|
10035
|
+
height: bubble_h,
|
|
10036
|
+
rx: 3,
|
|
10037
|
+
fill: "#0d1117",
|
|
10038
|
+
stroke: color2,
|
|
10039
|
+
strokeWidth: 0.5,
|
|
10040
|
+
fillOpacity: 0.92
|
|
10041
|
+
}
|
|
10042
|
+
),
|
|
10043
|
+
lines.map((line, k) => /* @__PURE__ */ jsx(
|
|
10044
|
+
"text",
|
|
10045
|
+
{
|
|
10046
|
+
x: bubble_x + 7,
|
|
10047
|
+
y: bubble_y + pad_v + k * line_h + line_h * 0.75,
|
|
10048
|
+
fill: line.accent ? color2 : AXIS_LABEL_COLOR2,
|
|
10049
|
+
fontSize: line.accent ? 10 : 8,
|
|
10050
|
+
fontWeight: line.accent ? 700 : 400,
|
|
10051
|
+
children: line.text
|
|
10052
|
+
},
|
|
10053
|
+
k
|
|
10054
|
+
))
|
|
10055
|
+
] });
|
|
10056
|
+
})()
|
|
10057
|
+
]
|
|
10058
|
+
}
|
|
10059
|
+
);
|
|
10060
|
+
}
|
|
10363
10061
|
|
|
10364
10062
|
// src/assets/celebration-chime.mp3
|
|
10365
10063
|
var celebration_chime_default = "data:text/plain;charset=utf-8,";
|
|
@@ -10817,6 +10515,6 @@ function HazoUiEtaProgress({
|
|
|
10817
10515
|
);
|
|
10818
10516
|
}
|
|
10819
10517
|
|
|
10820
|
-
export { ANIMATION_PRESETS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CELEBRATION_GRADIENT, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CelebrationProvider, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CommandNodeExtension, CommandPill, CommandPopover, DateRangeSelector, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorBanner, ErrorPage, HazoContextProvider, HazoUiConfirmDialog, HazoUiDialog, DialogClose as HazoUiDialogClose, DialogContent as HazoUiDialogContent, DialogDescription as HazoUiDialogDescription, DialogFooter as HazoUiDialogFooter, DialogHeader as HazoUiDialogHeader, DialogOverlay as HazoUiDialogOverlay, DialogPortal as HazoUiDialogPortal, Dialog as HazoUiDialogRoot, DialogTitle as HazoUiDialogTitle, DialogTrigger as HazoUiDialogTrigger, HazoUiEtaProgress, HazoUiFlexInput, HazoUiFlexRadio, HazoUiKanban, HazoUiKanbanFilter, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiPillRadio, HazoUiProgressBar, HazoUiRte, HazoUiTable, HazoUiTextarea, HazoUiTextbox, HazoUiToaster, HoverCard, HoverCardContent, HoverCardTrigger, Input, InverseSparkline, Label3 as Label,
|
|
10518
|
+
export { ANIMATION_PRESETS, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, CELEBRATION_GRADIENT, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CelebrationProvider, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CommandNodeExtension, CommandPill, CommandPopover, DateRangeSelector, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, ErrorBanner, ErrorPage, FunnelChart, HazoContextProvider, HazoUiConfirmDialog, HazoUiDialog, DialogClose as HazoUiDialogClose, DialogContent as HazoUiDialogContent, DialogDescription as HazoUiDialogDescription, DialogFooter as HazoUiDialogFooter, DialogHeader as HazoUiDialogHeader, DialogOverlay as HazoUiDialogOverlay, DialogPortal as HazoUiDialogPortal, Dialog as HazoUiDialogRoot, DialogTitle as HazoUiDialogTitle, DialogTrigger as HazoUiDialogTrigger, HazoUiEtaProgress, HazoUiFlexInput, HazoUiFlexRadio, HazoUiKanban, HazoUiKanbanFilter, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, HazoUiPillRadio, HazoUiProgressBar, HazoUiRte, HazoUiTable, HazoUiTextarea, HazoUiTextbox, HazoUiToaster, HoverCard, HoverCardContent, HoverCardTrigger, Input, InputAffix, InverseSparkline, Label3 as Label, LoadingTimeout, MarkdownEditor, Popover, PopoverContent, PopoverTrigger, ProgressiveImage, RadioGroup, RadioGroupItem, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator3 as Separator, Command as ShadcnCommand, CommandEmpty as ShadcnCommandEmpty, CommandGroup as ShadcnCommandGroup, CommandInput as ShadcnCommandInput, CommandItem as ShadcnCommandItem, CommandList as ShadcnCommandList, Skeleton, SkeletonBar, SkeletonCircle, SkeletonGroup, SkeletonRect, Slider, Sparkline, Spinner, StackedBars, Switch, Table2 as Table, TableBody, TableCaption, TableCell2 as TableCell, TableFooter, TableHead, TableHeader2 as TableHeader, TableRow2 as TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, applyKanbanFilter, buttonGroupVariants, celebrate, cn, computeEta, create_command_suggestion_extension, easeToward, errorToast, format_num, generateUUID, get_hazo_ui_config, get_logger, median, parse_commands_from_text, pick_x_label_indices, reset_hazo_ui_config, resolve_animation_classes, set_hazo_ui_config, set_logger, successToast, text_to_tiptap_content, toggleVariants, useClickOutside, useCopyToClipboard, useDebounce, useErrorDisplay, useEtaProgress, useFullscreen, useIsMobile, useLoadingState, useLocalStorage, useMediaQuery, useSessionStorage, useViewport, useWakeLock, use_fullscreen, use_wake_lock };
|
|
10821
10519
|
//# sourceMappingURL=index.js.map
|
|
10822
10520
|
//# sourceMappingURL=index.js.map
|