@unicitylabs/sphere-ui 0.1.9 → 0.1.12
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/README.md +1 -1
- package/dist/index.d.ts +25 -2
- package/dist/index.js +156 -82
- package/package.json +22 -14
- package/src/styles/components.css +9 -0
- package/src/styles/tokens.css +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Shared UI library for the Sphere ecosystem. Provides a unified design system, co
|
|
|
7
7
|
| App | Description |
|
|
8
8
|
|-----|-------------|
|
|
9
9
|
| [sphere](https://github.com/unicity-sphere/sphere) | Wallet & marketplace |
|
|
10
|
-
| [sphere-dev](https://github.com/unicity-sphere/sphere-dev) | Developer Portal |
|
|
10
|
+
| [sphere-dev-portal](https://github.com/unicity-sphere/sphere-dev-portal) | Developer Portal |
|
|
11
11
|
| [sphere-backoffice](https://github.com/unicity-sphere/sphere-backoffice) | Admin panel |
|
|
12
12
|
| [sphere-quest](https://github.com/unicity-sphere/sphere-quest) | Quest frontend (iframe) |
|
|
13
13
|
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ interface DashboardLayoutProps {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Dashboard shell with sidebar + main content area.
|
|
18
|
-
* Used by sphere-backoffice and sphere-dev.
|
|
18
|
+
* Used by sphere-backoffice and sphere-dev-portal.
|
|
19
19
|
*/
|
|
20
20
|
declare function DashboardLayout({ logo, nav, footer, children }: DashboardLayoutProps): react_jsx_runtime.JSX.Element;
|
|
21
21
|
|
|
@@ -137,6 +137,29 @@ interface EmptyStateProps {
|
|
|
137
137
|
}
|
|
138
138
|
declare function EmptyState({ title, description, action }: EmptyStateProps): react_jsx_runtime.JSX.Element;
|
|
139
139
|
|
|
140
|
+
interface SkeletonProps {
|
|
141
|
+
width?: string;
|
|
142
|
+
height?: string;
|
|
143
|
+
radius?: string;
|
|
144
|
+
className?: string;
|
|
145
|
+
}
|
|
146
|
+
declare function Skeleton({ width, height, radius, className, }: SkeletonProps): react_jsx_runtime.JSX.Element;
|
|
147
|
+
|
|
148
|
+
interface SkeletonTextProps {
|
|
149
|
+
lines?: number;
|
|
150
|
+
lineHeight?: string;
|
|
151
|
+
gap?: string;
|
|
152
|
+
className?: string;
|
|
153
|
+
}
|
|
154
|
+
declare function SkeletonText({ lines, lineHeight, gap, className, }: SkeletonTextProps): react_jsx_runtime.JSX.Element;
|
|
155
|
+
|
|
156
|
+
type SkeletonCircleSize = 'sm' | 'md' | 'lg' | (string & {});
|
|
157
|
+
interface SkeletonCircleProps {
|
|
158
|
+
size?: SkeletonCircleSize;
|
|
159
|
+
className?: string;
|
|
160
|
+
}
|
|
161
|
+
declare function SkeletonCircle({ size, className }: SkeletonCircleProps): react_jsx_runtime.JSX.Element;
|
|
162
|
+
|
|
140
163
|
interface SelectOption {
|
|
141
164
|
value: string;
|
|
142
165
|
label: string;
|
|
@@ -255,4 +278,4 @@ declare const IconStar: (p: IconProps) => react_jsx_runtime.JSX.Element;
|
|
|
255
278
|
declare const IconDiamond: (p: IconProps) => react_jsx_runtime.JSX.Element;
|
|
256
279
|
declare const IconCircle: (p: IconProps) => react_jsx_runtime.JSX.Element;
|
|
257
280
|
|
|
258
|
-
export { AddressDisplay, AlertBanner, AppLogo, Button, type ButtonProps, type ButtonVariant, ChainInput, ConfirmDialog, CustomSelect, DashboardLayout, DataTable, EmptyState, Field, FormModal, IconArrowRight, IconBack, IconChain, IconCheck, IconChevronDown, IconChevronUp, IconChevronsDown, IconChevronsRight, IconCircle, IconDiamond, IconEdit, IconPlay, IconPlus, IconQuests, IconSearch, IconSettings, IconStar, IconTracks, IconTrash, IconUndo, IconX, Input, type InputProps, JsonPanel, JsonToggleButton, type MemoCondition, MemoConditionsEditor, type NavGroup, type NavItem, PageShell, SearchInput, Section, Select, type SelectOption, type SelectProps, SidebarNav, StatusBadge, Textarea, type TextareaProps, tagColor };
|
|
281
|
+
export { AddressDisplay, AlertBanner, AppLogo, Button, type ButtonProps, type ButtonVariant, ChainInput, ConfirmDialog, CustomSelect, DashboardLayout, DataTable, EmptyState, Field, FormModal, IconArrowRight, IconBack, IconChain, IconCheck, IconChevronDown, IconChevronUp, IconChevronsDown, IconChevronsRight, IconCircle, IconDiamond, IconEdit, IconPlay, IconPlus, IconQuests, IconSearch, IconSettings, IconStar, IconTracks, IconTrash, IconUndo, IconX, Input, type InputProps, JsonPanel, JsonToggleButton, type MemoCondition, MemoConditionsEditor, type NavGroup, type NavItem, PageShell, SearchInput, Section, Select, type SelectOption, type SelectProps, SidebarNav, Skeleton, SkeletonCircle, type SkeletonCircleProps, type SkeletonCircleSize, type SkeletonProps, SkeletonText, type SkeletonTextProps, StatusBadge, Textarea, type TextareaProps, tagColor };
|
package/dist/index.js
CHANGED
|
@@ -479,10 +479,81 @@ function EmptyState({ title, description, action }) {
|
|
|
479
479
|
] });
|
|
480
480
|
}
|
|
481
481
|
|
|
482
|
+
// src/components/Skeleton.tsx
|
|
483
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
484
|
+
function Skeleton({
|
|
485
|
+
width = "100%",
|
|
486
|
+
height = "1rem",
|
|
487
|
+
radius = "var(--radius-md)",
|
|
488
|
+
className = ""
|
|
489
|
+
}) {
|
|
490
|
+
return /* @__PURE__ */ jsx11(
|
|
491
|
+
"div",
|
|
492
|
+
{
|
|
493
|
+
className: `animate-skeleton-pulse ${className}`.trim(),
|
|
494
|
+
"aria-busy": "true",
|
|
495
|
+
style: {
|
|
496
|
+
width,
|
|
497
|
+
height,
|
|
498
|
+
borderRadius: radius,
|
|
499
|
+
background: "var(--bg-hover)",
|
|
500
|
+
border: "1px solid var(--border)"
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// src/components/SkeletonText.tsx
|
|
507
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
508
|
+
function SkeletonText({
|
|
509
|
+
lines = 1,
|
|
510
|
+
lineHeight = "0.875rem",
|
|
511
|
+
gap = "0.5rem",
|
|
512
|
+
className = ""
|
|
513
|
+
}) {
|
|
514
|
+
return /* @__PURE__ */ jsx12(
|
|
515
|
+
"div",
|
|
516
|
+
{
|
|
517
|
+
className,
|
|
518
|
+
role: "status",
|
|
519
|
+
"aria-busy": "true",
|
|
520
|
+
style: { display: "flex", flexDirection: "column", gap },
|
|
521
|
+
children: Array.from({ length: lines }).map((_, i) => {
|
|
522
|
+
const isLast = i === lines - 1 && lines > 1;
|
|
523
|
+
return /* @__PURE__ */ jsx12(
|
|
524
|
+
Skeleton,
|
|
525
|
+
{
|
|
526
|
+
width: isLast ? "70%" : "100%",
|
|
527
|
+
height: lineHeight,
|
|
528
|
+
radius: "var(--radius-sm)"
|
|
529
|
+
},
|
|
530
|
+
i
|
|
531
|
+
);
|
|
532
|
+
})
|
|
533
|
+
}
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// src/components/SkeletonCircle.tsx
|
|
538
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
539
|
+
var NAMED_SIZES = {
|
|
540
|
+
sm: "1.5rem",
|
|
541
|
+
md: "2.5rem",
|
|
542
|
+
lg: "4rem"
|
|
543
|
+
};
|
|
544
|
+
function resolveSize(size) {
|
|
545
|
+
if (size === "sm" || size === "md" || size === "lg") return NAMED_SIZES[size];
|
|
546
|
+
return size;
|
|
547
|
+
}
|
|
548
|
+
function SkeletonCircle({ size = "md", className = "" }) {
|
|
549
|
+
const dim = resolveSize(size);
|
|
550
|
+
return /* @__PURE__ */ jsx13(Skeleton, { width: dim, height: dim, radius: "50%", className });
|
|
551
|
+
}
|
|
552
|
+
|
|
482
553
|
// src/components/CustomSelect.tsx
|
|
483
554
|
import { useState as useState2, useRef, useEffect as useEffect3, useCallback } from "react";
|
|
484
555
|
import { createPortal as createPortal3 } from "react-dom";
|
|
485
|
-
import { jsx as
|
|
556
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
486
557
|
function CustomSelect({
|
|
487
558
|
options,
|
|
488
559
|
value,
|
|
@@ -545,8 +616,8 @@ function CustomSelect({
|
|
|
545
616
|
className: `admin-input w-full flex items-center justify-between gap-2 ${textSize} text-left`,
|
|
546
617
|
style: { color: selected ? "var(--text-primary)" : "var(--text-muted)" },
|
|
547
618
|
children: [
|
|
548
|
-
/* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
619
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate", children: label }),
|
|
620
|
+
/* @__PURE__ */ jsx14(
|
|
550
621
|
"svg",
|
|
551
622
|
{
|
|
552
623
|
width: "12",
|
|
@@ -562,14 +633,14 @@ function CustomSelect({
|
|
|
562
633
|
color: "var(--text-muted)",
|
|
563
634
|
transform: open ? "rotate(180deg)" : "rotate(0deg)"
|
|
564
635
|
},
|
|
565
|
-
children: /* @__PURE__ */
|
|
636
|
+
children: /* @__PURE__ */ jsx14("path", { d: "M3 4.5L6 7.5L9 4.5" })
|
|
566
637
|
}
|
|
567
638
|
)
|
|
568
639
|
]
|
|
569
640
|
}
|
|
570
641
|
),
|
|
571
642
|
open && createPortal3(
|
|
572
|
-
/* @__PURE__ */
|
|
643
|
+
/* @__PURE__ */ jsx14(
|
|
573
644
|
"div",
|
|
574
645
|
{
|
|
575
646
|
ref: dropRef,
|
|
@@ -586,7 +657,7 @@ function CustomSelect({
|
|
|
586
657
|
borderRadius: "var(--radius-md)",
|
|
587
658
|
boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
|
|
588
659
|
},
|
|
589
|
-
children: options.map((opt) => /* @__PURE__ */
|
|
660
|
+
children: options.map((opt) => /* @__PURE__ */ jsx14(
|
|
590
661
|
"button",
|
|
591
662
|
{
|
|
592
663
|
type: "button",
|
|
@@ -617,17 +688,17 @@ function CustomSelect({
|
|
|
617
688
|
}
|
|
618
689
|
|
|
619
690
|
// src/components/PageShell.tsx
|
|
620
|
-
import { jsx as
|
|
691
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
621
692
|
function PageShell({ title, subtitle, action, maxWidth, children }) {
|
|
622
693
|
return /* @__PURE__ */ jsxs11("div", { className: `p-6 lg:p-8 ${maxWidth ?? ""}`, children: [
|
|
623
694
|
/* @__PURE__ */ jsxs11("div", { className: "page-header", children: [
|
|
624
695
|
/* @__PURE__ */ jsxs11("div", { children: [
|
|
625
|
-
/* @__PURE__ */
|
|
626
|
-
subtitle && /* @__PURE__ */
|
|
696
|
+
/* @__PURE__ */ jsx15("h1", { className: "page-title", children: title }),
|
|
697
|
+
subtitle && /* @__PURE__ */ jsx15("p", { className: "page-subtitle", children: subtitle })
|
|
627
698
|
] }),
|
|
628
699
|
action
|
|
629
700
|
] }),
|
|
630
|
-
/* @__PURE__ */
|
|
701
|
+
/* @__PURE__ */ jsx15("div", { className: "animate-fade-in", children })
|
|
631
702
|
] });
|
|
632
703
|
}
|
|
633
704
|
|
|
@@ -640,7 +711,7 @@ import {
|
|
|
640
711
|
getFilteredRowModel,
|
|
641
712
|
flexRender
|
|
642
713
|
} from "@tanstack/react-table";
|
|
643
|
-
import { jsx as
|
|
714
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
644
715
|
function DataTable({
|
|
645
716
|
columns,
|
|
646
717
|
data,
|
|
@@ -664,10 +735,10 @@ function DataTable({
|
|
|
664
735
|
getFilteredRowModel: getFilteredRowModel()
|
|
665
736
|
});
|
|
666
737
|
if (isLoading) {
|
|
667
|
-
return /* @__PURE__ */
|
|
738
|
+
return /* @__PURE__ */ jsx16("div", { className: "py-12 text-center", style: { color: "var(--text-muted)" }, children: "Loading\u2026" });
|
|
668
739
|
}
|
|
669
740
|
return /* @__PURE__ */ jsxs12("div", { children: [
|
|
670
|
-
enableSearch && /* @__PURE__ */
|
|
741
|
+
enableSearch && /* @__PURE__ */ jsx16("div", { className: "mb-4 max-w-xs", children: /* @__PURE__ */ jsx16(
|
|
671
742
|
SearchInput,
|
|
672
743
|
{
|
|
673
744
|
value: globalFilter,
|
|
@@ -675,21 +746,21 @@ function DataTable({
|
|
|
675
746
|
placeholder: searchPlaceholder ?? "Search..."
|
|
676
747
|
}
|
|
677
748
|
) }),
|
|
678
|
-
table.getRowModel().rows.length === 0 ? /* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
749
|
+
table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx16(EmptyState, { title: emptyMessage }) : /* @__PURE__ */ jsx16("div", { className: "admin-card overflow-hidden", children: /* @__PURE__ */ jsxs12("table", { className: "admin-table", children: [
|
|
750
|
+
/* @__PURE__ */ jsx16("thead", { children: table.getHeaderGroups().map((hg) => /* @__PURE__ */ jsx16("tr", { children: hg.headers.map((header) => /* @__PURE__ */ jsx16(
|
|
680
751
|
"th",
|
|
681
752
|
{
|
|
682
753
|
className: header.column.getCanSort() ? "cursor-pointer select-none" : "",
|
|
683
754
|
onClick: header.column.getToggleSortingHandler(),
|
|
684
755
|
children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
|
|
685
756
|
flexRender(header.column.columnDef.header, header.getContext()),
|
|
686
|
-
header.column.getIsSorted() === "asc" && /* @__PURE__ */
|
|
687
|
-
header.column.getIsSorted() === "desc" && /* @__PURE__ */
|
|
757
|
+
header.column.getIsSorted() === "asc" && /* @__PURE__ */ jsx16("span", { style: { color: "var(--accent-text)" }, children: "\u25B2" }),
|
|
758
|
+
header.column.getIsSorted() === "desc" && /* @__PURE__ */ jsx16("span", { style: { color: "var(--accent-text)" }, children: "\u25BC" })
|
|
688
759
|
] })
|
|
689
760
|
},
|
|
690
761
|
header.id
|
|
691
762
|
)) }, hg.id)) }),
|
|
692
|
-
/* @__PURE__ */
|
|
763
|
+
/* @__PURE__ */ jsx16("tbody", { children: table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx16(
|
|
693
764
|
"tr",
|
|
694
765
|
{
|
|
695
766
|
onClick: () => onRowClick?.(row.original),
|
|
@@ -701,7 +772,7 @@ function DataTable({
|
|
|
701
772
|
onMouseLeave: (e) => {
|
|
702
773
|
if (onRowClick) e.currentTarget.style.background = "";
|
|
703
774
|
},
|
|
704
|
-
children: row.getVisibleCells().map((cell) => /* @__PURE__ */
|
|
775
|
+
children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx16("td", { children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
|
|
705
776
|
},
|
|
706
777
|
row.id
|
|
707
778
|
)) })
|
|
@@ -710,7 +781,7 @@ function DataTable({
|
|
|
710
781
|
}
|
|
711
782
|
|
|
712
783
|
// src/components/AlertBanner.tsx
|
|
713
|
-
import { jsx as
|
|
784
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
714
785
|
var STYLES = {
|
|
715
786
|
warning: {
|
|
716
787
|
bg: "rgba(251,191,36,0.06)",
|
|
@@ -727,16 +798,16 @@ var STYLES = {
|
|
|
727
798
|
};
|
|
728
799
|
function AlertBanner({ type, title, children }) {
|
|
729
800
|
const s = STYLES[type];
|
|
730
|
-
return /* @__PURE__ */
|
|
801
|
+
return /* @__PURE__ */ jsx17(
|
|
731
802
|
"div",
|
|
732
803
|
{
|
|
733
804
|
className: "rounded-lg p-3 text-sm",
|
|
734
805
|
style: { background: s.bg, border: `1px solid ${s.border}` },
|
|
735
806
|
children: /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2", children: [
|
|
736
|
-
/* @__PURE__ */
|
|
807
|
+
/* @__PURE__ */ jsx17("span", { className: "flex-shrink-0 text-sm leading-5", children: s.icon }),
|
|
737
808
|
/* @__PURE__ */ jsxs13("div", { children: [
|
|
738
|
-
/* @__PURE__ */
|
|
739
|
-
/* @__PURE__ */
|
|
809
|
+
/* @__PURE__ */ jsx17("div", { className: "font-medium text-xs mb-0.5", style: { color: s.titleColor }, children: title }),
|
|
810
|
+
/* @__PURE__ */ jsx17("div", { style: { color: "var(--text-muted)", fontSize: "0.75rem", lineHeight: "1.4" }, children })
|
|
740
811
|
] })
|
|
741
812
|
] })
|
|
742
813
|
}
|
|
@@ -745,7 +816,7 @@ function AlertBanner({ type, title, children }) {
|
|
|
745
816
|
|
|
746
817
|
// src/components/AddressDisplay.tsx
|
|
747
818
|
import { useState as useState4, useCallback as useCallback2 } from "react";
|
|
748
|
-
import { Fragment as Fragment2, jsx as
|
|
819
|
+
import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
749
820
|
function truncateAddress(address) {
|
|
750
821
|
const prefix = "DIRECT://";
|
|
751
822
|
if (address.startsWith(prefix)) {
|
|
@@ -769,12 +840,12 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
769
840
|
}, [address]);
|
|
770
841
|
const displayAddress = truncate ? truncateAddress(address) : address;
|
|
771
842
|
return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
772
|
-
/* @__PURE__ */
|
|
843
|
+
/* @__PURE__ */ jsx18("div", { className: "min-w-0 flex-1", children: nametag ? /* @__PURE__ */ jsxs14(Fragment2, { children: [
|
|
773
844
|
/* @__PURE__ */ jsxs14("div", { className: "text-sm font-medium", style: { color: "var(--text-primary)" }, children: [
|
|
774
845
|
"@",
|
|
775
846
|
nametag
|
|
776
847
|
] }),
|
|
777
|
-
/* @__PURE__ */
|
|
848
|
+
/* @__PURE__ */ jsx18(
|
|
778
849
|
"div",
|
|
779
850
|
{
|
|
780
851
|
className: "text-[11px] font-mono truncate",
|
|
@@ -783,7 +854,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
783
854
|
children: displayAddress
|
|
784
855
|
}
|
|
785
856
|
)
|
|
786
|
-
] }) : /* @__PURE__ */
|
|
857
|
+
] }) : /* @__PURE__ */ jsx18(
|
|
787
858
|
"div",
|
|
788
859
|
{
|
|
789
860
|
className: "text-xs font-mono truncate",
|
|
@@ -792,7 +863,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
792
863
|
children: displayAddress
|
|
793
864
|
}
|
|
794
865
|
) }),
|
|
795
|
-
/* @__PURE__ */
|
|
866
|
+
/* @__PURE__ */ jsx18(
|
|
796
867
|
"button",
|
|
797
868
|
{
|
|
798
869
|
onClick: handleCopy,
|
|
@@ -805,9 +876,9 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
805
876
|
if (!copied) e.currentTarget.style.color = "var(--text-muted)";
|
|
806
877
|
},
|
|
807
878
|
title: copied ? "Copied!" : "Copy address",
|
|
808
|
-
children: copied ? /* @__PURE__ */
|
|
809
|
-
/* @__PURE__ */
|
|
810
|
-
/* @__PURE__ */
|
|
879
|
+
children: copied ? /* @__PURE__ */ jsx18("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx18("path", { d: "M20 6L9 17l-5-5" }) }) : /* @__PURE__ */ jsxs14("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
880
|
+
/* @__PURE__ */ jsx18("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
881
|
+
/* @__PURE__ */ jsx18("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
811
882
|
] })
|
|
812
883
|
}
|
|
813
884
|
)
|
|
@@ -816,7 +887,7 @@ function AddressDisplay({ address, nametag, truncate = true }) {
|
|
|
816
887
|
|
|
817
888
|
// src/components/JsonPanel.tsx
|
|
818
889
|
import { useState as useState5, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback3 } from "react";
|
|
819
|
-
import { jsx as
|
|
890
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
820
891
|
function JsonPanel({
|
|
821
892
|
value,
|
|
822
893
|
onChange,
|
|
@@ -864,9 +935,9 @@ function JsonPanel({
|
|
|
864
935
|
" ",
|
|
865
936
|
title
|
|
866
937
|
] }),
|
|
867
|
-
parseError && /* @__PURE__ */
|
|
938
|
+
parseError && /* @__PURE__ */ jsx19("span", { className: "text-[10px] px-1.5 py-0.5 rounded", style: { background: "rgba(239,68,68,0.1)", color: "#f87171" }, children: "Error" })
|
|
868
939
|
] }),
|
|
869
|
-
/* @__PURE__ */
|
|
940
|
+
/* @__PURE__ */ jsx19(
|
|
870
941
|
"button",
|
|
871
942
|
{
|
|
872
943
|
onClick: handleCopy,
|
|
@@ -887,8 +958,8 @@ function JsonPanel({
|
|
|
887
958
|
}
|
|
888
959
|
)
|
|
889
960
|
] }),
|
|
890
|
-
/* @__PURE__ */
|
|
891
|
-
/* @__PURE__ */
|
|
961
|
+
/* @__PURE__ */ jsx19("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsxs15("div", { className: "absolute inset-0 flex overflow-auto", children: [
|
|
962
|
+
/* @__PURE__ */ jsx19(
|
|
892
963
|
"div",
|
|
893
964
|
{
|
|
894
965
|
className: "shrink-0 text-right pr-2 pt-3 select-none",
|
|
@@ -902,10 +973,10 @@ function JsonPanel({
|
|
|
902
973
|
background: "var(--bg-surface)",
|
|
903
974
|
borderRight: "1px solid var(--border)"
|
|
904
975
|
},
|
|
905
|
-
children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */
|
|
976
|
+
children: Array.from({ length: lineCount }, (_, i) => /* @__PURE__ */ jsx19("div", { children: i + 1 }, i))
|
|
906
977
|
}
|
|
907
978
|
),
|
|
908
|
-
/* @__PURE__ */
|
|
979
|
+
/* @__PURE__ */ jsx19(
|
|
909
980
|
"textarea",
|
|
910
981
|
{
|
|
911
982
|
ref: textareaRef,
|
|
@@ -927,11 +998,11 @@ function JsonPanel({
|
|
|
927
998
|
}
|
|
928
999
|
)
|
|
929
1000
|
] }) }),
|
|
930
|
-
parseError && /* @__PURE__ */
|
|
1001
|
+
parseError && /* @__PURE__ */ jsx19("div", { className: "px-3 py-1.5 text-[10px]", style: { background: "rgba(239,68,68,0.06)", color: "#f87171", borderTop: "1px solid rgba(239,68,68,0.15)" }, children: parseError })
|
|
931
1002
|
] });
|
|
932
1003
|
}
|
|
933
1004
|
function JsonToggleButton({ active, onClick }) {
|
|
934
|
-
return /* @__PURE__ */
|
|
1005
|
+
return /* @__PURE__ */ jsx19(
|
|
935
1006
|
"button",
|
|
936
1007
|
{
|
|
937
1008
|
onClick,
|
|
@@ -963,7 +1034,7 @@ function JsonToggleButton({ active, onClick }) {
|
|
|
963
1034
|
|
|
964
1035
|
// src/components/ChainInput.tsx
|
|
965
1036
|
import { useState as useState6, useId } from "react";
|
|
966
|
-
import { jsx as
|
|
1037
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
967
1038
|
var TAG_PALETTES = [
|
|
968
1039
|
{ bg: "rgba(16, 185, 129, 0.12)", color: "#34d399", border: "rgba(16, 185, 129, 0.2)" },
|
|
969
1040
|
{ bg: "rgba(59, 130, 246, 0.12)", color: "#60a5fa", border: "rgba(59, 130, 246, 0.2)" },
|
|
@@ -1033,7 +1104,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
|
|
|
1033
1104
|
style: { background: c.bg, color: c.color, border: `1px solid ${c.border}` },
|
|
1034
1105
|
children: [
|
|
1035
1106
|
name,
|
|
1036
|
-
/* @__PURE__ */
|
|
1107
|
+
/* @__PURE__ */ jsx20(
|
|
1037
1108
|
"input",
|
|
1038
1109
|
{
|
|
1039
1110
|
type: "number",
|
|
@@ -1045,7 +1116,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
|
|
|
1045
1116
|
onClick: (e) => e.stopPropagation()
|
|
1046
1117
|
}
|
|
1047
1118
|
),
|
|
1048
|
-
/* @__PURE__ */
|
|
1119
|
+
/* @__PURE__ */ jsx20(
|
|
1049
1120
|
"button",
|
|
1050
1121
|
{
|
|
1051
1122
|
type: "button",
|
|
@@ -1062,7 +1133,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
|
|
|
1062
1133
|
name
|
|
1063
1134
|
);
|
|
1064
1135
|
}),
|
|
1065
|
-
/* @__PURE__ */
|
|
1136
|
+
/* @__PURE__ */ jsx20(
|
|
1066
1137
|
"input",
|
|
1067
1138
|
{
|
|
1068
1139
|
id: inputId,
|
|
@@ -1122,7 +1193,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
|
|
|
1122
1193
|
e.currentTarget.style.background = "transparent";
|
|
1123
1194
|
},
|
|
1124
1195
|
children: [
|
|
1125
|
-
/* @__PURE__ */
|
|
1196
|
+
/* @__PURE__ */ jsx20("span", { className: "w-2 h-2 rounded-full flex-shrink-0", style: { background: c.color } }),
|
|
1126
1197
|
s
|
|
1127
1198
|
]
|
|
1128
1199
|
},
|
|
@@ -1136,7 +1207,7 @@ function ChainInput({ chains, suggestions, onChange, size = "md" }) {
|
|
|
1136
1207
|
}
|
|
1137
1208
|
|
|
1138
1209
|
// src/components/MemoConditionsEditor.tsx
|
|
1139
|
-
import { Fragment as Fragment3, jsx as
|
|
1210
|
+
import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1140
1211
|
var MEMO_OPERATORS = [
|
|
1141
1212
|
{ value: "eq", label: "Equals (=)", values: 1 },
|
|
1142
1213
|
{ value: "neq", label: "Not equals (\u2260)", values: 1 },
|
|
@@ -1184,14 +1255,14 @@ function MemoConditionsEditor({ conditions, onChange }) {
|
|
|
1184
1255
|
const opMeta = (op) => MEMO_OPERATORS.find((o) => o.value === op) ?? MEMO_OPERATORS[0];
|
|
1185
1256
|
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1186
1257
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
1187
|
-
/* @__PURE__ */
|
|
1188
|
-
/* @__PURE__ */
|
|
1258
|
+
/* @__PURE__ */ jsx21("span", { className: "text-xs font-medium", style: { color: "var(--text-muted)" }, children: "Memo Conditions" }),
|
|
1259
|
+
/* @__PURE__ */ jsx21("button", { type: "button", onClick: add, className: "text-[10px] px-2 py-0.5 rounded cursor-pointer", style: { background: "var(--bg-elevated)", color: "var(--accent-text)" }, children: "+ Add" })
|
|
1189
1260
|
] }),
|
|
1190
|
-
conditions.length > 0 ? /* @__PURE__ */
|
|
1261
|
+
conditions.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "flex flex-col gap-2", children: conditions.map((cond, i) => {
|
|
1191
1262
|
const meta = opMeta(cond.operator);
|
|
1192
1263
|
return /* @__PURE__ */ jsxs17("div", { className: "rounded-lg p-2.5", style: { background: "rgba(255,255,255,0.02)", border: "1px solid var(--border)" }, children: [
|
|
1193
1264
|
/* @__PURE__ */ jsxs17("div", { className: "flex gap-2 items-center", children: [
|
|
1194
|
-
/* @__PURE__ */
|
|
1265
|
+
/* @__PURE__ */ jsx21(
|
|
1195
1266
|
"input",
|
|
1196
1267
|
{
|
|
1197
1268
|
className: "admin-input flex-1 text-xs",
|
|
@@ -1200,7 +1271,7 @@ function MemoConditionsEditor({ conditions, onChange }) {
|
|
|
1200
1271
|
onChange: (e) => update(i, { key: e.target.value })
|
|
1201
1272
|
}
|
|
1202
1273
|
),
|
|
1203
|
-
/* @__PURE__ */
|
|
1274
|
+
/* @__PURE__ */ jsx21(
|
|
1204
1275
|
CustomSelect,
|
|
1205
1276
|
{
|
|
1206
1277
|
size: "sm",
|
|
@@ -1210,7 +1281,7 @@ function MemoConditionsEditor({ conditions, onChange }) {
|
|
|
1210
1281
|
options: MEMO_OPERATORS.map((o) => ({ value: o.value, label: o.label }))
|
|
1211
1282
|
}
|
|
1212
1283
|
),
|
|
1213
|
-
meta.values >= 1 && /* @__PURE__ */
|
|
1284
|
+
meta.values >= 1 && /* @__PURE__ */ jsx21(
|
|
1214
1285
|
"input",
|
|
1215
1286
|
{
|
|
1216
1287
|
className: "admin-input flex-1 text-xs",
|
|
@@ -1220,8 +1291,8 @@ function MemoConditionsEditor({ conditions, onChange }) {
|
|
|
1220
1291
|
}
|
|
1221
1292
|
),
|
|
1222
1293
|
meta.values === 2 && /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
1223
|
-
/* @__PURE__ */
|
|
1224
|
-
/* @__PURE__ */
|
|
1294
|
+
/* @__PURE__ */ jsx21("span", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: "and" }),
|
|
1295
|
+
/* @__PURE__ */ jsx21(
|
|
1225
1296
|
"input",
|
|
1226
1297
|
{
|
|
1227
1298
|
className: "admin-input flex-1 text-xs",
|
|
@@ -1231,18 +1302,18 @@ function MemoConditionsEditor({ conditions, onChange }) {
|
|
|
1231
1302
|
}
|
|
1232
1303
|
)
|
|
1233
1304
|
] }),
|
|
1234
|
-
/* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx21("button", { type: "button", onClick: () => remove(i), className: "text-red-400 text-sm px-1 cursor-pointer", children: "\xD7" })
|
|
1235
1306
|
] }),
|
|
1236
|
-
/* @__PURE__ */
|
|
1307
|
+
/* @__PURE__ */ jsx21("p", { className: "text-[10px] mt-1.5 ml-0.5", style: { color: "var(--text-muted)", fontStyle: "italic" }, children: conditionPreview(cond) })
|
|
1237
1308
|
] }, i);
|
|
1238
|
-
}) }) : /* @__PURE__ */
|
|
1309
|
+
}) }) : /* @__PURE__ */ jsx21("p", { className: "text-[10px]", style: { color: "var(--text-muted)" }, children: 'No conditions \u2014 matches any memo transaction. Click "+ Add" to filter.' })
|
|
1239
1310
|
] });
|
|
1240
1311
|
}
|
|
1241
1312
|
|
|
1242
1313
|
// src/components/Icons.tsx
|
|
1243
|
-
import { jsx as
|
|
1314
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
1244
1315
|
function I({ d, size = 16, className, style }) {
|
|
1245
|
-
return /* @__PURE__ */
|
|
1316
|
+
return /* @__PURE__ */ jsx22(
|
|
1246
1317
|
"svg",
|
|
1247
1318
|
{
|
|
1248
1319
|
width: size,
|
|
@@ -1255,7 +1326,7 @@ function I({ d, size = 16, className, style }) {
|
|
|
1255
1326
|
strokeLinejoin: "round",
|
|
1256
1327
|
className,
|
|
1257
1328
|
style,
|
|
1258
|
-
children: /* @__PURE__ */
|
|
1329
|
+
children: /* @__PURE__ */ jsx22("path", { d })
|
|
1259
1330
|
}
|
|
1260
1331
|
);
|
|
1261
1332
|
}
|
|
@@ -1287,27 +1358,27 @@ var P = {
|
|
|
1287
1358
|
diamond: "M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41L13.7 2.71a2.41 2.41 0 0 0-3.41 0L2.7 10.3z",
|
|
1288
1359
|
circle: "M12 12m-4 0a4 4 0 1 0 8 0 4 4 0 1 0-8 0"
|
|
1289
1360
|
};
|
|
1290
|
-
var IconBack = (p) => /* @__PURE__ */
|
|
1291
|
-
var IconUndo = (p) => /* @__PURE__ */
|
|
1292
|
-
var IconQuests = (p) => /* @__PURE__ */
|
|
1293
|
-
var IconTracks = (p) => /* @__PURE__ */
|
|
1294
|
-
var IconSettings = (p) => /* @__PURE__ */
|
|
1295
|
-
var IconChain = (p) => /* @__PURE__ */
|
|
1296
|
-
var IconPlus = (p) => /* @__PURE__ */
|
|
1297
|
-
var IconEdit = (p) => /* @__PURE__ */
|
|
1298
|
-
var IconTrash = (p) => /* @__PURE__ */
|
|
1299
|
-
var IconX = (p) => /* @__PURE__ */
|
|
1300
|
-
var IconCheck = (p) => /* @__PURE__ */
|
|
1301
|
-
var IconSearch = (p) => /* @__PURE__ */
|
|
1302
|
-
var IconChevronUp = (p) => /* @__PURE__ */
|
|
1303
|
-
var IconChevronDown = (p) => /* @__PURE__ */
|
|
1304
|
-
var IconChevronsDown = (p) => /* @__PURE__ */
|
|
1305
|
-
var IconChevronsRight = (p) => /* @__PURE__ */
|
|
1306
|
-
var IconArrowRight = (p) => /* @__PURE__ */
|
|
1307
|
-
var IconPlay = (p) => /* @__PURE__ */
|
|
1308
|
-
var IconStar = (p) => /* @__PURE__ */
|
|
1309
|
-
var IconDiamond = (p) => /* @__PURE__ */
|
|
1310
|
-
var IconCircle = (p) => /* @__PURE__ */
|
|
1361
|
+
var IconBack = (p) => /* @__PURE__ */ jsx22(I, { d: P.back, ...p });
|
|
1362
|
+
var IconUndo = (p) => /* @__PURE__ */ jsx22(I, { d: P.undo, ...p });
|
|
1363
|
+
var IconQuests = (p) => /* @__PURE__ */ jsx22(I, { d: P.quests, ...p });
|
|
1364
|
+
var IconTracks = (p) => /* @__PURE__ */ jsx22(I, { d: P.tracks, ...p });
|
|
1365
|
+
var IconSettings = (p) => /* @__PURE__ */ jsx22(I, { d: P.settings, ...p });
|
|
1366
|
+
var IconChain = (p) => /* @__PURE__ */ jsx22(I, { d: P.chain, ...p });
|
|
1367
|
+
var IconPlus = (p) => /* @__PURE__ */ jsx22(I, { d: P.plus, ...p });
|
|
1368
|
+
var IconEdit = (p) => /* @__PURE__ */ jsx22(I, { d: P.edit, ...p });
|
|
1369
|
+
var IconTrash = (p) => /* @__PURE__ */ jsx22(I, { d: P.trash, ...p });
|
|
1370
|
+
var IconX = (p) => /* @__PURE__ */ jsx22(I, { d: P.x, ...p });
|
|
1371
|
+
var IconCheck = (p) => /* @__PURE__ */ jsx22(I, { d: P.check, ...p });
|
|
1372
|
+
var IconSearch = (p) => /* @__PURE__ */ jsx22(I, { d: P.search, ...p });
|
|
1373
|
+
var IconChevronUp = (p) => /* @__PURE__ */ jsx22(I, { d: P.chevronUp, ...p });
|
|
1374
|
+
var IconChevronDown = (p) => /* @__PURE__ */ jsx22(I, { d: P.chevronDown, ...p });
|
|
1375
|
+
var IconChevronsDown = (p) => /* @__PURE__ */ jsx22(I, { d: P.chevronsDown, ...p });
|
|
1376
|
+
var IconChevronsRight = (p) => /* @__PURE__ */ jsx22(I, { d: P.chevronsRight, ...p });
|
|
1377
|
+
var IconArrowRight = (p) => /* @__PURE__ */ jsx22(I, { d: P.arrowRight, ...p });
|
|
1378
|
+
var IconPlay = (p) => /* @__PURE__ */ jsx22(I, { d: P.play, ...p });
|
|
1379
|
+
var IconStar = (p) => /* @__PURE__ */ jsx22(I, { d: P.star, ...p });
|
|
1380
|
+
var IconDiamond = (p) => /* @__PURE__ */ jsx22(I, { d: P.diamond, ...p });
|
|
1381
|
+
var IconCircle = (p) => /* @__PURE__ */ jsx22(I, { d: P.circle, ...p });
|
|
1311
1382
|
export {
|
|
1312
1383
|
AddressDisplay,
|
|
1313
1384
|
AlertBanner,
|
|
@@ -1351,6 +1422,9 @@ export {
|
|
|
1351
1422
|
Section,
|
|
1352
1423
|
Select,
|
|
1353
1424
|
SidebarNav,
|
|
1425
|
+
Skeleton,
|
|
1426
|
+
SkeletonCircle,
|
|
1427
|
+
SkeletonText,
|
|
1354
1428
|
StatusBadge,
|
|
1355
1429
|
Textarea,
|
|
1356
1430
|
tagColor
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unicitylabs/sphere-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -35,29 +35,37 @@
|
|
|
35
35
|
"build": "tsup",
|
|
36
36
|
"dev": "tsup --watch",
|
|
37
37
|
"lint": "eslint src/",
|
|
38
|
-
"typecheck": "tsc --noEmit"
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"test": "vitest",
|
|
40
|
+
"test:run": "vitest run"
|
|
39
41
|
},
|
|
40
42
|
"peerDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
+
"@dnd-kit/core": "^6.0.0",
|
|
44
|
+
"@dnd-kit/sortable": "^8.0.0 || ^10.0.0",
|
|
43
45
|
"@tanstack/react-query": "^5.0.0",
|
|
44
46
|
"@tanstack/react-table": "^8.0.0",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
47
|
+
"lucide-react": "^0.400.0",
|
|
48
|
+
"react": "^19.0.0",
|
|
49
|
+
"react-dom": "^19.0.0"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
52
|
+
"@dnd-kit/core": "^6.0.0",
|
|
53
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
54
|
+
"@dnd-kit/utilities": "^3.0.0",
|
|
55
|
+
"@tanstack/react-query": "^5.40.0",
|
|
56
|
+
"@tanstack/react-table": "^8.17.3",
|
|
57
|
+
"@testing-library/dom": "^10.4.1",
|
|
58
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
59
|
+
"@testing-library/react": "^16.3.2",
|
|
50
60
|
"@types/react": "^19.0.0",
|
|
51
61
|
"@types/react-dom": "^19.0.0",
|
|
62
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
63
|
+
"jsdom": "^25.0.1",
|
|
64
|
+
"lucide-react": "^0.400.0",
|
|
52
65
|
"react": "^19.0.0",
|
|
53
66
|
"react-dom": "^19.0.0",
|
|
54
|
-
"@tanstack/react-query": "^5.40.0",
|
|
55
|
-
"@tanstack/react-table": "^8.17.3",
|
|
56
|
-
"@dnd-kit/core": "^6.0.0",
|
|
57
|
-
"@dnd-kit/sortable": "^8.0.0",
|
|
58
|
-
"@dnd-kit/utilities": "^3.0.0",
|
|
59
|
-
"lucide-react": "^0.400.0",
|
|
60
67
|
"tsup": "^8.0.0",
|
|
61
|
-
"typescript": "~5.9.0"
|
|
68
|
+
"typescript": "~5.9.0",
|
|
69
|
+
"vitest": "^2.1.9"
|
|
62
70
|
}
|
|
63
71
|
}
|
|
@@ -119,3 +119,12 @@ select.admin-input {
|
|
|
119
119
|
@keyframes pulse-glow { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.8; } }
|
|
120
120
|
@keyframes fade-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }
|
|
121
121
|
.animate-fade-in { animation: fade-in 0.3s ease-out both; }
|
|
122
|
+
|
|
123
|
+
/* ─── Skeleton ────────────────────────────────────────────────────────── */
|
|
124
|
+
@keyframes skeleton-pulse {
|
|
125
|
+
0%, 100% { opacity: 0.6; }
|
|
126
|
+
50% { opacity: 1; }
|
|
127
|
+
}
|
|
128
|
+
.animate-skeleton-pulse {
|
|
129
|
+
animation: skeleton-pulse 1.6s ease-in-out infinite;
|
|
130
|
+
}
|
package/src/styles/tokens.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* ═══════════════════════════════════════════════════════════════════════════
|
|
2
2
|
Sphere UI — Design Tokens
|
|
3
3
|
Brand: Unicity Brand Guidelines
|
|
4
|
-
Used by: sphere, sphere-backoffice, sphere-dev, sphere-quest
|
|
4
|
+
Used by: sphere, sphere-backoffice, sphere-dev-portal, sphere-quest
|
|
5
5
|
═══════════════════════════════════════════════════════════════════════════ */
|
|
6
6
|
|
|
7
7
|
/* Brand fonts — Anton (headlines), Geist (body), Geist Mono (code) */
|