@gearbox-protocol/permissionless-ui 1.4.3 → 1.5.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.
@@ -38,7 +38,7 @@ var import_class_variance_authority = require("class-variance-authority");
38
38
  var React = __toESM(require("react"));
39
39
  var import_utils = __toESM(require('../../utils/index.js'));
40
40
  const buttonVariants = (0, import_class_variance_authority.cva)(
41
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-transparent",
41
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-transparent outline-none focus-visible:outline-none",
42
42
  {
43
43
  variants: {
44
44
  variant: {
@@ -33,24 +33,28 @@ __export(detailed_page_title_exports, {
33
33
  module.exports = __toCommonJS(detailed_page_title_exports);
34
34
  var import_jsx_runtime = require("react/jsx-runtime");
35
35
  var import_lucide_react = require("lucide-react");
36
+ var React = __toESM(require("react"));
36
37
  var import_utils = __toESM(require('../utils/index.js'));
37
38
  var import_copy = require('../utils/copy.js');
38
39
  var import_button = require('./buttons/button.js');
39
40
  var import_dropdown_menu = require('./dropdown-menu/index.js');
40
41
  var import_page_title = require('./page-title.js');
41
42
  var import_token_icon = require('./token-icon.js');
43
+ var import_typed_intl = require('./typed-intl/index.js');
42
44
  function DetailedPageTitle({
43
45
  title,
44
46
  token,
45
47
  toCopy,
46
48
  explorerLinks,
47
- className,
48
- onCopySuccess
49
+ className
49
50
  }) {
51
+ const intl = (0, import_typed_intl.useIntlTyped)();
52
+ const [isPressed, setIsPressed] = React.useState(false);
50
53
  const handleCopy = () => {
51
54
  if (toCopy) {
52
55
  (0, import_copy.copyToClipboard)({ text: toCopy });
53
- onCopySuccess?.();
56
+ setIsPressed(true);
57
+ setTimeout(() => setIsPressed(false), 150);
54
58
  }
55
59
  };
56
60
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -65,6 +69,10 @@ function DetailedPageTitle({
65
69
  size: "icon",
66
70
  onClick: handleCopy,
67
71
  title: "Copy address",
72
+ className: (0, import_utils.default)(
73
+ "transition-all",
74
+ isPressed ? "scale-75" : "scale-100"
75
+ ),
68
76
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Copy, { className: "h-4 w-4" })
69
77
  }
70
78
  ),
@@ -61,8 +61,8 @@ const graphViewVariants = (0, import_class_variance_authority.cva)(
61
61
  padding: {
62
62
  none: "p-0",
63
63
  sm: "p-2",
64
- default: "p-6",
65
- lg: "p-8"
64
+ default: "p-4 sm:p-6",
65
+ lg: "p-6"
66
66
  }
67
67
  },
68
68
  defaultVariants: {
@@ -37,6 +37,7 @@ var import_jsx_runtime = require("react/jsx-runtime");
37
37
  var import_lightweight_charts = require("lightweight-charts");
38
38
  var React = __toESM(require("react"));
39
39
  var import_react = require("react");
40
+ var import_use_media_query = require('../../hooks/use-media-query.js');
40
41
  var import_cn = require('../../utils/cn.js');
41
42
  var import_colors = require('../../utils/colors.js');
42
43
  var import_default_config = require('./default-config.js');
@@ -100,6 +101,7 @@ function Graph({
100
101
  const chartRef = (0, import_react.useRef)(null);
101
102
  const seriesRefs = (0, import_react.useRef)(/* @__PURE__ */ new Map());
102
103
  const parentRef = (0, import_react.useRef)(null);
104
+ const isMobile = (0, import_use_media_query.useIsMobile)();
103
105
  const allPoints = React.useMemo(() => {
104
106
  return series.flatMap((s) => s.data);
105
107
  }, [series]);
@@ -145,7 +147,7 @@ function Graph({
145
147
  const hasZero = allPoints.some((p) => p.value === 0);
146
148
  const shouldPreventNegativeAxis = !hasNegativeValues && hasZero;
147
149
  const useMultiplePriceScales = series.length > 1;
148
- const shouldHideScaleLabels = useMultiplePriceScales;
150
+ const shouldHideScaleLabels = useMultiplePriceScales || isMobile;
149
151
  const defaultOptions = (0, import_default_config.getDefaultOptions)();
150
152
  const chart = initChart(graphId, {
151
153
  ...defaultOptions,
@@ -166,6 +168,7 @@ function Graph({
166
168
  },
167
169
  rightPriceScale: {
168
170
  ...defaultOptions.rightPriceScale || {},
171
+ visible: !isMobile,
169
172
  ...shouldPreventNegativeAxis && {
170
173
  scaleMargins: {
171
174
  top: 0.3,
@@ -308,7 +311,8 @@ function Graph({
308
311
  xMeasureUnit,
309
312
  yMeasureUnit,
310
313
  optionsOverrides,
311
- subscribeLegendMove
314
+ subscribeLegendMove,
315
+ isMobile
312
316
  ]);
313
317
  (0, import_react.useEffect)(() => {
314
318
  const ch = chartRef.current;
@@ -42,8 +42,7 @@ const BAD_HF = 11e3;
42
42
  const CRITICAL_HF = 10500;
43
43
  const getHFZones = (hf) => {
44
44
  if (!hf) return void 0;
45
- const numHf = Number(hf);
46
- const hfInBasisPoints = numHf < 1e3 ? numHf * import_format_money.PERCENTAGE_FACTOR : numHf;
45
+ const hfInBasisPoints = Number(hf);
47
46
  if (hfInBasisPoints >= GOOD_HF) return "good";
48
47
  if (hfInBasisPoints > BAD_HF) return "medium";
49
48
  if (hfInBasisPoints > CRITICAL_HF) return "bad";
@@ -84,8 +83,7 @@ function HealthFactor({
84
83
  const renderValue = () => {
85
84
  if (zeroDebt) return "N/A";
86
85
  const numValue = Number(value);
87
- const hfInBasisPoints = numValue < 1e3 ? numValue * import_format_money.PERCENTAGE_FACTOR : numValue;
88
- const hfDecimal = hfInBasisPoints / import_format_money.PERCENTAGE_FACTOR;
86
+ const hfDecimal = numValue / import_format_money.PERCENTAGE_FACTOR;
89
87
  const formatted = (0, import_format_money.formatPercentAmount)(hfDecimal, decimals);
90
88
  return String(formatted);
91
89
  };
@@ -28,13 +28,24 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var header_exports = {};
30
30
  __export(header_exports, {
31
- Header: () => Header
31
+ Header: () => Header,
32
+ useMobileMenu: () => useMobileMenu
32
33
  });
33
34
  module.exports = __toCommonJS(header_exports);
34
35
  var import_jsx_runtime = require("react/jsx-runtime");
35
36
  var import_lucide_react = require("lucide-react");
36
37
  var import_react = __toESM(require("react"));
37
38
  var import_cn = require('../../utils/cn.js');
39
+ const MobileMenuContext = import_react.default.createContext(
40
+ null
41
+ );
42
+ function useMobileMenu() {
43
+ const context = import_react.default.useContext(MobileMenuContext);
44
+ if (!context) {
45
+ throw new Error("useMobileMenu must be used within Header component");
46
+ }
47
+ return context;
48
+ }
38
49
  const Header = import_react.default.forwardRef(
39
50
  ({
40
51
  navigation,
@@ -87,10 +98,16 @@ const Header = import_react.default.forwardRef(
87
98
  ]
88
99
  }
89
100
  ),
90
- mobileMenuOpen && (navigation || mobileMenuContent) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute top-full left-0 right-0 bg-background border-b border-border md:hidden z-40 shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col px-4 py-4 space-y-2", children: [
91
- mobileMenuContent || navigation,
92
- actions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2 pt-4 border-t border-border mt-4", children: actions })
93
- ] }) })
101
+ mobileMenuOpen && (navigation || mobileMenuContent) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
102
+ MobileMenuContext.Provider,
103
+ {
104
+ value: { closeMobileMenu: () => setMobileMenuOpen(false) },
105
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "absolute top-full left-0 right-0 bg-background border-b border-border md:hidden z-40 shadow-lg", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col px-4 py-4 space-y-2", children: [
106
+ mobileMenuContent || navigation,
107
+ actions && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-col gap-2 pt-4 border-t border-border mt-4", children: actions })
108
+ ] }) })
109
+ }
110
+ )
94
111
  ]
95
112
  }
96
113
  );
@@ -99,5 +116,6 @@ const Header = import_react.default.forwardRef(
99
116
  Header.displayName = "Header";
100
117
  // Annotate the CommonJS export names for ESM import in node:
101
118
  0 && (module.exports = {
102
- Header
119
+ Header,
120
+ useMobileMenu
103
121
  });
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var liquidation_graph_exports = {};
30
20
  __export(liquidation_graph_exports, {
@@ -33,23 +23,12 @@ __export(liquidation_graph_exports, {
33
23
  module.exports = __toCommonJS(liquidation_graph_exports);
34
24
  var import_jsx_runtime = require("react/jsx-runtime");
35
25
  var import_react = require("react");
36
- var ColorHeatmapModule = __toESM(require("reactochart/ColorHeatmap"));
37
- var XAxisModule = __toESM(require("reactochart/XAxis"));
38
- var XLineModule = __toESM(require("reactochart/XLine"));
39
- var XYPlotModule = __toESM(require("reactochart/XYPlot"));
40
- var YAxisModule = __toESM(require("reactochart/YAxis"));
41
- var YLineModule = __toESM(require("reactochart/YLine"));
42
26
  var import_use_hf = require('../../hooks/use-hf.js');
43
27
  var import_use_liquidation = require('../../hooks/use-liquidation/index.js');
28
+ var import_reactochart_compat = require('../../utils/reactochart-compat.js');
44
29
  var import_vspace = require('../vspace.js');
45
30
  var import_liquidation_graph_legend = require('./liquidation-graph-legend.js');
46
31
  var import_liquidation_graph_tip = require('./liquidation-graph-tip.js');
47
- const ColorHeatmap = ColorHeatmapModule.default || ColorHeatmapModule;
48
- const XAxis = XAxisModule.default || XAxisModule;
49
- const XLine = XLineModule.default || XLineModule;
50
- const XYPlot = XYPlotModule.default || XYPlotModule;
51
- const YAxis = YAxisModule.default || YAxisModule;
52
- const YLine = YLineModule.default || YLineModule;
53
32
  const WIDTH = 300;
54
33
  const HEIGHT = 300;
55
34
  const CROSSHAIR_X = "rct-crosshair-x";
@@ -156,7 +135,7 @@ function LiquidationGraph({
156
135
  ) }),
157
136
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_vspace.VSpace, { height: 16 }),
158
137
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "w-full liquidation-graph-container", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
159
- XYPlot,
138
+ import_reactochart_compat.XYPlot,
160
139
  {
161
140
  width,
162
141
  height,
@@ -166,7 +145,7 @@ function LiquidationGraph({
166
145
  onMouseLeave: handleMouseLeave,
167
146
  children: [
168
147
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
169
- XAxis,
148
+ import_reactochart_compat.XAxis,
170
149
  {
171
150
  showLine: false,
172
151
  title: (0, import_use_liquidation.formatAxisTipLabel)(xLabel, underlyingToken, xOrder),
@@ -180,7 +159,7 @@ function LiquidationGraph({
180
159
  }
181
160
  ),
182
161
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
183
- YAxis,
162
+ import_reactochart_compat.YAxis,
184
163
  {
185
164
  showLine: false,
186
165
  title: (0, import_use_liquidation.formatAxisTipLabel)(yLabel, underlyingToken, yOrder),
@@ -194,7 +173,7 @@ function LiquidationGraph({
194
173
  }
195
174
  ),
196
175
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
197
- ColorHeatmap,
176
+ import_reactochart_compat.ColorHeatmap,
198
177
  {
199
178
  data: heatmap,
200
179
  value: (d) => d.value,
@@ -205,8 +184,8 @@ function LiquidationGraph({
205
184
  rectClassName: (p) => (0, import_use_liquidation.getCellClass)(p, currentPoint, activePointX, activePointY)
206
185
  }
207
186
  ),
208
- activePointX !== void 0 && activePointX !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XLine, { value: activePointX, className: CROSSHAIR_X }),
209
- activePointY !== void 0 && activePointY !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YLine, { value: activePointY, className: CROSSHAIR_Y })
187
+ activePointX !== void 0 && activePointX !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_reactochart_compat.XLine, { value: activePointX, className: CROSSHAIR_X }),
188
+ activePointY !== void 0 && activePointY !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_reactochart_compat.YLine, { value: activePointY, className: CROSSHAIR_Y })
210
189
  ]
211
190
  }
212
191
  ) }),
@@ -43,11 +43,11 @@ const navitemVariants = (0, import_class_variance_authority.cva)(
43
43
  {
44
44
  variants: {
45
45
  variant: {
46
- default: "text-decoration-none text-foreground hover:text-foreground hover:bg-secondary",
47
- active: "text-foreground",
48
- ghost: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-secondary",
49
- link: "text-decoration-none text-muted-foreground hover:text-foreground underline-offset-4 hover:underline",
50
- pill: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-accent rounded-full",
46
+ default: "text-decoration-none text-foreground hover:text-foreground hover:bg-secondary data-[active=true]:bg-secondary md:data-[active=true]:bg-transparent data-[active=true]:text-foreground",
47
+ active: "text-foreground bg-secondary",
48
+ ghost: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-secondary data-[active=true]:bg-secondary md:data-[active=true]:bg-transparent data-[active=true]:text-foreground",
49
+ link: "text-decoration-none text-muted-foreground hover:text-foreground underline-offset-4 hover:underline data-[active=true]:text-foreground data-[active=true]:underline",
50
+ pill: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-accent rounded-full data-[active=true]:bg-accent data-[active=true]:text-foreground",
51
51
  tab: "text-decoration-none text-muted-foreground hover:text-foreground border-b-2 border-transparent hover:border-border data-[active=true]:border-primary data-[active=true]:text-foreground rounded-none"
52
52
  },
53
53
  size: {
@@ -63,7 +63,7 @@ function TableLineSm({
63
63
  "div",
64
64
  {
65
65
  className: (0, import_utils.default)(
66
- "flex flex-col gap-3 p-4 border-b border-border",
66
+ "flex flex-col gap-3 py-3 px-0 md:px-4 border-b border-border",
67
67
  className
68
68
  ),
69
69
  ...props,
@@ -72,7 +72,7 @@ function TableLineSm({
72
72
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
73
73
  "div",
74
74
  {
75
- className: "grid gap-4 table-sm-grid",
75
+ className: "grid gap-2 md:gap-4 table-sm-grid",
76
76
  style: {
77
77
  "--grid-cols-xs": colsXs,
78
78
  "--grid-cols-sm": colsSm,
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var reactochart_compat_exports = {};
30
+ __export(reactochart_compat_exports, {
31
+ ColorHeatmap: () => ColorHeatmap,
32
+ XAxis: () => XAxis,
33
+ XLine: () => XLine,
34
+ XYPlot: () => XYPlot,
35
+ YAxis: () => YAxis,
36
+ YLine: () => YLine
37
+ });
38
+ module.exports = __toCommonJS(reactochart_compat_exports);
39
+ var import_ColorHeatmap = __toESM(require("reactochart/ColorHeatmap"));
40
+ var import_XAxis = __toESM(require("reactochart/XAxis"));
41
+ var import_XLine = __toESM(require("reactochart/XLine"));
42
+ var import_XYPlot = __toESM(require("reactochart/XYPlot"));
43
+ var import_YAxis = __toESM(require("reactochart/YAxis"));
44
+ var import_YLine = __toESM(require("reactochart/YLine"));
45
+ function resolveDefault(mod) {
46
+ return mod.default || mod;
47
+ }
48
+ const ColorHeatmap = resolveDefault(import_ColorHeatmap.default);
49
+ const XAxis = resolveDefault(import_XAxis.default);
50
+ const XLine = resolveDefault(import_XLine.default);
51
+ const XYPlot = resolveDefault(import_XYPlot.default);
52
+ const YAxis = resolveDefault(import_YAxis.default);
53
+ const YLine = resolveDefault(import_YLine.default);
54
+ // Annotate the CommonJS export names for ESM import in node:
55
+ 0 && (module.exports = {
56
+ ColorHeatmap,
57
+ XAxis,
58
+ XLine,
59
+ XYPlot,
60
+ YAxis,
61
+ YLine
62
+ });
@@ -4,7 +4,7 @@ import { cva } from "class-variance-authority";
4
4
  import * as React from "react";
5
5
  import cn from "../../utils/index.js";
6
6
  const buttonVariants = cva(
7
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-transparent",
7
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors cursor-pointer disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-transparent outline-none focus-visible:outline-none",
8
8
  {
9
9
  variants: {
10
10
  variant: {
@@ -1,5 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Copy, ExternalLink } from "lucide-react";
3
+ import * as React from "react";
3
4
  import cn from "../utils/index.js";
4
5
  import { copyToClipboard } from "../utils/copy.js";
5
6
  import { Button } from "./buttons/button.js";
@@ -11,18 +12,21 @@ import {
11
12
  } from "./dropdown-menu/index.js";
12
13
  import { PageTitle } from "./page-title.js";
13
14
  import { TokenIcon } from "./token-icon.js";
15
+ import { useIntlTyped } from "./typed-intl/index.js";
14
16
  function DetailedPageTitle({
15
17
  title,
16
18
  token,
17
19
  toCopy,
18
20
  explorerLinks,
19
- className,
20
- onCopySuccess
21
+ className
21
22
  }) {
23
+ const intl = useIntlTyped();
24
+ const [isPressed, setIsPressed] = React.useState(false);
22
25
  const handleCopy = () => {
23
26
  if (toCopy) {
24
27
  copyToClipboard({ text: toCopy });
25
- onCopySuccess?.();
28
+ setIsPressed(true);
29
+ setTimeout(() => setIsPressed(false), 150);
26
30
  }
27
31
  };
28
32
  return /* @__PURE__ */ jsx(
@@ -37,6 +41,10 @@ function DetailedPageTitle({
37
41
  size: "icon",
38
42
  onClick: handleCopy,
39
43
  title: "Copy address",
44
+ className: cn(
45
+ "transition-all",
46
+ isPressed ? "scale-75" : "scale-100"
47
+ ),
40
48
  children: /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" })
41
49
  }
42
50
  ),
@@ -25,8 +25,8 @@ const graphViewVariants = cva(
25
25
  padding: {
26
26
  none: "p-0",
27
27
  sm: "p-2",
28
- default: "p-6",
29
- lg: "p-8"
28
+ default: "p-4 sm:p-6",
29
+ lg: "p-6"
30
30
  }
31
31
  },
32
32
  defaultVariants: {
@@ -3,6 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { createChart } from "lightweight-charts";
4
4
  import * as React from "react";
5
5
  import { useCallback, useEffect, useRef, useState } from "react";
6
+ import { useIsMobile } from "../../hooks/use-media-query.js";
6
7
  import { cn } from "../../utils/cn.js";
7
8
  import { generateColorsFromBase } from "../../utils/colors.js";
8
9
  import {
@@ -70,6 +71,7 @@ function Graph({
70
71
  const chartRef = useRef(null);
71
72
  const seriesRefs = useRef(/* @__PURE__ */ new Map());
72
73
  const parentRef = useRef(null);
74
+ const isMobile = useIsMobile();
73
75
  const allPoints = React.useMemo(() => {
74
76
  return series.flatMap((s) => s.data);
75
77
  }, [series]);
@@ -115,7 +117,7 @@ function Graph({
115
117
  const hasZero = allPoints.some((p) => p.value === 0);
116
118
  const shouldPreventNegativeAxis = !hasNegativeValues && hasZero;
117
119
  const useMultiplePriceScales = series.length > 1;
118
- const shouldHideScaleLabels = useMultiplePriceScales;
120
+ const shouldHideScaleLabels = useMultiplePriceScales || isMobile;
119
121
  const defaultOptions = getDefaultOptions();
120
122
  const chart = initChart(graphId, {
121
123
  ...defaultOptions,
@@ -136,6 +138,7 @@ function Graph({
136
138
  },
137
139
  rightPriceScale: {
138
140
  ...defaultOptions.rightPriceScale || {},
141
+ visible: !isMobile,
139
142
  ...shouldPreventNegativeAxis && {
140
143
  scaleMargins: {
141
144
  top: 0.3,
@@ -278,7 +281,8 @@ function Graph({
278
281
  xMeasureUnit,
279
282
  yMeasureUnit,
280
283
  optionsOverrides,
281
- subscribeLegendMove
284
+ subscribeLegendMove,
285
+ isMobile
282
286
  ]);
283
287
  useEffect(() => {
284
288
  const ch = chartRef.current;
@@ -6,8 +6,7 @@ const BAD_HF = 11e3;
6
6
  const CRITICAL_HF = 10500;
7
7
  const getHFZones = (hf) => {
8
8
  if (!hf) return void 0;
9
- const numHf = Number(hf);
10
- const hfInBasisPoints = numHf < 1e3 ? numHf * PERCENTAGE_FACTOR : numHf;
9
+ const hfInBasisPoints = Number(hf);
11
10
  if (hfInBasisPoints >= GOOD_HF) return "good";
12
11
  if (hfInBasisPoints > BAD_HF) return "medium";
13
12
  if (hfInBasisPoints > CRITICAL_HF) return "bad";
@@ -48,8 +47,7 @@ function HealthFactor({
48
47
  const renderValue = () => {
49
48
  if (zeroDebt) return "N/A";
50
49
  const numValue = Number(value);
51
- const hfInBasisPoints = numValue < 1e3 ? numValue * PERCENTAGE_FACTOR : numValue;
52
- const hfDecimal = hfInBasisPoints / PERCENTAGE_FACTOR;
50
+ const hfDecimal = numValue / PERCENTAGE_FACTOR;
53
51
  const formatted = formatPercentAmount(hfDecimal, decimals);
54
52
  return String(formatted);
55
53
  };
@@ -2,6 +2,16 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Menu, X } from "lucide-react";
3
3
  import React from "react";
4
4
  import { cn } from "../../utils/cn.js";
5
+ const MobileMenuContext = React.createContext(
6
+ null
7
+ );
8
+ function useMobileMenu() {
9
+ const context = React.useContext(MobileMenuContext);
10
+ if (!context) {
11
+ throw new Error("useMobileMenu must be used within Header component");
12
+ }
13
+ return context;
14
+ }
5
15
  const Header = React.forwardRef(
6
16
  ({
7
17
  navigation,
@@ -54,10 +64,16 @@ const Header = React.forwardRef(
54
64
  ]
55
65
  }
56
66
  ),
57
- mobileMenuOpen && (navigation || mobileMenuContent) && /* @__PURE__ */ jsx("div", { className: "absolute top-full left-0 right-0 bg-background border-b border-border md:hidden z-40 shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-4 py-4 space-y-2", children: [
58
- mobileMenuContent || navigation,
59
- actions && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 pt-4 border-t border-border mt-4", children: actions })
60
- ] }) })
67
+ mobileMenuOpen && (navigation || mobileMenuContent) && /* @__PURE__ */ jsx(
68
+ MobileMenuContext.Provider,
69
+ {
70
+ value: { closeMobileMenu: () => setMobileMenuOpen(false) },
71
+ children: /* @__PURE__ */ jsx("div", { className: "absolute top-full left-0 right-0 bg-background border-b border-border md:hidden z-40 shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-4 py-4 space-y-2", children: [
72
+ mobileMenuContent || navigation,
73
+ actions && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2 pt-4 border-t border-border mt-4", children: actions })
74
+ ] }) })
75
+ }
76
+ )
61
77
  ]
62
78
  }
63
79
  );
@@ -65,5 +81,6 @@ const Header = React.forwardRef(
65
81
  );
66
82
  Header.displayName = "Header";
67
83
  export {
68
- Header
84
+ Header,
85
+ useMobileMenu
69
86
  };
@@ -1,11 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useCallback } from "react";
3
- import * as ColorHeatmapModule from "reactochart/ColorHeatmap";
4
- import * as XAxisModule from "reactochart/XAxis";
5
- import * as XLineModule from "reactochart/XLine";
6
- import * as XYPlotModule from "reactochart/XYPlot";
7
- import * as YAxisModule from "reactochart/YAxis";
8
- import * as YLineModule from "reactochart/YLine";
9
3
  import { useHF } from "../../hooks/use-hf.js";
10
4
  import {
11
5
  DEFAULT_AXIS_MAX,
@@ -19,15 +13,17 @@ import {
19
13
  useLiquidationHeatmap,
20
14
  useWithLiquidationGraphActivePrices
21
15
  } from "../../hooks/use-liquidation/index.js";
16
+ import {
17
+ ColorHeatmap,
18
+ XAxis,
19
+ XLine,
20
+ XYPlot,
21
+ YAxis,
22
+ YLine
23
+ } from "../../utils/reactochart-compat.js";
22
24
  import { VSpace } from "../vspace.js";
23
25
  import { LiquidationGraphLegend } from "./liquidation-graph-legend.js";
24
26
  import { LiquidationGraphTip } from "./liquidation-graph-tip.js";
25
- const ColorHeatmap = ColorHeatmapModule.default || ColorHeatmapModule;
26
- const XAxis = XAxisModule.default || XAxisModule;
27
- const XLine = XLineModule.default || XLineModule;
28
- const XYPlot = XYPlotModule.default || XYPlotModule;
29
- const YAxis = YAxisModule.default || YAxisModule;
30
- const YLine = YLineModule.default || YLineModule;
31
27
  const WIDTH = 300;
32
28
  const HEIGHT = 300;
33
29
  const CROSSHAIR_X = "rct-crosshair-x";
@@ -9,11 +9,11 @@ const navitemVariants = cva(
9
9
  {
10
10
  variants: {
11
11
  variant: {
12
- default: "text-decoration-none text-foreground hover:text-foreground hover:bg-secondary",
13
- active: "text-foreground",
14
- ghost: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-secondary",
15
- link: "text-decoration-none text-muted-foreground hover:text-foreground underline-offset-4 hover:underline",
16
- pill: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-accent rounded-full",
12
+ default: "text-decoration-none text-foreground hover:text-foreground hover:bg-secondary data-[active=true]:bg-secondary md:data-[active=true]:bg-transparent data-[active=true]:text-foreground",
13
+ active: "text-foreground bg-secondary",
14
+ ghost: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-secondary data-[active=true]:bg-secondary md:data-[active=true]:bg-transparent data-[active=true]:text-foreground",
15
+ link: "text-decoration-none text-muted-foreground hover:text-foreground underline-offset-4 hover:underline data-[active=true]:text-foreground data-[active=true]:underline",
16
+ pill: "text-decoration-none text-muted-foreground hover:text-foreground hover:bg-accent rounded-full data-[active=true]:bg-accent data-[active=true]:text-foreground",
17
17
  tab: "text-decoration-none text-muted-foreground hover:text-foreground border-b-2 border-transparent hover:border-border data-[active=true]:border-primary data-[active=true]:text-foreground rounded-none"
18
18
  },
19
19
  size: {
@@ -29,7 +29,7 @@ function TableLineSm({
29
29
  "div",
30
30
  {
31
31
  className: cn(
32
- "flex flex-col gap-3 p-4 border-b border-border",
32
+ "flex flex-col gap-3 py-3 px-0 md:px-4 border-b border-border",
33
33
  className
34
34
  ),
35
35
  ...props,
@@ -38,7 +38,7 @@ function TableLineSm({
38
38
  /* @__PURE__ */ jsx(
39
39
  "div",
40
40
  {
41
- className: "grid gap-4 table-sm-grid",
41
+ className: "grid gap-2 md:gap-4 table-sm-grid",
42
42
  style: {
43
43
  "--grid-cols-xs": colsXs,
44
44
  "--grid-cols-sm": colsSm,
@@ -0,0 +1,23 @@
1
+ function resolveDefault(mod) {
2
+ return mod.default || mod;
3
+ }
4
+ import ColorHeatmapImport from "reactochart/ColorHeatmap";
5
+ import XAxisImport from "reactochart/XAxis";
6
+ import XLineImport from "reactochart/XLine";
7
+ import XYPlotImport from "reactochart/XYPlot";
8
+ import YAxisImport from "reactochart/YAxis";
9
+ import YLineImport from "reactochart/YLine";
10
+ const ColorHeatmap = resolveDefault(ColorHeatmapImport);
11
+ const XAxis = resolveDefault(XAxisImport);
12
+ const XLine = resolveDefault(XLineImport);
13
+ const XYPlot = resolveDefault(XYPlotImport);
14
+ const YAxis = resolveDefault(YAxisImport);
15
+ const YLine = resolveDefault(YLineImport);
16
+ export {
17
+ ColorHeatmap,
18
+ XAxis,
19
+ XLine,
20
+ XYPlot,
21
+ YAxis,
22
+ YLine
23
+ };
@@ -1,5 +1,5 @@
1
1
  import type { TokenData } from "@gearbox-protocol/sdk";
2
- import type * as React from "react";
2
+ import * as React from "react";
3
3
  export interface ExplorerLink {
4
4
  link: string;
5
5
  label: string;
@@ -10,7 +10,6 @@ export interface DetailedPageTitleProps {
10
10
  toCopy?: string;
11
11
  explorerLinks?: Array<ExplorerLink>;
12
12
  className?: string;
13
- onCopySuccess?: () => void;
14
13
  }
15
14
  /**
16
15
  * DetailedPageTitle - page title with token icon, copy functionality, and explorer links
@@ -28,4 +27,4 @@ export interface DetailedPageTitleProps {
28
27
  * />
29
28
  * ```
30
29
  */
31
- export declare function DetailedPageTitle({ title, token, toCopy, explorerLinks, className, onCopySuccess, }: DetailedPageTitleProps): React.ReactElement;
30
+ export declare function DetailedPageTitle({ title, token, toCopy, explorerLinks, className, }: DetailedPageTitleProps): React.ReactElement;
@@ -4,17 +4,15 @@ export declare const GOOD_HF = 15000;
4
4
  export declare const BAD_HF = 11000;
5
5
  /**
6
6
  * Determines the health factor zone based on the value
7
- * @param hf - Health factor value (in basis points if >= 1000, otherwise as decimal)
7
+ * @param hf - Health factor value in basis points (e.g., 15000 for 1.5)
8
8
  * @returns The health factor zone or undefined
9
9
  */
10
10
  export declare const getHFZones: (hf: number | bigint | undefined) => HFZones | undefined;
11
11
  export interface HealthFactorProps extends React.HTMLAttributes<HTMLDivElement> {
12
12
  /**
13
- * The health factor value
14
- * Can be provided as:
15
- * - Decimal value (e.g., 1.5 for 150%)
16
- * - Basis points (e.g., 15000 for 150%)
17
- * Values >= 1000 are treated as basis points, < 1000 as decimal
13
+ * The health factor value in basis points
14
+ * For example: 15000 for health factor 1.5, 500 for health factor 0.05
15
+ * (SDK always returns health factor in basis points: 10000 = 1.0)
18
16
  */
19
17
  value: number | bigint;
20
18
  /**
@@ -49,15 +47,13 @@ export interface HealthFactorProps extends React.HTMLAttributes<HTMLDivElement>
49
47
  *
50
48
  * @example
51
49
  * ```tsx
52
- * // Using decimal value
53
- * <HealthFactor value={1.5} debt={1000000n} /> // Shows "1.500" in green
54
- * <HealthFactor value={1.2} debt={1000000n} decimals={2} /> // Shows "1.20" in yellow
55
- *
56
- * // Using basis points
50
+ * // Health factor in basis points (SDK format)
57
51
  * <HealthFactor value={15000} debt={1000000n} /> // Shows "1.500" in green
52
+ * <HealthFactor value={12000} debt={1000000n} decimals={2} /> // Shows "1.20" in yellow
53
+ * <HealthFactor value={500} debt={1000000n} /> // Shows "0.050" in red
58
54
  *
59
55
  * // Zero debt shows N/A
60
- * <HealthFactor value={1.5} debt={0n} /> // Shows "N/A"
56
+ * <HealthFactor value={15000} debt={0n} /> // Shows "N/A"
61
57
  * ```
62
58
  */
63
59
  export declare function HealthFactor({ value, debt, decimals, zone, showColor, className, ...props }: HealthFactorProps): import("react/jsx-runtime").JSX.Element;
@@ -1,4 +1,25 @@
1
1
  import React from "react";
2
+ interface MobileMenuContextValue {
3
+ closeMobileMenu: () => void;
4
+ }
5
+ /**
6
+ * Hook to access mobile menu control functions
7
+ * Use this hook inside mobileMenuContent to close the menu on navigation
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function MobileNav() {
12
+ * const { closeMobileMenu } = useMobileMenu();
13
+ *
14
+ * return (
15
+ * <nav>
16
+ * <a href="/" onClick={closeMobileMenu}>Home</a>
17
+ * </nav>
18
+ * );
19
+ * }
20
+ * ```
21
+ */
22
+ export declare function useMobileMenu(): MobileMenuContextValue;
2
23
  export interface HeaderProps extends React.HTMLAttributes<HTMLElement> {
3
24
  /**
4
25
  * Navigation content (shown on desktop, hidden on mobile unless specified)
@@ -79,3 +100,4 @@ export interface HeaderProps extends React.HTMLAttributes<HTMLElement> {
79
100
  * ```
80
101
  */
81
102
  export declare const Header: React.ForwardRefExoticComponent<HeaderProps & React.RefAttributes<HTMLElement>>;
103
+ export {};
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Compatibility layer for reactochart CommonJS modules in ESM context
3
+ * Handles the default export resolution for CommonJS modules
4
+ */
5
+ import ColorHeatmapImport from "reactochart/ColorHeatmap";
6
+ import XAxisImport from "reactochart/XAxis";
7
+ import XLineImport from "reactochart/XLine";
8
+ import XYPlotImport from "reactochart/XYPlot";
9
+ import YAxisImport from "reactochart/YAxis";
10
+ import YLineImport from "reactochart/YLine";
11
+ export declare const ColorHeatmap: typeof ColorHeatmapImport;
12
+ export declare const XAxis: typeof XAxisImport;
13
+ export declare const XLine: typeof XLineImport;
14
+ export declare const XYPlot: typeof XYPlotImport;
15
+ export declare const YAxis: typeof YAxisImport;
16
+ export declare const YLine: typeof YLineImport;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/permissionless-ui",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "description": "Internal UI components",
5
5
  "license": "MIT",
6
6
  "main": "./dist/cjs/index.js",
@@ -65,9 +65,8 @@
65
65
  "react-infinite-scroll-component": "^6.1.0",
66
66
  "react-markdown": "^9.0.3",
67
67
  "react-markdown-math": "^1.0.2",
68
- "reactochart": "^6.1.1",
69
68
  "remark-gfm": "^4.0.0",
70
- "sonner": "^1.7.2",
69
+ "sonner": "^2.0.7",
71
70
  "tailwind-merge": "^2.6.0",
72
71
  "tailwindcss-animate": "^1.0.7"
73
72
  },
@@ -82,6 +81,8 @@
82
81
  "react-dom": "^18 || ^19",
83
82
  "react-intl": "^6.0.0 || ^7.0.0",
84
83
  "react-router-dom": "^6.0.0 || ^7.0.0",
84
+ "reactochart": "^6.1.1",
85
+ "sonner": "^2.0.0",
85
86
  "viem": "^2.0.0",
86
87
  "wagmi": "^2.0.0"
87
88
  },
@@ -94,6 +95,9 @@
94
95
  },
95
96
  "react-router-dom": {
96
97
  "optional": true
98
+ },
99
+ "sonner": {
100
+ "optional": true
97
101
  }
98
102
  },
99
103
  "devDependencies": {
@@ -122,6 +126,7 @@
122
126
  "react-dom": "^19.1.1",
123
127
  "react-intl": "^6.7.4",
124
128
  "react-router-dom": "^7.9.6",
129
+ "reactochart": "^6.1.1",
125
130
  "tailwindcss": "^4.1.14",
126
131
  "tsup": "^8.5.0",
127
132
  "typescript": "^5.9.3",