ketcher-react 2.13.0-rc.3-dev.2 → 2.14.0-rc.1

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/dist/index.js CHANGED
@@ -273,7 +273,8 @@ function _copyImageToClipboard() {
273
273
  _context.next = 15;
274
274
  return ketcher.generateImage(structStr, {
275
275
  outputFormat: 'png',
276
- backgroundColor: '255, 255, 255'
276
+ backgroundColor: '255, 255, 255',
277
+ bondThickness: options.settings.bondThickness || ketcherCore.defaultBondThickness
277
278
  });
278
279
  case 15:
279
280
  image = _context.sent;
@@ -433,7 +434,6 @@ function _copy(cb, data) {
433
434
  cb.setData(fmt, data[fmt]);
434
435
  });
435
436
  } catch (ex) {
436
- console.info("Could not write exact type ".concat(curFmt));
437
437
  }
438
438
  }
439
439
  }
@@ -618,7 +618,7 @@ var render = {
618
618
  bondThickness: {
619
619
  title: 'Bond thickness',
620
620
  type: 'integer',
621
- "default": 2,
621
+ "default": ketcherCore.defaultBondThickness,
622
622
  minimum: 1,
623
623
  maximum: 96
624
624
  },
@@ -766,7 +766,6 @@ var storage = {
766
766
  try {
767
767
  item = JSON.parse(localStorage.getItem(key));
768
768
  } catch (ex) {
769
- console.info('LocalStorage:', ex.name);
770
769
  }
771
770
  return item;
772
771
  },
@@ -776,7 +775,6 @@ var storage = {
776
775
  localStorage.setItem(key, JSON.stringify(data));
777
776
  isSet = true;
778
777
  } catch (ex) {
779
- console.info('LocalStorage:', ex.name);
780
778
  isSet = false;
781
779
  }
782
780
  return isSet;
@@ -884,9 +882,11 @@ function optionsReducer() {
884
882
  if (type === 'APP_OPTIONS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
885
883
  app: _objectSpread$1j(_objectSpread$1j({}, state.app), data)
886
884
  });
887
- if (type === 'SAVE_SETTINGS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
888
- settings: data
889
- });
885
+ if (type === 'SAVE_SETTINGS') {
886
+ return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
887
+ settings: _objectSpread$1j(_objectSpread$1j({}, state.settings), data)
888
+ });
889
+ }
890
890
  if (type === 'SAVE_CHECK_OPTS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
891
891
  check: data
892
892
  });
@@ -911,7 +911,6 @@ function constant(schema, prop) {
911
911
  return desc.constant || desc["enum"][0];
912
912
  }
913
913
  function mapOf(schema, prop) {
914
- console.assert(schema.oneOf);
915
914
  return schema.oneOf.reduce(function (res, desc) {
916
915
  res[constant(desc, prop)] = desc;
917
916
  return res;
@@ -2224,7 +2223,7 @@ var toolActions = {
2224
2223
  }
2225
2224
  },
2226
2225
  'reaction-arrow-filled-triangle': {
2227
- title: 'Arrow Filled Triangle',
2226
+ title: 'Arrow Filled Triangle Tool',
2228
2227
  action: {
2229
2228
  tool: 'reactionarrow',
2230
2229
  opts: ketcherCore.RxnArrowMode.FilledTriangle
@@ -2603,7 +2602,6 @@ function onAction(action) {
2603
2602
  };
2604
2603
  }
2605
2604
  function parseStruct(struct, server, options) {
2606
- console.log('shared.ts::parseStruct::struct', struct);
2607
2605
  if (typeof struct === 'string') {
2608
2606
  options = options || {};
2609
2607
  var _options = options;
@@ -2611,9 +2609,7 @@ function parseStruct(struct, server, options) {
2611
2609
  _options.fragment;
2612
2610
  var formatterOptions = _objectWithoutProperties__default["default"](_options, _excluded$y);
2613
2611
  var format = ketcherCore.identifyStructFormat(struct);
2614
- console.log('shared.ts::parseStruct::format', format);
2615
2612
  if (format === ketcherCore.SupportedFormat.cdx) {
2616
- console.log('shared.ts::parseStruct::format === SupportedFormat.cdx');
2617
2613
  struct = "base64::".concat(struct.replace(/\s/g, ''));
2618
2614
  }
2619
2615
  var factory = new ketcherCore.FormatterFactory(server);
@@ -2635,7 +2631,6 @@ function load(struct, options) {
2635
2631
  while (1) {
2636
2632
  switch (_context.prev = _context.next) {
2637
2633
  case 0:
2638
- console.log('shared.ts::load::struct', struct);
2639
2634
  state = getState();
2640
2635
  editor = state.editor;
2641
2636
  server = state.server;
@@ -2647,26 +2642,26 @@ function load(struct, options) {
2647
2642
  ignoreChiralFlag: editor.options().ignoreChiralFlag
2648
2643
  });
2649
2644
  dispatch(setAnalyzingFile(true));
2650
- _context.prev = 9;
2651
- _context.next = 12;
2645
+ _context.prev = 8;
2646
+ _context.next = 11;
2652
2647
  return parseStruct(struct, server, otherOptions);
2653
- case 12:
2648
+ case 11:
2654
2649
  parsedStruct = _context.sent;
2655
2650
  _otherOptions = otherOptions, fragment = _otherOptions.fragment;
2656
2651
  hasUnsupportedGroups = parsedStruct.sgroups.some(function (sGroup) {
2657
2652
  return !supportedSGroupTypes[sGroup.type];
2658
2653
  });
2659
2654
  if (!hasUnsupportedGroups) {
2660
- _context.next = 19;
2655
+ _context.next = 18;
2661
2656
  break;
2662
2657
  }
2663
- _context.next = 18;
2658
+ _context.next = 17;
2664
2659
  return editor.event.confirm.dispatch();
2665
- case 18:
2660
+ case 17:
2666
2661
  parsedStruct.sgroups = parsedStruct.sgroups.filter(function (_key, sGroup) {
2667
2662
  return supportedSGroupTypes[sGroup.type];
2668
2663
  });
2669
- case 19:
2664
+ case 18:
2670
2665
  parsedStruct.rescale();
2671
2666
  if (editor.struct().atoms.size) {
2672
2667
  oldStruct = editor.struct().clone();
@@ -2719,23 +2714,23 @@ function load(struct, options) {
2719
2714
  dispatch({
2720
2715
  type: 'MODAL_CLOSE'
2721
2716
  });
2722
- _context.next = 37;
2717
+ _context.next = 36;
2723
2718
  break;
2724
- case 33:
2725
- _context.prev = 33;
2726
- _context.t0 = _context["catch"](9);
2719
+ case 32:
2720
+ _context.prev = 32;
2721
+ _context.t0 = _context["catch"](8);
2727
2722
  dispatch(setAnalyzingFile(false));
2728
2723
  _context.t0 && errorHandler && errorHandler(_context.t0.message);
2729
- case 37:
2730
- _context.prev = 37;
2724
+ case 36:
2725
+ _context.prev = 36;
2731
2726
  ketcherCore.emitEventRequestIsFinished();
2732
- return _context.finish(37);
2733
- case 40:
2727
+ return _context.finish(36);
2728
+ case 39:
2734
2729
  case "end":
2735
2730
  return _context.stop();
2736
2731
  }
2737
2732
  }
2738
- }, _callee, null, [[9, 33, 37, 40]]);
2733
+ }, _callee, null, [[8, 32, 36, 39]]);
2739
2734
  }));
2740
2735
  return function (_x, _x2) {
2741
2736
  return _ref.apply(this, arguments);
@@ -3110,7 +3105,7 @@ var zoom = {
3110
3105
 
3111
3106
  var openHelpLink = function openHelpLink() {
3112
3107
  var _window$open;
3113
- return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v2.13.0-rc.1\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3108
+ return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v2.14.0-rc.1\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3114
3109
  };
3115
3110
  var help = {
3116
3111
  help: {
@@ -5439,7 +5434,7 @@ function SvgClose(props) {
5439
5434
  xmlns: "http://www.w3.org/2000/svg"
5440
5435
  }, props), _path$1b || (_path$1b = /*#__PURE__*/React__namespace.createElement("path", {
5441
5436
  d: "M13.462 12.046l6.37 6.37-1.413 1.415-6.371-6.371-6.327 6.326-1.414-1.414 6.327-6.326-6.372-6.372L5.676 4.26l6.372 6.372 6.417-6.418 1.414 1.414-6.417 6.418z",
5442
- fill: "#333"
5437
+ fill: "currentColor"
5443
5438
  })));
5444
5439
  }
5445
5440
 
@@ -7253,7 +7248,8 @@ var ActionButton = function ActionButton(props) {
7253
7248
  disableableButtons = props.disableableButtons,
7254
7249
  indigoVerification = props.indigoVerification,
7255
7250
  className = props.className,
7256
- onAction = props.onAction;
7251
+ onAction = props.onAction,
7252
+ dataTestId = props.dataTestId;
7257
7253
  if (status.hidden) {
7258
7254
  return null;
7259
7255
  }
@@ -7265,7 +7261,7 @@ var ActionButton = function ActionButton(props) {
7265
7261
  }
7266
7262
  };
7267
7263
  return jsxRuntime.jsxs("button", {
7268
- "data-testid": name,
7264
+ "data-testid": dataTestId || name,
7269
7265
  disabled: disabled,
7270
7266
  onClick: handleClick,
7271
7267
  title: shortcut ? "".concat(action === null || action === void 0 ? void 0 : action.title, " (").concat(shortcut, ")") : action === null || action === void 0 ? void 0 : action.title,
@@ -7534,7 +7530,8 @@ var ToolbarMultiToolItem = function ToolbarMultiToolItem(props) {
7534
7530
  className = props.className,
7535
7531
  vertical = props.vertical,
7536
7532
  onAction = props.onAction,
7537
- onOpen = props.onOpen;
7533
+ onOpen = props.onOpen,
7534
+ dataTestId = props.dataTestId;
7538
7535
  var ref = React.useRef(null);
7539
7536
  var _usePortalOpening = usePortalOpening([id, opened, options]),
7540
7537
  _usePortalOpening2 = _slicedToArray__default["default"](_usePortalOpening, 1),
@@ -7599,7 +7596,7 @@ var ToolbarMultiToolItem = function ToolbarMultiToolItem(props) {
7599
7596
  action: config[currentId],
7600
7597
  status: currentStatus,
7601
7598
  selected: selected,
7602
- "data-testid": iconName
7599
+ dataTestId: dataTestId || iconName
7603
7600
  })), !isOpen && jsxRuntime.jsx(Icon, {
7604
7601
  className: "".concat(classes$N.icon, " ").concat((currentStatus === null || currentStatus === void 0 ? void 0 : currentStatus.selected) && classes$N.iconSelected),
7605
7602
  name: "dropdown",
@@ -7630,7 +7627,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7630
7627
  disableableButtons = props.disableableButtons,
7631
7628
  vertical = props.vertical,
7632
7629
  onAction = props.onAction,
7633
- onOpen = props.onOpen;
7630
+ onOpen = props.onOpen,
7631
+ dataTestId = props.dataTestId;
7634
7632
  if (!(options !== null && options !== void 0 && options.length)) {
7635
7633
  var _status$id;
7636
7634
  var iconName = getIconName(id);
@@ -7642,7 +7640,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7642
7640
  selected: !!((_status$id = status[id]) !== null && _status$id !== void 0 && _status$id.selected),
7643
7641
  indigoVerification: indigoVerification,
7644
7642
  disableableButtons: disableableButtons,
7645
- onAction: onAction
7643
+ onAction: onAction,
7644
+ dataTestId: dataTestId
7646
7645
  });
7647
7646
  }
7648
7647
  return jsxRuntime.jsx(ToolbarMultiToolItem, {
@@ -7655,7 +7654,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7655
7654
  indigoVerification: indigoVerification,
7656
7655
  onAction: onAction,
7657
7656
  onOpen: onOpen,
7658
- vertical: vertical
7657
+ vertical: vertical,
7658
+ dataTestId: dataTestId
7659
7659
  });
7660
7660
  };
7661
7661
 
@@ -8131,9 +8131,7 @@ function execute(activeTool, _ref) {
8131
8131
  }
8132
8132
  } else if (typeof action === 'function') {
8133
8133
  action(editor, server, options);
8134
- } else {
8135
- console.info('no action');
8136
- }
8134
+ } else ;
8137
8135
  return activeTool;
