@loafmarkets/ui 0.0.4 → 0.0.5

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
@@ -160,6 +160,27 @@ interface PropertyNewsUpdatesProps extends React.HTMLAttributes<HTMLDivElement>
160
160
  }
161
161
  declare const PropertyNewsUpdates: React.ForwardRefExoticComponent<PropertyNewsUpdatesProps & React.RefAttributes<HTMLDivElement>>;
162
162
 
163
+ type PropertyAddressOption = {
164
+ id: string;
165
+ label: string;
166
+ };
167
+ type PropertyCompareBarProps = React.HTMLAttributes<HTMLDivElement> & {
168
+ addresses: (PropertyAddressOption | string)[];
169
+ selectedAddressId?: string;
170
+ onSelectAddress?: (addressId: string) => void;
171
+ compareLabel?: string;
172
+ onCompareClick?: () => void;
173
+ compareIcon?: React.ReactNode;
174
+ };
175
+ declare const PropertyCompareBar: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
176
+ addresses: (PropertyAddressOption | string)[];
177
+ selectedAddressId?: string;
178
+ onSelectAddress?: (addressId: string) => void;
179
+ compareLabel?: string;
180
+ onCompareClick?: () => void;
181
+ compareIcon?: React.ReactNode;
182
+ } & React.RefAttributes<HTMLDivElement>>;
183
+
163
184
  type YourOrderSide = "buy" | "sell";
164
185
  type YourOrder = {
165
186
  id: string;
@@ -274,4 +295,4 @@ declare const PropertySubheader: React.ForwardRefExoticComponent<React.HTMLAttri
274
295
  actions?: PropertySubheaderAction[];
275
296
  } & React.RefAttributes<HTMLDivElement>>;
276
297
 
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 };
298
+ 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
@@ -160,6 +160,27 @@ interface PropertyNewsUpdatesProps extends React.HTMLAttributes<HTMLDivElement>
160
160
  }
161
161
  declare const PropertyNewsUpdates: React.ForwardRefExoticComponent<PropertyNewsUpdatesProps & React.RefAttributes<HTMLDivElement>>;
162
162
 
163
+ type PropertyAddressOption = {
164
+ id: string;
165
+ label: string;
166
+ };
167
+ type PropertyCompareBarProps = React.HTMLAttributes<HTMLDivElement> & {
168
+ addresses: (PropertyAddressOption | string)[];
169
+ selectedAddressId?: string;
170
+ onSelectAddress?: (addressId: string) => void;
171
+ compareLabel?: string;
172
+ onCompareClick?: () => void;
173
+ compareIcon?: React.ReactNode;
174
+ };
175
+ declare const PropertyCompareBar: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
176
+ addresses: (PropertyAddressOption | string)[];
177
+ selectedAddressId?: string;
178
+ onSelectAddress?: (addressId: string) => void;
179
+ compareLabel?: string;
180
+ onCompareClick?: () => void;
181
+ compareIcon?: React.ReactNode;
182
+ } & React.RefAttributes<HTMLDivElement>>;
183
+
163
184
  type YourOrderSide = "buy" | "sell";
164
185
  type YourOrder = {
165
186
  id: string;
@@ -274,4 +295,4 @@ declare const PropertySubheader: React.ForwardRefExoticComponent<React.HTMLAttri
274
295
  actions?: PropertySubheaderAction[];
275
296
  } & React.RefAttributes<HTMLDivElement>>;
276
297
 
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 };
298
+ 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
@@ -1249,6 +1249,143 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
1249
1249
  }
1250
1250
  );
1251
1251
  PropertyNewsUpdates.displayName = "PropertyNewsUpdates";
