@loafmarkets/ui 0.1.405 → 0.1.407

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
@@ -706,6 +706,11 @@ type HeaderProps = {
706
706
  onOrdersNavigate?: () => void;
707
707
  onWalletNavigate?: () => void;
708
708
  onSettingsClick?: () => void;
709
+ /** Fired by the "Refer" CTA button + user-menu "Refer" item. When omitted, both
710
+ * fall back to `onSettingsClick` (so existing consumers are unchanged). Lets a
711
+ * consumer route Refer somewhere other than Settings (e.g. an invite modal)
712
+ * without DOM-level click interception. */
713
+ onReferClick?: () => void;
709
714
  portfolioSummary?: HeaderPortfolioData | null;
710
715
  /**
711
716
  * True while a brand-new user's test funds (100k mock USD) are being deposited
@@ -716,7 +721,7 @@ type HeaderProps = {
716
721
  /**
717
722
  * The bar's authed CTA button. Defaults to "deposit" (the funding flow) so
718
723
  * existing consumers are unchanged. "refer" swaps it for a Refer button that
719
- * opens the Settings popup (same `onSettingsClick` as the user-menu Refer item).
724
+ * fires `onReferClick` (falling back to `onSettingsClick` when not provided).
720
725
  */
721
726
  headerCta?: "deposit" | "refer";
722
727
  /** Show the "Refer" user-menu item. Off by default — referral is feature-flagged
@@ -1093,7 +1098,7 @@ type ToastData = {
1093
1098
  amount?: string;
1094
1099
  /** On-chain tx hash — shown truncated with a block explorer link */
1095
1100
  txHash?: string;
1096
- /** Explorer base URL, defaults to Base Sepolia */
1101
+ /** Explorer base URL, defaults to Arbitrum Sepolia */
1097
1102
  explorerUrl?: string;
1098
1103
  /** Auto-dismiss after ms. 0 = never. Default 6000 */
1099
1104
  duration?: number;
@@ -1269,11 +1274,13 @@ type PropertyPhotoGalleryProps = {
1269
1274
  isOpen: boolean;
1270
1275
  onClose: () => void;
1271
1276
  startIndex?: number;
1277
+ startWithVideo?: boolean;
1272
1278
  images?: PropertyGalleryImage[];
1273
1279
  title?: string;
1274
1280
  subtitle?: string;
1281
+ videoUrl?: string;
1275
1282
  };
1276
- declare function PropertyPhotoGallery({ isOpen, onClose, startIndex, title, subtitle, images, }: PropertyPhotoGalleryProps): react_jsx_runtime.JSX.Element | null;
1283
+ declare function PropertyPhotoGallery({ isOpen, onClose, startIndex, startWithVideo, title, subtitle, images, videoUrl, }: PropertyPhotoGalleryProps): react_jsx_runtime.JSX.Element | null;
1277
1284
 
1278
1285
  type UseAdaptivePollingOptions = {
1279
1286
  enabled: boolean;
package/dist/index.d.ts CHANGED
@@ -706,6 +706,11 @@ type HeaderProps = {
706
706
  onOrdersNavigate?: () => void;
707
707
  onWalletNavigate?: () => void;
708
708
  onSettingsClick?: () => void;
709
+ /** Fired by the "Refer" CTA button + user-menu "Refer" item. When omitted, both
710
+ * fall back to `onSettingsClick` (so existing consumers are unchanged). Lets a
711
+ * consumer route Refer somewhere other than Settings (e.g. an invite modal)
712
+ * without DOM-level click interception. */
713
+ onReferClick?: () => void;
709
714
  portfolioSummary?: HeaderPortfolioData | null;
710
715
  /**
711
716
  * True while a brand-new user's test funds (100k mock USD) are being deposited
@@ -716,7 +721,7 @@ type HeaderProps = {
716
721
  /**
717
722
  * The bar's authed CTA button. Defaults to "deposit" (the funding flow) so
718
723
  * existing consumers are unchanged. "refer" swaps it for a Refer button that
719
- * opens the Settings popup (same `onSettingsClick` as the user-menu Refer item).
724
+ * fires `onReferClick` (falling back to `onSettingsClick` when not provided).
720
725
  */
721
726
  headerCta?: "deposit" | "refer";
722
727
  /** Show the "Refer" user-menu item. Off by default — referral is feature-flagged
@@ -1093,7 +1098,7 @@ type ToastData = {
1093
1098
  amount?: string;
1094
1099
  /** On-chain tx hash — shown truncated with a block explorer link */
1095
1100
  txHash?: string;
1096
- /** Explorer base URL, defaults to Base Sepolia */
1101
+ /** Explorer base URL, defaults to Arbitrum Sepolia */
1097
1102
  explorerUrl?: string;
1098
1103
  /** Auto-dismiss after ms. 0 = never. Default 6000 */
1099
1104
  duration?: number;
@@ -1269,11 +1274,13 @@ type PropertyPhotoGalleryProps = {
1269
1274
  isOpen: boolean;
1270
1275
  onClose: () => void;
1271
1276
  startIndex?: number;
1277
+ startWithVideo?: boolean;
1272
1278
  images?: PropertyGalleryImage[];
1273
1279
  title?: string;
1274
1280
  subtitle?: string;
1281
+ videoUrl?: string;
1275
1282
  };
1276
- declare function PropertyPhotoGallery({ isOpen, onClose, startIndex, title, subtitle, images, }: PropertyPhotoGalleryProps): react_jsx_runtime.JSX.Element | null;
1283
+ declare function PropertyPhotoGallery({ isOpen, onClose, startIndex, startWithVideo, title, subtitle, images, videoUrl, }: PropertyPhotoGalleryProps): react_jsx_runtime.JSX.Element | null;
1277
1284
 
1278
1285
  type UseAdaptivePollingOptions = {
1279
1286
  enabled: boolean;
package/dist/index.js CHANGED
@@ -5101,6 +5101,7 @@ var Header = ({
5101
5101
  onOrdersNavigate: _onOrdersNavigate,
5102
5102
  onWalletNavigate: _onWalletNavigate,
5103
5103
  onSettingsClick,
5104
+ onReferClick,
5104
5105
  portfolioSummary,
5105
5106
  fundsPending = false,
5106
5107
  transparentOnTop = false,
@@ -5539,7 +5540,7 @@ var Header = ({
5539
5540
  onClick: (event) => {
5540
5541
  event?.preventDefault();
5541
5542
  closeMenus();
5542
- onSettingsClick?.();
5543
+ (onReferClick ?? onSettingsClick)?.();
5543
5544
  },
5544
5545
  children: "Refer"
5545
5546
  }
@@ -5582,7 +5583,7 @@ var Header = ({
5582
5583
  onClick: (event) => {
5583
5584
  event?.preventDefault();
5584
5585
  closeMenus();
5585
- onSettingsClick?.();
5586
+ (onReferClick ?? onSettingsClick)?.();
5586
5587
  },
5587
5588
  children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { children: "Refer" })
5588
5589
  }
@@ -7575,6 +7576,7 @@ var LoginPopup = ({
7575
7576
  ] })
7576
7577
  ] });
7577
7578
  if (gate) {
7579
+ const codeAccepted = codeStatus === "valid";
7578
7580
  const showSignIn = signInMode || signInRevealed;
7579
7581
  return /* @__PURE__ */ jsxRuntime.jsxs(GateShell, { children: [
7580
7582
  /* @__PURE__ */ jsxRuntime.jsx(GateTint, { $reveal: showSignIn ? 1 : 0 }),
@@ -7600,30 +7602,35 @@ var LoginPopup = ({
7600
7602
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7601
7603
  /* @__PURE__ */ jsxRuntime.jsxs(CodeInputWrapper, { $status: codeStatus, children: [
7602
7604
  /* @__PURE__ */ jsxRuntime.jsx(CodePrefix, { children: CODE_PREFIX }),
7603
- codeInput
7605
+ codeInput,
7606
+ /* @__PURE__ */ jsxRuntime.jsx(
7607
+ GateSubmit,
7608
+ {
7609
+ type: "button",
7610
+ "aria-label": "Submit access code",
7611
+ $status: codeStatus,
7612
+ disabled: codeStatus === "checking" || !codeComplete,
7613
+ onClick: () => void runCodeValidation(referralCode),
7614
+ children: codeAccepted ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6L9 17l-5-5" }) }) : codeStatus === "checking" ? /* @__PURE__ */ jsxRuntime.jsx(GateSpinner, {}) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14M13 6l6 6-6 6" }) })
7615
+ }
7616
+ )
7604
7617
  ] }),
7605
7618
  (codeStatus === "invalid" || error && !signInRevealed) && /* @__PURE__ */ jsxRuntime.jsx(StatusMessage, { $error: true, children: error || "That code isn't valid. Double-check and try again." }),
7606
- signInRevealed ? signInStep : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7607
- /* @__PURE__ */ jsxRuntime.jsxs(GateResendText, { children: [
7608
- "Already have an account?",
7609
- " ",
7610
- /* @__PURE__ */ jsxRuntime.jsx(
7611
- "button",
7612
- {
7613
- type: "button",
7614
- onClick: () => {
7615
- setError("");
7616
- setIsSignUp(false);
7617
- setSignInMode(true);
7618
- },
7619
- children: "Sign in"
7620
- }
7621
- )
7622
- ] }),
7623
- /* @__PURE__ */ jsxRuntime.jsxs(GateEarlyAccess, { href: "https://loafmarkets.com/?waitlist=1", children: [
7624
- "Signup for early access",
7625
- /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14M13 6l6 6-6 6" }) })
7626
- ] })
7619
+ signInRevealed ? signInStep : /* @__PURE__ */ jsxRuntime.jsxs(GateResendText, { children: [
7620
+ "Already have an account?",
7621
+ " ",
7622
+ /* @__PURE__ */ jsxRuntime.jsx(
7623
+ "button",
7624
+ {
7625
+ type: "button",
7626
+ onClick: () => {
7627
+ setError("");
7628
+ setIsSignUp(false);
7629
+ setSignInMode(true);
7630
+ },
7631
+ children: "Sign in"
7632
+ }
7633
+ )
7627
7634
  ] })
7628
7635
  ] })
7629
7636
  ] })
