@loafmarkets/ui 0.1.411 → 0.1.412

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1062,6 +1062,18 @@ type PortfolioActivityPanelProps = {
1062
1062
  /** Click handler for the asset name in the Open Orders / Order History / Trade History rows — opens that asset. */
1063
1063
  onAssetClick?: (tokenName: string) => void;
1064
1064
  onClosePosition?: (tokenName: string, type: 'market' | 'limit', quantity: number, marketPrice: number) => void;
1065
+ /**
1066
+ * Close EVERY open position, in one handover to the host page. Sell All only
1067
+ * renders when this is provided.
1068
+ *
1069
+ * The panel deliberately does not sequence this itself: `onClosePosition` is
1070
+ * the per-ROW action, and on a trading page it re-points the page at that
1071
+ * row's market — so fanning it out per position navigated once per position
1072
+ * and closed nothing. The host owns ordering, per-order submission and the
1073
+ * result report (and, once the backend session signer is retired, the
1074
+ * signature prompt each order needs).
1075
+ */
1076
+ onCloseAllPositions?: (type: 'market' | 'limit') => Promise<void> | void;
1065
1077
  /** Open the shareable position card for a held position. */
1066
1078
  onSharePosition?: (pos: PortfolioPosition) => void;
1067
1079
  offeringOrders?: readonly OfferingOrder[];
@@ -1080,7 +1092,7 @@ type PortfolioActivityPanelProps = {
1080
1092
  className?: string;
1081
1093
  style?: React.CSSProperties;
1082
1094
  };
1083
- declare function PortfolioActivityPanel({ positions, showPositionsTab, showSubscriptionsTab, onPositionClick, onSharePosition, onAssetClick, onClosePosition, offeringOrders, openOrders, orderHistory, tradeHistory, transfers, onCancelOrder, onCancelAllOrders, cancellingOrderId, compactPositions, defaultTab, onTabChange, pageSize, blockExplorerBaseUrl: _blockExplorerBaseUrl, className, style, }: PortfolioActivityPanelProps): react_jsx_runtime.JSX.Element;
1095
+ declare function PortfolioActivityPanel({ positions, showPositionsTab, showSubscriptionsTab, onPositionClick, onSharePosition, onAssetClick, onClosePosition, onCloseAllPositions, offeringOrders, openOrders, orderHistory, tradeHistory, transfers, onCancelOrder, onCancelAllOrders, cancellingOrderId, compactPositions, defaultTab, onTabChange, pageSize, blockExplorerBaseUrl: _blockExplorerBaseUrl, className, style, }: PortfolioActivityPanelProps): react_jsx_runtime.JSX.Element;
1084
1096
 
1085
1097
  type SelectorItem = {
1086
1098
  readonly tokenName: string;
package/dist/index.d.ts CHANGED
@@ -1062,6 +1062,18 @@ type PortfolioActivityPanelProps = {
1062
1062
  /** Click handler for the asset name in the Open Orders / Order History / Trade History rows — opens that asset. */
1063
1063
  onAssetClick?: (tokenName: string) => void;
1064
1064
  onClosePosition?: (tokenName: string, type: 'market' | 'limit', quantity: number, marketPrice: number) => void;
1065
+ /**
1066
+ * Close EVERY open position, in one handover to the host page. Sell All only
1067
+ * renders when this is provided.
1068
+ *
1069
+ * The panel deliberately does not sequence this itself: `onClosePosition` is
1070
+ * the per-ROW action, and on a trading page it re-points the page at that
1071
+ * row's market — so fanning it out per position navigated once per position
1072
+ * and closed nothing. The host owns ordering, per-order submission and the
1073
+ * result report (and, once the backend session signer is retired, the
1074
+ * signature prompt each order needs).
1075
+ */
1076
+ onCloseAllPositions?: (type: 'market' | 'limit') => Promise<void> | void;
1065
1077
  /** Open the shareable position card for a held position. */
1066
1078
  onSharePosition?: (pos: PortfolioPosition) => void;
1067
1079
  offeringOrders?: readonly OfferingOrder[];
@@ -1080,7 +1092,7 @@ type PortfolioActivityPanelProps = {
1080
1092
  className?: string;
1081
1093
  style?: React.CSSProperties;
1082
1094
  };
1083
- declare function PortfolioActivityPanel({ positions, showPositionsTab, showSubscriptionsTab, onPositionClick, onSharePosition, onAssetClick, onClosePosition, offeringOrders, openOrders, orderHistory, tradeHistory, transfers, onCancelOrder, onCancelAllOrders, cancellingOrderId, compactPositions, defaultTab, onTabChange, pageSize, blockExplorerBaseUrl: _blockExplorerBaseUrl, className, style, }: PortfolioActivityPanelProps): react_jsx_runtime.JSX.Element;
1095
+ declare function PortfolioActivityPanel({ positions, showPositionsTab, showSubscriptionsTab, onPositionClick, onSharePosition, onAssetClick, onClosePosition, onCloseAllPositions, offeringOrders, openOrders, orderHistory, tradeHistory, transfers, onCancelOrder, onCancelAllOrders, cancellingOrderId, compactPositions, defaultTab, onTabChange, pageSize, blockExplorerBaseUrl: _blockExplorerBaseUrl, className, style, }: PortfolioActivityPanelProps): react_jsx_runtime.JSX.Element;
1084
1096
 
1085
1097
  type SelectorItem = {
1086
1098
  readonly tokenName: string;
package/dist/index.js CHANGED
@@ -15222,6 +15222,7 @@ function PortfolioActivityPanel({
15222
15222
  onSharePosition,
15223
15223
  onAssetClick,
15224
15224
  onClosePosition,
15225
+ onCloseAllPositions,
15225
15226
  offeringOrders = [],
15226
15227
  openOrders = [],
15227
15228
  orderHistory = [],
@@ -15246,6 +15247,8 @@ function PortfolioActivityPanel({
15246
15247
  const [cancellingAll, setCancellingAll] = React5.useState(false);
15247
15248
  const [closeAllOpen, setCloseAllOpen] = React5.useState(false);
15248
15249
  const [closeAllType, setCloseAllType] = React5.useState("market");
15250
+ const [closingAll, setClosingAll] = React5.useState(false);
15251
+ const hasPositionActions = !!(onClosePosition || onSharePosition || onCloseAllPositions);
15249
15252
  const [posSortKey, setPosSortKey] = React5.useState("asset");
15250
15253
  const [posSortAsc, setPosSortAsc] = React5.useState(true);
15251
15254
  const handlePosSort = (key) => {
@@ -15424,7 +15427,6 @@ function PortfolioActivityPanel({
15424
15427
  const pagedTradeHistory = sortedTradeHistory.slice(currentPage * pageSize, (currentPage + 1) * pageSize);
15425
15428
  const pagedTransfers = sortedTransfers.slice(currentPage * pageSize, (currentPage + 1) * pageSize);
15426
15429
  return /* @__PURE__ */ jsxRuntime.jsxs(Container2, { className, style, children: [
15427
- /* @__PURE__ */ jsxRuntime.jsx(PanelTitle, { children: "Activity" }),
15428
15430
  /* @__PURE__ */ jsxRuntime.jsxs(TabContainer, { children: [
15429
15431
  showPositionsTab && /* @__PURE__ */ jsxRuntime.jsxs(Tab, { $active: activeTab === "positions", onClick: () => handleTabChange("positions"), children: [
15430
15432
  "Trading Positions",
@@ -15480,7 +15482,7 @@ function PortfolioActivityPanel({
15480
15482
  ] }),
15481
15483
  /* @__PURE__ */ jsxRuntime.jsxs(CToolbarActions, { children: [
15482
15484
  /* @__PURE__ */ jsxRuntime.jsx(CToolbarLink, { onClick: toggleExpandAll, children: allExpanded ? "Collapse All" : "Expand All" }),
15483
- onClosePosition && /* @__PURE__ */ jsxRuntime.jsx(CToolbarLink, { onClick: () => setCloseAllOpen(true), children: "Sell All" })
15485
+ onCloseAllPositions && /* @__PURE__ */ jsxRuntime.jsx(CToolbarLink, { onClick: () => setCloseAllOpen(true), children: "Sell All" })
15484
15486
  ] })
15485
15487
  ] }),
15486
15488
  sortedPositions.map((pos) => {
@@ -15556,7 +15558,7 @@ function PortfolioActivityPanel({
15556
15558
  })
15557
15559
  ] }),
15558
15560
  positions.length > 0 && !compactPositions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15559
- /* @__PURE__ */ jsxRuntime.jsxs(PositionsHeader, { $hasClose: !!(onClosePosition || onSharePosition), children: [
15561
+ /* @__PURE__ */ jsxRuntime.jsxs(PositionsHeader, { $hasClose: hasPositionActions, children: [
15560
15562
  /* @__PURE__ */ jsxRuntime.jsxs(SortableHeaderCell, { $active: posSortKey === "asset", onClick: () => handlePosSort("asset"), children: [
15561
15563
  "Asset ",
15562
15564
  posSortKey === "asset" && (posSortAsc ? "\u2191" : "\u2193")
@@ -15581,7 +15583,7 @@ function PortfolioActivityPanel({
15581
15583
  "PNL (%) ",
15582
15584
  posSortKey === "pnl" && (posSortAsc ? "\u2191" : "\u2193")
15583
15585
  ] }),
15584
- onClosePosition && /* @__PURE__ */ jsxRuntime.jsx(PositionsHeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CloseAllHeaderBtn, { onClick: () => setCloseAllOpen(true), children: "Sell All" }) })
15586
+ onCloseAllPositions && /* @__PURE__ */ jsxRuntime.jsx(PositionsHeaderCell, { children: /* @__PURE__ */ jsxRuntime.jsx(CloseAllHeaderBtn, { onClick: () => setCloseAllOpen(true), children: "Sell All" }) })
15585
15587
  ] }),
15586
15588
  sortedPositions.map((pos) => {
15587
15589
  const currentValue = pos.totalQuantity * pos.marketPrice;
@@ -15589,7 +15591,7 @@ function PortfolioActivityPanel({
15589
15591
  const pnl = pos.propertyPnl ?? currentValue - costBasis;
15590
15592
  const pnlPercent = pos.propertyPnlPercent ?? pos.percentChange ?? 0;
15591
15593
  const isPositive = pnl >= 0;
15592
- return /* @__PURE__ */ jsxRuntime.jsxs(PositionsRow, { $hasClose: !!(onClosePosition || onSharePosition), children: [
15594
+ return /* @__PURE__ */ jsxRuntime.jsxs(PositionsRow, { $hasClose: hasPositionActions, children: [
15593
15595
  /* @__PURE__ */ jsxRuntime.jsx(PositionsCell, { children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
15594
15596
  /* @__PURE__ */ jsxRuntime.jsx(HoldingsPropertyLink, { onClick: () => onPositionClick?.(pos.tokenName, pos.isIpoAllocation), children: pos.tokenName }),
15595
15597
  pos.settling && /* @__PURE__ */ jsxRuntime.jsx(SettlingTip, { children: /* @__PURE__ */ jsxRuntime.jsx(SettlingSpinner, {}) })
@@ -15636,11 +15638,15 @@ function PortfolioActivityPanel({
15636
15638
  ] }, pos.tokenName);
15637
15639
  })
15638
15640
  ] }),
15639
- positions.length > 0 && closeAllOpen && onClosePosition && typeof document !== "undefined" && ReactDOM.createPortal(
15640
- /* @__PURE__ */ jsxRuntime.jsx(CloseAllOverlay, { onClick: () => setCloseAllOpen(false), children: /* @__PURE__ */ jsxRuntime.jsxs(CloseAllModal, { onClick: (e) => e.stopPropagation(), children: [
15641
- /* @__PURE__ */ jsxRuntime.jsx(CloseAllModalX, { onClick: () => setCloseAllOpen(false), children: "\xD7" }),
15641
+ positions.length > 0 && closeAllOpen && onCloseAllPositions && typeof document !== "undefined" && ReactDOM.createPortal(
15642
+ /* @__PURE__ */ jsxRuntime.jsx(CloseAllOverlay, { onClick: () => {
15643
+ if (!closingAll) setCloseAllOpen(false);
15644
+ }, children: /* @__PURE__ */ jsxRuntime.jsxs(CloseAllModal, { onClick: (e) => e.stopPropagation(), children: [
15645
+ /* @__PURE__ */ jsxRuntime.jsx(CloseAllModalX, { onClick: () => {
15646
+ if (!closingAll) setCloseAllOpen(false);
15647
+ }, children: "\xD7" }),
15642
15648
  /* @__PURE__ */ jsxRuntime.jsx(CloseAllTitle, { children: "Confirm Sell All" }),
15643
- /* @__PURE__ */ jsxRuntime.jsx(CloseAllDesc, { children: "This will sell all your positions and cancel their associated TP/SL orders." }),
15649
+ /* @__PURE__ */ jsxRuntime.jsx(CloseAllDesc, { children: "This places a sell order for every position you hold, one at a time." }),
15644
15650
  /* @__PURE__ */ jsxRuntime.jsxs(CloseAllOption, { onClick: () => setCloseAllType("market"), children: [
15645
15651
  /* @__PURE__ */ jsxRuntime.jsx(CloseAllRadio, { $selected: closeAllType === "market" }),
15646
15652
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Market Sell" })
@@ -15649,14 +15655,22 @@ function PortfolioActivityPanel({
15649
15655
  /* @__PURE__ */ jsxRuntime.jsx(CloseAllRadio, { $selected: closeAllType === "limit" }),
15650
15656
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Limit Sell at Mid Price" })
15651
15657
  ] }),
15652
- /* @__PURE__ */ jsxRuntime.jsxs(CloseAllConfirmBtn, { onClick: () => {
15653
- positions.forEach((pos) => onClosePosition(pos.tokenName, closeAllType, pos.quantity, pos.marketPrice));
15654
- setCloseAllOpen(false);
15655
- }, children: [
15656
- "Confirm ",
15657
- closeAllType === "market" ? "Market" : "Limit",
15658
- " Sell"
15659
- ] })
15658
+ /* @__PURE__ */ jsxRuntime.jsx(
15659
+ CloseAllConfirmBtn,
15660
+ {
15661
+ disabled: closingAll,
15662
+ onClick: async () => {
15663
+ setClosingAll(true);
15664
+ try {
15665
+ await onCloseAllPositions(closeAllType);
15666
+ } finally {
15667
+ setClosingAll(false);
15668
+ setCloseAllOpen(false);
15669
+ }
15670
+ },
15671
+ children: closingAll ? "Selling\u2026" : `Confirm ${closeAllType === "market" ? "Market" : "Limit"} Sell`
15672
+ }
15673
+ )
15660
15674
  ] }) }),
15661
15675
  document.body
15662
15676
  )
@@ -16215,17 +16229,6 @@ var ContentScroll = styled10__default.default.div`
16215
16229
  &::-webkit-scrollbar-track { background: transparent; }
16216
16230
  &::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.1); border-radius: 2px; }
16217
16231
  `;
16218
- var PanelTitle = styled10__default.default.h3`
16219
- font-size: 1rem;
16220
- font-weight: 600;
16221
- color: var(--color-text, #fff);
16222
- margin: 0 0 0.75rem;
16223
- padding-left: 1rem;
16224
- /* Redundant on mobile — the tab row already says what this is. Reclaim the space. */
16225
- @media (max-width: 768px) {
16226
- display: none;
16227
- }
16228
- `;
16229
16232
  var TabContainer = styled10__default.default.div`
16230
16233
  display: flex;
16231
16234
  gap: 0;
@@ -16678,9 +16681,14 @@ var CloseAllConfirmBtn = styled10__default.default.button`
16678
16681
  cursor: pointer;
16679
16682
  transition: all 0.15s ease;
16680
16683
 
16681
- &:hover {
16684
+ &:hover:not(:disabled) {
16682
16685
  background: rgba(246, 70, 93, 0.25);
16683
16686
  }
16687
+
16688
+ &:disabled {
16689
+ opacity: 0.5;
16690
+ cursor: not-allowed;
16691
+ }
16684
16692
  `;
16685
16693
  var CToolbar = styled10__default.default.div`
16686
16694
  display: flex;