@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.
Files changed (40) hide show
  1. package/README.md +224 -0
  2. package/dist/chunk-2RGM3KJL.js +351 -0
  3. package/dist/chunk-2RGM3KJL.js.map +1 -0
  4. package/dist/chunk-E5TTKYNS.js +55 -0
  5. package/dist/chunk-E5TTKYNS.js.map +1 -0
  6. package/dist/chunk-ERZSVDIB.js +270 -0
  7. package/dist/chunk-ERZSVDIB.js.map +1 -0
  8. package/dist/chunk-H4RMZQ2Z.js +213 -0
  9. package/dist/chunk-H4RMZQ2Z.js.map +1 -0
  10. package/dist/chunk-K7EIJSYQ.js +3 -0
  11. package/dist/chunk-K7EIJSYQ.js.map +1 -0
  12. package/dist/chunk-OJF67RNM.js +3 -0
  13. package/dist/chunk-OJF67RNM.js.map +1 -0
  14. package/dist/chunk-P5E2XNDI.js +2758 -0
  15. package/dist/chunk-P5E2XNDI.js.map +1 -0
  16. package/dist/chunk-T2XWV636.js +137 -0
  17. package/dist/chunk-T2XWV636.js.map +1 -0
  18. package/dist/chunk-VIRNUAYY.js +11 -0
  19. package/dist/chunk-VIRNUAYY.js.map +1 -0
  20. package/dist/components/index.d.ts +277 -0
  21. package/dist/components/index.js +6 -0
  22. package/dist/components/index.js.map +1 -0
  23. package/dist/components/ui/index.d.ts +396 -0
  24. package/dist/components/ui/index.js +6 -0
  25. package/dist/components/ui/index.js.map +1 -0
  26. package/dist/hooks/index.d.ts +27 -0
  27. package/dist/hooks/index.js +4 -0
  28. package/dist/hooks/index.js.map +1 -0
  29. package/dist/index.d.ts +34 -0
  30. package/dist/index.js +11 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/toast-D090UYOq.d.ts +19 -0
  33. package/dist/types/index.d.ts +2 -0
  34. package/dist/types/index.js +3 -0
  35. package/dist/types/index.js.map +1 -0
  36. package/dist/utils/index.d.ts +573 -0
  37. package/dist/utils/index.js +5 -0
  38. package/dist/utils/index.js.map +1 -0
  39. package/package.json +107 -0
  40. package/tailwind.config.js +96 -0
