@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.mjs CHANGED
@@ -8021,10 +8021,6 @@ function GalleryMapSection({
8021
8021
  videoUrl && /* @__PURE__ */ jsxs(FixedBtn, { $active: showVideo, onClick: () => setShowVideo((p) => !p), children: [
8022
8022
  /* @__PURE__ */ jsx(BiVideo, { size: 16 }),
8023
8023
  " Video"
8024
- ] }),
8025
- /* @__PURE__ */ jsxs(FixedBtn, { $active: false, onClick: () => setShowFullMap(true), children: [
8026
- /* @__PURE__ */ jsx(BiMap, { size: 16 }),
8027
- " Map View"
8028
8024
  ] })
8029
8025
  ] })
8030
8026
  ] }),
@@ -8093,10 +8089,10 @@ function GalleryMapSection({
8093
8089
  /* @__PURE__ */ 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." })
8094
8090
  ] })
8095
8091
  ] }),
8096
- showFullMap && /* @__PURE__ */ jsx(FullMapPopup, { onClose: () => setShowFullMap(false) })
8092
+ showFullMap && /* @__PURE__ */ jsx(FullMapPopup, { onClose: () => setShowFullMap(false), mapUrl: resolvedMapUrl })
8097
8093
  ] });
8098
8094
  }
