@loafmarkets/ui 0.1.164 → 0.1.166

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
@@ -758,8 +758,12 @@ type PropertyOverviewProps = {
758
758
  volume24h?: number | null;
759
759
  openOrdersValue?: number | null;
760
760
  holderCount?: number | null;
761
+ priceHistory?: {
762
+ time: number;
763
+ close: number;
764
+ }[] | null;
761
765
  };
762
- declare function PropertyOverview({ propertyName, location, midPrice, onTradeClick, 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, percentageTokenized, volume24h, openOrdersValue, holderCount, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
766
+ declare function PropertyOverview({ propertyName, location, midPrice, onTradeClick, 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, percentageTokenized, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
763
767
 
764
768
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
765
769
  type PropertyOffer = {
package/dist/index.d.ts CHANGED
@@ -758,8 +758,12 @@ type PropertyOverviewProps = {
758
758
  volume24h?: number | null;
759
759
  openOrdersValue?: number | null;
760
760
  holderCount?: number | null;
761
+ priceHistory?: {
762
+ time: number;
763
+ close: number;
764
+ }[] | null;
761
765
  };
762
- declare function PropertyOverview({ propertyName, location, midPrice, onTradeClick, 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, percentageTokenized, volume24h, openOrdersValue, holderCount, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
766
+ declare function PropertyOverview({ propertyName, location, midPrice, onTradeClick, 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, percentageTokenized, volume24h, openOrdersValue, holderCount, priceHistory: priceHistoryProp, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
763
767
 
764
768
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
765
769
  type PropertyOffer = {
package/dist/index.js CHANGED
@@ -7972,6 +7972,7 @@ function GalleryMapSection({
7972
7972
  const [showVideo, setShowVideo] = React5.useState(false);
7973
7973
  const [autoPlaying, setAutoPlaying] = React5.useState(autoPlay);
7974
7974
  const [showFullMap, setShowFullMap] = React5.useState(false);
7975
+ const [showFullVideo, setShowFullVideo] = React5.useState(false);
7975
7976
  const resolvedMapUrl = mapUrl ?? (tokenName ? `/map/${tokenName}?embed=true&zoom=14&hideOthers=true` : "about:blank");
7976
7977
  React5.useEffect(() => {
7977
7978
  if (!autoPlaying || images.length <= 1) return;
@@ -8030,7 +8031,7 @@ function GalleryMapSection({
8030
8031
  setCarouselIndex(actualIndex);
8031
8032
  }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: img.src, alt: img.title }) }, actualIndex);
8032
8033
  }) }),
8033
- (floorplanIndex !== -1 || videoUrl) && /* @__PURE__ */ jsxRuntime.jsx(ThumbDivider, {}),
8034
+ /* @__PURE__ */ jsxRuntime.jsx(ThumbDivider, {}),
8034
8035
  /* @__PURE__ */ jsxRuntime.jsxs(FixedButtons, { children: [
8035
8036
  floorplanIndex !== -1 && /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: isFloorplan, onClick: () => {
8036
8037
  stopAutoPlay();
@@ -8044,9 +8045,13 @@ function GalleryMapSection({
8044
8045
  ] }),
8045
8046
  "Floor Plan"
8046
8047
  ] }),
8047
- videoUrl && /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: showVideo, onClick: () => setShowVideo((p) => !p), children: [
8048
+ videoUrl && /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: false, onClick: () => setShowFullVideo(true), children: [
8048
8049
  /* @__PURE__ */ jsxRuntime.jsx(bi.BiVideo, { size: 16 }),
8049
8050
  " Video"
8051
+ ] }),
8052
+ /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: false, onClick: () => setShowFullMap(true), children: [
8053
+ /* @__PURE__ */ jsxRuntime.jsx(bi.BiMap, { size: 16 }),
8054
+ " Map View"
8050
8055
  ] })
8051
8056
  ] })
8052
8057
  ] }),
@@ -8115,7 +8120,8 @@ function GalleryMapSection({
8115
8120
  /* @__PURE__ */ jsxRuntime.jsx(SuburbDesc, { children: "Premium harbourside suburb on Sydney's Lower North Shore. Known for heritage homes, village atmosphere, and proximity to Taronga Zoo and Balmoral Beach." })
8116
8121
  ] })
