@topconsultnpm/sdkui-react-beta 6.13.76 → 6.13.77
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/lib/components/index.d.ts +6 -3
- package/lib/components/index.js +7 -4
- package/package.json +1 -1
- package/lib/components/layout/TMPanelLayout.d.ts +0 -39
- package/lib/components/layout/TMPanelLayout.js +0 -318
- package/lib/components/layout/panel/TMPanelContext.d.ts +0 -45
- package/lib/components/layout/panel/TMPanelContext.js +0 -314
- package/lib/components/layout/panel/TMPanelToolbar.d.ts +0 -6
- package/lib/components/layout/panel/TMPanelToolbar.js +0 -66
- package/lib/components/layout/panel/useResizablePanels.d.ts +0 -3
- package/lib/components/layout/panel/useResizablePanels.js +0 -67
|
@@ -78,6 +78,9 @@ export { default as TMFileManagerThumbnailItems } from "./base/TMFileManagerThum
|
|
|
78
78
|
export { default as TMCounterContainer } from "./base/TMCounterContainer";
|
|
79
79
|
export * from "./base/TMCounterContainer";
|
|
80
80
|
export { default as TMAreaManager } from "./base/TMAreaManager";
|
|
81
|
-
export * from "./layout/
|
|
82
|
-
export * from "./layout/
|
|
83
|
-
export * from "./layout/
|
|
81
|
+
export * from "./layout/panelManager/TMPanelManagerContainer";
|
|
82
|
+
export * from "./layout/panelManager/TMPanelManagerContext";
|
|
83
|
+
export * from "./layout/panelManager/TMPanelManagerToolbar";
|
|
84
|
+
export * from "./layout/panelManager/TMPanelWrapper";
|
|
85
|
+
export * from "./layout/panelManager/types";
|
|
86
|
+
export * from "./layout/panelManager/utils";
|
package/lib/components/index.js
CHANGED
|
@@ -93,7 +93,10 @@ export { default as TMFileManagerThumbnailItems } from "./base/TMFileManagerThum
|
|
|
93
93
|
export { default as TMCounterContainer } from "./base/TMCounterContainer";
|
|
94
94
|
export * from "./base/TMCounterContainer";
|
|
95
95
|
export { default as TMAreaManager } from "./base/TMAreaManager";
|
|
96
|
-
//
|
|
97
|
-
export * from "./layout/
|
|
98
|
-
export * from "./layout/
|
|
99
|
-
export * from "./layout/
|
|
96
|
+
// panel manager
|
|
97
|
+
export * from "./layout/panelManager/TMPanelManagerContainer";
|
|
98
|
+
export * from "./layout/panelManager/TMPanelManagerContext";
|
|
99
|
+
export * from "./layout/panelManager/TMPanelManagerToolbar";
|
|
100
|
+
export * from "./layout/panelManager/TMPanelWrapper";
|
|
101
|
+
export * from "./layout/panelManager/types";
|
|
102
|
+
export * from "./layout/panelManager/utils";
|
package/package.json
CHANGED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react';
|
|
2
|
-
type TMPanelManagerNewProps = {
|
|
3
|
-
children: ReactNode;
|
|
4
|
-
showToolbar?: boolean;
|
|
5
|
-
emptyContent?: ReactNode;
|
|
6
|
-
};
|
|
7
|
-
type TMPanelGroupProps = {
|
|
8
|
-
orientation?: 'horizontal' | 'vertical';
|
|
9
|
-
allowItemResize?: boolean;
|
|
10
|
-
gutters?: number;
|
|
11
|
-
panelVisibility?: boolean[];
|
|
12
|
-
onTogglePanel?: (idx: number) => void;
|
|
13
|
-
panelLabels?: string[];
|
|
14
|
-
children: ReactNode;
|
|
15
|
-
parentVisibility?: boolean;
|
|
16
|
-
parentPanelCount?: number;
|
|
17
|
-
parentPanelVisibility?: boolean[];
|
|
18
|
-
parentOnTogglePanel?: (idx: number, path: number[]) => void;
|
|
19
|
-
path?: number[];
|
|
20
|
-
};
|
|
21
|
-
type TMPanelItemProps = {
|
|
22
|
-
width?: string;
|
|
23
|
-
height?: string;
|
|
24
|
-
minWidth?: string;
|
|
25
|
-
minHeight?: string;
|
|
26
|
-
children: ReactNode;
|
|
27
|
-
style?: React.CSSProperties;
|
|
28
|
-
label?: string;
|
|
29
|
-
};
|
|
30
|
-
export declare const TMPanelItem: React.FC<TMPanelItemProps>;
|
|
31
|
-
export declare const TMPanelGroup: React.FC<TMPanelGroupProps>;
|
|
32
|
-
declare const TMPanelLayout: React.FC<TMPanelManagerNewProps>;
|
|
33
|
-
export default TMPanelLayout;
|
|
34
|
-
type TMPanelLayoutToolbarProps = {
|
|
35
|
-
panelLabels: string[];
|
|
36
|
-
panelVisibility: boolean[];
|
|
37
|
-
onTogglePanel: (idx: number) => void;
|
|
38
|
-
};
|
|
39
|
-
export declare const TMPanelLayoutToolbar: React.FC<TMPanelLayoutToolbarProps>;
|
|
@@ -1,318 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useRef, useState, Children, cloneElement, isValidElement, useEffect, useMemo, } from 'react';
|
|
3
|
-
import { SDKUI_Globals } from '../../helper';
|
|
4
|
-
import { useDeviceType } from '../base/TMDeviceProvider';
|
|
5
|
-
export const TMPanelItem = (props) => (_jsx("div", { style: {
|
|
6
|
-
flexBasis: props.width || props.height || 'auto',
|
|
7
|
-
minWidth: props.minWidth,
|
|
8
|
-
minHeight: props.minHeight,
|
|
9
|
-
flexGrow: 0,
|
|
10
|
-
flexShrink: 0,
|
|
11
|
-
height: '100%',
|
|
12
|
-
width: '100%',
|
|
13
|
-
// overflow: 'auto',
|
|
14
|
-
position: 'relative',
|
|
15
|
-
boxSizing: 'border-box',
|
|
16
|
-
display: 'flex',
|
|
17
|
-
flexDirection: 'column',
|
|
18
|
-
...props.style,
|
|
19
|
-
}, children: props.children }));
|
|
20
|
-
// Utility: recursively determine if a child is a group
|
|
21
|
-
function isGroup(child) {
|
|
22
|
-
return child?.type?.displayName === 'TMPanelGroup';
|
|
23
|
-
}
|
|
24
|
-
TMPanelItem.displayName = 'TMPanelItem';
|
|
25
|
-
export const TMPanelGroup = ({ orientation = 'horizontal', allowItemResize = false, gutters = SDKUI_Globals.userSettings.themeSettings.gutters, panelVisibility, onTogglePanel, panelLabels, children, parentVisibility = true, parentPanelCount, parentPanelVisibility, parentOnTogglePanel, path = [], ...rest }) => {
|
|
26
|
-
const childArray = Children.toArray(children).filter(Boolean);
|
|
27
|
-
const panelCount = childArray.length;
|
|
28
|
-
// Initial sizes in percent
|
|
29
|
-
const [sizes, setSizes] = useState(childArray.map((child) => orientation === 'horizontal'
|
|
30
|
-
? child.props.width
|
|
31
|
-
? parseFloat(child.props.width)
|
|
32
|
-
: 100 / panelCount
|
|
33
|
-
: child.props.height
|
|
34
|
-
? parseFloat(child.props.height)
|
|
35
|
-
: 100 / panelCount));
|
|
36
|
-
// Compute effective visibility for each child (recursively for groups)
|
|
37
|
-
const effectiveVisibility = childArray.map((child, idx) => {
|
|
38
|
-
if (isValidElement(child) && isGroup(child)) {
|
|
39
|
-
// For nested groups, pass down visibility
|
|
40
|
-
return !panelVisibility || panelVisibility[idx];
|
|
41
|
-
}
|
|
42
|
-
return !panelVisibility || panelVisibility[idx];
|
|
43
|
-
});
|
|
44
|
-
// Recursively render children, and collect which are visible
|
|
45
|
-
const renderedPanels = [];
|
|
46
|
-
const renderedSizes = [];
|
|
47
|
-
const renderedPaths = [];
|
|
48
|
-
let accHidden = 0;
|
|
49
|
-
for (let i = 0; i < panelCount; i++) {
|
|
50
|
-
const child = childArray[i];
|
|
51
|
-
const visible = effectiveVisibility[i];
|
|
52
|
-
let childIsVisible = visible;
|
|
53
|
-
let renderedChild = child;
|
|
54
|
-
let childPath = [...path, i];
|
|
55
|
-
if (isValidElement(child) && isGroup(child)) {
|
|
56
|
-
// Recursively render group
|
|
57
|
-
renderedChild = cloneElement(child, {
|
|
58
|
-
parentVisibility: visible,
|
|
59
|
-
parentPanelCount: panelCount,
|
|
60
|
-
parentPanelVisibility: panelVisibility,
|
|
61
|
-
parentOnTogglePanel: parentOnTogglePanel || onTogglePanel,
|
|
62
|
-
path: childPath,
|
|
63
|
-
});
|
|
64
|
-
// If the group renders nothing, treat as hidden
|
|
65
|
-
// We'll check after rendering below
|
|
66
|
-
}
|
|
67
|
-
// For groups, check if they actually rendered anything
|
|
68
|
-
let actuallyVisible = childIsVisible;
|
|
69
|
-
if (isValidElement(child) && isGroup(child)) {
|
|
70
|
-
// If the group is not visible (returns null), treat as hidden
|
|
71
|
-
// We'll check after rendering below
|
|
72
|
-
// For now, optimistically add, and filter after
|
|
73
|
-
renderedPanels.push(renderedChild);
|
|
74
|
-
renderedSizes.push(sizes[i] + accHidden);
|
|
75
|
-
renderedPaths.push(childPath);
|
|
76
|
-
accHidden = 0;
|
|
77
|
-
}
|
|
78
|
-
else if (childIsVisible) {
|
|
79
|
-
renderedPanels.push(renderedChild);
|
|
80
|
-
renderedSizes.push(sizes[i] + accHidden);
|
|
81
|
-
renderedPaths.push(childPath);
|
|
82
|
-
accHidden = 0;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
accHidden += sizes[i];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
// Remove panels that are null (hidden nested groups)
|
|
89
|
-
let filteredPanels = [];
|
|
90
|
-
let filteredSizes = [];
|
|
91
|
-
let filteredPaths = [];
|
|
92
|
-
let filteredAccHidden = 0;
|
|
93
|
-
for (let i = 0; i < renderedPanels.length; i++) {
|
|
94
|
-
if (renderedPanels[i] !== null && renderedPanels[i] !== undefined) {
|
|
95
|
-
filteredPanels.push(renderedPanels[i]);
|
|
96
|
-
filteredSizes.push(renderedSizes[i] + filteredAccHidden);
|
|
97
|
-
filteredPaths.push(renderedPaths[i]);
|
|
98
|
-
filteredAccHidden = 0;
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
filteredAccHidden += renderedSizes[i];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
// --- CORRECTED MERGING LOGIC: merge hidden into previous visible, or into the first visible if at the start ---
|
|
105
|
-
// Merge hidden panel sizes into the nearest visible sibling (prefer previous, else next)
|
|
106
|
-
const mergedPanels = [];
|
|
107
|
-
const mergedSizes = [];
|
|
108
|
-
const mergedPaths = [];
|
|
109
|
-
let lastVisibleIdx = -1;
|
|
110
|
-
for (let i = 0; i < filteredPanels.length; i++) {
|
|
111
|
-
if (filteredPanels[i] !== null && filteredPanels[i] !== undefined) {
|
|
112
|
-
// If there were hidden panels before the first visible, merge their sizes into this first visible
|
|
113
|
-
if (lastVisibleIdx === -1 && i > 0) {
|
|
114
|
-
let acc = 0;
|
|
115
|
-
for (let j = 0; j < i; j++)
|
|
116
|
-
acc += filteredSizes[j];
|
|
117
|
-
mergedSizes.push(filteredSizes[i] + acc);
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
mergedSizes.push(filteredSizes[i]);
|
|
121
|
-
}
|
|
122
|
-
mergedPanels.push(filteredPanels[i]);
|
|
123
|
-
mergedPaths.push(filteredPaths[i]);
|
|
124
|
-
lastVisibleIdx = mergedSizes.length - 1;
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
// Hidden panel: merge its size into the last visible panel (if any)
|
|
128
|
-
if (lastVisibleIdx >= 0) {
|
|
129
|
-
mergedSizes[lastVisibleIdx] += filteredSizes[i];
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// If nothing is visible, tell parent to treat this group as hidden
|
|
134
|
-
if (mergedPanels.length === 0 || parentVisibility === false) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
// Resizing logic (same as before, but for visible panels)
|
|
138
|
-
const containerRef = useRef(null);
|
|
139
|
-
const [dragIndex, setDragIndex] = useState(null);
|
|
140
|
-
const [startPos, setStartPos] = useState(0);
|
|
141
|
-
const [startSizes, setStartSizes] = useState([]);
|
|
142
|
-
const handleMouseDown = (idx) => (e) => {
|
|
143
|
-
setDragIndex(idx);
|
|
144
|
-
setStartSizes([...mergedSizes]);
|
|
145
|
-
setStartPos(orientation === 'horizontal' ? e.clientX : e.clientY);
|
|
146
|
-
document.body.style.userSelect = 'none';
|
|
147
|
-
};
|
|
148
|
-
useEffect(() => {
|
|
149
|
-
if (dragIndex === null)
|
|
150
|
-
return;
|
|
151
|
-
const handleMouseMove = (e) => {
|
|
152
|
-
if (!containerRef.current)
|
|
153
|
-
return;
|
|
154
|
-
const rect = containerRef.current.getBoundingClientRect();
|
|
155
|
-
const total = orientation === 'horizontal' ? rect.width : rect.height;
|
|
156
|
-
const currentPos = orientation === 'horizontal' ? e.clientX : e.clientY;
|
|
157
|
-
const deltaPx = currentPos - startPos;
|
|
158
|
-
const deltaPercent = (deltaPx / total) * 100;
|
|
159
|
-
let newSizes = [...startSizes];
|
|
160
|
-
let left = Math.max(5, startSizes[dragIndex] + deltaPercent);
|
|
161
|
-
let right = Math.max(5, startSizes[dragIndex + 1] - deltaPercent);
|
|
162
|
-
// Prevent overflow
|
|
163
|
-
const sum = startSizes[dragIndex] + startSizes[dragIndex + 1];
|
|
164
|
-
if (left + right > sum) {
|
|
165
|
-
if (left > sum - 5)
|
|
166
|
-
left = sum - 5;
|
|
167
|
-
if (right > sum - 5)
|
|
168
|
-
right = sum - 5;
|
|
169
|
-
}
|
|
170
|
-
newSizes[dragIndex] = left;
|
|
171
|
-
newSizes[dragIndex + 1] = right;
|
|
172
|
-
// Update the original sizes array for all panels
|
|
173
|
-
let newAllSizes = [...sizes];
|
|
174
|
-
let visIdx = 0;
|
|
175
|
-
for (let k = 0; k < panelCount; k++) {
|
|
176
|
-
if (effectiveVisibility[k]) {
|
|
177
|
-
// Only update for visible panels
|
|
178
|
-
newAllSizes[k] = newSizes[visIdx++];
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
setSizes(newAllSizes);
|
|
182
|
-
};
|
|
183
|
-
const handleMouseUp = () => {
|
|
184
|
-
setDragIndex(null);
|
|
185
|
-
document.body.style.userSelect = '';
|
|
186
|
-
};
|
|
187
|
-
window.addEventListener('mousemove', handleMouseMove);
|
|
188
|
-
window.addEventListener('mouseup', handleMouseUp);
|
|
189
|
-
return () => {
|
|
190
|
-
window.removeEventListener('mousemove', handleMouseMove);
|
|
191
|
-
window.removeEventListener('mouseup', handleMouseUp);
|
|
192
|
-
};
|
|
193
|
-
}, [dragIndex, orientation, startPos, startSizes, effectiveVisibility, sizes, panelCount]);
|
|
194
|
-
return (_jsx("div", { ref: containerRef, style: {
|
|
195
|
-
display: 'flex',
|
|
196
|
-
flexDirection: orientation === 'horizontal' ? 'row' : 'column',
|
|
197
|
-
width: '100%',
|
|
198
|
-
height: '100%',
|
|
199
|
-
position: 'relative',
|
|
200
|
-
overflow: 'hidden',
|
|
201
|
-
gap: allowItemResize ? 0 : gutters,
|
|
202
|
-
}, ...rest, children: mergedPanels.map((child, idx) => (_jsxs(React.Fragment, { children: [isValidElement(child) && !isGroup(child)
|
|
203
|
-
? cloneElement(child, {
|
|
204
|
-
style: {
|
|
205
|
-
...(child.props.style || {}),
|
|
206
|
-
flexBasis: `${mergedSizes[idx]}%`,
|
|
207
|
-
height: orientation === 'vertical'
|
|
208
|
-
? `${mergedSizes[idx]}%`
|
|
209
|
-
: '100%',
|
|
210
|
-
width: orientation === 'horizontal'
|
|
211
|
-
? `${mergedSizes[idx]}%`
|
|
212
|
-
: '100%',
|
|
213
|
-
},
|
|
214
|
-
})
|
|
215
|
-
: child, allowItemResize && idx < mergedPanels.length - 1 && (_jsx("div", { style: {
|
|
216
|
-
cursor: orientation === 'horizontal'
|
|
217
|
-
? 'col-resize'
|
|
218
|
-
: 'row-resize',
|
|
219
|
-
background: 'transparent',
|
|
220
|
-
width: orientation === 'horizontal' ? gutters : '100%',
|
|
221
|
-
height: orientation === 'vertical' ? gutters : '100%',
|
|
222
|
-
zIndex: 10,
|
|
223
|
-
userSelect: 'none',
|
|
224
|
-
flexShrink: 0,
|
|
225
|
-
flexGrow: 0,
|
|
226
|
-
borderRadius: 3,
|
|
227
|
-
minHeight: orientation === 'horizontal' ? '100%' : gutters,
|
|
228
|
-
minWidth: orientation === 'vertical' ? '100%' : gutters,
|
|
229
|
-
}, onMouseDown: handleMouseDown(idx) }))] }, mergedPaths[idx].join('-')))) }));
|
|
230
|
-
};
|
|
231
|
-
TMPanelGroup.displayName = 'TMPanelGroup';
|
|
232
|
-
function getAllPanelPaths(children, path = []) {
|
|
233
|
-
const arr = Children.toArray(children).filter(Boolean);
|
|
234
|
-
let result = [];
|
|
235
|
-
arr.forEach((child, idx) => {
|
|
236
|
-
if (isValidElement(child) && isGroup(child)) {
|
|
237
|
-
result = result.concat(getAllPanelPaths(child.props.children, [...path, idx]));
|
|
238
|
-
}
|
|
239
|
-
else if (isValidElement(child)) {
|
|
240
|
-
result.push({ label: child.props?.label || `Panel ${path.concat(idx).join('-')}`, path: path.concat(idx) });
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
return result;
|
|
244
|
-
}
|
|
245
|
-
const TMPanelLayout = ({ children, showToolbar = true, emptyContent, }) => {
|
|
246
|
-
// Only support a single TMPanelGroup as direct child for simplicity
|
|
247
|
-
const group = Children.only(children);
|
|
248
|
-
const childArray = Children.toArray(group.props.children).filter(Boolean);
|
|
249
|
-
// Build a flat list of all panel paths and labels for the toolbar
|
|
250
|
-
const allPanels = useMemo(() => getAllPanelPaths(group.props.children), [group.props.children]);
|
|
251
|
-
const [panelVisibility, setPanelVisibility] = useState(childArray.map(() => true));
|
|
252
|
-
// Helper to check if all panels (recursively) are hidden
|
|
253
|
-
function isAllPanelsHidden() {
|
|
254
|
-
// For now, just check top-level
|
|
255
|
-
return panelVisibility.every(v => !v);
|
|
256
|
-
}
|
|
257
|
-
// Toggle panel visibility by path (only top-level supported for now)
|
|
258
|
-
const handleTogglePanel = (idx) => {
|
|
259
|
-
setPanelVisibility((prev) => {
|
|
260
|
-
if (prev.filter(Boolean).length === 1 && prev[idx])
|
|
261
|
-
return prev;
|
|
262
|
-
const newArr = [...prev];
|
|
263
|
-
newArr[idx] = !newArr[idx];
|
|
264
|
-
return newArr;
|
|
265
|
-
});
|
|
266
|
-
};
|
|
267
|
-
// For nested: you can extend this to track nested visibility state if needed
|
|
268
|
-
const allHidden = isAllPanelsHidden();
|
|
269
|
-
const deviceType = useDeviceType();
|
|
270
|
-
const isMobile = useMemo(() => deviceType === 'mobile', [deviceType]);
|
|
271
|
-
return (_jsx("div", { style: {
|
|
272
|
-
width: '100%',
|
|
273
|
-
height: '100%',
|
|
274
|
-
position: 'relative',
|
|
275
|
-
overflow: 'hidden',
|
|
276
|
-
display: 'flex',
|
|
277
|
-
flexDirection: 'column',
|
|
278
|
-
}, children: _jsxs("div", { style: { display: 'flex', flexDirection: isMobile ? 'column' : 'row', height: '100%', width: '100%', gap: !isMobile ? SDKUI_Globals.userSettings.themeSettings.gutters : 0 }, children: [!allHidden &&
|
|
279
|
-
cloneElement(group, {
|
|
280
|
-
panelVisibility,
|
|
281
|
-
onTogglePanel: handleTogglePanel,
|
|
282
|
-
panelLabels: allPanels.map(p => p.label),
|
|
283
|
-
}), showToolbar && (_jsx("div", { style: {
|
|
284
|
-
display: 'flex',
|
|
285
|
-
flexDirection: isMobile ? 'row' : 'column',
|
|
286
|
-
alignItems: 'center',
|
|
287
|
-
width: isMobile ? '100%' : '50px',
|
|
288
|
-
height: isMobile ? '50px' : 'max-content',
|
|
289
|
-
background: 'transparent linear-gradient(90deg, #CCE0F4 0%, #7EC1E7 14%, #39A6DB 28%, #1E9CD7 35%, #0075BE 78%, #005B97 99%) 0% 0% no-repeat padding-box',
|
|
290
|
-
borderRadius: isMobile ? '10px' : '10px 0px 0px 10px',
|
|
291
|
-
padding: '10px',
|
|
292
|
-
gap: '10px'
|
|
293
|
-
}, children: _jsx(TMPanelLayoutToolbar, { panelLabels: allPanels.map(p => p.label), panelVisibility: panelVisibility, onTogglePanel: handleTogglePanel }) })), allHidden && (_jsx("div", { style: {
|
|
294
|
-
position: 'absolute',
|
|
295
|
-
left: 0,
|
|
296
|
-
top: 0,
|
|
297
|
-
width: '100%',
|
|
298
|
-
height: '100%',
|
|
299
|
-
background: '#fafbfc',
|
|
300
|
-
display: 'flex',
|
|
301
|
-
alignItems: 'center',
|
|
302
|
-
justifyContent: 'center',
|
|
303
|
-
zIndex: 1,
|
|
304
|
-
}, children: emptyContent || (_jsx("span", { style: { color: '#888', fontSize: 18 }, children: "No panels visible" })) }))] }) }));
|
|
305
|
-
};
|
|
306
|
-
export default TMPanelLayout;
|
|
307
|
-
export const TMPanelLayoutToolbar = ({ panelLabels, panelVisibility, onTogglePanel, }) => {
|
|
308
|
-
return (_jsx("div", { children: panelLabels.map((label, idx) => (_jsxs("button", { style: {
|
|
309
|
-
margin: 2,
|
|
310
|
-
padding: '4px 10px',
|
|
311
|
-
borderRadius: 4,
|
|
312
|
-
border: panelVisibility[idx] ? '2px solid #1976d2' : '1px solid #bbb',
|
|
313
|
-
background: panelVisibility[idx] ? '#1976d2' : '#eee',
|
|
314
|
-
color: panelVisibility[idx] ? '#fff' : '#555',
|
|
315
|
-
cursor: 'pointer',
|
|
316
|
-
opacity: 1,
|
|
317
|
-
}, onClick: () => onTogglePanel(idx), children: [panelVisibility[idx] ? 'Hide' : 'Show', " ", label] }, idx))) }));
|
|
318
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
export interface TMPanelManagerItemContext {
|
|
3
|
-
id: string;
|
|
4
|
-
name: string;
|
|
5
|
-
contentOptions: {
|
|
6
|
-
width: string;
|
|
7
|
-
height: string;
|
|
8
|
-
};
|
|
9
|
-
toolbarOptions: {
|
|
10
|
-
icon: string | JSX.Element;
|
|
11
|
-
visible: boolean;
|
|
12
|
-
isActive: boolean;
|
|
13
|
-
disabled?: boolean;
|
|
14
|
-
orderNumber?: number;
|
|
15
|
-
beginGroup?: boolean;
|
|
16
|
-
alwaysActiveColor?: boolean;
|
|
17
|
-
};
|
|
18
|
-
children: Array<TMPanelManagerItemContext>;
|
|
19
|
-
}
|
|
20
|
-
interface ITMPanelManagerContext {
|
|
21
|
-
panelTree: Array<TMPanelManagerItemContext>;
|
|
22
|
-
visibility: Record<string, boolean>;
|
|
23
|
-
calculateEffectiveVisibility: Record<string, boolean>;
|
|
24
|
-
setPanelVisibility: (id: string, visible: boolean) => void;
|
|
25
|
-
togglePanel: (id: string) => void;
|
|
26
|
-
findPanelById: (id: string) => TMPanelManagerItemContext | undefined;
|
|
27
|
-
getPanelDimensions: (id: string) => {
|
|
28
|
-
width: string;
|
|
29
|
-
height: string;
|
|
30
|
-
};
|
|
31
|
-
toggleMaximizePanel: (id: string) => void;
|
|
32
|
-
maximizedPanelId: string | null;
|
|
33
|
-
updatePanelSize: (id: string, width: string | number, height: string | number) => void;
|
|
34
|
-
setPanelVisibleById: (id: string, visible: boolean) => void;
|
|
35
|
-
setPanelDisabledById: (id: string, disabled: boolean) => void;
|
|
36
|
-
hasVisiblePanels: () => boolean;
|
|
37
|
-
}
|
|
38
|
-
export declare function useTMPanelContext(): ITMPanelManagerContext;
|
|
39
|
-
interface TMPanelContextProviderProps {
|
|
40
|
-
panels: Array<TMPanelManagerItemContext>;
|
|
41
|
-
initialMobilePanelId: string;
|
|
42
|
-
children: ReactNode;
|
|
43
|
-
}
|
|
44
|
-
export declare const TMPanelManagerContextProvider: (props: TMPanelContextProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
45
|
-
export {};
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { createContext, useContext, useMemo, useState, useEffect, } from 'react';
|
|
3
|
-
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
4
|
-
// Creazione del context
|
|
5
|
-
const TMPanelManagerContext = createContext(undefined);
|
|
6
|
-
// Hook custom per accedere al context
|
|
7
|
-
export function useTMPanelContext() {
|
|
8
|
-
const context = useContext(TMPanelManagerContext);
|
|
9
|
-
if (!context) {
|
|
10
|
-
throw new Error('useTMPanelContext must be used within a TMPanelContextProvider');
|
|
11
|
-
}
|
|
12
|
-
return context;
|
|
13
|
-
}
|
|
14
|
-
// Provider del context
|
|
15
|
-
export const TMPanelManagerContextProvider = (props) => {
|
|
16
|
-
const { panels, initialMobilePanelId, children } = props;
|
|
17
|
-
const [panelTree, setPanelTree] = useState(panels);
|
|
18
|
-
const [maximizedPanelId, setMaximizedPanelId] = useState(null);
|
|
19
|
-
const deviceType = useDeviceType();
|
|
20
|
-
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (isMobile) {
|
|
23
|
-
setVisibility(prev => updatePanelVisibility(initialMobilePanelId, true, prev));
|
|
24
|
-
}
|
|
25
|
-
}, [isMobile]);
|
|
26
|
-
// Stato iniziale per dimensioni pannelli
|
|
27
|
-
const [panelSizes, setPanelSizes] = useState(() => {
|
|
28
|
-
const sizes = {};
|
|
29
|
-
const flattenPanels = (panels) => panels.reduce((acc, p) => [...acc, p, ...flattenPanels(p.children)], []);
|
|
30
|
-
const allPanels = flattenPanels(panelTree);
|
|
31
|
-
allPanels.forEach(panel => {
|
|
32
|
-
sizes[panel.id] = { width: panel.contentOptions.width, height: panel.contentOptions.height };
|
|
33
|
-
});
|
|
34
|
-
return sizes;
|
|
35
|
-
});
|
|
36
|
-
// Trova un pannello tramite ID
|
|
37
|
-
const findPanelById = (id) => {
|
|
38
|
-
const findRecursive = (panels) => {
|
|
39
|
-
for (const panel of panels) {
|
|
40
|
-
if (panel.id === id)
|
|
41
|
-
return panel;
|
|
42
|
-
const found = findRecursive(panel.children);
|
|
43
|
-
if (found)
|
|
44
|
-
return found;
|
|
45
|
-
}
|
|
46
|
-
return undefined;
|
|
47
|
-
};
|
|
48
|
-
return findRecursive(panelTree);
|
|
49
|
-
};
|
|
50
|
-
// Mappa figlio -> genitori
|
|
51
|
-
const parentMap = useMemo(() => {
|
|
52
|
-
const map = new Map();
|
|
53
|
-
const buildMap = (panels, parents = []) => {
|
|
54
|
-
for (const panel of panels) {
|
|
55
|
-
map.set(panel.id, [...parents]);
|
|
56
|
-
buildMap(panel.children, [...parents, panel.id]);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
buildMap(panelTree);
|
|
60
|
-
return map;
|
|
61
|
-
}, [panelTree]);
|
|
62
|
-
// Mappa genitore -> figli
|
|
63
|
-
const parentToChildrenMap = useMemo(() => {
|
|
64
|
-
const map = new Map();
|
|
65
|
-
const buildMap = (panels) => {
|
|
66
|
-
for (const panel of panels) {
|
|
67
|
-
map.set(panel.id, panel.children.map(c => c.id));
|
|
68
|
-
buildMap(panel.children);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
buildMap(panelTree);
|
|
72
|
-
return map;
|
|
73
|
-
}, [panelTree]);
|
|
74
|
-
// Stato visibilità iniziale
|
|
75
|
-
const getInitialVisibility = (panels) => {
|
|
76
|
-
const vis = {};
|
|
77
|
-
const collect = (panels) => {
|
|
78
|
-
for (const panel of panels) {
|
|
79
|
-
vis[panel.id] = panel.toolbarOptions?.isActive ?? false;
|
|
80
|
-
collect(panel.children);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
collect(panels);
|
|
84
|
-
return vis;
|
|
85
|
-
};
|
|
86
|
-
const [visibility, setVisibility] = useState(() => getInitialVisibility(panelTree));
|
|
87
|
-
const getParentsOfPanel = (id) => parentMap.get(id) || [];
|
|
88
|
-
// Visibilità effettiva tenendo conto della gerarchia
|
|
89
|
-
const calculateEffectiveVisibility = useMemo(() => {
|
|
90
|
-
if (maximizedPanelId) {
|
|
91
|
-
return { ...visibility };
|
|
92
|
-
}
|
|
93
|
-
const updatedVisibility = { ...visibility };
|
|
94
|
-
const propagateToParents = (id) => {
|
|
95
|
-
for (const parent of parentMap.get(id) || []) {
|
|
96
|
-
if (!updatedVisibility[parent]) {
|
|
97
|
-
updatedVisibility[parent] = true;
|
|
98
|
-
propagateToParents(parent);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
Object.entries(updatedVisibility).forEach(([id, isVisible]) => {
|
|
103
|
-
if (isVisible)
|
|
104
|
-
propagateToParents(id);
|
|
105
|
-
});
|
|
106
|
-
const deactivateIfNoVisibleChildren = (parentId) => {
|
|
107
|
-
const children = parentToChildrenMap.get(parentId) || [];
|
|
108
|
-
if (children.length === 0)
|
|
109
|
-
return;
|
|
110
|
-
const anyVisible = children.some(id => updatedVisibility[id]);
|
|
111
|
-
if (!anyVisible && updatedVisibility[parentId]) {
|
|
112
|
-
updatedVisibility[parentId] = false;
|
|
113
|
-
for (const grand of parentMap.get(parentId) || []) {
|
|
114
|
-
deactivateIfNoVisibleChildren(grand);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
for (const parentId of parentToChildrenMap.keys()) {
|
|
119
|
-
deactivateIfNoVisibleChildren(parentId);
|
|
120
|
-
}
|
|
121
|
-
return updatedVisibility;
|
|
122
|
-
}, [visibility, parentMap, parentToChildrenMap, maximizedPanelId]);
|
|
123
|
-
// Calcolo delle dimensioni dinamiche in base alla visibilità
|
|
124
|
-
const dynamicSizesMap = useMemo(() => {
|
|
125
|
-
const flattenPanels = (panels) => panels.reduce((acc, p) => [...acc, p, ...flattenPanels(p.children)], []);
|
|
126
|
-
const allPanels = flattenPanels(panelTree);
|
|
127
|
-
const originalHeights = new Map();
|
|
128
|
-
const originalWidths = new Map();
|
|
129
|
-
allPanels.forEach(panel => {
|
|
130
|
-
originalHeights.set(panel.id, parseFloat(panel.contentOptions.height) || 0);
|
|
131
|
-
originalWidths.set(panel.id, parseFloat(panel.contentOptions.width) || 0);
|
|
132
|
-
});
|
|
133
|
-
if (maximizedPanelId) {
|
|
134
|
-
const parents = getParentsOfPanel(maximizedPanelId);
|
|
135
|
-
const allowed = new Set([maximizedPanelId, ...parents]);
|
|
136
|
-
const sizesMap = {};
|
|
137
|
-
allPanels.forEach(panel => {
|
|
138
|
-
sizesMap[panel.id] = allowed.has(panel.id)
|
|
139
|
-
? { width: '100%', height: '100%' }
|
|
140
|
-
: { width: '0%', height: '0%' };
|
|
141
|
-
});
|
|
142
|
-
return sizesMap;
|
|
143
|
-
}
|
|
144
|
-
const calcSiblingSizes = (siblings, originalSizes) => {
|
|
145
|
-
const visibleSiblings = siblings.filter(s => calculateEffectiveVisibility[s.id]);
|
|
146
|
-
const totalVisible = visibleSiblings.reduce((sum, s) => sum + (originalSizes.get(s.id) || 0), 0);
|
|
147
|
-
const totalAll = siblings.reduce((sum, s) => sum + (originalSizes.get(s.id) || 0), 0);
|
|
148
|
-
const map = {};
|
|
149
|
-
visibleSiblings.forEach(s => {
|
|
150
|
-
const orig = originalSizes.get(s.id) || 0;
|
|
151
|
-
map[s.id] = totalVisible === 0 ? 0 : (orig / totalVisible) * totalAll;
|
|
152
|
-
});
|
|
153
|
-
siblings.forEach(s => {
|
|
154
|
-
if (!calculateEffectiveVisibility[s.id])
|
|
155
|
-
map[s.id] = 0;
|
|
156
|
-
});
|
|
157
|
-
return map;
|
|
158
|
-
};
|
|
159
|
-
const widthSizesMap = {};
|
|
160
|
-
const heightSizesMap = {};
|
|
161
|
-
Object.assign(widthSizesMap, calcSiblingSizes(panelTree, originalWidths));
|
|
162
|
-
Object.assign(heightSizesMap, calcSiblingSizes(panelTree, originalHeights));
|
|
163
|
-
const processChildrenSizes = (panels) => {
|
|
164
|
-
panels.forEach(panel => {
|
|
165
|
-
if (panel.children.length > 0) {
|
|
166
|
-
Object.assign(widthSizesMap, calcSiblingSizes(panel.children, originalWidths));
|
|
167
|
-
Object.assign(heightSizesMap, calcSiblingSizes(panel.children, originalHeights));
|
|
168
|
-
processChildrenSizes(panel.children);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
};
|
|
172
|
-
processChildrenSizes(panelTree);
|
|
173
|
-
const sizesMap = {};
|
|
174
|
-
allPanels.forEach(panel => {
|
|
175
|
-
const width = Math.min(widthSizesMap[panel.id] ?? 0, 100);
|
|
176
|
-
const height = Math.min(heightSizesMap[panel.id] ?? 0, 100);
|
|
177
|
-
sizesMap[panel.id] = {
|
|
178
|
-
width: calculateEffectiveVisibility[panel.id] ? `${width.toFixed(2)}%` : '0%',
|
|
179
|
-
height: calculateEffectiveVisibility[panel.id] ? `${height.toFixed(2)}%` : '0%',
|
|
180
|
-
};
|
|
181
|
-
});
|
|
182
|
-
return sizesMap;
|
|
183
|
-
}, [calculateEffectiveVisibility, panelTree, maximizedPanelId]);
|
|
184
|
-
// Ottieni dimensioni di un pannello (override -> dinamico -> default)
|
|
185
|
-
const getPanelDimensions = (id) => {
|
|
186
|
-
if (panelSizes[id])
|
|
187
|
-
return panelSizes[id];
|
|
188
|
-
if (dynamicSizesMap[id])
|
|
189
|
-
return dynamicSizesMap[id];
|
|
190
|
-
const panel = findPanelById(id);
|
|
191
|
-
return panel ? { width: panel.contentOptions.width, height: panel.contentOptions.height } : { width: 'auto', height: 'auto' };
|
|
192
|
-
};
|
|
193
|
-
// Imposta manualmente le dimensioni di un pannello
|
|
194
|
-
const updatePanelSize = (id, width, height) => {
|
|
195
|
-
setPanelSizes(prev => ({
|
|
196
|
-
...prev,
|
|
197
|
-
[id]: {
|
|
198
|
-
width: typeof width === 'number' ? `${width}%` : width,
|
|
199
|
-
height: typeof height === 'number' ? `${height}%` : height,
|
|
200
|
-
},
|
|
201
|
-
}));
|
|
202
|
-
};
|
|
203
|
-
// Quando cambia visibilità o massimizzazione, resetta override
|
|
204
|
-
useEffect(() => {
|
|
205
|
-
setPanelSizes({});
|
|
206
|
-
}, [visibility, maximizedPanelId]);
|
|
207
|
-
// Massimizza o ripristina un pannello
|
|
208
|
-
const toggleMaximizePanel = (id) => {
|
|
209
|
-
setMaximizedPanelId(prev => (prev === id ? null : id));
|
|
210
|
-
};
|
|
211
|
-
const updatePanelVisibility = (id, visible, currentVisibility) => {
|
|
212
|
-
let next = { ...currentVisibility };
|
|
213
|
-
if (!visible && maximizedPanelId === id) {
|
|
214
|
-
setMaximizedPanelId(null);
|
|
215
|
-
}
|
|
216
|
-
// Se siamo su mobile, resettiamo tutto tranne il pannello selezionato e i suoi parent
|
|
217
|
-
if (isMobile && visible) {
|
|
218
|
-
const parents = parentMap.get(id) || [];
|
|
219
|
-
// Imposta tutti i pannelli come invisibili tranne il selezionato e i suoi parent
|
|
220
|
-
Object.keys(next).forEach(panelId => {
|
|
221
|
-
next[panelId] = (panelId === id || parents.includes(panelId));
|
|
222
|
-
});
|
|
223
|
-
// Applichiamo propagazione verso l’alto (attivazione dei genitori)
|
|
224
|
-
const activateParents = (childId) => {
|
|
225
|
-
for (const parent of parentMap.get(childId) || []) {
|
|
226
|
-
if (!next[parent]) {
|
|
227
|
-
next[parent] = true;
|
|
228
|
-
activateParents(parent);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
activateParents(id);
|
|
233
|
-
return next;
|
|
234
|
-
}
|
|
235
|
-
// Normal behavior (desktop)
|
|
236
|
-
next[id] = visible;
|
|
237
|
-
if (visible) {
|
|
238
|
-
const activateParents = (childId) => {
|
|
239
|
-
for (const parent of parentMap.get(childId) || []) {
|
|
240
|
-
if (!next[parent]) {
|
|
241
|
-
next[parent] = true;
|
|
242
|
-
activateParents(parent);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
};
|
|
246
|
-
activateParents(id);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
const deactivateParents = (childId) => {
|
|
250
|
-
for (const parent of parentMap.get(childId) || []) {
|
|
251
|
-
const children = parentToChildrenMap.get(parent) || [];
|
|
252
|
-
const anyVisible = children.some(cId => next[cId]);
|
|
253
|
-
if (!anyVisible && next[parent]) {
|
|
254
|
-
next[parent] = false;
|
|
255
|
-
deactivateParents(parent);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
};
|
|
259
|
-
deactivateParents(id);
|
|
260
|
-
}
|
|
261
|
-
return next;
|
|
262
|
-
};
|
|
263
|
-
// Attiva/disattiva visibilità di un pannello
|
|
264
|
-
const togglePanel = (id) => {
|
|
265
|
-
setVisibility(prev => updatePanelVisibility(id, !prev[id], prev));
|
|
266
|
-
};
|
|
267
|
-
// Imposta visibilità esplicita di un pannello
|
|
268
|
-
const setPanelVisibility = (id, visible) => {
|
|
269
|
-
setVisibility(prev => updatePanelVisibility(id, visible, prev));
|
|
270
|
-
};
|
|
271
|
-
// Cambia la visibilità direttamente nel pannello (opzionale, ma richiesto da te)
|
|
272
|
-
const setPanelVisibleById = (id, visible) => {
|
|
273
|
-
setPanelTree(prevTree => {
|
|
274
|
-
const update = (panels) => panels.map(panel => {
|
|
275
|
-
if (panel.id === id) {
|
|
276
|
-
return { ...panel, toolbarOptions: { ...panel.toolbarOptions, visible } };
|
|
277
|
-
}
|
|
278
|
-
return { ...panel, children: update(panel.children) };
|
|
279
|
-
});
|
|
280
|
-
return update(prevTree);
|
|
281
|
-
});
|
|
282
|
-
};
|
|
283
|
-
// Cambia il valore di disabled direttamente nel pannello
|
|
284
|
-
const setPanelDisabledById = (id, disabled) => {
|
|
285
|
-
setPanelTree(prevTree => {
|
|
286
|
-
const update = (panels) => panels.map(panel => {
|
|
287
|
-
if (panel.id === id) {
|
|
288
|
-
return { ...panel, toolbarOptions: { ...panel.toolbarOptions, disabled, } };
|
|
289
|
-
}
|
|
290
|
-
return { ...panel, children: update(panel.children) };
|
|
291
|
-
});
|
|
292
|
-
return update(prevTree);
|
|
293
|
-
});
|
|
294
|
-
};
|
|
295
|
-
const hasVisiblePanels = () => {
|
|
296
|
-
return Object.values(calculateEffectiveVisibility).some(visible => visible);
|
|
297
|
-
};
|
|
298
|
-
// Valori esposti dal context
|
|
299
|
-
return (_jsx(TMPanelManagerContext.Provider, { value: {
|
|
300
|
-
panelTree,
|
|
301
|
-
visibility,
|
|
302
|
-
calculateEffectiveVisibility,
|
|
303
|
-
setPanelVisibility,
|
|
304
|
-
togglePanel,
|
|
305
|
-
findPanelById,
|
|
306
|
-
getPanelDimensions,
|
|
307
|
-
toggleMaximizePanel,
|
|
308
|
-
maximizedPanelId,
|
|
309
|
-
updatePanelSize,
|
|
310
|
-
setPanelVisibleById,
|
|
311
|
-
setPanelDisabledById,
|
|
312
|
-
hasVisiblePanels
|
|
313
|
-
}, children: children }));
|
|
314
|
-
};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export declare const TMPanelToolbar: () => import("react/jsx-runtime").JSX.Element;
|
|
3
|
-
export declare const StyledToolbarButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
|
|
4
|
-
$isActive?: boolean;
|
|
5
|
-
$isDisabled?: boolean;
|
|
6
|
-
}>> & string;
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo } from 'react';
|
|
3
|
-
import { useTMPanelContext } from './TMPanelContext';
|
|
4
|
-
import styled from 'styled-components';
|
|
5
|
-
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
6
|
-
import TMTooltip from '../../base/TMTooltip';
|
|
7
|
-
export const TMPanelToolbar = () => {
|
|
8
|
-
const { panelTree, togglePanel, calculateEffectiveVisibility } = useTMPanelContext();
|
|
9
|
-
const deviceType = useDeviceType();
|
|
10
|
-
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
11
|
-
// Ricorsivamente trova tutti i pannelli parent (hanno figli)
|
|
12
|
-
const getParentIds = (panels, parents = new Set()) => {
|
|
13
|
-
for (const panel of panels) {
|
|
14
|
-
if (panel.children.length > 0) {
|
|
15
|
-
parents.add(panel.id);
|
|
16
|
-
getParentIds(panel.children, parents);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return parents;
|
|
20
|
-
};
|
|
21
|
-
// Ricorsivamente trova tutti i pannelli foglia (senza figli)
|
|
22
|
-
const getLeafPanels = (panels, leaves = []) => {
|
|
23
|
-
for (const panel of panels) {
|
|
24
|
-
if (panel.children.length === 0) {
|
|
25
|
-
leaves.push(panel);
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
getLeafPanels(panel.children, leaves);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return leaves;
|
|
32
|
-
};
|
|
33
|
-
const parentIds = getParentIds(panelTree);
|
|
34
|
-
const leafPanels = getLeafPanels(panelTree);
|
|
35
|
-
return (_jsx("div", { style: {
|
|
36
|
-
display: 'flex',
|
|
37
|
-
flexDirection: isMobile ? 'row' : 'column',
|
|
38
|
-
gap: '6px',
|
|
39
|
-
alignItems: 'center',
|
|
40
|
-
justifyContent: isMobile ? 'center' : 'flex-start',
|
|
41
|
-
width: '100%',
|
|
42
|
-
height: '100%'
|
|
43
|
-
}, children: leafPanels.filter(panel => panel.toolbarOptions.visible).map((item) => {
|
|
44
|
-
const isActive = calculateEffectiveVisibility[item.id];
|
|
45
|
-
return _jsx(TMTooltip, { content: item.name, position: isMobile ? 'top' : 'left', children: _jsx(StyledToolbarButton, { "$isActive": isActive || item.toolbarOptions?.alwaysActiveColor, "$isDisabled": item.toolbarOptions?.disabled, disabled: item.toolbarOptions?.disabled, onClick: () => { togglePanel(item.id); }, children: typeof item.toolbarOptions?.icon === 'string' ? (_jsx("i", { className: `dx-icon dx-icon-${item.toolbarOptions?.icon}` })) : (item.toolbarOptions?.icon) }) }, item.id);
|
|
46
|
-
}) }));
|
|
47
|
-
};
|
|
48
|
-
export const StyledToolbarButton = styled.button `
|
|
49
|
-
display: flex;
|
|
50
|
-
align-items: center;
|
|
51
|
-
justify-content: center;
|
|
52
|
-
height: 32px;
|
|
53
|
-
width: 32px;
|
|
54
|
-
border: none;
|
|
55
|
-
border-radius: 8px;
|
|
56
|
-
font-size: 18px;
|
|
57
|
-
padding: 0px;
|
|
58
|
-
color: #fff;
|
|
59
|
-
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
60
|
-
cursor: ${({ $isDisabled }) => ($isDisabled ? 'not-allowed' : 'pointer')};
|
|
61
|
-
opacity: ${({ $isDisabled }) => ($isDisabled ? 0.6 : 1)};
|
|
62
|
-
background: ${({ $isActive }) => $isActive ? 'rgba(255,255,255,0.35)' : 'transparent'};
|
|
63
|
-
&:hover {
|
|
64
|
-
background: ${({ $isDisabled }) => !$isDisabled ? 'rgba(255,255,255,0.35)' : undefined};
|
|
65
|
-
}
|
|
66
|
-
`;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { useRef, useCallback } from 'react';
|
|
2
|
-
import { useTMPanelContext } from './TMPanelContext';
|
|
3
|
-
export function useResizablePanels(containerRef) {
|
|
4
|
-
const { getPanelDimensions, updatePanelSize } = useTMPanelContext();
|
|
5
|
-
const resizingRef = useRef(null);
|
|
6
|
-
const getSizePercent = useCallback((panelId, isRow) => {
|
|
7
|
-
const dim = getPanelDimensions(panelId);
|
|
8
|
-
return isRow
|
|
9
|
-
? parseFloat(dim.width.replace('%', ''))
|
|
10
|
-
: parseFloat(dim.height.replace('%', ''));
|
|
11
|
-
}, [getPanelDimensions]);
|
|
12
|
-
const getContainerSize = useCallback((isRow) => {
|
|
13
|
-
if (!containerRef.current)
|
|
14
|
-
return 0;
|
|
15
|
-
return isRow ? containerRef.current.clientWidth : containerRef.current.clientHeight;
|
|
16
|
-
}, [containerRef]);
|
|
17
|
-
const updateSize = useCallback((panelId, sizePercent, otherDimension, isRow) => {
|
|
18
|
-
if (isRow) {
|
|
19
|
-
updatePanelSize(panelId, `${sizePercent.toFixed(2)}%`, otherDimension);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
updatePanelSize(panelId, otherDimension, `${sizePercent.toFixed(2)}%`);
|
|
23
|
-
}
|
|
24
|
-
}, [updatePanelSize]);
|
|
25
|
-
const onMouseMove = useCallback((e) => {
|
|
26
|
-
const data = resizingRef.current;
|
|
27
|
-
if (!data || !containerRef.current)
|
|
28
|
-
return;
|
|
29
|
-
const { panelBeforeId, panelAfterId, startPos, startSizeBefore, startSizeAfter, isRow } = data;
|
|
30
|
-
const containerSize = getContainerSize(isRow);
|
|
31
|
-
const currentPos = isRow ? e.clientX : e.clientY;
|
|
32
|
-
const delta = currentPos - startPos;
|
|
33
|
-
const sizeBeforePx = (startSizeBefore / 100) * containerSize + delta;
|
|
34
|
-
const sizeAfterPx = (startSizeAfter / 100) * containerSize - delta;
|
|
35
|
-
if (sizeBeforePx < 50 || sizeAfterPx < 50)
|
|
36
|
-
return;
|
|
37
|
-
const newSizeBefore = (sizeBeforePx / containerSize) * 100;
|
|
38
|
-
const newSizeAfter = (sizeAfterPx / containerSize) * 100;
|
|
39
|
-
const dimBefore = getPanelDimensions(panelBeforeId);
|
|
40
|
-
const dimAfter = getPanelDimensions(panelAfterId);
|
|
41
|
-
const otherDimBefore = isRow ? dimBefore.height : dimBefore.width;
|
|
42
|
-
const otherDimAfter = isRow ? dimAfter.height : dimAfter.width;
|
|
43
|
-
updateSize(panelBeforeId, newSizeBefore, otherDimBefore, isRow);
|
|
44
|
-
updateSize(panelAfterId, newSizeAfter, otherDimAfter, isRow);
|
|
45
|
-
}, [getContainerSize, getPanelDimensions, updateSize, containerRef]);
|
|
46
|
-
const onMouseUp = useCallback(() => {
|
|
47
|
-
resizingRef.current = null;
|
|
48
|
-
window.removeEventListener('mousemove', onMouseMove);
|
|
49
|
-
window.removeEventListener('mouseup', onMouseUp);
|
|
50
|
-
}, [onMouseMove]);
|
|
51
|
-
const onMouseDown = useCallback((e, panelBeforeId, panelAfterId, isRow) => {
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
if (!containerRef.current)
|
|
54
|
-
return;
|
|
55
|
-
resizingRef.current = {
|
|
56
|
-
panelBeforeId,
|
|
57
|
-
panelAfterId,
|
|
58
|
-
isRow,
|
|
59
|
-
startPos: isRow ? e.clientX : e.clientY,
|
|
60
|
-
startSizeBefore: getSizePercent(panelBeforeId, isRow),
|
|
61
|
-
startSizeAfter: getSizePercent(panelAfterId, isRow),
|
|
62
|
-
};
|
|
63
|
-
window.addEventListener('mousemove', onMouseMove);
|
|
64
|
-
window.addEventListener('mouseup', onMouseUp);
|
|
65
|
-
}, [getSizePercent, onMouseMove, onMouseUp, containerRef]);
|
|
66
|
-
return { onMouseDown };
|
|
67
|
-
}
|