@loafmarkets/ui 0.1.168 → 0.1.169

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.js CHANGED
@@ -8047,10 +8047,6 @@ function GalleryMapSection({
8047
8047
  videoUrl && /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: showVideo, onClick: () => setShowVideo((p) => !p), children: [
8048
8048
  /* @__PURE__ */ jsxRuntime.jsx(bi.BiVideo, { size: 16 }),
8049
8049
  " Video"
8050
- ] }),
8051
- /* @__PURE__ */ jsxRuntime.jsxs(FixedBtn, { $active: false, onClick: () => setShowFullMap(true), children: [
8052
- /* @__PURE__ */ jsxRuntime.jsx(bi.BiMap, { size: 16 }),
8053
- " Map View"
8054
8050
  ] })
8055
8051
  ] })
8056
8052
  ] }),
@@ -8119,10 +8115,10 @@ function GalleryMapSection({
8119
8115
  /* @__PURE__ */ jsxRuntime.jsx(SuburbDesc, { children: "One of Sydney's most prestigious harbourside suburbs, consistently ranked among Australia's highest-value residential markets. Strong capital growth driven by limited supply, heritage conservation overlays, and international buyer demand." })
8120
8116
  ] })
8121
8117
  ] }),
8122
- showFullMap && /* @__PURE__ */ jsxRuntime.jsx(FullMapPopup, { onClose: () => setShowFullMap(false) })
8118
+ showFullMap && /* @__PURE__ */ jsxRuntime.jsx(FullMapPopup, { onClose: () => setShowFullMap(false), mapUrl: resolvedMapUrl })
8123
8119
  ] });
8124
8120
  }
