@loafmarkets/ui 0.1.52 → 0.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1807,13 +1807,17 @@ function useMidPriceFlash(ref, midPrice, restBgColor) {
1807
1807
  prevMidRef.current = midPrice;
1808
1808
  }, [midPrice, ref, restBgColor]);
1809
1809
  }
1810
+ function ExternalLinkIcon() {
1811
+ return /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M1 9L9 1M9 1H4M9 1V6", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
1812
+ }
1810
1813
  function TradeRow({
1811
1814
  trade,
1812
1815
  tradeKey,
1813
1816
  precision,
1814
1817
  amountPrecision,
1815
1818
  seenTradeKeysRef,
1816
- compact
1819
+ compact,
1820
+ explorerUrl
1817
1821
  }) {
1818
1822
  const rowRef = React5.useRef(null);
1819
1823
  const { type } = trade;
@@ -1833,14 +1837,27 @@ function TradeRow({
1833
1837
  "div",
1834
1838
  {
1835
1839
  ref: rowRef,
1836
- className: "grid",
1840
+ className: "grid items-center",
1837
1841
  style: { gridTemplateColumns: "1.2fr 0.8fr", padding: "0.2rem 0", fontSize: "0.8rem" },
1838
1842
  children: [
1839
1843
  /* @__PURE__ */ jsxs("div", { style: { color: trade.type === "buy" ? "#0ecb81" : "#f6465d", fontWeight: 500 }, children: [
1840
1844
  "$",
1841
1845
  formatNumber(trade.price, precision)
1842
1846
  ] }),
1843
- /* @__PURE__ */ jsx("div", { style: { textAlign: "right", paddingRight: "0.5rem" }, children: formatNumber(trade.amount, amountPrecision) })
1847
+ /* @__PURE__ */ jsxs("div", { style: { textAlign: "right", paddingRight: "0.5rem", display: "flex", alignItems: "center", justifyContent: "flex-end", gap: "4px" }, children: [
1848
+ formatNumber(trade.amount, amountPrecision),
1849
+ explorerUrl && /* @__PURE__ */ jsx(
1850
+ "a",
1851
+ {
1852
+ href: explorerUrl,
1853
+ target: "_blank",
1854
+ rel: "noopener noreferrer",
1855
+ style: { color: "rgba(255,255,255,0.35)", lineHeight: 0 },
1856
+ onClick: (e) => e.stopPropagation(),
1857
+ children: /* @__PURE__ */ jsx(ExternalLinkIcon, {})
1858
+ }
1859
+ )
1860
+ ] })
1844
1861
  ]
1845
1862
  }
1846
1863
  );
@@ -1849,7 +1866,7 @@ function TradeRow({
1849
1866
  "div",
1850
1867
  {
1851
1868
  ref: rowRef,
1852
- className: "grid grid-cols-2 items-center gap-3 px-3 py-1.5",
1869
+ className: "grid grid-cols-3 items-center gap-3 px-3 py-1.5",
1853
1870
  children: [
1854
1871
  /* @__PURE__ */ jsxs(
1855
1872
  "div",
@@ -1864,7 +1881,22 @@ function TradeRow({
1864
1881
  ]
1865
1882
  }
1866
1883
  ),
1867
- /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums text-white/90", children: formatNumber(trade.amount, amountPrecision) })
1884
+ /* @__PURE__ */ jsx("div", { className: "text-right tabular-nums text-white/90", children: formatNumber(trade.amount, amountPrecision) }),
1885
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
1886
+ trade.time != null && /* @__PURE__ */ jsx("span", { className: "tabular-nums text-white/50 text-xs", children: trade.time }),
1887
+ explorerUrl && /* @__PURE__ */ jsx(
1888
+ "a",
1889
+ {
1890
+ href: explorerUrl,
1891
+ target: "_blank",
1892
+ rel: "noopener noreferrer",
1893
+ className: "text-white/35 hover:text-white/70 transition-colors",
1894
+ onClick: (e) => e.stopPropagation(),
1895
+ "aria-label": "View on explorer",
1896
+ children: /* @__PURE__ */ jsx(ExternalLinkIcon, {})
1897
+ }
1898
+ )
1899
+ ] })
1868
1900
  ]
1869
1901
  }
1870
1902
  );
