@loafmarkets/ui 0.0.4 → 0.0.6
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 +24 -2
- package/dist/index.d.ts +24 -2
- package/dist/index.js +168 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +168 -29
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -116,9 +116,10 @@ interface HousePositionSliderProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
116
116
|
pendingOrders?: HousePositionPendingOrder[];
|
|
117
117
|
defaultOrderType?: "market" | "limit";
|
|
118
118
|
orderbook?: HousePositionOrderbook;
|
|
119
|
+
ownershipPercentOverride?: number;
|
|
119
120
|
onConfirmOrder?: (payload: HousePositionSliderOrderPayload) => void;
|
|
120
121
|
}
|
|
121
|
-
declare function HousePositionSlider({ tokenId, tokenSymbol, totalTokens, currentPrice, availableCash, tokensHeld, pendingOrders, defaultOrderType, orderbook, onConfirmOrder, className, ...props }: HousePositionSliderProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
declare function HousePositionSlider({ tokenId, tokenSymbol, totalTokens, currentPrice, availableCash, tokensHeld, pendingOrders, defaultOrderType, orderbook, ownershipPercentOverride, onConfirmOrder, className, ...props }: HousePositionSliderProps): react_jsx_runtime.JSX.Element;
|
|
122
123
|
|
|
123
124
|
type PropertyTourProps = Omit<React.ComponentPropsWithoutRef<typeof Card>, "title"> & {
|
|
124
125
|
title: string;
|
|
@@ -160,6 +161,27 @@ interface PropertyNewsUpdatesProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
160
161
|
}
|
|
161
162
|
declare const PropertyNewsUpdates: React.ForwardRefExoticComponent<PropertyNewsUpdatesProps & React.RefAttributes<HTMLDivElement>>;
|
|
162
163
|
|
|
164
|
+
type PropertyAddressOption = {
|
|
165
|
+
id: string;
|
|
166
|
+
label: string;
|
|
167
|
+
};
|
|
168
|
+
type PropertyCompareBarProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
169
|
+
addresses: (PropertyAddressOption | string)[];
|
|
170
|
+
selectedAddressId?: string;
|
|
171
|
+
onSelectAddress?: (addressId: string) => void;
|
|
172
|
+
compareLabel?: string;
|
|
173
|
+
onCompareClick?: () => void;
|
|
174
|
+
compareIcon?: React.ReactNode;
|
|
175
|
+
};
|
|
176
|
+
declare const PropertyCompareBar: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
177
|
+
addresses: (PropertyAddressOption | string)[];
|
|
178
|
+
selectedAddressId?: string;
|
|
179
|
+
onSelectAddress?: (addressId: string) => void;
|
|
180
|
+
compareLabel?: string;
|
|
181
|
+
onCompareClick?: () => void;
|
|
182
|
+
compareIcon?: React.ReactNode;
|
|
183
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
184
|
+
|
|
163
185
|
type YourOrderSide = "buy" | "sell";
|
|
164
186
|
type YourOrder = {
|
|
165
187
|
id: string;
|
|
@@ -274,4 +296,4 @@ declare const PropertySubheader: React.ForwardRefExoticComponent<React.HTMLAttri
|
|
|
274
296
|
actions?: PropertySubheaderAction[];
|
|
275
297
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
276
298
|
|
|
277
|
-
export { Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, type HousePositionOrderbook, type HousePositionPendingOrder, HousePositionSlider, type HousePositionSliderOrderPayload, type HousePositionSliderProps, Orderbook, type OrderbookLevel, type OrderbookProps, type OrderbookSide, type OrderbookTrade, PortfolioSummary, type PortfolioSummaryProps, PriceChart, type PriceChartCandle, type PriceChartProps, type PriceChartRange, PropertyHeroHeader, type PropertyHeroHeaderProps, type PropertyNewsItem, type PropertyNewsType, PropertyNewsUpdates, type PropertyNewsUpdatesProps, PropertySubheader, type PropertySubheaderAction, type PropertySubheaderProps, type PropertySubheaderTab, PropertyTour, type PropertyTourProps, type YourOrder, type YourOrderSide, YourOrders, type YourOrdersProps, badgeVariants, buttonVariants };
|
|
299
|
+
export { Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, type HousePositionOrderbook, type HousePositionPendingOrder, HousePositionSlider, type HousePositionSliderOrderPayload, type HousePositionSliderProps, Orderbook, type OrderbookLevel, type OrderbookProps, type OrderbookSide, type OrderbookTrade, PortfolioSummary, type PortfolioSummaryProps, PriceChart, type PriceChartCandle, type PriceChartProps, type PriceChartRange, type PropertyAddressOption, PropertyCompareBar, type PropertyCompareBarProps, PropertyHeroHeader, type PropertyHeroHeaderProps, type PropertyNewsItem, type PropertyNewsType, PropertyNewsUpdates, type PropertyNewsUpdatesProps, PropertySubheader, type PropertySubheaderAction, type PropertySubheaderProps, type PropertySubheaderTab, PropertyTour, type PropertyTourProps, type YourOrder, type YourOrderSide, YourOrders, type YourOrdersProps, badgeVariants, buttonVariants };
|
package/dist/index.d.ts
CHANGED
|
@@ -116,9 +116,10 @@ interface HousePositionSliderProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
116
116
|
pendingOrders?: HousePositionPendingOrder[];
|
|
117
117
|
defaultOrderType?: "market" | "limit";
|
|
118
118
|
orderbook?: HousePositionOrderbook;
|
|
119
|
+
ownershipPercentOverride?: number;
|
|
119
120
|
onConfirmOrder?: (payload: HousePositionSliderOrderPayload) => void;
|
|
120
121
|
}
|
|
121
|
-
declare function HousePositionSlider({ tokenId, tokenSymbol, totalTokens, currentPrice, availableCash, tokensHeld, pendingOrders, defaultOrderType, orderbook, onConfirmOrder, className, ...props }: HousePositionSliderProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
declare function HousePositionSlider({ tokenId, tokenSymbol, totalTokens, currentPrice, availableCash, tokensHeld, pendingOrders, defaultOrderType, orderbook, ownershipPercentOverride, onConfirmOrder, className, ...props }: HousePositionSliderProps): react_jsx_runtime.JSX.Element;
|
|
122
123
|
|
|
123
124
|
type PropertyTourProps = Omit<React.ComponentPropsWithoutRef<typeof Card>, "title"> & {
|
|
124
125
|
title: string;
|
|
@@ -160,6 +161,27 @@ interface PropertyNewsUpdatesProps extends React.HTMLAttributes<HTMLDivElement>
|
|
|
160
161
|
}
|
|
161
162
|
declare const PropertyNewsUpdates: React.ForwardRefExoticComponent<PropertyNewsUpdatesProps & React.RefAttributes<HTMLDivElement>>;
|
|
162
163
|
|
|
164
|
+
type PropertyAddressOption = {
|
|
165
|
+
id: string;
|
|
166
|
+
label: string;
|
|
167
|
+
};
|
|
168
|
+
type PropertyCompareBarProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
169
|
+
addresses: (PropertyAddressOption | string)[];
|
|
170
|
+
selectedAddressId?: string;
|
|
171
|
+
onSelectAddress?: (addressId: string) => void;
|
|
172
|
+
compareLabel?: string;
|
|
173
|
+
onCompareClick?: () => void;
|
|
174
|
+
compareIcon?: React.ReactNode;
|
|
175
|
+
};
|
|
176
|
+
declare const PropertyCompareBar: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
177
|
+
addresses: (PropertyAddressOption | string)[];
|
|
178
|
+
selectedAddressId?: string;
|
|
179
|
+
onSelectAddress?: (addressId: string) => void;
|
|
180
|
+
compareLabel?: string;
|
|
181
|
+
onCompareClick?: () => void;
|
|
182
|
+
compareIcon?: React.ReactNode;
|
|
183
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
184
|
+
|
|
163
185
|
type YourOrderSide = "buy" | "sell";
|
|
164
186
|
type YourOrder = {
|
|
165
187
|
id: string;
|
|
@@ -274,4 +296,4 @@ declare const PropertySubheader: React.ForwardRefExoticComponent<React.HTMLAttri
|
|
|
274
296
|
actions?: PropertySubheaderAction[];
|
|
275
297
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
276
298
|
|
|
277
|
-
export { Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, type HousePositionOrderbook, type HousePositionPendingOrder, HousePositionSlider, type HousePositionSliderOrderPayload, type HousePositionSliderProps, Orderbook, type OrderbookLevel, type OrderbookProps, type OrderbookSide, type OrderbookTrade, PortfolioSummary, type PortfolioSummaryProps, PriceChart, type PriceChartCandle, type PriceChartProps, type PriceChartRange, PropertyHeroHeader, type PropertyHeroHeaderProps, type PropertyNewsItem, type PropertyNewsType, PropertyNewsUpdates, type PropertyNewsUpdatesProps, PropertySubheader, type PropertySubheaderAction, type PropertySubheaderProps, type PropertySubheaderTab, PropertyTour, type PropertyTourProps, type YourOrder, type YourOrderSide, YourOrders, type YourOrdersProps, badgeVariants, buttonVariants };
|
|
299
|
+
export { Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, type CardContentProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, CardTitle, type CardTitleProps, type HousePositionOrderbook, type HousePositionPendingOrder, HousePositionSlider, type HousePositionSliderOrderPayload, type HousePositionSliderProps, Orderbook, type OrderbookLevel, type OrderbookProps, type OrderbookSide, type OrderbookTrade, PortfolioSummary, type PortfolioSummaryProps, PriceChart, type PriceChartCandle, type PriceChartProps, type PriceChartRange, type PropertyAddressOption, PropertyCompareBar, type PropertyCompareBarProps, PropertyHeroHeader, type PropertyHeroHeaderProps, type PropertyNewsItem, type PropertyNewsType, PropertyNewsUpdates, type PropertyNewsUpdatesProps, PropertySubheader, type PropertySubheaderAction, type PropertySubheaderProps, type PropertySubheaderTab, PropertyTour, type PropertyTourProps, type YourOrder, type YourOrderSide, YourOrders, type YourOrdersProps, badgeVariants, buttonVariants };
|
package/dist/index.js
CHANGED
|
@@ -304,6 +304,7 @@ function HousePositionSlider({
|
|
|
304
304
|
pendingOrders = [],
|
|
305
305
|
defaultOrderType = "market",
|
|
306
306
|
orderbook,
|
|
307
|
+
ownershipPercentOverride,
|
|
307
308
|
onConfirmOrder,
|
|
308
309
|
className,
|
|
309
310
|
...props
|
|
@@ -314,6 +315,7 @@ function HousePositionSlider({
|
|
|
314
315
|
const [deltaTokensBuy, setDeltaTokensBuy] = React5__namespace.useState(0);
|
|
315
316
|
const [deltaTokensSell, setDeltaTokensSell] = React5__namespace.useState(0);
|
|
316
317
|
const [isDragging, setIsDragging] = React5__namespace.useState(false);
|
|
318
|
+
const [visualTargetPct, setVisualTargetPct] = React5__namespace.useState(null);
|
|
317
319
|
const [orderType, setOrderType] = React5__namespace.useState(defaultOrderType);
|
|
318
320
|
const [limitPrice, setLimitPrice] = React5__namespace.useState(currentPrice);
|
|
319
321
|
const [limitPriceInput, setLimitPriceInput] = React5__namespace.useState(currentPrice.toFixed(2));
|
|
@@ -335,9 +337,8 @@ function HousePositionSlider({
|
|
|
335
337
|
const effectiveAvailableCash = Math.max(0, availableCash - pendingBuyValue);
|
|
336
338
|
const effectiveTokensHeld = Math.max(0, tokensHeld - pendingSellTokens);
|
|
337
339
|
const holdingsValue = tokensHeld * effectivePrice;
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
const baselinePct = sliderTotalCapacity <= 0 ? 0 : sliderHoldingsValue / sliderTotalCapacity * 100;
|
|
340
|
+
const safeTotalTokens = totalTokens > 0 ? totalTokens : 1;
|
|
341
|
+
const baselineOwnershipActual = clamp(effectiveTokensHeld / safeTotalTokens * 100, 0, 100);
|
|
341
342
|
let deltaTokens = 0;
|
|
342
343
|
let deltaValue = 0;
|
|
343
344
|
let marketAvgPrice = null;
|
|
@@ -383,29 +384,21 @@ function HousePositionSlider({
|
|
|
383
384
|
}
|
|
384
385
|
targetTokens = tokensHeld + deltaTokens;
|
|
385
386
|
targetValue = targetTokens * effectivePrice;
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
if (buyTrackingMode === "dollars") {
|
|
389
|
-
const notional = Math.min(Math.max(0, deltaDollars), effectiveAvailableCash);
|
|
390
|
-
return notional;
|
|
391
|
-
}
|
|
392
|
-
const tokensPlanned = Math.max(0, deltaTokensBuy);
|
|
393
|
-
const referencePrice = orderType === "market" ? currentPrice || limitPriceSafe : limitPriceSafe;
|
|
394
|
-
return Math.min(tokensPlanned * referencePrice, effectiveAvailableCash);
|
|
395
|
-
}
|
|
396
|
-
if (orderMode === "sell") {
|
|
397
|
-
const tokensToSell = Math.abs(Math.min(0, deltaTokensSell));
|
|
398
|
-
const sellValue = tokensToSell * effectivePrice;
|
|
399
|
-
return -Math.min(sellValue, sliderHoldingsValue);
|
|
400
|
-
}
|
|
401
|
-
return 0;
|
|
402
|
-
})();
|
|
403
|
-
const sliderTargetValue = clamp(sliderHoldingsValue + plannedDeltaValue, 0, sliderTotalCapacity);
|
|
404
|
-
const targetPct = sliderTotalCapacity <= 0 ? 0 : sliderTargetValue / sliderTotalCapacity * 100;
|
|
387
|
+
const sliderTargetTokens = clamp(effectiveTokensHeld + deltaTokens, 0, safeTotalTokens);
|
|
388
|
+
const normalizedTargetPct = sliderTargetTokens / safeTotalTokens * 100;
|
|
405
389
|
const isIncrease = orderMode === "buy";
|
|
406
390
|
const hasChange = orderMode !== "none" && (Math.abs(deltaTokens) > 1e-3 || Math.abs(deltaValue) > 0.01);
|
|
407
|
-
const currentOwnership = totalTokens <= 0 ? 0 : tokensHeld / totalTokens * 100;
|
|
408
|
-
const targetOwnership = totalTokens <= 0 ? 0 : targetTokens / totalTokens * 100;
|
|
391
|
+
const currentOwnership = totalTokens <= 0 ? 0 : clamp(tokensHeld / totalTokens * 100, 0, 100);
|
|
392
|
+
const targetOwnership = totalTokens <= 0 ? 0 : clamp(targetTokens / totalTokens * 100, 0, 100);
|
|
393
|
+
const ownershipOverrideValue = typeof ownershipPercentOverride === "number" && Number.isFinite(ownershipPercentOverride) ? clamp(ownershipPercentOverride, 0, 100) : null;
|
|
394
|
+
const ownershipShift = ownershipOverrideValue != null ? ownershipOverrideValue - baselineOwnershipActual : 0;
|
|
395
|
+
const baselinePct = clamp(ownershipOverrideValue ?? baselineOwnershipActual, 0, 100);
|
|
396
|
+
const impliedTargetPct = clamp(normalizedTargetPct + ownershipShift, 0, 100);
|
|
397
|
+
const displayTargetPct = visualTargetPct ?? impliedTargetPct;
|
|
398
|
+
const targetPct = displayTargetPct;
|
|
399
|
+
const displayCurrentOwnership = clamp(ownershipOverrideValue ?? currentOwnership, 0, 100);
|
|
400
|
+
const impliedDisplayTargetOwnership = clamp(targetOwnership + ownershipShift, 0, 100);
|
|
401
|
+
const displayTargetOwnership = visualTargetPct ?? impliedDisplayTargetOwnership;
|
|
409
402
|
const estFeeTokens = Math.abs(deltaValue) * 5e-3 / (effectivePrice || 1);
|
|
410
403
|
const resetOrder = React5__namespace.useCallback(() => {
|
|
411
404
|
setOrderMode("none");
|
|
@@ -413,6 +406,7 @@ function HousePositionSlider({
|
|
|
413
406
|
setDeltaDollars(0);
|
|
414
407
|
setDeltaTokensBuy(0);
|
|
415
408
|
setDeltaTokensSell(0);
|
|
409
|
+
setVisualTargetPct(null);
|
|
416
410
|
}, []);
|
|
417
411
|
const updateOrderFromTargetValue = React5__namespace.useCallback(
|
|
418
412
|
(newTargetValue) => {
|
|
@@ -443,6 +437,7 @@ function HousePositionSlider({
|
|
|
443
437
|
const nextOwnership = clamp(newOwnershipPercent, 0, 100);
|
|
444
438
|
const newTargetTokens = nextOwnership / 100 * totalTokens;
|
|
445
439
|
updateOrderFromTargetValue(newTargetTokens * effectivePrice);
|
|
440
|
+
setVisualTargetPct(nextOwnership);
|
|
446
441
|
},
|
|
447
442
|
[effectivePrice, totalTokens, updateOrderFromTargetValue]
|
|
448
443
|
);
|
|
@@ -475,12 +470,14 @@ function HousePositionSlider({
|
|
|
475
470
|
const magnitude = Math.min(Math.abs(normalized), 1);
|
|
476
471
|
if (magnitude < 0.02) {
|
|
477
472
|
resetOrder();
|
|
473
|
+
setVisualTargetPct(null);
|
|
478
474
|
return;
|
|
479
475
|
}
|
|
480
476
|
if (normalized > 0) {
|
|
481
477
|
const notional = clamp(magnitude * effectiveAvailableCash, 0, effectiveAvailableCash);
|
|
482
478
|
if (notional <= 0) {
|
|
483
479
|
resetOrder();
|
|
480
|
+
setVisualTargetPct(null);
|
|
484
481
|
return;
|
|
485
482
|
}
|
|
486
483
|
setOrderMode("buy");
|
|
@@ -488,12 +485,14 @@ function HousePositionSlider({
|
|
|
488
485
|
setDeltaDollars(notional);
|
|
489
486
|
setDeltaTokensBuy(0);
|
|
490
487
|
setDeltaTokensSell(0);
|
|
488
|
+
setVisualTargetPct(clamp(pct, 0, 100));
|
|
491
489
|
return;
|
|
492
490
|
}
|
|
493
491
|
if (normalized < 0) {
|
|
494
492
|
const tokensToSell = clamp(magnitude * effectiveTokensHeld, 0, effectiveTokensHeld);
|
|
495
493
|
if (tokensToSell <= 0) {
|
|
496
494
|
resetOrder();
|
|
495
|
+
setVisualTargetPct(null);
|
|
497
496
|
return;
|
|
498
497
|
}
|
|
499
498
|
setOrderMode("sell");
|
|
@@ -501,9 +500,11 @@ function HousePositionSlider({
|
|
|
501
500
|
setDeltaTokensSell(-tokensToSell);
|
|
502
501
|
setDeltaDollars(0);
|
|
503
502
|
setDeltaTokensBuy(0);
|
|
503
|
+
setVisualTargetPct(clamp(pct, 0, 100));
|
|
504
504
|
return;
|
|
505
505
|
}
|
|
506
506
|
resetOrder();
|
|
507
|
+
setVisualTargetPct(null);
|
|
507
508
|
},
|
|
508
509
|
[effectiveAvailableCash, effectiveTokensHeld, resetOrder]
|
|
509
510
|
);
|
|
@@ -666,19 +667,19 @@ function HousePositionSlider({
|
|
|
666
667
|
" Ownership"
|
|
667
668
|
] }),
|
|
668
669
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-white", children: [
|
|
669
|
-
|
|
670
|
+
displayCurrentOwnership.toFixed(2),
|
|
670
671
|
"%",
|
|
671
672
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-1.5 text-white/50", children: "\u2192" }),
|
|
672
673
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
673
674
|
"input",
|
|
674
675
|
{
|
|
675
676
|
type: "text",
|
|
676
|
-
value: ownershipInput ||
|
|
677
|
+
value: ownershipInput || displayTargetOwnership.toFixed(2),
|
|
677
678
|
onChange: (e) => {
|
|
678
679
|
const val = e.target.value;
|
|
679
680
|
if (val === "" || /^[0-9]*\.?[0-9]*$/.test(val)) setOwnershipInput(val);
|
|
680
681
|
},
|
|
681
|
-
onFocus: () => setOwnershipInput(
|
|
682
|
+
onFocus: () => setOwnershipInput(displayTargetOwnership.toFixed(2)),
|
|
682
683
|
onBlur: () => {
|
|
683
684
|
const num = Number.parseFloat(ownershipInput);
|
|
684
685
|
if (Number.isFinite(num)) updateOrderFromOwnership(num);
|
|
@@ -689,7 +690,7 @@ function HousePositionSlider({
|
|
|
689
690
|
},
|
|
690
691
|
className: cn(
|
|
691
692
|
"w-[70px] rounded-[4px] border bg-white/10 px-2 py-1 text-right font-semibold outline-none",
|
|
692
|
-
|
|
693
|
+
displayTargetOwnership >= displayCurrentOwnership ? "border-[rgba(14,203,129,0.3)] text-[#0ecb81] focus:border-[#0ecb81]" : "border-[rgba(246,70,93,0.3)] text-[#f6465d] focus:border-[#f6465d]"
|
|
693
694
|
)
|
|
694
695
|
}
|
|
695
696
|
)
|
|
@@ -1249,6 +1250,144 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
|
|
|
1249
1250
|
}
|
|
1250
1251
|
);
|
|
1251
1252
|
PropertyNewsUpdates.displayName = "PropertyNewsUpdates";
|
|
1253
|
+
var PropertyCompareBar = React5__namespace.forwardRef(
|
|
1254
|
+
({
|
|
1255
|
+
className,
|
|
1256
|
+
addresses,
|
|
1257
|
+
selectedAddressId,
|
|
1258
|
+
onSelectAddress,
|
|
1259
|
+
compareLabel = "Compare",
|
|
1260
|
+
onCompareClick,
|
|
1261
|
+
compareIcon,
|
|
1262
|
+
...props
|
|
1263
|
+
}, ref) => {
|
|
1264
|
+
const normalizedAddresses = React5__namespace.useMemo(() => {
|
|
1265
|
+
return addresses.map(
|
|
1266
|
+
(option) => typeof option === "string" ? { id: option, label: option } : option
|
|
1267
|
+
);
|
|
1268
|
+
}, [addresses]);
|
|
1269
|
+
const hasAddresses = normalizedAddresses.length > 0;
|
|
1270
|
+
const firstAddressId = normalizedAddresses[0]?.id;
|
|
1271
|
+
const isControlled = selectedAddressId !== void 0;
|
|
1272
|
+
const [internalSelectedId, setInternalSelectedId] = React5__namespace.useState(
|
|
1273
|
+
() => isControlled ? void 0 : firstAddressId
|
|
1274
|
+
);
|
|
1275
|
+
const resolvedSelectedId = isControlled ? selectedAddressId : internalSelectedId;
|
|
1276
|
+
React5__namespace.useEffect(() => {
|
|
1277
|
+
if (!isControlled) {
|
|
1278
|
+
setInternalSelectedId((current) => {
|
|
1279
|
+
if (current != null && normalizedAddresses.some((option) => option.id === current)) {
|
|
1280
|
+
return current;
|
|
1281
|
+
}
|
|
1282
|
+
return firstAddressId;
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
}, [firstAddressId, isControlled, normalizedAddresses]);
|
|
1286
|
+
const selectedOption = normalizedAddresses.find((option) => option.id === resolvedSelectedId) ?? normalizedAddresses[0];
|
|
1287
|
+
const [isDropdownOpen, setIsDropdownOpen] = React5__namespace.useState(false);
|
|
1288
|
+
const dropdownRef = React5__namespace.useRef(null);
|
|
1289
|
+
React5__namespace.useEffect(() => {
|
|
1290
|
+
if (!isDropdownOpen) return;
|
|
1291
|
+
const handleClick = (event) => {
|
|
1292
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
1293
|
+
setIsDropdownOpen(false);
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
const handleKey = (event) => {
|
|
1297
|
+
if (event.key === "Escape") {
|
|
1298
|
+
setIsDropdownOpen(false);
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
document.addEventListener("mousedown", handleClick);
|
|
1302
|
+
document.addEventListener("keydown", handleKey);
|
|
1303
|
+
return () => {
|
|
1304
|
+
document.removeEventListener("mousedown", handleClick);
|
|
1305
|
+
document.removeEventListener("keydown", handleKey);
|
|
1306
|
+
};
|
|
1307
|
+
}, [isDropdownOpen]);
|
|
1308
|
+
const defaultCompareIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 4h7v7H4V4zm0 9h7v7H4v-7zm9-9h7v7h-7V4zm0 9h7v7h-7v-7z" }) });
|
|
1309
|
+
const handleAddressSelect = (addressId) => {
|
|
1310
|
+
if (!isControlled) {
|
|
1311
|
+
setInternalSelectedId(addressId);
|
|
1312
|
+
}
|
|
1313
|
+
onSelectAddress?.(addressId);
|
|
1314
|
+
setIsDropdownOpen(false);
|
|
1315
|
+
};
|
|
1316
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1317
|
+
"div",
|
|
1318
|
+
{
|
|
1319
|
+
ref,
|
|
1320
|
+
className: cn(
|
|
1321
|
+
"flex w-full flex-col gap-3 border border-white/10 px-4 py-3 text-white shadow-[0_18px_40px_rgba(0,0,0,0.55)] md:flex-row md:items-center md:justify-between md:gap-4",
|
|
1322
|
+
className
|
|
1323
|
+
),
|
|
1324
|
+
style: { borderRadius: "16px" },
|
|
1325
|
+
...props,
|
|
1326
|
+
children: [
|
|
1327
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-auto", ref: dropdownRef, children: [
|
|
1328
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1329
|
+
"button",
|
|
1330
|
+
{
|
|
1331
|
+
type: "button",
|
|
1332
|
+
disabled: !hasAddresses,
|
|
1333
|
+
onClick: () => setIsDropdownOpen((prev) => !prev),
|
|
1334
|
+
className: cn(
|
|
1335
|
+
"flex h-[42px] w-auto items-center gap-2 rounded-[12px] border border-transparent bg-transparent px-0 text-left text-[15px] font-semibold text-white transition hover:text-white/80 focus-visible:outline-none",
|
|
1336
|
+
!hasAddresses && "text-white/40"
|
|
1337
|
+
),
|
|
1338
|
+
children: [
|
|
1339
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : hasAddresses ? "Select address" : "No addresses available" }),
|
|
1340
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-3 flex items-center text-white/60 transition-transform", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1341
|
+
"svg",
|
|
1342
|
+
{
|
|
1343
|
+
width: "16",
|
|
1344
|
+
height: "16",
|
|
1345
|
+
viewBox: "0 0 24 24",
|
|
1346
|
+
fill: "currentColor",
|
|
1347
|
+
className: cn("transition-transform", isDropdownOpen && "rotate-180"),
|
|
1348
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 10l5 5 5-5H7z" })
|
|
1349
|
+
}
|
|
1350
|
+
) })
|
|
1351
|
+
]
|
|
1352
|
+
}
|
|
1353
|
+
),
|
|
1354
|
+
isDropdownOpen && hasAddresses ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-[calc(100%+8px)] z-20 w-full rounded-[12px] border border-white/10 py-1 shadow-[0_25px_55px_rgba(0,0,0,0.6)] bg-black", children: normalizedAddresses.map((option) => {
|
|
1355
|
+
const active = option.id === resolvedSelectedId;
|
|
1356
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1357
|
+
"button",
|
|
1358
|
+
{
|
|
1359
|
+
type: "button",
|
|
1360
|
+
className: cn(
|
|
1361
|
+
"flex w-full items-center px-4 py-2 text-left text-[14px] text-white/80 transition hover:bg-white/5 hover:text-white",
|
|
1362
|
+
active && "text-white"
|
|
1363
|
+
),
|
|
1364
|
+
onClick: () => handleAddressSelect(option.id),
|
|
1365
|
+
children: option.label
|
|
1366
|
+
},
|
|
1367
|
+
option.id
|
|
1368
|
+
);
|
|
1369
|
+
}) }) : null
|
|
1370
|
+
] }),
|
|
1371
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1372
|
+
Button,
|
|
1373
|
+
{
|
|
1374
|
+
variant: "accentOutline",
|
|
1375
|
+
size: "sm",
|
|
1376
|
+
className: "flex items-center justify-center gap-2 rounded-[10px] border-[var(--color-accent,#e6c87e)] bg-transparent px-4 py-2 text-[14px] font-semibold text-[var(--color-accent,#e6c87e)] transition hover:bg-[rgba(230,200,126,0.08)] md:ml-auto",
|
|
1377
|
+
onClick: onCompareClick,
|
|
1378
|
+
disabled: !hasAddresses,
|
|
1379
|
+
children: [
|
|
1380
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base", children: compareIcon ?? defaultCompareIcon }),
|
|
1381
|
+
compareLabel
|
|
1382
|
+
]
|
|
1383
|
+
}
|
|
1384
|
+
)
|
|
1385
|
+
]
|
|
1386
|
+
}
|
|
1387
|
+
);
|
|
1388
|
+
}
|
|
1389
|
+
);
|
|
1390
|
+
PropertyCompareBar.displayName = "PropertyCompareBar";
|
|
1252
1391
|
var clampPct = (pct) => Math.min(100, Math.max(0, pct));
|
|
1253
1392
|
var EditIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1254
1393
|
"svg",
|
|
@@ -1855,6 +1994,7 @@ exports.HousePositionSlider = HousePositionSlider;
|
|
|
1855
1994
|
exports.Orderbook = Orderbook;
|
|
1856
1995
|
exports.PortfolioSummary = PortfolioSummary;
|
|
1857
1996
|
exports.PriceChart = PriceChart;
|
|
1997
|
+
exports.PropertyCompareBar = PropertyCompareBar;
|
|
1858
1998
|
exports.PropertyHeroHeader = PropertyHeroHeader;
|
|
1859
1999
|
exports.PropertyNewsUpdates = PropertyNewsUpdates;
|
|
1860
2000
|
exports.PropertySubheader = PropertySubheader;
|