@loafmarkets/ui 0.0.6 → 0.0.8

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
@@ -168,8 +168,8 @@ var PortfolioSummary = React5__namespace.forwardRef(
168
168
  onResetAccount,
169
169
  positionsHeading = "Current Positions",
170
170
  emptyPositionsText = "No positions yet. Start trading to build your portfolio!",
171
- formatCurrency = defaultFormatCurrency,
172
- formatPercent = defaultFormatPercent,
171
+ formatCurrency: formatCurrency2 = defaultFormatCurrency,
172
+ formatPercent: formatPercent2 = defaultFormatPercent,
173
173
  formatSignedCurrency = defaultFormatSignedCurrency,
174
174
  className,
175
175
  children,
@@ -206,15 +206,15 @@ var PortfolioSummary = React5__namespace.forwardRef(
206
206
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
207
207
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
208
208
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-[0.5px] text-white/50", children: "Available Cash" }),
209
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[1.25rem] font-semibold text-white", children: formatCurrency(availableCash) })
209
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[1.25rem] font-semibold text-white", children: formatCurrency2(availableCash) })
210
210
  ] }),
211
211
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
212
212
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-[0.5px] text-white/50", children: "Portfolio Value" }),
213
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[1.25rem] font-semibold text-white", children: formatCurrency(portfolioValue) })
213
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[1.25rem] font-semibold text-white", children: formatCurrency2(portfolioValue) })
214
214
  ] }),
215
215
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
216
216
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-[0.5px] text-white/50", children: "Total Return" }),
217
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-1 text-[1.25rem] font-semibold", totalReturnClassName), children: formatPercent(totalReturnPercent) })
217
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-1 text-[1.25rem] font-semibold", totalReturnClassName), children: formatPercent2(totalReturnPercent) })
218
218
  ] }),
219
219
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
220
220
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs uppercase tracking-[0.5px] text-white/50", children: "Unrealized P&L" }),
@@ -841,6 +841,9 @@ function DepthRow({
841
841
  ] });
842
842
  }
843
843
  var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
844
+ var LEVEL_ROWS_VISIBLE = 6;
845
+ var DEPTH_ROW_HEIGHT_PX = 34;
846
+ var SECTION_HEIGHT = LEVEL_ROWS_VISIBLE * DEPTH_ROW_HEIGHT_PX;
844
847
  var Orderbook = React5__namespace.forwardRef(
845
848
  ({
846
849
  asks,
@@ -981,18 +984,25 @@ var Orderbook = React5__namespace.forwardRef(
981
984
  ] }, `${trade.type}-${trade.price}-${trade.amount}-${trade.time ?? i}`)) })
982
985
  }
983
986
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
984
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: asks.map((l, idx) => /* @__PURE__ */ jsxRuntime.jsx(
985
- DepthRow,
987
+ /* @__PURE__ */ jsxRuntime.jsx(
988
+ "div",
986
989
  {
987
- side: "ask",
988
- price: l.price,
989
- amount: l.amount,
990
- depthPct: (l.depth ?? l.amount) / maxAskDepth * 100,
991
- precision,
992
- amountPrecision
993
- },
994
- `ask-${idx}-${l.price}-${l.amount}`
995
- )) }),
990
+ className: "divide-y divide-white/5 overflow-y-auto",
991
+ style: { height: `${SECTION_HEIGHT}px`, scrollbarGutter: "stable" },
992
+ children: asks.map((l, idx) => /* @__PURE__ */ jsxRuntime.jsx(
993
+ DepthRow,
994
+ {
995
+ side: "ask",
996
+ price: l.price,
997
+ amount: l.amount,
998
+ depthPct: (l.depth ?? l.amount) / maxAskDepth * 100,
999
+ precision,
1000
+ amountPrecision
1001
+ },
1002
+ `ask-${idx}-${l.price}-${l.amount}`
1003
+ ))
1004
+ }
1005
+ ),
996
1006
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 grid grid-cols-2 items-center gap-3 bg-[#0b1a24] px-3 py-2", children: [
997
1007
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-lg font-semibold tabular-nums", midClass), children: [
998
1008
  "$",
@@ -1005,18 +1015,25 @@ var Orderbook = React5__namespace.forwardRef(
1005
1015
  ] }),
1006
1016
  /* @__PURE__ */ jsxRuntime.jsx("div", {})
1007
1017
  ] }),
1008
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-white/5", children: bids.map((l, idx) => /* @__PURE__ */ jsxRuntime.jsx(
1009
- DepthRow,
1018
+ /* @__PURE__ */ jsxRuntime.jsx(
1019
+ "div",
1010
1020
  {
1011
- side: "bid",
1012
- price: l.price,
1013
- amount: l.amount,
1014
- depthPct: (l.depth ?? l.amount) / maxBidDepth * 100,
1015
- precision,
1016
- amountPrecision
1017
- },
1018
- `bid-${idx}-${l.price}-${l.amount}`
1019
- )) })
1021
+ className: "divide-y divide-white/5 overflow-y-auto",
1022
+ style: { height: `${SECTION_HEIGHT}px`, scrollbarGutter: "stable" },
1023
+ children: bids.map((l, idx) => /* @__PURE__ */ jsxRuntime.jsx(
1024
+ DepthRow,
1025
+ {
1026
+ side: "bid",
1027
+ price: l.price,
1028
+ amount: l.amount,
1029
+ depthPct: (l.depth ?? l.amount) / maxBidDepth * 100,
1030
+ precision,
1031
+ amountPrecision
1032
+ },
1033
+ `bid-${idx}-${l.price}-${l.amount}`
1034
+ ))
1035
+ }
1036
+ )
1020
1037
  ] })