8125
- function FullMapPopup({ onClose }) {
8121
+ function FullMapPopup({ onClose, mapUrl }) {
8126
8122
  React5.useEffect(() => {
8127
8123
  const handleEsc = (e) => {
8128
8124
  if (e.key === "Escape") onClose();
@@ -8164,7 +8160,7 @@ function FullMapPopup({ onClose }) {
8164
8160
  "iframe",
8165
8161
  {
8166
8162
  ref: iframeRef,
8167
- src: "/map?embed=true",
8163
+ src: mapUrl ?? "/map?embed=true",
8168
8164
  width: "100%",
8169
8165
  height: "100%",
8170
8166
  style: { border: 0 },
@@ -8598,7 +8594,7 @@ function PropertyOverview({
8598
8594
  const annualDividend = resolvedValuation ? resolvedValuation * 0.02 : null;
8599
8595
  const monthlyDivPerShare = annualDividend && resolvedTokensIssued ? annualDividend / 12 / resolvedTokensIssued : null;
8600
8596
  const propertyStats = [
8601
- { label: "Last Valuation", value: isLoading && resolvedValuation == null ? loadingSkeleton : resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "\u2014" },
8597
+ { label: "Property Value", value: isLoading && tokenMarketCap == null ? loadingSkeleton : tokenMarketCap ? tokenMarketCap >= 1e6 ? `$${(tokenMarketCap / 1e6).toFixed(1)}M` : `$${tokenMarketCap.toLocaleString()}` : "\u2014" },
8602
8598
  { label: "Number of Offers", value: "3" },
8603
8599
  { label: "Growth (Past 5 Years)", value: "+90%" },
8604
8600
  { label: "Last Dividend", value: isLoading && monthlyDivPerShare == null ? loadingSkeleton : monthlyDivPerShare != null ? `${(monthlyDivPerShare * 100).toFixed(1)}c per Share` : "\u2014" },
@@ -8819,6 +8815,7 @@ function DividendHistoryPopup({
8819
8815
  onClose
8820
8816
  }) {
8821
8817
  const { records, priceHistory } = generateDividendHistory(valuation ?? 0, totalTokens ?? 0, tokenPrice ?? 0, realPriceHistory);
8818
+ const [highlightedIdx, setHighlightedIdx] = React5.useState(null);
8822
8819
  React5.useEffect(() => {
8823
8820
  const handleEsc = (e) => {
8824
8821
  if (e.key === "Escape") onClose();
@@ -8836,29 +8833,33 @@ function DividendHistoryPopup({
8836
8833
  const pad = { top: 20, right: 40, bottom: 30, left: 50 };
8837
8834
  const w = chartW - pad.left - pad.right;
8838
8835
  const h = chartH - pad.top - pad.bottom;
8839
- const minTime = priceHistory[0]?.time ?? 0;
8840
- const maxTime = priceHistory[priceHistory.length - 1]?.time ?? 1;
8836
+ const now = Date.now();
8837
+ const twelveMonthsAgo = now - 365 * 864e5;
8838
+ const minTime = Math.min(priceHistory[0]?.time ?? twelveMonthsAgo, twelveMonthsAgo);
8839
+ const maxTime = Math.max(priceHistory[priceHistory.length - 1]?.time ?? now, now);
8841
8840
  const prices = priceHistory.map((p) => p.price);
8842
8841
  const minP = Math.floor(Math.min(...prices) - 5);
8843
8842
  const maxP = Math.ceil(Math.max(...prices) + 5);
8844
8843
  const toX = (t) => pad.left + (t - minTime) / (maxTime - minTime) * w;
8845
8844
  const toY = (p) => pad.top + (1 - (p - minP) / (maxP - minP)) * h;
8846
8845
  const linePath = priceHistory.map((p, i) => `${i === 0 ? "M" : "L"}${toX(p.time).toFixed(1)},${toY(p.price).toFixed(1)}`).join(" ");
8847
- const areaPath = `${linePath} L${toX(priceHistory[priceHistory.length - 1].time).toFixed(1)},${(pad.top + h).toFixed(1)} L${toX(priceHistory[0].time).toFixed(1)},${(pad.top + h).toFixed(1)} Z`;
8846
+ const areaPath = priceHistory.length > 0 ? `${linePath} L${toX(priceHistory[priceHistory.length - 1].time).toFixed(1)},${(pad.top + h).toFixed(1)} L${toX(priceHistory[0].time).toFixed(1)},${(pad.top + h).toFixed(1)} Z` : "";
8848
8847
  const yTicks = Array.from({ length: 5 }, (_, i) => minP + (maxP - minP) / 4 * i);
8849
8848
  const monthLabels = [];
8850
- const seen = /* @__PURE__ */ new Set();
8851
- for (const p of priceHistory) {
8852
- const d = new Date(p.time);
8853
- const key = `${d.getFullYear()}-${d.getMonth()}`;
8854
- if (!seen.has(key)) {
8855
- seen.add(key);
8856
- monthLabels.push({ time: p.time, label: d.toLocaleDateString("en-AU", { month: "short" }) });
8857
- }
8858
- }
8859
- const divMarkers = dividendDates.filter((t) => t >= minTime && t <= maxTime).map((t) => {
8860
- const closest = priceHistory.reduce((best, p) => Math.abs(p.time - t) < Math.abs(best.time - t) ? p : best);
8861
- return { x: toX(t), y: toY(closest.price), price: closest.price };
8849
+ for (let i = 11; i >= 0; i--) {
8850
+ const d = /* @__PURE__ */ new Date();
8851
+ d.setMonth(d.getMonth() - i, 1);
8852
+ monthLabels.push({ time: d.getTime(), label: d.toLocaleDateString("en-AU", { month: "short" }) });
8853
+ }
8854
+ const divMarkers = dividendDates.map((t, idx) => {
8855
+ const closest = priceHistory.length > 0 ? priceHistory.reduce((best, p) => Math.abs(p.time - t) < Math.abs(best.time - t) ? p : best) : null;
8856
+ return {
8857
+ x: toX(t),
8858
+ y: closest ? toY(closest.price) : toY((minP + maxP) / 2),
8859
+ price: closest?.price ?? 0,
8860
+ recordIdx: idx,
8861
+ hasPrice: !!closest
8862
+ };
8862
8863
  });
8863
8864
  return /* @__PURE__ */ jsxRuntime.jsx(DivPopupOverlay, { onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DivPopupPanel, { onClick: (e) => e.stopPropagation(), children: [
8864
8865
  /* @__PURE__ */ jsxRuntime.jsxs(DivPopupHeader, { children: [
@@ -8882,13 +8883,26 @@ function DividendHistoryPopup({
8882
8883
  /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "rgba(230,200,126,0.2)" }),
8883
8884
  /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "rgba(230,200,126,0)" })
8884
8885
  ] }) }),
8885
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "url(#divAreaGrad)" }),
8886
+ areaPath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "url(#divAreaGrad)" }),
8886
8887
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: linePath, fill: "none", stroke: "#e6c87e", strokeWidth: "1.5" }),
8887
- divMarkers.map((m, i) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
8888
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: m.x, x2: m.x, y1: m.y, y2: pad.top + h, stroke: "rgba(14,203,129,0.25)", strokeWidth: "1", strokeDasharray: "3,3" }),
8889
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: m.x, cy: m.y, r: "4", fill: "#111", stroke: "#0ecb81", strokeWidth: "1.5" }),
8890
- /* @__PURE__ */ jsxRuntime.jsx("text", { x: m.x, y: m.y - 8, fill: "#0ecb81", fontSize: "8", fontWeight: "600", textAnchor: "middle", children: "$" })
8891
- ] }, i))
8888
+ divMarkers.map((m) => {
8889
+ const active = highlightedIdx === m.recordIdx;
8890
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8891
+ "g",
8892
+ {
8893
+ onMouseEnter: () => setHighlightedIdx(m.recordIdx),
8894
+ onMouseLeave: () => setHighlightedIdx(null),
8895
+ style: { cursor: "pointer" },
8896
+ children: [
8897
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: m.x - 10, y: pad.top, width: 20, height: h, fill: "transparent" }),
8898
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: m.x, x2: m.x, y1: m.y, y2: pad.top + h, stroke: active ? "rgba(14,203,129,0.6)" : "rgba(14,203,129,0.25)", strokeWidth: active ? 1.5 : 1, strokeDasharray: "3,3" }),
8899
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: m.x, cy: m.y, r: active ? 6 : 4, fill: active ? "#0ecb81" : "#111", stroke: "#0ecb81", strokeWidth: active ? 2 : 1.5, style: { transition: "r 0.15s ease" } }),
8900
+ /* @__PURE__ */ jsxRuntime.jsx("text", { x: m.x, y: m.y - (active ? 10 : 8), fill: "#0ecb81", fontSize: active ? "9" : "8", fontWeight: "600", textAnchor: "middle", children: "$" })
8901
+ ]
8902
+ },
8903
+ m.recordIdx
8904
+ );
8905
+ })
8892
8906
  ] }),
