@topconsultnpm/sdkui-react 6.20.0-dev1.6 → 6.20.0-dev1.7
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/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +187 -0
- package/lib/components/NewComponents/ContextMenu/hooks.d.ts +11 -0
- package/lib/components/NewComponents/ContextMenu/hooks.js +48 -0
- package/lib/components/NewComponents/ContextMenu/index.d.ts +2 -0
- package/lib/components/NewComponents/ContextMenu/index.js +1 -0
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +27 -0
- package/lib/components/NewComponents/ContextMenu/styles.js +308 -0
- package/lib/components/NewComponents/ContextMenu/types.d.ts +26 -0
- package/lib/components/NewComponents/ContextMenu/types.js +1 -0
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +4 -0
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +370 -0
- package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
- package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +38 -0
- package/lib/components/NewComponents/FloatingMenuBar/styles.js +267 -0
- package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +30 -0
- package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
- package/lib/components/NewComponents/Notification/Notification.d.ts +4 -0
- package/lib/components/NewComponents/Notification/Notification.js +60 -0
- package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +8 -0
- package/lib/components/NewComponents/Notification/NotificationContainer.js +33 -0
- package/lib/components/NewComponents/Notification/index.d.ts +2 -0
- package/lib/components/NewComponents/Notification/index.js +2 -0
- package/lib/components/NewComponents/Notification/styles.d.ts +21 -0
- package/lib/components/NewComponents/Notification/styles.js +180 -0
- package/lib/components/NewComponents/Notification/types.d.ts +18 -0
- package/lib/components/NewComponents/Notification/types.js +1 -0
- package/lib/components/features/documents/TMDcmtPreview.js +93 -58
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { TMContextMenuItemProps } from '../ContextMenu';
|
|
2
|
+
export interface TMFloatingMenuItem {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
isPinned?: boolean;
|
|
9
|
+
originalMenuItem?: TMContextMenuItemProps;
|
|
10
|
+
}
|
|
11
|
+
export interface TMFloatingMenuBarProps {
|
|
12
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
13
|
+
contextMenuItems?: TMContextMenuItemProps[];
|
|
14
|
+
storageKey?: string;
|
|
15
|
+
isConstrained?: boolean;
|
|
16
|
+
defaultPosition?: Position;
|
|
17
|
+
maxItems?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface Position {
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
}
|
|
23
|
+
export interface TMFloatingMenuBarState {
|
|
24
|
+
position: Position;
|
|
25
|
+
isDragging: boolean;
|
|
26
|
+
isConfigMode: boolean;
|
|
27
|
+
orientation: 'horizontal' | 'vertical';
|
|
28
|
+
items: TMFloatingMenuItem[];
|
|
29
|
+
draggedItemIndex: number | null;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useRef } from 'react';
|
|
3
|
+
import * as S from './styles';
|
|
4
|
+
const Notification = ({ title, message, mode = 'info', position = 'top-right', duration = 3000, closable = false, stopOnMouseEnter = true, hasProgress = true, onClose, }) => {
|
|
5
|
+
const [state, setState] = useState({
|
|
6
|
+
visible: true,
|
|
7
|
+
isPaused: false,
|
|
8
|
+
progress: 100,
|
|
9
|
+
});
|
|
10
|
+
const timeoutRef = useRef(undefined);
|
|
11
|
+
const remainingTimeRef = useRef(duration);
|
|
12
|
+
const pauseTimeRef = useRef(0);
|
|
13
|
+
const closeNotification = () => {
|
|
14
|
+
setState(prev => ({ ...prev, visible: false }));
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
onClose?.();
|
|
17
|
+
}, 300);
|
|
18
|
+
};
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
// Set up auto-close timer
|
|
21
|
+
timeoutRef.current = setTimeout(() => {
|
|
22
|
+
closeNotification();
|
|
23
|
+
}, duration);
|
|
24
|
+
return () => {
|
|
25
|
+
if (timeoutRef.current) {
|
|
26
|
+
clearTimeout(timeoutRef.current);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}, [duration]);
|
|
30
|
+
const handleMouseEnter = () => {
|
|
31
|
+
if (!stopOnMouseEnter)
|
|
32
|
+
return;
|
|
33
|
+
// Pause the timer
|
|
34
|
+
if (timeoutRef.current) {
|
|
35
|
+
clearTimeout(timeoutRef.current);
|
|
36
|
+
pauseTimeRef.current = Date.now();
|
|
37
|
+
}
|
|
38
|
+
setState(prev => ({ ...prev, isPaused: true }));
|
|
39
|
+
};
|
|
40
|
+
const handleMouseLeave = () => {
|
|
41
|
+
if (!stopOnMouseEnter)
|
|
42
|
+
return;
|
|
43
|
+
// Resume the timer with remaining time
|
|
44
|
+
const pauseDuration = Date.now() - pauseTimeRef.current;
|
|
45
|
+
remainingTimeRef.current = Math.max(0, remainingTimeRef.current - pauseDuration);
|
|
46
|
+
timeoutRef.current = setTimeout(() => {
|
|
47
|
+
closeNotification();
|
|
48
|
+
}, remainingTimeRef.current);
|
|
49
|
+
setState(prev => ({ ...prev, isPaused: false }));
|
|
50
|
+
};
|
|
51
|
+
const handleClose = (e) => {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
if (timeoutRef.current) {
|
|
54
|
+
clearTimeout(timeoutRef.current);
|
|
55
|
+
}
|
|
56
|
+
closeNotification();
|
|
57
|
+
};
|
|
58
|
+
return (_jsxs(S.NotificationContainer, { "$position": position, "$mode": mode, "$visible": state.visible, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, role: "alert", "aria-live": "assertive", children: [_jsxs(S.NotificationContent, { children: [_jsx(S.NotificationTitle, { children: title }), _jsx(S.NotificationMessage, { children: message })] }), closable && (_jsx(S.CloseButton, { onClick: handleClose, "aria-label": "Close notification", children: "\u00D7" })), hasProgress && (_jsx(S.ProgressBar, { "$duration": duration, "$mode": mode, "$isPaused": state.isPaused }))] }));
|
|
59
|
+
};
|
|
60
|
+
export default Notification;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { NotificationPosition } from './types';
|
|
3
|
+
interface NotificationContainerProps {
|
|
4
|
+
position: NotificationPosition;
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
declare const NotificationContainer: React.FC<NotificationContainerProps>;
|
|
8
|
+
export default NotificationContainer;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
const Container = styled.div `
|
|
4
|
+
position: fixed;
|
|
5
|
+
z-index: 10002;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: 12px;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
|
|
11
|
+
${props => {
|
|
12
|
+
const isTop = props.$position.startsWith('top');
|
|
13
|
+
const isBottom = props.$position.startsWith('bottom');
|
|
14
|
+
const isLeft = props.$position.endsWith('left');
|
|
15
|
+
const isRight = props.$position.endsWith('right');
|
|
16
|
+
const isCenter = props.$position.endsWith('center');
|
|
17
|
+
return `
|
|
18
|
+
${isTop ? 'top: 24px;' : ''}
|
|
19
|
+
${isBottom ? 'bottom: 24px;' : ''}
|
|
20
|
+
${isLeft ? 'left: 24px;' : ''}
|
|
21
|
+
${isRight ? 'right: 24px;' : ''}
|
|
22
|
+
${isCenter ? 'left: 50%; transform: translateX(-50%);' : ''}
|
|
23
|
+
`;
|
|
24
|
+
}}
|
|
25
|
+
|
|
26
|
+
& > * {
|
|
27
|
+
pointer-events: auto;
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
const NotificationContainer = ({ position, children }) => {
|
|
31
|
+
return _jsx(Container, { "$position": position, children: children });
|
|
32
|
+
};
|
|
33
|
+
export default NotificationContainer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NotificationMode, NotificationPosition } from './types';
|
|
2
|
+
export declare const NotificationContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
3
|
+
$position: NotificationPosition;
|
|
4
|
+
$mode: NotificationMode;
|
|
5
|
+
$visible: boolean;
|
|
6
|
+
}>> & string;
|
|
7
|
+
export declare const NotificationContent: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
8
|
+
export declare const NotificationTitle: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
9
|
+
export declare const NotificationMessage: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
10
|
+
export declare const CloseButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
|
|
11
|
+
export declare const ProgressBar: 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"> & {
|
|
12
|
+
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;
|
|
13
|
+
}>, {
|
|
14
|
+
$duration: number;
|
|
15
|
+
$mode: NotificationMode;
|
|
16
|
+
$isPaused: boolean;
|
|
17
|
+
}>, {
|
|
18
|
+
$duration: number;
|
|
19
|
+
$mode: NotificationMode;
|
|
20
|
+
$isPaused: boolean;
|
|
21
|
+
}>> & string;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import styled, { keyframes } from 'styled-components';
|
|
2
|
+
const slideInFromTop = keyframes `
|
|
3
|
+
from {
|
|
4
|
+
opacity: 0;
|
|
5
|
+
transform: translateY(-100%);
|
|
6
|
+
}
|
|
7
|
+
to {
|
|
8
|
+
opacity: 1;
|
|
9
|
+
transform: translateY(0);
|
|
10
|
+
}
|
|
11
|
+
`;
|
|
12
|
+
const slideInFromBottom = keyframes `
|
|
13
|
+
from {
|
|
14
|
+
opacity: 0;
|
|
15
|
+
transform: translateY(100%);
|
|
16
|
+
}
|
|
17
|
+
to {
|
|
18
|
+
opacity: 1;
|
|
19
|
+
transform: translateY(0);
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
const slideOut = keyframes `
|
|
23
|
+
from {
|
|
24
|
+
opacity: 1;
|
|
25
|
+
transform: scale(1);
|
|
26
|
+
}
|
|
27
|
+
to {
|
|
28
|
+
opacity: 0;
|
|
29
|
+
transform: scale(0.9);
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const getModeColors = (mode) => {
|
|
33
|
+
const colors = {
|
|
34
|
+
success: {
|
|
35
|
+
bg: '#10b981',
|
|
36
|
+
bgDark: '#059669',
|
|
37
|
+
border: '#34d399',
|
|
38
|
+
text: '#ffffff',
|
|
39
|
+
},
|
|
40
|
+
error: {
|
|
41
|
+
bg: '#ef4444',
|
|
42
|
+
bgDark: '#dc2626',
|
|
43
|
+
border: '#f87171',
|
|
44
|
+
text: '#ffffff',
|
|
45
|
+
},
|
|
46
|
+
warning: {
|
|
47
|
+
bg: '#f59e0b',
|
|
48
|
+
bgDark: '#d97706',
|
|
49
|
+
border: '#fbbf24',
|
|
50
|
+
text: '#ffffff',
|
|
51
|
+
},
|
|
52
|
+
info: {
|
|
53
|
+
bg: '#3b82f6',
|
|
54
|
+
bgDark: '#2563eb',
|
|
55
|
+
border: '#60a5fa',
|
|
56
|
+
text: '#ffffff',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
return colors[mode];
|
|
60
|
+
};
|
|
61
|
+
export const NotificationContainer = styled.div `
|
|
62
|
+
position: relative;
|
|
63
|
+
z-index: 1;
|
|
64
|
+
min-width: 320px;
|
|
65
|
+
max-width: 420px;
|
|
66
|
+
background: ${props => getModeColors(props.$mode).bg};
|
|
67
|
+
border-radius: 12px;
|
|
68
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2),
|
|
69
|
+
0 4px 12px rgba(0, 0, 0, 0.15);
|
|
70
|
+
padding: 16px 20px;
|
|
71
|
+
animation: ${props => {
|
|
72
|
+
if (!props.$visible)
|
|
73
|
+
return slideOut;
|
|
74
|
+
return props.$position.startsWith('top') ? slideInFromTop : slideInFromBottom;
|
|
75
|
+
}} 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
|
|
76
|
+
backdrop-filter: blur(10px);
|
|
77
|
+
border: 2px solid ${props => getModeColors(props.$mode).border};
|
|
78
|
+
color: ${props => getModeColors(props.$mode).text};
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
|
|
81
|
+
[data-theme='dark'] & {
|
|
82
|
+
background: ${props => getModeColors(props.$mode).bgDark};
|
|
83
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4),
|
|
84
|
+
0 4px 12px rgba(0, 0, 0, 0.3);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@media (max-width: 768px) {
|
|
88
|
+
min-width: 280px;
|
|
89
|
+
max-width: calc(100vw - 48px);
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
export const NotificationContent = styled.div `
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
gap: 6px;
|
|
96
|
+
padding-right: 24px;
|
|
97
|
+
`;
|
|
98
|
+
export const NotificationTitle = styled.div `
|
|
99
|
+
font-size: 16px;
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
line-height: 1.4;
|
|
102
|
+
letter-spacing: -0.01em;
|
|
103
|
+
`;
|
|
104
|
+
export const NotificationMessage = styled.div `
|
|
105
|
+
font-size: 14px;
|
|
106
|
+
font-weight: 400;
|
|
107
|
+
line-height: 1.5;
|
|
108
|
+
opacity: 0.95;
|
|
109
|
+
`;
|
|
110
|
+
export const CloseButton = styled.button `
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: 12px;
|
|
113
|
+
right: 12px;
|
|
114
|
+
background: transparent;
|
|
115
|
+
border: none;
|
|
116
|
+
color: inherit;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
width: 24px;
|
|
119
|
+
height: 24px;
|
|
120
|
+
display: flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
justify-content: center;
|
|
123
|
+
border-radius: 6px;
|
|
124
|
+
transition: all 0.15s ease;
|
|
125
|
+
font-size: 18px;
|
|
126
|
+
line-height: 1;
|
|
127
|
+
padding: 0;
|
|
128
|
+
opacity: 0.8;
|
|
129
|
+
|
|
130
|
+
&:hover {
|
|
131
|
+
opacity: 1;
|
|
132
|
+
background: rgba(255, 255, 255, 0.2);
|
|
133
|
+
transform: scale(1.1);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
&:active {
|
|
137
|
+
transform: scale(0.95);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&:focus {
|
|
141
|
+
outline: 2px solid rgba(255, 255, 255, 0.5);
|
|
142
|
+
outline-offset: 2px;
|
|
143
|
+
}
|
|
144
|
+
`;
|
|
145
|
+
export const ProgressBar = styled.div.attrs(props => ({
|
|
146
|
+
style: {
|
|
147
|
+
animationDuration: `${props.$duration}ms`,
|
|
148
|
+
},
|
|
149
|
+
})) `
|
|
150
|
+
position: absolute;
|
|
151
|
+
bottom: 0;
|
|
152
|
+
left: 0;
|
|
153
|
+
height: 4px;
|
|
154
|
+
width: 100%;
|
|
155
|
+
background: ${props => getModeColors(props.$mode).border};
|
|
156
|
+
border-radius: 0 0 0 10px;
|
|
157
|
+
box-shadow: 0 0 8px ${props => getModeColors(props.$mode).border};
|
|
158
|
+
transform-origin: left;
|
|
159
|
+
animation: progress-shrink linear forwards;
|
|
160
|
+
animation-play-state: ${props => props.$isPaused ? 'paused' : 'running'};
|
|
161
|
+
|
|
162
|
+
@keyframes progress-shrink {
|
|
163
|
+
from {
|
|
164
|
+
transform: scaleX(1);
|
|
165
|
+
}
|
|
166
|
+
to {
|
|
167
|
+
transform: scaleX(0);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&::after {
|
|
172
|
+
content: '';
|
|
173
|
+
position: absolute;
|
|
174
|
+
top: 0;
|
|
175
|
+
right: 0;
|
|
176
|
+
width: 20px;
|
|
177
|
+
height: 100%;
|
|
178
|
+
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4));
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type NotificationMode = 'warning' | 'info' | 'error' | 'success';
|
|
2
|
+
export type NotificationPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
3
|
+
export interface NotificationProps {
|
|
4
|
+
title: string;
|
|
5
|
+
message: string;
|
|
6
|
+
mode?: NotificationMode;
|
|
7
|
+
position?: NotificationPosition;
|
|
8
|
+
duration?: number;
|
|
9
|
+
closable?: boolean;
|
|
10
|
+
stopOnMouseEnter?: boolean;
|
|
11
|
+
hasProgress?: boolean;
|
|
12
|
+
onClose?: () => void;
|
|
13
|
+
}
|
|
14
|
+
export interface NotificationState {
|
|
15
|
+
visible: boolean;
|
|
16
|
+
isPaused: boolean;
|
|
17
|
+
progress: number;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -136,32 +136,32 @@ export const TMFileViewer = ({ fileBlob, isResizingActive }) => {
|
|
|
136
136
|
const [blobUrl, setBlobUrl] = useState(undefined);
|
|
137
137
|
const [fileType, setFileType] = useState(undefined);
|
|
138
138
|
const [formattedXml, setFormattedXml] = useState(undefined);
|
|
139
|
-
const [isMobile, setIsMobile] = useState(false);
|
|
140
|
-
useEffect(() => {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}, []);
|
|
139
|
+
// const [isMobile, setIsMobile] = useState<boolean>(false);
|
|
140
|
+
// useEffect(() => {
|
|
141
|
+
// const checkIsMobile = () => {
|
|
142
|
+
// const userAgent = navigator.userAgent || navigator.vendor || (window as any).opera;
|
|
143
|
+
// // Only detect actual mobile/tablet devices, NOT desktop browsers
|
|
144
|
+
// const isMobileDevice =
|
|
145
|
+
// // Traditional mobile detection (phones and tablets)
|
|
146
|
+
// /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent) ||
|
|
147
|
+
// // Additional Android tablet detection (covers tablets in landscape)
|
|
148
|
+
// /android.*tablet|android.*mobile/i.test(userAgent) ||
|
|
149
|
+
// // Touch-only devices (excludes laptops with touchscreen)
|
|
150
|
+
// (('ontouchstart' in window || navigator.maxTouchPoints > 0) &&
|
|
151
|
+
// !/Windows NT|Macintosh|Linux/.test(userAgent)) ||
|
|
152
|
+
// // Small screen mobile devices only
|
|
153
|
+
// (window.screen.width <= 768 && /Mobi|Android/i.test(userAgent));
|
|
154
|
+
// setIsMobile(isMobileDevice);
|
|
155
|
+
// };
|
|
156
|
+
// checkIsMobile();
|
|
157
|
+
// // Listen for orientation changes (important for tablets)
|
|
158
|
+
// window.addEventListener('orientationchange', checkIsMobile);
|
|
159
|
+
// window.addEventListener('resize', checkIsMobile);
|
|
160
|
+
// return () => {
|
|
161
|
+
// window.removeEventListener('orientationchange', checkIsMobile);
|
|
162
|
+
// window.removeEventListener('resize', checkIsMobile);
|
|
163
|
+
// };
|
|
164
|
+
// }, []);
|
|
165
165
|
useEffect(() => {
|
|
166
166
|
if (fileBlob) {
|
|
167
167
|
setFileType(fileBlob.type);
|
|
@@ -222,38 +222,73 @@ export const TMFileViewer = ({ fileBlob, isResizingActive }) => {
|
|
|
222
222
|
if (fileBlob.type.includes('image')) {
|
|
223
223
|
return (_jsx(ImageViewer, { fileBlob: fileBlob, alt: '' }));
|
|
224
224
|
}
|
|
225
|
-
if (fileType === 'application/pdf' && isMobile) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
225
|
+
// if (fileType === 'application/pdf' && isMobile) {
|
|
226
|
+
// return (
|
|
227
|
+
// <object
|
|
228
|
+
// key={blobUrl}
|
|
229
|
+
// data={blobUrl}
|
|
230
|
+
// type="application/pdf"
|
|
231
|
+
// width="100%"
|
|
232
|
+
// height="100%"
|
|
233
|
+
// style={{
|
|
234
|
+
// border: 'none',
|
|
235
|
+
// zIndex: 0,
|
|
236
|
+
// pointerEvents: isResizingActive === true ? "none" : "auto"
|
|
237
|
+
// }}
|
|
238
|
+
// >
|
|
239
|
+
// {/* Fallback UI if <object> tag fails to render PDF */}
|
|
240
|
+
// <div style={{
|
|
241
|
+
// padding: '40px',
|
|
242
|
+
// textAlign: 'center',
|
|
243
|
+
// display: 'flex',
|
|
244
|
+
// flexDirection: 'column',
|
|
245
|
+
// alignItems: 'center',
|
|
246
|
+
// justifyContent: 'center',
|
|
247
|
+
// height: '100%',
|
|
248
|
+
// gap: '20px'
|
|
249
|
+
// }}>
|
|
250
|
+
// <IconPreview fontSize={96} />
|
|
251
|
+
// <div>
|
|
252
|
+
// <h3>{SDKUI_Localizator.PDFDocument}</h3>
|
|
253
|
+
// <p>{SDKUI_Localizator.PreviewNotAvailableOnDevice}</p>
|
|
254
|
+
// </div>
|
|
255
|
+
// <div style={{ display: 'flex', gap: '10px', flexWrap: 'wrap', alignItems: 'center', justifyContent: 'center' }}>
|
|
256
|
+
// <a
|
|
257
|
+
// href={blobUrl}
|
|
258
|
+
// download="document.pdf"
|
|
259
|
+
// style={{
|
|
260
|
+
// minWidth: '180px',
|
|
261
|
+
// padding: '12px 24px',
|
|
262
|
+
// backgroundColor: TMColors.primaryColor,
|
|
263
|
+
// color: 'white',
|
|
264
|
+
// textDecoration: 'none',
|
|
265
|
+
// borderRadius: '4px',
|
|
266
|
+
// display: 'inline-block'
|
|
267
|
+
// }}
|
|
268
|
+
// >
|
|
269
|
+
// {SDKUI_Localizator.DownloadFile}
|
|
270
|
+
// </a>
|
|
271
|
+
// <a
|
|
272
|
+
// href={blobUrl}
|
|
273
|
+
// target="_blank"
|
|
274
|
+
// rel="noopener noreferrer"
|
|
275
|
+
// style={{
|
|
276
|
+
// minWidth: '180px',
|
|
277
|
+
// padding: '12px 24px',
|
|
278
|
+
// backgroundColor: TMColors.primaryColor,
|
|
279
|
+
// color: 'white',
|
|
280
|
+
// textDecoration: 'none',
|
|
281
|
+
// borderRadius: '4px',
|
|
282
|
+
// display: 'inline-block'
|
|
283
|
+
// }}
|
|
284
|
+
// >
|
|
285
|
+
// {SDKUI_Localizator.OpenInNewTab}
|
|
286
|
+
// </a>
|
|
287
|
+
// </div>
|
|
288
|
+
// </div>
|
|
289
|
+
// </object>
|
|
290
|
+
// );
|
|
291
|
+
// }
|
|
257
292
|
return (_jsx("iframe", { srcDoc: formattedXml ? `<html><body>${formattedXml}</body></html>` : undefined, src: !formattedXml
|
|
258
293
|
? (fileType === 'application/pdf' ? `${blobUrl}#view=FitH&scrollbar=1` : blobUrl)
|
|
259
294
|
: undefined, title: "File Viewer", width: "100%", height: "100%", style: { border: 'none', zIndex: 0, pointerEvents: isResizingActive === true ? "none" : "auto" } }, blobUrl));
|