@loafmarkets/ui 0.1.44 → 0.1.45

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.d.mts CHANGED
@@ -94,6 +94,12 @@ interface OrderbookProps extends React$1.HTMLAttributes<HTMLDivElement> {
94
94
  }[];
95
95
  /** When true, render skeleton placeholders in place of ask/bid rows and mid price. */
96
96
  isLoading?: boolean;
97
+ /**
98
+ * Called when the Loaf Liquidity badge in the right header is clicked. Consumers
99
+ * typically wire this to route to the Loaf Liquidity marketing page. Ignored if
100
+ * a custom `rightHeader` is supplied.
101
+ */
102
+ onLoafLiquidityClick?: () => void;
97
103
  }
98
104
  declare const Orderbook: React$1.ForwardRefExoticComponent<OrderbookProps & React$1.RefAttributes<HTMLDivElement>>;
99
105
 
package/dist/index.d.ts CHANGED
@@ -94,6 +94,12 @@ interface OrderbookProps extends React$1.HTMLAttributes<HTMLDivElement> {
94
94
  }[];
95
95
  /** When true, render skeleton placeholders in place of ask/bid rows and mid price. */
96
96
  isLoading?: boolean;
97
+ /**
98
+ * Called when the Loaf Liquidity badge in the right header is clicked. Consumers
99
+ * typically wire this to route to the Loaf Liquidity marketing page. Ignored if
100
+ * a custom `rightHeader` is supplied.
101
+ */
102
+ onLoafLiquidityClick?: () => void;
97
103
  }
98
104
  declare const Orderbook: React$1.ForwardRefExoticComponent<OrderbookProps & React$1.RefAttributes<HTMLDivElement>>;
99
105
 
package/dist/index.js CHANGED
@@ -1802,20 +1802,20 @@ function getTradeKey(trade, fallbackIndex) {
1802
1802
  if (trade.time != null) return `t-${trade.time}-${trade.type}-${trade.price}-${trade.amount}`;
1803
1803
  return `idx-${fallbackIndex}-${trade.type}-${trade.price}-${trade.amount}`;
1804
1804
  }
1805
- function useAmountChangeFlash(ref, amount) {
1805
+ function useAmountChangeFlash(ref, amount, side) {
1806
1806
  const prevAmountRef = React9__namespace.useRef(amount);
1807
1807
  React9__namespace.useEffect(() => {
1808
1808
  const prev = prevAmountRef.current;
1809
1809
  const node = ref.current;
1810
1810
  if (prev !== amount && node && typeof node.animate === "function") {
1811
- const color = amount > prev ? FLASH_UP_COLOR : FLASH_DOWN_COLOR;
1811
+ const color = side === "bid" ? FLASH_UP_COLOR : FLASH_DOWN_COLOR;
1812
1812
  node.animate(
1813
1813
  [{ backgroundColor: color }, { backgroundColor: "transparent" }],
1814
1814
  { duration: FLASH_DURATION_MS, easing: "ease-out" }
1815
1815
  );
1816
1816
  }
1817
1817
  prevAmountRef.current = amount;
1818
- }, [amount, ref]);
1818
+ }, [amount, ref, side]);
1819
1819
  }
