@loafmarkets/ui 0.1.350 → 0.1.352

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
@@ -778,8 +778,17 @@ type PropertyOverviewProps = {
778
778
  time: number;
779
779
  close: number;
780
780
  }[] | null;
781
- };
782
- declare function PropertyOverview({ propertyName: _propertyName, location, midPrice, onTradeClick, onDocumentsClick, onPhotosClick, description: descriptionProp, tradeButtonLabel, images, galleryCategories, videoUrl, tokenName, landSizeSqm: landProp, buildingSizeSqm: buildingProp, features: featuresProp, propertyInfo: _propertyInfoProp, overviewData, bedrooms, bathrooms, carSpaces, propertyTypeLabel, tokensIssued: tokensIssuedProp, isLoading, ticker, contractAddress, chain, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
781
+ /** Beta mode: hide sections that are hardcoded with no backend source (offers, narratives, mock holders, synthetic dividend history, tokenholder security). */
782
+ beta?: boolean;
783
+ /** Live market hours from the trade/token API. When present, Trading Hours renders from it; when absent it is gated by `beta`. */
784
+ marketHours?: {
785
+ marketOpenTime: string;
786
+ marketCloseTime: string;
787
+ marketTimezone: string;
788
+ marketClosedDays: readonly string[];
789
+ } | null;
790
+ };
791
+ declare function PropertyOverview({ propertyName: _propertyName, location, midPrice, onTradeClick, onDocumentsClick, onPhotosClick, description: descriptionProp, tradeButtonLabel, images, galleryCategories, videoUrl, tokenName, landSizeSqm: landProp, buildingSizeSqm: buildingProp, features: featuresProp, propertyInfo: _propertyInfoProp, overviewData, bedrooms, bathrooms, carSpaces, propertyTypeLabel, tokensIssued: tokensIssuedProp, isLoading, ticker, contractAddress, chain, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, beta, marketHours, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
783
792
 
784
793
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
785
794
  type PropertyOffer = {
@@ -984,8 +993,9 @@ type ToastContextValue = {
984
993
  update: (id: string, patch: Partial<Omit<ToastData, 'id'>>) => void;
985
994
  dismiss: (id: string) => void;
986
995
  };
987
- declare function ToastProvider({ children }: {
996
+ declare function ToastProvider({ children, maxVisible }: {
988
997
  children: React__default.ReactNode;
998
+ maxVisible?: number;
989
999
  }): react_jsx_runtime.JSX.Element;
990
1000
  declare function useToast(): ToastContextValue;
991
1001
 
package/dist/index.d.ts CHANGED
@@ -778,8 +778,17 @@ type PropertyOverviewProps = {
778
778
  time: number;
779
779
  close: number;
780
780
  }[] | null;
781
- };
782
- declare function PropertyOverview({ propertyName: _propertyName, location, midPrice, onTradeClick, onDocumentsClick, onPhotosClick, description: descriptionProp, tradeButtonLabel, images, galleryCategories, videoUrl, tokenName, landSizeSqm: landProp, buildingSizeSqm: buildingProp, features: featuresProp, propertyInfo: _propertyInfoProp, overviewData, bedrooms, bathrooms, carSpaces, propertyTypeLabel, tokensIssued: tokensIssuedProp, isLoading, ticker, contractAddress, chain, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
781
+ /** Beta mode: hide sections that are hardcoded with no backend source (offers, narratives, mock holders, synthetic dividend history, tokenholder security). */
782
+ beta?: boolean;
783
+ /** Live market hours from the trade/token API. When present, Trading Hours renders from it; when absent it is gated by `beta`. */
784
+ marketHours?: {
785
+ marketOpenTime: string;
786
+ marketCloseTime: string;
787
+ marketTimezone: string;
788
+ marketClosedDays: readonly string[];
789
+ } | null;
790
+ };
791
+ declare function PropertyOverview({ propertyName: _propertyName, location, midPrice, onTradeClick, onDocumentsClick, onPhotosClick, description: descriptionProp, tradeButtonLabel, images, galleryCategories, videoUrl, tokenName, landSizeSqm: landProp, buildingSizeSqm: buildingProp, features: featuresProp, propertyInfo: _propertyInfoProp, overviewData, bedrooms, bathrooms, carSpaces, propertyTypeLabel, tokensIssued: tokensIssuedProp, isLoading, ticker, contractAddress, chain, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, beta, marketHours, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
783
792
 
784
793
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
785
794
  type PropertyOffer = {
@@ -984,8 +993,9 @@ type ToastContextValue = {
984
993
  update: (id: string, patch: Partial<Omit<ToastData, 'id'>>) => void;
985
994
  dismiss: (id: string) => void;
986
995
  };
987
- declare function ToastProvider({ children }: {
996
+ declare function ToastProvider({ children, maxVisible }: {
988
997
  children: React__default.ReactNode;
998
+ maxVisible?: number;
989
999
  }): react_jsx_runtime.JSX.Element;
990
1000
  declare function useToast(): ToastContextValue;
991
1001
 
package/dist/index.js CHANGED
@@ -6704,7 +6704,11 @@ var LoginPopup = ({
6704
6704
  try {
6705
6705
  await onVerifyEmailCode({ code, email });
6706
6706
  if (isSignUp) {
6707
- setView(onSubmitReferralCode ? "referral" : "funding");
6707
+ if (onSubmitReferralCode) {
6708
+ setView("referral");
6709
+ } else {
6710
+ onClose();
6711
+ }
6708
6712
  setLoading(false);
6709
6713
  return;
6710
6714
  }
@@ -6917,7 +6921,8 @@ var LoginPopup = ({
6917
6921
  loading ? /* @__PURE__ */ jsxRuntime.jsxs(AccountCreationLoader, { children: [
6918
6922
  /* @__PURE__ */ jsxRuntime.jsx(SpinnerRing, {}),
6919
6923
  /* @__PURE__ */ jsxRuntime.jsx(AccountCreationText, { children: isSignUp ? "Preparing your account\u2026" : "Signing you in\u2026" }),
6920
- /* @__PURE__ */ jsxRuntime.jsx(AccountCreationSubtext, { children: "This may take a few seconds" })
6924
+ /* @__PURE__ */ jsxRuntime.jsx(AccountCreationSubtext, { children: "This may take a few seconds" }),
6925
+ /* @__PURE__ */ jsxRuntime.jsx(PreparingFacts, {})
6921
6926
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6922
6927
  /* @__PURE__ */ jsxRuntime.jsxs(BackButton, { onClick: () => setView("email"), children: [
6923
6928
  /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" }) }),
@@ -7120,7 +7125,7 @@ var LoginPopup = ({
7120
7125
  setReferralLoading(true);
7121
7126
  try {
7122
7127
  await onSubmitReferralCode?.(trimmed);
7123
- setView("funding");
7128
+ onClose();
7124
7129
  } catch (err) {
7125
7130
  setReferralError(err instanceof Error ? err.message : "Invalid referral code. Please try again.");
7126
7131
  } finally {
@@ -7147,7 +7152,7 @@ var LoginPopup = ({
7147
7152
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75" })
7148
7153
  ] }) }),
7149
7154
  /* @__PURE__ */ jsxRuntime.jsx(OnboardingHeading, { children: "Do you have a referral code?" }),
7150
- /* @__PURE__ */ jsxRuntime.jsx(OnboardingSubtext, { style: { marginBottom: "1.5rem" }, children: "Enter your code to unlock full access, or skip to continue." }),
7155
+ /* @__PURE__ */ jsxRuntime.jsx(OnboardingSubtext, { style: { marginBottom: "1.5rem" }, children: "Enter your code to unlock $100k in testnet USD, or skip to continue." }),
7151
7156
  /* @__PURE__ */ jsxRuntime.jsxs(EmailFormContainer, { style: { width: "100%", marginBottom: 0 }, children: [
7152
7157
  /* @__PURE__ */ jsxRuntime.jsx(
7153
7158
  EmailInput,
@@ -7180,7 +7185,7 @@ var LoginPopup = ({
7180
7185
  OnboardingSkipButton,
7181
7186
  {
7182
7187
  type: "button",
7183
- onClick: () => setView("funding"),
7188
+ onClick: onClose,
7184
7189
  style: { marginTop: "0.75rem" },
7185
7190
  children: "Skip for now"
7186
7191
  }
@@ -8022,6 +8027,59 @@ var SpinnerRing = styled9__default.default.div`
8022
8027
  to { transform: rotate(360deg); }
8023
8028
  }
8024
8029
  `;
8030
+ var PREPARING_FACTS = [
8031
+ "Property is the world's largest asset class \u2014 worth over US$300 trillion.",
8032
+ "Loaf settles trades in about 1 second. Traditional property takes ~90 days.",
8033
+ "Our matching engine processes orders in 30 microseconds.",
8034
+ "Every token is backed 1:1 by land-title-registered property.",
8035
+ "Own a slice of premium real estate \u2014 no mortgage, no paperwork.",
8036
+ "Buy and sell property as easily as a stock, on a live orderbook.",
8037
+ "Earn rental yield on the exact fraction of property you own.",
8038
+ "Title-backed by the NSW Land Registry \u2014 real ownership, on-chain.",
8039
+ "Loaf ran the world's first property IPO."
8040
+ ];
8041
+ var FactCard = styled9__default.default.div`
8042
+ margin-top: 1.5rem;
8043
+ max-width: 340px;
8044
+ padding: 0.85rem 1.1rem;
8045
+ border: 1px solid rgba(230, 198, 86, 0.18);
8046
+ border-radius: 12px;
8047
+ background: rgba(230, 198, 86, 0.05);
8048
+ text-align: center;
8049
+ `;
8050
+ var FactLabel = styled9__default.default.div`
8051
+ font-size: 0.6rem;
8052
+ letter-spacing: 0.12em;
8053
+ text-transform: uppercase;
8054
+ font-weight: 700;
8055
+ color: var(--color-accent, #e6c656);
8056
+ margin-bottom: 0.4rem;
8057
+ `;
8058
+ var FactText = styled9__default.default.p`
8059
+ margin: 0;
8060
+ font-size: 0.85rem;
8061
+ line-height: 1.5;
8062
+ color: var(--color-text, #eaecef);
8063
+ animation: factFade 0.5s ease;
8064
+
8065
+ @keyframes factFade {
8066
+ from { opacity: 0; transform: translateY(4px); }
8067
+ to { opacity: 1; transform: translateY(0); }
8068
+ }
8069
+ `;
8070
+ var PreparingFacts = () => {
8071
+ const [index, setIndex] = React5.useState(() => Math.floor(Math.random() * PREPARING_FACTS.length));
8072
+ React5.useEffect(() => {
8073
+ const id = setInterval(() => {
8074
+ setIndex((i) => (i + 1) % PREPARING_FACTS.length);
8075
+ }, 4e3);
8076
+ return () => clearInterval(id);
8077
+ }, []);
8078
+ return /* @__PURE__ */ jsxRuntime.jsxs(FactCard, { children: [
8079
+ /* @__PURE__ */ jsxRuntime.jsx(FactLabel, { children: "Did you know?" }),
8080
+ /* @__PURE__ */ jsxRuntime.jsx(FactText, { children: PREPARING_FACTS[index] }, index)
8081
+ ] });
8082
+ };
8025
8083
  LoginPopup.displayName = "LoginPopup";
8026
8084
  var PropertyCompareBar = React5__namespace.forwardRef(
8027
8085
  ({
@@ -8965,7 +9023,9 @@ function PropertyOverview({
8965
9023
  volume24h,
8966
9024
  openOrdersValue,
8967
9025
  holderCount,
8968
- priceHistory: priceHistoryProp
9026
+ priceHistory: priceHistoryProp,
9027
+ beta = false,
9028
+ marketHours
8969
9029
  }) {
8970
9030
  const [isDescExpanded, setDescExpanded] = React5.useState(false);
8971
9031
  const [showDividendHistory, setShowDividendHistory] = React5.useState(false);
@@ -9027,20 +9087,21 @@ function PropertyOverview({
9027
9087
  { label: "Open Orders", value: isLoading && openOrdersValue == null ? loadingSkeleton : openOrdersValue != null && openOrdersValue > 0 ? fmtDollar(openOrdersValue) : "\u2014" },
9028
9088
  { label: "Holders", value: isLoading && holderCount == null ? loadingSkeleton : holderCount != null ? holderCount.toLocaleString() : "\u2014" }
9029
9089
  ];
9030
- const annualDividend = resolvedValuation ? resolvedValuation * 0.02 : null;
9031
- const monthlyDivPerShare = annualDividend && resolvedTokensIssued ? annualDividend / 12 / resolvedTokensIssued : null;
9090
+ const growthPct = overviewData?.growth5Yr;
9032
9091
  const propertyStats = [
9033
9092
  { label: "Property Value", value: isLoading && tokenMarketCap == null ? loadingSkeleton : tokenMarketCap ? fmtDollar(tokenMarketCap) : "\u2014" },
9034
- { label: "Offers", value: "3" },
9035
- { label: "Growth (5yr)", value: "+90%" },
9036
- { label: "Last Dividend", value: isLoading && monthlyDivPerShare == null ? loadingSkeleton : monthlyDivPerShare != null ? `$${monthlyDivPerShare.toFixed(2)}` : "\u2014" },
9037
- { label: "Next Dividend", value: (() => {
9038
- const now = /* @__PURE__ */ new Date();
9039
- const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);
9040
- while (lastDay.getDay() === 0 || lastDay.getDay() === 6) lastDay.setDate(lastDay.getDate() - 1);
9041
- return lastDay.toLocaleDateString("en-AU", { day: "2-digit", month: "short", year: "numeric" });
9042
- })() }
9093
+ ...beta ? [] : [{ label: "Offers", value: "3" }],
9094
+ { label: "Growth (5yr)", value: growthPct != null ? `${growthPct > 0 ? "+" : ""}${growthPct}%` : "\u2014" },
9095
+ { label: "Last Dividend", value: overviewData?.lastDividend != null ? `$${overviewData.lastDividend.toFixed(2)}` : "\u2014" },
9096
+ { label: "Next Dividend", value: overviewData?.nextDividendDate != null ? new Date(overviewData.nextDividendDate * 1e3).toLocaleDateString("en-AU", { day: "2-digit", month: "short", year: "numeric" }) : "\u2014" }
9043
9097
  ];
9098
+ const ownershipLabel = overviewData?.ownership ? overviewData.ownership.charAt(0).toUpperCase() + overviewData.ownership.slice(1).toLowerCase() : null;
9099
+ const propertyHistory = overviewData?.propertyHistory ?? [];
9100
+ const closedDays = marketHours?.marketClosedDays.filter((d) => d.toLowerCase() !== "never") ?? [];
9101
+ const tradingHoursValue = marketHours ? marketHours.marketOpenTime === marketHours.marketCloseTime ? "24 Hours" : `${marketHours.marketOpenTime} \u2013 ${marketHours.marketCloseTime}` : "";
9102
+ const tradingDaysValue = marketHours ? closedDays.length ? `Closed ${closedDays.join(", ")}` : "Every day" : "";
9103
+ const tradingHoursNote = marketHours ? `All times shown in ${marketHours.marketTimezone}.` : "";
9104
+ const showTradingHours = marketHours != null;
9044
9105
  return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { children: [
9045
9106
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
9046
9107
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "About" }),
@@ -9092,7 +9153,7 @@ function PropertyOverview({
9092
9153
  /* @__PURE__ */ jsxRuntime.jsx(StatsRowLabel, { children: "Token Performance" }),
9093
9154
  /* @__PURE__ */ jsxRuntime.jsx(StatsHRow, { children: tokenStats.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(StatsHCell, { children: [
9094
9155
  /* @__PURE__ */ jsxRuntime.jsx(StatsHCellLabel, { children: item.label }),
9095
- item.label === "Holders" && holderCount != null ? /* @__PURE__ */ jsxRuntime.jsx(StatValueClickable, { onClick: () => setShowHolders(true), children: item.value }) : /* @__PURE__ */ jsxRuntime.jsx(StatsHCellValue, { $gold: !!item.gold, children: item.value })
9156
+ item.label === "Holders" && holderCount != null && !beta ? /* @__PURE__ */ jsxRuntime.jsx(StatValueClickable, { onClick: () => setShowHolders(true), children: item.value }) : /* @__PURE__ */ jsxRuntime.jsx(StatsHCellValue, { $gold: !!item.gold, children: item.value })
9096
9157
  ] }, item.label)) })
9097
9158
  ] }),
9098
9159
  /* @__PURE__ */ jsxRuntime.jsxs(StatsRowSection, { children: [
@@ -9101,7 +9162,7 @@ function PropertyOverview({
9101
9162
  /* @__PURE__ */ jsxRuntime.jsx(StatsHCellLabel, { children: item.label }),
9102
9163
  /* @__PURE__ */ jsxRuntime.jsx(StatsHCellValue, { children: item.value })
9103
9164
  ] }, item.label)) }),
9104
- /* @__PURE__ */ jsxRuntime.jsx(DividendHistoryBtn, { onClick: () => setShowDividendHistory(true), children: "See Dividend History \u2192" })
9165
+ !beta && /* @__PURE__ */ jsxRuntime.jsx(DividendHistoryBtn, { onClick: () => setShowDividendHistory(true), children: "See Dividend History \u2192" })
9105
9166
  ] })
9106
9167
  ] }),
9107
9168
  /* @__PURE__ */ jsxRuntime.jsx(StatsMobile, { children: /* @__PURE__ */ jsxRuntime.jsxs(StatsTabbedCard, { children: [
@@ -9111,14 +9172,14 @@ function PropertyOverview({
9111
9172
  ] }),
9112
9173
  statsTab === "token" && /* @__PURE__ */ jsxRuntime.jsx(StatsTabContent, { children: tokenStats.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { $gold: !!item.gold, children: [
9113
9174
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: item.label }),
9114
- item.label === "Holders" && holderCount != null ? /* @__PURE__ */ jsxRuntime.jsx(StatValueClickable, { onClick: () => setShowHolders(true), children: item.value }) : /* @__PURE__ */ jsxRuntime.jsx(StatValue, { $gold: !!item.gold, children: item.value })
9175
+ item.label === "Holders" && holderCount != null && !beta ? /* @__PURE__ */ jsxRuntime.jsx(StatValueClickable, { onClick: () => setShowHolders(true), children: item.value }) : /* @__PURE__ */ jsxRuntime.jsx(StatValue, { $gold: !!item.gold, children: item.value })
9115
9176
  ] }, item.label)) }),
9116
9177
  statsTab === "property" && /* @__PURE__ */ jsxRuntime.jsxs(StatsTabContent, { children: [
9117
9178
  propertyStats.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9118
9179
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: item.label }),
9119
9180
  /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: item.value })
9120
9181
  ] }, item.label)),
9121
- /* @__PURE__ */ jsxRuntime.jsx(DividendHistoryBtn, { onClick: () => setShowDividendHistory(true), children: "See Dividend History \u2192" })
9182
+ !beta && /* @__PURE__ */ jsxRuntime.jsx(DividendHistoryBtn, { onClick: () => setShowDividendHistory(true), children: "See Dividend History \u2192" })
9122
9183
  ] })
9123
9184
  ] }) })
9124
9185
  ] }),
@@ -9167,122 +9228,61 @@ function PropertyOverview({
9167
9228
  /* @__PURE__ */ jsxRuntime.jsxs(StatsColumn, { children: [
9168
9229
  /* @__PURE__ */ jsxRuntime.jsx(StatsColumnHeader, { children: "Asset Specification" }),
9169
9230
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9170
- /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Land (Freehold)" }),
9171
- /* @__PURE__ */ jsxRuntime.jsxs(StatValue, { children: [
9172
- landSize?.toLocaleString() ?? "1,848",
9173
- " sqm"
9174
- ] })
9231
+ /* @__PURE__ */ jsxRuntime.jsxs(StatLabel, { children: [
9232
+ "Land",
9233
+ ownershipLabel ? ` (${ownershipLabel})` : ""
9234
+ ] }),
9235
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: landSize != null ? `${landSize.toLocaleString()} sqm` : "\u2014" })
9175
9236
  ] }),
9176
9237
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9177
9238
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Interior" }),
9178
- /* @__PURE__ */ jsxRuntime.jsxs(StatValue, { children: [
9179
- buildingSize?.toLocaleString() ?? "~800",
9180
- " sqm"
9181
- ] })
9239
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: buildingSize != null ? `${buildingSize.toLocaleString()} sqm` : "\u2014" })
9182
9240
  ] }),
9183
9241
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9184
9242
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Built" }),
9185
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: "c.1880" })
9243
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.yearBuilt ?? "\u2014" })
9186
9244
  ] }),