@@ -7700,12 +7707,12 @@ var LoginPopup = ({
7700
7707
  marginBottom: "1.25rem"
7701
7708
  }, children: [
7702
7709
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: 7, height: 7, borderRadius: "50%", background: "#0052FF", flexShrink: 0 } }),
7703
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.72rem", fontWeight: 600, color: "#6b9fff", letterSpacing: "0.02em" }, children: "Base Sepolia" })
7710
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.72rem", fontWeight: 600, color: "#6b9fff", letterSpacing: "0.02em" }, children: "Arbitrum Sepolia" })
7704
7711
  ] }),
7705
7712
  /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.82rem", color: "rgba(255,255,255,0.5)", textAlign: "center", marginBottom: "1.1rem", lineHeight: 1.5, maxWidth: 320 }, children: [
7706
7713
  "Send ",
7707
7714
  /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: "rgba(255,255,255,0.8)" }, children: "USDC" }),
7708
- " on Base Sepolia to the address below. Only send on this network."
7715
+ " on Arbitrum Sepolia to the address below. Only send on this network."
7709
7716
  ] }),
7710
7717
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
7711
7718
  width: "100%",
@@ -8246,33 +8253,6 @@ var GateResendText = styled10__default.default.p`
8246
8253
  font-size: inherit;
8247
8254
  }
8248
8255
  `;