1820
1820
  function useMidPriceFlash(ref, midPrice, restBgColor) {
1821
1821
  const prevMidRef = React9__namespace.useRef(midPrice);
@@ -1905,41 +1905,49 @@ function DepthRow({
1905
1905
  }) {
1906
1906
  const isAsk = side === "ask";
1907
1907
  const rowRef = React9__namespace.useRef(null);
1908
- useAmountChangeFlash(rowRef, amount);
1909
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: rowRef, className: "relative grid grid-cols-2 items-center gap-3 px-3 py-1.5", children: [
1910
- /* @__PURE__ */ jsxRuntime.jsx(
1911
- "div",
1912
- {
1913
- className: cn(
1914
- "absolute inset-y-0 right-0",
1915
- isAsk ? "bg-rose-900/30" : "bg-emerald-900/30"
1908
+ useAmountChangeFlash(rowRef, amount, side);
1909
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1910
+ "div",
1911
+ {
1912
+ ref: rowRef,
1913
+ className: "relative grid grid-cols-2 items-center gap-3 px-3 text-[0.8rem]",
1914
+ style: { height: `${DEPTH_ROW_HEIGHT_PX}px` },
1915
+ children: [
1916
+ /* @__PURE__ */ jsxRuntime.jsx(
1917
+ "div",
1918
+ {
1919
+ className: cn(
1920
+ "absolute inset-y-0 right-0",
1921
+ isAsk ? "bg-rose-900/30" : "bg-emerald-900/30"
1922
+ ),
1923
+ style: { width: `${clamp3(depthPct, 0, 100)}%`, transition: "width 300ms ease-out" }
1924
+ }
1916
1925
  ),
1917
- style: { width: `${clamp3(depthPct, 0, 100)}%`, transition: "width 300ms ease-out" }
1918
- }
1919
- ),
1920
- hasUserOrder ? /* @__PURE__ */ jsxRuntime.jsx(
1921
- "span",
1922
- {
1923
- "aria-label": "Your order at this price",
1924
- className: "absolute left-0 top-0 bottom-0 z-[2] w-[3px] rounded-r-sm bg-[#C9A227] shadow-[0_0_6px_rgba(201,162,39,0.6)]"
1925
- }
1926
- ) : null,
1927
- /* @__PURE__ */ jsxRuntime.jsxs(
1928
- "div",
1929
- {
1930
- className: cn("relative z-[1] tabular-nums", isAsk ? "text-[#f6465d]" : "text-[#0ecb81]"),
1931
- children: [
1932
- "$",
1933
- formatNumber(price, precision)
1934
- ]
1935
- }
1936
- ),
1937
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-[1] text-right tabular-nums text-white/90", children: formatNumber(amount, amountPrecision) })
1938
- ] });
1926
+ hasUserOrder ? /* @__PURE__ */ jsxRuntime.jsx(
1927
+ "span",
1928
+ {
1929
+ "aria-label": "Your order at this price",
1930
+ 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)]"
1931
+ }
1932
+ ) : null,
1933
+ /* @__PURE__ */ jsxRuntime.jsxs(
1934
+ "div",
1935
+ {
1936
+ className: cn("relative z-[1] tabular-nums", isAsk ? "text-[#f6465d]" : "text-[#0ecb81]"),
1937
+ children: [
1938
+ "$",
1939
+ formatNumber(price, precision)
1940
+ ]
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative z-[1] text-right tabular-nums text-white/90", children: formatNumber(amount, amountPrecision) })
1944
+ ]
1945
+ }
1946
+ );
1939
1947
  }
1940
1948
  var clamp3 = (value, min, max) => Math.min(max, Math.max(min, value));
1941
1949
  var LEVEL_ROWS_VISIBLE = 6;
1942
- var DEPTH_ROW_HEIGHT_PX = 34;
1950
+ var DEPTH_ROW_HEIGHT_PX = 26;
1943
1951
  var COMPACT_ROWS_VISIBLE = 5;
1944
1952
  var COMPACT_ROW_HEIGHT_PX = 30;
1945
1953
  var COMPACT_BREAKPOINT_PX = 1024;