package/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # @revel8/core
2
+
3
+ Shared components, utilities, and types for Revel8 applications.
4
+
5
+ ## Overview
6
+
7
+ This package provides common functionality shared between:
8
+ - **revel8-explorer** - Web application for exploring the Intuition knowledge graph
9
+ - **intuition-extension** - Browser extension for Intuition insights
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ # Using pnpm (recommended)
15
+ pnpm add @revel8/core
16
+
17
+ # Using npm
18
+ npm install @revel8/core
19
+
20
+ # For local development (link)
21
+ cd revel8-core && pnpm link
22
+ cd ../revel8-explorer && pnpm link @revel8/core
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Utilities
28
+
29
+ ```typescript
30
+ import { cn, truncateId, ipfsToHttp, formatCompact } from '@revel8/core'
31
+
32
+ // Merge Tailwind classes
33
+ cn('px-4 py-2', isActive && 'bg-blue-500')
34
+
35
+ // Truncate atom/triple IDs for display
36
+ truncateId('0x123456789098765432') // '12345'
37
+
38
+ // Convert IPFS URIs to HTTP
39
+ ipfsToHttp('ipfs://QmHash123') // 'https://ipfs.io/ipfs/QmHash123'
40
+
41
+ // Format large numbers
42
+ formatCompact(1500000) // '1.5M'
43
+ ```
44
+
45
+ ### Components
46
+
47
+ ```typescript
48
+ // UI primitives
49
+ import { Button, Card, Tooltip } from '@revel8/core'
50
+
51
+ // Display components
52
+ import { CryptoAmount, AtomIcon, IpfsImage } from '@revel8/core'
53
+ ```
54
+
55
+ ### CryptoAmount Component
56
+
57
+ A unified component for displaying cryptocurrency amounts with optional fiat conversion.
58
+
59
+ ```tsx
60
+ import { CryptoAmount, createCryptoAmountRateProps } from '@revel8/core'
61
+
62
+ // Basic usage - crypto on top, fiat below
63
+ <CryptoAmount
64
+ value="1500000000000000000" // 1.5 tokens in wei
65
+ symbol="TRUST"
66
+ exchangeRate={0.42} // 1 TRUST = $0.42
67
+ currencyCode="usd"
68
+ />
69
+ // Renders:
70
+ // 1.5 TRUST
71
+ // $0.63
72
+
73
+ // Inline variant
74
+ <CryptoAmount
75
+ value="1500000000000000000"
76
+ symbol="TRUST"
77
+ exchangeRate={0.42}
78
+ variant="inline"
79
+ />
80
+ // Renders: 1.5 TRUST (~$0.63)
81
+
82
+ // Compact variant (for large amounts)
83
+ <CryptoAmount
84
+ value="1500000000000000000000000" // 1.5M tokens
85
+ symbol="TRUST"
86
+ variant="compact"
87
+ />
88
+ // Renders: 1.5M TRUST
89
+
90
+ // Crypto-only (no fiat)
91
+ <CryptoAmount
92
+ value="1500000000000000000"
93
+ symbol="TRUST"
94
+ variant="crypto-only"
95
+ />
96
+ // Renders: 1.5 TRUST
97
+
98
+ // Hook wrapper pattern for your app:
99
+ function useCryptoAmountProps() {
100
+ const { data } = useExchangeRates()
101
+ const { selectedCurrency } = useCurrency()
102
+ return createCryptoAmountRateProps(data?.rate, selectedCurrency)
103
+ }
104
+
105
+ // Then in components:
106
+ const rateProps = useCryptoAmountProps()
107
+ <CryptoAmount value={stake} symbol="TRUST" {...rateProps} />
108
+ ```
109
+
110
+ **Props:**
111
+ | Prop | Type | Default | Description |
112
+ |------|------|---------|-------------|
113
+ | `value` | `string \| bigint` | required | Raw amount in smallest unit (wei) |
114
+ | `symbol` | `string` | required | Token symbol (e.g., 'TRUST') |
115
+ | `decimals` | `number` | `18` | Token decimals |
116
+ | `exchangeRate` | `number \| null` | - | Fiat conversion rate (hides fiat if missing) |
117
+ | `currencyCode` | `string` | `'USD'` | Fiat currency code for formatting |
118
+ | `variant` | `'default' \| 'inline' \| 'crypto-only' \| 'compact'` | `'default'` | Display variant |
119
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Size variant |
120
+ | `maxSignificantDigits` | `number` | `10` | Digits before truncation (shows tooltip) |
121
+
122
+ ### Tailwind Configuration
123
+
124
+ Extend the shared Tailwind config in your app:
125
+
126
+ ```javascript
127
+ // tailwind.config.js
128
+ const sharedConfig = require('@revel8/core/tailwind.config')
129
+
130
+ module.exports = {
131
+ presets: [sharedConfig],
132
+ content: [
133
+ './src/**/*.{ts,tsx}',
134
+ './node_modules/@revel8/core/dist/**/*.js',
135
+ ],
136
+ // Your app-specific extensions...
137
+ }
138
+ ```
139
+
140
+ ## Development
141
+
142
+ ```bash
143
+ # Install dependencies
144
+ pnpm install
145
+
146
+ # Build the package
147
+ pnpm build
148
+
149
+ # Watch mode for development
150
+ pnpm dev
151
+
152
+ # Type check
153
+ pnpm typecheck
154
+ ```
155
+
156
+ ## Package Structure
157
+
158
+ ```
159
+ revel8-core/
160
+ ├── src/
161
+ │ ├── index.ts # Main entry point
162
+ │ ├── components/
163
+ │ │ ├── ui/ # shadcn/ui primitives
164
+ │ │ │ └── index.ts
165
+ │ │ └── display/ # Intuition display components
166
+ │ │ └── index.ts
167
+ │ ├── utils/
168
+ │ │ ├── index.ts
169
+ │ │ ├── cn.ts # Class name utility
170
+ │ │ └── formatting.ts # Formatting helpers
171
+ │ └── types/
172
+ │ └── index.ts # Shared TypeScript types
173
+ ├── tailwind.config.js # Shared Tailwind configuration
174
+ ├── tsconfig.json
175
+ ├── tsup.config.ts # Build configuration
176
+ └── package.json
177
+ ```
178
+
179
+ ## Exports
180
+
181
+ The package provides multiple entry points:
182
+
183
+ | Import Path | Contents |
184
+ |-------------|----------|
185
+ | `@revel8/core` | Everything (utils, components, types) |
186
+ | `@revel8/core/utils` | Utility functions only |
187
+ | `@revel8/core/components/ui` | UI primitives |
188
+ | `@revel8/core/components/display` | Display components |
189
+
190
+ ## Peer Dependencies
191
+
192
+ This package requires the following peer dependencies:
193
+
194
+ | Package | Version |
195
+ |---------|---------|
196
+ | `react` | ^18.0.0 \|\| ^19.0.0 |
197
+ | `react-dom` | ^18.0.0 \|\| ^19.0.0 |
198
+ | `tailwindcss` | ^3.0.0 \|\| ^4.0.0 (optional) |
199
+
200
+ ## Adding New Components
201
+
202
+ 1. Create the component in the appropriate directory
203
+ 2. Export it from the directory's `index.ts`
204
+ 3. Rebuild the package: `pnpm build`
205
+ 4. Update consuming apps to use the new component
206
+
207
+ ### Migration Checklist
208
+
209
+ When migrating a component from a consuming app:
210
+
211
+ - [ ] Copy component to `src/components/`
212
+ - [ ] Update imports to use relative paths (no `@/` or `~/` aliases)
213
+ - [ ] Ensure it only depends on:
214
+ - Other `@revel8/core` exports
215
+ - Peer dependencies (React, etc.)
216
+ - Direct dependencies listed in package.json
217
+ - [ ] Add export to the appropriate barrel file
218
+ - [ ] Test in both consuming apps
219
+ - [ ] Remove original from consuming apps
220
+
221
+ ## License
222
+
223
+ ISC © Kylan Hurt
224
+
@@ -0,0 +1,351 @@
1
+ import { strengthenImageUrl, ipfsToHttp, formatCryptoAmount } from './chunk-ERZSVDIB.js';
2
+ import { Tooltip as Tooltip$1, TooltipTrigger, TooltipContent } from './chunk-E5TTKYNS.js';
3
+ import { cn } from './chunk-VIRNUAYY.js';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+ import * as React2 from 'react';
6
+ import { useState } from 'react';
7
+ import { ResponsiveContainer, BarChart, XAxis, YAxis, Bar, AreaChart, CartesianGrid, Tooltip, Area } from 'recharts';
8
+
9
+ var AtomIcon = ({ ...props }) => {
10
+ return /* @__PURE__ */ jsxs(
11
+ "svg",
12
+ {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ width: "24",
15
+ height: "24",
16
+ viewBox: "0 0 24 24",
17
+ fill: "none",
18
+ stroke: "rgba(255,255,255,0.6)",
19
+ "stroke-width": "1.5",
20
+ "stroke-linecap": "round",
21
+ "stroke-linejoin": "round",
22
+ className: "lucide lucide-atom",
23
+ ...props,
24
+ children: [
25
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1" }),
26
+ /* @__PURE__ */ jsx("path", { d: "M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z" }),
27
+ /* @__PURE__ */ jsx("path", { d: "M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z" })
28
+ ]
29
+ }
30
+ );
31
+ };
32
+ var UnknownImage = ({
33
+ asLink = false,
34
+ src,
35
+ ...props
36
+ }) => {
37
+ if (!src) return null;
38
+ const [numberOfErrors, setNumberOfErrors] = useState(0);
39
+ const onImageError = (e, finalSrc2) => {
40
+ setNumberOfErrors(numberOfErrors + 1);
41
+ if (typeof window !== "undefined" && window.__DEV__) {
42
+ console.log("UnknownImage error:", e.currentTarget.src, finalSrc2);
43
+ }
44
+ };
45
+ const finalSrc = strengthenImageUrl(src);
46
+ const img = /* @__PURE__ */ jsx("img", { src: finalSrc, onError: (e) => onImageError(e, finalSrc), ...props });
47
+ if (asLink) {
48
+ return /* @__PURE__ */ jsx("a", { href: finalSrc, target: "_blank", rel: "noopener noreferrer", children: img });
49
+ }
50
+ return img;
51
+ };
52
+ function LoadingDots({
53
+ transitionDuration = 300,
54
+ isVisible = true,
55
+ className = ""
56
+ }) {
57
+ return /* @__PURE__ */ jsxs(
58
+ "div",
59
+ {
60
+ className: `flex gap-1 justify-center items-center ${className}`,
61
+ style: {
62
+ opacity: isVisible ? 1 : 0,
63
+ transition: `opacity ${transitionDuration}ms ease-in-out`
64
+ },
65
+ children: [
66
+ [0, 1, 2].map((i) => /* @__PURE__ */ jsx(
67
+ "span",
68
+ {
69
+ className: "w-2 h-2 bg-gray-600 rounded-full",
70
+ style: {
71
+ animation: "revel8-loading-dots-wave 1.2s infinite ease-in-out",
72
+ animationDelay: `${i * 0.2}s`
73
+ }
74
+ },
75
+ i
76
+ )),
77
+ /* @__PURE__ */ jsx("style", { children: `
78
+ @keyframes revel8-loading-dots-wave {
79
+ 0%, 100% {
80
+ transform: translateY(0);
81
+ }
82
+ 50% {
83
+ transform: translateY(-6px);
84
+ }
85
+ }
86
+ ` })
87
+ ]
88
+ }
89
+ );
90
+ }
91
+ var IpfsImage = ({ src, ...props }) => {
92
+ const finalSrc = ipfsToHttp(src) || src;
93
+ return /* @__PURE__ */ jsx("img", { src: finalSrc, ...props });
94
+ };
95
+ var TriplePositionsTornadoMinGraph = ({
96
+ data,
97
+ forColor = "#31ad31",
98
+ againstColor = "#bc4535",
99
+ className
100
+ }) => {
101
+ if (!data || data.length === 0) {
102
+ return null;
103
+ }
104
+ return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", className, children: /* @__PURE__ */ jsxs(
105
+ BarChart,
106
+ {
107
+ data,
108
+ stackOffset: "sign",
109
+ layout: "vertical",
110
+ barGap: 0,
111
+ barCategoryGap: 0,
112
+ children: [
113
+ /* @__PURE__ */ jsx(XAxis, { type: "number", hide: true }),
114
+ /* @__PURE__ */ jsx(YAxis, { dataKey: "name", type: "number", reversed: true, hide: true }),
115
+ /* @__PURE__ */ jsx(Bar, { dataKey: "aggregateVaultBalance", fill: forColor, stackId: "stack" }),
116
+ /* @__PURE__ */ jsx(
117
+ Bar,
118
+ {
119
+ dataKey: "aggregateCounterVaultBalance",
120
+ fill: againstColor,
121
+ stackId: "stack"
122
+ }
123
+ )
124
+ ]
125
+ }
126
+ ) });
127
+ };
128
+ var TripleAreaChart = ({
129
+ chartData,
130
+ variant = "min",
131
+ vaultColor = "green",
132
+ counterVaultColor = "red"
133
+ }) => {
134
+ const data = [...chartData];
135
+ const maxValue = Math.max(...data.map((d) => d.xValue));
136
+ const minValue = Math.min(...data.map((d) => d.xValue));
137
+ if (maxValue > 0) {
138
+ data.push({
139
+ xValue: maxValue * 1.2,
140
+ vault: maxValue
141
+ });
142
+ }
143
+ if (minValue < 0) {
144
+ data.push({
145
+ xValue: minValue * 1.2,
146
+ counterVault: minValue * -1
147
+ });
148
+ }
149
+ data.sort((a, b) => a.xValue - b.xValue);
150
+ const maxAbsValue = Math.max(...data.map((d) => Math.abs(d.xValue)));
151
+ const domain = [maxAbsValue * -1, maxAbsValue];
152
+ return /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(AreaChart, { data, layout: "vertical", children: [
153
+ variant !== "min" && /* @__PURE__ */ jsxs(Fragment, { children: [
154
+ /* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3" }),
155
+ /* @__PURE__ */ jsx(Tooltip, {})
156
+ ] }),
157
+ /* @__PURE__ */ jsx(XAxis, { type: "number", hide: variant === "min" }),
158
+ /* @__PURE__ */ jsx(
159
+ YAxis,
160
+ {
161
+ dataKey: "xValue",
162
+ type: "number",
163
+ reversed: true,
164
+ domain,
165
+ hide: variant === "min"
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsx(
169
+ Area,
170
+ {
171
+ type: "stepBefore",
172
+ dataKey: "vault",
173
+ stroke: vaultColor,
174
+ fill: vaultColor,
175
+ fillOpacity: 0.5
176
+ }
177
+ ),
178
+ /* @__PURE__ */ jsx(
179
+ Area,
180
+ {
181
+ type: "stepAfter",
182
+ dataKey: "counterVault",
183
+ stroke: counterVaultColor,
184
+ fill: counterVaultColor,
185
+ fillOpacity: 0.5
186
+ }
187
+ )
188
+ ] }) });
189
+ };
190
+ var ErrorBanner = ({
191
+ error,
192
+ code,
193
+ className
194
+ }) => {
195
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2 mt-12", className), children: [
196
+ /* @__PURE__ */ jsx("h2", { className: "text-center text-2xl font-bold mb-8", children: code ? `${code} Error` : "Error" }),
197
+ /* @__PURE__ */ jsx("p", { className: "text-center text-lg text-gray-500", children: error })
198
+ ] });
199
+ };
200
+ function CryptoAmount({
201
+ value,
202
+ decimals = 18,
203
+ isTokenUnits = false,
204
+ symbol,
205
+ exchangeRate,
206
+ currencyCode = "USD",
207
+ locale,
208
+ variant = "default",
209
+ size = "md",
210
+ maxSignificantDigits = 10,
211
+ maxDecimals = 6,
212
+ showSymbol = true,
213
+ showFiat = true,
214
+ className,
215
+ cryptoClassName,
216
+ fiatClassName
217
+ }) {
218
+ const effectiveLocale = locale || (typeof navigator !== "undefined" ? navigator.language : "en-US");
219
+ const formatted = React2.useMemo(() => {
220
+ if (isTokenUnits) {
221
+ const numericValue = typeof value === "string" ? parseFloat(value) : Number(value);
222
+ const displayValue = numericValue.toString();
223
+ return {
224
+ display: displayValue,
225
+ fullValue: displayValue,
226
+ isTruncated: false,
227
+ numericValue
228
+ };
229
+ }
230
+ const weiValue = typeof value === "number" ? value.toString() : value;
231
+ return formatCryptoAmount(weiValue, decimals, {
232
+ maxSignificantDigits,
233
+ maxDecimals,
234
+ compact: variant === "compact",
235
+ locale: effectiveLocale
236
+ });
237
+ }, [value, decimals, isTokenUnits, maxSignificantDigits, maxDecimals, variant, effectiveLocale]);
238
+ const fiatFormatted = React2.useMemo(() => {
239
+ if (!showFiat || exchangeRate == null || variant === "crypto-only") {
240
+ return null;
241
+ }
242
+ const fiatValue = formatted.numericValue * exchangeRate;
243
+ try {
244
+ return new Intl.NumberFormat(effectiveLocale, {
245
+ style: "currency",
246
+ currency: currencyCode.toUpperCase(),
247
+ minimumFractionDigits: 2,
248
+ maximumFractionDigits: 2
249
+ }).format(fiatValue);
250
+ } catch {
251
+ return `$${fiatValue.toFixed(2)}`;
252
+ }
253
+ }, [formatted.numericValue, exchangeRate, currencyCode, effectiveLocale, showFiat, variant]);
254
+ const sizeStyles = {
255
+ sm: {
256
+ crypto: "text-sm",
257
+ fiat: "text-xs"
258
+ },
259
+ md: {
260
+ crypto: "text-base",
261
+ fiat: "text-sm"
262
+ },
263
+ lg: {
264
+ crypto: "text-lg font-semibold",
265
+ fiat: "text-base"
266
+ }
267
+ };
268
+ const styles = sizeStyles[size];
269
+ const cryptoDisplay = showSymbol ? `${formatted.display} ${symbol}` : formatted.display;
270
+ const fullCryptoDisplay = showSymbol ? `${formatted.fullValue} ${symbol}` : formatted.fullValue;
271
+ const needsTooltip = formatted.isTruncated;
272
+ const cryptoElement = /* @__PURE__ */ jsx(
273
+ "span",
274
+ {
275
+ className: cn(
276
+ styles.crypto,
277
+ "font-medium",
278
+ cryptoClassName
279
+ ),
280
+ children: cryptoDisplay
281
+ }
282
+ );
283
+ const cryptoWithTooltip = needsTooltip ? /* @__PURE__ */ jsxs(Tooltip$1, { delayDuration: 1e3, children: [
284
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: cryptoElement }),
285
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: fullCryptoDisplay }) })
286
+ ] }) : cryptoElement;
287
+ if (variant === "crypto-only") {
288
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center", className), children: cryptoWithTooltip });
289
+ }
290
+ if (variant === "fiat-only") {
291
+ if (!fiatFormatted) {
292
+ return null;
293
+ }
294
+ return /* @__PURE__ */ jsxs("span", { className: cn(
295
+ styles.fiat,
296
+ "text-muted-foreground",
297
+ fiatClassName,
298
+ className
299
+ ), children: [
300
+ "\u2248 ",
301
+ fiatFormatted
302
+ ] });
303
+ }
304
+ if (variant === "inline") {
305
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-1", className), children: [
306
+ cryptoWithTooltip,
307
+ fiatFormatted && /* @__PURE__ */ jsxs("span", { className: cn(
308
+ styles.fiat,
309
+ "text-muted-foreground",
310
+ fiatClassName
311
+ ), children: [
312
+ "(~",
313
+ fiatFormatted,
314
+ ")"
315
+ ] })
316
+ ] });
317
+ }
318
+ if (variant === "compact") {
319
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-1", className), children: [
320
+ cryptoWithTooltip,
321
+ fiatFormatted && /* @__PURE__ */ jsxs("span", { className: cn(
322
+ styles.fiat,
323
+ "text-muted-foreground",
324
+ fiatClassName
325
+ ), children: [
326
+ "(",
327
+ fiatFormatted,
328
+ ")"
329
+ ] })
330
+ ] });
331
+ }
332
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", className), children: [
333
+ cryptoWithTooltip,
334
+ fiatFormatted && /* @__PURE__ */ jsx("span", { className: cn(
335
+ styles.fiat,
336
+ "text-muted-foreground",
337
+ fiatClassName
338
+ ), children: fiatFormatted })
339
+ ] });
340
+ }
341
+ function createCryptoAmountRateProps(exchangeRate, currencyCode = "USD", locale) {
342
+ return {
343
+ exchangeRate: exchangeRate ?? void 0,
344
+ currencyCode,
345
+ locale
346
+ };
347
+ }
348
+
349
+ export { AtomIcon, CryptoAmount, ErrorBanner, IpfsImage, LoadingDots, TripleAreaChart, TriplePositionsTornadoMinGraph, UnknownImage, createCryptoAmountRateProps };
350
+ //# sourceMappingURL=chunk-2RGM3KJL.js.map
351
+ //# sourceMappingURL=chunk-2RGM3KJL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/AtomIcon.tsx","../src/components/UnknownImage.tsx","../src/components/LoadingDots.tsx","../src/components/IpfsImage.tsx","../src/components/TriplePositionsTornadoMinGraph.tsx","../src/components/TripleAreaChart.tsx","../src/components/ErrorBanner.tsx","../src/components/CryptoAmount.tsx"],"names":["finalSrc","jsx","jsxs","ResponsiveContainer","Tooltip","XAxis","YAxis"],"mappings":"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","file":"chunk-2RGM3KJL.js","sourcesContent":["export const AtomIcon = ({ ...props }: React.SVGProps<SVGSVGElement>) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"rgba(255,255,255,0.6)\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n className=\"lucide lucide-atom\"\n {...props}\n >\n <circle cx=\"12\" cy=\"12\" r=\"1\" />\n <path d=\"M20.2 20.2c2.04-2.03.02-7.36-4.5-11.9-4.54-4.52-9.87-6.54-11.9-4.5-2.04 2.03-.02 7.36 4.5 11.9 4.54 4.52 9.87 6.54 11.9 4.5Z\" />\n <path d=\"M15.7 15.7c4.52-4.54 6.54-9.87 4.5-11.9-2.03-2.04-7.36-.02-11.9 4.5-4.52 4.54-6.54 9.87-4.5 11.9 2.03 2.04 7.36.02 11.9-4.5Z\" />\n </svg>\n )\n}\n","import React, { useState } from 'react'\nimport { strengthenImageUrl } from '../utils/formatting'\n\nexport interface UnknownImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** The image source URL - can be IPFS, HTTP, or raw hash */\n src: string\n /** Whether to wrap the image in an anchor link to the source */\n asLink?: boolean\n}\n\n/**\n * An image component that handles various URL formats including IPFS.\n * Automatically converts IPFS URIs and hashes to gateway URLs.\n * \n * @example\n * <UnknownImage src=\"ipfs://QmHash123\" alt=\"My image\" className=\"w-10 h-10\" />\n */\nexport const UnknownImage = ({\n asLink = false,\n src,\n ...props\n}: UnknownImageProps) => {\n if (!src) return null\n const [numberOfErrors, setNumberOfErrors] = useState(0)\n\n const onImageError = (\n e: React.SyntheticEvent<HTMLImageElement>,\n finalSrc: string\n ) => {\n setNumberOfErrors(numberOfErrors + 1)\n // Only log in development\n if (typeof window !== 'undefined' && (window as any).__DEV__) {\n console.log('UnknownImage error:', e.currentTarget.src, finalSrc)\n }\n }\n\n const finalSrc = strengthenImageUrl(src)\n\n const img = (\n <img src={finalSrc} onError={(e) => onImageError(e, finalSrc)} {...props} />\n )\n\n if (asLink) {\n return (\n <a href={finalSrc} target=\"_blank\" rel=\"noopener noreferrer\">\n {img}\n </a>\n )\n }\n\n return img\n}\n\nexport default UnknownImage\n\n","export interface LoadingDotsProps {\n /** Duration of opacity transition in ms */\n transitionDuration?: number\n /** Whether the dots are visible */\n isVisible?: boolean\n /** Additional CSS classes */\n className?: string\n}\n\n/**\n * Animated loading dots indicator.\n * Shows three dots with a wave animation.\n * \n * @example\n * <LoadingDots isVisible={isLoading} />\n */\nexport function LoadingDots({\n transitionDuration = 300,\n isVisible = true,\n className = '',\n}: LoadingDotsProps) {\n return (\n <div\n className={`flex gap-1 justify-center items-center ${className}`}\n style={{\n opacity: isVisible ? 1 : 0,\n transition: `opacity ${transitionDuration}ms ease-in-out`,\n }}\n >\n {[0, 1, 2].map((i) => (\n <span\n key={i}\n className=\"w-2 h-2 bg-gray-600 rounded-full\"\n style={{\n animation: 'revel8-loading-dots-wave 1.2s infinite ease-in-out',\n animationDelay: `${i * 0.2}s`,\n }}\n />\n ))}\n <style>{`\n @keyframes revel8-loading-dots-wave {\n 0%, 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-6px);\n }\n }\n `}</style>\n </div>\n )\n}\n\nexport default LoadingDots\n\n","import React from 'react'\nimport { ipfsToHttp } from '../utils/formatting'\n\nexport interface IpfsImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\n /** The image source - can be an ipfs:// URI or regular URL */\n src: string\n}\n\n/**\n * An image component that automatically converts IPFS URIs to gateway URLs.\n * \n * @example\n * <IpfsImage src=\"ipfs://QmHash123\" alt=\"IPFS image\" />\n */\nexport const IpfsImage = ({ src, ...props }: IpfsImageProps) => {\n const finalSrc = ipfsToHttp(src) || src\n return <img src={finalSrc} {...props} />\n}\n\nexport default IpfsImage\n\n","import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts'\n\nexport interface TornadoGraphDataPoint {\n /** The range identifier/name */\n name: number\n /** Vault balance for this range */\n vaultBalance?: number\n /** Counter vault balance for this range */\n counterVaultBalance?: number\n /** Aggregate vault balance (positive side) */\n aggregateVaultBalance: number\n /** Aggregate counter vault balance (negative side) */\n aggregateCounterVaultBalance: number\n}\n\nexport interface TriplePositionsTornadoMinGraphProps {\n /** Pre-formatted data for the tornado chart */\n data: TornadoGraphDataPoint[]\n /** Color for the \"FOR\" (vault) bars */\n forColor?: string\n /** Color for the \"AGAINST\" (counter vault) bars */\n againstColor?: string\n /** Additional className for the container */\n className?: string\n}\n\n/**\n * A minimal tornado/butterfly chart for displaying triple position distributions.\n * Shows FOR positions (green) on the right and AGAINST positions (red) on the left.\n * \n * @example\n * <TriplePositionsTornadoMinGraph \n * data={formattedRanges} \n * forColor=\"#31ad31\" \n * againstColor=\"#bc4535\" \n * />\n */\nexport const TriplePositionsTornadoMinGraph = ({\n data,\n forColor = '#31ad31',\n againstColor = '#bc4535',\n className,\n}: TriplePositionsTornadoMinGraphProps) => {\n if (!data || data.length === 0) {\n return null\n }\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\" className={className}>\n <BarChart\n data={data}\n stackOffset=\"sign\"\n layout=\"vertical\"\n barGap={0}\n barCategoryGap={0}\n >\n <XAxis type=\"number\" hide={true} />\n <YAxis dataKey=\"name\" type=\"number\" reversed hide={true} />\n <Bar dataKey=\"aggregateVaultBalance\" fill={forColor} stackId=\"stack\" />\n <Bar\n dataKey=\"aggregateCounterVaultBalance\"\n fill={againstColor}\n stackId=\"stack\"\n />\n </BarChart>\n </ResponsiveContainer>\n )\n}\n\nexport default TriplePositionsTornadoMinGraph\n\n","import {\n Area,\n AreaChart,\n CartesianGrid,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from 'recharts'\n\nexport interface TripleAreaChartDataPoint {\n /** The x-axis value (typically position value) */\n xValue: number\n /** Vault (FOR) position value */\n vault?: number\n /** Counter vault (AGAINST) position value */\n counterVault?: number\n}\n\nexport interface TripleAreaChartProps {\n /** Pre-formatted chart data points */\n chartData: TripleAreaChartDataPoint[]\n /** Display variant - 'min' hides axes/grid, 'max' shows full chart */\n variant?: 'min' | 'max'\n /** Color for vault (FOR) area */\n vaultColor?: string\n /** Color for counter vault (AGAINST) area */\n counterVaultColor?: string\n}\n\n/**\n * An area chart for visualizing triple position distributions.\n * Shows vault (FOR) positions on positive side and counter vault (AGAINST) on negative.\n * \n * @example\n * <TripleAreaChart \n * chartData={formattedPositions} \n * variant=\"min\" \n * />\n */\nexport const TripleAreaChart = ({\n chartData,\n variant = 'min',\n vaultColor = 'green',\n counterVaultColor = 'red',\n}: TripleAreaChartProps) => {\n // Clone data to avoid mutating props\n const data = [...chartData]\n \n const maxValue = Math.max(...data.map((d) => d.xValue))\n const minValue = Math.min(...data.map((d) => d.xValue))\n \n // Add padding points for better visualization\n if (maxValue > 0) {\n data.push({\n xValue: maxValue * 1.2,\n vault: maxValue,\n })\n }\n if (minValue < 0) {\n data.push({\n xValue: minValue * 1.2,\n counterVault: minValue * -1,\n })\n }\n \n data.sort((a, b) => a.xValue - b.xValue)\n const maxAbsValue = Math.max(...data.map((d) => Math.abs(d.xValue)))\n const domain = [maxAbsValue * -1, maxAbsValue]\n\n return (\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={data} layout=\"vertical\">\n {variant !== 'min' && (\n <>\n <CartesianGrid strokeDasharray=\"3 3\" />\n <Tooltip />\n </>\n )}\n <XAxis type=\"number\" hide={variant === 'min'} />\n <YAxis\n dataKey=\"xValue\"\n type=\"number\"\n reversed\n domain={domain}\n hide={variant === 'min'}\n />\n <Area\n type=\"stepBefore\"\n dataKey=\"vault\"\n stroke={vaultColor}\n fill={vaultColor}\n fillOpacity={0.5}\n />\n <Area\n type=\"stepAfter\"\n dataKey=\"counterVault\"\n stroke={counterVaultColor}\n fill={counterVaultColor}\n fillOpacity={0.5}\n />\n </AreaChart>\n </ResponsiveContainer>\n )\n}\n\nexport default TripleAreaChart\n\n","import { cn } from '../utils/cn'\n\nexport interface ErrorBannerProps {\n /** The error message to display */\n error: string\n /** Optional HTTP status code */\n code?: number\n /** Additional CSS classes */\n className?: string\n}\n\n/**\n * A simple error banner component for displaying error messages.\n * Centered layout with large heading and subtitle.\n * \n * @example\n * <ErrorBanner error=\"Page not found\" code={404} />\n */\nexport const ErrorBanner = ({ \n error, \n code, \n className \n}: ErrorBannerProps) => {\n return (\n <div className={cn(\"flex flex-col gap-2 mt-12\", className)}>\n <h2 className=\"text-center text-2xl font-bold mb-8\">\n {code ? `${code} Error` : 'Error'}\n </h2>\n <p className=\"text-center text-lg text-gray-500\">{error}</p>\n </div>\n )\n}\n\nexport default ErrorBanner\n\n","import * as React from 'react'\nimport { cn } from '../utils/cn'\nimport { Tooltip, TooltipTrigger, TooltipContent } from './ui/tooltip'\nimport { formatCryptoAmount } from '../utils/formatting'\n\n/**\n * Display variant for the CryptoAmount component.\n * \n * - `default`: Crypto on top, fiat below (stacked)\n * - `inline`: Single line with fiat in parentheses\n * - `crypto-only`: Just the native token amount\n * - `fiat-only`: Just the fiat equivalent (useful for previews)\n * - `compact`: Abbreviated format for large amounts (1.5M TRUST)\n */\nexport type CryptoAmountVariant = 'default' | 'inline' | 'crypto-only' | 'fiat-only' | 'compact'\n\n/**\n * Size variant for the CryptoAmount component.\n */\nexport type CryptoAmountSize = 'sm' | 'md' | 'lg'\n\nexport interface CryptoAmountProps {\n /** \n * The crypto amount. By default, expects wei/smallest unit (string or bigint).\n * If `isTokenUnits` is true, expects the value already in token units (e.g., 1.5 for 1.5 TRUST).\n */\n value: string | bigint | number\n \n /** Number of decimals for the token (default: 18). Ignored when isTokenUnits is true. */\n decimals?: number\n \n /**\n * When true, the value is already in token units (e.g., 1.5 for 1.5 TRUST).\n * When false (default), the value is in wei/smallest units and will be converted.\n */\n isTokenUnits?: boolean\n \n /** Token symbol to display (e.g., 'TRUST', 'ETH') */\n symbol: string\n \n /**\n * Exchange rate for fiat conversion (1 token = X fiat).\n * If undefined/null, fiat display is hidden.\n */\n exchangeRate?: number | null\n \n /**\n * Fiat currency code for formatting (default: 'USD').\n * Used with Intl.NumberFormat for proper currency display.\n */\n currencyCode?: string\n \n /**\n * Locale for number/currency formatting (default: browser locale or 'en-US')\n */\n locale?: string\n \n /** Display variant (default: 'default') */\n variant?: CryptoAmountVariant\n \n /** Size variant (default: 'md') */\n size?: CryptoAmountSize\n \n /**\n * Maximum significant digits before truncation (default: 10).\n * Amounts exceeding this will show \"...\" with full value in tooltip.\n */\n maxSignificantDigits?: number\n \n /**\n * Maximum decimal places to display (default: 6).\n * Applied after conversion but before significant digit truncation.\n */\n maxDecimals?: number\n \n /** Whether to show the token symbol (default: true) */\n showSymbol?: boolean\n \n /** Whether to show fiat value when exchange rate is available (default: true) */\n showFiat?: boolean\n \n /** Additional CSS classes for the container */\n className?: string\n \n /** Additional CSS classes for the crypto amount text */\n cryptoClassName?: string\n \n /** Additional CSS classes for the fiat amount text */\n fiatClassName?: string\n}\n\n/**\n * A unified component for displaying cryptocurrency amounts with optional fiat conversion.\n * \n * Features:\n * - Crypto-first display (native token amount is primary)\n * - Optional fiat conversion shown as secondary\n * - Truncation with tooltip for large amounts\n * - Multiple display variants (stacked, inline, compact)\n * - Proper number formatting based on locale\n * \n * @example\n * ```tsx\n * // Basic usage - stacked display\n * <CryptoAmount \n * value=\"1500000000000000000\" \n * symbol=\"TRUST\" \n * exchangeRate={0.42} \n * />\n * // Renders:\n * // 1.5 TRUST\n * // $0.63\n * \n * // Inline variant\n * <CryptoAmount \n * value=\"1500000000000000000\" \n * symbol=\"TRUST\" \n * exchangeRate={0.42}\n * variant=\"inline\"\n * />\n * // Renders: 1.5 TRUST (~$0.63)\n * \n * // Compact variant for large amounts\n * <CryptoAmount \n * value=\"1500000000000000000000000\" \n * symbol=\"TRUST\"\n * variant=\"compact\"\n * />\n * // Renders: 1.5M TRUST\n * ```\n */\nexport function CryptoAmount({\n value,\n decimals = 18,\n isTokenUnits = false,\n symbol,\n exchangeRate,\n currencyCode = 'USD',\n locale,\n variant = 'default',\n size = 'md',\n maxSignificantDigits = 10,\n maxDecimals = 6,\n showSymbol = true,\n showFiat = true,\n className,\n cryptoClassName,\n fiatClassName,\n}: CryptoAmountProps) {\n // Determine locale\n const effectiveLocale = locale || (typeof navigator !== 'undefined' ? navigator.language : 'en-US')\n \n // Format the crypto amount\n const formatted = React.useMemo(() => {\n // If value is already in token units, create a simple formatted result\n if (isTokenUnits) {\n const numericValue = typeof value === 'string' ? parseFloat(value) : Number(value)\n const displayValue = numericValue.toString()\n return {\n display: displayValue,\n fullValue: displayValue,\n isTruncated: false,\n numericValue,\n }\n }\n \n // Otherwise, convert from wei\n // Ensure value is string or bigint for formatCryptoAmount\n const weiValue = typeof value === 'number' ? value.toString() : value\n return formatCryptoAmount(weiValue, decimals, {\n maxSignificantDigits,\n maxDecimals,\n compact: variant === 'compact',\n locale: effectiveLocale,\n })\n }, [value, decimals, isTokenUnits, maxSignificantDigits, maxDecimals, variant, effectiveLocale])\n \n // Calculate fiat value if exchange rate is available\n const fiatFormatted = React.useMemo(() => {\n if (!showFiat || exchangeRate == null || variant === 'crypto-only') {\n return null\n }\n \n const fiatValue = formatted.numericValue * exchangeRate\n \n try {\n return new Intl.NumberFormat(effectiveLocale, {\n style: 'currency',\n currency: currencyCode.toUpperCase(),\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(fiatValue)\n } catch {\n // Fallback if currency code is invalid\n return `$${fiatValue.toFixed(2)}`\n }\n }, [formatted.numericValue, exchangeRate, currencyCode, effectiveLocale, showFiat, variant])\n \n // Size-based styling\n const sizeStyles = {\n sm: {\n crypto: 'text-sm',\n fiat: 'text-xs',\n },\n md: {\n crypto: 'text-base',\n fiat: 'text-sm',\n },\n lg: {\n crypto: 'text-lg font-semibold',\n fiat: 'text-base',\n },\n }\n \n const styles = sizeStyles[size]\n \n // Build the crypto display string\n const cryptoDisplay = showSymbol \n ? `${formatted.display} ${symbol}`\n : formatted.display\n \n // Full value for tooltip (when truncated)\n const fullCryptoDisplay = showSymbol\n ? `${formatted.fullValue} ${symbol}`\n : formatted.fullValue\n \n // Determine if we need a tooltip\n const needsTooltip = formatted.isTruncated\n \n // Render the crypto amount (with or without tooltip)\n const cryptoElement = (\n <span \n className={cn(\n styles.crypto,\n 'font-medium',\n cryptoClassName\n )}\n >\n {cryptoDisplay}\n </span>\n )\n \n const cryptoWithTooltip = needsTooltip ? (\n <Tooltip delayDuration={1000}>\n <TooltipTrigger asChild>\n {cryptoElement}\n </TooltipTrigger>\n <TooltipContent>\n <span className=\"font-mono text-xs\">{fullCryptoDisplay}</span>\n </TooltipContent>\n </Tooltip>\n ) : cryptoElement\n \n // Render based on variant\n if (variant === 'crypto-only') {\n return (\n <div className={cn('flex items-center', className)}>\n {cryptoWithTooltip}\n </div>\n )\n }\n \n if (variant === 'fiat-only') {\n // Only show fiat, return null if no exchange rate available\n if (!fiatFormatted) {\n return null\n }\n return (\n <span className={cn(\n styles.fiat,\n 'text-muted-foreground',\n fiatClassName,\n className\n )}>\n ≈ {fiatFormatted}\n </span>\n )\n }\n \n if (variant === 'inline') {\n return (\n <div className={cn('flex items-center gap-1', className)}>\n {cryptoWithTooltip}\n {fiatFormatted && (\n <span className={cn(\n styles.fiat,\n 'text-muted-foreground',\n fiatClassName\n )}>\n (~{fiatFormatted})\n </span>\n )}\n </div>\n )\n }\n \n if (variant === 'compact') {\n return (\n <div className={cn('flex items-center gap-1', className)}>\n {cryptoWithTooltip}\n {fiatFormatted && (\n <span className={cn(\n styles.fiat,\n 'text-muted-foreground',\n fiatClassName\n )}>\n ({fiatFormatted})\n </span>\n )}\n </div>\n )\n }\n \n // Default: stacked layout\n return (\n <div className={cn('flex flex-col', className)}>\n {cryptoWithTooltip}\n {fiatFormatted && (\n <span className={cn(\n styles.fiat,\n 'text-muted-foreground',\n fiatClassName\n )}>\n {fiatFormatted}\n </span>\n )}\n </div>\n )\n}\n\nexport default CryptoAmount\n\n// ============================================================================\n// Helper utilities for creating CryptoAmount props\n// ============================================================================\n\n/**\n * Props subset for creating a CryptoAmount from an exchange rate context.\n * Use this type when building a hook wrapper in your app.\n */\nexport type CryptoAmountRateProps = Pick<\n CryptoAmountProps,\n 'exchangeRate' | 'currencyCode' | 'locale'\n>\n\n/**\n * Creates CryptoAmountRateProps from an exchange rate and currency settings.\n * This is a helper for building hook wrappers in consuming applications.\n * \n * @param exchangeRate - The current exchange rate (1 token = X fiat), or null/undefined\n * @param currencyCode - The fiat currency code (e.g., 'USD', 'EUR')\n * @param locale - Optional locale for formatting\n * @returns Props object to spread onto CryptoAmount\n * \n * @example\n * ```tsx\n * // In your app's hook wrapper:\n * export function useCryptoAmountProps() {\n * const { data } = useExchangeRates()\n * const { selectedCurrency } = useCurrency()\n * \n * return createCryptoAmountRateProps(\n * data?.rate,\n * selectedCurrency,\n * navigator.language\n * )\n * }\n * \n * // Then in components:\n * const rateProps = useCryptoAmountProps()\n * <CryptoAmount value=\"1000000000000000000\" symbol=\"TRUST\" {...rateProps} />\n * ```\n */\nexport function createCryptoAmountRateProps(\n exchangeRate: number | null | undefined,\n currencyCode: string = 'USD',\n locale?: string\n): CryptoAmountRateProps {\n return {\n exchangeRate: exchangeRate ?? undefined,\n currencyCode,\n locale,\n }\n}\n\n"]}