@topconsultnpm/sdkui-react-beta 6.12.106 → 6.12.108
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.
@@ -70,7 +70,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
70
70
|
const [currentDcmt, setCurrentDcmt] = useState();
|
71
71
|
const [dcmtFile, setDcmtFile] = useState(null);
|
72
72
|
const [focusedMetadataValue, setFocusedMetadataValue] = useState();
|
73
|
-
const [showAll, setShowAll] = useState(
|
73
|
+
const [showAll, setShowAll] = useState(layoutMode === LayoutModes.Ark);
|
74
74
|
const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
|
75
75
|
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
|
76
76
|
const deviceType = useDeviceType();
|
@@ -144,9 +144,9 @@ const ImageViewer = ({ fileBlob, alt = 'Image', className }) => {
|
|
144
144
|
const [zoomFactor, setZoomFactor] = useState(1);
|
145
145
|
const [translateX, setTranslateX] = useState(0);
|
146
146
|
const [translateY, setTranslateY] = useState(0);
|
147
|
-
const isDragging =
|
148
|
-
const
|
149
|
-
const
|
147
|
+
const [isDragging, setIsDragging] = useState(false);
|
148
|
+
const dragStartX = useRef(0);
|
149
|
+
const dragStartY = useRef(0);
|
150
150
|
useEffect(() => {
|
151
151
|
if (fileBlob) {
|
152
152
|
const url = URL.createObjectURL(fileBlob);
|
@@ -162,29 +162,29 @@ const ImageViewer = ({ fileBlob, alt = 'Image', className }) => {
|
|
162
162
|
const container = containerRef.current;
|
163
163
|
const image = imageRef.current;
|
164
164
|
if (container && image) {
|
165
|
-
const
|
166
|
-
const
|
167
|
-
const
|
168
|
-
const
|
169
|
-
const scaleX =
|
170
|
-
const scaleY =
|
171
|
-
const
|
172
|
-
setBaseZoom(
|
165
|
+
const cw = container.clientWidth;
|
166
|
+
const ch = container.clientHeight;
|
167
|
+
const iw = image.naturalWidth;
|
168
|
+
const ih = image.naturalHeight;
|
169
|
+
const scaleX = cw / iw;
|
170
|
+
const scaleY = ch / ih;
|
171
|
+
const initialZoom = Math.min(scaleX, scaleY);
|
172
|
+
setBaseZoom(initialZoom);
|
173
173
|
setZoomFactor(1);
|
174
174
|
setTranslateX(0);
|
175
175
|
setTranslateY(0);
|
176
176
|
}
|
177
177
|
};
|
178
178
|
const img = imageRef.current;
|
179
|
-
if (img?.complete)
|
179
|
+
if (img?.complete)
|
180
180
|
handleLoad();
|
181
|
-
}
|
182
181
|
else {
|
183
182
|
img?.addEventListener('load', handleLoad);
|
184
183
|
return () => img?.removeEventListener('load', handleLoad);
|
185
184
|
}
|
186
185
|
return () => { };
|
187
186
|
}, [imageUrl]);
|
187
|
+
const fullZoom = baseZoom * zoomFactor;
|
188
188
|
const clampTranslation = (tx, ty, zoom) => {
|
189
189
|
const container = containerRef.current;
|
190
190
|
const image = imageRef.current;
|
@@ -201,68 +201,67 @@ const ImageViewer = ({ fileBlob, alt = 'Image', className }) => {
|
|
201
201
|
y: Math.max(minY, Math.min(0, ty)),
|
202
202
|
};
|
203
203
|
};
|
204
|
-
const
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
const handleZoomOut = () => setZoomFactor(prev => Math.max(prev - 0.25, 0.5));
|
204
|
+
const handleZoom = (delta) => {
|
205
|
+
const newZoom = Math.min(3, Math.max(0.5, zoomFactor + delta));
|
206
|
+
if (newZoom === zoomFactor)
|
207
|
+
return;
|
208
|
+
const scaleChange = newZoom / zoomFactor;
|
209
|
+
const newTx = translateX * scaleChange;
|
210
|
+
const newTy = translateY * scaleChange;
|
211
|
+
const clamped = clampTranslation(newTx, newTy, baseZoom * newZoom);
|
212
|
+
setTranslateX(clamped.x);
|
213
|
+
setTranslateY(clamped.y);
|
214
|
+
setZoomFactor(newZoom);
|
215
|
+
};
|
217
216
|
const handleResetZoom = () => {
|
218
217
|
setZoomFactor(1);
|
219
218
|
setTranslateX(0);
|
220
219
|
setTranslateY(0);
|
221
220
|
};
|
222
|
-
const
|
221
|
+
const handleZoomIn = () => handleZoom(0.25);
|
222
|
+
const handleZoomOut = () => handleZoom(-0.25);
|
223
|
+
const onMouseDown = (e) => {
|
223
224
|
if (zoomFactor === 1)
|
224
225
|
return;
|
225
|
-
|
226
|
-
const
|
227
|
-
|
228
|
-
|
229
|
-
lastY.current = clientY;
|
226
|
+
setIsDragging(true);
|
227
|
+
const point = 'touches' in e ? e.touches[0] : e;
|
228
|
+
dragStartX.current = point.clientX;
|
229
|
+
dragStartY.current = point.clientY;
|
230
230
|
};
|
231
|
-
const
|
232
|
-
if (!isDragging
|
231
|
+
const onMouseMove = (e) => {
|
232
|
+
if (!isDragging)
|
233
233
|
return;
|
234
|
-
const
|
235
|
-
const
|
236
|
-
const
|
237
|
-
const
|
238
|
-
const newTx = translateX + dx;
|
239
|
-
const newTy = translateY + dy;
|
240
|
-
const clamped = clampTranslation(newTx, newTy,
|
234
|
+
const point = 'touches' in e ? e.touches[0] : e;
|
235
|
+
const dx = point.clientX - dragStartX.current;
|
236
|
+
const dy = point.clientY - dragStartY.current;
|
237
|
+
const scale = baseZoom * zoomFactor;
|
238
|
+
const newTx = translateX + dx / scale;
|
239
|
+
const newTy = translateY + dy / scale;
|
240
|
+
const clamped = clampTranslation(newTx, newTy, scale);
|
241
241
|
setTranslateX(clamped.x);
|
242
242
|
setTranslateY(clamped.y);
|
243
|
-
|
244
|
-
|
245
|
-
};
|
246
|
-
const handleMouseUp = () => {
|
247
|
-
isDragging.current = false;
|
243
|
+
dragStartX.current = point.clientX;
|
244
|
+
dragStartY.current = point.clientY;
|
248
245
|
};
|
246
|
+
const stopDrag = () => setIsDragging(false);
|
249
247
|
useEffect(() => {
|
250
|
-
|
251
|
-
|
252
|
-
window.addEventListener('
|
253
|
-
window.addEventListener('
|
254
|
-
window.addEventListener('mouseup', upHandler);
|
255
|
-
window.addEventListener('touchend', upHandler);
|
248
|
+
window.addEventListener('mousemove', onMouseMove);
|
249
|
+
window.addEventListener('mouseup', stopDrag);
|
250
|
+
window.addEventListener('touchmove', onMouseMove);
|
251
|
+
window.addEventListener('touchend', stopDrag);
|
256
252
|
return () => {
|
257
|
-
window.removeEventListener('mousemove',
|
258
|
-
window.removeEventListener('
|
259
|
-
window.removeEventListener('
|
260
|
-
window.removeEventListener('touchend',
|
253
|
+
window.removeEventListener('mousemove', onMouseMove);
|
254
|
+
window.removeEventListener('mouseup', stopDrag);
|
255
|
+
window.removeEventListener('touchmove', onMouseMove);
|
256
|
+
window.removeEventListener('touchend', stopDrag);
|
261
257
|
};
|
262
|
-
}, [
|
263
|
-
const
|
264
|
-
|
265
|
-
|
258
|
+
}, [translateX, translateY, fullZoom, isDragging]);
|
259
|
+
const cursor = useMemo(() => {
|
260
|
+
if (zoomFactor <= 1)
|
261
|
+
return 'default';
|
262
|
+
return isDragging ? 'grabbing' : 'grab';
|
263
|
+
}, [zoomFactor, isDragging]);
|
264
|
+
return (_jsxs(ImageContainer, { ref: containerRef, onMouseDown: onMouseDown, onTouchStart: onMouseDown, "$cursor": cursor, className: className, children: [imageUrl && (_jsx(StyledImage, { ref: imageRef, src: imageUrl, alt: alt, "$scale": fullZoom, "$tx": translateX, "$ty": translateY })), _jsxs(Toolbar, { children: [_jsx(ZoomButton, { onClick: handleZoomOut, disabled: zoomFactor <= 0.5, children: _jsx(IconZoomOutLinear, {}) }), _jsx(ZoomButton, { onClick: handleResetZoom, disabled: zoomFactor === 1 && translateX === 0 && translateY === 0, children: SDKUI_Localizator.Restore }), _jsx(ZoomButton, { onClick: handleZoomIn, disabled: zoomFactor >= 3, children: _jsx(IconZoomInLinear, {}) })] })] }));
|
266
265
|
};
|
267
266
|
export const TMNothingToShow = ({ text = '', secondText, fileExt, icon = _jsx(IconPreview, { fontSize: 96 }) }) => {
|
268
267
|
return (_jsx(StyledAnimatedComponentOpacity, { style: { width: '100%', height: '100%' }, children: _jsxs(StyledPanelStatusContainer, { children: [icon, _jsxs(StyledPreviewNotAvailable, { children: [text && _jsx("div", { children: text }), _jsxs("div", { children: [" ", secondText ?? 'Anteprima non disponibile.', fileExt && _jsx("b", { children: ` (*.${fileExt})` })] })] })] }) }));
|
@@ -287,6 +286,19 @@ export const StyledHeaderIcon = styled.div ` color: ${props => props.$color}; c
|
|
287
286
|
export const StyledPanelStatusContainer = styled.div ` width: 100%; height: 100%; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; `;
|
288
287
|
const StyledPreviewNotAvailable = styled.div ` display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; `;
|
289
288
|
const ImageContainer = styled.div ` width: 100%; height: 100%; position: relative; overflow: hidden; background: #f5f5f5; touch-action: none; user-select: none; cursor: ${({ $cursor }) => $cursor ?? 'default'}; `;
|
289
|
+
const ZoomButton = styled.button ` display: flex; align-items: center; justify-content: center; background: ${TMColors.primary}; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 14px; &:disabled { background: #ccc; cursor: not-allowed; } `;
|
290
290
|
const Toolbar = styled.div ` position: absolute; bottom: 15px; left: 15px; display: flex; gap: 10px; background: rgba(255, 255, 255, 0.8); padding: 6px 10px; border-radius: 8px; box-shadow: 0 0 5px rgba(0, 0, 0, 0.15); z-index: 1; `;
|
291
|
-
const
|
292
|
-
|
291
|
+
const StyledImage = styled.img.attrs(props => ({
|
292
|
+
style: {
|
293
|
+
transform: `translate(${props.$tx}px, ${props.$ty}px) scale(${props.$scale})`,
|
294
|
+
},
|
295
|
+
})) `
|
296
|
+
display: block;
|
297
|
+
max-width: none;
|
298
|
+
max-height: none;
|
299
|
+
transform-origin: top left;
|
300
|
+
pointer-events: none;
|
301
|
+
position: absolute;
|
302
|
+
top: 0;
|
303
|
+
left: 0;
|
304
|
+
`;
|