1252
+ var PropertyCompareBar = React5__namespace.forwardRef(
1253
+ ({
1254
+ className,
1255
+ addresses,
1256
+ selectedAddressId,
1257
+ onSelectAddress,
1258
+ compareLabel = "Compare",
1259
+ onCompareClick,
1260
+ compareIcon,
1261
+ ...props
1262
+ }, ref) => {
1263
+ const normalizedAddresses = React5__namespace.useMemo(() => {
1264
+ return addresses.map(
1265
+ (option) => typeof option === "string" ? { id: option, label: option } : option
1266
+ );
1267
+ }, [addresses]);
1268
+ const hasAddresses = normalizedAddresses.length > 0;
1269
+ const firstAddressId = normalizedAddresses[0]?.id;
1270
+ const isControlled = selectedAddressId !== void 0;
1271
+ const [internalSelectedId, setInternalSelectedId] = React5__namespace.useState(
1272
+ () => isControlled ? void 0 : firstAddressId
1273
+ );
1274
+ const resolvedSelectedId = isControlled ? selectedAddressId : internalSelectedId;
1275
+ React5__namespace.useEffect(() => {
1276
+ if (!isControlled) {
1277
+ setInternalSelectedId((current) => {
1278
+ if (current != null && normalizedAddresses.some((option) => option.id === current)) {
1279
+ return current;
1280
+ }
1281
+ return firstAddressId;
1282
+ });
1283
+ }
1284
+ }, [firstAddressId, isControlled, normalizedAddresses]);
1285
+ const selectedOption = normalizedAddresses.find((option) => option.id === resolvedSelectedId) ?? normalizedAddresses[0];
1286
+ const [isDropdownOpen, setIsDropdownOpen] = React5__namespace.useState(false);
1287
+ const dropdownRef = React5__namespace.useRef(null);
1288
+ React5__namespace.useEffect(() => {
1289
+ if (!isDropdownOpen) return;
1290
+ const handleClick = (event) => {
1291
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1292
+ setIsDropdownOpen(false);
1293
+ }
1294
+ };
1295
+ const handleKey = (event) => {
1296
+ if (event.key === "Escape") {
1297
+ setIsDropdownOpen(false);
1298
+ }
1299
+ };
1300
+ document.addEventListener("mousedown", handleClick);
1301
+ document.addEventListener("keydown", handleKey);
1302
+ return () => {
1303
+ document.removeEventListener("mousedown", handleClick);
1304
+ document.removeEventListener("keydown", handleKey);
1305
+ };
1306
+ }, [isDropdownOpen]);
1307
+ 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" }) });
1308
+ const handleAddressSelect = (addressId) => {
1309
+ if (!isControlled) {
1310
+ setInternalSelectedId(addressId);
1311
+ }
1312
+ onSelectAddress?.(addressId);
1313
+ setIsDropdownOpen(false);
1314
+ };
1315
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1316
+ "div",
1317
+ {
1318
+ ref,
1319
+ className: cn(
1320
+ "flex w-full flex-col gap-3 rounded-[14px] border border-[#1a1f2b] bg-[#0f131c] px-4 py-3 text-white shadow-[0_18px_45px_rgba(0,0,0,0.55)] md:flex-row md:items-center md:gap-4",
1321
+ className
1322
+ ),
1323
+ ...props,
1324
+ children: [
1325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", ref: dropdownRef, children: [
1326
+ /* @__PURE__ */ jsxRuntime.jsxs(
1327
+ "button",
1328
+ {
1329
+ type: "button",
1330
+ disabled: !hasAddresses,
1331
+ onClick: () => setIsDropdownOpen((prev) => !prev),
1332
+ className: cn(
1333
+ "flex h-[42px] w-full items-center justify-between rounded-[10px] border border-[#202632] bg-[#181c27] px-4 text-left text-[15px] font-semibold text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] transition hover:bg-[#1d222e] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent,#e6c87e)]",
1334
+ !hasAddresses && "text-white/40"
1335
+ ),
1336
+ children: [
1337
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: selectedOption ? selectedOption.label : hasAddresses ? "Select address" : "No addresses available" }),
1338
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-3 flex items-center text-white/60 transition-transform", "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(
1339
+ "svg",
1340
+ {
1341
+ width: "16",
1342
+ height: "16",
1343
+ viewBox: "0 0 24 24",
1344
+ fill: "currentColor",
1345
+ className: cn("transition-transform", isDropdownOpen && "rotate-180"),
1346
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 10l5 5 5-5H7z" })
1347
+ }
1348
+ ) })
1349
+ ]
1350
+ }
1351
+ ),
1352
+ isDropdownOpen && hasAddresses ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 top-[calc(100%+8px)] z-20 w-full rounded-[12px] border border-[#1f2431] bg-[#161925] py-1 shadow-[0_25px_55px_rgba(0,0,0,0.65)] backdrop-blur-sm", children: normalizedAddresses.map((option) => {
1353
+ const active = option.id === resolvedSelectedId;
1354
+ return /* @__PURE__ */ jsxRuntime.jsx(
1355
+ "button",
1356
+ {
1357
+ type: "button",
1358
+ className: cn(
1359
+ "flex w-full items-center px-4 py-2 text-left text-[14px] text-white/80 transition hover:bg-white/5 hover:text-white",
1360
+ active && "text-white"
1361
+ ),
1362
+ onClick: () => handleAddressSelect(option.id),
1363
+ children: option.label
1364
+ },
1365
+ option.id
1366
+ );
1367
+ }) }) : null
1368
+ ] }),
1369
+ /* @__PURE__ */ jsxRuntime.jsxs(
1370
+ Button,
1371
+ {
1372
+ variant: "accentOutline",
1373
+ size: "sm",
1374
+ className: "flex w-full 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)] shadow-[0_10px_25px_rgba(0,0,0,0.45)] transition hover:bg-[rgba(230,200,126,0.08)] md:w-max",
1375
+ onClick: onCompareClick,
1376
+ disabled: !hasAddresses,
1377
+ children: [
1378
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base", children: compareIcon ?? defaultCompareIcon }),
1379
+ compareLabel
1380
+ ]
1381
+ }
1382
+ )
1383
+ ]
1384
+ }
1385
+ );
1386
+ }
1387
+ );
1388
+ PropertyCompareBar.displayName = "PropertyCompareBar";
1252
1389
  var clampPct = (pct) => Math.min(100, Math.max(0, pct));
1253
1390
  var EditIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs(
1254
1391
  "svg",
@@ -1855,6 +1992,7 @@ exports.HousePositionSlider = HousePositionSlider;
1855
1992
  exports.Orderbook = Orderbook;
1856
1993
  exports.PortfolioSummary = PortfolioSummary;
1857
1994
  exports.PriceChart = PriceChart;
1995
+ exports.PropertyCompareBar = PropertyCompareBar;
1858
1996
  exports.PropertyHeroHeader = PropertyHeroHeader;
1859
1997
  exports.PropertyNewsUpdates = PropertyNewsUpdates;
1860
1998
  exports.PropertySubheader = PropertySubheader;