cloudmr-ux 4.4.8 → 4.5.0

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.
@@ -1,8 +1,18 @@
1
1
  import React from "react";
2
2
  import "./Toolbar.css";
3
3
  import type { DrawToolkitProps } from "../draw-toolkit/DrawToolkit";
4
- /** Props for {@link DrawToolkit} minus brush controls when using {@link MroDrawToolkit}. */
5
- export type CloudMrDrawToolkitProps = Omit<DrawToolkitProps, "brushSize" | "updateBrushSize">;
4
+ /** Props for {@link MroDrawToolkit} extends draw toolkit with MRO pen/shape controls. */
5
+ export type CloudMrDrawToolkitProps = Omit<DrawToolkitProps, "rois" | "selectedROI" | "setSelectedROI" | "saveROI" | "labelsVisible" | "toggleLabelsVisible"> & {
6
+ penDrawMode?: "freehand" | "polyline";
7
+ onPenDrawModeChange?: (mode: "freehand" | "polyline") => void;
8
+ polylineVertexCount?: number;
9
+ onCancelPolyline?: () => void;
10
+ onFinishPolyline?: () => void;
11
+ onCloseFillPolyline?: () => void;
12
+ shapeDraftActive?: boolean;
13
+ onApplyShapeDraft?: () => void;
14
+ onCancelShapeDraft?: () => void;
15
+ };
6
16
  export interface CloudMrNiivuePanelProps {
7
17
  nv: any;
8
18
  pipelineID: string;
@@ -106,9 +106,13 @@ export function CloudMrNiivuePanel(props) {
106
106
  props.resampleImage();
107
107
  }, [histogram]);