1021
1038
  ] })
1022
1039
  ]
@@ -1118,132 +1135,208 @@ var PropertyTour = React5__namespace.forwardRef(
1118
1135
  }
1119
1136
  );
1120
1137
  PropertyTour.displayName = "PropertyTour";
1121
- var TYPE_META = {
1138
+ var ITEMS_PER_PAGE = 4;
1139
+ var ROW_HEIGHT_PX = 86;
1140
+ var ensureAnimationsInjected = () => {
1141
+ if (typeof document === "undefined") return;
1142
+ if (document.getElementById("property-news-updates-animations")) return;
1143
+ const style = document.createElement("style");
1144
+ style.id = "property-news-updates-animations";
1145
+ style.textContent = `
1146
+ @keyframes propertyNewsPulse {
1147
+ 0% { opacity: 0.6; transform: scale(0.9); }
1148
+ 50% { opacity: 1; transform: scale(1); }
1149
+ 100% { opacity: 0.6; transform: scale(0.9); }
1150
+ }
1151
+
1152
+ @keyframes propertyNewsSlideIn {
1153
+ from { transform: translateY(-6px); opacity: 0; }
1154
+ to { transform: translateY(0); opacity: 1; }
1155
+ }
1156
+ `;
1157
+ document.head.appendChild(style);
1158
+ };
1159
+ var categoryStyles = {
1122
1160
  property: {
1123
1161
  label: "Property Update",
1124
- accent: "#f8d12f",
1125
- pillBg: "rgba(248, 209, 47, 0.12)",
1126
- pillBorder: "rgba(248, 209, 47, 0.45)",
1127
- pillColor: "#f8d12f",
1128
- icon: lucideReact.Building2
1162
+ backgroundColor: "rgba(14, 203, 129, 0.15)",
1163
+ borderColor: "rgba(14, 203, 129, 0.45)",
1164
+ color: "#0ecb81"
1129
1165
  },
1130
1166
  market: {
1131
- label: "Market Insight",
1132
- accent: "#0ecb81",
1133
- pillBg: "rgba(14, 203, 129, 0.12)",
1134
- pillBorder: "rgba(14, 203, 129, 0.45)",
1135
- pillColor: "#0ecb81",
1136
- icon: lucideReact.LineChart
1137
- },
1138
- portfolio: {
1139
- label: "Portfolio Signal",
1140
- accent: "#6c8cff",
1141
- pillBg: "rgba(108, 140, 255, 0.12)",
1142
- pillBorder: "rgba(108, 140, 255, 0.45)",
1143
- pillColor: "#c9d5ff",
1144
- icon: lucideReact.Sparkles
1167
+ label: "Market News",
1168
+ backgroundColor: "rgba(248, 209, 47, 0.15)",
1169
+ borderColor: "rgba(248, 209, 47, 0.45)",
1170
+ color: "#f8d12f"
1145
1171
  }
1146
1172
  };
1147
- var getTypeMeta = (type) => {
1148
- if (!type) return TYPE_META.property;
1149
- const key = type;
1150
- if (key in TYPE_META) return TYPE_META[key];
1151
- return {
1152
- label: type.toString(),
1153
- accent: "#f5f5f5",
1154
- pillBg: "rgba(255,255,255,0.08)",
1155
- pillBorder: "rgba(255,255,255,0.25)",
1156
- pillColor: "#ffffff",
1157
- icon: lucideReact.Newspaper
1158
- };
1159
- };
1160
1173
  var formatDate = (value) => {
1161
- const date = typeof value === "string" ? new Date(value) : value;
1162
- if (Number.isNaN(date.getTime())) return typeof value === "string" ? value : "";
1163
- return date.toLocaleDateString(void 0, {
1174
+ if (typeof value === "string") return value;
1175
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) return "";
1176
+ return value.toLocaleDateString(void 0, {
1164
1177
  month: "short",
1165
1178
  day: "numeric",
1166
1179
  year: "numeric"
1167
1180
  });
1168
1181
  };
1169
1182
  var PropertyNewsUpdates = React5__namespace.forwardRef(
1170
- ({ className, heading = "Latest property intelligence", subheading, items, emptyState, ...props }, ref) => {
1183
+ ({
1184
+ className,
1185
+ heading = "Property News & Headlines",
1186
+ subheading,
1187
+ items,
1188
+ emptyState,
1189
+ highlightFirst = true,
1190
+ ...props
1191
+ }, ref) => {
1192
+ const [page, setPage] = React5__namespace.useState(0);
1193
+ React5__namespace.useEffect(() => {
1194
+ ensureAnimationsInjected();
1195
+ }, []);
1171
1196
  const hasItems = Array.isArray(items) && items.length > 0;
1197
+ const totalPages = React5__namespace.useMemo(() => hasItems ? Math.max(1, Math.ceil(items.length / ITEMS_PER_PAGE)) : 1, [hasItems, items.length]);
1198
+ React5__namespace.useEffect(() => {
1199
+ setPage((prev) => Math.min(prev, totalPages - 1));
1200
+ }, [totalPages]);
1201
+ const paginatedItems = hasItems ? items.slice(page * ITEMS_PER_PAGE, page * ITEMS_PER_PAGE + ITEMS_PER_PAGE) : [];
1172
1202
  return /* @__PURE__ */ jsxRuntime.jsxs(
1173
1203
  "div",
1174
1204
  {
1175
1205
  ref,
1176
1206
  className: cn(
1177
- "w-full max-w-[480px] rounded-[20px] border border-white/10 bg-gradient-to-br from-[#06090f] via-[#0f1621] to-[#111b2a] p-6 text-white shadow-[0_30px_80px_rgba(3,7,18,0.65)] backdrop-blur-xl",
1207
+ "w-full max-w-[840px] rounded-2xl border border-white/10 bg-[#0b0e10] p-5 text-white shadow-[0_20px_40px_rgba(0,0,0,0.35)]",
1178
1208
  className
1179
1209
  ),
1180
1210
  ...props,
1181
1211
  children: [
1182
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1183
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.85rem] uppercase tracking-[0.25em] text-white/50", children: heading }),
1184
- subheading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/60", children: subheading }) : null
1185
- ] }),
1186
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-5 flex flex-col gap-4", children: hasItems ? items.map((item, index) => {
1187
- const meta = getTypeMeta(item.type);
1188
- const Icon = meta.icon;
1189
- const key = item.id ?? `${item.title}-${index}`;
1190
- const content = /* @__PURE__ */ jsxRuntime.jsxs(
1212
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
1213
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1214
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg font-semibold text-white", children: heading }),
1215
+ subheading ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-white/60", children: subheading }) : null
1216
+ ] }),
1217
+ /* @__PURE__ */ jsxRuntime.jsxs(
1191
1218
  "div",
1192
1219
  {
1193
- className: "relative flex w-full gap-4 rounded-2xl border border-white/5 bg-white/[0.04] p-4 transition hover:border-white/15 hover:bg-white/[0.06]",
1220
+ className: "inline-flex items-center font-semibold uppercase text-emerald-300",
1221
+ style: { gap: "0.35rem", fontSize: "0.8rem", letterSpacing: "0.15em" },
1194
1222
  children: [
1195
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center", children: [
1196
- /* @__PURE__ */ jsxRuntime.jsx(
1197
- "div",
1198
- {
1199
- className: "flex h-12 w-12 items-center justify-center rounded-full border text-white",
1200
- style: {
1201
- background: meta.pillBg,
1202
- borderColor: meta.pillBorder,
1203
- color: meta.pillColor
1204
- },
1205
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-5 w-5" })
1206
- }
1207
- ),
1208
- index !== items.length - 1 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 h-full w-px flex-1 bg-white/10" }) : null
1209
- ] }),
1210
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col", children: [
1211
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
1212
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.7rem] font-semibold uppercase tracking-[0.3em]", style: { color: meta.accent }, children: meta.label }),
1213
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center text-xs text-white/60", children: [
1214
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CalendarDays, { className: "mr-1 h-3.5 w-3.5" }),
1215
- formatDate(item.date)
1216
- ] })
1217
- ] }),
1218
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-base font-semibold leading-snug", children: item.title }),
1219
- item.description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-sm text-white/65", children: item.description }) : null,
1220
- (item.href || item.onAction) && item.actionLabel ? /* @__PURE__ */ jsxRuntime.jsxs(
1221
- "button",
1222
- {
1223
- type: "button",
1224
- className: "group mt-3 inline-flex items-center gap-1 text-sm font-semibold text-white transition hover:text-white/80",
1225
- onClick: () => {
1226
- if (item.href) {
1227
- window?.open?.(item.href, "_blank", "noopener,noreferrer");
1228
- }
1229
- item.onAction?.(item);
1230
- },
1231
- children: [
1232
- item.actionLabel,
1233
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "h-4 w-4 transition group-hover:translate-x-0.5 group-hover:-translate-y-0.5" })
1234
- ]
1223
+ /* @__PURE__ */ jsxRuntime.jsx(
1224
+ "span",
1225
+ {
1226
+ style: {
1227
+ display: "inline-block",
1228
+ width: "6px",
1229
+ height: "6px",
1230
+ borderRadius: "50%",
1231
+ backgroundColor: "#34d399",
1232
+ animation: "propertyNewsPulse 2s infinite"
1235
1233
  }
1236
- ) : null
1237
- ] })
1234
+ }
1235
+ ),
1236
+ "LIVE"
1238
1237
  ]
