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.
@@ -24,7 +24,7 @@ import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
24
24
  import _regeneratorRuntime from '@babel/runtime/regenerator';
25
25
  import _classCallCheck$2 from '@babel/runtime/helpers/classCallCheck';
26
26
  import _createClass$1 from '@babel/runtime/helpers/createClass';
27
- import { KetSerializer, MolSerializer, Ketcher, FormatterFactory, StereLabelStyleType, StereoColoringType, ShowHydrogenLabels, ShowHydrogenLabelNames, Bond as Bond$2, Elements, AtomList, StereoLabel, isAttachmentBond, Atom as Atom$2, findStereoAtoms, RxnArrowMode, SimpleObjectMode, emitEventRequestIsFinished, SGroup as SGroup$1, Pile, getStereoAtomsMap, identifyStructFormat, SupportedFormat, ChemicalMimeType, RenderStruct, Struct, SdfSerializer, FunctionalGroupsProvider, SaltsAndSolventsProvider, KetcherAsyncEvents, ElementColor, Vec2, fromMultipleMove, scrollByVector, FunctionalGroup, Scale, fracAngle, fromSgroupDeletion, fromFragmentDeletion, mergeMapOfItemsToSet, fromBondAddition, Action, fromAtomAddition, fromAtomsAttrs, checkOverlapping, fromSeveralSgroupAddition, expandSGroupWithMultipleAttachmentPoint, SgContexts, fromSgroupAction, fromItemsFuse, ReBond, setExpandSGroup, fromBondsAttrs, OperationType, ReStruct, fromSimpleObjectResizing, fromArrowResizing, getItemsToFuse, getHoverToFuse, fromTextDeletion, fromTextUpdating, isCloseToEdgeOfCanvas, isCloseToEdgeOfScreen, getDirections, shiftAndExtendCanvasByVector, formatProperties, Fragment as Fragment$1, fromRGroupAttachmentPointUpdate, fromOneBondDeletion, bondChangingAction, fromChain, fromStereoFlagUpdate, fromOneAtomDeletion, fromArrowDeletion, fromPlusDeletion, fromSimpleObjectDeletion, fromRGroupAttachmentPointDeletion, fromPaste, fromTemplateOnAtom, RGroup as RGroup$2, fromRGroupFragment, fromUpdateIfThen, fromRGroupAttrs, fromArrowAddition, fromPlusAddition, fromRotate, fromFlip, fromSimpleObjectAddition, fromTemplateOnBondAction, fromTemplateOnCanvas, fromTextCreation, fromHighlightCreate, fromHighlightClear, fromNewCanvas, Render, fromDescriptorsAlign, getPropertiesByFormat, StereoFlag, getPropertiesByImgFormat, b64toBlob, Generics, TextCommand, DefaultStructServiceOptions } from 'ketcher-core';
27
+ import { KetSerializer, MolSerializer, Ketcher, defaultBondThickness, FormatterFactory, StereLabelStyleType, StereoColoringType, ShowHydrogenLabels, ShowHydrogenLabelNames, Bond as Bond$2, Elements, AtomList, StereoLabel, isAttachmentBond, Atom as Atom$2, findStereoAtoms, RxnArrowMode, SimpleObjectMode, emitEventRequestIsFinished, SGroup as SGroup$1, Pile, getStereoAtomsMap, identifyStructFormat, SupportedFormat, ChemicalMimeType, RenderStruct, Struct, SdfSerializer, FunctionalGroupsProvider, SaltsAndSolventsProvider, KetcherAsyncEvents, ElementColor, Vec2, fromMultipleMove, scrollByVector, FunctionalGroup, Scale, fromSgroupDeletion, fromFragmentDeletion, mergeMapOfItemsToSet, vectorUtils, fromBondAddition, Action, fromAtomAddition, fromAtomsAttrs, checkOverlapping, fromSeveralSgroupAddition, expandSGroupWithMultipleAttachmentPoint, SgContexts, fromSgroupAction, fromItemsFuse, ReBond, setExpandSGroup, fromBondsAttrs, OperationType, ReStruct, fromSimpleObjectResizing, fromArrowResizing, getItemsToFuse, getHoverToFuse, fromTextDeletion, fromTextUpdating, isCloseToEdgeOfCanvas, isCloseToEdgeOfScreen, getDirections, shiftAndExtendCanvasByVector, formatProperties, Fragment as Fragment$1, fromRGroupAttachmentPointUpdate, fromOneBondDeletion, bondChangingAction, fromChain, fromStereoFlagUpdate, fromOneAtomDeletion, fromArrowDeletion, fromPlusDeletion, fromSimpleObjectDeletion, fromRGroupAttachmentPointDeletion, fromPaste, fromTemplateOnAtom, RGroup as RGroup$2, fromRGroupFragment, fromUpdateIfThen, fromRGroupAttrs, fromArrowAddition, fromPlusAddition, fromRotate, fromFlip, fromSimpleObjectAddition, fromTemplateOnBondAction, fromTemplateOnCanvas, fromTextCreation, fromHighlightCreate, fromHighlightClear, fromNewCanvas, Render, fromDescriptorsAlign, getPropertiesByFormat, StereoFlag, getPropertiesByImgFormat, b64toBlob, Generics, TextCommand, DefaultStructServiceOptions } from 'ketcher-core';
28
28
  import * as React from 'react';
29
29
  import React__default, { createRef, Component, useRef, useEffect, useState, useMemo, createElement, forwardRef, useCallback, useLayoutEffect, Fragment as Fragment$2, PureComponent, lazy, Suspense } from 'react';
30
30
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
@@ -210,7 +210,8 @@ function _copyImageToClipboard() {
210
210
  _context.next = 15;
211
211
  return ketcher.generateImage(structStr, {
212
212
  outputFormat: 'png',
213
- backgroundColor: '255, 255, 255'
213
+ backgroundColor: '255, 255, 255',
214
+ bondThickness: options.settings.bondThickness || defaultBondThickness
214
215
  });
215
216
  case 15:
216
217
  image = _context.sent;
@@ -370,7 +371,6 @@ function _copy(cb, data) {
370
371
  cb.setData(fmt, data[fmt]);
371
372
  });
372
373
  } catch (ex) {
373
- console.info("Could not write exact type ".concat(curFmt));
374
374
  }
375
375
  }
376
376
  }
@@ -555,7 +555,7 @@ var render = {
555
555
  bondThickness: {
556
556
  title: 'Bond thickness',
557
557
  type: 'integer',
558
- "default": 2,
558
+ "default": defaultBondThickness,
559
559
  minimum: 1,
560
560
  maximum: 96
561
561
  },
@@ -703,7 +703,6 @@ var storage = {
703
703
  try {
704
704
  item = JSON.parse(localStorage.getItem(key));
705
705
  } catch (ex) {
706
- console.info('LocalStorage:', ex.name);
707
706
  }
708
707
  return item;
709
708
  },
@@ -713,7 +712,6 @@ var storage = {
713
712
  localStorage.setItem(key, JSON.stringify(data));
714
713
  isSet = true;
715
714
  } catch (ex) {
716
- console.info('LocalStorage:', ex.name);
717
715
  isSet = false;
718
716
  }
719
717
  return isSet;
@@ -821,9 +819,11 @@ function optionsReducer() {
821
819
  if (type === 'APP_OPTIONS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
822
820
  app: _objectSpread$1j(_objectSpread$1j({}, state.app), data)
823
821
  });
824
- if (type === 'SAVE_SETTINGS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
825
- settings: data
826
- });
822
+ if (type === 'SAVE_SETTINGS') {
823
+ return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
824
+ settings: _objectSpread$1j(_objectSpread$1j({}, state.settings), data)
825
+ });
826
+ }
827
827
  if (type === 'SAVE_CHECK_OPTS') return _objectSpread$1j(_objectSpread$1j({}, state), {}, {
828
828
  check: data
829
829
  });
@@ -848,7 +848,6 @@ function constant(schema, prop) {
848
848
  return desc.constant || desc["enum"][0];
849
849
  }
