@loafmarkets/ui 0.1.422 → 0.1.424
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 +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +112 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3016,6 +3016,74 @@ var PropertyTour = React9.forwardRef(
|
|
|
3016
3016
|
);
|
|
3017
3017
|
PropertyTour.displayName = "PropertyTour";
|
|
3018
3018
|
|
|
3019
|
+
// src/lib/breaking-dismissals.ts
|
|
3020
|
+
var BREAKING_WINDOW_HOURS = 6;
|
|
3021
|
+
var BREAKING_MEMORY_CAP = 50;
|
|
3022
|
+
var BREAKING_MEMORY_STORAGE_KEY = "loaf:dismissed-breaking";
|
|
3023
|
+
var emptyBreakingMemory = () => ({ dismissed: {}, pinned: {}, watermark: null });
|
|
3024
|
+
var isTimestampMap = (v) => typeof v === "object" && v !== null && !Array.isArray(v) && Object.values(v).every((t) => typeof t === "number" && Number.isFinite(t));
|
|
3025
|
+
var pruneMap = (map, cutoff) => {
|
|
3026
|
+
const fresh = Object.entries(map).filter(([, t]) => t >= cutoff);
|
|
3027
|
+
fresh.sort((a, b) => b[1] - a[1]);
|
|
3028
|
+
return Object.fromEntries(fresh.slice(0, BREAKING_MEMORY_CAP));
|
|
3029
|
+
};
|
|
3030
|
+
var prune = (mem, now) => {
|
|
3031
|
+
const cutoff = now - BREAKING_WINDOW_HOURS * 36e5;
|
|
3032
|
+
return {
|
|
3033
|
+
dismissed: pruneMap(mem.dismissed, cutoff),
|
|
3034
|
+
pinned: pruneMap(mem.pinned, cutoff),
|
|
3035
|
+
// An expired watermark can't block anything (every in-window story is newer).
|
|
3036
|
+
watermark: mem.watermark !== null && mem.watermark >= cutoff ? mem.watermark : null
|
|
3037
|
+
};
|
|
3038
|
+
};
|
|
3039
|
+
function parseBreakingMemory(raw, now) {
|
|
3040
|
+
if (!raw) return emptyBreakingMemory();
|
|
3041
|
+
try {
|
|
3042
|
+
const v = JSON.parse(raw);
|
|
3043
|
+
if (typeof v !== "object" || v === null || Array.isArray(v) || !isTimestampMap(v.dismissed) || !isTimestampMap(v.pinned) || !(v.watermark === null || typeof v.watermark === "number" && Number.isFinite(v.watermark))) {
|
|
3044
|
+
return emptyBreakingMemory();
|
|
3045
|
+
}
|
|
3046
|
+
return prune({ dismissed: v.dismissed, pinned: v.pinned, watermark: v.watermark ?? null }, now);
|
|
3047
|
+
} catch {
|
|
3048
|
+
return emptyBreakingMemory();
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
var serializeBreakingMemory = (mem) => JSON.stringify(mem);
|
|
3052
|
+
function recordBreakingDismissal(mem, key, publishedAtMs, now) {
|
|
3053
|
+
return prune(
|
|
3054
|
+
{
|
|
3055
|
+
dismissed: { ...mem.dismissed, [key]: publishedAtMs },
|
|
3056
|
+
pinned: mem.pinned,
|
|
3057
|
+
watermark: Math.max(mem.watermark ?? -Infinity, publishedAtMs)
|
|
3058
|
+
},
|
|
3059
|
+
now
|
|
3060
|
+
);
|
|
3061
|
+
}
|
|
3062
|
+
function recordBreakingPins(mem, pins, now) {
|
|
3063
|
+
if (pins.every((p) => mem.pinned[p.key] !== void 0)) return mem;
|
|
3064
|
+
const pinned = { ...mem.pinned };
|
|
3065
|
+
for (const p of pins) pinned[p.key] = p.publishedAtMs;
|
|
3066
|
+
return prune({ dismissed: mem.dismissed, pinned, watermark: mem.watermark }, now);
|
|
3067
|
+
}
|
|
3068
|
+
function mayPinBreaking(mem, key, publishedAtMs) {
|
|
3069
|
+
if (mem.dismissed[key] !== void 0) return false;
|
|
3070
|
+
if (mem.watermark === null) return true;
|
|
3071
|
+
return publishedAtMs > mem.watermark || mem.pinned[key] !== void 0;
|
|
3072
|
+
}
|
|
3073
|
+
function loadBreakingMemory(now) {
|
|
3074
|
+
try {
|
|
3075
|
+
return parseBreakingMemory(window.localStorage.getItem(BREAKING_MEMORY_STORAGE_KEY), now);
|
|
3076
|
+
} catch {
|
|
3077
|
+
return emptyBreakingMemory();
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
function saveBreakingMemory(mem) {
|
|
3081
|
+
try {
|
|
3082
|
+
window.localStorage.setItem(BREAKING_MEMORY_STORAGE_KEY, serializeBreakingMemory(mem));
|
|
3083
|
+
} catch {
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3019
3087
|
// src/lib/isSafeUrl.ts
|
|
3020
3088
|
var CONTROL_CHARS = /[\u0000-\u001F\u007F]/g;
|
|
3021
3089
|
function isSafeUrl(url) {
|
|
@@ -3036,13 +3104,27 @@ function matchesTab(item, tab) {
|
|
|
3036
3104
|
if (item.types && item.types.length > 0) return item.types.includes(tab);
|
|
3037
3105
|
return item.type === tab;
|
|
3038
3106
|
}
|
|
3039
|
-
var BREAKING_WINDOW_HOURS = 6;
|
|
3040
3107
|
var MAX_PINNED_BREAKING = 2;
|
|
3041
3108
|
var BREAKING_IMPACT_FLOOR = 8;
|
|
3042
3109
|
var breakingImpact = (it) => typeof it.impactScore === "number" && Number.isFinite(it.impactScore) ? it.impactScore : BREAKING_IMPACT_FLOOR;
|
|
3043
|
-
var
|
|
3044
|
-
var
|
|
3110
|
+
var breakingMemory = null;
|
|
3111
|
+
var getBreakingMemory = () => breakingMemory ??= loadBreakingMemory(Date.now());
|
|
3112
|
+
var commitBreakingMemory = (mem) => {
|
|
3113
|
+
breakingMemory = mem;
|
|
3114
|
+
saveBreakingMemory(mem);
|
|
3115
|
+
};
|
|
3116
|
+
var __resetDismissedBreaking = () => {
|
|
3117
|
+
breakingMemory = null;
|
|
3118
|
+
try {
|
|
3119
|
+
window.localStorage.removeItem(BREAKING_MEMORY_STORAGE_KEY);
|
|
3120
|
+
} catch {
|
|
3121
|
+
}
|
|
3122
|
+
};
|
|
3123
|
+
var __reloadBreakingMemory = () => {
|
|
3124
|
+
breakingMemory = null;
|
|
3125
|
+
};
|
|
3045
3126
|
var breakingKey = (it) => String(it.id ?? it.title);
|
|
3127
|
+
var breakingPublishedMs = (it) => new Date(it.publishedAt).getTime();
|
|
3046
3128
|
var BREAKING_SWIPE_MIN_PX = 80;
|
|
3047
3129
|
var ITEMS_PER_PAGE = 5;
|
|
3048
3130
|
var ITEMS_PER_PAGE_MOBILE = 5;
|
|
@@ -3570,8 +3652,19 @@ var PropertyNewsUpdates = React9.forwardRef(
|
|
|
3570
3652
|
});
|
|
3571
3653
|
};
|
|
3572
3654
|
const pinnedBreaking = React9.useMemo(() => {
|
|
3573
|
-
|
|
3655
|
+
const mem = getBreakingMemory();
|
|
3656
|
+
return breakingEligible.filter((it) => mayPinBreaking(mem, breakingKey(it), breakingPublishedMs(it))).sort((a, b) => breakingImpact(b) - breakingImpact(a)).slice(0, MAX_PINNED_BREAKING);
|
|
3574
3657
|
}, [breakingEligible, dismissedVersion]);
|
|
3658
|
+
React9.useEffect(() => {
|
|
3659
|
+
if (pinnedBreaking.length === 0) return;
|
|
3660
|
+
const mem = getBreakingMemory();
|
|
3661
|
+
const next = recordBreakingPins(
|
|
3662
|
+
mem,
|
|
3663
|
+
pinnedBreaking.map((it) => ({ key: breakingKey(it), publishedAtMs: breakingPublishedMs(it) })),
|
|
3664
|
+
Date.now()
|
|
3665
|
+
);
|
|
3666
|
+
if (next !== mem) commitBreakingMemory(next);
|
|
3667
|
+
}, [pinnedBreaking]);
|
|
3575
3668
|
const breakingRowKeys = React9.useMemo(
|
|
3576
3669
|
() => new Set(breakingEligible.map(breakingKey)),
|
|
3577
3670
|
[breakingEligible]
|
|
@@ -3676,8 +3769,13 @@ var PropertyNewsUpdates = React9.forwardRef(
|
|
|
3676
3769
|
const sentiment = getSentimentInfo(item.sentimentScore);
|
|
3677
3770
|
const k = breakingKey(item);
|
|
3678
3771
|
const dx = breakingSwipe?.key === k ? breakingSwipe.dx : 0;
|
|
3772
|
+
const persistDismissal = () => {
|
|
3773
|
+
commitBreakingMemory(
|
|
3774
|
+
recordBreakingDismissal(getBreakingMemory(), k, breakingPublishedMs(item), Date.now())
|
|
3775
|
+
);
|
|
3776
|
+
};
|
|
3679
3777
|
const finishDismiss = () => {
|
|
3680
|
-
|
|
3778
|
+
persistDismissal();
|
|
3681
3779
|
setDismissingBreakingKey(null);
|
|
3682
3780
|
setDismissedVersion((v) => v + 1);
|
|
3683
3781
|
};
|
|
@@ -3725,7 +3823,7 @@ var PropertyNewsUpdates = React9.forwardRef(
|
|
|
3725
3823
|
const drag = Math.max(0, e.clientX - breakingSwipeStartXRef.current);
|
|
3726
3824
|
const width = e.currentTarget.offsetWidth || 0;
|
|
3727
3825
|
if (drag >= Math.max(BREAKING_SWIPE_MIN_PX, width * 0.3)) {
|
|
3728
|
-
|
|
3826
|
+
persistDismissal();
|
|
3729
3827
|
setDismissedVersion((v) => v + 1);
|
|
3730
3828
|
}
|
|
3731
3829
|
},
|
|
@@ -7644,6 +7742,7 @@ var LoginPopup = ({
|
|
|
7644
7742
|
onFundWallet,
|
|
7645
7743
|
initialView,
|
|
7646
7744
|
initialCode,
|
|
7745
|
+
defaultHandle,
|
|
7647
7746
|
kycStatus: kycStatusProp,
|
|
7648
7747
|
walletAddress,
|
|
7649
7748
|
onSubmitReferralCode,
|
|
@@ -7654,6 +7753,12 @@ var LoginPopup = ({
|
|
|
7654
7753
|
const [view, setView] = useState(() => initialView ?? "main");
|
|
7655
7754
|
const [email, setEmail] = useState("");
|
|
7656
7755
|
const [handle, setHandle] = useState("");
|
|
7756
|
+
const seededDefaultHandleRef = React9__default.useRef(null);
|
|
7757
|
+
useEffect(() => {
|
|
7758
|
+
if (!defaultHandle || seededDefaultHandleRef.current === defaultHandle) return;
|
|
7759
|
+
seededDefaultHandleRef.current = defaultHandle;
|
|
7760
|
+
setHandle((current) => current ? current : defaultHandle);
|
|
7761
|
+
}, [defaultHandle]);
|
|
7657
7762
|
const [otp, setOtp] = useState(Array(OTP_INPUT_LENGTH).fill(""));
|
|
7658
7763
|
const [error, setError] = useState("");
|
|
7659
7764
|
const [copied, setCopied] = useState(false);
|
|
@@ -21940,6 +22045,6 @@ var SparklineChart = React9__default.memo(function SparklineChart2({ data, width
|
|
|
21940
22045
|
);
|
|
21941
22046
|
});
|
|
21942
22047
|
|
|
21943
|
-
export { AssetSelectorBar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ContactPopup, Header, HlsVideo, HousePositionSlider, HousePositionSliderMobile, LoafLiquidityBadge, LoafLiquidityLogo, LoginPopup, MobileTradeNav, OfferingProgressCard, OnboardingGuide, Orderbook, owner_booking_default as OwnerBooking, PaymentPopup, PortfolioActivityPanel, PortfolioSummary, PriceChart, PropertyBuy, PropertyCompareBar, PropertyDocuments, PropertyHeroHeader, PropertyHistory, PropertyInspectionTimes, PropertyMediaRow, PropertyNewsUpdates, PropertyOffers, PropertyOverview, PropertyPhotoGallery, PropertySubheader, PropertyTour, PropertyValuation, SentimentBar, SiteFooter, Skeleton, SlideDigit, SparklineChart, ToastProvider, TradeConfirmationModal, TradingSlider, YourOrders, __resetDismissedBreaking, badgeVariants, buttonVariants, extractSparkline, formatAge, hasPendingActivity, matchesTab, rowAgeLabel, useAdaptivePolling, useToast };
|
|
22048
|
+
export { AssetSelectorBar, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ContactPopup, Header, HlsVideo, HousePositionSlider, HousePositionSliderMobile, LoafLiquidityBadge, LoafLiquidityLogo, LoginPopup, MobileTradeNav, OfferingProgressCard, OnboardingGuide, Orderbook, owner_booking_default as OwnerBooking, PaymentPopup, PortfolioActivityPanel, PortfolioSummary, PriceChart, PropertyBuy, PropertyCompareBar, PropertyDocuments, PropertyHeroHeader, PropertyHistory, PropertyInspectionTimes, PropertyMediaRow, PropertyNewsUpdates, PropertyOffers, PropertyOverview, PropertyPhotoGallery, PropertySubheader, PropertyTour, PropertyValuation, SentimentBar, SiteFooter, Skeleton, SlideDigit, SparklineChart, ToastProvider, TradeConfirmationModal, TradingSlider, YourOrders, __reloadBreakingMemory, __resetDismissedBreaking, badgeVariants, buttonVariants, extractSparkline, formatAge, hasPendingActivity, matchesTab, rowAgeLabel, useAdaptivePolling, useToast };
|
|
21944
22049
|
//# sourceMappingURL=index.mjs.map
|
|
21945
22050
|
//# sourceMappingURL=index.mjs.map
|