9187
9245
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9188
9246
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Heritage Status" }),
9189
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: "Historic Site (Not Protected)" })
9247
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.heritageStatus || "\u2014" })
9190
9248
  ] }),
9191
9249
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9192
9250
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Zoning" }),
9193
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: "R3 Medium Density" })
9251
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.zoning || "\u2014" })
9194
9252
  ] }),
9195
9253
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9196
9254
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Development Optionality" }),
9197
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { style: { color: "#4ade80" }, children: "Low-rise / Apartments Permitted" })
9255
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.developmentOptionality || "\u2014" })
9198
9256
  ] }),
9199
9257
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9200
- /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Suburb Median (6 Bed)" }),
9201
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: "$5.5M (Mosman)" })
9258
+ /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Suburb Median" }),
9259
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.suburbMedian != null ? fmtDollar(overviewData.suburbMedian) : "\u2014" })
9202
9260
  ] }),
9203
9261
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9204
9262
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "5yr Property Growth" }),
9205
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { style: { color: "#4ade80" }, children: "+90%" })
9263
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { style: growthPct != null && growthPct > 0 ? { color: "#4ade80" } : void 0, children: growthPct != null ? `${growthPct > 0 ? "+" : ""}${growthPct}%` : "\u2014" })
9206
9264
  ] }),
