@loafmarkets/ui 0.1.42 → 0.1.44
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 +63 -6
- package/dist/index.d.ts +63 -6
- package/dist/index.js +793 -354
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +676 -240
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React9 = require('react');
|
|
4
4
|
var reactSlot = require('@radix-ui/react-slot');
|
|
5
5
|
var classVarianceAuthority = require('class-variance-authority');
|
|
6
6
|
var clsx = require('clsx');
|
|
@@ -33,7 +33,7 @@ function _interopNamespace(e) {
|
|
|
33
33
|
return Object.freeze(n);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
var
|
|
36
|
+
var React9__namespace = /*#__PURE__*/_interopNamespace(React9);
|
|
37
37
|
var styled24__default = /*#__PURE__*/_interopDefault(styled24);
|
|
38
38
|
var LightweightCharts__namespace = /*#__PURE__*/_interopNamespace(LightweightCharts);
|
|
39
39
|
|
|
@@ -75,7 +75,7 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
);
|
|
78
|
-
var Button =
|
|
78
|
+
var Button = React9__namespace.forwardRef(
|
|
79
79
|
({ className, variant, size, radius, asChild = false, ...props }, ref) => {
|
|
80
80
|
const Comp = asChild ? reactSlot.Slot : "button";
|
|
81
81
|
const coercedRadius = radius ?? (variant === "onboarding" || variant === "onboardingOutline" ? "square" : void 0);
|
|
@@ -114,11 +114,11 @@ var badgeVariants = classVarianceAuthority.cva(
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
);
|
|
117
|
-
var Badge =
|
|
117
|
+
var Badge = React9__namespace.forwardRef(
|
|
118
118
|
({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn(badgeVariants({ variant, size }), className), ...props })
|
|
119
119
|
);
|
|
120
120
|
Badge.displayName = "Badge";
|
|
121
|
-
var Card =
|
|
121
|
+
var Card = React9__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
122
122
|
"div",
|
|
123
123
|
{
|
|
124
124
|
ref,
|
|
@@ -130,11 +130,11 @@ var Card = React5__namespace.forwardRef(({ className, ...props }, ref) => /* @__
|
|
|
130
130
|
}
|
|
131
131
|
));
|
|
132
132
|
Card.displayName = "Card";
|
|
133
|
-
var CardHeader =
|
|
133
|
+
var CardHeader = React9__namespace.forwardRef(
|
|
134
134
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })
|
|
135
135
|
);
|
|
136
136
|
CardHeader.displayName = "CardHeader";
|
|
137
|
-
var CardTitle =
|
|
137
|
+
var CardTitle = React9__namespace.forwardRef(
|
|
138
138
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
139
139
|
"h3",
|
|
140
140
|
{
|
|
@@ -145,15 +145,15 @@ var CardTitle = React5__namespace.forwardRef(
|
|
|
145
145
|
)
|
|
146
146
|
);
|
|
147
147
|
CardTitle.displayName = "CardTitle";
|
|
148
|
-
var CardDescription =
|
|
148
|
+
var CardDescription = React9__namespace.forwardRef(
|
|
149
149
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-slate-500", className), ...props })
|
|
150
150
|
);
|
|
151
151
|
CardDescription.displayName = "CardDescription";
|
|
152
|
-
var CardContent =
|
|
152
|
+
var CardContent = React9__namespace.forwardRef(
|
|
153
153
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("px-6 pb-6 pt-2 text-sm text-slate-600", className), ...props })
|
|
154
154
|
);
|
|
155
155
|
CardContent.displayName = "CardContent";
|
|
156
|
-
var CardFooter =
|
|
156
|
+
var CardFooter = React9__namespace.forwardRef(
|
|
157
157
|
({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center border-t border-slate-100 px-6 py-4", className), ...props })
|
|
158
158
|
);
|
|
159
159
|
CardFooter.displayName = "CardFooter";
|
|
@@ -171,7 +171,7 @@ var defaultFormatSignedCurrency = (value) => {
|
|
|
171
171
|
const sign = value >= 0 ? "+" : "-";
|
|
172
172
|
return `${sign}${defaultFormatCurrency(Math.abs(value))}`;
|
|
173
173
|
};
|
|
174
|
-
var PortfolioSummary =
|
|
174
|
+
var PortfolioSummary = React9__namespace.forwardRef(
|
|
175
175
|
({
|
|
176
176
|
availableCash,
|
|
177
177
|
portfolioValue,
|
|
@@ -321,23 +321,23 @@ function HousePositionSlider({
|
|
|
321
321
|
className,
|
|
322
322
|
...props
|
|
323
323
|
}) {
|
|
324
|
-
const [orderMode, setOrderMode] =
|
|
325
|
-
const [buyTrackingMode, setBuyTrackingMode] =
|
|
326
|
-
const [deltaDollars, setDeltaDollars] =
|
|
327
|
-
const [deltaTokensBuy, setDeltaTokensBuy] =
|
|
328
|
-
const [deltaTokensSell, setDeltaTokensSell] =
|
|
329
|
-
const [_isDragging, setIsDragging] =
|
|
330
|
-
const [visualTargetPct, setVisualTargetPct] =
|
|
331
|
-
const [orderType, setOrderType] =
|
|
332
|
-
const [limitPrice, setLimitPrice] =
|
|
333
|
-
const [limitPriceInput, setLimitPriceInput] =
|
|
334
|
-
const [limitPriceDirty, setLimitPriceDirty] =
|
|
335
|
-
const [ownershipInput, setOwnershipInput] =
|
|
336
|
-
const [tokenAmountInput, setTokenAmountInput] =
|
|
337
|
-
const houseRef =
|
|
324
|
+
const [orderMode, setOrderMode] = React9__namespace.useState("none");
|
|
325
|
+
const [buyTrackingMode, setBuyTrackingMode] = React9__namespace.useState("dollars");
|
|
326
|
+
const [deltaDollars, setDeltaDollars] = React9__namespace.useState(0);
|
|
327
|
+
const [deltaTokensBuy, setDeltaTokensBuy] = React9__namespace.useState(0);
|
|
328
|
+
const [deltaTokensSell, setDeltaTokensSell] = React9__namespace.useState(0);
|
|
329
|
+
const [_isDragging, setIsDragging] = React9__namespace.useState(false);
|
|
330
|
+
const [visualTargetPct, setVisualTargetPct] = React9__namespace.useState(null);
|
|
331
|
+
const [orderType, setOrderType] = React9__namespace.useState(defaultOrderType);
|
|
332
|
+
const [limitPrice, setLimitPrice] = React9__namespace.useState(currentPrice);
|
|
333
|
+
const [limitPriceInput, setLimitPriceInput] = React9__namespace.useState(currentPrice.toFixed(2));
|
|
334
|
+
const [limitPriceDirty, setLimitPriceDirty] = React9__namespace.useState(false);
|
|
335
|
+
const [ownershipInput, setOwnershipInput] = React9__namespace.useState("");
|
|
336
|
+
const [tokenAmountInput, setTokenAmountInput] = React9__namespace.useState("");
|
|
337
|
+
const houseRef = React9__namespace.useRef(null);
|
|
338
338
|
const asks = orderbook?.asks ?? [];
|
|
339
339
|
const bids = orderbook?.bids ?? [];
|
|
340
|
-
|
|
340
|
+
React9__namespace.useEffect(() => {
|
|
341
341
|
if (orderType !== "limit") return;
|
|
342
342
|
if (limitPriceDirty) return;
|
|
343
343
|
setLimitPrice(currentPrice);
|
|
@@ -412,7 +412,7 @@ function HousePositionSlider({
|
|
|
412
412
|
const impliedDisplayTargetOwnership = clamp(targetOwnership + ownershipShift, 0, 100);
|
|
413
413
|
const displayTargetOwnership = visualTargetPct ?? impliedDisplayTargetOwnership;
|
|
414
414
|
const estFeeTokens = Math.abs(deltaValue) * 5e-3 / (effectivePrice || 1);
|
|
415
|
-
const resetOrder =
|
|
415
|
+
const resetOrder = React9__namespace.useCallback(() => {
|
|
416
416
|
setOrderMode("none");
|
|
417
417
|
setBuyTrackingMode("dollars");
|
|
418
418
|
setDeltaDollars(0);
|
|
@@ -420,7 +420,7 @@ function HousePositionSlider({
|
|
|
420
420
|
setDeltaTokensSell(0);
|
|
421
421
|
setVisualTargetPct(null);
|
|
422
422
|
}, []);
|
|
423
|
-
const updateOrderFromTargetValue =
|
|
423
|
+
const updateOrderFromTargetValue = React9__namespace.useCallback(
|
|
424
424
|
(newTargetValue) => {
|
|
425
425
|
const newDeltaValue = newTargetValue - holdingsValue;
|
|
426
426
|
if (newDeltaValue > 0) {
|
|
@@ -444,7 +444,7 @@ function HousePositionSlider({
|
|
|
444
444
|
},
|
|
445
445
|
[effectiveAvailableCash, effectivePrice, effectiveTokensHeld, holdingsValue, resetOrder, tokensHeld]
|
|
446
446
|
);
|
|
447
|
-
const updateOrderFromOwnership =
|
|
447
|
+
const updateOrderFromOwnership = React9__namespace.useCallback(
|
|
448
448
|
(newOwnershipPercent) => {
|
|
449
449
|
const nextOwnership = clamp(newOwnershipPercent, 0, 100);
|
|
450
450
|
const newTargetTokens = nextOwnership / 100 * totalTokens;
|
|
@@ -453,7 +453,7 @@ function HousePositionSlider({
|
|
|
453
453
|
},
|
|
454
454
|
[effectivePrice, totalTokens, updateOrderFromTargetValue]
|
|
455
455
|
);
|
|
456
|
-
const updateOrderFromTokenAmount =
|
|
456
|
+
const updateOrderFromTokenAmount = React9__namespace.useCallback(
|
|
457
457
|
(tokenAmountSigned) => {
|
|
458
458
|
if (tokenAmountSigned > 0) {
|
|
459
459
|
const maxTokens = effectiveAvailableCash / (effectivePrice || 1);
|
|
@@ -476,7 +476,7 @@ function HousePositionSlider({
|
|
|
476
476
|
},
|
|
477
477
|
[effectiveAvailableCash, effectivePrice, effectiveTokensHeld, resetOrder]
|
|
478
478
|
);
|
|
479
|
-
const updateOrderFromSlider =
|
|
479
|
+
const updateOrderFromSlider = React9__namespace.useCallback(
|
|
480
480
|
(pct) => {
|
|
481
481
|
const normalized = (pct - 50) / 50;
|
|
482
482
|
const magnitude = Math.min(Math.abs(normalized), 1);
|
|
@@ -520,7 +520,7 @@ function HousePositionSlider({
|
|
|
520
520
|
},
|
|
521
521
|
[effectiveAvailableCash, effectiveTokensHeld, resetOrder]
|
|
522
522
|
);
|
|
523
|
-
const handleDragAtClientY =
|
|
523
|
+
const handleDragAtClientY = React9__namespace.useCallback(
|
|
524
524
|
(clientY) => {
|
|
525
525
|
if (!houseRef.current) return;
|
|
526
526
|
const rect = houseRef.current.getBoundingClientRect();
|
|
@@ -1036,18 +1036,18 @@ function HousePositionSliderMobile({
|
|
|
1036
1036
|
className,
|
|
1037
1037
|
...props
|
|
1038
1038
|
}) {
|
|
1039
|
-
const [orderMode, setOrderMode] =
|
|
1040
|
-
const [deltaDollars, setDeltaDollars] =
|
|
1041
|
-
const [deltaTokensSell, setDeltaTokensSell] =
|
|
1042
|
-
const [deltaTokensBuy, setDeltaTokensBuy] =
|
|
1043
|
-
const [buyTrackingMode, setBuyTrackingMode] =
|
|
1044
|
-
const [orderType, setOrderType] =
|
|
1045
|
-
const [limitPrice, setLimitPrice] =
|
|
1046
|
-
const [limitPriceInput, setLimitPriceInput] =
|
|
1047
|
-
const [limitPriceDirty, setLimitPriceDirty] =
|
|
1048
|
-
const [tokenAmountInput, setTokenAmountInput] =
|
|
1049
|
-
const houseRef =
|
|
1050
|
-
|
|
1039
|
+
const [orderMode, setOrderMode] = React9__namespace.useState("none");
|
|
1040
|
+
const [deltaDollars, setDeltaDollars] = React9__namespace.useState(0);
|
|
1041
|
+
const [deltaTokensSell, setDeltaTokensSell] = React9__namespace.useState(0);
|
|
1042
|
+
const [deltaTokensBuy, setDeltaTokensBuy] = React9__namespace.useState(0);
|
|
1043
|
+
const [buyTrackingMode, setBuyTrackingMode] = React9__namespace.useState("dollars");
|
|
1044
|
+
const [orderType, setOrderType] = React9__namespace.useState(defaultOrderType);
|
|
1045
|
+
const [limitPrice, setLimitPrice] = React9__namespace.useState(currentPrice);
|
|
1046
|
+
const [limitPriceInput, setLimitPriceInput] = React9__namespace.useState(currentPrice.toFixed(2));
|
|
1047
|
+
const [limitPriceDirty, setLimitPriceDirty] = React9__namespace.useState(false);
|
|
1048
|
+
const [tokenAmountInput, setTokenAmountInput] = React9__namespace.useState("");
|
|
1049
|
+
const houseRef = React9__namespace.useRef(null);
|
|
1050
|
+
React9__namespace.useEffect(() => {
|
|
1051
1051
|
if (orderType !== "limit") return;
|
|
1052
1052
|
if (limitPriceDirty) return;
|
|
1053
1053
|
setLimitPrice(currentPrice);
|
|
@@ -1089,7 +1089,7 @@ function HousePositionSliderMobile({
|
|
|
1089
1089
|
const hasChange = orderMode !== "none" && (Math.abs(deltaTokens) > 1e-3 || Math.abs(deltaValue) > 0.01);
|
|
1090
1090
|
const targetOwnership = totalTokens > 0 ? targetTokens / totalTokens * 100 : 0;
|
|
1091
1091
|
const estFeeTokens = effectivePrice > 0 ? Math.abs(deltaValue) * 5e-3 / effectivePrice : 0;
|
|
1092
|
-
const updateOrderFromTargetValue =
|
|
1092
|
+
const updateOrderFromTargetValue = React9__namespace.useCallback(
|
|
1093
1093
|
(newTargetValue) => {
|
|
1094
1094
|
const newDeltaValue = newTargetValue - holdingsValue;
|
|
1095
1095
|
if (newDeltaValue > 0.01) {
|
|
@@ -1117,7 +1117,7 @@ function HousePositionSliderMobile({
|
|
|
1117
1117
|
},
|
|
1118
1118
|
[holdingsValue, availableCash, effectivePrice, tokensHeld]
|
|
1119
1119
|
);
|
|
1120
|
-
const updateOrderFromTokenAmount =
|
|
1120
|
+
const updateOrderFromTokenAmount = React9__namespace.useCallback(
|
|
1121
1121
|
(tokenAmount) => {
|
|
1122
1122
|
if (tokenAmount > 0) {
|
|
1123
1123
|
const maxTokens = effectivePrice > 0 ? availableCash / effectivePrice : 0;
|
|
@@ -1144,14 +1144,14 @@ function HousePositionSliderMobile({
|
|
|
1144
1144
|
},
|
|
1145
1145
|
[effectivePrice, availableCash, tokensHeld]
|
|
1146
1146
|
);
|
|
1147
|
-
const handleMarkerClick =
|
|
1147
|
+
const handleMarkerClick = React9__namespace.useCallback(
|
|
1148
1148
|
(pct) => {
|
|
1149
1149
|
const newTargetValue = pct / 100 * totalCapacity;
|
|
1150
1150
|
updateOrderFromTargetValue(newTargetValue);
|
|
1151
1151
|
},
|
|
1152
1152
|
[totalCapacity, updateOrderFromTargetValue]
|
|
1153
1153
|
);
|
|
1154
|
-
const onMouseDown =
|
|
1154
|
+
const onMouseDown = React9__namespace.useCallback(
|
|
1155
1155
|
(e) => {
|
|
1156
1156
|
e.preventDefault();
|
|
1157
1157
|
const move = (ev) => {
|
|
@@ -1171,7 +1171,7 @@ function HousePositionSliderMobile({
|
|
|
1171
1171
|
},
|
|
1172
1172
|
[totalCapacity, updateOrderFromTargetValue]
|
|
1173
1173
|
);
|
|
1174
|
-
const onTouchStart =
|
|
1174
|
+
const onTouchStart = React9__namespace.useCallback(
|
|
1175
1175
|
(e) => {
|
|
1176
1176
|
e.preventDefault();
|
|
1177
1177
|
e.stopPropagation();
|
|
@@ -1729,7 +1729,7 @@ var LiquidityText = styled24__default.default.span`
|
|
|
1729
1729
|
letter-spacing: 0.1px;
|
|
1730
1730
|
}
|
|
1731
1731
|
`;
|
|
1732
|
-
var LoafLiquidityBadge =
|
|
1732
|
+
var LoafLiquidityBadge = React9__namespace.forwardRef(
|
|
1733
1733
|
({ className, isGlowing, onClick, children, ...props }, ref) => {
|
|
1734
1734
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1735
1735
|
LogoContainer,
|
|
@@ -1757,9 +1757,34 @@ var LoafLiquidityBadge = React5__namespace.forwardRef(
|
|
|
1757
1757
|
}
|
|
1758
1758
|
);
|
|
1759
1759
|
LoafLiquidityBadge.displayName = "LoafLiquidityBadge";
|
|
1760
|
+
var toSize = (v, fallback) => v == null ? fallback : typeof v === "number" ? `${v}px` : v;
|
|
1761
|
+
var Skeleton = React9__namespace.forwardRef(
|
|
1762
|
+
({ width, height, radius, className, style, ...props }, ref) => {
|
|
1763
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1764
|
+
"div",
|
|
1765
|
+
{
|
|
1766
|
+
ref,
|
|
1767
|
+
"aria-busy": "true",
|
|
1768
|
+
"aria-live": "polite",
|
|
1769
|
+
className: cn(
|
|
1770
|
+
"inline-block align-middle bg-white/10 animate-pulse",
|
|
1771
|
+
className
|
|
1772
|
+
),
|
|
1773
|
+
style: {
|
|
1774
|
+
width: toSize(width, "100%"),
|
|
1775
|
+
height: toSize(height, "1em"),
|
|
1776
|
+
borderRadius: toSize(radius, "6px"),
|
|
1777
|
+
...style
|
|
1778
|
+
},
|
|
1779
|
+
...props
|
|
1780
|
+
}
|
|
1781
|
+
);
|
|
1782
|
+
}
|
|
1783
|
+
);
|
|
1784
|
+
Skeleton.displayName = "Skeleton";
|
|
1760
1785
|
function useViewportCompact(breakpoint) {
|
|
1761
|
-
const [isCompact, setIsCompact] =
|
|
1762
|
-
|
|
1786
|
+
const [isCompact, setIsCompact] = React9__namespace.useState(false);
|
|
1787
|
+
React9__namespace.useEffect(() => {
|
|
1763
1788
|
if (typeof window === "undefined") return;
|
|
1764
1789
|
const check = () => setIsCompact(window.innerWidth <= breakpoint);
|
|
1765
1790
|
check();
|
|
@@ -1769,16 +1794,119 @@ function useViewportCompact(breakpoint) {
|
|
|
1769
1794
|
return isCompact;
|
|
1770
1795
|
}
|
|
1771
1796
|
var formatNumber = (value, precision) => value.toFixed(precision);
|
|
1797
|
+
var FLASH_DURATION_MS = 450;
|
|
1798
|
+
var FLASH_UP_COLOR = "rgba(14, 203, 129, 0.35)";
|
|
1799
|
+
var FLASH_DOWN_COLOR = "rgba(246, 70, 93, 0.35)";
|
|
1800
|
+
function getTradeKey(trade, fallbackIndex) {
|
|
1801
|
+
if (trade.tradeId != null) return `id-${trade.tradeId}`;
|
|
1802
|
+
if (trade.time != null) return `t-${trade.time}-${trade.type}-${trade.price}-${trade.amount}`;
|
|
1803
|
+
return `idx-${fallbackIndex}-${trade.type}-${trade.price}-${trade.amount}`;
|
|
1804
|
+
}
|
|
1805
|
+
function useAmountChangeFlash(ref, amount) {
|
|
1806
|
+
const prevAmountRef = React9__namespace.useRef(amount);
|
|
1807
|
+
React9__namespace.useEffect(() => {
|
|
1808
|
+
const prev = prevAmountRef.current;
|
|
1809
|
+
const node = ref.current;
|
|
1810
|
+
if (prev !== amount && node && typeof node.animate === "function") {
|
|
1811
|
+
const color = amount > prev ? FLASH_UP_COLOR : FLASH_DOWN_COLOR;
|
|
1812
|
+
node.animate(
|
|
1813
|
+
[{ backgroundColor: color }, { backgroundColor: "transparent" }],
|
|
1814
|
+
{ duration: FLASH_DURATION_MS, easing: "ease-out" }
|
|
1815
|
+
);
|
|
1816
|
+
}
|
|
1817
|
+
prevAmountRef.current = amount;
|
|
1818
|
+
}, [amount, ref]);
|
|
1819
|
+
}
|
|
1820
|
+
function useMidPriceFlash(ref, midPrice, restBgColor) {
|
|
1821
|
+
const prevMidRef = React9__namespace.useRef(midPrice);
|
|
1822
|
+
React9__namespace.useEffect(() => {
|
|
1823
|
+
const prev = prevMidRef.current;
|
|
1824
|
+
const node = ref.current;
|
|
1825
|
+
if (prev !== midPrice && prev > 0 && midPrice > 0 && node && typeof node.animate === "function") {
|
|
1826
|
+
const color = midPrice > prev ? FLASH_UP_COLOR : FLASH_DOWN_COLOR;
|
|
1827
|
+
node.animate(
|
|
1828
|
+
[{ backgroundColor: color }, { backgroundColor: restBgColor }],
|
|
1829
|
+
{ duration: FLASH_DURATION_MS, easing: "ease-out" }
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
prevMidRef.current = midPrice;
|
|
1833
|
+
}, [midPrice, ref, restBgColor]);
|
|
1834
|
+
}
|
|
1835
|
+
function TradeRow({
|
|
1836
|
+
trade,
|
|
1837
|
+
tradeKey,
|
|
1838
|
+
precision,
|
|
1839
|
+
amountPrecision,
|
|
1840
|
+
seenTradeKeysRef,
|
|
1841
|
+
compact
|
|
1842
|
+
}) {
|
|
1843
|
+
const rowRef = React9__namespace.useRef(null);
|
|
1844
|
+
const { type } = trade;
|
|
1845
|
+
React9__namespace.useEffect(() => {
|
|
1846
|
+
if (seenTradeKeysRef.current.has(tradeKey)) return;
|
|
1847
|
+
seenTradeKeysRef.current.add(tradeKey);
|
|
1848
|
+
const node = rowRef.current;
|
|
1849
|
+
if (!node || typeof node.animate !== "function") return;
|
|
1850
|
+
const color = type === "buy" ? FLASH_UP_COLOR : FLASH_DOWN_COLOR;
|
|
1851
|
+
node.animate(
|
|
1852
|
+
[{ backgroundColor: color }, { backgroundColor: "transparent" }],
|
|
1853
|
+
{ duration: FLASH_DURATION_MS, easing: "ease-out" }
|
|
1854
|
+
);
|
|
1855
|
+
}, [tradeKey, seenTradeKeysRef, type]);
|
|
1856
|
+
if (compact) {
|
|
1857
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1858
|
+
"div",
|
|
1859
|
+
{
|
|
1860
|
+
ref: rowRef,
|
|
1861
|
+
className: "grid",
|
|
1862
|
+
style: { gridTemplateColumns: "1.2fr 0.8fr", padding: "0.2rem 0", fontSize: "0.8rem" },
|
|
1863
|
+
children: [
|
|
1864
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: trade.type === "buy" ? "#0ecb81" : "#f6465d", fontWeight: 500 }, children: [
|
|
1865
|
+
"$",
|
|
1866
|
+
formatNumber(trade.price, precision)
|
|
1867
|
+
] }),
|
|
1868
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "right", paddingRight: "0.5rem" }, children: formatNumber(trade.amount, amountPrecision) })
|
|
1869
|
+
]
|
|
1870
|
+
}
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1874
|
+
"div",
|
|
1875
|
+
{
|
|
1876
|
+
ref: rowRef,
|
|
1877
|
+
className: "grid grid-cols-2 items-center gap-3 px-3 py-1.5",
|
|
1878
|
+
children: [
|
|
1879
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1880
|
+
"div",
|
|
1881
|
+
{
|
|
1882
|
+
className: cn(
|
|
1883
|
+
"tabular-nums",
|
|
1884
|
+
trade.type === "buy" ? "text-[#0ecb81]" : "text-[#f6465d]"
|
|
1885
|
+
),
|
|
1886
|
+
children: [
|
|
1887
|
+
"$",
|
|
1888
|
+
formatNumber(trade.price, precision)
|
|
1889
|
+
]
|
|
1890
|
+
}
|
|
1891
|
+
),
|
|
1892
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right tabular-nums text-white/90", children: formatNumber(trade.amount, amountPrecision) })
|
|
1893
|
+
]
|
|
1894
|
+
}
|
|
1895
|
+
);
|
|
1896
|
+
}
|
|
1772
1897
|
function DepthRow({
|
|
1773
1898
|
side,
|
|
1774
1899
|
price,
|
|
1775
1900
|
amount,
|
|
1776
1901
|
depthPct,
|
|
1777
1902
|
precision,
|
|
1778
|
-
amountPrecision
|
|
1903
|
+
amountPrecision,
|
|
1904
|
+
hasUserOrder
|
|
1779
1905
|
}) {
|
|
1780
1906
|
const isAsk = side === "ask";
|
|
1781
|
-
|
|
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: [
|
|
1782
1910
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1783
1911
|
"div",
|
|
1784
1912
|
{
|
|
@@ -1786,9 +1914,16 @@ function DepthRow({
|
|
|
1786
1914
|
"absolute inset-y-0 right-0",
|
|
1787
1915
|
isAsk ? "bg-rose-900/30" : "bg-emerald-900/30"
|
|
1788
1916
|
),
|
|
1789
|
-
style: { width: `${clamp3(depthPct, 0, 100)}
|
|
1917
|
+
style: { width: `${clamp3(depthPct, 0, 100)}%`, transition: "width 300ms ease-out" }
|
|
1790
1918
|
}
|
|
1791
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,
|
|
1792
1927
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1793
1928
|
"div",
|
|
1794
1929
|
{
|
|
@@ -1808,7 +1943,7 @@ var DEPTH_ROW_HEIGHT_PX = 34;
|
|
|
1808
1943
|
var COMPACT_ROWS_VISIBLE = 5;
|
|
1809
1944
|
var COMPACT_ROW_HEIGHT_PX = 30;
|
|
1810
1945
|
var COMPACT_BREAKPOINT_PX = 1024;
|
|
1811
|
-
var Orderbook =
|
|
1946
|
+
var Orderbook = React9__namespace.forwardRef(
|
|
1812
1947
|
({
|
|
1813
1948
|
asks,
|
|
1814
1949
|
bids,
|
|
@@ -1823,13 +1958,44 @@ var Orderbook = React5__namespace.forwardRef(
|
|
|
1823
1958
|
onTabChange,
|
|
1824
1959
|
rightHeader = /* @__PURE__ */ jsxRuntime.jsx(LoafLiquidityBadge, { className: "text-[0.6rem]" }),
|
|
1825
1960
|
variant = "auto",
|
|
1961
|
+
userOrderPrices,
|
|
1962
|
+
isLoading = false,
|
|
1826
1963
|
className,
|
|
1827
1964
|
...props
|
|
1828
1965
|
}, ref) => {
|
|
1829
|
-
const [tab, setTab] =
|
|
1830
|
-
const [tradeFilter, setTradeFilter] =
|
|
1966
|
+
const [tab, setTab] = React9__namespace.useState(defaultTab);
|
|
1967
|
+
const [tradeFilter, setTradeFilter] = React9__namespace.useState("all");
|
|
1831
1968
|
const viewportCompact = useViewportCompact(COMPACT_BREAKPOINT_PX);
|
|
1832
|
-
|
|
1969
|
+
const { userAskPrices, userBidPrices } = React9__namespace.useMemo(() => {
|
|
1970
|
+
const ask = /* @__PURE__ */ new Set();
|
|
1971
|
+
const bid = /* @__PURE__ */ new Set();
|
|
1972
|
+
if (!userOrderPrices) return { userAskPrices: ask, userBidPrices: bid };
|
|
1973
|
+
for (const entry of userOrderPrices) {
|
|
1974
|
+
if (entry.side === "SELL") ask.add(entry.price);
|
|
1975
|
+
else bid.add(entry.price);
|
|
1976
|
+
}
|
|
1977
|
+
return { userAskPrices: ask, userBidPrices: bid };
|
|
1978
|
+
}, [userOrderPrices]);
|
|
1979
|
+
const seenTradeKeysRef = React9__namespace.useRef(/* @__PURE__ */ new Set());
|
|
1980
|
+
const initializedRef = React9__namespace.useRef(false);
|
|
1981
|
+
if (!initializedRef.current && trades.length > 0) {
|
|
1982
|
+
for (let i = 0; i < trades.length; i++) {
|
|
1983
|
+
seenTradeKeysRef.current.add(getTradeKey(trades[i], i));
|
|
1984
|
+
}
|
|
1985
|
+
initializedRef.current = true;
|
|
1986
|
+
}
|
|
1987
|
+
React9__namespace.useEffect(() => {
|
|
1988
|
+
if (!initializedRef.current) return;
|
|
1989
|
+
const live = /* @__PURE__ */ new Set();
|
|
1990
|
+
for (let i = 0; i < trades.length; i++) {
|
|
1991
|
+
live.add(getTradeKey(trades[i], i));
|
|
1992
|
+
}
|
|
1993
|
+
const seen = seenTradeKeysRef.current;
|
|
1994
|
+
for (const key of seen) {
|
|
1995
|
+
if (!live.has(key)) seen.delete(key);
|
|
1996
|
+
}
|
|
1997
|
+
}, [trades]);
|
|
1998
|
+
React9__namespace.useEffect(() => {
|
|
1833
1999
|
setTab(defaultTab);
|
|
1834
2000
|
}, [defaultTab]);
|
|
1835
2001
|
const handleTab = (next) => {
|
|
@@ -1860,7 +2026,11 @@ var Orderbook = React5__namespace.forwardRef(
|
|
|
1860
2026
|
midPrice,
|
|
1861
2027
|
midChangePercent,
|
|
1862
2028
|
midClass,
|
|
1863
|
-
sectionHeight
|
|
2029
|
+
sectionHeight,
|
|
2030
|
+
userAskPrices,
|
|
2031
|
+
userBidPrices,
|
|
2032
|
+
isLoading,
|
|
2033
|
+
seenTradeKeysRef
|
|
1864
2034
|
};
|
|
1865
2035
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1866
2036
|
Card,
|
|
@@ -1878,6 +2048,29 @@ var Orderbook = React5__namespace.forwardRef(
|
|
|
1878
2048
|
}
|
|
1879
2049
|
);
|
|
1880
2050
|
Orderbook.displayName = "Orderbook";
|
|
2051
|
+
function SkeletonRow({ compact }) {
|
|
2052
|
+
if (compact) {
|
|
2053
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2054
|
+
"div",
|
|
2055
|
+
{
|
|
2056
|
+
style: {
|
|
2057
|
+
display: "grid",
|
|
2058
|
+
gridTemplateColumns: "1.2fr 0.8fr",
|
|
2059
|
+
padding: "0.2rem 0",
|
|
2060
|
+
alignItems: "center"
|
|
2061
|
+
},
|
|
2062
|
+
children: [
|
|
2063
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: "60%", height: 10 }) }),
|
|
2064
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "right", paddingRight: "0.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: "50%", height: 10 }) })
|
|
2065
|
+
]
|
|
2066
|
+
}
|
|
2067
|
+
);
|
|
2068
|
+
}
|
|
2069
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 items-center gap-3 px-3 py-1.5", children: [
|
|
2070
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: "60%", height: 12 }),
|
|
2071
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: "50%", height: 12 }) })
|
|
2072
|
+
] });
|
|
2073
|
+
}
|
|
1881
2074
|
function DesktopOrderbookLayout({
|
|
1882
2075
|
tab,
|
|
1883
2076
|
handleTab,
|
|
@@ -1896,8 +2089,14 @@ function DesktopOrderbookLayout({
|
|
|
1896
2089
|
midPrice,
|
|
1897
2090
|
midChangePercent,
|
|
1898
2091
|
midClass,
|
|
1899
|
-
sectionHeight
|
|
2092
|
+
sectionHeight,
|
|
2093
|
+
userAskPrices,
|
|
2094
|
+
userBidPrices,
|
|
2095
|
+
isLoading,
|
|
2096
|
+
seenTradeKeysRef
|
|
1900
2097
|
}) {
|
|
2098
|
+
const midRef = React9__namespace.useRef(null);
|
|
2099
|
+
useMidPriceFlash(midRef, midPrice, "#0b1a24");
|
|
1901
2100
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1902
2101
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 pt-4", children: [
|
|
1903
2102
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
@@ -1981,29 +2180,20 @@ function DesktopOrderbookLayout({
|
|
|
1981
2180
|
{
|
|
1982
2181
|
className: "max-h-[380px] overflow-y-auto overflow-x-hidden",
|
|
1983
2182
|
style: { scrollbarGutter: "stable" },
|
|
1984
|
-
children: tradeFiltered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-10 text-center text-sm text-white/50", children: "No trades" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: tradeFiltered.map((trade, i) =>
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
formatNumber(trade.price, precision)
|
|
1999
|
-
]
|
|
2000
|
-
}
|
|
2001
|
-
),
|
|
2002
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right tabular-nums text-white/90", children: formatNumber(trade.amount, amountPrecision) })
|
|
2003
|
-
]
|
|
2004
|
-
},
|
|
2005
|
-
`${trade.type}-${trade.price}-${trade.amount}-${trade.time ?? i}`
|
|
2006
|
-
)) })
|
|
2183
|
+
children: isLoading && tradeFiltered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: Array.from({ length: LEVEL_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, {}, `trade-skel-${i}`)) }) : tradeFiltered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-10 text-center text-sm text-white/50", children: "No trades" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: tradeFiltered.map((trade, i) => {
|
|
2184
|
+
const tradeKey = getTradeKey(trade, i);
|
|
2185
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2186
|
+
TradeRow,
|
|
2187
|
+
{
|
|
2188
|
+
trade,
|
|
2189
|
+
tradeKey,
|
|
2190
|
+
precision,
|
|
2191
|
+
amountPrecision,
|
|
2192
|
+
seenTradeKeysRef
|
|
2193
|
+
},
|
|
2194
|
+
tradeKey
|
|
2195
|
+
);
|
|
2196
|
+
}) })
|
|
2007
2197
|
}
|
|
2008
2198
|
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col min-h-0", children: [
|
|
2009
2199
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2011,7 +2201,7 @@ function DesktopOrderbookLayout({
|
|
|
2011
2201
|
{
|
|
2012
2202
|
className: "flex flex-col justify-end divide-y divide-white/5 overflow-y-auto",
|
|
2013
2203
|
style: { height: `${sectionHeight}px`, scrollbarGutter: "stable" },
|
|
2014
|
-
children:
|
|
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(
|
|
2015
2205
|
DepthRow,
|
|
2016
2206
|
{
|
|
2017
2207
|
side: "ask",
|
|
@@ -2019,30 +2209,38 @@ function DesktopOrderbookLayout({
|
|
|
2019
2209
|
amount: l.amount,
|
|
2020
2210
|
depthPct: (l.depth ?? l.amount) / maxAskDepth * 100,
|
|
2021
2211
|
precision,
|
|
2022
|
-
amountPrecision
|
|
2212
|
+
amountPrecision,
|
|
2213
|
+
hasUserOrder: userAskPrices.has(l.price)
|
|
2023
2214
|
},
|
|
2024
|
-
`ask-${
|
|
2215
|
+
`ask-${l.price}`
|
|
2025
2216
|
))
|
|
2026
2217
|
}
|
|
2027
2218
|
),
|
|
2028
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2219
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2220
|
+
"div",
|
|
2221
|
+
{
|
|
2222
|
+
ref: midRef,
|
|
2223
|
+
className: "grid grid-cols-2 items-center gap-3 bg-[#0b1a24] px-3 py-2",
|
|
2224
|
+
children: [
|
|
2225
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("text-lg font-semibold tabular-nums", midClass), children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 110, height: 20 }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2226
|
+
"$",
|
|
2227
|
+
formatNumber(midPrice, precision),
|
|
2228
|
+
midChangePercent == null ? null : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("ml-2 text-sm font-semibold tabular-nums", midClass), children: [
|
|
2229
|
+
midChangePercent >= 0 ? "+" : "",
|
|
2230
|
+
midChangePercent.toFixed(2),
|
|
2231
|
+
"%"
|
|
2232
|
+
] })
|
|
2233
|
+
] }) }),
|
|
2234
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", {})
|
|
2235
|
+
]
|
|
2236
|
+
}
|
|
2237
|
+
),
|
|
2040
2238
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2041
2239
|
"div",
|
|
2042
2240
|
{
|
|
2043
2241
|
className: "divide-y divide-white/5 overflow-y-auto",
|
|
2044
2242
|
style: { height: `${sectionHeight}px`, scrollbarGutter: "stable" },
|
|
2045
|
-
children:
|
|
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(
|
|
2046
2244
|
DepthRow,
|
|
2047
2245
|
{
|
|
2048
2246
|
side: "bid",
|
|
@@ -2050,9 +2248,10 @@ function DesktopOrderbookLayout({
|
|
|
2050
2248
|
amount: l.amount,
|
|
2051
2249
|
depthPct: (l.depth ?? l.amount) / maxBidDepth * 100,
|
|
2052
2250
|
precision,
|
|
2053
|
-
amountPrecision
|
|
2251
|
+
amountPrecision,
|
|
2252
|
+
hasUserOrder: userBidPrices.has(l.price)
|
|
2054
2253
|
},
|
|
2055
|
-
`bid-${
|
|
2254
|
+
`bid-${l.price}`
|
|
2056
2255
|
))
|
|
2057
2256
|
}
|
|
2058
2257
|
)
|
|
@@ -2078,10 +2277,16 @@ function MobileOrderbookLayout({
|
|
|
2078
2277
|
midPrice,
|
|
2079
2278
|
midChangePercent,
|
|
2080
2279
|
midClass,
|
|
2081
|
-
sectionHeight: _sectionHeight
|
|
2280
|
+
sectionHeight: _sectionHeight,
|
|
2281
|
+
userAskPrices,
|
|
2282
|
+
userBidPrices,
|
|
2283
|
+
isLoading,
|
|
2284
|
+
seenTradeKeysRef
|
|
2082
2285
|
}) {
|
|
2083
|
-
const
|
|
2084
|
-
|
|
2286
|
+
const midRef = React9__namespace.useRef(null);
|
|
2287
|
+
useMidPriceFlash(midRef, midPrice, "transparent");
|
|
2288
|
+
const visibleAsks = React9__namespace.useMemo(() => asks.slice(0, COMPACT_ROWS_VISIBLE), [asks]);
|
|
2289
|
+
const visibleBids = React9__namespace.useMemo(() => bids.slice(0, COMPACT_ROWS_VISIBLE), [bids]);
|
|
2085
2290
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2086
2291
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2087
2292
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -2150,7 +2355,7 @@ function MobileOrderbookLayout({
|
|
|
2150
2355
|
]
|
|
2151
2356
|
}
|
|
2152
2357
|
),
|
|
2153
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, children:
|
|
2358
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, children: isLoading ? Array.from({ length: COMPACT_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, { compact: true }, `m-ask-skel-${i}`)) : visibleAsks.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem 0", textAlign: "center", color: "rgba(255,255,255,0.4)", fontSize: "0.72rem" }, children: "No asks" }) : visibleAsks.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2154
2359
|
MobileDepthRow,
|
|
2155
2360
|
{
|
|
2156
2361
|
side: "ask",
|
|
@@ -2158,13 +2363,15 @@ function MobileOrderbookLayout({
|
|
|
2158
2363
|
amount: l.amount,
|
|
2159
2364
|
depthPct: (l.depth ?? l.amount) / maxAskDepth * 100,
|
|
2160
2365
|
precision,
|
|
2161
|
-
amountPrecision
|
|
2366
|
+
amountPrecision,
|
|
2367
|
+
hasUserOrder: userAskPrices.has(l.price)
|
|
2162
2368
|
},
|
|
2163
|
-
`mobile-ask-${
|
|
2369
|
+
`mobile-ask-${l.price}`
|
|
2164
2370
|
)) }),
|
|
2165
2371
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2166
2372
|
"div",
|
|
2167
2373
|
{
|
|
2374
|
+
ref: midRef,
|
|
2168
2375
|
className: "grid",
|
|
2169
2376
|
style: {
|
|
2170
2377
|
gridTemplateColumns: "1.2fr 0.8fr",
|
|
@@ -2174,12 +2381,12 @@ function MobileOrderbookLayout({
|
|
|
2174
2381
|
borderBottom: "1px solid rgba(255,255,255,0.1)"
|
|
2175
2382
|
},
|
|
2176
2383
|
children: [
|
|
2177
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2384
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2178
2385
|
"div",
|
|
2179
2386
|
{
|
|
2180
2387
|
style: { fontWeight: "bold", display: "flex", alignItems: "center", gap: "8px" },
|
|
2181
2388
|
className: midClass,
|
|
2182
|
-
children: [
|
|
2389
|
+
children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 90, height: 16 }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2183
2390
|
"$",
|
|
2184
2391
|
formatNumber(midPrice, precision),
|
|
2185
2392
|
midChangePercent != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("text-[0.75rem] font-semibold tabular-nums", midClass), children: [
|
|
@@ -2187,14 +2394,14 @@ function MobileOrderbookLayout({
|
|
|
2187
2394
|
midChangePercent.toFixed(2),
|
|
2188
2395
|
"%"
|
|
2189
2396
|
] })
|
|
2190
|
-
]
|
|
2397
|
+
] })
|
|
2191
2398
|
}
|
|
2192
2399
|
),
|
|
2193
2400
|
/* @__PURE__ */ jsxRuntime.jsx("div", {})
|
|
2194
2401
|
]
|
|
2195
2402
|
}
|
|
2196
2403
|
),
|
|
2197
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, children:
|
|
2404
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column" }, children: isLoading ? Array.from({ length: COMPACT_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, { compact: true }, `m-bid-skel-${i}`)) : visibleBids.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "0.75rem 0", textAlign: "center", color: "rgba(255,255,255,0.4)", fontSize: "0.72rem" }, children: "No bids" }) : visibleBids.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2198
2405
|
MobileDepthRow,
|
|
2199
2406
|
{
|
|
2200
2407
|
side: "bid",
|
|
@@ -2202,9 +2409,10 @@ function MobileOrderbookLayout({
|
|
|
2202
2409
|
amount: l.amount,
|
|
2203
2410
|
depthPct: (l.depth ?? l.amount) / maxBidDepth * 100,
|
|
2204
2411
|
precision,
|
|
2205
|
-
amountPrecision
|
|
2412
|
+
amountPrecision,
|
|
2413
|
+
hasUserOrder: userBidPrices.has(l.price)
|
|
2206
2414
|
},
|
|
2207
|
-
`mobile-bid-${
|
|
2415
|
+
`mobile-bid-${l.price}`
|
|
2208
2416
|
)) })
|
|
2209
2417
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col overflow-hidden px-3 pb-2", children: [
|
|
2210
2418
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -2218,27 +2426,21 @@ function MobileOrderbookLayout({
|
|
|
2218
2426
|
]
|
|
2219
2427
|
}
|
|
2220
2428
|
),
|
|
2221
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: tradeFiltered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-6 text-center text-[0.7rem] text-white/50", children: "No trades" }) : tradeFiltered.map((trade, i) =>
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
),
|
|
2237
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { textAlign: "right", paddingRight: "0.5rem" }, children: formatNumber(trade.amount, amountPrecision) })
|
|
2238
|
-
]
|
|
2239
|
-
},
|
|
2240
|
-
`${trade.type}-${trade.price}-${trade.amount}-${trade.time ?? i}`
|
|
2241
|
-
)) })
|
|
2429
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: isLoading && tradeFiltered.length === 0 ? Array.from({ length: COMPACT_ROWS_VISIBLE }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(SkeletonRow, { compact: true }, `m-trade-skel-${i}`)) : tradeFiltered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-6 text-center text-[0.7rem] text-white/50", children: "No trades" }) : tradeFiltered.map((trade, i) => {
|
|
2430
|
+
const tradeKey = getTradeKey(trade, i);
|
|
2431
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2432
|
+
TradeRow,
|
|
2433
|
+
{
|
|
2434
|
+
trade,
|
|
2435
|
+
tradeKey,
|
|
2436
|
+
precision,
|
|
2437
|
+
amountPrecision,
|
|
2438
|
+
seenTradeKeysRef,
|
|
2439
|
+
compact: true
|
|
2440
|
+
},
|
|
2441
|
+
tradeKey
|
|
2442
|
+
);
|
|
2443
|
+
}) })
|
|
2242
2444
|
] })
|
|
2243
2445
|
] });
|
|
2244
2446
|
}
|
|
@@ -2248,12 +2450,16 @@ function MobileDepthRow({
|
|
|
2248
2450
|
amount,
|
|
2249
2451
|
depthPct,
|
|
2250
2452
|
precision,
|
|
2251
|
-
amountPrecision
|
|
2453
|
+
amountPrecision,
|
|
2454
|
+
hasUserOrder
|
|
2252
2455
|
}) {
|
|
2253
2456
|
const isAsk = side === "ask";
|
|
2457
|
+
const rowRef = React9__namespace.useRef(null);
|
|
2458
|
+
useAmountChangeFlash(rowRef, amount);
|
|
2254
2459
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2255
2460
|
"div",
|
|
2256
2461
|
{
|
|
2462
|
+
ref: rowRef,
|
|
2257
2463
|
style: {
|
|
2258
2464
|
display: "grid",
|
|
2259
2465
|
gridTemplateColumns: "1.2fr 0.8fr",
|
|
@@ -2262,6 +2468,24 @@ function MobileDepthRow({
|
|
|
2262
2468
|
position: "relative"
|
|
2263
2469
|
},
|
|
2264
2470
|
children: [
|
|
2471
|
+
hasUserOrder ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2472
|
+
"span",
|
|
2473
|
+
{
|
|
2474
|
+
"aria-label": "Your order at this price",
|
|
2475
|
+
style: {
|
|
2476
|
+
position: "absolute",
|
|
2477
|
+
left: 0,
|
|
2478
|
+
top: 0,
|
|
2479
|
+
bottom: 0,
|
|
2480
|
+
width: "3px",
|
|
2481
|
+
backgroundColor: "#C9A227",
|
|
2482
|
+
boxShadow: "0 0 6px rgba(201,162,39,0.6)",
|
|
2483
|
+
borderTopRightRadius: "2px",
|
|
2484
|
+
borderBottomRightRadius: "2px",
|
|
2485
|
+
zIndex: 2
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
) : null,
|
|
2265
2489
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", zIndex: 1, color: isAsk ? "#f6465d" : "#0ecb81" }, children: [
|
|
2266
2490
|
"$",
|
|
2267
2491
|
formatNumber(price, precision)
|
|
@@ -2278,7 +2502,8 @@ function MobileDepthRow({
|
|
|
2278
2502
|
width: `${clamp3(depthPct, 0, 100)}%`,
|
|
2279
2503
|
backgroundColor: isAsk ? "#f6465d" : "#0ecb81",
|
|
2280
2504
|
opacity: 0.1,
|
|
2281
|
-
zIndex: 0
|
|
2505
|
+
zIndex: 0,
|
|
2506
|
+
transition: "width 300ms ease-out"
|
|
2282
2507
|
}
|
|
2283
2508
|
}
|
|
2284
2509
|
)
|
|
@@ -2286,7 +2511,7 @@ function MobileDepthRow({
|
|
|
2286
2511
|
}
|
|
2287
2512
|
);
|
|
2288
2513
|
}
|
|
2289
|
-
var PropertyTour =
|
|
2514
|
+
var PropertyTour = React9__namespace.forwardRef(
|
|
2290
2515
|
({
|
|
2291
2516
|
className,
|
|
2292
2517
|
title,
|
|
@@ -2299,8 +2524,8 @@ var PropertyTour = React5__namespace.forwardRef(
|
|
|
2299
2524
|
playsInline = true,
|
|
2300
2525
|
...props
|
|
2301
2526
|
}, ref) => {
|
|
2302
|
-
const videoRef =
|
|
2303
|
-
|
|
2527
|
+
const videoRef = React9__namespace.useRef(null);
|
|
2528
|
+
React9__namespace.useEffect(() => {
|
|
2304
2529
|
const video = videoRef.current;
|
|
2305
2530
|
if (!video) return;
|
|
2306
2531
|
const handleFullscreenChange = () => {
|
|
@@ -2432,7 +2657,7 @@ var formatTimeAgo = (timestamp) => {
|
|
|
2432
2657
|
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
|
|
2433
2658
|
return `${Math.floor(diff / 3600)}h ago`;
|
|
2434
2659
|
};
|
|
2435
|
-
var PropertyNewsUpdates =
|
|
2660
|
+
var PropertyNewsUpdates = React9__namespace.forwardRef(
|
|
2436
2661
|
({
|
|
2437
2662
|
className,
|
|
2438
2663
|
heading,
|
|
@@ -2449,15 +2674,15 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
|
|
|
2449
2674
|
const isPurchaseVariant = variant === "purchases";
|
|
2450
2675
|
const isHomeVariant = variant === "home";
|
|
2451
2676
|
const resolvedHeading = heading ?? (isPurchaseVariant ? "Live Purchases" : "Property News & Headlines");
|
|
2452
|
-
const [homeTab, setHomeTab] =
|
|
2677
|
+
const [homeTab, setHomeTab] = React9__namespace.useState("all");
|
|
2453
2678
|
const purchaseItems = purchasesProp ?? [];
|
|
2454
|
-
const [page, setPage] =
|
|
2455
|
-
|
|
2679
|
+
const [page, setPage] = React9__namespace.useState(0);
|
|
2680
|
+
React9__namespace.useEffect(() => {
|
|
2456
2681
|
ensureAnimationsInjected();
|
|
2457
2682
|
}, []);
|
|
2458
2683
|
const hasItems = Array.isArray(items) && items.length > 0;
|
|
2459
|
-
const totalPages =
|
|
2460
|
-
|
|
2684
|
+
const totalPages = React9__namespace.useMemo(() => hasItems ? Math.max(1, Math.ceil(items.length / ITEMS_PER_PAGE)) : 1, [hasItems, items.length]);
|
|
2685
|
+
React9__namespace.useEffect(() => {
|
|
2461
2686
|
setPage((prev) => Math.min(prev, totalPages - 1));
|
|
2462
2687
|
}, [totalPages]);
|
|
2463
2688
|
const paginatedItems = hasItems ? items.slice(page * ITEMS_PER_PAGE, page * ITEMS_PER_PAGE + ITEMS_PER_PAGE) : [];
|
|
@@ -2765,7 +2990,7 @@ var defaultFormat = (value) => new Intl.NumberFormat("en-US", {
|
|
|
2765
2990
|
notation: value >= 1e5 ? "compact" : "standard",
|
|
2766
2991
|
maximumFractionDigits: value >= 1e3 ? 0 : 2
|
|
2767
2992
|
}).format(value);
|
|
2768
|
-
var TradingSlider =
|
|
2993
|
+
var TradingSlider = React9__namespace.forwardRef(
|
|
2769
2994
|
({
|
|
2770
2995
|
label = "Trade size",
|
|
2771
2996
|
helperText = "Drag to pick the desired notional.",
|
|
@@ -2783,7 +3008,7 @@ var TradingSlider = React5__namespace.forwardRef(
|
|
|
2783
3008
|
...rest
|
|
2784
3009
|
}, ref) => {
|
|
2785
3010
|
const isControlled = value !== void 0;
|
|
2786
|
-
const [internalValue, setInternalValue] =
|
|
3011
|
+
const [internalValue, setInternalValue] = React9__namespace.useState(
|
|
2787
3012
|
defaultValue ?? (typeof min === "number" ? min : 0)
|
|
2788
3013
|
);
|
|
2789
3014
|
const currentValue = isControlled ? Number(value) : internalValue;
|
|
@@ -2886,7 +3111,7 @@ var MobileToggleButton = styled24__default.default.button`
|
|
|
2886
3111
|
padding: 0.6rem 0.5rem;
|
|
2887
3112
|
}
|
|
2888
3113
|
`;
|
|
2889
|
-
var MobileTradeNav =
|
|
3114
|
+
var MobileTradeNav = React9__namespace.forwardRef(
|
|
2890
3115
|
({ className, items, activeId, onChange, ...props }, ref) => {
|
|
2891
3116
|
return /* @__PURE__ */ jsxRuntime.jsx(MobileToggleContainer, { ref, className: cn(className), ...props, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2892
3117
|
MobileToggleButton,
|
|
@@ -3537,7 +3762,7 @@ var formatPercent = (value, fractionDigits = 2) => {
|
|
|
3537
3762
|
if (value == null || Number.isNaN(value)) return "\u2014";
|
|
3538
3763
|
return `${value.toFixed(fractionDigits)}%`;
|
|
3539
3764
|
};
|
|
3540
|
-
var YourOrders =
|
|
3765
|
+
var YourOrders = React9__namespace.forwardRef(
|
|
3541
3766
|
({
|
|
3542
3767
|
className,
|
|
3543
3768
|
title,
|
|
@@ -3550,10 +3775,10 @@ var YourOrders = React5__namespace.forwardRef(
|
|
|
3550
3775
|
pageSize: pageSizeOverride,
|
|
3551
3776
|
...props
|
|
3552
3777
|
}, ref) => {
|
|
3553
|
-
const [internalActiveTab, setInternalActiveTab] =
|
|
3554
|
-
const [page, setPage] =
|
|
3778
|
+
const [internalActiveTab, setInternalActiveTab] = React9__namespace.useState(tabs?.[0]?.id ?? "portfolio");
|
|
3779
|
+
const [page, setPage] = React9__namespace.useState(0);
|
|
3555
3780
|
const effectiveActiveTabId = activeTabId ?? internalActiveTab;
|
|
3556
|
-
|
|
3781
|
+
React9__namespace.useEffect(() => {
|
|
3557
3782
|
setPage(0);
|
|
3558
3783
|
}, [effectiveActiveTabId]);
|
|
3559
3784
|
const handleTabChange = (tabId) => {
|
|
@@ -3935,7 +4160,7 @@ function createCandlestickSeries(chart, options) {
|
|
|
3935
4160
|
}
|
|
3936
4161
|
throw new Error("Candlestick series API is not available in the current lightweight-charts version.");
|
|
3937
4162
|
}
|
|
3938
|
-
var PriceChart =
|
|
4163
|
+
var PriceChart = React9__namespace.forwardRef(
|
|
3939
4164
|
({
|
|
3940
4165
|
className,
|
|
3941
4166
|
title = "Price Chart",
|
|
@@ -3949,18 +4174,18 @@ var PriceChart = React5__namespace.forwardRef(
|
|
|
3949
4174
|
height = 301.52,
|
|
3950
4175
|
...props
|
|
3951
4176
|
}, ref) => {
|
|
3952
|
-
const containerRef =
|
|
3953
|
-
const chartRef =
|
|
3954
|
-
const seriesRef =
|
|
3955
|
-
const priceLineRef =
|
|
3956
|
-
const [hoveredRange, setHoveredRange] =
|
|
3957
|
-
const [dropdownOpen, setDropdownOpen] =
|
|
3958
|
-
const dropdownRef =
|
|
3959
|
-
const isAutoScrollRef =
|
|
4177
|
+
const containerRef = React9__namespace.useRef(null);
|
|
4178
|
+
const chartRef = React9__namespace.useRef(null);
|
|
4179
|
+
const seriesRef = React9__namespace.useRef(null);
|
|
4180
|
+
const priceLineRef = React9__namespace.useRef(null);
|
|
4181
|
+
const [hoveredRange, setHoveredRange] = React9__namespace.useState(null);
|
|
4182
|
+
const [dropdownOpen, setDropdownOpen] = React9__namespace.useState(false);
|
|
4183
|
+
const dropdownRef = React9__namespace.useRef(null);
|
|
4184
|
+
const isAutoScrollRef = React9__namespace.useRef(true);
|
|
3960
4185
|
const visibleRanges = ranges.slice(0, VISIBLE_RANGE_COUNT);
|
|
3961
4186
|
const dropdownRanges = ranges.slice(VISIBLE_RANGE_COUNT);
|
|
3962
4187
|
const selectedInDropdown = dropdownRanges.includes(selectedRange);
|
|
3963
|
-
|
|
4188
|
+
React9__namespace.useEffect(() => {
|
|
3964
4189
|
const handleClickOutside = (e) => {
|
|
3965
4190
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
3966
4191
|
setDropdownOpen(false);
|
|
@@ -3969,25 +4194,25 @@ var PriceChart = React5__namespace.forwardRef(
|
|
|
3969
4194
|
document.addEventListener("mousedown", handleClickOutside);
|
|
3970
4195
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
3971
4196
|
}, []);
|
|
3972
|
-
const resolvedPrice =
|
|
4197
|
+
const resolvedPrice = React9__namespace.useMemo(() => {
|
|
3973
4198
|
if (price != null) return price;
|
|
3974
4199
|
const last = data.at(-1);
|
|
3975
4200
|
return last?.close;
|
|
3976
4201
|
}, [data, price]);
|
|
3977
|
-
const inferredChangePercent =
|
|
4202
|
+
const inferredChangePercent = React9__namespace.useMemo(() => {
|
|
3978
4203
|
if (changePercent != null) return changePercent;
|
|
3979
4204
|
const first = data[0]?.open;
|
|
3980
4205
|
const last = data.at(-1)?.close;
|
|
3981
4206
|
if (first == null || last == null || first === 0) return void 0;
|
|
3982
4207
|
return (last - first) / first * 100;
|
|
3983
4208
|
}, [changePercent, data]);
|
|
3984
|
-
const dollarChange =
|
|
4209
|
+
const dollarChange = React9__namespace.useMemo(() => {
|
|
3985
4210
|
const first = data[0]?.open;
|
|
3986
4211
|
const last = data.at(-1)?.close;
|
|
3987
4212
|
if (first == null || last == null) return void 0;
|
|
3988
4213
|
return last - first;
|
|
3989
4214
|
}, [data]);
|
|
3990
|
-
|
|
4215
|
+
React9__namespace.useEffect(() => {
|
|
3991
4216
|
const el = containerRef.current;
|
|
3992
4217
|
if (!el) return;
|
|
3993
4218
|
const chart = LightweightCharts__namespace.createChart(el, {
|
|
@@ -4032,7 +4257,7 @@ var PriceChart = React5__namespace.forwardRef(
|
|
|
4032
4257
|
chart.remove();
|
|
4033
4258
|
};
|
|
4034
4259
|
}, []);
|
|
4035
|
-
|
|
4260
|
+
React9__namespace.useEffect(() => {
|
|
4036
4261
|
const chart = chartRef.current;
|
|
4037
4262
|
if (!chart) return;
|
|
4038
4263
|
const effectiveRange = selectedRange ?? ranges?.[0] ?? "1D";
|
|
@@ -4040,7 +4265,7 @@ var PriceChart = React5__namespace.forwardRef(
|
|
|
4040
4265
|
timeScale: getTimeScaleOptions(effectiveRange)
|
|
4041
4266
|
});
|
|
4042
4267
|
}, [selectedRange, ranges]);
|
|
4043
|
-
|
|
4268
|
+
React9__namespace.useEffect(() => {
|
|
4044
4269
|
const chart = chartRef.current;
|
|
4045
4270
|
const series = seriesRef.current;
|
|
4046
4271
|
if (!chart || !series) return;
|
|
@@ -4245,7 +4470,7 @@ var formatPrice3 = (value, currencySymbol) => {
|
|
|
4245
4470
|
maximumFractionDigits: 3
|
|
4246
4471
|
})}`;
|
|
4247
4472
|
};
|
|
4248
|
-
var PropertyHeroHeader =
|
|
4473
|
+
var PropertyHeroHeader = React9__namespace.forwardRef(
|
|
4249
4474
|
({
|
|
4250
4475
|
className,
|
|
4251
4476
|
imageUrl,
|
|
@@ -4266,14 +4491,15 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4266
4491
|
makeOfferDisabled = false,
|
|
4267
4492
|
hideMakeOfferButton = false,
|
|
4268
4493
|
statusBadge,
|
|
4494
|
+
isLoading = false,
|
|
4269
4495
|
...props
|
|
4270
4496
|
}, ref) => {
|
|
4271
4497
|
const isPositive = changePercent == null ? void 0 : changePercent >= 0;
|
|
4272
4498
|
const accentColor = "#e6c87e";
|
|
4273
4499
|
const tradeHoverColor = "#f5dd9a";
|
|
4274
|
-
const [isTradeInteracting, setIsTradeInteracting] =
|
|
4275
|
-
const [isOfferInteracting, setIsOfferInteracting] =
|
|
4276
|
-
const hasAmenities = beds != null || baths != null || cars != null || propertyTypeLabel != null;
|
|
4500
|
+
const [isTradeInteracting, setIsTradeInteracting] = React9__namespace.useState(false);
|
|
4501
|
+
const [isOfferInteracting, setIsOfferInteracting] = React9__namespace.useState(false);
|
|
4502
|
+
const hasAmenities = isLoading || beds != null || baths != null || cars != null || propertyTypeLabel != null;
|
|
4277
4503
|
const isTradeDisabled = !onTrade;
|
|
4278
4504
|
const isMakeOfferButtonDisabled = makeOfferDisabled || !onMakeOffer;
|
|
4279
4505
|
const showMakeOfferButton = !hideMakeOfferButton;
|
|
@@ -4313,7 +4539,7 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4313
4539
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: headingStyle, className: "break-words", children: name }),
|
|
4314
4540
|
/* @__PURE__ */ jsxRuntime.jsxs(InfoRow, { className: "mb-3 max-[768px]:mb-[0.6rem] max-[480px]:mb-[0.5rem]", children: [
|
|
4315
4541
|
/* @__PURE__ */ jsxRuntime.jsx(LocationText, { children: location }),
|
|
4316
|
-
price == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(PriceBlock, { children: [
|
|
4542
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx(PriceBlock, { children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 110, height: 18 }) }) : price == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(PriceBlock, { children: [
|
|
4317
4543
|
formatPrice3(price, currencySymbol),
|
|
4318
4544
|
changePercent == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4319
4545
|
"span",
|
|
@@ -4343,7 +4569,21 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4343
4569
|
] })
|
|
4344
4570
|
] })
|
|
4345
4571
|
] }),
|
|
4346
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4572
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-6 text-[0.95rem] text-white/90 max-[768px]:hidden", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4573
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
4574
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BedDouble, { className: "mr-2 h-[18px] w-[18px] opacity-60" }),
|
|
4575
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 52, height: 14 })
|
|
4576
|
+
] }),
|
|
4577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
4578
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bath, { className: "mr-2 h-[18px] w-[18px] opacity-60" }),
|
|
4579
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 56, height: 14 })
|
|
4580
|
+
] }),
|
|
4581
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
4582
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CarFront, { className: "mr-2 h-[18px] w-[18px] opacity-60" }),
|
|
4583
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 50, height: 14 })
|
|
4584
|
+
] }),
|
|
4585
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 60, height: 14 })
|
|
4586
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4347
4587
|
beds == null ? null : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
4348
4588
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BedDouble, { className: "mr-2 h-[18px] w-[18px]" }),
|
|
4349
4589
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
@@ -4366,7 +4606,7 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4366
4606
|
] })
|
|
4367
4607
|
] }),
|
|
4368
4608
|
propertyTypeLabel == null ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { children: propertyTypeLabel })
|
|
4369
|
-
] })
|
|
4609
|
+
] }) })
|
|
4370
4610
|
] }),
|
|
4371
4611
|
/* @__PURE__ */ jsxRuntime.jsxs(ActionButtons, { children: [
|
|
4372
4612
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4428,7 +4668,21 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4428
4668
|
] })
|
|
4429
4669
|
] }) })
|
|
4430
4670
|
] }),
|
|
4431
|
-
hasAmenities ? /* @__PURE__ */ jsxRuntime.
|
|
4671
|
+
hasAmenities ? /* @__PURE__ */ jsxRuntime.jsx(MobileAmenities, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4672
|
+
/* @__PURE__ */ jsxRuntime.jsxs(MobileAmenity, { children: [
|
|
4673
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BedDouble, { className: "h-4 w-4 opacity-60" }),
|
|
4674
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 40, height: 12 })
|
|
4675
|
+
] }),
|
|
4676
|
+
/* @__PURE__ */ jsxRuntime.jsxs(MobileAmenity, { children: [
|
|
4677
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bath, { className: "h-4 w-4 opacity-60" }),
|
|
4678
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 44, height: 12 })
|
|
4679
|
+
] }),
|
|
4680
|
+
/* @__PURE__ */ jsxRuntime.jsxs(MobileAmenity, { children: [
|
|
4681
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CarFront, { className: "h-4 w-4 opacity-60" }),
|
|
4682
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 42, height: 12 })
|
|
4683
|
+
] }),
|
|
4684
|
+
/* @__PURE__ */ jsxRuntime.jsx(MobileAmenity, { children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 52, height: 12 }) })
|
|
4685
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4432
4686
|
beds == null ? null : /* @__PURE__ */ jsxRuntime.jsxs(MobileAmenity, { children: [
|
|
4433
4687
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BedDouble, { className: "h-4 w-4" }),
|
|
4434
4688
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
@@ -4451,7 +4705,7 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
|
|
|
4451
4705
|
] })
|
|
4452
4706
|
] }),
|
|
4453
4707
|
propertyTypeLabel == null ? null : /* @__PURE__ */ jsxRuntime.jsx(MobileAmenity, { children: propertyTypeLabel })
|
|
4454
|
-
] }) : null
|
|
4708
|
+
] }) }) : null
|
|
4455
4709
|
] });
|
|
4456
4710
|
}
|
|
4457
4711
|
);
|
|
@@ -4688,12 +4942,21 @@ var Header = ({
|
|
|
4688
4942
|
onWalletNavigate: _onWalletNavigate,
|
|
4689
4943
|
showTradeTab = true
|
|
4690
4944
|
}) => {
|
|
4691
|
-
const [isUserMenuOpen, setIsUserMenuOpen] =
|
|
4692
|
-
const [isMobileMenuOpen, setIsMobileMenuOpen] =
|
|
4693
|
-
const [isMoreMenuOpen, setIsMoreMenuOpen] =
|
|
4694
|
-
const [showLoginPopup, setShowLoginPopup] =
|
|
4695
|
-
const [loginPopupInitialView, setLoginPopupInitialView] =
|
|
4696
|
-
|
|
4945
|
+
const [isUserMenuOpen, setIsUserMenuOpen] = React9.useState(false);
|
|
4946
|
+
const [isMobileMenuOpen, setIsMobileMenuOpen] = React9.useState(false);
|
|
4947
|
+
const [isMoreMenuOpen, setIsMoreMenuOpen] = React9.useState(false);
|
|
4948
|
+
const [showLoginPopup, setShowLoginPopup] = React9.useState(false);
|
|
4949
|
+
const [loginPopupInitialView, setLoginPopupInitialView] = React9.useState(void 0);
|
|
4950
|
+
React9.useEffect(() => {
|
|
4951
|
+
if (typeof window === "undefined") return;
|
|
4952
|
+
const ua = navigator.userAgent;
|
|
4953
|
+
const isTelegram = /Telegram/i.test(ua);
|
|
4954
|
+
const isIOS = /iPhone|iPad|iPod/.test(ua);
|
|
4955
|
+
if (isTelegram && isIOS) {
|
|
4956
|
+
document.documentElement.style.setProperty("--telegram-safe-top", "59px");
|
|
4957
|
+
}
|
|
4958
|
+
}, []);
|
|
4959
|
+
React9.useEffect(() => {
|
|
4697
4960
|
const handleClickOutside = (event) => {
|
|
4698
4961
|
const target = event.target;
|
|
4699
4962
|
if (!target) return;
|
|
@@ -4713,7 +4976,7 @@ var Header = ({
|
|
|
4713
4976
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
4714
4977
|
};
|
|
4715
4978
|
}, [isUserMenuOpen, isMobileMenuOpen, isMoreMenuOpen]);
|
|
4716
|
-
|
|
4979
|
+
React9.useEffect(() => {
|
|
4717
4980
|
if (typeof window === "undefined") return;
|
|
4718
4981
|
const handleExternalLoginPopup = (event) => {
|
|
4719
4982
|
const customEvent = event;
|
|
@@ -4843,7 +5106,7 @@ var Header = ({
|
|
|
4843
5106
|
setShowLoginPopup(true);
|
|
4844
5107
|
}
|
|
4845
5108
|
};
|
|
4846
|
-
const handleLoginPopupClose =
|
|
5109
|
+
const handleLoginPopupClose = React9__namespace.default.useCallback(() => {
|
|
4847
5110
|
setShowLoginPopup(false);
|
|
4848
5111
|
setLoginPopupInitialView(void 0);
|
|
4849
5112
|
}, []);
|
|
@@ -5131,8 +5394,8 @@ var SafeAreaCover = styled24__default.default.div`
|
|
|
5131
5394
|
top: 0;
|
|
5132
5395
|
left: 0;
|
|
5133
5396
|
right: 0;
|
|
5134
|
-
height: env(safe-area-inset-top, 0px);
|
|
5135
|
-
min-height: env(safe-area-inset-top, 0px);
|
|
5397
|
+
height: max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px));
|
|
5398
|
+
min-height: max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px));
|
|
5136
5399
|
background-color: #0d1117;
|
|
5137
5400
|
z-index: 1001;
|
|
5138
5401
|
pointer-events: none;
|
|
@@ -5186,7 +5449,7 @@ var HeaderContainer = styled24__default.default.header`
|
|
|
5186
5449
|
/* Split padding so browsers that don't support env() inside shorthand
|
|
5187
5450
|
still get the horizontal padding — only the top falls back to 0 */
|
|
5188
5451
|
padding: 0 2rem;
|
|
5189
|
-
padding-top: env(safe-area-inset-top, 0px);
|
|
5452
|
+
padding-top: max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px));
|
|
5190
5453
|
background-color: #0d1117;
|
|
5191
5454
|
border-bottom: 1px solid #232a32;
|
|
5192
5455
|
position: fixed;
|
|
@@ -5197,18 +5460,18 @@ var HeaderContainer = styled24__default.default.header`
|
|
|
5197
5460
|
width: 100%;
|
|
5198
5461
|
/* Fallback min-height for browsers that can't evaluate calc+env */
|
|
5199
5462
|
min-height: 56px;
|
|
5200
|
-
min-height: calc(56px + env(safe-area-inset-top, 0px));
|
|
5463
|
+
min-height: calc(56px + max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px)));
|
|
5201
5464
|
box-sizing: border-box;
|
|
5202
5465
|
|
|
5203
5466
|
@media (max-width: 768px) {
|
|
5204
5467
|
padding: 0 1rem;
|
|
5205
|
-
padding-top: env(safe-area-inset-top, 0px);
|
|
5468
|
+
padding-top: max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px));
|
|
5206
5469
|
}
|
|
5207
5470
|
`;
|
|
5208
5471
|
var HeaderSpacer = styled24__default.default.div`
|
|
5209
5472
|
width: 100%;
|
|
5210
5473
|
min-height: 56px;
|
|
5211
|
-
min-height: calc(56px + env(safe-area-inset-top, 0px));
|
|
5474
|
+
min-height: calc(56px + max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px)));
|
|
5212
5475
|
flex-shrink: 0;
|
|
5213
5476
|
`;
|
|
5214
5477
|
var Logo = styled24__default.default.div`
|
|
@@ -5263,12 +5526,12 @@ var Nav = styled24__default.default.nav`
|
|
|
5263
5526
|
@media (max-width: 1300px) {
|
|
5264
5527
|
position: fixed;
|
|
5265
5528
|
top: 56px;
|
|
5266
|
-
top: calc(56px + env(safe-area-inset-top, 0px));
|
|
5529
|
+
top: calc(56px + max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px)));
|
|
5267
5530
|
right: ${(props) => props.$isOpen ? "0" : "-100%"} ;
|
|
5268
5531
|
width: 280px;
|
|
5269
5532
|
max-width: 280px;
|
|
5270
5533
|
height: calc(100vh - 56px);
|
|
5271
|
-
height: calc(100vh - 56px - env(safe-area-inset-top, 0px));
|
|
5534
|
+
height: calc(100vh - 56px - max(env(safe-area-inset-top, 0px), var(--telegram-safe-top, 0px)));
|
|
5272
5535
|
background: linear-gradient(180deg, #0f1419 0%, #0a0e13 100%);
|
|
5273
5536
|
z-index: 1000;
|
|
5274
5537
|
transition: right 0.3s ease;
|
|
@@ -5541,10 +5804,10 @@ var MobileNavItem = styled24__default.default.div`
|
|
|
5541
5804
|
padding-left: 24px;
|
|
5542
5805
|
}
|
|
5543
5806
|
`;
|
|
5544
|
-
var PropertySubheader =
|
|
5807
|
+
var PropertySubheader = React9__namespace.forwardRef(
|
|
5545
5808
|
({ className, tabs, activeTabId, onTabChange, actions, ...props }, ref) => {
|
|
5546
|
-
const tabsContainerRef =
|
|
5547
|
-
|
|
5809
|
+
const tabsContainerRef = React9__namespace.useRef(null);
|
|
5810
|
+
React9__namespace.useEffect(() => {
|
|
5548
5811
|
const container = tabsContainerRef.current;
|
|
5549
5812
|
if (!container) return;
|
|
5550
5813
|
const isMobile = window.innerWidth <= 768;
|
|
@@ -5686,27 +5949,27 @@ var LoginPopup = ({
|
|
|
5686
5949
|
onFundWallet,
|
|
5687
5950
|
initialView
|
|
5688
5951
|
}) => {
|
|
5689
|
-
const [view, setView] =
|
|
5690
|
-
const [email, setEmail] =
|
|
5691
|
-
const [handle, setHandle] =
|
|
5692
|
-
const [otp, setOtp] =
|
|
5693
|
-
const [error, setError] =
|
|
5694
|
-
const [loading, setLoading] =
|
|
5695
|
-
const [isSignUp, setIsSignUp] =
|
|
5696
|
-
const [fundingAmount] =
|
|
5697
|
-
const [kycLoading, setKycLoading] =
|
|
5698
|
-
const [showKycWidget, setShowKycWidget] =
|
|
5699
|
-
const [cryptoFundingLoading, setCryptoFundingLoading] =
|
|
5700
|
-
const [fiatFundingLoading, setFiatFundingLoading] =
|
|
5701
|
-
const [fundingError, setFundingError] =
|
|
5702
|
-
const [transakWidgetUrl, setTransakWidgetUrl] =
|
|
5703
|
-
const suppressAutoCloseRef =
|
|
5704
|
-
|
|
5952
|
+
const [view, setView] = React9.useState(() => initialView ?? "main");
|
|
5953
|
+
const [email, setEmail] = React9.useState("");
|
|
5954
|
+
const [handle, setHandle] = React9.useState("");
|
|
5955
|
+
const [otp, setOtp] = React9.useState(Array(OTP_INPUT_LENGTH).fill(""));
|
|
5956
|
+
const [error, setError] = React9.useState("");
|
|
5957
|
+
const [loading, setLoading] = React9.useState(false);
|
|
5958
|
+
const [isSignUp, setIsSignUp] = React9.useState(false);
|
|
5959
|
+
const [fundingAmount] = React9.useState("");
|
|
5960
|
+
const [kycLoading, setKycLoading] = React9.useState(false);
|
|
5961
|
+
const [showKycWidget, setShowKycWidget] = React9.useState(false);
|
|
5962
|
+
const [cryptoFundingLoading, setCryptoFundingLoading] = React9.useState(false);
|
|
5963
|
+
const [fiatFundingLoading, setFiatFundingLoading] = React9.useState(false);
|
|
5964
|
+
const [fundingError, setFundingError] = React9.useState("");
|
|
5965
|
+
const [transakWidgetUrl, setTransakWidgetUrl] = React9.useState(null);
|
|
5966
|
+
const suppressAutoCloseRef = React9__namespace.default.useRef(false);
|
|
5967
|
+
React9.useEffect(() => {
|
|
5705
5968
|
if (typeof initialView === "string") {
|
|
5706
5969
|
setView(initialView);
|
|
5707
5970
|
}
|
|
5708
5971
|
}, [initialView]);
|
|
5709
|
-
|
|
5972
|
+
React9.useEffect(() => {
|
|
5710
5973
|
if (!transakWidgetUrl) return;
|
|
5711
5974
|
const handleTransakMessage = (event) => {
|
|
5712
5975
|
if (!event.origin.includes("transak.com") && !event.origin.includes("global.transak.com")) {
|
|
@@ -5731,7 +5994,7 @@ var LoginPopup = ({
|
|
|
5731
5994
|
window.addEventListener("message", handleTransakMessage);
|
|
5732
5995
|
return () => window.removeEventListener("message", handleTransakMessage);
|
|
5733
5996
|
}, [transakWidgetUrl, onClose]);
|
|
5734
|
-
|
|
5997
|
+
React9.useEffect(() => {
|
|
5735
5998
|
if (!autoCloseOnAuth) {
|
|
5736
5999
|
return;
|
|
5737
6000
|
}
|
|
@@ -6703,8 +6966,8 @@ var TransakIframe = styled24__default.default.iframe`
|
|
|
6703
6966
|
border-radius: var(--border-radius, 12px);
|
|
6704
6967
|
`;
|
|
6705
6968
|
var MiniLiveFeed = () => {
|
|
6706
|
-
const [purchases, setPurchases] =
|
|
6707
|
-
|
|
6969
|
+
const [purchases, setPurchases] = React9.useState([]);
|
|
6970
|
+
React9.useEffect(() => {
|
|
6708
6971
|
const handles = [
|
|
6709
6972
|
"Landlord",
|
|
6710
6973
|
"PropertyKing",
|
|
@@ -6880,7 +7143,7 @@ var MiniLiveFeed = () => {
|
|
|
6880
7143
|
);
|
|
6881
7144
|
};
|
|
6882
7145
|
LoginPopup.displayName = "LoginPopup";
|
|
6883
|
-
var PropertyCompareBar =
|
|
7146
|
+
var PropertyCompareBar = React9__namespace.forwardRef(
|
|
6884
7147
|
({
|
|
6885
7148
|
className,
|
|
6886
7149
|
addresses,
|
|
@@ -6891,7 +7154,7 @@ var PropertyCompareBar = React5__namespace.forwardRef(
|
|
|
6891
7154
|
price,
|
|
6892
7155
|
...props
|
|
6893
7156
|
}, ref) => {
|
|
6894
|
-
const normalizedAddresses =
|
|
7157
|
+
const normalizedAddresses = React9__namespace.useMemo(() => {
|
|
6895
7158
|
return addresses.map(
|
|
6896
7159
|
(option) => typeof option === "string" ? { id: option, label: option } : option
|
|
6897
7160
|
);
|
|
@@ -6899,11 +7162,11 @@ var PropertyCompareBar = React5__namespace.forwardRef(
|
|
|
6899
7162
|
const hasAddresses = normalizedAddresses.length > 0;
|
|
6900
7163
|
const firstAddressId = normalizedAddresses[0]?.id;
|
|
6901
7164
|
const isControlled = selectedAddressId !== void 0;
|
|
6902
|
-
const [internalSelectedId, setInternalSelectedId] =
|
|
7165
|
+
const [internalSelectedId, setInternalSelectedId] = React9__namespace.useState(
|
|
6903
7166
|
() => isControlled ? void 0 : firstAddressId
|
|
6904
7167
|
);
|
|
6905
7168
|
const resolvedSelectedId = isControlled ? selectedAddressId : internalSelectedId;
|
|
6906
|
-
|
|
7169
|
+
React9__namespace.useEffect(() => {
|
|
6907
7170
|
if (!isControlled) {
|
|
6908
7171
|
setInternalSelectedId((current) => {
|
|
6909
7172
|
if (current != null && normalizedAddresses.some((option) => option.id === current)) {
|
|
@@ -6914,9 +7177,9 @@ var PropertyCompareBar = React5__namespace.forwardRef(
|
|
|
6914
7177
|
}
|
|
6915
7178
|
}, [firstAddressId, isControlled, normalizedAddresses]);
|
|
6916
7179
|
const selectedOption = normalizedAddresses.find((option) => option.id === resolvedSelectedId) ?? normalizedAddresses[0];
|
|
6917
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
6918
|
-
const dropdownRef =
|
|
6919
|
-
|
|
7180
|
+
const [isDropdownOpen, setIsDropdownOpen] = React9__namespace.useState(false);
|
|
7181
|
+
const dropdownRef = React9__namespace.useRef(null);
|
|
7182
|
+
React9__namespace.useEffect(() => {
|
|
6920
7183
|
if (!isDropdownOpen) return;
|
|
6921
7184
|
const handleClick = (event) => {
|
|
6922
7185
|
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
@@ -7319,11 +7582,11 @@ function GalleryMapSection({
|
|
|
7319
7582
|
autoPlay = true,
|
|
7320
7583
|
autoPlayInterval = 4e3
|
|
7321
7584
|
}) {
|
|
7322
|
-
const [carouselIndex, setCarouselIndex] =
|
|
7323
|
-
const [showVideo, setShowVideo] =
|
|
7324
|
-
const [autoPlaying, setAutoPlaying] =
|
|
7585
|
+
const [carouselIndex, setCarouselIndex] = React9.useState(0);
|
|
7586
|
+
const [showVideo, setShowVideo] = React9.useState(false);
|
|
7587
|
+
const [autoPlaying, setAutoPlaying] = React9.useState(autoPlay);
|
|
7325
7588
|
const resolvedMapUrl = mapUrl ?? (tokenName ? `/map/${tokenName}?embed=true&zoom=14&hideOthers=true` : "about:blank");
|
|
7326
|
-
|
|
7589
|
+
React9.useEffect(() => {
|
|
7327
7590
|
if (!autoPlaying || images.length <= 1) return;
|
|
7328
7591
|
const interval = setInterval(() => {
|
|
7329
7592
|
setCarouselIndex((p) => (p + 1) % images.length);
|
|
@@ -7639,9 +7902,10 @@ function PropertyOverview({
|
|
|
7639
7902
|
bathrooms,
|
|
7640
7903
|
carSpaces,
|
|
7641
7904
|
propertyTypeLabel,
|
|
7642
|
-
tokensIssued: tokensIssuedProp
|
|
7905
|
+
tokensIssued: tokensIssuedProp,
|
|
7906
|
+
isLoading = false
|
|
7643
7907
|
}) {
|
|
7644
|
-
const [isDescExpanded, setDescExpanded] =
|
|
7908
|
+
const [isDescExpanded, setDescExpanded] = React9.useState(false);
|
|
7645
7909
|
const description = descriptionProp ?? overviewData?.description ?? DEFAULT_DESCRIPTION;
|
|
7646
7910
|
const landSize = landProp ?? overviewData?.landSizeSqm ?? null;
|
|
7647
7911
|
const buildingSize = buildingProp ?? overviewData?.buildingSizeSqm ?? null;
|
|
@@ -7677,13 +7941,14 @@ function PropertyOverview({
|
|
|
7677
7941
|
const weeklyRent = overviewData?.weeklyRent ?? 0;
|
|
7678
7942
|
const annualRent = weeklyRent * 52;
|
|
7679
7943
|
const dividendYield = resolvedValuation && annualRent > 0 ? (annualRent / resolvedValuation * 100).toFixed(2) : null;
|
|
7944
|
+
const loadingSkeleton = /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 90, height: 18 });
|
|
7680
7945
|
const financialItems = financialItemsProp ?? [
|
|
7681
|
-
{ label: "Token Price", value: tokenPriceValue ? `$${tokenPriceValue.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : "N/A", gold: true },
|
|
7682
|
-
{ label: "Property Value", value: resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "N/A" },
|
|
7683
|
-
{ label: "Weekly Rent", value: weeklyRent > 0 ? `$${weeklyRent.toLocaleString()}/wk` : "N/A", badge: weeklyRent > 0 ? "Rented" : void 0 },
|
|
7684
|
-
{ label: "Dividend Yield", value: dividendYield ? `${dividendYield}%` : "N/A" },
|
|
7685
|
-
{ label: "Total Tokens", value: resolvedTokensIssued ? resolvedTokensIssued.toLocaleString() : "N/A" },
|
|
7686
|
-
{ label: "Indicative Listing", value: overviewData?.indicativeListing ?? "N/A" }
|
|
7946
|
+
{ label: "Token Price", value: isLoading && tokenPriceValue == null ? loadingSkeleton : tokenPriceValue ? `$${tokenPriceValue.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : "N/A", gold: true },
|
|
7947
|
+
{ label: "Property Value", value: isLoading && resolvedValuation == null ? loadingSkeleton : resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "N/A" },
|
|
7948
|
+
{ label: "Weekly Rent", value: isLoading && !overviewData ? loadingSkeleton : weeklyRent > 0 ? `$${weeklyRent.toLocaleString()}/wk` : "N/A", badge: weeklyRent > 0 ? "Rented" : void 0 },
|
|
7949
|
+
{ label: "Dividend Yield", value: isLoading && dividendYield == null && resolvedValuation == null ? loadingSkeleton : dividendYield ? `${dividendYield}%` : "N/A" },
|
|
7950
|
+
{ label: "Total Tokens", value: isLoading && resolvedTokensIssued == null ? loadingSkeleton : resolvedTokensIssued ? resolvedTokensIssued.toLocaleString() : "N/A" },
|
|
7951
|
+
{ label: "Indicative Listing", value: isLoading && !overviewData ? loadingSkeleton : overviewData?.indicativeListing ?? "N/A" }
|
|
7687
7952
|
];
|
|
7688
7953
|
const galleryImages = images ?? [];
|
|
7689
7954
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -7987,8 +8252,8 @@ var OfferPricePulse = styled24__default.default.span`
|
|
|
7987
8252
|
`;
|
|
7988
8253
|
var eventTypes = ["Leased", "Renovated", "Extended", "Rebuilt", "Rezoned", "DA Approval"];
|
|
7989
8254
|
function PropertyHistory() {
|
|
7990
|
-
const [historyFilter, setHistoryFilter] =
|
|
7991
|
-
const pastSales =
|
|
8255
|
+
const [historyFilter, setHistoryFilter] = React9.useState("all");
|
|
8256
|
+
const pastSales = React9.useMemo(() => generateMockPastSales(), []);
|
|
7992
8257
|
const loafListing = pastSales.find((sale) => sale.type === "Listed");
|
|
7993
8258
|
const loafEvents = pastSales.filter(
|
|
7994
8259
|
(sale) => sale.ownershipPeriod === "current" && sale.type !== "Listed" && (sale.id === "leased-current" || sale.id === "da-approval")
|
|
@@ -8125,7 +8390,7 @@ function PropertyHistory() {
|
|
|
8125
8390
|
] });
|
|
8126
8391
|
}
|
|
8127
8392
|
function EventDetails({ event }) {
|
|
8128
|
-
const [expanded, setExpanded] =
|
|
8393
|
+
const [expanded, setExpanded] = React9.useState(false);
|
|
8129
8394
|
const toggleExpand = () => {
|
|
8130
8395
|
setExpanded((prev) => !prev);
|
|
8131
8396
|
};
|
|
@@ -8913,7 +9178,7 @@ function AssetSelectorBar({
|
|
|
8913
9178
|
selectorItems,
|
|
8914
9179
|
onSelect
|
|
8915
9180
|
}) {
|
|
8916
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
9181
|
+
const [isDropdownOpen, setIsDropdownOpen] = React9.useState(false);
|
|
8917
9182
|
const hasItems = selectorItems && selectorItems.length > 0;
|
|
8918
9183
|
const metrics = metricsProp ?? [
|
|
8919
9184
|
...tokenPrice != null ? [{ label: "Unit Price", value: `$${tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`, accent: true }] : [],
|
|
@@ -9182,15 +9447,15 @@ function OfferingProgressCard({
|
|
|
9182
9447
|
targetAmount,
|
|
9183
9448
|
isPrivateClient = false
|
|
9184
9449
|
}) {
|
|
9185
|
-
const [currentTime, setCurrentTime] =
|
|
9186
|
-
const [countdown, setCountdown] =
|
|
9450
|
+
const [currentTime, setCurrentTime] = React9.useState(/* @__PURE__ */ new Date());
|
|
9451
|
+
const [countdown, setCountdown] = React9.useState(null);
|
|
9187
9452
|
const computedRaised = raisedAmount ?? totalSold * tokenPrice;
|
|
9188
9453
|
const computedTarget = targetAmount ?? supplyToSell * tokenPrice;
|
|
9189
|
-
|
|
9454
|
+
React9.useEffect(() => {
|
|
9190
9455
|
const timer = setInterval(() => setCurrentTime(/* @__PURE__ */ new Date()), 1e3);
|
|
9191
9456
|
return () => clearInterval(timer);
|
|
9192
9457
|
}, []);
|
|
9193
|
-
|
|
9458
|
+
React9.useEffect(() => {
|
|
9194
9459
|
if (!opensAt) {
|
|
9195
9460
|
setCountdown(null);
|
|
9196
9461
|
return;
|
|
@@ -9527,14 +9792,19 @@ var formatTimeAgo2 = (timestamp) => {
|
|
|
9527
9792
|
};
|
|
9528
9793
|
function VideoActivitySection({
|
|
9529
9794
|
ipoStarted,
|
|
9795
|
+
ipoEnded = false,
|
|
9796
|
+
isLoading = false,
|
|
9530
9797
|
recentOrders = [],
|
|
9531
9798
|
ordersAllocated = 0,
|
|
9532
9799
|
tokenPrice = 0
|
|
9533
9800
|
}) {
|
|
9534
|
-
const sortedOrders =
|
|
9801
|
+
const sortedOrders = React9.useMemo(
|
|
9535
9802
|
() => [...recentOrders].sort((a, b) => b.timestamp - a.timestamp).slice(0, 7),
|
|
9536
9803
|
[recentOrders]
|
|
9537
9804
|
);
|
|
9805
|
+
const headerStatusText = ipoEnded ? `Sale ended${ordersAllocated > 0 ? ` \xB7 ${ordersAllocated.toLocaleString()} orders` : ""}` : ipoStarted ? isLoading && sortedOrders.length === 0 ? "Loading orders\u2026" : `Active orders: ${ordersAllocated.toLocaleString()}` : "Waiting for Offer to Open";
|
|
9806
|
+
const showSkeletonFeed = ipoStarted && isLoading && sortedOrders.length === 0;
|
|
9807
|
+
const showOrderFeed = !showSkeletonFeed && (ipoStarted || ipoEnded && sortedOrders.length > 0);
|
|
9538
9808
|
return /* @__PURE__ */ jsxRuntime.jsxs(Section3, { children: [
|
|
9539
9809
|
/* @__PURE__ */ jsxRuntime.jsxs(VideoPanel, { children: [
|
|
9540
9810
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "section-header", children: /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Musgrave" }) }),
|
|
@@ -9546,31 +9816,40 @@ function VideoActivitySection({
|
|
|
9546
9816
|
/* @__PURE__ */ jsxRuntime.jsxs(ActivityPanel, { children: [
|
|
9547
9817
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "section-header", children: [
|
|
9548
9818
|
/* @__PURE__ */ jsxRuntime.jsxs("h3", { children: [
|
|
9549
|
-
/* @__PURE__ */ jsxRuntime.jsx(LiveIndicatorDot, { $active: ipoStarted }),
|
|
9819
|
+
/* @__PURE__ */ jsxRuntime.jsx(LiveIndicatorDot, { $active: ipoStarted && !ipoEnded }),
|
|
9550
9820
|
"Recent Order Activity"
|
|
9551
9821
|
] }),
|
|
9552
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
9822
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: headerStatusText })
|
|
9553
9823
|
] }),
|
|
9554
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "activity-content", children:
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9824
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "activity-content", children: showSkeletonFeed ? /* @__PURE__ */ jsxRuntime.jsx(FeedList, { children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(SkeletonFeedRow, { children: [
|
|
9825
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "info-col", children: [
|
|
9826
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 110, height: 14 }),
|
|
9827
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 56, height: 10 })
|
|
9828
|
+
] }),
|
|
9829
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { width: 70, height: 14 })
|
|
9830
|
+
] }, `feed-skel-${i}`)) }) : showOrderFeed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9831
|
+
ipoEnded && /* @__PURE__ */ jsxRuntime.jsx(EndedBanner, { children: "Sale ended \u2014 final allocations" }),
|
|
9832
|
+
/* @__PURE__ */ jsxRuntime.jsx(FeedList, { children: sortedOrders.map((order, index) => {
|
|
9833
|
+
const amount = tokenPrice * order.quantity;
|
|
9834
|
+
const barPercent = Math.min(85, Math.max(15, amount / MAX_DISPLAY_AMOUNT * 100));
|
|
9835
|
+
const isAlternate = index % 2 === 1;
|
|
9836
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9837
|
+
PurchaseItem,
|
|
9838
|
+
{
|
|
9839
|
+
$barWidth: `${barPercent}%`,
|
|
9840
|
+
$isAlternate: isAlternate,
|
|
9841
|
+
children: [
|
|
9842
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PurchaseInfo, { children: [
|
|
9843
|
+
/* @__PURE__ */ jsxRuntime.jsx(PurchaseName, { children: order.buyerHandle || `${order.buyerAddress.slice(0, 6)}...${order.buyerAddress.slice(-4)}` }),
|
|
9844
|
+
/* @__PURE__ */ jsxRuntime.jsx(PurchaseTime, { children: formatTimeAgo2(order.timestamp) })
|
|
9845
|
+
] }),
|
|
9846
|
+
/* @__PURE__ */ jsxRuntime.jsx(PurchaseAmount, { children: formatCurrency4(amount) })
|
|
9847
|
+
]
|
|
9848
|
+
},
|
|
9849
|
+
order.txHash
|
|
9850
|
+
);
|
|
9851
|
+
}) })
|
|
9852
|
+
] }) : ipoEnded ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "activity-empty", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Sale ended \u2014 no orders were placed." }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "activity-empty", children: [
|
|
9574
9853
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "spinner" }),
|
|
9575
9854
|
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Activity will appear once the Offering opens" })
|
|
9576
9855
|
] }) })
|
|
@@ -9711,6 +9990,43 @@ var ActivityPanel = styled24__default.default.div`
|
|
|
9711
9990
|
to { transform: rotate(360deg); }
|
|
9712
9991
|
}
|
|
9713
9992
|
`;
|
|
9993
|
+
var SkeletonFeedRow = styled24__default.default.div`
|
|
9994
|
+
padding: 0.625rem 0.75rem;
|
|
9995
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
9996
|
+
display: flex;
|
|
9997
|
+
justify-content: space-between;
|
|
9998
|
+
align-items: center;
|
|
9999
|
+
gap: 1rem;
|
|
10000
|
+
|
|
10001
|
+
&:last-child {
|
|
10002
|
+
border-bottom: none;
|
|
10003
|
+
}
|
|
10004
|
+
|
|
10005
|
+
.info-col {
|
|
10006
|
+
display: flex;
|
|
10007
|
+
flex-direction: column;
|
|
10008
|
+
gap: 0.3rem;
|
|
10009
|
+
min-width: 0;
|
|
10010
|
+
flex: 1;
|
|
10011
|
+
}
|
|
10012
|
+
|
|
10013
|
+
@media (max-width: 768px) {
|
|
10014
|
+
padding: 0.4rem 0.6rem;
|
|
10015
|
+
}
|
|
10016
|
+
`;
|
|
10017
|
+
var EndedBanner = styled24__default.default.div`
|
|
10018
|
+
font-size: 0.7rem;
|
|
10019
|
+
font-weight: 600;
|
|
10020
|
+
letter-spacing: 0.04em;
|
|
10021
|
+
text-transform: uppercase;
|
|
10022
|
+
color: rgba(255, 255, 255, 0.55);
|
|
10023
|
+
background: rgba(255, 255, 255, 0.04);
|
|
10024
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
10025
|
+
border-radius: 6px;
|
|
10026
|
+
padding: 0.4rem 0.6rem;
|
|
10027
|
+
margin-bottom: 0.5rem;
|
|
10028
|
+
text-align: center;
|
|
10029
|
+
`;
|
|
9714
10030
|
var FeedList = styled24__default.default.div`
|
|
9715
10031
|
width: 100%;
|
|
9716
10032
|
overflow-y: auto;
|
|
@@ -9828,10 +10144,10 @@ function OrderPanel({
|
|
|
9828
10144
|
tokenDisplayName,
|
|
9829
10145
|
tokenSymbol
|
|
9830
10146
|
}) {
|
|
9831
|
-
const [payInputValue, setPayInputValue] =
|
|
9832
|
-
const [receiveInputValue, setReceiveInputValue] =
|
|
9833
|
-
const [isPayInputFocused, setIsPayInputFocused] =
|
|
9834
|
-
const [isReceiveInputFocused, setIsReceiveInputFocused] =
|
|
10147
|
+
const [payInputValue, setPayInputValue] = React9.useState("");
|
|
10148
|
+
const [receiveInputValue, setReceiveInputValue] = React9.useState("");
|
|
10149
|
+
const [isPayInputFocused, setIsPayInputFocused] = React9.useState(false);
|
|
10150
|
+
const [isReceiveInputFocused, setIsReceiveInputFocused] = React9.useState(false);
|
|
9835
10151
|
const handlePayBlur = () => {
|
|
9836
10152
|
setIsPayInputFocused(false);
|
|
9837
10153
|
const parsed = parseInt(payInputValue.replace(/[^0-9]/g, ""), 10) || 0;
|
|
@@ -10677,9 +10993,9 @@ function PortfolioActivityPanel({
|
|
|
10677
10993
|
style
|
|
10678
10994
|
}) {
|
|
10679
10995
|
const resolvedDefaultTab = defaultTab ?? (showPositionsTab ? "positions" : "subscriptions");
|
|
10680
|
-
const [activeTab, setActiveTab] =
|
|
10681
|
-
const [activityPage, setActivityPage] =
|
|
10682
|
-
const activeTabTotal =
|
|
10996
|
+
const [activeTab, setActiveTab] = React9.useState(resolvedDefaultTab);
|
|
10997
|
+
const [activityPage, setActivityPage] = React9.useState(0);
|
|
10998
|
+
const activeTabTotal = React9.useMemo(() => {
|
|
10683
10999
|
switch (activeTab) {
|
|
10684
11000
|
case "positions":
|
|
10685
11001
|
return positions.length;
|
|
@@ -10697,6 +11013,22 @@ function PortfolioActivityPanel({
|
|
|
10697
11013
|
return 0;
|
|
10698
11014
|
}
|
|
10699
11015
|
}, [activeTab, positions.length, offeringOrders.length, openOrders.length, orderHistory.length, tradeHistory.length, transfers.length]);
|
|
11016
|
+
const positionsCount = positions.length;
|
|
11017
|
+
const openOrdersCount = React9.useMemo(
|
|
11018
|
+
() => openOrders.filter((o) => o.status === "OPEN" || o.status === "PARTIALLY_FILLED").length,
|
|
11019
|
+
[openOrders]
|
|
11020
|
+
);
|
|
11021
|
+
const pendingHistoryCount = React9.useMemo(
|
|
11022
|
+
() => orderHistory.filter((o) => o.status === "OPEN" || o.status === "PARTIALLY_FILLED").length,
|
|
11023
|
+
[orderHistory]
|
|
11024
|
+
);
|
|
11025
|
+
const pendingOfferingsCount = React9.useMemo(
|
|
11026
|
+
() => offeringOrders.filter((o) => {
|
|
11027
|
+
const s = o.status.toUpperCase();
|
|
11028
|
+
return s !== "FILLED" && s !== "ALLOCATED" && s !== "CONFIRMED" && s !== "CANCELLED" && s !== "CANCELED" && s !== "REJECTED";
|
|
11029
|
+
}).length,
|
|
11030
|
+
[offeringOrders]
|
|
11031
|
+
);
|
|
10700
11032
|
const activityTotalPages = Math.ceil(activeTabTotal / pageSize);
|
|
10701
11033
|
const pageSlice = (arr) => arr.slice(activityPage * pageSize, (activityPage + 1) * pageSize);
|
|
10702
11034
|
const handleTabChange = (tab) => {
|
|
@@ -10706,10 +11038,38 @@ function PortfolioActivityPanel({
|
|
|
10706
11038
|
return /* @__PURE__ */ jsxRuntime.jsxs(Container2, { className, style, children: [
|
|
10707
11039
|
/* @__PURE__ */ jsxRuntime.jsx(PanelTitle, { children: "Activity" }),
|
|
10708
11040
|
/* @__PURE__ */ jsxRuntime.jsxs(TabContainer, { children: [
|
|
10709
|
-
showPositionsTab && /* @__PURE__ */ jsxRuntime.
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
11041
|
+
showPositionsTab && /* @__PURE__ */ jsxRuntime.jsxs(Tab, { $active: activeTab === "positions", onClick: () => handleTabChange("positions"), children: [
|
|
11042
|
+
"Positions",
|
|
11043
|
+
positionsCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(TabCount, { children: [
|
|
11044
|
+
" (",
|
|
11045
|
+
positionsCount,
|
|
11046
|
+
")"
|
|
11047
|
+
] })
|
|
11048
|
+
] }),
|
|
11049
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tab, { $active: activeTab === "subscriptions", onClick: () => handleTabChange("subscriptions"), children: [
|
|
11050
|
+
"Initial Offerings",
|
|
11051
|
+
pendingOfferingsCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(TabCount, { children: [
|
|
11052
|
+
" (",
|
|
11053
|
+
pendingOfferingsCount,
|
|
11054
|
+
")"
|
|
11055
|
+
] })
|
|
11056
|
+
] }),
|
|
11057
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tab, { $active: activeTab === "open-orders", onClick: () => handleTabChange("open-orders"), children: [
|
|
11058
|
+
"Open Orders",
|
|
11059
|
+
openOrdersCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(TabCount, { children: [
|
|
11060
|
+
" (",
|
|
11061
|
+
openOrdersCount,
|
|
11062
|
+
")"
|
|
11063
|
+
] })
|
|
11064
|
+
] }),
|
|
11065
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tab, { $active: activeTab === "orders", onClick: () => handleTabChange("orders"), children: [
|
|
11066
|
+
"Order History",
|
|
11067
|
+
pendingHistoryCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs(TabCount, { children: [
|
|
11068
|
+
" (",
|
|
11069
|
+
pendingHistoryCount,
|
|
11070
|
+
")"
|
|
11071
|
+
] })
|
|
11072
|
+
] }),
|
|
10713
11073
|
/* @__PURE__ */ jsxRuntime.jsx(Tab, { $active: activeTab === "trades", onClick: () => handleTabChange("trades"), children: "Trade History" }),
|
|
10714
11074
|
/* @__PURE__ */ jsxRuntime.jsx(Tab, { $active: activeTab === "transfers", onClick: () => handleTabChange("transfers"), children: "Transfers" })
|
|
10715
11075
|
] }),
|
|
@@ -10794,8 +11154,10 @@ function PortfolioActivityPanel({
|
|
|
10794
11154
|
openOrders.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { children: "Open orders will appear here while they are working in the market." }),
|
|
10795
11155
|
pageSlice(openOrders).map((order) => {
|
|
10796
11156
|
const meta = getOrderStatusMeta(order.status);
|
|
10797
|
-
const
|
|
10798
|
-
const
|
|
11157
|
+
const isMarket = order.type === "MARKET";
|
|
11158
|
+
const priceSegment = isMarket || !order.price ? "" : ` \xB7 ${formatCurrency5(order.price)}`;
|
|
11159
|
+
const filledPercent = order.quantity > 0 ? Math.round(order.filledQuantity / order.quantity * 100) : 0;
|
|
11160
|
+
const amountDisplay = !isMarket && order.price ? formatCurrency5(order.price * order.quantity) : "\u2014";
|
|
10799
11161
|
const isCancelling = cancellingOrderId === order.id;
|
|
10800
11162
|
return /* @__PURE__ */ jsxRuntime.jsxs(ActivityRow, { children: [
|
|
10801
11163
|
/* @__PURE__ */ jsxRuntime.jsx(ActivitySideBadge, { $side: sideLabel(order.side), children: sideLabel(order.side) }),
|
|
@@ -10805,9 +11167,10 @@ function PortfolioActivityPanel({
|
|
|
10805
11167
|
formatNumber2(order.quantity),
|
|
10806
11168
|
" tokens \xB7 ",
|
|
10807
11169
|
prettyLabel(order.type),
|
|
11170
|
+
priceSegment,
|
|
10808
11171
|
" \xB7 ",
|
|
10809
|
-
|
|
10810
|
-
" \xB7 ",
|
|
11172
|
+
filledPercent,
|
|
11173
|
+
"% filled \xB7 ",
|
|
10811
11174
|
formatTimestamp(order.createdAt)
|
|
10812
11175
|
] })
|
|
10813
11176
|
] }),
|
|
@@ -10834,8 +11197,10 @@ function PortfolioActivityPanel({
|
|
|
10834
11197
|
orderHistory.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { children: "No orders yet. Place a trade to see it appear here." }),
|
|
10835
11198
|
pageSlice(orderHistory).map((order) => {
|
|
10836
11199
|
const meta = getOrderStatusMeta(order.status);
|
|
10837
|
-
const
|
|
10838
|
-
const
|
|
11200
|
+
const isMarket = order.type === "MARKET";
|
|
11201
|
+
const priceSegment = isMarket || !order.price ? "" : ` \xB7 ${formatCurrency5(order.price)}`;
|
|
11202
|
+
const filledPercent = order.quantity > 0 ? Math.round(order.filledQuantity / order.quantity * 100) : 0;
|
|
11203
|
+
const amountDisplay = !isMarket && order.price ? formatCurrency5(order.price * order.quantity) : "\u2014";
|
|
10839
11204
|
return /* @__PURE__ */ jsxRuntime.jsxs(ActivityRow, { children: [
|
|
10840
11205
|
/* @__PURE__ */ jsxRuntime.jsx(ActivitySideBadge, { $side: sideLabel(order.side), children: sideLabel(order.side) }),
|
|
10841
11206
|
/* @__PURE__ */ jsxRuntime.jsxs(ActivityInfo, { children: [
|
|
@@ -10844,9 +11209,10 @@ function PortfolioActivityPanel({
|
|
|
10844
11209
|
formatNumber2(order.quantity),
|
|
10845
11210
|
" tokens \xB7 ",
|
|
10846
11211
|
prettyLabel(order.type),
|
|
11212
|
+
priceSegment,
|
|
10847
11213
|
" \xB7 ",
|
|
10848
|
-
|
|
10849
|
-
" \xB7 ",
|
|
11214
|
+
filledPercent,
|
|
11215
|
+
"% filled \xB7 ",
|
|
10850
11216
|
formatTimestamp(order.createdAt)
|
|
10851
11217
|
] })
|
|
10852
11218
|
] }),
|
|
@@ -10988,6 +11354,11 @@ var Tab = styled24__default.default.button`
|
|
|
10988
11354
|
color: ${({ $active }) => $active ? "#fff" : "rgba(255, 255, 255, 0.65)"};
|
|
10989
11355
|
}
|
|
10990
11356
|
`;
|
|
11357
|
+
var TabCount = styled24__default.default.span`
|
|
11358
|
+
color: #E6C656;
|
|
11359
|
+
font-weight: 600;
|
|
11360
|
+
margin-left: 2px;
|
|
11361
|
+
`;
|
|
10991
11362
|
var ActivityRow = styled24__default.default.div`
|
|
10992
11363
|
display: grid;
|
|
10993
11364
|
grid-template-columns: auto 1fr auto auto;
|
|
@@ -11631,23 +12002,24 @@ function PropertyBuy({
|
|
|
11631
12002
|
recentOrders = [],
|
|
11632
12003
|
ordersAllocated = 0,
|
|
11633
12004
|
subscribers = 0,
|
|
12005
|
+
isLoadingActivity = false,
|
|
11634
12006
|
selectorItems,
|
|
11635
12007
|
onSelectorSelect,
|
|
11636
12008
|
portfolioActivity
|
|
11637
12009
|
}) {
|
|
11638
|
-
const [sliderValue, setSliderValue] =
|
|
11639
|
-
const [availableBalance, setAvailableBalance] =
|
|
11640
|
-
const [manualOrderAmount, setManualOrderAmount] =
|
|
11641
|
-
const [ownedTokens, setOwnedTokens] =
|
|
11642
|
-
const [displayedOwnedTokens, setDisplayedOwnedTokens] =
|
|
11643
|
-
const [ownedTokensJustUpdated, setOwnedTokensJustUpdated] =
|
|
11644
|
-
const [lastOrderQuantity, setLastOrderQuantity] =
|
|
11645
|
-
const [orderPendingAllocation, setOrderPendingAllocation] =
|
|
11646
|
-
const [orderPlacedSuccess, setOrderPlacedSuccess] =
|
|
11647
|
-
const [lastOrderDetails, setLastOrderDetails] =
|
|
11648
|
-
const [showOrderConfirmModal, setShowOrderConfirmModal] =
|
|
11649
|
-
const [, setLiveNewsIndex] =
|
|
11650
|
-
const [newsItems, setNewsItems] =
|
|
12010
|
+
const [sliderValue, setSliderValue] = React9.useState(0);
|
|
12011
|
+
const [availableBalance, setAvailableBalance] = React9.useState(walletUsdcBalance ?? 0);
|
|
12012
|
+
const [manualOrderAmount, setManualOrderAmount] = React9.useState(null);
|
|
12013
|
+
const [ownedTokens, setOwnedTokens] = React9.useState(0);
|
|
12014
|
+
const [displayedOwnedTokens, setDisplayedOwnedTokens] = React9.useState(0);
|
|
12015
|
+
const [ownedTokensJustUpdated, setOwnedTokensJustUpdated] = React9.useState(false);
|
|
12016
|
+
const [lastOrderQuantity, setLastOrderQuantity] = React9.useState(0);
|
|
12017
|
+
const [orderPendingAllocation, setOrderPendingAllocation] = React9.useState(false);
|
|
12018
|
+
const [orderPlacedSuccess, setOrderPlacedSuccess] = React9.useState(false);
|
|
12019
|
+
const [lastOrderDetails, setLastOrderDetails] = React9.useState(null);
|
|
12020
|
+
const [showOrderConfirmModal, setShowOrderConfirmModal] = React9.useState(false);
|
|
12021
|
+
const [, setLiveNewsIndex] = React9.useState(0);
|
|
12022
|
+
const [newsItems, setNewsItems] = React9.useState(
|
|
11651
12023
|
() => allNewsItems.slice(0, 4).map((item, index) => ({
|
|
11652
12024
|
...item,
|
|
11653
12025
|
displayId: `${item.id}-initial-${index}`,
|
|
@@ -11663,6 +12035,7 @@ function PropertyBuy({
|
|
|
11663
12035
|
const offeringValuation = saleData?.offeringValuation ?? tokenPrice * supplyToSell;
|
|
11664
12036
|
const ipoStatus = saleData?.status ?? "PENDING";
|
|
11665
12037
|
const ipoStarted = ipoStatus === "LIVE" || isPrivateClient && ipoStatus === "PENDING";
|
|
12038
|
+
const ipoEnded = ipoStatus === "CLOSED" || ipoStatus === "CANCELLED";
|
|
11666
12039
|
const statusLabel = ipoStatus;
|
|
11667
12040
|
const statusColor = STATUS_COLOR2[ipoStatus] ?? "#D4AF37";
|
|
11668
12041
|
const displayStatusLabel = isPrivateClient && ipoStatus !== "LIVE" ? "Private Client Access" : statusLabel;
|
|
@@ -11673,12 +12046,12 @@ function PropertyBuy({
|
|
|
11673
12046
|
const orderTotal = tokenQuantity * tokenPrice + feeInUsd;
|
|
11674
12047
|
const estExposure = (tokenQuantity / supplyToSell * 100).toFixed(4);
|
|
11675
12048
|
const hasInsufficientFunds = orderTotal > availableBalance;
|
|
11676
|
-
|
|
12049
|
+
React9.useEffect(() => {
|
|
11677
12050
|
if (walletUsdcBalance != null) {
|
|
11678
12051
|
setAvailableBalance(walletUsdcBalance);
|
|
11679
12052
|
}
|
|
11680
12053
|
}, [walletUsdcBalance]);
|
|
11681
|
-
|
|
12054
|
+
React9.useEffect(() => {
|
|
11682
12055
|
if (walletPropertyTokenBalance != null) {
|
|
11683
12056
|
setOwnedTokens(walletPropertyTokenBalance);
|
|
11684
12057
|
setDisplayedOwnedTokens(walletPropertyTokenBalance);
|
|
@@ -11690,13 +12063,13 @@ function PropertyBuy({
|
|
|
11690
12063
|
}
|
|
11691
12064
|
setShowOrderConfirmModal(true);
|
|
11692
12065
|
};
|
|
11693
|
-
|
|
12066
|
+
React9.useEffect(() => {
|
|
11694
12067
|
if (purchaseStatus === "success" && orderPendingAllocation) {
|
|
11695
12068
|
setOrderPendingAllocation(false);
|
|
11696
12069
|
setOrderPlacedSuccess(true);
|
|
11697
12070
|
}
|
|
11698
12071
|
}, [purchaseStatus, orderPendingAllocation]);
|
|
11699
|
-
const handlePlaceAnotherOrder =
|
|
12072
|
+
const handlePlaceAnotherOrder = React9.useCallback(() => {
|
|
11700
12073
|
setOrderPlacedSuccess(false);
|
|
11701
12074
|
setOrderPendingAllocation(false);
|
|
11702
12075
|
}, []);
|
|
@@ -11753,7 +12126,7 @@ function PropertyBuy({
|
|
|
11753
12126
|
setSliderValue(0);
|
|
11754
12127
|
setManualOrderAmount(null);
|
|
11755
12128
|
};
|
|
11756
|
-
|
|
12129
|
+
React9.useEffect(() => {
|
|
11757
12130
|
const newsInterval = setInterval(() => {
|
|
11758
12131
|
setLiveNewsIndex((prev) => {
|
|
11759
12132
|
const nextIndex = (prev + 1) % allNewsItems.length;
|
|
@@ -11813,6 +12186,8 @@ function PropertyBuy({
|
|
|
11813
12186
|
VideoActivitySection,
|
|
11814
12187
|
{
|
|
11815
12188
|
ipoStarted,
|
|
12189
|
+
ipoEnded,
|
|
12190
|
+
isLoading: isLoadingActivity,
|
|
11816
12191
|
recentOrders,
|
|
11817
12192
|
ordersAllocated,
|
|
11818
12193
|
tokenPrice
|
|
@@ -12047,7 +12422,7 @@ function PaymentPopup({
|
|
|
12047
12422
|
userTokenHoldings,
|
|
12048
12423
|
propertyName
|
|
12049
12424
|
}) {
|
|
12050
|
-
const [selectedPaymentMethod, setSelectedPaymentMethod] =
|
|
12425
|
+
const [selectedPaymentMethod, setSelectedPaymentMethod] = React9.useState(
|
|
12051
12426
|
"tokens"
|
|
12052
12427
|
);
|
|
12053
12428
|
if (!isOpen) return null;
|
|
@@ -12226,20 +12601,20 @@ function PaymentPopup({
|
|
|
12226
12601
|
var payment_popup_default = PaymentPopup;
|
|
12227
12602
|
var SUMMER_MONTHS = /* @__PURE__ */ new Set([11, 0, 1]);
|
|
12228
12603
|
var OwnerBooking = ({ propertyName, token }) => {
|
|
12229
|
-
const today =
|
|
12604
|
+
const today = React9.useMemo(() => {
|
|
12230
12605
|
const base = /* @__PURE__ */ new Date();
|
|
12231
12606
|
base.setHours(0, 0, 0, 0);
|
|
12232
12607
|
return base;
|
|
12233
12608
|
}, []);
|
|
12234
|
-
const [currentYear, setCurrentYear] =
|
|
12235
|
-
const [currentMonth, setCurrentMonth] =
|
|
12236
|
-
const [dateRanges, setDateRanges] =
|
|
12237
|
-
const [selectedDates, setSelectedDates] =
|
|
12238
|
-
const [hoverDate, setHoverDate] =
|
|
12239
|
-
const [isDateSelectorOpen, setIsDateSelectorOpen] =
|
|
12240
|
-
const [selectorYear, setSelectorYear] =
|
|
12241
|
-
const [isPaymentPopupOpen, setIsPaymentPopupOpen] =
|
|
12242
|
-
const dateSelectorRef =
|
|
12609
|
+
const [currentYear, setCurrentYear] = React9.useState(today.getFullYear());
|
|
12610
|
+
const [currentMonth, setCurrentMonth] = React9.useState(today.getMonth());
|
|
12611
|
+
const [dateRanges, setDateRanges] = React9.useState([]);
|
|
12612
|
+
const [selectedDates, setSelectedDates] = React9.useState([]);
|
|
12613
|
+
const [hoverDate, setHoverDate] = React9.useState(null);
|
|
12614
|
+
const [isDateSelectorOpen, setIsDateSelectorOpen] = React9.useState(false);
|
|
12615
|
+
const [selectorYear, setSelectorYear] = React9.useState(today.getFullYear());
|
|
12616
|
+
const [isPaymentPopupOpen, setIsPaymentPopupOpen] = React9.useState(false);
|
|
12617
|
+
const dateSelectorRef = React9.useRef(null);
|
|
12243
12618
|
const tokenPrice = token.price ?? 700;
|
|
12244
12619
|
const userTokenHoldings = 2.2;
|
|
12245
12620
|
const MIN_NIGHTS = 3;
|
|
@@ -12249,25 +12624,25 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12249
12624
|
{ bg: "rgba(230, 126, 34, 0.25)", border: "rgba(230, 126, 34, 0.6)" },
|
|
12250
12625
|
{ bg: "rgba(46, 204, 113, 0.25)", border: "rgba(46, 204, 113, 0.6)" }
|
|
12251
12626
|
];
|
|
12252
|
-
const calculateTokensPerDayOwner =
|
|
12627
|
+
const calculateTokensPerDayOwner = React9.useCallback(() => {
|
|
12253
12628
|
if (tokenPrice <= 0) return 0;
|
|
12254
12629
|
const target = 650;
|
|
12255
12630
|
const raw = target / tokenPrice;
|
|
12256
12631
|
return Math.ceil(raw * 1e4) / 1e4;
|
|
12257
12632
|
}, [tokenPrice]);
|
|
12258
|
-
const calculateTokensPerDayMarket =
|
|
12633
|
+
const calculateTokensPerDayMarket = React9.useCallback(() => {
|
|
12259
12634
|
if (tokenPrice <= 0) return 0;
|
|
12260
12635
|
const target = 900;
|
|
12261
12636
|
const raw = target / tokenPrice;
|
|
12262
12637
|
return Math.ceil(raw * 1e4) / 1e4;
|
|
12263
12638
|
}, [tokenPrice]);
|
|
12264
12639
|
const qualifiesForOwnerRate = userTokenHoldings >= 0.1;
|
|
12265
|
-
const getTokensPerDay =
|
|
12640
|
+
const getTokensPerDay = React9.useCallback(
|
|
12266
12641
|
() => calculateTokensPerDayOwner() ,
|
|
12267
12642
|
[qualifiesForOwnerRate, calculateTokensPerDayOwner, calculateTokensPerDayMarket]
|
|
12268
12643
|
);
|
|
12269
12644
|
const getRateLabel = () => "Owner's Rate" ;
|
|
12270
|
-
const selectionStats =
|
|
12645
|
+
const selectionStats = React9.useMemo(() => {
|
|
12271
12646
|
if (selectedDates.length !== 2) return null;
|
|
12272
12647
|
const [a, b] = selectedDates;
|
|
12273
12648
|
const start = a < b ? a : b;
|
|
@@ -12278,10 +12653,10 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12278
12653
|
const usd = tokens * tokenPrice;
|
|
12279
12654
|
return { nights, tokensPerDay, tokens, usd, start, end };
|
|
12280
12655
|
}, [selectedDates, getTokensPerDay, tokenPrice]);
|
|
12281
|
-
const totalNights =
|
|
12282
|
-
const totalTokens =
|
|
12656
|
+
const totalNights = React9.useMemo(() => dateRanges.reduce((sum, r) => sum + r.nights, 0), [dateRanges]);
|
|
12657
|
+
const totalTokens = React9.useMemo(() => dateRanges.reduce((sum, r) => sum + r.tokens, 0), [dateRanges]);
|
|
12283
12658
|
const totalUSD = totalTokens * tokenPrice;
|
|
12284
|
-
const generateCalendarDays =
|
|
12659
|
+
const generateCalendarDays = React9.useCallback(
|
|
12285
12660
|
(year, month) => {
|
|
12286
12661
|
const first = new Date(year, month, 1);
|
|
12287
12662
|
const last = new Date(year, month + 1, 0);
|
|
@@ -12310,11 +12685,11 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12310
12685
|
},
|
|
12311
12686
|
[today]
|
|
12312
12687
|
);
|
|
12313
|
-
const calendarDays =
|
|
12688
|
+
const calendarDays = React9.useMemo(
|
|
12314
12689
|
() => generateCalendarDays(currentYear, currentMonth),
|
|
12315
12690
|
[currentYear, currentMonth, generateCalendarDays]
|
|
12316
12691
|
);
|
|
12317
|
-
const isDateReserved =
|
|
12692
|
+
const isDateReserved = React9.useCallback(
|
|
12318
12693
|
(date) => dateRanges.some((r) => date >= r.arrival && date <= r.departure),
|
|
12319
12694
|
[dateRanges]
|
|
12320
12695
|
);
|
|
@@ -12408,14 +12783,14 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12408
12783
|
"December"
|
|
12409
12784
|
];
|
|
12410
12785
|
const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
12411
|
-
const setMonthYear =
|
|
12786
|
+
const setMonthYear = React9.useCallback(
|
|
12412
12787
|
(month, year) => {
|
|
12413
12788
|
setCurrentMonth(month);
|
|
12414
12789
|
setCurrentYear(year);
|
|
12415
12790
|
},
|
|
12416
12791
|
[setCurrentMonth, setCurrentYear]
|
|
12417
12792
|
);
|
|
12418
|
-
const shiftMonth =
|
|
12793
|
+
const shiftMonth = React9.useCallback(
|
|
12419
12794
|
(direction) => {
|
|
12420
12795
|
const delta = direction === "prev" ? -1 : 1;
|
|
12421
12796
|
let newMonth = currentMonth + delta;
|
|
@@ -12432,7 +12807,7 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12432
12807
|
},
|
|
12433
12808
|
[currentMonth, currentYear, setMonthYear]
|
|
12434
12809
|
);
|
|
12435
|
-
const jumpToNextAvailable =
|
|
12810
|
+
const jumpToNextAvailable = React9.useCallback(() => {
|
|
12436
12811
|
for (let offset = 1; offset <= 12; offset++) {
|
|
12437
12812
|
const candidateMonth = (currentMonth + offset) % 12;
|
|
12438
12813
|
if (!SUMMER_MONTHS.has(candidateMonth)) continue;
|
|
@@ -12449,7 +12824,7 @@ var OwnerBooking = ({ propertyName, token }) => {
|
|
|
12449
12824
|
setMonthYear(month, selectorYear);
|
|
12450
12825
|
setIsDateSelectorOpen(false);
|
|
12451
12826
|
};
|
|
12452
|
-
|
|
12827
|
+
React9.useEffect(() => {
|
|
12453
12828
|
const handleClickOutside = (event) => {
|
|
12454
12829
|
if (dateSelectorRef.current && !dateSelectorRef.current.contains(event.target)) {
|
|
12455
12830
|
setIsDateSelectorOpen(false);
|
|
@@ -12893,21 +13268,21 @@ function PropertyValuation({
|
|
|
12893
13268
|
loading = false,
|
|
12894
13269
|
error = null
|
|
12895
13270
|
}) {
|
|
12896
|
-
const now =
|
|
12897
|
-
const lastPrice =
|
|
13271
|
+
const now = React9.useMemo(() => /* @__PURE__ */ new Date(), []);
|
|
13272
|
+
const lastPrice = React9.useMemo(() => {
|
|
12898
13273
|
const fallback = Number.isFinite(tokenPrice) && tokenPrice > 0 ? tokenPrice : 0;
|
|
12899
13274
|
if (!summary?.lastPrice || summary.lastPrice <= 0) {
|
|
12900
13275
|
return fallback;
|
|
12901
13276
|
}
|
|
12902
13277
|
return summary.lastPrice;
|
|
12903
13278
|
}, [summary, tokenPrice]);
|
|
12904
|
-
const fairValue =
|
|
13279
|
+
const fairValue = React9.useMemo(() => {
|
|
12905
13280
|
if (summary?.fairValue && summary.fairValue > 0) {
|
|
12906
13281
|
return summary.fairValue;
|
|
12907
13282
|
}
|
|
12908
13283
|
return lastPrice || 1;
|
|
12909
13284
|
}, [summary, lastPrice]);
|
|
12910
|
-
const tokensOutstanding =
|
|
13285
|
+
const tokensOutstanding = React9.useMemo(() => {
|
|
12911
13286
|
if (summary?.totalTokens && summary.totalTokens > 0) {
|
|
12912
13287
|
return summary.totalTokens;
|
|
12913
13288
|
}
|
|
@@ -12922,8 +13297,8 @@ function PropertyValuation({
|
|
|
12922
13297
|
const valuationStatus = summary?.valuationStatus ?? (lastPrice < fairValue ? "Undervalued" : lastPrice > fairValue ? "Overvalued" : "Fair Value");
|
|
12923
13298
|
const valuationDelta = summary?.valuationDeltaPercent ?? (lastPrice - fairValue) / fairValue * 100;
|
|
12924
13299
|
const valuationDeltaFormatted = `${valuationDelta >= 0 ? "+" : ""}${valuationDelta.toFixed(1)}%`;
|
|
12925
|
-
const { valuationPath, fairValuePath, axisLabels } =
|
|
12926
|
-
const recentSales =
|
|
13300
|
+
const { valuationPath, fairValuePath, axisLabels } = React9.useMemo(() => buildChartPaths(history, fairValue), [history, fairValue]);
|
|
13301
|
+
const recentSales = React9.useMemo(() => {
|
|
12927
13302
|
if (summary?.recentSales?.length) {
|
|
12928
13303
|
return summary.recentSales;
|
|
12929
13304
|
}
|
|
@@ -14075,19 +14450,19 @@ function PropertyPhotoGallery({
|
|
|
14075
14450
|
);
|
|
14076
14451
|
}
|
|
14077
14452
|
function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose }) {
|
|
14078
|
-
const [currentIndex, setCurrentIndex] =
|
|
14079
|
-
const [activeHotspotId, setActiveHotspotId] =
|
|
14080
|
-
const sliderRef =
|
|
14081
|
-
const [isDragging, setIsDragging] =
|
|
14082
|
-
const wasDraggingRef =
|
|
14083
|
-
const touchStartX =
|
|
14084
|
-
const touchStartY =
|
|
14085
|
-
const isSwiping =
|
|
14086
|
-
const progress =
|
|
14453
|
+
const [currentIndex, setCurrentIndex] = React9.useState(() => clampIndex(startIndex, galleryImages.length));
|
|
14454
|
+
const [activeHotspotId, setActiveHotspotId] = React9.useState(null);
|
|
14455
|
+
const sliderRef = React9.useRef(null);
|
|
14456
|
+
const [isDragging, setIsDragging] = React9.useState(false);
|
|
14457
|
+
const wasDraggingRef = React9.useRef(false);
|
|
14458
|
+
const touchStartX = React9.useRef(null);
|
|
14459
|
+
const touchStartY = React9.useRef(null);
|
|
14460
|
+
const isSwiping = React9.useRef(false);
|
|
14461
|
+
const progress = React9.useMemo(() => {
|
|
14087
14462
|
if (galleryImages.length <= 1) return 0;
|
|
14088
14463
|
return currentIndex / (galleryImages.length - 1) * 100;
|
|
14089
14464
|
}, [currentIndex, galleryImages.length]);
|
|
14090
|
-
|
|
14465
|
+
React9.useEffect(() => {
|
|
14091
14466
|
document.body.style.overflow = "hidden";
|
|
14092
14467
|
document.body.style.touchAction = "none";
|
|
14093
14468
|
return () => {
|
|
@@ -14095,7 +14470,7 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
|
|
|
14095
14470
|
document.body.style.touchAction = "";
|
|
14096
14471
|
};
|
|
14097
14472
|
}, []);
|
|
14098
|
-
|
|
14473
|
+
React9.useEffect(() => {
|
|
14099
14474
|
const handleKey = (event) => {
|
|
14100
14475
|
if (event.key === "Escape") onClose();
|
|
14101
14476
|
if (event.key === "ArrowLeft") setCurrentIndex((i) => i === 0 ? galleryImages.length - 1 : i - 1);
|
|
@@ -14368,13 +14743,13 @@ function truncateHash(hash) {
|
|
|
14368
14743
|
return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
|
|
14369
14744
|
}
|
|
14370
14745
|
function ToastItem({ toast, onDismiss }) {
|
|
14371
|
-
const [exiting, setExiting] =
|
|
14372
|
-
const timerRef =
|
|
14373
|
-
const dismiss =
|
|
14746
|
+
const [exiting, setExiting] = React9.useState(false);
|
|
14747
|
+
const timerRef = React9.useRef(null);
|
|
14748
|
+
const dismiss = React9.useCallback(() => {
|
|
14374
14749
|
setExiting(true);
|
|
14375
14750
|
setTimeout(() => onDismiss(toast.id), 280);
|
|
14376
14751
|
}, [onDismiss, toast.id]);
|
|
14377
|
-
|
|
14752
|
+
React9.useEffect(() => {
|
|
14378
14753
|
const duration2 = toast.duration ?? 6e3;
|
|
14379
14754
|
if (duration2 > 0) {
|
|
14380
14755
|
timerRef.current = setTimeout(dismiss, duration2);
|
|
@@ -14403,15 +14778,15 @@ function ToastItem({ toast, onDismiss }) {
|
|
|
14403
14778
|
duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar, { $color: accent, $duration: duration })
|
|
14404
14779
|
] });
|
|
14405
14780
|
}
|
|
14406
|
-
var ToastContext =
|
|
14781
|
+
var ToastContext = React9.createContext(null);
|
|
14407
14782
|
function ToastProvider({ children }) {
|
|
14408
|
-
const [toasts, setToasts] =
|
|
14409
|
-
const addToast =
|
|
14783
|
+
const [toasts, setToasts] = React9.useState([]);
|
|
14784
|
+
const addToast = React9.useCallback((data) => {
|
|
14410
14785
|
const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
14411
14786
|
setToasts((prev) => [...prev, { ...data, id }]);
|
|
14412
14787
|
return id;
|
|
14413
14788
|
}, []);
|
|
14414
|
-
const dismiss =
|
|
14789
|
+
const dismiss = React9.useCallback((id) => {
|
|
14415
14790
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
14416
14791
|
}, []);
|
|
14417
14792
|
return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
|
|
@@ -14420,10 +14795,71 @@ function ToastProvider({ children }) {
|
|
|
14420
14795
|
] });
|
|
14421
14796
|
}
|
|
14422
14797
|
function useToast() {
|
|
14423
|
-
const ctx =
|
|
14798
|
+
const ctx = React9.useContext(ToastContext);
|
|
14424
14799
|
if (!ctx) throw new Error("useToast must be used within a ToastProvider");
|
|
14425
14800
|
return ctx;
|
|
14426
14801
|
}
|
|
14802
|
+
var INTERVALS = [1e3, 2e3, 4e3, 5e3, 7e3, 1e4, 12e3];
|
|
14803
|
+
function useAdaptivePolling({ enabled, onPoll }) {
|
|
14804
|
+
const onPollRef = React9.useRef(onPoll);
|
|
14805
|
+
onPollRef.current = onPoll;
|
|
14806
|
+
React9.useEffect(() => {
|
|
14807
|
+
if (!enabled) return;
|
|
14808
|
+
let cancelled = false;
|
|
14809
|
+
let timeoutId = null;
|
|
14810
|
+
let step = 0;
|
|
14811
|
+
const clear = () => {
|
|
14812
|
+
if (timeoutId) {
|
|
14813
|
+
clearTimeout(timeoutId);
|
|
14814
|
+
timeoutId = null;
|
|
14815
|
+
}
|
|
14816
|
+
};
|
|
14817
|
+
const isHidden = () => typeof document !== "undefined" && document.visibilityState === "hidden";
|
|
14818
|
+
const tick = async () => {
|
|
14819
|
+
if (cancelled) return;
|
|
14820
|
+
if (isHidden()) {
|
|
14821
|
+
return;
|
|
14822
|
+
}
|
|
14823
|
+
try {
|
|
14824
|
+
await onPollRef.current();
|
|
14825
|
+
} catch {
|
|
14826
|
+
}
|
|
14827
|
+
if (cancelled) return;
|
|
14828
|
+
step = Math.min(step + 1, INTERVALS.length - 1);
|
|
14829
|
+
timeoutId = setTimeout(tick, INTERVALS[step]);
|
|
14830
|
+
};
|
|
14831
|
+
const onVisibility = () => {
|
|
14832
|
+
if (document.visibilityState === "visible") {
|
|
14833
|
+
step = 0;
|
|
14834
|
+
clear();
|
|
14835
|
+
timeoutId = setTimeout(tick, 0);
|
|
14836
|
+
}
|
|
14837
|
+
};
|
|
14838
|
+
if (typeof document !== "undefined") {
|
|
14839
|
+
document.addEventListener("visibilitychange", onVisibility);
|
|
14840
|
+
}
|
|
14841
|
+
timeoutId = setTimeout(tick, INTERVALS[0]);
|
|
14842
|
+
return () => {
|
|
14843
|
+
cancelled = true;
|
|
14844
|
+
clear();
|
|
14845
|
+
if (typeof document !== "undefined") {
|
|
14846
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
14847
|
+
}
|
|
14848
|
+
};
|
|
14849
|
+
}, [enabled]);
|
|
14850
|
+
}
|
|
14851
|
+
function hasPendingActivity(data) {
|
|
14852
|
+
if (!data) return false;
|
|
14853
|
+
const openPending = data.openOrders?.some((o) => {
|
|
14854
|
+
const s = o.status.toUpperCase();
|
|
14855
|
+
return s === "OPEN" || s === "PARTIALLY_FILLED";
|
|
14856
|
+
}) ?? false;
|
|
14857
|
+
if (openPending) return true;
|
|
14858
|
+
return data.offeringOrders?.some((o) => {
|
|
14859
|
+
const s = o.status.toUpperCase();
|
|
14860
|
+
return s !== "FILLED" && s !== "ALLOCATED" && s !== "CONFIRMED" && s !== "CANCELLED" && s !== "CANCELED" && s !== "REJECTED";
|
|
14861
|
+
}) ?? false;
|
|
14862
|
+
}
|
|
14427
14863
|
|
|
14428
14864
|
exports.AssetSelectorBar = AssetSelectorBar;
|
|
14429
14865
|
exports.Badge = Badge;
|
|
@@ -14460,12 +14896,15 @@ exports.PropertyPhotoGallery = PropertyPhotoGallery;
|
|
|
14460
14896
|
exports.PropertySubheader = PropertySubheader;
|
|
14461
14897
|
exports.PropertyTour = PropertyTour;
|
|
14462
14898
|
exports.PropertyValuation = PropertyValuation;
|
|
14899
|
+
exports.Skeleton = Skeleton;
|
|
14463
14900
|
exports.ToastProvider = ToastProvider;
|
|
14464
14901
|
exports.TradeConfirmationModal = TradeConfirmationModal;
|
|
14465
14902
|
exports.TradingSlider = TradingSlider;
|
|
14466
14903
|
exports.YourOrders = YourOrders;
|
|
14467
14904
|
exports.badgeVariants = badgeVariants;
|
|
14468
14905
|
exports.buttonVariants = buttonVariants;
|
|
14906
|
+
exports.hasPendingActivity = hasPendingActivity;
|
|
14907
|
+
exports.useAdaptivePolling = useAdaptivePolling;
|
|
14469
14908
|
exports.useToast = useToast;
|
|
14470
14909
|
//# sourceMappingURL=index.js.map
|
|
14471
14910
|
//# sourceMappingURL=index.js.map
|