@loafmarkets/ui 0.1.263 → 0.1.265

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -13613,6 +13613,7 @@ function PortfolioActivityPanel({
13613
13613
  onCancelAllOrders,
13614
13614
  onAmendOrder,
13615
13615
  cancellingOrderId = null,
13616
+ compactPositions = false,
13616
13617
  defaultTab,
13617
13618
  pageSize = ACTIVITY_PAGE_SIZE_DEFAULT,
13618
13619
  blockExplorerBaseUrl = "https://sepolia.basescan.org/tx",
@@ -13637,6 +13638,36 @@ function PortfolioActivityPanel({
13637
13638
  setPosSortAsc(key === "asset");
13638
13639
  }
13639
13640
  };
13641
+ const [expandedPositions, setExpandedPositions] = useState(/* @__PURE__ */ new Set());
13642
+ const [allExpanded, setAllExpanded] = useState(false);
13643
+ const [sortDropdownOpen, setSortDropdownOpen] = useState(false);
13644
+ const togglePosition = (tokenName) => {
13645
+ setExpandedPositions((prev) => {
13646
+ const next = new Set(prev);
13647
+ if (next.has(tokenName)) next.delete(tokenName);
13648
+ else next.add(tokenName);
13649
+ return next;
13650
+ });
13651
+ };
13652
+ const sortKeyLabel = (key) => {
13653
+ switch (key) {
13654
+ case "asset":
13655
+ return "Asset";
13656
+ case "units":
13657
+ return "Units";
13658
+ case "value":
13659
+ return "Value";
13660
+ case "avgPrice":
13661
+ return "Avg Price";
13662
+ case "currentPrice":
13663
+ return "Price";
13664
+ case "pnl":
13665
+ return "PNL";
13666
+ default:
13667
+ return "Asset";
13668
+ }
13669
+ };
13670
+ const sortKeys = ["asset", "units", "value", "avgPrice", "currentPrice", "pnl"];
13640
13671
  const sortedPositions = useMemo(() => {
13641
13672
  const arr = [...positions];
13642
13673
  const dir = posSortAsc ? 1 : -1;
@@ -13663,6 +13694,15 @@ function PortfolioActivityPanel({
13663
13694
  });
13664
13695
  return arr;
13665
13696
  }, [positions, posSortKey, posSortAsc]);
13697
+ const toggleExpandAll = () => {
13698
+ if (allExpanded) {
13699
+ setExpandedPositions(/* @__PURE__ */ new Set());
13700
+ setAllExpanded(false);
13701
+ } else {
13702
+ setExpandedPositions(new Set(sortedPositions.map((p) => p.tokenName)));
13703
+ setAllExpanded(true);
13704
+ }
13705
+ };
13666
13706
  const activeTabTotal = useMemo(() => {
13667
13707
  switch (activeTab) {
13668
13708
  case "positions":
@@ -13743,7 +13783,90 @@ function PortfolioActivityPanel({
13743
13783
  ] }),
13744
13784
  activeTab === "positions" && showPositionsTab && /* @__PURE__ */ jsxs(Fragment, { children: [
13745
13785
  positions.length === 0 && /* @__PURE__ */ jsx(EmptyState, { children: "No positions yet. Subscribe to an offering or buy on the secondary market." }),
13746
- positions.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
13786
+ positions.length > 0 && compactPositions && /* @__PURE__ */ jsxs(Fragment, { children: [
13787
+ /* @__PURE__ */ jsxs(CToolbar, { children: [
13788
+ /* @__PURE__ */ jsxs(CSortWrap, { children: [
13789
+ /* @__PURE__ */ jsxs(CSortBtn, { onClick: () => setSortDropdownOpen((v) => !v), children: [
13790
+ "Sort by: ",
13791
+ sortKeyLabel(posSortKey),
13792
+ " \u25BE"
13793
+ ] }),
13794
+ sortDropdownOpen && /* @__PURE__ */ jsx(CSortDropdown, { children: sortKeys.map((k) => /* @__PURE__ */ jsx(CSortOption, { $active: posSortKey === k, onClick: () => {
13795
+ setPosSortKey(k);
13796
+ setPosSortAsc(true);
13797
+ setSortDropdownOpen(false);
13798
+ }, children: sortKeyLabel(k) }, k)) })
13799
+ ] }),
13800
+ /* @__PURE__ */ jsxs(CToolbarActions, { children: [
13801
+ /* @__PURE__ */ jsx(CToolbarLink, { onClick: toggleExpandAll, children: allExpanded ? "Collapse All" : "Expand All" }),
13802
+ onClosePosition && /* @__PURE__ */ jsx(CToolbarLink, { onClick: () => setCloseAllOpen(true), children: "Sell All" })
13803
+ ] })
13804
+ ] }),
13805
+ pageSlice(sortedPositions).map((pos) => {
13806
+ const currentValue = pos.quantity * pos.marketPrice;
13807
+ const costBasis = pos.quantity * pos.averageEntryPrice;
13808
+ const pnl = pos.propertyPnl ?? currentValue - costBasis;
13809
+ const pnlPercent = pos.propertyPnlPercent ?? pos.percentChange ?? 0;
13810
+ const isPositive = pnl >= 0;
13811
+ const posExpanded = expandedPositions.has(pos.tokenName) || allExpanded;
13812
+ const ticker = pos.tokenName.toUpperCase().slice(0, 7);
13813
+ return /* @__PURE__ */ jsxs("div", { children: [
13814
+ /* @__PURE__ */ jsxs(CRow, { $expanded: posExpanded, onClick: () => togglePosition(pos.tokenName), children: [
13815
+ /* @__PURE__ */ jsxs(CAssetCell, { onClick: (e) => {
13816
+ e.stopPropagation();
13817
+ onPositionClick?.(pos.tokenName, pos.isIpoAllocation);
13818
+ }, children: [
13819
+ /* @__PURE__ */ jsx(CCellLabel, { children: "Asset" }),
13820
+ /* @__PURE__ */ jsxs(CAssetName, { children: [
13821
+ pos.imageUrl && /* @__PURE__ */ jsx(CAssetLogo, { src: pos.imageUrl, alt: "" }),
13822
+ pos.tokenName
13823
+ ] })
13824
+ ] }),
13825
+ /* @__PURE__ */ jsxs(CUnitsCell, { children: [
13826
+ /* @__PURE__ */ jsx(CCellLabel, { children: "Units" }),
13827
+ formatNumber2(pos.quantity, pos.quantity >= 100 ? 0 : 2),
13828
+ " ",
13829
+ ticker
13830
+ ] }),
13831
+ /* @__PURE__ */ jsxs(CPnlCell, { children: [
13832
+ /* @__PURE__ */ jsx(CCellLabel, { children: "PNL (%)" }),
13833
+ /* @__PURE__ */ jsxs(CPnlValue, { $positive: isPositive, children: [
13834
+ isPositive ? "+" : "-",
13835
+ formatCurrency4(Math.abs(pnl))
13836
+ ] }),
13837
+ /* @__PURE__ */ jsxs(CPnlPct, { $positive: isPositive, children: [
13838
+ "(",
13839
+ isPositive ? "+" : "",
13840
+ pnlPercent.toFixed(1),
13841
+ "%)"
13842
+ ] })
13843
+ ] }),
13844
+ /* @__PURE__ */ jsx(CChevronWrap, { $open: posExpanded, children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "rgba(255,255,255,0.5)", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "6 9 12 15 18 9" }) }) })
13845
+ ] }),
13846
+ posExpanded && /* @__PURE__ */ jsxs(CExpandedWrap, { children: [
13847
+ /* @__PURE__ */ jsxs(CDetailGrid, { children: [
13848
+ /* @__PURE__ */ jsxs(CDetailItem, { children: [
13849
+ /* @__PURE__ */ jsx(CDLabel, { children: "Position Value" }),
13850
+ /* @__PURE__ */ jsx(CDValue, { children: formatCurrency4(currentValue, { minimumFractionDigits: 0, maximumFractionDigits: 0 }) })
13851
+ ] }),
13852
+ /* @__PURE__ */ jsxs(CDetailItem, { children: [
13853
+ /* @__PURE__ */ jsx(CDLabel, { children: "Avg Price" }),
13854
+ /* @__PURE__ */ jsx(CDValue, { children: formatCurrency4(pos.averageEntryPrice) })
13855
+ ] }),
13856
+ /* @__PURE__ */ jsxs(CDetailItem, { children: [
13857
+ /* @__PURE__ */ jsx(CDLabel, { children: "Current Price" }),
13858
+ /* @__PURE__ */ jsx(CDValue, { children: formatCurrency4(pos.marketPrice) })
13859
+ ] })
13860
+ ] }),
13861
+ onClosePosition && /* @__PURE__ */ jsxs(CActionRow, { children: [
13862
+ /* @__PURE__ */ jsx(CCloseBtn, { onClick: () => onClosePosition(pos.tokenName, "market", pos.quantity, pos.marketPrice), children: "Market Sell" }),
13863
+ /* @__PURE__ */ jsx(CCloseBtn, { onClick: () => onClosePosition(pos.tokenName, "limit", pos.quantity, pos.marketPrice), children: "Limit Sell" })
13864
+ ] })
13865
+ ] })
13866
+ ] }, pos.tokenName);
13867
+ })
13868
+ ] }),
13869
+ positions.length > 0 && !compactPositions && /* @__PURE__ */ jsxs(Fragment, { children: [
13747
13870
  /* @__PURE__ */ jsxs(PositionsHeader, { $hasClose: !!onClosePosition, children: [
13748
13871
  /* @__PURE__ */ jsxs(SortableHeaderCell, { $active: posSortKey === "asset", onClick: () => handlePosSort("asset"), children: [
13749
13872
  "Asset ",
@@ -13813,29 +13936,29 @@ function PortfolioActivityPanel({
13813
13936
  }, children: "Limit Sell" })
13814
13937
  ] }) })
13815
13938
  ] }, pos.tokenName);
13816
- }),
13817
- closeAllOpen && onClosePosition && /* @__PURE__ */ jsx(CloseAllOverlay, { onClick: () => setCloseAllOpen(false), children: /* @__PURE__ */ jsxs(CloseAllModal, { onClick: (e) => e.stopPropagation(), children: [
13818
- /* @__PURE__ */ jsx(CloseAllModalX, { onClick: () => setCloseAllOpen(false), children: "\xD7" }),
13819
- /* @__PURE__ */ jsx(CloseAllTitle, { children: "Confirm Sell All" }),
13820
- /* @__PURE__ */ jsx(CloseAllDesc, { children: "This will sell all your positions and cancel their associated TP/SL orders." }),
13821
- /* @__PURE__ */ jsxs(CloseAllOption, { onClick: () => setCloseAllType("market"), children: [
13822
- /* @__PURE__ */ jsx(CloseAllRadio, { $selected: closeAllType === "market" }),
13823
- /* @__PURE__ */ jsx("span", { children: "Market Sell" })
13824
- ] }),
13825
- /* @__PURE__ */ jsxs(CloseAllOption, { onClick: () => setCloseAllType("limit"), children: [
13826
- /* @__PURE__ */ jsx(CloseAllRadio, { $selected: closeAllType === "limit" }),
13827
- /* @__PURE__ */ jsx("span", { children: "Limit Sell at Mid Price" })
13828
- ] }),
13829
- /* @__PURE__ */ jsxs(CloseAllConfirmBtn, { onClick: () => {
13830
- positions.forEach((pos) => onClosePosition(pos.tokenName, closeAllType, pos.quantity, pos.marketPrice));
13831
- setCloseAllOpen(false);
13832
- }, children: [
13833
- "Confirm ",
13834
- closeAllType === "market" ? "Market" : "Limit",
13835
- " Sell"
13836
- ] })
13837
- ] }) })
13838
- ] })
13939
+ })
13940
+ ] }),
13941
+ positions.length > 0 && closeAllOpen && onClosePosition && /* @__PURE__ */ jsx(CloseAllOverlay, { onClick: () => setCloseAllOpen(false), children: /* @__PURE__ */ jsxs(CloseAllModal, { onClick: (e) => e.stopPropagation(), children: [
13942
+ /* @__PURE__ */ jsx(CloseAllModalX, { onClick: () => setCloseAllOpen(false), children: "\xD7" }),
13943
+ /* @__PURE__ */ jsx(CloseAllTitle, { children: "Confirm Sell All" }),
13944
+ /* @__PURE__ */ jsx(CloseAllDesc, { children: "This will sell all your positions and cancel their associated TP/SL orders." }),
13945
+ /* @__PURE__ */ jsxs(CloseAllOption, { onClick: () => setCloseAllType("market"), children: [
13946
+ /* @__PURE__ */ jsx(CloseAllRadio, { $selected: closeAllType === "market" }),
13947
+ /* @__PURE__ */ jsx("span", { children: "Market Sell" })
13948
+ ] }),
13949
+ /* @__PURE__ */ jsxs(CloseAllOption, { onClick: () => setCloseAllType("limit"), children: [
13950
+ /* @__PURE__ */ jsx(CloseAllRadio, { $selected: closeAllType === "limit" }),
13951
+ /* @__PURE__ */ jsx("span", { children: "Limit Sell at Mid Price" })
13952
+ ] }),
13953
+ /* @__PURE__ */ jsxs(CloseAllConfirmBtn, { onClick: () => {
13954
+ positions.forEach((pos) => onClosePosition(pos.tokenName, closeAllType, pos.quantity, pos.marketPrice));
13955
+ setCloseAllOpen(false);
13956
+ }, children: [
13957
+ "Confirm ",
13958
+ closeAllType === "market" ? "Market" : "Limit",
13959
+ " Sell"
13960
+ ] })
13961
+ ] }) })
13839
13962
  ] }),