850
850
  function mapOf(schema, prop) {
851
- console.assert(schema.oneOf);
852
851
  return schema.oneOf.reduce(function (res, desc) {
853
852
  res[constant(desc, prop)] = desc;
854
853
  return res;
@@ -2161,7 +2160,7 @@ var toolActions = {
2161
2160
  }
2162
2161
  },
2163
2162
  'reaction-arrow-filled-triangle': {
2164
- title: 'Arrow Filled Triangle',
2163
+ title: 'Arrow Filled Triangle Tool',
2165
2164
  action: {
2166
2165
  tool: 'reactionarrow',
2167
2166
  opts: RxnArrowMode.FilledTriangle
@@ -2540,7 +2539,6 @@ function onAction(action) {
2540
2539
  };
2541
2540
  }
2542
2541
  function parseStruct(struct, server, options) {
2543
- console.log('shared.ts::parseStruct::struct', struct);
2544
2542
  if (typeof struct === 'string') {
2545
2543
  options = options || {};
2546
2544
  var _options = options;
@@ -2548,9 +2546,7 @@ function parseStruct(struct, server, options) {
2548
2546
  _options.fragment;
2549
2547
  var formatterOptions = _objectWithoutProperties(_options, _excluded$y);
2550
2548
  var format = identifyStructFormat(struct);
2551
- console.log('shared.ts::parseStruct::format', format);
2552
2549
  if (format === SupportedFormat.cdx) {
2553
- console.log('shared.ts::parseStruct::format === SupportedFormat.cdx');
2554
2550
  struct = "base64::".concat(struct.replace(/\s/g, ''));
2555
2551
  }
2556
2552
  var factory = new FormatterFactory(server);
@@ -2572,7 +2568,6 @@ function load(struct, options) {
2572
2568
  while (1) {
2573
2569
  switch (_context.prev = _context.next) {
2574
2570
  case 0:
2575
- console.log('shared.ts::load::struct', struct);
2576
2571
  state = getState();
2577
2572
  editor = state.editor;
2578
2573
  server = state.server;
@@ -2584,26 +2579,26 @@ function load(struct, options) {
2584
2579
  ignoreChiralFlag: editor.options().ignoreChiralFlag
2585
2580
  });
2586
2581
  dispatch(setAnalyzingFile(true));
2587
- _context.prev = 9;
2588
- _context.next = 12;
2582
+ _context.prev = 8;
2583
+ _context.next = 11;
2589
2584
  return parseStruct(struct, server, otherOptions);
2590
- case 12:
2585
+ case 11:
2591
2586
  parsedStruct = _context.sent;
2592
2587
  _otherOptions = otherOptions, fragment = _otherOptions.fragment;
2593
2588
  hasUnsupportedGroups = parsedStruct.sgroups.some(function (sGroup) {
2594
2589
  return !supportedSGroupTypes[sGroup.type];
2595
2590
  });
2596
2591
  if (!hasUnsupportedGroups) {
2597
- _context.next = 19;
2592
+ _context.next = 18;
2598
2593
  break;
2599
2594
  }
2600
- _context.next = 18;
2595
+ _context.next = 17;
2601
2596
  return editor.event.confirm.dispatch();
2602
- case 18:
2597
+ case 17:
2603
2598
  parsedStruct.sgroups = parsedStruct.sgroups.filter(function (_key, sGroup) {
2604
2599
  return supportedSGroupTypes[sGroup.type];
2605
2600
  });
2606
- case 19:
2601
+ case 18:
2607
2602
  parsedStruct.rescale();
2608
2603
  if (editor.struct().atoms.size) {
2609
2604
  oldStruct = editor.struct().clone();
@@ -2656,23 +2651,23 @@ function load(struct, options) {
2656
2651
  dispatch({
2657
2652
  type: 'MODAL_CLOSE'
2658
2653
  });
2659
- _context.next = 37;
2654
+ _context.next = 36;
2660
2655
  break;
2661
- case 33:
2662
- _context.prev = 33;
2663
- _context.t0 = _context["catch"](9);
2656
+ case 32:
2657
+ _context.prev = 32;
2658
+ _context.t0 = _context["catch"](8);
2664
2659
  dispatch(setAnalyzingFile(false));
2665
2660
  _context.t0 && errorHandler && errorHandler(_context.t0.message);
2666
- case 37:
2667
- _context.prev = 37;
2661
+ case 36:
2662
+ _context.prev = 36;
2668
2663
  emitEventRequestIsFinished();
2669
- return _context.finish(37);
2670
- case 40:
2664
+ return _context.finish(36);
2665
+ case 39:
2671
2666
  case "end":
2672
2667
  return _context.stop();
2673
2668
  }
2674
2669
  }
2675
- }, _callee, null, [[9, 33, 37, 40]]);
2670
+ }, _callee, null, [[8, 32, 36, 39]]);
2676
2671
  }));
2677
2672
  return function (_x, _x2) {
2678
2673
  return _ref.apply(this, arguments);
@@ -3047,7 +3042,7 @@ var zoom = {
3047
3042
 
3048
3043
  var openHelpLink = function openHelpLink() {
3049
3044
  var _window$open;
3050
- 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();
3045
+ 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();
3051
3046
  };
3052
3047
  var help = {
3053
3048
  help: {
@@ -5376,7 +5371,7 @@ function SvgClose(props) {
5376
5371
  xmlns: "http://www.w3.org/2000/svg"
5377
5372
  }, props), _path$1b || (_path$1b = /*#__PURE__*/React.createElement("path", {
5378
5373
  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",
5379
- fill: "#333"
5374
+ fill: "currentColor"
5380
5375
  })));
5381
5376
  }
5382
5377
 
@@ -7190,7 +7185,8 @@ var ActionButton = function ActionButton(props) {
7190
7185
  disableableButtons = props.disableableButtons,
7191
7186
  indigoVerification = props.indigoVerification,
7192
7187
  className = props.className,
7193
- onAction = props.onAction;
7188
+ onAction = props.onAction,
7189
+ dataTestId = props.dataTestId;
7194
7190
  if (status.hidden) {
7195
7191
  return null;
7196
7192
  }
@@ -7202,7 +7198,7 @@ var ActionButton = function ActionButton(props) {
7202
7198
  }
7203
7199
  };
7204
7200
  return jsxs("button", {
7205
- "data-testid": name,
7201
+ "data-testid": dataTestId || name,
7206
7202
  disabled: disabled,
7207
7203
  onClick: handleClick,
7208
7204
  title: shortcut ? "".concat(action === null || action === void 0 ? void 0 : action.title, " (").concat(shortcut, ")") : action === null || action === void 0 ? void 0 : action.title,
@@ -7471,7 +7467,8 @@ var ToolbarMultiToolItem = function ToolbarMultiToolItem(props) {
7471
7467
  className = props.className,
7472
7468
  vertical = props.vertical,
7473
7469
  onAction = props.onAction,
7474
- onOpen = props.onOpen;
7470
+ onOpen = props.onOpen,
7471
+ dataTestId = props.dataTestId;
7475
7472
  var ref = useRef(null);
7476
7473
  var _usePortalOpening = usePortalOpening([id, opened, options]),
7477
7474
  _usePortalOpening2 = _slicedToArray$1(_usePortalOpening, 1),
@@ -7536,7 +7533,7 @@ var ToolbarMultiToolItem = function ToolbarMultiToolItem(props) {
7536
7533
  action: config[currentId],
7537
7534
  status: currentStatus,
7538
7535
  selected: selected,
7539
- "data-testid": iconName
7536
+ dataTestId: dataTestId || iconName
7540
7537
  })), !isOpen && jsx(Icon, {
7541
7538
  className: "".concat(classes$N.icon, " ").concat((currentStatus === null || currentStatus === void 0 ? void 0 : currentStatus.selected) && classes$N.iconSelected),
7542
7539
  name: "dropdown",
@@ -7567,7 +7564,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7567
7564
  disableableButtons = props.disableableButtons,
7568
7565
  vertical = props.vertical,
7569
7566
  onAction = props.onAction,
7570
- onOpen = props.onOpen;
7567
+ onOpen = props.onOpen,
7568
+ dataTestId = props.dataTestId;
7571
7569
  if (!(options !== null && options !== void 0 && options.length)) {
7572
7570
  var _status$id;
7573
7571
  var iconName = getIconName(id);
@@ -7579,7 +7577,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7579
7577
  selected: !!((_status$id = status[id]) !== null && _status$id !== void 0 && _status$id.selected),
7580
7578
  indigoVerification: indigoVerification,
7581
7579
  disableableButtons: disableableButtons,
7582
- onAction: onAction
7580
+ onAction: onAction,
7581
+ dataTestId: dataTestId
7583
7582
  });
7584
7583
  }
7585
7584
  return jsx(ToolbarMultiToolItem, {
@@ -7592,7 +7591,8 @@ var ToolbarGroupItem = function ToolbarGroupItem(props) {
7592
7591
  indigoVerification: indigoVerification,
7593
7592
  onAction: onAction,
7594
7593
  onOpen: onOpen,
7595
- vertical: vertical
7594
+ vertical: vertical,
7595
+ dataTestId: dataTestId
7596
7596
  });
7597
7597
  };
7598
7598
 
@@ -8068,9 +8068,7 @@ function execute(activeTool, _ref) {
8068
8068
  }
8069
8069
  } else if (typeof action === 'function') {
8070
8070
  action(editor, server, options);
8071
- } else {
8072
- console.info('no action');
8073
- }
8071
+ } else ;
8074
8072
  return activeTool;
8075
8073
  }
