@kodiak-finance/orderly-layout-split 2.9.2-alpha.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,3326 @@
1
+ import React, { createContext, forwardRef, useMemo, useCallback, useContext, useState, useEffect, useRef } from 'react';
2
+ import { cn, Box, Flex, createInterceptor, Text, CloseIcon, Divider, DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuPortal, DropdownMenuContent } from '@kodiak-finance/orderly-ui';
3
+ import * as ResizablePrimitive from 'react-resizable-panels';
4
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
5
+ import { useTranslation } from '@kodiak-finance/orderly-i18n';
6
+ import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter, DragOverlay } from '@dnd-kit/core';
7
+ import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
8
+ import { useSortable, sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, arrayMove } from '@dnd-kit/sortable';
9
+ import { CSS } from '@dnd-kit/utilities';
10
+ import { useMediaQuery, useLocalStorage } from '@kodiak-finance/orderly-hooks';
11
+ import { TRADING_PANEL_IDS } from '@kodiak-finance/orderly-layout-core';
12
+ import { TradingviewFullscreenKey } from '@kodiak-finance/orderly-types';
13
+ import Split from '@uiw/react-split';
14
+ import { RestrictToVerticalAxis } from '@dnd-kit/abstract/modifiers';
15
+ import { DragDropProvider } from '@dnd-kit/react';
16
+ import { isSortable, useSortable as useSortable$1 } from '@dnd-kit/react/sortable';
17
+
18
+ // src/components/SplitLayout.tsx
19
+ function ResizablePanelGroup({
20
+ className,
21
+ ...props
22
+ }) {
23
+ return /* @__PURE__ */ jsx(
24
+ ResizablePrimitive.Group,
25
+ {
26
+ "data-slot": "resizable-panel-group",
27
+ className: cn(
28
+ "aria-[orientation=vertical]:oui-flex-col oui-flex oui-w-full oui-h-full",
29
+ className
30
+ ),
31
+ ...props
32
+ }
33
+ );
34
+ }
35
+ function ResizablePanel({
36
+ className,
37
+ ...props
38
+ }) {
39
+ return /* @__PURE__ */ jsx(
40
+ ResizablePrimitive.Panel,
41
+ {
42
+ "data-slot": "resizable-panel",
43
+ className: cn(className),
44
+ ...props
45
+ }
46
+ );
47
+ }
48
+ function ResizableHandle({
49
+ withHandle,
50
+ className,
51
+ ...props
52
+ }) {
53
+ return /* @__PURE__ */ jsx(
54
+ ResizablePrimitive.Separator,
55
+ {
56
+ "data-slot": "resizable-handle",
57
+ className: cn(
58
+ "oui-bg-primary focus:oui-ring-0 focus-visible:oui-ring-0 focus-visible:oui-outline-none after:oui-absolute after:oui-inset-y-0 after:oui-left-1/2 after:oui-w-1 after:-oui-translate-x-1/2 aria-[orientation=horizontal]:oui-h-px aria-[orientation=horizontal]:oui-w-full aria-[orientation=horizontal]:after:oui-left-0 aria-[orientation=horizontal]:after:oui-h-1 aria-[orientation=horizontal]:after:oui-w-full aria-[orientation=horizontal]:after:oui-translate-x-0 aria-[orientation=horizontal]:after:-oui-translate-y-1/2 [&[aria-orientation=horizontal]>div]:oui-rotate-90 oui-relative oui-flex oui-w-px oui-items-center oui-justify-center",
59
+ className
60
+ ),
61
+ ...props,
62
+ children: withHandle && /* @__PURE__ */ jsx("div", { className: "oui-bg-primary oui-z-10 oui-flex oui-h-6 oui-w-1 oui-shrink-0 oui-rounded-lg" })
63
+ }
64
+ );
65
+ }
66
+ function sizesToDefaultLayout(sizes, count) {
67
+ if (!sizes || sizes.length !== count) return void 0;
68
+ const result = {};
69
+ let fixedTotal = 0;
70
+ const autoIndices = [];
71
+ for (let i = 0; i < count; i++) {
72
+ const s = sizes[i];
73
+ if (s === "fixed") continue;
74
+ const num = parseFloat(String(s).replace(/%/g, ""));
75
+ if (!isNaN(num)) {
76
+ result[String(i)] = Math.round(num);
77
+ fixedTotal += num;
78
+ } else {
79
+ autoIndices.push(i);
80
+ }
81
+ }
82
+ if (autoIndices.length > 0) {
83
+ const remainder = Math.max(0, 100 - fixedTotal);
84
+ const autoSize = remainder / autoIndices.length;
85
+ for (const i of autoIndices) {
86
+ result[String(i)] = Math.round(autoSize);
87
+ }
88
+ }
89
+ return Object.keys(result).length > 0 ? result : void 0;
90
+ }
91
+ var SPLIT_HANDLE_BASE_CLASSNAME = [
92
+ "!oui-transition-none",
93
+ "!oui-shadow-none",
94
+ "!oui-bg-transparent",
95
+ "hover:!oui-bg-primary-light",
96
+ "hover:!oui-shadow-[0px_0px_2px_0px]",
97
+ "hover:!oui-shadow-primary-light/80",
98
+ "active:!oui-bg-primary-light",
99
+ "active:!oui-shadow-[0px_0px_2px_0px]",
100
+ "active:!oui-shadow-primary-light/80"
101
+ // "focus:!oui-bg-primary-light",
102
+ // "focus:!oui-shadow-[0px_0px_4px_0px]",
103
+ // "focus:!oui-shadow-primary-light/80",
104
+ ];
105
+ function SplitLayout({
106
+ orientation,
107
+ sizes,
108
+ panelConstraints,
109
+ onSizeChange,
110
+ children,
111
+ className,
112
+ style,
113
+ classNames,
114
+ gap
115
+ }) {
116
+ const childArray = React.Children.toArray(children);
117
+ const count = childArray.length;
118
+ const defaultLayout = useMemo(
119
+ () => sizesToDefaultLayout(sizes, count),
120
+ [sizes, count]
121
+ );
122
+ const handleLayoutChanged = useCallback(
123
+ (layout) => {
124
+ const panelIds = Array.from({ length: count }, (_, i) => String(i));
125
+ const sizesAsStrings = panelIds.map((id, index) => {
126
+ const value = layout[id];
127
+ if (typeof value === "number") {
128
+ return `${Math.round(value)}%`;
129
+ }
130
+ const originalSize = sizes?.[index];
131
+ return originalSize ?? "auto";
132
+ });
133
+ onSizeChange?.(sizesAsStrings);
134
+ },
135
+ [onSizeChange, count]
136
+ );
137
+ if (count === 0) return /* @__PURE__ */ jsx(Fragment, {});
138
+ const marginPx = gap != null ? gap * 2 : 4;
139
+ const handleStyle = orientation === "horizontal" ? { width: 2, marginLeft: marginPx, marginRight: marginPx } : { height: 2, marginTop: marginPx, marginBottom: marginPx };
140
+ return /* @__PURE__ */ jsx(
141
+ ResizablePanelGroup,
142
+ {
143
+ orientation,
144
+ defaultLayout,
145
+ onLayoutChanged: handleLayoutChanged,
146
+ className: cn(className, classNames?.panelGroup),
147
+ style,
148
+ children: childArray.map((child, index) => {
149
+ const constraints = panelConstraints?.[index];
150
+ const size = sizes?.[index];
151
+ const isFixed = size === "fixed";
152
+ const nextIsFixed = sizes?.[index + 1] === "fixed";
153
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
154
+ isFixed ? child : /* @__PURE__ */ jsx(
155
+ ResizablePanel,
156
+ {
157
+ id: String(index),
158
+ defaultSize: size,
159
+ minSize: constraints?.minSize,
160
+ maxSize: constraints?.maxSize,
161
+ disabled: constraints?.disabled,
162
+ className: classNames?.panel,
163
+ children: child
164
+ }
165
+ ),
166
+ index < count - 1 && !isFixed && !nextIsFixed && /* @__PURE__ */ jsx(
167
+ ResizableHandle,
168
+ {
169
+ className: cn(SPLIT_HANDLE_BASE_CLASSNAME, classNames?.handle),
170
+ style: handleStyle
171
+ }
172
+ )
173
+ ] }, `panel-${index}`);
174
+ })
175
+ }
176
+ );
177
+ }
178
+ SplitLayout.displayName = "SplitLayout";
179
+
180
+ // src/constants.ts
181
+ var BREAKPOINT_KEYS = [
182
+ "lg",
183
+ "md",
184
+ "sm",
185
+ "xs"
186
+ ];
187
+ var BREAKPOINT_VALUES = {
188
+ lg: 1680,
189
+ md: 1440,
190
+ sm: 1280,
191
+ xs: 768
192
+ };
193
+ var SPLIT_BREAKPOINT_ORDER = BREAKPOINT_KEYS;
194
+ var DEFAULT_SPLIT_BREAKPOINTS = BREAKPOINT_VALUES;
195
+ var VIEWPORT_BREAKPOINTS = BREAKPOINT_VALUES;
196
+ var VIEWPORT_BREAKPOINT_ORDER = BREAKPOINT_KEYS;
197
+
198
+ // src/utils/splitLayoutUtils.ts
199
+ function getSortableIdForChild(child, path, index) {
200
+ if (child.type === "panel" && child.id) {
201
+ return child.id;
202
+ }
203
+ return `sortable-${path.join("-")}-${index}`;
204
+ }
205
+ function updateOrderAtPath(node, path, newOrder) {
206
+ if (node.type === "panel") return node;
207
+ if (path.length === 0) {
208
+ return { ...node, children: newOrder };
209
+ }
210
+ const [childIndex, ...restPath] = path;
211
+ const updatedChildren = [...node.children];
212
+ if (childIndex < updatedChildren.length) {
213
+ updatedChildren[childIndex] = updateOrderAtPath(
214
+ updatedChildren[childIndex],
215
+ restPath,
216
+ newOrder
217
+ );
218
+ }
219
+ return { ...node, children: updatedChildren };
220
+ }
221
+ function createDefaultSplitLayout(panelIds) {
222
+ if (panelIds.length === 0) {
223
+ throw new Error(
224
+ "Cannot create default split layout: no panel IDs provided"
225
+ );
226
+ }
227
+ let singleRoot;
228
+ if (panelIds.length === 1) {
229
+ singleRoot = { type: "panel", id: panelIds[0] };
230
+ } else {
231
+ singleRoot = {
232
+ type: "split",
233
+ orientation: "horizontal",
234
+ children: panelIds.map((panelId) => ({
235
+ type: "panel",
236
+ id: panelId
237
+ }))
238
+ };
239
+ }
240
+ const layouts = {
241
+ lg: singleRoot,
242
+ md: singleRoot,
243
+ sm: singleRoot,
244
+ xs: singleRoot
245
+ };
246
+ return {
247
+ layouts,
248
+ breakpoints: DEFAULT_SPLIT_BREAKPOINTS
249
+ };
250
+ }
251
+ function isValidOrientation(v) {
252
+ return v === "horizontal" || v === "vertical";
253
+ }
254
+ function validateContainerNode(n) {
255
+ return isValidOrientation(n.orientation) && Array.isArray(n.children) && n.children.every((c) => validateSplitLayoutNode(c));
256
+ }
257
+ function validateSplitLayoutNode(node) {
258
+ if (!node || typeof node !== "object") return false;
259
+ const n = node;
260
+ if (n.type === "panel") {
261
+ return typeof n.id === "string" && n.id.length > 0 && (n.size === void 0 || typeof n.size === "string") && (n.minSize === void 0 || typeof n.minSize === "string") && (n.maxSize === void 0 || typeof n.maxSize === "string") && (n.disabled === void 0 || typeof n.disabled === "boolean") && (n.className === void 0 || typeof n.className === "string") && (n.style === void 0 || typeof n.style === "object");
262
+ }
263
+ if (n.type === "split" || n.type === "sort") return validateContainerNode(n);
264
+ return false;
265
+ }
266
+ function validateSplitLayoutModel(parsed) {
267
+ if (!parsed || typeof parsed !== "object") return false;
268
+ const p = parsed;
269
+ const layoutsSource = p.layouts ?? p.roots;
270
+ if (!layoutsSource || typeof layoutsSource !== "object") return false;
271
+ if (!p.breakpoints || typeof p.breakpoints !== "object") return false;
272
+ const layouts = layoutsSource;
273
+ const bp = p.breakpoints;
274
+ for (const k of SPLIT_BREAKPOINT_ORDER) {
275
+ if (!validateSplitLayoutNode(layouts[k]) || typeof bp[k] !== "number") {
276
+ return false;
277
+ }
278
+ }
279
+ return true;
280
+ }
281
+ function serializeSplitLayout(layout) {
282
+ return JSON.stringify(layout);
283
+ }
284
+ function deserializeSplitLayout(json) {
285
+ try {
286
+ const parsed = JSON.parse(json);
287
+ if (!validateSplitLayoutModel(parsed)) {
288
+ throw new Error(
289
+ "Invalid split layout: must have layouts (lg,md,sm,xs) and breakpoints"
290
+ );
291
+ }
292
+ const layout = parsed;
293
+ const layoutsSource = layout.layouts ?? layout.roots;
294
+ const layouts = {};
295
+ for (const bp of SPLIT_BREAKPOINT_ORDER) {
296
+ layouts[bp] = layoutsSource[bp];
297
+ }
298
+ const { roots: _roots, ...rest } = layout;
299
+ return { ...rest, layouts };
300
+ } catch (error) {
301
+ if (error instanceof Error) {
302
+ throw new Error(`Failed to deserialize split layout: ${error.message}`);
303
+ }
304
+ throw new Error(`Failed to deserialize split layout: ${error}`);
305
+ }
306
+ }
307
+ var SplitLayoutConfigContext = createContext(
308
+ null
309
+ );
310
+ function SplitLayoutConfigProvider({
311
+ panels,
312
+ layout,
313
+ breakpoint,
314
+ onLayoutChange,
315
+ onSizeChange,
316
+ onSizePersist,
317
+ classNames,
318
+ gap,
319
+ collapsedPanels,
320
+ togglePanelCollapse,
321
+ isPanelCollapsed,
322
+ collapsiblePanels,
323
+ isPanelCollapsible,
324
+ children
325
+ }) {
326
+ const value = useMemo(
327
+ () => ({
328
+ panels,
329
+ layout,
330
+ breakpoint,
331
+ onLayoutChange,
332
+ onSizeChange,
333
+ onSizePersist,
334
+ classNames,
335
+ gap,
336
+ collapsedPanels,
337
+ togglePanelCollapse,
338
+ isPanelCollapsed,
339
+ collapsiblePanels,
340
+ isPanelCollapsible
341
+ }),
342
+ [
343
+ panels,
344
+ layout,
345
+ breakpoint,
346
+ onLayoutChange,
347
+ onSizeChange,
348
+ onSizePersist,
349
+ classNames,
350
+ gap,
351
+ collapsedPanels,
352
+ togglePanelCollapse,
353
+ isPanelCollapsed,
354
+ collapsiblePanels,
355
+ isPanelCollapsible
356
+ ]
357
+ );
358
+ return /* @__PURE__ */ jsx(SplitLayoutConfigContext.Provider, { value, children });
359
+ }
360
+ function useSplitLayoutConfig() {
361
+ const ctx = useContext(SplitLayoutConfigContext);
362
+ if (!ctx) {
363
+ throw new Error(
364
+ "useSplitLayoutConfig must be used within SplitLayoutConfigProvider"
365
+ );
366
+ }
367
+ return ctx;
368
+ }
369
+ var OrderEntryIcon = (props) => /* @__PURE__ */ jsxs(
370
+ "svg",
371
+ {
372
+ width: "36",
373
+ height: "84",
374
+ viewBox: "0 0 36 84",
375
+ fill: "none",
376
+ xmlns: "http://www.w3.org/2000/svg",
377
+ ...props,
378
+ children: [
379
+ /* @__PURE__ */ jsx("rect", { width: "36", height: "17", rx: "2", fill: "rgb(var(--oui-color-base-7))" }),
380
+ /* @__PURE__ */ jsx(
381
+ "rect",
382
+ {
383
+ y: "19",
384
+ width: "36",
385
+ height: "54",
386
+ rx: "2",
387
+ fill: "rgb(var(--oui-color-base-7))"
388
+ }
389
+ ),
390
+ /* @__PURE__ */ jsx(
391
+ "rect",
392
+ {
393
+ y: "75",
394
+ width: "36",
395
+ height: "9",
396
+ rx: "2",
397
+ fill: "rgb(var(--oui-color-base-7))"
398
+ }
399
+ ),
400
+ /* @__PURE__ */ jsx(
401
+ "rect",
402
+ {
403
+ x: "3",
404
+ y: "79",
405
+ width: "30",
406
+ height: "1",
407
+ rx: "0.5",
408
+ fill: "url(#paint0_linear_17647_26849)"
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsx(
412
+ "rect",
413
+ {
414
+ x: "3",
415
+ y: "22",
416
+ width: "14",
417
+ height: "6",
418
+ rx: "2",
419
+ fill: "rgb(var(--oui-color-success-darken))"
420
+ }
421
+ ),
422
+ /* @__PURE__ */ jsx(
423
+ "rect",
424
+ {
425
+ x: "19",
426
+ y: "22",
427
+ width: "14",
428
+ height: "6",
429
+ rx: "2",
430
+ fill: "rgb(var(--oui-color-danger-darken))"
431
+ }
432
+ ),
433
+ /* @__PURE__ */ jsx(
434
+ "rect",
435
+ {
436
+ x: "3",
437
+ y: "11",
438
+ width: "14",
439
+ height: "3",
440
+ rx: "1.5",
441
+ fill: "rgb(var(--oui-color-base-4))"
442
+ }
443
+ ),
444
+ /* @__PURE__ */ jsx(
445
+ "rect",
446
+ {
447
+ x: "19",
448
+ y: "11",
449
+ width: "14",
450
+ height: "3",
451
+ rx: "1.5",
452
+ fill: "rgb(var(--oui-color-primary-darken))"
453
+ }
454
+ ),
455
+ /* @__PURE__ */ jsx(
456
+ "rect",
457
+ {
458
+ x: "3",
459
+ y: "62",
460
+ width: "30",
461
+ height: "8",
462
+ rx: "2",
463
+ fill: "rgb(var(--oui-color-success-darken))"
464
+ }
465
+ ),
466
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
467
+ "linearGradient",
468
+ {
469
+ id: "paint0_linear_17647_26849",
470
+ x1: "33",
471
+ y1: "79.5",
472
+ x2: "3",
473
+ y2: "79.5",
474
+ gradientUnits: "userSpaceOnUse",
475
+ children: [
476
+ /* @__PURE__ */ jsx("stop", { stopColor: "rgb(var(--oui-color-primary-light))" }),
477
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "rgb(var(--oui-gradient-brand-start))" })
478
+ ]
479
+ }
480
+ ) })
481
+ ]
482
+ }
483
+ );
484
+ var MarketLeftIcon = ({
485
+ isSelected,
486
+ isHovered,
487
+ ...props
488
+ }) => {
489
+ const getStrokeColor = () => {
490
+ if (isSelected) return "rgb(var(--oui-color-primary-light))";
491
+ if (isHovered) return "rgb(var(--oui-color-primary-light))";
492
+ return "rgb(var(--oui-color-base-5))";
493
+ };
494
+ return /* @__PURE__ */ jsxs(
495
+ "svg",
496
+ {
497
+ width: "148",
498
+ height: "100",
499
+ viewBox: "0 0 148 100",
500
+ fill: "none",
501
+ xmlns: "http://www.w3.org/2000/svg",
502
+ ...props,
503
+ children: [
504
+ /* @__PURE__ */ jsx(
505
+ "rect",
506
+ {
507
+ x: "2",
508
+ y: "2",
509
+ width: "144",
510
+ height: "96",
511
+ rx: "10",
512
+ fill: "rgb(var(--oui-color-base-10))",
513
+ stroke: getStrokeColor(),
514
+ strokeWidth: "4"
515
+ }
516
+ ),
517
+ /* @__PURE__ */ jsx(
518
+ "rect",
519
+ {
520
+ x: "8",
521
+ y: "8",
522
+ width: "24",
523
+ height: "84",
524
+ rx: "2",
525
+ fill: "rgb(var(--oui-color-base-7))"
526
+ }
527
+ ),
528
+ /* @__PURE__ */ jsx(
529
+ "rect",
530
+ {
531
+ x: "16",
532
+ y: "10",
533
+ width: "4",
534
+ height: "2",
535
+ rx: "1",
536
+ fill: "rgb(var(--oui-color-base-4))"
537
+ }
538
+ ),
539
+ /* @__PURE__ */ jsx(
540
+ "rect",
541
+ {
542
+ x: "21",
543
+ y: "10",
544
+ width: "4",
545
+ height: "2",
546
+ rx: "1",
547
+ fill: "rgb(var(--oui-color-base-4))"
548
+ }
549
+ ),
550
+ /* @__PURE__ */ jsx(
551
+ "rect",
552
+ {
553
+ x: "26",
554
+ y: "10",
555
+ width: "4",
556
+ height: "2",
557
+ rx: "1",
558
+ fill: "rgb(var(--oui-color-base-4))"
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsx(
562
+ "rect",
563
+ {
564
+ x: "10",
565
+ y: "10",
566
+ width: "5",
567
+ height: "2",
568
+ rx: "1",
569
+ fill: "rgb(var(--oui-color-primary-darken))"
570
+ }
571
+ ),
572
+ /* @__PURE__ */ jsx(
573
+ "rect",
574
+ {
575
+ x: "10",
576
+ y: "14",
577
+ width: "20",
578
+ height: "76",
579
+ rx: "2",
580
+ fill: "rgb(var(--oui-color-base-5))"
581
+ }
582
+ )
583
+ ]
584
+ }
585
+ );
586
+ };
587
+ var MarketTopIcon = ({
588
+ isSelected,
589
+ isHovered,
590
+ ...props
591
+ }) => {
592
+ const getStrokeColor = () => {
593
+ if (isSelected) return "rgb(var(--oui-color-primary-light))";
594
+ if (isHovered) return "rgb(var(--oui-color-primary-light))";
595
+ return "rgb(var(--oui-color-base-5))";
596
+ };
597
+ return /* @__PURE__ */ jsxs(
598
+ "svg",
599
+ {
600
+ width: "148",
601
+ height: "100",
602
+ viewBox: "0 0 148 100",
603
+ fill: "none",
604
+ xmlns: "http://www.w3.org/2000/svg",
605
+ ...props,
606
+ children: [
607
+ /* @__PURE__ */ jsx(
608
+ "rect",
609
+ {
610
+ x: "2",
611
+ y: "2",
612
+ width: "144",
613
+ height: "96",
614
+ rx: "10",
615
+ fill: "rgb(var(--oui-color-base-10))",
616
+ stroke: getStrokeColor(),
617
+ strokeWidth: "4"
618
+ }
619
+ ),
620
+ /* @__PURE__ */ jsx(
621
+ "rect",
622
+ {
623
+ x: "8",
624
+ y: "8",
625
+ width: "132",
626
+ height: "8",
627
+ rx: "2",
628
+ fill: "rgb(var(--oui-color-base-7))"
629
+ }
630
+ ),
631
+ /* @__PURE__ */ jsxs("g", { clipPath: "url(#clip0_31319_74729)", children: [
632
+ /* @__PURE__ */ jsx(
633
+ "rect",
634
+ {
635
+ x: "10",
636
+ y: "10",
637
+ width: "16",
638
+ height: "4",
639
+ rx: "2",
640
+ fill: "rgb(var(--oui-color-primary-darken))"
641
+ }
642
+ ),
643
+ /* @__PURE__ */ jsx(
644
+ "rect",
645
+ {
646
+ x: "28",
647
+ y: "10",
648
+ width: "16",
649
+ height: "4",
650
+ rx: "2",
651
+ fill: "rgb(var(--oui-color-base-4))"
652
+ }
653
+ ),
654
+ /* @__PURE__ */ jsx(
655
+ "rect",
656
+ {
657
+ x: "46",
658
+ y: "10",
659
+ width: "16",
660
+ height: "4",
661
+ rx: "2",
662
+ fill: "rgb(var(--oui-color-base-4))"
663
+ }
664
+ ),
665
+ /* @__PURE__ */ jsx(
666
+ "rect",
667
+ {
668
+ x: "64",
669
+ y: "10",
670
+ width: "16",
671
+ height: "4",
672
+ rx: "2",
673
+ fill: "rgb(var(--oui-color-base-4))"
674
+ }
675
+ ),
676
+ /* @__PURE__ */ jsx(
677
+ "rect",
678
+ {
679
+ x: "82",
680
+ y: "10",
681
+ width: "16",
682
+ height: "4",
683
+ rx: "2",
684
+ fill: "rgb(var(--oui-color-base-4))"
685
+ }
686
+ ),
687
+ /* @__PURE__ */ jsx(
688
+ "rect",
689
+ {
690
+ x: "100",
691
+ y: "10",
692
+ width: "16",
693
+ height: "4",
694
+ rx: "2",
695
+ fill: "rgb(var(--oui-color-base-4))"
696
+ }
697
+ ),
698
+ /* @__PURE__ */ jsx(
699
+ "rect",
700
+ {
701
+ x: "118",
702
+ y: "10",
703
+ width: "16",
704
+ height: "4",
705
+ rx: "2",
706
+ fill: "rgb(var(--oui-color-base-4))"
707
+ }
708
+ ),
709
+ /* @__PURE__ */ jsx(
710
+ "rect",
711
+ {
712
+ x: "136",
713
+ y: "10",
714
+ width: "16",
715
+ height: "4",
716
+ rx: "2",
717
+ fill: "rgb(var(--oui-color-base-4))"
718
+ }
719
+ )
720
+ ] }),
721
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: "clip0_31319_74729", children: /* @__PURE__ */ jsx(
722
+ "rect",
723
+ {
724
+ width: "130",
725
+ height: "4",
726
+ fill: "rgb(var(--oui-color-base-foreground))",
727
+ transform: "translate(10 10)"
728
+ }
729
+ ) }) })
730
+ ]
731
+ }
732
+ );
733
+ };
734
+ var MarketBottomIcon = ({
735
+ isSelected,
736
+ isHovered,
737
+ ...props
738
+ }) => {
739
+ const getStrokeColor = () => {
740
+ if (isSelected) return "rgb(var(--oui-color-primary-light))";
741
+ if (isHovered) return "rgb(var(--oui-color-primary-light))";
742
+ return "rgb(var(--oui-color-base-5))";
743
+ };
744
+ return /* @__PURE__ */ jsxs(
745
+ "svg",
746
+ {
747
+ width: "148",
748
+ height: "100",
749
+ viewBox: "0 0 148 100",
750
+ fill: "none",
751
+ xmlns: "http://www.w3.org/2000/svg",
752
+ ...props,
753
+ children: [
754
+ /* @__PURE__ */ jsx(
755
+ "rect",
756
+ {
757
+ x: "2",
758
+ y: "2",
759
+ width: "144",
760
+ height: "96",
761
+ rx: "10",
762
+ fill: "rgb(var(--oui-color-base-10))",
763
+ stroke: getStrokeColor(),
764
+ strokeWidth: "4"
765
+ }
766
+ ),
767
+ /* @__PURE__ */ jsx(
768
+ "rect",
769
+ {
770
+ x: "8",
771
+ y: "84",
772
+ width: "132",
773
+ height: "8",
774
+ rx: "2",
775
+ fill: "rgb(var(--oui-color-base-7))"
776
+ }
777
+ ),
778
+ /* @__PURE__ */ jsxs("g", { clipPath: "url(#clip0_31319_74743)", children: [
779
+ /* @__PURE__ */ jsx(
780
+ "rect",
781
+ {
782
+ x: "10",
783
+ y: "86",
784
+ width: "16",
785
+ height: "4",
786
+ rx: "2",
787
+ fill: "rgb(var(--oui-color-primary-darken))"
788
+ }
789
+ ),
790
+ /* @__PURE__ */ jsx(
791
+ "rect",
792
+ {
793
+ x: "28",
794
+ y: "86",
795
+ width: "16",
796
+ height: "4",
797
+ rx: "2",
798
+ fill: "rgb(var(--oui-color-base-4))"
799
+ }
800
+ ),
801
+ /* @__PURE__ */ jsx(
802
+ "rect",
803
+ {
804
+ x: "46",
805
+ y: "86",
806
+ width: "16",
807
+ height: "4",
808
+ rx: "2",
809
+ fill: "rgb(var(--oui-color-base-4))"
810
+ }
811
+ ),
812
+ /* @__PURE__ */ jsx(
813
+ "rect",
814
+ {
815
+ x: "64",
816
+ y: "86",
817
+ width: "16",
818
+ height: "4",
819
+ rx: "2",
820
+ fill: "rgb(var(--oui-color-base-4))"
821
+ }
822
+ ),
823
+ /* @__PURE__ */ jsx(
824
+ "rect",
825
+ {
826
+ x: "82",
827
+ y: "86",
828
+ width: "16",
829
+ height: "4",
830
+ rx: "2",
831
+ fill: "rgb(var(--oui-color-base-4))"
832
+ }
833
+ ),
834
+ /* @__PURE__ */ jsx(
835
+ "rect",
836
+ {
837
+ x: "100",
838
+ y: "86",
839
+ width: "16",
840
+ height: "4",
841
+ rx: "2",
842
+ fill: "rgb(var(--oui-color-base-4))"
843
+ }
844
+ ),
845
+ /* @__PURE__ */ jsx(
846
+ "rect",
847
+ {
848
+ x: "118",
849
+ y: "86",
850
+ width: "16",
851
+ height: "4",
852
+ rx: "2",
853
+ fill: "rgb(var(--oui-color-base-4))"
854
+ }
855
+ ),
856
+ /* @__PURE__ */ jsx(
857
+ "rect",
858
+ {
859
+ x: "136",
860
+ y: "86",
861
+ width: "16",
862
+ height: "4",
863
+ rx: "2",
864
+ fill: "rgb(var(--oui-color-base-4))"
865
+ }
866
+ )
867
+ ] }),
868
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: "clip0_31319_74743", children: /* @__PURE__ */ jsx(
869
+ "rect",
870
+ {
871
+ width: "130",
872
+ height: "4",
873
+ fill: "rgb(var(--oui-color-base-foreground))",
874
+ transform: "translate(10 86)"
875
+ }
876
+ ) }) })
877
+ ]
878
+ }
879
+ );
880
+ };
881
+ var MarketHideIcon = ({
882
+ isSelected,
883
+ isHovered,
884
+ ...props
885
+ }) => {
886
+ const getStrokeColor = () => {
887
+ if (isSelected) return "rgb(var(--oui-color-primary-light))";
888
+ if (isHovered) return "rgb(var(--oui-color-primary-light))";
889
+ return "rgb(var(--oui-color-base-5))";
890
+ };
891
+ return /* @__PURE__ */ jsxs(
892
+ "svg",
893
+ {
894
+ width: "148",
895
+ height: "100",
896
+ viewBox: "0 0 148 100",
897
+ fill: "none",
898
+ xmlns: "http://www.w3.org/2000/svg",
899
+ ...props,
900
+ children: [
901
+ /* @__PURE__ */ jsx(
902
+ "rect",
903
+ {
904
+ x: "2",
905
+ y: "2",
906
+ width: "144",
907
+ height: "96",
908
+ rx: "10",
909
+ fill: "rgb(var(--oui-color-base-10))",
910
+ stroke: getStrokeColor(),
911
+ strokeWidth: "4"
912
+ }
913
+ ),
914
+ /* @__PURE__ */ jsxs("g", { clipPath: "url(#clip0_31319_74757)", children: [
915
+ /* @__PURE__ */ jsx(
916
+ "rect",
917
+ {
918
+ x: "8",
919
+ y: "8",
920
+ width: "132",
921
+ height: "84",
922
+ rx: "2",
923
+ fill: "rgb(var(--oui-color-base-7))"
924
+ }
925
+ ),
926
+ /* @__PURE__ */ jsx(
927
+ "rect",
928
+ {
929
+ x: "66.8789",
930
+ y: "-76",
931
+ width: "4",
932
+ height: "188",
933
+ rx: "2",
934
+ transform: "rotate(45 66.8789 -76)",
935
+ fill: "rgb(var(--oui-color-base-6))"
936
+ }
937
+ ),
938
+ /* @__PURE__ */ jsx(
939
+ "rect",
940
+ {
941
+ x: "73.9492",
942
+ y: "-68.929",
943
+ width: "4",
944
+ height: "188",
945
+ rx: "2",
946
+ transform: "rotate(45 73.9492 -68.929)",
947
+ fill: "rgb(var(--oui-color-base-6))"
948
+ }
949
+ ),
950
+ /* @__PURE__ */ jsx(
951
+ "rect",
952
+ {
953
+ x: "81.0195",
954
+ y: "-61.8579",
955
+ width: "4",
956
+ height: "188",
957
+ rx: "2",
958
+ transform: "rotate(45 81.0195 -61.8579)",
959
+ fill: "rgb(var(--oui-color-base-6))"
960
+ }
961
+ ),
962
+ /* @__PURE__ */ jsx(
963
+ "rect",
964
+ {
965
+ x: "88.0938",
966
+ y: "-54.7867",
967
+ width: "4",
968
+ height: "188",
969
+ rx: "2",
970
+ transform: "rotate(45 88.0938 -54.7867)",
971
+ fill: "rgb(var(--oui-color-base-6))"
972
+ }
973
+ ),
974
+ /* @__PURE__ */ jsx(
975
+ "rect",
976
+ {
977
+ x: "95.1641",
978
+ y: "-47.7157",
979
+ width: "4",
980
+ height: "188",
981
+ rx: "2",
982
+ transform: "rotate(45 95.1641 -47.7157)",
983
+ fill: "rgb(var(--oui-color-base-6))"
984
+ }
985
+ ),
986
+ /* @__PURE__ */ jsx(
987
+ "rect",
988
+ {
989
+ x: "102.234",
990
+ y: "-40.6447",
991
+ width: "4",
992
+ height: "188",
993
+ rx: "2",
994
+ transform: "rotate(45 102.234 -40.6447)",
995
+ fill: "rgb(var(--oui-color-base-6))"
996
+ }
997
+ ),
998
+ /* @__PURE__ */ jsx(
999
+ "rect",
1000
+ {
1001
+ x: "109.305",
1002
+ y: "-33.5736",
1003
+ width: "4",
1004
+ height: "188",
1005
+ rx: "2",
1006
+ transform: "rotate(45 109.305 -33.5736)",
1007
+ fill: "rgb(var(--oui-color-base-6))"
1008
+ }
1009
+ ),
1010
+ /* @__PURE__ */ jsx(
1011
+ "rect",
1012
+ {
1013
+ x: "116.375",
1014
+ y: "-26.5026",
1015
+ width: "4",
1016
+ height: "188",
1017
+ rx: "2",
1018
+ transform: "rotate(45 116.375 -26.5026)",
1019
+ fill: "rgb(var(--oui-color-base-6))"
1020
+ }
1021
+ ),
1022
+ /* @__PURE__ */ jsx(
1023
+ "rect",
1024
+ {
1025
+ x: "123.449",
1026
+ y: "-19.4315",
1027
+ width: "4",
1028
+ height: "188",
1029
+ rx: "2",
1030
+ transform: "rotate(45 123.449 -19.4315)",
1031
+ fill: "rgb(var(--oui-color-base-6))"
1032
+ }
1033
+ ),
1034
+ /* @__PURE__ */ jsx(
1035
+ "rect",
1036
+ {
1037
+ x: "130.52",
1038
+ y: "-12.3604",
1039
+ width: "4",
1040
+ height: "188",
1041
+ rx: "2",
1042
+ transform: "rotate(45 130.52 -12.3604)",
1043
+ fill: "rgb(var(--oui-color-base-6))"
1044
+ }
1045
+ ),
1046
+ /* @__PURE__ */ jsx(
1047
+ "rect",
1048
+ {
1049
+ x: "137.59",
1050
+ y: "-5.28931",
1051
+ width: "4",
1052
+ height: "188",
1053
+ rx: "2",
1054
+ transform: "rotate(45 137.59 -5.28931)",
1055
+ fill: "rgb(var(--oui-color-base-6))"
1056
+ }
1057
+ ),
1058
+ /* @__PURE__ */ jsx(
1059
+ "rect",
1060
+ {
1061
+ x: "144.66",
1062
+ y: "1.78174",
1063
+ width: "4",
1064
+ height: "188",
1065
+ rx: "2",
1066
+ transform: "rotate(45 144.66 1.78174)",
1067
+ fill: "rgb(var(--oui-color-base-6))"
1068
+ }
1069
+ ),
1070
+ /* @__PURE__ */ jsx(
1071
+ "rect",
1072
+ {
1073
+ x: "151.73",
1074
+ y: "8.85278",
1075
+ width: "4",
1076
+ height: "188",
1077
+ rx: "2",
1078
+ transform: "rotate(45 151.73 8.85278)",
1079
+ fill: "rgb(var(--oui-color-base-6))"
1080
+ }
1081
+ ),
1082
+ /* @__PURE__ */ jsx(
1083
+ "rect",
1084
+ {
1085
+ x: "158.805",
1086
+ y: "15.9238",
1087
+ width: "4",
1088
+ height: "188",
1089
+ rx: "2",
1090
+ transform: "rotate(45 158.805 15.9238)",
1091
+ fill: "rgb(var(--oui-color-base-6))"
1092
+ }
1093
+ ),
1094
+ /* @__PURE__ */ jsx(
1095
+ "rect",
1096
+ {
1097
+ x: "165.875",
1098
+ y: "22.995",
1099
+ width: "4",
1100
+ height: "188",
1101
+ rx: "2",
1102
+ transform: "rotate(45 165.875 22.995)",
1103
+ fill: "rgb(var(--oui-color-base-6))"
1104
+ }
1105
+ ),
1106
+ /* @__PURE__ */ jsx(
1107
+ "rect",
1108
+ {
1109
+ x: "172.945",
1110
+ y: "30.066",
1111
+ width: "4",
1112
+ height: "188",
1113
+ rx: "2",
1114
+ transform: "rotate(45 172.945 30.066)",
1115
+ fill: "rgb(var(--oui-color-base-6))"
1116
+ }
1117
+ ),
1118
+ /* @__PURE__ */ jsx(
1119
+ "rect",
1120
+ {
1121
+ x: "180.016",
1122
+ y: "37.1371",
1123
+ width: "4",
1124
+ height: "188",
1125
+ rx: "2",
1126
+ transform: "rotate(45 180.016 37.1371)",
1127
+ fill: "rgb(var(--oui-color-base-6))"
1128
+ }
1129
+ ),
1130
+ /* @__PURE__ */ jsx(
1131
+ "rect",
1132
+ {
1133
+ x: "187.086",
1134
+ y: "44.2081",
1135
+ width: "4",
1136
+ height: "188",
1137
+ rx: "2",
1138
+ transform: "rotate(45 187.086 44.2081)",
1139
+ fill: "rgb(var(--oui-color-base-6))"
1140
+ }
1141
+ ),
1142
+ /* @__PURE__ */ jsx(
1143
+ "rect",
1144
+ {
1145
+ x: "194.156",
1146
+ y: "51.2792",
1147
+ width: "4",
1148
+ height: "188",
1149
+ rx: "2",
1150
+ transform: "rotate(45 194.156 51.2792)",
1151
+ fill: "rgb(var(--oui-color-base-6))"
1152
+ }
1153
+ ),
1154
+ /* @__PURE__ */ jsx(
1155
+ "rect",
1156
+ {
1157
+ x: "201.23",
1158
+ y: "58.3503",
1159
+ width: "4",
1160
+ height: "188",
1161
+ rx: "2",
1162
+ transform: "rotate(45 201.23 58.3503)",
1163
+ fill: "rgb(var(--oui-color-base-6))"
1164
+ }
1165
+ )
1166
+ ] }),
1167
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: "clip0_31319_74757", children: /* @__PURE__ */ jsx(
1168
+ "rect",
1169
+ {
1170
+ width: "132",
1171
+ height: "84",
1172
+ fill: "rgb(var(--oui-color-base-foreground))",
1173
+ transform: "translate(8 8)"
1174
+ }
1175
+ ) }) })
1176
+ ]
1177
+ }
1178
+ );
1179
+ };
1180
+ var LayoutSwitchButton = ({
1181
+ layout,
1182
+ markets,
1183
+ onLayoutChange,
1184
+ onMarketChange
1185
+ }) => {
1186
+ const { t } = useTranslation();
1187
+ const [open, setOpen] = React.useState(false);
1188
+ const [hoveredMarket, setHoveredMarket] = React.useState(null);
1189
+ const renderLayoutItem = (position) => /* @__PURE__ */ jsxs(
1190
+ Flex,
1191
+ {
1192
+ direction: "column",
1193
+ gapY: 2,
1194
+ onClick: () => {
1195
+ onLayoutChange(position);
1196
+ setOpen(false);
1197
+ },
1198
+ className: "oui-group",
1199
+ children: [
1200
+ /* @__PURE__ */ jsx(
1201
+ Flex,
1202
+ {
1203
+ justify: position === "right" ? "end" : "start",
1204
+ className: cn(
1205
+ "oui-w-[148px] oui-h-[100px]",
1206
+ "oui-bg-base-10 oui-rounded-[10px]",
1207
+ "oui-border-[4px] oui-border-base-5 group-hover:oui-border-primary-light",
1208
+ layout === position && "!oui-border-primary-light"
1209
+ ),
1210
+ children: /* @__PURE__ */ jsx(Box, { p: 1, children: /* @__PURE__ */ jsx(OrderEntryIcon, {}) })
1211
+ }
1212
+ ),
1213
+ /* @__PURE__ */ jsx(
1214
+ Text,
1215
+ {
1216
+ size: "2xs",
1217
+ intensity: 54,
1218
+ className: cn(
1219
+ "oui-text-base-contrast-54 group-hover:oui-text-base-contrast-80",
1220
+ layout === position && "oui-text-base-contrast-80"
1221
+ ),
1222
+ children: String(
1223
+ position === "right" ? t("trading.layout.advanced.right") : t("trading.layout.advanced.left")
1224
+ )
1225
+ }
1226
+ )
1227
+ ]
1228
+ }
1229
+ );
1230
+ const renderMarketItem = (position) => {
1231
+ const isSelected = markets === position;
1232
+ const isHovered = hoveredMarket === position;
1233
+ const getLabel = () => {
1234
+ switch (position) {
1235
+ case "left":
1236
+ return t("trading.layout.markets.left");
1237
+ case "top":
1238
+ return t("trading.layout.markets.top");
1239
+ case "bottom":
1240
+ return t("trading.layout.markets.bottom");
1241
+ case "hide":
1242
+ return t("trading.layout.markets.hide");
1243
+ default:
1244
+ return t("trading.layout.markets.left");
1245
+ }
1246
+ };
1247
+ return /* @__PURE__ */ jsxs(
1248
+ Flex,
1249
+ {
1250
+ direction: "column",
1251
+ gapY: 2,
1252
+ onClick: () => {
1253
+ onMarketChange(position);
1254
+ setOpen(false);
1255
+ },
1256
+ onMouseEnter: () => setHoveredMarket(position),
1257
+ onMouseLeave: () => setHoveredMarket(null),
1258
+ className: "oui-group",
1259
+ children: [
1260
+ /* @__PURE__ */ jsxs(Flex, { justify: "center", className: "oui-w-[148px] oui-h-[100px]", children: [
1261
+ position === "left" && /* @__PURE__ */ jsx(MarketLeftIcon, { isSelected, isHovered }),
1262
+ position === "top" && /* @__PURE__ */ jsx(MarketTopIcon, { isSelected, isHovered }),
1263
+ position === "bottom" && /* @__PURE__ */ jsx(MarketBottomIcon, { isSelected, isHovered }),
1264
+ position === "hide" && /* @__PURE__ */ jsx(MarketHideIcon, { isSelected, isHovered })
1265
+ ] }),
1266
+ /* @__PURE__ */ jsx(
1267
+ Text,
1268
+ {
1269
+ size: "2xs",
1270
+ intensity: 54,
1271
+ className: cn(
1272
+ "oui-text-base-contrast-54 group-hover:oui-text-base-contrast-80",
1273
+ isSelected && "oui-text-base-contrast-80"
1274
+ ),
1275
+ children: String(getLabel())
1276
+ }
1277
+ )
1278
+ ]
1279
+ }
1280
+ );
1281
+ };
1282
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1283
+ /* @__PURE__ */ jsxs(
1284
+ Flex,
1285
+ {
1286
+ itemAlign: "center",
1287
+ justify: "between",
1288
+ mt: 3,
1289
+ className: "oui-mb-[10px] oui-min-w-[500px]",
1290
+ children: [
1291
+ /* @__PURE__ */ jsx(Text, { size: "base", intensity: 98, children: t("trading.layout") }),
1292
+ /* @__PURE__ */ jsx(
1293
+ CloseIcon,
1294
+ {
1295
+ size: 16,
1296
+ className: "oui-cursor-pointer oui-text-base-contrast-80",
1297
+ opacity: 0.98,
1298
+ onClick: () => {
1299
+ setOpen(false);
1300
+ }
1301
+ }
1302
+ )
1303
+ ]
1304
+ }
1305
+ ),
1306
+ /* @__PURE__ */ jsx(Divider, {}),
1307
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gapY: 2, mt: 5, itemAlign: "start", children: [
1308
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 98, children: String(t("trading.layout.advanced")) }),
1309
+ /* @__PURE__ */ jsxs(Flex, { gapX: 6, children: [
1310
+ renderLayoutItem("left"),
1311
+ renderLayoutItem("right")
1312
+ ] })
1313
+ ] }),
1314
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gapY: 2, mt: 5, itemAlign: "start", children: [
1315
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 98, children: String(t("trading.layout.markets")) }),
1316
+ /* @__PURE__ */ jsxs(Flex, { gapX: 6, children: [
1317
+ renderMarketItem("left"),
1318
+ renderMarketItem("top"),
1319
+ renderMarketItem("bottom"),
1320
+ renderMarketItem("hide")
1321
+ ] })
1322
+ ] })
1323
+ ] });
1324
+ return /* @__PURE__ */ jsxs(DropdownMenuRoot, { open, onOpenChange: setOpen, children: [
1325
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
1326
+ Flex,
1327
+ {
1328
+ px: 3,
1329
+ className: cn(
1330
+ "oui-rounded-md",
1331
+ "oui-h-[28px]",
1332
+ "oui-cursor-pointer oui-transition-all",
1333
+ "oui-bg-base-6 hover:oui-bg-base-4",
1334
+ "oui-text-base-contrast-54 hover:oui-text-base-contrast-80"
1335
+ ),
1336
+ gapX: 1,
1337
+ ml: 3,
1338
+ justify: "center",
1339
+ itemAlign: "center",
1340
+ children: /* @__PURE__ */ jsx(Text, { size: "2xs", weight: "semibold", children: t("trading.layout") })
1341
+ }
1342
+ ) }),
1343
+ /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(
1344
+ DropdownMenuContent,
1345
+ {
1346
+ onCloseAutoFocus: (e) => e.preventDefault(),
1347
+ onClick: (e) => e.stopPropagation(),
1348
+ align: "end",
1349
+ className: cn("oui-bg-base-8 oui-p-5 oui-pt-0 oui-font-semibold"),
1350
+ children: content
1351
+ }
1352
+ ) })
1353
+ ] });
1354
+ };
1355
+ var SymbolBarLayoutSwitcher = ({
1356
+ layout = "right",
1357
+ marketLayout = "left",
1358
+ onLayoutChange,
1359
+ onMarketLayoutChange
1360
+ }) => {
1361
+ if (!onLayoutChange || !onMarketLayoutChange) {
1362
+ return /* @__PURE__ */ jsx(Fragment, {});
1363
+ }
1364
+ return /* @__PURE__ */ jsx(
1365
+ LayoutSwitchButton,
1366
+ {
1367
+ layout,
1368
+ markets: marketLayout,
1369
+ onLayoutChange,
1370
+ onMarketChange: onMarketLayoutChange
1371
+ }
1372
+ );
1373
+ };
1374
+ function getViewportBreakpointKey(viewportWidth, breakpoints = VIEWPORT_BREAKPOINTS) {
1375
+ for (const bp of BREAKPOINT_KEYS) {
1376
+ if (viewportWidth >= breakpoints[bp]) return bp;
1377
+ }
1378
+ return "xs";
1379
+ }
1380
+ function useViewportBreakpoint(options = {}) {
1381
+ const {
1382
+ breakpoints = VIEWPORT_BREAKPOINTS,
1383
+ fallbackWidth = typeof window !== "undefined" ? window.innerWidth : 1440
1384
+ } = options;
1385
+ const [width, setWidth] = useState(fallbackWidth);
1386
+ useEffect(() => {
1387
+ const element = document.documentElement;
1388
+ if (!element) return;
1389
+ setWidth(window.innerWidth);
1390
+ const resizeObserver = new ResizeObserver((entries) => {
1391
+ for (const entry of entries) {
1392
+ setWidth(entry.contentRect.width);
1393
+ }
1394
+ });
1395
+ resizeObserver.observe(element);
1396
+ return () => resizeObserver.disconnect();
1397
+ }, []);
1398
+ const bp = getViewportBreakpointKey(width, breakpoints);
1399
+ return bp;
1400
+ }
1401
+
1402
+ // src/hooks/useSplitLayout.ts
1403
+ var ORDER_ENTRY_MIN_WIDTH = 280;
1404
+ var ORDER_ENTRY_MAX_WIDTH = 360;
1405
+ var ORDERBOOK_MIN_WIDTH = 280;
1406
+ var ORDERBOOK_MAX_WIDTH = 732;
1407
+ var ORDERBOOK_MIN_HEIGHT = 464;
1408
+ var ORDERBOOK_MAX_HEIGHT = 728;
1409
+ var TRADINGVIEW_MIN_HEIGHT = 320;
1410
+ var TRADINGVIEW_MIN_WIDTH = 540;
1411
+ var DATA_LIST_MAX_HEIGHT = 800;
1412
+ var DATA_LIST_INITIAL_HEIGHT = 350;
1413
+ var SPACE = 8;
1414
+ var SYMBOL_INFO_BAR_HEIGHT = 54;
1415
+ var ORDERLY_ORDER_ENTRY_SIDE_MARKETS_LAYOUT = "orderly_order_entry_side_markets_layout";
1416
+ var ORDERLY_SIDE_MARKETS_MODE_KEY = "orderly_side_markets_mode";
1417
+ var ORDERLY_HORIZONTAL_MARKETS_LAYOUT = "orderly_horizontal_markets_layout";
1418
+ var ORDERLY_MAIN_SPLIT_SIZE = "orderly_main_split_size";
1419
+ var ORDERLY_DATA_LIST_SPLIT_SIZE = "orderly_datalist_split_size";
1420
+ var ORDERLY_ORDERBOOK_SPLIT_SIZE = "orderly_orderbook_split_size";
1421
+ var ORDERLY_DATA_LIST_SPLIT_HEIGHT_SM = "orderly_datalist_split_height_sm";
1422
+ var ORDERLY_ORDERBOOK_SPLIT_HEIGHT_SM = "orderly_orderbook_split_height_sm";
1423
+ var ORDERLY_ORDER_ENTRY_EXTRA_HEIGHT = "orderly_order_entry_extra_height";
1424
+ function buildLayoutTree(layout, marketLayout, max2XL) {
1425
+ if (max2XL) {
1426
+ return buildSMLayoutTree(layout, marketLayout);
1427
+ }
1428
+ return buildLGLayoutTree(layout, marketLayout);
1429
+ }
1430
+ function buildLGLayoutTree(layout, marketLayout) {
1431
+ const orderEntrySort = {
1432
+ type: "sort",
1433
+ orientation: "vertical",
1434
+ children: [
1435
+ { type: "panel", id: TRADING_PANEL_IDS.MARGIN },
1436
+ { type: "panel", id: TRADING_PANEL_IDS.ASSETS },
1437
+ { type: "panel", id: TRADING_PANEL_IDS.ORDER_ENTRY }
1438
+ ]
1439
+ };
1440
+ const tvObSplit = {
1441
+ type: "split",
1442
+ orientation: "horizontal",
1443
+ children: [
1444
+ { type: "panel", id: TRADING_PANEL_IDS.TRADING_VIEW },
1445
+ { type: "panel", id: TRADING_PANEL_IDS.ORDERBOOK }
1446
+ ]
1447
+ };
1448
+ const mainCol = {
1449
+ type: "split",
1450
+ orientation: "vertical",
1451
+ children: [
1452
+ {
1453
+ type: "panel",
1454
+ id: TRADING_PANEL_IDS.SYMBOL_INFO_BAR,
1455
+ size: "fixed",
1456
+ disabled: true
1457
+ },
1458
+ tvObSplit,
1459
+ { type: "panel", id: TRADING_PANEL_IDS.DATA_LIST }
1460
+ ]
1461
+ };
1462
+ if (marketLayout === "top") {
1463
+ return {
1464
+ type: "split",
1465
+ orientation: "vertical",
1466
+ children: [
1467
+ {
1468
+ type: "panel",
1469
+ id: TRADING_PANEL_IDS.HORIZONTAL_MARKETS,
1470
+ size: "fixed",
1471
+ disabled: true
1472
+ },
1473
+ layout === "left" ? {
1474
+ type: "split",
1475
+ orientation: "horizontal",
1476
+ children: [orderEntrySort, mainCol]
1477
+ } : {
1478
+ type: "split",
1479
+ orientation: "horizontal",
1480
+ children: [mainCol, orderEntrySort]
1481
+ }
1482
+ ]
1483
+ };
1484
+ }
1485
+ if (marketLayout === "bottom") {
1486
+ return layout === "left" ? {
1487
+ type: "split",
1488
+ orientation: "horizontal",
1489
+ children: [
1490
+ orderEntrySort,
1491
+ {
1492
+ type: "split",
1493
+ orientation: "vertical",
1494
+ children: [
1495
+ mainCol,
1496
+ {
1497
+ type: "panel",
1498
+ id: TRADING_PANEL_IDS.HORIZONTAL_MARKETS,
1499
+ size: "fixed",
1500
+ disabled: true
1501
+ }
1502
+ ]
1503
+ }
1504
+ ]
1505
+ } : {
1506
+ type: "split",
1507
+ orientation: "horizontal",
1508
+ children: [
1509
+ {
1510
+ type: "split",
1511
+ orientation: "vertical",
1512
+ children: [
1513
+ mainCol,
1514
+ {
1515
+ type: "panel",
1516
+ id: TRADING_PANEL_IDS.HORIZONTAL_MARKETS,
1517
+ size: "fixed",
1518
+ disabled: true
1519
+ }
1520
+ ]
1521
+ },
1522
+ orderEntrySort
1523
+ ]
1524
+ };
1525
+ }
1526
+ if (marketLayout === "hide") {
1527
+ return layout === "left" ? {
1528
+ type: "split",
1529
+ orientation: "horizontal",
1530
+ children: [orderEntrySort, mainCol]
1531
+ } : {
1532
+ type: "split",
1533
+ orientation: "horizontal",
1534
+ children: [mainCol, orderEntrySort]
1535
+ };
1536
+ }
1537
+ return {
1538
+ type: "split",
1539
+ orientation: "horizontal",
1540
+ children: [
1541
+ {
1542
+ type: "panel",
1543
+ id: TRADING_PANEL_IDS.MARKETS,
1544
+ size: "fixed",
1545
+ disabled: true
1546
+ },
1547
+ layout === "left" ? {
1548
+ type: "split",
1549
+ orientation: "horizontal",
1550
+ children: [orderEntrySort, mainCol]
1551
+ } : {
1552
+ type: "split",
1553
+ orientation: "horizontal",
1554
+ children: [mainCol, orderEntrySort]
1555
+ }
1556
+ ]
1557
+ };
1558
+ }
1559
+ function buildSMLayoutTree(layout, marketLayout) {
1560
+ const orderEntrySort = {
1561
+ type: "sort",
1562
+ orientation: "vertical",
1563
+ children: [
1564
+ { type: "panel", id: TRADING_PANEL_IDS.MARGIN },
1565
+ { type: "panel", id: TRADING_PANEL_IDS.ASSETS },
1566
+ { type: "panel", id: TRADING_PANEL_IDS.ORDER_ENTRY }
1567
+ ]
1568
+ };
1569
+ const tvObSplit = {
1570
+ type: "split",
1571
+ orientation: "vertical",
1572
+ children: [
1573
+ { type: "panel", id: TRADING_PANEL_IDS.TRADING_VIEW },
1574
+ { type: "panel", id: TRADING_PANEL_IDS.ORDERBOOK }
1575
+ ]
1576
+ };
1577
+ const mainCol = {
1578
+ type: "split",
1579
+ orientation: "vertical",
1580
+ children: [
1581
+ {
1582
+ type: "panel",
1583
+ id: TRADING_PANEL_IDS.SYMBOL_INFO_BAR,
1584
+ size: "fixed",
1585
+ disabled: true
1586
+ },
1587
+ tvObSplit,
1588
+ { type: "panel", id: TRADING_PANEL_IDS.DATA_LIST }
1589
+ ]
1590
+ };
1591
+ if (marketLayout === "top") {
1592
+ return {
1593
+ type: "split",
1594
+ orientation: "vertical",
1595
+ children: [
1596
+ {
1597
+ type: "panel",
1598
+ id: TRADING_PANEL_IDS.HORIZONTAL_MARKETS,
1599
+ size: "fixed",
1600
+ disabled: true
1601
+ },
1602
+ {
1603
+ type: "split",
1604
+ orientation: "vertical",
1605
+ children: [orderEntrySort, mainCol]
1606
+ }
1607
+ ]
1608
+ };
1609
+ }
1610
+ if (marketLayout === "hide") {
1611
+ return {
1612
+ type: "split",
1613
+ orientation: "vertical",
1614
+ children: [orderEntrySort, mainCol]
1615
+ };
1616
+ }
1617
+ if (marketLayout === "bottom") {
1618
+ return {
1619
+ type: "split",
1620
+ orientation: "vertical",
1621
+ children: [
1622
+ mainCol,
1623
+ {
1624
+ type: "panel",
1625
+ id: TRADING_PANEL_IDS.HORIZONTAL_MARKETS,
1626
+ size: "fixed",
1627
+ disabled: true
1628
+ }
1629
+ ]
1630
+ };
1631
+ }
1632
+ return {
1633
+ type: "split",
1634
+ orientation: "vertical",
1635
+ children: [
1636
+ {
1637
+ type: "split",
1638
+ orientation: "horizontal",
1639
+ children: [orderEntrySort, mainCol]
1640
+ }
1641
+ ]
1642
+ };
1643
+ }
1644
+ function useSplitLayout(options = {}) {
1645
+ const {
1646
+ initialLayout = "right",
1647
+ initialMarketLayout = "left",
1648
+ canTrade = true,
1649
+ isFirstTimeDeposit = false
1650
+ } = options;
1651
+ const max2XL = useMediaQuery("(max-width: 1279px)");
1652
+ const min3XL = useMediaQuery("(min-width: 1440px)");
1653
+ const max4XL = useMediaQuery("(max-width: 1680px)");
1654
+ const breakpoint = useViewportBreakpoint();
1655
+ const [layout, setLayout] = useLocalStorage(
1656
+ ORDERLY_ORDER_ENTRY_SIDE_MARKETS_LAYOUT,
1657
+ initialLayout
1658
+ );
1659
+ const [marketLayout, setMarketLayout] = useLocalStorage(
1660
+ ORDERLY_HORIZONTAL_MARKETS_LAYOUT,
1661
+ initialMarketLayout
1662
+ );
1663
+ const [panelSize, setPanelSize] = useLocalStorage(
1664
+ ORDERLY_SIDE_MARKETS_MODE_KEY,
1665
+ "large"
1666
+ );
1667
+ const marketsWidth = useMemo(() => {
1668
+ switch (panelSize) {
1669
+ case "small":
1670
+ return 0;
1671
+ case "middle":
1672
+ return 70;
1673
+ case "large":
1674
+ return 280;
1675
+ default:
1676
+ return 0;
1677
+ }
1678
+ }, [panelSize]);
1679
+ const horizontalDraggable = min3XL;
1680
+ const [mainSplitSize, setMainSplitSize] = useLocalStorage(
1681
+ ORDERLY_MAIN_SPLIT_SIZE,
1682
+ `${ORDER_ENTRY_MIN_WIDTH}px`
1683
+ );
1684
+ const [orderBookSplitSize, setOrderbookSplitSize] = useLocalStorage(
1685
+ ORDERLY_ORDERBOOK_SPLIT_SIZE,
1686
+ "280px"
1687
+ );
1688
+ const [dataListSplitSize, setDataListSplitSize] = useLocalStorage(
1689
+ ORDERLY_DATA_LIST_SPLIT_SIZE,
1690
+ `${DATA_LIST_INITIAL_HEIGHT}px`
1691
+ );
1692
+ const [dataListSplitHeightSM, setDataListSplitHeightSM] = useLocalStorage(
1693
+ ORDERLY_DATA_LIST_SPLIT_HEIGHT_SM,
1694
+ "350px"
1695
+ );
1696
+ const [orderBookSplitHeightSM, setOrderbookSplitHeightSM] = useLocalStorage(
1697
+ ORDERLY_ORDERBOOK_SPLIT_HEIGHT_SM,
1698
+ "280px"
1699
+ );
1700
+ const [extraHeight, setExtraHeight] = useLocalStorage(
1701
+ ORDERLY_ORDER_ENTRY_EXTRA_HEIGHT,
1702
+ 0
1703
+ );
1704
+ useCallback(
1705
+ (preSize, nextSize, boxHeight) => {
1706
+ if (!boxHeight) return;
1707
+ const splitTradingviewHeight = boxHeight * preSize / 100;
1708
+ const splitOrderbookHeight = boxHeight * nextSize / 100;
1709
+ const tradingviewHeight = Math.min(
1710
+ Math.max(splitTradingviewHeight, TRADINGVIEW_MIN_HEIGHT),
1711
+ max2XL ? 1200 : 600
1712
+ );
1713
+ const orderbookHeight = Math.min(
1714
+ Math.max(splitOrderbookHeight, ORDERBOOK_MIN_HEIGHT),
1715
+ ORDERBOOK_MAX_HEIGHT
1716
+ );
1717
+ if (splitOrderbookHeight >= orderbookHeight) {
1718
+ const offset = splitOrderbookHeight - orderbookHeight;
1719
+ setExtraHeight(Math.max(0, extraHeight - offset));
1720
+ } else if (tradingviewHeight + orderbookHeight < (max2XL ? 1200 : 600) + ORDERBOOK_MAX_HEIGHT) {
1721
+ const height = tradingviewHeight + orderbookHeight + SPACE + SYMBOL_INFO_BAR_HEIGHT;
1722
+ const offset = Math.max(0, height - 0);
1723
+ setExtraHeight(extraHeight + offset);
1724
+ }
1725
+ },
1726
+ [max2XL, extraHeight, setExtraHeight]
1727
+ );
1728
+ const tradingviewMaxHeight = max2XL ? 1200 : 600;
1729
+ const dataListHeight = canTrade ? 379 : 277;
1730
+ const memoizedPanelSize = useMemo(() => {
1731
+ const normalized = panelSize === "large" ? "large" : "middle";
1732
+ return horizontalDraggable ? normalized : "middle";
1733
+ }, [horizontalDraggable, panelSize]);
1734
+ const layoutTree = useMemo(
1735
+ () => buildLayoutTree(layout, marketLayout, max2XL),
1736
+ [layout, marketLayout, max2XL]
1737
+ );
1738
+ return {
1739
+ // Layout position
1740
+ layout,
1741
+ setLayout,
1742
+ marketLayout,
1743
+ setMarketLayout,
1744
+ // Breakpoint
1745
+ breakpoint,
1746
+ max2XL,
1747
+ min3XL,
1748
+ max4XL,
1749
+ horizontalDraggable,
1750
+ // Markets panel
1751
+ panelSize: memoizedPanelSize,
1752
+ setPanelSize: (size) => setPanelSize(size),
1753
+ marketsWidth,
1754
+ // Split sizes
1755
+ mainSplitSize,
1756
+ setMainSplitSize,
1757
+ orderBookSplitSize,
1758
+ setOrderbookSplitSize,
1759
+ dataListSplitSize,
1760
+ setDataListSplitSize,
1761
+ dataListSplitHeightSM,
1762
+ setDataListSplitHeightSM,
1763
+ orderBookSplitHeightSM,
1764
+ setOrderbookSplitHeightSM,
1765
+ // Extra height
1766
+ extraHeight,
1767
+ setExtraHeight,
1768
+ // Data list
1769
+ dataListHeight,
1770
+ // Trading view
1771
+ tradingviewMaxHeight,
1772
+ // Layout tree (for compat)
1773
+ layoutTree,
1774
+ // Constants
1775
+ symbolInfoBarHeight: SYMBOL_INFO_BAR_HEIGHT,
1776
+ space: SPACE,
1777
+ orderbookMinWidth: ORDERBOOK_MIN_WIDTH,
1778
+ orderbookMaxWidth: ORDERBOOK_MAX_WIDTH,
1779
+ orderbookMinHeight: ORDERBOOK_MIN_HEIGHT,
1780
+ orderbookMaxHeight: ORDERBOOK_MAX_HEIGHT,
1781
+ tradingviewMinHeight: TRADINGVIEW_MIN_HEIGHT,
1782
+ orderEntryMinWidth: ORDER_ENTRY_MIN_WIDTH,
1783
+ orderEntryMaxWidth: ORDER_ENTRY_MAX_WIDTH
1784
+ };
1785
+ }
1786
+ var IndicatorIcon = (props) => /* @__PURE__ */ jsxs(
1787
+ "svg",
1788
+ {
1789
+ width: "10",
1790
+ height: "16",
1791
+ viewBox: "0 0 10 16",
1792
+ fill: "currentColor",
1793
+ xmlns: "http://www.w3.org/2000/svg",
1794
+ ...props,
1795
+ children: [
1796
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "6", height: "2", rx: "1" }),
1797
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "7", width: "6", height: "2", rx: "1" }),
1798
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "12", width: "6", height: "2", rx: "1" })
1799
+ ]
1800
+ }
1801
+ );
1802
+ var TradingSortablePanel = (props) => {
1803
+ const { showIndicator, dragOverlay } = props;
1804
+ const nodeRef = useRef(null);
1805
+ const [dimensions, setDimensions] = React.useState(null);
1806
+ const {
1807
+ setNodeRef,
1808
+ attributes,
1809
+ listeners,
1810
+ transform,
1811
+ transition,
1812
+ isDragging,
1813
+ setActivatorNodeRef
1814
+ } = useSortable({ id: props.id });
1815
+ useEffect(() => {
1816
+ if (isDragging && nodeRef.current && !dimensions) {
1817
+ const rect = nodeRef.current.getBoundingClientRect();
1818
+ setDimensions({ width: rect.width, height: rect.height });
1819
+ } else if (!isDragging && dimensions) {
1820
+ setDimensions(null);
1821
+ }
1822
+ }, [isDragging, dimensions]);
1823
+ const combinedRef = (node) => {
1824
+ setNodeRef(node);
1825
+ nodeRef.current = node;
1826
+ };
1827
+ const style = {
1828
+ transform: CSS.Transform.toString(transform),
1829
+ transition
1830
+ };
1831
+ if (isDragging && dimensions && !dragOverlay) {
1832
+ return /* @__PURE__ */ jsx(
1833
+ Box,
1834
+ {
1835
+ intensity: 900,
1836
+ r: "2xl",
1837
+ p: 3,
1838
+ className: "oui-relative",
1839
+ style: {
1840
+ ...style,
1841
+ width: dimensions.width,
1842
+ height: dimensions.height,
1843
+ minWidth: dimensions.width,
1844
+ minHeight: dimensions.height,
1845
+ maxWidth: dimensions.width,
1846
+ maxHeight: dimensions.height,
1847
+ border: "1px solid rgb(var(--oui-color-primary))",
1848
+ backgroundImage: `repeating-linear-gradient(135deg, rgb(var(--oui-color-base-6)) 0px, rgb(var(--oui-color-base-6)) 4px, transparent 4px, transparent 8px)`
1849
+ }
1850
+ }
1851
+ );
1852
+ }
1853
+ return /* @__PURE__ */ jsxs(
1854
+ Box,
1855
+ {
1856
+ intensity: 900,
1857
+ r: "2xl",
1858
+ p: 3,
1859
+ width: "100%",
1860
+ className: cn("oui-relative", props.className),
1861
+ ref: combinedRef,
1862
+ style,
1863
+ children: [
1864
+ /* @__PURE__ */ jsx(
1865
+ "div",
1866
+ {
1867
+ className: cn(
1868
+ "inner-content oui-transition-transform",
1869
+ dragOverlay && "oui-scale-95"
1870
+ ),
1871
+ children: props.children
1872
+ }
1873
+ ),
1874
+ showIndicator && /* @__PURE__ */ jsx(
1875
+ "button",
1876
+ {
1877
+ ...attributes,
1878
+ ...listeners,
1879
+ className: "oui-absolute oui-right-0 oui-top-4 oui-cursor-move oui-py-1",
1880
+ style: { touchAction: "none" },
1881
+ ref: setActivatorNodeRef,
1882
+ children: /* @__PURE__ */ jsx(IndicatorIcon, { className: "oui-text-base-contrast-20 hover:oui-text-base-contrast-80" })
1883
+ }
1884
+ )
1885
+ ]
1886
+ }
1887
+ );
1888
+ };
1889
+ var SplitLineBar = (props) => {
1890
+ const { onMouseDown, mode = "horizontal", ...rest } = props;
1891
+ const disable = useMemo(
1892
+ () => props.className?.split(" ").includes("disable"),
1893
+ [props.className]
1894
+ );
1895
+ const filteredCls = useMemo(
1896
+ () => props.className?.split(" ").filter((cls) => cls !== "disable"),
1897
+ [props.className]
1898
+ );
1899
+ return /* @__PURE__ */ jsx(
1900
+ "div",
1901
+ {
1902
+ ...rest,
1903
+ className: cn(
1904
+ filteredCls,
1905
+ "!oui-transition-none",
1906
+ "!oui-shadow-none !oui-bg-transparent",
1907
+ "hover:!oui-bg-primary-light hover:!oui-shadow-[0px_0px_4px_0px] hover:!oui-shadow-primary-light/80",
1908
+ "active:!oui-bg-primary-light active:!oui-shadow-[0px_0px_4px_0px] active:!oui-shadow-primary-light/80",
1909
+ "focus:!oui-bg-primary-light focus:!oui-shadow-[0px_0px_4px_0px] focus:!oui-shadow-primary-light/80",
1910
+ mode === "horizontal" ? "!oui-w-[2px] !oui-min-w-[2px] !oui-mx-[3px]" : "!oui-h-[2px] !oui-min-h-[2px] !oui-my-[3px]",
1911
+ disable && "oui-pointer-events-none"
1912
+ ),
1913
+ children: /* @__PURE__ */ jsx(
1914
+ "div",
1915
+ {
1916
+ onMouseDown,
1917
+ className: cn(
1918
+ "!oui-transition-none",
1919
+ mode === "horizontal" ? "after:!oui-w-[2px]" : "after:!oui-h-[2px]",
1920
+ "after:!oui-bg-transparent after:!oui-shadow-transparent"
1921
+ )
1922
+ }
1923
+ )
1924
+ }
1925
+ );
1926
+ };
1927
+ var TradingSplitLayout = forwardRef(
1928
+ (props, ref) => {
1929
+ const { onSizeChange, ...rest } = props;
1930
+ return /* @__PURE__ */ jsx(
1931
+ Split,
1932
+ {
1933
+ ref,
1934
+ ...rest,
1935
+ lineBar: true,
1936
+ renderBar: (barProps) => /* @__PURE__ */ jsx(SplitLineBar, { ...barProps, mode: props.mode }),
1937
+ onDragEnd: (_, width) => onSizeChange?.(`${width}`)
1938
+ }
1939
+ );
1940
+ }
1941
+ );
1942
+ TradingSplitLayout.displayName = "TradingSplitLayout";
1943
+ var SCROLLBAR_WIDTH = 6;
1944
+ var TOP_BAR_HEIGHT = 48;
1945
+ var BOTTOM_BAR_HEIGHT = 29;
1946
+ var ORDER_ENTRY_SORT_KEY = "orderly_order_entry_sortable_items";
1947
+ var DEFAULT_SORTABLE_ITEMS = [
1948
+ TRADING_PANEL_IDS.MARGIN,
1949
+ TRADING_PANEL_IDS.ASSETS,
1950
+ TRADING_PANEL_IDS.ORDER_ENTRY
1951
+ ];
1952
+ var dropAnimationConfig = {
1953
+ keyframes({
1954
+ transform
1955
+ }) {
1956
+ return [
1957
+ {
1958
+ transform: CSS.Transform.toString({
1959
+ ...transform.initial,
1960
+ scaleX: 1.05,
1961
+ scaleY: 1.05
1962
+ })
1963
+ },
1964
+ {
1965
+ transform: CSS.Transform.toString({
1966
+ ...transform.final,
1967
+ scaleX: 1,
1968
+ scaleY: 1
1969
+ })
1970
+ }
1971
+ ];
1972
+ },
1973
+ sideEffects: ({
1974
+ active,
1975
+ dragOverlay
1976
+ }) => {
1977
+ active.node.style.opacity = "0";
1978
+ const inner = dragOverlay.node.querySelector(".inner-content");
1979
+ if (inner) inner.classList.add("oui-animate-shake");
1980
+ return () => {
1981
+ active.node.style.opacity = "";
1982
+ };
1983
+ }
1984
+ };
1985
+ function SplitTradingLayout(props) {
1986
+ const { panels, className } = props;
1987
+ const {
1988
+ layout,
1989
+ marketLayout,
1990
+ max2XL,
1991
+ max4XL,
1992
+ horizontalDraggable,
1993
+ panelSize,
1994
+ setPanelSize,
1995
+ marketsWidth,
1996
+ mainSplitSize,
1997
+ setMainSplitSize,
1998
+ orderBookSplitSize,
1999
+ setOrderbookSplitSize,
2000
+ dataListSplitSize,
2001
+ setDataListSplitSize,
2002
+ dataListSplitHeightSM,
2003
+ setDataListSplitHeightSM,
2004
+ orderBookSplitHeightSM,
2005
+ setOrderbookSplitHeightSM,
2006
+ tradingviewMaxHeight: tradindviewMaxHeight,
2007
+ extraHeight,
2008
+ setExtraHeight,
2009
+ dataListHeight: dataListMinHeight,
2010
+ symbolInfoBarHeight
2011
+ } = useSplitLayout();
2012
+ const [tradingViewFullScreen] = useLocalStorage(
2013
+ TradingviewFullscreenKey,
2014
+ false
2015
+ );
2016
+ const [animating, setAnimating] = useState(false);
2017
+ const [sortableItems, setSortableItems] = useLocalStorage(
2018
+ ORDER_ENTRY_SORT_KEY,
2019
+ DEFAULT_SORTABLE_ITEMS
2020
+ );
2021
+ const tradingviewAndOrderbookSplitRef = useRef(null);
2022
+ const max2XLSplitRef = useRef(null);
2023
+ const orderEntryViewRef = useRef(null);
2024
+ const [orderEntryHeight, setOrderEntryHeight] = useState(0);
2025
+ useEffect(() => {
2026
+ const el = orderEntryViewRef.current;
2027
+ if (!el) return;
2028
+ const observer = new ResizeObserver((entries) => {
2029
+ const entry = entries[0];
2030
+ if (entry) setOrderEntryHeight(entry.contentRect.height);
2031
+ });
2032
+ observer.observe(el);
2033
+ return () => observer.disconnect();
2034
+ }, []);
2035
+ const onDataListSplitHeightDragging = useCallback(() => {
2036
+ setExtraHeight(0);
2037
+ }, [setExtraHeight]);
2038
+ const onTradingviewAndOrderbookDragging = useCallback(() => {
2039
+ }, []);
2040
+ const [activeId, setActiveId] = useState(null);
2041
+ const showPositionIcon = true;
2042
+ const sensors = useSensors(
2043
+ useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
2044
+ useSensor(KeyboardSensor, {
2045
+ coordinateGetter: sortableKeyboardCoordinates
2046
+ })
2047
+ );
2048
+ function handleDragStart(event) {
2049
+ setActiveId(event.active.id);
2050
+ }
2051
+ function handleDragEnd(event) {
2052
+ const { active, over } = event;
2053
+ if (active.id !== over?.id && over) {
2054
+ const oldIndex = sortableItems.indexOf(active.id);
2055
+ const newIndex = sortableItems.indexOf(over.id);
2056
+ if (oldIndex !== -1 && newIndex !== -1) {
2057
+ setSortableItems(arrayMove(sortableItems, oldIndex, newIndex));
2058
+ }
2059
+ }
2060
+ setActiveId(null);
2061
+ }
2062
+ const onMainSplitSizeChange = (width) => layout === "left" ? setMainSplitSize(`${100 - Math.min(Number(width), 100)}`) : setMainSplitSize(width);
2063
+ const minScreenHeight = useMemo(() => {
2064
+ return tradingViewFullScreen ? 0 : symbolInfoBarHeight + ORDERBOOK_MAX_HEIGHT + DATA_LIST_INITIAL_HEIGHT + SPACE * 4;
2065
+ }, [tradingViewFullScreen, symbolInfoBarHeight]);
2066
+ const minScreenHeightSM = TOP_BAR_HEIGHT + BOTTOM_BAR_HEIGHT + symbolInfoBarHeight + TRADINGVIEW_MIN_HEIGHT + ORDERBOOK_MIN_HEIGHT + dataListMinHeight + SPACE * 4;
2067
+ const containerPaddingX = useMemo(() => max4XL ? 12 : 8, [max4XL]);
2068
+ const getPanel = (id) => panels.get(id)?.node ?? null;
2069
+ const horizontalMarketsView = getPanel(TRADING_PANEL_IDS.HORIZONTAL_MARKETS);
2070
+ const stickyHorizontalMarketsView = /* @__PURE__ */ jsx(
2071
+ Box,
2072
+ {
2073
+ className: cn(
2074
+ "oui-trading-markets-container",
2075
+ "oui-bg-base-10",
2076
+ "oui-sticky oui-z-30 oui-mb-[-8px] oui-py-2",
2077
+ !max4XL && "oui-mt-[-8px]"
2078
+ ),
2079
+ style: {
2080
+ bottom: 0,
2081
+ minWidth: (max4XL ? 1024 : 1440) - SCROLLBAR_WIDTH - containerPaddingX * 2
2082
+ },
2083
+ children: horizontalMarketsView
2084
+ }
2085
+ );
2086
+ const marketsWidget = getPanel(TRADING_PANEL_IDS.MARKETS);
2087
+ const marketsView = /* @__PURE__ */ jsx(
2088
+ Box,
2089
+ {
2090
+ intensity: 900,
2091
+ pt: 3,
2092
+ r: "2xl",
2093
+ height: "100%",
2094
+ width: marketsWidth,
2095
+ style: { minWidth: marketsWidth },
2096
+ className: "oui-trading-markets-container oui-transition-all oui-duration-150",
2097
+ onTransitionEnd: () => setAnimating(false),
2098
+ children: !animating && marketLayout === "left" && marketsWidget
2099
+ }
2100
+ );
2101
+ const symbolInfoBarView = /* @__PURE__ */ jsx(
2102
+ Box,
2103
+ {
2104
+ className: "oui-trading-symbolInfoBar-container",
2105
+ intensity: 900,
2106
+ r: "2xl",
2107
+ px: 3,
2108
+ width: "100%",
2109
+ style: { minHeight: symbolInfoBarHeight, height: symbolInfoBarHeight },
2110
+ children: getPanel(TRADING_PANEL_IDS.SYMBOL_INFO_BAR)
2111
+ }
2112
+ );
2113
+ const tradingviewWidget = getPanel(TRADING_PANEL_IDS.TRADING_VIEW);
2114
+ const tradingView = /* @__PURE__ */ jsx(
2115
+ Box,
2116
+ {
2117
+ width: "100%",
2118
+ height: "100%",
2119
+ intensity: 900,
2120
+ r: "2xl",
2121
+ style: { flex: 1, minWidth: TRADINGVIEW_MIN_WIDTH },
2122
+ className: "oui-trading-tradingview-container oui-overflow-hidden",
2123
+ children: tradingviewWidget
2124
+ }
2125
+ );
2126
+ const orderbookView = /* @__PURE__ */ jsx(
2127
+ Box,
2128
+ {
2129
+ r: "2xl",
2130
+ height: "100%",
2131
+ style: {
2132
+ minWidth: ORDERBOOK_MIN_WIDTH,
2133
+ maxWidth: horizontalDraggable ? ORDERBOOK_MAX_WIDTH : ORDERBOOK_MIN_WIDTH,
2134
+ width: orderBookSplitSize
2135
+ },
2136
+ className: "oui-trading-orderBook-container oui-overflow-hidden",
2137
+ children: getPanel(TRADING_PANEL_IDS.ORDERBOOK)
2138
+ }
2139
+ );
2140
+ const dataListView = /* @__PURE__ */ jsx(
2141
+ Box,
2142
+ {
2143
+ intensity: 900,
2144
+ r: "2xl",
2145
+ p: 2,
2146
+ style: {
2147
+ height: dataListSplitSize,
2148
+ minHeight: DATA_LIST_INITIAL_HEIGHT
2149
+ },
2150
+ className: "oui-trading-dataList-container oui-overflow-hidden",
2151
+ children: getPanel(TRADING_PANEL_IDS.DATA_LIST)
2152
+ }
2153
+ );
2154
+ const orderEntryView = /* @__PURE__ */ jsx(
2155
+ Flex,
2156
+ {
2157
+ className: "oui-trading-orderEntry-container",
2158
+ gapY: 2,
2159
+ direction: "column",
2160
+ height: "100%",
2161
+ style: {
2162
+ minWidth: ORDER_ENTRY_MIN_WIDTH,
2163
+ maxWidth: horizontalDraggable ? ORDER_ENTRY_MAX_WIDTH : ORDER_ENTRY_MIN_WIDTH,
2164
+ width: mainSplitSize
2165
+ },
2166
+ children: sortableItems.map((id) => /* @__PURE__ */ jsx(
2167
+ TradingSortablePanel,
2168
+ {
2169
+ id,
2170
+ showIndicator: showPositionIcon,
2171
+ className: cn(
2172
+ id === TRADING_PANEL_IDS.MARGIN && "oui-trading-riskRate-container",
2173
+ id === TRADING_PANEL_IDS.ASSETS && "oui-trading-assetsView-container oui-border oui-border-line-12",
2174
+ id === TRADING_PANEL_IDS.ORDER_ENTRY && "oui-trading-orderEntry-container",
2175
+ // Support legacy short-name keys
2176
+ id === "margin" && "oui-trading-riskRate-container",
2177
+ id === "assets" && "oui-trading-assetsView-container oui-border oui-border-line-12",
2178
+ id === "orderEntry" && "oui-trading-orderEntry-container"
2179
+ ),
2180
+ children: getPanel(id)
2181
+ },
2182
+ id
2183
+ ))
2184
+ }
2185
+ );
2186
+ const renderTradingView = () => {
2187
+ if (max4XL && layout === "right") {
2188
+ return /* @__PURE__ */ jsxs(
2189
+ Flex,
2190
+ {
2191
+ gap: 2,
2192
+ className: "oui-flex-1 oui-overflow-hidden",
2193
+ style: { minWidth: marketsWidth + TRADINGVIEW_MIN_WIDTH + SPACE },
2194
+ children: [
2195
+ marketLayout === "left" && marketsView,
2196
+ tradingView
2197
+ ]
2198
+ }
2199
+ );
2200
+ }
2201
+ return tradingView;
2202
+ };
2203
+ const tradingViewAndOrderbookView = /* @__PURE__ */ jsxs(
2204
+ TradingSplitLayout,
2205
+ {
2206
+ style: { flex: 1, minHeight: ORDERBOOK_MIN_HEIGHT },
2207
+ onSizeChange: setOrderbookSplitSize,
2208
+ disable: !horizontalDraggable,
2209
+ children: [
2210
+ renderTradingView(),
2211
+ orderbookView
2212
+ ]
2213
+ }
2214
+ );
2215
+ const renderTradingViewAndOrderbookView = () => {
2216
+ if (max4XL && layout === "left") {
2217
+ return /* @__PURE__ */ jsxs(
2218
+ Flex,
2219
+ {
2220
+ gapX: 2,
2221
+ style: { minHeight: ORDERBOOK_MIN_HEIGHT },
2222
+ height: "100%",
2223
+ children: [
2224
+ tradingViewAndOrderbookView,
2225
+ marketLayout === "left" && marketsView
2226
+ ]
2227
+ }
2228
+ );
2229
+ }
2230
+ return tradingViewAndOrderbookView;
2231
+ };
2232
+ const mainView = /* @__PURE__ */ jsxs(
2233
+ Flex,
2234
+ {
2235
+ direction: "column",
2236
+ className: "oui-flex-1 oui-overflow-hidden",
2237
+ gap: 2,
2238
+ style: {
2239
+ minWidth: max4XL ? marketsWidth + TRADINGVIEW_MIN_WIDTH + ORDERBOOK_MIN_WIDTH + SPACE * 2 : TRADINGVIEW_MIN_WIDTH + ORDERBOOK_MIN_WIDTH + SPACE
2240
+ },
2241
+ children: [
2242
+ symbolInfoBarView,
2243
+ /* @__PURE__ */ jsxs(
2244
+ TradingSplitLayout,
2245
+ {
2246
+ style: {
2247
+ maxHeight: `calc(100% - ${symbolInfoBarHeight}px - ${SPACE}px)`
2248
+ },
2249
+ className: "oui-w-full",
2250
+ mode: "vertical",
2251
+ onSizeChange: setDataListSplitSize,
2252
+ children: [
2253
+ renderTradingViewAndOrderbookView(),
2254
+ dataListView
2255
+ ]
2256
+ }
2257
+ )
2258
+ ]
2259
+ }
2260
+ );
2261
+ const dragOverlayContent = activeId ? /* @__PURE__ */ jsx(
2262
+ TradingSortablePanel,
2263
+ {
2264
+ id: activeId,
2265
+ showIndicator: showPositionIcon,
2266
+ dragOverlay: true,
2267
+ className: "oui-shadow-lg oui-shadow-base-9",
2268
+ children: getPanel(activeId)
2269
+ }
2270
+ ) : null;
2271
+ if (max2XL) {
2272
+ return /* @__PURE__ */ jsxs(
2273
+ DndContext,
2274
+ {
2275
+ sensors,
2276
+ collisionDetection: closestCenter,
2277
+ onDragStart: handleDragStart,
2278
+ onDragEnd: handleDragEnd,
2279
+ modifiers: [restrictToVerticalAxis],
2280
+ children: [
2281
+ /* @__PURE__ */ jsx(
2282
+ SortableContext,
2283
+ {
2284
+ items: sortableItems,
2285
+ strategy: verticalListSortingStrategy,
2286
+ children: /* @__PURE__ */ jsxs(Box, { height: "100%", children: [
2287
+ marketLayout === "top" && /* @__PURE__ */ jsx(
2288
+ Box,
2289
+ {
2290
+ className: cn(
2291
+ "oui-trading-markets-container oui-mt-2 oui-max-h-8 oui-px-3",
2292
+ className
2293
+ ),
2294
+ children: horizontalMarketsView
2295
+ }
2296
+ ),
2297
+ /* @__PURE__ */ jsxs(
2298
+ TradingSplitLayout,
2299
+ {
2300
+ ref: max2XLSplitRef,
2301
+ style: {
2302
+ minHeight: minScreenHeightSM,
2303
+ minWidth: 1024 - SCROLLBAR_WIDTH
2304
+ },
2305
+ className: cn(
2306
+ "oui-flex oui-flex-1",
2307
+ "oui-size-full oui-min-w-[1018px]",
2308
+ "oui-px-3 oui-py-2",
2309
+ className
2310
+ ),
2311
+ onSizeChange: setDataListSplitHeightSM,
2312
+ onDragging: onDataListSplitHeightDragging,
2313
+ mode: "vertical",
2314
+ children: [
2315
+ /* @__PURE__ */ jsxs(
2316
+ Flex,
2317
+ {
2318
+ gapX: 2,
2319
+ itemAlign: "stretch",
2320
+ className: cn(
2321
+ "oui-flex-1",
2322
+ layout === "left" && "oui-flex-row-reverse"
2323
+ ),
2324
+ style: {
2325
+ minHeight: Math.max(
2326
+ symbolInfoBarHeight + TRADINGVIEW_MIN_HEIGHT + ORDERBOOK_MIN_HEIGHT + SPACE * 2,
2327
+ orderEntryHeight
2328
+ ),
2329
+ maxHeight: symbolInfoBarHeight + tradindviewMaxHeight + ORDERBOOK_MAX_HEIGHT + SPACE * 2
2330
+ },
2331
+ children: [
2332
+ /* @__PURE__ */ jsxs(
2333
+ Flex,
2334
+ {
2335
+ height: "100%",
2336
+ className: "oui-w-[calc(100%_-_280px_-_12px)] oui-flex-1",
2337
+ direction: "column",
2338
+ gapY: 2,
2339
+ children: [
2340
+ symbolInfoBarView,
2341
+ /* @__PURE__ */ jsxs(
2342
+ Flex,
2343
+ {
2344
+ width: "100%",
2345
+ height: "100%",
2346
+ gapX: 2,
2347
+ itemAlign: "stretch",
2348
+ style: {
2349
+ minHeight: TRADINGVIEW_MIN_HEIGHT + ORDERBOOK_MIN_HEIGHT + SPACE,
2350
+ maxHeight: tradindviewMaxHeight + ORDERBOOK_MAX_HEIGHT + SPACE
2351
+ },
2352
+ className: cn(
2353
+ "oui-flex-1",
2354
+ layout === "left" && "oui-flex-row-reverse"
2355
+ ),
2356
+ children: [
2357
+ marketLayout === "left" && /* @__PURE__ */ jsx(
2358
+ Box,
2359
+ {
2360
+ intensity: 900,
2361
+ pt: 3,
2362
+ r: "2xl",
2363
+ width: marketsWidth,
2364
+ style: {
2365
+ minHeight: TRADINGVIEW_MIN_HEIGHT + ORDERBOOK_MIN_HEIGHT + SPACE,
2366
+ maxHeight: tradindviewMaxHeight + ORDERBOOK_MAX_HEIGHT + SPACE
2367
+ },
2368
+ children: marketsWidget
2369
+ }
2370
+ ),
2371
+ /* @__PURE__ */ jsxs(
2372
+ TradingSplitLayout,
2373
+ {
2374
+ ref: tradingviewAndOrderbookSplitRef,
2375
+ mode: "vertical",
2376
+ style: { width: `calc(100% - ${marketsWidth}px)` },
2377
+ className: "oui-flex-1",
2378
+ onSizeChange: setOrderbookSplitHeightSM,
2379
+ onDragging: onTradingviewAndOrderbookDragging,
2380
+ children: [
2381
+ /* @__PURE__ */ jsx(
2382
+ Box,
2383
+ {
2384
+ width: "100%",
2385
+ intensity: 900,
2386
+ r: "2xl",
2387
+ style: {
2388
+ minHeight: TRADINGVIEW_MIN_HEIGHT,
2389
+ maxHeight: tradindviewMaxHeight,
2390
+ height: 1200
2391
+ },
2392
+ children: tradingviewWidget
2393
+ }
2394
+ ),
2395
+ /* @__PURE__ */ jsx(
2396
+ Box,
2397
+ {
2398
+ r: "2xl",
2399
+ height: "100%",
2400
+ width: "100%",
2401
+ style: {
2402
+ minHeight: ORDERBOOK_MIN_HEIGHT,
2403
+ maxHeight: ORDERBOOK_MAX_HEIGHT,
2404
+ height: orderBookSplitHeightSM
2405
+ },
2406
+ className: "oui-flex-1",
2407
+ children: getPanel(TRADING_PANEL_IDS.ORDERBOOK)
2408
+ }
2409
+ )
2410
+ ]
2411
+ }
2412
+ )
2413
+ ]
2414
+ }
2415
+ )
2416
+ ]
2417
+ }
2418
+ ),
2419
+ /* @__PURE__ */ jsxs(
2420
+ Flex,
2421
+ {
2422
+ ref: orderEntryViewRef,
2423
+ id: "orderEntryView",
2424
+ gapY: 3,
2425
+ direction: "column",
2426
+ className: "oui-relative",
2427
+ style: {
2428
+ width: ORDER_ENTRY_MIN_WIDTH,
2429
+ height: "max-content"
2430
+ },
2431
+ children: [
2432
+ /* @__PURE__ */ jsx(
2433
+ Flex,
2434
+ {
2435
+ gapY: 2,
2436
+ direction: "column",
2437
+ height: "100%",
2438
+ style: {
2439
+ minWidth: ORDER_ENTRY_MIN_WIDTH,
2440
+ maxWidth: horizontalDraggable ? ORDER_ENTRY_MAX_WIDTH : ORDER_ENTRY_MIN_WIDTH,
2441
+ width: mainSplitSize
2442
+ },
2443
+ children: sortableItems.map((id) => /* @__PURE__ */ jsx(
2444
+ TradingSortablePanel,
2445
+ {
2446
+ id,
2447
+ showIndicator: showPositionIcon,
2448
+ className: cn(
2449
+ id === TRADING_PANEL_IDS.MARGIN && "oui-trading-riskRate-container",
2450
+ id === TRADING_PANEL_IDS.ASSETS && "oui-trading-assetsView-container oui-border oui-border-line-12",
2451
+ id === TRADING_PANEL_IDS.ORDER_ENTRY && "oui-trading-orderEntry-container",
2452
+ id === "margin" && "oui-trading-riskRate-container",
2453
+ id === "assets" && "oui-trading-assetsView-container oui-border oui-border-line-12",
2454
+ id === "orderEntry" && "oui-trading-orderEntry-container"
2455
+ ),
2456
+ children: getPanel(id)
2457
+ },
2458
+ id
2459
+ ))
2460
+ }
2461
+ ),
2462
+ /* @__PURE__ */ jsx(Box, { height: extraHeight })
2463
+ ]
2464
+ }
2465
+ )
2466
+ ]
2467
+ }
2468
+ ),
2469
+ /* @__PURE__ */ jsx(
2470
+ Box,
2471
+ {
2472
+ intensity: 900,
2473
+ r: "2xl",
2474
+ p: 2,
2475
+ style: {
2476
+ height: dataListSplitHeightSM,
2477
+ minHeight: Math.max(dataListMinHeight, 0),
2478
+ maxHeight: DATA_LIST_MAX_HEIGHT
2479
+ },
2480
+ className: "oui-overflow-hidden",
2481
+ children: getPanel(TRADING_PANEL_IDS.DATA_LIST)
2482
+ }
2483
+ ),
2484
+ marketLayout === "bottom" && stickyHorizontalMarketsView
2485
+ ]
2486
+ }
2487
+ )
2488
+ ] })
2489
+ }
2490
+ ),
2491
+ /* @__PURE__ */ jsx(DragOverlay, { dropAnimation: dropAnimationConfig, children: dragOverlayContent })
2492
+ ]
2493
+ }
2494
+ );
2495
+ }
2496
+ return /* @__PURE__ */ jsxs(
2497
+ DndContext,
2498
+ {
2499
+ sensors,
2500
+ collisionDetection: closestCenter,
2501
+ onDragStart: handleDragStart,
2502
+ onDragEnd: handleDragEnd,
2503
+ modifiers: [restrictToVerticalAxis],
2504
+ children: [
2505
+ /* @__PURE__ */ jsx(
2506
+ SortableContext,
2507
+ {
2508
+ items: sortableItems,
2509
+ strategy: verticalListSortingStrategy,
2510
+ children: /* @__PURE__ */ jsxs(
2511
+ Flex,
2512
+ {
2513
+ style: {
2514
+ minHeight: minScreenHeight,
2515
+ minWidth: 1440 - SCROLLBAR_WIDTH
2516
+ },
2517
+ className: cn(
2518
+ className,
2519
+ "oui-justify-start",
2520
+ tradingViewFullScreen && "oui-relative oui-h-[calc(100vh-80px)] oui-w-screen oui-overflow-hidden !oui-p-0"
2521
+ ),
2522
+ width: "100%",
2523
+ p: 2,
2524
+ gap: 2,
2525
+ itemAlign: "stretch",
2526
+ direction: "column",
2527
+ children: [
2528
+ marketLayout === "top" && horizontalMarketsView,
2529
+ /* @__PURE__ */ jsxs(
2530
+ Flex,
2531
+ {
2532
+ className: cn(
2533
+ "oui-flex-1 oui-overflow-hidden",
2534
+ layout === "left" && "oui-flex-row-reverse"
2535
+ ),
2536
+ gap: 2,
2537
+ children: [
2538
+ !max4XL && marketLayout === "left" && marketsView,
2539
+ /* @__PURE__ */ jsxs(
2540
+ TradingSplitLayout,
2541
+ {
2542
+ className: "oui-flex oui-flex-1 oui-overflow-hidden",
2543
+ onSizeChange: onMainSplitSizeChange,
2544
+ disable: !horizontalDraggable,
2545
+ children: [
2546
+ layout === "left" && orderEntryView,
2547
+ mainView,
2548
+ layout === "right" && orderEntryView
2549
+ ]
2550
+ }
2551
+ )
2552
+ ]
2553
+ }
2554
+ ),
2555
+ marketLayout === "bottom" && stickyHorizontalMarketsView
2556
+ ]
2557
+ }
2558
+ )
2559
+ }
2560
+ ),
2561
+ /* @__PURE__ */ jsx(DragOverlay, { dropAnimation: dropAnimationConfig, children: dragOverlayContent })
2562
+ ]
2563
+ }
2564
+ );
2565
+ }
2566
+
2567
+ // src/splitTradingStrategy.ts
2568
+ var splitTradingStrategy = {
2569
+ id: "split-trading",
2570
+ displayName: "Split Trading Layout",
2571
+ /** No layout model needed — state is managed internally by SplitTradingLayout. */
2572
+ defaultLayout: () => ({}),
2573
+ serialize: () => "{}",
2574
+ deserialize: () => ({}),
2575
+ /** SplitTradingLayout implements LayoutRendererProps<Record<string, unknown>>. */
2576
+ Renderer: SplitTradingLayout
2577
+ };
2578
+ var PLUGIN_ID = "orderly-layout-split";
2579
+ var PLUGIN_NAME = "Split Layout";
2580
+ var PLUGIN_VERSION = "1.0.0";
2581
+ function registerLayoutSplitPlugin(options = {}) {
2582
+ return (SDK) => {
2583
+ SDK.registerPlugin({
2584
+ id: PLUGIN_ID,
2585
+ name: PLUGIN_NAME,
2586
+ version: PLUGIN_VERSION,
2587
+ orderlyVersion: ">=1.0.0",
2588
+ interceptors: [
2589
+ createInterceptor("Trading.Layout.Desktop", (Original, props) => /* @__PURE__ */ jsx(
2590
+ Original,
2591
+ {
2592
+ ...props,
2593
+ layoutStrategy: splitTradingStrategy,
2594
+ getInitialLayout: () => ({}),
2595
+ disableLayoutPersistence: true
2596
+ }
2597
+ )),
2598
+ createInterceptor(
2599
+ "Trading.SymbolInfoBar.Desktop",
2600
+ (Original, props) => /* @__PURE__ */ jsx(
2601
+ Original,
2602
+ {
2603
+ ...props,
2604
+ trailing: /* @__PURE__ */ jsxs(Fragment, { children: [
2605
+ props.trailing,
2606
+ /* @__PURE__ */ jsx(SymbolBarLayoutSwitcher, {})
2607
+ ] })
2608
+ }
2609
+ )
2610
+ )
2611
+ ]
2612
+ });
2613
+ };
2614
+ }
2615
+ var SplitTradingDesktopContext = React.createContext(null);
2616
+ SplitTradingDesktopContext.displayName = "SplitTradingDesktopContext";
2617
+ function useSplitTradingDesktopContext() {
2618
+ return React.useContext(SplitTradingDesktopContext);
2619
+ }
2620
+ function useDropAnimationConfig() {
2621
+ return useMemo(
2622
+ () => ({
2623
+ keyframes({
2624
+ transform
2625
+ }) {
2626
+ return [
2627
+ {
2628
+ transform: CSS.Transform.toString({
2629
+ ...transform.initial,
2630
+ scaleX: 1.05,
2631
+ scaleY: 1.05
2632
+ })
2633
+ },
2634
+ {
2635
+ transform: CSS.Transform.toString({
2636
+ ...transform.final,
2637
+ scaleX: 1,
2638
+ scaleY: 1
2639
+ })
2640
+ }
2641
+ ];
2642
+ },
2643
+ sideEffects: ({
2644
+ active,
2645
+ dragOverlay
2646
+ }) => {
2647
+ active.node.style.opacity = "0";
2648
+ const inner = dragOverlay.node.querySelector(".inner-content");
2649
+ if (inner) inner.classList.add("oui-animate-shake");
2650
+ return () => {
2651
+ active.node.style.opacity = "";
2652
+ };
2653
+ }
2654
+ }),
2655
+ []
2656
+ );
2657
+ }
2658
+ function SplitTradingDesktopChrome(props) {
2659
+ const {
2660
+ children,
2661
+ max2XL,
2662
+ tradingViewFullScreen,
2663
+ sortableItems,
2664
+ setSortableItems,
2665
+ className
2666
+ } = props;
2667
+ const [activeId, setActiveId] = useState(null);
2668
+ const dropAnimationConfig2 = useDropAnimationConfig();
2669
+ const sensors = useSensors(
2670
+ useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
2671
+ useSensor(KeyboardSensor, {
2672
+ coordinateGetter: sortableKeyboardCoordinates
2673
+ })
2674
+ );
2675
+ const handleDragStart = (event) => {
2676
+ setActiveId(event.active.id);
2677
+ };
2678
+ const handleDragEnd = (event) => {
2679
+ const { active, over } = event;
2680
+ if (active.id !== over?.id && over) {
2681
+ const oldIndex = sortableItems?.indexOf(active.id) ?? -1;
2682
+ const newIndex = sortableItems?.indexOf(over.id) ?? -1;
2683
+ if (oldIndex !== -1 && newIndex !== -1) {
2684
+ setSortableItems?.(
2685
+ arrayMove(sortableItems ?? [], oldIndex, newIndex)
2686
+ );
2687
+ }
2688
+ }
2689
+ setActiveId(null);
2690
+ };
2691
+ return /* @__PURE__ */ jsx(SplitTradingDesktopContext.Provider, { value: props, children: /* @__PURE__ */ jsxs(
2692
+ DndContext,
2693
+ {
2694
+ sensors,
2695
+ collisionDetection: closestCenter,
2696
+ onDragStart: handleDragStart,
2697
+ onDragEnd: handleDragEnd,
2698
+ modifiers: [restrictToVerticalAxis],
2699
+ children: [
2700
+ /* @__PURE__ */ jsx(
2701
+ SortableContext,
2702
+ {
2703
+ items: sortableItems ?? [],
2704
+ strategy: verticalListSortingStrategy,
2705
+ children: max2XL ? /* @__PURE__ */ jsx(Box, { height: "100%", className, children }) : /* @__PURE__ */ jsx(
2706
+ Flex,
2707
+ {
2708
+ style: {
2709
+ // minHeight: minScreenHeight,
2710
+ // minWidth: 1440 - scrollBarWidth,
2711
+ },
2712
+ className: cn(
2713
+ className,
2714
+ "oui-flex-1 oui-justify-start oui-overflow-hidden",
2715
+ tradingViewFullScreen && "oui-relative oui-h-[calc(100vh-80px)] oui-w-screen oui-overflow-hidden !oui-p-0"
2716
+ ),
2717
+ width: "100%",
2718
+ p: 2,
2719
+ gap: 2,
2720
+ itemAlign: "stretch",
2721
+ direction: "column",
2722
+ children
2723
+ }
2724
+ )
2725
+ }
2726
+ ),
2727
+ /* @__PURE__ */ jsx(DragOverlay, { dropAnimation: dropAnimationConfig2, children: activeId ? /* @__PURE__ */ jsxs("div", { className: "oui-pointer-events-none oui-opacity-80", children: [
2728
+ "id: ",
2729
+ activeId
2730
+ ] }) : null })
2731
+ ]
2732
+ }
2733
+ ) });
2734
+ }
2735
+ var SplitPresetContext = createContext(null);
2736
+ function useSplitPresetContext() {
2737
+ return useContext(SplitPresetContext);
2738
+ }
2739
+ var ExpandIcon = (props) => /* @__PURE__ */ jsx(
2740
+ "svg",
2741
+ {
2742
+ width: "16",
2743
+ height: "16",
2744
+ viewBox: "0 0 16 16",
2745
+ fill: "currentColor",
2746
+ xmlns: "http://www.w3.org/2000/svg",
2747
+ ...props,
2748
+ children: /* @__PURE__ */ jsx("path", { d: "M6.326 8.826a.84.84 0 0 0-.6.234L2.16 12.627v-2.135H.492v4.167c0 .46.373.833.834.833h4.166v-1.667H3.357l3.567-3.567a.857.857 0 0 0 0-1.198.84.84 0 0 0-.598-.234M10.502.492V2.16h2.135L9.07 5.726a.857.857 0 0 0 0 1.199.86.86 0 0 0 1.197 0l3.568-3.568v2.135h1.667V1.326a.834.834 0 0 0-.834-.834z" })
2749
+ }
2750
+ );
2751
+ var CollapseIcon = (props) => /* @__PURE__ */ jsx(
2752
+ "svg",
2753
+ {
2754
+ width: "16",
2755
+ height: "16",
2756
+ viewBox: "0 0 16 16",
2757
+ fill: "currentColor",
2758
+ xmlns: "http://www.w3.org/2000/svg",
2759
+ ...props,
2760
+ children: /* @__PURE__ */ jsx("path", { d: "M14.668.492a.85.85 0 0 0-.599.234l-3.567 3.568V2.159H8.835v4.167c0 .46.373.833.833.833h4.167V5.492H11.7l3.569-3.567a.86.86 0 0 0 0-1.199.85.85 0 0 0-.6-.234m-12.5 8.334v1.666h2.135L.736 14.06a.86.86 0 0 0 0 1.198.86.86 0 0 0 1.198 0l3.568-3.567v2.134h1.666V9.66a.834.834 0 0 0-.833-.833z" })
2761
+ }
2762
+ );
2763
+ var CollapsiblePanel = ({
2764
+ title,
2765
+ collapsible,
2766
+ collapsed,
2767
+ onToggle,
2768
+ minSize,
2769
+ maxSize,
2770
+ children,
2771
+ className,
2772
+ style
2773
+ }) => {
2774
+ const computedStyle = Object.assign(
2775
+ {},
2776
+ style,
2777
+ typeof collapsible !== "undefined" ? collapsed ? { width: minSize } : { width: maxSize } : {}
2778
+ );
2779
+ const bodyClassName = useMemo(() => {
2780
+ return typeof !!title ? "oui-h-[calc(100%_-_40px)]" : "oui-h-full";
2781
+ }, [title]);
2782
+ const renderCollapsibleHeader = () => {
2783
+ return /* @__PURE__ */ jsxs(
2784
+ Flex,
2785
+ {
2786
+ className: cn(
2787
+ "oui-text-base-contrast-36"
2788
+ // collapsed ? "oui-absolute oui-end-[-20px] oui-z-50" : "oui-relative",
2789
+ ),
2790
+ justify: collapsed ? "center" : "between",
2791
+ width: "100%",
2792
+ px: 3,
2793
+ pt: 3,
2794
+ children: [
2795
+ !collapsed && title && /* @__PURE__ */ jsx(Text, { size: "base", intensity: 80, children: title }),
2796
+ /* @__PURE__ */ jsx(
2797
+ "button",
2798
+ {
2799
+ onClick: onToggle,
2800
+ className: cn("oui-cursor-pointer hover:oui-text-base-contrast-80"),
2801
+ children: collapsed ? /* @__PURE__ */ jsx(ExpandIcon, { className: "oui-text-base-contrast-36" }) : /* @__PURE__ */ jsx(CollapseIcon, { className: "oui-text-base-contrast-36" })
2802
+ }
2803
+ )
2804
+ ]
2805
+ }
2806
+ );
2807
+ };
2808
+ return /* @__PURE__ */ jsxs(
2809
+ "div",
2810
+ {
2811
+ className: cn(
2812
+ "oui-flex oui-flex-col oui-gap-y-5 oui-overflow-hidden oui-rounded-2xl oui-bg-base-9 oui-w-full oui-h-full",
2813
+ className
2814
+ ),
2815
+ style: computedStyle,
2816
+ children: [
2817
+ renderCollapsibleHeader(),
2818
+ /* @__PURE__ */ jsx("div", { className: cn("oui-collapsible-content", bodyClassName), children: React.cloneElement(children, {
2819
+ collapsed
2820
+ // panelSize: "small",
2821
+ }) })
2822
+ ]
2823
+ }
2824
+ );
2825
+ };
2826
+ var DEFAULT_SHOW_INDICATOR = true;
2827
+ function IndicatorIcon2(props) {
2828
+ return /* @__PURE__ */ jsxs(
2829
+ "svg",
2830
+ {
2831
+ width: "10",
2832
+ height: "16",
2833
+ viewBox: "0 0 10 16",
2834
+ fill: "currentColor",
2835
+ xmlns: "http://www.w3.org/2000/svg",
2836
+ ...props,
2837
+ children: [
2838
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "6", height: "2", rx: "1" }),
2839
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "7", width: "6", height: "2", rx: "1" }),
2840
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "12", width: "6", height: "2", rx: "1" })
2841
+ ]
2842
+ }
2843
+ );
2844
+ }
2845
+ function SortableSortChild({
2846
+ id,
2847
+ child,
2848
+ showIndicator,
2849
+ path,
2850
+ rootNode,
2851
+ index
2852
+ }) {
2853
+ const { ref, handleRef, isDragging } = useSortable$1({
2854
+ id,
2855
+ index
2856
+ });
2857
+ const showHandle = showIndicator && child.type === "panel";
2858
+ return /* @__PURE__ */ jsxs(
2859
+ "div",
2860
+ {
2861
+ ref,
2862
+ className: cn("oui-relative", isDragging && "oui-opacity-50"),
2863
+ children: [
2864
+ showHandle && /* @__PURE__ */ jsx(
2865
+ "button",
2866
+ {
2867
+ className: "oui-absolute oui-right-0 oui-top-4 oui-cursor-move oui-py-1",
2868
+ style: { touchAction: "none" },
2869
+ ref: handleRef,
2870
+ children: /* @__PURE__ */ jsx(
2871
+ IndicatorIcon2,
2872
+ {
2873
+ className: cn(
2874
+ "oui-text-base-contrast-20 hover:oui-text-base-contrast-80"
2875
+ )
2876
+ }
2877
+ )
2878
+ }
2879
+ ),
2880
+ /* @__PURE__ */ jsx(SplitNodeRenderer, { node: child, path, rootNode })
2881
+ ]
2882
+ }
2883
+ );
2884
+ }
2885
+ function SortNodeRenderer({
2886
+ node,
2887
+ path,
2888
+ rootNode,
2889
+ classNames
2890
+ }) {
2891
+ const { onLayoutChange, layout, breakpoint } = useSplitLayoutConfig();
2892
+ const { orientation, children } = node;
2893
+ const ctx = useSplitPresetContext();
2894
+ const showIndicator = ctx?.showIndicator ?? DEFAULT_SHOW_INDICATOR;
2895
+ const items = children.map(
2896
+ (child, index) => getSortableIdForChild(child, path, index)
2897
+ );
2898
+ const isVertical = orientation === "vertical";
2899
+ const handleDragEnd = useCallback(
2900
+ (event) => {
2901
+ const anyEvent = event;
2902
+ if (!anyEvent.operation || anyEvent.canceled) return;
2903
+ const { source } = anyEvent.operation;
2904
+ if (!isSortable(source)) return;
2905
+ const { initialIndex, index } = source;
2906
+ if (initialIndex === index) return;
2907
+ const newOrder = [...children];
2908
+ const [removed] = newOrder.splice(initialIndex, 1);
2909
+ newOrder.splice(index, 0, removed);
2910
+ const updatedRoot = updateOrderAtPath(rootNode, path, newOrder);
2911
+ onLayoutChange({
2912
+ ...layout,
2913
+ layouts: {
2914
+ ...layout.layouts,
2915
+ [breakpoint]: updatedRoot
2916
+ }
2917
+ });
2918
+ },
2919
+ [children, path, rootNode, breakpoint, layout, onLayoutChange]
2920
+ );
2921
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
2922
+ DragDropProvider,
2923
+ {
2924
+ onDragEnd: handleDragEnd,
2925
+ modifiers: (defaults) => [...defaults, RestrictToVerticalAxis],
2926
+ children: /* @__PURE__ */ jsx(
2927
+ "div",
2928
+ {
2929
+ className: cn(
2930
+ isVertical ? "oui-flex oui-w-full oui-flex-col oui-gap-2" : "oui-flex oui-w-full oui-flex-row oui-gap-2",
2931
+ node.className,
2932
+ classNames?.panel
2933
+ ),
2934
+ style: node.style,
2935
+ children: children.map((child, index) => /* @__PURE__ */ jsx(
2936
+ SortableSortChild,
2937
+ {
2938
+ id: items[index],
2939
+ child,
2940
+ showIndicator,
2941
+ path: [...path, index],
2942
+ rootNode,
2943
+ index
2944
+ },
2945
+ items[index]
2946
+ ))
2947
+ }
2948
+ )
2949
+ }
2950
+ ) });
2951
+ }
2952
+ function SplitNodeRenderer({
2953
+ node,
2954
+ path,
2955
+ rootNode
2956
+ }) {
2957
+ const {
2958
+ panels,
2959
+ onSizeChange,
2960
+ onSizePersist,
2961
+ classNames,
2962
+ gap,
2963
+ isPanelCollapsed,
2964
+ togglePanelCollapse,
2965
+ isPanelCollapsible
2966
+ } = useSplitLayoutConfig();
2967
+ if (node.type === "panel") {
2968
+ const panelWrapper = panels.get(node.id);
2969
+ const panel = panelWrapper?.node;
2970
+ if (!panel) {
2971
+ return /* @__PURE__ */ jsx(
2972
+ "div",
2973
+ {
2974
+ className: cn(
2975
+ "oui-text-base-contrast-40 oui-rounded-2xl oui-bg-base-9 oui-p-3 oui-text-xs",
2976
+ node.size !== "fixed" && "oui-size-full",
2977
+ classNames?.panel,
2978
+ node.className
2979
+ ),
2980
+ style: node.style,
2981
+ "data-panel-id": node.id,
2982
+ children: node.id ? `Panel not found: ${node.id}` : "Panel not found"
2983
+ }
2984
+ );
2985
+ }
2986
+ const title = node.title ?? panelWrapper?.props?.title;
2987
+ if (typeof node.collapsible !== "undefined") {
2988
+ return /* @__PURE__ */ jsx(
2989
+ CollapsiblePanel,
2990
+ {
2991
+ title,
2992
+ collapsible: node.collapsible || isPanelCollapsible(node.id),
2993
+ collapsed: isPanelCollapsed(node.id),
2994
+ onToggle: () => togglePanelCollapse(node.id),
2995
+ minSize: node.minSize,
2996
+ maxSize: node.maxSize,
2997
+ className: cn(
2998
+ node.size !== "fixed" && "oui-size-full",
2999
+ classNames?.panel,
3000
+ node.className
3001
+ ),
3002
+ style: node.style,
3003
+ "data-panel-id": node.id,
3004
+ children: panel
3005
+ }
3006
+ );
3007
+ }
3008
+ return /* @__PURE__ */ jsx(
3009
+ "div",
3010
+ {
3011
+ className: cn(
3012
+ "oui-overflow-hidden oui-rounded-2xl oui-bg-base-9",
3013
+ node.size !== "fixed" && "oui-size-full",
3014
+ classNames?.panel,
3015
+ node.className
3016
+ ),
3017
+ style: node.style,
3018
+ "data-panel-id": node.id,
3019
+ children: panel
3020
+ }
3021
+ );
3022
+ }
3023
+ if (node.type === "sort") {
3024
+ return /* @__PURE__ */ jsx(
3025
+ SortNodeRenderer,
3026
+ {
3027
+ node,
3028
+ path,
3029
+ rootNode,
3030
+ classNames
3031
+ }
3032
+ );
3033
+ }
3034
+ const { orientation, children } = node;
3035
+ const sizes = children.map((child) => child.size ?? "auto");
3036
+ const panelConstraints = children.map((child) => ({
3037
+ // Nested split/sort nodes need minSize to prevent collapse (lib default 0% causes inner area to collapse)
3038
+ minSize: child.minSize ?? (child.type === "split" || child.type === "sort" ? "10%" : void 0),
3039
+ maxSize: child.maxSize,
3040
+ disabled: child.disabled
3041
+ }));
3042
+ return /* @__PURE__ */ jsx(
3043
+ SplitLayout,
3044
+ {
3045
+ orientation,
3046
+ sizes,
3047
+ panelConstraints,
3048
+ onSizeChange: (sizesAsStrings) => {
3049
+ onSizeChange(path, sizesAsStrings);
3050
+ onSizePersist?.(path, sizesAsStrings);
3051
+ },
3052
+ classNames,
3053
+ gap,
3054
+ className: node.className,
3055
+ style: node.style,
3056
+ children: children.map((child, index) => /* @__PURE__ */ jsx(
3057
+ SplitNodeRenderer,
3058
+ {
3059
+ node: child,
3060
+ path: [...path, index],
3061
+ rootNode
3062
+ },
3063
+ `child-${index}`
3064
+ ))
3065
+ }
3066
+ );
3067
+ }
3068
+
3069
+ // src/utils/splitRendererUtils.ts
3070
+ function getNodeAtPath(node, path) {
3071
+ if (path.length === 0) return node;
3072
+ if (node.type === "panel") return null;
3073
+ const [childIndex, ...restPath] = path;
3074
+ if (childIndex >= node.children.length) return null;
3075
+ return getNodeAtPath(node.children[childIndex], restPath);
3076
+ }
3077
+ function getSizesFromChildren(children) {
3078
+ return children.map((child) => child.size ?? "auto");
3079
+ }
3080
+ function sizesAreEqual(current, next) {
3081
+ if (!current || current.length !== next.length) return false;
3082
+ const toNum = (value) => Math.round(parseFloat(String(value).replace(/%/g, "")) || 0);
3083
+ return current.every((c, index) => toNum(c) === toNum(next[index]));
3084
+ }
3085
+ function updateDefaultCollapsedAtPath(node, panelId, defaultCollapsed) {
3086
+ if (node.type === "panel" && node.id === panelId) {
3087
+ return { ...node, defaultCollapsed };
3088
+ }
3089
+ if (node.type === "split" || node.type === "sort") {
3090
+ return {
3091
+ ...node,
3092
+ children: node.children.map(
3093
+ (child) => updateDefaultCollapsedAtPath(child, panelId, defaultCollapsed)
3094
+ )
3095
+ };
3096
+ }
3097
+ return node;
3098
+ }
3099
+ function updateSizeAtPath(node, path, newSizes) {
3100
+ if (node.type === "panel") {
3101
+ const size = newSizes[0];
3102
+ return size !== void 0 ? { ...node, size } : node;
3103
+ }
3104
+ if (node.type === "sort") {
3105
+ if (path.length === 0) return node;
3106
+ const [childIndex2, ...restPath2] = path;
3107
+ const updatedChildren = [...node.children];
3108
+ if (childIndex2 < updatedChildren.length) {
3109
+ updatedChildren[childIndex2] = updateSizeAtPath(
3110
+ updatedChildren[childIndex2],
3111
+ restPath2,
3112
+ newSizes
3113
+ );
3114
+ }
3115
+ return { ...node, children: updatedChildren };
3116
+ }
3117
+ const updatedNode = {
3118
+ ...node,
3119
+ children: [...node.children]
3120
+ };
3121
+ if (path.length === 0) {
3122
+ updatedNode.children = node.children.map((child, index) => ({
3123
+ ...child,
3124
+ size: newSizes[index] ?? child.size ?? "auto"
3125
+ }));
3126
+ return updatedNode;
3127
+ }
3128
+ const [childIndex, ...restPath] = path;
3129
+ if (childIndex < updatedNode.children.length) {
3130
+ updatedNode.children[childIndex] = updateSizeAtPath(
3131
+ updatedNode.children[childIndex],
3132
+ restPath,
3133
+ newSizes
3134
+ );
3135
+ }
3136
+ return updatedNode;
3137
+ }
3138
+ function getCollapsiblePanels(node) {
3139
+ const collapsible = /* @__PURE__ */ new Map();
3140
+ const traverse = (n) => {
3141
+ if (n.type === "panel" && n.id) {
3142
+ collapsible.set(n.id, n.collapsible ?? false);
3143
+ }
3144
+ if (n.type === "split" || n.type === "sort") {
3145
+ for (const child of n.children ?? []) {
3146
+ traverse(child);
3147
+ }
3148
+ }
3149
+ };
3150
+ traverse(node);
3151
+ return collapsible;
3152
+ }
3153
+ function createUpdatedLayout(rootNode, layout, breakpoint, path, sizes) {
3154
+ const updatedRoot = updateSizeAtPath(rootNode, path, sizes);
3155
+ return {
3156
+ ...layout,
3157
+ layouts: {
3158
+ ...layout.layouts,
3159
+ [breakpoint]: updatedRoot
3160
+ }
3161
+ };
3162
+ }
3163
+ function SplitRenderer(props) {
3164
+ const { layout, panels, onLayoutChange, onLayoutPersist, className, style } = props;
3165
+ const ctx = useSplitPresetContext();
3166
+ const containerRef = useRef(null);
3167
+ const presetName = ctx?.presets?.find(
3168
+ (p) => p.id === ctx?.selectedPresetId
3169
+ )?.name;
3170
+ const breakpoint = useViewportBreakpoint({
3171
+ fallbackWidth: typeof window !== "undefined" ? window.innerWidth : 1440
3172
+ });
3173
+ const rootNode = layout.layouts[breakpoint];
3174
+ const computeUpdatedLayout = useCallback(
3175
+ (path, sizes) => {
3176
+ const nodeAtPath = getNodeAtPath(rootNode, path);
3177
+ const currentSizes = nodeAtPath?.type === "split" ? getSizesFromChildren(nodeAtPath.children) : void 0;
3178
+ if (sizesAreEqual(currentSizes, sizes)) {
3179
+ return null;
3180
+ }
3181
+ return createUpdatedLayout(rootNode, layout, breakpoint, path, sizes);
3182
+ },
3183
+ [layout, breakpoint, rootNode]
3184
+ );
3185
+ const handleSizeChange = useCallback(
3186
+ (path, sizes) => {
3187
+ const updatedLayout = computeUpdatedLayout(path, sizes);
3188
+ if (updatedLayout) {
3189
+ onLayoutChange(updatedLayout);
3190
+ }
3191
+ },
3192
+ [computeUpdatedLayout, onLayoutChange]
3193
+ );
3194
+ const handleSizePersist = useCallback(
3195
+ (path, sizes) => {
3196
+ if (!onLayoutPersist) return;
3197
+ const updatedLayout = computeUpdatedLayout(path, sizes);
3198
+ if (updatedLayout) {
3199
+ onLayoutPersist(updatedLayout);
3200
+ }
3201
+ },
3202
+ [computeUpdatedLayout, onLayoutPersist]
3203
+ );
3204
+ const collapsiblePanels = useMemo(
3205
+ () => getCollapsiblePanels(rootNode),
3206
+ [rootNode]
3207
+ );
3208
+ const collapsedPanels = useMemo(() => {
3209
+ const collapsed = /* @__PURE__ */ new Set();
3210
+ const traverse = (node) => {
3211
+ if (node.type === "panel" && node.id && node.defaultCollapsed) {
3212
+ collapsed.add(node.id);
3213
+ }
3214
+ if (node.type === "split" || node.type === "sort") {
3215
+ node.children?.forEach(traverse);
3216
+ }
3217
+ };
3218
+ traverse(rootNode);
3219
+ return collapsed;
3220
+ }, [rootNode]);
3221
+ const computeUpdatedLayoutForCollapse = useCallback(
3222
+ (panelId, collapsed) => {
3223
+ const updatedLayouts = {};
3224
+ for (const bp of BREAKPOINT_KEYS) {
3225
+ if (layout.layouts[bp]) {
3226
+ updatedLayouts[bp] = updateDefaultCollapsedAtPath(
3227
+ layout.layouts[bp],
3228
+ panelId,
3229
+ collapsed
3230
+ );
3231
+ }
3232
+ }
3233
+ return { ...layout, layouts: updatedLayouts };
3234
+ },
3235
+ [layout]
3236
+ );
3237
+ const isPanelCollapsible = useCallback(
3238
+ (panelId) => collapsiblePanels.get(panelId) ?? false,
3239
+ [collapsiblePanels]
3240
+ );
3241
+ const togglePanelCollapse = useCallback(
3242
+ (panelId) => {
3243
+ const isCurrentlyCollapsed = collapsedPanels.has(panelId);
3244
+ const updatedLayout = computeUpdatedLayoutForCollapse(
3245
+ panelId,
3246
+ !isCurrentlyCollapsed
3247
+ );
3248
+ onLayoutChange(updatedLayout);
3249
+ onLayoutPersist?.(updatedLayout);
3250
+ },
3251
+ [
3252
+ collapsedPanels,
3253
+ computeUpdatedLayoutForCollapse,
3254
+ onLayoutChange,
3255
+ onLayoutPersist
3256
+ ]
3257
+ );
3258
+ const isPanelCollapsed = useCallback(
3259
+ (panelId) => collapsedPanels.has(panelId),
3260
+ [collapsedPanels]
3261
+ );
3262
+ if (panels.size === 0) {
3263
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, className, style });
3264
+ }
3265
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className, children: [
3266
+ /* @__PURE__ */ jsx(
3267
+ SplitLayoutConfigProvider,
3268
+ {
3269
+ panels,
3270
+ layout,
3271
+ breakpoint,
3272
+ onLayoutChange,
3273
+ onSizeChange: handleSizeChange,
3274
+ onSizePersist: handleSizePersist,
3275
+ classNames: ctx?.classNames,
3276
+ gap: ctx?.gap,
3277
+ collapsedPanels,
3278
+ togglePanelCollapse,
3279
+ isPanelCollapsed,
3280
+ collapsiblePanels,
3281
+ isPanelCollapsible,
3282
+ children: /* @__PURE__ */ jsx(SplitNodeRenderer, { node: rootNode, path: [], rootNode })
3283
+ }
3284
+ ),
3285
+ /* @__PURE__ */ jsxs(
3286
+ "div",
3287
+ {
3288
+ className: "oui-fixed oui-right-2 oui-bottom-5 oui-text-lg oui-text-trade-loss oui-flex oui-flex-col oui-items-end",
3289
+ style: { zIndex: 1e3 },
3290
+ children: [
3291
+ /* @__PURE__ */ jsx("span", { children: breakpoint }),
3292
+ presetName && /* @__PURE__ */ jsx("span", { className: "oui-text-sm", children: presetName }),
3293
+ /* @__PURE__ */ jsx(
3294
+ "button",
3295
+ {
3296
+ onClick: () => ctx?.reset(),
3297
+ className: "oui-mt-1 oui-px-2 oui-py-1 oui-text-sm oui-bg-gray-500 oui-text-white oui-rounded",
3298
+ children: "Reset"
3299
+ }
3300
+ )
3301
+ ]
3302
+ }
3303
+ )
3304
+ ] });
3305
+ }
3306
+
3307
+ // src/splitStrategy.ts
3308
+ var splitStrategy = {
3309
+ id: "split",
3310
+ displayName: "Split Layout",
3311
+ defaultLayout: createDefaultSplitLayout,
3312
+ serialize: serializeSplitLayout,
3313
+ deserialize: deserializeSplitLayout,
3314
+ Renderer: SplitRenderer
3315
+ };
3316
+ function SplitInlinedLayout({
3317
+ Original,
3318
+ props
3319
+ }) {
3320
+ const layoutStrategy = props.layoutStrategy ?? splitStrategy;
3321
+ return /* @__PURE__ */ jsx(SplitTradingDesktopChrome, { ...props, children: /* @__PURE__ */ jsx(Original, { ...props, layoutStrategy }) });
3322
+ }
3323
+
3324
+ export { DATA_LIST_INITIAL_HEIGHT, DATA_LIST_MAX_HEIGHT, DEFAULT_SPLIT_BREAKPOINTS, ORDERBOOK_MAX_HEIGHT, ORDERBOOK_MAX_WIDTH, ORDERBOOK_MIN_HEIGHT, ORDERBOOK_MIN_WIDTH, ORDER_ENTRY_MAX_WIDTH, ORDER_ENTRY_MIN_WIDTH, SPACE, SPLIT_BREAKPOINT_ORDER, SYMBOL_INFO_BAR_HEIGHT, SplitInlinedLayout, SplitLayout, SplitLayoutConfigProvider, SplitTradingDesktopChrome, SplitTradingLayout, TRADINGVIEW_MIN_HEIGHT, TRADINGVIEW_MIN_WIDTH, TradingSortablePanel, TradingSplitLayout, VIEWPORT_BREAKPOINTS, VIEWPORT_BREAKPOINT_ORDER, createDefaultSplitLayout, deserializeSplitLayout, getSortableIdForChild, registerLayoutSplitPlugin, serializeSplitLayout, splitTradingStrategy, updateOrderAtPath, useSplitLayout, useSplitLayoutConfig, useSplitTradingDesktopContext, useViewportBreakpoint };
3325
+ //# sourceMappingURL=index.mjs.map
3326
+ //# sourceMappingURL=index.mjs.map