@luxfi/ui 7.4.11 → 7.4.13
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/alert.cjs +68 -46
- package/dist/alert.js +69 -46
- package/dist/avatar.cjs +49 -47
- package/dist/avatar.js +52 -49
- package/dist/badge.cjs +82 -49
- package/dist/badge.js +83 -50
- package/dist/checkbox.cjs +42 -75
- package/dist/checkbox.js +43 -76
- package/dist/chrome.cjs +3 -7
- package/dist/chrome.js +3 -7
- package/dist/close-button.cjs +3 -7
- package/dist/close-button.js +3 -7
- package/dist/dialog.cjs +3 -7
- package/dist/dialog.js +3 -7
- package/dist/drawer.cjs +3 -7
- package/dist/drawer.js +3 -7
- package/dist/empty-state.cjs +13 -13
- package/dist/empty-state.js +13 -13
- package/dist/expiration-selector.cjs +58 -63
- package/dist/expiration-selector.js +58 -63
- package/dist/greeks-display.cjs +48 -39
- package/dist/greeks-display.js +48 -39
- package/dist/index.cjs +1053 -888
- package/dist/index.js +1054 -889
- package/dist/input-group.cjs +36 -19
- package/dist/input-group.js +37 -19
- package/dist/option-chain.cjs +89 -67
- package/dist/option-chain.js +89 -67
- package/dist/option-position.cjs +88 -85
- package/dist/option-position.js +88 -85
- package/dist/pin-input.cjs +30 -29
- package/dist/pin-input.js +30 -29
- package/dist/pnl-diagram.cjs +20 -20
- package/dist/pnl-diagram.js +20 -20
- package/dist/popover.cjs +3 -7
- package/dist/popover.js +3 -7
- package/dist/progress-circle.cjs +40 -22
- package/dist/progress-circle.d.cts +5 -5
- package/dist/progress-circle.d.ts +5 -5
- package/dist/progress-circle.js +41 -22
- package/dist/progress.cjs +15 -22
- package/dist/progress.d.cts +6 -6
- package/dist/progress.d.ts +6 -6
- package/dist/progress.js +15 -22
- package/dist/radio.cjs +35 -68
- package/dist/radio.d.cts +18 -18
- package/dist/radio.d.ts +18 -18
- package/dist/radio.js +36 -69
- package/dist/rating.cjs +15 -17
- package/dist/rating.js +15 -17
- package/dist/slider.cjs +33 -50
- package/dist/slider.js +34 -51
- package/dist/strategy-builder.cjs +194 -115
- package/dist/strategy-builder.js +194 -115
- package/dist/switch.cjs +48 -55
- package/dist/switch.js +49 -56
- package/dist/tag.cjs +115 -69
- package/dist/tag.js +116 -69
- package/dist/tooltip.cjs +28 -17
- package/dist/tooltip.js +30 -18
- package/package.json +1 -1
- package/src/alert.tsx +78 -45
- package/src/avatar.tsx +54 -38
- package/src/badge.tsx +65 -44
- package/src/checkbox.tsx +70 -89
- package/src/close-button.tsx +3 -8
- package/src/empty-state.tsx +21 -17
- package/src/expiration-selector.tsx +84 -66
- package/src/greeks-display.tsx +59 -51
- package/src/input-group.tsx +38 -24
- package/src/option-chain.tsx +154 -104
- package/src/option-position.tsx +143 -114
- package/src/pin-input.tsx +37 -29
- package/src/pnl-diagram.tsx +36 -28
- package/src/progress-circle.tsx +52 -28
- package/src/progress.tsx +17 -21
- package/src/radio.tsx +56 -76
- package/src/rating.tsx +22 -20
- package/src/slider.tsx +43 -45
- package/src/strategy-builder.tsx +260 -162
- package/src/switch.tsx +63 -64
- package/src/tag.tsx +89 -51
- package/src/tooltip.tsx +21 -13
- package/tokens.css +18 -0
package/src/strategy-builder.tsx
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { Text, View, XStack, YStack } from '@hanzo/gui';
|
|
3
4
|
import * as React from 'react';
|
|
4
5
|
|
|
5
|
-
import { cn } from './utils';
|
|
6
|
-
|
|
7
6
|
// ---------------------------------------------------------------------------
|
|
8
7
|
// Types
|
|
9
8
|
// ---------------------------------------------------------------------------
|
|
@@ -163,6 +162,26 @@ const STRATEGY_PRESETS: StrategyPreset[] = [
|
|
|
163
162
|
},
|
|
164
163
|
];
|
|
165
164
|
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Shared native-control shape — same tokens input.tsx's own control uses.
|
|
167
|
+
// `<select>`/`<input>` render no gui Text of their own, so every text-facing
|
|
168
|
+
// property (colour, size, family) rides the `style` escape hatch here rather
|
|
169
|
+
// than a typed prop: View's typed props are the same regardless of what tag
|
|
170
|
+
// `render` points at, and none of them cover text — only Text has those.
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
|
|
173
|
+
const MONO = 'monospace';
|
|
174
|
+
|
|
175
|
+
const CONTROL_BOX = {
|
|
176
|
+
backgroundColor: 'var(--color-input-bg)',
|
|
177
|
+
borderWidth: 1,
|
|
178
|
+
borderColor: 'var(--color-input-border)',
|
|
179
|
+
outlineWidth: 0,
|
|
180
|
+
focusStyle: { borderColor: 'var(--color-input-border-focus)' },
|
|
181
|
+
} as const;
|
|
182
|
+
|
|
183
|
+
const CONTROL_INK = { color: 'var(--color-input-fg)' };
|
|
184
|
+
|
|
166
185
|
// ---------------------------------------------------------------------------
|
|
167
186
|
// LegRow
|
|
168
187
|
// ---------------------------------------------------------------------------
|
|
@@ -183,100 +202,153 @@ function LegRow({ leg, index, strikes, expirations, removable, onChange, onRemov
|
|
|
183
202
|
};
|
|
184
203
|
|
|
185
204
|
return (
|
|
186
|
-
<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
205
|
+
<XStack
|
|
206
|
+
alignItems="center"
|
|
207
|
+
gap={ 8 }
|
|
208
|
+
borderRadius={ 6 }
|
|
209
|
+
backgroundColor={ 'var(--color-tag-subtle-bg)' as never }
|
|
210
|
+
paddingHorizontal={ 8 }
|
|
211
|
+
paddingVertical={ 6 }
|
|
212
|
+
>
|
|
213
|
+
<Text fontSize={ 10 } style={ { fontFamily: MONO } as never } flexShrink={ 0 } width={ 16 } color={ 'var(--color-text-secondary)' as never }>
|
|
214
|
+
{ index + 1 }
|
|
215
|
+
</Text>
|
|
190
216
|
|
|
191
217
|
{/* Action */}
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
<XStack
|
|
219
|
+
unstyled
|
|
220
|
+
render={ <button type="button"/> }
|
|
221
|
+
onClick={ () => update({ action: leg.action === 'buy' ? 'sell' : 'buy' }) }
|
|
222
|
+
paddingHorizontal={ 8 }
|
|
223
|
+
paddingVertical={ 2 }
|
|
224
|
+
borderRadius={ 4 }
|
|
225
|
+
borderWidth={ 0 }
|
|
226
|
+
cursor="pointer"
|
|
227
|
+
transition="quick"
|
|
228
|
+
backgroundColor={ (leg.action === 'buy'
|
|
229
|
+
? 'color-mix(in srgb, var(--color-status-good) 20%, transparent)'
|
|
230
|
+
: 'color-mix(in srgb, var(--color-status-bad) 20%, transparent)') as never }
|
|
201
231
|
>
|
|
202
|
-
{leg.action === 'buy' ? '
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
232
|
+
<Text fontSize={ 12 } fontWeight="600" color={ (leg.action === 'buy' ? 'var(--color-status-good)' : 'var(--color-status-bad)') as never }>
|
|
233
|
+
{ leg.action === 'buy' ? 'BUY' : 'SELL' }
|
|
234
|
+
</Text>
|
|
235
|
+
</XStack>
|
|
236
|
+
|
|
237
|
+
{/* Type — call vs put is a rank difference, not a hue difference. */}
|
|
238
|
+
<XStack
|
|
239
|
+
unstyled
|
|
240
|
+
render={ <button type="button"/> }
|
|
241
|
+
onClick={ () => update({ type: leg.type === 'call' ? 'put' : 'call' }) }
|
|
242
|
+
paddingHorizontal={ 8 }
|
|
243
|
+
paddingVertical={ 2 }
|
|
244
|
+
borderRadius={ 4 }
|
|
245
|
+
borderWidth={ 0 }
|
|
246
|
+
cursor="pointer"
|
|
247
|
+
transition="quick"
|
|
248
|
+
backgroundColor={ (leg.type === 'call' ? 'var(--secondary)' : 'var(--muted)') as never }
|
|
216
249
|
>
|
|
217
|
-
{leg.type === 'call' ? '
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
250
|
+
<Text fontSize={ 12 } fontWeight="500" color={ (leg.type === 'call' ? 'var(--foreground)' : 'var(--muted-foreground)') as never }>
|
|
251
|
+
{ leg.type === 'call' ? 'CALL' : 'PUT' }
|
|
252
|
+
</Text>
|
|
253
|
+
</XStack>
|
|
254
|
+
|
|
255
|
+
{/* Strike. `value`/`onChange` are native <select> attributes, not gui
|
|
256
|
+
style props — View's prop set is fixed regardless of what `render`
|
|
257
|
+
points at, so anything the host tag itself needs (not a style) lives
|
|
258
|
+
on the `render` element, same as `type="button"` does for buttons. */}
|
|
259
|
+
<View
|
|
260
|
+
unstyled
|
|
261
|
+
render={ <select value={ leg.strike } onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => update({ strike: Number(e.target.value) }) }/> as never }
|
|
262
|
+
{ ...CONTROL_BOX }
|
|
263
|
+
borderRadius={ 4 }
|
|
264
|
+
paddingHorizontal={ 6 }
|
|
265
|
+
paddingVertical={ 2 }
|
|
266
|
+
minWidth={ 72 }
|
|
267
|
+
style={ { ...CONTROL_INK, fontFamily: MONO, fontSize: 12 } as never }
|
|
225
268
|
>
|
|
226
|
-
{strikes.map((s) => (
|
|
227
|
-
<option key={s} value={s}>
|
|
228
|
-
{s.toFixed(2)}
|
|
269
|
+
{ strikes.map((s) => (
|
|
270
|
+
<option key={ s } value={ s }>
|
|
271
|
+
{ s.toFixed(2) }
|
|
229
272
|
</option>
|
|
230
|
-
))}
|
|
231
|
-
</
|
|
273
|
+
)) }
|
|
274
|
+
</View>
|
|
232
275
|
|
|
233
276
|
{/* Expiration */}
|
|
234
|
-
<
|
|
235
|
-
|
|
236
|
-
onChange={(e) => update({ expiration: e.target.value })}
|
|
237
|
-
|
|
277
|
+
<View
|
|
278
|
+
unstyled
|
|
279
|
+
render={ <select value={ leg.expiration } onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => update({ expiration: e.target.value }) }/> as never }
|
|
280
|
+
{ ...CONTROL_BOX }
|
|
281
|
+
borderRadius={ 4 }
|
|
282
|
+
paddingHorizontal={ 6 }
|
|
283
|
+
paddingVertical={ 2 }
|
|
284
|
+
minWidth={ 80 }
|
|
285
|
+
style={ { ...CONTROL_INK, fontSize: 12 } as never }
|
|
238
286
|
>
|
|
239
|
-
{expirations.map((exp) => (
|
|
240
|
-
<option key={exp} value={exp}>
|
|
241
|
-
{exp}
|
|
287
|
+
{ expirations.map((exp) => (
|
|
288
|
+
<option key={ exp } value={ exp }>
|
|
289
|
+
{ exp }
|
|
242
290
|
</option>
|
|
243
|
-
))}
|
|
244
|
-
</
|
|
291
|
+
)) }
|
|
292
|
+
</View>
|
|
245
293
|
|
|
246
294
|
{/* Quantity */}
|
|
247
|
-
<
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
295
|
+
<View
|
|
296
|
+
unstyled
|
|
297
|
+
render={ (
|
|
298
|
+
<input
|
|
299
|
+
type="number"
|
|
300
|
+
min={ 1 }
|
|
301
|
+
max={ 999 }
|
|
302
|
+
value={ leg.quantity }
|
|
303
|
+
onChange={ (e: React.ChangeEvent<HTMLInputElement>) => update({ quantity: Math.max(1, parseInt(e.target.value, 10) || 1) }) }
|
|
304
|
+
/>
|
|
305
|
+
) as never }
|
|
306
|
+
{ ...CONTROL_BOX }
|
|
307
|
+
borderRadius={ 4 }
|
|
308
|
+
paddingHorizontal={ 6 }
|
|
309
|
+
paddingVertical={ 2 }
|
|
310
|
+
width={ 48 }
|
|
311
|
+
style={ { ...CONTROL_INK, fontFamily: MONO, fontSize: 12, textAlign: 'center' } as never }
|
|
254
312
|
/>
|
|
255
313
|
|
|
256
314
|
{/* Premium (read-only if provided) */}
|
|
257
|
-
{leg.premium !== undefined && (
|
|
258
|
-
<
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
315
|
+
{ leg.premium !== undefined && (
|
|
316
|
+
<Text
|
|
317
|
+
fontSize={ 12 }
|
|
318
|
+
style={ { fontFamily: MONO } as never }
|
|
319
|
+
fontVariant={ ['tabular-nums'] as never }
|
|
320
|
+
marginLeft="auto"
|
|
321
|
+
color={ (leg.premium >= 0 ? 'var(--color-status-good)' : 'var(--color-status-bad)') as never }
|
|
322
|
+
>
|
|
323
|
+
{ leg.premium >= 0 ? '+' : '' }{ leg.premium.toFixed(2) }
|
|
324
|
+
</Text>
|
|
325
|
+
) }
|
|
326
|
+
|
|
327
|
+
{/* Remove. The icon's `currentColor` needs a real ancestor CSS colour —
|
|
328
|
+
not a gui prop (Stacks have none) — so it rides `style`. The
|
|
329
|
+
hover→red retint from the original Tailwind isn't reachable without
|
|
330
|
+
either a new named class (out of scope) or component-local hover
|
|
331
|
+
state, so resting colour is kept and a same-family opacity shift
|
|
332
|
+
substitutes for hover feedback. */ }
|
|
333
|
+
{ removable && (
|
|
334
|
+
<XStack
|
|
335
|
+
unstyled
|
|
336
|
+
render={ <button type="button" aria-label="Remove leg"/> }
|
|
337
|
+
onClick={ () => onRemove(index) }
|
|
338
|
+
marginLeft="auto"
|
|
339
|
+
padding={ 2 }
|
|
340
|
+
borderWidth={ 0 }
|
|
341
|
+
cursor="pointer"
|
|
342
|
+
transition="quick"
|
|
343
|
+
style={ { color: 'var(--color-text-secondary)' } as never }
|
|
344
|
+
hoverStyle={ { opacity: 0.7 } as never }
|
|
273
345
|
>
|
|
274
|
-
<svg
|
|
275
|
-
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
|
346
|
+
<svg width={ 14 } height={ 14 } viewBox="0 0 24 24" fill="none">
|
|
347
|
+
<path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
|
|
276
348
|
</svg>
|
|
277
|
-
</
|
|
278
|
-
)}
|
|
279
|
-
</
|
|
349
|
+
</XStack>
|
|
350
|
+
) }
|
|
351
|
+
</XStack>
|
|
280
352
|
);
|
|
281
353
|
}
|
|
282
354
|
|
|
@@ -360,108 +432,134 @@ export const StrategyBuilder = React.forwardRef<HTMLDivElement, StrategyBuilderP
|
|
|
360
432
|
}, [onSubmit, strategyType, legs, netPremium]);
|
|
361
433
|
|
|
362
434
|
const currentPreset = STRATEGY_PRESETS.find((p) => p.value === strategyType);
|
|
435
|
+
const netColor = netPremium > 0 ? 'var(--color-status-good)' : netPremium < 0 ? 'var(--color-status-bad)' : 'var(--color-text-secondary)';
|
|
363
436
|
|
|
364
437
|
return (
|
|
365
|
-
<
|
|
366
|
-
ref={ref}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
)}
|
|
371
|
-
{
|
|
438
|
+
<YStack
|
|
439
|
+
ref={ ref as never }
|
|
440
|
+
gap={ 12 }
|
|
441
|
+
borderRadius={ 8 }
|
|
442
|
+
borderWidth={ 1 }
|
|
443
|
+
borderColor={ 'var(--color-border-divider)' as never }
|
|
444
|
+
backgroundColor={ 'var(--card)' as never }
|
|
445
|
+
padding={ 12 }
|
|
446
|
+
className={ className }
|
|
447
|
+
{ ...(rest as object) }
|
|
372
448
|
>
|
|
373
449
|
{/* Header */}
|
|
374
|
-
<
|
|
375
|
-
<
|
|
376
|
-
<
|
|
450
|
+
<XStack alignItems="center" justifyContent="space-between" gap={ 12 }>
|
|
451
|
+
<XStack alignItems="center" gap={ 8 }>
|
|
452
|
+
<Text fontSize={ 12 } fontWeight="600" textTransform="uppercase" letterSpacing={ 0.6 } color={ 'var(--color-text-secondary)' as never }>
|
|
377
453
|
Strategy
|
|
378
|
-
</
|
|
379
|
-
<
|
|
380
|
-
{underlying}
|
|
381
|
-
</
|
|
382
|
-
</
|
|
383
|
-
<
|
|
384
|
-
Spot: <
|
|
385
|
-
</
|
|
386
|
-
</
|
|
454
|
+
</Text>
|
|
455
|
+
<Text fontSize={ 14 } fontWeight="500" color={ 'var(--color-text-primary)' as never }>
|
|
456
|
+
{ underlying }
|
|
457
|
+
</Text>
|
|
458
|
+
</XStack>
|
|
459
|
+
<Text fontSize={ 10 } color={ 'var(--color-text-secondary)' as never }>
|
|
460
|
+
Spot: <Text style={ { fontFamily: MONO } as never } fontVariant={ ['tabular-nums'] as never } color={ 'var(--color-text-primary)' as never }>{ spotPrice.toFixed(2) }</Text>
|
|
461
|
+
</Text>
|
|
462
|
+
</XStack>
|
|
387
463
|
|
|
388
464
|
{/* Strategy selector */}
|
|
389
|
-
<
|
|
390
|
-
<
|
|
391
|
-
|
|
392
|
-
onChange={handleStrategyChange}
|
|
393
|
-
|
|
465
|
+
<XStack alignItems="center" gap={ 8 }>
|
|
466
|
+
<View
|
|
467
|
+
unstyled
|
|
468
|
+
render={ <select value={ strategyType } onChange={ handleStrategyChange }/> as never }
|
|
469
|
+
flex={ 1 }
|
|
470
|
+
{ ...CONTROL_BOX }
|
|
471
|
+
borderRadius={ 6 }
|
|
472
|
+
paddingHorizontal={ 10 }
|
|
473
|
+
paddingVertical={ 6 }
|
|
474
|
+
style={ { ...CONTROL_INK, fontSize: 14 } as never }
|
|
394
475
|
>
|
|
395
|
-
{STRATEGY_PRESETS.map((preset) => (
|
|
396
|
-
<option key={preset.value} value={preset.value}>
|
|
397
|
-
{preset.label}
|
|
476
|
+
{ STRATEGY_PRESETS.map((preset) => (
|
|
477
|
+
<option key={ preset.value } value={ preset.value }>
|
|
478
|
+
{ preset.label }
|
|
398
479
|
</option>
|
|
399
|
-
))}
|
|
400
|
-
</
|
|
401
|
-
</
|
|
480
|
+
)) }
|
|
481
|
+
</View>
|
|
482
|
+
</XStack>
|
|
402
483
|
|
|
403
|
-
{currentPreset && (
|
|
404
|
-
<
|
|
405
|
-
{currentPreset.description}
|
|
406
|
-
</
|
|
407
|
-
)}
|
|
484
|
+
{ currentPreset && (
|
|
485
|
+
<Text fontSize={ 11 } marginTop={ -4 } color={ 'var(--color-text-secondary)' as never }>
|
|
486
|
+
{ currentPreset.description }
|
|
487
|
+
</Text>
|
|
488
|
+
) }
|
|
408
489
|
|
|
409
490
|
{/* Legs */}
|
|
410
|
-
<
|
|
411
|
-
{legs.map((leg, i) => (
|
|
491
|
+
<YStack gap={ 6 }>
|
|
492
|
+
{ legs.map((leg, i) => (
|
|
412
493
|
<LegRow
|
|
413
|
-
key={i}
|
|
414
|
-
leg={leg}
|
|
415
|
-
index={i}
|
|
416
|
-
strikes={strikes}
|
|
417
|
-
expirations={expirations}
|
|
418
|
-
removable={strategyType === 'custom' && legs.length > 1}
|
|
419
|
-
onChange={handleLegChange}
|
|
420
|
-
onRemove={handleLegRemove}
|
|
494
|
+
key={ i }
|
|
495
|
+
leg={ leg }
|
|
496
|
+
index={ i }
|
|
497
|
+
strikes={ strikes }
|
|
498
|
+
expirations={ expirations }
|
|
499
|
+
removable={ strategyType === 'custom' && legs.length > 1 }
|
|
500
|
+
onChange={ handleLegChange }
|
|
501
|
+
onRemove={ handleLegRemove }
|
|
421
502
|
/>
|
|
422
|
-
))}
|
|
423
|
-
</
|
|
424
|
-
|
|
425
|
-
{/* Add leg button (custom only)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
503
|
+
)) }
|
|
504
|
+
</YStack>
|
|
505
|
+
|
|
506
|
+
{/* Add leg button (custom only). Resting ink rides `style` so the
|
|
507
|
+
icon's `currentColor` and the label both resolve it; hover keeps
|
|
508
|
+
the border re-tint (a valid Stack prop) as the interactive cue. */}
|
|
509
|
+
{ strategyType === 'custom' && legs.length < 4 && (
|
|
510
|
+
<XStack
|
|
511
|
+
unstyled
|
|
512
|
+
render={ <button type="button"/> }
|
|
513
|
+
onClick={ handleAddLeg }
|
|
514
|
+
alignItems="center"
|
|
515
|
+
justifyContent="center"
|
|
516
|
+
gap={ 4 }
|
|
517
|
+
borderRadius={ 6 }
|
|
518
|
+
borderWidth={ 1 }
|
|
519
|
+
paddingVertical={ 4 }
|
|
520
|
+
cursor="pointer"
|
|
521
|
+
transition="quick"
|
|
522
|
+
borderColor={ 'var(--color-border-divider)' as never }
|
|
523
|
+
hoverStyle={ { borderColor: 'var(--color-hover)' } as never }
|
|
524
|
+
style={ { color: 'var(--color-text-secondary)', borderStyle: 'dashed' } as never }
|
|
431
525
|
>
|
|
432
|
-
<svg
|
|
433
|
-
<path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
|
526
|
+
<svg width={ 12 } height={ 12 } viewBox="0 0 24 24" fill="none">
|
|
527
|
+
<path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/>
|
|
434
528
|
</svg>
|
|
435
|
-
Add Leg
|
|
436
|
-
</
|
|
437
|
-
)}
|
|
529
|
+
<Text fontSize={ 12 } color={ 'var(--color-text-secondary)' as never }>Add Leg</Text>
|
|
530
|
+
</XStack>
|
|
531
|
+
) }
|
|
438
532
|
|
|
439
533
|
{/* Net premium + submit */}
|
|
440
|
-
<
|
|
441
|
-
<
|
|
442
|
-
<
|
|
443
|
-
<
|
|
444
|
-
'
|
|
445
|
-
netPremium
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
)}
|
|
534
|
+
<XStack alignItems="center" justifyContent="space-between" paddingTop={ 4 } borderTopWidth={ 1 } borderColor={ 'var(--color-border-divider)' as never }>
|
|
535
|
+
<XStack alignItems="center" gap={ 8 }>
|
|
536
|
+
<Text fontSize={ 12 } color={ 'var(--color-text-secondary)' as never }>Net:</Text>
|
|
537
|
+
<Text fontSize={ 14 } fontWeight="600" style={ { fontFamily: MONO } as never } fontVariant={ ['tabular-nums'] as never } color={ netColor as never }>
|
|
538
|
+
{ netPremium > 0 ? 'Credit ' : netPremium < 0 ? 'Debit ' : '' }
|
|
539
|
+
{ netPremium !== 0 ? `$${ Math.abs(netPremium).toFixed(2) }` : '-' }
|
|
540
|
+
</Text>
|
|
541
|
+
</XStack>
|
|
542
|
+
<XStack
|
|
543
|
+
unstyled
|
|
544
|
+
render={ <button type="button"/> }
|
|
545
|
+
onClick={ handleSubmit }
|
|
546
|
+
disabled={ legs.length === 0 }
|
|
547
|
+
paddingHorizontal={ 16 }
|
|
548
|
+
paddingVertical={ 6 }
|
|
549
|
+
borderRadius={ 6 }
|
|
550
|
+
borderWidth={ 0 }
|
|
551
|
+
cursor="pointer"
|
|
552
|
+
transition="quick"
|
|
553
|
+
backgroundColor={ 'var(--color-button-solid-bg)' as never }
|
|
554
|
+
hoverStyle={ { backgroundColor: 'var(--color-hover)' } as never }
|
|
555
|
+
disabledStyle={ { opacity: 0.4, cursor: 'not-allowed' } as never }
|
|
460
556
|
>
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
557
|
+
<Text fontSize={ 12 } fontWeight="600" color={ 'var(--color-button-solid-text)' as never }>
|
|
558
|
+
Review Order
|
|
559
|
+
</Text>
|
|
560
|
+
</XStack>
|
|
561
|
+
</XStack>
|
|
562
|
+
</YStack>
|
|
465
563
|
);
|
|
466
564
|
},
|
|
467
565
|
);
|