@orangecheck/design 0.1.1 → 0.3.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/dist/format.d.mts +19 -0
- package/dist/format.d.ts +19 -0
- package/dist/format.js +68 -0
- package/dist/format.js.map +1 -0
- package/dist/format.mjs +58 -0
- package/dist/format.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +389 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +371 -13
- package/dist/index.mjs.map +1 -1
- package/dist/primitives.d.mts +92 -1
- package/dist/primitives.d.ts +92 -1
- package/dist/primitives.js +319 -0
- package/dist/primitives.js.map +1 -1
- package/dist/primitives.mjs +310 -3
- package/dist/primitives.mjs.map +1 -1
- package/dist/styles/themes/gold.css +108 -0
- package/dist/styles/themes/lightning.css +107 -0
- package/dist/styles/themes.css +2 -2
- package/dist/tokens.js +10 -10
- package/dist/tokens.js.map +1 -1
- package/dist/tokens.mjs +10 -10
- package/dist/tokens.mjs.map +1 -1
- package/package.json +8 -1
- package/dist/styles/themes/aurora.css +0 -130
- package/dist/styles/themes/midnight.css +0 -105
package/dist/index.mjs
CHANGED
|
@@ -2,9 +2,9 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as React2 from 'react';
|
|
4
4
|
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useContext } from 'react';
|
|
5
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { useTheme } from 'next-themes';
|
|
7
|
-
import { ChevronDown, Palette, Check, Sun, Moon, X, XIcon, AlertTriangle, Pencil, ChevronLeft, ChevronRight, ChevronDownIcon, CheckIcon, ChevronUpIcon } from 'lucide-react';
|
|
7
|
+
import { ChevronDown, Palette, Check, Sun, Moon, X, XIcon, AlertTriangle, Pencil, ChevronLeft, ChevronRight, ChevronDownIcon, CheckIcon, ChevronUpIcon, Maximize2, Copy } from 'lucide-react';
|
|
8
8
|
import { Slot } from '@radix-ui/react-slot';
|
|
9
9
|
import { cva } from 'class-variance-authority';
|
|
10
10
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
@@ -14,6 +14,7 @@ import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
|
14
14
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
15
15
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
16
16
|
import { Toaster as Toaster$1 } from 'sonner';
|
|
17
|
+
import QRCode from 'qrcode';
|
|
17
18
|
import * as ui_star from '@orangecheck/ui';
|
|
18
19
|
|
|
19
20
|
var __defProp = Object.defineProperty;
|
|
@@ -47,8 +48,12 @@ __export(src_exports, {
|
|
|
47
48
|
AlertWithAction: () => AlertWithAction,
|
|
48
49
|
AlertWithCountdown: () => AlertWithCountdown,
|
|
49
50
|
Badge: () => Badge,
|
|
51
|
+
Bar: () => Bar,
|
|
52
|
+
BitcoinAddress: () => BitcoinAddress,
|
|
50
53
|
Button: () => Button,
|
|
54
|
+
Card: () => Card,
|
|
51
55
|
ConfirmHost: () => ConfirmHost,
|
|
56
|
+
CopyButton: () => CopyButton,
|
|
52
57
|
DEFAULT_OC_THEME: () => DEFAULT_OC_THEME,
|
|
53
58
|
Dialog: () => Dialog,
|
|
54
59
|
DialogClose: () => DialogClose,
|
|
@@ -75,6 +80,9 @@ __export(src_exports, {
|
|
|
75
80
|
PopoverContent: () => PopoverContent,
|
|
76
81
|
PopoverTrigger: () => PopoverTrigger,
|
|
77
82
|
PromptHost: () => PromptHost,
|
|
83
|
+
QrCode: () => QrCode,
|
|
84
|
+
REFERENCE_BTC_USD: () => REFERENCE_BTC_USD,
|
|
85
|
+
SatsAmount: () => SatsAmount,
|
|
78
86
|
Select: () => Select,
|
|
79
87
|
SelectContent: () => SelectContent,
|
|
80
88
|
SelectGroup: () => SelectGroup,
|
|
@@ -95,6 +103,9 @@ __export(src_exports, {
|
|
|
95
103
|
SheetTitle: () => SheetTitle,
|
|
96
104
|
SheetTrigger: () => SheetTrigger,
|
|
97
105
|
Skeleton: () => Skeleton,
|
|
106
|
+
Sparkline: () => Sparkline,
|
|
107
|
+
StatBlock: () => StatBlock,
|
|
108
|
+
StatusPill: () => StatusPill,
|
|
98
109
|
Textarea: () => Textarea,
|
|
99
110
|
ThemeToggle: () => ThemeToggle,
|
|
100
111
|
ThemeToggleLink: () => ThemeToggleLink,
|
|
@@ -105,10 +116,18 @@ __export(src_exports, {
|
|
|
105
116
|
buttonVariants: () => buttonVariants,
|
|
106
117
|
cn: () => cn,
|
|
107
118
|
confirm: () => confirm,
|
|
119
|
+
explorerUrl: () => explorerUrl,
|
|
120
|
+
formatSats: () => formatSats,
|
|
121
|
+
formatSatsCompact: () => formatSatsCompact,
|
|
108
122
|
getOcThemeInitScript: () => getOcThemeInitScript,
|
|
109
123
|
isKnownTheme: () => isKnownTheme,
|
|
124
|
+
priceBoth: () => priceBoth,
|
|
110
125
|
prompt: () => prompt,
|
|
126
|
+
relativeTime: () => relativeTime,
|
|
111
127
|
resolveTheme: () => resolveTheme,
|
|
128
|
+
satsToUsd: () => satsToUsd,
|
|
129
|
+
shortenAddress: () => shortenAddress,
|
|
130
|
+
usdToSats: () => usdToSats,
|
|
112
131
|
useOcSkin: () => useOcSkin
|
|
113
132
|
});
|
|
114
133
|
function cn(...inputs) {
|
|
@@ -120,22 +139,22 @@ var OC_THEMES = [
|
|
|
120
139
|
{
|
|
121
140
|
id: "orangecheck",
|
|
122
141
|
label: "orangecheck",
|
|
123
|
-
description: "the
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
id: "midnight",
|
|
127
|
-
label: "midnight",
|
|
128
|
-
description: "indigo on slate, softer rounded 0.625rem corners, Manrope sans \u2014 calmer, SaaS-ier"
|
|
142
|
+
description: "the chain \u2014 Bitcoin orange, sharp 0.25rem corners, Inter + JetBrains Mono"
|
|
129
143
|
},
|
|
130
144
|
{
|
|
131
145
|
id: "phosphor",
|
|
132
146
|
label: "phosphor",
|
|
133
|
-
description: "CRT terminal green, hard 0.125rem
|
|
147
|
+
description: "the node \u2014 CRT terminal green, hard 0.125rem, all-mono \xB7 sovereignty & verify"
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: "lightning",
|
|
151
|
+
label: "lightning",
|
|
152
|
+
description: "the network \u2014 electric violet (L2), hardest 0rem edges, sans \xB7 instant"
|
|
134
153
|
},
|
|
135
154
|
{
|
|
136
|
-
id: "
|
|
137
|
-
label: "
|
|
138
|
-
description: "
|
|
155
|
+
id: "gold",
|
|
156
|
+
label: "gold",
|
|
157
|
+
description: "sound money \u2014 digital gold, hard 0.125rem milled edge, mono ledger \xB7 21M"
|
|
139
158
|
}
|
|
140
159
|
];
|
|
141
160
|
var DEFAULT_OC_THEME = "orangecheck";
|
|
@@ -1475,6 +1494,345 @@ var Toaster = ({ ...props }) => {
|
|
|
1475
1494
|
}
|
|
1476
1495
|
);
|
|
1477
1496
|
};
|
|
1497
|
+
function Card({
|
|
1498
|
+
id,
|
|
1499
|
+
title,
|
|
1500
|
+
subtitle,
|
|
1501
|
+
refreshedAt,
|
|
1502
|
+
actions,
|
|
1503
|
+
children,
|
|
1504
|
+
className,
|
|
1505
|
+
tone = "default",
|
|
1506
|
+
expandable = true
|
|
1507
|
+
}) {
|
|
1508
|
+
const [expanded, setExpanded] = useState(false);
|
|
1509
|
+
const toneClass = tone === "warning" ? "border-warning/60" : tone === "destructive" ? "border-destructive/60" : tone === "muted" ? "border-border opacity-90" : "border-border";
|
|
1510
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1511
|
+
/* @__PURE__ */ jsxs(
|
|
1512
|
+
"section",
|
|
1513
|
+
{
|
|
1514
|
+
id,
|
|
1515
|
+
className: cn("terminal flex flex-col rounded-sm border scroll-mt-16", toneClass, className),
|
|
1516
|
+
children: [
|
|
1517
|
+
/* @__PURE__ */ jsxs("div", { className: "terminal-title flex items-center justify-between gap-3", children: [
|
|
1518
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1519
|
+
/* @__PURE__ */ jsx("span", { className: "terminal-dot", "aria-hidden": true }),
|
|
1520
|
+
/* @__PURE__ */ jsx("span", { className: "terminal-dot opacity-70", "aria-hidden": true }),
|
|
1521
|
+
/* @__PURE__ */ jsx("span", { className: "terminal-dot opacity-50", "aria-hidden": true }),
|
|
1522
|
+
/* @__PURE__ */ jsx("span", { className: "ml-2 truncate", children: title }),
|
|
1523
|
+
subtitle && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground/70 ml-1 truncate text-[10px] tracking-normal normal-case", children: [
|
|
1524
|
+
"\xB7 ",
|
|
1525
|
+
subtitle
|
|
1526
|
+
] })
|
|
1527
|
+
] }),
|
|
1528
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1529
|
+
refreshedAt && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/60 hidden text-[10px] tracking-normal normal-case sm:inline", children: refreshedAt }),
|
|
1530
|
+
actions,
|
|
1531
|
+
expandable && /* @__PURE__ */ jsx(
|
|
1532
|
+
"button",
|
|
1533
|
+
{
|
|
1534
|
+
type: "button",
|
|
1535
|
+
onClick: () => setExpanded(true),
|
|
1536
|
+
"aria-label": `expand ${title}`,
|
|
1537
|
+
title: "expand to fullscreen",
|
|
1538
|
+
className: "text-muted-foreground/70 hover:text-foreground inline-flex h-6 w-6 items-center justify-center rounded-sm",
|
|
1539
|
+
children: /* @__PURE__ */ jsx(Maximize2, { className: "size-3" })
|
|
1540
|
+
}
|
|
1541
|
+
)
|
|
1542
|
+
] })
|
|
1543
|
+
] }),
|
|
1544
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 p-4 sm:p-5", children })
|
|
1545
|
+
]
|
|
1546
|
+
}
|
|
1547
|
+
),
|
|
1548
|
+
expandable && /* @__PURE__ */ jsx(
|
|
1549
|
+
Modal,
|
|
1550
|
+
{
|
|
1551
|
+
open: expanded,
|
|
1552
|
+
onOpenChange: setExpanded,
|
|
1553
|
+
title,
|
|
1554
|
+
...subtitle ? { subtitle } : {},
|
|
1555
|
+
actions: refreshedAt ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/60 hidden text-[10px] tracking-normal normal-case sm:inline", children: refreshedAt }) : null,
|
|
1556
|
+
children
|
|
1557
|
+
}
|
|
1558
|
+
)
|
|
1559
|
+
] });
|
|
1560
|
+
}
|
|
1561
|
+
function Sparkline({ data, width = 96, height = 24, area = false, className }) {
|
|
1562
|
+
if (data.length === 0) {
|
|
1563
|
+
return /* @__PURE__ */ jsx("svg", { width, height, className: cn(className), "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
1564
|
+
"line",
|
|
1565
|
+
{
|
|
1566
|
+
x1: 0,
|
|
1567
|
+
x2: width,
|
|
1568
|
+
y1: height / 2,
|
|
1569
|
+
y2: height / 2,
|
|
1570
|
+
stroke: "currentColor",
|
|
1571
|
+
strokeWidth: 1,
|
|
1572
|
+
opacity: 0.25
|
|
1573
|
+
}
|
|
1574
|
+
) });
|
|
1575
|
+
}
|
|
1576
|
+
const min = Math.min(...data);
|
|
1577
|
+
const max = Math.max(...data);
|
|
1578
|
+
const range = max - min || 1;
|
|
1579
|
+
const step = data.length === 1 ? width : width / (data.length - 1);
|
|
1580
|
+
const points = data.map((v, i) => {
|
|
1581
|
+
const x = i * step;
|
|
1582
|
+
const y = height - (v - min) / range * (height - 2) - 1;
|
|
1583
|
+
return [x, y];
|
|
1584
|
+
});
|
|
1585
|
+
const linePath = points.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x.toFixed(2)},${y.toFixed(2)}`).join(" ");
|
|
1586
|
+
const areaPath = area ? `${linePath} L${width.toFixed(2)},${height.toFixed(2)} L0,${height.toFixed(2)} Z` : null;
|
|
1587
|
+
return /* @__PURE__ */ jsxs(
|
|
1588
|
+
"svg",
|
|
1589
|
+
{
|
|
1590
|
+
width,
|
|
1591
|
+
height,
|
|
1592
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
1593
|
+
className: cn("text-primary", className),
|
|
1594
|
+
"aria-hidden": true,
|
|
1595
|
+
children: [
|
|
1596
|
+
areaPath && /* @__PURE__ */ jsx("path", { d: areaPath, fill: "currentColor", opacity: 0.12 }),
|
|
1597
|
+
/* @__PURE__ */ jsx("path", { d: linePath, fill: "none", stroke: "currentColor", strokeWidth: 1.25 })
|
|
1598
|
+
]
|
|
1599
|
+
}
|
|
1600
|
+
);
|
|
1601
|
+
}
|
|
1602
|
+
function StatBlock({ label, value, sub, delta, tone = "default", className }) {
|
|
1603
|
+
const toneClass = tone === "success" ? "text-success" : tone === "warning" ? "text-warning" : tone === "destructive" ? "text-destructive" : "text-foreground";
|
|
1604
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
|
|
1605
|
+
/* @__PURE__ */ jsx("span", { className: "label-mono text-[10px]", children: label }),
|
|
1606
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-display text-2xl leading-none", toneClass), children: value }),
|
|
1607
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
1608
|
+
sub && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground font-mono text-[11px] tracking-wide lowercase", children: sub }),
|
|
1609
|
+
delta && /* @__PURE__ */ jsxs(
|
|
1610
|
+
"span",
|
|
1611
|
+
{
|
|
1612
|
+
className: cn(
|
|
1613
|
+
"font-mono text-[11px] tracking-wide",
|
|
1614
|
+
delta.value > 0 ? "text-success" : delta.value < 0 ? "text-destructive" : "text-muted-foreground"
|
|
1615
|
+
),
|
|
1616
|
+
children: [
|
|
1617
|
+
delta.value > 0 ? "\u25B2" : delta.value < 0 ? "\u25BC" : "\xB7",
|
|
1618
|
+
" ",
|
|
1619
|
+
Math.abs(delta.value).toFixed(1),
|
|
1620
|
+
delta.suffix ?? "%"
|
|
1621
|
+
]
|
|
1622
|
+
}
|
|
1623
|
+
)
|
|
1624
|
+
] })
|
|
1625
|
+
] });
|
|
1626
|
+
}
|
|
1627
|
+
var ACCENT = {
|
|
1628
|
+
primary: "bg-primary",
|
|
1629
|
+
warning: "bg-warning",
|
|
1630
|
+
destructive: "bg-destructive",
|
|
1631
|
+
success: "bg-success"
|
|
1632
|
+
};
|
|
1633
|
+
function Bar({ pct, accent = "primary", label, right, className }) {
|
|
1634
|
+
const clamped = Math.max(0, Math.min(100, pct));
|
|
1635
|
+
return /* @__PURE__ */ jsxs("div", { className: cn(className), children: [
|
|
1636
|
+
(label || right) && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between font-mono text-[10.5px] tracking-widest uppercase", children: [
|
|
1637
|
+
label && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label }),
|
|
1638
|
+
right && /* @__PURE__ */ jsx("span", { className: "text-foreground tabular-nums", children: right })
|
|
1639
|
+
] }),
|
|
1640
|
+
/* @__PURE__ */ jsx("div", { className: "bg-muted mt-1.5 h-1.5 w-full overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: cn("h-full", ACCENT[accent]), style: { width: `${clamped}%` } }) })
|
|
1641
|
+
] });
|
|
1642
|
+
}
|
|
1643
|
+
var TONE = {
|
|
1644
|
+
success: "text-success",
|
|
1645
|
+
warning: "text-warning",
|
|
1646
|
+
destructive: "text-destructive",
|
|
1647
|
+
muted: "text-muted-foreground",
|
|
1648
|
+
primary: "text-primary",
|
|
1649
|
+
info: "text-info"
|
|
1650
|
+
};
|
|
1651
|
+
function StatusPill({ label, tone = "muted", icon, className }) {
|
|
1652
|
+
return /* @__PURE__ */ jsxs(
|
|
1653
|
+
"span",
|
|
1654
|
+
{
|
|
1655
|
+
className: cn(
|
|
1656
|
+
"inline-flex items-center gap-1.5 font-mono text-[11px] tracking-wider lowercase",
|
|
1657
|
+
TONE[tone],
|
|
1658
|
+
className
|
|
1659
|
+
),
|
|
1660
|
+
children: [
|
|
1661
|
+
icon,
|
|
1662
|
+
label
|
|
1663
|
+
]
|
|
1664
|
+
}
|
|
1665
|
+
);
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
// src/format/index.ts
|
|
1669
|
+
var REFERENCE_BTC_USD = 95e3;
|
|
1670
|
+
function formatSats(sats) {
|
|
1671
|
+
return new Intl.NumberFormat("en-US").format(Math.round(sats));
|
|
1672
|
+
}
|
|
1673
|
+
function formatSatsCompact(sats) {
|
|
1674
|
+
const n = Math.round(sats);
|
|
1675
|
+
if (n < 1e3) return `${n} sats`;
|
|
1676
|
+
const k = n / 1e3;
|
|
1677
|
+
return `${Number.isInteger(k) ? k : k.toFixed(1)}k sats`;
|
|
1678
|
+
}
|
|
1679
|
+
function satsToUsd(sats, btcUsd = REFERENCE_BTC_USD) {
|
|
1680
|
+
const usd = sats / 1e8 * btcUsd;
|
|
1681
|
+
if (usd > 0 && usd < 0.01) return "< $0.01";
|
|
1682
|
+
const fractionDigits = usd >= 100 ? 0 : 2;
|
|
1683
|
+
return new Intl.NumberFormat("en-US", {
|
|
1684
|
+
style: "currency",
|
|
1685
|
+
currency: "USD",
|
|
1686
|
+
minimumFractionDigits: fractionDigits,
|
|
1687
|
+
maximumFractionDigits: fractionDigits
|
|
1688
|
+
}).format(usd);
|
|
1689
|
+
}
|
|
1690
|
+
function usdToSats(usd, btcUsd = REFERENCE_BTC_USD) {
|
|
1691
|
+
return Math.round(usd / btcUsd * 1e8);
|
|
1692
|
+
}
|
|
1693
|
+
function priceBoth(sats, btcUsd = REFERENCE_BTC_USD) {
|
|
1694
|
+
return `${formatSats(sats)} sats \xB7 ${satsToUsd(sats, btcUsd)}`;
|
|
1695
|
+
}
|
|
1696
|
+
function relativeTime(when) {
|
|
1697
|
+
const t = when instanceof Date ? when.getTime() : new Date(when).getTime();
|
|
1698
|
+
if (Number.isNaN(t)) return "";
|
|
1699
|
+
const diff = Date.now() - t;
|
|
1700
|
+
const m = Math.floor(diff / 6e4);
|
|
1701
|
+
if (m < 1) return "now";
|
|
1702
|
+
if (m < 60) return `${m}m ago`;
|
|
1703
|
+
const h = Math.floor(m / 60);
|
|
1704
|
+
if (h < 24) return `${h}h ago`;
|
|
1705
|
+
const d = Math.floor(h / 24);
|
|
1706
|
+
if (d < 30) return `${d}d ago`;
|
|
1707
|
+
const mo = Math.floor(d / 30);
|
|
1708
|
+
if (mo < 12) return `${mo}mo ago`;
|
|
1709
|
+
return `${Math.floor(mo / 12)}y ago`;
|
|
1710
|
+
}
|
|
1711
|
+
function shortenAddress(value, head = 8, tail = 4) {
|
|
1712
|
+
if (!value) return "";
|
|
1713
|
+
if (value.length <= head + tail + 1) return value;
|
|
1714
|
+
return `${value.slice(0, head)}\u2026${value.slice(-tail)}`;
|
|
1715
|
+
}
|
|
1716
|
+
function explorerUrl(target, network = "mainnet") {
|
|
1717
|
+
const base = network === "mainnet" ? "https://mempool.space" : `https://mempool.space/${network}`;
|
|
1718
|
+
if ("address" in target) return `${base}/address/${target.address}`;
|
|
1719
|
+
if ("tx" in target) return `${base}/tx/${target.tx}`;
|
|
1720
|
+
return `${base}/block/${target.block}`;
|
|
1721
|
+
}
|
|
1722
|
+
function SatsAmount({ sats, unit = true, usd = false, btcUsd, className }) {
|
|
1723
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("font-mono tabular-nums", className), children: [
|
|
1724
|
+
formatSats(sats),
|
|
1725
|
+
unit && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: " sats" }),
|
|
1726
|
+
usd && /* @__PURE__ */ jsxs("span", { className: "text-muted-foreground", children: [
|
|
1727
|
+
" \xB7 ",
|
|
1728
|
+
satsToUsd(sats, btcUsd)
|
|
1729
|
+
] })
|
|
1730
|
+
] });
|
|
1731
|
+
}
|
|
1732
|
+
function CopyButton({
|
|
1733
|
+
value,
|
|
1734
|
+
label,
|
|
1735
|
+
clearAfter,
|
|
1736
|
+
size = "md",
|
|
1737
|
+
className,
|
|
1738
|
+
title,
|
|
1739
|
+
onCopied
|
|
1740
|
+
}) {
|
|
1741
|
+
const [copied, setCopied] = useState(false);
|
|
1742
|
+
const resetRef = useRef(null);
|
|
1743
|
+
const copy = useCallback(async () => {
|
|
1744
|
+
try {
|
|
1745
|
+
await navigator.clipboard.writeText(value);
|
|
1746
|
+
setCopied(true);
|
|
1747
|
+
onCopied?.();
|
|
1748
|
+
if (resetRef.current) clearTimeout(resetRef.current);
|
|
1749
|
+
resetRef.current = setTimeout(() => setCopied(false), 1500);
|
|
1750
|
+
if (clearAfter && clearAfter > 0) {
|
|
1751
|
+
setTimeout(() => void wipeIfUnchanged(value), clearAfter * 1e3);
|
|
1752
|
+
}
|
|
1753
|
+
} catch {
|
|
1754
|
+
}
|
|
1755
|
+
}, [value, clearAfter, onCopied]);
|
|
1756
|
+
const iconSize = size === "sm" ? "size-3" : "size-3.5";
|
|
1757
|
+
return /* @__PURE__ */ jsxs(
|
|
1758
|
+
"button",
|
|
1759
|
+
{
|
|
1760
|
+
type: "button",
|
|
1761
|
+
onClick: copy,
|
|
1762
|
+
"aria-label": title ?? (copied ? "copied" : "copy"),
|
|
1763
|
+
title: title ?? "copy",
|
|
1764
|
+
className: cn(
|
|
1765
|
+
"text-muted-foreground hover:text-foreground inline-flex items-center gap-1.5 rounded-sm transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
1766
|
+
size === "sm" ? "text-[11px]" : "text-xs",
|
|
1767
|
+
className
|
|
1768
|
+
),
|
|
1769
|
+
children: [
|
|
1770
|
+
copied ? /* @__PURE__ */ jsx(Check, { className: cn(iconSize, "text-success"), "aria-hidden": true }) : /* @__PURE__ */ jsx(Copy, { className: iconSize, "aria-hidden": true }),
|
|
1771
|
+
label && /* @__PURE__ */ jsx("span", { className: "font-mono", children: copied ? "copied" : label })
|
|
1772
|
+
]
|
|
1773
|
+
}
|
|
1774
|
+
);
|
|
1775
|
+
}
|
|
1776
|
+
async function wipeIfUnchanged(expected) {
|
|
1777
|
+
try {
|
|
1778
|
+
const current = await navigator.clipboard.readText();
|
|
1779
|
+
if (current !== expected) return;
|
|
1780
|
+
await navigator.clipboard.writeText("");
|
|
1781
|
+
} catch {
|
|
1782
|
+
try {
|
|
1783
|
+
await navigator.clipboard.writeText("");
|
|
1784
|
+
} catch {
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
function BitcoinAddress({
|
|
1789
|
+
address,
|
|
1790
|
+
head = 8,
|
|
1791
|
+
tail = 4,
|
|
1792
|
+
copyable = true,
|
|
1793
|
+
full = false,
|
|
1794
|
+
className
|
|
1795
|
+
}) {
|
|
1796
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center gap-1.5 font-mono text-xs", className), children: [
|
|
1797
|
+
/* @__PURE__ */ jsx("span", { title: address, children: full ? address : shortenAddress(address, head, tail) }),
|
|
1798
|
+
copyable && /* @__PURE__ */ jsx(CopyButton, { value: address, size: "sm", title: "copy address" })
|
|
1799
|
+
] });
|
|
1800
|
+
}
|
|
1801
|
+
function QrCode({ value, size = 200, label, className }) {
|
|
1802
|
+
const [svg, setSvg] = useState(null);
|
|
1803
|
+
useEffect(() => {
|
|
1804
|
+
let cancelled = false;
|
|
1805
|
+
QRCode.toString(value, {
|
|
1806
|
+
type: "svg",
|
|
1807
|
+
errorCorrectionLevel: "M",
|
|
1808
|
+
margin: 1,
|
|
1809
|
+
color: { dark: "#000000", light: "#ffffff" }
|
|
1810
|
+
}).then((out) => {
|
|
1811
|
+
if (!cancelled) setSvg(out);
|
|
1812
|
+
}).catch(() => {
|
|
1813
|
+
if (!cancelled) setSvg(null);
|
|
1814
|
+
});
|
|
1815
|
+
return () => {
|
|
1816
|
+
cancelled = true;
|
|
1817
|
+
};
|
|
1818
|
+
}, [value]);
|
|
1819
|
+
return /* @__PURE__ */ jsx(
|
|
1820
|
+
"div",
|
|
1821
|
+
{
|
|
1822
|
+
role: "img",
|
|
1823
|
+
"aria-label": label ?? `QR code for ${value.slice(0, 24)}\u2026`,
|
|
1824
|
+
className: "inline-block overflow-hidden rounded-md bg-white p-3 " + (className ?? ""),
|
|
1825
|
+
style: { width: size, height: size },
|
|
1826
|
+
children: svg ? /* @__PURE__ */ jsx(
|
|
1827
|
+
"div",
|
|
1828
|
+
{
|
|
1829
|
+
className: "size-full [&_svg]:block [&_svg]:size-full",
|
|
1830
|
+
dangerouslySetInnerHTML: { __html: svg }
|
|
1831
|
+
}
|
|
1832
|
+
) : /* @__PURE__ */ jsx("div", { className: "bg-muted/40 size-full animate-pulse rounded", "aria-hidden": true })
|
|
1833
|
+
}
|
|
1834
|
+
);
|
|
1835
|
+
}
|
|
1478
1836
|
|
|
1479
1837
|
// src/components/index.ts
|
|
1480
1838
|
var components_exports = {};
|
|
@@ -1483,6 +1841,6 @@ __reExport(components_exports, ui_star);
|
|
|
1483
1841
|
// src/index.ts
|
|
1484
1842
|
__reExport(src_exports, components_exports);
|
|
1485
1843
|
|
|
1486
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertTitle, AlertWithAction, AlertWithCountdown, Badge, Button, ConfirmHost, DEFAULT_OC_THEME, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, ErrorBoundary, Input, Label, Modal, OC_SKIN_COOKIE, OC_THEMES, OcThemeBridge, OcThemePicker, OcThemeProvider, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PromptHost, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Skeleton, Textarea, ThemeToggle, ThemeToggleLink, Toaster, Working, WorkingPanel, badgeVariants, buttonVariants, cn, confirm, getOcThemeInitScript, isKnownTheme, prompt, resolveTheme, useOcSkin };
|
|
1844
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertTitle, AlertWithAction, AlertWithCountdown, Badge, Bar, BitcoinAddress, Button, Card, ConfirmHost, CopyButton, DEFAULT_OC_THEME, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, ErrorBoundary, Input, Label, Modal, OC_SKIN_COOKIE, OC_THEMES, OcThemeBridge, OcThemePicker, OcThemeProvider, Pagination, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PromptHost, QrCode, REFERENCE_BTC_USD, SatsAmount, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetContent, SheetDescription, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Skeleton, Sparkline, StatBlock, StatusPill, Textarea, ThemeToggle, ThemeToggleLink, Toaster, Working, WorkingPanel, badgeVariants, buttonVariants, cn, confirm, explorerUrl, formatSats, formatSatsCompact, getOcThemeInitScript, isKnownTheme, priceBoth, prompt, relativeTime, resolveTheme, satsToUsd, shortenAddress, usdToSats, useOcSkin };
|
|
1487
1845
|
//# sourceMappingURL=index.mjs.map
|
|
1488
1846
|
//# sourceMappingURL=index.mjs.map
|