8076
8074
  function selected(actObj, activeTool, _ref2) {
@@ -8162,28 +8160,22 @@ function fileOpener(server) {
8162
8160
  }
8163
8161
  function throughFileReader(file) {
8164
8162
  var isCDX = file.name.endsWith('cdx') && !file.name.endsWith('b64cdx');
8165
- console.log('fileOpener.js::throughFileReader::file', file);
8166
8163
  return new Promise(function (resolve, reject) {
8167
8164
  var rd = new FileReader();
8168
8165
  rd.onload = function () {
8169
- console.log('fileOpener.js::throughFileReader::onload::rd.result', rd.result);
8170
8166
  var content;
8171
8167
  if (isCDX) {
8172
8168
  var base64String = rd.result.split(',').at(-1);
8173
- console.log('fileOpener.js::throughFileReader::onload::base64String', base64String);
8174
8169
  content = base64String;
8175
8170
  } else {
8176
8171
  content = rd.result;
8177
8172
  }
8178
- console.log('fileOpener.js::throughFileReader::onload::content', content);
8179
- console.log('fileOpener.js::throughFileReader::onload::file.msClose', file.msClose);
8180
8173
  if (file.msClose) file.msClose();
8181
8174
  resolve(content);
8182
8175
  };
8183
8176
  rd.onerror = function (event) {
8184
8177
  reject(event);
8185
8178
  };
8186
- console.log('fileOpener.js::throughFileReader::isCdx', isCDX);
8187
8179
  isCDX ? rd.readAsDataURL(file) : rd.readAsText(file, 'UTF-8');
8188
8180
  });
8189
8181
  }
@@ -13024,9 +13016,7 @@ var useSubscriptionOnEvents = function useSubscriptionOnEvents() {
13024
13016
  var unsubscribeOnUnMount = function unsubscribeOnUnMount() {
13025
13017
  unsubscribe(getKetcherInstance());
13026
13018
  };
13027
- window.addEventListener(KETCHER_INIT_EVENT_NAME, function () {
13028
- subscribeOnInit();
13029
- });
13019
+ window.addEventListener(KETCHER_INIT_EVENT_NAME, subscribeOnInit);
13030
13020
  return function () {
13031
13021
  unsubscribeOnUnMount();
13032
13022
  window.removeEventListener(KETCHER_INIT_EVENT_NAME, subscribeOnInit);
@@ -13174,10 +13164,12 @@ var LeftToolbar = function LeftToolbar(props) {
13174
13164
  var sizeRef = useRef();
13175
13165
  var Item = function Item(_ref) {
13176
13166
  var id = _ref.id,
13177
- options = _ref.options;
13167
+ options = _ref.options,
13168
+ dataTestId = _ref.dataTestId;
13178
13169
  return ToolbarGroupItem(_objectSpread$V({
13179
13170
  id: id,
13180
- options: options
13171
+ options: options,
13172
+ dataTestId: dataTestId
13181
13173
  }, rest));
13182
13174
  };
13183
13175
  var scrollUp = function scrollUp() {
@@ -13223,6 +13215,12 @@ var LeftToolbar = function LeftToolbar(props) {
13223
13215
  return createElement(Shape, _objectSpread$V(_objectSpread$V({}, rest), {}, {
13224
13216
  key: item.id
13225
13217
  }));
13218
+ case 'bonds':
13219
+ return jsx(Item, {
13220
+ id: item.id,
13221
+ options: item.options,
13222
+ dataTestId: "bonds"
13223
+ }, item.id);
13226
13224
  default:
13227
13225
  return jsx(Item, {
13228
13226
  id: item.id,
@@ -14091,7 +14089,6 @@ var TopToolbar = function TopToolbar(_ref) {
14091
14089
  isCollapsed: width < collapseLimit
14092
14090
  }), jsx(SystemControls, {
14093
14091
  onHistoryClick: function onHistoryClick() {
14094
- console.log('History button clicked');
14095
14092
  },
14096
14093
  onSettingsOpen: onSettingsOpen,
14097
14094
  onFullscreen: onFullscreen,
@@ -14751,38 +14748,6 @@ var LassoHelper = function () {
14751
14748
  return LassoHelper;
14752
14749
  }();
14753
14750
 
14754
- function calcAngle$1(pos0, pos1) {
14755
- var v = Vec2.diff(pos1, pos0);
14756
- return Math.atan2(v.y, v.x);
14757
- }
14758
- function calcNewAtomPos(pos0, pos1, ctrlKey) {
14759
- var v = new Vec2(1, 0).rotate(ctrlKey ? calcAngle$1(pos0, pos1) : fracAngle(pos0, pos1));
14760
- v.add_(pos0);
14761
- return v;
14762
- }
14763
- function degrees(angle) {
14764
- var degree = Math.round(angle / Math.PI * 180);
14765
- if (degree > 180) degree -= 360;else if (degree <= -180) degree += 360;
14766
- return degree;
14767
- }
14768
- function normalizeAngle(angle) {
14769
- var angleWithinFullCircle = angle % (2 * Math.PI);
14770
- if (angleWithinFullCircle > Math.PI) {
14771
- return angleWithinFullCircle - 2 * Math.PI;
14772
- }
14773
- if (angleWithinFullCircle <= -Math.PI) {
14774
- return angleWithinFullCircle + 2 * Math.PI;
14775
- }
14776
- return angleWithinFullCircle;
14777
- }
14778
- var utils = {
14779
- calcAngle: calcAngle$1,
14780
- fracAngle: fracAngle,
14781
- calcNewAtomPos: calcNewAtomPos,
14782
- degrees: degrees,
14783
- normalizeAngle: normalizeAngle
14784
- };
14785
-
14786
14751
  function deleteFunctionalGroups(sGroupsId, struct, action) {
14787
14752
  var deletedAtoms = [];
14788
14753
  var functionalGroups = struct.molecule.functionalGroups;
@@ -14935,13 +14900,13 @@ var AtomTool = function () {
14935
14900
  }
14936
14901
  if (atomId !== undefined) {
14937
14902
  var atom = molecule.atoms.get(atomId);
14938
- var angle = utils.calcAngle(atom === null || atom === void 0 ? void 0 : atom.pp, rnd.page2obj(event));
14939
- if (!event.ctrlKey) angle = utils.fracAngle(angle, null);
14940
- var degrees = utils.degrees(angle);
14903
+ var angle = vectorUtils.calcAngle(atom.pp, rnd.page2obj(event));
14904
+ if (!event.ctrlKey) angle = vectorUtils.fracAngle(angle, null);
14905
+ var degrees = vectorUtils.degrees(angle);
14941
14906
  editor.event.message.dispatch({
14942
14907
  info: degrees + 'º'
14943
14908
  });
14944
- var newAtomPos = utils.calcNewAtomPos(atom === null || atom === void 0 ? void 0 : atom.pp, rnd.page2obj(event), event.ctrlKey);
14909
+ var newAtomPos = vectorUtils.calcNewAtomPos(atom.pp, rnd.page2obj(event), event.ctrlKey);
14945
14910
  if (dragCtx.action) {
14946
14911
  dragCtx.action.perform(reStruct);
14947
14912
  }
@@ -15468,7 +15433,6 @@ var SGroupTool = function () {
15468
15433
  editor.selection(null);
15469
15434
  }
15470
15435
  })["catch"](function (error) {
15471
- console.error(error);
15472
15436
  });
15473
15437
  }
15474
15438
  }]);
@@ -15908,7 +15872,6 @@ function getStructCenter(ReStruct, selection) {
15908
15872
  return Vec2.lc2(bb.p0, 0.5, bb.p1, 0.5);
15909
15873
  }
15910
15874
  function recoordinate(editor, rp) {
15911
- console.assert(rp, 'Reference point not specified');
15912
15875
  if (rp) {
15913
15876
  editor.render.setScrollOffset(rp.x, rp.y);
15914
15877
  } else {
@@ -16037,8 +16000,8 @@ var SelectTool = function () {
16037
16000
  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;
16038
16001
  if (shouldDisplayDegree) {
16039
16002
  var pos = rnd.page2obj(event);
16040
- var angle = utils.calcAngle(dragCtx.xy0, pos);
16041
- var degrees = utils.degrees(angle);
16003
+ var angle = vectorUtils.calcAngle(dragCtx.xy0, pos);
16004
+ var degrees = vectorUtils.degrees(angle);
16042
16005
  editor.event.message.dispatch({
16043
16006
  info: degrees + 'º'
16044
16007
  });
@@ -17963,9 +17926,9 @@ var BondTool = function () {
17963
17926
  if ('dragCtx' in this) {
17964
17927
  var dragCtx = this.dragCtx;
17965
17928
  var pos = rnd.page2obj(event);
17966
- var angle = utils.calcAngle(dragCtx.xy0, pos);
17967
- if (!event.ctrlKey) angle = utils.fracAngle(angle, null);
17968
- var degrees = utils.degrees(angle);
17929
+ var angle = vectorUtils.calcAngle(dragCtx.xy0, pos);
17930
+ if (!event.ctrlKey) angle = vectorUtils.fracAngle(angle, null);
17931
+ var degrees = vectorUtils.degrees(angle);
17969
17932
  this.editor.event.message.dispatch({
17970
17933
  info: degrees + 'º'
17971
17934
  });
@@ -18053,10 +18016,11 @@ var BondTool = function () {
18053
18016
  var xy1 = rnd.page2obj(event);
18054
18017
  dist = Vec2.dist(dragCtx.xy0, xy1);
18055
18018
  if (beginPos) {
18056
- endPos = utils.calcNewAtomPos(beginPos, xy1, event.ctrlKey);
18019
+ endPos = vectorUtils.calcNewAtomPos(beginPos, xy1, event.ctrlKey);
18057
18020
  } else {
18058
18021
  var atom = rnd.ctab.molecule.atoms.get(beginAtom);
18059
- endPos = utils.calcNewAtomPos(atom === null || atom === void 0 ? void 0 : atom.pp.get_xy0(), xy1, event.ctrlKey);
18022
+ endPos = vectorUtils.calcNewAtomPos(
18023
+ atom.pp.get_xy0(), xy1, event.ctrlKey);
18060
18024
  }
18061
18025
  }
18062
18026
  if (dist > 0.3) {
@@ -18289,7 +18253,7 @@ var ChainTool = function () {
18289
18253
  var pos0 = dragCtx.item ? (_atoms$get = atoms.get(dragCtx.item.id)) === null || _atoms$get === void 0 ? void 0 : _atoms$get.pp : dragCtx.xy0;
18290
18254
  var pos1 = editor.render.page2obj(event);
18291
18255
  var sectCount = Math.ceil(Vec2.diff(pos1, pos0).length());
18292
- var angle = event.ctrlKey ? utils.calcAngle(pos0, pos1) : utils.fracAngle(pos0, pos1);
18256
+ var angle = event.ctrlKey ? vectorUtils.calcAngle(pos0, pos1) : vectorUtils.fracAngle(pos0, pos1);
18293
18257
  var _fromChain = fromChain(restruct, pos0, angle, sectCount, dragCtx.item ? dragCtx.item.id : null),
18294
18258
  _fromChain2 = _slicedToArray$1(_fromChain, 2),
18295
18259
  action = _fromChain2[0],
@@ -18795,7 +18759,6 @@ var EraserTool = function () {
18795
18759
  } else if (ci.map === 'rgroupAttachmentPoints') {
18796
18760
  this.editor.update(fromRGroupAttachmentPointDeletion(restruct, ci.id));
18797
18761
  } else {
18798
- console.error('EraserTool: unable to delete the object ' + ci.map + '[' + ci.id + ']');
18799
18762
  return;
18800
18763
  }
18801
18764
  this.editor.selection(null);
@@ -18974,11 +18937,11 @@ var PasteTool = function () {
18974
18937
  var atom = this.editor.struct().atoms.get(atomId);
18975
18938
  pos0 = atom === null || atom === void 0 ? void 0 : atom.pp;
18976
18939
  }
18977
- var angle = utils.calcAngle(pos0, pos1);
18940
+ var angle = vectorUtils.calcAngle(pos0, pos1);
18978
18941
  if (!event.ctrlKey) {
18979
- angle = utils.fracAngle(angle, null);
18942
+ angle = vectorUtils.fracAngle(angle, null);
18980
18943
  }
18981
- var degrees = utils.degrees(angle);
18944
+ var degrees = vectorUtils.degrees(angle);
18982
18945
  if (
18983
18946
  this.dragCtx.hasOwnProperty('angle') && this.dragCtx.angle === degrees) return;
18984
18947
  if (this.dragCtx.action) {
@@ -19038,7 +19001,7 @@ var PasteTool = function () {
19038
19001
  var action = this.action;
19039
19002
  delete this.action;
19040
19003
  if (!this.isSingleContractedGroup || !this.mergeItems) {
19041
- this.editor.update(dropAndMerge(this.editor, this.mergeItems, action, true));
19004
+ dropAndMerge(this.editor, this.mergeItems, action, true);
19042
19005
  }
19043
19006
  }
19044
19007
  }
@@ -19073,7 +19036,7 @@ function prepareTemplateFromSingleGroup(molecule) {
19073
19036
  template.xy0 = xy0.scaled(1 / (molecule.atoms.size || 1));
19074
19037
  var atom = molecule.atoms.get(template.aid);
19075
19038
  if (atom) {
19076
- template.angle0 = utils.calcAngle(atom.pp, template.xy0);
19039
+ template.angle0 = vectorUtils.calcAngle(atom.pp, template.xy0);
19077
19040
  }
19078
19041
  return template;
19079
19042
  }
@@ -19661,6 +19624,17 @@ var ReactionUnmapTool = function () {
19661
19624
  return ReactionUnmapTool;
19662
19625
  }();
19663
19626
 
19627
+ function normalizeAngle(angle) {
19628
+ var angleWithinFullCircle = angle % (2 * Math.PI);
19629
+ if (angleWithinFullCircle > Math.PI) {
19630
+ return angleWithinFullCircle - 2 * Math.PI;
19631
+ }
19632
+ if (angleWithinFullCircle <= -Math.PI) {
19633
+ return angleWithinFullCircle + 2 * Math.PI;
19634
+ }
19635
+ return angleWithinFullCircle;
19636
+ }
19637
+
19664
19638
  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; }
19665
19639
  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$1(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; }
19666
19640
  var SNAP_ANGLES_RELATIVE_TO_FIXED_BOND = [Math.PI / 2, -Math.PI / 2, 2 * Math.PI / 3, -(2 * Math.PI) / 3, Math.PI];
@@ -19679,7 +19653,7 @@ var RotateTool = function () {
19679
19653
  }
19680
19654
  var dragCtx = _this.dragCtx;
19681
19655
  var mousePos = _this.editor.render.page2obj(event);
19682
- var mouseMoveAngle = utils.calcAngle(dragCtx.xy0, mousePos) - dragCtx.angle1;
19656
+ var mouseMoveAngle = vectorUtils.calcAngle(dragCtx.xy0, mousePos) - dragCtx.angle1;
19683
19657
  var rotateAngle = mouseMoveAngle;
19684
19658
  _this.reStruct.clearSnappingBonds();
19685
19659
  if (_this.snapInfo) {
@@ -19690,9 +19664,9 @@ var RotateTool = function () {
19690
19664
  _this$snap2 = _slicedToArray$1(_this$snap, 2),
19691
19665
  isSnapping = _this$snap2[0],
19692
19666
  rotateAngleWithSnapping = _this$snap2[1];
19693
- rotateAngle = isSnapping ? rotateAngleWithSnapping : utils.fracAngle(mouseMoveAngle, null);
19667
+ rotateAngle = isSnapping ? rotateAngleWithSnapping : vectorUtils.fracAngle(mouseMoveAngle, null);
19694
19668
  }
19695
- var rotateAngleInDegrees = utils.degrees(rotateAngle);
19669
+ var rotateAngleInDegrees = vectorUtils.degrees(rotateAngle);
19696
19670
  if ('angle' in dragCtx && dragCtx.angle === rotateAngleInDegrees) {
19697
19671
  return true;
19698
19672
  }
@@ -19750,7 +19724,7 @@ var RotateTool = function () {
19750
19724
  value: function mousedownHandle(handleCenter, center) {
19751
19725
  this.dragCtx = {
19752
19726
  xy0: center,
19753
- angle1: utils.calcAngle(center, handleCenter)
19727
+ angle1: vectorUtils.calcAngle(center, handleCenter)
19754
19728
  };
19755
19729
  this.initSnapInfo();
19756
19730
  }
@@ -19897,7 +19871,7 @@ var RotateTool = function () {
19897
19871
  var absoluteSnapAngles = [];
19898
19872
  var snapAngleToHalfBonds = new Map();
19899
19873
  SNAP_ANGLES_RELATIVE_TO_FIXED_BOND.forEach(function (angle) {
19900
- var snapAngle = utils.normalizeAngle(fixedHalfBondAngle + angle);
19874
+ var snapAngle = normalizeAngle(fixedHalfBondAngle + angle);
19901
19875
  absoluteSnapAngles.push(snapAngle);
19902
19876
  snapAngleToHalfBonds.set(snapAngle, [rotatableHalfBondId, fixedHalfBondId]);
19903
19877
  });
@@ -19916,8 +19890,8 @@ var RotateTool = function () {
19916
19890
  var currentHalfBondId = fixedHalfBondIds[j];
19917
19891
  var currentHalfBondAngle = fixedHalfBondAngles[j];
19918
19892
  var difference = currentHalfBondAngle - previousHalfBondAngle;
19919
- var bisectorAngle = utils.normalizeAngle(currentHalfBondAngle - difference / 2);
19920
- var snapAngle = difference > Math.PI ? bisectorAngle : utils.normalizeAngle(bisectorAngle + Math.PI);
19893
+ var bisectorAngle = normalizeAngle(currentHalfBondAngle - difference / 2);
19894
+ var snapAngle = difference > Math.PI ? bisectorAngle : normalizeAngle(bisectorAngle + Math.PI);
19921
19895
  absoluteSnapAngles.push(snapAngle);
19922
19896
  snapAngleToHalfBonds.set(snapAngle, [rotatableHalfBondId, previousHalfBondId, currentHalfBondId]);
19923
19897
  }
@@ -19963,7 +19937,7 @@ var RotateTool = function () {
19963
19937
  if (!this.snapInfo) {
19964
19938
  return [isSnapping, rotateAngle];
19965
19939
  }
19966
- var newRotatedHalfBondAngle = utils.normalizeAngle(this.snapInfo.rotatableHalfBondAngle + mouseMoveAngle);
19940
+ var newRotatedHalfBondAngle = normalizeAngle(this.snapInfo.rotatableHalfBondAngle + mouseMoveAngle);
19967
19941
  this.snapInfo.absoluteSnapAngles.some(function (snapAngle, index) {
19968
19942
  if (Math.abs(newRotatedHalfBondAngle - snapAngle) <= MAX_SNAP_DELTA) {
19969
19943
  isSnapping = true;
@@ -20094,11 +20068,74 @@ var SimpleObjectTool = function () {
20094
20068
 
20095
20069
  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; }
20096
20070
  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$1(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; }
20071
+ var PREVIEW_DELAY = 300;
20072
+ function getBondFlipSign(struct, bond) {
20073
+ var _struct$atoms$get, _struct$halfBonds$get;
20074
+ var xy0 = new Vec2();
20075
+ 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;
20076
+ var frIds = struct.getFragmentIds(frid);
20077
+ var count = 0;
20078
+ 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;
20079
+ if (loop && loop < 0) {
20080
+ var _struct$halfBonds$get2;
20081
+ 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;
20082
+ }
20083
+ if (loop && loop >= 0) {
20084
+ var _struct$loops$get;
20085
+ var loopHbs = (_struct$loops$get = struct.loops.get(loop)) === null || _struct$loops$get === void 0 ? void 0 : _struct$loops$get.hbs;
20086
+ loopHbs === null || loopHbs === void 0 ? void 0 : loopHbs.forEach(function (hb) {
20087
+ var _struct$halfBonds$get3;
20088
+ var halfBondBegin = (_struct$halfBonds$get3 = struct.halfBonds.get(hb)) === null || _struct$halfBonds$get3 === void 0 ? void 0 : _struct$halfBonds$get3.begin;
20089
+ if (halfBondBegin) {
20090
+ var hbbAtom = struct.atoms.get(halfBondBegin);
20091
+ if (hbbAtom) {
20092
+ xy0.add_(hbbAtom.pp);
20093
+ count++;
20094
+ }
20095
+ }
20096
+ });
20097
+ } else {
20098
+ frIds.forEach(function (id) {
20099
+ var atomById = struct.atoms.get(id);
20100
+ if (atomById) {
20101
+ xy0.add_(atomById.pp);
20102
+ count++;
20103
+ }
20104
+ });
20105
+ }
20106
+ var v0 = xy0.scaled(1 / count);
20107
+ return getSign(struct, bond, v0) || 1;
20108
+ }
20109
+ function getAngleFromEvent(event, ci, restruct) {
20110
+ var _restruct$atoms$get;
20111
+ var degree = (_restruct$atoms$get = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get === void 0 ? void 0 : _restruct$atoms$get.a.neighbors.length;
20112
+ var angle;
20113
+ if (degree && degree > 1) {
20114
+ angle = null;
20115
+ } else if (degree === 1) {
20116
+ var _restruct$molecule$ha;
20117
+ var atom = restruct.molecule.atoms.get(ci.id);
20118
+ 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);
20119
+ var nei = (neiId || neiId === 0) && restruct.molecule.atoms.get(neiId);
20120
+ angle = event.ctrlKey ? vectorUtils.calcAngle(nei === null || nei === void 0 ? void 0 : nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp) : vectorUtils.fracAngle(vectorUtils.calcAngle(nei.pp, atom === null || atom === void 0 ? void 0 : atom.pp), null);
20121
+ } else {
20122
+ angle = 0;
20123
+ }
20124
+ return angle;
20125
+ }
20126
+ function getUniqueCiId(ci) {
20127
+ return "".concat(ci.id, "-").concat(ci.map);
20128
+ }
20097
20129
  var TemplateTool = function () {
20098
20130
  function TemplateTool(editor, tmpl) {
20099
20131
  _classCallCheck$2(this, TemplateTool);
20132
+ _defineProperty$1(this, "previewTimeout", null);
20100
20133
  _defineProperty$1(this, "targetGroupsIds", []);
20101
20134
  this.editor = editor;
20135
+ this.isPreviewVisible = false;
20136
+ this.previewRemoveAction = new Action();
20137
+ this.previewTimeout = null;
20138
+ this.lastPreviewId = null;
20102
20139
  this.mode = getTemplateMode(tmpl);
20103
20140
  this.editor.selection(null);
20104
20141
  this.isSaltOrSolvent = SGroup$1.isSaltOrSolvent(tmpl.struct.name);
@@ -20118,7 +20155,7 @@ var TemplateTool = function () {
20118
20155
  this.template.xy0 = xy0.scaled(1 / (frag.atoms.size || 1));
20119
20156
  var atom = frag.atoms.get(this.template.aid);
20120
20157
  if (atom) {
20121
- this.template.angle0 = utils.calcAngle(atom.pp, this.template.xy0);
20158
+ this.template.angle0 = vectorUtils.calcAngle(atom.pp, this.template.xy0);
20122
20159
  this.findItems.push('atoms');
20123
20160
  }
20124
20161
  var bond = frag.bonds.get(this.template.bid);
@@ -20191,13 +20228,13 @@ var TemplateTool = function () {
20191
20228
  key: "mousedown",
20192
20229
  value: function () {
20193
20230
  var _mousedown = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(event) {
20194
- var _this2 = this;
20195
- 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;
20231
+ var _this$closestItem2, _this$closestItem3, _this$closestItem4, dragCtx, ci, bond;
20196
20232
  return _regeneratorRuntime.wrap(function _callee$(_context) {
20197
20233
  while (1) {
20198
20234
  switch (_context.prev = _context.next) {
20199
20235
  case 0:
20200
20236
  this.event = event;
20237
+ this.hidePreview();
20201
20238
  if (this.functionalGroups.size) {
20202
20239
  this.targetGroupsIds = getGroupIdsFromItemArrays(this.struct, _objectSpread$M(_objectSpread$M({}, ((_this$closestItem2 = this.closestItem) === null || _this$closestItem2 === void 0 ? void 0 : _this$closestItem2.map) === 'atoms' && {
20203
20240
  atoms: [this.closestItem.id]
@@ -20210,14 +20247,14 @@ var TemplateTool = function () {
20210
20247
  }
20211
20248
  }
20212
20249
  if (!this.isNeedToShowRemoveAbbreviationPopup) {
20213
- _context.next = 6;
20250
+ _context.next = 7;
20214
20251
  break;
20215
20252
  }
20216
- _context.next = 5;
20253
+ _context.next = 6;
20217
20254
  return this.showRemoveAbbreviationPopup();
20218
- case 5:
20219
- return _context.abrupt("return");
20220
20255
  case 6:
20256
+ return _context.abrupt("return");
20257
+ case 7:
20221
20258
  this.editor.hover(null);
20222
20259
  this.dragCtx = {
20223
20260
  xy0: this.editor.render.page2obj(event),
@@ -20226,50 +20263,18 @@ var TemplateTool = function () {
20226
20263
  dragCtx = this.dragCtx;
20227
20264
  ci = dragCtx.item;
20228
20265
  if (ci) {
20229
- _context.next = 13;
20266
+ _context.next = 14;
20230
20267
  break;
20231
20268
  }
20232
20269
  delete dragCtx.item;
20233
20270
  return _context.abrupt("return");
20234
- case 13:
20271
+ case 14:
20235
20272
  if (ci.map === 'bonds' && !this.isModeFunctionalGroup) {
20236
- xy0 = new Vec2();
20237
20273
  bond = this.struct.bonds.get(ci.id);
20238
- 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;
20239
- frIds = this.struct.getFragmentIds(frid);
20240
- count = 0;
20241
- 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;
20242
- if (loop && loop < 0) {
20243
- 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;
20244
- }
20245
- if (loop && loop >= 0) {
20246
- loopHbs = (_this$struct$loops$ge = this.struct.loops.get(loop)) === null || _this$struct$loops$ge === void 0 ? void 0 : _this$struct$loops$ge.hbs;
20247
- loopHbs === null || loopHbs === void 0 ? void 0 : loopHbs.forEach(function (hb) {
20248
- var _this2$struct$halfBon;
20249
- var halfBondBegin = (_this2$struct$halfBon = _this2.struct.halfBonds.get(hb)) === null || _this2$struct$halfBon === void 0 ? void 0 : _this2$struct$halfBon.begin;
20250
- if (halfBondBegin) {
20251
- var hbbAtom = _this2.struct.atoms.get(halfBondBegin);
20252
- if (hbbAtom) {
20253
- xy0.add_(hbbAtom.pp);
20254
- count++;
20255
- }
20256
- }
20257
- });
20258
- } else {
20259
- frIds.forEach(function (id) {
20260
- var atomById = _this2.struct.atoms.get(id);
20261
- if (atomById) {
20262
- xy0.add_(atomById.pp);
20263
- count++;
20264
- }
20265
- });
20266
- }
20267
- dragCtx.v0 = xy0.scaled(1 / count);
20268
- sign = getSign(this.struct, bond, dragCtx.v0);
20269
- dragCtx.sign1 = sign || 1;
20274
+ dragCtx.sign1 = getBondFlipSign(this.struct, bond);
20270
20275
  dragCtx.sign2 = this.template.sign;
20271
20276
  }
20272
- case 14:
20277
+ case 15:
20273
20278
  case "end":
20274
20279
  return _context.stop();
20275
20280
  }
@@ -20284,10 +20289,31 @@ var TemplateTool = function () {
20284
20289
  }, {
20285
20290
  key: "mousemove",
20286
20291
  value: function mousemove(event) {
20292
+ var _this2 = this;
20287
20293
  if (!this.dragCtx) {
20288
- this.editor.hoverIcon.show();
20289
20294
  this.editor.hoverIcon.updatePosition();
20290
20295
  this.editor.hover(this.editor.findItem(event, this.findItems), null, event);
20296
+ var restruct = this.editor.render.ctab;
20297
+ var _ci = this.editor.findItem(event, ['atoms', 'bonds']);
20298
+ if (!_ci) {
20299
+ this.editor.hoverIcon.show();
20300
+ }
20301
+ var isMouseAwayFromAtomsAndBonds = !_ci;
20302
+ var isPreviewTargetChanged = _ci && this.lastPreviewId !== getUniqueCiId(_ci);
20303
+ var shouldHidePreview = isMouseAwayFromAtomsAndBonds || isPreviewTargetChanged;
20304
+ if (shouldHidePreview) {
20305
+ this.hidePreview();
20306
+ if (!this.editor.hoverIcon.isShown) {
20307
+ this.editor.hoverIcon.show();
20308
+ }
20309
+ }
20310
+ var shouldShowPreview = _ci && !this.isSaltOrSolvent && !this.isPreviewVisible && !this.previewTimeout;
20311
+ if (shouldShowPreview) {
20312
+ this.lastPreviewId = getUniqueCiId(_ci);
20313
+ this.previewTimeout = setTimeout(function () {
20314
+ _this2.showPreview(_ci, restruct);
20315
+ }, PREVIEW_DELAY);
20316
+ }
20291
20317
  return true;
20292
20318
  }
20293
20319
  if (this.isSaltOrSolvent) {
@@ -20336,11 +20362,11 @@ var TemplateTool = function () {
20336
20362
  if (!targetPos) {
20337
20363
  return true;
20338
20364
  }
20339
- var angle = utils.calcAngle(targetPos, eventPos);
20365
+ var angle = vectorUtils.calcAngle(targetPos, eventPos);
20340
20366
  if (!event.ctrlKey) {
20341
- angle = utils.fracAngle(angle, null);
20367
+ angle = vectorUtils.fracAngle(angle, null);
20342
20368
  }
20343
- var degrees = utils.degrees(angle);
20369
+ var degrees = vectorUtils.degrees(angle);
20344
20370
  this.editor.event.message.dispatch({
20345
20371
  info: degrees + 'º'
20346
20372
  });
@@ -20386,7 +20412,7 @@ var TemplateTool = function () {
20386
20412
  key: "mouseup",
20387
20413
  value: function mouseup(event) {
20388
20414
  var _this3 = this,
20389
- _ci;
20415
+ _ci2;
20390
20416
  var dragCtx = this.dragCtx;
20391
20417
  if (!dragCtx) {
20392
20418
  return true;
@@ -20409,7 +20435,7 @@ var TemplateTool = function () {
20409
20435
  }
20410
20436
  var action, functionalGroupRemoveAction;
20411
20437
  var pasteItems = null;
20412
- if (((_ci = ci) === null || _ci === void 0 ? void 0 : _ci.map) === 'functionalGroups' && FunctionalGroup.isContractedFunctionalGroup(ci.id, this.functionalGroups) && this.isModeFunctionalGroup && this.targetGroupsIds.length) {
20438
+ if (((_ci2 = ci) === null || _ci2 === void 0 ? void 0 : _ci2.map) === 'functionalGroups' && FunctionalGroup.isContractedFunctionalGroup(ci.id, this.functionalGroups) && this.isModeFunctionalGroup && this.targetGroupsIds.length) {
20413
20439
  var _restruct = this.editor.render.ctab;
20414
20440
  var functionalGroupToReplace = this.struct.sgroups.get(ci.id);
20415
20441
  if (this.isSaltOrSolvent && functionalGroupToReplace.isGroupAttached(this.struct)) {
@@ -20439,24 +20465,13 @@ var TemplateTool = function () {
20439
20465
  pasteItems = _fromTemplateOnCanvas4[1];
20440
20466
  dragCtx.action = action;
20441
20467
  } else if (ci.map === 'atoms') {
20442
- var _restruct$atoms$get;
20443
- var degree = (_restruct$atoms$get = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get === void 0 ? void 0 : _restruct$atoms$get.a.neighbors.length;
20468
+ var _restruct$atoms$get2;
20469
+ var degree = (_restruct$atoms$get2 = restruct.atoms.get(ci.id)) === null || _restruct$atoms$get2 === void 0 ? void 0 : _restruct$atoms$get2.a.neighbors.length;
20444
20470
  if (degree && degree >= 1 && this.isSaltOrSolvent) {
20445
20471
  addSaltsAndSolventsOnCanvasWithoutMerge(restruct, this.template, dragCtx, this.editor);
20446
20472
  return true;
20447
20473
  }
20448
- var angle;
20449
- if (degree && degree > 1) {
20450
- angle = null;
20451
- } else if (degree === 1) {
20452
- var _this$struct$halfBond3;
20453
- var atom = this.struct.atoms.get(ci.id);
20454
- 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);
20455
- var nei = (neiId || neiId === 0) && this.struct.atoms.get(neiId);
20456
- 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);
20457
- } else {
20458
- angle = 0;
20459
- }
20474
+ var angle = getAngleFromEvent(event, ci, restruct);
20460
20475
  var _fromTemplateOnAtom3 = fromTemplateOnAtom(restruct, this.template, ci.id, angle, false);
20461
20476
  var _fromTemplateOnAtom4 = _slicedToArray$1(_fromTemplateOnAtom3, 2);
20462
20477
  action = _fromTemplateOnAtom4[0];
@@ -20499,6 +20514,7 @@ var TemplateTool = function () {
20499
20514
  }, {
20500
20515
  key: "cancel",
20501
20516
  value: function cancel() {
20517
+ this.hidePreview();
20502
20518
  this.mouseup();
20503
20519
  }
20504
20520
  }, {
@@ -20506,6 +20522,59 @@ var TemplateTool = function () {
20506
20522
  value: function mouseleave(e) {
20507
20523
  this.mouseup(e);
20508
20524
  }
20525
+ }, {
20526
+ key: "hidePreview",
20527
+ value: function hidePreview() {
20528
+ if (this.isPreviewVisible && this.previewRemoveAction) {
20529
+ this.previewRemoveAction.perform(this.editor.render.ctab);
20530
+ this.previewRemoveAction = null;
20531
+ this.isPreviewVisible = false;
20532
+ this.editor.render.update();
20533
+ }
20534
+ if (this.previewTimeout) {
20535
+ clearTimeout(this.previewTimeout);
20536
+ this.previewTimeout = null;
20537
+ }
20538
+ }
20539
+ }, {
20540
+ key: "showPreview",
20541
+ value: function showPreview(ci, restruct) {
20542
+ var _this4 = this;
20543
+ if (ci.map === 'bonds' && !this.isModeFunctionalGroup) {
20544
+ this.isPreviewVisible = true;
20545
+ this.editor.hoverIcon.hide();
20546
+ var bond = this.struct.bonds.get(ci.id);
20547
+ var sign1 = getBondFlipSign(this.struct, bond);
20548
+ var sign2 = this.template.sign;
20549
+ var shouldFlip = sign1 * sign2 > 0;
20550
+ var promise = fromTemplateOnBondAction(restruct, this.template, ci.id, this.editor.event, shouldFlip, true, true);
20551
+ promise.then(function (_ref5) {
20552
+ var _ref6 = _slicedToArray$1(_ref5, 2),
20553
+ action = _ref6[0],
20554
+ pasteItems = _ref6[1];
20555
+ if (!_this4.isModeFunctionalGroup) {
20556
+ var mergeItems = getItemsToFuse(_this4.editor, pasteItems);
20557
+ action = fromItemsFuse(restruct, mergeItems).mergeWith(action);
20558
+ _this4.editor.update(action, true);
20559
+ _this4.previewRemoveAction = action;
20560
+ }
20561
+ });
20562
+ } else if (ci.map === 'atoms') {
20563
+ this.isPreviewVisible = true;
20564
+ this.editor.hoverIcon.hide();
20565
+ var angle = getAngleFromEvent(event, ci, restruct);
20566
+ var _fromTemplateOnAtom5 = fromTemplateOnAtom(restruct, this.template, ci.id, angle, false, true),
20567
+ _fromTemplateOnAtom6 = _slicedToArray$1(_fromTemplateOnAtom5, 2),
20568
+ action = _fromTemplateOnAtom6[0],
20569
+ pasteItems = _fromTemplateOnAtom6[1];
20570
+ if (pasteItems && !this.isModeFunctionalGroup) {
20571
+ var mergeItems = getItemsToFuse(this.editor, pasteItems);
20572
+ action = fromItemsFuse(restruct, mergeItems).mergeWith(action);
20573
+ }
20574
+ this.editor.update(action, true);
20575
+ this.previewRemoveAction = action;
20576
+ }
20577
+ }
20509
20578
  }]);
20510
20579
  return TemplateTool;
20511
20580
  }();
@@ -21486,7 +21555,7 @@ var RotateController = function () {
21486
21555
  this.snapAngleIndicator = this.paper.set();
21487
21556
  var LINE_LENGTH = 30;
21488
21557
  var TEXT_FONT_SIZE = 12;
21489
- var relativeSnapAngleInDegrees = utils.degrees(relativeSnapAngle);
21558
+ var relativeSnapAngleInDegrees = vectorUtils.degrees(relativeSnapAngle);
21490
21559
  var drawText = function drawText(textPosition) {
21491
21560
  return _this3.paper.text(textPosition.x, textPosition.y, "".concat(Math.abs(relativeSnapAngleInDegrees), "\xB0")).attr({
21492
21561
  'font-size': TEXT_FONT_SIZE
@@ -21502,7 +21571,7 @@ var RotateController = function () {
21502
21571
  switch (state) {
21503
21572
  case 'noLine':
21504
21573
  {
21505
- var textAngle = utils.normalizeAngle(absoluteSnapAngle - relativeSnapAngle / 2);
21574
+ var textAngle = normalizeAngle(absoluteSnapAngle - relativeSnapAngle / 2);
21506
21575
  var textPosition = new Vec2(20, 0).rotate(textAngle);
21507
21576
  var text = drawText(textPosition).attr({
21508
21577
  fill: STYLE.ACTIVE_COLOR
@@ -21687,7 +21756,7 @@ var Editor$3 = function () {
21687
21756
  key: "setOptions",
21688
21757
  value: function setOptions(opts) {
21689
21758
  var options = JSON.parse(opts);
21690
- this.event.apiSettings.dispatch(_objectSpread$L(_objectSpread$L({}, this.options()), options));
21759
+ this.event.apiSettings.dispatch(_objectSpread$L({}, options));
21691
21760
  return this.render.updateOptions(opts);
21692
21761
  }
21693
21762
  }, {
@@ -22075,7 +22144,10 @@ function domEventSetup(editor, clientArea) {
22075
22144
  toolEventHandler = _ref.toolEventHandler;
22076
22145
  editor.event[eventName] = new DOMSubscription();
22077
22146
  var subs = editor.event[eventName];
22078
- target.addEventListener(eventName, subs.dispatch.bind(subs));
22147
+ target.addEventListener(eventName, function () {
22148
+ if (window.isPolymerEditorTurnedOn) return;
22149
+ subs.dispatch.apply(subs, arguments);
22150
+ });
22079
22151
  subs.add(function (event) {
22080
22152
  updateLastCursorPosition(editor, event);
22081
22153
  if (['mouseup', 'mousedown', 'click', 'dbclick'].includes(event.type) && !isMouseMainButtonPressed(event)) {
@@ -24692,6 +24764,7 @@ var SaveButton$1 = function SaveButton(props) {
24692
24764
  _props$filename = props.filename,
24693
24765
  filename = _props$filename === void 0 ? 'unnamed' : _props$filename,
24694
24766
  outputFormat = props.outputFormat,
24767
+ bondThickness = props.bondThickness,
24695
24768
  data = props.data,
24696
24769
  type = props.type,
24697
24770
  _props$mode = props.mode,
@@ -24721,7 +24794,8 @@ var SaveButton$1 = function SaveButton(props) {
24721
24794
  var ketcherInstance = getKetcherInstance();
24722
24795
  if (outputFormat) {
24723
24796
  ketcherInstance.generateImage(data, {
24724
- outputFormat: outputFormat
24797
+ outputFormat: outputFormat,
24798
+ bondThickness: bondThickness || defaultBondThickness
24725
24799
  }).then(function (blob) {
24726
24800
  saveAs(blob, "".concat(filename, ".").concat(outputFormat));
24727
24801
  onSave();
@@ -25182,7 +25256,6 @@ var mapDispatchToProps$d = function mapDispatchToProps(dispatch, ownProps) {
25182
25256
  result: JSON.parse(newOpts)
25183
25257
  }));
25184
25258
  } catch (ex) {
25185
- console.info('Bad file');
25186
25259
  }
25187
25260
  },
25188
25261
  onReset: function onReset() {
@@ -25894,7 +25967,7 @@ var MiewDialog = function MiewDialog(_ref) {
25894
25967
  miew.setOptions(miewOpts);
25895
25968
  setIsIsInitialized(true);
25896
25969
  })["catch"](function (ex) {
25897
- return console.error(ex.message);
25970
+ return (void 0);
25898
25971
  });
25899
25972
  }, [miewOpts, server, struct]);
25900
25973
  var exportCML = useCallback(function () {
@@ -26636,16 +26709,13 @@ var Open = function Open(props) {
26636
26709
  }
26637
26710
  }, [server]);
26638
26711
  var onFileLoad = function onFileLoad(files) {
26639
- console.log('Open.tsx::onFileLoad::files', files);
26640
26712
  var onLoad = function onLoad(fileContent) {
26641
- console.log('Open.tsx::onLoad::fileContent', fileContent);
26642
26713
  setStructStr(fileContent);
26643
26714
  setCurrentState(MODAL_STATES.textEditor);
26644
26715
  };
26645
26716
  var onError = function onError() {
26646
26717
  return errorHandler('Error processing file');
26647
26718
  };
26648
- console.log('Open.tsx::onLoad::files[0].name', files[0].name);
26649
26719
  setFileName(files[0].name);
26650
26720
  opener.chosenOpener(files[0]).then(onLoad, onError);
26651
26721
  };
@@ -26655,14 +26725,12 @@ var Open = function Open(props) {
26655
26725
  };
26656
26726
  var onOk = rest.onOk;
26657
26727
  var copyHandler = function copyHandler() {
26658
- console.log('Open.tsx::copyHandler::structStr', structStr);
26659
26728
  onOk({
26660
26729
  structStr: structStr,
26661
26730
  fragment: true
26662
26731
  });
26663
26732
  };
26664
26733
  var openHandler = function openHandler() {
26665
- console.log('Open.tsx::openHandler::structStr', structStr);
26666
26734
  onOk({
26667
26735
  structStr: structStr,
26668
26736
  fragment: false
@@ -26721,7 +26789,6 @@ var mapDispatchToProps$7 = function mapDispatchToProps(dispatch) {
26721
26789
  return {
26722
26790
  onOk: function onOk(result) {
26723
26791
  if (result.fragment) exec('copy');
26724
- console.log('Open.container.ts::mapDispatchToProps::result', result);
26725
26792
  dispatch(load(result.structStr, {
26726
26793
  badHeaderRecover: true,
26727
26794
  fragment: result.fragment
@@ -26925,7 +26992,8 @@ var SaveDialog = function (_Component) {
26925
26992
  server = _this$props.server,
26926
26993
  options = _this$props.options,
26927
26994
  formState = _this$props.formState,
26928
- ignoreChiralFlag = _this$props.ignoreChiralFlag;
26995
+ ignoreChiralFlag = _this$props.ignoreChiralFlag,
26996
+ bondThickness = _this$props.bondThickness;
26929
26997
  var errorHandler = _this.context.errorHandler;
26930
26998
  if (_this.isImageFormat(type)) {
26931
26999
  var ketSerialize = new KetSerializer();
@@ -26939,6 +27007,7 @@ var SaveDialog = function (_Component) {
26939
27007
  });
26940
27008
  var _options = {};
26941
27009
  _options.outputFormat = type;
27010
+ _options.bondThickness = bondThickness;
26942
27011
  return server.generateImageAsBase64(structStr, _options).then(function (base64) {
26943
27012
  _this.setState({
26944
27013
  disableControls: false,
@@ -27128,7 +27197,9 @@ var SaveDialog = function (_Component) {
27128
27197
  imageFormat = _this$state2.imageFormat,
27129
27198
  isLoading = _this$state2.isLoading,
27130
27199
  structStr = _this$state2.structStr;
27131
- var formState = _this.props.formState;
27200
+ var _this$props3 = _this.props,
27201
+ formState = _this$props3.formState,
27202
+ bondThickness = _this$props3.bondThickness;
27132
27203
  var _formState$result2 = formState.result,
27133
27204
  filename = _formState$result2.filename,
27134
27205
  format = _formState$result2.format;
@@ -27158,6 +27229,7 @@ var SaveDialog = function (_Component) {
27158
27229
  data: structStr,
27159
27230
  filename: filename,
27160
27231
  outputFormat: imageFormat,
27232
+ bondThickness: bondThickness,
27161
27233
  type: "image/".concat(format, "+xml"),
27162
27234
  onSave: _this.props.onOk,
27163
27235
  disabled: disableControls || !formState.valid || isCleanStruct || !_this.props.server,
@@ -27243,6 +27315,7 @@ var mapStateToProps$4 = function mapStateToProps(state) {
27243
27315
  formState: state.modal.form,
27244
27316
  moleculeErrors: state.modal.form.moleculeErrors,
27245
27317
  checkState: state.options.check,
27318
+ bondThickness: state.options.settings.bondThickness,
27246
27319
  ignoreChiralFlag: state.editor.render.options.ignoreChiralFlag
27247
27320
  };
27248
27321
  };
@@ -30252,13 +30325,12 @@ function handleRightClick(getState) {
30252
30325
  }
30253
30326
  }
30254
30327
 
30255
- function initApp(element, staticResourcesUrl, options, server, setEditor) {
30328
+ function initApp(element, appRoot, staticResourcesUrl, options, server, setEditor) {
30256
30329
  var store = createStore(options, server, setEditor);
30257
30330
  store.dispatch(initKeydownListener(element));
30258
30331
  store.dispatch(initMouseListener(element));
30259
30332
  store.dispatch(initResize());
30260
- var root = createRoot(element);
30261
- root.render(jsx(Provider, {
30333
+ appRoot.render(jsx(Provider, {
30262
30334
  store: store,
30263
30335
  children: jsx(settingsContext.Provider, {
30264
30336
  value: {
@@ -30318,7 +30390,7 @@ var KetcherBuilder = function () {
30318
30390
  }, {
30319
30391
  key: "appendUiAsync",
30320
30392
  value: function () {
30321
- var _appendUiAsync = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2(element, staticResourcesUrl, errorHandler, buttons) {
30393
+ var _appendUiAsync = _asyncToGenerator( _regeneratorRuntime.mark(function _callee2(element, appRoot, staticResourcesUrl, errorHandler, buttons) {
30322
30394
  var structService, editor;
30323
30395
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
30324
30396
  while (1) {
@@ -30327,11 +30399,11 @@ var KetcherBuilder = function () {
30327
30399
  structService = this.structService;
30328
30400
  _context2.next = 3;
30329
30401
  return new Promise(function (resolve) {
30330
- initApp(element, staticResourcesUrl, {
30402
+ initApp(element, appRoot, staticResourcesUrl, {
30331
30403
  buttons: buttons || {},
30332
30404
  errorHandler: errorHandler || null,
30333
- version: "2.13.0-rc.3-dev.2" ,
30334
- buildDate: "2023-08-11T07:09:24" ,
30405
+ version: "2.14.0-rc.1" ,
30406
+ buildDate: "2023-08-15T11:24:53" ,
30335
30407
  buildNumber: ''
30336
30408
  }, structService, resolve);
30337
30409
  });
@@ -30348,7 +30420,7 @@ var KetcherBuilder = function () {
30348
30420
  }
30349
30421
  }, _callee2, this);
30350
30422
  }));
30351
- function appendUiAsync(_x2, _x3, _x4, _x5) {
30423
+ function appendUiAsync(_x2, _x3, _x4, _x5, _x6) {
30352
30424
  return _appendUiAsync.apply(this, arguments);
30353
30425
  }
30354
30426
  return appendUiAsync;
@@ -30383,19 +30455,19 @@ function buildKetcherAsync(_x) {
30383
30455
  }
30384
30456
  function _buildKetcherAsync() {
30385
30457
  _buildKetcherAsync = _asyncToGenerator( _regeneratorRuntime.mark(function _callee(_ref) {
30386
- var element, staticResourcesUrl, structServiceProvider, buttons, errorHandler, builder;
30458
+ var element, appRoot, staticResourcesUrl, structServiceProvider, buttons, errorHandler, builder;
30387
30459
  return _regeneratorRuntime.wrap(function _callee$(_context) {
30388
30460
  while (1) {
30389
30461
  switch (_context.prev = _context.next) {
30390
30462
  case 0:
30391
- element = _ref.element, staticResourcesUrl = _ref.staticResourcesUrl, structServiceProvider = _ref.structServiceProvider, buttons = _ref.buttons, errorHandler = _ref.errorHandler;
30463
+ element = _ref.element, appRoot = _ref.appRoot, staticResourcesUrl = _ref.staticResourcesUrl, structServiceProvider = _ref.structServiceProvider, buttons = _ref.buttons, errorHandler = _ref.errorHandler;
30392
30464
  builder = new KetcherBuilder();
30393
30465
  _context.next = 4;
30394
30466
  return builder.appendApiAsync(structServiceProvider);
30395
30467
  case 4:
30396
30468
  builder.appendServiceMode(structServiceProvider.mode);
30397
30469
  _context.next = 7;
30398
- return builder.appendUiAsync(element, staticResourcesUrl, errorHandler, buttons);
30470
+ return builder.appendUiAsync(element, appRoot, staticResourcesUrl, errorHandler, buttons);
30399
30471
  case 7:
30400
30472
  return _context.abrupt("return", builder.build());
30401
30473
  case 8:
@@ -30426,14 +30498,21 @@ function Editor(props) {
30426
30498
  width = _useResizeObserver.width;
30427
30499
  var ketcherInitEvent = new Event(KETCHER_INIT_EVENT_NAME);
30428
30500
  useEffect(function () {
30501
+ var appRoot = createRoot(rootElRef.current);
30429
30502
  buildKetcherAsync(_objectSpread(_objectSpread({}, props), {}, {
30430
- element: rootElRef.current
30503
+ element: rootElRef.current,
30504
+ appRoot: appRoot
30431
30505
  })).then(function (ketcher) {
30432
30506
  if (typeof onInit === 'function') {
30433
30507
  onInit(ketcher);
30434
30508
  window.dispatchEvent(ketcherInitEvent);
30435
30509
  }
30436
30510
  });
30511
+ return function () {
30512
+ setTimeout(function () {
30513
+ appRoot.unmount();
30514
+ });
30515
+ };
30437
30516
  }, []);
30438
30517
  return jsx("div", {
30439
30518
  ref: rootElRef,