@loafmarkets/ui 0.1.63 → 0.1.65

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
@@ -7,6 +7,7 @@ var clsx = require('clsx');
7
7
  var tailwindMerge = require('tailwind-merge');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var styled25 = require('styled-components');
10
+ var ReactDOM = require('react-dom');
10
11
  var lucideReact = require('lucide-react');
11
12
  var LightweightCharts = require('lightweight-charts');
12
13
  var bi = require('react-icons/bi');
@@ -35,6 +36,7 @@ function _interopNamespace(e) {
35
36
 
36
37
  var React5__namespace = /*#__PURE__*/_interopNamespace(React5);
37
38
  var styled25__default = /*#__PURE__*/_interopDefault(styled25);
39
+ var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM);
38
40
  var LightweightCharts__namespace = /*#__PURE__*/_interopNamespace(LightweightCharts);
39
41
 
40
42
  // src/components/button.tsx
@@ -2700,15 +2702,17 @@ var ensureAnimationsInjected = () => {
2700
2702
  50% { opacity: 1; transform: scale(1); }
2701
2703
  100% { opacity: 0.6; transform: scale(0.9); }
2702
2704
  }
2703
-
2704
2705
  @keyframes propertyNewsSlideIn {
2705
2706
  from { transform: translateY(-6px); opacity: 0; }
2706
2707
  to { transform: translateY(0); opacity: 1; }
2707
2708
  }
2708
-
2709
2709
  @keyframes propertyNewsSpin {
2710
2710
  to { transform: rotate(360deg); }
2711
2711
  }