@@ -1873,6 +1905,7 @@ function DepthRow({
1873
1905
  side,
1874
1906
  price,
1875
1907
  amount,
1908
+ cumDepth,
1876
1909
  depthPct,
1877
1910
  precision,
1878
1911
  amountPrecision,
@@ -1885,7 +1918,7 @@ function DepthRow({
1885
1918
  "div",
1886
1919
  {
1887
1920
  ref: rowRef,
1888
- className: "relative grid grid-cols-2 items-center gap-3 px-3 text-[0.8rem]",
1921
+ className: "relative grid grid-cols-3 items-center gap-3 px-3 text-[0.8rem]",
1889
1922
  style: { height: `${DEPTH_ROW_HEIGHT_PX}px` },
1890
1923
  children: [
1891
1924
  /* @__PURE__ */ jsx(
@@ -1905,17 +1938,12 @@ function DepthRow({
1905
1938
  className: "absolute left-2 top-1/2 -translate-y-1/2 z-[2] h-[6px] w-[6px] rounded-full bg-[#C9A227] shadow-[0_0_6px_rgba(201,162,39,0.7)]"
1906
1939
  }
1907
1940
  ) : null,
1908
- /* @__PURE__ */ jsxs(
1909
- "div",
1910
- {
1911
- className: cn("relative z-[1] tabular-nums", isAsk ? "text-[#f6465d]" : "text-[#0ecb81]"),
1912
- children: [
1913
- "$",
1914
- formatNumber(price, precision)
1915
- ]
1916
- }
1917
- ),
1918
- /* @__PURE__ */ jsx("div", { className: "relative z-[1] text-right tabular-nums text-white/90", children: formatNumber(amount, amountPrecision) })
1941
+ /* @__PURE__ */ jsxs("div", { className: cn("relative z-[1] tabular-nums", isAsk ? "text-[#f6465d]" : "text-[#0ecb81]"), children: [
1942
+ "$",
1943
+ formatNumber(price, precision)
1944
+ ] }),
1945
+ /* @__PURE__ */ jsx("div", { className: "relative z-[1] text-right tabular-nums text-white/90", children: formatNumber(amount, amountPrecision) }),
1946
+ /* @__PURE__ */ jsx("div", { className: "relative z-[1] text-right tabular-nums text-white/50", children: formatNumber(cumDepth, amountPrecision) })
1919
1947
  ]
1920
1948
  }
1921
1949
  );
@@ -1944,6 +1972,7 @@ var Orderbook = React5.forwardRef(
1944
1972
  userOrderPrices,
1945
1973
  isLoading = false,
1946
1974
  onLoafLiquidityClick,
1975
+ tradeExplorerUrl,
1947
1976
  className,
1948
1977
  ...props
1949
1978
  }, ref) => {
@@ -2036,7 +2065,8 @@ var Orderbook = React5.forwardRef(
2036
2065
  userAskPrices,
2037
2066
  userBidPrices,
2038
2067
  isLoading,
2039
- seenTradeKeysRef
2068
+ seenTradeKeysRef,
2069
+ tradeExplorerUrl
2040
2070
  };
2041
2071
  return /* @__PURE__ */ jsx(
2042
2072
  Card,
@@ -2072,9 +2102,10 @@ function SkeletonRow({ compact }) {
2072
2102
  }
2073
2103
  );
2074
2104
  }
2075
- return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-center gap-3 px-3 py-1.5", children: [
2105
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 items-center gap-3 px-3 py-1.5", children: [
2076
2106
  /* @__PURE__ */ jsx(Skeleton, { width: "60%", height: 12 }),
2077
- /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Skeleton, { width: "50%", height: 12 }) })
2107
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Skeleton, { width: "50%", height: 12 }) }),
2108
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: /* @__PURE__ */ jsx(Skeleton, { width: "40%", height: 12 }) })
2078
2109
  ] });
2079
2110
  }
2080
2111
  function DesktopOrderbookLayout({
@@ -2100,7 +2131,8 @@ function DesktopOrderbookLayout({
2100
2131
  userAskPrices,
2101
2132
  userBidPrices,
2102
2133
  isLoading,
2103
- seenTradeKeysRef
2134
+ seenTradeKeysRef,
2135
+ tradeExplorerUrl
2104
2136
  }) {
2105
2137
  const midRef = React5.useRef(null);
2106
2138
  useMidPriceFlash(midRef, midPrice, "#0b1a24");
@@ -2178,9 +2210,10 @@ function DesktopOrderbookLayout({
2178
2210
  ] }) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: rightHeader })
2179
2211
  ] }),
2180
2212
  /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col min-h-0 px-4 pt-2", children: [