8099
- function FullMapPopup({ onClose }) {
8095
+ function FullMapPopup({ onClose, mapUrl }) {
8100
8096
  useEffect(() => {
8101
8097
  const handleEsc = (e) => {
8102
8098
  if (e.key === "Escape") onClose();
@@ -8138,7 +8134,7 @@ function FullMapPopup({ onClose }) {
8138
8134
  "iframe",
8139
8135
  {
8140
8136
  ref: iframeRef,
8141
- src: "/map?embed=true",
8137
+ src: mapUrl ?? "/map?embed=true",
8142
8138
  width: "100%",
8143
8139
  height: "100%",
8144
8140
  style: { border: 0 },
@@ -8572,7 +8568,7 @@ function PropertyOverview({
8572
8568
  const annualDividend = resolvedValuation ? resolvedValuation * 0.02 : null;
8573
8569
  const monthlyDivPerShare = annualDividend && resolvedTokensIssued ? annualDividend / 12 / resolvedTokensIssued : null;
8574
8570
  const propertyStats = [
8575
- { label: "Last Valuation", value: isLoading && resolvedValuation == null ? loadingSkeleton : resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "\u2014" },
8571
+ { label: "Property Value", value: isLoading && tokenMarketCap == null ? loadingSkeleton : tokenMarketCap ? tokenMarketCap >= 1e6 ? `$${(tokenMarketCap / 1e6).toFixed(1)}M` : `$${tokenMarketCap.toLocaleString()}` : "\u2014" },
8576
8572
  { label: "Number of Offers", value: "3" },
8577
8573
  { label: "Growth (Past 5 Years)", value: "+90%" },
8578
8574
  { label: "Last Dividend", value: isLoading && monthlyDivPerShare == null ? loadingSkeleton : monthlyDivPerShare != null ? `${(monthlyDivPerShare * 100).toFixed(1)}c per Share` : "\u2014" },
@@ -8793,6 +8789,7 @@ function DividendHistoryPopup({
8793
8789
  onClose
8794
8790
  }) {
8795
8791
  const { records, priceHistory } = generateDividendHistory(valuation ?? 0, totalTokens ?? 0, tokenPrice ?? 0, realPriceHistory);
8792
+ const [highlightedIdx, setHighlightedIdx] = useState(null);
8796
8793
  useEffect(() => {
8797
8794
  const handleEsc = (e) => {
8798
8795
  if (e.key === "Escape") onClose();
@@ -8810,29 +8807,33 @@ function DividendHistoryPopup({
8810
8807
  const pad = { top: 20, right: 40, bottom: 30, left: 50 };
8811
8808
  const w = chartW - pad.left - pad.right;
8812
8809
  const h = chartH - pad.top - pad.bottom;
8813
- const minTime = priceHistory[0]?.time ?? 0;
8814
- const maxTime = priceHistory[priceHistory.length - 1]?.time ?? 1;
8810
+ const now = Date.now();
8811
+ const twelveMonthsAgo = now - 365 * 864e5;
8812
+ const minTime = Math.min(priceHistory[0]?.time ?? twelveMonthsAgo, twelveMonthsAgo);
8813
+ const maxTime = Math.max(priceHistory[priceHistory.length - 1]?.time ?? now, now);
8815
8814
  const prices = priceHistory.map((p) => p.price);
8816
8815
  const minP = Math.floor(Math.min(...prices) - 5);
8817
8816
  const maxP = Math.ceil(Math.max(...prices) + 5);
8818
8817
  const toX = (t) => pad.left + (t - minTime) / (maxTime - minTime) * w;
8819
8818
  const toY = (p) => pad.top + (1 - (p - minP) / (maxP - minP)) * h;
8820
8819
  const linePath = priceHistory.map((p, i) => `${i === 0 ? "M" : "L"}${toX(p.time).toFixed(1)},${toY(p.price).toFixed(1)}`).join(" ");
8821
- 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`;
8820
+ 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` : "";
8822
8821
  const yTicks = Array.from({ length: 5 }, (_, i) => minP + (maxP - minP) / 4 * i);
8823
8822
  const monthLabels = [];
8824
- const seen = /* @__PURE__ */ new Set();
8825
- for (const p of priceHistory) {
8826
- const d = new Date(p.time);
8827
- const key = `${d.getFullYear()}-${d.getMonth()}`;
8828
- if (!seen.has(key)) {
8829
- seen.add(key);
8830
- monthLabels.push({ time: p.time, label: d.toLocaleDateString("en-AU", { month: "short" }) });
8831
- }
8832
- }
8833
- const divMarkers = dividendDates.filter((t) => t >= minTime && t <= maxTime).map((t) => {
8834
- const closest = priceHistory.reduce((best, p) => Math.abs(p.time - t) < Math.abs(best.time - t) ? p : best);
8835
- return { x: toX(t), y: toY(closest.price), price: closest.price };
8823
+ for (let i = 11; i >= 0; i--) {
8824
+ const d = /* @__PURE__ */ new Date();
8825
+ d.setMonth(d.getMonth() - i, 1);
8826
+ monthLabels.push({ time: d.getTime(), label: d.toLocaleDateString("en-AU", { month: "short" }) });
8827
+ }
8828
+ const divMarkers = dividendDates.map((t, idx) => {
8829
+ const closest = priceHistory.length > 0 ? priceHistory.reduce((best, p) => Math.abs(p.time - t) < Math.abs(best.time - t) ? p : best) : null;
8830
+ return {
8831
+ x: toX(t),
8832
+ y: closest ? toY(closest.price) : toY((minP + maxP) / 2),
8833
+ price: closest?.price ?? 0,
8834
+ recordIdx: idx,
8835
+ hasPrice: !!closest
8836
+ };
8836
8837
  });
8837
8838
  return /* @__PURE__ */ jsx(DivPopupOverlay, { onClick: onClose, children: /* @__PURE__ */ jsxs(DivPopupPanel, { onClick: (e) => e.stopPropagation(), children: [
8838
8839
  /* @__PURE__ */ jsxs(DivPopupHeader, { children: [
@@ -8856,13 +8857,26 @@ function DividendHistoryPopup({
8856
8857
  /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "rgba(230,200,126,0.2)" }),
8857
8858
  /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "rgba(230,200,126,0)" })
8858
8859
  ] }) }),
8859
- /* @__PURE__ */ jsx("path", { d: areaPath, fill: "url(#divAreaGrad)" }),
8860
+ areaPath && /* @__PURE__ */ jsx("path", { d: areaPath, fill: "url(#divAreaGrad)" }),
8860
8861
  /* @__PURE__ */ jsx("path", { d: linePath, fill: "none", stroke: "#e6c87e", strokeWidth: "1.5" }),
8861
- divMarkers.map((m, i) => /* @__PURE__ */ jsxs("g", { children: [
8862
- /* @__PURE__ */ 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" }),
8863
- /* @__PURE__ */ jsx("circle", { cx: m.x, cy: m.y, r: "4", fill: "#111", stroke: "#0ecb81", strokeWidth: "1.5" }),
8864
- /* @__PURE__ */ jsx("text", { x: m.x, y: m.y - 8, fill: "#0ecb81", fontSize: "8", fontWeight: "600", textAnchor: "middle", children: "$" })
8865
- ] }, i))
8862
+ divMarkers.map((m) => {
8863
+ const active = highlightedIdx === m.recordIdx;
8864
+ return /* @__PURE__ */ jsxs(
8865
+ "g",
8866
+ {
8867
+ onMouseEnter: () => setHighlightedIdx(m.recordIdx),
8868
+ onMouseLeave: () => setHighlightedIdx(null),
8869
+ style: { cursor: "pointer" },
8870
+ children: [
8871
+ /* @__PURE__ */ jsx("rect", { x: m.x - 10, y: pad.top, width: 20, height: h, fill: "transparent" }),
8872
+ /* @__PURE__ */ 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" }),
8873
+ /* @__PURE__ */ 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" } }),
8874
+ /* @__PURE__ */ jsx("text", { x: m.x, y: m.y - (active ? 10 : 8), fill: "#0ecb81", fontSize: active ? "9" : "8", fontWeight: "600", textAnchor: "middle", children: "$" })
8875
+ ]
8876
+ },
8877
+ m.recordIdx
8878
+ );
8879
+ })
8866
8880
  ] }),
8867
8881
  /* @__PURE__ */ jsxs(DivChartLegend, { children: [
8868
8882
  /* @__PURE__ */ jsxs(DivChartLegendItem, { children: [
@@ -8882,18 +8896,27 @@ function DividendHistoryPopup({
8882
8896
  /* @__PURE__ */ jsx(DivTableTH, { style: { textAlign: "right" }, children: "Dividend/Share" }),
8883
8897
  /* @__PURE__ */ jsx(DivTableTH, { style: { textAlign: "right" }, children: "Annualised Yield" })
8884
8898
  ] }) }),
8885
- /* @__PURE__ */ jsx("tbody", { children: records.map((r, i) => /* @__PURE__ */ jsxs(DivTableRow, { children: [
8886
- /* @__PURE__ */ jsx(DivTableTD, { children: r.exDate }),
8887
- /* @__PURE__ */ jsx(DivTableTD, { children: r.payDate }),
8888
- /* @__PURE__ */ jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8889
- "$",
8890
- r.perShare.toFixed(4)
8891
- ] }),
8892
- /* @__PURE__ */ jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8893
- r.yieldPct.toFixed(2),
8894
- "%"
8895
- ] })
8896
- ] }, i)) })
8899
+ /* @__PURE__ */ jsx("tbody", { children: records.map((r, i) => /* @__PURE__ */ jsxs(
8900
+ DivTableRow,
8901
+ {
8902
+ $highlighted: highlightedIdx === i,
8903
+ onMouseEnter: () => setHighlightedIdx(i),
8904
+ onMouseLeave: () => setHighlightedIdx(null),
8905
+ children: [
8906
+ /* @__PURE__ */ jsx(DivTableTD, { children: r.exDate }),
8907
+ /* @__PURE__ */ jsx(DivTableTD, { children: r.payDate }),
8908
+ /* @__PURE__ */ jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8909
+ "$",
8910
+ r.perShare.toFixed(4)
8911
+ ] }),
8912
+ /* @__PURE__ */ jsxs(DivTableTD, { style: { textAlign: "right", fontVariantNumeric: "tabular-nums" }, children: [
8913
+ r.yieldPct.toFixed(2),
8914
+ "%"
8915
+ ] })
8916
+ ]
8917
+ },
8918
+ i
8919
+ )) })
8897
8920
  ] }) })
8898
8921
  ] }) });
8899
8922
  }
@@ -9439,7 +9462,11 @@ var DivTableTH = styled9.th`
9439
9462
  `;
9440
9463
  var DivTableRow = styled9.tr`
9441
9464
  border-bottom: 1px solid rgba(255,255,255,0.03);
9465
+ background: ${(p) => p.$highlighted ? "rgba(14,203,129,0.08)" : "transparent"};
9466
+ transition: background 0.15s ease;
9467
+ cursor: pointer;
9442
9468
  &:last-child { border-bottom: none; }
9469
+ &:hover { background: rgba(14,203,129,0.08); }
9443
9470
  `;
9444
9471
  var DivTableTD = styled9.td`
9445
9472
  padding: 0.55rem 0.5rem;