@hivemindhq/core 0.4.0
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 +224 -0
- package/dist/chunk-2RGM3KJL.js +351 -0
- package/dist/chunk-2RGM3KJL.js.map +1 -0
- package/dist/chunk-E5TTKYNS.js +55 -0
- package/dist/chunk-E5TTKYNS.js.map +1 -0
- package/dist/chunk-ERZSVDIB.js +270 -0
- package/dist/chunk-ERZSVDIB.js.map +1 -0
- package/dist/chunk-H4RMZQ2Z.js +213 -0
- package/dist/chunk-H4RMZQ2Z.js.map +1 -0
- package/dist/chunk-K7EIJSYQ.js +3 -0
- package/dist/chunk-K7EIJSYQ.js.map +1 -0
- package/dist/chunk-OJF67RNM.js +3 -0
- package/dist/chunk-OJF67RNM.js.map +1 -0
- package/dist/chunk-P5E2XNDI.js +2758 -0
- package/dist/chunk-P5E2XNDI.js.map +1 -0
- package/dist/chunk-T2XWV636.js +137 -0
- package/dist/chunk-T2XWV636.js.map +1 -0
- package/dist/chunk-VIRNUAYY.js +11 -0
- package/dist/chunk-VIRNUAYY.js.map +1 -0
- package/dist/components/index.d.ts +277 -0
- package/dist/components/index.js +6 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/ui/index.d.ts +396 -0
- package/dist/components/ui/index.js +6 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/hooks/index.d.ts +27 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/toast-D090UYOq.d.ts +19 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.d.ts +573 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +107 -0
- package/tailwind.config.js +96 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { cn } from './chunk-VIRNUAYY.js';
|
|
2
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function TooltipProvider({
|
|
6
|
+
delayDuration = 0,
|
|
7
|
+
...props
|
|
8
|
+
}) {
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
TooltipPrimitive.Provider,
|
|
11
|
+
{
|
|
12
|
+
"data-slot": "tooltip-provider",
|
|
13
|
+
delayDuration,
|
|
14
|
+
...props
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
function Tooltip({
|
|
19
|
+
...props
|
|
20
|
+
}) {
|
|
21
|
+
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
22
|
+
}
|
|
23
|
+
function TooltipTrigger({
|
|
24
|
+
...props
|
|
25
|
+
}) {
|
|
26
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
27
|
+
}
|
|
28
|
+
function TooltipContent({
|
|
29
|
+
className,
|
|
30
|
+
sideOffset = 0,
|
|
31
|
+
children,
|
|
32
|
+
container,
|
|
33
|
+
...props
|
|
34
|
+
}) {
|
|
35
|
+
return /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { container, children: /* @__PURE__ */ jsxs(
|
|
36
|
+
TooltipPrimitive.Content,
|
|
37
|
+
{
|
|
38
|
+
"data-slot": "tooltip-content",
|
|
39
|
+
sideOffset,
|
|
40
|
+
className: cn(
|
|
41
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
42
|
+
className
|
|
43
|
+
),
|
|
44
|
+
...props,
|
|
45
|
+
children: [
|
|
46
|
+
children,
|
|
47
|
+
/* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
) });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
|
|
54
|
+
//# sourceMappingURL=chunk-E5TTKYNS.js.map
|
|
55
|
+
//# sourceMappingURL=chunk-E5TTKYNS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/tooltip.tsx"],"names":[],"mappings":";;;;AAIA,SAAS,eAAA,CAAgB;AAAA,EACvB,aAAA,GAAgB,CAAA;AAAA,EAChB,GAAG;AACL,CAAA,EAA2D;AACzD,EAAA,uBACE,GAAA;AAAA,IAAkB,gBAAA,CAAA,QAAA;AAAA,IAAjB;AAAA,MACC,WAAA,EAAU,kBAAA;AAAA,MACV,aAAA;AAAA,MACC,GAAG;AAAA;AAAA,GACN;AAEJ;AAEA,SAAS,OAAA,CAAQ;AAAA,EACf,GAAG;AACL,CAAA,EAAuD;AACrD,EAAA,uBACE,GAAA,CAAC,mBACC,QAAA,kBAAA,GAAA,CAAkB,gBAAA,CAAA,IAAA,EAAjB,EAAsB,WAAA,EAAU,SAAA,EAAW,GAAG,KAAA,EAAO,CAAA,EACxD,CAAA;AAEJ;AAEA,SAAS,cAAA,CAAe;AAAA,EACtB,GAAG;AACL,CAAA,EAA0D;AACxD,EAAA,2BAAyB,gBAAA,CAAA,OAAA,EAAjB,EAAyB,WAAA,EAAU,iBAAA,EAAmB,GAAG,KAAA,EAAO,CAAA;AAC1E;AAEA,SAAS,cAAA,CAAe;AAAA,EACtB,SAAA;AAAA,EACA,UAAA,GAAa,CAAA;AAAA,EACb,QAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAEG;AACD,EAAA,uBACE,GAAA,CAAkB,gBAAA,CAAA,MAAA,EAAjB,EAAwB,SAAA,EACvB,QAAA,kBAAA,IAAA;AAAA,IAAkB,gBAAA,CAAA,OAAA;AAAA,IAAjB;AAAA,MACC,WAAA,EAAU,iBAAA;AAAA,MACV,UAAA;AAAA,MACA,SAAA,EAAW,EAAA;AAAA,QACT,waAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,wBACD,GAAA,CAAkB,gBAAA,CAAA,KAAA,EAAjB,EAAuB,SAAA,EAAU,8FAAA,EAA+F;AAAA;AAAA;AAAA,GACnI,EACF,CAAA;AAEJ","file":"chunk-E5TTKYNS.js","sourcesContent":["import * as TooltipPrimitive from '@radix-ui/react-tooltip'\nimport * as React from 'react'\nimport { cn } from '../../utils/cn'\n\nfunction TooltipProvider({\n delayDuration = 0,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delayDuration={delayDuration}\n {...props}\n />\n )\n}\n\nfunction Tooltip({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Root>) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n sideOffset = 0,\n children,\n container,\n ...props\n}: React.ComponentProps<typeof TooltipPrimitive.Content> & {\n container?: HTMLElement\n}) {\n return (\n <TooltipPrimitive.Portal container={container}>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance',\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]\" />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n"]}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// src/utils/formatting.ts
|
|
2
|
+
function formatCryptoAmount(value, decimals = 18, options = {}) {
|
|
3
|
+
const {
|
|
4
|
+
maxSignificantDigits = 10,
|
|
5
|
+
compact = false,
|
|
6
|
+
locale = "en-US",
|
|
7
|
+
minDecimals = 0,
|
|
8
|
+
maxDecimals = 6
|
|
9
|
+
} = options;
|
|
10
|
+
const bigIntValue = typeof value === "string" ? BigInt(value) : value;
|
|
11
|
+
if (bigIntValue === 0n) {
|
|
12
|
+
return {
|
|
13
|
+
display: "0",
|
|
14
|
+
fullValue: "0",
|
|
15
|
+
isTruncated: false,
|
|
16
|
+
numericValue: 0
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const divisor = 10n ** BigInt(decimals);
|
|
20
|
+
const wholePart = bigIntValue / divisor;
|
|
21
|
+
const fractionalPart = bigIntValue % divisor;
|
|
22
|
+
const fractionalStr = fractionalPart.toString().padStart(decimals, "0");
|
|
23
|
+
const trimmedFractional = fractionalStr.replace(/0+$/, "");
|
|
24
|
+
const fullValue = trimmedFractional ? `${wholePart}.${trimmedFractional}` : wholePart.toString();
|
|
25
|
+
const numericValue = Number(fullValue);
|
|
26
|
+
if (compact && Math.abs(numericValue) >= 1e3) {
|
|
27
|
+
const compactDisplay = formatCompact(numericValue);
|
|
28
|
+
return {
|
|
29
|
+
display: compactDisplay,
|
|
30
|
+
fullValue,
|
|
31
|
+
isTruncated: true,
|
|
32
|
+
// Compact is always "truncated" conceptually
|
|
33
|
+
numericValue
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const originalDecimalCount = trimmedFractional.length;
|
|
37
|
+
const decimalsWillBeTruncated = originalDecimalCount > maxDecimals;
|
|
38
|
+
let decimalLimitedValue;
|
|
39
|
+
try {
|
|
40
|
+
decimalLimitedValue = new Intl.NumberFormat(locale, {
|
|
41
|
+
minimumFractionDigits: minDecimals,
|
|
42
|
+
maximumFractionDigits: maxDecimals,
|
|
43
|
+
useGrouping: false
|
|
44
|
+
// Disable commas for significant digit counting
|
|
45
|
+
}).format(numericValue);
|
|
46
|
+
} catch {
|
|
47
|
+
decimalLimitedValue = fullValue;
|
|
48
|
+
}
|
|
49
|
+
const { truncated, isTruncated: sigDigitsTruncated } = truncateSignificantDigits(
|
|
50
|
+
decimalLimitedValue,
|
|
51
|
+
maxSignificantDigits
|
|
52
|
+
);
|
|
53
|
+
const isTruncated = decimalsWillBeTruncated || sigDigitsTruncated;
|
|
54
|
+
let display;
|
|
55
|
+
if (sigDigitsTruncated) {
|
|
56
|
+
display = truncated;
|
|
57
|
+
} else {
|
|
58
|
+
try {
|
|
59
|
+
display = new Intl.NumberFormat(locale, {
|
|
60
|
+
minimumFractionDigits: minDecimals,
|
|
61
|
+
maximumFractionDigits: maxDecimals
|
|
62
|
+
}).format(numericValue);
|
|
63
|
+
} catch {
|
|
64
|
+
display = decimalLimitedValue;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
display,
|
|
69
|
+
fullValue,
|
|
70
|
+
isTruncated,
|
|
71
|
+
numericValue
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function truncateSignificantDigits(value, maxDigits) {
|
|
75
|
+
if (!value) {
|
|
76
|
+
return { truncated: "0", isTruncated: false };
|
|
77
|
+
}
|
|
78
|
+
const isNegative = value.startsWith("-");
|
|
79
|
+
const absValue = isNegative ? value.slice(1) : value;
|
|
80
|
+
const [wholePart, fractionalPart] = absValue.split(".");
|
|
81
|
+
let significantCount = 0;
|
|
82
|
+
let truncatedWhole = "";
|
|
83
|
+
let truncatedFractional = "";
|
|
84
|
+
let isTruncated = false;
|
|
85
|
+
if (wholePart !== "0") {
|
|
86
|
+
for (const char of wholePart) {
|
|
87
|
+
if (significantCount >= maxDigits) {
|
|
88
|
+
isTruncated = true;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
truncatedWhole += char;
|
|
92
|
+
significantCount++;
|
|
93
|
+
}
|
|
94
|
+
if (isTruncated) {
|
|
95
|
+
const result2 = isNegative ? `-${truncatedWhole}` : truncatedWhole;
|
|
96
|
+
return { truncated: `${result2}\u2026`, isTruncated: true };
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
truncatedWhole = "0";
|
|
100
|
+
}
|
|
101
|
+
if (fractionalPart) {
|
|
102
|
+
let foundNonZero = wholePart !== "0";
|
|
103
|
+
for (const char of fractionalPart) {
|
|
104
|
+
if (!foundNonZero && char === "0") {
|
|
105
|
+
truncatedFractional += char;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
foundNonZero = true;
|
|
109
|
+
if (significantCount >= maxDigits) {
|
|
110
|
+
isTruncated = true;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
truncatedFractional += char;
|
|
114
|
+
significantCount++;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
let result = truncatedWhole;
|
|
118
|
+
if (truncatedFractional) {
|
|
119
|
+
result += `.${truncatedFractional}`;
|
|
120
|
+
}
|
|
121
|
+
if (isNegative) {
|
|
122
|
+
result = `-${result}`;
|
|
123
|
+
}
|
|
124
|
+
return { truncated: result, isTruncated };
|
|
125
|
+
}
|
|
126
|
+
function truncateId(value, chars = 5, prefix = "0x") {
|
|
127
|
+
if (!value) return "";
|
|
128
|
+
const start = value.startsWith(prefix) ? prefix.length : 0;
|
|
129
|
+
return value.slice(start, start + chars);
|
|
130
|
+
}
|
|
131
|
+
function ipfsToHttp(uri, gateway = "https://ipfs.io/ipfs/") {
|
|
132
|
+
if (!uri) return void 0;
|
|
133
|
+
if (uri.startsWith("ipfs://")) {
|
|
134
|
+
return uri.replace("ipfs://", gateway);
|
|
135
|
+
}
|
|
136
|
+
return uri;
|
|
137
|
+
}
|
|
138
|
+
function formatCompact(value, decimals = 2) {
|
|
139
|
+
if (value === 0) return "0";
|
|
140
|
+
const formatter = new Intl.NumberFormat("en-US", {
|
|
141
|
+
notation: "compact",
|
|
142
|
+
maximumFractionDigits: decimals
|
|
143
|
+
});
|
|
144
|
+
return formatter.format(value);
|
|
145
|
+
}
|
|
146
|
+
function strengthenImageUrl(url = "") {
|
|
147
|
+
if (!url || typeof url !== "string" || url.trim() === "") {
|
|
148
|
+
return url;
|
|
149
|
+
}
|
|
150
|
+
const trimmedUrl = url.trim();
|
|
151
|
+
if (trimmedUrl.startsWith("ipfs://")) {
|
|
152
|
+
return trimmedUrl.replace("ipfs://", "https://ipfs.io/ipfs/");
|
|
153
|
+
}
|
|
154
|
+
if (trimmedUrl.startsWith("https://") || trimmedUrl.startsWith("http://")) {
|
|
155
|
+
return trimmedUrl;
|
|
156
|
+
}
|
|
157
|
+
if (trimmedUrl.startsWith("Qm") || trimmedUrl.startsWith("baf")) {
|
|
158
|
+
return "https://ipfs.io/ipfs/" + trimmedUrl;
|
|
159
|
+
}
|
|
160
|
+
return trimmedUrl;
|
|
161
|
+
}
|
|
162
|
+
function ellipsizeString(str, length) {
|
|
163
|
+
if (!str) return "";
|
|
164
|
+
if (str.length < length) return str;
|
|
165
|
+
const first = str.substring(0, length / 2);
|
|
166
|
+
const second = str.substring(str.length - length / 2, str.length);
|
|
167
|
+
return [first, second].join("...");
|
|
168
|
+
}
|
|
169
|
+
function ellipsizeHex(hex, length = 12) {
|
|
170
|
+
if (!hex || !hex.startsWith("0x")) throw new Error("Invalid hex");
|
|
171
|
+
const prefix = "0x";
|
|
172
|
+
const payload = hex.replace("0x", "");
|
|
173
|
+
const shortenedPayload = ellipsizeString(payload, length);
|
|
174
|
+
return `${prefix}${shortenedPayload}`;
|
|
175
|
+
}
|
|
176
|
+
function truncateString(str = "", length) {
|
|
177
|
+
if (!str) return "";
|
|
178
|
+
if (str.length < length) return str;
|
|
179
|
+
return `${str.substring(0, length)}...`;
|
|
180
|
+
}
|
|
181
|
+
function shortenLabel(label, length = 50) {
|
|
182
|
+
if (!label) return "";
|
|
183
|
+
if (label.startsWith("0x")) {
|
|
184
|
+
return ellipsizeHex(label, 12);
|
|
185
|
+
}
|
|
186
|
+
if (label.startsWith("bafkre")) {
|
|
187
|
+
return ellipsizeString(label, 12);
|
|
188
|
+
}
|
|
189
|
+
if (label.startsWith("ipfs://bafkre")) {
|
|
190
|
+
return ellipsizeString(label.replace("ipfs://", ""), 12);
|
|
191
|
+
}
|
|
192
|
+
if (label.startsWith("https://") || label.startsWith("http://")) {
|
|
193
|
+
const cleanUrl = label.replace(/^https?:\/\//, "");
|
|
194
|
+
return cleanUrl.length > length ? cleanUrl.slice(0, length) + "..." : cleanUrl;
|
|
195
|
+
}
|
|
196
|
+
if (label.startsWith("did:")) {
|
|
197
|
+
if (label.includes("eip155:") && label.includes("|discord:")) {
|
|
198
|
+
const parts = label.split("|");
|
|
199
|
+
const ethPart = parts[0];
|
|
200
|
+
const discordPart = parts[1];
|
|
201
|
+
const addressMatch = ethPart.match(/0x[a-fA-F0-9]+/);
|
|
202
|
+
const address = addressMatch ? ellipsizeHex(addressMatch[0], 8) : ethPart;
|
|
203
|
+
return `${address} | ${discordPart}`;
|
|
204
|
+
}
|
|
205
|
+
return ellipsizeString(label, length);
|
|
206
|
+
}
|
|
207
|
+
if (label.startsWith("caip10:eip155:")) {
|
|
208
|
+
const parsedLabel = label.split(":");
|
|
209
|
+
const addressIndex = parsedLabel.findIndex((part) => part.startsWith("0x"));
|
|
210
|
+
if (addressIndex !== -1) {
|
|
211
|
+
const address = parsedLabel[addressIndex];
|
|
212
|
+
parsedLabel[addressIndex] = ellipsizeHex(address, 12);
|
|
213
|
+
}
|
|
214
|
+
return parsedLabel.join(":");
|
|
215
|
+
}
|
|
216
|
+
return label.length > length ? label.slice(0, length) + "..." : label;
|
|
217
|
+
}
|
|
218
|
+
function capitalizeFirstLetter(str) {
|
|
219
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
220
|
+
}
|
|
221
|
+
function capitalize(phrase) {
|
|
222
|
+
if (!phrase) return "";
|
|
223
|
+
return phrase.split(" ").map((word) => word ? word.charAt(0).toUpperCase() + word.slice(1) : "").join(" ");
|
|
224
|
+
}
|
|
225
|
+
function secondsToHms(seconds) {
|
|
226
|
+
seconds = Number(seconds);
|
|
227
|
+
const d = Math.floor(seconds / (3600 * 24));
|
|
228
|
+
if (d > 0) return `${d}d`;
|
|
229
|
+
const h = Math.floor(seconds / 3600);
|
|
230
|
+
if (h > 0) return `${h}h`;
|
|
231
|
+
const m = Math.floor(seconds % 3600 / 60);
|
|
232
|
+
if (m > 0) return `${m}m`;
|
|
233
|
+
const s = Math.floor(seconds % 3600 % 60);
|
|
234
|
+
if (s > 0) return `${s}s`;
|
|
235
|
+
return "";
|
|
236
|
+
}
|
|
237
|
+
function timeAgo(date, ago = true) {
|
|
238
|
+
let output;
|
|
239
|
+
if (typeof date === "string") {
|
|
240
|
+
if (date.length === 10) {
|
|
241
|
+
output = new Date(parseInt(date) * 1e3);
|
|
242
|
+
} else if (date.length === 13) {
|
|
243
|
+
output = new Date(parseInt(date));
|
|
244
|
+
} else {
|
|
245
|
+
output = new Date(date);
|
|
246
|
+
}
|
|
247
|
+
} else {
|
|
248
|
+
output = date;
|
|
249
|
+
}
|
|
250
|
+
const dateTimestamp = output.getTime() / 1e3;
|
|
251
|
+
const nowTimestamp = Date.now() / 1e3;
|
|
252
|
+
const timeGap = secondsToHms(nowTimestamp - dateTimestamp);
|
|
253
|
+
return ago ? `${timeGap} ago` : timeGap;
|
|
254
|
+
}
|
|
255
|
+
function secondsToDhms(inputVar) {
|
|
256
|
+
const inputNumber = Number(inputVar);
|
|
257
|
+
const days = Math.floor(inputNumber / (3600 * 24));
|
|
258
|
+
const hours = Math.floor(inputNumber % (3600 * 24) / 3600);
|
|
259
|
+
const minutes = Math.floor(inputNumber % (3600 * 24) % 3600 / 60);
|
|
260
|
+
const seconds = Math.floor(inputNumber % (3600 * 24) % 3600 % 60);
|
|
261
|
+
if (days) return `${days} d`;
|
|
262
|
+
if (hours) return `${hours} h`;
|
|
263
|
+
if (minutes) return `${minutes} m`;
|
|
264
|
+
if (seconds) return `${seconds} s`;
|
|
265
|
+
return "";
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { capitalize, capitalizeFirstLetter, ellipsizeHex, ellipsizeString, formatCompact, formatCryptoAmount, ipfsToHttp, secondsToDhms, secondsToHms, shortenLabel, strengthenImageUrl, timeAgo, truncateId, truncateSignificantDigits, truncateString };
|
|
269
|
+
//# sourceMappingURL=chunk-ERZSVDIB.js.map
|
|
270
|
+
//# sourceMappingURL=chunk-ERZSVDIB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/formatting.ts"],"names":["result"],"mappings":"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","file":"chunk-ERZSVDIB.js","sourcesContent":["/**\n * Formatting utilities for display purposes\n */\n\n// ============================================================================\n// Crypto Amount Formatting\n// ============================================================================\n\n/**\n * Options for formatting crypto amounts.\n */\nexport interface FormatCryptoAmountOptions {\n /** Maximum significant digits before truncation (default: 10) */\n maxSignificantDigits?: number\n /** Use compact notation for large numbers (default: false) */\n compact?: boolean\n /** Locale for number formatting (default: 'en-US') */\n locale?: string\n /** Minimum decimal places to show (default: 0) */\n minDecimals?: number\n /** Maximum decimal places to show (default: 6) */\n maxDecimals?: number\n}\n\n/**\n * Result of formatting a crypto amount.\n */\nexport interface FormattedCryptoAmount {\n /** The display string (may be truncated) */\n display: string\n /** The full value string (for tooltips) */\n fullValue: string\n /** Whether the display was truncated */\n isTruncated: boolean\n /** The numeric value (for calculations) */\n numericValue: number\n}\n\n/**\n * Formats a raw crypto amount (in wei/smallest unit) for display.\n * \n * Handles:\n * - Conversion from smallest unit to readable format\n * - Truncation of excessive precision with tooltip support\n * - Compact notation for large amounts (1.5M, 2.3B)\n * - Locale-aware number formatting\n * \n * @param value - Raw amount as string or bigint (e.g., \"1500000000000000000\" for 1.5 tokens)\n * @param decimals - Token decimals (default: 18)\n * @param options - Formatting options\n * @returns Formatted amount with display string and metadata\n * \n * @example\n * formatCryptoAmount(\"1500000000000000000\", 18)\n * // Returns: { display: \"1.5\", fullValue: \"1.5\", isTruncated: false, numericValue: 1.5 }\n * \n * formatCryptoAmount(\"12345678901234567890123\", 18, { maxSignificantDigits: 6 })\n * // Returns: { display: \"12345.6...\", fullValue: \"12345.678901234567890123\", isTruncated: true, ... }\n */\nexport function formatCryptoAmount(\n value: string | bigint,\n decimals: number = 18,\n options: FormatCryptoAmountOptions = {}\n): FormattedCryptoAmount {\n const {\n maxSignificantDigits = 10,\n compact = false,\n locale = 'en-US',\n minDecimals = 0,\n maxDecimals = 6,\n } = options\n \n // Convert to bigint if string\n const bigIntValue = typeof value === 'string' ? BigInt(value) : value\n \n // Handle zero case\n if (bigIntValue === 0n) {\n return {\n display: '0',\n fullValue: '0',\n isTruncated: false,\n numericValue: 0,\n }\n }\n \n // Convert from smallest unit to readable format\n const divisor = 10n ** BigInt(decimals)\n const wholePart = bigIntValue / divisor\n const fractionalPart = bigIntValue % divisor\n \n // Build the full decimal string\n const fractionalStr = fractionalPart.toString().padStart(decimals, '0')\n const trimmedFractional = fractionalStr.replace(/0+$/, '') // Remove trailing zeros\n \n const fullValue = trimmedFractional \n ? `${wholePart}.${trimmedFractional}`\n : wholePart.toString()\n \n const numericValue = Number(fullValue)\n \n // Handle compact notation\n if (compact && Math.abs(numericValue) >= 1000) {\n const compactDisplay = formatCompact(numericValue)\n return {\n display: compactDisplay,\n fullValue,\n isTruncated: true, // Compact is always \"truncated\" conceptually\n numericValue,\n }\n }\n \n // Step 1: Check if decimals will be truncated (for tooltip purposes)\n const originalDecimalCount = trimmedFractional.length\n const decimalsWillBeTruncated = originalDecimalCount > maxDecimals\n \n // Step 2: Apply maxDecimals limit FIRST (this is the primary display constraint)\n let decimalLimitedValue: string\n try {\n decimalLimitedValue = new Intl.NumberFormat(locale, {\n minimumFractionDigits: minDecimals,\n maximumFractionDigits: maxDecimals,\n useGrouping: false, // Disable commas for significant digit counting\n }).format(numericValue)\n } catch {\n decimalLimitedValue = fullValue\n }\n \n // Step 3: Check if significant digits truncation is STILL needed after decimal limiting\n const { truncated, isTruncated: sigDigitsTruncated } = truncateSignificantDigits(\n decimalLimitedValue, \n maxSignificantDigits\n )\n \n // isTruncated is true if EITHER decimals were limited OR significant digits were truncated\n const isTruncated = decimalsWillBeTruncated || sigDigitsTruncated\n \n // Step 4: Format for display\n let display: string\n if (sigDigitsTruncated) {\n display = truncated\n } else {\n // Re-apply locale formatting with grouping (commas) for final display\n try {\n display = new Intl.NumberFormat(locale, {\n minimumFractionDigits: minDecimals,\n maximumFractionDigits: maxDecimals,\n }).format(numericValue)\n } catch {\n display = decimalLimitedValue\n }\n }\n \n return {\n display,\n fullValue,\n isTruncated,\n numericValue,\n }\n}\n\n/**\n * Truncates a numeric string to a maximum number of significant digits.\n * Leading zeros in decimals don't count toward the limit.\n * \n * @param value - The numeric string to truncate\n * @param maxDigits - Maximum significant digits to keep\n * @returns Object with truncated string and whether truncation occurred\n * \n * @example\n * truncateSignificantDigits(\"123456789012\", 10)\n * // Returns: { truncated: \"1234567890…\", isTruncated: true }\n * \n * truncateSignificantDigits(\"0.0000123456789\", 10)\n * // Returns: { truncated: \"0.0000123456789\", isTruncated: false }\n * // (leading zeros don't count, only 9 significant digits)\n */\nexport function truncateSignificantDigits(\n value: string,\n maxDigits: number\n): { truncated: string; isTruncated: boolean } {\n if (!value) {\n return { truncated: '0', isTruncated: false }\n }\n \n // Handle negative numbers\n const isNegative = value.startsWith('-')\n const absValue = isNegative ? value.slice(1) : value\n \n // Split into whole and fractional parts\n const [wholePart, fractionalPart] = absValue.split('.')\n \n // Count significant digits (skip leading zeros in fractional part)\n let significantCount = 0\n let truncatedWhole = ''\n let truncatedFractional = ''\n let isTruncated = false\n \n // Process whole part (all digits are significant unless the whole thing is \"0\")\n if (wholePart !== '0') {\n for (const char of wholePart) {\n if (significantCount >= maxDigits) {\n isTruncated = true\n break\n }\n truncatedWhole += char\n significantCount++\n }\n \n // If we truncated in whole part, we're done (no fractional)\n if (isTruncated) {\n const result = isNegative ? `-${truncatedWhole}` : truncatedWhole\n return { truncated: `${result}…`, isTruncated: true }\n }\n } else {\n truncatedWhole = '0'\n }\n \n // Process fractional part if exists\n if (fractionalPart) {\n let foundNonZero = wholePart !== '0' // If whole is non-zero, all fractional digits count\n \n for (const char of fractionalPart) {\n if (!foundNonZero && char === '0') {\n // Leading zeros in fractional don't count\n truncatedFractional += char\n continue\n }\n \n foundNonZero = true\n \n if (significantCount >= maxDigits) {\n isTruncated = true\n break\n }\n \n truncatedFractional += char\n significantCount++\n }\n }\n \n // Build final result\n let result = truncatedWhole\n if (truncatedFractional) {\n result += `.${truncatedFractional}`\n }\n \n if (isNegative) {\n result = `-${result}`\n }\n \n return { truncated: result, isTruncated }\n}\n\n/**\n * Truncates an address or ID for display.\n * Shows first N characters after optional prefix.\n *\n * @param value - The full address or ID string\n * @param chars - Number of characters to show (default: 5)\n * @param prefix - Prefix to skip (default: '0x')\n * @returns Truncated string\n *\n * @example\n * truncateId('0x123456789098765432') // Returns: '12345'\n * truncateId('0x123456789098765432', 8) // Returns: '12345678'\n */\nexport function truncateId(\n value: string,\n chars: number = 5,\n prefix: string = '0x'\n): string {\n if (!value) return ''\n const start = value.startsWith(prefix) ? prefix.length : 0\n return value.slice(start, start + chars)\n}\n\n/**\n * Converts an IPFS URI to an HTTP gateway URL.\n *\n * @param uri - The IPFS URI (ipfs://... format)\n * @param gateway - The gateway to use (default: ipfs.io)\n * @returns HTTP URL for the content\n *\n * @example\n * ipfsToHttp('ipfs://QmHash123') // Returns: 'https://ipfs.io/ipfs/QmHash123'\n */\nexport function ipfsToHttp(\n uri: string | undefined | null,\n gateway: string = 'https://ipfs.io/ipfs/'\n): string | undefined {\n if (!uri) return undefined\n if (uri.startsWith('ipfs://')) {\n return uri.replace('ipfs://', gateway)\n }\n return uri\n}\n\n/**\n * Formats a number with compact notation (K, M, B, etc.)\n *\n * @param value - The number to format\n * @param decimals - Maximum decimal places (default: 2)\n * @returns Formatted string\n *\n * @example\n * formatCompact(1500) // Returns: '1.5K'\n * formatCompact(2500000) // Returns: '2.5M'\n */\nexport function formatCompact(\n value: number,\n decimals: number = 2\n): string {\n if (value === 0) return '0'\n \n const formatter = new Intl.NumberFormat('en-US', {\n notation: 'compact',\n maximumFractionDigits: decimals,\n })\n \n return formatter.format(value)\n}\n\n/**\n * Strengthens/normalizes an image URL to ensure it's displayable.\n * Handles IPFS URIs, raw IPFS hashes, and validates HTTP URLs.\n *\n * @param url - The image URL to process\n * @returns A normalized HTTP(S) URL\n *\n * @example\n * strengthenImageUrl('ipfs://QmHash123') // Returns: 'https://ipfs.io/ipfs/QmHash123'\n * strengthenImageUrl('QmHash123') // Returns: 'https://ipfs.io/ipfs/QmHash123'\n * strengthenImageUrl('https://example.com/img.png') // Returns: 'https://example.com/img.png'\n */\nexport function strengthenImageUrl(url: string = ''): string {\n // Validate input\n if (!url || typeof url !== 'string' || url.trim() === '') {\n return url\n }\n \n const trimmedUrl = url.trim()\n \n // Handle IPFS protocol\n if (trimmedUrl.startsWith('ipfs://')) {\n return trimmedUrl.replace('ipfs://', 'https://ipfs.io/ipfs/')\n }\n \n // Already a valid HTTP(S) URL\n if (trimmedUrl.startsWith('https://') || trimmedUrl.startsWith('http://')) {\n return trimmedUrl\n }\n \n // Handle IPFS hashes without protocol (Qm... or baf...)\n if (trimmedUrl.startsWith('Qm') || trimmedUrl.startsWith('baf')) {\n return 'https://ipfs.io/ipfs/' + trimmedUrl\n }\n \n return trimmedUrl\n}\n\n// ============================================================================\n// String Manipulation Utilities\n// ============================================================================\n\n/**\n * Ellipsizes a string by showing characters from start and end with '...' in middle.\n *\n * @param str - The string to ellipsize\n * @param length - Total visible characters (split between start and end)\n * @returns Ellipsized string or original if shorter than length\n *\n * @example\n * ellipsizeString('0x1234567890abcdef', 8) // Returns: '0x12...cdef'\n */\nexport function ellipsizeString(\n str: string | undefined | null,\n length: number\n): string {\n if (!str) return ''\n if (str.length < length) return str\n const first = str.substring(0, length / 2)\n const second = str.substring(str.length - length / 2, str.length)\n return [first, second].join('...')\n}\n\n/**\n * Ellipsizes a hex string (0x-prefixed) preserving the prefix.\n *\n * @param hex - The hex string to ellipsize (must start with 0x)\n * @param length - Visible characters in the payload (default: 12)\n * @returns Ellipsized hex string\n * @throws Error if hex doesn't start with 0x\n *\n * @example\n * ellipsizeHex('0x1234567890abcdef1234567890abcdef') // Returns: '0x123456...abcdef'\n */\nexport function ellipsizeHex(hex: string, length: number = 12): string {\n if (!hex || !hex.startsWith('0x')) throw new Error('Invalid hex')\n const prefix = '0x'\n const payload = hex.replace('0x', '')\n const shortenedPayload = ellipsizeString(payload, length)\n return `${prefix}${shortenedPayload}`\n}\n\n/**\n * Truncates a string to a specified length, adding '...' at the end.\n *\n * @param str - The string to truncate\n * @param length - Maximum length before truncation\n * @returns Truncated string with '...' or original if shorter\n *\n * @example\n * truncateString('Hello World', 5) // Returns: 'Hello...'\n */\nexport function truncateString(\n str: string | undefined | null = '',\n length: number\n): string {\n if (!str) return ''\n if (str.length < length) return str\n return `${str.substring(0, length)}...`\n}\n\n/**\n * Intelligently shortens a label based on its type (hex, URL, IPFS, DID, etc.)\n * This is the main utility for displaying atom/entity labels in the UI.\n *\n * @param label - The label to shorten\n * @param length - Maximum length for generic strings (default: 50)\n * @returns Shortened label appropriate for its type\n *\n * @example\n * shortenLabel('0x1234567890abcdef...') // Returns: '0x1234...cdef'\n * shortenLabel('https://example.com/page') // Returns: 'example.com/page'\n * shortenLabel('ipfs://bafkre...') // Returns: 'bafkre...xyz'\n */\nexport function shortenLabel(\n label: string | null | undefined,\n length: number = 50\n): string {\n if (!label) return ''\n\n // Handle hex addresses\n if (label.startsWith('0x')) {\n return ellipsizeHex(label, 12)\n }\n\n // Handle IPFS\n if (label.startsWith('bafkre')) {\n return ellipsizeString(label, 12)\n }\n if (label.startsWith('ipfs://bafkre')) {\n return ellipsizeString(label.replace('ipfs://', ''), 12)\n }\n\n // Handle URLs - remove protocol and truncate if needed\n if (label.startsWith('https://') || label.startsWith('http://')) {\n const cleanUrl = label.replace(/^https?:\\/\\//, '')\n return cleanUrl.length > length ? cleanUrl.slice(0, length) + '...' : cleanUrl\n }\n\n // Handle DID URIs\n if (label.startsWith('did:')) {\n // Extract meaningful parts of DID\n if (label.includes('eip155:') && label.includes('|discord:')) {\n const parts = label.split('|')\n const ethPart = parts[0] // did:eip155:84532:0x...\n const discordPart = parts[1] // discord:391378559945670667\n\n // Extract just the address from the first part\n const addressMatch = ethPart.match(/0x[a-fA-F0-9]+/)\n const address = addressMatch ? ellipsizeHex(addressMatch[0], 8) : ethPart\n\n return `${address} | ${discordPart}`\n }\n\n // Fallback for other DID formats\n return ellipsizeString(label, length)\n }\n\n // Handle CAIP-10 identifiers\n if (label.startsWith('caip10:eip155:')) {\n const parsedLabel = label.split(':')\n const addressIndex = parsedLabel.findIndex(part => part.startsWith('0x'))\n if (addressIndex !== -1) {\n const address = parsedLabel[addressIndex]\n parsedLabel[addressIndex] = ellipsizeHex(address, 12)\n }\n return parsedLabel.join(':')\n }\n\n // Default: truncate to specified length\n return label.length > length ? label.slice(0, length) + '...' : label\n}\n\n// ============================================================================\n// Capitalization Utilities\n// ============================================================================\n\n/**\n * Capitalizes the first letter of a string.\n *\n * @param str - The string to capitalize\n * @returns String with first letter capitalized\n *\n * @example\n * capitalizeFirstLetter('hello') // Returns: 'Hello'\n */\nexport function capitalizeFirstLetter(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n\n/**\n * Capitalizes the first letter of each word in a phrase.\n *\n * @param phrase - The phrase to capitalize\n * @returns Phrase with each word capitalized\n *\n * @example\n * capitalize('hello world') // Returns: 'Hello World'\n */\nexport function capitalize(phrase: string): string {\n if (!phrase) return ''\n return phrase\n .split(' ')\n .map(word => word ? word.charAt(0).toUpperCase() + word.slice(1) : '')\n .join(' ')\n}\n\n// ============================================================================\n// Time Utilities\n// ============================================================================\n\n/**\n * Converts seconds to a compact human-readable format (e.g., \"5d\", \"3h\", \"10m\").\n *\n * @param seconds - Number of seconds\n * @returns Compact time string\n *\n * @example\n * secondsToHms(3700) // Returns: '1h'\n * secondsToHms(90) // Returns: '1m'\n */\nexport function secondsToHms(seconds: number): string {\n seconds = Number(seconds)\n const d = Math.floor(seconds / (3600 * 24))\n if (d > 0) return `${d}d`\n const h = Math.floor(seconds / 3600)\n if (h > 0) return `${h}h`\n const m = Math.floor((seconds % 3600) / 60)\n if (m > 0) return `${m}m`\n const s = Math.floor((seconds % 3600) % 60)\n if (s > 0) return `${s}s`\n return ''\n}\n\n/**\n * Formats a date as a human-readable \"time ago\" string.\n * Handles various date input formats including Unix timestamps.\n *\n * @param date - Date object, ISO string, or Unix timestamp (10 or 13 digits)\n * @param ago - Whether to append \"ago\" suffix (default: true)\n * @returns Human-readable time difference string\n *\n * @example\n * timeAgo(new Date(Date.now() - 3600000)) // Returns: '1h ago'\n * timeAgo('1703001600', false) // Returns: '5d'\n */\nexport function timeAgo(date: Date | string, ago: boolean = true): string {\n let output: Date\n if (typeof date === 'string') {\n if (date.length === 10) {\n // Unix timestamp in seconds\n output = new Date(parseInt(date) * 1000)\n } else if (date.length === 13) {\n // Unix timestamp in milliseconds\n output = new Date(parseInt(date))\n } else {\n // ISO string or other format\n output = new Date(date)\n }\n } else {\n output = date\n }\n \n const dateTimestamp = output.getTime() / 1000\n const nowTimestamp = Date.now() / 1000\n const timeGap = secondsToHms(nowTimestamp - dateTimestamp)\n \n return ago ? `${timeGap} ago` : timeGap\n}\n\n/**\n * Converts seconds to a descriptive duration string (e.g., \"5 d\", \"3 h\").\n *\n * @param inputVar - Seconds as number or string\n * @returns Duration string with space before unit\n *\n * @example\n * secondsToDhms(90000) // Returns: '1 d'\n */\nexport function secondsToDhms(inputVar: string | number): string {\n const inputNumber = Number(inputVar)\n const days = Math.floor(inputNumber / (3600 * 24))\n const hours = Math.floor((inputNumber % (3600 * 24)) / 3600)\n const minutes = Math.floor(((inputNumber % (3600 * 24)) % 3600) / 60)\n const seconds = Math.floor(((inputNumber % (3600 * 24)) % 3600) % 60)\n\n if (days) return `${days} d`\n if (hours) return `${hours} h`\n if (minutes) return `${minutes} m`\n if (seconds) return `${seconds} s`\n return ''\n}\n\n"]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
// src/utils/atom.ts
|
|
4
|
+
var ATOM_TYPES = [
|
|
5
|
+
"Account",
|
|
6
|
+
"Book",
|
|
7
|
+
"ByteObject",
|
|
8
|
+
"Caip10",
|
|
9
|
+
"FollowAction",
|
|
10
|
+
"JsonObject",
|
|
11
|
+
"Keywords",
|
|
12
|
+
"LikeAction",
|
|
13
|
+
"Organization",
|
|
14
|
+
"OrganizationPredicate",
|
|
15
|
+
"Person",
|
|
16
|
+
"PersonPredicate",
|
|
17
|
+
"TextObject",
|
|
18
|
+
"Thing",
|
|
19
|
+
"ThingPredicate",
|
|
20
|
+
"Unknown"
|
|
21
|
+
];
|
|
22
|
+
function detectTypeFromData(data) {
|
|
23
|
+
if (!data) return void 0;
|
|
24
|
+
const lowered = data.toLowerCase();
|
|
25
|
+
const trimmed = data.trim();
|
|
26
|
+
if (data.startsWith("0x") && data.length === 42) {
|
|
27
|
+
return "Account";
|
|
28
|
+
}
|
|
29
|
+
if (lowered.startsWith("caip10:") || lowered.includes("eip155:")) {
|
|
30
|
+
return "Caip10";
|
|
31
|
+
}
|
|
32
|
+
if (lowered.includes("schema.org/")) {
|
|
33
|
+
if (lowered.includes("person")) return "PersonPredicate";
|
|
34
|
+
if (lowered.includes("organization")) return "OrganizationPredicate";
|
|
35
|
+
if (lowered.includes("thing")) return "ThingPredicate";
|
|
36
|
+
if (lowered.includes("likeaction")) return "LikeAction";
|
|
37
|
+
if (lowered.includes("followaction")) return "FollowAction";
|
|
38
|
+
}
|
|
39
|
+
if (data.startsWith("ipfs://")) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
const firstChar = trimmed[0];
|
|
46
|
+
if (firstChar === "{" || firstChar === "[") {
|
|
47
|
+
return void 0;
|
|
48
|
+
}
|
|
49
|
+
if (trimmed.length > 0) {
|
|
50
|
+
return "TextObject";
|
|
51
|
+
}
|
|
52
|
+
return void 0;
|
|
53
|
+
}
|
|
54
|
+
function getAtomType(atom) {
|
|
55
|
+
console.log("getAtomType", atom);
|
|
56
|
+
if (!atom) return void 0;
|
|
57
|
+
if (atom.type && typeof atom.type === "string") {
|
|
58
|
+
return atom.type;
|
|
59
|
+
}
|
|
60
|
+
if (atom.atomType && typeof atom.atomType === "string") {
|
|
61
|
+
return atom.atomType;
|
|
62
|
+
}
|
|
63
|
+
if (atom.value) {
|
|
64
|
+
if (atom.value.person) return "Person";
|
|
65
|
+
if (atom.value.organization) return "Organization";
|
|
66
|
+
if (atom.value.book) return "Book";
|
|
67
|
+
if (atom.value.thing) return "Thing";
|
|
68
|
+
if (atom.value.account) return "Account";
|
|
69
|
+
if (atom.value.text_object) return "TextObject";
|
|
70
|
+
if (atom.value.json_object) return "JsonObject";
|
|
71
|
+
if (atom.value.byte_object) return "ByteObject";
|
|
72
|
+
}
|
|
73
|
+
if (atom.data && typeof atom.data === "string") {
|
|
74
|
+
return detectTypeFromData(atom.data);
|
|
75
|
+
}
|
|
76
|
+
return void 0;
|
|
77
|
+
}
|
|
78
|
+
function formatAtomType(type) {
|
|
79
|
+
console.log("formatAtomType", type);
|
|
80
|
+
if (!type) return "";
|
|
81
|
+
if (type.endsWith("Object")) {
|
|
82
|
+
return type.replace("Object", "");
|
|
83
|
+
}
|
|
84
|
+
if (type.endsWith("Predicate")) {
|
|
85
|
+
const base = type.replace("Predicate", "");
|
|
86
|
+
return `${base} Predicate`;
|
|
87
|
+
}
|
|
88
|
+
if (type.endsWith("Action")) {
|
|
89
|
+
return type.replace("Action", "");
|
|
90
|
+
}
|
|
91
|
+
return type;
|
|
92
|
+
}
|
|
93
|
+
function isPredicateType(type) {
|
|
94
|
+
if (!type) return false;
|
|
95
|
+
return type.endsWith("Predicate") || type === "LikeAction" || type === "FollowAction";
|
|
96
|
+
}
|
|
97
|
+
function isEntityType(type) {
|
|
98
|
+
if (!type) return false;
|
|
99
|
+
return ["Person", "Organization", "Thing", "Book"].includes(type);
|
|
100
|
+
}
|
|
101
|
+
function isRawDataType(type) {
|
|
102
|
+
if (!type) return false;
|
|
103
|
+
return ["TextObject", "JsonObject", "ByteObject"].includes(type);
|
|
104
|
+
}
|
|
105
|
+
function isPlainTextType(type) {
|
|
106
|
+
return type === "TextObject";
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/utils/search/ranking.ts
|
|
110
|
+
function calculateMatchScore(text, searchTerm) {
|
|
111
|
+
if (!text || !searchTerm) return 0;
|
|
112
|
+
const lowerText = text.toLowerCase();
|
|
113
|
+
const lowerSearch = searchTerm.toLowerCase();
|
|
114
|
+
if (lowerText === lowerSearch) return 100;
|
|
115
|
+
if (lowerText.startsWith(lowerSearch)) return 90;
|
|
116
|
+
if (lowerText.includes(lowerSearch)) {
|
|
117
|
+
const position = lowerText.indexOf(lowerSearch);
|
|
118
|
+
return 50 - position * 0.5;
|
|
119
|
+
}
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
function rankAtoms(atoms, searchTerm) {
|
|
123
|
+
const rankedAtoms = atoms.map((atom) => {
|
|
124
|
+
let matchScore = 0;
|
|
125
|
+
const isExactTermIdMatch = atom.term_id?.toLowerCase() === searchTerm.toLowerCase();
|
|
126
|
+
if (isExactTermIdMatch) {
|
|
127
|
+
matchScore = 1e3;
|
|
128
|
+
} else {
|
|
129
|
+
matchScore += calculateMatchScore(atom.label || "", searchTerm) * 3;
|
|
130
|
+
const name = atom.value?.thing?.name || atom.value?.person?.name || atom.value?.organization?.name || "";
|
|
131
|
+
matchScore += calculateMatchScore(name, searchTerm) * 2;
|
|
132
|
+
if (atom.data) {
|
|
133
|
+
matchScore += calculateMatchScore(atom.data, searchTerm) * 2.5;
|
|
134
|
+
}
|
|
135
|
+
const description = atom.value?.thing?.description || atom.value?.person?.description || atom.value?.organization?.description || "";
|
|
136
|
+
matchScore += calculateMatchScore(description, searchTerm) * 0.5;
|
|
137
|
+
}
|
|
138
|
+
const marketCap = atom.term?.vaults?.[0]?.market_cap || "0";
|
|
139
|
+
const stakeScore = Number(marketCap);
|
|
140
|
+
const isExactMatch = atom.label?.toLowerCase() === searchTerm.toLowerCase() || isExactTermIdMatch;
|
|
141
|
+
return {
|
|
142
|
+
...atom,
|
|
143
|
+
matchScore,
|
|
144
|
+
stakeScore,
|
|
145
|
+
isExactMatch,
|
|
146
|
+
isExactTermIdMatch,
|
|
147
|
+
// Combined score for display/debugging
|
|
148
|
+
totalScore: matchScore + Math.log10(stakeScore + 1)
|
|
149
|
+
};
|
|
150
|
+
}).filter((atom) => atom.isExactTermIdMatch || atom.matchScore > 10).sort((a, b) => {
|
|
151
|
+
if (a.isExactTermIdMatch && !b.isExactTermIdMatch) return -1;
|
|
152
|
+
if (!a.isExactTermIdMatch && b.isExactTermIdMatch) return 1;
|
|
153
|
+
if (a.stakeScore !== b.stakeScore) {
|
|
154
|
+
return b.stakeScore - a.stakeScore;
|
|
155
|
+
}
|
|
156
|
+
const aMatchScore = a.matchScore + (a.isExactMatch ? 50 : 0);
|
|
157
|
+
const bMatchScore = b.matchScore + (b.isExactMatch ? 50 : 0);
|
|
158
|
+
return bMatchScore - aMatchScore;
|
|
159
|
+
});
|
|
160
|
+
return rankedAtoms;
|
|
161
|
+
}
|
|
162
|
+
function getAtomDisplayName(atom) {
|
|
163
|
+
return atom.value?.thing?.name || atom.value?.person?.name || atom.value?.organization?.name || atom.label || atom.data || "";
|
|
164
|
+
}
|
|
165
|
+
function getAtomDescription(atom) {
|
|
166
|
+
return atom.value?.thing?.description || atom.value?.person?.description || atom.value?.organization?.description || "";
|
|
167
|
+
}
|
|
168
|
+
function getAtomImage(atom) {
|
|
169
|
+
const image = atom.image || atom.value?.thing?.image || atom.value?.person?.image || atom.value?.organization?.image || "";
|
|
170
|
+
if (image.startsWith("ipfs://")) {
|
|
171
|
+
return image.replace("ipfs://", "https://ipfs.io/ipfs/");
|
|
172
|
+
}
|
|
173
|
+
return image;
|
|
174
|
+
}
|
|
175
|
+
function formatStake(marketCap) {
|
|
176
|
+
if (!marketCap) return "0";
|
|
177
|
+
const trustValue = Number(BigInt(marketCap)) / 1e18;
|
|
178
|
+
if (trustValue === 0) return "0";
|
|
179
|
+
const formatWithDecimals = (value, decimals = 2) => {
|
|
180
|
+
return value.toFixed(decimals).replace(/\.?0+$/, "");
|
|
181
|
+
};
|
|
182
|
+
if (trustValue >= 1e9) {
|
|
183
|
+
return `${formatWithDecimals(trustValue / 1e9, 2)}B`;
|
|
184
|
+
} else if (trustValue >= 1e6) {
|
|
185
|
+
return `${formatWithDecimals(trustValue / 1e6, 2)}M`;
|
|
186
|
+
} else if (trustValue >= 1e3) {
|
|
187
|
+
return `${formatWithDecimals(trustValue / 1e3, 2)}K`;
|
|
188
|
+
} else {
|
|
189
|
+
return formatWithDecimals(trustValue, 2);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function highlightMatch(text, searchTerm) {
|
|
193
|
+
if (!text || !searchTerm) return text;
|
|
194
|
+
const regex = new RegExp(`(${escapeRegExp(searchTerm)})`, "gi");
|
|
195
|
+
const parts = text.split(regex);
|
|
196
|
+
return parts.map(
|
|
197
|
+
(part, i) => part.toLowerCase() === searchTerm.toLowerCase() ? /* @__PURE__ */ jsx("strong", { className: "bg-yellow-500/20 text-yellow-500", children: part }, i) : part
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
function escapeRegExp(string) {
|
|
201
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
202
|
+
}
|
|
203
|
+
function formatTermId(termId) {
|
|
204
|
+
if (!termId) return "";
|
|
205
|
+
if (termId.startsWith("0x")) {
|
|
206
|
+
return termId.slice(2, 7);
|
|
207
|
+
}
|
|
208
|
+
return termId.slice(0, 5);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { ATOM_TYPES, calculateMatchScore, formatAtomType, formatStake, formatTermId, getAtomDescription, getAtomDisplayName, getAtomImage, getAtomType, highlightMatch, isEntityType, isPlainTextType, isPredicateType, isRawDataType, rankAtoms };
|
|
212
|
+
//# sourceMappingURL=chunk-H4RMZQ2Z.js.map
|
|
213
|
+
//# sourceMappingURL=chunk-H4RMZQ2Z.js.map
|