9207
9265
  /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { children: [
9208
9266
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: "Current Dividend" }),
9209
- /* @__PURE__ */ jsxRuntime.jsx(StatValue, { style: { color: "#4ade80" }, children: "$0.042 / share / mo" })
9267
+ /* @__PURE__ */ jsxRuntime.jsx(StatValue, { children: overviewData?.lastDividend != null ? `$${overviewData.lastDividend.toFixed(2)} / share / mo` : "\u2014" })
9210
9268
  ] }),
9211
- /* @__PURE__ */ jsxRuntime.jsx(StatsColumnHeader, { style: { marginTop: "1.25rem" }, children: "Capital History" }),
9212
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineWrap, { children: [
9213
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { children: [
9214
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "1880s" }),
9215
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, {}),
9216
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDetail, { children: /* @__PURE__ */ jsxRuntime.jsx(TimelineLabel, { children: "Built c.1880, Pre-Federation" }) })
9217
- ] }),
9218
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { children: [
9219
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "1976" }),
9220
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, {}),
9221
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9222
- /* @__PURE__ */ jsxRuntime.jsx(TimelineLabel, { children: "Acquired" }),
9223
- /* @__PURE__ */ jsxRuntime.jsx(TimelinePriceWrap, { children: /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { children: "\xA340,000" }) })
9224
- ] })
9225
- ] }),
9226
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { children: [
9227
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "1993" }),
9228
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, {}),
9229
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9230
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineLabel, { children: [
9231
- "Sold ",
9232
- /* @__PURE__ */ jsxRuntime.jsx(TimelineHoldPeriod, { children: "17 yrs" })
9233
- ] }),
9234
- /* @__PURE__ */ jsxRuntime.jsxs(TimelinePriceWrap, { children: [
9235
- /* @__PURE__ */ jsxRuntime.jsx(TimelineGain, { children: "+1,563%" }),
9236
- /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { children: "$1.33M" })
9237
- ] })
9238
- ] })
9239
- ] }),
9240
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { children: [
9241
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "2006" }),
9242
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, {}),
9243
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9244
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineLabel, { children: [
9245
- "Sold ",
9246
- /* @__PURE__ */ jsxRuntime.jsx(TimelineHoldPeriod, { children: "13 yrs" })
9247
- ] }),
9248
- /* @__PURE__ */ jsxRuntime.jsxs(TimelinePriceWrap, { children: [
9249
- /* @__PURE__ */ jsxRuntime.jsx(TimelineGain, { children: "+491%" }),
9250
- /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { children: "$7.86M" })
9251
- ] })
9252
- ] })
9253
- ] }),
9254
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { children: [
9255
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "2021" }),
9256
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, {}),
9257
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9258
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineLabel, { children: [
9259
- "Sold (COVID correction) ",
9260
- /* @__PURE__ */ jsxRuntime.jsx(TimelineHoldPeriod, { children: "15 yrs" })
9261
- ] }),
9262
- /* @__PURE__ */ jsxRuntime.jsxs(TimelinePriceWrap, { children: [
9263
- /* @__PURE__ */ jsxRuntime.jsx(TimelineGain, { children: "+16%" }),
9264
- /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { children: "$9.09M" })
9265
- ] })
9266
- ] })
9267
- ] }),
9268
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { $last: true, children: [
9269
- /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: "2026" }),
9270
- /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, { $active: true }),
9271
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9272
- /* @__PURE__ */ jsxRuntime.jsxs(TimelineLabel, { children: [
9273
- "Loaf Offering ",
9274
- /* @__PURE__ */ jsxRuntime.jsx(TimelineHoldPeriod, { children: "5 yrs" })
9275
- ] }),
9276
- /* @__PURE__ */ jsxRuntime.jsxs(TimelinePriceWrap, { children: [
9277
- /* @__PURE__ */ jsxRuntime.jsx(TimelineGain, { children: "+105%" }),
9278
- /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { $gold: true, children: "$18.65M" })
9269
+ propertyHistory.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9270
+ /* @__PURE__ */ jsxRuntime.jsx(StatsColumnHeader, { style: { marginTop: "1.25rem" }, children: "Capital History" }),
9271
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineWrap, { children: propertyHistory.map((h, i) => {
9272
+ const last = i === propertyHistory.length - 1;
9273
+ return /* @__PURE__ */ jsxRuntime.jsxs(TimelineEntry, { $last: last, children: [
9274
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineYear, { children: h.year }),
9275
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineDot, { $active: last }),
9276
+ /* @__PURE__ */ jsxRuntime.jsxs(TimelineDetail, { children: [
9277
+ /* @__PURE__ */ jsxRuntime.jsx(TimelineLabel, { children: h.event }),
9278
+ h.amount != null && /* @__PURE__ */ jsxRuntime.jsx(TimelinePriceWrap, { children: /* @__PURE__ */ jsxRuntime.jsx(TimelinePrice, { $gold: last, children: fmtDollar(h.amount) }) })
9279
9279
  ] })
9280
- ] })
9281
- ] })
9280
+ ] }, `${h.year}-${i}`);
9281
+ }) })
9282
9282
  ] })
