@loafmarkets/ui 0.1.408 → 0.1.410
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 +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +327 -46
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +327 -46
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -712,6 +712,11 @@ type HeaderProps = {
|
|
|
712
712
|
* without DOM-level click interception. */
|
|
713
713
|
onReferClick?: () => void;
|
|
714
714
|
portfolioSummary?: HeaderPortfolioData | null;
|
|
715
|
+
/**
|
|
716
|
+
* Cumulative competition points the user has earned across all rounds up to now.
|
|
717
|
+
* When provided, the account dropdown leads with a "Total Points" summary row.
|
|
718
|
+
*/
|
|
719
|
+
totalPoints?: number | null;
|
|
715
720
|
/**
|
|
716
721
|
* True while a brand-new user's test funds (100k mock USD) are being deposited
|
|
717
722
|
* on-chain (~10s). Replaces the portfolio metrics with a "funds arriving" banner.
|
|
@@ -768,9 +773,12 @@ interface OnboardingGuideProps {
|
|
|
768
773
|
onEnterCode?: () => void;
|
|
769
774
|
/** Dismiss / skip (✕, "Skip for now", or after Browse). */
|
|
770
775
|
onClose: () => void;
|
|
776
|
+
/** Save the chosen handle (optional step). Reject to surface an error
|
|
777
|
+
* (e.g. handle taken). If omitted, the handle step is skipped entirely. */
|
|
778
|
+
onClaimHandle?: (handle: string) => Promise<void> | void;
|
|
771
779
|
logoSrc?: string;
|
|
772
780
|
}
|
|
773
|
-
declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
|
|
781
|
+
declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, onClaimHandle, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
|
|
774
782
|
|
|
775
783
|
type PropertyAddressOption = {
|
|
776
784
|
id: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -712,6 +712,11 @@ type HeaderProps = {
|
|
|
712
712
|
* without DOM-level click interception. */
|
|
713
713
|
onReferClick?: () => void;
|
|
714
714
|
portfolioSummary?: HeaderPortfolioData | null;
|
|
715
|
+
/**
|
|
716
|
+
* Cumulative competition points the user has earned across all rounds up to now.
|
|
717
|
+
* When provided, the account dropdown leads with a "Total Points" summary row.
|
|
718
|
+
*/
|
|
719
|
+
totalPoints?: number | null;
|
|
715
720
|
/**
|
|
716
721
|
* True while a brand-new user's test funds (100k mock USD) are being deposited
|
|
717
722
|
* on-chain (~10s). Replaces the portfolio metrics with a "funds arriving" banner.
|
|
@@ -768,9 +773,12 @@ interface OnboardingGuideProps {
|
|
|
768
773
|
onEnterCode?: () => void;
|
|
769
774
|
/** Dismiss / skip (✕, "Skip for now", or after Browse). */
|
|
770
775
|
onClose: () => void;
|
|
776
|
+
/** Save the chosen handle (optional step). Reject to surface an error
|
|
777
|
+
* (e.g. handle taken). If omitted, the handle step is skipped entirely. */
|
|
778
|
+
onClaimHandle?: (handle: string) => Promise<void> | void;
|
|
771
779
|
logoSrc?: string;
|
|
772
780
|
}
|
|
773
|
-
declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
|
|
781
|
+
declare function OnboardingGuide({ open, fundsReady, cashLabel, onBrowseProperties, onEnterCode, onClose, onClaimHandle, logoSrc, }: OnboardingGuideProps): react_jsx_runtime.JSX.Element | null;
|
|
774
782
|
|
|
775
783
|
type PropertyAddressOption = {
|
|
776
784
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -2669,6 +2669,22 @@ var PropertyTour = React5__namespace.forwardRef(
|
|
|
2669
2669
|
}
|
|
2670
2670
|
);
|
|
2671
2671
|
PropertyTour.displayName = "PropertyTour";
|
|
2672
|
+
|
|
2673
|
+
// src/lib/isSafeUrl.ts
|
|
2674
|
+
var CONTROL_CHARS = /[\u0000-\u001F\u007F]/g;
|
|
2675
|
+
function isSafeUrl(url) {
|
|
2676
|
+
if (!url) return false;
|
|
2677
|
+
const cleaned = url.replace(CONTROL_CHARS, "").replace(/\\/g, "/").trim();
|
|
2678
|
+
if (cleaned === "") return false;
|
|
2679
|
+
if (cleaned.startsWith("//")) return false;
|
|
2680
|
+
if (cleaned.startsWith("/")) return true;
|
|
2681
|
+
try {
|
|
2682
|
+
const { protocol } = new URL(cleaned);
|
|
2683
|
+
return protocol === "http:" || protocol === "https:";
|
|
2684
|
+
} catch {
|
|
2685
|
+
return false;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2672
2688
|
var ITEMS_PER_PAGE = 5;
|
|
2673
2689
|
var ITEMS_PER_PAGE_MOBILE = 5;
|
|
2674
2690
|
var ensureAnimationsInjected = () => {
|
|
@@ -2864,7 +2880,7 @@ function NewsArticleModal({ item, onClose }) {
|
|
|
2864
2880
|
] }),
|
|
2865
2881
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "1px", background: "rgba(255,255,255,0.08)", marginBottom: "1.25rem" } }),
|
|
2866
2882
|
item.summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: "rgba(255,255,255,0.8)", lineHeight: 1.75, margin: 0 }, children: item.summary }) : /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8rem", color: "rgba(255,255,255,0.35)", fontStyle: "italic", margin: 0 }, children: "Summary not available for this article." }),
|
|
2867
|
-
item.url && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "1.25rem", paddingTop: "1rem", borderTop: "1px solid rgba(255,255,255,0.08)" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2883
|
+
item.url && isSafeUrl(item.url) && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "1.25rem", paddingTop: "1rem", borderTop: "1px solid rgba(255,255,255,0.08)" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2868
2884
|
"a",
|
|
2869
2885
|
{
|
|
2870
2886
|
href: item.url,
|
|
@@ -5103,6 +5119,7 @@ var Header = ({
|
|
|
5103
5119
|
onSettingsClick,
|
|
5104
5120
|
onReferClick,
|
|
5105
5121
|
portfolioSummary,
|
|
5122
|
+
totalPoints,
|
|
5106
5123
|
fundsPending = false,
|
|
5107
5124
|
transparentOnTop = false,
|
|
5108
5125
|
headerCta = "deposit",
|
|
@@ -5566,6 +5583,11 @@ var Header = ({
|
|
|
5566
5583
|
}
|
|
5567
5584
|
),
|
|
5568
5585
|
isUserMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { className: "user-menu-dropdown", children: [
|
|
5586
|
+
totalPoints != null && /* @__PURE__ */ jsxRuntime.jsxs(PointsHeader, { children: [
|
|
5587
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-label", children: "Total Points" }),
|
|
5588
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-value", children: totalPoints.toLocaleString() }),
|
|
5589
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pts-note", children: "Cumulative points earned. More soon." })
|
|
5590
|
+
] }),
|
|
5569
5591
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5570
5592
|
"button",
|
|
5571
5593
|
{
|
|
@@ -5623,7 +5645,7 @@ var Header = ({
|
|
|
5623
5645
|
}
|
|
5624
5646
|
)
|
|
5625
5647
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
5626
|
-
/* @__PURE__ */ jsxRuntime.jsx(Button2, { className: "signup", onClick: handleSignIn, children: "
|
|
5648
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button2, { className: "signup", onClick: handleSignIn, children: "Join Competition" }),
|
|
5627
5649
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5628
5650
|
MobileOnlyButton,
|
|
5629
5651
|
{
|
|
@@ -6151,6 +6173,33 @@ var DropdownMenu = styled10__default.default.div`
|
|
|
6151
6173
|
display: block;
|
|
6152
6174
|
}
|
|
6153
6175
|
`;
|
|
6176
|
+
var PointsHeader = styled10__default.default.div`
|
|
6177
|
+
padding: 0.7rem 1.25rem 0.8rem;
|
|
6178
|
+
margin-bottom: 0.35rem;
|
|
6179
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
6180
|
+
.pts-note {
|
|
6181
|
+
margin-top: 0.4rem;
|
|
6182
|
+
font-size: 0.6rem;
|
|
6183
|
+
line-height: 1.4;
|
|
6184
|
+
color: rgba(255, 255, 255, 0.4);
|
|
6185
|
+
}
|
|
6186
|
+
.pts-label {
|
|
6187
|
+
font-family: 'SF Mono', 'Fira Code', ui-monospace, monospace;
|
|
6188
|
+
font-size: 0.56rem;
|
|
6189
|
+
font-weight: 700;
|
|
6190
|
+
letter-spacing: 0.16em;
|
|
6191
|
+
text-transform: uppercase;
|
|
6192
|
+
color: rgba(255, 255, 255, 0.45);
|
|
6193
|
+
}
|
|
6194
|
+
.pts-value {
|
|
6195
|
+
margin-top: 0.2rem;
|
|
6196
|
+
font-size: 1.15rem;
|
|
6197
|
+
font-weight: 800;
|
|
6198
|
+
color: #E6C87E;
|
|
6199
|
+
font-variant-numeric: tabular-nums;
|
|
6200
|
+
line-height: 1;
|
|
6201
|
+
}
|
|
6202
|
+
`;
|
|
6154
6203
|
var MenuItem = styled10__default.default.div`
|
|
6155
6204
|
padding: 0.75rem 1.25rem;
|
|
6156
6205
|
cursor: pointer;
|
|
@@ -6607,6 +6656,16 @@ var PropertySubheader = React5__namespace.forwardRef(
|
|
|
6607
6656
|
}
|
|
6608
6657
|
);
|
|
6609
6658
|
PropertySubheader.displayName = "PropertySubheader";
|
|
6659
|
+
|
|
6660
|
+
// src/lib/isTrustedTransakOrigin.ts
|
|
6661
|
+
function isTrustedTransakOrigin(eventOrigin, widgetUrl) {
|
|
6662
|
+
if (!widgetUrl) return false;
|
|
6663
|
+
try {
|
|
6664
|
+
return eventOrigin === new URL(widgetUrl).origin;
|
|
6665
|
+
} catch {
|
|
6666
|
+
return false;
|
|
6667
|
+
}
|
|
6668
|
+
}
|
|
6610
6669
|
var DEFAULT_LOGO_SRC = Loaf_logo_Banner_default;
|
|
6611
6670
|
var DEFAULT_LOGO_ALT = "Loaf";
|
|
6612
6671
|
var OTP_INPUT_LENGTH = 6;
|
|
@@ -6747,7 +6806,7 @@ var LoginPopup = ({
|
|
|
6747
6806
|
React5.useEffect(() => {
|
|
6748
6807
|
if (!transakWidgetUrl) return;
|
|
6749
6808
|
const handleTransakMessage = (event) => {
|
|
6750
|
-
if (!event.origin
|
|
6809
|
+
if (!isTrustedTransakOrigin(event.origin, transakWidgetUrl)) {
|
|
6751
6810
|
return;
|
|
6752
6811
|
}
|
|
6753
6812
|
try {
|
|
@@ -9053,6 +9112,48 @@ var CodeLink = styled10__default.default.button`
|
|
|
9053
9112
|
text-underline-offset: 2px;
|
|
9054
9113
|
}
|
|
9055
9114
|
`;
|
|
9115
|
+
var HandleField = styled10__default.default.div`
|
|
9116
|
+
display: flex;
|
|
9117
|
+
align-items: center;
|
|
9118
|
+
gap: 0.1rem;
|
|
9119
|
+
width: 100%;
|
|
9120
|
+
margin-bottom: 0.4rem;
|
|
9121
|
+
padding: 0 0.9rem;
|
|
9122
|
+
background: rgba(255, 255, 255, 0.04);
|
|
9123
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
9124
|
+
border-radius: 10px;
|
|
9125
|
+
transition: border-color 0.15s ease;
|
|
9126
|
+
|
|
9127
|
+
&:focus-within {
|
|
9128
|
+
border-color: rgba(230, 200, 126, 0.6);
|
|
9129
|
+
}
|
|
9130
|
+
`;
|
|
9131
|
+
var HandleAt = styled10__default.default.span`
|
|
9132
|
+
color: rgba(255, 255, 255, 0.4);
|
|
9133
|
+
font-size: 1rem;
|
|
9134
|
+
font-weight: 600;
|
|
9135
|
+
`;
|
|
9136
|
+
var HandleInput = styled10__default.default.input`
|
|
9137
|
+
flex: 1;
|
|
9138
|
+
min-width: 0;
|
|
9139
|
+
padding: 0.85rem 0.4rem;
|
|
9140
|
+
border: none;
|
|
9141
|
+
background: transparent;
|
|
9142
|
+
color: #fff;
|
|
9143
|
+
font-size: 1rem;
|
|
9144
|
+
font-family: inherit;
|
|
9145
|
+
outline: none;
|
|
9146
|
+
|
|
9147
|
+
&::placeholder {
|
|
9148
|
+
color: rgba(255, 255, 255, 0.35);
|
|
9149
|
+
}
|
|
9150
|
+
`;
|
|
9151
|
+
var FieldError = styled10__default.default.div`
|
|
9152
|
+
width: 100%;
|
|
9153
|
+
margin-bottom: 0.6rem;
|
|
9154
|
+
font-size: 0.78rem;
|
|
9155
|
+
color: #ff6b6b;
|
|
9156
|
+
`;
|
|
9056
9157
|
function OnboardingGuide({
|
|
9057
9158
|
open,
|
|
9058
9159
|
fundsReady,
|
|
@@ -9060,8 +9161,21 @@ function OnboardingGuide({
|
|
|
9060
9161
|
onBrowseProperties,
|
|
9061
9162
|
onEnterCode,
|
|
9062
9163
|
onClose,
|
|
9164
|
+
onClaimHandle,
|
|
9063
9165
|
logoSrc = "/Loaf-logo-Banner.png"
|
|
9064
9166
|
}) {
|
|
9167
|
+
const [step, setStep] = React5.useState(onClaimHandle ? "handle" : "funds");
|
|
9168
|
+
const [handle, setHandle] = React5.useState("");
|
|
9169
|
+
const [claiming, setClaiming] = React5.useState(false);
|
|
9170
|
+
const [handleError, setHandleError] = React5.useState("");
|
|
9171
|
+
React5.useEffect(() => {
|
|
9172
|
+
if (open) {
|
|
9173
|
+
setStep(onClaimHandle ? "handle" : "funds");
|
|
9174
|
+
setHandle("");
|
|
9175
|
+
setClaiming(false);
|
|
9176
|
+
setHandleError("");
|
|
9177
|
+
}
|
|
9178
|
+
}, [open, onClaimHandle]);
|
|
9065
9179
|
React5.useEffect(() => {
|
|
9066
9180
|
if (!open) return;
|
|
9067
9181
|
const onKey = (e) => {
|
|
@@ -9071,6 +9185,58 @@ function OnboardingGuide({
|
|
|
9071
9185
|
return () => window.removeEventListener("keydown", onKey);
|
|
9072
9186
|
}, [open, onClose]);
|
|
9073
9187
|
if (!open) return null;
|
|
9188
|
+
const handleClaimContinue = async () => {
|
|
9189
|
+
const trimmed = handle.trim().replace(/^@+/, "");
|
|
9190
|
+
if (trimmed && onClaimHandle) {
|
|
9191
|
+
setClaiming(true);
|
|
9192
|
+
setHandleError("");
|
|
9193
|
+
try {
|
|
9194
|
+
await onClaimHandle(trimmed);
|
|
9195
|
+
} catch (err) {
|
|
9196
|
+
setHandleError(err instanceof Error ? err.message : "Couldn't claim that handle. Try another or skip.");
|
|
9197
|
+
setClaiming(false);
|
|
9198
|
+
return;
|
|
9199
|
+
}
|
|
9200
|
+
setClaiming(false);
|
|
9201
|
+
}
|
|
9202
|
+
setStep("funds");
|
|
9203
|
+
};
|
|
9204
|
+
if (step === "handle") {
|
|
9205
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Overlay3, { onClick: onClose, role: "dialog", "aria-modal": "true", "aria-label": "Claim your handle", children: /* @__PURE__ */ jsxRuntime.jsxs(Card2, { onClick: (e) => e.stopPropagation(), children: [
|
|
9206
|
+
/* @__PURE__ */ jsxRuntime.jsx(CloseButton2, { onClick: onClose, "aria-label": "Skip", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) }) }),
|
|
9207
|
+
/* @__PURE__ */ jsxRuntime.jsxs(LogoRow, { children: [
|
|
9208
|
+
/* @__PURE__ */ jsxRuntime.jsx(LogoImage2, { src: logoSrc, alt: "Loaf" }),
|
|
9209
|
+
/* @__PURE__ */ jsxRuntime.jsx(LogoBeta2, { children: "Private Beta" })
|
|
9210
|
+
] }),
|
|
9211
|
+
/* @__PURE__ */ jsxRuntime.jsx(Title2, { children: "Claim your handle" }),
|
|
9212
|
+
/* @__PURE__ */ jsxRuntime.jsx(Subtitle2, { children: "Pick a username for your Loaf profile. It's optional \u2014 you can set or change it later." }),
|
|
9213
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HandleField, { children: [
|
|
9214
|
+
/* @__PURE__ */ jsxRuntime.jsx(HandleAt, { children: "@" }),
|
|
9215
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9216
|
+
HandleInput,
|
|
9217
|
+
{
|
|
9218
|
+
type: "text",
|
|
9219
|
+
autoComplete: "off",
|
|
9220
|
+
autoCapitalize: "none",
|
|
9221
|
+
spellCheck: false,
|
|
9222
|
+
placeholder: "username (optional)",
|
|
9223
|
+
value: handle,
|
|
9224
|
+
onChange: (e) => {
|
|
9225
|
+
setHandle(e.target.value.replace(/[^a-zA-Z0-9_]/g, ""));
|
|
9226
|
+
setHandleError("");
|
|
9227
|
+
},
|
|
9228
|
+
onKeyDown: (e) => {
|
|
9229
|
+
if (e.key === "Enter" && !claiming) void handleClaimContinue();
|
|
9230
|
+
},
|
|
9231
|
+
autoFocus: true
|
|
9232
|
+
}
|
|
9233
|
+
)
|
|
9234
|
+
] }),
|
|
9235
|
+
handleError && /* @__PURE__ */ jsxRuntime.jsx(FieldError, { children: handleError }),
|
|
9236
|
+
/* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { onClick: () => void handleClaimContinue(), disabled: claiming, children: claiming ? "Saving\u2026" : "Continue" }),
|
|
9237
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkipButton, { onClick: () => setStep("funds"), disabled: claiming, children: "Skip for now" })
|
|
9238
|
+
] }) });
|
|
9239
|
+
}
|
|
9074
9240
|
return /* @__PURE__ */ jsxRuntime.jsx(Overlay3, { onClick: onClose, role: "dialog", "aria-modal": "true", "aria-label": "Welcome to Loaf", children: /* @__PURE__ */ jsxRuntime.jsxs(Card2, { onClick: (e) => e.stopPropagation(), children: [
|
|
9075
9241
|
/* @__PURE__ */ jsxRuntime.jsx(CloseButton2, { onClick: onClose, "aria-label": "Skip", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 6l12 12M18 6L6 18" }) }) }),
|
|
9076
9242
|
/* @__PURE__ */ jsxRuntime.jsxs(LogoRow, { children: [
|
|
@@ -12134,6 +12300,11 @@ var DocIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height
|
|
|
12134
12300
|
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
|
|
12135
12301
|
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "10 9 9 9 8 9" })
|
|
12136
12302
|
] });
|
|
12303
|
+
var DownloadIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
12304
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
12305
|
+
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "7 10 12 15 17 10" }),
|
|
12306
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
|
|
12307
|
+
] });
|
|
12137
12308
|
var LIVE_TITLE_PATTERNS = [/term\s*sheet/i, /memo/i];
|
|
12138
12309
|
var COMING_SOON_TITLES = [
|
|
12139
12310
|
"Valuation Report",
|
|
@@ -12148,11 +12319,30 @@ var COMING_SOON_TITLES = [
|
|
|
12148
12319
|
];
|
|
12149
12320
|
function PropertyDocuments({ documentsData, highlightDocument, onClearHighlight }) {
|
|
12150
12321
|
const highlightRef = React5.useRef(null);
|
|
12151
|
-
React5.
|
|
12322
|
+
const [previewUrl, setPreviewUrl] = React5.useState(null);
|
|
12323
|
+
const [previewTitle, setPreviewTitle] = React5.useState(null);
|
|
12324
|
+
const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : [];
|
|
12325
|
+
const liveDocs = backendDocuments.filter(
|
|
12326
|
+
(d) => Boolean(d.documentUrl) && isSafeUrl(d.documentUrl) && LIVE_TITLE_PATTERNS.some((rx) => rx.test(d.title))
|
|
12327
|
+
);
|
|
12328
|
+
const comingSoonDocs = COMING_SOON_TITLES.filter(
|
|
12329
|
+
(title) => !liveDocs.some((d) => d.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(d.title.toLowerCase()))
|
|
12330
|
+
).map((title) => ({ title, documentUrl: "" }));
|
|
12331
|
+
const documents = [...liveDocs, ...comingSoonDocs];
|
|
12332
|
+
const activeUrl = previewUrl ?? (liveDocs[0]?.documentUrl || null);
|
|
12333
|
+
const activeTitle = previewUrl ? previewTitle : liveDocs[0]?.title || null;
|
|
12334
|
+
const selectPreview = (doc) => {
|
|
12335
|
+
setPreviewUrl(doc.documentUrl);
|
|
12336
|
+
setPreviewTitle(doc.title);
|
|
12337
|
+
};
|
|
12152
12338
|
React5.useEffect(() => {
|
|
12153
12339
|
if (highlightDocument && highlightRef.current) {
|
|
12154
12340
|
highlightRef.current.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
12155
12341
|
}
|
|
12342
|
+
if (highlightDocument) {
|
|
12343
|
+
const hit = liveDocs.find((d) => d.title.toLowerCase().includes(highlightDocument.toLowerCase()));
|
|
12344
|
+
if (hit) selectPreview(hit);
|
|
12345
|
+
}
|
|
12156
12346
|
}, [highlightDocument]);
|
|
12157
12347
|
React5.useEffect(() => {
|
|
12158
12348
|
if (!highlightDocument || !onClearHighlight) return;
|
|
@@ -12164,36 +12354,58 @@ function PropertyDocuments({ documentsData, highlightDocument, onClearHighlight
|
|
|
12164
12354
|
document.addEventListener("click", handler, true);
|
|
12165
12355
|
return () => document.removeEventListener("click", handler, true);
|
|
12166
12356
|
}, [highlightDocument, onClearHighlight]);
|
|
12167
|
-
const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : [];
|
|
12168
|
-
const liveDocs = backendDocuments.filter(
|
|
12169
|
-
(d) => Boolean(d.documentUrl) && LIVE_TITLE_PATTERNS.some((rx) => rx.test(d.title))
|
|
12170
|
-
);
|
|
12171
|
-
const comingSoonDocs = COMING_SOON_TITLES.filter(
|
|
12172
|
-
(title) => !liveDocs.some((d) => d.title.toLowerCase().includes(title.toLowerCase()) || title.toLowerCase().includes(d.title.toLowerCase()))
|
|
12173
|
-
).map((title) => ({ title, documentUrl: "" }));
|
|
12174
|
-
const documents = [...liveDocs, ...comingSoonDocs];
|
|
12175
12357
|
return /* @__PURE__ */ jsxRuntime.jsxs(Section2, { children: [
|
|
12176
12358
|
/* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { children: "Investment Documents" }),
|
|
12177
|
-
/* @__PURE__ */ jsxRuntime.
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12359
|
+
/* @__PURE__ */ jsxRuntime.jsxs(SplitLayout, { children: [
|
|
12360
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocList, { children: documents.map(({ documentUrl, title }) => {
|
|
12361
|
+
const isAvailable = Boolean(documentUrl);
|
|
12362
|
+
const isHighlighted = highlightDocument != null && title.toLowerCase().includes(highlightDocument.toLowerCase());
|
|
12363
|
+
const isActive = isAvailable && documentUrl === activeUrl;
|
|
12364
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
12365
|
+
DocItem,
|
|
12366
|
+
{
|
|
12367
|
+
ref: isHighlighted ? highlightRef : void 0,
|
|
12368
|
+
$highlighted: isHighlighted,
|
|
12369
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
12370
|
+
DocRow,
|
|
12371
|
+
{
|
|
12372
|
+
$available: isAvailable,
|
|
12373
|
+
$active: isActive,
|
|
12374
|
+
onMouseEnter: isAvailable ? () => selectPreview({ documentUrl, title }) : void 0,
|
|
12375
|
+
onClick: isAvailable ? () => selectPreview({ documentUrl, title }) : void 0,
|
|
12376
|
+
children: [
|
|
12377
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DocName, { $available: isAvailable, children: [
|
|
12378
|
+
/* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
|
|
12379
|
+
title
|
|
12380
|
+
] }),
|
|
12381
|
+
isAvailable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12382
|
+
DownloadBtn,
|
|
12383
|
+
{
|
|
12384
|
+
href: documentUrl,
|
|
12385
|
+
target: "_blank",
|
|
12386
|
+
rel: "noopener noreferrer",
|
|
12387
|
+
"aria-label": `Open ${title}`,
|
|
12388
|
+
title: "Open document",
|
|
12389
|
+
onClick: (e) => e.stopPropagation(),
|
|
12390
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DownloadIcon, {})
|
|
12391
|
+
}
|
|
12392
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
|
|
12393
|
+
]
|
|
12394
|
+
}
|
|
12395
|
+
)
|
|
12396
|
+
},
|
|
12397
|
+
`${title}-${documentUrl || "pending"}`
|
|
12398
|
+
);
|
|
12399
|
+
}) }),
|
|
12400
|
+
/* @__PURE__ */ jsxRuntime.jsx(PreviewPane, { children: activeUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
12401
|
+
PreviewFrame,
|
|
12182
12402
|
{
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
children: isAvailable ? /* @__PURE__ */ jsxRuntime.jsxs(DocLink, { href: documentUrl, target: "_blank", rel: "noopener noreferrer", children: [
|
|
12186
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
|
|
12187
|
-
title
|
|
12188
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(DocItemDisabled, { children: [
|
|
12189
|
-
/* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
|
|
12190
|
-
title,
|
|
12191
|
-
/* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
|
|
12192
|
-
] })
|
|
12403
|
+
src: `${activeUrl}#toolbar=0&navpanes=0&view=FitH`,
|
|
12404
|
+
title: activeTitle ?? "Document preview"
|
|
12193
12405
|
},
|
|
12194
|
-
|
|
12195
|
-
)
|
|
12196
|
-
|
|
12406
|
+
activeUrl
|
|
12407
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(PreviewEmpty, { children: "Hover a document to preview it here" }) })
|
|
12408
|
+
] })
|
|
12197
12409
|
] });
|
|
12198
12410
|
}
|
|
12199
12411
|
var Section2 = styled10__default.default.section`
|
|
@@ -12213,45 +12425,103 @@ var SectionHeading = styled10__default.default.h2`
|
|
|
12213
12425
|
align-items: center;
|
|
12214
12426
|
gap: 0.5rem;
|
|
12215
12427
|
`;
|
|
12428
|
+
var SplitLayout = styled10__default.default.div`
|
|
12429
|
+
display: flex;
|
|
12430
|
+
gap: 1.25rem;
|
|
12431
|
+
align-items: stretch;
|
|
12432
|
+
|
|
12433
|
+
@media (max-width: 768px) {
|
|
12434
|
+
flex-direction: column;
|
|
12435
|
+
}
|
|
12436
|
+
`;
|
|
12216
12437
|
var DocList = styled10__default.default.ul`
|
|
12217
12438
|
list-style: none;
|
|
12218
12439
|
padding: 0;
|
|
12219
12440
|
margin: 0;
|
|
12441
|
+
flex: 1 1 50%;
|
|
12442
|
+
min-width: 0;
|
|
12220
12443
|
`;
|
|
12221
12444
|
var DocItem = styled10__default.default.li`
|
|
12222
|
-
padding: 0.
|
|
12445
|
+
padding: 0.35rem 0;
|
|
12223
12446
|
border-bottom: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
|
|
12224
12447
|
border-radius: ${(p) => p.$highlighted ? "6px" : "0"};
|
|
12225
12448
|
background: ${(p) => p.$highlighted ? "rgba(212, 175, 55, 0.08)" : "transparent"};
|
|
12226
|
-
${(p) => p.$highlighted ? "padding: 0.75rem;" : ""}
|
|
12227
12449
|
transition: background 0.3s;
|
|
12228
12450
|
|
|
12229
12451
|
&:last-child {
|
|
12230
12452
|
border-bottom: none;
|
|
12231
12453
|
}
|
|
12232
12454
|
`;
|
|
12233
|
-
var
|
|
12455
|
+
var DocRow = styled10__default.default.div`
|
|
12234
12456
|
display: flex;
|
|
12235
12457
|
align-items: center;
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12458
|
+
gap: 0.5rem;
|
|
12459
|
+
padding: 0.4rem 0.5rem;
|
|
12460
|
+
border-radius: 6px;
|
|
12461
|
+
cursor: ${(p) => p.$available ? "pointer" : "not-allowed"};
|
|
12462
|
+
background: ${(p) => p.$active ? "rgba(230, 200, 126, 0.10)" : "transparent"};
|
|
12463
|
+
transition: background 0.2s, color 0.2s;
|
|
12239
12464
|
|
|
12240
|
-
&:hover {
|
|
12241
|
-
color: var(--color-accent);
|
|
12242
|
-
}
|
|
12465
|
+
${(p) => p.$available && !p.$active ? "&:hover { background: rgba(230, 200, 126, 0.06); }" : ""}
|
|
12243
12466
|
`;
|
|
12244
|
-
var
|
|
12467
|
+
var DocName = styled10__default.default.span`
|
|
12245
12468
|
display: flex;
|
|
12246
12469
|
align-items: center;
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12470
|
+
flex: 1;
|
|
12471
|
+
min-width: 0;
|
|
12472
|
+
color: ${(p) => p.$available ? "var(--color-text)" : "var(--color-text-secondary)"};
|
|
12473
|
+
opacity: ${(p) => p.$available ? 1 : 0.6};
|
|
12250
12474
|
`;
|
|
12251
12475
|
var DocIconWrapper = styled10__default.default.span`
|
|
12252
12476
|
margin-right: 0.75rem;
|
|
12253
12477
|
flex-shrink: 0;
|
|
12254
12478
|
color: var(--color-text-secondary);
|
|
12479
|
+
display: inline-flex;
|
|
12480
|
+
`;
|
|
12481
|
+
var DownloadBtn = styled10__default.default.a`
|
|
12482
|
+
flex-shrink: 0;
|
|
12483
|
+
display: inline-flex;
|
|
12484
|
+
align-items: center;
|
|
12485
|
+
justify-content: center;
|
|
12486
|
+
width: 30px;
|
|
12487
|
+
height: 30px;
|
|
12488
|
+
border-radius: 6px;
|
|
12489
|
+
color: var(--color-text-secondary);
|
|
12490
|
+
transition: color 0.2s, background 0.2s;
|
|
12491
|
+
|
|
12492
|
+
&:hover {
|
|
12493
|
+
color: var(--color-accent);
|
|
12494
|
+
background: rgba(230, 200, 126, 0.1);
|
|
12495
|
+
}
|
|
12496
|
+
`;
|
|
12497
|
+
var PreviewPane = styled10__default.default.div`
|
|
12498
|
+
flex: 1 1 50%;
|
|
12499
|
+
min-width: 0;
|
|
12500
|
+
min-height: 360px;
|
|
12501
|
+
display: flex;
|
|
12502
|
+
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
|
|
12503
|
+
border-radius: 10px;
|
|
12504
|
+
overflow: hidden;
|
|
12505
|
+
background: rgba(0, 0, 0, 0.25);
|
|
12506
|
+
|
|
12507
|
+
/* No hover on touch devices — fall back to the list + download icon. */
|
|
12508
|
+
@media (max-width: 768px) {
|
|
12509
|
+
display: none;
|
|
12510
|
+
}
|
|
12511
|
+
`;
|
|
12512
|
+
var PreviewFrame = styled10__default.default.iframe`
|
|
12513
|
+
width: 100%;
|
|
12514
|
+
height: 100%;
|
|
12515
|
+
min-height: 360px;
|
|
12516
|
+
border: 0;
|
|
12517
|
+
background: #fff;
|
|
12518
|
+
`;
|
|
12519
|
+
var PreviewEmpty = styled10__default.default.div`
|
|
12520
|
+
margin: auto;
|
|
12521
|
+
padding: 1rem;
|
|
12522
|
+
text-align: center;
|
|
12523
|
+
color: var(--color-text-secondary);
|
|
12524
|
+
font-size: 0.85rem;
|
|
12255
12525
|
`;
|
|
12256
12526
|
var ComingSoonBadge = styled10__default.default.span`
|
|
12257
12527
|
margin-left: auto;
|
|
@@ -12263,6 +12533,7 @@ var ComingSoonBadge = styled10__default.default.span`
|
|
|
12263
12533
|
font-weight: 500;
|
|
12264
12534
|
text-transform: uppercase;
|
|
12265
12535
|
letter-spacing: 0.05em;
|
|
12536
|
+
flex-shrink: 0;
|
|
12266
12537
|
`;
|
|
12267
12538
|
var formatIsoDate = (value) => {
|
|
12268
12539
|
const parsed = new Date(value);
|
|
@@ -19900,7 +20171,7 @@ var OpenMailButton = styled10__default.default.a`
|
|
|
19900
20171
|
`;
|
|
19901
20172
|
var ContactPopup = ({ onClose }) => {
|
|
19902
20173
|
const [copied, setCopied] = React5.useState(false);
|
|
19903
|
-
const email = "
|
|
20174
|
+
const email = "admin@loafmarkets.com";
|
|
19904
20175
|
const handleCopy = async () => {
|
|
19905
20176
|
try {
|
|
19906
20177
|
await navigator.clipboard.writeText(email);
|
|
@@ -20127,7 +20398,17 @@ var SiteFooter = () => {
|
|
|
20127
20398
|
/* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/trade", children: "Trade" }) }),
|
|
20128
20399
|
/* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/offerings", children: "Initial Offerings" }) }),
|
|
20129
20400
|
/* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(FooterLink, { href: "/map", children: "Property Map" }) }),
|
|
20130
|
-
/* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20401
|
+
/* @__PURE__ */ jsxRuntime.jsx(FooterLinkItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
20402
|
+
FooterLink,
|
|
20403
|
+
{
|
|
20404
|
+
href: "/loaf-liquidity",
|
|
20405
|
+
onClick: (e) => {
|
|
20406
|
+
e.preventDefault();
|
|
20407
|
+
if (typeof window !== "undefined") window.dispatchEvent(new CustomEvent("loaf:open-liquidity-popup"));
|
|
20408
|
+
},
|
|
20409
|
+
children: "Loaf Liquidity"
|
|
20410
|
+
}
|
|
20411
|
+
) })
|
|
20131
20412
|
] })
|
|
20132
20413
|
] }),
|
|
20133
20414
|
/* @__PURE__ */ jsxRuntime.jsxs(FooterColumn, { children: [
|
|
@@ -20163,7 +20444,7 @@ var SiteFooter = () => {
|
|
|
20163
20444
|
/* @__PURE__ */ jsxRuntime.jsx(LegalLink, { href: "/cookies", children: "Cookie Policy" })
|
|
20164
20445
|
] })
|
|
20165
20446
|
] }),
|
|
20166
|
-
/* @__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
|
|
20447
|
+
/* @__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." }) })
|
|
20167
20448
|
] }) }),
|
|
20168
20449
|
showContactPopup && /* @__PURE__ */ jsxRuntime.jsx(ContactPopup, { onClose: () => setShowContactPopup(false) })
|
|
20169
20450
|
] });
|