8893
8907
  /* @__PURE__ */ jsxRuntime.jsxs(DivChartLegend, { children: [
8894
8908
  /* @__PURE__ */ jsxRuntime.jsxs(DivChartLegendItem, { children: [
@@ -8908,18 +8922,27 @@ function DividendHistoryPopup({
8908
8922
  /* @__PURE__ */ jsxRuntime.jsx(DivTableTH, { style: { textAlign: "right" }, children: "Dividend/Share" }),
8909
8923
  /* @__PURE__ */ jsxRuntime.jsx(DivTableTH, { style: { textAlign: "right" }, children: "Annualised Yield" })
8910
8924
  ] }) }),
8911
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: records.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(DivTableRow, { children: [
8912
- /* @__PURE__ */ jsxRuntime.jsx(DivTableTD, { children: r.exDate }),
8913
- /* @__PURE__ */ jsxRuntime.jsx(DivTableTD, { children: r.payDate }),
8914
- /* @__PURE__ */ jsxRuntime.jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8915
- "$",
8916
- r.perShare.toFixed(4)
8917
- ] }),
8918
- /* @__PURE__ */ jsxRuntime.jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8919
- r.yieldPct.toFixed(2),
8920
- "%"
8921
- ] })
8922
- ] }, i)) })
8925
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: records.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(
8926
+ DivTableRow,
8927
+ {
8928
+ $highlighted: highlightedIdx === i,
8929
+ onMouseEnter: () => setHighlightedIdx(i),
8930
+ onMouseLeave: () => setHighlightedIdx(null),
8931
+ children: [
8932
+ /* @__PURE__ */ jsxRuntime.jsx(DivTableTD, { children: r.exDate }),
8933
+ /* @__PURE__ */ jsxRuntime.jsx(DivTableTD, { children: r.payDate }),
8934
+ /* @__PURE__ */ jsxRuntime.jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8935
+ "$",
8936
+ r.perShare.toFixed(4)
8937
+ ] }),
8938
+ /* @__PURE__ */ jsxRuntime.jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8939
+ r.yieldPct.toFixed(2),
8940
+ "%"
8941
+ ] })
8942
+ ]
8943
+ },
8944
+ i
8945
+ )) })
8923
8946
  ] }) })
8924
8947
  ] }) });
8925
8948
  }
@@ -9465,7 +9488,11 @@ var DivTableTH = styled9__default.default.th`
9465
9488
  `;
9466
9489
  var DivTableRow = styled9__default.default.tr`
9467
9490
  border-bottom: 1px solid rgba(255,255,255,0.03);
9491
+ background: ${(p) => p.$highlighted ? "rgba(14,203,129,0.08)" : "transparent"};
9492
+ transition: background 0.15s ease;
9493
+ cursor: pointer;
9468
9494
  &:last-child { border-bottom: none; }
9495
+ &:hover { background: rgba(14,203,129,0.08); }
9469
9496
  `;
9470
9497
  var DivTableTD = styled9__default.default.td`
9471
9498
  padding: 0.55rem 0.5rem;