@loafmarkets/ui 0.1.16 → 0.1.17

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
@@ -479,6 +479,8 @@ type LoginPopupProps = {
479
479
  }> | void;
480
480
  /** Optional view to show immediately when the popup opens. */
481
481
  initialView?: LoginPopupView;
482
+ /** Handler invoked when the user selects "Sign in with Wallet". */
483
+ onWalletLogin?: () => Promise<void> | void;
482
484
  };
483
485
  declare const LoginPopup: React__default.FC<LoginPopupProps>;
484
486
 
@@ -487,7 +489,7 @@ type HeaderUser = {
487
489
  email?: string | null;
488
490
  walletAddress?: string | null;
489
491
  };
490
- type HeaderActiveTab = "home" | "trade" | "offerings" | "propertyMap" | "about";
492
+ type HeaderActiveTab = "home" | "trade" | "offerings" | "propertyMap" | "about" | "portfolio" | "learn";
491
493
  type HeaderLoginPopupComponentProps = {
492
494
  onClose: () => void;
493
495
  initialView?: LoginPopupView;
@@ -505,8 +507,10 @@ type HeaderProps = {
505
507
  tradePath?: string;
506
508
  homePath?: string;
507
509
  aboutPath?: string;
510
+ learnPath?: string;
508
511
  offeringsPath?: string;
509
512
  propertyMapPath?: string;
513
+ portfolioPath?: string;
510
514
  loafLiquidityPath?: string;
511
515
  /** Absolute URL for the auth/login surface (e.g. https://auth.loafmarkets.com/login). */
512
516
  authLoginUrl?: string | null;
@@ -716,6 +720,8 @@ type PropertySubscription = {
716
720
  type PropertyBuyProps = {
717
721
  propertyName?: string;
718
722
  propertyLocation?: string;
723
+ tokenDisplayName?: string;
724
+ tokenSymbol?: string;
719
725
  isAuthenticated: boolean;
720
726
  onSignIn: () => void;
721
727
  saleData?: SaleData | null;
@@ -727,7 +733,7 @@ type PropertyBuyProps = {
727
733
  onDeposit?: () => void;
728
734
  initialUserSubscriptions?: PropertySubscription[];
729
735
  };
730
- declare function PropertyBuy({ propertyName, propertyLocation: propertyLocationLabel, isAuthenticated, onSignIn, saleData, walletUsdcBalance, walletPropertyTokenBalance, onPurchase, purchaseStatus, purchaseError, onDeposit, initialUserSubscriptions, }: PropertyBuyProps): react_jsx_runtime.JSX.Element;
736
+ declare function PropertyBuy({ propertyName, propertyLocation: propertyLocationLabel, tokenDisplayName, tokenSymbol, isAuthenticated, onSignIn, saleData, walletUsdcBalance, walletPropertyTokenBalance, onPurchase, purchaseStatus, purchaseError, onDeposit, initialUserSubscriptions, }: PropertyBuyProps): react_jsx_runtime.JSX.Element;
731
737
 
732
738
  type OwnerBookingProps = {
733
739
  propertyName?: string | null;
package/dist/index.d.ts CHANGED
@@ -479,6 +479,8 @@ type LoginPopupProps = {
479
479
  }> | void;
480
480
  /** Optional view to show immediately when the popup opens. */
481
481
  initialView?: LoginPopupView;
482
+ /** Handler invoked when the user selects "Sign in with Wallet". */
483
+ onWalletLogin?: () => Promise<void> | void;
482
484
  };
483
485
  declare const LoginPopup: React__default.FC<LoginPopupProps>;
484
486
 
@@ -487,7 +489,7 @@ type HeaderUser = {
487
489
  email?: string | null;
488
490
  walletAddress?: string | null;
489
491
  };
490
- type HeaderActiveTab = "home" | "trade" | "offerings" | "propertyMap" | "about";
492
+ type HeaderActiveTab = "home" | "trade" | "offerings" | "propertyMap" | "about" | "portfolio" | "learn";
491
493
  type HeaderLoginPopupComponentProps = {
492
494
  onClose: () => void;
493
495
  initialView?: LoginPopupView;
@@ -505,8 +507,10 @@ type HeaderProps = {
505
507
  tradePath?: string;
506
508
  homePath?: string;
507
509
  aboutPath?: string;
510
+ learnPath?: string;
508
511
  offeringsPath?: string;
509
512
  propertyMapPath?: string;
513
+ portfolioPath?: string;
510
514
  loafLiquidityPath?: string;
511
515
  /** Absolute URL for the auth/login surface (e.g. https://auth.loafmarkets.com/login). */
512
516
  authLoginUrl?: string | null;
@@ -716,6 +720,8 @@ type PropertySubscription = {
716
720
  type PropertyBuyProps = {
717
721
  propertyName?: string;
718
722
  propertyLocation?: string;
723
+ tokenDisplayName?: string;
724
+ tokenSymbol?: string;
719
725
  isAuthenticated: boolean;
720
726
  onSignIn: () => void;
721
727
  saleData?: SaleData | null;
@@ -727,7 +733,7 @@ type PropertyBuyProps = {
727
733
  onDeposit?: () => void;
728
734
  initialUserSubscriptions?: PropertySubscription[];
729
735
  };
730
- declare function PropertyBuy({ propertyName, propertyLocation: propertyLocationLabel, isAuthenticated, onSignIn, saleData, walletUsdcBalance, walletPropertyTokenBalance, onPurchase, purchaseStatus, purchaseError, onDeposit, initialUserSubscriptions, }: PropertyBuyProps): react_jsx_runtime.JSX.Element;
736
+ declare function PropertyBuy({ propertyName, propertyLocation: propertyLocationLabel, tokenDisplayName, tokenSymbol, isAuthenticated, onSignIn, saleData, walletUsdcBalance, walletPropertyTokenBalance, onPurchase, purchaseStatus, purchaseError, onDeposit, initialUserSubscriptions, }: PropertyBuyProps): react_jsx_runtime.JSX.Element;
731
737
 
732
738
  type OwnerBookingProps = {
733
739
  propertyName?: string | null;
package/dist/index.js CHANGED
@@ -4441,11 +4441,14 @@ var DEFAULT_TRADE_URL = "https://loafx-frontend-web.vercel.app/";
4441
4441
  var DEFAULT_TRADE_PATH = "/trade";
4442
4442
  var DEFAULT_HOME_PATH = "/";
4443
4443
  var DEFAULT_ABOUT_PATH = "/about";
4444
+ var DEFAULT_LEARN_PATH = "/learn";
4444
4445
  var DEFAULT_OFFERINGS_PATH = "/ipo/musgrave";
4445
4446
  var DEFAULT_PROPERTY_MAP_PATH = "/map";
4447
+ var DEFAULT_PORTFOLIO_PATH = "/portfolio";
4446
4448
  var DEFAULT_LOAF_LIQUIDITY_PATH = "/loaf-liquidity";
4447
4449
  var DEFAULT_AUTH_LOGIN_URL = "http://localhost:5174/";
4448
4450
  var DEFAULT_AUTH_RETURN_PARAM = "returnTo";
4451
+ var LOGIN_POPUP_EVENT = "loaf:open-login-popup";
4449
4452
  var Header = ({
4450
4453
  currentUser,
4451
4454
  isAuthenticated = false,
@@ -4459,8 +4462,10 @@ var Header = ({
4459
4462
  tradePath = DEFAULT_TRADE_PATH,
4460
4463
  homePath = DEFAULT_HOME_PATH,
4461
4464
  aboutPath = DEFAULT_ABOUT_PATH,
4465
+ learnPath = DEFAULT_LEARN_PATH,
4462
4466
  offeringsPath = DEFAULT_OFFERINGS_PATH,
4463
4467
  propertyMapPath = DEFAULT_PROPERTY_MAP_PATH,
4468
+ portfolioPath = DEFAULT_PORTFOLIO_PATH,
4464
4469
  loafLiquidityPath = DEFAULT_LOAF_LIQUIDITY_PATH,
4465
4470
  authLoginUrl = DEFAULT_AUTH_LOGIN_URL,
4466
4471
  authReturnParam = DEFAULT_AUTH_RETURN_PARAM,
@@ -4478,13 +4483,23 @@ var Header = ({
4478
4483
  const [isMoreMenuOpen, setIsMoreMenuOpen] = React5.useState(false);
4479
4484
  const [showLoginPopup, setShowLoginPopup] = React5.useState(false);
4480
4485
  const [loginPopupInitialView, setLoginPopupInitialView] = React5.useState(void 0);
4486
+ React5.useEffect(() => {
4487
+ console.log("[LoginTrace][Header] mounted");
4488
+ return () => console.log("[LoginTrace][Header] unmounted");
4489
+ }, []);
4490
+ React5.useEffect(() => {
4491
+ console.log("[LoginTrace][Header] showLoginPopup changed", { showLoginPopup, loginPopupInitialView });
4492
+ }, [showLoginPopup, loginPopupInitialView]);
4493
+ React5.useEffect(() => {
4494
+ console.log("[LoginTrace][Header] loginPopupComponent updated", { hasComponent: Boolean(LoginPopupComponent) });
4495
+ }, [LoginPopupComponent]);
4481
4496
  React5.useEffect(() => {
4482
4497
  const handleClickOutside = (event) => {
4483
4498
  const target = event.target;
4484
4499
  if (!target) return;
4485
4500
  const clickedInsideUserMenu = target.closest(".user-menu") || target.closest(".user-menu-dropdown");
4486
4501
  if (isUserMenuOpen && !clickedInsideUserMenu) {
4487
- console.log("[Header] Closing user menu due to outside click");
4502
+ console.log("[LoginTrace][Header] Closing user menu due to outside click");
4488
4503
  setIsUserMenuOpen(false);
4489
4504
  }
4490
4505
  if (isMobileMenuOpen && !target.closest(".mobile-menu") && !target.closest(".mobile-menu-button")) {
@@ -4499,6 +4514,19 @@ var Header = ({
4499
4514
  document.removeEventListener("mousedown", handleClickOutside);
4500
4515
  };
4501
4516
  }, [isUserMenuOpen, isMobileMenuOpen, isMoreMenuOpen]);
4517
+ React5.useEffect(() => {
4518
+ if (typeof window === "undefined") return;
4519
+ const handleExternalLoginPopup = (event) => {
4520
+ const customEvent = event;
4521
+ setLoginPopupInitialView(customEvent.detail?.initialView);
4522
+ console.log("[LoginTrace][Header] Received LOGIN_POPUP_EVENT", customEvent.detail);
4523
+ setShowLoginPopup(true);
4524
+ };
4525
+ window.addEventListener(LOGIN_POPUP_EVENT, handleExternalLoginPopup);
4526
+ return () => {
4527
+ window.removeEventListener(LOGIN_POPUP_EVENT, handleExternalLoginPopup);
4528
+ };
4529
+ }, []);
4502
4530
  const closeMenus = () => {
4503
4531
  setIsMobileMenuOpen(false);
4504
4532
  setIsUserMenuOpen(false);
@@ -4506,7 +4534,7 @@ var Header = ({
4506
4534
  };
4507
4535
  const handleUserMenuToggle = () => {
4508
4536
  const nextState = !isUserMenuOpen;
4509
- console.log("[Header] User dropdown toggle clicked", { nextState });
4537
+ console.log("[LoginTrace][Header] User dropdown toggle clicked", { nextState });
4510
4538
  setIsUserMenuOpen(nextState);
4511
4539
  };
4512
4540
  const performNavigation = (path) => {
@@ -4550,13 +4578,13 @@ var Header = ({
4550
4578
  const handleLogoutClick = async (event) => {
4551
4579
  event?.preventDefault();
4552
4580
  closeMenus();
4553
- console.log("[Header] Logout option selected, invoking onLogout handler");
4581
+ console.log("[LoginTrace][Header] Logout option selected, invoking onLogout handler");
4554
4582
  await onLogout?.();
4555
4583
  };
4556
4584
  const handleAddFundingClick = (event) => {
4557
4585
  event?.preventDefault();
4558
4586
  closeMenus();
4559
- console.log("[Header] Add funding selected");
4587
+ console.log("[LoginTrace][Header] Add funding selected");
4560
4588
  if (LoginPopupComponent) {
4561
4589
  setLoginPopupInitialView("funding");
4562
4590
  setShowLoginPopup(true);
@@ -4565,7 +4593,7 @@ var Header = ({
4565
4593
  const handlePortfolioNavigate = (event) => {
4566
4594
  event?.preventDefault();
4567
4595
  closeMenus();
4568
- console.log("[Header] Portfolio selected");
4596
+ console.log("[LoginTrace][Header] Portfolio selected");
4569
4597
  if (_onOrdersNavigate) {
4570
4598
  _onOrdersNavigate();
4571
4599
  return;
@@ -4607,6 +4635,7 @@ var Header = ({
4607
4635
  return false;
4608
4636
  };
4609
4637
  const handleSignIn = () => {
4638
+ console.log("[LoginTrace][Header] handleSignIn invoked", { hasCustomHandler: Boolean(onSignInClick) });
4610
4639
  if (onSignInClick) {
4611
4640
  onSignInClick();
4612
4641
  return;
@@ -4615,15 +4644,23 @@ var Header = ({
4615
4644
  return;
4616
4645
  }
4617
4646
  if (LoginPopupComponent) {
4647
+ console.log("[LoginTrace][Header] Opening login popup via handleSignIn");
4618
4648
  setShowLoginPopup(true);
4619
4649
  }
4620
4650
  };
4651
+ const handleLoginPopupClose = React5__namespace.default.useCallback(() => {
4652
+ console.log("[LoginTrace][Header] Closing login popup via onClose handler");
4653
+ setShowLoginPopup(false);
4654
+ setLoginPopupInitialView(void 0);
4655
+ }, []);
4621
4656
  const inferredActiveTab = (() => {
4622
4657
  if (locationPath === tradePath) return "trade";
4623
4658
  if (locationPath === homePath) return "home";
4624
4659
  if (locationPath === aboutPath) return "about";
4660
+ if (locationPath === learnPath) return "learn";
4625
4661
  if (locationPath.startsWith(offeringsPath)) return "offerings";
4626
4662
  if (locationPath === propertyMapPath) return "propertyMap";
4663
+ if (locationPath === portfolioPath) return "portfolio";
4627
4664
  return null;
4628
4665
  })();
4629
4666
  const resolvedActiveTab = activeTab ?? inferredActiveTab;
@@ -4632,6 +4669,8 @@ var Header = ({
4632
4669
  const offeringsActive = resolvedActiveTab === "offerings";
4633
4670
  const propertyMapActive = resolvedActiveTab === "propertyMap";
4634
4671
  const aboutActive = resolvedActiveTab === "about";
4672
+ const portfolioActive = resolvedActiveTab === "portfolio";
4673
+ const learnActive = resolvedActiveTab === "learn";
4635
4674
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4636
4675
  /* @__PURE__ */ jsxRuntime.jsx(Overlay, { $isOpen: isMobileMenuOpen, onClick: () => setIsMobileMenuOpen(false) }),
4637
4676
  /* @__PURE__ */ jsxRuntime.jsxs(HeaderContainer, { children: [
@@ -4671,6 +4710,18 @@ var Header = ({
4671
4710
  children: "Trade"
4672
4711
  }
4673
4712
  ),
4713
+ /* @__PURE__ */ jsxRuntime.jsx(
4714
+ NavLink,
4715
+ {
4716
+ href: portfolioPath,
4717
+ className: portfolioActive ? "active" : "",
4718
+ onClick: (event) => {
4719
+ event.preventDefault();
4720
+ handleNavigation(portfolioPath);
4721
+ },
4722
+ children: "Portfolio"
4723
+ }
4724
+ ),
4674
4725
  /* @__PURE__ */ jsxRuntime.jsx(
4675
4726
  NavLink,
4676
4727
  {
@@ -4680,7 +4731,7 @@ var Header = ({
4680
4731
  event.preventDefault();
4681
4732
  handleNavigation(offeringsPath);
4682
4733
  },
4683
- children: "Offerings"
4734
+ children: "Initial Offerings"
4684
4735
  }
4685
4736
  ),
4686
4737
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4695,6 +4746,18 @@ var Header = ({
4695
4746
  children: "Property Map"
4696
4747
  }
4697
4748
  ),
4749
+ /* @__PURE__ */ jsxRuntime.jsx(
4750
+ NavLink,
4751
+ {
4752
+ href: learnPath,
4753
+ className: learnActive ? "active" : "",
4754
+ onClick: (event) => {
4755
+ event.preventDefault();
4756
+ handleNavigation(learnPath);
4757
+ },
4758
+ children: "Learn"
4759
+ }
4760
+ ),
4698
4761
  /* @__PURE__ */ jsxRuntime.jsx(
4699
4762
  NavLink,
4700
4763
  {
@@ -4742,8 +4805,10 @@ var Header = ({
4742
4805
  children: "Trade"
4743
4806
  }
4744
4807
  ),
4745
- /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(offeringsPath), children: "Offerings" }),
4808
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(portfolioPath), children: "Portfolio" }),
4809
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(offeringsPath), children: "Initial Offerings" }),
4746
4810
  /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(propertyMapPath), children: "Property Map" }),
4811
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(learnPath), children: "Learn" }),
4747
4812
  /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(aboutPath), children: "About" }),
4748
4813
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { borderTop: "1px solid #2b3139", margin: "8px 0" } }),
4749
4814
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4799,7 +4864,7 @@ var Header = ({
4799
4864
  {
4800
4865
  type: "button",
4801
4866
  onClick: (event) => {
4802
- console.log("[Header] Add funding menu item clicked");
4867
+ console.log("[LoginTrace][Header] Add funding menu item clicked");
4803
4868
  handleAddFundingClick(event);
4804
4869
  },
4805
4870
  children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { children: "Add funding" })
@@ -4810,7 +4875,7 @@ var Header = ({
4810
4875
  {
4811
4876
  type: "button",
4812
4877
  onClick: (event) => {
4813
- console.log("[Header] Logout menu item clicked");
4878
+ console.log("[LoginTrace][Header] Logout menu item clicked");
4814
4879
  void handleLogoutClick(event);
4815
4880
  },
4816
4881
  children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { className: "logout", children: "Logout" })
@@ -4845,10 +4910,7 @@ var Header = ({
4845
4910
  LoginPopupComponent && showLoginPopup && /* @__PURE__ */ jsxRuntime.jsx(
4846
4911
  LoginPopupComponent,
4847
4912
  {
4848
- onClose: () => {
4849
- setShowLoginPopup(false);
4850
- setLoginPopupInitialView(void 0);
4851
- },
4913
+ onClose: handleLoginPopupClose,
4852
4914
  initialView: loginPopupInitialView
4853
4915
  }
4854
4916
  )
@@ -5376,6 +5438,7 @@ var OTP_INPUT_LENGTH = 6;
5376
5438
  var LoginPopup = ({
5377
5439
  onClose,
5378
5440
  onOpenEarlyAccess,
5441
+ onWalletLogin,
5379
5442
  isAuthenticated,
5380
5443
  currentUser,
5381
5444
  onSendEmailCode,
@@ -5400,38 +5463,74 @@ var LoginPopup = ({
5400
5463
  const [fundingLoading, setFundingLoading] = React5.useState(false);
5401
5464
  const [fundingError, setFundingError] = React5.useState("");
5402
5465
  const suppressAutoCloseRef = React5__namespace.default.useRef(false);
5466
+ React5.useEffect(() => {
5467
+ console.log("[LoginTrace][Popup] mounted");
5468
+ return () => console.log("[LoginTrace][Popup] unmounted");
5469
+ }, []);
5470
+ React5.useEffect(() => {
5471
+ console.log("[LoginTrace][Popup] view updated", { view });
5472
+ }, [view]);
5473
+ React5.useEffect(() => {
5474
+ console.log("[LoginTrace][Popup] auth props updated", { isAuthenticated, hasUser: Boolean(currentUser) });
5475
+ }, [isAuthenticated, currentUser]);
5403
5476
  React5.useEffect(() => {
5404
5477
  if (typeof initialView === "string") {
5478
+ console.log("[LoginTrace][Popup] initialView prop changed", { initialView });
5405
5479
  setView(initialView);
5406
5480
  }
5407
5481
  }, [initialView]);
5408
5482
  React5.useEffect(() => {
5409
5483
  if (!autoCloseOnAuth) {
5484
+ console.log("[LoginTrace][Popup] autoClose disabled", { autoCloseOnAuth, view });
5410
5485
  return;
5411
5486
  }
5412
5487
  if (suppressAutoCloseRef.current) {
5488
+ console.log("[LoginTrace][Popup] autoClose suppressed", { view });
5413
5489
  return;
5414
5490
  }
5415
5491
  if (view === "kyc" || view === "kyc-success" || view === "kyc-failed" || view === "funding") {
5492
+ console.log("[LoginTrace][Popup] autoClose skipped due to onboarding view", { view });
5416
5493
  return;
5417
5494
  }
5495
+ console.log("[LoginTrace][Popup] autoClose effect evaluating", {
5496
+ autoCloseOnAuth,
5497
+ isAuthenticated,
5498
+ hasUser: Boolean(currentUser),
5499
+ view
5500
+ });
5418
5501
  if (isAuthenticated || currentUser) {
5502
+ console.log("[LoginTrace][Popup] autoClose triggered", { isAuthenticated, hasUser: Boolean(currentUser), view });
5419
5503
  onClose();
5420
5504
  }
5421
5505
  }, [autoCloseOnAuth, currentUser, isAuthenticated, onClose, view]);
5422
- const handleWalletLogin = () => {
5506
+ const handleWalletLogin = async () => {
5507
+ console.log("[LoginTrace][Popup] Wallet login clicked, onWalletLogin:", !!onWalletLogin);
5508
+ if (onWalletLogin) {
5509
+ try {
5510
+ console.log("[LoginTrace][Popup] Calling onWalletLogin...");
5511
+ await onWalletLogin();
5512
+ console.log("[LoginTrace][Popup] onWalletLogin completed, closing popup");
5513
+ onClose();
5514
+ return;
5515
+ } catch (err) {
5516
+ console.error("[LoginTrace][Popup] Wallet login failed", err);
5517
+ }
5518
+ }
5519
+ console.log("[LoginTrace][Popup] No onWalletLogin handler, closing popup");
5423
5520
  onClose();
5424
5521
  if (onOpenEarlyAccess) {
5425
5522
  onOpenEarlyAccess();
5426
5523
  }
5427
5524
  };
5428
5525
  const handleEmailClick = (signUp = false) => {
5526
+ console.log("[LoginTrace][Popup] handleEmailClick", { signUp });
5429
5527
  setIsSignUp(signUp);
5430
5528
  setView("email");
5431
5529
  setError("");
5432
5530
  };
5433
5531
  const handleSendCode = async (event) => {
5434
5532
  event?.preventDefault();
5533
+ console.log("[LoginTrace][Popup] handleSendCode invoked", { email, isSignUp, handle, eventType: event?.type });
5435
5534
  if (!email || !email.includes("@")) {
5436
5535
  setError("Please enter a valid email address");
5437
5536
  return;
@@ -5444,13 +5543,15 @@ var LoginPopup = ({
5444
5543
  setError("");
5445
5544
  const normalizedHandle = isSignUp ? handle.trim() : void 0;
5446
5545
  try {
5546
+ console.log("[LoginTrace][Popup] Attempting demo login fallback", { hasDemoHandler: Boolean(onDemoLogin) });
5447
5547
  const demoResult = await onDemoLogin?.(email, normalizedHandle ?? null);
5448
5548
  if (demoResult && demoResult.success) {
5549
+ console.log("[LoginTrace][Popup] Demo login succeeded, skipping OTP flow");
5449
5550
  setLoading(false);
5450
5551
  return;
5451
5552
  }
5452
5553
  } catch (err) {
5453
- console.warn("Demo login failed, attempting email OTP", err);
5554
+ console.warn("[LoginTrace][Popup] Demo login failed, attempting email OTP", err);
5454
5555
  }
5455
5556
  if (!onSendEmailCode) {
5456
5557
  setError("Email authentication is not configured for this popup.");
@@ -5458,10 +5559,13 @@ var LoginPopup = ({
5458
5559
  return;
5459
5560
  }
5460
5561
  try {
5562
+ console.log("[LoginTrace][Popup] Calling onSendEmailCode", { email, isSignUp, normalizedHandle });
5461
5563
  await onSendEmailCode({ email, isSignUp, handle: normalizedHandle ?? null });
5564
+ console.log("[LoginTrace][Popup] onSendEmailCode resolved, switching to OTP view");
5462
5565
  setView("otp");
5463
5566
  setOtp(Array(OTP_INPUT_LENGTH).fill(""));
5464
5567
  } catch (err) {
5568
+ console.error("[LoginTrace][Popup] onSendEmailCode threw", err);
5465
5569
  setError(err instanceof Error ? err.message : "Failed to send verification code");
5466
5570
  } finally {
5467
5571
  setLoading(false);
@@ -5494,9 +5598,32 @@ var LoginPopup = ({
5494
5598
  document.getElementById(`otp-${index - 1}`)?.focus();
5495
5599
  }
5496
5600
  };
5601
+ const handleOTPInput = (index, event) => {
5602
+ const rawValue = event.currentTarget.value ?? "";
5603
+ const nativeEvent = event.nativeEvent;
5604
+ const isPasteLike = nativeEvent?.inputType === "insertFromPaste" || rawValue.length > 1;
5605
+ if (isPasteLike) {
5606
+ handleOTPChange(index, rawValue);
5607
+ }
5608
+ };
5609
+ const handleOTPPaste = (event) => {
5610
+ event.preventDefault();
5611
+ const pasted = event.clipboardData?.getData("text") ?? "";
5612
+ const digits = pasted.replace(/\D/g, "").slice(0, OTP_INPUT_LENGTH).split("");
5613
+ if (digits.length === 0) return;
5614
+ const next = Array.from({ length: OTP_INPUT_LENGTH }, (_, i) => digits[i] ?? "");
5615
+ setOtp(next);
5616
+ const lastIndex = Math.min(digits.length, OTP_INPUT_LENGTH) - 1;
5617
+ if (lastIndex >= 0) {
5618
+ requestAnimationFrame(() => {
5619
+ document.getElementById(`otp-${lastIndex}`)?.focus();
5620
+ });
5621
+ }
5622
+ };
5497
5623
  const handleVerifyCode = async (event) => {
5498
5624
  event.preventDefault();
5499
5625
  const code = otp.join("");
5626
+ console.log("[LoginTrace][Popup] handleVerifyCode", { codeLength: code.length, isSignUp });
5500
5627
  if (code.length !== OTP_INPUT_LENGTH) {
5501
5628
  setError("Please enter the 6-digit code");
5502
5629
  return;
@@ -5511,13 +5638,16 @@ var LoginPopup = ({
5511
5638
  suppressAutoCloseRef.current = true;
5512
5639
  }
5513
5640
  try {
5641
+ console.log("[LoginTrace][Popup] Calling onVerifyEmailCode");
5514
5642
  await onVerifyEmailCode({ code, email });
5515
5643
  if (isSignUp) {
5644
+ console.log("[LoginTrace][Popup] Signup OTP verified, moving to KYC view");
5516
5645
  setView("kyc");
5517
5646
  setLoading(false);
5518
5647
  return;
5519
5648
  }
5520
5649
  } catch (err) {
5650
+ console.error("[LoginTrace][Popup] onVerifyEmailCode threw", err);
5521
5651
  suppressAutoCloseRef.current = false;
5522
5652
  setError(err instanceof Error ? err.message : "Invalid verification code");
5523
5653
  } finally {
@@ -5702,6 +5832,9 @@ var LoginPopup = ({
5702
5832
  value: digit,
5703
5833
  onChange: (event) => handleOTPChange(index, event.target.value),
5704
5834
  onKeyDown: (event) => handleOTPKeyDown(index, event),
5835
+ onInput: (event) => handleOTPInput(index, event),
5836
+ onPaste: handleOTPPaste,
5837
+ autoComplete: index === 0 ? "one-time-code" : "off",
5705
5838
  autoFocus: index === 0
5706
5839
  },
5707
5840
  index
@@ -8685,6 +8818,7 @@ function OrderPanel({
8685
8818
  statusLabel,
8686
8819
  statusColor,
8687
8820
  ipoStarted,
8821
+ isAuthenticated,
8688
8822
  tokenPrice,
8689
8823
  feeRate,
8690
8824
  supplyToSell,
@@ -8702,11 +8836,14 @@ function OrderPanel({
8702
8836
  setSliderValue,
8703
8837
  setManualOrderAmount,
8704
8838
  onOrderButtonClick,
8839
+ onSignInClick,
8705
8840
  orderButtonText,
8706
8841
  isOrderButtonDisabled,
8707
8842
  hasInsufficientFunds,
8708
8843
  onPlaceAnotherOrder,
8709
- onDeposit
8844
+ onDeposit,
8845
+ tokenDisplayName,
8846
+ tokenSymbol
8710
8847
  }) {
8711
8848
  const [payInputValue, setPayInputValue] = React5.useState("");
8712
8849
  const [receiveInputValue, setReceiveInputValue] = React5.useState("");
@@ -8764,10 +8901,10 @@ function OrderPanel({
8764
8901
  ] }),
8765
8902
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "success-body", children: [
8766
8903
  [
8767
- { label: "Units Acquired", value: `${lastOrderDetails?.tokens?.toFixed(2) || "0.00"} MUS` },
8904
+ { label: "Units Acquired", value: `${lastOrderDetails?.tokens?.toFixed(2) || "0.00"} ${tokenSymbol}` },
8768
8905
  { label: "Price Per Unit", value: `$${tokenPrice.toFixed(2)}` },
8769
8906
  {
8770
- label: "Musgrave Exposure",
8907
+ label: `${tokenDisplayName} Exposure`,
8771
8908
  value: `${((lastOrderDetails?.tokens ?? 0) / supplyToSell * 100).toFixed(3)}%`
8772
8909
  }
8773
8910
  ].map((row) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "success-row", children: [
@@ -8829,13 +8966,19 @@ function OrderPanel({
8829
8966
  ] }),
8830
8967
  /* @__PURE__ */ jsxRuntime.jsxs(FundsRow, { children: [
8831
8968
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8832
- "Available Funds: ",
8833
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8834
- "$",
8835
- availableBalance.toLocaleString()
8836
- ] })
8969
+ "Available Funds:",
8970
+ " ",
8971
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: isAuthenticated ? `$${availableBalance.toLocaleString()}` : "\u2014" })
8837
8972
  ] }),
8838
- /* @__PURE__ */ jsxRuntime.jsx(DepositButton, { type: "button", onClick: onDeposit, children: "+ Deposit" })
8973
+ /* @__PURE__ */ jsxRuntime.jsx(
8974
+ DepositButton,
8975
+ {
8976
+ type: "button",
8977
+ onClick: isAuthenticated ? onDeposit : void 0,
8978
+ disabled: !isAuthenticated,
8979
+ children: "+ Deposit"
8980
+ }
8981
+ )
8839
8982
  ] }),
8840
8983
  /* @__PURE__ */ jsxRuntime.jsx(Divider2, { children: "\u2193" }),
8841
8984
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
@@ -8867,7 +9010,7 @@ function OrderPanel({
8867
9010
  }
8868
9011
  }
8869
9012
  ),
8870
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "MUSGRAVE" })
9013
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: tokenDisplayName })
8871
9014
  ] })
8872
9015
  ] }),
8873
9016
  /* @__PURE__ */ jsxRuntime.jsxs(OrderSummary, { children: [
@@ -8883,7 +9026,8 @@ function OrderPanel({
8883
9026
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Buying" }),
8884
9027
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8885
9028
  tokenQuantity.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
8886
- " units"
9029
+ " ",
9030
+ tokenSymbol
8887
9031
  ] })
8888
9032
  ] }),
8889
9033
  /* @__PURE__ */ jsxRuntime.jsxs(SummaryRow, { children: [
@@ -8894,7 +9038,8 @@ function OrderPanel({
8894
9038
  ] }),
8895
9039
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8896
9040
  feeInTokens.toFixed(2),
8897
- " units"
9041
+ " ",
9042
+ tokenSymbol
8898
9043
  ] })
8899
9044
  ] }),
8900
9045
  /* @__PURE__ */ jsxRuntime.jsxs(SummaryTotal, { children: [
@@ -8913,11 +9058,17 @@ function OrderPanel({
8913
9058
  type: "button",
8914
9059
  disabled: isOrderButtonDisabled,
8915
9060
  "data-green": orderButtonText === "Place Order",
8916
- onClick: onOrderButtonClick,
9061
+ onClick: () => {
9062
+ if (!isAuthenticated) {
9063
+ onSignInClick();
9064
+ return;
9065
+ }
9066
+ onOrderButtonClick();
9067
+ },
8917
9068
  children: orderButtonText
8918
9069
  }
8919
9070
  ),
8920
- /* @__PURE__ */ jsxRuntime.jsxs(BalanceCards, { children: [
9071
+ isAuthenticated && /* @__PURE__ */ jsxRuntime.jsxs(BalanceCards, { children: [
8921
9072
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceCard, { children: [
8922
9073
  /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: "Available to Invest" }),
8923
9074
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceValue, { children: [
@@ -8927,18 +9078,26 @@ function OrderPanel({
8927
9078
  /* @__PURE__ */ jsxRuntime.jsx(BalanceAction, { onClick: onDeposit, style: { cursor: onDeposit ? "pointer" : "default" }, children: "+ Deposit" })
8928
9079
  ] }),
8929
9080
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceCard, { children: [
8930
- /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: "Musgrave Owned" }),
9081
+ /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: `${tokenDisplayName} Owned` }),
8931
9082
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceValue, { children: [
8932
9083
  displayedOwnedTokens.toFixed(2),
9084
+ " ",
9085
+ tokenSymbol,
8933
9086
  ownedTokensJustUpdated && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8934
9087
  "+",
8935
- lastOrderQuantity.toFixed(2)
9088
+ lastOrderQuantity.toFixed(2),
9089
+ " ",
9090
+ tokenSymbol
8936
9091
  ] })
8937
9092
  ] }),
8938
9093
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceSub, { children: [
8939
9094
  "$",
8940
- (displayedOwnedTokens * tokenPrice).toLocaleString(),
8941
- " \u2022 ",
9095
+ (displayedOwnedTokens * tokenPrice).toLocaleString("en-US", {
9096
+ minimumFractionDigits: 0,
9097
+ maximumFractionDigits: 0
9098
+ }),
9099
+ " ",
9100
+ "\u2022 ",
8942
9101
  (displayedOwnedTokens / supplyToSell * 100).toFixed(3),
8943
9102
  "%"
8944
9103
  ] })
@@ -10067,8 +10226,10 @@ var ButtonRow = styled23__default.default.div`
10067
10226
  }
10068
10227
  `;
10069
10228
  function PropertyBuy({
10070
- propertyName = "8c Mcleod Street (Musgrave)",
10071
- propertyLocation: propertyLocationLabel = "Mosman, Sydney",
10229
+ propertyName = "Loaf Property",
10230
+ propertyLocation: propertyLocationLabel = "Sydney, NSW",
10231
+ tokenDisplayName = "Property Token",
10232
+ tokenSymbol = "LOAF",
10072
10233
  isAuthenticated,
10073
10234
  onSignIn,
10074
10235
  saleData,
@@ -10135,10 +10296,6 @@ function PropertyBuy({
10135
10296
  }
10136
10297
  }, [walletPropertyTokenBalance]);
10137
10298
  const handleOrderButtonClick = () => {
10138
- if (!isAuthenticated) {
10139
- onSignIn();
10140
- return;
10141
- }
10142
10299
  if (!ipoStarted || tokenQuantity === 0) {
10143
10300
  return;
10144
10301
  }
@@ -10185,7 +10342,7 @@ function PropertyBuy({
10185
10342
  setTimeout(() => setOwnedTokensJustUpdated(false), 2e3);
10186
10343
  const optimisticEntry = {
10187
10344
  propertyName,
10188
- tokenSymbol: "MUS",
10345
+ tokenSymbol,
10189
10346
  tokens: tokenAmountInt,
10190
10347
  value: orderTotal,
10191
10348
  avgPrice: tokenPrice,
@@ -10262,6 +10419,8 @@ function PropertyBuy({
10262
10419
  statusLabel,
10263
10420
  statusColor,
10264
10421
  ipoStarted,
10422
+ tokenDisplayName,
10423
+ tokenSymbol,
10265
10424
  isAuthenticated,
10266
10425
  tokenPrice,
10267
10426
  feeRate,
@@ -10279,6 +10438,7 @@ function PropertyBuy({
10279
10438
  manualOrderAmount,
10280
10439
  setSliderValue,
10281
10440
  setManualOrderAmount,
10441
+ onSignInClick: onSignIn,
10282
10442
  onOrderButtonClick: handleOrderButtonClick,
10283
10443
  orderButtonText: getOrderButtonText(),
10284
10444
  isOrderButtonDisabled: isOrderButtonDisabled(),