@kodiak-finance/orderly-layout-grid 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.js ADDED
@@ -0,0 +1,541 @@
1
+ 'use strict';
2
+
3
+ require('react-grid-layout/css/styles.css');
4
+ require('react-resizable/css/styles.css');
5
+ var React = require('react');
6
+ var reactGridLayout = require('react-grid-layout');
7
+ var orderlyUi = require('@kodiak-finance/orderly-ui');
8
+ var orderlyLayoutCore = require('@kodiak-finance/orderly-layout-core');
9
+ var jsxRuntime = require('react/jsx-runtime');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ var React__default = /*#__PURE__*/_interopDefault(React);
14
+
15
+ // src/index.ts
16
+ var S = orderlyLayoutCore.TRADING_PANEL_IDS;
17
+ var regularLayoutRule = [
18
+ {
19
+ panelId: S.SYMBOL_INFO_BAR,
20
+ x: 0,
21
+ y: 0,
22
+ w: 19,
23
+ h: 4,
24
+ minW: 8,
25
+ minH: 2,
26
+ static: true,
27
+ isResizable: false,
28
+ className: "oui-px-3"
29
+ },
30
+ {
31
+ panelId: S.MARKETS,
32
+ x: 0,
33
+ y: 4,
34
+ w: 5,
35
+ h: 38,
36
+ minW: 1
37
+ },
38
+ {
39
+ panelId: S.TRADING_VIEW,
40
+ x: 5,
41
+ y: 3,
42
+ w: 10,
43
+ h: 38,
44
+ minW: 4,
45
+ minH: 8,
46
+ resizeHandles: ["se"]
47
+ },
48
+ {
49
+ panelId: S.ORDERBOOK,
50
+ x: 15,
51
+ y: 3,
52
+ w: 4,
53
+ h: 38,
54
+ minW: 3,
55
+ minH: 4,
56
+ resizeHandles: ["se"]
57
+ },
58
+ {
59
+ panelId: S.MARGIN,
60
+ x: 19,
61
+ y: 0,
62
+ w: 5,
63
+ h: 4,
64
+ minW: 3,
65
+ minH: 2,
66
+ isResizable: false,
67
+ className: "oui-p-3"
68
+ },
69
+ {
70
+ panelId: S.ASSETS,
71
+ x: 19,
72
+ y: 15,
73
+ w: 5,
74
+ h: 20,
75
+ minW: 3,
76
+ minH: 24,
77
+ isResizable: false,
78
+ className: "oui-p-3"
79
+ },
80
+ {
81
+ panelId: S.ORDER_ENTRY,
82
+ x: 19,
83
+ y: 4,
84
+ w: 5,
85
+ h: 38,
86
+ minW: 3,
87
+ minH: 38,
88
+ className: "oui-p-3",
89
+ isResizable: false,
90
+ autoHeight: true
91
+ },
92
+ {
93
+ panelId: S.DATA_LIST,
94
+ x: 0,
95
+ y: 39,
96
+ w: 19,
97
+ h: 20,
98
+ className: "oui-p-2"
99
+ }
100
+ ];
101
+ var exchangeStyleRule = {
102
+ lg: regularLayoutRule,
103
+ md: regularLayoutRule,
104
+ sm: regularLayoutRule,
105
+ xs: regularLayoutRule
106
+ // md: [
107
+ // { panelId: S.SYMBOL_INFO_BAR, x: 0, y: 0, w: 10, h: 3, minW: 6, minH: 2 },
108
+ // { panelId: S.TRADING_VIEW, x: 0, y: 3, w: 6, h: 14, minW: 4, minH: 8 },
109
+ // { panelId: S.ORDERBOOK, x: 6, y: 3, w: 4, h: 5, minW: 3, minH: 3 },
110
+ // {
111
+ // panelId: S.ORDER_ENTRY,
112
+ // x: 6,
113
+ // y: 8,
114
+ // w: 4,
115
+ // h: 5,
116
+ // minW: 3,
117
+ // minH: 4,
118
+ // autoHeight: true,
119
+ // },
120
+ // { panelId: S.DATA_LIST, x: 6, y: 13, w: 4, h: 4, minW: 3, minH: 3 },
121
+ // { panelId: S.MARKETS, x: 0, y: 17, w: 10, h: 6, minW: 4, minH: 4 },
122
+ // ],
123
+ };
124
+ var DEFAULT_GRID_LAYOUT_RULE = exchangeStyleRule;
125
+ var DEFAULT_GRID_PRESETS = [
126
+ {
127
+ id: "exchange-style",
128
+ name: "Exchange Style",
129
+ rule: exchangeStyleRule,
130
+ rowHeight: 10
131
+ }
132
+ ];
133
+ function getDefaultGridPresets() {
134
+ return [...DEFAULT_GRID_PRESETS];
135
+ }
136
+
137
+ // src/utils/gridLayoutUtils.ts
138
+ var BREAKPOINT_ORDER = ["lg", "md", "sm", "xs"];
139
+ var DEFAULT_GRID_CONFIG = {
140
+ rowHeight: 30,
141
+ margin: [4, 4],
142
+ containerPadding: [0, 0],
143
+ compactType: "vertical",
144
+ isDraggable: true,
145
+ isResizable: true
146
+ };
147
+ function mergeGridConfig(userConfig, presetRowHeight) {
148
+ return {
149
+ ...DEFAULT_GRID_CONFIG,
150
+ ...presetRowHeight !== void 0 && { rowHeight: presetRowHeight },
151
+ ...userConfig
152
+ };
153
+ }
154
+ var DEFAULT_BREAKPOINTS = {
155
+ lg: 1680,
156
+ md: 1440,
157
+ sm: 1280,
158
+ xs: 768
159
+ };
160
+ var DEFAULT_COLS = {
161
+ lg: 24,
162
+ md: 24,
163
+ sm: 24,
164
+ xs: 24
165
+ };
166
+ function specsToItems(specs, panelIds) {
167
+ const idSet = new Set(panelIds);
168
+ return specs.filter((spec) => idSet.has(spec.panelId)).map((spec) => ({
169
+ i: spec.panelId,
170
+ panelId: spec.panelId,
171
+ x: spec.x,
172
+ y: spec.y,
173
+ w: spec.w,
174
+ h: spec.h,
175
+ minW: spec.minW,
176
+ minH: spec.minH,
177
+ maxW: spec.maxW,
178
+ maxH: spec.maxH,
179
+ isDraggable: spec.isDraggable,
180
+ isResizable: spec.isResizable,
181
+ resizeHandles: spec.resizeHandles,
182
+ static: spec.static,
183
+ className: spec.className,
184
+ style: spec.style,
185
+ autoHeight: spec.autoHeight
186
+ }));
187
+ }
188
+ function buildLayoutsFromRule(rule, panelIds) {
189
+ const result = {};
190
+ const fallbackSpecs = rule.lg ?? [];
191
+ for (const bp of BREAKPOINT_ORDER) {
192
+ const specs = rule[bp] ?? fallbackSpecs;
193
+ result[bp] = specsToItems(specs, panelIds);
194
+ }
195
+ return result;
196
+ }
197
+ function createDefaultGridLayout(panelIds, rule, rowHeight) {
198
+ const effectiveRule = rule ?? DEFAULT_GRID_LAYOUT_RULE;
199
+ const layouts = buildLayoutsFromRule(effectiveRule, panelIds);
200
+ const effectiveConfig = mergeGridConfig(void 0, rowHeight);
201
+ return {
202
+ layouts,
203
+ breakpoints: DEFAULT_BREAKPOINTS,
204
+ cols: DEFAULT_COLS,
205
+ // For the default layout we always use vertical compaction.
206
+ compactType: "vertical",
207
+ isDraggable: effectiveConfig.isDraggable,
208
+ isResizable: effectiveConfig.isResizable,
209
+ margin: effectiveConfig.margin,
210
+ containerPadding: effectiveConfig.containerPadding,
211
+ rowHeight: effectiveConfig.rowHeight
212
+ };
213
+ }
214
+ function serializeGridLayout(layout) {
215
+ return JSON.stringify(layout);
216
+ }
217
+ function deserializeGridLayout(json) {
218
+ try {
219
+ const parsed = JSON.parse(json);
220
+ if (!parsed.layouts) {
221
+ throw new Error("Invalid grid layout: missing layouts");
222
+ }
223
+ return parsed;
224
+ } catch (error) {
225
+ throw new Error(`Failed to deserialize grid layout: ${error}`);
226
+ }
227
+ }
228
+ function toReactGridLayouts(layouts) {
229
+ const result = {};
230
+ Object.keys(layouts).forEach((breakpoint) => {
231
+ const items = layouts[breakpoint];
232
+ if (items) {
233
+ result[breakpoint] = items.map((item) => ({
234
+ i: item.i,
235
+ x: item.x,
236
+ y: item.y,
237
+ w: item.w,
238
+ h: item.h,
239
+ minW: item.minW,
240
+ minH: item.minH,
241
+ maxW: item.maxW,
242
+ maxH: item.maxH,
243
+ static: item.static,
244
+ isDraggable: item.isDraggable,
245
+ isResizable: item.isResizable,
246
+ resizeHandles: item.resizeHandles
247
+ }));
248
+ }
249
+ });
250
+ return result;
251
+ }
252
+ function GridRenderer(props) {
253
+ const { layout, panels, onLayoutChange, className, style } = props;
254
+ const { width, containerRef, mounted } = reactGridLayout.useContainerWidth();
255
+ const layoutsRef = React.useRef(layout.layouts);
256
+ React.useEffect(() => {
257
+ layoutsRef.current = layout.layouts;
258
+ }, [layout.layouts]);
259
+ const reactGridLayouts = React.useMemo(
260
+ () => toReactGridLayouts(layout.layouts),
261
+ [layout.layouts]
262
+ );
263
+ const handleLayoutChange = React.useCallback(
264
+ (_currentLayout, allLayouts) => {
265
+ const updatedLayouts = {};
266
+ Object.keys(allLayouts).forEach((bp) => {
267
+ const items = allLayouts[bp];
268
+ if (items) {
269
+ const originalItems = layout.layouts[bp] || [];
270
+ updatedLayouts[bp] = items.map((item) => {
271
+ const originalItem = originalItems.find((i) => i.i === item.i);
272
+ return {
273
+ ...item,
274
+ panelId: originalItem?.panelId || item.i,
275
+ className: originalItem?.className,
276
+ style: originalItem?.style
277
+ };
278
+ });
279
+ }
280
+ });
281
+ layoutsRef.current = updatedLayouts;
282
+ onLayoutChange({ ...layout, layouts: updatedLayouts });
283
+ },
284
+ [layout, onLayoutChange]
285
+ );
286
+ const { layout: currentLayout, cols } = reactGridLayout.useResponsiveLayout({
287
+ width,
288
+ breakpoints: layout.breakpoints || DEFAULT_BREAKPOINTS,
289
+ cols: layout.cols || DEFAULT_COLS,
290
+ layouts: reactGridLayouts,
291
+ onLayoutChange: handleLayoutChange
292
+ });
293
+ const layoutItems = React.useMemo(() => {
294
+ const breakpoints = ["lg", "md", "sm", "xs", "xxs"];
295
+ for (const bp of breakpoints) {
296
+ const items = layout.layouts[bp];
297
+ if (items?.length)
298
+ return items;
299
+ }
300
+ return [];
301
+ }, [layout.layouts]);
302
+ const children = React.useMemo(
303
+ () => layoutItems.map((config) => {
304
+ const panelId = config.panelId;
305
+ const panelWrapper = panels.get(panelId);
306
+ const panel = panelWrapper?.node;
307
+ if (!panel) {
308
+ return null;
309
+ }
310
+ const title = panelWrapper?.props?.title;
311
+ const isCollapsible = config.collapsible === true;
312
+ const layoutItem = currentLayout?.find(
313
+ (item) => item.i === config.i
314
+ );
315
+ let collapsed = false;
316
+ if (isCollapsible && layoutItem && typeof config.minW === "number" && Number.isFinite(config.minW)) {
317
+ collapsed = layoutItem.w <= config.minW;
318
+ }
319
+ const bodyClassName = typeof title !== "undefined" && title !== null ? "oui-h-[calc(100%_-_44px)]" : "oui-h-full";
320
+ return /* @__PURE__ */ jsxRuntime.jsxs(
321
+ "div",
322
+ {
323
+ className: orderlyUi.cn(
324
+ "oui-layout-grid-item oui-relative oui-size-full oui-overflow-hidden oui-rounded oui-bg-base-9",
325
+ config.className
326
+ ),
327
+ style: config.style,
328
+ children: [
329
+ title && /* @__PURE__ */ jsxRuntime.jsx(
330
+ orderlyUi.Flex,
331
+ {
332
+ className: "oui-text-base-contrast-36",
333
+ justify: "between",
334
+ width: "100%",
335
+ px: 3,
336
+ pt: 3,
337
+ pb: 2,
338
+ children: /* @__PURE__ */ jsxRuntime.jsx(orderlyUi.Text, { size: "base", intensity: 80, children: title })
339
+ }
340
+ ),
341
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: orderlyUi.cn("oui-collapsible-content", bodyClassName), children: React__default.default.isValidElement(panel) ? React__default.default.cloneElement(panel, {
342
+ /** Pass collapsed state down so panel can adjust its own UI. */
343
+ collapsed
344
+ }) : panel })
345
+ ]
346
+ },
347
+ panelId
348
+ );
349
+ }),
350
+ [currentLayout, layoutItems, panels]
351
+ );
352
+ if (panels.size === 0) {
353
+ return /* @__PURE__ */ jsxRuntime.jsx(
354
+ "div",
355
+ {
356
+ ref: containerRef,
357
+ className,
358
+ style
359
+ }
360
+ );
361
+ }
362
+ if (!mounted) {
363
+ return /* @__PURE__ */ jsxRuntime.jsx(
364
+ "div",
365
+ {
366
+ ref: containerRef,
367
+ className,
368
+ style
369
+ }
370
+ );
371
+ }
372
+ return /* @__PURE__ */ jsxRuntime.jsx(
373
+ "div",
374
+ {
375
+ ref: containerRef,
376
+ className: orderlyUi.cn("oui-grid-layout-container oui-p-1", className),
377
+ style,
378
+ children: /* @__PURE__ */ jsxRuntime.jsx(
379
+ reactGridLayout.GridLayout,
380
+ {
381
+ width,
382
+ layout: currentLayout,
383
+ gridConfig: {
384
+ cols,
385
+ rowHeight: layout.rowHeight ?? 30,
386
+ margin: layout.margin || [4, 4],
387
+ containerPadding: layout.containerPadding || [0, 0]
388
+ },
389
+ compactor: reactGridLayout.getCompactor(
390
+ layout.compactType,
391
+ false,
392
+ layout.compactType === null
393
+ ),
394
+ dragConfig: {
395
+ enabled: layout.isDraggable !== false
396
+ },
397
+ resizeConfig: {
398
+ enabled: layout.isResizable !== false
399
+ },
400
+ children
401
+ }
402
+ )
403
+ }
404
+ );
405
+ }
406
+
407
+ // src/gridStrategy.ts
408
+ var gridStrategy = {
409
+ id: "grid",
410
+ displayName: "Grid Layout",
411
+ defaultLayout: createDefaultGridLayout,
412
+ serialize: serializeGridLayout,
413
+ deserialize: deserializeGridLayout,
414
+ Renderer: GridRenderer
415
+ };
416
+ function createTradingGridLayoutFromPreset(preset) {
417
+ const panelIds = orderlyLayoutCore.getTradingPanelIds();
418
+ const p = preset ?? DEFAULT_GRID_PRESETS[0];
419
+ if (!p)
420
+ throw new Error("Grid layout: no default presets");
421
+ return createDefaultGridLayout(panelIds, p.rule, p.rowHeight);
422
+ }
423
+ function createTradingGridLayout() {
424
+ return createTradingGridLayoutFromPreset();
425
+ }
426
+ var GridPresetContext = React.createContext(null);
427
+ function useGridPresetContext() {
428
+ return React.useContext(GridPresetContext);
429
+ }
430
+ function GridLayoutSwitcher({
431
+ className,
432
+ style,
433
+ "aria-label": ariaLabel = "Grid layout preset"
434
+ }) {
435
+ const ctx = useGridPresetContext();
436
+ if (!ctx || ctx.presets.length === 0)
437
+ return null;
438
+ return /* @__PURE__ */ jsxRuntime.jsx(
439
+ "select",
440
+ {
441
+ className,
442
+ style,
443
+ "aria-label": ariaLabel,
444
+ value: ctx.selectedPresetId,
445
+ onChange: (e) => ctx.setSelectedPresetId(e.target.value),
446
+ children: ctx.presets.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.id, children: p.name }, p.id))
447
+ }
448
+ );
449
+ }
450
+
451
+ // src/utils/gridPluginConfig.ts
452
+ function createDefaultGetInitialLayout(presets) {
453
+ return () => {
454
+ const preset = presets[0];
455
+ return createTradingGridLayoutFromPreset(preset);
456
+ };
457
+ }
458
+ function GridDesktopInjector({
459
+ Original,
460
+ props,
461
+ options
462
+ }) {
463
+ const presets = options.presets ?? getDefaultGridPresets();
464
+ const presetRowHeight = presets[0]?.rowHeight;
465
+ const gridConfig = mergeGridConfig(options.grid, presetRowHeight);
466
+ const { persistLayout = false } = options;
467
+ const getInitialLayout = React__default.default.useCallback(() => {
468
+ const baseLayout = options.getInitialLayout?.() ?? createDefaultGetInitialLayout(presets)();
469
+ return {
470
+ ...baseLayout,
471
+ rowHeight: gridConfig.rowHeight,
472
+ margin: gridConfig.margin,
473
+ containerPadding: gridConfig.containerPadding,
474
+ compactType: gridConfig.compactType,
475
+ isDraggable: gridConfig.isDraggable,
476
+ isResizable: gridConfig.isResizable
477
+ };
478
+ }, [
479
+ options.getInitialLayout,
480
+ presets,
481
+ gridConfig.rowHeight,
482
+ gridConfig.margin,
483
+ gridConfig.containerPadding,
484
+ gridConfig.compactType,
485
+ gridConfig.isDraggable,
486
+ gridConfig.isResizable
487
+ ]);
488
+ const storageKey = persistLayout ? "orderly_trading_grid" : void 0;
489
+ return /* @__PURE__ */ jsxRuntime.jsx(
490
+ Original,
491
+ {
492
+ ...props,
493
+ layoutStrategy: gridStrategy,
494
+ getInitialLayout: props.getInitialLayout ?? ((_opts) => getInitialLayout()),
495
+ storageKey,
496
+ disableLayoutPersistence: !persistLayout
497
+ }
498
+ );
499
+ }
500
+ var PLUGIN_ID = "orderly-layout-grid";
501
+ var PLUGIN_NAME = "Grid Layout";
502
+ var PLUGIN_VERSION = "1.0.0";
503
+ function registerLayoutGridPlugin(options) {
504
+ const resolvedPresets = options?.presets ?? getDefaultGridPresets();
505
+ return (SDK) => {
506
+ SDK.registerPlugin({
507
+ id: PLUGIN_ID,
508
+ name: PLUGIN_NAME,
509
+ version: PLUGIN_VERSION,
510
+ orderlyVersion: ">=1.0.0",
511
+ interceptors: [
512
+ orderlyUi.createInterceptor("Trading.Layout.Desktop", (Original, props) => /* @__PURE__ */ jsxRuntime.jsx(
513
+ GridDesktopInjector,
514
+ {
515
+ Original,
516
+ props,
517
+ options: {
518
+ ...options,
519
+ presets: resolvedPresets
520
+ }
521
+ }
522
+ ))
523
+ ]
524
+ });
525
+ };
526
+ }
527
+
528
+ exports.DEFAULT_BREAKPOINTS = DEFAULT_BREAKPOINTS;
529
+ exports.DEFAULT_COLS = DEFAULT_COLS;
530
+ exports.DEFAULT_GRID_PRESETS = DEFAULT_GRID_PRESETS;
531
+ exports.GridLayoutSwitcher = GridLayoutSwitcher;
532
+ exports.createDefaultGridLayout = createDefaultGridLayout;
533
+ exports.createTradingGridLayout = createTradingGridLayout;
534
+ exports.createTradingGridLayoutFromPreset = createTradingGridLayoutFromPreset;
535
+ exports.deserializeGridLayout = deserializeGridLayout;
536
+ exports.getDefaultGridPresets = getDefaultGridPresets;
537
+ exports.gridStrategy = gridStrategy;
538
+ exports.registerLayoutGridPlugin = registerLayoutGridPlugin;
539
+ exports.serializeGridLayout = serializeGridLayout;
540
+ //# sourceMappingURL=out.js.map
541
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/GridRenderer.tsx","../src/utils/defaultPresets.ts","../src/utils/gridLayoutUtils.ts","../src/gridStrategy.ts","../src/utils/tradingGridLayout.ts","../src/GridPresetContext.tsx","../src/GridLayoutSwitcher.tsx","../src/plugin.tsx","../src/components/GridDesktopInjector.tsx","../src/utils/gridPluginConfig.ts"],"names":["useMemo","jsx","React"],"mappings":"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","sourcesContent":["/** @orderly.network/layout-grid */\nimport \"react-grid-layout/css/styles.css\";\nimport \"react-resizable/css/styles.css\";\nimport \"./styles.css\";\n\nexport { gridStrategy } from \"./gridStrategy\";\nexport type {\n GridLayoutModel,\n GridLayoutItem,\n GridLayoutRule,\n GridLayoutItemSpec,\n // GridLayoutBreakpointKey,\n GridLayoutPreset,\n GridConfig,\n} from \"./types\";\nexport {\n createDefaultGridLayout,\n serializeGridLayout,\n deserializeGridLayout,\n DEFAULT_BREAKPOINTS,\n DEFAULT_COLS,\n} from \"./utils/gridLayoutUtils\";\nexport {\n createTradingGridLayout,\n createTradingGridLayoutFromPreset,\n} from \"./utils/tradingGridLayout\";\nexport {\n getDefaultGridPresets,\n DEFAULT_GRID_PRESETS,\n} from \"./utils/defaultPresets\";\nexport type { GridPresetContextValue } from \"./GridPresetContext\";\nexport { GridLayoutSwitcher } from \"./GridLayoutSwitcher\";\nexport type { GridLayoutSwitcherProps } from \"./GridLayoutSwitcher\";\n\nexport {\n registerLayoutGridPlugin,\n type LayoutGridPluginOptions,\n} from \"./plugin\";\n","import React, { useMemo, useCallback, useEffect, useRef } from \"react\";\nimport {\n GridLayout,\n useContainerWidth,\n useResponsiveLayout,\n getCompactor,\n type Layout,\n type LayoutItem,\n type CompactType,\n} from \"react-grid-layout\";\nimport type { LayoutRendererProps } from \"@kodiak-finance/orderly-layout-core\";\nimport { cn, Flex, Text } from \"@kodiak-finance/orderly-ui\";\nimport type { GridLayoutModel, GridLayoutItem, BreakpointKey } from \"./types\";\nimport { DEFAULT_BREAKPOINTS, DEFAULT_COLS } from \"./utils/gridLayoutUtils\";\n\ntype ResponsiveLayouts = Partial<Record<string, Layout>>;\n\n/** GridLayoutItem[] -> react-grid-layout Layout */\nfunction toReactGridLayouts(\n layouts: GridLayoutModel[\"layouts\"],\n): ResponsiveLayouts {\n const result: Record<string, LayoutItem[]> = {};\n\n (Object.keys(layouts) as BreakpointKey[]).forEach((breakpoint) => {\n const items = layouts[breakpoint];\n if (items) {\n result[breakpoint] = items.map((item) => ({\n i: item.i,\n x: item.x,\n y: item.y,\n w: item.w,\n h: item.h,\n minW: item.minW,\n minH: item.minH,\n maxW: item.maxW,\n maxH: item.maxH,\n static: item.static,\n isDraggable: item.isDraggable,\n isResizable: item.isResizable,\n resizeHandles: item.resizeHandles,\n }));\n }\n });\n\n return result as ResponsiveLayouts;\n}\n\n/** Responsive grid layout renderer (react-grid-layout). */\nexport function GridRenderer(\n props: LayoutRendererProps<GridLayoutModel>,\n): React.ReactElement {\n const { layout, panels, onLayoutChange, className, style } = props;\n const { width, containerRef, mounted } = useContainerWidth();\n\n const layoutsRef = useRef(layout.layouts);\n\n useEffect(() => {\n layoutsRef.current = layout.layouts;\n }, [layout.layouts]);\n\n const reactGridLayouts = useMemo(\n () => toReactGridLayouts(layout.layouts),\n [layout.layouts],\n );\n\n const handleLayoutChange = useCallback(\n (_currentLayout: Layout, allLayouts: ResponsiveLayouts) => {\n const updatedLayouts: GridLayoutModel[\"layouts\"] = {};\n (Object.keys(allLayouts) as BreakpointKey[]).forEach((bp) => {\n const items = allLayouts[bp];\n if (items) {\n const originalItems = layout.layouts[bp] || [];\n updatedLayouts[bp] = items.map((item: LayoutItem) => {\n const originalItem = originalItems.find((i) => i.i === item.i);\n return {\n ...item,\n panelId: originalItem?.panelId || item.i,\n className: originalItem?.className,\n style: originalItem?.style,\n } as GridLayoutItem;\n });\n }\n });\n layoutsRef.current = updatedLayouts;\n onLayoutChange({ ...layout, layouts: updatedLayouts });\n },\n [layout, onLayoutChange],\n );\n\n const { layout: currentLayout, cols } = useResponsiveLayout({\n width,\n breakpoints: layout.breakpoints || DEFAULT_BREAKPOINTS,\n cols: layout.cols || DEFAULT_COLS,\n layouts: reactGridLayouts,\n onLayoutChange: handleLayoutChange,\n });\n\n // const handleGridLayoutChange = useCallback(\n // (newLayout: Layout) => setLayoutForBreakpoint(breakpoint, newLayout),\n // [breakpoint, setLayoutForBreakpoint],\n // );\n\n // const handlePersistLayout = useCallback(\n // (_: Layout) => {\n // if (onLayoutPersist) {\n // onLayoutPersist({ ...layout, layouts: layoutsRef.current });\n // }\n // },\n // [layout, onLayoutPersist],\n // );\n\n const layoutItems = useMemo(() => {\n const breakpoints: BreakpointKey[] = [\"lg\", \"md\", \"sm\", \"xs\", \"xxs\"];\n for (const bp of breakpoints) {\n const items = layout.layouts[bp];\n if (items?.length) return items;\n }\n return [];\n }, [layout.layouts]);\n\n const children = useMemo(\n () =>\n layoutItems.map((config) => {\n const panelId = config.panelId;\n const panelWrapper = panels.get(panelId);\n const panel = panelWrapper?.node;\n if (!panel) {\n console.warn(`Panel ${panelId} not found in registry`);\n return null;\n }\n\n /** Resolve title from panel registration props (if any). */\n const title = panelWrapper?.props?.title as\n | string\n | React.ReactNode\n | undefined;\n\n /** Determine whether this item should participate in collapse logic. */\n const isCollapsible = config.collapsible === true;\n\n /**\n * Derive collapsed state from current layout width.\n *\n * - For collapsible items, `w` is the expanded width and `minW` is the\n * collapsed width.\n * - When the user drags the item so that its current width is at or\n * below `minW`, we treat it as collapsed.\n */\n const layoutItem = currentLayout?.find(\n (item) => item.i === config.i,\n ) as LayoutItem | undefined;\n\n let collapsed = false;\n // console.log(\">>>>>>>>>layoutItem\", layoutItem);\n if (\n isCollapsible &&\n layoutItem &&\n typeof config.minW === \"number\" &&\n Number.isFinite(config.minW)\n ) {\n collapsed = layoutItem.w <= config.minW;\n }\n\n /** Body height adjusts when a title header is present. */\n const bodyClassName =\n typeof title !== \"undefined\" && title !== null\n ? \"oui-h-[calc(100%_-_44px)]\"\n : \"oui-h-full\";\n\n return (\n <div\n key={panelId}\n className={cn(\n \"oui-layout-grid-item oui-relative oui-size-full oui-overflow-hidden oui-rounded oui-bg-base-9\",\n config.className,\n )}\n style={config.style}\n >\n {title && (\n <Flex\n className=\"oui-text-base-contrast-36\"\n justify=\"between\"\n width=\"100%\"\n px={3}\n pt={3}\n pb={2}\n >\n <Text size=\"base\" intensity={80}>\n {title}\n </Text>\n </Flex>\n )}\n\n <div className={cn(\"oui-collapsible-content\", bodyClassName)}>\n {React.isValidElement(panel)\n ? React.cloneElement(panel, {\n /** Pass collapsed state down so panel can adjust its own UI. */\n collapsed,\n })\n : panel}\n </div>\n </div>\n );\n }),\n [currentLayout, layoutItems, panels],\n );\n\n if (panels.size === 0) {\n return (\n <div\n ref={containerRef as React.RefObject<HTMLDivElement>}\n className={className}\n style={style}\n ></div>\n );\n }\n\n if (!mounted) {\n return (\n <div\n ref={containerRef as React.RefObject<HTMLDivElement>}\n className={className}\n style={style}\n />\n );\n }\n\n return (\n <div\n ref={containerRef as React.RefObject<HTMLDivElement>}\n className={cn(\"oui-grid-layout-container oui-p-1\", className)}\n style={style}\n >\n <GridLayout\n width={width}\n layout={currentLayout}\n gridConfig={{\n cols: cols,\n rowHeight: layout.rowHeight ?? 30,\n margin: layout.margin || [4, 4],\n containerPadding: layout.containerPadding || [0, 0],\n }}\n compactor={getCompactor(\n layout.compactType as CompactType,\n false,\n layout.compactType === null,\n )}\n dragConfig={{\n enabled: layout.isDraggable !== false,\n }}\n resizeConfig={{\n enabled: layout.isResizable !== false,\n }}\n // onLayoutChange={handleGridLayoutChange}\n // onDragStop={handlePersistLayout}\n // onResizeStop={handlePersistLayout}\n >\n {children}\n </GridLayout>\n </div>\n );\n}\n","import { TRADING_PANEL_IDS } from \"@kodiak-finance/orderly-layout-core\";\nimport type {\n GridLayoutItemSpec,\n GridLayoutPreset,\n GridLayoutRule,\n} from \"../types\";\n\nconst S = TRADING_PANEL_IDS;\n\nconst regularLayoutRule: GridLayoutItemSpec[] = [\n {\n panelId: S.SYMBOL_INFO_BAR,\n x: 0,\n y: 0,\n w: 19,\n h: 4,\n minW: 8,\n minH: 2,\n static: true,\n isResizable: false,\n className: \"oui-px-3\",\n },\n {\n panelId: S.MARKETS,\n x: 0,\n y: 4,\n w: 5,\n h: 38,\n minW: 1,\n },\n {\n panelId: S.TRADING_VIEW,\n x: 5,\n y: 3,\n w: 10,\n h: 38,\n minW: 4,\n minH: 8,\n resizeHandles: [\"se\"],\n },\n {\n panelId: S.ORDERBOOK,\n x: 15,\n y: 3,\n w: 4,\n h: 38,\n minW: 3,\n minH: 4,\n resizeHandles: [\"se\"],\n },\n {\n panelId: S.MARGIN,\n x: 19,\n y: 0,\n w: 5,\n h: 4,\n minW: 3,\n minH: 2,\n isResizable: false,\n className: \"oui-p-3\",\n },\n {\n panelId: S.ASSETS,\n x: 19,\n y: 15,\n w: 5,\n h: 20,\n minW: 3,\n minH: 24,\n isResizable: false,\n className: \"oui-p-3\",\n },\n {\n panelId: S.ORDER_ENTRY,\n x: 19,\n y: 4,\n w: 5,\n h: 38,\n minW: 3,\n minH: 38,\n className: \"oui-p-3\",\n isResizable: false,\n autoHeight: true,\n },\n {\n panelId: S.DATA_LIST,\n x: 0,\n y: 39,\n w: 19,\n h: 20,\n className: \"oui-p-2\",\n },\n];\n\nconst exchangeStyleRule: GridLayoutRule = {\n lg: regularLayoutRule,\n md: regularLayoutRule,\n sm: regularLayoutRule,\n xs: regularLayoutRule,\n // md: [\n // { panelId: S.SYMBOL_INFO_BAR, x: 0, y: 0, w: 10, h: 3, minW: 6, minH: 2 },\n // { panelId: S.TRADING_VIEW, x: 0, y: 3, w: 6, h: 14, minW: 4, minH: 8 },\n // { panelId: S.ORDERBOOK, x: 6, y: 3, w: 4, h: 5, minW: 3, minH: 3 },\n // {\n // panelId: S.ORDER_ENTRY,\n // x: 6,\n // y: 8,\n // w: 4,\n // h: 5,\n // minW: 3,\n // minH: 4,\n // autoHeight: true,\n // },\n // { panelId: S.DATA_LIST, x: 6, y: 13, w: 4, h: 4, minW: 3, minH: 3 },\n // { panelId: S.MARKETS, x: 0, y: 17, w: 10, h: 6, minW: 4, minH: 4 },\n // ],\n};\n\n/** Default layout rule when none is provided; uses lg (and md) so all breakpoints fall back to lg. */\nexport const DEFAULT_GRID_LAYOUT_RULE: GridLayoutRule = exchangeStyleRule;\n\nexport const DEFAULT_GRID_PRESETS: GridLayoutPreset[] = [\n {\n id: \"exchange-style\",\n name: \"Exchange Style\",\n rule: exchangeStyleRule,\n rowHeight: 10,\n } as GridLayoutPreset,\n];\n\nexport function getDefaultGridPresets(): GridLayoutPreset[] {\n return [...DEFAULT_GRID_PRESETS];\n}\n","import type {\n GridLayoutModel,\n GridLayoutItem,\n GridLayoutRule,\n GridLayoutItemSpec,\n BreakpointKey,\n GridConfig,\n} from \"../types\";\nimport { DEFAULT_GRID_LAYOUT_RULE } from \"./defaultPresets\";\n\nconst BREAKPOINT_ORDER: BreakpointKey[] = [\"lg\", \"md\", \"sm\", \"xs\"];\n\n/** Default grid configuration shared by layout utils and plugin config. */\nexport const DEFAULT_GRID_CONFIG: GridConfig = {\n rowHeight: 30,\n margin: [4, 4],\n containerPadding: [0, 0],\n compactType: \"vertical\",\n isDraggable: true,\n isResizable: true,\n};\n\n/** Merge user grid config with defaults and optional preset rowHeight. */\nexport function mergeGridConfig(\n userConfig: GridConfig | undefined,\n presetRowHeight?: number,\n): GridConfig {\n return {\n ...DEFAULT_GRID_CONFIG,\n ...(presetRowHeight !== undefined && { rowHeight: presetRowHeight }),\n ...userConfig,\n };\n}\n\nexport const DEFAULT_BREAKPOINTS = {\n lg: 1680,\n md: 1440,\n sm: 1280,\n xs: 768,\n};\n\nexport const DEFAULT_COLS = {\n lg: 24,\n md: 24,\n sm: 24,\n xs: 24,\n};\n\nfunction specsToItems(\n specs: GridLayoutItemSpec[],\n panelIds: string[],\n): GridLayoutItem[] {\n const idSet = new Set(panelIds);\n return specs\n .filter((spec) => idSet.has(spec.panelId))\n .map((spec) => ({\n i: spec.panelId,\n panelId: spec.panelId,\n x: spec.x,\n y: spec.y,\n w: spec.w,\n h: spec.h,\n minW: spec.minW,\n minH: spec.minH,\n maxW: spec.maxW,\n maxH: spec.maxH,\n isDraggable: spec.isDraggable,\n isResizable: spec.isResizable,\n resizeHandles: spec.resizeHandles,\n static: spec.static,\n className: spec.className,\n style: spec.style,\n autoHeight: spec.autoHeight,\n }));\n}\n\nfunction buildLayoutsFromRule(\n rule: GridLayoutRule,\n panelIds: string[],\n): GridLayoutModel[\"layouts\"] {\n const result: GridLayoutModel[\"layouts\"] = {};\n const fallbackSpecs = rule.lg ?? [];\n for (const bp of BREAKPOINT_ORDER) {\n const specs = rule[bp] ?? fallbackSpecs;\n result[bp] = specsToItems(specs, panelIds);\n }\n return result;\n}\n\n/** Build grid layout from panelIds; optional rule (missing breakpoints fall back to lg), else default lg rule from defaultPresets. */\nexport function createDefaultGridLayout(\n panelIds: string[],\n rule?: GridLayoutRule,\n rowHeight?: number,\n): GridLayoutModel {\n const effectiveRule = rule ?? DEFAULT_GRID_LAYOUT_RULE;\n const layouts = buildLayoutsFromRule(effectiveRule, panelIds);\n\n const effectiveConfig = mergeGridConfig(undefined, rowHeight);\n\n return {\n layouts,\n breakpoints: DEFAULT_BREAKPOINTS,\n cols: DEFAULT_COLS,\n // For the default layout we always use vertical compaction.\n compactType: \"vertical\",\n isDraggable: effectiveConfig.isDraggable,\n isResizable: effectiveConfig.isResizable,\n margin: effectiveConfig.margin,\n containerPadding: effectiveConfig.containerPadding,\n rowHeight: effectiveConfig.rowHeight,\n };\n}\n\nexport function serializeGridLayout(layout: GridLayoutModel): string {\n return JSON.stringify(layout);\n}\n\nexport function deserializeGridLayout(json: string): GridLayoutModel {\n try {\n const parsed = JSON.parse(json);\n if (!parsed.layouts) {\n throw new Error(\"Invalid grid layout: missing layouts\");\n }\n return parsed as GridLayoutModel;\n } catch (error) {\n throw new Error(`Failed to deserialize grid layout: ${error}`);\n }\n}\n","import type { LayoutStrategy } from \"@kodiak-finance/orderly-layout-core\";\nimport { GridRenderer } from \"./GridRenderer\";\nimport type { GridLayoutModel } from \"./types\";\nimport {\n createDefaultGridLayout,\n serializeGridLayout,\n deserializeGridLayout,\n} from \"./utils/gridLayoutUtils\";\n\nexport const gridStrategy: LayoutStrategy<GridLayoutModel> = {\n id: \"grid\",\n displayName: \"Grid Layout\",\n defaultLayout: createDefaultGridLayout,\n serialize: serializeGridLayout,\n deserialize: deserializeGridLayout,\n Renderer: GridRenderer,\n};\n","import { getTradingPanelIds } from \"@kodiak-finance/orderly-layout-core\";\nimport type { GridLayoutModel, GridLayoutPreset } from \"../types\";\nimport { DEFAULT_GRID_PRESETS } from \"./defaultPresets\";\nimport { createDefaultGridLayout } from \"./gridLayoutUtils\";\n\nexport function createTradingGridLayoutFromPreset(\n preset?: GridLayoutPreset | null,\n): GridLayoutModel {\n const panelIds = getTradingPanelIds();\n const p = preset ?? DEFAULT_GRID_PRESETS[0];\n if (!p) throw new Error(\"Grid layout: no default presets\");\n return createDefaultGridLayout(panelIds as string[], p.rule, p.rowHeight);\n}\n\nexport function createTradingGridLayout(): GridLayoutModel {\n return createTradingGridLayoutFromPreset();\n}\n","/** Preset list + selected id (LayoutRuleManager); used by plugin for getInitialLayout/storageKey. */\nimport React, { createContext, useContext, useMemo } from \"react\";\nimport {\n LayoutRuleManager,\n useLayoutRuleManager,\n} from \"@kodiak-finance/orderly-layout-core\";\nimport {\n GRID_PRESET_ID_STORAGE_KEY,\n GRID_LAYOUT_STORAGE_KEY_PREFIX,\n} from \"./constants\";\nimport type { GridLayoutPreset } from \"./types\";\n\nexport interface GridPresetContextValue {\n presets: GridLayoutPreset[];\n selectedPresetId: string;\n setSelectedPresetId: (id: string) => void;\n layoutStorageKey: string;\n reset: () => void;\n rowHeight?: number;\n}\n\nconst GridPresetContext = createContext<GridPresetContextValue | null>(null);\n\nexport interface GridPresetProviderProps {\n presets: GridLayoutPreset[];\n persistLayout?: boolean;\n children: React.ReactNode;\n}\n\nexport function GridPresetProvider({\n presets,\n persistLayout = true,\n children,\n}: GridPresetProviderProps): React.ReactElement {\n const manager = useMemo(\n () =>\n new LayoutRuleManager(presets, {\n presetIdStorageKey: GRID_PRESET_ID_STORAGE_KEY,\n layoutStorageKeyPrefix: GRID_LAYOUT_STORAGE_KEY_PREFIX,\n persist: persistLayout,\n }),\n [presets, persistLayout],\n );\n\n const ruleState = useLayoutRuleManager(manager);\n\n const value = useMemo<GridPresetContextValue>(() => {\n const selectedPreset = (ruleState.presets as GridLayoutPreset[]).find(\n (p) => p.id === ruleState.selectedPresetId,\n );\n return {\n presets: ruleState.presets as GridLayoutPreset[],\n selectedPresetId: ruleState.selectedPresetId,\n setSelectedPresetId: ruleState.setSelectedPresetId,\n layoutStorageKey: ruleState.layoutStorageKey,\n reset: ruleState.reset,\n rowHeight: selectedPreset?.rowHeight,\n };\n }, [\n ruleState.presets,\n ruleState.selectedPresetId,\n ruleState.setSelectedPresetId,\n ruleState.layoutStorageKey,\n ruleState.reset,\n ]);\n\n return (\n <GridPresetContext.Provider value={value}>\n {children}\n </GridPresetContext.Provider>\n );\n}\n\nexport function useGridPresetContext(): GridPresetContextValue | null {\n return useContext(GridPresetContext);\n}\n","/** Preset dropdown; use inside GridPresetProvider. */\nimport React from \"react\";\nimport { useGridPresetContext } from \"./GridPresetContext\";\n\nexport interface GridLayoutSwitcherProps {\n className?: string;\n style?: React.CSSProperties;\n \"aria-label\"?: string;\n}\n\nexport function GridLayoutSwitcher({\n className,\n style,\n \"aria-label\": ariaLabel = \"Grid layout preset\",\n}: GridLayoutSwitcherProps): React.ReactElement | null {\n const ctx = useGridPresetContext();\n if (!ctx || ctx.presets.length === 0) return null;\n\n return (\n <select\n className={className}\n style={style}\n aria-label={ariaLabel}\n value={ctx.selectedPresetId}\n onChange={(e) => ctx.setSelectedPresetId(e.target.value)}\n >\n {ctx.presets.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n </option>\n ))}\n </select>\n );\n}\n","/// <reference types=\"@kodiak-finance/orderly-trading-next\" />\nimport React from \"react\";\nimport type { OrderlySDK } from \"@kodiak-finance/orderly-ui\";\nimport { createInterceptor } from \"@kodiak-finance/orderly-ui\";\nimport { GridDesktopInjector } from \"./components/GridDesktopInjector\";\nimport type { LayoutGridPluginOptions } from \"./types\";\nimport { getDefaultGridPresets } from \"./utils/defaultPresets\";\n\nconst PLUGIN_ID = \"orderly-layout-grid\";\nconst PLUGIN_NAME = \"Grid Layout\";\nconst PLUGIN_VERSION = \"1.0.0\";\n\nexport type { LayoutGridPluginOptions } from \"./types\";\n\n/** Registers the grid layout plugin (Trading.Layout.Desktop interceptor). */\nexport function registerLayoutGridPlugin(\n options?: LayoutGridPluginOptions,\n): (SDK: OrderlySDK) => void {\n const resolvedPresets = options?.presets ?? getDefaultGridPresets();\n\n return (SDK: OrderlySDK) => {\n SDK.registerPlugin({\n id: PLUGIN_ID,\n name: PLUGIN_NAME,\n version: PLUGIN_VERSION,\n orderlyVersion: \">=1.0.0\",\n interceptors: [\n createInterceptor(\"Trading.Layout.Desktop\", (Original, props) => (\n <GridDesktopInjector\n Original={\n Original as unknown as React.ComponentType<\n Record<string, unknown>\n >\n }\n props={props as unknown as Record<string, unknown>}\n options={{\n ...options,\n presets: resolvedPresets,\n }}\n />\n )),\n ],\n });\n };\n}\n","import React from \"react\";\nimport type { LayoutStrategy } from \"@kodiak-finance/orderly-layout-core\";\nimport type { DesktopLayoutInitialOptions } from \"@kodiak-finance/orderly-trading-next\";\nimport { gridStrategy } from \"../gridStrategy\";\nimport type { GridLayoutModel, LayoutGridPluginOptions } from \"../types\";\nimport { getDefaultGridPresets } from \"../utils/defaultPresets\";\nimport { mergeGridConfig } from \"../utils/gridLayoutUtils\";\nimport { createDefaultGetInitialLayout } from \"../utils/gridPluginConfig\";\n\nexport interface GridDesktopInjectorProps {\n Original: React.ComponentType<Record<string, unknown>>;\n props: Record<string, unknown>;\n options: LayoutGridPluginOptions;\n}\n\nexport function GridDesktopInjector({\n Original,\n props,\n options,\n}: GridDesktopInjectorProps): React.ReactElement {\n const presets = options.presets ?? getDefaultGridPresets();\n const presetRowHeight = presets[0]?.rowHeight;\n const gridConfig = mergeGridConfig(options.grid, presetRowHeight);\n\n const { persistLayout = false } = options;\n\n const getInitialLayout = React.useCallback(() => {\n const baseLayout =\n options.getInitialLayout?.() ?? createDefaultGetInitialLayout(presets)();\n return {\n ...baseLayout,\n rowHeight: gridConfig.rowHeight,\n margin: gridConfig.margin,\n containerPadding: gridConfig.containerPadding,\n compactType: gridConfig.compactType,\n isDraggable: gridConfig.isDraggable,\n isResizable: gridConfig.isResizable,\n };\n }, [\n options.getInitialLayout,\n presets,\n gridConfig.rowHeight,\n gridConfig.margin,\n gridConfig.containerPadding,\n gridConfig.compactType,\n gridConfig.isDraggable,\n gridConfig.isResizable,\n ]);\n\n const storageKey = persistLayout ? \"orderly_trading_grid\" : undefined;\n\n return (\n <Original\n {...props}\n layoutStrategy={gridStrategy as unknown as LayoutStrategy}\n getInitialLayout={\n (props.getInitialLayout as\n | ((opts: DesktopLayoutInitialOptions) => GridLayoutModel | undefined)\n | undefined) ??\n ((_opts: DesktopLayoutInitialOptions) => getInitialLayout())\n }\n storageKey={storageKey}\n disableLayoutPersistence={!persistLayout}\n />\n );\n}\n","import type { GridLayoutModel, GridLayoutPreset } from \"../types\";\nimport { createTradingGridLayoutFromPreset } from \"./tradingGridLayout\";\n\nexport function createDefaultGetInitialLayout(\n presets: GridLayoutPreset[],\n): () => GridLayoutModel {\n return () => {\n const preset = presets[0];\n return createTradingGridLayoutFromPreset(preset);\n };\n}\n"]}