1239
- },
1240
- key
1241
- );
1242
- return content;
1243
- }) : emptyState ?? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center rounded-2xl border border-dashed border-white/20 px-6 py-10 text-center text-sm text-white/60", children: [
1244
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Newspaper, { className: "mb-3 h-8 w-8 text-white/40" }),
1245
- "No property news yet. Updates will land here as soon as we receive new intelligence."
1246
- ] }) })
1238
+ }
1239
+ )
1240
+ ] }),
1241
+ /* @__PURE__ */ jsxRuntime.jsx(
1242
+ "div",
1243
+ {
1244
+ className: "mt-4 flex flex-col gap-3",
1245
+ style: { minHeight: `${ITEMS_PER_PAGE * ROW_HEIGHT_PX}px` },
1246
+ children: hasItems ? paginatedItems.map((item, index) => {
1247
+ const absoluteIndex = page * ITEMS_PER_PAGE + index;
1248
+ const key = item.displayId ?? item.id ?? `${item.title}-${absoluteIndex}`;
1249
+ const styles = categoryStyles[item.type] ?? categoryStyles.market;
1250
+ const dateLabel = item.isNew ?? (highlightFirst && absoluteIndex === 0) ? "Just now" : typeof item.date === "string" && item.date.trim().length > 0 ? item.date : formatDate(item.date);
1251
+ const isHighlighted = item.isNew ?? (highlightFirst && absoluteIndex === 0);
1252
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1253
+ "div",
1254
+ {
1255
+ style: {
1256
+ padding: "0.75rem",
1257
+ borderRadius: "6px",
1258
+ backgroundColor: isHighlighted ? "rgba(14, 203, 129, 0.1)" : "transparent",
1259
+ border: "1px solid transparent",
1260
+ transition: "background-color 0.2s",
1261
+ animation: item.isNew ? "propertyNewsSlideIn 0.5s ease-out" : void 0
1262
+ },
1263
+ children: [
1264
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.9375rem", fontWeight: 500, marginBottom: "0.35rem" }, children: item.title }),
1265
+ /* @__PURE__ */ jsxRuntime.jsxs(
1266
+ "div",
1267
+ {
1268
+ style: {
1269
+ display: "flex",
1270
+ justifyContent: "space-between",
1271
+ alignItems: "center",
1272
+ fontSize: "0.75rem",
1273
+ color: "#b5b8c5"
1274
+ },
1275
+ children: [
1276
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: isHighlighted ? "#0ecb81" : "inherit" }, children: dateLabel }),
1277
+ /* @__PURE__ */ jsxRuntime.jsx(
1278
+ "span",
1279
+ {
1280
+ style: {
1281
+ padding: "0.25rem 0.6rem",
1282
+ borderRadius: "4px",
1283
+ border: `1px solid ${styles.borderColor}`,
1284
+ backgroundColor: styles.backgroundColor,
1285
+ color: styles.color,
1286
+ fontSize: "0.68rem",
1287
+ fontWeight: 600,
1288
+ textTransform: "uppercase"
1289
+ },
1290
+ children: item.type === "property" ? styles.label : "Market News"
1291
+ }
1292
+ )
1293
+ ]
1294
+ }
1295
+ )
1296
+ ]
1297
+ },
1298
+ key
1299
+ );
1300
+ }) : emptyState ?? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center rounded-2xl border border-dashed border-white/20 px-6 py-10 text-center text-sm text-white/60", children: [
1301
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Newspaper, { className: "mb-3 h-8 w-8 text-white/40" }),
1302
+ "No property news yet. Updates will land here as soon as we receive new intelligence."
1303
+ ] })
1304
+ }
1305
+ ),
1306
+ hasItems && totalPages > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-between text-xs text-white/60", children: [
1307
+ /* @__PURE__ */ jsxRuntime.jsx(
1308
+ "button",
1309
+ {
1310
+ type: "button",
1311
+ onClick: () => setPage((prev) => Math.max(0, prev - 1)),
1312
+ disabled: page === 0,
1313
+ className: cn(
1314
+ "rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]",
1315
+ page === 0 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"
1316
+ ),
1317
+ children: "Prev"
1318
+ }
1319
+ ),
1320
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium text-white/70", children: [
1321
+ "Page ",
1322
+ page + 1,
1323
+ " / ",
1324
+ totalPages
1325
+ ] }),
1326
+ /* @__PURE__ */ jsxRuntime.jsx(
1327
+ "button",
1328
+ {
1329
+ type: "button",
1330
+ onClick: () => setPage((prev) => Math.min(totalPages - 1, prev + 1)),
1331
+ disabled: page >= totalPages - 1,
1332
+ className: cn(
1333
+ "rounded-full border border-white/15 px-3 py-1 uppercase tracking-[0.2em]",
1334
+ page >= totalPages - 1 ? "opacity-40 cursor-not-allowed" : "hover:border-white/40"
1335
+ ),
1336
+ children: "Next"
1337
+ }
1338
+ )
1339
+ ] }) : null
1247
1340
  ]
