@astralui/core 0.1.2 → 0.1.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/dist/index.js CHANGED
@@ -607,7 +607,313 @@ function GridBackground({ children, className, style, fixed }) {
607
607
  const s = fixed ? { position: "fixed", inset: 0, ...style } : style ?? {};
608
608
  return /* @__PURE__ */ jsx("div", { className: cls("astral-grid-bg", className), style: s, children });
609
609
  }
610
+ function chartColor(c) {
611
+ if (c.startsWith("var(") || c.startsWith("#") || c.startsWith("rgb") || c.startsWith("hsl")) return c;
612
+ return `var(--astral-color-${c.replace(".", "-")})`;
613
+ }
614
+ function Sparkline({ points, color }) {
615
+ if (!points || points.length < 2 || points.every((p) => p === 0)) return null;
616
+ const w = 100, h = 28;
617
+ const max = Math.max(...points), min = Math.min(...points);
618
+ const range = max - min || 1;
619
+ const step = w / (points.length - 1);
620
+ const d = points.map((p, i) => `${i === 0 ? "M" : "L"}${(i * step).toFixed(1)},${(h - (p - min) / range * h).toFixed(1)}`).join(" ");
621
+ return /* @__PURE__ */ jsx("svg", { className: "au-spark", viewBox: `0 0 ${w} ${h}`, preserveAspectRatio: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d, fill: "none", stroke: chartColor(color), strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" }) });
622
+ }
623
+ function Delta({ current, previous }) {
624
+ if (previous == null || previous === 0) return null;
625
+ const pct = Math.round((current - previous) / previous * 100);
626
+ if (pct === 0) return null;
627
+ const up = pct > 0;
628
+ return /* @__PURE__ */ jsxs("span", { className: `au-delta ${up ? "up" : "down"}`, children: [
629
+ up ? "\u25B2" : "\u25BC",
630
+ " ",
631
+ Math.abs(pct),
632
+ "%"
633
+ ] });
634
+ }
635
+ function Donut({ data, centerValue, centerLabel }) {
636
+ const [hovered, setHovered] = useState(null);
637
+ const total = data.reduce((s, d) => s + d.value, 0) || 1;
638
+ const c = 75, r = 58, sw = 18, circ = 2 * Math.PI * r;
639
+ let offset = 0;
640
+ return /* @__PURE__ */ jsxs("div", { className: "au-donut", children: [
641
+ /* @__PURE__ */ jsxs("div", { className: "au-donut-ring", children: [
642
+ /* @__PURE__ */ jsxs("svg", { width: 150, height: 150, viewBox: "0 0 150 150", children: [
643
+ /* @__PURE__ */ jsx("circle", { cx: c, cy: c, r, fill: "none", stroke: "var(--au-surface-2)", strokeWidth: sw }),
644
+ data.map((d, i) => {
645
+ const dash = d.value / total * circ;
646
+ const el = /* @__PURE__ */ jsx(
647
+ "circle",
648
+ {
649
+ cx: c,
650
+ cy: c,
651
+ r,
652
+ fill: "none",
653
+ stroke: chartColor(d.color),
654
+ strokeWidth: hovered === i ? sw + 4 : sw,
655
+ strokeDasharray: `${dash} ${circ - dash}`,
656
+ strokeDashoffset: -offset,
657
+ transform: `rotate(-90 ${c} ${c})`,
658
+ style: {
659
+ opacity: hovered == null || hovered === i ? 1 : 0.28,
660
+ transition: "opacity .15s, stroke-width .15s",
661
+ cursor: "pointer"
662
+ },
663
+ onMouseEnter: () => setHovered(i),
664
+ onMouseLeave: () => setHovered(null)
665
+ },
666
+ i
667
+ );
668
+ offset += dash;
669
+ return el;
670
+ })
671
+ ] }),
672
+ /* @__PURE__ */ jsxs("div", { className: "au-donut-ctr", children: [
673
+ /* @__PURE__ */ jsx("b", { children: centerValue }),
674
+ /* @__PURE__ */ jsx("span", { children: centerLabel })
675
+ ] })
676
+ ] }),
677
+ /* @__PURE__ */ jsx("div", { className: "au-donut-legend", children: data.map((d, i) => /* @__PURE__ */ jsxs(
678
+ "div",
679
+ {
680
+ className: `au-dl ${hovered === i ? "on" : hovered != null ? "off" : ""}`,
681
+ onMouseEnter: () => setHovered(i),
682
+ onMouseLeave: () => setHovered(null),
683
+ children: [
684
+ /* @__PURE__ */ jsx("span", { className: "dot", style: { background: chartColor(d.color) } }),
685
+ /* @__PURE__ */ jsx("b", { children: d.value.toLocaleString() }),
686
+ /* @__PURE__ */ jsx("span", { className: "dll", children: d.name })
687
+ ]
688
+ },
689
+ i
690
+ )) })
691
+ ] });
692
+ }
693
+ function FunnelBars({ data }) {
694
+ const [hov, setHov] = useState(null);
695
+ const max = Math.max(...data.map((d) => d.value), 1);
696
+ return /* @__PURE__ */ jsx("div", { className: "au-funnel", children: data.map((d, i) => /* @__PURE__ */ jsxs(
697
+ "div",
698
+ {
699
+ className: `au-fbar ${hov === i ? "on" : hov != null ? "off" : ""}`,
700
+ onMouseEnter: () => setHov(i),
701
+ onMouseLeave: () => setHov(null),
702
+ children: [
703
+ /* @__PURE__ */ jsx("span", { className: "au-fbar-label", children: d.stage }),
704
+ /* @__PURE__ */ jsx("div", { className: "au-fbar-track", children: /* @__PURE__ */ jsx("div", { className: "au-fbar-fill", style: { width: `${d.value / max * 100}%`, background: chartColor(d.color) } }) }),
705
+ /* @__PURE__ */ jsx("span", { className: "au-fbar-val", children: d.value.toLocaleString() })
706
+ ]
707
+ },
708
+ d.stage
709
+ )) });
710
+ }
711
+ function StackedBars({ rows, series }) {
712
+ const [hovSeries, setHovSeries] = useState(null);
713
+ const [hovSeg, setHovSeg] = useState(null);
714
+ const max = Math.max(...rows.map((r) => r.values.reduce((a, b) => a + b, 0)), 1);
715
+ const anyHover = hovSeries != null || hovSeg != null;
716
+ const active = (row, s) => hovSeries != null ? s === hovSeries : hovSeg != null ? hovSeg.row === row && hovSeg.s === s : true;
717
+ return /* @__PURE__ */ jsxs("div", { className: "au-usage", children: [
718
+ /* @__PURE__ */ jsx("div", { className: "au-usage-legend", children: series.map((s, si) => /* @__PURE__ */ jsxs(
719
+ "div",
720
+ {
721
+ className: `au-ulg ${hovSeries === si ? "on" : hovSeries != null ? "off" : ""}`,
722
+ onMouseEnter: () => setHovSeries(si),
723
+ onMouseLeave: () => setHovSeries(null),
724
+ children: [
725
+ /* @__PURE__ */ jsx("span", { className: "dot", style: { background: chartColor(s.color) } }),
726
+ s.label
727
+ ]
728
+ },
729
+ si
730
+ )) }),
731
+ /* @__PURE__ */ jsx("div", { className: "au-usage-rows", children: rows.map((r, i) => /* @__PURE__ */ jsxs("div", { className: `au-urow ${hovSeg?.row === i ? "on" : ""}`, children: [
732
+ /* @__PURE__ */ jsx("span", { className: "au-urow-label", title: r.label, children: r.label }),
733
+ /* @__PURE__ */ jsx("div", { className: "au-utrack", children: r.values.map((v, si) => /* @__PURE__ */ jsx(
734
+ "div",
735
+ {
736
+ className: "au-useg",
737
+ onMouseEnter: () => setHovSeg({ row: i, s: si }),
738
+ onMouseLeave: () => setHovSeg(null),
739
+ style: {
740
+ width: `${v / max * 100}%`,
741
+ background: chartColor(series[si].color),
742
+ opacity: anyHover && !active(i, si) ? 0.2 : 1,
743
+ filter: anyHover && active(i, si) ? "brightness(1.2)" : void 0
744
+ }
745
+ },
746
+ si
747
+ )) }),
748
+ /* @__PURE__ */ jsx("span", { className: "au-unums", children: r.values.map((v, si) => /* @__PURE__ */ jsx(
749
+ "b",
750
+ {
751
+ style: {
752
+ color: chartColor(series[si].color),
753
+ opacity: anyHover && !active(i, si) ? 0.28 : 1,
754
+ textShadow: anyHover && active(i, si) ? `0 0 10px ${chartColor(series[si].color)}` : void 0
755
+ },
756
+ children: v.toLocaleString()
757
+ },
758
+ si
759
+ )) })
760
+ ] }, i)) })
761
+ ] });
762
+ }
763
+ function AuthShell({ children, backdrop = "space", topLeft, topRight, className, style }) {
764
+ const cls2 = `au-auth${backdrop === "space" ? " astral-space-bg" : ""}${className ? " " + className : ""}`;
765
+ return /* @__PURE__ */ jsxs("div", { className: cls2, style, children: [
766
+ backdrop === "space" ? /* @__PURE__ */ jsx("div", { className: "astral-stars", "aria-hidden": "true" }) : /* @__PURE__ */ jsx("div", { className: "au-auth-bg", "aria-hidden": "true" }),
767
+ topLeft,
768
+ topRight ? /* @__PURE__ */ jsx("div", { className: "au-auth-lang", children: topRight }) : null,
769
+ children
770
+ ] });
771
+ }
772
+ function AuthCard({ children, banner, className, style }) {
773
+ return /* @__PURE__ */ jsxs("div", { className: `au-auth-card${className ? " " + className : ""}`, style, children: [
774
+ banner ? /* @__PURE__ */ jsx("div", { className: "au-auth-banner", children: banner }) : null,
775
+ children
776
+ ] });
777
+ }
778
+ function ConfirmModal({
779
+ opened,
780
+ onClose,
781
+ onConfirm,
782
+ title,
783
+ message,
784
+ confirmLabel = "Confirm",
785
+ cancelLabel = "Cancel",
786
+ danger,
787
+ loading,
788
+ width = 420,
789
+ children
790
+ }) {
791
+ return /* @__PURE__ */ jsx(AstralModal, { opened, onClose, title, width, children: /* @__PURE__ */ jsxs("div", { className: "clay-form", children: [
792
+ message != null && /* @__PURE__ */ jsx("div", { style: { fontSize: 13, lineHeight: 1.55, color: "var(--au-dim)" }, children: message }),
793
+ children,
794
+ /* @__PURE__ */ jsxs("div", { className: "clay-actions", children: [
795
+ /* @__PURE__ */ jsx("button", { type: "button", className: "au-btn", onClick: onClose, disabled: loading, children: cancelLabel }),
796
+ /* @__PURE__ */ jsxs(
797
+ "button",
798
+ {
799
+ type: "button",
800
+ className: `au-btn ${danger ? "solidred" : "primary"}`,
801
+ onClick: onConfirm,
802
+ disabled: loading,
803
+ children: [
804
+ loading ? /* @__PURE__ */ jsx("span", { className: "au-spinner", style: { width: 14, height: 14 } }) : null,
805
+ confirmLabel
806
+ ]
807
+ }
808
+ )
809
+ ] })
810
+ ] }) });
811
+ }
812
+ function Avatar({ url, name, size = 36, radius = "50%", className = "", overlay = false, color }) {
813
+ const [broken, setBroken] = useState(false);
814
+ useEffect(() => {
815
+ setBroken(false);
816
+ }, [url]);
817
+ if (overlay) {
818
+ if (!url || broken) return null;
819
+ return /* @__PURE__ */ jsx(
820
+ "img",
821
+ {
822
+ src: url,
823
+ alt: name || "",
824
+ className,
825
+ referrerPolicy: "no-referrer",
826
+ onError: () => setBroken(true),
827
+ style: { position: "absolute", inset: 0, width: "100%", height: "100%", borderRadius: radius, objectFit: "cover" }
828
+ }
829
+ );
830
+ }
831
+ if (url && !broken) {
832
+ return /* @__PURE__ */ jsx(
833
+ "img",
834
+ {
835
+ src: url,
836
+ alt: name || "",
837
+ className,
838
+ width: size,
839
+ height: size,
840
+ referrerPolicy: "no-referrer",
841
+ loading: "lazy",
842
+ onError: () => setBroken(true),
843
+ style: { width: size, height: size, borderRadius: radius, objectFit: "cover", display: "block", flex: "0 0 auto" }
844
+ }
845
+ );
846
+ }
847
+ const initials = (name || "").trim().slice(0, 2).toUpperCase() || "-";
848
+ return /* @__PURE__ */ jsx(
849
+ "span",
850
+ {
851
+ className,
852
+ "aria-hidden": true,
853
+ style: {
854
+ width: size,
855
+ height: size,
856
+ borderRadius: radius,
857
+ flex: "0 0 auto",
858
+ display: "inline-grid",
859
+ placeItems: "center",
860
+ color: "#fff",
861
+ fontWeight: 700,
862
+ fontSize: Math.max(9, Math.round(size * 0.4)),
863
+ lineHeight: 1,
864
+ background: color ?? "linear-gradient(135deg, var(--astral-color-violet-6), var(--astral-color-violet-8))"
865
+ },
866
+ children: initials
867
+ }
868
+ );
869
+ }
870
+ var COLOR_MAP = {
871
+ offline: "#3b82f6",
872
+ online: "#16a34a",
873
+ active: "#16a34a",
874
+ suspended: "#eab308",
875
+ banned: "#ef4444",
876
+ creating: "#06b6d4",
877
+ verification_needed: "#EF8E2E",
878
+ signup_failed: "#ef4444",
879
+ untested: "#9ca3af",
880
+ failed: "#ef4444",
881
+ idle: "#9ca3af",
882
+ starting: "#06b6d4",
883
+ running: "#16a34a",
884
+ stopping: "#eab308",
885
+ stopped: "#EF8E2E",
886
+ error: "#ef4444",
887
+ draft: "#9ca3af",
888
+ scheduled: "#3b82f6",
889
+ paused: "#eab308",
890
+ completed: "#16a34a",
891
+ skipped: "#EF8E2E",
892
+ in_campaign: "#8b5cf6",
893
+ in_progress: "#3b82f6",
894
+ pending: "#9ca3af",
895
+ replied: "#8b5cf6",
896
+ success: "#16a34a"
897
+ };
898
+ var FILLED = /* @__PURE__ */ new Set(["running", "active", "online"]);
899
+ function StatusBadge({ status, label, color, filled }) {
900
+ const c = color ?? COLOR_MAP[status] ?? "#9ca3af";
901
+ const isFilled = filled ?? FILLED.has(status);
902
+ const text = label ?? status;
903
+ return /* @__PURE__ */ jsxs(
904
+ "span",
905
+ {
906
+ className: `au-sbadge${isFilled ? " filled" : ""}`,
907
+ style: { "--au-sb": c },
908
+ title: typeof text === "string" ? text : void 0,
909
+ children: [
910
+ /* @__PURE__ */ jsx("span", { className: "au-sbadge-dot" }),
911
+ text
912
+ ]
913
+ }
914
+ );
915
+ }
610
916
 
611
- export { AstralDrawer, AstralMenu, AstralModal, AstralPinInput, AstralSelect, AstralThemeProvider, AstralToaster, ColorSchemeProvider, DateInput, GridBackground, SpaceBackground, Spinner2 as Spinner, buildOrgCss, dateTimeToInputStr, dateToInputStr, generateColors, notifications, useColorScheme, useThemePreview };
917
+ export { AstralDrawer, AstralMenu, AstralModal, AstralPinInput, AstralSelect, AstralThemeProvider, AstralToaster, AuthCard, AuthShell, Avatar, ColorSchemeProvider, ConfirmModal, DateInput, Delta, Donut, FunnelBars, GridBackground, SpaceBackground, Sparkline, Spinner2 as Spinner, StackedBars, StatusBadge, buildOrgCss, chartColor, dateTimeToInputStr, dateToInputStr, generateColors, notifications, useColorScheme, useThemePreview };
612
918
  //# sourceMappingURL=index.js.map
613
919
  //# sourceMappingURL=index.js.map