9283
9283
  ] })
9284
9284
  ] }),
9285
- /* @__PURE__ */ jsxRuntime.jsxs(AssetBentoNarratives, { children: [
9285
+ !beta && /* @__PURE__ */ jsxRuntime.jsxs(AssetBentoNarratives, { children: [
9286
9286
  /* @__PURE__ */ jsxRuntime.jsxs(NarrativeCard, { children: [
9287
9287
  /* @__PURE__ */ jsxRuntime.jsx(NarrativeIcon, { children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M22 12h-4l-3 9L9 3l-3 9H2" }) }) }),
9288
9288
  /* @__PURE__ */ jsxRuntime.jsx(NarrativeTitle, { children: "Generational Compounding" }),
@@ -9304,23 +9304,23 @@ function PropertyOverview({
9304
9304
  ] })
9305
9305
  ] })
9306
9306
  ] }),
9307
- /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
9307
+ showTradingHours && /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
9308
9308
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "Trading Hours" }),
9309
9309
  /* @__PURE__ */ jsxRuntime.jsxs(TradingHoursCard, { children: [
9310
9310
  /* @__PURE__ */ jsxRuntime.jsxs(TradingHoursRow, { children: [
9311
9311
  /* @__PURE__ */ jsxRuntime.jsx(THLabel, { children: "Session" }),
9312
- /* @__PURE__ */ jsxRuntime.jsx(THLabel, { children: "Hours (AEST)" }),
9312
+ /* @__PURE__ */ jsxRuntime.jsx(THLabel, { children: "Hours" }),
9313
9313
  /* @__PURE__ */ jsxRuntime.jsx(THLabel, { children: "Days" })
9314
9314
  ] }),
9315
9315
  /* @__PURE__ */ jsxRuntime.jsxs(TradingHoursRow, { $last: true, children: [
9316
9316
  /* @__PURE__ */ jsxRuntime.jsx(THValue, { children: "Continuous Trading" }),
9317
- /* @__PURE__ */ jsxRuntime.jsx(THValue, { children: "10:00 \u2013 16:00" }),
9318
- /* @__PURE__ */ jsxRuntime.jsx(THValue, { children: "Mon \u2013 Fri" })
9317
+ /* @__PURE__ */ jsxRuntime.jsx(THValue, { children: tradingHoursValue }),
9318
+ /* @__PURE__ */ jsxRuntime.jsx(THValue, { children: tradingDaysValue })
9319
9319
  ] }),
9320
- /* @__PURE__ */ jsxRuntime.jsx(TradingHoursNote, { children: "All times are Australian Eastern Standard Time (AEST/AEDT). Markets are closed on Australian public holidays." })
9320
+ /* @__PURE__ */ jsxRuntime.jsx(TradingHoursNote, { children: tradingHoursNote })
9321
9321
  ] })
9322
9322
  ] }),