1248
1341
  }
1249
1342
  );
@@ -1388,152 +1481,264 @@ var PropertyCompareBar = React5__namespace.forwardRef(
1388
1481
  }
1389
1482
  );
1390
1483
  PropertyCompareBar.displayName = "PropertyCompareBar";
1391
- var clampPct = (pct) => Math.min(100, Math.max(0, pct));
1392
- var EditIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs(
1393
- "svg",
1394
- {
1395
- viewBox: "0 0 24 24",
1396
- fill: "none",
1397
- xmlns: "http://www.w3.org/2000/svg",
1398
- className,
1399
- children: [
1400
- /* @__PURE__ */ jsxRuntime.jsx(
1401
- "path",
1402
- {
1403
- d: "M12 20H21",
1404
- stroke: "currentColor",
1405
- strokeWidth: "2",
1406
- strokeLinecap: "round",
1407
- strokeLinejoin: "round"
1408
- }
1409
- ),
1410
- /* @__PURE__ */ jsxRuntime.jsx(
1411
- "path",
1412
- {
1413
- d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5Z",
1414
- stroke: "currentColor",
1415
- strokeWidth: "2",
1416
- strokeLinecap: "round",
1417
- strokeLinejoin: "round"
1418
- }
1419
- )
1420
- ]
1421
- }
1422
- );
1484
+ var TABS = [
1485
+ { id: "portfolio", label: "Portfolio" },
1486
+ { id: "openOrders", label: "Open Orders" },
1487
+ { id: "tradeHistory", label: "Trade History" },
1488
+ { id: "orderHistory", label: "Order History" }
1489
+ ];
1490
+ var panelStyle = {
1491
+ width: "100%",
1492
+ borderRadius: "16px",
1493
+ backgroundColor: "#111111",
1494
+ border: "1px solid rgba(255,255,255,0.08)",
1495
+ color: "#ffffff",
1496
+ display: "flex",
1497
+ flexDirection: "column"
1498
+ };
1499
+ var headerStyle = {
1500
+ padding: "1.25rem 1.5rem 0.5rem"
1501
+ };
1502
+ var titleStyle = {
1503
+ margin: 0,
1504
+ fontSize: "1.1rem",
1505
+ fontWeight: 600
1506
+ };
1507
+ var tabsRowStyle = {
1508
+ display: "flex",
1509
+ gap: "0.5rem",
1510
+ padding: "0 1.5rem",
1511
+ borderBottom: "1px solid rgba(255,255,255,0.08)"
1512
+ };
1513
+ var tabButtonBase = {
1514
+ background: "none",
1515
+ border: "none",
1516
+ color: "rgba(255,255,255,0.5)",
1517
+ fontSize: "0.9rem",
1518
+ fontWeight: 400,
1519
+ padding: "0.75rem 1rem",
1520
+ cursor: "pointer",
1521
+ position: "relative",
1522
+ transition: "color 0.2s ease"
1523
+ };
1524
+ var tabContentWrapper = {
1525
+ padding: "1.25rem 1.5rem 1.5rem",
1526
+ display: "flex",
1527
+ flexDirection: "column",
1528
+ gap: "0.75rem",
1529
+ flex: 1
1530
+ };
1531
+ var tableHeaderStyle = {
1532
+ display: "grid",
1533
+ gridTemplateColumns: "1.8fr 0.9fr 0.7fr 0.8fr 0.8fr 1fr",
1534
+ gap: "0.5rem",
1535
+ paddingBottom: "0.75rem",
1536
+ borderBottom: "1px solid rgba(255,255,255,0.1)",
1537
+ minWidth: "700px"
1538
+ };
1539
+ var tableHeaderCell = {
1540
+ fontSize: "0.7rem",
1541
+ fontWeight: 700,
1542
+ color: "#ffffff",
1543
+ textTransform: "uppercase",
1544
+ letterSpacing: "0.3px"
1545
+ };
1546
+ var emptyStateStyle = {
1547
+ flex: 1,
1548
+ display: "flex",
1549
+ alignItems: "center",
1550
+ justifyContent: "center",
1551
+ textAlign: "center",
1552
+ color: "rgba(255,255,255,0.6)",
1553
+ fontSize: "0.95rem",
1554
+ border: "1px dashed rgba(255,255,255,0.12)",
1555
+ borderRadius: "8px",
1556
+ minHeight: "220px"
1557
+ };
1558
+ var rowStyle = {
1559
+ display: "grid",
1560
+ gridTemplateColumns: "1.8fr 0.9fr 0.7fr 0.8fr 0.8fr 1fr",
1561
+ gap: "0.5rem",
1562
+ alignItems: "center",
1563
+ minWidth: "700px",
1564
+ padding: "0.75rem 0",
1565
+ borderBottom: "1px solid rgba(255,255,255,0.08)"
1566
+ };
1567
+ var formatCurrency = (value) => {
1568
+ if (value == null || Number.isNaN(value)) return "\u2014";
1569
+ return `$${value.toLocaleString(void 0, {
1570
+ minimumFractionDigits: 2,
1571
+ maximumFractionDigits: 2
1572
+ })}`;
1573
+ };
1574
+ var formatPercent = (value, fractionDigits = 2) => {
1575
+ if (value == null || Number.isNaN(value)) return "\u2014";
1576
+ return `${value.toFixed(fractionDigits)}%`;
1577
+ };
1423
1578
  var YourOrders = React5__namespace.forwardRef(
1424
- ({
1425
- className,
1426
- title = "Your Orders",
1427
- orders,
1428
- onEditPrice,
1429
- onEditAmount,
1430
- onCancel,
1431
- ...props
1432
- }, ref) => {
1433
- return /* @__PURE__ */ jsxRuntime.jsxs(
1434
- Card,
1435
- {
1436
- ref,
1437
- className: cn(
1438
- "w-full min-h-[301.52px] rounded-[12px] border border-white/10 bg-black/30 text-white backdrop-blur-md max-[1024px]:min-h-[250px] max-[480px]:min-h-[200px]",
1439
- className
1440
- ),
1441
- ...props,
1442
- children: [
1443
- /* @__PURE__ */ jsxRuntime.jsx(CardHeader, { className: "px-6 pb-2 pt-6", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle, { className: "m-0 text-[1.1rem] font-semibold text-white", children: title }) }),
1444
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6 pt-2", children: [
1445
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1.2fr_0.8fr_1fr_1fr_1fr_1fr_1.2fr_0.8fr] border-b border-white/10 pb-2 text-[0.85rem] font-medium text-white/60", children: [
1446
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Asset" }),
1447
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Type" }),
1448
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Date" }),
1449
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Price" }),
1450
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Amount" }),
1451
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Total" }),
1452
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2", children: "Filled" }),
1453
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 text-center", children: "Actions" })
1454
- ] }),
1455
- orders.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-10 text-center text-sm text-white/50", children: "No orders" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: orders.map((order) => {
1456
- const sideClass = order.side === "buy" ? "text-[#0ecb81]" : "text-[#f6465d]";
1457
- const filled = clampPct(order.filledPercent ?? 0);
1458
- const isCancelled = order.status?.toUpperCase() === "CANCELLED";
1459
- const canEditPrice = Boolean(onEditPrice);
1460
- const canEditAmount = Boolean(onEditAmount);
1461
- const canCancel = Boolean(onCancel);
1462
- return /* @__PURE__ */ jsxRuntime.jsxs(
1463
- "div",
1464
- {
1465
- className: "grid grid-cols-[1.5fr_0.8fr_0.8fr_1fr_0.8fr_1fr_1fr_0.8fr] items-center border-b border-white/5 py-2 text-[0.9rem] transition-colors hover:bg-white/[0.03]",
1466
- children: [
1467
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate px-2 font-medium", children: order.asset }),
1468
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-2 font-medium uppercase", sideClass), children: order.side }),
1469
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 font-medium", children: order.date }),
1470
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-2 font-medium", children: [
1471
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums", children: [
1472
- "$",
1473
- order.price.toLocaleString()
1474
- ] }),
1475
- /* @__PURE__ */ jsxRuntime.jsx(
1476
- "button",
1477
- {
1478
- type: "button",
1479
- onClick: canEditPrice ? () => onEditPrice?.(order) : void 0,
1480
- className: cn(
1481
- "ml-1 inline-flex items-center justify-center text-white/60 transition-colors",
1482
- canEditPrice ? "cursor-pointer hover:text-[#C9A227] active:translate-y-px" : "cursor-default"
1483
- ),
1484
- "aria-label": "Edit price",
1485
- children: /* @__PURE__ */ jsxRuntime.jsx(EditIcon, { className: "h-[14px] w-[14px]" })
1486
- }
1487
- )
1488
- ] }),
1489
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-2 font-medium", children: [
1490
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: order.amount.toLocaleString() }),
1491
- /* @__PURE__ */ jsxRuntime.jsx(
1492
- "button",
1579
+ ({ className, title = "Portfolio Holdings (Demo)", orders, renderOrderActions, ...props }, ref) => {
1580
+ const [activeTab, setActiveTab] = React5__namespace.useState("portfolio");
1581
+ const hasOrders = Array.isArray(orders) && orders.length > 0;
1582
+ const renderPortfolio = () => {
1583
+ if (!hasOrders) {
1584
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: emptyStateStyle, children: "No holdings yet. Start trading to build your portfolio." });
1585
+ }
1586
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1587
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: tableHeaderStyle, children: [
1588
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "Property" }),
1589
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "Value" }),
1590
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "Holding" }),
1591
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "% of Property" }),
1592
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "Avg Price" }),
1593
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tableHeaderCell, children: "P&L" })
1594
+ ] }),
1595
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.65rem" }, children: orders.map((order) => {
1596
+ const propertyName = order.asset;
1597
+ const holding = order.holdingLabel ?? `${order.amount.toLocaleString(void 0, {
1598
+ minimumFractionDigits: 0,
1599
+ maximumFractionDigits: 2
1600
+ })} ${propertyName}`;
1601
+ const value = order.value ?? order.total;
1602
+ const portfolioShare = order.portfolioSharePercent != null ? `${order.portfolioSharePercent.toFixed(1)}% of portfolio` : void 0;
1603
+ const propertyPercent = order.propertyPercent;
1604
+ const avgPrice = order.avgEntryPrice ?? order.price;
1605
+ const pnlValue = order.pnlValue;
1606
+ const pnlPercent = order.pnlPercent;
1607
+ const pnlPositive = pnlValue != null ? pnlValue >= 0 : (pnlPercent ?? 0) >= 0;
1608
+ const currentPrice = order.currentPrice ?? order.price;
1609
+ const priceChangePercent = order.priceChangePercent ?? order.pnlPercent;
1610
+ const priceChangePositive = order.priceChangePositive ?? (priceChangePercent != null ? priceChangePercent >= 0 : void 0);
1611
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...rowStyle, gridTemplateColumns: renderOrderActions ? "1.8fr 0.8fr 0.7fr 0.8fr 0.8fr 0.9fr 0.8fr" : "1.8fr 0.9fr 0.7fr 0.8fr 0.8fr 1fr" }, children: [
1612
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "1rem", alignItems: "center" }, children: [
1613
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.15rem" }, children: [
1614
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.9rem", fontWeight: 500 }, children: propertyName }),
1615
+ portfolioShare ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.72rem", color: "rgba(255,255,255,0.5)" }, children: portfolioShare }) : null
1616
+ ] }),
1617
+ currentPrice != null ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1618
+ /* @__PURE__ */ jsxRuntime.jsxs(
1619
+ "div",
1620
+ {
1621
+ style: {
1622
+ fontSize: "0.9rem",
1623
+ color: "var(--color-text, #ffffff)",
1624
+ display: "flex",
1625
+ alignItems: "center",
1626
+ gap: "0.25rem"
1627
+ },
1628
+ children: [
1629
+ priceChangePositive != null ? /* @__PURE__ */ jsxRuntime.jsx(
1630
+ "span",
1493
1631
  {
1494
- type: "button",
1495
- onClick: canEditAmount ? () => onEditAmount?.(order) : void 0,
1496
- className: cn(
1497
- "ml-1 inline-flex items-center justify-center text-white/60 transition-colors",
1498
- canEditAmount ? "cursor-pointer hover:text-[#C9A227] active:translate-y-px" : "cursor-default"
1499
- ),
1500
- "aria-label": "Edit amount",
1501
- children: /* @__PURE__ */ jsxRuntime.jsx(EditIcon, { className: "h-[14px] w-[14px]" })
1632
+ style: {
1633
+ color: priceChangePositive ? "#0ecb81" : "#f6465d",
1634
+ fontSize: "0.7em"
1635
+ },
1636
+ children: priceChangePositive ? "\u25B2" : "\u25BC"
1502
1637
  }
1503
- )
1504
- ] }),
1505
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-2 font-medium tabular-nums", children: [
1506
- "$",
1507
- order.total.toLocaleString()
1508
- ] }),
1509
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-2", children: [
1510
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[0.875rem] font-medium tabular-nums", children: [
1511
- filled.toFixed(0),
1512
- "%"
1513
- ] }),
1514
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 h-1 w-4/5 overflow-hidden rounded-sm bg-white/10", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-sm bg-[#C9A227]", style: { width: `${filled}%` } }) })
1515
- ] }),
1516
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 text-center", children: isCancelled ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center justify-center rounded border border-white/20 px-3 py-1 text-[0.78rem] uppercase tracking-wide text-[#f6465d]", children: "Cancelled" }) : /* @__PURE__ */ jsxRuntime.jsx(
1517
- "button",
1518
- {
1519
- type: "button",
1520
- onClick: canCancel ? () => onCancel?.(order) : void 0,
1521
- className: cn(
1522
- "rounded border border-white/40 px-3 py-1 text-[0.8rem] text-white/70 transition-colors",
1523
- canCancel ? "cursor-pointer hover:bg-white/10 active:text-[#f6465d] active:border-[#f6465d] active:translate-y-px" : "cursor-default"
1524
- ),
1525
- children: "Cancel"
1526
- }
1527
- ) })
1528
- ]
1638
+ ) : null,
1639
+ formatCurrency(currentPrice)
1640
+ ]
1641
+ }
1642
+ ),
1643
+ priceChangePercent != null ? /* @__PURE__ */ jsxRuntime.jsxs(
1644
+ "div",
1645
+ {
1646
+ style: {
1647
+ fontSize: "0.7rem",
1648
+ color: priceChangePositive ? "#0ecb81" : "#f6465d"
1649
+ },
1650
+ children: [
1651
+ "(",
1652
+ priceChangePositive ? "+" : "",
1653
+ priceChangePercent.toFixed(2),
1654
+ "%)"
1655
+ ]
1656
+ }
1657
+ ) : null
1658
+ ] }) : null
1659
+ ] }),
1660
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.9rem", fontWeight: 500, color: "#D4AF37" }, children: formatCurrency(value) }),
1661
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.9rem", color: "rgba(255,255,255,0.92)" }, children: holding }),
1662
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.9rem", color: "rgba(255,255,255,0.8)" }, children: formatPercent(propertyPercent, 3) }),
1663
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: "0.9rem", color: "rgba(255,255,255,0.9)" }, children: formatCurrency(avgPrice) }),
1664
+ /* @__PURE__ */ jsxRuntime.jsxs(
1665
+ "div",
1666
+ {
1667
+ style: {
1668
+ fontSize: "0.9rem",
1669
+ fontWeight: 500,
1670
+ color: pnlPositive ? "#0ecb81" : "#f6465d"
1529
1671
  },
1530
- order.id
1531
- );
1532
- }) })
1533
- ] })
1534
- ]
1535
- }
1536
- );
1672
+ children: [
1673
+ pnlValue != null ? `${pnlPositive ? "+" : "-"}${formatCurrency(Math.abs(pnlValue))}` : formatCurrency(pnlValue),
1674
+ pnlPercent != null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { marginLeft: "0.35rem", fontSize: "0.75rem", color: "rgba(255,255,255,0.6)" }, children: [
1675
+ "(",
1676
+ pnlPositive ? "+" : "",
1677
+ pnlPercent.toFixed(1),
1678
+ "%)"
1679
+ ] }) : null
1680
+ ]
1681
+ }
1682
+ ),
1683
+ renderOrderActions ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "flex-end" }, children: renderOrderActions(order) }) : null
1684
+ ] }, order.id);
1685
+ }) })
1686
+ ] });
1687
+ };
1688
+ const renderOtherTab = (label) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: emptyStateStyle, children: `No ${label.toLowerCase()} data available.` });
1689
+ let tabContent = null;
1690
+ switch (activeTab) {
1691
+ case "portfolio":
1692
+ tabContent = renderPortfolio();
1693
+ break;
1694
+ case "openOrders":
1695
+ tabContent = renderOtherTab("Open Orders");
1696
+ break;
1697
+ case "tradeHistory":
1698
+ tabContent = renderOtherTab("Trade History");
1699
+ break;
1700
+ case "orderHistory":
1701
+ tabContent = renderOtherTab("Order History");
1702
+ break;
1703
+ default:
1704
+ tabContent = null;
1705
+ }
1706
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, style: panelStyle, className, ...props, children: [
1707
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: headerStyle, children: /* @__PURE__ */ jsxRuntime.jsx("h3", { style: titleStyle, children: title }) }),
1708
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tabsRowStyle, children: TABS.map((tab) => {
1709
+ const isActive = activeTab === tab.id;
1710
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1711
+ "button",
1712
+ {
1713
+ type: "button",
1714
+ onClick: () => setActiveTab(tab.id),
1715
+ style: {
1716
+ ...tabButtonBase,
1717
+ color: isActive ? "#ffffff" : "rgba(255,255,255,0.55)",
1718
+ fontWeight: isActive ? 600 : 400
1719
+ },
1720
+ children: [
1721
+ tab.label,
1722
+ isActive ? /* @__PURE__ */ jsxRuntime.jsx(
1723
+ "div",
1724
+ {
1725
+ style: {
1726
+ position: "absolute",
1727
+ bottom: "-1px",
1728
+ left: 0,
1729
+ right: 0,
1730
+ height: "2px",
1731
+ background: "#f0b90b"
1732
+ }
1733
+ }
1734
+ ) : null
1735
+ ]
1736
+ },
1737
+ tab.id
1738
+ );
1739
+ }) }),
1740
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: tabContentWrapper, children: tabContent })
1741
+ ] });
1537
1742
  }
