@loafmarkets/ui 0.1.144 → 0.1.145

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
@@ -755,8 +755,11 @@ type PropertyOverviewProps = {
755
755
  contractAddress?: string;
756
756
  chain?: string;
757
757
  percentageTokenized?: number | null;
758
+ volume24h?: number | null;
759
+ openOrdersValue?: number | null;
760
+ holderCount?: number | null;
758
761
  };
759
- 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, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
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;
760
763
 
761
764
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
762
765
  type PropertyOffer = {
package/dist/index.d.ts CHANGED
@@ -755,8 +755,11 @@ type PropertyOverviewProps = {
755
755
  contractAddress?: string;
756
756
  chain?: string;
757
757
  percentageTokenized?: number | null;
758
+ volume24h?: number | null;
759
+ openOrdersValue?: number | null;
760
+ holderCount?: number | null;
758
761
  };
759
- 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, }: PropertyOverviewProps): react_jsx_runtime.JSX.Element;
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;
760
763
 
761
764
  type OfferStatus = 'active' | 'rejected' | 'expired' | 'historical' | 'pending';
762
765
  type PropertyOffer = {
package/dist/index.js CHANGED
@@ -8323,7 +8323,10 @@ function PropertyOverview({
8323
8323
  ticker,
8324
8324
  contractAddress,
8325
8325
  chain = "Base (Ethereum L2)",
8326
- percentageTokenized
8326
+ percentageTokenized,
8327
+ volume24h,
8328
+ openOrdersValue,
8329
+ holderCount
8327
8330
  }) {
8328
8331
  const [isDescExpanded, setDescExpanded] = React5.useState(false);
8329
8332
  const description = descriptionProp ?? overviewData?.description ?? DEFAULT_DESCRIPTION;
@@ -8360,7 +8363,7 @@ function PropertyOverview({
8360
8363
  const tokenPriceValue = midPrice > 0 ? midPrice : null;
8361
8364
  const weeklyRent = overviewData?.weeklyRent ?? 0;
8362
8365
  const annualRent = weeklyRent * 52;
8363
- const dividendYield = resolvedValuation && annualRent > 0 ? (annualRent / resolvedValuation * 100).toFixed(2) : null;
8366
+ resolvedValuation && annualRent > 0 ? (annualRent / resolvedValuation * 100).toFixed(2) : null;
8364
8367
  const monthlyCoupon = annualRent / 12;
8365
8368
  const tokenMarketCap = tokenPriceValue && resolvedTokensIssued ? tokenPriceValue * resolvedTokensIssued : null;
8366
8369
  const currentDividendYield = tokenMarketCap && monthlyCoupon > 0 ? (monthlyCoupon * 12 / tokenMarketCap * 100).toFixed(2) : null;
@@ -8376,11 +8379,19 @@ function PropertyOverview({
8376
8379
  { label: "Property Type", value: resolvedPropertyType ?? "\u2014" },
8377
8380
  { label: "Location", value: location || "\u2014" }
8378
8381
  ];
8382
+ const vol24hDollar = volume24h != null && tokenPriceValue ? volume24h * tokenPriceValue : null;
8383
+ const holdRatio = (() => {
8384
+ if (!tokenMarketCap || tokenMarketCap <= 0 || vol24hDollar == null) return null;
8385
+ const turnover = vol24hDollar / (tokenMarketCap / 2);
8386
+ const holdPct = Math.max(0, Math.min(100, (1 - turnover) * 100));
8387
+ return { holdPct, tradePct: +(100 - holdPct).toFixed(1) };
8388
+ })();
8379
8389
  const tokenStats = [
8380
8390
  { label: "Token Price", value: isLoading && tokenPriceValue == null ? loadingSkeleton : tokenPriceValue ? `$${tokenPriceValue.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}` : "\u2014", gold: true },
8381
- { label: "Property Value", value: isLoading && resolvedValuation == null ? loadingSkeleton : resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "\u2014" },
8382
- { label: "Dividend Yield", value: isLoading && dividendYield == null ? loadingSkeleton : dividendYield ? `${dividendYield}%` : "\u2014" },
8383
- { label: "Total Tokens", value: isLoading && resolvedTokensIssued == null ? loadingSkeleton : resolvedTokensIssued?.toLocaleString() ?? "\u2014" }
8391
+ { label: "24h Volume", value: isLoading && vol24hDollar == null ? loadingSkeleton : vol24hDollar != null && vol24hDollar > 0 ? `$${Math.round(vol24hDollar).toLocaleString()}` : "\u2014" },
8392
+ { label: "Current Dividend Yield", value: isLoading && currentDividendYield == null ? loadingSkeleton : currentDividendYield ? `${currentDividendYield}%` : "\u2014" },
8393
+ { label: "Open Orders", value: isLoading && openOrdersValue == null ? loadingSkeleton : openOrdersValue != null && openOrdersValue > 0 ? `$${Math.round(openOrdersValue).toLocaleString()}` : "\u2014" },
8394
+ { label: "Holders", value: isLoading && holderCount == null ? loadingSkeleton : holderCount != null ? holderCount.toLocaleString() : "\u2014" }
8384
8395
  ];
8385
8396
  const propertyStats = [
8386
8397
  { label: "Offering Valuation", value: isLoading && resolvedValuation == null ? loadingSkeleton : resolvedValuation ? resolvedValuation >= 1e6 ? `$${(resolvedValuation / 1e6).toFixed(2)}M` : `$${resolvedValuation.toLocaleString()}` : "\u2014" },
@@ -8419,7 +8430,30 @@ function PropertyOverview({
8419
8430
  tokenStats.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(StatRow, { $gold: !!item.gold, children: [
8420
8431
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { children: item.label }),
8421
8432
  /* @__PURE__ */ jsxRuntime.jsx(StatValue, { $gold: !!item.gold, children: item.value })
8422
- ] }, item.label))
8433
+ ] }, item.label)),
8434
+ holdRatio && /* @__PURE__ */ jsxRuntime.jsxs(HoldRatioWrap, { children: [
8435
+ /* @__PURE__ */ jsxRuntime.jsxs(HoldRatioTitle, { children: [
8436
+ /* @__PURE__ */ jsxRuntime.jsx(HoldRatioTitleText, { children: "Holding Ratio" }),
8437
+ /* @__PURE__ */ jsxRuntime.jsx(HoldRatioInfo, { "data-tip": "Proportion of token holders vs active traders over the last 24 hours, measured by trading volume against market capitalisation.", children: "?" })
8438
+ ] }),
8439
+ /* @__PURE__ */ jsxRuntime.jsxs(HoldRatioHeader, { children: [
8440
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8441
+ /* @__PURE__ */ jsxRuntime.jsx(HoldRatioLabel, { $side: "hold", children: "Holding " }),
8442
+ /* @__PURE__ */ jsxRuntime.jsxs(HoldRatioValue, { $side: "hold", children: [
8443
+ holdRatio.holdPct.toFixed(1),
8444
+ "%"
8445
+ ] })
8446
+ ] }),
8447
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8448
+ /* @__PURE__ */ jsxRuntime.jsxs(HoldRatioValue, { $side: "trade", children: [
8449
+ holdRatio.tradePct,
8450
+ "%"
8451
+ ] }),
8452
+ /* @__PURE__ */ jsxRuntime.jsx(HoldRatioLabel, { $side: "trade", children: " Trading" })
8453
+ ] })
8454
+ ] }),
8455
+ /* @__PURE__ */ jsxRuntime.jsx(HoldRatioTrack, { children: /* @__PURE__ */ jsxRuntime.jsx(HoldRatioFill, { $pct: holdRatio.holdPct }) })
8456
+ ] })
8423
8457
  ] }),
