ketcher-react 2.8.0-rc.2 → 2.8.0-rc.3

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.
@@ -43,7 +43,7 @@ import { connect, useDispatch, Provider } from 'react-redux';
43
43
  import { combineReducers, createStore as createStore$1, applyMiddleware } from 'redux';
44
44
  import 'redux-logger';
45
45
  import thunk from 'redux-thunk';
46
- import { throttle as throttle$1, inRange, difference, isEqual as isEqual$1, range as range$1 } from 'lodash';
46
+ import { throttle as throttle$1, inRange, difference, cloneDeep, isEqual as isEqual$1, range as range$1 } from 'lodash';
47
47
  import useResizeObserver from 'use-resize-observer/polyfilled';
48
48
  import { useInView } from 'react-intersection-observer';
49
49
  import styled from '@emotion/styled';
@@ -3008,7 +3008,7 @@ var zoom = {
3008
3008
 
3009
3009
  var openHelpLink = function openHelpLink() {
3010
3010
  var _window$open;
3011
- return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v2.8.0-rc.2\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3011
+ return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v2.8.0-rc.3\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3012
3012
  };
3013
3013
  var help = {
3014
3014
  help: {
@@ -10151,7 +10151,7 @@ var APointTool = function () {
10151
10151
  var closestItem = this.editor.findItem(event, ['atoms']);
10152
10152
  if (closestItem) {
10153
10153
  var atom = struct.atoms.get(closestItem.id);
10154
- if ((atom === null || atom === void 0 ? void 0 : atom.label) !== 'R#' && (atom === null || atom === void 0 ? void 0 : atom.rglabel) === null) this.editor.hover(closestItem);
10154
+ if ((atom === null || atom === void 0 ? void 0 : atom.label) !== 'R#' && (atom === null || atom === void 0 ? void 0 : atom.rglabel) === null) this.editor.hover(closestItem, null, event);
10155
10155
  } else {
10156
10156
  this.editor.hover(null);
10157
10157
  }
@@ -11694,7 +11694,7 @@ var SGroupTool = function () {
11694
11694
  if (this.lassoHelper.running(event)) {
11695
11695
  this.editor.selection(this.lassoHelper.addPoint(event));
11696
11696
  } else {
11697
- this.editor.hover(this.editor.findItem(event, searchMaps));
11697
+ this.editor.hover(this.editor.findItem(event, searchMaps), null, event);
11698
11698
  }
11699
11699
  }
11700
11700
  }, {
@@ -12018,6 +12018,68 @@ function countOfSelectedComponents(restruct, atoms) {
12018
12018
  }, 0);
12019
12019
  }
12020
12020
 
12021
+ function isAtomsArray(selectedElements) {
12022
+ return Array.isArray(selectedElements) && (selectedElements === null || selectedElements === void 0 ? void 0 : selectedElements.every(function (element) {
12023
+ return element instanceof Atom$2;
12024
+ }));
12025
+ }
12026
+ function generateCommonProperties(selectedElements) {
12027
+ var normalizedAtom = fromElement(selectedElements[0]);
12028
+ var properties = Object.getOwnPropertyNames(normalizedAtom);
12029
+ var resultAtomAttributes = {};
12030
+ properties.forEach(function (property) {
12031
+ var uniqueValues = new Set();
12032
+ selectedElements.forEach(function (element) {
12033
+ uniqueValues.add(element[property]);
12034
+ });
12035
+ var allAtomsHaveTheSameValue = uniqueValues.size === 1;
12036
+ if (allAtomsHaveTheSameValue) {
12037
+ resultAtomAttributes[property] = normalizedAtom[property];
12038
+ } else {
12039
+ resultAtomAttributes[property] = '';
12040
+ }
12041
+ });
12042
+ return resultAtomAttributes;
12043
+ }
12044
+ function updateOnlyChangedProperties(atomId, userChangedAtom, molecule) {
12045
+ var unchangedAtom = molecule.atoms.get(atomId);
12046
+ var updatedKeys = Object.getOwnPropertyNames(userChangedAtom).filter(function (key) {
12047
+ return userChangedAtom[key] !== '';
12048
+ });
12049
+ return Object.getOwnPropertyNames(unchangedAtom).reduce(function (updatedAtom, key) {
12050
+ var isPropertyChanged = updatedKeys.includes(key);
12051
+ if (isPropertyChanged) {
12052
+ updatedAtom[key] = userChangedAtom[key];
12053
+ if (key === 'charge') {
12054
+ updatedAtom[key] = Number(updatedAtom[key]);
12055
+ }
12056
+ } else {
12057
+ updatedAtom[key] = unchangedAtom[key];
12058
+ }
12059
+ return updatedAtom;
12060
+ }, {});
12061
+ }
12062
+ function updateSelectedAtoms(_ref) {
12063
+ var selection = _ref.selection,
12064
+ changeAtomPromise = _ref.changeAtomPromise,
12065
+ editor = _ref.editor;
12066
+ var action = new Action();
12067
+ var struct = editor.render.ctab;
12068
+ var molecule = struct.molecule;
12069
+ if (selection !== null && selection !== void 0 && selection.atoms) {
12070
+ var selectionAtoms = selection.atoms;
12071
+ Promise.resolve(changeAtomPromise).then(function (userChangedAtom) {
12072
+ selectionAtoms.forEach(function (atomId) {
12073
+ var atomWithChangedProperties = updateOnlyChangedProperties(atomId, userChangedAtom, molecule);
12074
+ action.mergeWith(fromAtomsAttrs(struct, atomId, atomWithChangedProperties, false));
12075
+ });
12076
+ editor.update(action);
12077
+ })["catch"](function () {
12078
+ return null;
12079
+ });
12080
+ }
12081
+ }
12082
+
12021
12083
  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; }
12022
12084
  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(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; }
12023
12085
  function _createForOfIteratorHelper$9(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray$9(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
@@ -12395,32 +12457,25 @@ var SelectTool = function () {
12395
12457
  if (!ci) return true;
12396
12458
  var selection = this.editor.selection();
12397
12459
  if (ci.map === 'atoms') {
12398
- var action = new Action();
12399
- var atom = molecule.atoms.get(ci.id);
12400
- var ra = editor.event.elementEdit.dispatch(atom);
12401
- if (selection !== null && selection !== void 0 && selection.atoms) {
12402
- var selectionAtoms = selection.atoms;
12403
- Promise.resolve(ra).then(function (newatom) {
12404
- selectionAtoms.forEach(function (aid) {
12405
- action.mergeWith(fromAtomsAttrs(struct, aid, newatom, false));
12406
- });
12407
- editor.update(action);
12408
- })["catch"](function () {
12409
- return null;
12410
- });
12411
- }
12460
+ var atoms = getSelectedAtoms(selection, molecule);
12461
+ var changeAtomPromise = editor.event.elementEdit.dispatch(atoms);
12462
+ updateSelectedAtoms({
12463
+ selection: selection,
12464
+ editor: editor,
12465
+ changeAtomPromise: changeAtomPromise
12466
+ });
12412
12467
  } else if (ci.map === 'bonds') {
12413
12468
  var _rnd$ctab$bonds$get;
12414
12469
  var bond = (_rnd$ctab$bonds$get = rnd.ctab.bonds.get(ci.id)) === null || _rnd$ctab$bonds$get === void 0 ? void 0 : _rnd$ctab$bonds$get.b;
12415
12470
  var rb = editor.event.bondEdit.dispatch(bond);
12416
12471
  if (selection !== null && selection !== void 0 && selection.bonds) {
12417
- var _action = new Action();
12472
+ var action = new Action();
12418
12473
  var bondsSelection = selection.bonds;
12419
12474
  Promise.resolve(rb).then(function (newbond) {
12420
12475
  bondsSelection.forEach(function (bid) {
12421
- _action.mergeWith(fromBondsAttrs(struct, bid, newbond));
12476
+ action.mergeWith(fromBondsAttrs(struct, bid, newbond));
12422
12477
  });
12423
- editor.update(_action);
12478
+ editor.update(action);
12424
12479
  })["catch"](function () {
12425
12480
  return null;
12426
12481
  });
@@ -12505,6 +12560,18 @@ function selMerge(selection, add, reversible) {
12505
12560
  function isSelected(selection, item) {
12506
12561
  return selection && selection[item.map] && selection[item.map].includes(item.id);
12507
12562
  }
12563
+ function getSelectedAtoms(selection, molecule) {
12564
+ if (selection !== null && selection !== void 0 && selection.atoms) {
12565
+ return mapAtomIdsToAtoms(selection === null || selection === void 0 ? void 0 : selection.atoms, molecule);
12566
+ }
12567
+ return [];
12568
+ }
12569
+ function mapAtomIdsToAtoms(atomsIds, molecule) {
12570
+ return atomsIds.map(function (atomId) {
12571
+ var atomOrReAtom = molecule.atoms.get(atomId);
12572
+ return atomOrReAtom.a || atomOrReAtom;
12573
+ });
12574
+ }
12508
12575
  function uniqArray(dest, add, reversible) {
12509
12576
  return add.reduce(function (_, item) {
12510
12577
  if (reversible) dest = xor(dest, [item]);else if (!dest.includes(item)) dest.push(item);
@@ -12553,7 +12620,7 @@ var EraserTool = function () {
12553
12620
  if (this.lassoHelper.running()) {
12554
12621
  this.editor.selection(this.lassoHelper.addPoint(event));
12555
12622
  } else {
12556
- this.editor.hover(this.editor.findItem(event, this.maps));
12623
+ this.editor.hover(this.editor.findItem(event, this.maps), null, event);
12557
12624
  }
12558
12625
  }
12559
12626
  }, {
@@ -12689,9 +12756,8 @@ var EraserTool = function () {
12689
12756
  value: function click(event) {
12690
12757
  var rnd = this.editor.render;
12691
12758
  var restruct = rnd.ctab;
12692
- var struct = this.editor.render.ctab;
12693
- var sgroups = struct.sgroups;
12694
- var molecule = struct.molecule;
12759
+ var sgroups = restruct.sgroups;
12760
+ var molecule = restruct.molecule;
12695
12761
  var functionalGroups = molecule.functionalGroups;
12696
12762
  var ci = this.editor.findItem(event, this.maps);
12697
12763
  var atomResult = [];
@@ -12703,16 +12769,16 @@ var EraserTool = function () {
12703
12769
  result.push(ci.id);
12704
12770
  }
12705
12771
  } else if (ci && functionalGroups && ci.map === 'atoms') {
12706
- var _struct$atoms$get2;
12772
+ var _restruct$atoms$get;
12707
12773
  var atomId = FunctionalGroup.atomsInFunctionalGroup(functionalGroups, ci.id);
12708
- var atomFromStruct = atomId !== null && ((_struct$atoms$get2 = struct.atoms.get(atomId)) === null || _struct$atoms$get2 === void 0 ? void 0 : _struct$atoms$get2.a);
12774
+ var atomFromStruct = atomId !== null && ((_restruct$atoms$get = restruct.atoms.get(atomId)) === null || _restruct$atoms$get === void 0 ? void 0 : _restruct$atoms$get.a);
12709
12775
  if (atomFromStruct && !FunctionalGroup.isAtomInContractedFunctionalGroup(atomFromStruct, sgroups, functionalGroups, true)) {
12710
12776
  atomResult.push(atomId);
12711
12777
  }
12712
12778
  } else if (ci && functionalGroups && ci.map === 'bonds') {
12713
- var _struct$bonds$get2;
12779
+ var _restruct$bonds$get;
12714
12780
  var bondId = FunctionalGroup.bondsInFunctionalGroup(molecule, functionalGroups, ci.id);
12715
- var bondFromStruct = bondId !== null && ((_struct$bonds$get2 = struct.bonds.get(bondId)) === null || _struct$bonds$get2 === void 0 ? void 0 : _struct$bonds$get2.b);
12781
+ var bondFromStruct = bondId !== null && ((_restruct$bonds$get = restruct.bonds.get(bondId)) === null || _restruct$bonds$get === void 0 ? void 0 : _restruct$bonds$get.b);
12716
12782
  if (bondFromStruct && !FunctionalGroup.isBondInContractedFunctionalGroup(bondFromStruct, sgroups, functionalGroups, true)) {
12717
12783
  bondResult.push(bondId);
12718
12784
  }
@@ -12840,7 +12906,10 @@ var HandTool = function () {
12840
12906
  this.editor.event.cursor.dispatch({
12841
12907
  status: 'move'
12842
12908
  });
12843
- if (this.begPos == null) return;
12909
+ this.editor.hover(this.editor.findItem(event, ['atoms', 'bonds'], null), null, event);
12910
+ if (this.begPos == null) {
12911
+ return;
12912
+ }
12844
12913
  var clientX = event.clientX,
12845
12914
  clientY = event.clientY;
12846
12915
  this.endPos = new Vec2(clientX, clientY);
@@ -13061,7 +13130,7 @@ var RGroupAtomTool = function () {
13061
13130
  var ci = this.editor.findItem(event, ['atoms']);
13062
13131
  if (ci) {
13063
13132
  var atom = struct.atoms.get(ci.id);
13064
- if ((atom === null || atom === void 0 ? void 0 : atom.attpnt) === null) this.editor.hover(ci);
13133
+ if ((atom === null || atom === void 0 ? void 0 : atom.attpnt) === null) this.editor.hover(ci, null, event);
13065
13134
  } else {
13066
13135
  this.editor.hover(null);
13067
13136
  }
@@ -13159,7 +13228,7 @@ var RGroupFragmentTool = function () {
13159
13228
  _createClass(RGroupFragmentTool, [{
13160
13229
  key: "mousemove",
13161
13230
  value: function mousemove(event) {
13162
- this.editor.hover(this.editor.findItem(event, ['frags', 'rgroups']));
13231
+ this.editor.hover(this.editor.findItem(event, ['frags', 'rgroups']), null, event);
13163
13232
  }
13164
13233
  }, {
13165
13234
  key: "click",
@@ -13426,7 +13495,7 @@ var ReactionMapTool = function () {
13426
13495
  this.updateLine((_atoms$get3 = atoms.get(this.dragCtx.item.id)) === null || _atoms$get3 === void 0 ? void 0 : _atoms$get3.pp, rnd.page2obj(event));
13427
13496
  }
13428
13497
  } else {
13429
- editor.hover(editor.findItem(event, ['atoms']));
13498
+ editor.hover(editor.findItem(event, ['atoms']), null, event);
13430
13499
  }
13431
13500
  }
13432
13501
  }, {
@@ -13524,7 +13593,7 @@ var ReactionPlusTool = function () {
13524
13593
  this.dragCtx.action = fromMultipleMove(rnd.ctab, this.editor.selection() || {}, rnd.page2obj(event).sub(this.dragCtx.xy0));
13525
13594
  editor.update(this.dragCtx.action, true);
13526
13595
  } else {
13527
- editor.hover(editor.findItem(event, ['rxnPluses']));
13596
+ editor.hover(editor.findItem(event, ['rxnPluses']), null, event);
13528
13597
  }
13529
13598
  }
13530
13599
  }, {
@@ -13564,7 +13633,7 @@ var ReactionUnmapTool = function () {
13564
13633
  var ci = this.editor.findItem(event, ['atoms']);
13565
13634
  if (ci && ci.map === 'atoms') {
13566
13635
  var _this$editor$render$c;
13567
- this.editor.hover((_this$editor$render$c = this.editor.render.ctab.molecule.atoms.get(ci.id)) !== null && _this$editor$render$c !== void 0 && _this$editor$render$c.aam ? ci : null);
13636
+ this.editor.hover((_this$editor$render$c = this.editor.render.ctab.molecule.atoms.get(ci.id)) !== null && _this$editor$render$c !== void 0 && _this$editor$render$c.aam ? ci : null, null, event);
13568
13637
  } else {
13569
13638
  this.editor.hover(null);
13570
13639
  }
@@ -13679,6 +13748,7 @@ var RotateTool = function () {
13679
13748
  key: "mousemove",
13680
13749
  value: function mousemove(event) {
13681
13750
  if (!this.dragCtx) {
13751
+ this.editor.hover(null, null, event);
13682
13752
  return true;
13683
13753
  }
13684
13754
  var rnd = this.editor.render;
@@ -13702,7 +13772,7 @@ var RotateTool = function () {
13702
13772
  });
13703
13773
  var expSel = this.editor.explicitSelected();
13704
13774
  dragCtx.mergeItems = getItemsToFuse(this.editor, expSel);
13705
- this.editor.hover(getHoverToFuse(dragCtx.mergeItems));
13775
+ this.editor.hover(getHoverToFuse(dragCtx.mergeItems), null, event);
13706
13776
  this.editor.update(dragCtx.action, true);
13707
13777
  return true;
13708
13778
  }
@@ -13800,7 +13870,7 @@ var SimpleObjectTool = function () {
13800
13870
  }
13801
13871
  } else {
13802
13872
  var items = this.editor.findItem(event, ['simpleObjects']);
13803
- this.editor.hover(items);
13873
+ this.editor.hover(items, null, event);
13804
13874
  }
13805
13875
  }
13806
13876
  }, {
@@ -13831,7 +13901,7 @@ var TemplateTool = function () {
13831
13901
  function TemplateTool(editor, tmpl) {
13832
13902
  _classCallCheck(this, TemplateTool);
13833
13903
  this.editor = editor;
13834
- this.mode = tmpl.mode;
13904
+ this.mode = getTemplateMode(tmpl);
13835
13905
  this.editor.selection(null);
13836
13906
  this.template = {
13837
13907
  aid: parseInt(tmpl.aid) || 0,
@@ -13846,6 +13916,7 @@ var TemplateTool = function () {
13846
13916
  this.template.molecule = frag;
13847
13917
  this.findItems = [];
13848
13918
  this.template.xy0 = xy0.scaled(1 / (frag.atoms.size || 1));
13919
+ this.findItems.push('functionalGroups');
13849
13920
  var atom = frag.atoms.get(this.template.aid);
13850
13921
  if (atom) {
13851
13922
  this.template.angle0 = utils.calcAngle(atom.pp, this.template.xy0);
@@ -13936,7 +14007,7 @@ var TemplateTool = function () {
13936
14007
  _iterator3.f();
13937
14008
  }
13938
14009
  }
13939
- if (result.length) {
14010
+ if (result.length && (this.mode !== 'fg' || SGroup.isSaltOrSolvent(this.template.molecule.name))) {
13940
14011
  this.editor.event.removeFG.dispatch({
13941
14012
  fgIds: result
13942
14013
  });
@@ -14042,6 +14113,9 @@ var TemplateTool = function () {
14042
14113
  extraBond = this.mode === 'fg' ? true : Vec2.dist(pos0, pos1) > 1;
14043
14114
  }
14044
14115
  }
14116
+ if (!pos0) {
14117
+ return true;
14118
+ }
14045
14119
  var angle = utils.calcAngle(pos0, pos1);
14046
14120
  if (!event.ctrlKey) {
14047
14121
  angle = utils.fracAngle(angle, null);
@@ -14086,8 +14160,10 @@ var TemplateTool = function () {
14086
14160
  }
14087
14161
  delete this.dragCtx;
14088
14162
  var restruct = this.editor.render.ctab;
14163
+ var sgroups = restruct.sgroups;
14089
14164
  var struct = restruct.molecule;
14090
14165
  var ci = dragCtx.item;
14166
+ var functionalGroups = struct.functionalGroups;
14091
14167
  if (dragCtx.action && ci && ci.map === 'bonds' && this.mode !== 'fg') {
14092
14168
  dragCtx.action.perform(restruct);
14093
14169
  var promise = fromTemplateOnBondAction(restruct, this.template, ci.id, this.editor.event, dragCtx.sign1 * dragCtx.sign2 > 0, true);
@@ -14103,12 +14179,20 @@ var TemplateTool = function () {
14103
14179
  }
14104
14180
  var action;
14105
14181
  var pasteItems = null;
14182
+ var isFunctionalGroupReplace = false;
14106
14183
  if (SGroup.isSaltOrSolvent(this.template.molecule.name)) {
14107
14184
  addSaltsAndSolventsOnCanvasWithoutMerge(restruct, this.template, dragCtx, this.editor);
14108
14185
  return true;
14186
+ } else if ((ci === null || ci === void 0 ? void 0 : ci.map) === 'functionalGroups' && FunctionalGroup.isContractedFunctionalGroup(ci.id, functionalGroups) && this.mode === 'fg') {
14187
+ var sGroup = sgroups.get(ci.id);
14188
+ this.editor.update(fromFragmentDeletion(this.editor.render.ctab, {
14189
+ atoms: _toConsumableArray(SGroup.getAtoms(struct, sGroup === null || sGroup === void 0 ? void 0 : sGroup.item)),
14190
+ bonds: _toConsumableArray(SGroup.getBonds(struct, sGroup === null || sGroup === void 0 ? void 0 : sGroup.item))
14191
+ }));
14192
+ isFunctionalGroupReplace = true;
14109
14193
  }
14110
14194
  if (!dragCtx.action) {
14111
- if (!ci) {
14195
+ if (!ci || isFunctionalGroupReplace) {
14112
14196
  var _fromTemplateOnCanvas = fromTemplateOnCanvas(restruct, this.template, dragCtx.xy0, 0);
14113
14197
  var _fromTemplateOnCanvas2 = _slicedToArray(_fromTemplateOnCanvas, 2);
14114
14198
  action = _fromTemplateOnCanvas2[0];
@@ -14158,14 +14242,15 @@ var TemplateTool = function () {
14158
14242
  dragCtx.mergeItems = getItemsToFuse(this.editor, pasteItems);
14159
14243
  }
14160
14244
  dragCtx.action = dragCtx.action ? fromItemsFuse(restruct, dragCtx.mergeItems).mergeWith(dragCtx.action) : fromItemsFuse(restruct, dragCtx.mergeItems);
14161
- this.editor.hover(null);
14162
14245
  var completeAction = dragCtx.action;
14163
14246
  if (completeAction && !completeAction.isDummy()) {
14164
14247
  this.editor.update(completeAction);
14165
14248
  }
14249
+ this.editor.event.showInfo.dispatch(null);
14166
14250
  this.editor.event.message.dispatch({
14167
14251
  info: false
14168
14252
  });
14253
+ this.editor.hover(this.editor.findItem(event, this.findItems), null, event);
14169
14254
  return true;
14170
14255
  }
14171
14256
  }, {
@@ -14192,6 +14277,12 @@ function addSaltsAndSolventsOnCanvasWithoutMerge(restruct, template, dragCtx, ed
14192
14277
  info: false
14193
14278
  });
14194
14279
  }
14280
+ function getTemplateMode(tmpl) {
14281
+ var _tmpl$props;
14282
+ if (tmpl.mode) return tmpl.mode;
14283
+ if (['Functional Groups', 'Salts and Solvents'].includes((_tmpl$props = tmpl.props) === null || _tmpl$props === void 0 ? void 0 : _tmpl$props.group)) return 'fg';
14284
+ return null;
14285
+ }
14195
14286
  function getSign(molecule, bond, v) {
14196
14287
  var begin = molecule.atoms.get(bond.begin).pp;
14197
14288
  var end = molecule.atoms.get(bond.end).pp;
@@ -14846,7 +14937,9 @@ var Dialog = function Dialog(props) {
14846
14937
  };
14847
14938
  var exit = function exit(mode) {
14848
14939
  var key = isButtonOk(mode) ? 'onOk' : 'onCancel';
14849
- if (params && key in params && (key !== 'onOk' || valid())) params[key](result());
14940
+ if (params && key in params && (key !== 'onOk' || valid())) {
14941
+ params[key](result());
14942
+ }
14850
14943
  };
14851
14944
  var keyDown = function keyDown(event) {
14852
14945
  var key = KN.keyName(event);
@@ -16327,42 +16420,27 @@ var AtomBatchEdit = function AtomBatchEdit(props) {
16327
16420
  getKetcherInstance = _useAppContext2.getKetcherInstance;
16328
16421
  var isDisabled = useDisabled$1();
16329
16422
  var handleClick = useCallback( _asyncToGenerator( _regeneratorRuntime.mark(function _callee() {
16330
- var editor, defaultAtom, _editor$selection2, newAtom, selectedAtomIds;
16423
+ var editor, molecule, selection, selectedAtoms, newAtom;
16331
16424
  return _regeneratorRuntime.wrap(function _callee$(_context) {
16332
16425
  while (1) {
16333
16426
  switch (_context.prev = _context.next) {
16334
16427
  case 0:
16335
16428
  editor = getKetcherInstance().editor;
16336
- defaultAtom = toElement({
16337
- label: 'C',
16338
- charge: 0,
16339
- isotope: 0,
16340
- explicitValence: -1,
16341
- radical: 0,
16342
- invRet: 0,
16343
- ringBondCount: 0,
16344
- substitutionCount: 0,
16345
- hCount: 0,
16346
- stereoParity: 0
16429
+ molecule = editor.render.ctab;
16430
+ selection = editor.selection();
16431
+ selectedAtoms = getSelectedAtoms(selection, molecule);
16432
+ newAtom = editor.event.elementEdit.dispatch(selectedAtoms);
16433
+ updateSelectedAtoms({
16434
+ selection: selection,
16435
+ changeAtomPromise: newAtom,
16436
+ editor: editor
16347
16437
  });
16348
- _context.prev = 2;
16349
- _context.next = 5;
16350
- return editor.event.elementEdit.dispatch(defaultAtom);
16351
- case 5:
16352
- newAtom = _context.sent;
16353
- selectedAtomIds = (_editor$selection2 = editor.selection()) === null || _editor$selection2 === void 0 ? void 0 : _editor$selection2.atoms;
16354
- editor.update(fromAtomsAttrs(editor.render.ctab, selectedAtomIds, newAtom, false));
16355
- _context.next = 13;
16356
- break;
16357
- case 10:
16358
- _context.prev = 10;
16359
- _context.t0 = _context["catch"](2);
16360
- case 13:
16438
+ case 6:
16361
16439
  case "end":
16362
16440
  return _context.stop();
16363
16441
  }
16364
16442
  }
16365
- }, _callee, null, [[2, 10]]);
16443
+ }, _callee);
16366
16444
  })), [getKetcherInstance]);
16367
16445
  return jsx(Item, _objectSpread$I(_objectSpread$I({}, props), {}, {
16368
16446
  hidden: isBatchOperationHidden,
@@ -16408,7 +16486,7 @@ var AtomStereoBatchEdit = function AtomStereoBatchEdit(props) {
16408
16486
  }, _callee2, null, [[3, 10]]);
16409
16487
  })), [getKetcherInstance]);
16410
16488
  var isStereoDisabled = useCallback(function (_ref4) {
16411
- var _editor$selection3;
16489
+ var _editor$selection2;
16412
16490
  var props = _ref4.props,
16413
16491
  triggerEvent = _ref4.triggerEvent;
16414
16492
  if (isDisabled({
@@ -16418,7 +16496,7 @@ var AtomStereoBatchEdit = function AtomStereoBatchEdit(props) {
16418
16496
  return true;
16419
16497
  }
16420
16498
  var editor = getKetcherInstance().editor;
16421
- var selectedAtomIds = (_editor$selection3 = editor.selection()) === null || _editor$selection3 === void 0 ? void 0 : _editor$selection3.atoms;
16499
+ var selectedAtomIds = (_editor$selection2 = editor.selection()) === null || _editor$selection2 === void 0 ? void 0 : _editor$selection2.atoms;
16422
16500
  var stereoAtomIds = findStereoAtoms(editor.struct(), selectedAtomIds);
16423
16501
  stereoAtomIdsRef.current = stereoAtomIds;
16424
16502
  if (Array.isArray(stereoAtomIds) && stereoAtomIds.length !== 0) {
@@ -16770,11 +16848,23 @@ var ContextMenu = function ContextMenu() {
16770
16848
  return jsxs(Menu, {
16771
16849
  id: CONTEXT_MENU_ID,
16772
16850
  animation: false,
16773
- className: styles$b.contextMenu,
16851
+ className: "".concat(CONTEXT_MENU_ID, " ").concat(styles$b.contextMenu),
16774
16852
  children: [jsx(BondSingleOperations, {}), jsx(AtomSingleOperations, {}), jsx(BondBatchEdit, {}), jsx(AtomBatchEdit, {}), jsx(BondTypeBatchChange, {}), jsx(AtomStereoBatchEdit, {}), jsx(BatchDelete, {})]
16775
16853
  });
16776
16854
  };
16777
16855
 
16856
+ var fixContextMenuPosition = function fixContextMenuPosition() {
16857
+ var contextMenu = document.querySelector(".".concat(CONTEXT_MENU_ID));
16858
+ if (contextMenu) {
16859
+ var computedStyles = getComputedStyle(contextMenu);
16860
+ var contextMenuHeight = parseInt(computedStyles.height);
16861
+ var currentTopPosition = parseInt(contextMenu.style.top);
16862
+ var screenSize = document.body.clientHeight;
16863
+ if (currentTopPosition + contextMenuHeight > screenSize) {
16864
+ contextMenu.style.top = screenSize - contextMenuHeight + 'px';
16865
+ }
16866
+ }
16867
+ };
16778
16868
  var ContextMenuTrigger = function ContextMenuTrigger(_ref) {
16779
16869
  var children = _ref.children;
16780
16870
  var _useAppContext = useAppContext(),
@@ -16845,6 +16935,7 @@ var ContextMenuTrigger = function ContextMenuTrigger(_ref) {
16845
16935
  }
16846
16936
  });
16847
16937
  }
16938
+ fixContextMenuPosition();
16848
16939
  }, [getKetcherInstance, hasConflictWithFunctionalGroupMenu, hideAll, show]);
16849
16940
  return jsx("div", {
16850
16941
  style: {
@@ -17490,7 +17581,7 @@ var _excluded$p = ["schema", "value", "onChange", "innerRef", "type", "isFocused
17490
17581
  _excluded3$1 = ["schema", "value", "onChange", "innerRef"],
17491
17582
  _excluded4$1 = ["schema", "value", "selected", "onSelect", "type", "checked"],
17492
17583
  _excluded5$1 = ["value", "onChange", "name"],
17493
- _excluded6 = ["Component"],
17584
+ _excluded6$1 = ["Component"],
17494
17585
  _excluded7 = ["children", "onChange"];
17495
17586
  function _createSuper$8(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$8(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
17496
17587
  function _isNativeReflectConstruct$8() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
@@ -17507,9 +17598,9 @@ function GenericInput(_ref) {
17507
17598
  _ref$isFocused = _ref.isFocused,
17508
17599
  isFocused = _ref$isFocused === void 0 ? false : _ref$isFocused,
17509
17600
  props = _objectWithoutProperties(_ref, _excluded$p);
17510
- var inputRef = useRef(null);
17601
+ var inputRef = useRef(innerRef);
17511
17602
  useEffect(function () {
17512
- if (innerRef !== null && innerRef !== void 0 && innerRef.current && inputRef.current) {
17603
+ if (innerRef && inputRef.current) {
17513
17604
  innerRef.current = inputRef.current;
17514
17605
  }
17515
17606
  }, [innerRef]);
@@ -17556,9 +17647,9 @@ function CheckBox(_ref3) {
17556
17647
  _ref3.schema;
17557
17648
  var _ref3$value = _ref3.value,
17558
17649
  value = _ref3$value === void 0 ? '' : _ref3$value,
17559
- onChange = _ref3.onChange;
17560
- _ref3.innerRef;
17561
- var rest = _objectWithoutProperties(_ref3, _excluded3$1);
17650
+ onChange = _ref3.onChange,
17651
+ innerRef = _ref3.innerRef,
17652
+ rest = _objectWithoutProperties(_ref3, _excluded3$1);
17562
17653
  return jsxs("div", {
17563
17654
  className: classes$A.fieldSetItem,
17564
17655
  children: [jsx("input", _objectSpread$A({
@@ -17566,7 +17657,8 @@ function CheckBox(_ref3) {
17566
17657
  checked: Boolean(value),
17567
17658
  onClick: onChange,
17568
17659
  onChange: onChange,
17569
- className: classes$A.input
17660
+ className: classes$A.input,
17661
+ ref: innerRef
17570
17662
  }, rest)), jsx("span", {
17571
17663
  className: classes$A.checkbox
17572
17664
  })]
@@ -17755,7 +17847,7 @@ function componentMap(props) {
17755
17847
  }
17756
17848
  var AnyComponentWithRef = React__default.forwardRef(function (_ref7, ref) {
17757
17849
  var Component = _ref7.Component,
17758
- props = _objectWithoutProperties(_ref7, _excluded6);
17850
+ props = _objectWithoutProperties(_ref7, _excluded6$1);
17759
17851
  return jsx(Component, _objectSpread$A(_objectSpread$A({}, props), {}, {
17760
17852
  innerRef: ref
17761
17853
  }));
@@ -17850,7 +17942,8 @@ var _excluded$o = ["schema", "result", "customValid"],
17850
17942
  _excluded2$3 = ["labelPos", "title", "children"],
17851
17943
  _excluded3 = ["name", "onChange", "component", "labelPos", "className"],
17852
17944
  _excluded4 = ["dataError"],
17853
- _excluded5 = ["title", "name", "schema"];
17945
+ _excluded5 = ["title", "name", "schema"],
17946
+ _excluded6 = ["pattern", "maxLength", "enum", "enumNames"];
17854
17947
  function ownKeys$z(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; }
17855
17948
  function _objectSpread$z(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$z(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$z(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
17856
17949
  function _createSuper$7(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct$7(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
@@ -18049,23 +18142,31 @@ function propSchema(schema, _ref2) {
18049
18142
  verbose: true,
18050
18143
  strictSchema: false
18051
18144
  });
18145
+ var schemaCopy = cloneDeep(schema);
18052
18146
  if (customValid) {
18053
- schema = Object.assign({}, schema);
18054
- schema.properties = Object.keys(customValid).reduce(function (res, prop) {
18055
- ajv.addFormat(customValid[prop].name, customValid[prop]);
18056
- res[prop] = _objectSpread$z({
18057
- format: prop
18058
- }, res[prop]);
18059
- return res;
18060
- }, schema.properties);
18147
+ Object.entries(customValid).forEach(function (_ref3) {
18148
+ var _ref4 = _slicedToArray(_ref3, 2),
18149
+ formatName = _ref4[0],
18150
+ formatValidator = _ref4[1];
18151
+ ajv.addFormat(formatName, formatValidator);
18152
+ var _schemaCopy$propertie = schemaCopy.properties[formatName];
18153
+ _schemaCopy$propertie.pattern;
18154
+ _schemaCopy$propertie.maxLength;
18155
+ _schemaCopy$propertie["enum"];
18156
+ _schemaCopy$propertie.enumNames;
18157
+ var rest = _objectWithoutProperties(_schemaCopy$propertie, _excluded6);
18158
+ schemaCopy.properties[formatName] = _objectSpread$z(_objectSpread$z({}, rest), {}, {
18159
+ format: formatName
18160
+ });
18161
+ });
18061
18162
  }
18062
- var validate = ajv.compile(schema);
18163
+ var validate = ajv.compile(schemaCopy);
18063
18164
  return {
18064
18165
  key: schema.key || '',
18065
18166
  serialize: function serialize(inst) {
18066
18167
  validate(inst);
18067
18168
  return {
18068
- instance: serializeRewrite(_serialize, inst, schema),
18169
+ instance: serializeRewrite(_serialize, inst, schemaCopy),
18069
18170
  valid: validate(inst),
18070
18171
  errors: validate.errors || []
18071
18172
  };
@@ -19645,14 +19746,16 @@ var ElementNumber = function ElementNumber(props) {
19645
19746
 
19646
19747
  var classes$r = {"button-common-styles":"Atom-module_button-common-styles__ipWaI","scrollbar":"Atom-module_scrollbar__z5cVx","atomProps":"Atom-module_atomProps__pqBjY","accordionWrapper":"Atom-module_accordionWrapper__MSuU7","expandIcon":"Atom-module_expandIcon__mPszC","turnedIcon":"Atom-module_turnedIcon__0Kzwy","accordionSummaryWrapper":"Atom-module_accordionSummaryWrapper__MGqsq","accordionSummary":"Atom-module_accordionSummary__HMKzl","accordionDetailsWrapper":"Atom-module_accordionDetailsWrapper__p6EI7","hiddenAccordion":"Atom-module_hiddenAccordion__pDNdM","accordionDetails":"Atom-module_accordionDetails__-B3jK","checkbox":"Atom-module_checkbox__Vup40","reactionFlags":"Atom-module_reactionFlags__gdNb1","querySpecific":"Atom-module_querySpecific__7XxMr"};
19647
19748
 
19648
- var _excluded$g = ["formState", "stereoParity"];
19749
+ var _excluded$g = ["formState", "stereoParity", "isMultipleAtoms"];
19649
19750
  function ownKeys$t(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; }
19650
19751
  function _objectSpread$t(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys$t(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys$t(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
19651
19752
  var atomProps = atom.properties;
19652
19753
  var Atom = function Atom(props) {
19653
19754
  var formState = props.formState;
19654
19755
  props.stereoParity;
19655
- var rest = _objectWithoutProperties(props, _excluded$g);
19756
+ var _props$isMultipleAtom = props.isMultipleAtoms,
19757
+ isMultipleAtoms = _props$isMultipleAtom === void 0 ? false : _props$isMultipleAtom,
19758
+ rest = _objectWithoutProperties(props, _excluded$g);
19656
19759
  var _useState = useState(rest.label),
19657
19760
  _useState2 = _slicedToArray(_useState, 2),
19658
19761
  currentLabel = _useState2[0],
@@ -19754,10 +19857,10 @@ var Atom = function Atom(props) {
19754
19857
  schema: atom,
19755
19858
  customValid: {
19756
19859
  label: function label(_label) {
19757
- return atomValid(_label);
19860
+ return atomValid(_label, isMultipleAtoms);
19758
19861
  },
19759
19862
  charge: function charge(_charge) {
19760
- return chargeValid(_charge);
19863
+ return chargeValid(_charge, isMultipleAtoms);
19761
19864
  }
19762
19865
  },
19763
19866
  init: rest
@@ -19795,13 +19898,21 @@ var Atom = function Atom(props) {
19795
19898
  }))
19796
19899
  });
19797
19900
  };
19798
- function atomValid(label) {
19799
- return label && !!Elements.get(capitalize(label));
19901
+ function atomValid(label, isMultipleAtoms) {
19902
+ var isChemicalElement = !!Elements.get(capitalize(label));
19903
+ if (isMultipleAtoms) {
19904
+ return label === '' || isChemicalElement;
19905
+ }
19906
+ return label && isChemicalElement;
19800
19907
  }
19801
- function chargeValid(charge) {
19908
+ function chargeValid(charge, isMultipleAtoms) {
19802
19909
  var regex = new RegExp(atom.properties.charge.pattern);
19803
19910
  var result = regex.exec(charge);
19804
- return result && (result[1] === '' || result[3] === '');
19911
+ var isValidCharge = result && (result[1] === '' || result[3] === '');
19912
+ if (isMultipleAtoms) {
19913
+ return charge === '0' || charge === 0 || charge === '' || isValidCharge;
19914
+ }
19915
+ return isValidCharge;
19805
19916
  }
19806
19917
 
19807
19918
  var mapStateToProps$9 = function mapStateToProps(state) {
@@ -23193,6 +23304,12 @@ function initEditor(dispatch, getState) {
23193
23304
  updateAction();
23194
23305
  },
23195
23306
  onElementEdit: function onElementEdit(selem) {
23307
+ if (isAtomsArray(selem)) {
23308
+ var atomAttributes = generateCommonProperties(selem);
23309
+ return openDialog(dispatch, 'atomProps', _objectSpread$1(_objectSpread$1({}, atomAttributes), {}, {
23310
+ isMultipleAtoms: true
23311
+ })).then(toElement);
23312
+ }
23196
23313
  var elem = selem.type === 'text' ? selem : fromElement(selem);
23197
23314
  var dlg = null;
23198
23315
  if (elem.type === 'text') {
@@ -23474,8 +23591,8 @@ var KetcherBuilder = function () {
23474
23591
  initApp(element, staticResourcesUrl, {
23475
23592
  buttons: buttons || {},
23476
23593
  errorHandler: errorHandler || null,
23477
- version: "2.8.0-rc.2" ,
23478
- buildDate: "2023-01-31T08:44:09" ,
23594
+ version: "2.8.0-rc.3" ,
23595
+ buildDate: "2023-02-15T12:49:59" ,
23479
23596
  buildNumber: ''
23480
23597
  }, structService, resolve);
23481
23598
  });