ketcher-react 3.9.0-rc.1 → 3.9.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -100,7 +100,9 @@ declare class Editor implements KetcherEditor {
100
100
  private potentialLeavingAtomsForAutoAssignment;
101
101
  private potentialLeavingAtomsForManualAssignment;
102
102
  get isMonomerCreationWizardEnabled(): boolean;
103
+ isMinimalViableStructure(): boolean;
103
104
  static isStructureContinuous(struct: Struct, selection?: Selection): boolean;
105
+ static isStructureImpure(struct: Struct): boolean;
104
106
  private originalStruct;
105
107
  private originalSelection;
106
108
  private selectedToOriginalAtomsIdMap;
@@ -62,7 +62,7 @@ declare const _default: {
62
62
  hidden: (options: any) => boolean;
63
63
  };
64
64
  'charge-plus': {
65
- shortcut: string;
65
+ shortcut: string[];
66
66
  title: string;
67
67
  action: {
68
68
  tool: string;
@@ -71,7 +71,7 @@ declare const _default: {
71
71
  hidden: (options: any) => boolean;
72
72
  };
73
73
  'charge-minus': {
74
- shortcut: string;
74
+ shortcut: string[];
75
75
  title: string;
76
76
  action: {
77
77
  tool: string;
@@ -13,7 +13,7 @@ export declare type WizardValues = {
13
13
  [key in StringWizardFormFieldId]: string;
14
14
  };
15
15
  export declare type WizardNotificationType = 'info' | 'error';
16
- export declare type WizardNotificationId = 'defaultAttachmentPoints' | 'emptyMandatoryFields' | 'invalidSymbol' | 'symbolExists' | 'editingIsNotAllowed' | 'noAttachmentPoints' | 'incorrectAttachmentPointsOrder' | 'creationSuccessful' | 'incontinuousStructure';
16
+ export declare type WizardNotificationId = 'defaultAttachmentPoints' | 'emptyMandatoryFields' | 'invalidSymbol' | 'symbolExists' | 'editingIsNotAllowed' | 'noAttachmentPoints' | 'incorrectAttachmentPointsOrder' | 'creationSuccessful' | 'incontinuousStructure' | 'notMinimalViableStructure' | 'impureStructure';
17
17
  export declare type WizardNotificationTypeMap = Record<WizardNotificationId, WizardNotificationType>;
18
18
  export declare type WizardNotificationMessageMap = Record<WizardNotificationId, string>;
19
19
  export declare type WizardNotification = {
package/dist/index.js CHANGED
@@ -42,7 +42,6 @@ import _, { isNumber, throttle as throttle$1, debounce as debounce$1, intersecti
42
42
  import _taggedTemplateLiteral from '@babel/runtime/helpers/taggedTemplateLiteral';
43
43
  import styled from '@emotion/styled';
44
44
  import { css } from '@emotion/react';
45
- import * as KN from 'w3c-keyname';
46
45
  import require$$0$3 from 'util';
47
46
  import ReactDOM, { createPortal } from 'react-dom';
48
47
  import { connect, useDispatch, useSelector, Provider } from 'react-redux';
@@ -2791,7 +2790,7 @@ var toolActions = (_toolActions = {
2791
2790
  }
2792
2791
  },
2793
2792
  'charge-plus': {
2794
- shortcut: '+',
2793
+ shortcut: ['Equal', 'Shift+Equal', 'NumpadAdd'],
2795
2794
  title: 'Charge Plus',
2796
2795
  action: {
2797
2796
  tool: 'charge',
@@ -2802,7 +2801,7 @@ var toolActions = (_toolActions = {
2802
2801
  }
2803
2802
  },
2804
2803
  'charge-minus': {
2805
- shortcut: '-',
2804
+ shortcut: ['Minus', 'NumpadSubtract'],
2806
2805
  title: 'Charge Minus',
2807
2806
  action: {
2808
2807
  tool: 'charge',
@@ -3839,7 +3838,7 @@ var zoom = {
3839
3838
  }
3840
3839
  },
3841
3840
  'zoom-out': {
3842
- shortcut: ['Ctrl+_', 'Ctrl+-'],
3841
+ shortcut: ['Mod+Minus', 'Mod+NumpadSubtract'],
3843
3842
  title: 'Zoom Out',
3844
3843
  enabledInViewOnly: true,
3845
3844
  disabled: function disabled(editor) {
@@ -3861,7 +3860,7 @@ var zoom = {
3861
3860
  }
3862
3861
  },
3863
3862
  'zoom-in': {
3864
- shortcut: ['Ctrl+=', 'Ctrl++'],
3863
+ shortcut: ['Mod+Equal', 'Mod+NumpadAdd'],
3865
3864
  title: 'Zoom In',
3866
3865
  enabledInViewOnly: true,
3867
3866
  disabled: function disabled(editor) {
@@ -3892,7 +3891,7 @@ var zoom = {
3892
3891
 
3893
3892
  var openHelpLink = function openHelpLink() {
3894
3893
  var _window$open;
3895
- return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v3.9.0-rc.1\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3894
+ return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v3.9.0-rc.2\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3896
3895
  };
3897
3896
  var help = {
3898
3897
  help: {
@@ -8853,7 +8852,7 @@ var Dialog = function Dialog(props) {
8853
8852
  }
8854
8853
  };
8855
8854
  var keyDown = function keyDown(event) {
8856
- var key = KN.keyName(event);
8855
+ var key = event.key;
8857
8856
  var active = document.activeElement;
8858
8857
  var activeTextarea = active && active.tagName === 'TEXTAREA';
8859
8858
  if (key === 'Escape' || key === 'Enter' && !activeTextarea) {
@@ -20353,8 +20352,8 @@ function keyHandle(dispatch, getState, hotKeys, event) {
20353
20352
  var hoveredItem = getHoveredItem(render.ctab);
20354
20353
  if (key && key.length === 1 && !hoveredItem) {
20355
20354
  var currentlyPressedKeys = selectAbbreviationLookupValue(state);
20356
- var isShortcutKey = shortcutKeys.includes(key === null || key === void 0 ? void 0 : key.toLowerCase());
20357
- var isTheSameKey = key === currentlyPressedKeys;
20355
+ var isShortcutKey = shortcutKeys.includes(key.toLowerCase());
20356
+ var isTheSameKey = key.toLowerCase() === currentlyPressedKeys;
20358
20357
  var isAbbreviationLookupShown = (!isTheSameKey || !isShortcutKey) && currentlyPressedKeys;
20359
20358
  if (isAbbreviationLookupShown) {
20360
20359
  dispatch(showAbbreviationLookup(event.key));
@@ -20372,7 +20371,7 @@ function keyHandle(dispatch, getState, hotKeys, event) {
20372
20371
  dispatch(initAbbreviationLookup(event.key));
20373
20372
  }
20374
20373
  }
20375
- if (key && key.length === 1 && key.match('/')) {
20374
+ if (key === 'Slash') {
20376
20375
  var hotkeyDialogTypes = {
20377
20376
  atoms: configWithNonViewOnlyActionsDisabled['atom-props'].action,
20378
20377
  bonds: configWithNonViewOnlyActionsDisabled['bond-props'].action
@@ -25578,11 +25577,35 @@ var Editor$3 = function () {
25578
25577
  }
25579
25578
  return false;
25580
25579
  }
25580
+ }, {
25581
+ key: "isMinimalViableStructure",
25582
+ value: function isMinimalViableStructure() {
25583
+ var _this = this;
25584
+ var nonLeavingAtoms = this.struct().atoms.filter(function (atomId) {
25585
+ assert_1(_this.monomerCreationState);
25586
+ return Array.from(_this.monomerCreationState.assignedAttachmentPoints.values()).every(function (atomPair) {
25587
+ return atomPair[1] !== atomId;
25588
+ });
25589
+ });
25590
+ if (nonLeavingAtoms.size < 2) {
25591
+ return false;
25592
+ }
25593
+ var nonLeavingAtomBonds = this.struct().bonds.filter(function (_, bond) {
25594
+ return nonLeavingAtoms.has(bond.begin) && nonLeavingAtoms.has(bond.end);
25595
+ });
25596
+ if (nonLeavingAtomBonds.size < 1) {
25597
+ return false;
25598
+ }
25599
+ var simpleSingleBonds = nonLeavingAtomBonds.filter(function (_, bond) {
25600
+ return bond.type === Bond$2.PATTERN.TYPE.SINGLE && bond.stereo === Bond$2.PATTERN.STEREO.NONE;
25601
+ });
25602
+ return simpleSingleBonds.size >= 1;
25603
+ }
25581
25604
  }, {
25582
25605
  key: "openMonomerCreationWizard",
25583
25606
  value: function openMonomerCreationWizard() {
25584
25607
  var _selection$atoms2,
25585
- _this = this;
25608
+ _this2 = this;
25586
25609
  var currentStruct = this.render.ctab.molecule;
25587
25610
  var selection = this.selection();
25588
25611
  assert_1(selection);
@@ -25594,7 +25617,7 @@ var Editor$3 = function () {
25594
25617
  return a - b;
25595
25618
  }).forEach(function (atomId, i) {
25596
25619
  originalToSelectedAtomsIdMap.set(atomId, i);
25597
- _this.selectedToOriginalAtomsIdMap.set(i, atomId);
25620
+ _this2.selectedToOriginalAtomsIdMap.set(i, atomId);
25598
25621
  });
25599
25622
  var assignedAttachmentPoints = new Map();
25600
25623
  var sideTerminalSGroupAtoms = this.terminalRGroupAtoms.filter(function (_ref) {
@@ -25663,10 +25686,10 @@ var Editor$3 = function () {
25663
25686
  pp: leavingAtom.pp
25664
25687
  });
25665
25688
  var selectedStructLeavingAtomId = selectedStruct.atoms.add(selectedStructLeavingAtom);
25666
- _this.selectedToOriginalAtomsIdMap.set(selectedStructLeavingAtomId, atomId);
25689
+ _this2.selectedToOriginalAtomsIdMap.set(selectedStructLeavingAtomId, atomId);
25667
25690
  var selectedStructAttachmentAtomId = originalToSelectedAtomsIdMap.get(attachmentAtomId);
25668
25691
  assert_1(selectedStructAttachmentAtomId !== undefined);
25669
- _this.selectedToOriginalAtomsIdMap.set(selectedStructAttachmentAtomId, attachmentAtomId);
25692
+ _this2.selectedToOriginalAtomsIdMap.set(selectedStructAttachmentAtomId, attachmentAtomId);
25670
25693
  var newBond = new Bond$2({
25671
25694
  type: Bond$2.PATTERN.TYPE.SINGLE,
25672
25695
  begin: selectedStructAttachmentAtomId,
@@ -25760,7 +25783,7 @@ var Editor$3 = function () {
25760
25783
  }, {
25761
25784
  key: "assignConnectionPointAtom",
25762
25785
  value: function assignConnectionPointAtom(atomId) {
25763
- var _this2 = this;
25786
+ var _this3 = this;
25764
25787
  assert_1(this.monomerCreationState);
25765
25788
  var potentialLeavingAtoms = this.monomerCreationState.potentialAttachmentPoints.get(atomId);
25766
25789
  var leavingAtomId;
@@ -25769,7 +25792,7 @@ var Editor$3 = function () {
25769
25792
  return a - b;
25770
25793
  }).reduce(function (acc, currentAtomId) {
25771
25794
  var _Elements$get;
25772
- var atom = _this2.struct().atoms.get(currentAtomId);
25795
+ var atom = _this3.struct().atoms.get(currentAtomId);
25773
25796
  assert_1(atom);
25774
25797
  var atomicNumber = (_Elements$get = Elements.get(atom.label)) === null || _Elements$get === void 0 ? void 0 : _Elements$get.number;
25775
25798
  if (atomicNumber !== undefined) {
@@ -25825,14 +25848,16 @@ var Editor$3 = function () {
25825
25848
  assert_1(isNumber(originalLeavingAtomId));
25826
25849
  var originalLeavingAtom = this.originalStruct.atoms.get(originalLeavingAtomId);
25827
25850
  assert_1(originalLeavingAtom);
25828
- originalLeavingAtom.rglabel = null;
25829
- originalLeavingAtom.label = leavingAtom.label;
25830
- this.originalStruct.calcImplicitHydrogen(originalLeavingAtomId);
25851
+ if (originalLeavingAtom.rglabel !== null) {
25852
+ originalLeavingAtom.rglabel = null;
25853
+ originalLeavingAtom.label = leavingAtom.label;
25854
+ this.originalStruct.calcImplicitHydrogen(originalLeavingAtomId);
25855
+ }
25831
25856
  }
25832
25857
  }, {
25833
25858
  key: "saveNewMonomer",
25834
25859
  value: function saveNewMonomer(data) {
25835
- var _this3 = this,
25860
+ var _this4 = this,
25836
25861
  _this$originalSelecti;
25837
25862
  if (!this.monomerCreationState) {
25838
25863
  throw new Error('Monomer creation wizard is not active, cannot save new monomer');
@@ -25889,25 +25914,25 @@ var Editor$3 = function () {
25889
25914
  this.monomerCreationState.assignedAttachmentPoints.forEach(function (_ref11) {
25890
25915
  var _ref12 = _slicedToArray$1(_ref11, 2),
25891
25916
  leavingAtomId = _ref12[1];
25892
- return _this3.cleanupAttachmentPoint(leavingAtomId);
25917
+ return _this4.cleanupAttachmentPoint(leavingAtomId);
25893
25918
  });
25894
25919
  this.monomerCreationState.potentialAttachmentPoints.forEach(function (leavingAtomIds) {
25895
25920
  return Array.from(leavingAtomIds.values()).forEach(function (leavingAtomId) {
25896
- return _this3.cleanupAttachmentPoint(leavingAtomId);
25921
+ return _this4.cleanupAttachmentPoint(leavingAtomId);
25897
25922
  });
25898
25923
  });
25899
25924
  this.closeMonomerCreationWizard();
25900
25925
  (_this$originalSelecti = this.originalSelection.atoms) === null || _this$originalSelecti === void 0 || _this$originalSelecti.forEach(function (atomId) {
25901
- var atom = _this3.render.ctab.molecule.atoms.get(atomId);
25926
+ var atom = _this4.render.ctab.molecule.atoms.get(atomId);
25902
25927
  if (atom) {
25903
25928
  atom.fragment = -1;
25904
25929
  }
25905
25930
  });
25906
25931
  var sGroupAttachmentPoints = MacromoleculesConverter.convertMonomerAttachmentPointsToSGroupAttachmentPoints(monomer, this.selectedToOriginalAtomsIdMap);
25907
25932
  sGroupAttachmentPoints.forEach(function (ap) {
25908
- _this3.render.ctab.molecule.bonds.forEach(function (bond) {
25909
- var _this3$originalSelect, _this3$originalSelect2;
25910
- if ((bond.begin === ap.atomId || bond.end === ap.atomId) && (!((_this3$originalSelect = _this3.originalSelection.atoms) !== null && _this3$originalSelect !== void 0 && _this3$originalSelect.includes(bond.begin)) || !((_this3$originalSelect2 = _this3.originalSelection.atoms) !== null && _this3$originalSelect2 !== void 0 && _this3$originalSelect2.includes(bond.end)))) {
25933
+ _this4.render.ctab.molecule.bonds.forEach(function (bond) {
25934
+ var _this4$originalSelect, _this4$originalSelect2;
25935
+ if ((bond.begin === ap.atomId || bond.end === ap.atomId) && (!((_this4$originalSelect = _this4.originalSelection.atoms) !== null && _this4$originalSelect !== void 0 && _this4$originalSelect.includes(bond.begin)) || !((_this4$originalSelect2 = _this4.originalSelection.atoms) !== null && _this4$originalSelect2 !== void 0 && _this4$originalSelect2.includes(bond.end)))) {
25911
25936
  bond.beginSuperatomAttachmentPointNumber = ap.attachmentPointNumber;
25912
25937
  }
25913
25938
  });
@@ -25976,6 +26001,7 @@ var Editor$3 = function () {
25976
26001
  }, {
25977
26002
  key: "removeAttachmentPoint",
25978
26003
  value: function removeAttachmentPoint(name) {
26004
+ var _this5 = this;
25979
26005
  assert_1(this.monomerCreationState);
25980
26006
  var atomPair = this.monomerCreationState.assignedAttachmentPoints.get(name);
25981
26007
  assert_1(atomPair);
@@ -25992,8 +26018,18 @@ var Editor$3 = function () {
25992
26018
  var action = fromOneBondDeletion(this.render.ctab, preservedBondId).mergeWith(fromOneAtomDeletion(this.render.ctab, preservedLeavingAtomId));
25993
26019
  this.update(action, true);
25994
26020
  }
26021
+ this.preservedConnectionPointData["delete"](attachmentAtomId);
26022
+ } else {
26023
+ var leavingAtoms = this.findPotentialLeavingAtoms(attachmentAtomId);
26024
+ var leavingAtomIdsSet = new Set();
26025
+ leavingAtoms.forEach(function (atom) {
26026
+ var atomId = _this5.struct().atoms.keyOf(atom);
26027
+ if (atomId !== null) {
26028
+ leavingAtomIdsSet.add(atomId);
26029
+ }
26030
+ });
26031
+ this.monomerCreationState.potentialAttachmentPoints.set(attachmentAtomId, leavingAtomIdsSet);
25995
26032
  }
25996
- this.preservedConnectionPointData["delete"](attachmentAtomId);
25997
26033
  this.monomerCreationState.assignedAttachmentPoints["delete"](name);
25998
26034
  this.monomerCreationState = Object.assign({}, this.monomerCreationState);
25999
26035
  this.render.update(true);
@@ -26042,7 +26078,7 @@ var Editor$3 = function () {
26042
26078
  }, {
26043
26079
  key: "findPotentialLeavingAtoms",
26044
26080
  value: function findPotentialLeavingAtoms(attachmentAtomId) {
26045
- var _this4 = this;
26081
+ var _this6 = this;
26046
26082
  var bondsToOutside = this.struct().bonds.filter(function (_, bond) {
26047
26083
  return attachmentAtomId === bond.begin && attachmentAtomId !== bond.end || attachmentAtomId === bond.end && attachmentAtomId !== bond.begin;
26048
26084
  });
@@ -26052,7 +26088,7 @@ var Editor$3 = function () {
26052
26088
  return;
26053
26089
  }
26054
26090
  var atomIdToUse = attachmentAtomId === bond.begin ? bond.end : bond.begin;
26055
- var atom = _this4.struct().atoms.get(atomIdToUse);
26091
+ var atom = _this6.struct().atoms.get(atomIdToUse);
26056
26092
  assert_1(atom);
26057
26093
  if (atom.neighbors.length === 1) {
26058
26094
  potentialLeavingAtoms.push(atom);
@@ -26063,15 +26099,15 @@ var Editor$3 = function () {
26063
26099
  }, {
26064
26100
  key: "subscribeToChangeEventInMonomerCreationWizard",
26065
26101
  value: function subscribeToChangeEventInMonomerCreationWizard() {
26066
- var _this5 = this;
26102
+ var _this7 = this;
26067
26103
  if (this.changeEventSubscriber) {
26068
26104
  return;
26069
26105
  }
26070
26106
  var handleChangeEvent = function handleChangeEvent(data) {
26071
- if (!_this5.isMonomerCreationWizardActive || data.length === 0) {
26107
+ if (!_this7.isMonomerCreationWizardActive || data.length === 0) {
26072
26108
  return;
26073
26109
  }
26074
- _this5.collectChangesForMonomerCreationStateInvalidation(data);
26110
+ _this7.collectChangesForMonomerCreationStateInvalidation(data);
26075
26111
  };
26076
26112
  this.changeEventSubscriber = this.subscribe('change', handleChangeEvent);
26077
26113
  }
@@ -26114,7 +26150,7 @@ var Editor$3 = function () {
26114
26150
  }, {
26115
26151
  key: "invalidateMonomerCreationWizardState",
26116
26152
  value: function invalidateMonomerCreationWizardState(changesMap) {
26117
- var _this6 = this;
26153
+ var _this8 = this;
26118
26154
  if (!this.monomerCreationState) {
26119
26155
  return;
26120
26156
  }
@@ -26128,7 +26164,7 @@ var Editor$3 = function () {
26128
26164
  switch (operation) {
26129
26165
  case OperationType.ATOM_DELETE:
26130
26166
  {
26131
- var attachmentPointsToInvalidate = Array.from(_this6.monomerCreationState.assignedAttachmentPoints.entries()).filter(function (_ref13) {
26167
+ var attachmentPointsToInvalidate = Array.from(_this8.monomerCreationState.assignedAttachmentPoints.entries()).filter(function (_ref13) {
26132
26168
  var _ref14 = _slicedToArray$1(_ref13, 2),
26133
26169
  atomPair = _ref14[1];
26134
26170
  return ids.has(atomPair[0]) || ids.has(atomPair[1]);
@@ -26144,18 +26180,39 @@ var Editor$3 = function () {
26144
26180
  attachmentAtomId = _atomPair4[0],
26145
26181
  leavingAtomId = _atomPair4[1];
26146
26182
  if (ids.has(attachmentAtomId)) {
26147
- var _this6$monomerCreatio;
26148
- (_this6$monomerCreatio = _this6.monomerCreationState) === null || _this6$monomerCreatio === void 0 || _this6$monomerCreatio.assignedAttachmentPoints["delete"](attachmentPointName);
26183
+ var _this8$monomerCreatio;
26184
+ (_this8$monomerCreatio = _this8.monomerCreationState) === null || _this8$monomerCreatio === void 0 || _this8$monomerCreatio.assignedAttachmentPoints["delete"](attachmentPointName);
26149
26185
  } else if (ids.has(leavingAtomId)) {
26150
- var potentialLeavingAtoms = _this6.findPotentialLeavingAtoms(attachmentAtomId);
26186
+ var potentialLeavingAtoms = _this8.findPotentialLeavingAtoms(attachmentAtomId);
26151
26187
  if (potentialLeavingAtoms.length === 0) {
26152
- var _this6$monomerCreatio2;
26153
- (_this6$monomerCreatio2 = _this6.monomerCreationState) === null || _this6$monomerCreatio2 === void 0 || _this6$monomerCreatio2.assignedAttachmentPoints["delete"](attachmentPointName);
26188
+ var _this8$monomerCreatio2;
26189
+ (_this8$monomerCreatio2 = _this8.monomerCreationState) === null || _this8$monomerCreatio2 === void 0 || _this8$monomerCreatio2.assignedAttachmentPoints["delete"](attachmentPointName);
26154
26190
  } else {
26155
- var _this6$monomerCreatio3;
26156
- var newLeavingAtomId = _this6.struct().atoms.keyOf(potentialLeavingAtoms[0]);
26191
+ var _this8$monomerCreatio3;
26192
+ var newLeavingAtomId = _this8.struct().atoms.keyOf(potentialLeavingAtoms[0]);
26157
26193
  assert_1(newLeavingAtomId !== null);
26158
- (_this6$monomerCreatio3 = _this6.monomerCreationState) === null || _this6$monomerCreatio3 === void 0 || _this6$monomerCreatio3.assignedAttachmentPoints.set(attachmentPointName, [attachmentAtomId, newLeavingAtomId]);
26194
+ (_this8$monomerCreatio3 = _this8.monomerCreationState) === null || _this8$monomerCreatio3 === void 0 || _this8$monomerCreatio3.assignedAttachmentPoints.set(attachmentPointName, [attachmentAtomId, newLeavingAtomId]);
26195
+ }
26196
+ }
26197
+ });
26198
+ var potentialAttachmentPointsToInvalidate = Array.from(_this8.monomerCreationState.potentialAttachmentPoints.entries());
26199
+ potentialAttachmentPointsToInvalidate.forEach(function (_ref17) {
26200
+ var _ref18 = _slicedToArray$1(_ref17, 2),
26201
+ attachmentAtomId = _ref18[0],
26202
+ leavingAtomIds = _ref18[1];
26203
+ if (ids.has(attachmentAtomId)) {
26204
+ var _this8$monomerCreatio4;
26205
+ (_this8$monomerCreatio4 = _this8.monomerCreationState) === null || _this8$monomerCreatio4 === void 0 || _this8$monomerCreatio4.potentialAttachmentPoints["delete"](attachmentAtomId);
26206
+ } else {
26207
+ var updatedLeavingAtomIds = new Set(Array.from(leavingAtomIds).filter(function (id) {
26208
+ return !ids.has(id);
26209
+ }));
26210
+ if (updatedLeavingAtomIds.size === 0) {
26211
+ var _this8$monomerCreatio5;
26212
+ (_this8$monomerCreatio5 = _this8.monomerCreationState) === null || _this8$monomerCreatio5 === void 0 || _this8$monomerCreatio5.potentialAttachmentPoints["delete"](attachmentAtomId);
26213
+ } else {
26214
+ var _this8$monomerCreatio6;
26215
+ (_this8$monomerCreatio6 = _this8.monomerCreationState) === null || _this8$monomerCreatio6 === void 0 || _this8$monomerCreatio6.potentialAttachmentPoints.set(attachmentAtomId, updatedLeavingAtomIds);
26159
26216
  }
26160
26217
  }
26161
26218
  });
@@ -26168,24 +26225,40 @@ var Editor$3 = function () {
26168
26225
  try {
26169
26226
  var _loop2 = function _loop2() {
26170
26227
  var id = _step3.value;
26171
- var bond = _this6.struct().bonds.get(id);
26228
+ var bond = _this8.struct().bonds.get(id);
26172
26229
  assert_1(bond);
26173
- var attachmentPointWithBond = Array.from(_this6.monomerCreationState.assignedAttachmentPoints.entries()).find(function (_ref17) {
26174
- var _ref18 = _slicedToArray$1(_ref17, 2),
26175
- atomPair = _ref18[1];
26230
+ var attachmentPointWithBond = Array.from(_this8.monomerCreationState.assignedAttachmentPoints.entries()).find(function (_ref19) {
26231
+ var _ref20 = _slicedToArray$1(_ref19, 2),
26232
+ atomPair = _ref20[1];
26176
26233
  return bond.begin === atomPair[0] && bond.end === atomPair[1] || bond.begin === atomPair[1] && bond.end === atomPair[0];
26177
26234
  });
26178
- if (!attachmentPointWithBond) {
26179
- return 1;
26235
+ if (attachmentPointWithBond) {
26236
+ if (bond.type !== Bond$2.PATTERN.TYPE.SINGLE || bond.stereo !== Bond$2.PATTERN.STEREO.NONE) {
26237
+ _this8.monomerCreationState.problematicAttachmentPoints.add(attachmentPointWithBond[0]);
26238
+ } else {
26239
+ _this8.monomerCreationState.problematicAttachmentPoints["delete"](attachmentPointWithBond[0]);
26240
+ }
26180
26241
  }
26181
26242
  if (bond.type !== Bond$2.PATTERN.TYPE.SINGLE || bond.stereo !== Bond$2.PATTERN.STEREO.NONE) {
26182
- _this6.monomerCreationState.problematicAttachmentPoints.add(attachmentPointWithBond[0]);
26183
- } else {
26184
- _this6.monomerCreationState.problematicAttachmentPoints["delete"](attachmentPointWithBond[0]);
26243
+ _this8.monomerCreationState.potentialAttachmentPoints.forEach(function (leavingAtomIds, attachmentAtomId) {
26244
+ var updatedLeavingAtomIds = new Set(leavingAtomIds);
26245
+ var bondFromAttachmentAtom = bond.begin === attachmentAtomId && leavingAtomIds.has(bond.end);
26246
+ var bondToAttachmentAtom = bond.end === attachmentAtomId && leavingAtomIds.has(bond.begin);
26247
+ if (bondFromAttachmentAtom || bondToAttachmentAtom) {
26248
+ updatedLeavingAtomIds["delete"](bondFromAttachmentAtom ? bond.end : bond.begin);
26249
+ }
26250
+ if (updatedLeavingAtomIds.size === 0) {
26251
+ var _this8$monomerCreatio7;
26252
+ (_this8$monomerCreatio7 = _this8.monomerCreationState) === null || _this8$monomerCreatio7 === void 0 || _this8$monomerCreatio7.potentialAttachmentPoints["delete"](attachmentAtomId);
26253
+ } else {
26254
+ var _this8$monomerCreatio8;
26255
+ (_this8$monomerCreatio8 = _this8.monomerCreationState) === null || _this8$monomerCreatio8 === void 0 || _this8$monomerCreatio8.potentialAttachmentPoints.set(attachmentAtomId, updatedLeavingAtomIds);
26256
+ }
26257
+ });
26185
26258
  }
26186
26259
  };
26187
26260
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
26188
- if (_loop2()) continue;
26261
+ _loop2();
26189
26262
  }
26190
26263
  } catch (err) {
26191
26264
  _iterator3.e(err);
@@ -26201,23 +26274,44 @@ var Editor$3 = function () {
26201
26274
  try {
26202
26275
  var _loop3 = function _loop3() {
26203
26276
  var id = _step4.value;
26204
- var bond = _this6.struct().bonds.get(id);
26277
+ var bond = _this8.struct().bonds.get(id);
26205
26278
  assert_1(bond);
26206
- var attachmentPointWithBondToLeavingAtom = Array.from(_this6.monomerCreationState.assignedAttachmentPoints.entries()).find(function (_ref19) {
26207
- var _ref20 = _slicedToArray$1(_ref19, 2),
26208
- _ref20$ = _slicedToArray$1(_ref20[1], 2),
26209
- leavingAtomId = _ref20$[1];
26279
+ var attachmentPointWithBondToLeavingAtom = Array.from(_this8.monomerCreationState.assignedAttachmentPoints.entries()).find(function (_ref21) {
26280
+ var _ref22 = _slicedToArray$1(_ref21, 2),
26281
+ _ref22$ = _slicedToArray$1(_ref22[1], 2),
26282
+ leavingAtomId = _ref22$[1];
26210
26283
  return bond.begin === leavingAtomId || bond.end === leavingAtomId;
26211
26284
  });
26212
- if (!attachmentPointWithBondToLeavingAtom) {
26213
- return 1;
26285
+ if (attachmentPointWithBondToLeavingAtom) {
26286
+ var _attachmentPointWithB = _slicedToArray$1(attachmentPointWithBondToLeavingAtom, 1),
26287
+ attachmentPointName = _attachmentPointWithB[0];
26288
+ _this8.monomerCreationState.assignedAttachmentPoints["delete"](attachmentPointName);
26289
+ }
26290
+ if (bond.type === Bond$2.PATTERN.TYPE.SINGLE && bond.stereo === Bond$2.PATTERN.STEREO.NONE) {
26291
+ if (_this8.monomerCreationState.potentialAttachmentPoints.has(bond.begin)) {
26292
+ var leavingAtomIds = _this8.monomerCreationState.potentialAttachmentPoints.get(bond.begin);
26293
+ assert_1(leavingAtomIds);
26294
+ var endAtom = _this8.struct().atoms.get(bond.end);
26295
+ if (endAtom && endAtom.neighbors.length === 1) {
26296
+ var updatedLeavingAtomIds = new Set(leavingAtomIds);
26297
+ updatedLeavingAtomIds.add(bond.end);
26298
+ _this8.monomerCreationState.potentialAttachmentPoints.set(bond.begin, updatedLeavingAtomIds);
26299
+ }
26300
+ }
26301
+ if (_this8.monomerCreationState.potentialAttachmentPoints.has(bond.end)) {
26302
+ var _leavingAtomIds = _this8.monomerCreationState.potentialAttachmentPoints.get(bond.end);
26303
+ assert_1(_leavingAtomIds);
26304
+ var beginAtom = _this8.struct().atoms.get(bond.begin);
26305
+ if (beginAtom && beginAtom.neighbors.length === 1) {
26306
+ var _updatedLeavingAtomIds = new Set(_leavingAtomIds);
26307
+ _updatedLeavingAtomIds.add(bond.begin);
26308
+ _this8.monomerCreationState.potentialAttachmentPoints.set(bond.end, _updatedLeavingAtomIds);
26309
+ }
26310
+ }
26214
26311
  }
26215
- var _attachmentPointWithB = _slicedToArray$1(attachmentPointWithBondToLeavingAtom, 1),
26216
- attachmentPointName = _attachmentPointWithB[0];
26217
- _this6.monomerCreationState.assignedAttachmentPoints["delete"](attachmentPointName);
26218
26312
  };
26219
26313
  for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
26220
- if (_loop3()) continue;
26314
+ _loop3();
26221
26315
  }
26222
26316
  } catch (err) {
26223
26317
  _iterator4.e(err);
@@ -26592,6 +26686,17 @@ var Editor$3 = function () {
26592
26686
  }
26593
26687
  return visited.size === atomIds.length;
26594
26688
  }
26689
+ }, {
26690
+ key: "isStructureImpure",
26691
+ value: function isStructureImpure(struct) {
26692
+ var atoms = struct.atoms,
26693
+ sgroups = struct.sgroups,
26694
+ rgroups = struct.rgroups,
26695
+ functionalGroups = struct.functionalGroups;
26696
+ return sgroups.size > 0 || rgroups.size > 0 || functionalGroups.size > 0 || Array.from(atoms.values()).some(function (atom) {
26697
+ return genericsList.includes(atom.label);
26698
+ });
26699
+ }
26595
26700
  }]);
26596
26701
  return Editor;
26597
26702
  }();
@@ -26667,10 +26772,10 @@ function domEventSetup(editor, clientArea) {
26667
26772
  eventName: 'mouseover',
26668
26773
  toolEventHandler: 'mouseover'
26669
26774
  }];
26670
- trackedDomEvents.forEach(function (_ref21) {
26671
- var target = _ref21.target,
26672
- eventName = _ref21.eventName,
26673
- toolEventHandler = _ref21.toolEventHandler;
26775
+ trackedDomEvents.forEach(function (_ref23) {
26776
+ var target = _ref23.target,
26777
+ eventName = _ref23.eventName,
26778
+ toolEventHandler = _ref23.toolEventHandler;
26674
26779
  editor.event[eventName] = new DOMSubscription();
26675
26780
  var subs = editor.event[eventName];
26676
26781
  target.addEventListener(eventName, function () {
@@ -29376,9 +29481,11 @@ var useAttachmentPointSelectsData = function useAttachmentPointSelectsData(edito
29376
29481
  leavingAtomId = _atomPair[1];
29377
29482
  var attachmentAtom = editor.struct().atoms.get(attachmentAtomId);
29378
29483
  assert_1(attachmentAtom);
29379
- var attachmentPointNameOptionsLength = Math.max.apply(Math, _toConsumableArray(Array.from(assignedAttachmentPoints.keys()).map(function (name) {
29484
+ var usedNumbers = Array.from(assignedAttachmentPoints.keys()).map(function (name) {
29380
29485
  return getAttachmentPointNumberFromLabel(name);
29381
- })));
29486
+ });
29487
+ var maxUsedNumber = Math.max.apply(Math, _toConsumableArray(usedNumbers));
29488
+ var attachmentPointNameOptionsLength = maxUsedNumber <= 3 ? 3 : Math.min(maxUsedNumber, 8);
29382
29489
  var nameOptions = Array.from({
29383
29490
  length: attachmentPointNameOptionsLength
29384
29491
  }).map(function (_, i) {
@@ -29538,7 +29645,9 @@ var NotificationMessages = {
29538
29645
  noAttachmentPoints: 'The monomer must have at least one attachment point.',
29539
29646
  incorrectAttachmentPointsOrder: 'Attachment point numbers must be in order, but R1 and R2 may be skipped.',
29540
29647
  creationSuccessful: 'The monomer was successfully added to the library.',
29541
- incontinuousStructure: 'All monomers must have a continuous structure.'
29648
+ incontinuousStructure: 'All monomers must have a continuous structure.',
29649
+ notMinimalViableStructure: 'Minimal monomer structure is two atoms connected via a single bond.',
29650
+ impureStructure: 'Monomer structure cannot contain S-groups, R-groups, special atoms, or any other query properties.'
29542
29651
  };
29543
29652
  var NotificationTypes = {
29544
29653
  defaultAttachmentPoints: 'info',
@@ -29549,7 +29658,9 @@ var NotificationTypes = {
29549
29658
  noAttachmentPoints: 'error',
29550
29659
  incorrectAttachmentPointsOrder: 'error',
29551
29660
  creationSuccessful: 'info',
29552
- incontinuousStructure: 'error'
29661
+ incontinuousStructure: 'error',
29662
+ notMinimalViableStructure: 'error',
29663
+ impureStructure: 'error'
29553
29664
  };
29554
29665
  var MonomerCreationExternalNotificationAction = 'MonomerCreationExternalNotification';
29555
29666
 
@@ -29804,6 +29915,21 @@ var validateAttachmentPoints = function validateAttachmentPoints(attachmentPoint
29804
29915
  };
29805
29916
  var validateStructure = function validateStructure(editor) {
29806
29917
  var notifications = new Map();
29918
+ var isStructureImpure = Editor$3.isStructureImpure(editor.struct());
29919
+ if (isStructureImpure) {
29920
+ notifications.set('impureStructure', {
29921
+ type: 'error',
29922
+ message: NotificationMessages.impureStructure
29923
+ });
29924
+ }
29925
+ var isMinimalViableStructure = editor.isMinimalViableStructure();
29926
+ if (!isMinimalViableStructure) {
29927
+ notifications.set('notMinimalViableStructure', {
29928
+ type: 'error',
29929
+ message: NotificationMessages.notMinimalViableStructure
29930
+ });
29931
+ return notifications;
29932
+ }
29807
29933
  var isStructureContinuous = Editor$3.isStructureContinuous(editor.struct());
29808
29934
  if (!isStructureContinuous) {
29809
29935
  notifications.set('incontinuousStructure', {
@@ -36641,6 +36767,11 @@ var TemplateDialog = function TemplateDialog(props) {
36641
36767
  onTabChange(initialTab);
36642
36768
  }
36643
36769
  }, [initialTab, onTabChange]);
36770
+ useEffect(function () {
36771
+ if (isMonomerCreationWizardActive && tab === TemplateTabs.FunctionalGroupLibrary) {
36772
+ onTabChange(TemplateTabs.TemplateLibrary);
36773
+ }
36774
+ }, [isMonomerCreationWizardActive, tab, onTabChange]);
36644
36775
  var handleAccordionChange = function handleAccordionChange(accordion) {
36645
36776
  return function (_, isExpanded) {
36646
36777
  setExpandedAccordions(isExpanded ? [].concat(_toConsumableArray(expandedAccordions), [accordion]) : _toConsumableArray(expandedAccordions).filter(function (expandedAccordion) {
@@ -37848,12 +37979,12 @@ var AbbreviationLookup = function AbbreviationLookup(_ref) {
37848
37979
  });
37849
37980
  },
37850
37981
  renderOption: function renderOption(props, option) {
37851
- return jsx("li", _objectSpread$2(_objectSpread$2({}, props), {}, {
37982
+ return createElement("li", _objectSpread$2(_objectSpread$2({}, props), {}, {
37852
37983
  title: option.label,
37853
- children: jsx("div", {
37854
- className: classes.optionItemContent,
37855
- children: highlightOptionLabel(option, loweredLookupValue)
37856
- })
37984
+ key: option.label
37985
+ }), jsx("div", {
37986
+ className: classes.optionItemContent,
37987
+ children: highlightOptionLabel(option, loweredLookupValue)
37857
37988
  }));
37858
37989
  },
37859
37990
  "data-testid": ABBREVIATION_LOOKUP_TEST_ID
@@ -38131,8 +38262,8 @@ var KetcherBuilder = function () {
38131
38262
  cleanup = initApp(prevKetcherId, ketcherId, element, appRoot, staticResourcesUrl, {
38132
38263
  buttons: buttons || {},
38133
38264
  errorHandler: errorHandler || null,
38134
- version: "3.9.0-rc.1" ,
38135
- buildDate: "2025-10-02T16:45:46" ,
38265
+ version: "3.9.0-rc.2" ,
38266
+ buildDate: "2025-10-16T18:57:23" ,
38136
38267
  buildNumber: '',
38137
38268
  customButtons: customButtons || []
38138
38269
  }, structService, resolve, togglerComponent);
@@ -38427,7 +38558,7 @@ var ModeControl = function ModeControl(_ref3) {
38427
38558
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
38428
38559
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty$1(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
38429
38560
  var MacromoleculesEditorComponent = lazy(function () {
38430
- return import('./index.modern-dbbd94e2.js');
38561
+ return import('./index.modern-87b29a80.js');
38431
38562
  });
38432
38563
  var Editor = function Editor(props) {
38433
38564
  var _useState = useState(false),