8424
8458
  /* @__PURE__ */ jsxRuntime.jsxs(StatsColumn, { children: [
8425
8459
  /* @__PURE__ */ jsxRuntime.jsx(StatsColumnHeader, { children: "Property Fundamentals" }),
@@ -8808,6 +8842,101 @@ var ProtectionDesc = styled19__default.default.div`
8808
8842
  color: rgba(255,255,255,0.5);
8809
8843
  line-height: 1.5;
8810
8844
  `;
8845
+ var HoldRatioWrap = styled19__default.default.div`
8846
+ display: flex;
8847
+ flex-direction: column;
8848
+ gap: 6px;
8849
+ padding: 0.75rem 0 0;
8850
+ margin-top: 0.5rem;
8851
+ border-top: 1px solid rgba(255,255,255,0.04);
8852
+ `;
8853
+ var HoldRatioTitle = styled19__default.default.div`
8854
+ display: flex;
8855
+ align-items: center;
8856
+ gap: 5px;
8857
+ `;
8858
+ var HoldRatioTitleText = styled19__default.default.span`
8859
+ font-size: 0.65rem;
8860
+ font-weight: 600;
8861
+ text-transform: uppercase;
8862
+ letter-spacing: 0.06em;
8863
+ color: rgba(255,255,255,0.4);
8864
+ `;
8865
+ var HoldRatioInfo = styled19__default.default.span`
8866
+ position: relative;
8867
+ display: inline-flex;
8868
+ align-items: center;
8869
+ justify-content: center;
8870
+ width: 13px;
8871
+ height: 13px;
8872
+ border-radius: 50%;
8873
+ border: 1px solid rgba(255,255,255,0.15);
8874
+ font-size: 0.5rem;
8875
+ font-weight: 700;
8876
+ color: rgba(255,255,255,0.3);
8877
+ cursor: help;
8878
+ flex-shrink: 0;
8879
+
8880
+ &::after {
8881
+ content: attr(data-tip);
8882
+ position: absolute;
8883
+ bottom: calc(100% + 6px);
8884
+ left: 0;
8885
+ width: max-content;
8886
+ max-width: 260px;
8887
+ padding: 8px 12px;
8888
+ border-radius: 6px;
8889
+ background: #1a1a1e;
8890
+ border: 1px solid rgba(255,255,255,0.1);
8891
+ color: rgba(255,255,255,0.7);
8892
+ font-size: 0.7rem;
8893
+ font-weight: 400;
8894
+ letter-spacing: 0;
8895
+ text-transform: none;
8896
+ line-height: 1.45;
8897
+ white-space: normal;
8898
+ pointer-events: none;
8899
+ opacity: 0;
8900
+ transition: opacity 0.15s;
8901
+ z-index: 10;
8902
+ }
8903
+
8904
+ &:hover::after {
8905
+ opacity: 1;
8906
+ }
8907
+ `;
8908
+ var HoldRatioHeader = styled19__default.default.div`
8909
+ display: flex;
8910
+ align-items: center;
8911
+ justify-content: space-between;
8912
+ `;
8913
+ var HoldRatioLabel = styled19__default.default.span`
8914
+ font-size: 0.7rem;
8915
+ font-weight: 600;
8916
+ text-transform: uppercase;
8917
+ letter-spacing: 0.05em;
8918
+ color: ${(p) => p.$side === "trade" ? "rgba(246, 70, 93, 0.6)" : "rgba(14, 203, 129, 0.6)"};
8919
+ `;
8920
+ var HoldRatioValue = styled19__default.default.span`
8921
+ font-size: 0.75rem;
8922
+ font-weight: 600;
8923
+ font-variant-numeric: tabular-nums;
8924
+ color: ${(p) => p.$side === "trade" ? "rgba(246, 70, 93, 0.7)" : "rgba(14, 203, 129, 0.7)"};
8925
+ `;
8926
+ var HoldRatioTrack = styled19__default.default.div`
8927
+ height: 6px;
8928
+ border-radius: 3px;
8929
+ background: rgba(246, 70, 93, 0.15);
8930
+ overflow: hidden;
8931
+ position: relative;
8932
+ `;
8933
+ var HoldRatioFill = styled19__default.default.div`
8934
+ height: 100%;
8935
+ width: ${(p) => p.$pct}%;
8936
+ border-radius: 3px;
8937
+ background: rgba(14, 203, 129, 0.35);
8938
+ transition: width 0.6s ease;
8939
+ `;
8811
8940
  var STATUS_BG = {
8812
8941
  active: "rgba(14,203,129,0.18)",
8813
8942
  rejected: "rgba(246,70,93,0.18)",