9323
- /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
9323
+ !beta && /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
9324
9324
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { children: "Tokenholder Security" }),
9325
9325
  /* @__PURE__ */ jsxRuntime.jsxs(SecurityGrid, { children: [
9326
9326
  /* @__PURE__ */ jsxRuntime.jsxs(SecurityCol, { children: [
@@ -9940,22 +9940,6 @@ var TimelinePrice = styled9__default.default.span`
9940
9940
  color: ${(p) => p.$gold ? "#D4AF37" : "#fff"};
9941
9941
  font-variant-numeric: tabular-nums;
9942
9942
  `;
9943
- var TimelineGain = styled9__default.default.span`
9944
- font-size: 0.68rem;
9945
- font-weight: 600;
9946
- color: #4ade80;
9947
- background: rgba(74,222,128,0.08);
9948
- border: 1px solid rgba(74,222,128,0.15);
9949
- padding: 1px 6px;
9950
- border-radius: 4px;
9951
- font-variant-numeric: tabular-nums;
9952
- white-space: nowrap;
9953
- `;
9954
- var TimelineHoldPeriod = styled9__default.default.span`
9955
- font-size: 0.68rem;
9956
- color: rgba(255,255,255,0.25);
9957
- font-weight: 400;
9958
- `;
9959
9943
  var FeaturesPanel = styled9__default.default.div`
9960
9944
  display: flex;
9961
9945
  flex-wrap: wrap;
@@ -18099,13 +18083,16 @@ function ToastItem({ toast, onDismiss }) {
18099
18083
  ] });
18100
18084
  }
18101
18085
  var ToastContext = React5.createContext(null);
18102
- function ToastProvider({ children }) {
18086
+ function ToastProvider({ children, maxVisible }) {
18103
18087
  const [toasts, setToasts] = React5.useState([]);
18104
18088
  const addToast = React5.useCallback((data) => {
18105
18089
  const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
18106
- setToasts((prev) => [...prev, { ...data, id }]);
18090
+ setToasts((prev) => {
18091
+ const next = [...prev, { ...data, id }];
18092
+ return maxVisible && next.length > maxVisible ? next.slice(next.length - maxVisible) : next;
18093
+ });
18107
18094
  return id;
18108
- }, []);
18095
+ }, [maxVisible]);
18109
18096
  const update = React5.useCallback((id, patch) => {
18110
18097
  setToasts((prev) => prev.map((t) => t.id === id ? { ...t, ...patch } : t));
18111
18098
  }, []);