carbon-addons-iot-react 5.8.0 → 5.8.2
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/css/carbon-addons-iot-react.css +1 -1
- package/css/carbon-addons-iot-react.css.map +1 -1
- package/es/components/HotspotEditorModal/HotspotEditorModal.js +4 -0
- package/es/components/HotspotEditorModal/hooks/hotspotStateHook.js +33 -3
- package/es/components/ImageCard/HotspotContent.js +1 -1
- package/es/components/ImageCard/ImageHotspots.js +187 -9
- package/lib/components/HotspotEditorModal/HotspotEditorModal.js +4 -0
- package/lib/components/HotspotEditorModal/hooks/hotspotStateHook.js +33 -3
- package/lib/components/ImageCard/HotspotContent.js +1 -1
- package/lib/components/ImageCard/ImageHotspots.js +186 -8
- package/lib/css/carbon-addons-iot-react.css +1 -1
- package/lib/css/carbon-addons-iot-react.css.map +1 -1
- package/lib/scss/components/ValueCard/_attribute.scss +1 -1
- package/package.json +1 -1
- package/scss/components/ValueCard/_attribute.scss +1 -1
- package/umd/carbon-addons-iot-react.js +224 -12
|
@@ -89,6 +89,10 @@ var propTypes = {
|
|
|
89
89
|
* Emits position obj {x, y} of hotspot to be added.
|
|
90
90
|
*/
|
|
91
91
|
onAddHotspotPosition: PropTypes__default.default.func,
|
|
92
|
+
/** Callback when a hotspot is dragged to new position in isEditable mode
|
|
93
|
+
* Emits new hotspots and updated position obj {x, y} of hotspot.
|
|
94
|
+
*/
|
|
95
|
+
onUpdateHotspotPosition: PropTypes__default.default.func,
|
|
92
96
|
/** Callback when a hotspot is clicked in isEditable mode, emits position obj {x, y} */
|
|
93
97
|
onSelectHotspot: PropTypes__default.default.func,
|
|
94
98
|
/**
|
|
@@ -129,6 +133,7 @@ var defaultProps = {
|
|
|
129
133
|
isHotspotDataLoading: false,
|
|
130
134
|
isEditable: false,
|
|
131
135
|
onAddHotspotPosition: function onAddHotspotPosition() {},
|
|
136
|
+
onUpdateHotspotPosition: function onUpdateHotspotPosition() {},
|
|
132
137
|
onSelectHotspot: function onSelectHotspot() {},
|
|
133
138
|
onHotspotContentChanged: function onHotspotContentChanged() {},
|
|
134
139
|
background: '#eee',
|
|
@@ -247,6 +252,7 @@ var calculateHotspotContainerLayout = function calculateHotspotContainerLayout(_
|
|
|
247
252
|
var width;
|
|
248
253
|
var height;
|
|
249
254
|
var top;
|
|
255
|
+
var left;
|
|
250
256
|
|
|
251
257
|
// CONTAIN
|
|
252
258
|
if (objectFit === 'contain') {
|
|
@@ -254,32 +260,38 @@ var calculateHotspotContainerLayout = function calculateHotspotContainerLayout(_
|
|
|
254
260
|
width = imageWidth;
|
|
255
261
|
height = imageWidth / imageRatio;
|
|
256
262
|
top = imageScale > 1 ? imageOffsetY : imageObjectFitOffsetY;
|
|
263
|
+
left = imageScale > 1 ? 0 : (containerWidth - imageWidth) / 2;
|
|
257
264
|
} else if (imageOrientation === 'portrait') {
|
|
258
265
|
width = imageHeight / imageRatio;
|
|
259
266
|
height = imageHeight;
|
|
260
267
|
top = imageOffsetY;
|
|
268
|
+
left = (containerWidth - width) / 2;
|
|
261
269
|
}
|
|
262
270
|
// FILL
|
|
263
271
|
} else if (objectFit === 'fill') {
|
|
264
272
|
width = imageScale > 1 ? imageWidth : containerWidth;
|
|
265
273
|
height = imageScale > 1 ? imageHeight : containerHeight;
|
|
266
274
|
top = imageOffsetY;
|
|
275
|
+
left = 0;
|
|
267
276
|
// NO OBJECT FIT
|
|
268
277
|
} else if (!objectFit) {
|
|
269
278
|
if (imageOrientation === 'landscape') {
|
|
270
279
|
width = imageWidth;
|
|
271
280
|
height = imageWidth / imageRatio;
|
|
272
281
|
top = imageOffsetY;
|
|
282
|
+
left = 0;
|
|
273
283
|
} else if (imageOrientation === 'portrait') {
|
|
274
284
|
width = imageHeight / imageRatio;
|
|
275
285
|
height = imageHeight;
|
|
276
286
|
top = imageOffsetY;
|
|
287
|
+
left = (containerWidth - width) / 2;
|
|
277
288
|
}
|
|
278
289
|
}
|
|
279
290
|
return {
|
|
280
291
|
width: width,
|
|
281
292
|
height: height,
|
|
282
|
-
top: top
|
|
293
|
+
top: top,
|
|
294
|
+
left: left
|
|
283
295
|
};
|
|
284
296
|
};
|
|
285
297
|
var calculateObjectFitOffset = function calculateObjectFitOffset(_ref5) {
|
|
@@ -524,6 +536,7 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
524
536
|
isEditable = _ref9.isEditable,
|
|
525
537
|
isHotspotDataLoading = _ref9.isHotspotDataLoading,
|
|
526
538
|
onAddHotspotPosition = _ref9.onAddHotspotPosition,
|
|
539
|
+
onUpdateHotspotPosition = _ref9.onUpdateHotspotPosition,
|
|
527
540
|
onSelectHotspot = _ref9.onSelectHotspot,
|
|
528
541
|
onHotspotContentChanged = _ref9.onHotspotContentChanged,
|
|
529
542
|
zoomMax = _ref9.zoomMax,
|
|
@@ -568,9 +581,52 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
568
581
|
_useState12 = _slicedToArray__default.default(_useState11, 2),
|
|
569
582
|
options = _useState12[0],
|
|
570
583
|
setOptions = _useState12[1];
|
|
584
|
+
// Tracks if a hotspot is being dragged and which one.
|
|
585
|
+
var _useState13 = React.useState(null),
|
|
586
|
+
_useState14 = _slicedToArray__default.default(_useState13, 2),
|
|
587
|
+
draggingHotspotId = _useState14[0],
|
|
588
|
+
setDraggingHotspotId = _useState14[1];
|
|
589
|
+
|
|
590
|
+
// Ref for outer container
|
|
591
|
+
var containerRef = React.useRef(null);
|
|
592
|
+
var dragStateRef = React.useRef({
|
|
593
|
+
// Flag to indicate if a drag is active
|
|
594
|
+
isDragging: false,
|
|
595
|
+
// Stores the starting mouse position of a drag
|
|
596
|
+
dragStartPosition: {
|
|
597
|
+
x: 0,
|
|
598
|
+
y: 0
|
|
599
|
+
},
|
|
600
|
+
// Tracks the current position during a drag
|
|
601
|
+
currentDargPosition: null,
|
|
602
|
+
// Stores layout of image and container
|
|
603
|
+
layout: {
|
|
604
|
+
rect: null,
|
|
605
|
+
hotspotLayout: null
|
|
606
|
+
},
|
|
607
|
+
// Tracks Scheduled Animation Frames
|
|
608
|
+
frame: null
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// Minimum pixel movement before a drag is initiated
|
|
612
|
+
var DRAG_THRESHOLD = 5;
|
|
571
613
|
var mergedI18n = React.useMemo(function () {
|
|
572
614
|
return _objectSpread(_objectSpread({}, defaultProps.i18n), i18n);
|
|
573
615
|
}, [i18n]);
|
|
616
|
+
var hotspotsWithId = React.useMemo(function () {
|
|
617
|
+
return hotspots.map(function (hotspot, index) {
|
|
618
|
+
return _objectSpread(_objectSpread({}, hotspot), {}, {
|
|
619
|
+
id: "".concat(hotspot.x, "-").concat(hotspot.y, "-").concat(index)
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
}, [hotspots]);
|
|
623
|
+
var _useState15 = React.useState(hotspotsWithId),
|
|
624
|
+
_useState16 = _slicedToArray__default.default(_useState15, 2),
|
|
625
|
+
editableHotspots = _useState16[0],
|
|
626
|
+
setEditableHotspots = _useState16[1];
|
|
627
|
+
React.useEffect(function () {
|
|
628
|
+
setEditableHotspots(hotspotsWithId);
|
|
629
|
+
}, [hotspotsWithId]);
|
|
574
630
|
var handleCtrlKeyUp = React.useCallback(function (event) {
|
|
575
631
|
// Was the control key unpressed
|
|
576
632
|
if (event.key === KeyCodeConstants.keyboardKeys.CONTROL) {
|
|
@@ -642,6 +698,11 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
642
698
|
objectFit: displayOption
|
|
643
699
|
};
|
|
644
700
|
var onHotspotClicked = React.useCallback(function (evt, position) {
|
|
701
|
+
// prevent click behavior after drag
|
|
702
|
+
if (dragStateRef.current.isDragging) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
|
|
645
706
|
// It is possible to receive two events here, one Mouse event and one Pointer event.
|
|
646
707
|
// When used in the ImageHotspots component the Pointer event can somehow be from a
|
|
647
708
|
// previously clicked hotspot. See https://github.com/carbon-design-system/carbon-addons-iot-react/issues/1803
|
|
@@ -650,6 +711,108 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
650
711
|
onSelectHotspot(position);
|
|
651
712
|
}
|
|
652
713
|
}, [onSelectHotspot, isEditable]);
|
|
714
|
+
var handleMouseDownHotspot = React.useCallback(function (e, id1) {
|
|
715
|
+
var hotspot = editableHotspots.find(function (h) {
|
|
716
|
+
return h.id === id1;
|
|
717
|
+
});
|
|
718
|
+
if (!isEditable || (hotspot === null || hotspot === void 0 ? void 0 : hotspot.type) === 'dynamic') {
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
e.stopPropagation();
|
|
722
|
+
setDraggingHotspotId(id1);
|
|
723
|
+
dragStateRef.current.isDragging = true;
|
|
724
|
+
dragStateRef.current.dragStartPosition = {
|
|
725
|
+
x: e.clientX,
|
|
726
|
+
y: e.clientY
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
// Calculate layout once at drag start
|
|
730
|
+
if (containerRef.current) {
|
|
731
|
+
var rect = containerRef.current.getBoundingClientRect();
|
|
732
|
+
var hotspotLayout = calculateHotspotContainerLayout(image, container, displayOption);
|
|
733
|
+
dragStateRef.current.layout = {
|
|
734
|
+
rect: rect,
|
|
735
|
+
hotspotLayout: hotspotLayout
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
}, [container, displayOption, image, isEditable, editableHotspots]);
|
|
739
|
+
var handleMouseMoveHotspot = React.useCallback(function (e) {
|
|
740
|
+
if (draggingHotspotId !== null && containerRef.current) {
|
|
741
|
+
var _dragStateRef$current = dragStateRef.current,
|
|
742
|
+
isDragging = _dragStateRef$current.isDragging,
|
|
743
|
+
dragStartPosition = _dragStateRef$current.dragStartPosition,
|
|
744
|
+
layout = _dragStateRef$current.layout;
|
|
745
|
+
var dx = e.clientX - dragStartPosition.x;
|
|
746
|
+
var dy = e.clientY - dragStartPosition.y;
|
|
747
|
+
var distance = Math.sqrt(dx * dx + dy * dy);
|
|
748
|
+
if (distance > DRAG_THRESHOLD && isDragging) {
|
|
749
|
+
var rect = layout.rect,
|
|
750
|
+
hotspotLayout = layout.hotspotLayout;
|
|
751
|
+
var x = (e.clientX - rect.left - hotspotLayout.left) / hotspotLayout.width * 100;
|
|
752
|
+
var y = (e.clientY - rect.top - hotspotLayout.top) / hotspotLayout.height * 100;
|
|
753
|
+
// Clamp within image boundaries
|
|
754
|
+
x = Math.max(0, Math.min(100, x));
|
|
755
|
+
y = Math.max(0, Math.min(100, y));
|
|
756
|
+
dragStateRef.current.currentDargPosition = {
|
|
757
|
+
x: x,
|
|
758
|
+
y: y
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
// throttle with requestAnimationFrame
|
|
762
|
+
if (dragStateRef.current.frame === null) {
|
|
763
|
+
dragStateRef.current.frame = requestAnimationFrame(function () {
|
|
764
|
+
setEditableHotspots(function (prev) {
|
|
765
|
+
return prev.map(function (item) {
|
|
766
|
+
return item.id === draggingHotspotId ? _objectSpread(_objectSpread({}, item), {}, {
|
|
767
|
+
x: dragStateRef.current.currentDargPosition.x,
|
|
768
|
+
y: dragStateRef.current.currentDargPosition.y
|
|
769
|
+
}) : item;
|
|
770
|
+
});
|
|
771
|
+
});
|
|
772
|
+
dragStateRef.current.frame = null;
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}, [draggingHotspotId]);
|
|
778
|
+
var handleMouseUpHotspot = React.useCallback(function (e) {
|
|
779
|
+
if (draggingHotspotId !== null && dragStateRef.current.isDragging) {
|
|
780
|
+
e.stopPropagation();
|
|
781
|
+
var _ref10 = dragStateRef.current.currentDargPosition || {},
|
|
782
|
+
x = _ref10.x,
|
|
783
|
+
y = _ref10.y;
|
|
784
|
+
onUpdateHotspotPosition({
|
|
785
|
+
newHotspots: editableHotspots,
|
|
786
|
+
position: {
|
|
787
|
+
x: x,
|
|
788
|
+
y: y
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
setDraggingHotspotId(null);
|
|
792
|
+
dragStateRef.current.currentDargPosition = null;
|
|
793
|
+
dragStateRef.current.isDragging = false;
|
|
794
|
+
}
|
|
795
|
+
}, [editableHotspots, draggingHotspotId, onUpdateHotspotPosition]);
|
|
796
|
+
React.useEffect(function () {
|
|
797
|
+
var dragState = dragStateRef.current;
|
|
798
|
+
return function () {
|
|
799
|
+
if (dragState.frame !== null) {
|
|
800
|
+
cancelAnimationFrame(dragState.frame);
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
}, []);
|
|
804
|
+
|
|
805
|
+
// Listens to mouse movement for dragging hotspot
|
|
806
|
+
React.useEffect(function () {
|
|
807
|
+
if (!isEditable) return undefined;
|
|
808
|
+
var containerElement = containerRef.current;
|
|
809
|
+
containerElement.addEventListener('mousemove', handleMouseMoveHotspot);
|
|
810
|
+
containerElement.addEventListener('mouseup', handleMouseUpHotspot);
|
|
811
|
+
return function () {
|
|
812
|
+
containerElement.removeEventListener('mousemove', handleMouseMoveHotspot);
|
|
813
|
+
containerElement.removeEventListener('mouseup', handleMouseUpHotspot);
|
|
814
|
+
};
|
|
815
|
+
}, [draggingHotspotId, handleMouseMoveHotspot, handleMouseUpHotspot, isEditable]);
|
|
653
816
|
var getIconRenderFunction = React.useCallback(function () {
|
|
654
817
|
return renderIconByName || (Array.isArray(icons) ? function (name, props) {
|
|
655
818
|
var _icons$find;
|
|
@@ -668,7 +831,7 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
668
831
|
|
|
669
832
|
// Performance improvement
|
|
670
833
|
var cachedHotspots = React.useMemo(function () {
|
|
671
|
-
return
|
|
834
|
+
return editableHotspots.map(function (hotspot, index) {
|
|
672
835
|
var _hotspot$content;
|
|
673
836
|
var x = hotspot.x,
|
|
674
837
|
y = hotspot.y;
|
|
@@ -678,10 +841,10 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
678
841
|
// Determine whether the icon needs to be dynamically overridden by a threshold
|
|
679
842
|
var matchingAttributeThresholds = [];
|
|
680
843
|
if ((_hotspot$content = hotspot.content) !== null && _hotspot$content !== void 0 && _hotspot$content.attributes) {
|
|
681
|
-
hotspot.content.attributes.forEach(function (
|
|
844
|
+
hotspot.content.attributes.forEach(function (_ref11) {
|
|
682
845
|
var _hotspot$content2;
|
|
683
|
-
var thresholds =
|
|
684
|
-
dataSourceId =
|
|
846
|
+
var thresholds = _ref11.thresholds,
|
|
847
|
+
dataSourceId = _ref11.dataSourceId;
|
|
685
848
|
if (!isEmpty(thresholds) && !isEmpty((_hotspot$content2 = hotspot.content) === null || _hotspot$content2 === void 0 ? void 0 : _hotspot$content2.values)) {
|
|
686
849
|
var _hotspot$content3;
|
|
687
850
|
var attributeThresholds = cardUtilityFunctions.findMatchingThresholds(thresholds.map(function (threshold) {
|
|
@@ -707,10 +870,13 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
707
870
|
key: "".concat(x, "-").concat(y, "-").concat(index),
|
|
708
871
|
renderIconByName: getIconRenderFunction(),
|
|
709
872
|
isSelected: hotspotIsSelected,
|
|
710
|
-
onClick: onHotspotClicked
|
|
873
|
+
onClick: onHotspotClicked,
|
|
874
|
+
onMouseDown: function onMouseDown(e) {
|
|
875
|
+
return handleMouseDownHotspot(e, hotspot.id);
|
|
876
|
+
}
|
|
711
877
|
}));
|
|
712
878
|
});
|
|
713
|
-
}, [
|
|
879
|
+
}, [editableHotspots, selectedHotspots, locale, getIconRenderFunction, isEditable, onHotspotContentChanged, mergedI18n, onHotspotClicked, handleMouseDownHotspot]);
|
|
714
880
|
var hotspotsStyle = {
|
|
715
881
|
position: 'absolute',
|
|
716
882
|
left: image.offsetX,
|
|
@@ -753,7 +919,8 @@ var ImageHotspots = function ImageHotspots(_ref9) {
|
|
|
753
919
|
// If we leave the container, stop detecting the drag
|
|
754
920
|
stopDrag(cursor, setCursor);
|
|
755
921
|
}
|
|
756
|
-
}
|
|
922
|
+
},
|
|
923
|
+
ref: containerRef
|
|
757
924
|
}, src ? /*#__PURE__*/React__default.default.createElement("img", {
|
|
758
925
|
id: id,
|
|
759
926
|
className: "".concat(iotPrefix, "--image-card-img"),
|
|
@@ -980,6 +1147,17 @@ ImageHotspots.__docgenInfo = {
|
|
|
980
1147
|
},
|
|
981
1148
|
"required": false
|
|
982
1149
|
},
|
|
1150
|
+
"onUpdateHotspotPosition": {
|
|
1151
|
+
"defaultValue": {
|
|
1152
|
+
"value": "() => {}",
|
|
1153
|
+
"computed": false
|
|
1154
|
+
},
|
|
1155
|
+
"description": "Callback when a hotspot is dragged to new position in isEditable mode\nEmits new hotspots and updated position obj {x, y} of hotspot.",
|
|
1156
|
+
"type": {
|
|
1157
|
+
"name": "func"
|
|
1158
|
+
},
|
|
1159
|
+
"required": false
|
|
1160
|
+
},
|
|
983
1161
|
"onSelectHotspot": {
|
|
984
1162
|
"defaultValue": {
|
|
985
1163
|
"value": "() => {}",
|
|
@@ -40829,7 +40829,7 @@ html[dir=rtl] .iot--time-picker__wrapper .iot--time-picker__controls {
|
|
|
40829
40829
|
|
|
40830
40830
|
.iot--value-card__attribute {
|
|
40831
40831
|
display: flex;
|
|
40832
|
-
height:
|
|
40832
|
+
height: 44px;
|
|
40833
40833
|
align-items: baseline;
|
|
40834
40834
|
padding-right: 1rem;
|
|
40835
40835
|
}
|