108
108
  function applyDrawShapeTool(tool) {
109
+ var _a, _b;
109
110
  if (props.shapeDraft) {
110
111
  props.onCancelShapeDraft();
111
112
  }
113
+ if (tool !== "pen") {
114
+ (_b = (_a = props.drawToolkitProps).onPenDrawModeChange) === null || _b === void 0 ? void 0 : _b.call(_a, "freehand");
115
+ }
112
116
  props.setDrawShapeTool(tool);
113
117
  var nv = props.nv;
114
118
  nv.opts.deferShapeCommit = tool === "rectangle" || tool === "ellipse";
@@ -108,6 +108,7 @@ export var nv = new Niivue({
108
108
  penType: NI_PEN_TYPE.PEN
109
109
  });
110
110
  nv.opts.penBounds = 0;
111
+ nv.opts.penSize = 1;
111
112
  window.nv = nv;
112
113
  // The NiiVue component wraps all other components in the UI.
113
114
  // It is exported so that it can be used in other projects easily
@@ -169,15 +170,19 @@ export default function CloudMrNiivueViewer(props) {
169
170
  var _21 = useState(false), saving = _21[0], setSaving = _21[1];
170
171
  var _22 = useState(null), drawShapeTool = _22[0], setDrawShapeTool = _22[1];
171
172
  var _23 = useState(null), shapeDraft = _23[0], setShapeDraft = _23[1];
173
+ var _24 = useState("freehand"), penDrawMode = _24[0], setPenDrawMode = _24[1];
174
+ var _25 = useState(0), polylineVertexCount = _25[0], setPolylineVertexCount = _25[1];
175
+ var _26 = useState(1), brushSize = _26[0], setBrushSize = _26[1];
172
176
  var shapeDraftRef = React.useRef(null);
173
177
  var drawShapeToolRef = React.useRef(null);
174
178
  drawShapeToolRef.current = drawShapeTool;
175
179
  shapeDraftRef.current = shapeDraft;
176
180
  React.useEffect(function () {
177
181
  nv.opts.penBounds = 0;
182
+ nv.opts.penSize = 1;
178
183
  }, []);
179
- var _24 = React.useState(1.0), gamma = _24[0], setGamma = _24[1];
180
- var _25 = React.useState(0), gammaKey = _25[0], setGammaKey = _25[1];
184
+ var _27 = React.useState(1.0), gamma = _27[0], setGamma = _27[1];
185
+ var _28 = React.useState(0), gammaKey = _28[0], setGammaKey = _28[1];
181
186
  // Niivue → React bridge so other places (Toolbar) can force the UI to reset
182
187
  nv.onResetGamma = function () {
183
188
  setGamma(1.0);
@@ -222,13 +227,13 @@ export default function CloudMrNiivueViewer(props) {
222
227
  // setLayers([...nv.volumes])
223
228
  // }, [])
224
229
  // values dualslider
225
- var _26 = useState(0), rangeKey = _26[0], setRangeKey = _26[1];
230
+ var _29 = useState(0), rangeKey = _29[0], setRangeKey = _29[1];
226
231
  nv.onResetContrast = function () {
227
232
  setRangeKey(rangeKey + 1);
228
233
  };
229
- var _27 = useState([0, 0, 0]), boundMins = _27[0], setBoundMins = _27[1];
230
- var _28 = useState([1, 1, 1]), boundMaxs = _28[0], setBoundMaxs = _28[1];
231
- var _29 = useState([0.5, 0.5, 0.5]), mms = _29[0], setMMs = _29[1];
234
+ var _30 = useState([0, 0, 0]), boundMins = _30[0], setBoundMins = _30[1];
235
+ var _31 = useState([1, 1, 1]), boundMaxs = _31[0], setBoundMaxs = _31[1];
236
+ var _32 = useState([0.5, 0.5, 0.5]), mms = _32[0], setMMs = _32[1];
232
237
  nv.onImageLoaded = function () {
233
238
  var _a, _b;
234
239
  var oldCrosshairPos = __spreadArray([], nv.scene.crosshairPos, true);
@@ -511,7 +516,7 @@ export default function CloudMrNiivueViewer(props) {
511
516
  setTextsVisible(true);
512
517
  }
513
518
  }
514
- var _30 = useState("pan"), dragMode = _30[0], setDragMode = _30[1];
519
+ var _33 = useState("pan"), dragMode = _33[0], setDragMode = _33[1];
515
520
  function nvSetDragMode(dragMode) {
516
521
  switch (dragMode) {
517
522
  case "none":
@@ -548,11 +553,15 @@ export default function CloudMrNiivueViewer(props) {
548
553
  nv.setDrawingEnabled(enabled);
549
554
  nv.drawScene();
550
555
  }
556
+ function nvUpdateBrushSize(size) {
557
+ setBrushSize(size);
558
+ nv.opts.penBounds = (size - 1) / 2;
559
+ nv.opts.penSize = size;
560
+ }
551
561
  function nvUpdateDrawPen(a) {
552
562
  var raw = Number(a.target.value);
553
563
  setDrawPen(raw);
554
564
  var penValue = raw;
555
- nv.opts.penBounds = 0;
556
565
  nv.setPenValue(penValue & 7, penValue > 0);
557
566
  if (penValue == 8) {
558
567
  nv.setPenValue(0, true);
@@ -720,7 +729,7 @@ export default function CloudMrNiivueViewer(props) {
720
729
  nv.opts.crosshairWidth = w;
721
730
  nv.drawScene();
722
731
  }
723
- var _31 = useState({}), labelMapping = _31[0], setLabelMapping = _31[1];
732
+ var _34 = useState({}), labelMapping = _34[0], setLabelMapping = _34[1];
724
733
  function resampleImage(mapping) {
725
734
  if (mapping === void 0) { mapping = labelMapping; }
726
735
  var el = typeof document !== "undefined" ? document.getElementById("histoplot") : null;
@@ -733,6 +742,34 @@ export default function CloudMrNiivueViewer(props) {
733
742
  setROIs(next);
734
743
  }
735
744
  }
745
+ function syncPenDrawMode(mode) {
746
+ var _a;
747
+ setPenDrawMode(mode);
748
+ nv.opts.polylinePenMode = mode === "polyline";
749
+ nv.opts.isFilledPen = mode === "freehand";
750
+ if (mode === "freehand") {
751
+ (_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
752
+ }
753
+ }
754
+ function cancelPolylineDraft() {
755
+ var _a;
756
+ (_a = nv.cloudMrCancelPolyline) === null || _a === void 0 ? void 0 : _a.call(nv);
757
+ }
758
+ function finishPolylineOpen() {
759
+ if (nv.cloudMrFinishPolyline(false)) {
760
+ setDrawingChanged(true);
761
+ resampleImage();
762
+ }
763
+ }
764
+ function finishPolylineClosed() {
765
+ if (nv.cloudMrFinishPolyline(true)) {
766
+ setDrawingChanged(true);
767
+ resampleImage();
768
+ }
769
+ }
770
+ nv.onPolylineChange = function (count) {
771
+ setPolylineVertexCount(count);
772
+ };
736
773
  function cancelShapeDraft() {
737
774
  var draft = shapeDraftRef.current;
738
775
  if (!draft)
@@ -771,26 +808,38 @@ export default function CloudMrNiivueViewer(props) {
771
808
  nvSetDrawingEnabled(false);
772
809
  };
773
810
  React.useEffect(function () {
774
- if (!shapeDraft)
811
+ if (!shapeDraft && !(penDrawMode === "polyline" && polylineVertexCount >= 2)) {
775
812
  return undefined;
813
+ }
776
814
  var onKeyDown = function (event) {
777
- if (event.key === "Enter") {
815
+ if (event.key === "Escape") {
778
816
  event.preventDefault();
779
- applyShapeDraft();
817
+ if (shapeDraft) {
818
+ cancelShapeDraft();
819
+ }
820
+ else if (polylineVertexCount >= 2) {
821
+ cancelPolylineDraft();
822
+ }
823
+ return;
780
824
  }
781
- else if (event.key === "Escape") {
825
+ if (event.key === "Enter") {
782
826
  event.preventDefault();
783
- cancelShapeDraft();
827
+ if (shapeDraft) {
828
+ applyShapeDraft();
829
+ }
830
+ else if (penDrawMode === "polyline" && polylineVertexCount >= 2) {
831
+ finishPolylineOpen();
832
+ }
784
833
  }
785
834
  };
786
835
  window.addEventListener("keydown", onKeyDown);
787
836
  return function () { return window.removeEventListener("keydown", onKeyDown); };
788
- }, [shapeDraft]);
837
+ }, [shapeDraft, penDrawMode, polylineVertexCount]);
789
838
  function nvUpdateSelectionBoxColor(rgb01) {
790
839
  setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
791
840
  nv.setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
792
841
  }
793
- var _32 = React.useState('axial'), sliceType = _32[0], setSliceType = _32[1];
842
+ var _35 = React.useState('axial'), sliceType = _35[0], setSliceType = _35[1];
794
843
  function nvUpdateSliceType(newSliceType) {
795
844
  setSliceType(newSliceType);
796
845
  if (newSliceType === 'axial') {
@@ -930,14 +979,14 @@ export default function CloudMrNiivueViewer(props) {
930
979
  return [2 /*return*/];
931
980
  });
932
981
  }); };
933
- var _33 = useState(''), selectedROI = _33[0], setSelectedDrawingLayer = _33[1];
934
- var _34 = useState(false), saveDialogOpen = _34[0], setSaveDialogOpen = _34[1];
935
- var _35 = useState(function () {
936
- }), saveConfirmCallback = _35[0], setSaveConfirmCallback = _35[1];
937
- var _36 = useState(false), confirmationOpen = _36[0], setConfirmationOpen = _36[1];
938
- var _37 = useState(function () { }), warningConfirmationCallback = _37[0], setWarningConfirmationCallback = _37[1];
939
- var _38 = useState(function () { }), warningCancelCallback = _38[0], setWarningCancelCallback = _38[1];
940
- var _39 = useState(false), drawingChanged = _39[0], setDrawingChanged = _39[1];
982
+ var _36 = useState(''), selectedROI = _36[0], setSelectedDrawingLayer = _36[1];
983
+ var _37 = useState(false), saveDialogOpen = _37[0], setSaveDialogOpen = _37[1];
984
+ var _38 = useState(function () {
985
+ }), saveConfirmCallback = _38[0], setSaveConfirmCallback = _38[1];
986
+ var _39 = useState(false), confirmationOpen = _39[0], setConfirmationOpen = _39[1];
987
+ var _40 = useState(function () { }), warningConfirmationCallback = _40[0], setWarningConfirmationCallback = _40[1];
988
+ var _41 = useState(function () { }), warningCancelCallback = _41[0], setWarningCancelCallback = _41[1];
989
+ var _42 = useState(false), drawingChanged = _42[0], setDrawingChanged = _42[1];
941
990
  // When new drawing strokes are made on top of a saved ROI, reset the dropdown
942
991
  // so it shows the "ROI Layer" placeholder instead of the stale saved name.
943
992
  React.useEffect(function () {
@@ -1264,6 +1313,10 @@ export default function CloudMrNiivueViewer(props) {
1264
1313
  cancelShapeDraft();
1265
1314
  return;
1266
1315
  }
1316
+ if (polylineVertexCount > 0) {
1317
+ cancelPolylineDraft();
1318
+ return;
1319
+ }
1267
1320
  nv.drawUndo();
1268
1321
  resampleImage();
1269
1322
  if (nv.drawBitmap && nv.drawBitmap.every(function (v) { return v === 0; })) {
@@ -1275,7 +1328,15 @@ export default function CloudMrNiivueViewer(props) {
1275
1328
  toggleROIVisible: toggleROIVisible,
1276
1329
  drawingOpacity: drawingOpacity,
1277
1330
  setDrawingOpacity: nvUpdateDrawingOpacity,
1278
- setDrawingChanged: setDrawingChanged
1331
+ setDrawingChanged: setDrawingChanged,
1332
+ penDrawMode: penDrawMode,
1333
+ onPenDrawModeChange: syncPenDrawMode,
1334
+ polylineVertexCount: polylineVertexCount,
1335
+ onCancelPolyline: cancelPolylineDraft,
1336
+ onFinishPolyline: finishPolylineOpen,
1337
+ onCloseFillPolyline: finishPolylineClosed,
1338
+ brushSize: brushSize,
1339
+ updateBrushSize: nvUpdateBrushSize
1279
1340
  };
1280
1341
  return (_jsxs(Box, __assign({ sx: {
1281
1342
  display: 'flex',
@@ -7,6 +7,15 @@ import {
7
7
  isDraftTooSmall,
8
8
  shouldDeferShapeCommit,
9
9
  } from "./shapeDraftUtils.js";
10
+ import {
11
+ addPolylineVertex,
12
+ cancelPolyline,
13
+ finishPolyline,
14
+ isClickWithoutDrag,
15
+ isPolylinePenActive,
16
+ previewPolylineSegment,
17
+ resetPolylineState,
18
+ } from "./polylinePenUtils.js";
10
19
 
11
20
  /*
12
21
  * bitmapOverlay — in-browser state only: remembers each voxel's label *before* Group
@@ -1414,14 +1423,63 @@ Niivue.prototype.drawAddUndoBitmap = function cloudMrDrawAddUndoBitmap(...args)
1414
1423
  return _drawAddUndoBitmap.apply(this, args);
1415
1424
  };
1416
1425
 
1426
+ Niivue.prototype.cloudMrCancelPolyline = function cloudMrCancelPolyline() {
1427
+ cancelPolyline(this);
1428
+ };
1429
+
1430
+ Niivue.prototype.cloudMrFinishPolyline = function cloudMrFinishPolyline(fillClosed = false) {
1431
+ return finishPolyline(this, { fillClosed });
1432
+ };
1433
+
1434
+ Niivue.prototype.cloudMrResetPolyline = function cloudMrResetPolyline() {
1435
+ resetPolylineState(this);
1436
+ };
1437
+
1438
+ const _mouseClick = Niivue.prototype.mouseClick;
1439
+ Niivue.prototype.mouseClick = function cloudMrMouseClick(...args) {
1440
+ if (isPolylinePenActive(this)) {
1441
+ if (this._cloudMrPolylineVertices?.length > 0) {
1442
+ previewPolylineSegment(this);
1443
+ }
1444
+ return false;
1445
+ }
1446
+ return _mouseClick.apply(this, args);
1447
+ };
1448
+
1449
+ const _mouseMoveListener = Niivue.prototype.mouseMoveListener;
1450
+ Niivue.prototype.mouseMoveListener = function cloudMrMouseMoveListener(event) {
1451
+ const result = _mouseMoveListener.call(this, event);
1452
+ if (isPolylinePenActive(this) && this._cloudMrPolylineVertices?.length > 0) {
1453
+ previewPolylineSegment(this);
1454
+ }
1455
+ return result;
1456
+ };
1457
+
1417
1458
  const _mouseUpListener = Niivue.prototype.mouseUpListener;
1418
1459
  Niivue.prototype.mouseUpListener = function cloudMrMouseUpListener() {
1419
1460
  let pendingDraft = null;
1461
+ let polylineClick = false;
1462
+
1420
1463
  if (shouldDeferShapeCommit(this)) {
1421
1464
  this._cloudMrSkipNextUndoBitmap = true;
1422
1465
  pendingDraft = captureDeferredShapeDraft(this);
1423
1466
  }
1467
+
1468
+ if (isPolylinePenActive(this) && isClickWithoutDrag(this.uiData)) {
1469
+ this.drawPenLocation = [NaN, NaN, NaN];
1470
+ this.drawPenFillPts = [];
1471
+ this._cloudMrSkipNextUndoBitmap = true;
1472
+ this._cloudMrSuppressDrawingChangedMouseUp = true;
1473
+ polylineClick = true;
1474
+ }
1475
+
1424
1476
  _mouseUpListener.call(this);
1477
+
1478
+ if (polylineClick) {
1479
+ addPolylineVertex(this);
1480
+ return;
1481
+ }
1482
+
1425
1483
  if (!pendingDraft?.baseBitmap) {
1426
1484
  return;
1427
1485
  }
@@ -0,0 +1,5 @@
1
+ export function BrushSizeSlider({ label, brushSize, updateBrushSize }: {
2
+ label: any;
3
+ brushSize: any;
4
+ updateBrushSize: any;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,36 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
13
+ import { Stack, Slider, Typography } from "@mui/material";
14
+ var SLIDER_SX = {
15
+ width: "80%",
16
+ color: "#fff",
17
+ "& .MuiSlider-track": { backgroundColor: "#fff", border: "none" },
18
+ "& .MuiSlider-rail": { backgroundColor: "rgba(255,255,255,0.3)" },
19
+ "& .MuiSlider-thumb": {
20
+ backgroundColor: "#fff",
21
+ border: "2px solid #fff",
22
+ "&:hover, &.Mui-focusVisible, &.Mui-active": {
23
+ boxShadow: "0 0 0 8px rgba(255,255,255,0.16)"
24
+ }
25
+ },
26
+ "& .MuiSlider-mark": { backgroundColor: "#fff" },
27
+ "& .MuiSlider-markActive": { backgroundColor: "#fff" },
28
+ "& .MuiSlider-valueLabel": {
29
+ backgroundColor: "#fff",
30
+ color: "#000"
31
+ }
32
+ };
33
+ export function BrushSizeSlider(_a) {
34
+ var label = _a.label, brushSize = _a.brushSize, updateBrushSize = _a.updateBrushSize;
35
+ return (_jsxs(Stack, __assign({ sx: { mb: 0.5, px: 0.5 }, alignItems: "center", width: "100%" }, { children: [_jsxs(Typography, __assign({ color: "white", noWrap: true, width: "100%", marginLeft: "6pt", fontSize: "11pt", sx: { userSelect: "none" } }, { children: [label, ": ", brushSize] })), _jsx(Slider, { value: brushSize, sx: SLIDER_SX, step: 2, min: 1, max: 15, marks: true, onChange: function (_event, value) { return updateBrushSize(value); } })] })));
36
+ }
@@ -1,7 +1,16 @@
1
- export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, shapeDraftActive, onApplyShapeDraft, onCancelShapeDraft, }: {
1
+ export default function DrawColorPlatte({ expanded, updateDrawPen, setDrawingEnabled, showPenModes, penDrawMode, onPenDrawModeChange, polylineVertexCount, onCancelPolyline, onFinishPolyline, onCloseFillPolyline, brushSize, updateBrushSize, shapeDraftActive, onApplyShapeDraft, onCancelShapeDraft, }: {
2
2
  expanded: any;
3
3
  updateDrawPen: any;
4
4
  setDrawingEnabled: any;
5
+ showPenModes?: boolean | undefined;
6
+ penDrawMode?: string | undefined;
7
+ onPenDrawModeChange: any;
8
+ polylineVertexCount?: number | undefined;
9
+ onCancelPolyline: any;
10
+ onFinishPolyline: any;
11
+ onCloseFillPolyline: any;
12
+ brushSize?: number | undefined;
13
+ updateBrushSize: any;
5
14
  shapeDraftActive?: boolean | undefined;
6
15
  onApplyShapeDraft: any;
7
16
  onCancelShapeDraft: any;
@@ -12,12 +12,13 @@ var __assign = (this && this.__assign) || function () {
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  /**
14
14
  * Shared ROI label color row (NiiVue pen indices 1–6). Used by pen, rectangle, and ellipse tools.
15
- * Rectangle/ellipse palettes may also show Apply/Cancel while a shape draft is being adjusted.
15
+ * Pen palette adds freehand vs straight-line mode; rectangle/ellipse show Apply/Cancel while adjusting.
16
16
  */
17
- import { Stack, IconButton, Button, Tooltip } from "@mui/material";
17
+ import { Stack, IconButton, Button, Tooltip, Typography } from "@mui/material";
18
18
  import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
19
19
  import CheckIcon from "@mui/icons-material/Check";
20
20
  import CloseIcon from "@mui/icons-material/Close";
21
+ import { BrushSizeSlider } from "./BrushSizeSlider";
21
22
  var FILLED_COLORS = [
22
23
  { sx: { color: "red" } },
23
24
  { sx: { color: "green" } },
@@ -28,24 +29,56 @@ var FILLED_COLORS = [
28
29
  ];
29
30
  var ACTION_FONT_SIZE = "0.75rem";
30
31
  var ACTION_ICON_SIZE = "0.875rem";
32
+ var modeBtnSx = function (active) { return ({
33
+ color: active ? "#c9a0e8" : "#bbb",
34
+ fontSize: ACTION_FONT_SIZE,
35
+ textTransform: "none",
36
+ minWidth: 0,
37
+ py: 0.25,
38
+ px: 0.75
39
+ }); };
31
40
  export default function DrawColorPlatte(_a) {
32
- var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.shapeDraftActive, shapeDraftActive = _b === void 0 ? false : _b, onApplyShapeDraft = _a.onApplyShapeDraft, onCancelShapeDraft = _a.onCancelShapeDraft;
41
+ var expanded = _a.expanded, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.showPenModes, showPenModes = _b === void 0 ? false : _b, _c = _a.penDrawMode, penDrawMode = _c === void 0 ? "freehand" : _c, onPenDrawModeChange = _a.onPenDrawModeChange, _d = _a.polylineVertexCount, polylineVertexCount = _d === void 0 ? 0 : _d, onCancelPolyline = _a.onCancelPolyline, onFinishPolyline = _a.onFinishPolyline, onCloseFillPolyline = _a.onCloseFillPolyline, _e = _a.brushSize, brushSize = _e === void 0 ? 1 : _e, updateBrushSize = _a.updateBrushSize, _f = _a.shapeDraftActive, shapeDraftActive = _f === void 0 ? false : _f, onApplyShapeDraft = _a.onApplyShapeDraft, onCancelShapeDraft = _a.onCancelShapeDraft;
33
42
  return (_jsxs(Stack, __assign({ style: {
34
43
  position: "absolute",
35
44
  top: "100%",
36
45
  left: 0,
37
46
  zIndex: 1500,
38
47
  border: "".concat(expanded ? "1px" : 0, " solid #bbb"),
39
- maxWidth: expanded ? 300 : 0,
48
+ maxWidth: expanded ? 320 : 0,
49
+ minWidth: expanded ? 240 : 0,
40
50
  overflow: expanded ? "visible" : "hidden",
41
51
  borderRadius: "16px",
42
52
  borderTopLeftRadius: "6pt",
43
53
  borderTopRightRadius: "6pt",
44
54
  background: "#333"
45
- }, direction: "column", spacing: 0.5, sx: { py: shapeDraftActive && expanded ? 0.5 : 0 } }, { children: [_jsx(Stack, __assign({ direction: "row" }, { children: FILLED_COLORS.map(function (color, index) { return (_jsx(IconButton, __assign({ onClick: function () {
55
+ }, direction: "column", spacing: 0.5, sx: { py: expanded ? 0.5 : 0 } }, { children: [showPenModes && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 0.5, sx: { px: 0.75, pt: 0.25 } }, { children: [_jsx(Button, __assign({ size: "small", onClick: function () { return onPenDrawModeChange === null || onPenDrawModeChange === void 0 ? void 0 : onPenDrawModeChange("freehand"); }, sx: modeBtnSx(penDrawMode === "freehand") }, { children: "Freehand" })), _jsx(Button, __assign({ size: "small", onClick: function () { return onPenDrawModeChange === null || onPenDrawModeChange === void 0 ? void 0 : onPenDrawModeChange("polyline"); }, sx: modeBtnSx(penDrawMode === "polyline") }, { children: "Straight lines" }))] }))), showPenModes && expanded && updateBrushSize && (_jsx(BrushSizeSlider, { label: "Line thickness", brushSize: brushSize, updateBrushSize: updateBrushSize })), _jsx(Stack, __assign({ direction: "row" }, { children: FILLED_COLORS.map(function (color, index) { return (_jsx(IconButton, __assign({ onClick: function () {
46
56
  updateDrawPen({ target: { value: index + 1 } });
47
57
  setDrawingEnabled(true);
48
- } }, { children: _jsx(FiberManualRecordIcon, { sx: color.sx }) }), index)); }) })), shapeDraftActive && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Cancel shape (Esc)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel shape", onClick: function () { return onCancelShapeDraft === null || onCancelShapeDraft === void 0 ? void 0 : onCancelShapeDraft(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
58
+ } }, { children: _jsx(FiberManualRecordIcon, { sx: color.sx }) }), index)); }) })), showPenModes && penDrawMode === "polyline" && expanded && polylineVertexCount === 0 && (_jsx(Typography, __assign({ sx: { px: 1, pb: 0.5, fontSize: "0.68rem", color: "#aaa", userSelect: "none" } }, { children: "Click each corner to draw connected straight lines" }))), showPenModes && penDrawMode === "polyline" && expanded && polylineVertexCount >= 2 && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Discard current outline" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel polyline", onClick: function () { return onCancelPolyline === null || onCancelPolyline === void 0 ? void 0 : onCancelPolyline(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
59
+ color: "#ccc",
60
+ fontSize: ACTION_FONT_SIZE,
61
+ textTransform: "none",
62
+ minWidth: 0,
63
+ py: 0.25,
64
+ px: 0.75,
65
+ "& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
66
+ } }, { children: "Cancel" })) })), _jsxs(Stack, __assign({ direction: "row", alignItems: "center", spacing: 1 }, { children: [polylineVertexCount >= 3 && (_jsx(Tooltip, __assign({ title: "Connect last point to first and fill" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "close and fill polyline", onClick: function () { return onCloseFillPolyline === null || onCloseFillPolyline === void 0 ? void 0 : onCloseFillPolyline(); }, sx: {
67
+ color: "#c9a0e8",
68
+ fontSize: ACTION_FONT_SIZE,
69
+ textTransform: "none",
70
+ minWidth: 0,
71
+ py: 0.25,
72
+ px: 0.75
73
+ } }, { children: "Close & fill" })) }))), _jsx(Tooltip, __assign({ title: "Keep outline only (Enter)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "finish polyline", onClick: function () { return onFinishPolyline === null || onFinishPolyline === void 0 ? void 0 : onFinishPolyline(); }, startIcon: _jsx(CheckIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
74
+ color: "#c9a0e8",
75
+ fontSize: ACTION_FONT_SIZE,
76
+ textTransform: "none",
77
+ minWidth: 0,
78
+ py: 0.25,
79
+ px: 0.75,
80
+ "& .MuiButton-startIcon": { mr: 0.5, ml: 0 }
81
+ } }, { children: "Done" })) }))] }))] }))), shapeDraftActive && expanded && (_jsxs(Stack, __assign({ direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.5, borderTop: "1px solid #555", width: "100%" } }, { children: [_jsx(Tooltip, __assign({ title: "Cancel shape (Esc)" }, { children: _jsx(Button, __assign({ size: "small", "aria-label": "cancel shape", onClick: function () { return onCancelShapeDraft === null || onCancelShapeDraft === void 0 ? void 0 : onCancelShapeDraft(); }, startIcon: _jsx(CloseIcon, { sx: { fontSize: ACTION_ICON_SIZE } }), sx: {
49
82
  color: "#ccc",
50
83
  fontSize: ACTION_FONT_SIZE,
51
84
  textTransform: "none",
@@ -1,2 +1,7 @@
1
- export default EraserPlatte;
2
- declare function EraserPlatte(_a: any): import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
1
+ export default function EraserPlatte({ expandEraseOptions, updateDrawPen, setDrawingEnabled, brushSize, updateBrushSize, }: {
2
+ expandEraseOptions: any;
3
+ updateDrawPen: any;
4
+ setDrawingEnabled: any;
5
+ brushSize?: number | undefined;
6
+ updateBrushSize: any;
7
+ }): import("react/jsx-runtime").JSX.Element;
@@ -1,29 +1,26 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
1
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
13
  import { Stack, IconButton } from "@mui/material";
3
14
  import FiberManualRecordIcon from "@mui/icons-material/FiberManualRecord";
4
15
  import FiberManualRecordOutlinedIcon from "@mui/icons-material/FiberManualRecordOutlined";
5
- var __assign = function () {
6
- __assign =
7
- Object.assign ||
8
- function (t) {
9
- for (var s, i = 1, n = arguments.length; i < n; i++) {
10
- s = arguments[i];
11
- for (var p in s)
12
- if (Object.prototype.hasOwnProperty.call(s, p))
13
- t[p] = s[p];
14
- }
15
- return t;
16
- };
17
- return __assign.apply(this, arguments);
18
- };
19
- var EraserPlatte = function (_a) {
20
- var expandEraseOptions = _a.expandEraseOptions, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled;
16
+ import { BrushSizeSlider } from "./BrushSizeSlider";
17
+ export default function EraserPlatte(_a) {
18
+ var expandEraseOptions = _a.expandEraseOptions, updateDrawPen = _a.updateDrawPen, setDrawingEnabled = _a.setDrawingEnabled, _b = _a.brushSize, brushSize = _b === void 0 ? 1 : _b, updateBrushSize = _a.updateBrushSize;
21
19
  var eraseOptions = [
22
20
  _jsx(FiberManualRecordIcon, { style: { color: "white" } }, "e0"),
23
21
  _jsx(FiberManualRecordOutlinedIcon, { style: { color: "white" } }, "e1"),
24
22
  ];
25
- return _jsxs(Stack, __assign({
26
- style: {
23
+ return (_jsxs(Stack, __assign({ style: {
27
24
  position: "absolute",
28
25
  top: "100%",
29
26
  left: 0,
@@ -36,21 +33,8 @@ var EraserPlatte = function (_a) {
36
33
  borderTopRightRadius: "6pt",
37
34
  background: "#333",
38
35
  width: 150
39
- },
40
- direction: "column"
41
- }, {
42
- children: [
43
- _jsx(Stack, __assign({ direction: "row", style: { justifyContent: "center" } }, {
44
- children: eraseOptions.map(function (value, index) {
45
- return _jsx(IconButton, __assign({
46
- onClick: function () {
47
- updateDrawPen({ target: { value: index === 0 ? 8 : 0 } });
48
- setDrawingEnabled(true);
49
- }
50
- }, { children: value }), index);
51
- })
52
- })),
53
- ]
54
- }));
55
- };
56
- export default EraserPlatte;
36
+ }, direction: "column" }, { children: [updateBrushSize && (_jsx(BrushSizeSlider, { label: "Eraser size", brushSize: brushSize, updateBrushSize: updateBrushSize })), _jsx(Stack, __assign({ direction: "row", style: { justifyContent: "center" } }, { children: eraseOptions.map(function (value, index) { return (_jsx(IconButton, __assign({ onClick: function () {
37
+ updateDrawPen({ target: { value: index === 0 ? 8 : 0 } });
38
+ setDrawingEnabled(true);
39
+ } }, { children: value }), index)); }) }))] })));
40
+ }
@@ -170,7 +170,7 @@ export function MroDrawToolkit(props) {
170
170
  alignItems: "center",
171
171
  gap: 4,
172
172
  overflow: "visible"
173
- } }, { children: [_jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "d" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Pen" }, { children: _jsx(IconButton, __assign({ "aria-label": "pen", size: "small", onClick: clickPen, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("pen")) }, { children: _jsx(DrawIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "d", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "r" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Rectangle" }, { children: _jsx(IconButton, __assign({ "aria-label": "rectangle", size: "small", onClick: clickRectangle, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("rectangle")) }, { children: _jsx(CropSquareOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "r", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "rectangle", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "l" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Ellipse" }, { children: _jsx(IconButton, __assign({ "aria-label": "ellipse", size: "small", onClick: clickEllipse, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("ellipse")) }, { children: _jsx(CircleOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "l", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "ellipse", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "e" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Eraser" }, { children: _jsx(IconButton, __assign({ "aria-label": "erase", size: "small", onClick: clickEraser, sx: toolBtnSx }, { children: filled || expandedOption !== "e" ? (_jsx(EraserIcon, {})) : (_jsx(AutoFixNormalOutlinedIcon, { sx: { color: ICON_COLOR } })) })) })), _jsx(EraserPlatte, { expandEraseOptions: expandedOption === "e", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled })] })), _jsx(Tooltip, __assign({ title: "Undo" }, { children: _jsx(IconButton, __assign({ "aria-label": "revert", size: "small", onClick: function () { return props.drawUndo(); }, sx: toolBtnSx }, { children: _jsx(ReplyIcon, { sx: { color: ICON_COLOR } }) })) })), _jsx(Tooltip, __assign({ title: "Save screenshot" }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ "aria-label": "capture", size: "small", disabled: !vol, onClick: function () { return vol && props.nv.saveScene("".concat(vol.name, "_drawing.png")); }, sx: toolBtnSx }, { children: _jsx(CameraAltIcon, { sx: { color: ICON_COLOR } }) })) }) })), _jsx(Tooltip, __assign({ title: "Clear drawing" }, { children: _jsx(IconButton, __assign({ "aria-label": "delete", size: "small", onClick: function () {
173
+ } }, { children: [_jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "d" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Pen" }, { children: _jsx(IconButton, __assign({ "aria-label": "pen", size: "small", onClick: clickPen, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("pen")) }, { children: _jsx(DrawIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "d", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, showPenModes: true, penDrawMode: props.penDrawMode, onPenDrawModeChange: props.onPenDrawModeChange, polylineVertexCount: props.polylineVertexCount, onCancelPolyline: props.onCancelPolyline, onFinishPolyline: props.onFinishPolyline, onCloseFillPolyline: props.onCloseFillPolyline, brushSize: props.brushSize, updateBrushSize: props.updateBrushSize })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "r" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Rectangle" }, { children: _jsx(IconButton, __assign({ "aria-label": "rectangle", size: "small", onClick: clickRectangle, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("rectangle")) }, { children: _jsx(CropSquareOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "r", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "rectangle", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "l" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Ellipse" }, { children: _jsx(IconButton, __assign({ "aria-label": "ellipse", size: "small", onClick: clickEllipse, sx: __assign(__assign({}, toolBtnSx), shapeSelectedSx("ellipse")) }, { children: _jsx(CircleOutlinedIcon, { sx: { color: "inherit" } }) })) })), _jsx(DrawColorPlatte, { expanded: expandedOption === "l", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, shapeDraftActive: props.shapeDraftActive && drawShapeTool === "ellipse", onApplyShapeDraft: props.onApplyShapeDraft, onCancelShapeDraft: props.onCancelShapeDraft })] })), _jsxs(Box, __assign({ sx: { position: "relative", zIndex: expandedOption === "e" ? 1600 : "auto", display: "inline-flex", alignItems: "center" } }, { children: [_jsx(Tooltip, __assign({ title: "Eraser" }, { children: _jsx(IconButton, __assign({ "aria-label": "erase", size: "small", onClick: clickEraser, sx: toolBtnSx }, { children: filled || expandedOption !== "e" ? (_jsx(EraserIcon, {})) : (_jsx(AutoFixNormalOutlinedIcon, { sx: { color: ICON_COLOR } })) })) })), _jsx(EraserPlatte, { expandEraseOptions: expandedOption === "e", updateDrawPen: props.updateDrawPen, setDrawingEnabled: props.setDrawingEnabled, brushSize: props.brushSize, updateBrushSize: props.updateBrushSize })] })), _jsx(Tooltip, __assign({ title: "Undo" }, { children: _jsx(IconButton, __assign({ "aria-label": "revert", size: "small", onClick: function () { return props.drawUndo(); }, sx: toolBtnSx }, { children: _jsx(ReplyIcon, { sx: { color: ICON_COLOR } }) })) })), _jsx(Tooltip, __assign({ title: "Save screenshot" }, { children: _jsx("span", { children: _jsx(IconButton, __assign({ "aria-label": "capture", size: "small", disabled: !vol, onClick: function () { return vol && props.nv.saveScene("".concat(vol.name, "_drawing.png")); }, sx: toolBtnSx }, { children: _jsx(CameraAltIcon, { sx: { color: ICON_COLOR } }) })) }) })), _jsx(Tooltip, __assign({ title: "Clear drawing" }, { children: _jsx(IconButton, __assign({ "aria-label": "delete", size: "small", onClick: function () {
174
174
  props.nv.clearDrawing();
175
175
  props.resampleImage();
176
176
  props.setDrawingChanged(false);
@@ -0,0 +1,12 @@
1
+ export function isPolylinePenActive(nv: any): any;
2
+ export function isClickWithoutDrag(uiData: any, thresholdPx?: number): boolean;
3
+ export function axCorSagFromMouse(nv: any): any;
4
+ export function voxFromMouse(nv: any): any[] | null;
5
+ export function notifyPolylineChange(nv: any, count: any): void;
6
+ export function resetPolylineState(nv: any): void;
7
+ export function cancelPolyline(nv: any): void;
8
+ export function previewPolylineSegment(nv: any): void;
9
+ export function addPolylineVertex(nv: any): boolean;
10
+ export function finishPolyline(nv: any, { fillClosed }?: {
11
+ fillClosed?: boolean | undefined;
12
+ }): boolean;
@@ -0,0 +1,123 @@
1
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
+ if (ar || !(i in from)) {
4
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
+ ar[i] = from[i];
6
+ }
7
+ }
8
+ return to.concat(ar || Array.prototype.slice.call(from));
9
+ };
10
+ import { NI_PEN_TYPE } from "./niivuePenType";
11
+ var CLICK_DRAG_PX = 5;
12
+ export function isPolylinePenActive(nv) {
13
+ return (nv.opts.polylinePenMode &&
14
+ nv.opts.drawingEnabled &&
15
+ nv.opts.penType === NI_PEN_TYPE.PEN);
16
+ }
17
+ export function isClickWithoutDrag(uiData, thresholdPx) {
18
+ if (thresholdPx === void 0) { thresholdPx = CLICK_DRAG_PX; }
19
+ var dx = uiData.dragStart[0] - uiData.dragEnd[0];
20
+ var dy = uiData.dragStart[1] - uiData.dragEnd[1];
21
+ return dx * dx + dy * dy <= thresholdPx * thresholdPx;
22
+ }
23
+ export function axCorSagFromMouse(nv) {
24
+ var _a;
25
+ var tile = nv.tileIndex(nv.mousePos[0], nv.mousePos[1]);
26
+ if (tile >= 0 && ((_a = nv.screenSlices) === null || _a === void 0 ? void 0 : _a[tile])) {
27
+ return nv.screenSlices[tile].axCorSag;
28
+ }
29
+ return nv.drawPenAxCorSag >= 0 ? nv.drawPenAxCorSag : 0;
30
+ }
31
+ export function voxFromMouse(nv) {
32
+ var frac = nv.canvasPos2frac(nv.mousePos);
33
+ if (!frac || frac[0] < 0)
34
+ return null;
35
+ var vox = nv.frac2vox(frac);
36
+ return [vox[0], vox[1], vox[2]];
37
+ }
38
+ export function notifyPolylineChange(nv, count) {
39
+ if (typeof nv.onPolylineChange === "function") {
40
+ nv.onPolylineChange(count);
41
+ }
42
+ }
43
+ export function resetPolylineState(nv) {
44
+ nv._cloudMrPolylineVertices = [];
45
+ nv._cloudMrPolylineBaseBitmap = null;
46
+ nv._cloudMrPolylineSessionStartBitmap = null;
47
+ nv._cloudMrPolylineAxCorSag = -1;
48
+ notifyPolylineChange(nv, 0);
49
+ }
50
+ export function cancelPolyline(nv) {
51
+ if (nv._cloudMrPolylineSessionStartBitmap) {
52
+ nv.drawBitmap.set(nv._cloudMrPolylineSessionStartBitmap);
53
+ nv.refreshDrawing(true, false);
54
+ nv.drawScene();
55
+ }
56
+ resetPolylineState(nv);
57
+ }
58
+ export function previewPolylineSegment(nv) {
59
+ var verts = nv._cloudMrPolylineVertices;
60
+ if (!(verts === null || verts === void 0 ? void 0 : verts.length) || !nv._cloudMrPolylineBaseBitmap)
61
+ return;
62
+ var cursor = voxFromMouse(nv);
63
+ if (!cursor)
64
+ return;
65
+ nv.drawBitmap.set(nv._cloudMrPolylineBaseBitmap);
66
+ nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
67
+ nv.drawPenLine(cursor, verts[verts.length - 1], nv.opts.penValue);
68
+ nv.refreshDrawing(false, false);
69
+ nv.drawScene();
70
+ }
71
+ export function addPolylineVertex(nv) {
72
+ var pt = voxFromMouse(nv);
73
+ if (!pt)
74
+ return false;
75
+ var penValue = nv.opts.penValue;
76
+ var verts = nv._cloudMrPolylineVertices || (nv._cloudMrPolylineVertices = []);
77
+ if (verts.length === 0) {
78
+ nv._cloudMrPolylineSessionStartBitmap = nv.drawBitmap.slice();
79
+ nv._cloudMrPolylineBaseBitmap = nv._cloudMrPolylineSessionStartBitmap.slice();
80
+ nv._cloudMrPolylineAxCorSag = axCorSagFromMouse(nv);
81
+ nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
82
+ verts.push(pt);
83
+ nv.drawPt(pt[0], pt[1], pt[2], penValue);
84
+ nv.refreshDrawing(false, false);
85
+ }
86
+ else {
87
+ var prev = verts[verts.length - 1];
88
+ if (prev[0] === pt[0] && prev[1] === pt[1] && prev[2] === pt[2]) {
89
+ return false;
90
+ }
91
+ nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
92
+ nv.drawPenLine(pt, prev, penValue);
93
+ verts.push(pt);
94
+ nv._cloudMrPolylineBaseBitmap = nv.drawBitmap.slice();
95
+ nv.refreshDrawing(false, false);
96
+ }
97
+ nv.drawScene();
98
+ notifyPolylineChange(nv, verts.length);
99
+ return true;
100
+ }
101
+ export function finishPolyline(nv, _a) {
102
+ var _b = _a === void 0 ? {} : _a, _c = _b.fillClosed, fillClosed = _c === void 0 ? false : _c;
103
+ var verts = nv._cloudMrPolylineVertices;
104
+ if (!verts || verts.length < 2) {
105
+ resetPolylineState(nv);
106
+ return false;
107
+ }
108
+ if (fillClosed && verts.length >= 3) {
109
+ var first = verts[0];
110
+ var last = verts[verts.length - 1];
111
+ nv.drawPenAxCorSag = nv._cloudMrPolylineAxCorSag;
112
+ nv.drawPenLine(first, last, nv.opts.penValue);
113
+ nv.drawPenFillPts = verts.map(function (v) { return __spreadArray([], v, true); });
114
+ nv.drawPenFilled();
115
+ }
116
+ nv.drawAddUndoBitmap(nv.drawFillOverwrites);
117
+ if (typeof nv.onDrawingChanged === "function") {
118
+ nv.onDrawingChanged("draw");
119
+ }
120
+ resetPolylineState(nv);
121
+ nv.drawScene();
122
+ return true;
123
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudmr-ux",
3
- "version": "4.4.8",
3
+ "version": "4.5.0",
4
4
  "author": "erosmontin@gmail.com",
5
5
  "license": "MIT",
6
6
  "repository": "erosmontin/cloudmr-ux",