@topconsultnpm/sdkui-react 6.20.0-dev1.19 → 6.20.0-dev1.20

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.
@@ -78,9 +78,8 @@ export const MenuItem = styled.div `
78
78
  opacity: ${props => props.$disabled ? 0.4 : 1};
79
79
  }
80
80
 
81
- /* Keep right-icon-btn always enabled and visible */
81
+ /* Right icon button hidden by default, shown on hover */
82
82
  & .right-icon-btn {
83
- opacity: 1 !important;
84
83
  cursor: pointer !important;
85
84
  }
86
85
 
@@ -89,6 +88,11 @@ export const MenuItem = styled.div `
89
88
  background: linear-gradient(90deg, #f0f7ff 0%, #e6f2ff 100%);
90
89
  color: #0066cc;
91
90
  `}
91
+
92
+ /* Show right icon on hover */
93
+ & .right-icon-btn {
94
+ opacity: 1 !important;
95
+ }
92
96
  }
93
97
 
94
98
  &:active {
@@ -157,8 +161,8 @@ export const RightIconButton = styled.button.attrs({
157
161
  margin-left: 8px;
158
162
  border-radius: 6px;
159
163
  font-size: 14px;
160
- opacity: 1 !important;
161
- transition: all 0.15s ease;
164
+ opacity: 0 !important;
165
+ transition: opacity 0.15s ease, background 0.15s ease, transform 0.15s ease;
162
166
 
163
167
  &:hover {
164
168
  background: rgba(0, 0, 0, 0.05);
@@ -4,7 +4,7 @@ import { ContextMenu } from '../ContextMenu';
4
4
  import Notification from '../Notification';
5
5
  import TMTooltip from '../../base/TMTooltip';
6
6
  import * as S from './styles';
7
- import { IconApply, IconMenuKebab, IconMenuVertical, IconSettings, IconPin } from '../../../helper';
7
+ import { IconApply, IconMenuKebab, IconMenuVertical, IconPencil, IconPin } from '../../../helper';
8
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
9
  const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = 'floatingMenuBar-config', isConstrained = false, defaultPosition = { x: 100, y: 100 }, maxItems = 8, }) => {
10
10
  const loadConfig = () => {
@@ -347,7 +347,7 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
347
347
  setState(s => ({ ...s, draggedItemIndex: null }));
348
348
  setDragOverIndex(null);
349
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) => {
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.Separator, { "$orientation": state.orientation }), state.items.map((item, index) => {
351
351
  // Get current state (disabled and onClick) from contextMenuItems
352
352
  const currentState = getCurrentItemState(item.name);
353
353
  const isDisabled = currentState.disabled || false;
@@ -365,6 +365,6 @@ const TMFloatingMenuBar = ({ containerRef, contextMenuItems = [], storageKey = '
365
365
  currentOnClick();
366
366
  }
367
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) }) }))] }));
368
+ }), !state.isConfigMode && contextMenuItems.length > 0 && (_jsx(ContextMenu, { items: enhancedContextMenuItems(), trigger: "left", children: _jsx(S.ContextMenuButton, { children: _jsx(IconMenuVertical, {}) }) }, Array.from(pinnedItemIds).join(','))), _jsx(S.ConfigButton, { onClick: toggleConfigMode, "$isActive": state.isConfigMode, children: state.isConfigMode ? _jsx(IconApply, {}) : _jsx(IconPencil, {}) }), !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
369
  };
370
370
  export default TMFloatingMenuBar;
@@ -21,12 +21,20 @@ export declare const FloatingContainer: import("styled-components/dist/types").I
21
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
22
  $orientation: "horizontal" | "vertical";
23
23
  }>> & string;
24
+ export declare const Separator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
25
+ $orientation: "horizontal" | "vertical";
26
+ }>> & string;
24
27
  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
28
  $isActive?: boolean;
26
29
  }>> & string;
27
30
  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
31
  $isActive?: boolean;
29
32
  }>> & string;
33
+ export declare const ContextMenuButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<Omit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "$isActive"> & {
34
+ $isActive?: boolean;
35
+ }, "ref"> & {
36
+ ref?: ((instance: HTMLButtonElement | 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<HTMLButtonElement> | null | undefined;
37
+ }, never>> & string;
30
38
  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
39
  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
40
  $orientation: "horizontal" | "vertical";
@@ -55,7 +55,7 @@ export const FloatingContainer = styled.div.attrs(props => ({
55
55
  transition: none;
56
56
 
57
57
  &:hover {
58
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
58
+ background: linear-gradient(135deg, #0071BC 0%, #1B1464 100%);
59
59
  border: 1px solid #667eea;
60
60
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.3),
61
61
  0 6px 16px rgba(0, 0, 0, 0.2);
@@ -98,6 +98,13 @@ export const GripHandle = styled.div `
98
98
  height: 14px;
99
99
  }
100
100
  `;
101
+ export const Separator = styled.div `
102
+ background: rgba(255, 255, 255, 0.25);
103
+ width: ${props => props.$orientation === 'horizontal' ? '1px' : '100%'};
104
+ height: ${props => props.$orientation === 'horizontal' ? '24px' : '1px'};
105
+ margin: ${props => props.$orientation === 'horizontal' ? '0 4px' : '4px 0'};
106
+ flex-shrink: 0;
107
+ `;
101
108
  export const MenuButton = styled.button `
102
109
  display: flex;
103
110
  align-items: center;