2181
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3 px-3 py-2 text-xs text-white/60", children: [
2213
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3 px-3 py-2 text-xs text-white/60", children: [
2182
2214
  /* @__PURE__ */ jsx("div", { children: priceLabel }),
2183
- /* @__PURE__ */ jsx("div", { className: "text-right", children: amountLabel })
2215
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: amountLabel }),
2216
+ /* @__PURE__ */ jsx("div", { className: "text-right", children: tab === "orderbook" ? "Total" : "Time" })
2184
2217
  ] }),
2185
2218
  tab === "trades" ? /* @__PURE__ */ jsx(
2186
2219
  "div",
@@ -2189,6 +2222,7 @@ function DesktopOrderbookLayout({
2189
2222
  style: { scrollbarGutter: "stable" },
2190
2223
  children: isLoading && tradeFiltered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "divide-y divide-white/5", children: Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsx(SkeletonRow, {}, `trade-skel-${i}`)) }) : tradeFiltered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-10 text-center text-sm text-white/50", children: "No trades" }) : /* @__PURE__ */ jsx("div", { className: "divide-y divide-white/5", children: tradeFiltered.map((trade, i) => {
2191
2224
  const tradeKey = getTradeKey(trade, i);
2225
+ const explorerUrl = trade.txHash && tradeExplorerUrl ? tradeExplorerUrl(trade.txHash) : trade.txHash ? `https://sepolia.etherscan.io/tx/${trade.txHash}` : void 0;
2192
2226
  return /* @__PURE__ */ jsx(
2193
2227
  TradeRow,
2194
2228
  {
@@ -2196,7 +2230,8 @@ function DesktopOrderbookLayout({
2196
2230
  tradeKey,
2197
2231
  precision,
2198
2232
  amountPrecision,
2199
- seenTradeKeysRef
2233
+ seenTradeKeysRef,
2234
+ explorerUrl
2200
2235
  },
2201
2236
  tradeKey
2202
2237
  );
@@ -2214,6 +2249,7 @@ function DesktopOrderbookLayout({
2214
2249
  side: "ask",
2215
2250
  price: l.price,
2216
2251
  amount: l.amount,
2252
+ cumDepth: askCumDepths[i],
2217
2253
  depthPct: askCumDepths[i] / combinedMaxCumDepth * 100,
2218
2254
  precision,
2219
2255
  amountPrecision,
@@ -2253,6 +2289,7 @@ function DesktopOrderbookLayout({
2253
2289
  side: "bid",
2254
2290
  price: l.price,
2255
2291
  amount: l.amount,
2292
+ cumDepth: bidCumDepths[i],
2256
2293
  depthPct: bidCumDepths[i] / combinedMaxCumDepth * 100,
2257
2294
  precision,
2258
2295
  amountPrecision,
@@ -2289,7 +2326,8 @@ function MobileOrderbookLayout({
2289
2326
  userAskPrices,
2290
2327
  userBidPrices,
2291
2328
  isLoading,
2292
- seenTradeKeysRef
2329
+ seenTradeKeysRef,
2330
+ tradeExplorerUrl
2293
2331
  }) {
2294
2332
  const midRef = React5.useRef(null);
2295
2333
  useMidPriceFlash(midRef, midPrice, "transparent");
@@ -2434,6 +2472,7 @@ function MobileOrderbookLayout({
2434
2472
  ),
2435
2473
  /* @__PURE__ */ jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: isLoading && tradeFiltered.length === 0 ? Array.from({ length: COMPACT_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsx(SkeletonRow, { compact: true }, `m-trade-skel-${i}`)) : tradeFiltered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-6 text-center text-[0.7rem] text-white/50", children: "No trades" }) : tradeFiltered.map((trade, i) => {
2436
2474
  const tradeKey = getTradeKey(trade, i);
2475
+ const explorerUrl = trade.txHash && tradeExplorerUrl ? tradeExplorerUrl(trade.txHash) : trade.txHash ? `https://sepolia.etherscan.io/tx/${trade.txHash}` : void 0;
2437
2476
  return /* @__PURE__ */ jsx(
2438
2477
  TradeRow,
2439
2478
  {
@@ -2442,7 +2481,8 @@ function MobileOrderbookLayout({
2442
2481
  precision,
2443
2482
  amountPrecision,
2444
2483
  seenTradeKeysRef,
2445
- compact: true
2484
+ compact: true,
2485
+ explorerUrl
2446
2486
  },
2447
2487
  tradeKey
2448
2488
  );