8249
- var GateEarlyAccess = styled10__default.default.a`
8250
- display: inline-flex;
8251
- align-items: center;
8252
- gap: 0.4rem;
8253
- margin-top: 0.15rem;
8254
- color: var(--color-text-secondary, #848e9c);
8255
- font-size: 0.8rem;
8256
- font-weight: 500;
8257
- letter-spacing: 0.02em;
8258
- text-decoration: none;
8259
- cursor: pointer;
8260
- transition: color 0.15s ease;
8261
-
8262
- svg {
8263
- width: 13px;
8264
- height: 13px;
8265
- transition: transform 0.15s ease;
8266
- }
8267
-
8268
- &:hover {
8269
- color: var(--color-accent, #E6C87E);
8270
- }
8271
-
8272
- &:hover svg {
8273
- transform: translateX(3px);
8274
- }
8275
- `;
8276
8256
  var GateSubmit = styled10__default.default.button`
8277
8257
  display: flex;
8278
8258
  align-items: center;
@@ -10350,7 +10330,7 @@ function PropertyOverview({
10350
10330
  isLoading = false,
10351
10331
  ticker,
10352
10332
  contractAddress,
10353
- chain = "Base (Ethereum L2)",
10333
+ chain = "Arbitrum (Ethereum L2)",
10354
10334
  volume24h,
10355
10335
  priceHistory: priceHistoryProp,
10356
10336
  beta = false,
@@ -10389,13 +10369,13 @@ function PropertyOverview({
10389
10369
  const resolvedPropertyType = rawPropertyType?.toLowerCase() === "house" ? "Residential" : rawPropertyType;
10390
10370
  const galleryImages = images ?? [];
10391
10371
  const chainValue = /* @__PURE__ */ jsxRuntime.jsxs(ChainLogos, { children: [
10392
- /* @__PURE__ */ jsxRuntime.jsx(ChainLogoImg, { src: "/Base-Symbol.png", alt: "Base" }),
10372
+ /* @__PURE__ */ jsxRuntime.jsx(ChainLogoImg, { src: "/Arbitrum-Symbol.svg", alt: "Arbitrum" }),
10393
10373
  /* @__PURE__ */ jsxRuntime.jsx(ChainLogoImg, { src: "/Ethereum-Logo.png", alt: "Ethereum", style: { filter: "brightness(0) invert(1)" } }),
10394
10374
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: chain })
10395
10375
  ] });
10396
10376
  const tokenDetailsItems = [
10397
10377
  { label: "Chain", value: chainValue },
10398
- { label: "On-Chain Address", value: contractAddress ? truncateAddress(contractAddress) : "\u2014", mono: true, link: contractAddress ? `https://sepolia.basescan.org/address/${contractAddress}` : void 0, copyValue: contractAddress },
10378
+ { label: "On-Chain Address", value: contractAddress ? truncateAddress(contractAddress) : "\u2014", mono: true, link: contractAddress ? `https://sepolia.arbiscan.io/address/${contractAddress}` : void 0, copyValue: contractAddress },
10399
10379
  { label: "Token Ticker", value: ticker ?? "\u2014" },