@@ -110,16 +117,15 @@ export const MenuButton = styled.button `
110
117
  color: white;
111
118
  font-size: 16px;
112
119
  cursor: pointer;
113
- transition: all 0.2s ease;
120
+ transition: background 0.2s ease;
114
121
  position: relative;
115
122
 
116
123
  &:hover:not(:disabled) {
117
124
  background: rgba(255, 255, 255, 0.2);
118
- transform: scale(1.1);
119
125
  }
120
126
 
121
127
  &:active:not(:disabled) {
122
- transform: scale(0.95);
128
+ opacity: 0.8;
123
129
  }
124
130
 
125
131
  &:disabled {
@@ -131,14 +137,15 @@ export const MenuButton = styled.button `
131
137
  svg {
132
138
  width: 18px;
133
139
  height: 18px;
140
+ transform: translateY(2px);
134
141
  }
135
142
  `;
136
143
  export const ConfigButton = styled.button `
137
144
  display: flex;
138
145
  align-items: center;
139
146
  justify-content: center;
140
- width: 34px;
141
- height: 34px;
147
+ width: 28px;
148
+ height: 28px;
142
149
  background: ${props => props.$isActive
143
150
  ? 'rgba(0, 0, 0, 0.2)'
144
151
  : 'rgba(0, 0, 0, 0.1)'};
@@ -147,9 +154,9 @@ export const ConfigButton = styled.button `
147
154
  : 'rgba(255, 255, 255, 0.15)'};
148
155
  border-radius: 8px;
149
156
  color: white;
150
- font-size: 16px;
157
+ font-size: 14px;
151
158
  cursor: pointer;
152
- transition: all 0.2s ease;
159
+ transition: background 0.2s ease, border-color 0.2s ease;
153
160
  position: relative;
154
161
 
155
162
  &:hover {
@@ -157,16 +164,20 @@ export const ConfigButton = styled.button `
157
164
  ? 'rgba(0, 0, 0, 0.25)'
158
165
  : 'rgba(0, 0, 0, 0.15)'};
159
166
  border-color: rgba(255, 255, 255, 0.35);
160
- transform: scale(1.05);
161
167
  }
162
168
 
163
169
  &:active {
164
- transform: scale(0.95);
170
+ opacity: 0.8;
165
171
  }
166
172
 
167
173
  svg {
168
- width: 20px;
169
- height: 20px;
174
+ width: 16px;
175
+ height: 16px;
176
+ }
177
+ `;
178
+ export const ContextMenuButton = styled(MenuButton) `
179
+ svg {
180
+ transform: translateY(0);
170
181
  }
171
182
  `;
172
183
  export const RemoveButton = styled.button `
@@ -19,20 +19,30 @@ let Document = null;
19
19
  let Page = null;
20
20
  let pdfjs = null;
21
21
  let isPdfLibraryLoaded = false;
22
+ let loadingPromise = null;
22
23
  const loadPdfLibrary = async () => {
23
24
  if (isPdfLibraryLoaded)
24
25
  return;
25
- try {
26
- const reactPdf = await import('react-pdf');
27
- Document = reactPdf.Document;
28
- Page = reactPdf.Page;
29
- pdfjs = reactPdf.pdfjs;
30
- pdfjs.GlobalWorkerOptions.workerSrc = require('pdfjs-dist/build/pdf.worker.mjs');
31
- isPdfLibraryLoaded = true;
32
- }
33
- catch (error) {
34
- console.error('Failed to load react-pdf library:', error);
35
- }
26
+ if (loadingPromise)
27
+ return loadingPromise;
28
+ loadingPromise = (async () => {
29
+ try {
30
+ const reactPdf = await import('react-pdf');
31
+ Document = reactPdf.Document;
32
+ Page = reactPdf.Page;
33
+ pdfjs = reactPdf.pdfjs;
34
+ pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
35
+ isPdfLibraryLoaded = true;
36
+ }
37
+ catch (error) {
38
+ console.error('Failed to load react-pdf library:', error);
39
+ throw error;
40
+ }
41
+ finally {
42
+ loadingPromise = null;
43
+ }
44
+ })();
45
+ return loadingPromise;
36
46
  };
37
47
  const ErrorContent = ({ error, isAbortError, onRetry }) => {
38
48
  if (isAbortError) {
@@ -183,16 +193,25 @@ export const TMFileViewer = ({ fileBlob, isResizingActive }) => {
183
193
  window.removeEventListener('resize', checkIsMobile);
184
194
  };
185
195
  }, []);
186
- useEffect(() => {
187
- if (isMobile && fileType === 'application/pdf' && !isPdfLibraryLoaded && !pdfLibraryLoading) {
188
- setPdfLibraryLoading(true);
189
- loadPdfLibrary().finally(() => setPdfLibraryLoading(false));
190
- }
191
- }, [isMobile, fileType, pdfLibraryLoading]);
192
196
  useEffect(() => {
193
197
  if (fileBlob) {
194
- setFileType(fileBlob.type);
198
+ const blobType = fileBlob.type;
199
+ setFileType(blobType);
195
200
  setFormattedXml(undefined);
201
+ // Load PDF library immediately if it's a PDF file on mobile
202
+ if (isMobile && blobType === 'application/pdf' && !isPdfLibraryLoaded && !pdfLibraryLoading) {
203
+ setPdfLibraryLoading(true);
204
+ loadPdfLibrary()
205
+ .then(() => {
206
+ console.log('PDF library loaded successfully');
207
+ })
208
+ .catch((error) => {
209
+ console.error('Failed to load PDF library:', error);
210
+ })
211
+ .finally(() => {
212
+ setPdfLibraryLoading(false);
213
+ });
214
+ }
196
215
  const fileName = fileBlob.name || '';
197
216
  const fileExtension = fileName.split('.').pop()?.toLowerCase() || '';
198
217
  const isConfigFile = ['config', 'cfg'].includes(fileExtension);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.20.0-dev1.19",
3
+ "version": "6.20.0-dev1.20",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",