@topconsultnpm/sdkui-react 6.19.0-dev2.27 → 6.19.0-dev2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
  2. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +187 -0
  3. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +11 -0
  4. package/lib/components/NewComponents/ContextMenu/hooks.js +48 -0
  5. package/lib/components/NewComponents/ContextMenu/index.d.ts +2 -0
  6. package/lib/components/NewComponents/ContextMenu/index.js +1 -0
  7. package/lib/components/NewComponents/ContextMenu/styles.d.ts +27 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.js +308 -0
  9. package/lib/components/NewComponents/ContextMenu/types.d.ts +26 -0
  10. package/lib/components/NewComponents/ContextMenu/types.js +1 -0
  11. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +4 -0
  12. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +370 -0
  13. package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
  14. package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
  15. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +38 -0
  16. package/lib/components/NewComponents/FloatingMenuBar/styles.js +267 -0
  17. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +30 -0
  18. package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
  19. package/lib/components/NewComponents/Notification/Notification.d.ts +4 -0
  20. package/lib/components/NewComponents/Notification/Notification.js +60 -0
  21. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +8 -0
  22. package/lib/components/NewComponents/Notification/NotificationContainer.js +33 -0
  23. package/lib/components/NewComponents/Notification/index.d.ts +2 -0
  24. package/lib/components/NewComponents/Notification/index.js +2 -0
  25. package/lib/components/NewComponents/Notification/styles.d.ts +21 -0
  26. package/lib/components/NewComponents/Notification/styles.js +180 -0
  27. package/lib/components/NewComponents/Notification/types.d.ts +18 -0
  28. package/lib/components/NewComponents/Notification/types.js +1 -0
  29. package/lib/components/features/documents/TMDcmtForm.js +278 -17
  30. package/package.json +1 -1
