@luxfi/ui 6.1.2 → 7.0.0

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.
Files changed (240) hide show
  1. package/dist/accordion.cjs +213 -0
  2. package/dist/accordion.d.cts +74 -0
  3. package/dist/accordion.d.ts +74 -0
  4. package/dist/accordion.js +186 -0
  5. package/dist/alert.cjs +553 -0
  6. package/dist/alert.d.cts +30 -0
  7. package/dist/alert.d.ts +30 -0
  8. package/dist/alert.js +531 -0
  9. package/dist/avatar.cjs +149 -0
  10. package/dist/avatar.d.cts +25 -0
  11. package/dist/avatar.d.ts +25 -0
  12. package/dist/avatar.js +125 -0
  13. package/dist/badge.cjs +611 -0
  14. package/dist/badge.d.cts +23 -0
  15. package/dist/badge.d.ts +23 -0
  16. package/dist/badge.js +589 -0
  17. package/dist/bank.cjs +272 -0
  18. package/dist/bank.d.cts +76 -0
  19. package/dist/bank.d.ts +76 -0
  20. package/dist/bank.js +258 -0
  21. package/dist/button.cjs +689 -0
  22. package/dist/button.d.cts +52 -0
  23. package/dist/button.d.ts +52 -0
  24. package/dist/button.js +664 -0
  25. package/dist/checkbox.cjs +265 -0
  26. package/dist/checkbox.d.cts +31 -0
  27. package/dist/checkbox.d.ts +31 -0
  28. package/dist/checkbox.js +241 -0
  29. package/dist/close-button.cjs +73 -0
  30. package/dist/close-button.d.cts +9 -0
  31. package/dist/close-button.d.ts +9 -0
  32. package/dist/close-button.js +51 -0
  33. package/dist/collapsible.cjs +702 -0
  34. package/dist/collapsible.d.cts +23 -0
  35. package/dist/collapsible.d.ts +23 -0
  36. package/dist/collapsible.js +679 -0
  37. package/dist/color-mode.cjs +96 -0
  38. package/dist/color-mode.d.cts +25 -0
  39. package/dist/color-mode.d.ts +25 -0
  40. package/dist/color-mode.js +72 -0
  41. package/dist/dialog.cjs +279 -0
  42. package/dist/dialog.d.cts +66 -0
  43. package/dist/dialog.d.ts +66 -0
  44. package/dist/dialog.js +246 -0
  45. package/dist/drawer.cjs +207 -0
  46. package/dist/drawer.d.cts +36 -0
  47. package/dist/drawer.d.ts +36 -0
  48. package/dist/drawer.js +175 -0
  49. package/dist/empty-state.cjs +93 -0
  50. package/dist/empty-state.d.cts +13 -0
  51. package/dist/empty-state.d.ts +13 -0
  52. package/dist/empty-state.js +71 -0
  53. package/dist/expiration-selector.cjs +138 -0
  54. package/dist/expiration-selector.d.cts +16 -0
  55. package/dist/expiration-selector.d.ts +16 -0
  56. package/dist/expiration-selector.js +116 -0
  57. package/dist/field.cjs +183 -0
  58. package/dist/field.d.cts +24 -0
  59. package/dist/field.d.ts +24 -0
  60. package/dist/field.js +160 -0
  61. package/dist/greeks-display.cjs +114 -0
  62. package/dist/greeks-display.d.cts +14 -0
  63. package/dist/greeks-display.d.ts +14 -0
  64. package/dist/greeks-display.js +92 -0
  65. package/dist/heading.cjs +46 -0
  66. package/dist/heading.d.cts +10 -0
  67. package/dist/heading.d.ts +10 -0
  68. package/dist/heading.js +40 -0
  69. package/dist/icon-button.cjs +491 -0
  70. package/dist/icon-button.d.cts +33 -0
  71. package/dist/icon-button.d.ts +33 -0
  72. package/dist/icon-button.js +470 -0
  73. package/dist/image.cjs +572 -0
  74. package/dist/image.d.cts +57 -0
  75. package/dist/image.d.ts +57 -0
  76. package/dist/image.js +551 -0
  77. package/dist/index.cjs +7316 -0
  78. package/dist/index.d.cts +58 -0
  79. package/dist/index.d.ts +58 -0
  80. package/dist/index.js +7137 -0
  81. package/dist/input-group.cjs +155 -0
  82. package/dist/input-group.d.cts +17 -0
  83. package/dist/input-group.d.ts +17 -0
  84. package/dist/input-group.js +133 -0
  85. package/dist/input.cjs +65 -0
  86. package/dist/input.d.cts +11 -0
  87. package/dist/input.d.ts +11 -0
  88. package/dist/input.js +59 -0
  89. package/dist/link.cjs +630 -0
  90. package/dist/link.d.cts +37 -0
  91. package/dist/link.d.ts +37 -0
  92. package/dist/link.js +606 -0
  93. package/dist/menu.cjs +305 -0
  94. package/dist/menu.d.cts +84 -0
  95. package/dist/menu.d.ts +84 -0
  96. package/dist/menu.js +269 -0
  97. package/dist/option-chain.cjs +221 -0
  98. package/dist/option-chain.d.cts +37 -0
  99. package/dist/option-chain.d.ts +37 -0
  100. package/dist/option-chain.js +199 -0
  101. package/dist/option-position.cjs +164 -0
  102. package/dist/option-position.d.cts +29 -0
  103. package/dist/option-position.d.ts +29 -0
  104. package/dist/option-position.js +142 -0
  105. package/dist/pin-input.cjs +182 -0
  106. package/dist/pin-input.d.cts +25 -0
  107. package/dist/pin-input.d.ts +25 -0
  108. package/dist/pin-input.js +160 -0
  109. package/dist/pnl-diagram.cjs +453 -0
  110. package/dist/pnl-diagram.d.cts +11 -0
  111. package/dist/pnl-diagram.d.ts +11 -0
  112. package/dist/pnl-diagram.js +431 -0
  113. package/dist/popover.cjs +327 -0
  114. package/dist/popover.d.cts +73 -0
  115. package/dist/popover.d.ts +73 -0
  116. package/dist/popover.js +294 -0
  117. package/dist/progress-circle.cjs +152 -0
  118. package/dist/progress-circle.d.cts +47 -0
  119. package/dist/progress-circle.d.ts +47 -0
  120. package/dist/progress-circle.js +128 -0
  121. package/dist/progress.cjs +117 -0
  122. package/dist/progress.d.cts +28 -0
  123. package/dist/progress.d.ts +28 -0
  124. package/dist/progress.js +94 -0
  125. package/dist/provider.cjs +62 -0
  126. package/dist/provider.d.cts +7 -0
  127. package/dist/provider.d.ts +7 -0
  128. package/dist/provider.js +40 -0
  129. package/dist/radio.cjs +177 -0
  130. package/dist/radio.d.cts +53 -0
  131. package/dist/radio.d.ts +53 -0
  132. package/dist/radio.js +153 -0
  133. package/dist/rating.cjs +80 -0
  134. package/dist/rating.d.cts +14 -0
  135. package/dist/rating.d.ts +14 -0
  136. package/dist/rating.js +58 -0
  137. package/dist/select.cjs +791 -0
  138. package/dist/select.d.cts +130 -0
  139. package/dist/select.d.ts +130 -0
  140. package/dist/select.js +757 -0
  141. package/dist/separator.cjs +57 -0
  142. package/dist/separator.d.cts +13 -0
  143. package/dist/separator.d.ts +13 -0
  144. package/dist/separator.js +51 -0
  145. package/dist/skeleton.cjs +370 -0
  146. package/dist/skeleton.d.cts +60 -0
  147. package/dist/skeleton.d.ts +60 -0
  148. package/dist/skeleton.js +346 -0
  149. package/dist/slider.cjs +138 -0
  150. package/dist/slider.d.cts +24 -0
  151. package/dist/slider.d.ts +24 -0
  152. package/dist/slider.js +115 -0
  153. package/dist/strategy-builder.cjs +373 -0
  154. package/dist/strategy-builder.d.cts +26 -0
  155. package/dist/strategy-builder.d.ts +26 -0
  156. package/dist/strategy-builder.js +351 -0
  157. package/dist/switch.cjs +163 -0
  158. package/dist/switch.d.cts +27 -0
  159. package/dist/switch.d.ts +27 -0
  160. package/dist/switch.js +140 -0
  161. package/dist/table.cjs +1044 -0
  162. package/dist/table.d.cts +107 -0
  163. package/dist/table.d.ts +107 -0
  164. package/dist/table.js +1013 -0
  165. package/dist/tabs.cjs +240 -0
  166. package/dist/tabs.d.cts +78 -0
  167. package/dist/tabs.d.ts +78 -0
  168. package/dist/tabs.js +213 -0
  169. package/dist/tag.cjs +651 -0
  170. package/dist/tag.d.cts +21 -0
  171. package/dist/tag.d.ts +21 -0
  172. package/dist/tag.js +628 -0
  173. package/dist/textarea.cjs +65 -0
  174. package/dist/textarea.d.cts +11 -0
  175. package/dist/textarea.d.ts +11 -0
  176. package/dist/textarea.js +59 -0
  177. package/dist/toaster.cjs +99 -0
  178. package/dist/toaster.d.cts +29 -0
  179. package/dist/toaster.d.ts +29 -0
  180. package/dist/toaster.js +96 -0
  181. package/dist/tooltip.cjs +171 -0
  182. package/dist/tooltip.d.cts +39 -0
  183. package/dist/tooltip.d.ts +39 -0
  184. package/dist/tooltip.js +148 -0
  185. package/dist/utils.cjs +11 -0
  186. package/dist/utils.d.cts +5 -0
  187. package/dist/utils.d.ts +5 -0
  188. package/dist/utils.js +9 -0
  189. package/package.json +284 -85
  190. package/src/accordion.tsx +285 -0
  191. package/src/alert.tsx +221 -0
  192. package/src/avatar.tsx +174 -0
  193. package/src/badge.tsx +158 -0
  194. package/src/bank.tsx +325 -0
  195. package/src/button.tsx +411 -0
  196. package/src/checkbox.tsx +307 -0
  197. package/src/close-button.tsx +51 -0
  198. package/src/collapsible.tsx +126 -0
  199. package/src/color-mode.tsx +125 -0
  200. package/src/dialog.tsx +356 -0
  201. package/src/drawer.tsx +186 -0
  202. package/src/empty-state.tsx +97 -0
  203. package/src/expiration-selector.tsx +163 -0
  204. package/src/field.tsx +202 -0
  205. package/src/greeks-display.tsx +138 -0
  206. package/src/heading.tsx +55 -0
  207. package/src/icon-button.tsx +192 -0
  208. package/src/image.tsx +280 -0
  209. package/src/index.ts +268 -0
  210. package/src/input-group.tsx +159 -0
  211. package/src/input.tsx +60 -0
  212. package/src/link.tsx +326 -0
  213. package/src/menu.tsx +471 -0
  214. package/src/option-chain.tsx +261 -0
  215. package/src/option-position.tsx +200 -0
  216. package/src/pin-input.tsx +187 -0
  217. package/src/pnl-diagram.tsx +458 -0
  218. package/src/popover.tsx +400 -0
  219. package/src/progress-circle.tsx +180 -0
  220. package/src/progress.tsx +109 -0
  221. package/src/provider.tsx +12 -0
  222. package/src/radio.tsx +175 -0
  223. package/src/rating.tsx +79 -0
  224. package/src/select.tsx +696 -0
  225. package/src/separator.tsx +59 -0
  226. package/src/skeleton.tsx +302 -0
  227. package/src/slider.tsx +152 -0
  228. package/src/strategy-builder.tsx +466 -0
  229. package/src/switch.tsx +158 -0
  230. package/src/table.tsx +621 -0
  231. package/src/tabs.tsx +354 -0
  232. package/src/tag.tsx +159 -0
  233. package/src/textarea.tsx +60 -0
  234. package/src/toaster.tsx +117 -0
  235. package/src/tokens.css +438 -0
  236. package/src/tooltip.tsx +184 -0
  237. package/src/utils/cn.ts +7 -0
  238. package/src/utils.ts +6 -0
  239. package/tokens.css +438 -0
  240. package/README.md +0 -109