8117
8122
  ] }),
8118
- showFullMap && /* @__PURE__ */ jsxRuntime.jsx(FullMapPopup, { onClose: () => setShowFullMap(false) })
8123
+ showFullMap && /* @__PURE__ */ jsxRuntime.jsx(FullMapPopup, { onClose: () => setShowFullMap(false) }),
8124
+ showFullVideo && videoUrl && /* @__PURE__ */ jsxRuntime.jsx(FullVideoPopup, { videoUrl, onClose: () => setShowFullVideo(false) })
8119
8125
  ] });
8120
8126
  }
8121
8127
  function FullMapPopup({ onClose }) {
@@ -8171,6 +8177,25 @@ function FullMapPopup({ onClose }) {
8171
8177
  ) })
8172
8178
  ] }) });
8173
8179
  }
8180
+ function FullVideoPopup({ videoUrl, onClose }) {
8181
+ React5.useEffect(() => {
8182
+ const handleEsc = (e) => {
8183
+ if (e.key === "Escape") onClose();
8184
+ };
8185
+ window.addEventListener("keydown", handleEsc);
8186
+ return () => window.removeEventListener("keydown", handleEsc);
8187
+ }, [onClose]);
8188
+ return /* @__PURE__ */ jsxRuntime.jsx(FullMapOverlay, { onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(FullMapPanel, { onClick: (e) => e.stopPropagation(), style: { maxWidth: 1e3 }, children: [
8189
+ /* @__PURE__ */ jsxRuntime.jsxs(FullMapHeader, { children: [
8190
+ /* @__PURE__ */ jsxRuntime.jsxs(FullMapTitle, { children: [
8191
+ /* @__PURE__ */ jsxRuntime.jsx(bi.BiVideo, {}),
8192
+ " Property Video"
8193
+ ] }),
8194
+ /* @__PURE__ */ jsxRuntime.jsx(FullMapClose, { onClick: onClose, "aria-label": "Close video", children: "\u2715" })
8195
+ ] }),
8196
+ /* @__PURE__ */ jsxRuntime.jsx(FullVideoFrame, { children: /* @__PURE__ */ jsxRuntime.jsx("video", { autoPlay: true, loop: true, playsInline: true, controls: true, style: { width: "100%", height: "100%", objectFit: "contain", background: "#000", borderRadius: 8 }, children: /* @__PURE__ */ jsxRuntime.jsx("source", { src: videoUrl, type: "video/mp4" }) }) })
8197
+ ] }) });
8198
+ }
8174
8199
  var Row = styled9__default.default.div`
8175
8200
  display: grid;
8176
8201
  grid-template-columns: 2fr 1fr;
@@ -8393,6 +8418,14 @@ var FullMapFrame = styled9__default.default.div`
8393
8418
  flex: 1;
8394
8419
  min-height: 0;
