@luxfi/ui 6.1.3 → 7.1.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 (241) 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 +430 -0
  6. package/dist/alert.d.cts +30 -0
  7. package/dist/alert.d.ts +30 -0
  8. package/dist/alert.js +408 -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 +452 -0
  14. package/dist/badge.d.cts +19 -0
  15. package/dist/badge.d.ts +19 -0
  16. package/dist/badge.js +431 -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 +578 -0
  22. package/dist/button.d.cts +55 -0
  23. package/dist/button.d.ts +55 -0
  24. package/dist/button.js +553 -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 +92 -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 +70 -0
  33. package/dist/collapsible.cjs +555 -0
  34. package/dist/collapsible.d.cts +23 -0
  35. package/dist/collapsible.d.ts +23 -0
  36. package/dist/collapsible.js +532 -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 +295 -0
  42. package/dist/dialog.d.cts +65 -0
  43. package/dist/dialog.d.ts +65 -0
  44. package/dist/dialog.js +263 -0
  45. package/dist/drawer.cjs +231 -0
  46. package/dist/drawer.d.cts +36 -0
  47. package/dist/drawer.d.ts +36 -0
  48. package/dist/drawer.js +199 -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 +41 -0
  66. package/dist/heading.d.cts +10 -0
  67. package/dist/heading.d.ts +10 -0
  68. package/dist/heading.js +35 -0
  69. package/dist/icon-button.cjs +367 -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 +345 -0
  73. package/dist/image.cjs +425 -0
  74. package/dist/image.d.cts +57 -0
  75. package/dist/image.d.ts +57 -0
  76. package/dist/image.js +404 -0
  77. package/dist/index.cjs +7220 -0
  78. package/dist/index.d.cts +55 -0
  79. package/dist/index.d.ts +55 -0
  80. package/dist/index.js +7043 -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 +483 -0
  90. package/dist/link.d.cts +37 -0
  91. package/dist/link.d.ts +37 -0
  92. package/dist/link.js +459 -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 +342 -0
  114. package/dist/popover.d.cts +73 -0
  115. package/dist/popover.d.ts +73 -0
  116. package/dist/popover.js +310 -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 +644 -0
  138. package/dist/select.d.cts +130 -0
  139. package/dist/select.d.ts +130 -0
  140. package/dist/select.js +610 -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 +223 -0
  146. package/dist/skeleton.d.cts +60 -0
  147. package/dist/skeleton.d.ts +60 -0
  148. package/dist/skeleton.js +199 -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 +897 -0
  162. package/dist/table.d.cts +107 -0
  163. package/dist/table.d.ts +107 -0
  164. package/dist/table.js +866 -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 +529 -0
  170. package/dist/tag.d.cts +21 -0
  171. package/dist/tag.d.ts +21 -0
  172. package/dist/tag.js +507 -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 +172 -0
  182. package/dist/tooltip.d.cts +38 -0
  183. package/dist/tooltip.d.ts +38 -0
  184. package/dist/tooltip.js +150 -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 -89
  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 +147 -0
  194. package/src/bank.tsx +325 -0
  195. package/src/button.tsx +477 -0
  196. package/src/checkbox.tsx +307 -0
  197. package/src/close-button.tsx +77 -0
  198. package/src/collapsible.tsx +126 -0
  199. package/src/color-mode.tsx +125 -0
  200. package/src/dialog.tsx +346 -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 +44 -0
  207. package/src/icon-button.tsx +217 -0
  208. package/src/image.tsx +280 -0
  209. package/src/index.ts +267 -138
  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 +386 -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 +254 -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 +191 -0
  237. package/src/utils/cn.ts +7 -0
  238. package/src/utils.ts +6 -0
  239. package/tokens.css +438 -0
  240. package/LICENSE +0 -122
  241. package/README.md +0 -109
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var RadixSlider = require('@radix-ui/react-slider');
5
+ var React = require('react');
6
+ var clsx = require('clsx');
7
+ var tailwindMerge = require('tailwind-merge');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var RadixSlider__namespace = /*#__PURE__*/_interopNamespace(RadixSlider);
29
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
30
+
31
+ // src/slider.tsx
32
+ function cn(...inputs) {
33
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
34
+ }
35
+ var THUMB_SIZE = 20;
36
+ var TRACK_HEIGHT = 6;
37
+ var Slider = React__namespace.forwardRef(
38
+ function Slider2(props, ref) {
39
+ const {
40
+ marks: marksProp,
41
+ label,
42
+ showValue,
43
+ value,
44
+ defaultValue,
45
+ min = 0,
46
+ max = 100,
47
+ step,
48
+ disabled,
49
+ orientation,
50
+ name,
51
+ onValueChange,
52
+ onValueCommit,
53
+ className
54
+ } = props;
55
+ const resolvedValue = defaultValue ?? value;
56
+ const marks = marksProp?.map((mark) => {
57
+ if (typeof mark === "number") return { value: mark, label: void 0 };
58
+ return mark;
59
+ });
60
+ const hasMarkLabel = Boolean(marks?.some((mark) => mark.label));
61
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
62
+ label && !showValue && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-text-secondary", children: label }),
63
+ label && showValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-text-secondary", children: label }),
65
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-text-secondary", children: (value ?? defaultValue ?? [])?.join(", ") })
66
+ ] }),
67
+ /* @__PURE__ */ jsxRuntime.jsxs(
68
+ RadixSlider__namespace.Root,
69
+ {
70
+ ref,
71
+ className: cn(
72
+ "relative flex w-full touch-none select-none items-center",
73
+ hasMarkLabel && "mb-6"
74
+ ),
75
+ value,
76
+ defaultValue,
77
+ min,
78
+ max,
79
+ step,
80
+ disabled,
81
+ orientation,
82
+ name,
83
+ onValueChange,
84
+ onValueCommit,
85
+ children: [
86
+ /* @__PURE__ */ jsxRuntime.jsx(
87
+ RadixSlider__namespace.Track,
88
+ {
89
+ className: cn(
90
+ "relative grow rounded-full bg-border-divider",
91
+ `h-[${TRACK_HEIGHT}px]`
92
+ ),
93
+ children: /* @__PURE__ */ jsxRuntime.jsx(RadixSlider__namespace.Range, { className: "absolute h-full rounded-full bg-link-primary" })
94
+ }
95
+ ),
96
+ resolvedValue?.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
97
+ RadixSlider__namespace.Thumb,
98
+ {
99
+ className: cn(
100
+ `block h-[${THUMB_SIZE}px] w-[${THUMB_SIZE}px]`,
101
+ "rounded-full border-2 border-link-primary bg-white",
102
+ "shadow-sm transition-colors",
103
+ "hover:border-link-primary-hover",
104
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-link-primary focus-visible:ring-offset-2",
105
+ "disabled:pointer-events-none disabled:opacity-50"
106
+ )
107
+ },
108
+ index
109
+ ))
110
+ ]
111
+ }
112
+ ),
113
+ /* @__PURE__ */ jsxRuntime.jsx(SliderMarks, { marks, min, max })
114
+ ] });
115
+ }
116
+ );
117
+ function SliderMarks(props) {
118
+ const { marks, min, max } = props;
119
+ if (!marks?.length) return null;
120
+ const range = max - min;
121
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full h-4", children: marks.map((mark, index) => {
122
+ const percent = (mark.value - min) / range * 100;
123
+ return /* @__PURE__ */ jsxRuntime.jsxs(
124
+ "div",
125
+ {
126
+ className: "absolute flex flex-col items-center -translate-x-1/2",
127
+ style: { left: `${percent}%` },
128
+ children: [
129
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1.5 w-0.5 bg-border-divider" }),
130
+ mark.label != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 text-xs text-text-secondary whitespace-nowrap", children: mark.label })
131
+ ]
132
+ },
133
+ index
134
+ );
135
+ }) });
136
+ }
137
+
138
+ exports.Slider = Slider;
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ interface SliderProps {
4
+ readonly marks?: Array<number | {
5
+ readonly value: number;
6
+ readonly label: React.ReactNode;
7
+ }>;
8
+ readonly label?: React.ReactNode;
9
+ readonly showValue?: boolean;
10
+ readonly value?: Array<number>;
11
+ readonly defaultValue?: Array<number>;
12
+ readonly min?: number;
13
+ readonly max?: number;
14
+ readonly step?: number;
15
+ readonly disabled?: boolean;
16
+ readonly orientation?: 'horizontal' | 'vertical';
17
+ readonly name?: string;
18
+ readonly onValueChange?: (value: Array<number>) => void;
19
+ readonly onValueCommit?: (value: Array<number>) => void;
20
+ readonly className?: string;
21
+ }
22
+ declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLSpanElement>>;
23
+
24
+ export { Slider, type SliderProps };
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+
3
+ interface SliderProps {
4
+ readonly marks?: Array<number | {
5
+ readonly value: number;
6
+ readonly label: React.ReactNode;
7
+ }>;
8
+ readonly label?: React.ReactNode;
9
+ readonly showValue?: boolean;
10
+ readonly value?: Array<number>;
11
+ readonly defaultValue?: Array<number>;
12
+ readonly min?: number;
13
+ readonly max?: number;
14
+ readonly step?: number;
15
+ readonly disabled?: boolean;
16
+ readonly orientation?: 'horizontal' | 'vertical';
17
+ readonly name?: string;
18
+ readonly onValueChange?: (value: Array<number>) => void;
19
+ readonly onValueCommit?: (value: Array<number>) => void;
20
+ readonly className?: string;
21
+ }
22
+ declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLSpanElement>>;
23
+
24
+ export { Slider, type SliderProps };
package/dist/slider.js ADDED
@@ -0,0 +1,115 @@
1
+ "use client";
2
+ import * as RadixSlider from '@radix-ui/react-slider';
3
+ import * as React from 'react';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ // src/slider.tsx
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+ var THUMB_SIZE = 20;
13
+ var TRACK_HEIGHT = 6;
14
+ var Slider = React.forwardRef(
15
+ function Slider2(props, ref) {
16
+ const {
17
+ marks: marksProp,
18
+ label,
19
+ showValue,
20
+ value,
21
+ defaultValue,
22
+ min = 0,
23
+ max = 100,
24
+ step,
25
+ disabled,
26
+ orientation,
27
+ name,
28
+ onValueChange,
29
+ onValueCommit,
30
+ className
31
+ } = props;
32
+ const resolvedValue = defaultValue ?? value;
33
+ const marks = marksProp?.map((mark) => {
34
+ if (typeof mark === "number") return { value: mark, label: void 0 };
35
+ return mark;
36
+ });
37
+ const hasMarkLabel = Boolean(marks?.some((mark) => mark.label));
38
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
39
+ label && !showValue && /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-text-secondary", children: label }),
40
+ label && showValue && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
41
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-text-secondary", children: label }),
42
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-text-secondary", children: (value ?? defaultValue ?? [])?.join(", ") })
43
+ ] }),
44
+ /* @__PURE__ */ jsxs(
45
+ RadixSlider.Root,
46
+ {
47
+ ref,
48
+ className: cn(
49
+ "relative flex w-full touch-none select-none items-center",
50
+ hasMarkLabel && "mb-6"
51
+ ),
52
+ value,
53
+ defaultValue,
54
+ min,
55
+ max,
56
+ step,
57
+ disabled,
58
+ orientation,
59
+ name,
60
+ onValueChange,
61
+ onValueCommit,
62
+ children: [
63
+ /* @__PURE__ */ jsx(
64
+ RadixSlider.Track,
65
+ {
66
+ className: cn(
67
+ "relative grow rounded-full bg-border-divider",
68
+ `h-[${TRACK_HEIGHT}px]`
69
+ ),
70
+ children: /* @__PURE__ */ jsx(RadixSlider.Range, { className: "absolute h-full rounded-full bg-link-primary" })
71
+ }
72
+ ),
73
+ resolvedValue?.map((_, index) => /* @__PURE__ */ jsx(
74
+ RadixSlider.Thumb,
75
+ {
76
+ className: cn(
77
+ `block h-[${THUMB_SIZE}px] w-[${THUMB_SIZE}px]`,
78
+ "rounded-full border-2 border-link-primary bg-white",
79
+ "shadow-sm transition-colors",
80
+ "hover:border-link-primary-hover",
81
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-link-primary focus-visible:ring-offset-2",
82
+ "disabled:pointer-events-none disabled:opacity-50"
83
+ )
84
+ },
85
+ index
86
+ ))
87
+ ]
88
+ }
89
+ ),
90
+ /* @__PURE__ */ jsx(SliderMarks, { marks, min, max })
91
+ ] });
92
+ }
93
+ );
94
+ function SliderMarks(props) {
95
+ const { marks, min, max } = props;
96
+ if (!marks?.length) return null;
97
+ const range = max - min;
98
+ return /* @__PURE__ */ jsx("div", { className: "relative w-full h-4", children: marks.map((mark, index) => {
99
+ const percent = (mark.value - min) / range * 100;
100
+ return /* @__PURE__ */ jsxs(
101
+ "div",
102
+ {
103
+ className: "absolute flex flex-col items-center -translate-x-1/2",
104
+ style: { left: `${percent}%` },
105
+ children: [
106
+ /* @__PURE__ */ jsx("div", { className: "h-1.5 w-0.5 bg-border-divider" }),
107
+ mark.label != null && /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-xs text-text-secondary whitespace-nowrap", children: mark.label })
108
+ ]
109
+ },
110
+ index
111
+ );
112
+ }) });
113
+ }
114
+
115
+ export { Slider };
@@ -0,0 +1,373 @@
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 findATM(strikes, spot) {
33
+ if (strikes.length === 0) return spot;
34
+ return strikes.reduce(
35
+ (prev, curr) => Math.abs(curr - spot) < Math.abs(prev - spot) ? curr : prev
36
+ );
37
+ }
38
+ function findOTM(strikes, spot, type, offset) {
39
+ const sorted = [...strikes].sort((a, b) => a - b);
40
+ const atm = findATM(strikes, spot);
41
+ const atIdx = sorted.indexOf(atm);
42
+ if (type === "call") {
43
+ return sorted[Math.min(atIdx + offset, sorted.length - 1)] ?? atm;
44
+ }
45
+ return sorted[Math.max(atIdx - offset, 0)] ?? atm;
46
+ }
47
+ var STRATEGY_PRESETS = [
48
+ {
49
+ label: "Bull Call Spread",
50
+ value: "bull_call_spread",
51
+ description: "Buy lower strike call, sell higher strike call",
52
+ buildLegs: (strikes, spot, exp) => {
53
+ const lower = findATM(strikes, spot);
54
+ const upper = findOTM(strikes, spot, "call", 2);
55
+ return [
56
+ { action: "buy", type: "call", strike: lower, expiration: exp, quantity: 1 },
57
+ { action: "sell", type: "call", strike: upper, expiration: exp, quantity: 1 }
58
+ ];
59
+ }
60
+ },
61
+ {
62
+ label: "Bear Put Spread",
63
+ value: "bear_put_spread",
64
+ description: "Buy higher strike put, sell lower strike put",
65
+ buildLegs: (strikes, spot, exp) => {
66
+ const upper = findATM(strikes, spot);
67
+ const lower = findOTM(strikes, spot, "put", 2);
68
+ return [
69
+ { action: "buy", type: "put", strike: upper, expiration: exp, quantity: 1 },
70
+ { action: "sell", type: "put", strike: lower, expiration: exp, quantity: 1 }
71
+ ];
72
+ }
73
+ },
74
+ {
75
+ label: "Iron Condor",
76
+ value: "iron_condor",
77
+ description: "Sell OTM put + call, buy further OTM put + call",
78
+ buildLegs: (strikes, spot, exp) => {
79
+ const sellPut = findOTM(strikes, spot, "put", 1);
80
+ const buyPut = findOTM(strikes, spot, "put", 3);
81
+ const sellCall = findOTM(strikes, spot, "call", 1);
82
+ const buyCall = findOTM(strikes, spot, "call", 3);
83
+ return [
84
+ { action: "buy", type: "put", strike: buyPut, expiration: exp, quantity: 1 },
85
+ { action: "sell", type: "put", strike: sellPut, expiration: exp, quantity: 1 },
86
+ { action: "sell", type: "call", strike: sellCall, expiration: exp, quantity: 1 },
87
+ { action: "buy", type: "call", strike: buyCall, expiration: exp, quantity: 1 }
88
+ ];
89
+ }
90
+ },
91
+ {
92
+ label: "Butterfly",
93
+ value: "butterfly",
94
+ description: "Buy 1 low, sell 2 middle, buy 1 high",
95
+ buildLegs: (strikes, spot, exp) => {
96
+ const mid = findATM(strikes, spot);
97
+ const low = findOTM(strikes, spot, "put", 2);
98
+ const high = findOTM(strikes, spot, "call", 2);
99
+ return [
100
+ { action: "buy", type: "call", strike: low, expiration: exp, quantity: 1 },
101
+ { action: "sell", type: "call", strike: mid, expiration: exp, quantity: 2 },
102
+ { action: "buy", type: "call", strike: high, expiration: exp, quantity: 1 }
103
+ ];
104
+ }
105
+ },
106
+ {
107
+ label: "Straddle",
108
+ value: "straddle",
109
+ description: "Buy call + put at same strike",
110
+ buildLegs: (strikes, spot, exp) => {
111
+ const atm = findATM(strikes, spot);
112
+ return [
113
+ { action: "buy", type: "call", strike: atm, expiration: exp, quantity: 1 },
114
+ { action: "buy", type: "put", strike: atm, expiration: exp, quantity: 1 }
115
+ ];
116
+ }
117
+ },
118
+ {
119
+ label: "Strangle",
120
+ value: "strangle",
121
+ description: "Buy OTM call + OTM put",
122
+ buildLegs: (strikes, spot, exp) => {
123
+ const otmCall = findOTM(strikes, spot, "call", 2);
124
+ const otmPut = findOTM(strikes, spot, "put", 2);
125
+ return [
126
+ { action: "buy", type: "put", strike: otmPut, expiration: exp, quantity: 1 },
127
+ { action: "buy", type: "call", strike: otmCall, expiration: exp, quantity: 1 }
128
+ ];
129
+ }
130
+ },
131
+ {
132
+ label: "Custom",
133
+ value: "custom",
134
+ description: "Build your own multi-leg strategy",
135
+ buildLegs: (_strikes, spot, exp) => [
136
+ { action: "buy", type: "call", strike: spot, expiration: exp, quantity: 1 }
137
+ ]
138
+ }
139
+ ];
140
+ function LegRow({ leg, index, strikes, expirations, removable, onChange, onRemove }) {
141
+ const update = (patch) => {
142
+ onChange(index, { ...leg, ...patch });
143
+ };
144
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-md bg-zinc-800/50 px-2 py-1.5", children: [
145
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-mono text-zinc-500 w-4 shrink-0", children: index + 1 }),
146
+ /* @__PURE__ */ jsxRuntime.jsx(
147
+ "button",
148
+ {
149
+ type: "button",
150
+ className: cn(
151
+ "px-2 py-0.5 rounded text-xs font-semibold transition-colors",
152
+ leg.action === "buy" ? "bg-emerald-900/60 text-emerald-400" : "bg-red-900/60 text-red-400"
153
+ ),
154
+ onClick: () => update({ action: leg.action === "buy" ? "sell" : "buy" }),
155
+ children: leg.action === "buy" ? "BUY" : "SELL"
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsxRuntime.jsx(
159
+ "button",
160
+ {
161
+ type: "button",
162
+ className: cn(
163
+ "px-2 py-0.5 rounded text-xs font-medium transition-colors",
164
+ leg.type === "call" ? "bg-blue-900/40 text-blue-400" : "bg-orange-900/40 text-orange-400"
165
+ ),
166
+ onClick: () => update({ type: leg.type === "call" ? "put" : "call" }),
167
+ children: leg.type === "call" ? "CALL" : "PUT"
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsxRuntime.jsx(
171
+ "select",
172
+ {
173
+ value: leg.strike,
174
+ onChange: (e) => update({ strike: Number(e.target.value) }),
175
+ className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs font-mono text-zinc-200 outline-none focus:border-zinc-500 min-w-[72px]",
176
+ children: strikes.map((s) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: s, children: s.toFixed(2) }, s))
177
+ }
178
+ ),
179
+ /* @__PURE__ */ jsxRuntime.jsx(
180
+ "select",
181
+ {
182
+ value: leg.expiration,
183
+ onChange: (e) => update({ expiration: e.target.value }),
184
+ className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs text-zinc-200 outline-none focus:border-zinc-500 min-w-[80px]",
185
+ children: expirations.map((exp) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: exp, children: exp }, exp))
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsxRuntime.jsx(
189
+ "input",
190
+ {
191
+ type: "number",
192
+ min: 1,
193
+ max: 999,
194
+ value: leg.quantity,
195
+ onChange: (e) => update({ quantity: Math.max(1, parseInt(e.target.value, 10) || 1) }),
196
+ className: "bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 text-xs font-mono text-zinc-200 outline-none focus:border-zinc-500 w-[48px] text-center"
197
+ }
198
+ ),
199
+ leg.premium !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
200
+ "font-mono tabular-nums text-xs ml-auto",
201
+ leg.premium >= 0 ? "text-emerald-400" : "text-red-400"
202
+ ), children: [
203
+ leg.premium >= 0 ? "+" : "",
204
+ leg.premium.toFixed(2)
205
+ ] }),
206
+ removable && /* @__PURE__ */ jsxRuntime.jsx(
207
+ "button",
208
+ {
209
+ type: "button",
210
+ onClick: () => onRemove(index),
211
+ className: "ml-auto p-0.5 text-zinc-500 hover:text-red-400 transition-colors",
212
+ "aria-label": "Remove leg",
213
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
214
+ }
215
+ )
216
+ ] });
217
+ }
218
+ var StrategyBuilder = React__namespace.forwardRef(
219
+ function StrategyBuilder2(props, ref) {
220
+ const {
221
+ underlying,
222
+ expirations,
223
+ strikes,
224
+ spotPrice,
225
+ onSubmit,
226
+ className,
227
+ ...rest
228
+ } = props;
229
+ const defaultExp = expirations[0] ?? "";
230
+ const [strategyType, setStrategyType] = React__namespace.useState("bull_call_spread");
231
+ const [legs, setLegs] = React__namespace.useState(() => {
232
+ const preset = STRATEGY_PRESETS.find((p) => p.value === "bull_call_spread");
233
+ return preset ? preset.buildLegs(strikes, spotPrice, defaultExp) : [];
234
+ });
235
+ const handleStrategyChange = React__namespace.useCallback(
236
+ (e) => {
237
+ const type = e.target.value;
238
+ setStrategyType(type);
239
+ const preset = STRATEGY_PRESETS.find((p) => p.value === type);
240
+ if (preset) {
241
+ setLegs(preset.buildLegs(strikes, spotPrice, defaultExp));
242
+ }
243
+ },
244
+ [strikes, spotPrice, defaultExp]
245
+ );
246
+ const handleLegChange = React__namespace.useCallback(
247
+ (index, leg) => {
248
+ setLegs((prev) => {
249
+ const next = [...prev];
250
+ next[index] = leg;
251
+ return next;
252
+ });
253
+ },
254
+ []
255
+ );
256
+ const handleLegRemove = React__namespace.useCallback(
257
+ (index) => {
258
+ setLegs((prev) => prev.filter((_, i) => i !== index));
259
+ },
260
+ []
261
+ );
262
+ const handleAddLeg = React__namespace.useCallback(() => {
263
+ if (legs.length >= 4) return;
264
+ const atm = findATM(strikes, spotPrice);
265
+ setLegs((prev) => [
266
+ ...prev,
267
+ { action: "buy", type: "call", strike: atm, expiration: defaultExp, quantity: 1 }
268
+ ]);
269
+ }, [legs.length, strikes, spotPrice, defaultExp]);
270
+ const netPremium = React__namespace.useMemo(() => {
271
+ return legs.reduce((sum, leg) => {
272
+ if (leg.premium === void 0) return sum;
273
+ const sign = leg.action === "buy" ? -1 : 1;
274
+ return sum + sign * leg.premium * leg.quantity;
275
+ }, 0);
276
+ }, [legs]);
277
+ const handleSubmit = React__namespace.useCallback(() => {
278
+ if (!onSubmit || legs.length === 0) return;
279
+ onSubmit({
280
+ type: strategyType,
281
+ legs,
282
+ netPremium
283
+ });
284
+ }, [onSubmit, strategyType, legs, netPremium]);
285
+ const currentPreset = STRATEGY_PRESETS.find((p) => p.value === strategyType);
286
+ return /* @__PURE__ */ jsxRuntime.jsxs(
287
+ "div",
288
+ {
289
+ ref,
290
+ className: cn(
291
+ "flex flex-col gap-3 rounded-lg border border-zinc-800 bg-zinc-900/50 p-3",
292
+ className
293
+ ),
294
+ ...rest,
295
+ children: [
296
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
297
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
298
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-zinc-500", children: "Strategy" }),
299
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-zinc-200", children: underlying })
300
+ ] }),
301
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-zinc-500", children: [
302
+ "Spot: ",
303
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono tabular-nums text-zinc-300", children: spotPrice.toFixed(2) })
304
+ ] })
305
+ ] }),
306
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
307
+ "select",
308
+ {
309
+ value: strategyType,
310
+ onChange: handleStrategyChange,
311
+ className: "flex-1 bg-zinc-900 border border-zinc-700 rounded-md px-2.5 py-1.5 text-sm text-zinc-200 outline-none focus:border-zinc-500",
312
+ children: STRATEGY_PRESETS.map((preset) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: preset.value, children: preset.label }, preset.value))
313
+ }
314
+ ) }),
315
+ currentPreset && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-zinc-500 -mt-1", children: currentPreset.description }),
316
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1.5", children: legs.map((leg, i) => /* @__PURE__ */ jsxRuntime.jsx(
317
+ LegRow,
318
+ {
319
+ leg,
320
+ index: i,
321
+ strikes,
322
+ expirations,
323
+ removable: strategyType === "custom" && legs.length > 1,
324
+ onChange: handleLegChange,
325
+ onRemove: handleLegRemove
326
+ },
327
+ i
328
+ )) }),
329
+ strategyType === "custom" && legs.length < 4 && /* @__PURE__ */ jsxRuntime.jsxs(
330
+ "button",
331
+ {
332
+ type: "button",
333
+ onClick: handleAddLeg,
334
+ className: "flex items-center justify-center gap-1 rounded-md border border-dashed border-zinc-700 py-1 text-xs text-zinc-500 hover:text-zinc-300 hover:border-zinc-500 transition-colors",
335
+ children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "h-3 w-3", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 5v14M5 12h14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) }),
337
+ "Add Leg"
338
+ ]
339
+ }
340
+ ),
341
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pt-1 border-t border-zinc-800", children: [
342
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
343
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-zinc-500", children: "Net:" }),
344
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn(
345
+ "font-mono tabular-nums text-sm font-semibold",
346
+ netPremium > 0 ? "text-emerald-400" : netPremium < 0 ? "text-red-400" : "text-zinc-400"
347
+ ), children: [
348
+ netPremium > 0 ? "Credit " : netPremium < 0 ? "Debit " : "",
349
+ netPremium !== 0 ? `$${Math.abs(netPremium).toFixed(2)}` : "-"
350
+ ] })
351
+ ] }),
352
+ /* @__PURE__ */ jsxRuntime.jsx(
353
+ "button",
354
+ {
355
+ type: "button",
356
+ onClick: handleSubmit,
357
+ disabled: legs.length === 0,
358
+ className: cn(
359
+ "px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
360
+ "bg-blue-600 text-white hover:bg-blue-500",
361
+ "disabled:opacity-40 disabled:cursor-not-allowed"
362
+ ),
363
+ children: "Review Order"
364
+ }
365
+ )
366
+ ] })
367
+ ]
368
+ }
369
+ );
370
+ }
371
+ );
372
+
373
+ exports.StrategyBuilder = StrategyBuilder;