@@ -1956,13 +1964,15 @@ var Orderbook = React9__namespace.forwardRef(
1956
1964
  amountPrecision = 2,
1957
1965
  defaultTab = "orderbook",
1958
1966
  onTabChange,
1959
- rightHeader = /* @__PURE__ */ jsxRuntime.jsx(LoafLiquidityBadge, { className: "text-[0.6rem]" }),
1967
+ rightHeader,
1960
1968
  variant = "auto",
1961
1969
  userOrderPrices,
1962
1970
  isLoading = false,
1971
+ onLoafLiquidityClick,
1963
1972
  className,
1964
1973
  ...props
1965
1974
  }, ref) => {
1975
+ const resolvedRightHeader = rightHeader ?? /* @__PURE__ */ jsxRuntime.jsx(LoafLiquidityBadge, { className: "text-[0.6rem]", onClick: onLoafLiquidityClick });
1966
1976
  const [tab, setTab] = React9__namespace.useState(defaultTab);
1967
1977
  const [tradeFilter, setTradeFilter] = React9__namespace.useState("all");
1968
1978
  const viewportCompact = useViewportCompact(COMPACT_BREAKPOINT_PX);
@@ -2013,7 +2023,7 @@ var Orderbook = React9__namespace.forwardRef(
2013
2023
  handleTab,
2014
2024
  tradeFilter,
2015
2025
  setTradeFilter,
2016
- rightHeader,
2026
+ rightHeader: resolvedRightHeader,
2017
2027
  priceLabel,
2018
2028
  amountLabel,
2019
2029
  tradeFiltered,
@@ -2199,9 +2209,9 @@ function DesktopOrderbookLayout({
2199
2209
  /* @__PURE__ */ jsxRuntime.jsx(
2200
2210
  "div",
2201
2211
  {
2202
- className: "flex flex-col justify-end divide-y divide-white/5 overflow-y-auto",
2203
- style: { height: `${sectionHeight}px`, scrollbarGutter: "stable" },
2204
- children: isLoading ? Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, {}, `ask-skel-${i}`)) : asks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-3 text-xs text-white/40", children: "No asks" }) : asks.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
2212
+ className: "flex flex-col justify-end divide-y divide-white/5 overflow-hidden",
2213
+ style: { height: `${sectionHeight}px` },
2214
+ children: isLoading ? Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, {}, `ask-skel-${i}`)) : asks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-3 text-xs text-white/40", children: "No asks" }) : asks.slice(-LEVEL_ROWS_VISIBLE).map((l) => /* @__PURE__ */ jsxRuntime.jsx(
2205
2215
  DepthRow,
2206
2216
  {
2207
2217
  side: "ask",
@@ -2238,9 +2248,9 @@ function DesktopOrderbookLayout({
2238
2248
  /* @__PURE__ */ jsxRuntime.jsx(
2239
2249
  "div",
2240
2250
  {
2241
- className: "divide-y divide-white/5 overflow-y-auto",
2242
- style: { height: `${sectionHeight}px`, scrollbarGutter: "stable" },
2243
- children: isLoading ? Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, {}, `bid-skel-${i}`)) : bids.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-3 text-xs text-white/40", children: "No bids" }) : bids.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
2251
+ className: "divide-y divide-white/5 overflow-hidden",
2252
+ style: { height: `${sectionHeight}px` },
2253
+ children: isLoading ? Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, {}, `bid-skel-${i}`)) : bids.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-3 text-xs text-white/40", children: "No bids" }) : bids.slice(0, LEVEL_ROWS_VISIBLE).map((l) => /* @__PURE__ */ jsxRuntime.jsx(
2244
2254
  DepthRow,
2245
2255
  {
2246
2256
  side: "bid",
@@ -2285,7 +2295,7 @@ function MobileOrderbookLayout({
2285
2295
  }) {
2286
2296
  const midRef = React9__namespace.useRef(null);
2287
2297
  useMidPriceFlash(midRef, midPrice, "transparent");
2288
- const visibleAsks = React9__namespace.useMemo(() => asks.slice(0, COMPACT_ROWS_VISIBLE), [asks]);
2298
+ const visibleAsks = React9__namespace.useMemo(() => asks.slice(-COMPACT_ROWS_VISIBLE), [asks]);
2289
2299
  const visibleBids = React9__namespace.useMemo(() => bids.slice(0, COMPACT_ROWS_VISIBLE), [bids]);
2290
2300
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2291
2301
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
@@ -2455,7 +2465,7 @@ function MobileDepthRow({
2455
2465
  }) {
2456
2466
  const isAsk = side === "ask";
2457
2467
  const rowRef = React9__namespace.useRef(null);
2458
- useAmountChangeFlash(rowRef, amount);
2468
+ useAmountChangeFlash(rowRef, amount, side);
2459
2469
  return /* @__PURE__ */ jsxRuntime.jsxs(
2460
2470
  "div",
2461
2471
  {
@@ -2474,14 +2484,14 @@ function MobileDepthRow({
2474
2484
  "aria-label": "Your order at this price",
2475
2485
  style: {
2476
2486
  position: "absolute",
2477
- left: 0,
2478
- top: 0,
2479
- bottom: 0,
2480
- width: "3px",
2487
+ left: "6px",
2488
+ top: "50%",
2489
+ transform: "translateY(-50%)",
2490
+ width: "6px",
2491
+ height: "6px",
2492
+ borderRadius: "50%",
2481
2493
  backgroundColor: "#C9A227",
2482
- boxShadow: "0 0 6px rgba(201,162,39,0.6)",
2483
- borderTopRightRadius: "2px",
2484
- borderBottomRightRadius: "2px",
2494
+ boxShadow: "0 0 6px rgba(201,162,39,0.7)",
2485
2495
  zIndex: 2
2486
2496
  }
2487
2497
  }