10400
10380
  { label: "Total Circulating Tokens", value: isLoading && resolvedTokensIssued == null ? loadingSkeleton : resolvedTokensIssued?.toLocaleString() ?? "\u2014" },
10401
10381
  { label: "Legal Structuring", value: "See Documents", docLink: true },
@@ -10415,7 +10395,9 @@ function PropertyOverview({
10415
10395
  ];
10416
10396
  const growthPct = overviewData?.growth5Yr;
10417
10397
  const propertyStats = [
10418
- { label: "Property Value", value: isLoading && tokenMarketCap == null ? loadingSkeleton : tokenMarketCap ? fmtDollar(tokenMarketCap) : "\u2014" },
10398
+ // Property Value = the API offeringValuation (OverviewResponse.offeringValuation), NOT
10399
+ // midPrice×tokensIssued market cap (fixed 2026-07-22). null → '—', never a fabricated cap.
10400
+ { label: "Property Value", value: isLoading && overviewData?.offeringValuation == null ? loadingSkeleton : overviewData?.offeringValuation ? fmtDollar(overviewData.offeringValuation) : "\u2014" },
10419
10401
  ...beta ? [] : [{ label: "Offers", value: "3" }],
10420
10402
  { label: "Growth (5yr)", value: growthPct != null ? `${growthPct > 0 ? "+" : ""}${growthPct}%` : "\u2014" },
10421
10403
  { label: "Last Dividend", value: overviewData?.lastDividend != null ? `$${overviewData.lastDividend.toFixed(2)}` : "\u2014" },
@@ -14916,7 +14898,7 @@ var getOrderStatusMeta = (statusRaw) => {
14916
14898
  return { color: "#E6C87E", bg: "rgba(240,185,11,0.15)" };
14917
14899
  };
14918
14900
  var ChevronDown = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "rgba(255,255,255,0.5)", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) });
14919
- var BaseScanIconLink = ({ url }) => /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: url, target: "_blank", rel: "noopener noreferrer", title: "View on BaseScan", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
14901
+ var ArbiscanIconLink = ({ url }) => /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: url, target: "_blank", rel: "noopener noreferrer", title: "View on Arbiscan", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
14920
14902
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
14921
14903
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
14922
14904
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
@@ -14941,7 +14923,7 @@ function PortfolioActivityPanel({
14941
14923
  defaultTab,
14942
14924
  onTabChange,
14943
14925
  pageSize = ACTIVITY_PAGE_SIZE_DEFAULT,
14944
- blockExplorerBaseUrl: _blockExplorerBaseUrl = "https://sepolia.basescan.org/tx",
14926
+ blockExplorerBaseUrl: _blockExplorerBaseUrl = "https://sepolia.arbiscan.io/tx",
14945
14927
  className,
14946
14928
  style
14947
14929
  }) {
@@ -15385,7 +15367,7 @@ function PortfolioActivityPanel({
15385
15367
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "0.35rem" }, children: [
15386
15368
  formatNumber2(order.quantity),
15387
15369
  order.ticker && /* @__PURE__ */ jsxRuntime.jsx(TickerTag, { style: { marginLeft: 0 }, children: order.ticker.toUpperCase() }),
15388
- order.txHash && /* @__PURE__ */ jsxRuntime.jsx(BaseScanIconLink, { url: `${_blockExplorerBaseUrl}/${order.txHash}` })
15370
+ order.txHash && /* @__PURE__ */ jsxRuntime.jsx(ArbiscanIconLink, { url: `${_blockExplorerBaseUrl}/${order.txHash}` })
15389
15371
  ] })
15390
15372
  ] }),
15391
15373
  /* @__PURE__ */ jsxRuntime.jsxs(CUnitsCell, { children: [
@@ -15438,7 +15420,7 @@ function PortfolioActivityPanel({
15438
15420
  order.status === "REJECTED" && order.rejectionReason && /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, style: { fontSize: "0.62rem", marginTop: "0.2rem", maxWidth: "120px", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: order.rejectionReason, children: order.rejectionReason })
15439
15421
  ] }),
15440
15422
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: formatTimestamp(order.createdAt) }) }),
15441
- /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: order.txHash && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: `${_blockExplorerBaseUrl}/${order.txHash}`, target: "_blank", rel: "noopener noreferrer", title: "View on BaseScan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15423
+ /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: order.txHash && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: `${_blockExplorerBaseUrl}/${order.txHash}`, target: "_blank", rel: "noopener noreferrer", title: "View on Arbiscan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15442
15424
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
15443
15425
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
15444
15426
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
@@ -15481,7 +15463,11 @@ function PortfolioActivityPanel({
15481
15463
  /* @__PURE__ */ jsxRuntime.jsx(CChevronWrap, { $open: ordExpanded, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "rgba(255,255,255,0.5)", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) }) })