8138
8136
  }
8139
8137
  function selected(actObj, activeTool, _ref2) {
@@ -8225,28 +8223,22 @@ function fileOpener(server) {
8225
8223
  }
8226
8224
  function throughFileReader(file) {
8227
8225
  var isCDX = file.name.endsWith('cdx') && !file.name.endsWith('b64cdx');
8228
- console.log('fileOpener.js::throughFileReader::file', file);
8229
8226
  return new Promise(function (resolve, reject) {
8230
8227
  var rd = new FileReader();
8231
8228
  rd.onload = function () {
8232
- console.log('fileOpener.js::throughFileReader::onload::rd.result', rd.result);
8233
8229
  var content;
8234
8230
  if (isCDX) {
8235
8231
  var base64String = rd.result.split(',').at(-1);
8236
- console.log('fileOpener.js::throughFileReader::onload::base64String', base64String);
8237
8232
  content = base64String;
8238
8233
  } else {
8239
8234
  content = rd.result;
8240
8235
  }
8241
- console.log('fileOpener.js::throughFileReader::onload::content', content);
8242
- console.log('fileOpener.js::throughFileReader::onload::file.msClose', file.msClose);
8243
8236
  if (file.msClose) file.msClose();
8244
8237
  resolve(content);
8245
8238
  };
8246
8239
  rd.onerror = function (event) {
8247
8240
  reject(event);
8248
8241
  };
8249
- console.log('fileOpener.js::throughFileReader::isCdx', isCDX);
8250
8242
  isCDX ? rd.readAsDataURL(file) : rd.readAsText(file, 'UTF-8');
8251
8243
  });
8252
8244
  }
@@ -13087,9 +13079,7 @@ var useSubscriptionOnEvents = function useSubscriptionOnEvents() {
13087
13079
  var unsubscribeOnUnMount = function unsubscribeOnUnMount() {
13088
13080
  unsubscribe(getKetcherInstance());
13089
13081
  };
13090
- window.addEventListener(KETCHER_INIT_EVENT_NAME, function () {
13091
- subscribeOnInit();
13092
- });
13082
+ window.addEventListener(KETCHER_INIT_EVENT_NAME, subscribeOnInit);
13093
13083
  return function () {
13094
13084
  unsubscribeOnUnMount();
13095
13085
  window.removeEventListener(KETCHER_INIT_EVENT_NAME, subscribeOnInit);
@@ -13237,10 +13227,12 @@ var LeftToolbar = function LeftToolbar(props) {
13237
13227
  var sizeRef = React.useRef();
13238
13228
  var Item = function Item(_ref) {
13239
13229
  var id = _ref.id,
13240
- options = _ref.options;
13230
+ options = _ref.options,
13231
+ dataTestId = _ref.dataTestId;
13241
13232
  return ToolbarGroupItem(_objectSpread$V({
13242
13233
  id: id,
13243
- options: options
13234
+ options: options,
13235
+ dataTestId: dataTestId
13244
13236
  }, rest));
13245
13237
  };
13246
13238
  var scrollUp = function scrollUp() {
@@ -13286,6 +13278,12 @@ var LeftToolbar = function LeftToolbar(props) {
13286
13278
  return React.createElement(Shape, _objectSpread$V(_objectSpread$V({}, rest), {}, {
13287
13279
  key: item.id
13288
13280
  }));
13281
+ case 'bonds':
13282
+ return jsxRuntime.jsx(Item, {
13283
+ id: item.id,
13284
+ options: item.options,
13285
+ dataTestId: "bonds"
13286
+ }, item.id);
13289
13287
  default:
13290
13288
  return jsxRuntime.jsx(Item, {
13291
13289
  id: item.id,
@@ -14154,7 +14152,6 @@ var TopToolbar = function TopToolbar(_ref) {
14154
14152
  isCollapsed: width < collapseLimit
14155
14153
  }), jsxRuntime.jsx(SystemControls, {
14156
14154
  onHistoryClick: function onHistoryClick() {
14157
- console.log('History button clicked');
14158
14155
  },
14159
14156
  onSettingsOpen: onSettingsOpen,
14160
14157
  onFullscreen: onFullscreen,
@@ -14814,38 +14811,6 @@ var LassoHelper = function () {
14814
14811
  return LassoHelper;
14815
14812
  }();
14816
14813
 
14817
- function calcAngle$1(pos0, pos1) {
14818
- var v = ketcherCore.Vec2.diff(pos1, pos0);
14819
- return Math.atan2(v.y, v.x);
14820
- }
14821
- function calcNewAtomPos(pos0, pos1, ctrlKey) {
14822
- var v = new ketcherCore.Vec2(1, 0).rotate(ctrlKey ? calcAngle$1(pos0, pos1) : ketcherCore.fracAngle(pos0, pos1));
14823
- v.add_(pos0);
14824
- return v;
14825
- }
14826
- function degrees(angle) {
14827
- var degree = Math.round(angle / Math.PI * 180);
14828
- if (degree > 180) degree -= 360;else if (degree <= -180) degree += 360;
14829
- return degree;
14830
- }
14831
- function normalizeAngle(angle) {
14832
- var angleWithinFullCircle = angle % (2 * Math.PI);
14833
- if (angleWithinFullCircle > Math.PI) {
14834
- return angleWithinFullCircle - 2 * Math.PI;
14835
- }
14836
- if (angleWithinFullCircle <= -Math.PI) {
14837
- return angleWithinFullCircle + 2 * Math.PI;
14838
- }
14839
- return angleWithinFullCircle;
14840
- }
14841
- var utils = {
14842
- calcAngle: calcAngle$1,
14843
- fracAngle: ketcherCore.fracAngle,
14844
- calcNewAtomPos: calcNewAtomPos,
14845
- degrees: degrees,
14846
- normalizeAngle: normalizeAngle
14847
- };
14848
-
14849
14814
  function deleteFunctionalGroups(sGroupsId, struct, action) {
14850
14815
  var deletedAtoms = [];
14851
14816
  var functionalGroups = struct.molecule.functionalGroups;
@@ -14998,13 +14963,13 @@ var AtomTool = function () {
14998
14963
  }
14999
14964
  if (atomId !== undefined) {
15000
14965
  var atom = molecule.atoms.get(atomId);
15001
- var angle = utils.calcAngle(atom === null || atom === void 0 ? void 0 : atom.pp, rnd.page2obj(event));
15002
- if (!event.ctrlKey) angle = utils.fracAngle(angle, null);
15003
- var degrees = utils.degrees(angle);
14966
+ var angle = ketcherCore.vectorUtils.calcAngle(atom.pp, rnd.page2obj(event));
14967
+ if (!event.ctrlKey) angle = ketcherCore.vectorUtils.fracAngle(angle, null);
14968
+ var degrees = ketcherCore.vectorUtils.degrees(angle);
15004
14969
  editor.event.message.dispatch({
15005
14970
  info: degrees + 'º'
15006
14971
  });
15007
- var newAtomPos = utils.calcNewAtomPos(atom === null || atom === void 0 ? void 0 : atom.pp, rnd.page2obj(event), event.ctrlKey);
14972
+ var newAtomPos = ketcherCore.vectorUtils.calcNewAtomPos(atom.pp, rnd.page2obj(event), event.ctrlKey);
15008
14973
  if (dragCtx.action) {
15009
14974
  dragCtx.action.perform(reStruct);
15010
14975
  }
@@ -15531,7 +15496,6 @@ var SGroupTool = function () {
15531
15496
  editor.selection(null);
15532
15497
  }
15533
15498
  })["catch"](function (error) {
15534
- console.error(error);
15535
15499
  });
15536
15500
  }
15537
15501
  }]);
@@ -15971,7 +15935,6 @@ function getStructCenter(ReStruct, selection) {
15971
15935
  return ketcherCore.Vec2.lc2(bb.p0, 0.5, bb.p1, 0.5);
15972
15936
  }
15973
15937
  function recoordinate(editor, rp) {
15974
- console.assert(rp, 'Reference point not specified');
15975
15938
  if (rp) {
15976
15939
  editor.render.setScrollOffset(rp.x, rp.y);
15977
15940
  } else {
@@ -16100,8 +16063,8 @@ var SelectTool = function () {
16100
16063
  var shouldDisplayDegree = dragCtx.item.map === 'atoms' && (atoms === null || atoms === void 0 ? void 0 : (_atoms$get = atoms.get(dragCtx.item.id)) === null || _atoms$get === void 0 ? void 0 : _atoms$get.neighbors.length) === 1 && (selection === null || selection === void 0 ? void 0 : (_selection$atoms = selection.atoms) === null || _selection$atoms === void 0 ? void 0 : _selection$atoms.length) === 1 && !selection.bonds;
16101
16064
  if (shouldDisplayDegree) {
16102
16065
  var pos = rnd.page2obj(event);
16103
- var angle = utils.calcAngle(dragCtx.xy0, pos);
16104
- var degrees = utils.degrees(angle);
16066
+ var angle = ketcherCore.vectorUtils.calcAngle(dragCtx.xy0, pos);
16067
+ var degrees = ketcherCore.vectorUtils.degrees(angle);
16105
16068
  editor.event.message.dispatch({
16106
16069
  info: degrees + 'º'
16107
16070
  });
@@ -18026,9 +17989,9 @@ var BondTool = function () {
18026
17989
  if ('dragCtx' in this) {
18027
17990
  var dragCtx = this.dragCtx;
18028
17991
  var pos = rnd.page2obj(event);
18029
- var angle = utils.calcAngle(dragCtx.xy0, pos);
18030
- if (!event.ctrlKey) angle = utils.fracAngle(angle, null);
18031
- var degrees = utils.degrees(angle);
17992
+ var angle = ketcherCore.vectorUtils.calcAngle(dragCtx.xy0, pos);
17993
+ if (!event.ctrlKey) angle = ketcherCore.vectorUtils.fracAngle(angle, null);
17994
+ var degrees = ketcherCore.vectorUtils.degrees(angle);
18032
17995
  this.editor.event.message.dispatch({
18033
17996
  info: degrees + 'º'
18034
17997
  });
@@ -18116,10 +18079,11 @@ var BondTool = function () {
18116
18079
  var xy1 = rnd.page2obj(event);
18117
18080
  dist = ketcherCore.Vec2.dist(dragCtx.xy0, xy1);
18118
18081
  if (beginPos) {
18119
- endPos = utils.calcNewAtomPos(beginPos, xy1, event.ctrlKey);
18082
+ endPos = ketcherCore.vectorUtils.calcNewAtomPos(beginPos, xy1, event.ctrlKey);
18120
18083
  } else {
18121
18084
  var atom = rnd.ctab.molecule.atoms.get(beginAtom);
18122
- endPos = utils.calcNewAtomPos(atom === null || atom === void 0 ? void 0 : atom.pp.get_xy0(), xy1, event.ctrlKey);
18085
+ endPos = ketcherCore.vectorUtils.calcNewAtomPos(
18086
+ atom.pp.get_xy0(), xy1, event.ctrlKey);
18123
18087
  }
18124
18088
  }
18125
18089
  if (dist > 0.3) {
@@ -18352,7 +18316,7 @@ var ChainTool = function () {
18352
18316
  var pos0 = dragCtx.item ? (_atoms$get = atoms.get(dragCtx.item.id)) === null || _atoms$get === void 0 ? void 0 : _atoms$get.pp : dragCtx.xy0;
18353
18317
  var pos1 = editor.render.page2obj(event);
18354
18318
  var sectCount = Math.ceil(ketcherCore.Vec2.diff(pos1, pos0).length());
18355
- var angle = event.ctrlKey ? utils.calcAngle(pos0, pos1) : utils.fracAngle(pos0, pos1);
18319
+ var angle = event.ctrlKey ? ketcherCore.vectorUtils.calcAngle(pos0, pos1) : ketcherCore.vectorUtils.fracAngle(pos0, pos1);
18356
18320
  var _fromChain = ketcherCore.fromChain(restruct, pos0, angle, sectCount, dragCtx.item ? dragCtx.item.id : null),
18357
18321
  _fromChain2 = _slicedToArray__default["default"](_fromChain, 2),
18358
18322
  action = _fromChain2[0],
@@ -18858,7 +18822,6 @@ var EraserTool = function () {
18858
18822
  } else if (ci.map === 'rgroupAttachmentPoints') {
18859
18823
  this.editor.update(ketcherCore.fromRGroupAttachmentPointDeletion(restruct, ci.id));
18860
18824
  } else {
18861
- console.error('EraserTool: unable to delete the object ' + ci.map + '[' + ci.id + ']');
18862
18825
  return;
18863
18826
  }
18864
18827
  this.editor.selection(null);
@@ -19037,11 +19000,11 @@ var PasteTool = function () {
19037
19000
  var atom = this.editor.struct().atoms.get(atomId);
19038
19001
  pos0 = atom === null || atom === void 0 ? void 0 : atom.pp;
19039
19002
  }
19040
- var angle = utils.calcAngle(pos0, pos1);
19003
+ var angle = ketcherCore.vectorUtils.calcAngle(pos0, pos1);
19041
19004
  if (!event.ctrlKey) {
19042
- angle = utils.fracAngle(angle, null);
19005
+ angle = ketcherCore.vectorUtils.fracAngle(angle, null);
19043
19006
  }
19044
- var degrees = utils.degrees(angle);
19007
+ var degrees = ketcherCore.vectorUtils.degrees(angle);
19045
19008
  if (
19046
19009
  this.dragCtx.hasOwnProperty('angle') && this.dragCtx.angle === degrees) return;
19047
19010
  if (this.dragCtx.action) {
@@ -19101,7 +19064,7 @@ var PasteTool = function () {
19101
19064
  var action = this.action;
19102
19065
  delete this.action;
19103
19066
  if (!this.isSingleContractedGroup || !this.mergeItems) {
19104
- this.editor.update(dropAndMerge(this.editor, this.mergeItems, action, true));
19067
+ dropAndMerge(this.editor, this.mergeItems, action, true);
19105
19068
  }
19106
19069
  }
19107
19070
  }
@@ -19136,7 +19099,7 @@ function prepareTemplateFromSingleGroup(molecule) {
19136
19099
  template.xy0 = xy0.scaled(1 / (molecule.atoms.size || 1));
19137
19100
  var atom = molecule.atoms.get(template.aid);
19138
19101
  if (atom) {
19139
- template.angle0 = utils.calcAngle(atom.pp, template.xy0);
19102
+ template.angle0 = ketcherCore.vectorUtils.calcAngle(atom.pp, template.xy0);
19140
19103
  }
19141
19104
  return template;
19142
19105
  }
@@ -19724,6 +19687,17 @@ var ReactionUnmapTool = function () {
19724
19687
  return ReactionUnmapTool;
19725
19688
  }();
19726
19689
 
19690
+ function normalizeAngle(angle) {
19691
+ var angleWithinFullCircle = angle % (2 * Math.PI);
19692
+ if (angleWithinFullCircle > Math.PI) {
19693
+ return angleWithinFullCircle - 2 * Math.PI;
19694
+ }
19695
+ if (angleWithinFullCircle <= -Math.PI) {
19696
+ return angleWithinFullCircle + 2 * Math.PI;
19697
+ }
19698
+ return angleWithinFullCircle;
19699
+ }
19700
+
19727
19701
  function ownKeys$N(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
19728
19702
  function _objectSpread$N(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$N(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$N(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
19729
19703
  var SNAP_ANGLES_RELATIVE_TO_FIXED_BOND = [Math.PI / 2, -Math.PI / 2, 2 * Math.PI / 3, -(2 * Math.PI) / 3, Math.PI];
@@ -19742,7 +19716,7 @@ var RotateTool = function () {
19742
19716
  }
19743
19717
  var dragCtx = _this.dragCtx;
19744
19718
  var mousePos = _this.editor.render.page2obj(event);
19745
- var mouseMoveAngle = utils.calcAngle(dragCtx.xy0, mousePos) - dragCtx.angle1;
19719
+ var mouseMoveAngle = ketcherCore.vectorUtils.calcAngle(dragCtx.xy0, mousePos) - dragCtx.angle1;
19746
19720
  var rotateAngle = mouseMoveAngle;
19747
19721
  _this.reStruct.clearSnappingBonds();
19748
19722
  if (_this.snapInfo) {
@@ -19753,9 +19727,9 @@ var RotateTool = function () {
19753
19727
  _this$snap2 = _slicedToArray__default["default"](_this$snap, 2),
19754
19728
  isSnapping = _this$snap2[0],
19755
19729
  rotateAngleWithSnapping = _this$snap2[1];
19756
- rotateAngle = isSnapping ? rotateAngleWithSnapping : utils.fracAngle(mouseMoveAngle, null);
19730
+ rotateAngle = isSnapping ? rotateAngleWithSnapping : ketcherCore.vectorUtils.fracAngle(mouseMoveAngle, null);
19757
19731
  }
19758
- var rotateAngleInDegrees = utils.degrees(rotateAngle);
19732
+ var rotateAngleInDegrees = ketcherCore.vectorUtils.degrees(rotateAngle);
19759
19733
  if ('angle' in dragCtx && dragCtx.angle === rotateAngleInDegrees) {
19760
19734
  return true;
19761
19735
  }
@@ -19813,7 +19787,7 @@ var RotateTool = function () {
19813
19787
  value: function mousedownHandle(handleCenter, center) {
19814
19788
  this.dragCtx = {
19815
19789
  xy0: center,
19816
- angle1: utils.calcAngle(center, handleCenter)
19790
+ angle1: ketcherCore.vectorUtils.calcAngle(center, handleCenter)
19817
19791
  };
19818
19792
  this.initSnapInfo();
19819
19793
  }
@@ -19960,7 +19934,7 @@ var RotateTool = function () {
19960
19934
  var absoluteSnapAngles = [];
19961
19935
  var snapAngleToHalfBonds = new Map();
19962
19936
  SNAP_ANGLES_RELATIVE_TO_FIXED_BOND.forEach(function (angle) {
19963
- var snapAngle = utils.normalizeAngle(fixedHalfBondAngle + angle);
19937
+ var snapAngle = normalizeAngle(fixedHalfBondAngle + angle);
19964
19938
  absoluteSnapAngles.push(snapAngle);
19965
19939
  snapAngleToHalfBonds.set(snapAngle, [rotatableHalfBondId, fixedHalfBondId]);
19966
19940
  });
@@ -19979,8 +19953,8 @@ var RotateTool = function () {
19979
19953
  var currentHalfBondId = fixedHalfBondIds[j];
19980
19954
  var currentHalfBondAngle = fixedHalfBondAngles[j];
19981
19955
  var difference = currentHalfBondAngle - previousHalfBondAngle;
19982
- var bisectorAngle = utils.normalizeAngle(currentHalfBondAngle - difference / 2);
19983
- var snapAngle = difference > Math.PI ? bisectorAngle : utils.normalizeAngle(bisectorAngle + Math.PI);
19956
+ var bisectorAngle = normalizeAngle(currentHalfBondAngle - difference / 2);
19957
+ var snapAngle = difference > Math.PI ? bisectorAngle : normalizeAngle(bisectorAngle + Math.PI);
19984
19958
  absoluteSnapAngles.push(snapAngle);
19985
19959
  snapAngleToHalfBonds.set(snapAngle, [rotatableHalfBondId, previousHalfBondId, currentHalfBondId]);
19986
19960
  }
@@ -20026,7 +20000,7 @@ var RotateTool = function () {
20026
20000
  if (!this.snapInfo) {
20027
20001
  return [isSnapping, rotateAngle];
20028
20002
  }
20029
- var newRotatedHalfBondAngle = utils.normalizeAngle(this.snapInfo.rotatableHalfBondAngle + mouseMoveAngle);
20003
+ var newRotatedHalfBondAngle = normalizeAngle(this.snapInfo.rotatableHalfBondAngle + mouseMoveAngle);
20030
20004
  this.snapInfo.absoluteSnapAngles.some(function (snapAngle, index) {
20031
20005
  if (Math.abs(newRotatedHalfBondAngle - snapAngle) <= MAX_SNAP_DELTA) {
20032
20006
  isSnapping = true;
@@ -20157,11 +20131,74 @@ var SimpleObjectTool = function () {
20157
20131
 
20158
20132
  function ownKeys$M(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
20159
20133
  function _objectSpread$M(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$M(Object(source), !0).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$M(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
20134
+ var PREVIEW_DELAY = 300;
20135
+ function getBondFlipSign(struct, bond) {
20136
+ var _struct$atoms$get, _struct$halfBonds$get;
20137
+ var xy0 = new ketcherCore.Vec2();
20138
+ var frid = (_struct$atoms$get = struct.atoms.get(bond === null || bond === void 0 ? void 0 : bond.begin)) === null || _struct$atoms$get === void 0 ? void 0 : _struct$atoms$get.fragment;
20139
+ var frIds = struct.getFragmentIds(frid);
20140
+ var count = 0;
20141
+ var loop = (_struct$halfBonds$get = struct.halfBonds.get(bond === null || bond === void 0 ? void 0 : bond.hb1)) === null || _struct$halfBonds$get === void 0 ? void 0 : _struct$halfBonds$get.loop;
20142
+ if (loop && loop < 0) {
20143
+ var _struct$halfBonds$get2;
20144
+ loop = (_struct$halfBonds$get2 = struct.halfBonds.get(bond === null || bond === void 0 ? void 0 : bond.hb2)) === null || _struct$halfBonds$get2 === void 0 ? void 0 : _struct$halfBonds$get2.loop;
20145
+ }
20146
+ if (loop && loop >= 0) {
20147
+ var _struct$loops$get;
20148
+ var loopHbs = (_struct$loops$get = struct.loops.get(loop)) === null || _struct$loops$get === void 0 ? void 0 : _struct$loops$get.hbs;
20149
+ loopHbs === null || loopHbs === void 0 ? void 0 : loopHbs.forEach(function (hb) {
20150
+ var _struct$halfBonds$get3;
20151
+ var halfBondBegin = (_struct$halfBonds$get3 = struct.halfBonds.get(hb)) === null || _struct$halfBonds$get3 === void 0 ? void 0 : _struct$halfBonds$get3.begin;
20152
+ if (halfBondBegin) {
20153
+ var hbbAtom = struct.atoms.get(halfBondBegin);
20154
+ if (hbbAtom) {
20155
+ xy0.add_(hbbAtom.pp);
20156
+ count++;
20157
+ }
20158
+ }
20159
+ });
20160
+ } else {
20161
+ frIds.forEach(function (id) {
20162
+ var atomById = struct.atoms.get(id);
20163
+ if (atomById) {
20164
+ xy0.add_(atomById.pp);
20165
+ count++;
20166
+ }
20167
+ });
20168
+ }
20169
+ var v0 = xy0.scaled(1 / count);
20170
+ return getSign(struct, bond, v0) || 1;
20171
+ }
20172
+ function getAngleFromEvent(event, ci, restruct) {
20173
+ var _restruct$atoms$get;
20174
+ var degree = (_restruct$atoms$get = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get === void 0 ? void 0 : _restruct$atoms$get.a.neighbors.length;
20175
+ var angle;
20176
+ if (degree && degree > 1) {
20177
+ angle = null;
20178
+ } else if (degree === 1) {
20179
+ var _restruct$molecule$ha;
20180
+ var atom = restruct.molecule.atoms.get(ci.id);
20181
+ var neiId = atom && ((_restruct$molecule$ha = restruct.molecule.halfBonds.get(atom.neighbors[0])) === null || _restruct$molecule$ha === void 0 ? void 0 : _restruct$molecule$ha.end);
20182
+ var nei = (neiId || neiId === 0) && restruct.molecule.atoms.get(neiId);
20183
+ angle = event.ctrlKey ? ketcherCore.vectorUtils.calcAngle(nei === null || nei === void 0 ? void 0 : nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp) : ketcherCore.vectorUtils.fracAngle(ketcherCore.vectorUtils.calcAngle(nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp), null);
20184
+ } else {
20185
+ angle = 0;
20186
+ }
20187
+ return angle;
20188
+ }
20189
+ function getUniqueCiId(ci) {
20190
+ return "".concat(ci.id, "-").concat(ci.map);
20191
+ }
20160
20192
  var TemplateTool = function () {
20161
20193
  function TemplateTool(editor, tmpl) {
20162
20194
  _classCallCheck__default["default"](this, TemplateTool);
20195
+ _defineProperty__default["default"](this, "previewTimeout", null);
20163
20196
  _defineProperty__default["default"](this, "targetGroupsIds", []);
20164
20197
  this.editor = editor;
20198
+ this.isPreviewVisible = false;
20199
+ this.previewRemoveAction = new ketcherCore.Action();
20200
+ this.previewTimeout = null;
20201
+ this.lastPreviewId = null;
20165
20202
  this.mode = getTemplateMode(tmpl);
20166
20203
  this.editor.selection(null);
20167
20204
  this.isSaltOrSolvent = ketcherCore.SGroup.isSaltOrSolvent(tmpl.struct.name);
@@ -20181,7 +20218,7 @@ var TemplateTool = function () {
20181
20218
  this.template.xy0 = xy0.scaled(1 / (frag.atoms.size || 1));
20182
20219
  var atom = frag.atoms.get(this.template.aid);
20183
20220
  if (atom) {
20184
- this.template.angle0 = utils.calcAngle(atom.pp, this.template.xy0);
20221
+ this.template.angle0 = ketcherCore.vectorUtils.calcAngle(atom.pp, this.template.xy0);
20185
20222
  this.findItems.push('atoms');
20186
20223
  }
20187
20224
  var bond = frag.bonds.get(this.template.bid);
@@ -20254,13 +20291,13 @@ var TemplateTool = function () {
20254
20291
  key: "mousedown",
20255
20292
  value: function () {
20256
20293
  var _mousedown = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee(event) {
20257
- var _this2 = this;
20258
- var _this$closestItem2, _this$closestItem3, _this$closestItem4, dragCtx, ci, _this$struct$atoms$ge, _this$struct$halfBond, xy0, bond, frid, frIds, count, loop, _this$struct$halfBond2, _this$struct$loops$ge, loopHbs, sign;
20294
+ var _this$closestItem2, _this$closestItem3, _this$closestItem4, dragCtx, ci, bond;
20259
20295
  return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
20260
20296
  while (1) {
20261
20297
  switch (_context.prev = _context.next) {
20262
20298
  case 0:
20263
20299
  this.event = event;
20300
+ this.hidePreview();
20264
20301
  if (this.functionalGroups.size) {
20265
20302
  this.targetGroupsIds = getGroupIdsFromItemArrays(this.struct, _objectSpread$M(_objectSpread$M({}, ((_this$closestItem2 = this.closestItem) === null || _this$closestItem2 === void 0 ? void 0 : _this$closestItem2.map) === 'atoms' && {
20266
20303
  atoms: [this.closestItem.id]
@@ -20273,14 +20310,14 @@ var TemplateTool = function () {
20273
20310
  }
20274
20311
  }
20275
20312
  if (!this.isNeedToShowRemoveAbbreviationPopup) {
20276
- _context.next = 6;
20313
+ _context.next = 7;
20277
20314
  break;
20278
20315
  }
20279
- _context.next = 5;
20316
+ _context.next = 6;
20280
20317
  return this.showRemoveAbbreviationPopup();
20281
- case 5:
20282
- return _context.abrupt("return");
20283
20318
  case 6:
20319
+ return _context.abrupt("return");
20320
+ case 7:
20284
20321
  this.editor.hover(null);
20285
20322
  this.dragCtx = {
20286
20323
  xy0: this.editor.render.page2obj(event),
@@ -20289,50 +20326,18 @@ var TemplateTool = function () {
20289
20326
  dragCtx = this.dragCtx;
20290
20327
  ci = dragCtx.item;
20291
20328
  if (ci) {
20292
- _context.next = 13;
20329
+ _context.next = 14;
20293
20330
  break;
20294
20331
  }
20295
20332
  delete dragCtx.item;
20296
20333
  return _context.abrupt("return");
20297
- case 13:
20334
+ case 14:
20298
20335
  if (ci.map === 'bonds' && !this.isModeFunctionalGroup) {
20299
- xy0 = new ketcherCore.Vec2();
20300
20336
  bond = this.struct.bonds.get(ci.id);
20301
- frid = (_this$struct$atoms$ge = this.struct.atoms.get(bond === null || bond === void 0 ? void 0 : bond.begin)) === null || _this$struct$atoms$ge === void 0 ? void 0 : _this$struct$atoms$ge.fragment;
20302
- frIds = this.struct.getFragmentIds(frid);
20303
- count = 0;
20304
- loop = (_this$struct$halfBond = this.struct.halfBonds.get(bond === null || bond === void 0 ? void 0 : bond.hb1)) === null || _this$struct$halfBond === void 0 ? void 0 : _this$struct$halfBond.loop;
20305
- if (loop && loop < 0) {
20306
- loop = (_this$struct$halfBond2 = this.struct.halfBonds.get(bond === null || bond === void 0 ? void 0 : bond.hb2)) === null || _this$struct$halfBond2 === void 0 ? void 0 : _this$struct$halfBond2.loop;
20307
- }
20308
- if (loop && loop >= 0) {
20309
- loopHbs = (_this$struct$loops$ge = this.struct.loops.get(loop)) === null || _this$struct$loops$ge === void 0 ? void 0 : _this$struct$loops$ge.hbs;
20310
- loopHbs === null || loopHbs === void 0 ? void 0 : loopHbs.forEach(function (hb) {
20311
- var _this2$struct$halfBon;
20312
- var halfBondBegin = (_this2$struct$halfBon = _this2.struct.halfBonds.get(hb)) === null || _this2$struct$halfBon === void 0 ? void 0 : _this2$struct$halfBon.begin;
20313
- if (halfBondBegin) {
20314
- var hbbAtom = _this2.struct.atoms.get(halfBondBegin);
20315
- if (hbbAtom) {
20316
- xy0.add_(hbbAtom.pp);
20317
- count++;
20318
- }
20319
- }
20320
- });
20321
- } else {
20322
- frIds.forEach(function (id) {
20323
- var atomById = _this2.struct.atoms.get(id);
20324
- if (atomById) {
20325
- xy0.add_(atomById.pp);
20326
- count++;
20327
- }
20328
- });
20329
- }
20330
- dragCtx.v0 = xy0.scaled(1 / count);
20331
- sign = getSign(this.struct, bond, dragCtx.v0);
20332
- dragCtx.sign1 = sign || 1;
20337
+ dragCtx.sign1 = getBondFlipSign(this.struct, bond);
20333
20338
  dragCtx.sign2 = this.template.sign;
20334
20339
  }
20335
- case 14:
20340
+ case 15:
20336
20341
  case "end":
20337
20342
  return _context.stop();
20338
20343
  }
@@ -20347,10 +20352,31 @@ var TemplateTool = function () {
20347
20352
  }, {
20348
20353
  key: "mousemove",
20349
20354
  value: function mousemove(event) {
20355
+ var _this2 = this;
20350
20356
  if (!this.dragCtx) {
20351
- this.editor.hoverIcon.show();
20352
20357
  this.editor.hoverIcon.updatePosition();
20353
20358
  this.editor.hover(this.editor.findItem(event, this.findItems), null, event);
20359
+ var restruct = this.editor.render.ctab;
20360
+ var _ci = this.editor.findItem(event, ['atoms', 'bonds']);
20361
+ if (!_ci) {
20362
+ this.editor.hoverIcon.show();
20363
+ }
20364
+ var isMouseAwayFromAtomsAndBonds = !_ci;
20365
+ var isPreviewTargetChanged = _ci && this.lastPreviewId !== getUniqueCiId(_ci);
20366
+ var shouldHidePreview = isMouseAwayFromAtomsAndBonds || isPreviewTargetChanged;
20367
+ if (shouldHidePreview) {
20368
+ this.hidePreview();
20369
+ if (!this.editor.hoverIcon.isShown) {
20370
+ this.editor.hoverIcon.show();
20371
+ }
20372
+ }
20373
+ var shouldShowPreview = _ci && !this.isSaltOrSolvent && !this.isPreviewVisible && !this.previewTimeout;
20374
+ if (shouldShowPreview) {
20375
+ this.lastPreviewId = getUniqueCiId(_ci);
20376
+ this.previewTimeout = setTimeout(function () {
20377
+ _this2.showPreview(_ci, restruct);
20378
+ }, PREVIEW_DELAY);
20379
+ }
20354
20380
  return true;
20355
20381
  }
20356
20382
  if (this.isSaltOrSolvent) {
@@ -20399,11 +20425,11 @@ var TemplateTool = function () {
20399
20425
  if (!targetPos) {
20400
20426
  return true;
20401
20427
  }
20402
- var angle = utils.calcAngle(targetPos, eventPos);
20428
+ var angle = ketcherCore.vectorUtils.calcAngle(targetPos, eventPos);
20403
20429
  if (!event.ctrlKey) {
20404
- angle = utils.fracAngle(angle, null);
20430
+ angle = ketcherCore.vectorUtils.fracAngle(angle, null);
20405
20431
  }
20406
- var degrees = utils.degrees(angle);
20432
+ var degrees = ketcherCore.vectorUtils.degrees(angle);
20407
20433
  this.editor.event.message.dispatch({
20408
20434
  info: degrees + 'º'
20409
20435
  });
@@ -20449,7 +20475,7 @@ var TemplateTool = function () {
20449
20475
  key: "mouseup",
20450
20476
  value: function mouseup(event) {
20451
20477
  var _this3 = this,
20452
- _ci;
20478
+ _ci2;
20453
20479
  var dragCtx = this.dragCtx;
20454
20480
  if (!dragCtx) {
20455
20481
  return true;
@@ -20472,7 +20498,7 @@ var TemplateTool = function () {
20472
20498
  }
20473
20499
  var action, functionalGroupRemoveAction;
20474
20500
  var pasteItems = null;
20475
- if (((_ci = ci) === null || _ci === void 0 ? void 0 : _ci.map) === 'functionalGroups' && ketcherCore.FunctionalGroup.isContractedFunctionalGroup(ci.id, this.functionalGroups) && this.isModeFunctionalGroup && this.targetGroupsIds.length) {
20501
+ if (((_ci2 = ci) === null || _ci2 === void 0 ? void 0 : _ci2.map) === 'functionalGroups' && ketcherCore.FunctionalGroup.isContractedFunctionalGroup(ci.id, this.functionalGroups) && this.isModeFunctionalGroup && this.targetGroupsIds.length) {
20476
20502
  var _restruct = this.editor.render.ctab;
20477
20503
  var functionalGroupToReplace = this.struct.sgroups.get(ci.id);
20478
20504
  if (this.isSaltOrSolvent && functionalGroupToReplace.isGroupAttached(this.struct)) {
@@ -20502,24 +20528,13 @@ var TemplateTool = function () {
20502
20528
  pasteItems = _fromTemplateOnCanvas4[1];
20503
20529
  dragCtx.action = action;
20504
20530
  } else if (ci.map === 'atoms') {
20505
- var _restruct$atoms$get;
20506
- var degree = (_restruct$atoms$get = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get === void 0 ? void 0 : _restruct$atoms$get.a.neighbors.length;
20531
+ var _restruct$atoms$get2;
20532
+ var degree = (_restruct$atoms$get2 = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get2 === void 0 ? void 0 : _restruct$atoms$get2.a.neighbors.length;
20507
20533
  if (degree && degree >= 1 && this.isSaltOrSolvent) {
20508
20534
  addSaltsAndSolventsOnCanvasWithoutMerge(restruct, this.template, dragCtx, this.editor);
20509
20535
  return true;
20510
20536
  }
20511
- var angle;
20512
- if (degree && degree > 1) {
20513
- angle = null;
20514
- } else if (degree === 1) {
20515
- var _this$struct$halfBond3;
20516
- var atom = this.struct.atoms.get(ci.id);
20517
- var neiId = atom && ((_this$struct$halfBond3 = this.struct.halfBonds.get(atom.neighbors[0])) === null || _this$struct$halfBond3 === void 0 ? void 0 : _this$struct$halfBond3.end);
20518
- var nei = (neiId || neiId === 0) && this.struct.atoms.get(neiId);
20519
- angle = event.ctrlKey ? utils.calcAngle(nei === null || nei === void 0 ? void 0 : nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp) : utils.fracAngle(utils.calcAngle(nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp), null);
20520
- } else {
20521
- angle = 0;
20522
- }
20537
+ var angle = getAngleFromEvent(event, ci, restruct);
20523
20538
  var _fromTemplateOnAtom3 = ketcherCore.fromTemplateOnAtom(restruct, this.template, ci.id, angle, false);
20524
20539
  var _fromTemplateOnAtom4 = _slicedToArray__default["default"](_fromTemplateOnAtom3, 2);
20525
20540
  action = _fromTemplateOnAtom4[0];
@@ -20562,6 +20577,7 @@ var TemplateTool = function () {
20562
20577
  }, {
20563
20578
  key: "cancel",
20564
20579
  value: function cancel() {
20580
+ this.hidePreview();
20565
20581
  this.mouseup();
20566
20582
  }
20567
20583
  }, {
@@ -20569,6 +20585,59 @@ var TemplateTool = function () {
20569
20585
  value: function mouseleave(e) {
20570
20586
  this.mouseup(e);
20571
20587
  }
20588
+ }, {
20589
+ key: "hidePreview",
20590
+ value: function hidePreview() {
20591
+ if (this.isPreviewVisible && this.previewRemoveAction) {
20592
+ this.previewRemoveAction.perform(this.editor.render.ctab);
20593
+ this.previewRemoveAction = null;
20594
+ this.isPreviewVisible = false;
20595
+ this.editor.render.update();
20596
+ }
20597
+ if (this.previewTimeout) {
20598
+ clearTimeout(this.previewTimeout);
20599
+ this.previewTimeout = null;
20600
+ }
20601
+ }
20602
+ }, {
20603
+ key: "showPreview",
20604
+ value: function showPreview(ci, restruct) {
20605
+ var _this4 = this;
20606
+ if (ci.map === 'bonds' && !this.isModeFunctionalGroup) {
20607
+ this.isPreviewVisible = true;
20608
+ this.editor.hoverIcon.hide();
20609
+ var bond = this.struct.bonds.get(ci.id);
20610
+ var sign1 = getBondFlipSign(this.struct, bond);
20611
+ var sign2 = this.template.sign;
20612
+ var shouldFlip = sign1 * sign2 > 0;
20613
+ var promise = ketcherCore.fromTemplateOnBondAction(restruct, this.template, ci.id, this.editor.event, shouldFlip, true, true);
20614
+ promise.then(function (_ref5) {
20615
+ var _ref6 = _slicedToArray__default["default"](_ref5, 2),
20616
+ action = _ref6[0],
20617
+ pasteItems = _ref6[1];
20618
+ if (!_this4.isModeFunctionalGroup) {
20619
+ var mergeItems = ketcherCore.getItemsToFuse(_this4.editor, pasteItems);
20620
+ action = ketcherCore.fromItemsFuse(restruct, mergeItems).mergeWith(action);
20621
+ _this4.editor.update(action, true);
20622
+ _this4.previewRemoveAction = action;
20623
+ }
20624
+ });
20625
+ } else if (ci.map === 'atoms') {
20626
+ this.isPreviewVisible = true;
20627
+ this.editor.hoverIcon.hide();
20628
+ var angle = getAngleFromEvent(event, ci, restruct);
20629
+ var _fromTemplateOnAtom5 = ketcherCore.fromTemplateOnAtom(restruct, this.template, ci.id, angle, false, true),
20630
+ _fromTemplateOnAtom6 = _slicedToArray__default["default"](_fromTemplateOnAtom5, 2),
20631
+ action = _fromTemplateOnAtom6[0],
20632
+ pasteItems = _fromTemplateOnAtom6[1];
20633
+ if (pasteItems && !this.isModeFunctionalGroup) {
20634
+ var mergeItems = ketcherCore.getItemsToFuse(this.editor, pasteItems);
20635
+ action = ketcherCore.fromItemsFuse(restruct, mergeItems).mergeWith(action);
20636
+ }
20637
+ this.editor.update(action, true);
20638
+ this.previewRemoveAction = action;
20639
+ }
20640
+ }
20572
20641
  }]);
20573
20642
  return TemplateTool;
20574
20643
  }();
@@ -21549,7 +21618,7 @@ var RotateController = function () {
21549
21618
  this.snapAngleIndicator = this.paper.set();
21550
21619
  var LINE_LENGTH = 30;
21551
21620
  var TEXT_FONT_SIZE = 12;
21552
- var relativeSnapAngleInDegrees = utils.degrees(relativeSnapAngle);
21621
+ var relativeSnapAngleInDegrees = ketcherCore.vectorUtils.degrees(relativeSnapAngle);
21553
21622
  var drawText = function drawText(textPosition) {
21554
21623
  return _this3.paper.text(textPosition.x, textPosition.y, "".concat(Math.abs(relativeSnapAngleInDegrees), "\xB0")).attr({
21555
21624
  'font-size': TEXT_FONT_SIZE
@@ -21565,7 +21634,7 @@ var RotateController = function () {
21565
21634
  switch (state) {
21566
21635
  case 'noLine':
21567
21636
  {
21568
- var textAngle = utils.normalizeAngle(absoluteSnapAngle - relativeSnapAngle / 2);
21637
+ var textAngle = normalizeAngle(absoluteSnapAngle - relativeSnapAngle / 2);
21569
21638
  var textPosition = new ketcherCore.Vec2(20, 0).rotate(textAngle);
21570
21639
  var text = drawText(textPosition).attr({
21571
21640
  fill: STYLE.ACTIVE_COLOR
@@ -21750,7 +21819,7 @@ var Editor$3 = function () {
21750
21819
  key: "setOptions",
21751
21820
  value: function setOptions(opts) {
21752
21821
  var options = JSON.parse(opts);
21753
- this.event.apiSettings.dispatch(_objectSpread$L(_objectSpread$L({}, this.options()), options));
21822
+ this.event.apiSettings.dispatch(_objectSpread$L({}, options));
21754
21823
  return this.render.updateOptions(opts);
21755
21824
  }
21756
21825
  }, {
@@ -22138,7 +22207,10 @@ function domEventSetup(editor, clientArea) {
22138
22207
  toolEventHandler = _ref.toolEventHandler;
22139
22208
  editor.event[eventName] = new subscription.DOMSubscription();
22140
22209
  var subs = editor.event[eventName];
22141
- target.addEventListener(eventName, subs.dispatch.bind(subs));
22210
+ target.addEventListener(eventName, function () {
22211
+ if (window.isPolymerEditorTurnedOn) return;
22212
+ subs.dispatch.apply(subs, arguments);
22213
+ });
22142
22214
  subs.add(function (event) {
22143
22215
  updateLastCursorPosition(editor, event);
22144
22216
  if (['mouseup', 'mousedown', 'click', 'dbclick'].includes(event.type) && !isMouseMainButtonPressed(event)) {
@@ -24755,6 +24827,7 @@ var SaveButton$1 = function SaveButton(props) {
24755
24827
  _props$filename = props.filename,
24756
24828
  filename = _props$filename === void 0 ? 'unnamed' : _props$filename,
24757
24829
  outputFormat = props.outputFormat,
24830
+ bondThickness = props.bondThickness,
24758
24831
  data = props.data,
24759
24832
  type = props.type,
24760
24833
  _props$mode = props.mode,
@@ -24784,7 +24857,8 @@ var SaveButton$1 = function SaveButton(props) {
24784
24857
  var ketcherInstance = getKetcherInstance();
24785
24858
  if (outputFormat) {
24786
24859
  ketcherInstance.generateImage(data, {
24787
- outputFormat: outputFormat
24860
+ outputFormat: outputFormat,
24861
+ bondThickness: bondThickness || ketcherCore.defaultBondThickness
24788
24862
  }).then(function (blob) {
24789
24863
  fileSaver$1.saveAs(blob, "".concat(filename, ".").concat(outputFormat));
24790
24864
  onSave();
@@ -25245,7 +25319,6 @@ var mapDispatchToProps$d = function mapDispatchToProps(dispatch, ownProps) {
25245
25319
  result: JSON.parse(newOpts)
25246
25320
  }));
25247
25321
  } catch (ex) {
25248
- console.info('Bad file');
25249
25322
  }
25250
25323
  },
25251
25324
  onReset: function onReset() {
@@ -25957,7 +26030,7 @@ var MiewDialog = function MiewDialog(_ref) {
25957
26030
  miew.setOptions(miewOpts);
25958
26031
  setIsIsInitialized(true);
25959
26032
  })["catch"](function (ex) {
25960
- return console.error(ex.message);
26033
+ return (void 0);
25961
26034
  });
25962
26035
  }, [miewOpts, server, struct]);
25963
26036
  var exportCML = React.useCallback(function () {
@@ -26699,16 +26772,13 @@ var Open = function Open(props) {
26699
26772
  }
26700
26773
  }, [server]);
26701
26774
  var onFileLoad = function onFileLoad(files) {
26702
- console.log('Open.tsx::onFileLoad::files', files);
26703
26775
  var onLoad = function onLoad(fileContent) {
26704
- console.log('Open.tsx::onLoad::fileContent', fileContent);
26705
26776
  setStructStr(fileContent);
26706
26777
  setCurrentState(MODAL_STATES.textEditor);
26707
26778
  };
26708
26779
  var onError = function onError() {
26709
26780
  return errorHandler('Error processing file');
26710
26781
  };
26711
- console.log('Open.tsx::onLoad::files[0].name', files[0].name);
26712
26782
  setFileName(files[0].name);
26713
26783
  opener.chosenOpener(files[0]).then(onLoad, onError);
26714
26784
  };
@@ -26718,14 +26788,12 @@ var Open = function Open(props) {
26718
26788
  };
26719
26789
  var onOk = rest.onOk;
26720
26790
  var copyHandler = function copyHandler() {
26721
- console.log('Open.tsx::copyHandler::structStr', structStr);
26722
26791
  onOk({
26723
26792
  structStr: structStr,
26724
26793
  fragment: true
26725
26794
  });
26726
26795
  };
26727
26796
  var openHandler = function openHandler() {
26728
- console.log('Open.tsx::openHandler::structStr', structStr);
26729
26797
  onOk({
26730
26798
  structStr: structStr,
26731
26799
  fragment: false
@@ -26784,7 +26852,6 @@ var mapDispatchToProps$7 = function mapDispatchToProps(dispatch) {
26784
26852
  return {
26785
26853
  onOk: function onOk(result) {
26786
26854
  if (result.fragment) exec('copy');
26787
- console.log('Open.container.ts::mapDispatchToProps::result', result);
26788
26855
  dispatch(load(result.structStr, {
26789
26856
  badHeaderRecover: true,
26790
26857
  fragment: result.fragment
@@ -26988,7 +27055,8 @@ var SaveDialog = function (_Component) {
26988
27055
  server = _this$props.server,
26989
27056
  options = _this$props.options,
26990
27057
  formState = _this$props.formState,
26991
- ignoreChiralFlag = _this$props.ignoreChiralFlag;
27058
+ ignoreChiralFlag = _this$props.ignoreChiralFlag,
27059
+ bondThickness = _this$props.bondThickness;
26992
27060
  var errorHandler = _this.context.errorHandler;
26993
27061
  if (_this.isImageFormat(type)) {
26994
27062
  var ketSerialize = new ketcherCore.KetSerializer();
@@ -27002,6 +27070,7 @@ var SaveDialog = function (_Component) {
27002
27070
  });
27003
27071
  var _options = {};
27004
27072
  _options.outputFormat = type;
27073
+ _options.bondThickness = bondThickness;
27005
27074
  return server.generateImageAsBase64(structStr, _options).then(function (base64) {
27006
27075
  _this.setState({
27007
27076
  disableControls: false,
@@ -27191,7 +27260,9 @@ var SaveDialog = function (_Component) {
27191
27260
  imageFormat = _this$state2.imageFormat,
27192
27261
  isLoading = _this$state2.isLoading,
27193
27262
  structStr = _this$state2.structStr;
27194
- var formState = _this.props.formState;
27263
+ var _this$props3 = _this.props,
27264
+ formState = _this$props3.formState,
27265
+ bondThickness = _this$props3.bondThickness;
27195
27266
  var _formState$result2 = formState.result,
27196
27267
  filename = _formState$result2.filename,
27197
27268
  format = _formState$result2.format;
@@ -27221,6 +27292,7 @@ var SaveDialog = function (_Component) {
27221
27292
  data: structStr,
27222
27293
  filename: filename,
27223
27294
  outputFormat: imageFormat,
27295
+ bondThickness: bondThickness,
27224
27296
  type: "image/".concat(format, "+xml"),
27225
27297
  onSave: _this.props.onOk,
27226
27298
  disabled: disableControls || !formState.valid || isCleanStruct || !_this.props.server,
@@ -27306,6 +27378,7 @@ var mapStateToProps$4 = function mapStateToProps(state) {
27306
27378
  formState: state.modal.form,
27307
27379
  moleculeErrors: state.modal.form.moleculeErrors,
27308
27380
  checkState: state.options.check,
27381
+ bondThickness: state.options.settings.bondThickness,
27309
27382
  ignoreChiralFlag: state.editor.render.options.ignoreChiralFlag
27310
27383
  };
27311
27384
  };
@@ -30315,13 +30388,12 @@ function handleRightClick(getState) {
30315
30388
  }
30316
30389
  }
30317
30390
 
30318
- function initApp(element, staticResourcesUrl, options, server, setEditor) {
30391
+ function initApp(element, appRoot, staticResourcesUrl, options, server, setEditor) {
30319
30392
  var store = createStore(options, server, setEditor);
30320
30393
  store.dispatch(initKeydownListener(element));
30321
30394
  store.dispatch(initMouseListener(element));
30322
30395
  store.dispatch(initResize());
30323
- var root = client.createRoot(element);
30324
- root.render(jsxRuntime.jsx(reactRedux.Provider, {
30396
+ appRoot.render(jsxRuntime.jsx(reactRedux.Provider, {
30325
30397
  store: store,
30326
30398
  children: jsxRuntime.jsx(settingsContext.Provider, {
30327
30399
  value: {
@@ -30381,7 +30453,7 @@ var KetcherBuilder = function () {
30381
30453
  }, {
30382
30454
  key: "appendUiAsync",
30383
30455
  value: function () {
30384
- var _appendUiAsync = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee2(element, staticResourcesUrl, errorHandler, buttons) {
30456
+ var _appendUiAsync = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee2(element, appRoot, staticResourcesUrl, errorHandler, buttons) {
30385
30457
  var structService, editor;
30386
30458
  return _regeneratorRuntime__default["default"].wrap(function _callee2$(_context2) {
30387
30459
  while (1) {
@@ -30390,11 +30462,11 @@ var KetcherBuilder = function () {
30390
30462
  structService = this.structService;
30391
30463
  _context2.next = 3;
30392
30464
  return new Promise(function (resolve) {
30393
- initApp(element, staticResourcesUrl, {
30465
+ initApp(element, appRoot, staticResourcesUrl, {
30394
30466
  buttons: buttons || {},
30395
30467
  errorHandler: errorHandler || null,
30396
- version: "2.13.0-rc.3-dev.2" ,
30397
- buildDate: "2023-08-11T07:09:24" ,
30468
+ version: "2.14.0-rc.1" ,
30469
+ buildDate: "2023-08-15T11:24:53" ,
30398
30470
  buildNumber: ''
30399
30471
  }, structService, resolve);
30400
30472
  });
@@ -30411,7 +30483,7 @@ var KetcherBuilder = function () {
30411
30483
  }
30412
30484
  }, _callee2, this);
30413
30485
  }));
30414
- function appendUiAsync(_x2, _x3, _x4, _x5) {
30486
+ function appendUiAsync(_x2, _x3, _x4, _x5, _x6) {
30415
30487
  return _appendUiAsync.apply(this, arguments);
30416
30488
  }
30417
30489
  return appendUiAsync;
@@ -30446,19 +30518,19 @@ function buildKetcherAsync(_x) {
30446
30518
  }
30447
30519
  function _buildKetcherAsync() {
30448
30520
  _buildKetcherAsync = _asyncToGenerator__default["default"]( _regeneratorRuntime__default["default"].mark(function _callee(_ref) {
30449
- var element, staticResourcesUrl, structServiceProvider, buttons, errorHandler, builder;
30521
+ var element, appRoot, staticResourcesUrl, structServiceProvider, buttons, errorHandler, builder;
30450
30522
  return _regeneratorRuntime__default["default"].wrap(function _callee$(_context) {
30451
30523
  while (1) {
30452
30524
  switch (_context.prev = _context.next) {
30453
30525
  case 0:
30454
- element = _ref.element, staticResourcesUrl = _ref.staticResourcesUrl, structServiceProvider = _ref.structServiceProvider, buttons = _ref.buttons, errorHandler = _ref.errorHandler;
30526
+ element = _ref.element, appRoot = _ref.appRoot, staticResourcesUrl = _ref.staticResourcesUrl, structServiceProvider = _ref.structServiceProvider, buttons = _ref.buttons, errorHandler = _ref.errorHandler;
30455
30527
  builder = new KetcherBuilder();
30456
30528
  _context.next = 4;
30457
30529
  return builder.appendApiAsync(structServiceProvider);
30458
30530
  case 4:
30459
30531
  builder.appendServiceMode(structServiceProvider.mode);
30460
30532
  _context.next = 7;
30461
- return builder.appendUiAsync(element, staticResourcesUrl, errorHandler, buttons);
30533
+ return builder.appendUiAsync(element, appRoot, staticResourcesUrl, errorHandler, buttons);
30462
30534
  case 7:
30463
30535
  return _context.abrupt("return", builder.build());
30464
30536
  case 8:
@@ -30489,14 +30561,21 @@ function Editor(props) {
30489
30561
  width = _useResizeObserver.width;
30490
30562
  var ketcherInitEvent = new Event(KETCHER_INIT_EVENT_NAME);
30491
30563
  React.useEffect(function () {
30564
+ var appRoot = client.createRoot(rootElRef.current);
30492
30565
  buildKetcherAsync(_objectSpread(_objectSpread({}, props), {}, {
30493
- element: rootElRef.current
30566
+ element: rootElRef.current,
30567
+ appRoot: appRoot
30494
30568
  })).then(function (ketcher) {
30495
30569
  if (typeof onInit === 'function') {
30496
30570
  onInit(ketcher);
30497
30571
  window.dispatchEvent(ketcherInitEvent);
30498
30572
  }
30499
30573
  });
30574
+ return function () {
30575
+ setTimeout(function () {
30576
+ appRoot.unmount();
30577
+ });
30578
+ };
30500
30579
  }, []);
30501
30580
  return jsxRuntime.jsx("div", {
30502
30581
  ref: rootElRef,