1538
1743
  );
1539
1744
  YourOrders.displayName = "YourOrders";
@@ -1743,7 +1948,10 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
1743
1948
  ...props
1744
1949
  }, ref) => {
1745
1950
  const isPositive = changePercent == null ? void 0 : changePercent >= 0;
1746
- const tradeHoverColor = "var(--color-accent-hover, #f8d12f)";
1951
+ const accentColor = "#e6c87e";
1952
+ const tradeHoverColor = "#f5dd9a";
1953
+ const [isTradeInteracting, setIsTradeInteracting] = React5__namespace.useState(false);
1954
+ const [isOfferInteracting, setIsOfferInteracting] = React5__namespace.useState(false);
1747
1955
  return /* @__PURE__ */ jsxRuntime.jsxs(
1748
1956
  "div",
1749
1957
  {
@@ -1829,20 +2037,30 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
1829
2037
  propertyTypeLabel == null ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { children: propertyTypeLabel })
1830
2038
  ] })
1831
2039
  ] }),
1832
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 max-[768px]:w-full max-[768px]:flex-row max-[768px]:justify-between max-[768px]:gap-2 max-[480px]:gap-2", children: [
2040
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3 max-[768px]:w-full max-[768px]:justify-between max-[768px]:gap-2 max-[480px]:gap-2", children: [
1833
2041
  /* @__PURE__ */ jsxRuntime.jsx(
1834
2042
  "button",
1835
2043
  {
1836
2044
  type: "button",
1837
2045
  onClick: onTrade,
1838
- className: "rounded border border-transparent px-6 py-3 font-semibold transition-all hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] max-[768px]:flex-1 max-[768px]:px-5 max-[768px]:py-2.5 max-[768px]:text-[0.95rem] max-[480px]:px-4 max-[480px]:py-2 max-[480px]:text-[0.9rem]",
1839
- style: { backgroundColor: "var(--color-accent, #e6c87e)", color: "black" },
1840
- onMouseEnter: (e) => {
1841
- e.currentTarget.style.backgroundColor = tradeHoverColor;
1842
- },
1843
- onMouseLeave: (e) => {
1844
- e.currentTarget.style.backgroundColor = "var(--color-accent, #e6c87e)";
2046
+ className: "flex items-center justify-center rounded border font-semibold transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] text-[0.95rem] max-[480px]:text-[0.9rem]",
2047
+ style: {
2048
+ backgroundColor: isTradeInteracting ? tradeHoverColor : accentColor,
2049
+ color: "black",
2050
+ width: "88.06px",
2051
+ height: "43px",
2052
+ minWidth: "88.06px",
2053
+ borderColor: isTradeInteracting ? accentColor : "transparent",
2054
+ boxShadow: isTradeInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none"
1845
2055
  },
2056
+ onMouseEnter: () => setIsTradeInteracting(true),
2057
+ onMouseLeave: () => setIsTradeInteracting(false),
2058
+ onMouseDown: () => setIsTradeInteracting(true),
2059
+ onMouseUp: () => setIsTradeInteracting(false),
2060
+ onFocus: () => setIsTradeInteracting(true),
2061
+ onBlur: () => setIsTradeInteracting(false),
2062
+ onTouchStart: () => setIsTradeInteracting(true),
2063
+ onTouchEnd: () => setIsTradeInteracting(false),
1846
2064
  children: "Trade"
1847
2065
  }
1848
2066
  ),
@@ -1851,18 +2069,24 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
1851
2069
  {
1852
2070
  type: "button",
1853
2071
  onClick: onMakeOffer,
1854
- className: "rounded border px-6 py-3 font-semibold transition-all hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] max-[768px]:flex-1 max-[768px]:px-5 max-[768px]:py-2.5 max-[768px]:text-[0.95rem] max-[480px]:px-4 max-[480px]:py-2 max-[480px]:text-[0.9rem]",
2072
+ className: "flex items-center justify-center rounded border font-semibold transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] text-[0.95rem] max-[480px]:text-[0.9rem]",
1855
2073
  style: {
1856
- backgroundColor: "transparent",
1857
- borderColor: "var(--color-accent, #e6c87e)",
1858
- color: "var(--color-accent, #e6c87e)"
1859
- },
1860
- onMouseEnter: (e) => {
1861
- e.currentTarget.style.backgroundColor = "rgba(240, 185, 11, 0.1)";
1862
- },
1863
- onMouseLeave: (e) => {
1864
- e.currentTarget.style.backgroundColor = "transparent";
2074
+ backgroundColor: isOfferInteracting ? accentColor : "transparent",
2075
+ borderColor: accentColor,
2076
+ color: isOfferInteracting ? "black" : accentColor,
2077
+ width: "127.14px",
2078
+ height: "43px",
2079
+ minWidth: "127.14px",
2080
+ boxShadow: isOfferInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none"
1865
2081
  },
2082
+ onMouseEnter: () => setIsOfferInteracting(true),
2083
+ onMouseLeave: () => setIsOfferInteracting(false),
2084
+ onMouseDown: () => setIsOfferInteracting(true),
2085
+ onMouseUp: () => setIsOfferInteracting(false),
2086
+ onFocus: () => setIsOfferInteracting(true),
2087
+ onBlur: () => setIsOfferInteracting(false),
2088
+ onTouchStart: () => setIsOfferInteracting(true),
2089
+ onTouchEnd: () => setIsOfferInteracting(false),
1866
2090
  children: "Make Offer"
1867
2091
  }
1868
2092
  )