13840
13963
  activeTab === "subscriptions" && /* @__PURE__ */ jsxs(Fragment, { children: [
13841
13964
  offeringOrders.length === 0 && /* @__PURE__ */ jsx(EmptyState, { children: "IPO allocations will appear here once you subscribe." }),
@@ -14638,6 +14761,182 @@ var CloseAllConfirmBtn = styled9.button`
14638
14761
  background: rgba(246, 70, 93, 0.25);
14639
14762
  }
14640
14763
  `;
14764
+ var CToolbar = styled9.div`
14765
+ display: flex;
14766
+ align-items: center;
14767
+ justify-content: space-between;
14768
+ padding: 0.3rem 0.6rem;
14769
+ border-bottom: 1px solid rgba(255, 255, 255, 0.04);
14770
+ `;
14771
+ var CSortWrap = styled9.div`
14772
+ position: relative;
14773
+ `;
14774
+ var CSortBtn = styled9.button`
14775
+ font-size: 0.6rem;
14776
+ color: rgba(255, 255, 255, 0.45);
14777
+ background: none;
14778
+ border: none;
14779
+ cursor: pointer;
14780
+ display: flex;
14781
+ align-items: center;
14782
+ gap: 0.2rem;
14783
+ &:hover { color: rgba(255, 255, 255, 0.7); }
14784
+ `;
14785
+ var CSortDropdown = styled9.div`
14786
+ position: absolute;
14787
+ top: 100%;
14788
+ left: 0;
14789
+ z-index: 10;
14790
+ margin-top: 2px;
14791
+ background: #1a1c24;
14792
+ border: 1px solid rgba(255, 255, 255, 0.1);
14793
+ border-radius: 6px;
14794
+ overflow: hidden;
14795
+ min-width: 120px;
14796
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
14797
+ `;
14798
+ var CSortOption = styled9.button`
14799
+ display: block;
14800
+ width: 100%;
14801
+ padding: 0.4rem 0.6rem;
14802
+ font-size: 0.6rem;
14803
+ font-weight: ${(p) => p.$active ? 600 : 400};
14804
+ color: ${(p) => p.$active ? "#E6C87E" : "rgba(255, 255, 255, 0.6)"};
14805
+ background: ${(p) => p.$active ? "rgba(230, 200, 126, 0.06)" : "none"};
14806
+ border: none;
14807
+ text-align: left;
14808
+ cursor: pointer;
14809
+ &:hover { background: rgba(255, 255, 255, 0.05); }
14810
+ `;
14811
+ var CToolbarActions = styled9.div`
14812
+ display: flex;
14813
+ gap: 0.5rem;
14814
+ `;
14815
+ var CToolbarLink = styled9.button`
14816
+ font-size: 0.58rem;
14817
+ font-weight: 500;
14818
+ color: rgba(255, 255, 255, 0.45);
14819
+ background: none;
14820
+ border: none;
14821
+ cursor: pointer;
14822
+ text-decoration: underline;
14823
+ text-decoration-color: rgba(255, 255, 255, 0.15);
14824
+ &:hover { color: rgba(255, 255, 255, 0.7); }
14825
+ `;
14826
+ var CRow = styled9.button`
14827
+ display: grid;
14828
+ grid-template-columns: 1fr 1fr 1fr 24px;
14829
+ align-items: center;
14830
+ width: calc(100% - 1rem);
14831
+ margin: 0.25rem 0.5rem;
14832
+ margin-bottom: ${(p) => p.$expanded ? "0" : "0.25rem"};
14833
+ padding: 0.55rem 0.65rem;
14834
+ background: rgba(255, 255, 255, 0.035);
14835
+ border: 1px solid rgba(255, 255, 255, 0.06);
14836
+ border-bottom: ${(p) => p.$expanded ? "none" : "1px solid rgba(255, 255, 255, 0.06)"};
14837
+ border-radius: ${(p) => p.$expanded ? "8px 8px 0 0" : "8px"};
14838
+ cursor: pointer;
14839
+ text-align: left;
14840
+ transition: background 0.15s;
14841
+ outline: none;
14842
+ &:active { background: rgba(255, 255, 255, 0.06); }
14843
+ &:focus { outline: none; }
14844
+ &:focus-visible { outline: none; }
14845
+ `;
14846
+ var CCellLabel = styled9.div`
14847
+ font-size: 0.6rem;
14848
+ font-weight: 500;
14849
+ color: rgba(255, 255, 255, 0.3);
14850
+ margin-bottom: 1px;
14851
+ `;
14852
+ var CAssetCell = styled9.div``;
14853
+ var CAssetName = styled9.div`
14854
+ font-size: 0.85rem;
14855
+ font-weight: 600;
14856
+ color: #fff;
14857
+ display: flex;
14858
+ align-items: center;
14859
+ gap: 0.3rem;
14860
+ `;
14861
+ var CAssetLogo = styled9.img`
14862
+ width: 22px;
14863
+ height: 22px;
14864
+ border-radius: 4px;
14865
+ object-fit: cover;
14866
+ flex-shrink: 0;
14867
+ `;
14868
+ var CUnitsCell = styled9.div`
14869
+ font-size: 0.78rem;
14870
+ color: rgba(255, 255, 255, 0.8);
14871
+ font-variant-numeric: tabular-nums;
14872
+ `;
14873
+ var CPnlCell = styled9.div``;
14874
+ var CPnlValue = styled9.div`
14875
+ font-size: 0.78rem;
14876
+ font-weight: 600;
14877
+ color: ${(p) => p.$positive ? "#0ecb81" : "#f6465d"};
14878
+ font-variant-numeric: tabular-nums;
14879
+ `;
14880
+ var CPnlPct = styled9.div`
14881
+ font-size: 0.62rem;
14882
+ color: ${(p) => p.$positive ? "rgba(14, 203, 129, 0.65)" : "rgba(246, 70, 93, 0.65)"};
14883
+ margin-top: 1px;
14884
+ `;
14885
+ var CChevronWrap = styled9.span`
14886
+ display: flex;
14887
+ align-items: center;
14888
+ justify-content: center;
14889
+ transition: transform 0.2s;
14890
+ transform: rotate(${(p) => p.$open ? "180deg" : "0deg"});
14891
+ `;
14892
+ var CExpandedWrap = styled9.div`
14893
+ margin: 0 0.5rem 0.25rem;
14894
+ padding: 0.4rem 0.65rem 0.5rem;
14895
+ background: rgba(255, 255, 255, 0.035);
14896
+ border: 1px solid rgba(255, 255, 255, 0.06);
14897
+ border-top: none;
14898
+ border-radius: 0 0 8px 8px;
14899
+ `;
14900
+ var CDetailGrid = styled9.div`
14901
+ display: grid;
14902
+ grid-template-columns: 1fr 1fr 1fr 24px;
14903
+ gap: 0.45rem 0;
14904
+ `;
14905
+ var CDetailItem = styled9.div``;
14906
+ var CDLabel = styled9.div`
14907
+ font-size: 0.6rem;
14908
+ color: rgba(255, 255, 255, 0.3);
14909
+ margin-bottom: 1px;
14910
+ `;
14911
+ var CDValue = styled9.div`
14912
+ font-size: 0.78rem;
14913
+ font-weight: 500;
14914
+ color: rgba(255, 255, 255, 0.85);
14915
+ font-variant-numeric: tabular-nums;
14916
+ `;
14917
+ var CActionRow = styled9.div`
14918
+ display: grid;
14919
+ grid-template-columns: 1fr 1fr;
14920
+ gap: 0.5rem;
14921
+ margin-top: 0.5rem;
14922
+ `;
14923
+ var CCloseBtn = styled9.button`
14924
+ background: transparent;
14925
+ border: 1px solid rgba(230, 200, 126, 0.25);
14926
+ border-radius: 6px;
14927
+ padding: 0.45rem 0.6rem;
14928
+ font-size: 0.72rem;
14929
+ font-weight: 600;
14930
+ color: #E6C87E;
14931
+ cursor: pointer;
14932
+ white-space: nowrap;
14933
+ text-align: center;
14934
+ transition: all 0.15s ease;
14935
+ &:hover {
14936
+ background: rgba(230, 200, 126, 0.1);
14937
+ border-color: rgba(230, 200, 126, 0.5);
14938
+ }
14939
+ `;
14641
14940
  function PropertyBuy({
14642
14941
  propertyName = "Loaf Property",
14643
14942
  propertyLocation: propertyLocationLabel = "Sydney, NSW",