@@ -0,0 +1,370 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect, useCallback } from 'react';
3
+ import { ContextMenu } from '../ContextMenu';
4
+ import Notification from '../Notification';
5
+ import TMTooltip from '../../base/TMTooltip';
6
+ import * as S from './styles';
7
+ import { IconApply, IconMenuKebab, IconMenuVertical, IconSettings, IconStar } from '../../../helper';
8
+ const IconDraggableDots = (props) => (_jsx("svg", { fontSize: 18, viewBox: "0 0 24 24", fill: "currentColor", height: "1em", width: "1em", ...props, children: _jsx("path", { d: "M9 3a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm10-18a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0zm0 9a2 2 0 11-4 0 2 2 0 014 0z" }) }));
9
+ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = 'floatingMenuBar-config', isConstrained = false, defaultPosition = { x: 100, y: 100 }, maxItems = 8, }) => {
10
+ const loadConfig = () => {
11
+ try {
12
+ const saved = localStorage.getItem(storageKey);
13
+ if (saved) {
14
+ const config = JSON.parse(saved);
15
+ return {
16
+ orientation: config.orientation || 'horizontal',
17
+ pinnedItemIds: new Set(config.pinnedItemIds || []),
18
+ savedItemIds: config.itemIds || [],
19
+ };
20
+ }
21
+ }
22
+ catch (error) {
23
+ console.error('Failed to load FloatingMenuBar config:', error);
24
+ }
25
+ return {
26
+ orientation: 'horizontal',
27
+ pinnedItemIds: new Set(),
28
+ savedItemIds: [],
29
+ };
30
+ };
31
+ const initialConfig = loadConfig();
32
+ const [state, setState] = useState({
33
+ position: defaultPosition,
34
+ isDragging: false,
35
+ isConfigMode: false,
36
+ orientation: initialConfig.orientation,
37
+ items: [],
38
+ draggedItemIndex: null,
39
+ });
40
+ const floatingRef = useRef(null);
41
+ const dragOffset = useRef({ x: 0, y: 0 });
42
+ const [pinnedItemIds, setPinnedItemIds] = useState(initialConfig.pinnedItemIds);
43
+ const [dragOverIndex, setDragOverIndex] = useState(null);
44
+ const [showMaxItemsNotification, setShowMaxItemsNotification] = useState(false);
45
+ // Use refs to track item IDs without causing re-renders
46
+ const floatingBarItemIds = useRef(new Set());
47
+ const floatingBarItemNames = useRef(new Set());
48
+ // Update refs when items change, but don't trigger re-renders
49
+ useEffect(() => {
50
+ floatingBarItemIds.current = new Set(state.items.map(i => i.id));
51
+ floatingBarItemNames.current = new Set(state.items.map(i => i.name));
52
+ }, [state.items]);
53
+ // Convert menu items to flat list with pinned status
54
+ const flattenMenuItems = useCallback((items, parentPath = '') => {
55
+ const result = [];
56
+ items.forEach((item, index) => {
57
+ const itemId = `${parentPath}${item.name}-${index}`;
58
+ // Only add items that have onClick (final actions, not submenu parents)
59
+ if (item.onClick && !item.submenu) {
60
+ result.push({
61
+ id: itemId,
62
+ name: item.name,
63
+ icon: item.icon || _jsx(IconStar, {}),
64
+ onClick: item.onClick,
65
+ disabled: item.disabled,
66
+ isPinned: pinnedItemIds.has(itemId),
67
+ originalMenuItem: item,
68
+ });
69
+ }
70
+ // Recursively process submenus
71
+ if (item.submenu) {
72
+ result.push(...flattenMenuItems(item.submenu, `${itemId}/`));
73
+ }
74
+ });
75
+ return result;
76
+ }, [pinnedItemIds]);
77
+ // Restore items on mount from savedItemIds
78
+ useEffect(() => {
79
+ if (contextMenuItems.length > 0) {
80
+ const flatItems = flattenMenuItems(contextMenuItems);
81
+ // Restore items in the saved order from localStorage
82
+ const restoredItems = initialConfig.savedItemIds
83
+ .map((id) => flatItems.find(item => item.id === id))
84
+ .filter((item) => item !== undefined);
85
+ if (restoredItems.length > 0) {
86
+ setState(s => ({ ...s, items: restoredItems }));
87
+ }
88
+ }
89
+ }, []); // Only run once on mount
90
+ const togglePin = useCallback((item) => {
91
+ setState(s => {
92
+ const isInFloatingBar = s.items.some(i => i.id === item.id || i.name === item.name);
93
+ if (isInFloatingBar) {
94
+ // Remove from floating bar
95
+ const newItems = s.items.filter(i => i.id !== item.id && i.name !== item.name);
96
+ return { ...s, items: newItems };
97
+ }
98
+ else {
99
+ // Add to floating bar
100
+ if (s.items.length >= maxItems) {
101
+ setShowMaxItemsNotification(true);
102
+ setTimeout(() => setShowMaxItemsNotification(false), 3000);
103
+ return s;
104
+ }
105
+ return { ...s, items: [...s.items, item] };
106
+ }
107
+ });
108
+ // Update pinned IDs for context menu items
109
+ setPinnedItemIds(prev => {
110
+ const newSet = new Set(prev);
111
+ if (newSet.has(item.id)) {
112
+ newSet.delete(item.id);
113
+ }
114
+ else {
115
+ newSet.add(item.id);
116
+ }
117
+ return newSet;
118
+ });
119
+ }, [maxItems]);
120
+ // Get current item state (disabled and onClick) from contextMenuItems
121
+ const getCurrentItemState = useCallback((itemName) => {
122
+ const findInItems = (items) => {
123
+ for (const item of items) {
124
+ if (item.name === itemName)
125
+ return item;
126
+ if (item.submenu) {
127
+ const found = findInItems(item.submenu);
128
+ if (found)
129
+ return found;
130
+ }
131
+ }
132
+ return undefined;
133
+ };
134
+ const foundItem = findInItems(contextMenuItems);
135
+ return {
136
+ disabled: foundItem?.disabled,
137
+ onClick: foundItem?.onClick
138
+ };
139
+ }, [contextMenuItems]); // Enhanced context menu items with pin functionality
140
+ const enhancedContextMenuItems = useCallback(() => {
141
+ const flatItems = flattenMenuItems(contextMenuItems);
142
+ // Calculate current pinned items directly from state.items (not refs)
143
+ const currentItemIds = new Set(state.items.map(i => i.id));
144
+ const currentItemNames = new Set(state.items.map(i => i.name));
145
+ const enhanceItems = (items) => {
146
+ return items.map(item => {
147
+ const flatItem = flatItems.find(fi => fi.name === item.name);
148
+ const itemId = flatItem?.id || '';
149
+ // Check if item is in the floating bar using current state
150
+ const isInFloatingBar = currentItemIds.has(itemId) || currentItemNames.has(item.name);
151
+ const enhanced = {
152
+ ...item,
153
+ rightIcon: item.onClick && !item.submenu ? (isInFloatingBar ? _jsx(IconStar, { color: "#FFD700" }) : _jsx(IconStar, {})) : undefined,
154
+ onRightIconClick: item.onClick && !item.submenu ? () => {
155
+ if (flatItem) {
156
+ togglePin(flatItem);
157
+ }
158
+ } : undefined,
159
+ };
160
+ if (item.submenu) {
161
+ enhanced.submenu = enhanceItems(item.submenu);
162
+ }
163
+ return enhanced;
164
+ });
165
+ };
166
+ return enhanceItems(contextMenuItems);
167
+ }, [contextMenuItems, flattenMenuItems, togglePin, state.items]);
168
+ const handleMouseDown = (e) => {
169
+ if (state.isConfigMode)
170
+ return;
171
+ const containerRect = containerRef.current?.getBoundingClientRect();
172
+ if (containerRect) {
173
+ // Calculate drag offset based on positioning mode
174
+ if (isConstrained) {
175
+ // For absolute positioning, offset is relative to container
176
+ dragOffset.current = {
177
+ x: e.clientX - containerRect.left - state.position.x,
178
+ y: e.clientY - containerRect.top - state.position.y,
179
+ };
180
+ }
181
+ else {
182
+ // For fixed positioning, offset is relative to viewport
183
+ dragOffset.current = {
184
+ x: e.clientX - state.position.x,
185
+ y: e.clientY - state.position.y,
186
+ };
187
+ }
188
+ }
189
+ setState(s => ({ ...s, isDragging: true }));
190
+ };
191
+ const handleMouseMove = useCallback((e) => {
192
+ if (!state.isDragging || !containerRef.current || !floatingRef.current)
193
+ return;
194
+ const container = containerRef.current.getBoundingClientRect();
195
+ const floating = floatingRef.current.getBoundingClientRect();
196
+ let newX, newY;
197
+ if (isConstrained) {
198
+ // For constrained (absolute positioning), use container coordinates
199
+ newX = e.clientX - container.left - dragOffset.current.x;
200
+ newY = e.clientY - container.top - dragOffset.current.y;
201
+ // Constrain to container bounds
202
+ newX = Math.max(0, Math.min(newX, container.width - floating.width));
203
+ newY = Math.max(0, Math.min(newY, container.height - floating.height));
204
+ }
205
+ else {
206
+ // For unconstrained (fixed positioning), use viewport coordinates
207
+ newX = e.clientX - dragOffset.current.x;
208
+ newY = e.clientY - dragOffset.current.y;
209
+ // Constrain to viewport bounds
210
+ newX = Math.max(0, Math.min(newX, window.innerWidth - floating.width));
211
+ newY = Math.max(0, Math.min(newY, window.innerHeight - floating.height));
212
+ }
213
+ setState(s => ({
214
+ ...s,
215
+ position: { x: newX, y: newY },
216
+ }));
217
+ }, [state.isDragging, containerRef, isConstrained]);
218
+ const handleMouseUp = useCallback(() => {
219
+ setState(s => ({ ...s, isDragging: false }));
220
+ }, []);
221
+ useEffect(() => {
222
+ if (state.isDragging) {
223
+ document.addEventListener('mousemove', handleMouseMove);
224
+ document.addEventListener('mouseup', handleMouseUp);
225
+ return () => {
226
+ document.removeEventListener('mousemove', handleMouseMove);
227
+ document.removeEventListener('mouseup', handleMouseUp);
228
+ };
229
+ }
230
+ return undefined;
231
+ }, [state.isDragging, handleMouseMove, handleMouseUp]);
232
+ // Save to localStorage whenever config changes (excluding position)
233
+ useEffect(() => {
234
+ try {
235
+ const config = {
236
+ orientation: state.orientation,
237
+ pinnedItemIds: Array.from(pinnedItemIds),
238
+ itemIds: state.items.map(item => item.id), // Save only IDs, not functions
239
+ };
240
+ localStorage.setItem(storageKey, JSON.stringify(config));
241
+ }
242
+ catch (error) {
243
+ console.error('Failed to save FloatingMenuBar config:', error);
244
+ }
245
+ }, [state.orientation, state.items, pinnedItemIds, storageKey]);
246
+ const toggleConfigMode = () => {
247
+ setState(s => ({ ...s, isConfigMode: !s.isConfigMode }));
248
+ };
249
+ const toggleOrientation = () => {
250
+ const newOrientation = state.orientation === 'horizontal' ? 'vertical' : 'horizontal';
251
+ // First, change the orientation
252
+ setState(s => ({
253
+ ...s,
254
+ orientation: newOrientation,
255
+ }));
256
+ // Then, after DOM updates, adjust position to stay in bounds
257
+ requestAnimationFrame(() => {
258
+ requestAnimationFrame(() => {
259
+ if (containerRef.current && floatingRef.current) {
260
+ const container = containerRef.current.getBoundingClientRect();
261
+ const floating = floatingRef.current.getBoundingClientRect();
262
+ let newX, newY;
263
+ if (isConstrained) {
264
+ // For constrained mode, use container bounds
265
+ newX = Math.max(0, Math.min(state.position.x, container.width - floating.width));
266
+ newY = Math.max(0, Math.min(state.position.y, container.height - floating.height));
267
+ }
268
+ else {
269
+ // For unconstrained mode, use viewport bounds
270
+ newX = Math.max(0, Math.min(state.position.x, window.innerWidth - floating.width));
271
+ newY = Math.max(0, Math.min(state.position.y, window.innerHeight - floating.height));
272
+ }
273
+ // Only update position if it changed (to avoid unnecessary re-render)
274
+ if (newX !== state.position.x || newY !== state.position.y) {
275
+ setState(s => ({
276
+ ...s,
277
+ position: { x: newX, y: newY },
278
+ }));
279
+ }
280
+ }
281
+ });
282
+ });
283
+ };
284
+ const removeItem = (itemId) => {
285
+ setState(s => ({
286
+ ...s,
287
+ items: s.items.filter(item => item.id !== itemId),
288
+ }));
289
+ // Also remove from pinned items if it was pinned
290
+ setPinnedItemIds(prev => {
291
+ const newSet = new Set(prev);
292
+ newSet.delete(itemId);
293
+ return newSet;
294
+ });
295
+ };
296
+ // Drag and drop for reordering
297
+ const handleDragStart = (e, index) => {
298
+ if (!state.isConfigMode)
299
+ return;
300
+ e.dataTransfer.effectAllowed = 'move';
301
+ e.dataTransfer.setData('text/plain', index.toString());
302
+ setState(s => ({ ...s, draggedItemIndex: index }));
303
+ };
304
+ const handleDragEnter = (e, index) => {
305
+ if (!state.isConfigMode)
306
+ return;
307
+ e.preventDefault();
308
+ if (state.draggedItemIndex !== index) {
309
+ setDragOverIndex(index);
310
+ }
311
+ };
312
+ const handleDragOver = (e) => {
313
+ if (!state.isConfigMode)
314
+ return;
315
+ e.preventDefault();
316
+ e.dataTransfer.dropEffect = 'move';
317
+ };
318
+ const handleDragLeave = (_e, index) => {
319
+ if (!state.isConfigMode)
320
+ return;
321
+ // Only clear if we're actually leaving this specific item
322
+ if (dragOverIndex === index) {
323
+ setDragOverIndex(null);
324
+ }
325
+ };
326
+ const handleDrop = (e, dropIndex) => {
327
+ if (!state.isConfigMode || state.draggedItemIndex === null)
328
+ return;
329
+ e.preventDefault();
330
+ e.stopPropagation();
331
+ const dragIndex = state.draggedItemIndex;
332
+ if (dragIndex === dropIndex) {
333
+ setDragOverIndex(null);
334
+ return;
335
+ }
336
+ const newItems = [...state.items];
337
+ const [draggedItem] = newItems.splice(dragIndex, 1);
338
+ newItems.splice(dropIndex, 0, draggedItem);
339
+ setState(s => ({
340
+ ...s,
341
+ items: newItems,
342
+ draggedItemIndex: null,
343
+ }));
344
+ setDragOverIndex(null);
345
+ };
346
+ const handleDragEnd = () => {
347
+ setState(s => ({ ...s, draggedItemIndex: null }));
348
+ setDragOverIndex(null);
349
+ };
350
+ return (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { "$visible": state.isConfigMode }), _jsxs(S.FloatingContainer, { ref: floatingRef, "$x": state.position.x, "$y": state.position.y, "$orientation": state.orientation, "$isDragging": state.isDragging, "$isConfigMode": state.isConfigMode, "$isConstrained": isConstrained, children: [_jsx(S.GripHandle, { "$orientation": state.orientation, onMouseDown: handleMouseDown, children: _jsx(IconDraggableDots, {}) }), _jsx(S.ConfigButton, { onClick: toggleConfigMode, "$isActive": state.isConfigMode, children: state.isConfigMode ? _jsx(IconApply, {}) : _jsx(IconSettings, {}) }), state.items.map((item, index) => {
351
+ // Get current state (disabled and onClick) from contextMenuItems
352
+ const currentState = getCurrentItemState(item.name);
353
+ const isDisabled = currentState.disabled || false;
354
+ const currentOnClick = currentState.onClick || item.onClick; // Fallback to stored onClick if not found
355
+ return (_jsxs(S.DraggableItem, { "$isDragging": state.draggedItemIndex === index, "$isDragOver": dragOverIndex === index && state.draggedItemIndex !== index, draggable: state.isConfigMode, onDragStart: (e) => handleDragStart(e, index), onDragEnter: (e) => handleDragEnter(e, index), onDragOver: handleDragOver, onDragLeave: (e) => handleDragLeave(e, index), onDrop: (e) => handleDrop(e, index), onDragEnd: handleDragEnd, children: [state.isConfigMode ? (_jsx(S.MenuButton, { onClick: () => {
356
+ if (state.isConfigMode || isDisabled)
357
+ return;
358
+ if (currentOnClick) {
359
+ currentOnClick();
360
+ }
361
+ }, disabled: isDisabled && !state.isConfigMode, children: item.icon })) : (_jsx(TMTooltip, { content: item.name, position: "top", children: _jsx(S.MenuButton, { onClick: () => {
362
+ if (state.isConfigMode || isDisabled)
363
+ return;
364
+ if (currentOnClick) {
365
+ currentOnClick();
366
+ }
367
+ }, disabled: isDisabled, children: item.icon }) })), state.isConfigMode && (_jsx(S.RemoveButton, { onClick: () => removeItem(item.id), children: "\u00D7" }))] }, item.id));
368
+ }), !state.isConfigMode && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: enhancedContextMenuItems(), trigger: "left", children: _jsx(S.MenuButton, { children: _jsx(IconMenuVertical, {}) }) }, Array.from(pinnedItemIds).join(','))), !state.isConfigMode && (_jsx(S.OrientationToggle, { "$orientation": state.orientation, onClick: toggleOrientation, children: _jsx(IconMenuKebab, {}) }))] }), showMaxItemsNotification && (_jsx("div", { style: { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', zIndex: 100001 }, children: _jsx(Notification, { title: "Maximum Items Reached", message: `You have reached the maximum number of pinned items (${maxItems}). Please unpin an item before adding a new one.`, mode: "warning", position: "top-center", duration: 4000, closable: true, stopOnMouseEnter: true, hasProgress: true, onClose: () => setShowMaxItemsNotification(false) }) }))] }));
369
+ };
370
+ export default TMFloatingMenuBar;
@@ -0,0 +1,2 @@
1
+ export { default } from './TMFloatingMenuBar';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ export { default } from './TMFloatingMenuBar';
2
+ export * from './types';
@@ -0,0 +1,38 @@
1
+ export declare const Overlay: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
2
+ $visible: boolean;
3
+ }>> & string;
4
+ export declare const FloatingContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
5
+ ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
6
+ }>, {
7
+ $x: number;
8
+ $y: number;
9
+ $orientation: "horizontal" | "vertical";
10
+ $isDragging: boolean;
11
+ $isConfigMode: boolean;
12
+ $isConstrained?: boolean;
13
+ }>, {
14
+ $x: number;
15
+ $y: number;
16
+ $orientation: "horizontal" | "vertical";
17
+ $isDragging: boolean;
18
+ $isConfigMode: boolean;
19
+ $isConstrained?: boolean;
20
+ }>> & string;
21
+ export declare const GripHandle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
22
+ $orientation: "horizontal" | "vertical";
23
+ }>> & string;
24
+ export declare const MenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
25
+ $isActive?: boolean;
26
+ }>> & string;
27
+ export declare const ConfigButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
28
+ $isActive?: boolean;
29
+ }>> & string;
30
+ export declare const RemoveButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
31
+ export declare const OrientationToggle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, {
32
+ $orientation: "horizontal" | "vertical";
33
+ }>> & string;
34
+ export declare const DraggableItem: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
35
+ $isDragging: boolean;
36
+ $isDragOver: boolean;
37
+ }>> & string;
38
+ export declare const ContextMenuWrapper: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
@@ -0,0 +1,267 @@
1
+ import styled, { keyframes, css } from 'styled-components';
2
+ const fadeIn = keyframes `
3
+ from {
4
+ opacity: 0;
5
+ transform: scale(0.95);
6
+ }
7
+ to {
8
+ opacity: 1;
9
+ transform: scale(1);
10
+ }
11
+ `;
12
+ const shake = keyframes `
13
+ 0%, 100% { transform: translateX(0); }
14
+ 25% { transform: translateX(-2px); }
15
+ 75% { transform: translateX(2px); }
16
+ `;
17
+ export const Overlay = styled.div `
18
+ position: fixed;
19
+ top: 0;
20
+ left: 0;
21
+ right: 0;
22
+ bottom: 0;
23
+ background: rgba(255, 255, 255, 0.8);
24
+ z-index: 9998;
25
+ display: ${props => props.$visible ? 'block' : 'none'};
26
+ animation: ${fadeIn} 0.2s ease-out;
27
+ backdrop-filter: blur(2px);
28
+
29
+ [data-theme='dark'] & {
30
+ background: rgba(0, 0, 0, 0.8);
31
+ }
32
+ `;
33
+ export const FloatingContainer = styled.div.attrs(props => ({
34
+ style: {
35
+ left: `${props.$x}px`,
36
+ top: `${props.$y}px`,
37
+ },
38
+ })) `
39
+ position: ${props => props.$isConstrained ? 'absolute' : 'fixed'};
40
+ z-index: ${props => props.$isConfigMode ? 9999 : 10000};
41
+ display: flex;
42
+ flex-direction: ${props => props.$orientation === 'horizontal' ? 'row' : 'column'};
43
+ align-items: center;
44
+ background: ${props => props.$isDragging || props.$isConfigMode
45
+ ? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
46
+ : 'rgba(102, 126, 234, 0.9)'};
47
+ border: 1px solid rgba(255, 255, 255, 0.2);
48
+ border-radius: 14px;
49
+ padding: 6px;
50
+ gap: 3px;
51
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
52
+ cursor: ${props => props.$isDragging ? 'grabbing' : 'default'};
53
+ user-select: none;
54
+ animation: ${props => props.$isConfigMode && css `${shake} 0.3s ease-in-out`};
55
+ transition: none;
56
+
57
+ &:hover {
58
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
59
+ border: 1px solid #667eea;
60
+ box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
61
+ 0 6px 16px rgba(0, 0, 0, 0.2);
62
+ }
63
+
64
+ [data-theme='dark'] & {
65
+ background: ${props => props.$isDragging || props.$isConfigMode
66
+ ? 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)'
67
+ : 'rgba(26, 26, 46, 0.9)'};
68
+ border-color: rgba(255, 255, 255, 0.1);
69
+
70
+ &:hover {
71
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
72
+ border: 1px solid #1a1a2e;
73
+ }
74
+ }
75
+ `;
76
+ export const GripHandle = styled.div `
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ padding: ${props => props.$orientation === 'horizontal' ? '10px 6px' : '6px 10px'};
81
+ cursor: grab;
82
+ color: rgba(255, 255, 255, 0.7);
83
+ transition: all 0.2s ease;
84
+ border-radius: 6px;
85
+
86
+ &:hover {
87
+ background: rgba(255, 255, 255, 0.1);
88
+ color: rgba(255, 255, 255, 1);
89
+ }
90
+
91
+ &:active {
92
+ cursor: grabbing;
93
+ background: rgba(255, 255, 255, 0.15);
94
+ }
95
+
96
+ svg {
97
+ width: 14px;
98
+ height: 14px;
99
+ }
100
+ `;
101
+ export const MenuButton = styled.button `
102
+ display: flex;
103
+ align-items: center;
104
+ justify-content: center;
105
+ width: 34px;
106
+ height: 34px;
107
+ background: transparent;
108
+ border: none;
109
+ border-radius: 8px;
110
+ color: white;
111
+ font-size: 16px;
112
+ cursor: pointer;
113
+ transition: all 0.2s ease;
114
+ position: relative;
115
+
116
+ &:hover:not(:disabled) {
117
+ background: rgba(255, 255, 255, 0.2);
118
+ transform: scale(1.1);
119
+ }
120
+
121
+ &:active:not(:disabled) {
122
+ transform: scale(0.95);
123
+ }
124
+
125
+ &:disabled {
126
+ opacity: 0.3;
127
+ cursor: not-allowed;
128
+ background: rgba(255, 255, 255, 0.05);
129
+ color: rgba(255, 255, 255, 0.4);
130
+ }
131
+
132
+ svg {
133
+ width: 18px;
134
+ height: 18px;
135
+ }
136
+ `;
137
+ export const ConfigButton = styled.button `
138
+ display: flex;
139
+ align-items: center;
140
+ justify-content: center;
141
+ width: 34px;
142
+ height: 34px;
143
+ background: ${props => props.$isActive
144
+ ? 'rgba(0, 0, 0, 0.2)'
145
+ : 'rgba(0, 0, 0, 0.1)'};
146
+ border: 1px solid ${props => props.$isActive
147
+ ? 'rgba(255, 255, 255, 0.3)'
148
+ : 'rgba(255, 255, 255, 0.15)'};
149
+ border-radius: 8px;
150
+ color: white;
151
+ font-size: 16px;
152
+ cursor: pointer;
153
+ transition: all 0.2s ease;
154
+ position: relative;
155
+
156
+ &:hover {
157
+ background: ${props => props.$isActive
158
+ ? 'rgba(0, 0, 0, 0.25)'
159
+ : 'rgba(0, 0, 0, 0.15)'};
160
+ border-color: rgba(255, 255, 255, 0.35);
161
+ transform: scale(1.05);
162
+ }
163
+
164
+ &:active {
165
+ transform: scale(0.95);
166
+ }
167
+
168
+ svg {
169
+ width: 20px;
170
+ height: 20px;
171
+ }
172
+ `;
173
+ export const RemoveButton = styled.button `
174
+ position: absolute;
175
+ top: -6px;
176
+ right: -6px;
177
+ width: 20px;
178
+ height: 20px;
179
+ background: #ef4444;
180
+ border: 2px solid white;
181
+ border-radius: 50%;
182
+ color: white;
183
+ font-size: 12px;
184
+ font-weight: bold;
185
+ cursor: pointer;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ transition: all 0.2s ease;
190
+ z-index: 1;
191
+
192
+ &:hover {
193
+ background: #dc2626;
194
+ transform: scale(1.15);
195
+ }
196
+
197
+ &:active {
198
+ transform: scale(0.9);
199
+ }
200
+ `;
201
+ export const OrientationToggle = styled.button `
202
+ display: flex;
203
+ align-items: center;
204
+ justify-content: center;
205
+ width: 20px;
206
+ height: 20px;
207
+ background: transparent;
208
+ border: none;
209
+ border-radius: 4px;
210
+ color: rgba(255, 255, 255, 0.5);
211
+ font-size: 10px;
212
+ cursor: pointer;
213
+ transition: all 0.2s ease;
214
+ padding: 2px;
215
+ transform: ${props => props.$orientation === 'vertical' ? 'rotate(90deg)' : 'rotate(0deg)'};
216
+
217
+ &:hover {
218
+ background: rgba(255, 255, 255, 0.1);
219
+ color: rgba(255, 255, 255, 0.8);
220
+ }
221
+
222
+ &:active {
223
+ transform: ${props => props.$orientation === 'vertical' ? 'rotate(90deg) scale(0.9)' : 'scale(0.9)'};
224
+ }
225
+
226
+ svg {
227
+ width: 10px;
228
+ height: 10px;
229
+ }
230
+ `;
231
+ export const DraggableItem = styled.div `
232
+ position: relative;
233
+ opacity: ${props => props.$isDragging ? 0.3 : 1};
234
+ transform: ${props => {
235
+ if (props.$isDragging)
236
+ return 'scale(1.1) rotate(5deg)';
237
+ if (props.$isDragOver)
238
+ return 'scale(1.05)';
239
+ return 'scale(1)';
240
+ }};
241
+ transition: all 0.2s ease;
242
+ filter: ${props => props.$isDragging ? 'brightness(1.3)' : 'brightness(1)'};
243
+
244
+ ${props => props.$isDragging && css `
245
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
246
+ z-index: 100;
247
+ `}
248
+
249
+ ${props => props.$isDragOver && css `
250
+ &::before {
251
+ content: '';
252
+ position: absolute;
253
+ top: -4px;
254
+ left: 50%;
255
+ transform: translateX(-50%);
256
+ width: 40px;
257
+ height: 3px;
258
+ background: rgba(255, 255, 255, 0.8);
259
+ border-radius: 2px;
260
+ box-shadow: 0 0 8px rgba(255, 255, 255, 0.6);
261
+ }
262
+ `}
263
+ `;
264
+ export const ContextMenuWrapper = styled.div `
265
+ position: static;
266
+ display: contents;
267
+ `;