@loafmarkets/ui 0.1.380 → 0.1.382

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
@@ -580,6 +580,13 @@ type LoginPopupProps = {
580
580
  onFundWallet?: (params: FundWalletParams) => Promise<FundWalletResult> | void;
581
581
  /** Optional view to show immediately when the popup opens. */
582
582
  initialView?: LoginPopupView;
583
+ /**
584
+ * Gate-only: an access code supplied out-of-band (e.g. the `?code=` param on an
585
+ * invite link). Any form is accepted ("LOAF-M8TRP" / "loaf-m8trp" / "M8TRP").
586
+ * Pre-fills the code field and, when complete, auto-validates on open so the
587
+ * gate advances straight to sign-in.
588
+ */
589
+ initialCode?: string;
583
590
  /** Wallet address used for the receive funds view (bypasses Privy modal). */
584
591
  walletAddress?: string | null;
585
592
  /** Called when the user submits a referral code during onboarding. */
package/dist/index.d.ts CHANGED
@@ -580,6 +580,13 @@ type LoginPopupProps = {
580
580
  onFundWallet?: (params: FundWalletParams) => Promise<FundWalletResult> | void;
581
581
  /** Optional view to show immediately when the popup opens. */
582
582
  initialView?: LoginPopupView;
583
+ /**
584
+ * Gate-only: an access code supplied out-of-band (e.g. the `?code=` param on an
585
+ * invite link). Any form is accepted ("LOAF-M8TRP" / "loaf-m8trp" / "M8TRP").
586
+ * Pre-fills the code field and, when complete, auto-validates on open so the
587
+ * gate advances straight to sign-in.
588
+ */
589
+ initialCode?: string;
583
590
  /** Wallet address used for the receive funds view (bypasses Privy modal). */
584
591
  walletAddress?: string | null;
585
592
  /** Called when the user submits a referral code during onboarding. */
package/dist/index.js CHANGED
@@ -6626,6 +6626,9 @@ PropertySubheader.displayName = "PropertySubheader";
6626
6626
  var DEFAULT_LOGO_SRC = Loaf_logo_Banner_default;
6627
6627
  var DEFAULT_LOGO_ALT = "Loaf";
6628
6628
  var OTP_INPUT_LENGTH = 6;
6629
+ var CODE_PREFIX = "LOAF-";
6630
+ var CODE_SUFFIX_LEN = 5;
6631
+ var normalizeAccessCode = (raw) => CODE_PREFIX + raw.toUpperCase().replace(/^LOAF-?/, "").replace(/[^A-Z0-9]/g, "").slice(0, CODE_SUFFIX_LEN);
6629
6632
  var friendlyError = (err, fallback) => {
6630
6633
  const data = err?.response?.data;
6631
6634
  if (typeof data?.error === "string" && data.error.trim()) return data.error;
@@ -6652,6 +6655,7 @@ var LoginPopup = ({
6652
6655
  renderKycWidget,
6653
6656
  onFundWallet,
6654
6657
  initialView,
6658
+ initialCode,
6655
6659
  kycStatus: kycStatusProp,
6656
6660
  walletAddress,
6657
6661
  onSubmitReferralCode,
@@ -6665,7 +6669,9 @@ var LoginPopup = ({
6665
6669
  const [otp, setOtp] = React5.useState(Array(OTP_INPUT_LENGTH).fill(""));
6666
6670
  const [error, setError] = React5.useState("");
6667
6671
  const [copied, setCopied] = React5.useState(false);
6668
- const [referralCode, setReferralCode] = React5.useState("");
6672
+ const [referralCode, setReferralCode] = React5.useState(
6673
+ () => gate && initialCode ? normalizeAccessCode(initialCode) : ""
6674
+ );
6669
6675
  const [referralLoading, setReferralLoading] = React5.useState(false);
6670
6676
  const [referralError, setReferralError] = React5.useState("");
6671
6677
  const [codeStatus, setCodeStatus] = React5.useState("idle");
@@ -6674,20 +6680,6 @@ var LoginPopup = ({
6674
6680
  const [signInMode, setSignInMode] = React5.useState(false);
6675
6681
  const [loading, setLoading] = React5.useState(false);
6676
6682
  const [isSignUp, setIsSignUp] = React5.useState(false);
6677
- const [gateViewportH, setGateViewportH] = React5.useState(void 0);
6678
- React5.useEffect(() => {
6679
- if (!gate || typeof window === "undefined") return;
6680
- const vv = window.visualViewport;
6681
- if (!vv) return;
6682
- const sync = () => setGateViewportH(vv.height);
6683
- sync();
6684
- vv.addEventListener("resize", sync);
6685
- vv.addEventListener("scroll", sync);
6686
- return () => {
6687
- vv.removeEventListener("resize", sync);
6688
- vv.removeEventListener("scroll", sync);
6689
- };
6690
- }, [gate]);
6691
6683
  const [fundingAmount] = React5.useState("");
6692
6684
  const [kycLoading, setKycLoading] = React5.useState(false);
6693
6685
  const [showKycWidget, setShowKycWidget] = React5.useState(false);
@@ -6724,6 +6716,37 @@ var LoginPopup = ({
6724
6716
  );
6725
6717
  return false;
6726
6718
  }, [gate, onSubmitReferralCode, onCheckAccess]);
6719
+ const runCodeValidation = React5__namespace.default.useCallback(async (fullCode) => {
6720
+ setCodeStatus("checking");
6721
+ setError("");
6722
+ try {
6723
+ const ok = onValidateCode ? await onValidateCode(fullCode) : true;
6724
+ if (!ok) {
6725
+ validatedCodeRef.current = null;
6726
+ setCodeStatus("invalid");
6727
+ return;
6728
+ }
6729
+ validatedCodeRef.current = fullCode;
6730
+ setCodeStatus("valid");
6731
+ if (isAuthenticated) {
6732
+ if (await finishGate()) setTimeout(() => onClose(), 500);
6733
+ return;
6734
+ }
6735
+ setIsSignUp(true);
6736
+ setSignInRevealed(true);
6737
+ } catch {
6738
+ validatedCodeRef.current = null;
6739
+ setCodeStatus("invalid");
6740
+ }
6741
+ }, [onValidateCode, isAuthenticated, finishGate, onClose]);
6742
+ const autoCodeTriedRef = React5__namespace.default.useRef(false);
6743
+ React5.useEffect(() => {
6744
+ if (autoCodeTriedRef.current || !gate || !initialCode) return;
6745
+ const full = normalizeAccessCode(initialCode);
6746
+ if (full.length !== CODE_PREFIX.length + CODE_SUFFIX_LEN) return;
6747
+ autoCodeTriedRef.current = true;
6748
+ void runCodeValidation(full);
6749
+ }, [gate, initialCode, runCodeValidation]);
6727
6750
  React5.useEffect(() => {
6728
6751
  if (typeof initialView === "string") {
6729
6752
  setView(initialView);
@@ -7209,7 +7232,7 @@ var LoginPopup = ({
7209
7232
  }
7210
7233
  if (view === "otp") {
7211
7234
  if (gate) {
7212
- return /* @__PURE__ */ jsxRuntime.jsxs(GateShell, { $h: gateViewportH, children: [
7235
+ return /* @__PURE__ */ jsxRuntime.jsxs(GateShell, { children: [
7213
7236
  /* @__PURE__ */ jsxRuntime.jsx(GateTint, { $reveal: otpStatus === "valid" ? 3 : 2 }),
7214
7237
  /* @__PURE__ */ jsxRuntime.jsxs(GateForm, { children: [
7215
7238
  /* @__PURE__ */ jsxRuntime.jsxs(GateBrand, { children: [
@@ -7492,31 +7515,7 @@ var LoginPopup = ({
7492
7515
  setReferralLoading(false);
7493
7516
  }
7494
7517
  };
7495
- const CODE_PREFIX = "LOAF-";
7496
7518
  const codeSuffix = referralCode.startsWith(CODE_PREFIX) ? referralCode.slice(CODE_PREFIX.length) : referralCode.replace(/^LOAF-?/i, "");
7497
- const runCodeValidation = async (fullCode) => {
7498
- setCodeStatus("checking");
7499
- setError("");
7500
- try {
7501
- const ok = onValidateCode ? await onValidateCode(fullCode) : true;
7502
- if (!ok) {
7503
- validatedCodeRef.current = null;
7504
- setCodeStatus("invalid");
7505
- return;
7506
- }
7507
- validatedCodeRef.current = fullCode;
7508
- setCodeStatus("valid");
7509
- if (isAuthenticated) {
7510
- if (await finishGate()) setTimeout(() => onClose(), 500);
7511
- return;
7512
- }
7513
- setIsSignUp(true);
7514
- setSignInRevealed(true);
7515
- } catch {
7516
- validatedCodeRef.current = null;
7517
- setCodeStatus("invalid");
7518
- }
7519
- };
7520
7519
  const setCodeSuffix = (suffix) => {
7521
7520
  setReferralCode(CODE_PREFIX + suffix);
7522
7521
  setReferralError("");
@@ -7590,7 +7589,7 @@ var LoginPopup = ({
7590
7589
  if (gate) {
7591
7590
  const codeAccepted = codeStatus === "valid";
7592
7591
  const showSignIn = signInMode || signInRevealed;
7593
- return /* @__PURE__ */ jsxRuntime.jsxs(GateShell, { $h: gateViewportH, children: [
7592
+ return /* @__PURE__ */ jsxRuntime.jsxs(GateShell, { children: [
7594
7593
  /* @__PURE__ */ jsxRuntime.jsx(GateTint, { $reveal: showSignIn ? 1 : 0 }),
7595
7594
  /* @__PURE__ */ jsxRuntime.jsxs(GateForm, { children: [
7596
7595
  /* @__PURE__ */ jsxRuntime.jsxs(GateBrand, { children: [
@@ -8217,21 +8216,12 @@ var GateForm = styled10__default.default.div`
8217
8216
  `;
8218
8217
  var GateShell = styled10__default.default.div`
8219
8218
  position: fixed;
8220
- top: 0;
8221
- left: 0;
8222
- right: 0;
8223
- /* Visual-viewport height when available (see gateViewportH) so the gate ends
8224
- at the keyboard top with nothing hidden below it to scroll to; 100% else. */
8225
- height: ${(props) => props.$h ? `${props.$h}px` : "100%"};
8219
+ inset: 0;
8226
8220
  display: flex;
8227
8221
  align-items: center;
8228
8222
  justify-content: center;
8229
8223
  z-index: 10000;
8230
8224
  background-color: rgba(10, 10, 12, 0.66);
8231
- /* If content can't fit the visible area (very short screen + keyboard), scroll
8232
- WITHIN the gate only — never chain to the platform underneath. */
8233
- overflow-y: auto;
8234
- overscroll-behavior: contain;
8235
8225
  `;
8236
8226
  var GateTint = styled10__default.default.div`
8237
8227
  position: absolute;