15482
15464
  ] }),
15483
15465
  ordExpanded && /* @__PURE__ */ jsxRuntime.jsxs(CExpandedWrap, { children: [
15484
- /* @__PURE__ */ jsxRuntime.jsxs(CDetailGrid, { children: [
15466
+ /* @__PURE__ */ jsxRuntime.jsxs(CDetailGrid3, { children: [
15467
+ /* @__PURE__ */ jsxRuntime.jsxs(CDetailItem, { children: [
15468
+ /* @__PURE__ */ jsxRuntime.jsx(CDLabel, { children: "Order ID" }),
15469
+ /* @__PURE__ */ jsxRuntime.jsx(CDValue, { children: order.id > 0 ? `#${order.id}` : "\u2014" })
15470
+ ] }),
15485
15471
  /* @__PURE__ */ jsxRuntime.jsxs(CDetailItem, { children: [
15486
15472
  /* @__PURE__ */ jsxRuntime.jsx(CDLabel, { children: "Type" }),
15487
15473
  /* @__PURE__ */ jsxRuntime.jsx(CDValue, { children: prettyLabel(order.type) })
@@ -15510,7 +15496,8 @@ function PortfolioActivityPanel({
15510
15496
  ] })
15511
15497
  ] }, `open-${order.id}`);
15512
15498
  }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15513
- /* @__PURE__ */ jsxRuntime.jsxs(GridHeader, { $columns: onCancelOrder ? "1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr 82px" : "1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr", children: [
15499
+ /* @__PURE__ */ jsxRuntime.jsxs(GridHeader, { $columns: onCancelOrder ? "0.5fr 1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr 82px" : "0.5fr 1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr", children: [
15500
+ /* @__PURE__ */ jsxRuntime.jsx(GridHeaderCell, { children: "ID" }),
15514
15501
  /* @__PURE__ */ jsxRuntime.jsx(GridHeaderCell, { children: "Asset" }),
15515
15502
  /* @__PURE__ */ jsxRuntime.jsx(GridHeaderCell, { children: "Side" }),
15516
15503
  /* @__PURE__ */ jsxRuntime.jsx(GridHeaderCell, { children: "Type" }),
@@ -15526,7 +15513,8 @@ function PortfolioActivityPanel({
15526
15513
  const filledPercent = order.quantity > 0 ? Math.round(order.filledQuantity / order.quantity * 100) : 0;
15527
15514
  const isCancelling = cancellingOrderId === order.id;
15528
15515
  const sideColor = sideLabel(order.side) === "Buy" ? "#0ecb81" : "#f6465d";
15529
- return /* @__PURE__ */ jsxRuntime.jsxs(GridRow, { $columns: onCancelOrder ? "1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr 82px" : "1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr", children: [
15516
+ return /* @__PURE__ */ jsxRuntime.jsxs(GridRow, { $columns: onCancelOrder ? "0.5fr 1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr 82px" : "0.5fr 1.2fr 0.6fr 0.7fr 0.8fr 1fr 0.8fr 0.8fr", children: [
15517
+ /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: order.id > 0 ? `#${order.id}` : "\u2014" }) }),
15530
15518
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $primary: true, $color: sideColor, $noHoverColor: true, $clickable: !!onAssetClick, onClick: onAssetClick ? () => onAssetClick(order.tokenName) : void 0, children: order.tokenName }) }),
15531
15519
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(SideBadge, { $side: sideLabel(order.side), children: sideLabel(order.side) }) }),
15532
15520
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: prettyLabel(order.type) }) }),
@@ -15682,7 +15670,7 @@ function PortfolioActivityPanel({
15682
15670
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: "0.35rem" }, children: [
15683
15671
  formatNumber2(trade.quantity),
15684
15672
  trade.ticker && /* @__PURE__ */ jsxRuntime.jsx(TickerTag, { style: { marginLeft: 0 }, children: trade.ticker.toUpperCase() }),
15685
- trade.txHash && /* @__PURE__ */ jsxRuntime.jsx(BaseScanIconLink, { url: `${_blockExplorerBaseUrl}/${trade.txHash}` })
15673
+ trade.txHash && /* @__PURE__ */ jsxRuntime.jsx(ArbiscanIconLink, { url: `${_blockExplorerBaseUrl}/${trade.txHash}` })
15686
15674
  ] })
15687
15675
  ] }),
15688
15676
  /* @__PURE__ */ jsxRuntime.jsxs(CUnitsCell, { children: [
@@ -15749,7 +15737,7 @@ function PortfolioActivityPanel({
15749
15737
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { children: formatCurrency4(trade.price * trade.quantity) }) }),
15750
15738
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: settlementMeta ? /* @__PURE__ */ jsxRuntime.jsx(ActivityTag, { $color: settlementMeta.color, $bg: settlementMeta.bg, children: settlementLabel }) : /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: "\u2014" }) }),
15751
15739
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: formatTimestamp(trade.executedAt) }) }),
15752
- /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: trade.txHash && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: `${_blockExplorerBaseUrl}/${trade.txHash}`, target: "_blank", rel: "noopener noreferrer", title: "View on BaseScan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15740
+ /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: trade.txHash && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: `${_blockExplorerBaseUrl}/${trade.txHash}`, target: "_blank", rel: "noopener noreferrer", title: "View on Arbiscan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15753
15741
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
15754
15742
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
15755
15743
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
@@ -15796,7 +15784,7 @@ function PortfolioActivityPanel({
15796
15784
  /* @__PURE__ */ jsxRuntime.jsx(CDValue, { children: formatTimestamp(t.createdAt) })
15797
15785
  ] })
