@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(false);
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 = useRef(false);
148
- const lastX = useRef(0);
149
- const lastY = useRef(0);
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 containerWidth = container.clientWidth;
166
- const containerHeight = container.clientHeight;
167
- const imageWidth = image.naturalWidth;
168
- const imageHeight = image.naturalHeight;
169
- const scaleX = containerWidth / imageWidth;
170
- const scaleY = containerHeight / imageHeight;
171
- const initialScale = Math.min(scaleX, scaleY);
172
- setBaseZoom(initialScale);
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 isZoomedIn = useMemo(() => {
205
- return zoomFactor > 1;
206
- }, [zoomFactor]);
207
- const containerCursor = useMemo(() => {
208
- if (isZoomedIn) {
209
- if (isDragging)
210
- return 'grabbing';
211
- return 'grab';
212
- }
213
- return 'default';
214
- }, [isZoomedIn, isDragging]);
215
- const handleZoomIn = () => setZoomFactor(prev => Math.min(prev + 0.25, 3));
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 handleMouseDown = (e) => {
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
- isDragging.current = true;
226
- const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
227
- const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
228
- lastX.current = clientX;
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 handleMouseMove = (e) => {
232
- if (!isDragging.current)
231
+ const onMouseMove = (e) => {
232
+ if (!isDragging)
233
233
  return;
234
- const clientX = 'touches' in e ? e.touches[0].clientX : e.clientX;
235
- const clientY = 'touches' in e ? e.touches[0].clientY : e.clientY;
236
- const dx = clientX - lastX.current;
237
- const dy = clientY - lastY.current;
238
- const newTx = translateX + dx;
239
- const newTy = translateY + dy;
240
- const clamped = clampTranslation(newTx, newTy, baseZoom * zoomFactor);
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
- lastX.current = clientX;
244
- lastY.current = clientY;
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
- const moveHandler = (e) => handleMouseMove(e);
251
- const upHandler = () => handleMouseUp();
252
- window.addEventListener('mousemove', moveHandler);
253
- window.addEventListener('touchmove', moveHandler);
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', moveHandler);
258
- window.removeEventListener('touchmove', moveHandler);
259
- window.removeEventListener('mouseup', upHandler);
260
- window.removeEventListener('touchend', upHandler);
253
+ window.removeEventListener('mousemove', onMouseMove);
254
+ window.removeEventListener('mouseup', stopDrag);
255
+ window.removeEventListener('touchmove', onMouseMove);
256
+ window.removeEventListener('touchend', stopDrag);
261
257
  };
262
- }, [baseZoom, zoomFactor, translateX, translateY]);
263
- const fullZoom = baseZoom * zoomFactor;
264
- const transform = `scale(${fullZoom}) translate(${translateX}px, ${translateY}px)`;
265
- return (_jsxs(ImageContainer, { className: className, ref: containerRef, onMouseDown: handleMouseDown, onTouchStart: handleMouseDown, "$cursor": containerCursor, children: [imageUrl && (_jsx(StyledImage, { ref: imageRef, src: imageUrl, alt: alt, "$transform": transform })), _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, {}) })] })] }));
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 ZoomButton = styled.button ` display: flex; align-items: center; justify-content: center; background: #007bff; color: white; border: none; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 14px; &:disabled { background: #ccc; cursor: not-allowed; } `;
292
- const StyledImage = styled.img.attrs(props => ({ style: { transform: props.$transform, }, })) ` position: absolute; top: 0; left: 0; transform-origin: top left; pointer-events: none; `;
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
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.12.106",
3
+ "version": "6.12.108",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",