8395
8420
  `;
8421
+ var FullVideoFrame = styled9__default.default.div`
8422
+ flex: 1;
8423
+ min-height: 0;
8424
+ display: flex;
8425
+ align-items: center;
8426
+ justify-content: center;
8427
+ padding: 0 1rem 1rem;
8428
+ `;
8396
8429
  var BedIcon = /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
8397
8430
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 4v16" }),
8398
8431
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 8h18a2 2 0 0 1 2 2v10" }),
@@ -8454,32 +8487,36 @@ function truncateAddress(addr) {
8454
8487
  if (addr.length <= 12) return addr;
8455
8488
  return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
8456
8489
  }
8457
- function generateDividendHistory(valuation, totalTokens, tokenPrice) {
8490
+ function generateDividendHistory(valuation, totalTokens, tokenPrice, realPriceHistory) {
8458
8491
  if (valuation <= 0 || !totalTokens || !tokenPrice) return { records: [], priceHistory: [] };
8459
8492
  const annualDiv = valuation * 0.02;
8460
8493
  const monthlyDivPerShare = annualDiv / 12 / totalTokens;
8461
8494
  const records = [];
8462
- const priceHistory = [];
8495
+ const priceHistory = realPriceHistory?.length ? realPriceHistory.map((c) => ({ time: typeof c.time === "number" && c.time < 1e12 ? c.time * 1e3 : c.time, price: c.close })) : (() => {
8496
+ const pts = [];
8497
+ let price = tokenPrice * 0.84;
8498
+ for (let i = 365; i >= 0; i--) {
8499
+ const t = Date.now() - i * 864e5;
8500
+ const progress = (365 - i) / 365;
8501
+ const target = tokenPrice * (0.84 + progress * 0.16);
8502
+ price += (target - price) * 0.03 + (Math.random() - 0.5) * 0.8;
8503
+ price = Math.max(tokenPrice * 0.75, price);
8504
+ pts.push({ time: t, price: Math.round(price * 100) / 100 });
8505
+ }
8506
+ return pts;
8507
+ })();
8463
8508
  const now = /* @__PURE__ */ new Date();
8464
- let price = tokenPrice * 0.84;
8465
- for (let i = 365; i >= 0; i--) {
8466
- const t = Date.now() - i * 864e5;
8467
- const progress = (365 - i) / 365;
8468
- const target = tokenPrice * (0.84 + progress * 0.16);
8469
- price += (target - price) * 0.03 + (Math.random() - 0.5) * 0.8;
8470
- price = Math.max(tokenPrice * 0.75, price);
8471
- priceHistory.push({ time: t, price: Math.round(price * 100) / 100 });
8472
- }
8473
8509
  for (let i = 11; i >= 0; i--) {
8474
8510
  const exDate = new Date(now.getFullYear(), now.getMonth() - i, 1);
8475
8511
  const exTime = exDate.getTime();
8476
8512
  const closest = priceHistory.reduce((best, p) => Math.abs(p.time - exTime) < Math.abs(best.time - exTime) ? p : best);
8477
8513
  const priceAtEx = closest.price;
8514
+ const annualisedYield = priceAtEx > 0 ? monthlyDivPerShare * 12 / priceAtEx * 100 : 2;
8478
8515
  records.push({
8479
8516
  exDate: exDate.toLocaleDateString("en-AU", { day: "2-digit", month: "short", year: "numeric" }),
8480
8517
  payDate: new Date(exDate.getFullYear(), exDate.getMonth(), 15).toLocaleDateString("en-AU", { day: "2-digit", month: "short", year: "numeric" }),
8481
8518
  perShare: monthlyDivPerShare,
8482
- yieldPct: monthlyDivPerShare * 12 / priceAtEx * 100
8519
+ yieldPct: annualisedYield
8483
8520
  });
8484
8521
  }
8485
8522
  return { records, priceHistory };
@@ -8513,7 +8550,8 @@ function PropertyOverview({
8513
8550
  percentageTokenized,
8514
8551
  volume24h,
8515
8552
  openOrdersValue,
8516
- holderCount
8553
+ holderCount,
8554
+ priceHistory: priceHistoryProp
8517
8555
  }) {
8518
8556
  const [isDescExpanded, setDescExpanded] = React5.useState(false);
8519
8557
  const [showDividendHistory, setShowDividendHistory] = React5.useState(false);
@@ -8673,6 +8711,7 @@ function PropertyOverview({
8673
8711
  totalTokens: resolvedTokensIssued,
8674
8712
  tokenPrice: tokenPriceValue,
8675
8713
  ticker,
8714
+ priceHistory: priceHistoryProp,
8676
8715
  onClose: () => setShowDividendHistory(false)
8677
8716
  }
8678
8717
  ),
@@ -8805,9 +8844,10 @@ function DividendHistoryPopup({
8805
8844
  totalTokens,
8806
8845
  tokenPrice,
8807
8846
  ticker,
8847
+ priceHistory: realPriceHistory,
8808
8848
  onClose
8809
8849
  }) {
8810
- const { records, priceHistory } = generateDividendHistory(valuation ?? 0, totalTokens ?? 0, tokenPrice ?? 0);
8850
+ const { records, priceHistory } = generateDividendHistory(valuation ?? 0, totalTokens ?? 0, tokenPrice ?? 0, realPriceHistory);
8811
8851
  React5.useEffect(() => {
8812
8852
  const handleEsc = (e) => {
8813
8853
  if (e.key === "Escape") onClose();