ketcher-react 3.8.0-rc.2 → 3.8.0-rc.4

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.
@@ -107,10 +107,13 @@ declare class Editor implements KetcherEditor {
107
107
  openMonomerCreationWizard(): void;
108
108
  assignLeavingGroupAtom(atomId: number): void;
109
109
  closeMonomerCreationWizard(): void;
110
+ private cleanupAttachmentPoint;
110
111
  saveNewMonomer(data: any): void;
111
112
  reassignAttachmentPointAtom(atomId: number, atomLabel: string): void;
112
113
  reassignAttachmentPoint(currentName: AttachmentPointName, newName: AttachmentPointName): void;
113
114
  removeAttachmentPoint(name: AttachmentPointName): void;
115
+ cleanupCloseAttachmentPointEditPopup(): void;
116
+ setProblematicAttachmentPoints(problematicPoints: Set<AttachmentPointName>): void;
114
117
  selection(ci?: any): Selection | null;
115
118
  hover(ci: {
116
119
  id: number;
@@ -2,6 +2,7 @@ import { AttachmentPointName } from 'ketcher-core';
2
2
  declare type Props = {
3
3
  name: AttachmentPointName;
4
4
  atomLabel: string;
5
+ implicitH: number;
5
6
  };
6
- declare const AttachmentPoint: ({ name, atomLabel }: Props) => import("react/jsx-runtime").JSX.Element;
7
+ declare const AttachmentPoint: ({ name, atomLabel, implicitH }: Props) => import("react/jsx-runtime").JSX.Element;
7
8
  export default AttachmentPoint;
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import 'url-search-params-polyfill';
27
27
  import 'whatwg-fetch';
28
28
  import _classCallCheck$2 from '@babel/runtime/helpers/classCallCheck';
29
29
  import _createClass$2 from '@babel/runtime/helpers/createClass';
30
- import { KetSerializer, MolSerializer, KetcherLogger, ketcherProvider, defaultBondThickness, isClipboardAPIAvailable, notifyCopyCut, notifyRequestCompleted, isControlKey, StereLabelStyleType, StereoColoringType, ShowHydrogenLabels, ShowHydrogenLabelNames, SettingsManager, SdfSerializer, KETCHER_SAVED_OPTIONS_KEY, SUPERATOM_CLASS, Bond as Bond$2, Elements, AtomList, getAtomType, StereoLabel, isAttachmentBond, Atom as Atom$2, findStereoAtoms, RxnArrowMode, MULTITAIL_ARROW_TOOL_NAME, CREATE_MONOMER_TOOL_NAME, SimpleObjectMode, IMAGE_KEY, SGroup as SGroup$1, identifyStructFormat, SupportedFormat, FormatterFactory, MULTITAIL_ARROW_KEY, ChemicalMimeType, RenderStruct, Struct, ZoomTool, KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR, shortcutStr, MonomerMicromolecule, UnresolvedMonomer, FunctionalGroupsProvider, SaltsAndSolventsProvider, KetcherAsyncEvents, ElementColor, generateMenuShortcuts, Vec2, Scale, fromMultipleMove, FunctionalGroup, mergeMapOfItemsToSet, fromSgroupDeletion, fromFragmentDeletion, vectorUtils, fromBondAddition, Action, fromAtomAddition, fromAtomsAttrs, checkOverlapping, fromSeveralSgroupAddition, expandSGroupWithMultipleAttachmentPoint, SgContexts, Pile, fromSgroupAction, fromItemsFuse, ReBond, setExpandSGroup, fromBondsAttrs, OperationType, ReStruct, imageReferencePositionToCursor, multitailArrowReferenceLinesToCursor, multitailReferencePositionToCursor, CoordinateTransformation, MultitailArrowRefName, fromMultitailArrowHeadTailMove, fromMultitailArrowHeadTailsResize, fromMultitailArrowMove, fromArrowResizing, fromPaste, fromImageResize, fromSimpleObjectResizing, getItemsToFuse, getHoverToFuse, fromTextDeletion, fromTextUpdating, fromTemplateOnCanvas, fromTemplateOnBondAction, fromTemplateOnAtom, BondAttr, AtomAttr, formatProperties, runAsyncAction, getStructStringFromClipboardData, getStructure, initHotKeys, keyNorm, Fragment as Fragment$1, fromRGroupAttachmentPointUpdate, fromOneBondDeletion, bondChangingAction, fromChain, removeInfoLabelFromAtoms, fromStereoFlagUpdate, fromOneAtomDeletion, fromArrowDeletion, fromPlusDeletion, fromSimpleObjectDeletion, fromRGroupAttachmentPointDeletion, fromImageDeletion, fromMultitailArrowDeletion, notifyItemsToMergeInitializationComplete, RGroup as RGroup$2, fromRGroupFragment, fromUpdateIfThen, fromRGroupAttrs, fromArrowAddition, fromMultitailArrowCreation, fromPlusAddition, getRelSGroupsBySelection, RotateMonomerOperation, fromRotate, fromFlip, fromSimpleObjectAddition, fromTextCreation, fromImageMove, fromImageCreation, fromHighlightCreate, fromHighlightClear, getOptionsWithConvertedUnits, provideEditorSettings, fromNewCanvas, Render, Coordinates, genericsList, getAttachmentPointLabel, getNextFreeAttachmentPoint, AttachmentPointName, setMonomerTemplatePrefix, getHELMClassByKetMonomerClass, fillNaturalAnalogueForPhosphateAndSugar, KetTemplateType, normalizeMonomerAtomsPositions, monomerFactory, MacromoleculesConverter, fromSgroupAddition, fromDescriptorsAlign, MonomerCreationAttachmentPointClickEvent, atomGetAttr, fromBondFlipping, setExpandMonomerSGroup, fromMultitailArrowTailAdd, MultitailArrow, fromMultitailArrowTailRemove, AmbiguousMonomer, KetMonomerClass, AtomLabel, CoreEditor, getAttachmentPointNumberFromLabel, getAtomCustomQuery, getFormatMimeTypeByFileName, getPropertiesByFormat, StereoFlag, getPropertiesByImgFormat, legacyCopy as legacyCopy$1, b64toBlob, Generics, TextCommand, Ketcher, DefaultStructServiceOptions } from 'ketcher-core';
30
+ import { KetSerializer, MolSerializer, KetcherLogger, ketcherProvider, defaultBondThickness, isClipboardAPIAvailable, notifyCopyCut, notifyRequestCompleted, isControlKey, StereLabelStyleType, StereoColoringType, ShowHydrogenLabels, ShowHydrogenLabelNames, SettingsManager, SdfSerializer, KETCHER_SAVED_OPTIONS_KEY, SUPERATOM_CLASS, Bond as Bond$2, Elements, AtomList, getAtomType, StereoLabel, isAttachmentBond, Atom as Atom$2, findStereoAtoms, RxnArrowMode, MULTITAIL_ARROW_TOOL_NAME, CREATE_MONOMER_TOOL_NAME, SimpleObjectMode, IMAGE_KEY, SGroup as SGroup$1, identifyStructFormat, SupportedFormat, FormatterFactory, MULTITAIL_ARROW_KEY, ChemicalMimeType, RenderStruct, Struct, ZoomTool, KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR, shortcutStr, MonomerMicromolecule, UnresolvedMonomer, FunctionalGroupsProvider, SaltsAndSolventsProvider, KetcherAsyncEvents, ElementColor, generateMenuShortcuts, Vec2, Scale, fromMultipleMove, FunctionalGroup, mergeMapOfItemsToSet, fromSgroupDeletion, fromFragmentDeletion, vectorUtils, fromBondAddition, Action, fromAtomAddition, fromAtomsAttrs, checkOverlapping, fromSeveralSgroupAddition, expandSGroupWithMultipleAttachmentPoint, SgContexts, Pile, fromSgroupAction, fromItemsFuse, ReBond, setExpandSGroup, fromBondsAttrs, OperationType, ReStruct, imageReferencePositionToCursor, multitailArrowReferenceLinesToCursor, multitailReferencePositionToCursor, CoordinateTransformation, MultitailArrowRefName, fromMultitailArrowHeadTailMove, fromMultitailArrowHeadTailsResize, fromMultitailArrowMove, fromArrowResizing, fromPaste, fromImageResize, fromSimpleObjectResizing, getItemsToFuse, getHoverToFuse, fromTextDeletion, fromTextUpdating, fromTemplateOnCanvas, fromTemplateOnBondAction, fromTemplateOnAtom, BondAttr, AtomAttr, formatProperties, runAsyncAction, getStructStringFromClipboardData, getStructure, initHotKeys, keyNorm, Fragment as Fragment$1, fromRGroupAttachmentPointUpdate, fromOneBondDeletion, bondChangingAction, fromChain, removeInfoLabelFromAtoms, fromStereoFlagUpdate, fromOneAtomDeletion, fromArrowDeletion, fromPlusDeletion, fromSimpleObjectDeletion, fromRGroupAttachmentPointDeletion, fromImageDeletion, fromMultitailArrowDeletion, notifyItemsToMergeInitializationComplete, RGroup as RGroup$2, fromRGroupFragment, fromUpdateIfThen, fromRGroupAttrs, fromArrowAddition, fromMultitailArrowCreation, fromPlusAddition, getRelSGroupsBySelection, RotateMonomerOperation, fromRotate, fromFlip, fromSimpleObjectAddition, fromTextCreation, fromImageMove, fromImageCreation, fromHighlightCreate, fromHighlightClear, getOptionsWithConvertedUnits, provideEditorSettings, fromNewCanvas, Render, Coordinates, isSingleRGroupAttachmentPoint, genericsList, getAttachmentPointLabelWithBinaryShift, AttachmentPointName, getAttachmentPointLabel, getAttachmentPointNumberFromLabel, getNextFreeAttachmentPoint, AtomLabel, setMonomerTemplatePrefix, getHELMClassByKetMonomerClass, fillNaturalAnalogueForPhosphateAndSugar, KetTemplateType, normalizeMonomerAtomsPositions, monomerFactory, MacromoleculesConverter, fromSgroupAddition, fromDescriptorsAlign, MonomerCreationAttachmentPointClickEvent, atomGetAttr, fromBondFlipping, setExpandMonomerSGroup, fromMultitailArrowTailAdd, MultitailArrow, fromMultitailArrowTailRemove, AmbiguousMonomer, KetMonomerClass, CoreEditor, getAtomCustomQuery, getFormatMimeTypeByFileName, getPropertiesByFormat, StereoFlag, getPropertiesByImgFormat, legacyCopy as legacyCopy$1, b64toBlob, Generics, TextCommand, Ketcher, DefaultStructServiceOptions } from 'ketcher-core';
31
31
  export { EditorClassName, KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR } from 'ketcher-core';
32
32
  import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
33
33
  import _possibleConstructorReturn$2 from '@babel/runtime/helpers/possibleConstructorReturn';
@@ -3787,7 +3787,7 @@ var zoom = {
3787
3787
 
3788
3788
  var openHelpLink = function openHelpLink() {
3789
3789
  var _window$open;
3790
- return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v3.8.0-rc.2\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3790
+ return (_window$open = window.open("https://github.com/epam/ketcher/blob/".concat("v3.8.0-rc.4\n", "/documentation/help.md#ketcher-overview"))) === null || _window$open === void 0 ? void 0 : _window$open.focus();
3791
3791
  };
3792
3792
  var help = {
3793
3793
  help: {
@@ -24268,8 +24268,9 @@ var HoverIcon = function () {
24268
24268
  }, {
24269
24269
  key: "isOverLoader",
24270
24270
  value: function isOverLoader(event) {
24271
+ var _target$classList;
24271
24272
  var target = (event === null || event === void 0 ? void 0 : event.relatedTarget) || event.target;
24272
- return target === null || target === void 0 ? void 0 : target.classList.contains('loading-spinner');
24273
+ return target === null || target === void 0 || (_target$classList = target.classList) === null || _target$classList === void 0 ? void 0 : _target$classList.contains('loading-spinner');
24273
24274
  }
24274
24275
  }, {
24275
24276
  key: "onMouseMove",
@@ -25342,10 +25343,23 @@ var Editor$3 = function () {
25342
25343
  var currentStruct = this.render.ctab.molecule;
25343
25344
  var selectionInvalid = selection.atoms.some(function (atomId) {
25344
25345
  var atom = _this.render.ctab.molecule.atoms.get(atomId);
25345
- assert_1(atom);
25346
- return atom.sgs.size > 0 || atom.attachmentPoints !== null || atom.rglabel !== null && atom.neighbors.length > 1 || _this.render.ctab.molecule.rgroups.some(function (rgroup) {
25346
+ if (!atom) {
25347
+ return true;
25348
+ }
25349
+ var sgs = atom.sgs,
25350
+ attachmentPoints = atom.attachmentPoints,
25351
+ rglabel = atom.rglabel,
25352
+ neighbors = atom.neighbors,
25353
+ label = atom.label;
25354
+ var belongsToSGroup = sgs.size > 0;
25355
+ var isAttachmentPoint = attachmentPoints !== null;
25356
+ var isNonTerminalRGroupLabel = rglabel !== null && neighbors.length > 1;
25357
+ var hasMultipleRGroupLabel = rglabel !== null && !isSingleRGroupAttachmentPoint(Number(rglabel));
25358
+ var belongsToRGroup = _this.render.ctab.molecule.rgroups.some(function (rgroup) {
25347
25359
  return rgroup.frags.has(atom.fragment);
25348
- }) || genericsList.includes(atom.label);
25360
+ });
25361
+ var isExtendedTableAtom = genericsList.includes(label);
25362
+ return belongsToSGroup || isAttachmentPoint || isNonTerminalRGroupLabel || hasMultipleRGroupLabel || belongsToRGroup || isExtendedTableAtom;
25349
25363
  });
25350
25364
  if (selectionInvalid) {
25351
25365
  return false;
@@ -25356,7 +25370,9 @@ var Editor$3 = function () {
25356
25370
  }
25357
25371
  var terminalRGroupAtoms = selection.atoms.filter(function (atomId) {
25358
25372
  var atom = currentStruct.atoms.get(atomId);
25359
- assert_1(atom);
25373
+ if (!atom) {
25374
+ return false;
25375
+ }
25360
25376
  return atom.rglabel !== null && atom.neighbors.length === 1;
25361
25377
  });
25362
25378
  var selectionAtoms = new Set(selection.atoms);
@@ -25374,11 +25390,24 @@ var Editor$3 = function () {
25374
25390
  potentialLeavingAtoms.push(bond.begin);
25375
25391
  }
25376
25392
  });
25393
+ selectionAtoms.forEach(function (selectionAtomId) {
25394
+ var selectionAtom = currentStruct.atoms.get(selectionAtomId);
25395
+ assert_1(selectionAtom);
25396
+ if (selectionAtom.neighbors.length === 1 && !isNumber(selectionAtom.rglabel)) {
25397
+ potentialLeavingAtoms.push(selectionAtomId);
25398
+ }
25399
+ });
25377
25400
  var totalPotentialLeavingAtoms = terminalRGroupAtoms.length + potentialLeavingAtoms.length;
25378
25401
  if (totalPotentialLeavingAtoms > 8) {
25379
25402
  return false;
25380
25403
  }
25381
- this.terminalRGroupAtoms = terminalRGroupAtoms;
25404
+ this.terminalRGroupAtoms = terminalRGroupAtoms.map(function (atomId) {
25405
+ var atom = currentStruct.atoms.get(atomId);
25406
+ assert_1(atom);
25407
+ assert_1(atom.rglabel);
25408
+ var attachmentPointLabel = getAttachmentPointLabelWithBinaryShift(Number(atom.rglabel));
25409
+ return [atomId, attachmentPointLabel];
25410
+ });
25382
25411
  this.potentialLeavingAtoms = potentialLeavingAtoms;
25383
25412
  return terminalRGroupAtoms.length > 0 || potentialLeavingAtoms.length > 0;
25384
25413
  }
@@ -25403,21 +25432,54 @@ var Editor$3 = function () {
25403
25432
  _this2.selectedToOriginalAtomsIdMap.set(i, atomId);
25404
25433
  });
25405
25434
  var assignedAttachmentPoints = new Map();
25406
- this.terminalRGroupAtoms.forEach(function (atomId, i) {
25435
+ var sideTerminalSGroupAtoms = this.terminalRGroupAtoms.filter(function (_ref) {
25436
+ var _ref2 = _slicedToArray$1(_ref, 2),
25437
+ attachmentPointLabel = _ref2[1];
25438
+ return attachmentPointLabel !== AttachmentPointName.R1 && attachmentPointLabel !== AttachmentPointName.R2;
25439
+ });
25440
+ var sideAttachmentPointsNames = [];
25441
+ for (var i = 0; i < sideTerminalSGroupAtoms.length; i++) {
25442
+ var attachmentPointNumber = i + 3;
25443
+ if (attachmentPointNumber > 8) {
25444
+ break;
25445
+ }
25446
+ sideAttachmentPointsNames = sideAttachmentPointsNames.concat(getAttachmentPointLabel(attachmentPointNumber));
25447
+ }
25448
+ var terminalRGroupAtomsSortedByLabel = _toConsumableArray(this.terminalRGroupAtoms).sort(function (_ref3, _ref4) {
25449
+ var _ref5 = _slicedToArray$1(_ref3, 2),
25450
+ labelA = _ref5[1];
25451
+ var _ref6 = _slicedToArray$1(_ref4, 2),
25452
+ labelB = _ref6[1];
25453
+ var labelANumber = getAttachmentPointNumberFromLabel(labelA);
25454
+ var labelBNumber = getAttachmentPointNumberFromLabel(labelB);
25455
+ return labelANumber - labelBNumber;
25456
+ });
25457
+ terminalRGroupAtomsSortedByLabel.forEach(function (_ref7) {
25407
25458
  var _selectedStruct$halfB;
25459
+ var _ref8 = _slicedToArray$1(_ref7, 2),
25460
+ atomId = _ref8[0],
25461
+ attachmentPointLabel = _ref8[1];
25408
25462
  var selectedStructLeavingAtomId = originalToSelectedAtomsIdMap.get(atomId);
25409
25463
  assert_1(selectedStructLeavingAtomId !== undefined);
25410
25464
  var selectedStructLeavingAtom = selectedStruct.atoms.get(selectedStructLeavingAtomId);
25411
25465
  assert_1(selectedStructLeavingAtom);
25466
+ assert_1(selectedStructLeavingAtom.rglabel);
25467
+ var attachmentPointName;
25468
+ if (attachmentPointLabel === AttachmentPointName.R1 || attachmentPointLabel === AttachmentPointName.R2 || sideAttachmentPointsNames.includes(attachmentPointLabel)) {
25469
+ attachmentPointName = attachmentPointLabel;
25470
+ } else {
25471
+ var assignedAttachmentPointNames = Array.from(assignedAttachmentPoints.keys());
25472
+ attachmentPointName = getNextFreeAttachmentPoint(assignedAttachmentPointNames, assignedAttachmentPointNames.length < sideAttachmentPointsNames.length);
25473
+ }
25412
25474
  selectedStructLeavingAtom.rglabel = null;
25413
- selectedStructLeavingAtom.label = 'H';
25475
+ selectedStructLeavingAtom.label = AtomLabel.H;
25414
25476
  var neighborHalfBondId = selectedStructLeavingAtom.neighbors[0];
25415
25477
  var selectedStructAttachmentAtomId = (_selectedStruct$halfB = selectedStruct.halfBonds.get(neighborHalfBondId)) === null || _selectedStruct$halfB === void 0 ? void 0 : _selectedStruct$halfB.end;
25416
- var attachmentPointName = getAttachmentPointLabel(i + 1);
25417
25478
  assert_1(selectedStructAttachmentAtomId !== undefined);
25418
25479
  assignedAttachmentPoints.set(attachmentPointName, [selectedStructAttachmentAtomId, selectedStructLeavingAtomId]);
25419
25480
  });
25420
- this.potentialLeavingAtoms.forEach(function (atomId, i) {
25481
+ var selectedPotentialLeavingAtoms = new Map();
25482
+ this.potentialLeavingAtoms.forEach(function (atomId) {
25421
25483
  var _selectedStruct$atoms, _selectedStruct$atoms2;
25422
25484
  var leavingAtom = currentStruct.atoms.get(atomId);
25423
25485
  assert_1(leavingAtom);
@@ -25433,7 +25495,20 @@ var Editor$3 = function () {
25433
25495
  if (attachmentAtomId === -1) {
25434
25496
  return;
25435
25497
  }
25436
- var selectedStructLeavingAtom = leavingAtom.clone();
25498
+ var originalLeavingAtomId = originalToSelectedAtomsIdMap.get(atomId);
25499
+ var isLeavingAtomSelected = isNumber(originalLeavingAtomId);
25500
+ if (isLeavingAtomSelected) {
25501
+ var originalAttachmentAtomId = originalToSelectedAtomsIdMap.get(attachmentAtomId);
25502
+ if (!isNumber(originalAttachmentAtomId)) {
25503
+ return;
25504
+ }
25505
+ selectedPotentialLeavingAtoms.set(originalAttachmentAtomId, originalLeavingAtomId);
25506
+ return;
25507
+ }
25508
+ var selectedStructLeavingAtom = new Atom$2({
25509
+ label: AtomLabel.H,
25510
+ pp: leavingAtom.pp
25511
+ });
25437
25512
  selectedStructLeavingAtom.fragment = (_selectedStruct$atoms = (_selectedStruct$atoms2 = selectedStruct.atoms.get(0)) === null || _selectedStruct$atoms2 === void 0 ? void 0 : _selectedStruct$atoms2.fragment) !== null && _selectedStruct$atoms !== void 0 ? _selectedStruct$atoms : 0;
25438
25513
  var selectedStructLeavingAtomId = selectedStruct.atoms.add(selectedStructLeavingAtom);
25439
25514
  _this2.selectedToOriginalAtomsIdMap.set(selectedStructLeavingAtomId, atomId);
@@ -25446,12 +25521,14 @@ var Editor$3 = function () {
25446
25521
  end: selectedStructLeavingAtomId
25447
25522
  });
25448
25523
  selectedStruct.bonds.add(newBond);
25449
- var attachmentPointName = getAttachmentPointLabel(_this2.terminalRGroupAtoms.length + i + 1);
25524
+ var assignedAttachmentPointNames = Array.from(assignedAttachmentPoints.keys());
25525
+ var attachmentPointName = getNextFreeAttachmentPoint(assignedAttachmentPointNames, assignedAttachmentPointNames.length < sideAttachmentPointsNames.length);
25450
25526
  assignedAttachmentPoints.set(attachmentPointName, [selectedStructAttachmentAtomId, selectedStructLeavingAtomId]);
25451
25527
  });
25452
25528
  this.monomerCreationState = {
25453
25529
  assignedAttachmentPoints: assignedAttachmentPoints,
25454
- potentialAttachmentPoints: new Map()
25530
+ potentialAttachmentPoints: selectedPotentialLeavingAtoms,
25531
+ problematicAttachmentPoints: new Set()
25455
25532
  };
25456
25533
  this.originalStruct = currentStruct;
25457
25534
  this.struct(selectedStruct);
@@ -25504,6 +25581,19 @@ var Editor$3 = function () {
25504
25581
  this.struct(this.originalStruct, false);
25505
25582
  this.tool('select');
25506
25583
  }
25584
+ }, {
25585
+ key: "cleanupAttachmentPoint",
25586
+ value: function cleanupAttachmentPoint(leavingAtomId) {
25587
+ var leavingAtom = this.struct().atoms.get(leavingAtomId);
25588
+ assert_1(leavingAtom);
25589
+ var originalLeavingAtomId = this.selectedToOriginalAtomsIdMap.get(leavingAtomId);
25590
+ assert_1(isNumber(originalLeavingAtomId));
25591
+ var originalLeavingAtom = this.originalStruct.atoms.get(originalLeavingAtomId);
25592
+ assert_1(originalLeavingAtom);
25593
+ originalLeavingAtom.rglabel = null;
25594
+ originalLeavingAtom.label = leavingAtom.label;
25595
+ this.originalStruct.calcImplicitHydrogen(originalLeavingAtomId);
25596
+ }
25507
25597
  }, {
25508
25598
  key: "saveNewMonomer",
25509
25599
  value: function saveNewMonomer(data) {
@@ -25519,10 +25609,10 @@ var Editor$3 = function () {
25519
25609
  type = data.type,
25520
25610
  naturalAnalogue = data.naturalAnalogue;
25521
25611
  var attachmentPoints = [];
25522
- this.monomerCreationState.assignedAttachmentPoints.forEach(function (_ref, attachmentPointName) {
25523
- var _ref2 = _slicedToArray$1(_ref, 2),
25524
- attachmentAtomId = _ref2[0],
25525
- leavingAtomId = _ref2[1];
25612
+ this.monomerCreationState.assignedAttachmentPoints.forEach(function (_ref9, attachmentPointName) {
25613
+ var _ref10 = _slicedToArray$1(_ref9, 2),
25614
+ attachmentAtomId = _ref10[0],
25615
+ leavingAtomId = _ref10[1];
25526
25616
  var attachmentPoint = {
25527
25617
  attachmentAtom: attachmentAtomId,
25528
25618
  leavingGroup: {
@@ -25561,19 +25651,13 @@ var Editor$3 = function () {
25561
25651
  Monomer = _monomerFactory2[0];
25562
25652
  var monomerPosition = new Vec2((this.selectionBBox.min.x + this.selectionBBox.max.x) / 2, (this.selectionBBox.min.y + this.selectionBBox.max.y) / 2);
25563
25653
  var monomer = new Monomer(monomerItem, monomerPosition);
25564
- var finalAttachmentPoints = this.monomerCreationState.assignedAttachmentPoints;
25565
- finalAttachmentPoints.forEach(function (atomPair) {
25566
- var _atomPair2 = _slicedToArray$1(atomPair, 2),
25567
- leavingAtomId = _atomPair2[1];
25568
- var leavingAtom = _this3.struct().atoms.get(leavingAtomId);
25569
- assert_1(leavingAtom);
25570
- var originalLeavingAtomId = _this3.selectedToOriginalAtomsIdMap.get(leavingAtomId);
25571
- assert_1(originalLeavingAtomId);
25572
- var originalLeavingAtom = _this3.originalStruct.atoms.get(originalLeavingAtomId);
25573
- assert_1(originalLeavingAtom);
25574
- originalLeavingAtom.rglabel = null;
25575
- originalLeavingAtom.label = leavingAtom.label;
25576
- _this3.originalStruct.calcImplicitHydrogen(originalLeavingAtomId);
25654
+ this.monomerCreationState.assignedAttachmentPoints.forEach(function (_ref11) {
25655
+ var _ref12 = _slicedToArray$1(_ref11, 2),
25656
+ leavingAtomId = _ref12[1];
25657
+ return _this3.cleanupAttachmentPoint(leavingAtomId);
25658
+ });
25659
+ this.monomerCreationState.potentialAttachmentPoints.forEach(function (leavingAtomId) {
25660
+ return _this3.cleanupAttachmentPoint(leavingAtomId);
25577
25661
  });
25578
25662
  this.closeMonomerCreationWizard();
25579
25663
  (_this$originalSelecti = this.originalSelection.atoms) === null || _this$originalSelecti === void 0 || _this$originalSelecti.forEach(function (atomId) {
@@ -25583,9 +25667,19 @@ var Editor$3 = function () {
25583
25667
  }
25584
25668
  });
25585
25669
  var sGroupAttachmentPoints = MacromoleculesConverter.convertMonomerAttachmentPointsToSGroupAttachmentPoints(monomer, this.selectedToOriginalAtomsIdMap);
25670
+ sGroupAttachmentPoints.forEach(function (ap) {
25671
+ _this3.render.ctab.molecule.bonds.forEach(function (bond) {
25672
+ var _this3$originalSelect, _this3$originalSelect2;
25673
+ 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)))) {
25674
+ bond.beginSuperatomAttachmentPointNumber = ap.attachmentPointNumber;
25675
+ }
25676
+ });
25677
+ });
25586
25678
  var action = fromSgroupAddition(this.render.ctab, SGroup$1.TYPES.SUP, this.originalSelection.atoms, {
25587
25679
  expanded: true
25588
25680
  }, this.render.ctab.molecule.sgroups.newId(), sGroupAttachmentPoints, monomer.position, true, monomer.monomerItem.props.MonomerName, null, monomer);
25681
+ this.render.ctab.molecule.clearFragments();
25682
+ this.render.ctab.molecule.markFragments();
25589
25683
  this.update(action);
25590
25684
  var templateRoot = monomerTemplate.root,
25591
25685
  templateData = _objectWithoutProperties(monomerTemplate, _excluded$p);
@@ -25610,6 +25704,7 @@ var Editor$3 = function () {
25610
25704
  key: "reassignAttachmentPoint",
25611
25705
  value: function reassignAttachmentPoint(currentName, newName) {
25612
25706
  assert_1(this.monomerCreationState);
25707
+ this.monomerCreationState.problematicAttachmentPoints["delete"](currentName);
25613
25708
  var atomPair = this.monomerCreationState.assignedAttachmentPoints.get(currentName);
25614
25709
  assert_1(atomPair);
25615
25710
  if (this.monomerCreationState.assignedAttachmentPoints.has(newName)) {
@@ -25634,6 +25729,21 @@ var Editor$3 = function () {
25634
25729
  this.monomerCreationState = Object.assign({}, this.monomerCreationState);
25635
25730
  this.render.update(true);
25636
25731
  }
25732
+ }, {
25733
+ key: "cleanupCloseAttachmentPointEditPopup",
25734
+ value: function cleanupCloseAttachmentPointEditPopup() {
25735
+ assert_1(this.monomerCreationState);
25736
+ this.monomerCreationState.clickedAttachmentPoint = null;
25737
+ this.render.update(true);
25738
+ }
25739
+ }, {
25740
+ key: "setProblematicAttachmentPoints",
25741
+ value: function setProblematicAttachmentPoints(problematicPoints) {
25742
+ assert_1(this.monomerCreationState);
25743
+ this.monomerCreationState.problematicAttachmentPoints = problematicPoints;
25744
+ this.monomerCreationState = Object.assign({}, this.monomerCreationState);
25745
+ this.render.update(true);
25746
+ }
25637
25747
  }, {
25638
25748
  key: "selection",
25639
25749
  value: function selection(ci) {
@@ -26053,10 +26163,10 @@ function domEventSetup(editor, clientArea) {
26053
26163
  eventName: 'mouseover',
26054
26164
  toolEventHandler: 'mouseover'
26055
26165
  }];
26056
- trackedDomEvents.forEach(function (_ref3) {
26057
- var target = _ref3.target,
26058
- eventName = _ref3.eventName,
26059
- toolEventHandler = _ref3.toolEventHandler;
26166
+ trackedDomEvents.forEach(function (_ref13) {
26167
+ var target = _ref13.target,
26168
+ eventName = _ref13.eventName,
26169
+ toolEventHandler = _ref13.toolEventHandler;
26060
26170
  editor.event[eventName] = new DOMSubscription();
26061
26171
  var subs = editor.event[eventName];
26062
26172
  target.addEventListener(eventName, function () {
@@ -26430,7 +26540,7 @@ var useMakeLeavingGroupAtomMenuItem = function useMakeLeavingGroupAtomMenuItem(_
26430
26540
  var attachmentPointName = Array.from(assignedAttachmentPoints.keys()).find(function (key) {
26431
26541
  var atomsPair = assignedAttachmentPoints.get(key);
26432
26542
  assert_1(atomsPair);
26433
- return atomsPair.includes(selectedAtomId);
26543
+ return atomsPair[1] === selectedAtomId;
26434
26544
  });
26435
26545
  var isAtomAssignedAttachmentPoint = Boolean(attachmentPointName);
26436
26546
  if (!isAtomPotentialAttachmentPoint && !isAtomAssignedAttachmentPoint) {
@@ -28591,6 +28701,9 @@ var attachmentPointAtomOptions = [{
28591
28701
  }, {
28592
28702
  value: AtomLabel.F,
28593
28703
  label: 'F'
28704
+ }, {
28705
+ value: AtomLabel.C,
28706
+ label: 'CH3'
28594
28707
  }];
28595
28708
  var AttachmentPointEditPopup = function AttachmentPointEditPopup(_ref) {
28596
28709
  var data = _ref.data,
@@ -28682,7 +28795,8 @@ var styles$f = {"attachmentPoint":"AttachmentPoint-module_attachmentPoint__6KD5K
28682
28795
 
28683
28796
  var AttachmentPoint = function AttachmentPoint(_ref) {
28684
28797
  var name = _ref.name,
28685
- atomLabel = _ref.atomLabel;
28798
+ atomLabel = _ref.atomLabel,
28799
+ implicitH = _ref.implicitH;
28686
28800
  return jsx("div", {
28687
28801
  className: styles$f.attachmentPoint,
28688
28802
  children: jsxs("p", {
@@ -28690,7 +28804,13 @@ var AttachmentPoint = function AttachmentPoint(_ref) {
28690
28804
  children: [jsx("span", {
28691
28805
  className: styles$f.attachmentPointIndex,
28692
28806
  children: name
28693
- }), "\xA0(", atomLabel, ")"]
28807
+ }), "\xA0", jsxs("span", {
28808
+ children: ["(", implicitH > 1 && jsxs(Fragment, {
28809
+ children: ["H", jsx("sub", {
28810
+ children: implicitH
28811
+ })]
28812
+ }), atomLabel, ")"]
28813
+ })]
28694
28814
  })
28695
28815
  });
28696
28816
  };
@@ -28817,31 +28937,50 @@ var validateInputs = function validateInputs(values) {
28817
28937
  };
28818
28938
  var validateAttachmentPoints = function validateAttachmentPoints(attachmentPoints) {
28819
28939
  var notifications = new Map();
28940
+ var problematicAttachmentPoints = new Set();
28820
28941
  if (attachmentPoints.length === 0) {
28821
28942
  notifications.set('noAttachmentPoints', {
28822
28943
  type: 'error',
28823
28944
  message: NotificationMessages.noAttachmentPoints
28824
28945
  });
28825
- return notifications;
28946
+ return {
28947
+ notifications: notifications,
28948
+ problematicAttachmentPoints: problematicAttachmentPoints
28949
+ };
28826
28950
  }
28827
- var attachmentPointNumbers = attachmentPoints.map(getAttachmentPointNumberFromLabel);
28828
- attachmentPointNumbers.sort(function (a, b) {
28829
- return a - b;
28951
+ var sideAttachmentPoints = attachmentPoints.filter(function (attachmentPointName) {
28952
+ var pointNumber = getAttachmentPointNumberFromLabel(attachmentPointName);
28953
+ return pointNumber > 2;
28830
28954
  });
28831
- var startingIndex = 0;
28832
- while (attachmentPointNumbers[startingIndex] <= 2) {
28833
- startingIndex++;
28955
+ if (sideAttachmentPoints.length === 0) {
28956
+ return {
28957
+ notifications: notifications,
28958
+ problematicAttachmentPoints: problematicAttachmentPoints
28959
+ };
28834
28960
  }
28835
- for (var i = startingIndex; i < attachmentPointNumbers.length; i++) {
28836
- if (attachmentPointNumbers[i] - attachmentPointNumbers[i - 1] > 1) {
28837
- notifications.set('incorrectAttachmentPointsOrder', {
28838
- type: 'error',
28839
- message: NotificationMessages.incorrectAttachmentPointsOrder
28840
- });
28841
- break;
28961
+ var expectedSequence = [];
28962
+ for (var i = 3; i < 3 + sideAttachmentPoints.length; i++) {
28963
+ expectedSequence.push(i);
28964
+ }
28965
+ var actualNumbers = sideAttachmentPoints.map(getAttachmentPointNumberFromLabel).sort(function (a, b) {
28966
+ return a - b;
28967
+ });
28968
+ actualNumbers.forEach(function (actualNumber) {
28969
+ if (!expectedSequence.includes(actualNumber)) {
28970
+ var problematicPointName = getAttachmentPointLabel(actualNumber);
28971
+ problematicAttachmentPoints.add(problematicPointName);
28842
28972
  }
28973
+ });
28974
+ if (problematicAttachmentPoints.size > 0) {
28975
+ notifications.set('incorrectAttachmentPointsOrder', {
28976
+ type: 'error',
28977
+ message: NotificationMessages.incorrectAttachmentPointsOrder
28978
+ });
28843
28979
  }
28844
- return notifications;
28980
+ return {
28981
+ notifications: notifications,
28982
+ problematicAttachmentPoints: problematicAttachmentPoints
28983
+ };
28845
28984
  };
28846
28985
  var MonomerCreationWizard = function MonomerCreationWizard() {
28847
28986
  var _useAppContext = useAppContext(),
@@ -28938,6 +29077,7 @@ var MonomerCreationWizard = function MonomerCreationWizard() {
28938
29077
  };
28939
29078
  var handleAttachmentPointEditPopupClose = function handleAttachmentPointEditPopupClose() {
28940
29079
  setAttachmentPointEditPopupData(null);
29080
+ editor.cleanupCloseAttachmentPointEditPopup();
28941
29081
  };
28942
29082
  var handleDiscard = function handleDiscard() {
28943
29083
  editor.closeMonomerCreationWizard();
@@ -28947,6 +29087,7 @@ var MonomerCreationWizard = function MonomerCreationWizard() {
28947
29087
  wizardStateDispatch({
28948
29088
  type: 'ResetErrors'
28949
29089
  });
29090
+ editor.setProblematicAttachmentPoints(new Set());
28950
29091
  var _validateInputs = validateInputs(values),
28951
29092
  inputsErrors = _validateInputs.errors,
28952
29093
  inputsNotifications = _validateInputs.notifications;
@@ -28962,12 +29103,15 @@ var MonomerCreationWizard = function MonomerCreationWizard() {
28962
29103
  return;
28963
29104
  }
28964
29105
  assert_1(editor.monomerCreationState);
28965
- var attachmentPointsNotifications = validateAttachmentPoints(Array.from(editor.monomerCreationState.assignedAttachmentPoints.keys()));
29106
+ var _validateAttachmentPo = validateAttachmentPoints(Array.from(editor.monomerCreationState.assignedAttachmentPoints.keys())),
29107
+ attachmentPointsNotifications = _validateAttachmentPo.notifications,
29108
+ problematicAttachmentPoints = _validateAttachmentPo.problematicAttachmentPoints;
28966
29109
  if (attachmentPointsNotifications.size > 0) {
28967
29110
  wizardStateDispatch({
28968
29111
  type: 'SetNotifications',
28969
29112
  notifications: attachmentPointsNotifications
28970
29113
  });
29114
+ editor.setProblematicAttachmentPoints(problematicAttachmentPoints);
28971
29115
  return;
28972
29116
  }
28973
29117
  editor.saveNewMonomer({
@@ -28992,12 +29136,14 @@ var MonomerCreationWizard = function MonomerCreationWizard() {
28992
29136
  if (!atom) {
28993
29137
  return {
28994
29138
  name: attachmentPointName,
28995
- atomLabel: 'H'
29139
+ atomLabel: 'H',
29140
+ implicitH: 0
28996
29141
  };
28997
29142
  }
28998
29143
  return {
28999
29144
  name: attachmentPointName,
29000
- atomLabel: atom.label
29145
+ atomLabel: atom.label,
29146
+ implicitH: atom.implicitH
29001
29147
  };
29002
29148
  });
29003
29149
  var ketcherEditorRootElement = document.querySelector(KETCHER_ROOT_NODE_CSS_SELECTOR);
@@ -29097,10 +29243,12 @@ var MonomerCreationWizard = function MonomerCreationWizard() {
29097
29243
  className: styles$l.attachmentPoints,
29098
29244
  children: attachmentPointsData.map(function (_ref5) {
29099
29245
  var name = _ref5.name,
29100
- atomLabel = _ref5.atomLabel;
29246
+ atomLabel = _ref5.atomLabel,
29247
+ implicitH = _ref5.implicitH;
29101
29248
  return jsx(AttachmentPoint, {
29102
29249
  name: name,
29103
- atomLabel: atomLabel
29250
+ atomLabel: atomLabel,
29251
+ implicitH: implicitH
29104
29252
  }, name);
29105
29253
  })
29106
29254
  })]
@@ -37111,8 +37259,8 @@ var KetcherBuilder = function () {
37111
37259
  cleanup = initApp(prevKetcherId, ketcherId, element, appRoot, staticResourcesUrl, {
37112
37260
  buttons: buttons || {},
37113
37261
  errorHandler: errorHandler || null,
37114
- version: "3.8.0-rc.2" ,
37115
- buildDate: "2025-09-05T18:59:48" ,
37262
+ version: "3.8.0-rc.4" ,
37263
+ buildDate: "2025-09-17T17:13:08" ,
37116
37264
  buildNumber: '',
37117
37265
  customButtons: customButtons || []
37118
37266
  }, structService, resolve, togglerComponent);
@@ -37407,7 +37555,7 @@ var ModeControl = function ModeControl(_ref3) {
37407
37555
  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; }
37408
37556
  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; }
37409
37557
  var MacromoleculesEditorComponent = lazy(function () {
37410
- return import('./index.modern-7694d091.js');
37558
+ return import('./index.modern-eb9aa0eb.js');
37411
37559
  });
37412
37560
  var Editor = function Editor(props) {
37413
37561
  var _useState = useState(false),