15798
15786
  ] }),
15799
- txUrl && /* @__PURE__ */ jsxRuntime.jsx(CExpandedLink, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: "View on BaseScan \u2197" })
15787
+ txUrl && /* @__PURE__ */ jsxRuntime.jsx(CExpandedLink, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: "View on Arbiscan \u2197" })
15800
15788
  ] })
15801
15789
  ] }, rowKey);
15802
15790
  }),
@@ -15822,7 +15810,7 @@ function PortfolioActivityPanel({
15822
15810
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: formatAddress(t.address) }) }),
15823
15811
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(ActivityTag, { $color: statusMeta.color, $bg: statusMeta.bg, children: prettyLabel(t.status) }) }),
15824
15812
  /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CellText, { $muted: true, children: formatTimestamp(t.createdAt) }) }),
15825
- /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: txUrl && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: txUrl, target: "_blank", rel: "noopener noreferrer", title: "View on BaseScan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15813
+ /* @__PURE__ */ jsxRuntime.jsx(GridCell, { children: txUrl && /* @__PURE__ */ jsxRuntime.jsx(TxLink, { href: txUrl, target: "_blank", rel: "noopener noreferrer", title: "View on Arbiscan", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
15826
15814
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
15827
15815
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
15828
15816
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
@@ -18925,13 +18913,14 @@ var CloseButton3 = styled10__default.default.button`
18925
18913
  var MainImageContainer = styled10__default.default.div`
18926
18914
  position: relative;
18927
18915
  flex: 1;
18916
+ min-height: 0;
18928
18917
  display: flex;
18929
18918
  align-items: center;
18930
18919
  justify-content: center;
18931
- padding: 80px 20px 140px;
18920
+ padding: 20px 20px 160px;
18932
18921
 
18933
18922
  @media (max-width: 768px) {
18934
- padding: 60px 0 110px;
18923
+ padding: 10px 0 130px;
18935
18924
  }
18936
18925
  `;
18937
18926
  var MainImage = styled10__default.default.img`
@@ -18943,8 +18932,11 @@ var MainImage = styled10__default.default.img`
18943
18932
  opacity: ${(p) => p.$visible ? 1 : 0};
18944
18933
  pointer-events: ${(p) => p.$visible ? "auto" : "none"};
18945
18934
  transition: opacity 300ms ease;
18946
- /* Inset box excludes the bottom thumbnail strip so margin:auto centres the image in the
18947
- space ABOVE the thumbnails (absolute ignores the parent's padding). */
18935
+ /* All slides share the same absolute box so switching only crossfades opacity
18936
+ no relative↔absolute size jump (the "grow then shrink" on navigation).
18937
+ The inset box excludes the bottom thumbnail strip so margin:auto centres the image
18938
+ in the space ABOVE the thumbnails (absolute positioning ignores the parent's padding,
18939
+ which otherwise let the image sink behind the thumbnails / "lean down"). */
18948
18940
  position: absolute;
18949
18941
  top: 24px;
18950
18942
  left: 24px;
@@ -19138,9 +19130,11 @@ function PropertyPhotoGallery({
19138
19130
  isOpen,
19139
19131
  onClose,
19140
19132
  startIndex = 0,
19133
+ startWithVideo = false,
19141
19134
  title = "28 Derby Street, Vaucluse",
19142
19135
  subtitle = "Elara \u2014 Luxury Harbour Residence",
19143
- images
19136
+ images,
19137
+ videoUrl
19144
19138
  }) {
19145
19139
  const galleryImages = images?.length ? images : DEFAULT_IMAGES;
19146
19140
  if (!isOpen) return null;
@@ -19149,16 +19143,19 @@ function PropertyPhotoGallery({
19149
19143
  {
19150
19144
  galleryImages,
19151
19145
  startIndex,
19146
+ startWithVideo,
19152
19147
  title,
19153
19148
  subtitle,
19154
- onClose
19149
+ onClose,
19150
+ videoUrl
19155
19151
  },
19156
- `${startIndex}-${galleryImages.length}`
19152
+ `${startIndex}-${galleryImages.length}-${startWithVideo}`
19157
19153
  );
19158
19154
  }
19159
- function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose }) {
19155
+ function GalleryContent({ galleryImages, startIndex, startWithVideo, title, subtitle, onClose, videoUrl }) {
19160
19156
  const [currentIndex, setCurrentIndex] = React5.useState(() => clampIndex(startIndex, galleryImages.length));
19161
19157
  const [activeHotspotId, setActiveHotspotId] = React5.useState(null);
19158
+ const [showVideo, setShowVideo] = React5.useState(startWithVideo ?? false);
19162
19159
  const sliderRef = React5.useRef(null);
19163
19160
  const [isDragging, setIsDragging] = React5.useState(false);
19164
19161
  const wasDraggingRef = React5.useRef(false);
@@ -19208,7 +19205,7 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19208
19205
  ] }),
19209
19206
  /* @__PURE__ */ jsxRuntime.jsx(CloseButton3, { onClick: onClose, "aria-label": "Close gallery", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l12 12M6 18L18 6" }) }) })
19210
19207
  ] }),
19211
- /* @__PURE__ */ jsxRuntime.jsxs(SliderContainer, { onClick: (event) => event.stopPropagation(), children: [
19208
+ !showVideo && /* @__PURE__ */ jsxRuntime.jsxs(SliderContainer, { onClick: (event) => event.stopPropagation(), children: [
19212
19209
  /* @__PURE__ */ jsxRuntime.jsxs(
19213
19210
  SliderTrack,
19214
19211
  {
@@ -19271,7 +19268,21 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19271
19268
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", width: "22", height: "22", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6" }) })
19272
19269
  }
19273
19270
  ),
19274
- galleryImages.map((image, idx) => /* @__PURE__ */ jsxRuntime.jsx(MainImage, { src: image.src, alt: image.alt, $visible: idx === currentIndex }, image.alt)),
19271
+ showVideo && videoUrl ? /* @__PURE__ */ jsxRuntime.jsx(GalleryVideoWrap, { children: /* @__PURE__ */ jsxRuntime.jsx(
19272
+ "video",
19273
+ {
19274
+ autoPlay: true,
19275
+ loop: true,
19276
+ playsInline: true,
19277
+ muted: true,
19278
+ controls: true,
19279
+ onVolumeChange: (e) => {
19280
+ if (!e.currentTarget.muted) e.currentTarget.muted = true;
19281
+ },
19282
+ style: { objectFit: "contain", borderRadius: 12, boxShadow: "0 30px 80px rgba(0,0,0,0.55)" },
19283
+ children: /* @__PURE__ */ jsxRuntime.jsx("source", { src: videoUrl, type: "video/mp4" })
19284
+ }
19285
+ ) }) : galleryImages.map((image, idx) => /* @__PURE__ */ jsxRuntime.jsx(MainImage, { src: image.src, alt: image.alt, $visible: idx === currentIndex }, image.alt)),
19275
19286
  galleryImages[currentIndex]?.hotspots?.map((hotspot) => /* @__PURE__ */ jsxRuntime.jsx(
19276
19287
  Hotspot,
19277
19288
  {
@@ -19316,11 +19327,83 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
19316
19327
  ]
19317
19328
  }
19318
19329
  ),
19319
- /* @__PURE__ */ jsxRuntime.jsx(ThumbnailStrip, { onClick: (event) => event.stopPropagation(), children: galleryImages.map((image, idx) => /* @__PURE__ */ jsxRuntime.jsx(Thumbnail3, { $active: idx === currentIndex, onClick: () => setCurrentIndex(idx), "aria-label": `Preview ${image.label}`, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: image.src, alt: image.alt }) }, image.alt)) })
19330
+ /* @__PURE__ */ jsxRuntime.jsxs(ThumbnailStrip, { onClick: (event) => event.stopPropagation(), children: [
19331
+ galleryImages.map((image, idx) => /* @__PURE__ */ jsxRuntime.jsx(Thumbnail3, { $active: !showVideo && idx === currentIndex, onClick: () => {
19332
+ setShowVideo(false);
19333
+ setCurrentIndex(idx);
19334
+ }, "aria-label": `Preview ${image.label}`, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: image.src, alt: image.alt }) }, image.alt)),
19335
+ videoUrl && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19336
+ /* @__PURE__ */ jsxRuntime.jsx(ThumbnailDivider, {}),
19337
+ /* @__PURE__ */ jsxRuntime.jsxs(VideoBtn, { $active: showVideo, onClick: () => setShowVideo(true), children: [
19338
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
19339
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "4", width: "14", height: "16", rx: "2" }),
19340
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 8l6-4v16l-6-4z" })
19341
+ ] }),
19342
+ "Video"
19343
+ ] })
19344
+ ] })
19345
+ ] })
19320
19346
  ]
19321
19347
  }
19322
19348
  );
19323
19349
  }
19350
+ var GalleryVideoWrap = styled10__default.default.div`
19351
+ position: absolute;
19352
+ inset: 0;
19353
+ display: flex;
19354
+ align-items: center;
19355
+ justify-content: center;
19356
+ padding: 20px 20px 160px;
19357
+
19358
+ video {
19359
+ max-width: 90%;
19360
+ max-height: 100%;
19361
+ }
19362
+
19363
+ /* Property videos stay permanently muted — remove the volume + mute buttons
19364
+ from the native player (Chrome/Edge/Safari/iOS/Android). Firefox ignores
19365
+ these and is covered by the onVolumeChange force-mute fallback. */
19366
+ video::-webkit-media-controls-mute-button,
19367
+ video::-webkit-media-controls-volume-slider,
19368
+ video::-webkit-media-controls-volume-control-container {
19369
+ display: none !important;
19370
+ }
19371
+
19372
+ @media (max-width: 768px) {
19373
+ padding: 10px 0 130px;
19374
+
19375
+ video {
19376
+ max-width: 100%;
19377
+ }
19378
+ }
19379
+ `;
19380
+ var ThumbnailDivider = styled10__default.default.div`
19381
+ width: 1px;
19382
+ height: 48px;
19383
+ background: rgba(255, 255, 255, 0.15);
19384
+ flex-shrink: 0;
19385
+ align-self: center;
19386
+ `;
19387
+ var VideoBtn = styled10__default.default.button`
19388
+ display: flex;
19389
+ align-items: center;
19390
+ gap: 6px;
19391
+ padding: 8px 14px;
19392
+ border-radius: 8px;
19393
+ border: 1px solid ${(p) => p.$active ? "var(--color-accent, #E6C87E)" : "rgba(255, 255, 255, 0.2)"};
19394
+ background: ${(p) => p.$active ? "rgba(240, 185, 11, 0.15)" : "rgba(255, 255, 255, 0.08)"};
19395
+ color: ${(p) => p.$active ? "var(--color-accent, #E6C87E)" : "#fff"};
19396
+ font-size: 0.82rem;
19397
+ font-weight: 500;
19398
+ cursor: pointer;
19399
+ flex-shrink: 0;
19400
+ transition: all 0.2s ease;
19401
+
19402
+ &:hover {
19403
+ background: rgba(255, 255, 255, 0.15);
19404
+ border-color: rgba(255, 255, 255, 0.3);
19405
+ }
19406
+ `;
19324
19407
  var slideIn2 = styled10.keyframes`
19325
19408
  from { transform: translateX(110%); opacity: 0; }
19326
19409
  to { transform: translateX(0); opacity: 1; }
@@ -19489,7 +19572,7 @@ var Container3 = styled10__default.default.div`
19489
19572
  gap: 8px;
19490
19573
  }
19491
19574
  `;
19492
- var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
19575
+ var DEFAULT_EXPLORER = "https://sepolia.arbiscan.io/tx/";
19493
19576
  function truncateHash(hash) {
19494
19577
  return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
19495
19578
  }
@@ -20056,8 +20139,7 @@ var SiteFooter = () => {
20056
20139
  /* @__PURE__ */ jsxRuntime.jsxs(LegalLinks, { children: [
20057
20140
  /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/privacy", children: "Privacy Policy" }),
20058
20141
  /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/terms", children: "Terms of Use" }),
20059
- /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/cookies", children: "Cookie Policy" }),
20060
- /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/risk", children: "Risk Warning" })
20142
+ /* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/cookies", children: "Cookie Policy" })
20061
20143
  ] })
20062
20144
  ] }),
20063
20145
  /* @__PURE__ */ jsxRuntime.jsx(Disclaimer2, { children: /* @__PURE__ */ jsxRuntime.jsx(DisclaimerText, { children: "Warning: Digital asset prices can be volatile. The value of your investment can go down or up and you may not get back the amount invested. Past gains are not indicative of future returns. You are solely responsible for your investment decisions and Loaf is not liable for any losses you may incur. The information here should not be regarded as financial or investment advice. For more information, see our Terms of Use and Risk Warning." }) })