2712
+ @keyframes propertyNewsModalIn {
2713
+ from { opacity: 0; transform: translateY(12px) scale(0.98); }
2714
+ to { opacity: 1; transform: translateY(0) scale(1); }
2715
+ }
2712
2716
  `;
2713
2717
  document.head.appendChild(style);
2714
2718
  };
@@ -2729,11 +2733,7 @@ var categoryStyles = {
2729
2733
  var formatDate = (value) => {
2730
2734
  if (typeof value === "string") return value;
2731
2735
  if (!(value instanceof Date) || Number.isNaN(value.getTime())) return "";
2732
- return value.toLocaleDateString(void 0, {
2733
- month: "short",
2734
- day: "numeric",
2735
- year: "numeric"
2736
- });
2736
+ return value.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" });
2737
2737
  };
2738
2738
  var formatTimeAgo = (timestamp) => {
2739
2739
  const diff = (Date.now() - new Date(timestamp).getTime()) / 1e3;
@@ -2741,6 +2741,144 @@ var formatTimeAgo = (timestamp) => {
2741
2741
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
2742
2742
  return `${Math.floor(diff / 3600)}h ago`;
2743
2743
  };
2744
+ function getSentimentInfo(score) {
2745
+ if (score == null) return null;
2746
+ if (score > 0.15) return { arrow: "\u25B2", label: "Bullish", color: "#0ecb81" };
2747
+ if (score < -0.15) return { arrow: "\u25BC", label: "Bearish", color: "#f6465d" };
2748
+ return { arrow: "\u2014", label: "Neutral", color: "#848e9c" };
2749
+ }
2750
+ function NewsArticleModal({ item, onClose }) {
2751
+ const sentimentInfo = getSentimentInfo(item.sentimentScore);
2752
+ const catStyle = categoryStyles[item.type] ?? categoryStyles.market;
2753
+ React5__namespace.useEffect(() => {
2754
+ const handler = (e) => {
2755
+ if (e.key === "Escape") onClose();
2756
+ };
2757
+ document.addEventListener("keydown", handler);
2758
+ document.body.style.overflow = "hidden";
2759
+ return () => {
2760
+ document.removeEventListener("keydown", handler);
2761
+ document.body.style.overflow = "";
2762
+ };
2763
+ }, [onClose]);
2764
+ const modal = /* @__PURE__ */ jsxRuntime.jsx(
2765
+ "div",
2766
+ {
2767
+ style: {
2768
+ position: "fixed",
2769
+ inset: 0,
2770
+ background: "rgba(0,0,0,0.72)",
2771
+ zIndex: 9999,
2772
+ display: "flex",
2773
+ alignItems: "center",
2774
+ justifyContent: "center",
2775
+ padding: "1rem"
2776
+ },
2777
+ onClick: onClose,
2778
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2779
+ "div",
2780
+ {
2781
+ style: {
2782
+ background: "#1c1c1c",
2783
+ border: "1px solid rgba(255,255,255,0.12)",
2784
+ borderRadius: "14px",
2785
+ padding: "1.5rem",
2786
+ maxWidth: "540px",
2787
+ width: "100%",
2788
+ maxHeight: "80vh",
2789
+ overflowY: "auto",
2790
+ boxShadow: "0 24px 64px rgba(0,0,0,0.6)",
2791
+ animation: "propertyNewsModalIn 0.22s ease-out"
2792
+ },
2793
+ onClick: (e) => e.stopPropagation(),
2794
+ children: [
2795
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "flex-end", marginBottom: "0.75rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2796
+ "button",
2797
+ {
2798
+ type: "button",
2799
+ onClick: onClose,
2800
+ style: {
2801
+ background: "rgba(255,255,255,0.07)",
2802
+ border: "none",
2803
+ borderRadius: "6px",
2804
+ cursor: "pointer",
2805
+ color: "rgba(255,255,255,0.6)",
2806
+ padding: "0.3rem 0.5rem",
2807
+ lineHeight: 1,
2808
+ display: "flex",
2809
+ alignItems: "center"
2810
+ },
2811
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) })
2812
+ }
2813
+ ) }),
2814
+ sentimentInfo && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginBottom: "0.6rem" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
2815
+ "span",
2816
+ {
2817
+ style: {
2818
+ display: "inline-flex",
2819
+ alignItems: "center",
2820
+ gap: "0.3rem",
2821
+ fontSize: "0.7rem",
2822
+ fontWeight: 700,
2823
+ color: sentimentInfo.color,
2824
+ padding: "0.2rem 0.55rem",
2825
+ borderRadius: "4px",
2826
+ background: `${sentimentInfo.color}1a`,
2827
+ border: `1px solid ${sentimentInfo.color}40`
2828
+ },
2829
+ children: [
2830
+ sentimentInfo.arrow,
2831
+ " ",
2832
+ sentimentInfo.label
2833
+ ]
2834
+ }
2835
+ ) }),
2836
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { style: { fontSize: "1rem", fontWeight: 600, color: "#fff", lineHeight: 1.5, margin: "0 0 1rem" }, children: item.title }),
2837
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center", flexWrap: "wrap", marginBottom: "1.25rem" }, children: [
2838
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.72rem", color: "#848e9c" }, children: typeof item.date === "string" ? item.date : formatDate(item.date) }),
2839
+ item.source && /* @__PURE__ */ jsxRuntime.jsx(
2840
+ "span",
2841
+ {
2842
+ style: {
2843
+ padding: "0.15rem 0.45rem",
2844
+ borderRadius: "3px",
2845
+ fontSize: "0.65rem",
2846
+ fontWeight: 500,
2847
+ background: "rgba(255,255,255,0.07)",
2848
+ color: "#848e9c"
2849
+ },
2850
+ children: item.source
2851
+ }
2852
+ ),
2853
+ /* @__PURE__ */ jsxRuntime.jsx(
2854
+ "span",
2855
+ {
2856
+ style: {
2857
+ padding: "0.2rem 0.55rem",
2858
+ borderRadius: "4px",
2859
+ border: `1px solid ${catStyle.borderColor}`,
2860
+ background: catStyle.backgroundColor,
2861
+ color: catStyle.color,
2862
+ fontSize: "0.65rem",
2863
+ fontWeight: 600,
2864
+ textTransform: "uppercase"
2865
+ },
2866
+ children: item.type === "property" ? catStyle.label : "Market News"
2867
+ }
2868
+ )
2869
+ ] }),
2870
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "1px", background: "rgba(255,255,255,0.08)", marginBottom: "1.25rem" } }),
2871
+ item.summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: "rgba(255,255,255,0.8)", lineHeight: 1.75, margin: 0 }, children: item.summary }) : /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8rem", color: "rgba(255,255,255,0.35)", fontStyle: "italic", margin: 0 }, children: "Summary not available for this article." })
2872
+ ]
2873
+ }
2874
+ )
2875
+ }
2876
+ );
2877
+ if (typeof document !== "undefined") {
2878
+ return ReactDOM__namespace.createPortal(modal, document.body);
2879
+ }
2880
+ return modal;
2881
+ }
2744
2882
  var PropertyNewsUpdates = React5__namespace.forwardRef(
2745
2883
  ({
2746
2884
  className,
@@ -2763,6 +2901,8 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2763
2901
  const [homePage, setHomePage] = React5__namespace.useState(0);
2764
2902
  const purchaseItems = purchasesProp ?? [];
2765
2903
  const [page, setPage] = React5__namespace.useState(0);
2904
+ const [expandedId, setExpandedId] = React5__namespace.useState(null);
2905
+ const [selectedItem, setSelectedItem] = React5__namespace.useState(null);
2766
2906
  React5__namespace.useEffect(() => {
2767
2907
  ensureAnimationsInjected();
2768
2908
  }, []);
@@ -2770,7 +2910,10 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2770
2910
  setHomePage(0);
2771
2911
  }, [homeTab]);
2772
2912
  const hasItems = Array.isArray(items) && items.length > 0;
2773
- const totalPages = React5__namespace.useMemo(() => hasItems ? Math.max(1, Math.ceil(items.length / ITEMS_PER_PAGE)) : 1, [hasItems, items.length]);
2913
+ const totalPages = React5__namespace.useMemo(
2914
+ () => hasItems ? Math.max(1, Math.ceil(items.length / ITEMS_PER_PAGE)) : 1,
2915
+ [hasItems, items.length]
2916
+ );
2774
2917
  React5__namespace.useEffect(() => {
2775
2918
  setPage((prev) => Math.min(prev, totalPages - 1));
2776
2919
  }, [totalPages]);
@@ -2784,6 +2927,9 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2784
2927
  [homeFilteredItems.length]
2785
2928
  );
2786
2929
  const homePaginatedItems = homeFilteredItems.slice(homePage * ITEMS_PER_PAGE, (homePage + 1) * ITEMS_PER_PAGE);
2930
+ const toggleExpand = React5__namespace.useCallback((key) => {
2931
+ setExpandedId((prev) => prev === key ? null : key);
2932
+ }, []);
2787
2933
  return /* @__PURE__ */ jsxRuntime.jsxs(
2788
2934
  "div",
2789
2935
  {
@@ -2797,89 +2943,22 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2797
2943
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2798
2944
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [
2799
2945
  isHomeVariant && /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", style: { color: "var(--color-text, #fff)" }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z" }) }),
2800
- isPurchaseVariant && /* @__PURE__ */ jsxRuntime.jsx(
2801
- "span",
2802
- {
2803
- style: {
2804
- display: "inline-block",
2805
- width: "8px",
2806
- height: "8px",
2807
- borderRadius: "50%",
2808
- backgroundColor: "#0ecb81",
2809
- boxShadow: "0 0 8px rgba(14,203,129,0.8)",
2810
- animation: "propertyNewsPulse 1.5s infinite"
2811
- }
2812
- }
2813
- ),
2946
+ isPurchaseVariant && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "8px", height: "8px", borderRadius: "50%", backgroundColor: "#0ecb81", boxShadow: "0 0 8px rgba(14,203,129,0.8)", animation: "propertyNewsPulse 1.5s infinite" } }),
2814
2947
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2815
2948
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: isHomeVariant ? "text-base font-semibold text-white" : "text-lg font-semibold text-white", children: resolvedHeading }),
2816
2949
  subheading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/60", children: subheading }) : null
2817
2950
  ] })
2818
2951
  ] }),
2819
- isHomeVariant && viewAllHref ? /* @__PURE__ */ jsxRuntime.jsxs(
2820
- "a",
2821
- {
2822
- href: viewAllHref,
2823
- style: {
2824
- color: "var(--color-accent, #f0b90b)",
2825
- fontWeight: 500,
2826
- fontSize: "0.8rem",
2827
- textDecoration: "none",
2828
- display: "flex",
2829
- alignItems: "center",
2830
- gap: "0.25rem"
2831
- },
2832
- children: [
2833
- viewAllLabel,
2834
- /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" }) })
2835
- ]
2836
- }
2837
- ) : !isHomeVariant && !isPurchaseVariant ? connectionStatus === "connecting" ? /* @__PURE__ */ jsxRuntime.jsxs(
2838
- "div",
2839
- {
2840
- className: "inline-flex items-center font-semibold uppercase",
2841
- style: { gap: "0.35rem", fontSize: "0.8rem", letterSpacing: "0.15em", color: "#f97316" },
2842
- children: [
2843
- /* @__PURE__ */ jsxRuntime.jsx(
2844
- "span",
2845
- {
2846
- style: {
2847
- display: "inline-block",
2848
- width: "10px",
2849
- height: "10px",
2850
- borderRadius: "50%",
2851
- border: "2px solid rgba(249,115,22,0.3)",
2852
- borderTopColor: "#f97316",
2853
- animation: "propertyNewsSpin 0.8s linear infinite"
2854
- }
2855
- }
2856
- ),
2857
- "CONNECTING"
2858
- ]
2859
- }
2860
- ) : /* @__PURE__ */ jsxRuntime.jsxs(
2861
- "div",
2862
- {
2863
- className: "inline-flex items-center font-semibold uppercase text-emerald-300",
2864
- style: { gap: "0.35rem", fontSize: "0.8rem", letterSpacing: "0.15em" },
2865
- children: [
2866
- /* @__PURE__ */ jsxRuntime.jsx(
2867
- "span",
2868
- {
2869
- style: {
2870
- display: "inline-block",
2871
- width: "6px",
2872
- height: "6px",
2873
- borderRadius: "50%",
2874
- backgroundColor: "#34d399",
2875
- animation: "propertyNewsPulse 2s infinite"
2876
- }
2877
- }
2878
- ),
2879
- "LIVE"
2880
- ]
2881
- }
2882
- ) : null
2952
+ isHomeVariant && viewAllHref ? /* @__PURE__ */ jsxRuntime.jsxs("a", { href: viewAllHref, style: { color: "var(--color-accent, #f0b90b)", fontWeight: 500, fontSize: "0.8rem", textDecoration: "none", display: "flex", alignItems: "center", gap: "0.25rem" }, children: [
2953
+ viewAllLabel,
2954
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" }) })
2955
+ ] }) : !isHomeVariant && !isPurchaseVariant ? connectionStatus === "connecting" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center font-semibold uppercase", style: { gap: "0.35rem", fontSize: "0.8rem", letterSpacing: "0.15em", color: "#f97316" }, children: [
2956
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "10px", height: "10px", borderRadius: "50%", border: "2px solid rgba(249,115,22,0.3)", borderTopColor: "#f97316", animation: "propertyNewsSpin 0.8s linear infinite" } }),
2957
+ "CONNECTING"
2958
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center font-semibold uppercase text-emerald-300", style: { gap: "0.35rem", fontSize: "0.8rem", letterSpacing: "0.15em" }, children: [
2959
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-block", width: "6px", height: "6px", borderRadius: "50%", backgroundColor: "#34d399", animation: "propertyNewsPulse 2s infinite" } }),
2960
+ "LIVE"
2961
+ ] }) : null
2883
2962
  ] }),
2884
2963
  isHomeVariant && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", gap: 0, marginTop: "0.75rem", marginBottom: "0.25rem" }, children: ["all", "property", "market"].map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
2885
2964
  "button",
@@ -2904,8 +2983,8 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2904
2983
  /* @__PURE__ */ jsxRuntime.jsx(
2905
2984
  "div",
2906
2985
  {
2907
- className: "mt-4 flex flex-1 flex-col gap-3 overflow-visible",
2908
- style: !isPurchaseVariant && !isHomeVariant ? { minHeight: `${ITEMS_PER_PAGE * 88}px` } : void 0,
2986
+ className: "mt-4 flex flex-1 flex-col gap-3 overflow-hidden",
2987
+ style: !isPurchaseVariant && !isHomeVariant ? { minHeight: `${ITEMS_PER_PAGE * 86}px` } : void 0,
2909
2988
  children: isPurchaseVariant ? purchaseItems.length > 0 ? purchaseItems.slice(0, 7).map((purchase, index) => {
2910
2989
  const maxAmount = 6e4;
2911
2990
  const barPercent = Math.min(85, Math.max(15, purchase.amount / maxAmount * 100));
@@ -2913,31 +2992,9 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2913
2992
  return /* @__PURE__ */ jsxRuntime.jsxs(
2914
2993
  "div",
2915
2994
  {
2916
- style: {
2917
- display: "flex",
2918
- justifyContent: "space-between",
2919
- alignItems: "center",
2920
- padding: "0.625rem 0.75rem",
2921
- borderBottom: "1px solid rgba(255,255,255,0.05)",
2922
- position: "relative",
2923
- overflow: "hidden",
2924
- backgroundColor: isAlternate ? "rgba(255,255,255,0.03)" : "transparent"
2925
- },
2995
+ style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0.625rem 0.75rem", borderBottom: "1px solid rgba(255,255,255,0.05)", position: "relative", overflow: "hidden", backgroundColor: isAlternate ? "rgba(255,255,255,0.03)" : "transparent" },
2926
2996
  children: [
2927
- /* @__PURE__ */ jsxRuntime.jsx(
2928
- "div",
2929
- {
2930
- style: {
2931
- position: "absolute",
2932
- top: 0,
2933
- right: 0,
2934
- bottom: 0,
2935
- width: `${barPercent}%`,
2936
- background: "linear-gradient(90deg, transparent 0%, rgba(14,203,129,0.15) 100%)",
2937
- pointerEvents: "none"
2938
- }
2939
- }
2940
- ),
2997
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", top: 0, right: 0, bottom: 0, width: `${barPercent}%`, background: "linear-gradient(90deg, transparent 0%, rgba(14,203,129,0.15) 100%)", pointerEvents: "none" } }),
2941
2998
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", minWidth: 0, position: "relative" }, children: [
2942
2999
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, fontSize: "0.875rem", color: "#fff", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: purchase.name }),
2943
3000
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.7rem", color: "var(--color-text-secondary, #848e9c)", marginTop: "0.125rem" }, children: formatTimeAgo(purchase.timestamp) })
@@ -2951,77 +3008,43 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
2951
3008
  purchase.id
2952
3009
  );
2953
3010
  }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", padding: "3rem 0", gap: "0.75rem" }, children: [
2954
- /* @__PURE__ */ jsxRuntime.jsx(
2955
- "div",
2956
- {
2957
- style: {
2958
- width: "28px",
2959
- height: "28px",
2960
- border: "3px solid rgba(255,255,255,0.1)",
2961
- borderTopColor: "var(--color-accent, #f0b90b)",
2962
- borderRadius: "50%",
2963
- animation: "propertyNewsSpin 1s linear infinite"
2964
- }
2965
- }
2966
- ),
3011
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "28px", height: "28px", border: "3px solid rgba(255,255,255,0.1)", borderTopColor: "var(--color-accent, #f0b90b)", borderRadius: "50%", animation: "propertyNewsSpin 1s linear infinite" } }),
2967
3012
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.8rem", color: "rgba(255,255,255,0.4)" }, children: "Awaiting offering..." })
2968
3013
  ] }) : isHomeVariant ? hasItems ? homePaginatedItems.map((item, index) => {
2969
3014
  const key = item.displayId ?? item.id ?? `${item.title}-${index}`;
2970
- const tagType = item.type;
2971
- const isProperty = tagType === "property";
3015
+ const isProperty = item.type === "property";
3016
+ const sentimentInfo = getSentimentInfo(item.sentimentScore);
3017
+ const isExpanded = expandedId === key;
2972
3018
  return /* @__PURE__ */ jsxRuntime.jsxs(
2973
- "a",
3019
+ "div",
2974
3020
  {
2975
- href: item.url ?? "#",
2976
- target: "_blank",
2977
- rel: "noopener noreferrer",
2978
- style: {
2979
- display: "flex",
2980
- justifyContent: "space-between",
2981
- alignItems: "center",
2982
- padding: "0.75rem 0",
2983
- borderBottom: index < homePaginatedItems.length - 1 ? "1px solid rgba(255,255,255,0.05)" : "none",
2984
- cursor: "pointer",
2985
- textDecoration: "none",
2986
- color: "inherit"
2987
- },
3021
+ style: { padding: "0.75rem 0", borderBottom: index < homePaginatedItems.length - 1 ? "1px solid rgba(255,255,255,0.05)" : "none" },
2988
3022
  children: [
2989
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
2990
- /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "0.85rem", fontWeight: 400, marginBottom: "0.25rem", color: "#f8f9fa", lineHeight: 1.4 }, children: item.title }),
2991
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center", flexWrap: "wrap" }, children: [
2992
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#848e9c", fontSize: "0.7rem" }, children: typeof item.date === "string" ? item.date : formatDate(item.date) }),
2993
- item.source && /* @__PURE__ */ jsxRuntime.jsx(
2994
- "span",
2995
- {
2996
- style: {
2997
- padding: "0.1rem 0.4rem",
2998
- borderRadius: "3px",
2999
- fontSize: "0.62rem",
3000
- fontWeight: 500,
3001
- backgroundColor: "rgba(255,255,255,0.07)",
3002
- color: "#848e9c",
3003
- whiteSpace: "nowrap"
3004
- },
3005
- children: item.source
3006
- }
3007
- ),
3008
- /* @__PURE__ */ jsxRuntime.jsx(
3009
- "span",
3010
- {
3011
- style: {
3012
- padding: "0.15rem 0.4rem",
3013
- borderRadius: "2px",
3014
- fontSize: "0.65rem",
3015
- fontWeight: 500,
3016
- backgroundColor: isProperty ? "rgba(14,203,129,0.1)" : "rgba(240,185,11,0.1)",
3017
- color: isProperty ? "#0ecb81" : "#f0b90b"
3018
- },
3019
- children: isProperty ? "Property Update" : "Market News"
3020
- }
3021
- )
3022
- ] })
3023
- ] }),
3024
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", color: "#848e9c", marginLeft: "0.5rem" }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z" }) }) })
3023
+ /* @__PURE__ */ jsxRuntime.jsxs(
3024
+ "button",
3025
+ {
3026
+ type: "button",
3027
+ onClick: () => toggleExpand(key),
3028
+ style: { width: "100%", textAlign: "left", background: "transparent", border: "none", cursor: "pointer", padding: 0, display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: "0.5rem", color: "inherit" },
3029
+ children: [
3030
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1 }, children: [
3031
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { style: { fontSize: "0.85rem", fontWeight: 400, marginBottom: "0.25rem", color: "#f8f9fa", lineHeight: 1.4 }, children: item.title }),
3032
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center", flexWrap: "wrap" }, children: [
3033
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#848e9c", fontSize: "0.7rem" }, children: typeof item.date === "string" ? item.date : formatDate(item.date) }),
3034
+ item.source && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { padding: "0.1rem 0.4rem", borderRadius: "3px", fontSize: "0.62rem", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.07)", color: "#848e9c", whiteSpace: "nowrap" }, children: item.source }),
3035
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { padding: "0.15rem 0.4rem", borderRadius: "2px", fontSize: "0.65rem", fontWeight: 500, backgroundColor: isProperty ? "rgba(14,203,129,0.1)" : "rgba(240,185,11,0.1)", color: isProperty ? "#0ecb81" : "#f0b90b" }, children: isProperty ? "Property Update" : "Market News" }),
3036
+ sentimentInfo && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.65rem", fontWeight: 600, color: sentimentInfo.color }, children: [
3037
+ sentimentInfo.arrow,
3038
+ " ",
3039
+ sentimentInfo.label
3040
+ ] })
3041
+ ] })
3042
+ ] }),
3043
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", color: "#848e9c", marginLeft: "0.5rem", paddingTop: "2px" }, children: /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", style: { transition: "transform 0.2s", transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)" }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z" }) }) })
3044
+ ]
3045
+ }
3046
+ ),
3047
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "0.625rem", padding: "0.75rem", background: "rgba(255,255,255,0.04)", borderRadius: "6px", borderLeft: `3px solid ${sentimentInfo?.color ?? "rgba(255,255,255,0.15)"}`, animation: "propertyNewsSlideIn 0.2s ease-out" }, children: item.summary ? /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8rem", color: "rgba(255,255,255,0.72)", lineHeight: 1.65, margin: 0 }, children: item.summary }) : /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.78rem", color: "rgba(255,255,255,0.35)", fontStyle: "italic", margin: 0 }, children: "Summary not available." }) })
3025
3048
  ]
3026
3049
  },
3027
3050
  key
@@ -3029,92 +3052,60 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
3029
3052
  }) : emptyState ?? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-center justify-center py-10 text-center text-sm text-white/60", children: "No property news yet." }) : hasItems ? paginatedItems.map((item, index) => {
3030
3053
  const absoluteIndex = page * ITEMS_PER_PAGE + index;
3031
3054
  const key = item.displayId ?? item.id ?? `${item.title}-${absoluteIndex}`;
3032
- const styles2 = categoryStyles[item.type] ?? categoryStyles.market;
3055
+ const catStyle = categoryStyles[item.type] ?? categoryStyles.market;
3033
3056
  const dateLabel = item.isNew ?? (highlightFirst && absoluteIndex === 0) ? "Just now" : typeof item.date === "string" && item.date.trim().length > 0 ? item.date : formatDate(item.date);
3034
3057
  const isHighlighted = item.isNew ?? (highlightFirst && absoluteIndex === 0);
3035
- return /* @__PURE__ */ jsxRuntime.jsxs(
3036
- "div",
3058
+ const sentimentInfo = getSentimentInfo(item.sentimentScore);
3059
+ return /* @__PURE__ */ jsxRuntime.jsx(
3060
+ "button",
3037
3061
  {
3062
+ type: "button",
3063
+ onClick: () => setSelectedItem(item),
3038
3064
  style: {
3039
- padding: "0.75rem",
3040
- borderRadius: "6px",
3041
- backgroundColor: isHighlighted ? "rgba(14, 203, 129, 0.1)" : "transparent",
3042
- border: "1px solid transparent",
3043
- transition: "background-color 0.2s",
3044
- animation: item.isNew ? "propertyNewsSlideIn 0.5s ease-out" : void 0
3065
+ display: "block",
3066
+ width: "100%",
3067
+ textAlign: "left",
3068
+ background: "transparent",
3069
+ border: "none",
3070
+ cursor: "pointer",
3071
+ padding: 0,
3072
+ color: "inherit"
3045
3073
  },
3046
- children: [
3047
- /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.9375rem", fontWeight: 500, marginBottom: "0.35rem", color: "#fff" }, children: item.url ? /* @__PURE__ */ jsxRuntime.jsx(
3048
- "a",
3049
- {
3050
- href: item.url,
3051
- target: "_blank",
3052
- rel: "noopener noreferrer",
3053
- style: { color: "inherit", textDecoration: "none" },
3054
- onMouseEnter: (e) => {
3055
- e.currentTarget.style.textDecoration = "underline";
3056
- },
3057
- onMouseLeave: (e) => {
3058
- e.currentTarget.style.textDecoration = "none";
3059
- },
3060
- children: item.title
3061
- }
3062
- ) : item.title }),
3063
- /* @__PURE__ */ jsxRuntime.jsxs(
3064
- "div",
3065
- {
3066
- style: {
3067
- display: "flex",
3068
- justifyContent: "space-between",
3069
- alignItems: "center",
3070
- fontSize: "0.75rem",
3071
- color: "#b5b8c5",
3072
- gap: "0.5rem"
3073
- },
3074
- children: [
3075
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", minWidth: 0 }, children: [
3076
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: isHighlighted ? "#0ecb81" : "inherit", whiteSpace: "nowrap" }, children: dateLabel }),
3077
- item.source && /* @__PURE__ */ jsxRuntime.jsx(
3078
- "span",
3079
- {
3080
- style: {
3081
- padding: "0.15rem 0.45rem",
3082
- borderRadius: "3px",
3083
- fontSize: "0.65rem",
3084
- fontWeight: 500,
3085
- backgroundColor: "rgba(255,255,255,0.07)",
3086
- color: "#848e9c",
3087
- whiteSpace: "nowrap",
3088
- overflow: "hidden",
3089
- textOverflow: "ellipsis",
3090
- maxWidth: "120px"
3091
- },
3092
- children: item.source
3093
- }
3094
- )
3074
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
3075
+ "div",
3076
+ {
3077
+ style: {
3078
+ padding: "0.75rem",
3079
+ borderRadius: "6px",
3080
+ backgroundColor: isHighlighted ? "rgba(14, 203, 129, 0.1)" : "transparent",
3081
+ transition: "background-color 0.15s",
3082
+ animation: item.isNew ? "propertyNewsSlideIn 0.5s ease-out" : void 0
3083
+ },
3084
+ onMouseEnter: (e) => {
3085
+ if (!isHighlighted) e.currentTarget.style.backgroundColor = "rgba(255,255,255,0.04)";
3086
+ },
3087
+ onMouseLeave: (e) => {
3088
+ if (!isHighlighted) e.currentTarget.style.backgroundColor = "transparent";
3089
+ },
3090
+ children: [
3091
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.9375rem", fontWeight: 500, marginBottom: "0.4rem", color: "#fff", lineHeight: 1.4 }, children: item.title }),
3092
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-end", gap: "0.5rem" }, children: [
3093
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem", minWidth: 0, flexWrap: "wrap" }, children: [
3094
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: "0.75rem", color: isHighlighted ? "#0ecb81" : "#b5b8c5", whiteSpace: "nowrap" }, children: dateLabel }),
3095
+ item.source && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { padding: "0.15rem 0.45rem", borderRadius: "3px", fontSize: "0.65rem", fontWeight: 500, backgroundColor: "rgba(255,255,255,0.07)", color: "#848e9c", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "120px" }, children: item.source })
3095
3096
  ] }),
3096
- /* @__PURE__ */ jsxRuntime.jsx(
3097
- "span",
3098
- {
3099
- style: {
3100
- padding: "0.25rem 0.6rem",
3101
- borderRadius: "4px",
3102
- border: `1px solid ${styles2.borderColor}`,
3103
- backgroundColor: styles2.backgroundColor,
3104
- color: styles2.color,
3105
- fontSize: "0.68rem",
3106
- fontWeight: 600,
3107
- textTransform: "uppercase",
3108
- whiteSpace: "nowrap",
3109
- flexShrink: 0
3110
- },
3111
- children: item.type === "property" ? styles2.label : "Market News"
3112
- }
3113
- )
3114
- ]
3115
- }
3116
- )
3117
- ]
3097
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: "0.3rem", flexShrink: 0 }, children: [
3098
+ sentimentInfo && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: "0.65rem", fontWeight: 700, color: sentimentInfo.color, whiteSpace: "nowrap" }, children: [
3099
+ sentimentInfo.arrow,
3100
+ " ",
3101
+ sentimentInfo.label
3102
+ ] }),
3103
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { padding: "0.25rem 0.6rem", borderRadius: "4px", border: `1px solid ${catStyle.borderColor}`, backgroundColor: catStyle.backgroundColor, color: catStyle.color, fontSize: "0.68rem", fontWeight: 600, textTransform: "uppercase", whiteSpace: "nowrap" }, children: item.type === "property" ? catStyle.label : "Market News" })
3104
+ ] })
3105
+ ] })
3106
+ ]
3107
+ }
3108
+ )
3118
3109
  },
3119
3110
  key
3120
3111
  );
@@ -3124,25 +3115,14 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
3124
3115
  ] })
3125
3116
  }
3126
3117
  ),
3127
- isHomeVariant && homeTotalPages > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-center justify-between text-xs text-white/60", children: [
3118
+ isHomeVariant && homeTotalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 flex items-center justify-between text-xs text-white/60", children: [
3128
3119
  /* @__PURE__ */ jsxRuntime.jsx(
3129
3120
  "button",
3130
3121
  {
3131
3122
  type: "button",
3132
- onClick: () => setHomePage((prev) => Math.max(0, prev - 1)),
3123
+ onClick: () => setHomePage((p) => Math.max(0, p - 1)),
3133
3124
  disabled: homePage === 0,
3134
- style: {
3135
- background: "transparent",
3136
- border: "1px solid rgba(255,255,255,0.15)",
3137
- borderRadius: "999px",
3138
- padding: "0.2rem 0.75rem",
3139
- fontSize: "0.7rem",
3140
- textTransform: "uppercase",
3141
- letterSpacing: "0.15em",
3142
- cursor: homePage === 0 ? "not-allowed" : "pointer",
3143
- opacity: homePage === 0 ? 0.4 : 1,
3144
- color: "rgba(255,255,255,0.6)"
3145
- },
3125
+ style: { background: "transparent", border: "1px solid rgba(255,255,255,0.15)", borderRadius: "999px", padding: "0.2rem 0.75rem", fontSize: "0.7rem", textTransform: "uppercase", letterSpacing: "0.15em", cursor: homePage === 0 ? "not-allowed" : "pointer", opacity: homePage === 0 ? 0.4 : 1, color: "rgba(255,255,255,0.6)" },
3146
3126
  children: "Prev"
3147
3127
  }
3148
3128
  ),
@@ -3155,35 +3135,21 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
3155
3135
  "button",
3156
3136
  {
3157
3137
  type: "button",
3158
- onClick: () => setHomePage((prev) => Math.min(homeTotalPages - 1, prev + 1)),
3138
+ onClick: () => setHomePage((p) => Math.min(homeTotalPages - 1, p + 1)),
3159
3139
  disabled: homePage >= homeTotalPages - 1,
3160
- style: {
3161
- background: "transparent",
3162
- border: "1px solid rgba(255,255,255,0.15)",
3163
- borderRadius: "999px",
3164
- padding: "0.2rem 0.75rem",
3165
- fontSize: "0.7rem",
3166
- textTransform: "uppercase",
3167
- letterSpacing: "0.15em",
3168
- cursor: homePage >= homeTotalPages - 1 ? "not-allowed" : "pointer",
3169
- opacity: homePage >= homeTotalPages - 1 ? 0.4 : 1,
3170
- color: "rgba(255,255,255,0.6)"
3171
- },
3140
+ style: { background: "transparent", border: "1px solid rgba(255,255,255,0.15)", borderRadius: "999px", padding: "0.2rem 0.75rem", fontSize: "0.7rem", textTransform: "uppercase", letterSpacing: "0.15em", cursor: homePage >= homeTotalPages - 1 ? "not-allowed" : "pointer", opacity: homePage >= homeTotalPages - 1 ? 0.4 : 1, color: "rgba(255,255,255,0.6)" },
3172
3141
  children: "Next"
3173
3142
  }
3174
3143
  )
3175
- ] }) : null,
3176
- !isPurchaseVariant && !isHomeVariant && hasItems && totalPages > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between text-xs text-white/60", children: [
3144
+ ] }),
3145
+ !isPurchaseVariant && !isHomeVariant && hasItems && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between text-xs text-white/60", children: [
3177
3146
  /* @__PURE__ */ jsxRuntime.jsx(
3178
3147
  "button",
3179
3148
  {
3180
3149
  type: "button",
3181
- onClick: () => setPage((prev) => Math.max(0, prev - 1)),
3150
+ onClick: () => setPage((p) => Math.max(0, p - 1)),
3182
3151
  disabled: page === 0,
3183
- className: cn(
3184
- "rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]",
3185
- page === 0 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"
3186
- ),
3152
+ className: cn("rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]", page === 0 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"),
3187
3153
  children: "Prev"
3188
3154
  }
3189
3155
  ),
@@ -3197,16 +3163,14 @@ var PropertyNewsUpdates = React5__namespace.forwardRef(
3197
3163
  "button",
3198
3164
  {
3199
3165
  type: "button",
3200
- onClick: () => setPage((prev) => Math.min(totalPages - 1, prev + 1)),
3166
+ onClick: () => setPage((p) => Math.min(totalPages - 1, p + 1)),
3201
3167
  disabled: page >= totalPages - 1,
3202
- className: cn(
3203
- "rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]",
3204
- page >= totalPages - 1 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"
3205
- ),
3168
+ className: cn("rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]", page >= totalPages - 1 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"),
3206
3169
  children: "Next"
3207
3170
  }
3208
3171
  )
3209
- ] }) : null
3172
+ ] }),
3173
+ selectedItem && !isHomeVariant && !isPurchaseVariant && /* @__PURE__ */ jsxRuntime.jsx(NewsArticleModal, { item: selectedItem, onClose: () => setSelectedItem(null) })
3210
3174
  ]
3211
3175
  }
3212
3176
  );