@unicitylabs/sphere-ui 0.1.7 → 0.1.9
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 +87 -46
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -396,13 +396,19 @@ function ConfirmDialog({
|
|
|
396
396
|
// src/components/StatusBadge.tsx
|
|
397
397
|
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
398
398
|
var STATUS_COLORS = {
|
|
399
|
+
// Quest/Achievement statuses (uppercase)
|
|
399
400
|
ACTIVE: "badge-green",
|
|
400
401
|
DRAFT: "badge-gray",
|
|
401
402
|
PAUSED: "badge-yellow",
|
|
402
403
|
EXPIRED: "badge-red",
|
|
403
404
|
ENDED: "badge-red",
|
|
404
405
|
AWARDED: "badge-green",
|
|
405
|
-
REJECTED: "badge-red"
|
|
406
|
+
REJECTED: "badge-red",
|
|
407
|
+
// Project statuses (lowercase)
|
|
408
|
+
draft: "badge-gray",
|
|
409
|
+
review: "badge-yellow",
|
|
410
|
+
published: "badge-green",
|
|
411
|
+
suspended: "badge-red"
|
|
406
412
|
};
|
|
407
413
|
function StatusBadge({ status, className = "" }) {
|
|
408
414
|
return /* @__PURE__ */ jsx8("span", { className: `badge ${STATUS_COLORS[status] ?? "badge-gray"} ${className}`, children: status });
|
|
@@ -474,7 +480,8 @@ function EmptyState({ title, description, action }) {
|
|
|
474
480
|
}
|
|
475
481
|
|
|
476
482
|
// src/components/CustomSelect.tsx
|
|
477
|
-
import { useState as useState2, useRef, useEffect as useEffect3 } from "react";
|
|
483
|
+
import { useState as useState2, useRef, useEffect as useEffect3, useCallback } from "react";
|
|
484
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
478
485
|
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
479
486
|
function CustomSelect({
|
|
480
487
|
options,
|
|
@@ -485,13 +492,23 @@ function CustomSelect({
|
|
|
485
492
|
size = "md"
|
|
486
493
|
}) {
|
|
487
494
|
const [open, setOpen] = useState2(false);
|
|
488
|
-
const
|
|
495
|
+
const btnRef = useRef(null);
|
|
496
|
+
const dropRef = useRef(null);
|
|
497
|
+
const [pos, setPos] = useState2({ top: 0, left: 0, width: 0 });
|
|
489
498
|
const selected = options.find((o) => o.value === value);
|
|
490
499
|
const label = selected?.label ?? placeholder ?? "Select...";
|
|
500
|
+
const updatePos = useCallback(() => {
|
|
501
|
+
if (!btnRef.current) return;
|
|
502
|
+
const rect = btnRef.current.getBoundingClientRect();
|
|
503
|
+
setPos({ top: rect.bottom + 4, left: rect.left, width: rect.width });
|
|
504
|
+
}, []);
|
|
491
505
|
useEffect3(() => {
|
|
492
506
|
if (!open) return;
|
|
493
507
|
const handler = (e) => {
|
|
494
|
-
|
|
508
|
+
const target = e.target;
|
|
509
|
+
if (btnRef.current?.contains(target)) return;
|
|
510
|
+
if (dropRef.current?.contains(target)) return;
|
|
511
|
+
setOpen(false);
|
|
495
512
|
};
|
|
496
513
|
document.addEventListener("mousedown", handler);
|
|
497
514
|
return () => document.removeEventListener("mousedown", handler);
|
|
@@ -504,13 +521,27 @@ function CustomSelect({
|
|
|
504
521
|
document.addEventListener("keydown", handler);
|
|
505
522
|
return () => document.removeEventListener("keydown", handler);
|
|
506
523
|
}, [open]);
|
|
524
|
+
useEffect3(() => {
|
|
525
|
+
if (!open) return;
|
|
526
|
+
updatePos();
|
|
527
|
+
window.addEventListener("scroll", updatePos, true);
|
|
528
|
+
window.addEventListener("resize", updatePos);
|
|
529
|
+
return () => {
|
|
530
|
+
window.removeEventListener("scroll", updatePos, true);
|
|
531
|
+
window.removeEventListener("resize", updatePos);
|
|
532
|
+
};
|
|
533
|
+
}, [open, updatePos]);
|
|
507
534
|
const textSize = size === "sm" ? "text-xs" : "text-sm";
|
|
508
|
-
return /* @__PURE__ */ jsxs10("div", {
|
|
535
|
+
return /* @__PURE__ */ jsxs10("div", { className, children: [
|
|
509
536
|
/* @__PURE__ */ jsxs10(
|
|
510
537
|
"button",
|
|
511
538
|
{
|
|
539
|
+
ref: btnRef,
|
|
512
540
|
type: "button",
|
|
513
|
-
onClick: () =>
|
|
541
|
+
onClick: () => {
|
|
542
|
+
updatePos();
|
|
543
|
+
setOpen((o) => !o);
|
|
544
|
+
},
|
|
514
545
|
className: `admin-input w-full flex items-center justify-between gap-2 ${textSize} text-left`,
|
|
515
546
|
style: { color: selected ? "var(--text-primary)" : "var(--text-muted)" },
|
|
516
547
|
children: [
|
|
@@ -537,40 +568,50 @@ function CustomSelect({
|
|
|
537
568
|
]
|
|
538
569
|
}
|
|
539
570
|
),
|
|
540
|
-
open &&
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
},
|
|
558
|
-
className: `block w-full text-left px-3 py-1.5 ${textSize} transition-colors`,
|
|
559
|
-
style: {
|
|
560
|
-
color: opt.value === value ? "var(--accent-text)" : "var(--text-primary)",
|
|
561
|
-
background: opt.value === value ? "var(--accent-glow)" : "transparent"
|
|
562
|
-
},
|
|
563
|
-
onMouseEnter: (e) => {
|
|
564
|
-
if (opt.value !== value) e.currentTarget.style.background = "var(--bg-hover)";
|
|
565
|
-
},
|
|
566
|
-
onMouseLeave: (e) => {
|
|
567
|
-
e.currentTarget.style.background = opt.value === value ? "var(--accent-glow)" : "transparent";
|
|
568
|
-
},
|
|
569
|
-
children: opt.label
|
|
571
|
+
open && createPortal3(
|
|
572
|
+
/* @__PURE__ */ jsx11(
|
|
573
|
+
"div",
|
|
574
|
+
{
|
|
575
|
+
ref: dropRef,
|
|
576
|
+
className: "py-1 max-h-48 overflow-y-auto",
|
|
577
|
+
style: {
|
|
578
|
+
position: "fixed",
|
|
579
|
+
top: pos.top,
|
|
580
|
+
left: pos.left,
|
|
581
|
+
width: pos.width,
|
|
582
|
+
minWidth: 120,
|
|
583
|
+
zIndex: 9999,
|
|
584
|
+
background: "var(--bg-elevated)",
|
|
585
|
+
border: "1px solid var(--border)",
|
|
586
|
+
borderRadius: "var(--radius-md)",
|
|
587
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
570
588
|
},
|
|
571
|
-
opt
|
|
572
|
-
|
|
573
|
-
|
|
589
|
+
children: options.map((opt) => /* @__PURE__ */ jsx11(
|
|
590
|
+
"button",
|
|
591
|
+
{
|
|
592
|
+
type: "button",
|
|
593
|
+
onClick: () => {
|
|
594
|
+
onChange(opt.value);
|
|
595
|
+
setOpen(false);
|
|
596
|
+
},
|
|
597
|
+
className: `block w-full text-left px-3 py-1.5 ${textSize} transition-colors`,
|
|
598
|
+
style: {
|
|
599
|
+
color: opt.value === value ? "var(--accent-text)" : "var(--text-primary)",
|
|
600
|
+
background: opt.value === value ? "var(--accent-glow)" : "transparent"
|
|
601
|
+
},
|
|
602
|
+
onMouseEnter: (e) => {
|
|
603
|
+
if (opt.value !== value) e.currentTarget.style.background = "var(--bg-hover)";
|
|
604
|
+
},
|
|
605
|
+
onMouseLeave: (e) => {
|
|
606
|
+
e.currentTarget.style.background = opt.value === value ? "var(--accent-glow)" : "transparent";
|
|
607
|
+
},
|
|
608
|
+
children: opt.label
|
|
609
|
+
},
|
|
610
|
+
opt.value
|
|
611
|
+
))
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
document.body
|
|
574
615
|
)
|
|
575
616
|
] });
|
|
576
617
|
}
|
|
@@ -703,7 +744,7 @@ function AlertBanner({ type, title, children }) {
|
|
|
703
744
|
}
|
|
704
745
|
|
|
705
746
|
// src/components/AddressDisplay.tsx
|
|
706
|
-
import { useState as useState4, useCallback } from "react";
|
|
747
|
+
import { useState as useState4, useCallback as useCallback2 } from "react";
|
|
707
748
|
import { Fragment as Fragment2, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
708
749
|
function truncateAddress(address) {
|
|
709
750
|
const prefix = "DIRECT://";
|
|
@@ -720,7 +761,7 @@ function truncateAddress(address) {
|
|
|
720
761
|
}
|
|
721
762
|
function AddressDisplay({ address, nametag, truncate = true }) {
|
|
722
763
|
const [copied, setCopied] = useState4(false);
|
|
723
|
-
const handleCopy =
|
|
764
|
+
const handleCopy = useCallback2(() => {
|
|
724
765
|
navigator.clipboard.writeText(address).then(() => {
|
|
725
766
|
setCopied(true);
|
|
726
767
|
setTimeout(() => setCopied(false), 1500);
|
|
@@ -774,7 +815,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
774
815
|
}
|
|
775
816
|
|
|
776
817
|
// src/components/JsonPanel.tsx
|
|
777
|
-
import { useState as useState5, useEffect as useEffect4, useRef as useRef2, useCallback as
|
|
818
|
+
import { useState as useState5, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback3 } from "react";
|
|
778
819
|
import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
779
820
|
function JsonPanel({
|
|
780
821
|
value,
|
|
@@ -796,7 +837,7 @@ function JsonPanel({
|
|
|
796
837
|
setText(JSON.stringify(clean, null, 2));
|
|
797
838
|
setParseError(null);
|
|
798
839
|
}, [value, isEditing, excludeKeys]);
|
|
799
|
-
const handleChange =
|
|
840
|
+
const handleChange = useCallback3((newText) => {
|
|
800
841
|
setText(newText);
|
|
801
842
|
try {
|
|
802
843
|
const parsed = JSON.parse(newText);
|
|
@@ -806,10 +847,10 @@ function JsonPanel({
|
|
|
806
847
|
setParseError(e instanceof Error ? e.message : "Invalid JSON");
|
|
807
848
|
}
|
|
808
849
|
}, [onChange]);
|
|
809
|
-
const handleFocus =
|
|
810
|
-
const handleBlur =
|
|
850
|
+
const handleFocus = useCallback3(() => setIsEditing(true), []);
|
|
851
|
+
const handleBlur = useCallback3(() => setIsEditing(false), []);
|
|
811
852
|
const [copied, setCopied] = useState5(false);
|
|
812
|
-
const handleCopy =
|
|
853
|
+
const handleCopy = useCallback3(async () => {
|
|
813
854
|
await navigator.clipboard.writeText(text);
|
|
814
855
|
setCopied(true);
|
|
815
856
|
setTimeout(() => setCopied(false), 1500);
|