@@ -0,0 +1,199 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ function fmt(n, decimals = 2) {
11
+ if (n === void 0 || n === null) return "-";
12
+ return n.toFixed(decimals);
13
+ }
14
+ function fmtInt(n) {
15
+ if (n === void 0 || n === null) return "-";
16
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
17
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
18
+ return n.toLocaleString();
19
+ }
20
+ function fmtPct(n) {
21
+ if (n === void 0 || n === null) return "-";
22
+ return `${(n * 100).toFixed(1)}%`;
23
+ }
24
+ function QuoteCell({ value, highlight, align = "right", onClick, className }) {
25
+ return /* @__PURE__ */ jsx(
26
+ "td",
27
+ {
28
+ className: cn(
29
+ "px-1.5 py-1 font-mono tabular-nums text-xs whitespace-nowrap",
30
+ align === "right" ? "text-right" : "text-left",
31
+ highlight && "text-zinc-100",
32
+ !highlight && "text-zinc-400",
33
+ onClick && "cursor-pointer hover:bg-zinc-700/50 transition-colors",
34
+ className
35
+ ),
36
+ onClick,
37
+ children: value
38
+ }
39
+ );
40
+ }
41
+ var CALL_HEADERS = ["Bid", "Ask", "Last", "Vol", "OI", "IV", "Delta"];
42
+ var PUT_HEADERS = ["Delta", "IV", "OI", "Vol", "Last", "Ask", "Bid"];
43
+ var OptionChain = React.forwardRef(
44
+ function OptionChain2(props, ref) {
45
+ const {
46
+ symbol: _symbol,
47
+ expiration: _expiration,
48
+ strikes,
49
+ spotPrice,
50
+ onSelectContract,
51
+ className,
52
+ ...rest
53
+ } = props;
54
+ const handleClick = React.useCallback(
55
+ (quote, type, strike) => {
56
+ if (!quote || !onSelectContract) return;
57
+ onSelectContract({
58
+ symbol: quote.symbol,
59
+ type,
60
+ strike,
61
+ bid: quote.bid,
62
+ ask: quote.ask
63
+ });
64
+ },
65
+ [onSelectContract]
66
+ );
67
+ return /* @__PURE__ */ jsx(
68
+ "div",
69
+ {
70
+ ref,
71
+ className: cn("w-full overflow-x-auto", className),
72
+ ...rest,
73
+ children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse text-xs", children: [
74
+ /* @__PURE__ */ jsxs("thead", { children: [
75
+ /* @__PURE__ */ jsxs("tr", { className: "border-b border-zinc-800", children: [
76
+ /* @__PURE__ */ jsx(
77
+ "th",
78
+ {
79
+ colSpan: CALL_HEADERS.length,
80
+ className: "px-2 py-1.5 text-center text-[10px] font-semibold uppercase tracking-wider text-emerald-400",
81
+ children: "Calls"
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsx("th", { className: "px-2 py-1.5 text-center text-[10px] font-semibold uppercase tracking-wider text-zinc-500", children: "Strike" }),
85
+ /* @__PURE__ */ jsx(
86
+ "th",
87
+ {
88
+ colSpan: PUT_HEADERS.length,
89
+ className: "px-2 py-1.5 text-center text-[10px] font-semibold uppercase tracking-wider text-red-400",
90
+ children: "Puts"
91
+ }
92
+ )
93
+ ] }),
94
+ /* @__PURE__ */ jsxs("tr", { className: "border-b border-zinc-800/60", children: [
95
+ CALL_HEADERS.map((h) => /* @__PURE__ */ jsx(
96
+ "th",
97
+ {
98
+ className: "px-1.5 py-1 text-right text-[10px] font-medium uppercase tracking-wider text-zinc-500",
99
+ children: h
100
+ },
101
+ `call-${h}`
102
+ )),
103
+ /* @__PURE__ */ jsx("th", { className: "px-2 py-1 text-center text-[10px] font-medium uppercase tracking-wider text-zinc-500" }),
104
+ PUT_HEADERS.map((h) => /* @__PURE__ */ jsx(
105
+ "th",
106
+ {
107
+ className: cn(
108
+ "px-1.5 py-1 text-[10px] font-medium uppercase tracking-wider text-zinc-500",
109
+ h === "Bid" || h === "Ask" || h === "Last" ? "text-left" : "text-right"
110
+ ),
111
+ children: h
112
+ },
113
+ `put-${h}`
114
+ ))
115
+ ] })
116
+ ] }),
117
+ /* @__PURE__ */ jsx("tbody", { children: strikes.map((row) => {
118
+ const isATM = Math.abs(row.strike - spotPrice) <= (strikes.length > 1 ? Math.abs((strikes[1]?.strike ?? 0) - (strikes[0]?.strike ?? 0)) / 2 : 0.5);
119
+ const callITM = row.strike < spotPrice;
120
+ const putITM = row.strike > spotPrice;
121
+ const c = row.call;
122
+ const p = row.put;
123
+ return /* @__PURE__ */ jsxs(
124
+ "tr",
125
+ {
126
+ className: cn(
127
+ "border-b border-zinc-800/30 transition-colors",
128
+ isATM && "bg-zinc-800/60",
129
+ !isATM && callITM && "bg-emerald-950/20",
130
+ !isATM && putITM && "bg-red-950/20",
131
+ !isATM && !callITM && !putITM && "hover:bg-zinc-800/30"
132
+ ),
133
+ children: [
134
+ /* @__PURE__ */ jsx(
135
+ QuoteCell,
136
+ {
137
+ value: fmt(c?.bid),
138
+ highlight: !!c,
139
+ onClick: () => handleClick(c, "call", row.strike)
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsx(
143
+ QuoteCell,
144
+ {
145
+ value: fmt(c?.ask),
146
+ highlight: !!c,
147
+ onClick: () => handleClick(c, "call", row.strike)
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmt(c?.last), highlight: !!c }),
151
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtInt(c?.volume) }),
152
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtInt(c?.openInterest) }),
153
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtPct(c?.iv) }),
154
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmt(c?.delta, 3) }),
155
+ /* @__PURE__ */ jsx(
156
+ "td",
157
+ {
158
+ className: cn(
159
+ "px-2 py-1 text-center font-mono tabular-nums text-xs font-semibold",
160
+ isATM ? "text-amber-400 bg-zinc-800/80" : "text-zinc-300"
161
+ ),
162
+ children: fmt(row.strike)
163
+ }
164
+ ),
165
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmt(p?.delta, 3), align: "right" }),
166
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtPct(p?.iv), align: "right" }),
167
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtInt(p?.openInterest), align: "right" }),
168
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmtInt(p?.volume), align: "right" }),
169
+ /* @__PURE__ */ jsx(QuoteCell, { value: fmt(p?.last), align: "left", highlight: !!p }),
170
+ /* @__PURE__ */ jsx(
171
+ QuoteCell,
172
+ {
173
+ value: fmt(p?.ask),
174
+ align: "left",
175
+ highlight: !!p,
176
+ onClick: () => handleClick(p, "put", row.strike)
177
+ }
178
+ ),
179
+ /* @__PURE__ */ jsx(
180
+ QuoteCell,
181
+ {
182
+ value: fmt(p?.bid),
183
+ align: "left",
184
+ highlight: !!p,
185
+ onClick: () => handleClick(p, "put", row.strike)
186
+ }
187
+ )
188
+ ]
189
+ },
190
+ row.strike
191
+ );
192
+ }) })
193
+ ] })
194
+ }
195
+ );
196
+ }
197
+ );
198
+
199
+ export { OptionChain };
@@ -0,0 +1,164 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var React = require('react');
5
+ var clsx = require('clsx');
6
+ var tailwindMerge = require('tailwind-merge');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ function _interopNamespace(e) {
10
+ if (e && e.__esModule) return e;
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
28
+
29
+ function cn(...inputs) {
30
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
31
+ }
32
+ function formatDate(date) {
33
+ const d = new Date(date);
34
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
35
+ }
36
+ var OptionPositionCard = React__namespace.forwardRef(
37
+ function OptionPositionCard2(props, ref) {
38
+ const {
39
+ position,
40
+ onClose,
41
+ onExercise,
42
+ onRoll,
43
+ className,
44
+ ...rest
45
+ } = props;
46
+ const isLong = position.quantity > 0;
47
+ const isCall = position.type === "call";
48
+ const isProfitable = position.pnl >= 0;
49
+ return /* @__PURE__ */ jsxRuntime.jsxs(
50
+ "div",
51
+ {
52
+ ref,
53
+ className: cn(
54
+ "flex flex-col gap-2 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3",
55
+ className
56
+ ),
57
+ ...rest,
58
+ children: [
59
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
60
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
61
+ "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-semibold",
62
+ isCall ? "bg-blue-900/40 text-blue-400" : "bg-orange-900/40 text-orange-400"
63
+ ), children: [
64
+ position.underlying,
65
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono tabular-nums", children: position.strike }),
66
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "uppercase", children: position.type === "call" ? "C" : "P" }),
67
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-500 font-normal", children: formatDate(position.expiration) })
68
+ ] }) }),
69
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
70
+ "text-xs font-semibold font-mono tabular-nums",
71
+ isLong ? "text-emerald-400" : "text-red-400"
72
+ ), children: [
73
+ isLong ? "+" : "",
74
+ position.quantity
75
+ ] })
76
+ ] }),
77
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
78
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
79
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "Avg Cost" }),
80
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono tabular-nums text-xs text-zinc-300", children: [
81
+ "$",
82
+ position.avgCost.toFixed(2)
83
+ ] })
84
+ ] }),
85
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
86
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "Value" }),
87
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono tabular-nums text-xs text-zinc-300", children: [
88
+ "$",
89
+ position.currentValue.toFixed(2)
90
+ ] })
91
+ ] }),
92
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end", children: [
93
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "P/L" }),
94
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
95
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
96
+ "font-mono tabular-nums text-xs font-semibold",
97
+ isProfitable ? "text-emerald-400" : "text-red-400"
98
+ ), children: [
99
+ isProfitable ? "+" : "",
100
+ position.pnl.toFixed(2)
101
+ ] }),
102
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
103
+ "font-mono tabular-nums text-[10px]",
104
+ isProfitable ? "text-emerald-500/70" : "text-red-500/70"
105
+ ), children: [
106
+ "(",
107
+ isProfitable ? "+" : "",
108
+ position.pnlPercent.toFixed(1),
109
+ "%)"
110
+ ] })
111
+ ] })
112
+ ] })
113
+ ] }),
114
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 border-t border-zinc-800/60 pt-2", children: [
115
+ /* @__PURE__ */ jsxRuntime.jsx(GreekPill, { label: "\u0394", value: position.greeks.delta, color: "text-blue-400" }),
116
+ /* @__PURE__ */ jsxRuntime.jsx(GreekPill, { label: "\u0393", value: position.greeks.gamma, color: "text-purple-400" }),
117
+ /* @__PURE__ */ jsxRuntime.jsx(GreekPill, { label: "\u0398", value: position.greeks.theta, color: "text-red-400" }),
118
+ /* @__PURE__ */ jsxRuntime.jsx(GreekPill, { label: "\u03BD", value: position.greeks.vega, color: "text-emerald-400" })
119
+ ] }),
120
+ (onClose || onExercise || onRoll) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border-t border-zinc-800/60 pt-2", children: [
121
+ onClose && /* @__PURE__ */ jsxRuntime.jsx(
122
+ "button",
123
+ {
124
+ type: "button",
125
+ onClick: () => onClose(position),
126
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
127
+ children: "Close"
128
+ }
129
+ ),
130
+ onExercise && /* @__PURE__ */ jsxRuntime.jsx(
131
+ "button",
132
+ {
133
+ type: "button",
134
+ onClick: () => onExercise(position),
135
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
136
+ children: "Exercise"
137
+ }
138
+ ),
139
+ onRoll && /* @__PURE__ */ jsxRuntime.jsx(
140
+ "button",
141
+ {
142
+ type: "button",
143
+ onClick: () => onRoll(position),
144
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
145
+ children: "Roll"
146
+ }
147
+ )
148
+ ] })
149
+ ]
150
+ }
151
+ );
152
+ }
153
+ );
154
+ function GreekPill({ label, value, color }) {
155
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
156
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-[10px] font-semibold", color), children: label }),
157
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(
158
+ "font-mono tabular-nums text-[11px]",
159
+ value < 0 ? "text-red-400" : "text-zinc-400"
160
+ ), children: value.toFixed(4) })
161
+ ] });
162
+ }
163
+
164
+ exports.OptionPositionCard = OptionPositionCard;
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+
3
+ interface OptionPosition {
4
+ symbol: string;
5
+ underlying: string;
6
+ type: 'call' | 'put';
7
+ strike: number;
8
+ expiration: string;
9
+ quantity: number;
10
+ avgCost: number;
11
+ currentValue: number;
12
+ pnl: number;
13
+ pnlPercent: number;
14
+ greeks: {
15
+ delta: number;
16
+ gamma: number;
17
+ theta: number;
18
+ vega: number;
19
+ };
20
+ }
21
+ interface OptionPositionCardProps extends React.HTMLAttributes<HTMLDivElement> {
22
+ readonly position: OptionPosition;
23
+ readonly onClose?: (position: OptionPosition) => void;
24
+ readonly onExercise?: (position: OptionPosition) => void;
25
+ readonly onRoll?: (position: OptionPosition) => void;
26
+ }
27
+ declare const OptionPositionCard: React.ForwardRefExoticComponent<OptionPositionCardProps & React.RefAttributes<HTMLDivElement>>;
28
+
29
+ export { type OptionPosition, OptionPositionCard, type OptionPositionCardProps };
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+
3
+ interface OptionPosition {
4
+ symbol: string;
5
+ underlying: string;
6
+ type: 'call' | 'put';
7
+ strike: number;
8
+ expiration: string;
9
+ quantity: number;
10
+ avgCost: number;
11
+ currentValue: number;
12
+ pnl: number;
13
+ pnlPercent: number;
14
+ greeks: {
15
+ delta: number;
16
+ gamma: number;
17
+ theta: number;
18
+ vega: number;
19
+ };
20
+ }
21
+ interface OptionPositionCardProps extends React.HTMLAttributes<HTMLDivElement> {
22
+ readonly position: OptionPosition;
23
+ readonly onClose?: (position: OptionPosition) => void;
24
+ readonly onExercise?: (position: OptionPosition) => void;
25
+ readonly onRoll?: (position: OptionPosition) => void;
26
+ }
27
+ declare const OptionPositionCard: React.ForwardRefExoticComponent<OptionPositionCardProps & React.RefAttributes<HTMLDivElement>>;
28
+
29
+ export { type OptionPosition, OptionPositionCard, type OptionPositionCardProps };
@@ -0,0 +1,142 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import { clsx } from 'clsx';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function cn(...inputs) {
8
+ return twMerge(clsx(inputs));
9
+ }
10
+ function formatDate(date) {
11
+ const d = new Date(date);
12
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
13
+ }
14
+ var OptionPositionCard = React.forwardRef(
15
+ function OptionPositionCard2(props, ref) {
16
+ const {
17
+ position,
18
+ onClose,
19
+ onExercise,
20
+ onRoll,
21
+ className,
22
+ ...rest
23
+ } = props;
24
+ const isLong = position.quantity > 0;
25
+ const isCall = position.type === "call";
26
+ const isProfitable = position.pnl >= 0;
27
+ return /* @__PURE__ */ jsxs(
28
+ "div",
29
+ {
30
+ ref,
31
+ className: cn(
32
+ "flex flex-col gap-2 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3",
33
+ className
34
+ ),
35
+ ...rest,
36
+ children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
38
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs("span", { className: cn(
39
+ "inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs font-semibold",
40
+ isCall ? "bg-blue-900/40 text-blue-400" : "bg-orange-900/40 text-orange-400"
41
+ ), children: [
42
+ position.underlying,
43
+ /* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums", children: position.strike }),
44
+ /* @__PURE__ */ jsx("span", { className: "uppercase", children: position.type === "call" ? "C" : "P" }),
45
+ /* @__PURE__ */ jsx("span", { className: "text-zinc-500 font-normal", children: formatDate(position.expiration) })
46
+ ] }) }),
47
+ /* @__PURE__ */ jsxs("span", { className: cn(
48
+ "text-xs font-semibold font-mono tabular-nums",
49
+ isLong ? "text-emerald-400" : "text-red-400"
50
+ ), children: [
51
+ isLong ? "+" : "",
52
+ position.quantity
53
+ ] })
54
+ ] }),
55
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
56
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
57
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "Avg Cost" }),
58
+ /* @__PURE__ */ jsxs("span", { className: "font-mono tabular-nums text-xs text-zinc-300", children: [
59
+ "$",
60
+ position.avgCost.toFixed(2)
61
+ ] })
62
+ ] }),
63
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
64
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "Value" }),
65
+ /* @__PURE__ */ jsxs("span", { className: "font-mono tabular-nums text-xs text-zinc-300", children: [
66
+ "$",
67
+ position.currentValue.toFixed(2)
68
+ ] })
69
+ ] }),
70
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end", children: [
71
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] uppercase tracking-wider text-zinc-500", children: "P/L" }),
72
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
73
+ /* @__PURE__ */ jsxs("span", { className: cn(
74
+ "font-mono tabular-nums text-xs font-semibold",
75
+ isProfitable ? "text-emerald-400" : "text-red-400"
76
+ ), children: [
77
+ isProfitable ? "+" : "",
78
+ position.pnl.toFixed(2)
79
+ ] }),
80
+ /* @__PURE__ */ jsxs("span", { className: cn(
81
+ "font-mono tabular-nums text-[10px]",
82
+ isProfitable ? "text-emerald-500/70" : "text-red-500/70"
83
+ ), children: [
84
+ "(",
85
+ isProfitable ? "+" : "",
86
+ position.pnlPercent.toFixed(1),
87
+ "%)"
88
+ ] })
89
+ ] })
90
+ ] })
91
+ ] }),
92
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 border-t border-zinc-800/60 pt-2", children: [
93
+ /* @__PURE__ */ jsx(GreekPill, { label: "\u0394", value: position.greeks.delta, color: "text-blue-400" }),
94
+ /* @__PURE__ */ jsx(GreekPill, { label: "\u0393", value: position.greeks.gamma, color: "text-purple-400" }),
95
+ /* @__PURE__ */ jsx(GreekPill, { label: "\u0398", value: position.greeks.theta, color: "text-red-400" }),
96
+ /* @__PURE__ */ jsx(GreekPill, { label: "\u03BD", value: position.greeks.vega, color: "text-emerald-400" })
97
+ ] }),
98
+ (onClose || onExercise || onRoll) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-t border-zinc-800/60 pt-2", children: [
99
+ onClose && /* @__PURE__ */ jsx(
100
+ "button",
101
+ {
102
+ type: "button",
103
+ onClick: () => onClose(position),
104
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
105
+ children: "Close"
106
+ }
107
+ ),
108
+ onExercise && /* @__PURE__ */ jsx(
109
+ "button",
110
+ {
111
+ type: "button",
112
+ onClick: () => onExercise(position),
113
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
114
+ children: "Exercise"
115
+ }
116
+ ),
117
+ onRoll && /* @__PURE__ */ jsx(
118
+ "button",
119
+ {
120
+ type: "button",
121
+ onClick: () => onRoll(position),
122
+ className: "flex-1 rounded-md bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-300 hover:bg-zinc-700 hover:text-zinc-100 transition-colors",
123
+ children: "Roll"
124
+ }
125
+ )
126
+ ] })
127
+ ]
128
+ }
129
+ );
130
+ }
131
+ );
132
+ function GreekPill({ label, value, color }) {
133
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
134
+ /* @__PURE__ */ jsx("span", { className: cn("text-[10px] font-semibold", color), children: label }),
135
+ /* @__PURE__ */ jsx("span", { className: cn(
136
+ "font-mono tabular-nums text-[11px]",
137
+ value < 0 ? "text-red-400" : "text-zinc-400"
138
+ ), children: value.toFixed(4) })
139
+ ] });
140
+ }
141
+
142
+ export { OptionPositionCard };