@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 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 sliderHoldingsValue = effectiveTokensHeld * effectivePrice;
339
- const sliderTotalCapacity = sliderHoldingsValue + effectiveAvailableCash;
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 plannedDeltaValue = (() => {
387
- if (orderMode === "buy") {
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
- currentOwnership.toFixed(2),
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 || targetOwnership.toFixed(2),
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(targetOwnership.toFixed(2)),
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
- targetOwnership >= currentOwnership ? "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
+ 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;