@datagrok/sequence-translator 1.10.8 → 1.10.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
3
  "friendlyName": "Sequence Translator",
4
- "version": "1.10.8",
4
+ "version": "1.10.9",
5
5
  "author": {
6
6
  "name": "Davit Rizhinashvili",
7
7
  "email": "drizhinashvili@datagrok.ai"
@@ -22,7 +22,7 @@
22
22
  }
23
23
  ],
24
24
  "dependencies": {
25
- "@datagrok-libraries/bio": "^5.61.6",
25
+ "@datagrok-libraries/bio": "^5.62.0",
26
26
  "@datagrok-libraries/chem-meta": "^1.2.8",
27
27
  "@datagrok-libraries/tutorials": "^1.6.1",
28
28
  "@datagrok-libraries/utils": "^4.6.5",
@@ -2,7 +2,6 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
- import {delay} from '@datagrok-libraries/test/src/test';
6
5
  import {PackageFunctions} from '../package';
7
6
  import {tryCatch} from '../apps/common/model/helpers';
8
7
 
@@ -23,7 +22,7 @@ export async function demoOligoPatternUI() {
23
22
  export async function demoOligoStructureUI() {
24
23
  await tryCatch(async () => {
25
24
  async function setInputValue(idx: number, sequence: string): Promise<void> {
26
- await delay(500);
25
+ await DG.delay(500);
27
26
  const textInputs: NodeListOf<HTMLTextAreaElement> = document.querySelectorAll('.st-colored-text-input > textarea');
28
27
  const textarea = textInputs[idx];
29
28
  textarea.value = sequence;
@@ -45,5 +45,4 @@ export const PT_ENUM_TYPE_TOOLTIPS: Record<string, string> = {
45
45
  'single': 'Each position is enumerated independently. Total results = sum of monomers across all positions.',
46
46
  'parallel': 'The i-th result uses the i-th monomer from every position (zip). All positions must have the same number of monomers. Total results = number of monomers per position.',
47
47
  'matrix': 'Cartesian product of all positions. Total results = product of monomer counts across all positions.',
48
- 'library': 'Substitutes all monomers from a selected library at a single position.',
49
48
  };
@@ -22,7 +22,6 @@ import {NOTATION} from '@datagrok-libraries/bio/src/utils/macromolecule';
22
22
  import {SeqTemps} from '@datagrok-libraries/bio/src/utils/macromolecule/seq-handler';
23
23
 
24
24
  import {PolyToolEnumeratorParams, PolyToolEnumeratorType, PolyToolEnumeratorTypes} from './types';
25
- import {getLibrariesList, LIB_PATH} from './utils';
26
25
  import {doPolyToolEnumerateHelm, PT_HELM_EXAMPLE} from './pt-enumeration-helm';
27
26
  import {PolyToolPlaceholdersInput} from './pt-placeholders-input';
28
27
  import {showMonomerSelectionDialog} from './pt-monomer-selection-dialog';
@@ -47,7 +46,7 @@ import {INotationProvider, NotationProviderBase} from '@datagrok-libraries/bio/s
47
46
  *
48
47
  * Provides the UI for enumerating macromolecule variants. The user selects positions
49
48
  * on a HELM molecule and specifies substitute monomers at each position. Supports
50
- * multiple enumeration strategies (Single, Parallel, Matrix, Library) and optional
49
+ * multiple enumeration strategies (Single, Parallel, Matrix) and optional
51
50
  * downstream processing (atomic-level conversion, chirality, rules).
52
51
  *
53
52
  * Architecture:
@@ -67,7 +66,6 @@ type PolyToolEnumerateInputs = {
67
66
  generateHelm: DG.InputBase<boolean>;
68
67
  chiralityEngine: DG.InputBase<boolean>;
69
68
  highlightMonomers: DG.InputBase<boolean>;
70
- library: DG.InputBase<string>;
71
69
  rules: { header: HTMLElement, form: HTMLDivElement },
72
70
  };
73
71
 
@@ -84,7 +82,6 @@ type PolyToolEnumerateHelmSerialized = {
84
82
  chiralityEngine: boolean;
85
83
  highlightMonomers: boolean;
86
84
  rules: string[],
87
- library: string;
88
85
  };
89
86
 
90
87
  /** Entry point: creates, sizes, and shows the enumeration dialog. */
@@ -163,7 +160,6 @@ async function getPolyToolEnumerateDialog(
163
160
  const logPrefix = `ST: PT: HelmDialog()`;
164
161
  let inputs: PolyToolEnumerateInputs;
165
162
  const subs: Unsubscribable[] = [];
166
- // Track previous enumeration type to clean up state when switching to/from Library mode
167
163
  let prevEnumerationType: PolyToolEnumeratorType = PolyToolEnumeratorTypes.Single;
168
164
  const destroy = () => {
169
165
  for (const sub of subs) sub.unsubscribe();
@@ -176,7 +172,7 @@ async function getPolyToolEnumerateDialog(
176
172
  const seqHelper = await getSeqHelper();
177
173
  const emptyDf: DG.DataFrame = DG.DataFrame.fromColumns([]);
178
174
 
179
- const [_libList, helmHelper] = await Promise.all([getLibrariesList(), getHelmHelper()]);
175
+ const helmHelper = await getHelmHelper();
180
176
  const monomerLibFuncs = helmHelper.buildMonomersFuncsFromLib(monomerLib);
181
177
 
182
178
  // Resolves the source macromolecule from the given cell or falls back to a default example.
@@ -310,7 +306,6 @@ async function getPolyToolEnumerateDialog(
310
306
  },
311
307
  nullable: true,
312
308
  }),
313
- library: ui.input.choice('Monomer Library', {items: _libList, value: _libList[0], nullable: true}) as DG.InputBase<string>,
314
309
  };
315
310
  // #### Inputs END
316
311
 
@@ -321,7 +316,6 @@ async function getPolyToolEnumerateDialog(
321
316
  };
322
317
  updateEnumTypeTooltip();
323
318
 
324
- inputs.library.root.style.setProperty('display', 'none');
325
319
  inputs.trivialNameCol.addOptions(trivialNameSampleDiv);
326
320
 
327
321
  // Wire up monomer cell double-click to open selection dialog
@@ -332,7 +326,7 @@ async function getPolyToolEnumerateDialog(
332
326
  const atom = mol.atoms[position];
333
327
  const helmType: HelmType = atom.biotype()!;
334
328
  const polymerType = helmTypeToPolymerType(helmType);
335
- return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers);
329
+ return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers, libHelper);
336
330
  };
337
331
 
338
332
  // Wire up breadth monomer cell double-click to open selection dialog
@@ -345,7 +339,7 @@ async function getPolyToolEnumerateDialog(
345
339
  const atom = mol.atoms[start];
346
340
  const helmType: HelmType = atom.biotype()!;
347
341
  const polymerType = helmTypeToPolymerType(helmType);
348
- return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers);
342
+ return showMonomerSelectionDialog(monomerLib, polymerType, currentMonomers, libHelper);
349
343
  };
350
344
 
351
345
  // === VALIDATORS ===
@@ -356,20 +350,6 @@ async function getPolyToolEnumerateDialog(
356
350
  const errors: string[] = [];
357
351
  setTimeout(() => { updateWarnings(); }, 100);
358
352
  try {
359
- // for library, ony one placeholder is allowed
360
- if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
361
- const pcs = inputs.placeholders.placeholdersValue;
362
- if (pcs.length > 1)
363
- placeholdersValidity = 'Only one placeholder is allowed for Library mode';
364
- if (pcs.length === 1) {
365
- if (pcs[0].position == null)
366
- placeholdersValidity = 'Position is required for Library mode';
367
- if (pcs[0].position > inputs.macromolecule.molValue.atoms.length)
368
- placeholdersValidity = `There is no monomer at position ${pcs[0].position + 1}.`;
369
- }
370
- return placeholdersValidity;
371
- }
372
-
373
353
  // Parallel mode: all placeholders must have the same monomer count
374
354
  if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Parallel) {
375
355
  const pcs = inputs.placeholders.placeholdersValue;
@@ -480,32 +460,7 @@ async function getPolyToolEnumerateDialog(
480
460
  // return placeholdersValidity;
481
461
  // });
482
462
 
483
- inputs.library.addValidator((_value) => {
484
- if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library && !inputs.library.value)
485
- return 'Monomer Library is required for this enumerator type';
486
- return null;
487
- });
488
-
489
- inputs.library.onChanged.subscribe(() => {
490
- if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library)
491
- inputs.placeholders.setMonomersValue(0, inputs.library.value ?? '');
492
- });
493
-
494
463
  inputs.enumeratorType.onChanged.subscribe((_) => {
495
- const isLibraryModeChosen = inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library;
496
- inputs.library.root.style.setProperty('display', isLibraryModeChosen ? 'flex' : 'none');
497
- try {
498
- if ((prevEnumerationType !== PolyToolEnumeratorTypes.Library && isLibraryModeChosen) || (prevEnumerationType === PolyToolEnumeratorTypes.Library && !isLibraryModeChosen)) {
499
- const prevSinglePosition = inputs.placeholders.placeholdersValue.length === 1 ? inputs.placeholders.placeholdersValue[0].position : null;
500
- // clear the placeHolders input and helm inputs if switching happened to/from Library mode
501
- inputs.placeholders.clearInput();
502
- inputs.placeholdersBreadth.clearInput();
503
- if (isLibraryModeChosen && prevSinglePosition != null)
504
- inputs.placeholders.addPosition(prevSinglePosition, inputs.library.value ?? '');
505
- }
506
- } catch (err: any) {
507
- defaultErrorHandler(err, false);
508
- }
509
464
  prevEnumerationType = inputs.enumeratorType.value;
510
465
  updateEnumTypeTooltip();
511
466
  // Re-validate placeholders (Parallel mode has different constraints than Single/Matrix)
@@ -550,13 +505,7 @@ async function getPolyToolEnumerateDialog(
550
505
  const clickedAtom = helmHelper.getHoveredAtom(argsX, argsY, mol, inputs.macromolecule.root.clientHeight);
551
506
  if (clickedAtom) {
552
507
  const clickedAtomContIdx = clickedAtom._parent.atoms.indexOf(clickedAtom);
553
- const clickedAtomContIdxStr = String(clickedAtomContIdx + 1);
554
- let monomerValue = '';
555
- if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
556
- inputs.placeholders.clearInput();
557
- monomerValue = inputs.library.value ?? '';
558
- }
559
- inputs.placeholders.addPosition(clickedAtomContIdx, monomerValue);
508
+ inputs.placeholders.addPosition(clickedAtomContIdx, '');
560
509
  }
561
510
  } catch (err: any) {
562
511
  defaultErrorHandler(err);
@@ -660,23 +609,10 @@ async function getPolyToolEnumerateDialog(
660
609
  updateViewRules();
661
610
 
662
611
  // === EXECUTION (OK button handler) ===
663
- // Pre-flight validates inputs, resolves Library mode, builds params, and runs enumeration.
612
+ // Pre-flight validates inputs, builds params, and runs enumeration.
664
613
  const exec = async (): Promise<void> => {
665
614
  try {
666
615
  const srcHelm = inputs.macromolecule.stringValue;
667
- const helmSelections = wu.enumerate<HelmAtom>(inputs.macromolecule.molValue.atoms)
668
- .filter(([a, aI]) => a.highlighted)
669
- .map(([a, aI]) => a).toArray();
670
- if (inputs.enumeratorType.value === PolyToolEnumeratorTypes.Library) {
671
- if (helmSelections.length === 0) {
672
- grok.shell.warning('PolyTool: position for enumeration was not selected');
673
- return;
674
- }
675
- if (!inputs.library.value) {
676
- grok.shell.warning('PolyTool: No monomer library was selected');
677
- return;
678
- }
679
- }
680
616
  if (srcHelm === undefined || srcHelm === '') {
681
617
  grok.shell.warning('PolyTool: no molecule was provided');
682
618
  } else {
@@ -689,28 +625,7 @@ async function getPolyToolEnumerateDialog(
689
625
  await getHelmHelper(); // initializes JSDraw and org
690
626
 
691
627
  const placeHoldersValue = inputs.placeholders.placeholdersValue;
692
- // Library mode: load all monomers from the selected library and convert to Single mode
693
- let enumerationType = inputs.enumeratorType.value;
694
- if (enumerationType === PolyToolEnumeratorTypes.Library) {
695
- if (placeHoldersValue.length !== 1) {
696
- grok.shell.warning('Only one placeholder is allowed for Library mode');
697
- return;
698
- }
699
- if (!placeHoldersValue[0].monomers || !_libList.includes(placeHoldersValue[0].monomers[0])) {
700
- grok.shell.warning('Valid Monomer Library is required for this enumerator type');
701
- return;
702
- }
703
- const monLibName = placeHoldersValue[0].monomers[0];
704
- const monLib = await libHelper.readSingleLibraryByName(monLibName);
705
- if (!monLib) {
706
- grok.shell.warning(`Monomer Library '${monLibName}' was not found`);
707
- return;
708
- }
709
- const polymerType = helmTypeToPolymerType(helmSelections[0].biotype() ?? 'HELM_AA');
710
- const peptideMonomers = monLib.getMonomerSymbolsByType(polymerType);
711
- placeHoldersValue[0].monomers = peptideMonomers;
712
- enumerationType = PolyToolEnumeratorTypes.Single;
713
- }
628
+ const enumerationType = inputs.enumeratorType.value;
714
629
 
715
630
  if (enumerationType === PolyToolEnumeratorTypes.Parallel) {
716
631
  const nonEmpty = placeHoldersValue.filter((ph) => ph.monomers.length > 0);
@@ -762,7 +677,7 @@ async function getPolyToolEnumerateDialog(
762
677
  .add(ui.divH([
763
678
  ui.divV([
764
679
  inputs.placeholders.root,
765
- inputs.enumeratorType.root, inputs.library.root],
680
+ inputs.enumeratorType.root],
766
681
  {style: {width: '50%'}}
767
682
  ),
768
683
  ui.divV([
@@ -810,7 +725,6 @@ async function getPolyToolEnumerateDialog(
810
725
  chiralityEngine: inputs.chiralityEngine.value,
811
726
  highlightMonomers: inputs.highlightMonomers.value,
812
727
  rules: ruleFileList,
813
- library: inputs.library.value,
814
728
  };
815
729
  },
816
730
  /* applyInput */ (x: PolyToolEnumerateHelmSerialized): void => {
@@ -825,7 +739,6 @@ async function getPolyToolEnumerateDialog(
825
739
  inputs.chiralityEngine.value = x.chiralityEngine ?? false;
826
740
  inputs.highlightMonomers.value = x.highlightMonomers ?? false;
827
741
  ruleInputs.setActive(x.rules);
828
- inputs.library.value = x.library;
829
742
  setTimeout(() => {
830
743
  inputs.placeholders.invalidateGrid();
831
744
  inputs.placeholdersBreadth.invalidateGrid();
@@ -3,17 +3,19 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {HelmType, PolymerType} from '@datagrok-libraries/bio/src/helm/types';
6
- import {IMonomerLib, Monomer} from '@datagrok-libraries/bio/src/types/monomer-library';
6
+ import {IMonomerLib, IMonomerLibHelper, Monomer} from '@datagrok-libraries/bio/src/types/monomer-library';
7
7
  import {polymerTypeToHelmType} from '@datagrok-libraries/bio/src/utils/macromolecule/utils';
8
8
 
9
9
  import {parseMonomerSymbolList} from './pt-placeholders-input';
10
10
 
11
11
  const MAX_SUGGESTIONS = 20;
12
12
 
13
- /** Shows a dialog for selecting monomers with autocomplete and tag-based display.
14
- * @returns comma-separated monomer symbols, or null if cancelled */
13
+ /** Shows a dialog for selecting monomers with autocomplete, tag-based display,
14
+ * and bulk-add from monomer libraries or collections.
15
+ * @returns monomer symbols array, or null if cancelled */
15
16
  export async function showMonomerSelectionDialog(
16
17
  monomerLib: IMonomerLib, polymerType: PolymerType, presetMonomers?: string[],
18
+ libHelper?: IMonomerLibHelper,
17
19
  ): Promise<string[] | null> {
18
20
  return new Promise<string[] | null>((resolve) => {
19
21
  const helmType: HelmType = polymerTypeToHelmType(polymerType);
@@ -21,11 +23,19 @@ export async function showMonomerSelectionDialog(
21
23
 
22
24
  const selectedMonomers: string[] = presetMonomers ? [...presetMonomers] : [];
23
25
 
24
- const tagsHost = ui.div([], {style: {display: 'flex', flexWrap: 'wrap', gap: '4px', marginTop: '8px', maxWidth: '400px'}});
25
- const input = ui.input.string('Monomers', {value: ''});
26
+ // --- Tags display (selected monomers) ---
27
+ const tagsHost = ui.div([], {style: {display: 'flex', flexWrap: 'wrap', gap: '4px', marginTop: '4px', maxHeight: '150px', overflowY: 'auto'}});
28
+ const countLabel = ui.divText('', {style: {fontSize: '11px', color: 'var(--grey-4)', marginTop: '4px'}});
29
+
30
+ function updateCountLabel(): void {
31
+ countLabel.textContent = selectedMonomers.length > 0 ? `${selectedMonomers.length} monomer(s) selected` : '';
32
+ }
33
+
34
+ // --- Autocomplete input ---
35
+ const input = ui.input.string('Search', {value: ''});
26
36
  const inputEl = input.input as HTMLInputElement;
27
37
  inputEl.setAttribute('autocomplete', 'off');
28
- inputEl.placeholder = 'Type to search...';
38
+ inputEl.placeholder = 'Type to search monomers...';
29
39
 
30
40
  let currentMenu: DG.Menu | null = null;
31
41
  let menuItems: HTMLElement[] = [];
@@ -39,6 +49,7 @@ export async function showMonomerSelectionDialog(
39
49
  if (idx >= 0) {
40
50
  selectedMonomers.splice(idx, 1);
41
51
  renderTags();
52
+ updateCountLabel();
42
53
  }
43
54
  });
44
55
  removeBtn.style.marginLeft = '4px';
@@ -53,7 +64,7 @@ export async function showMonomerSelectionDialog(
53
64
  },
54
65
  });
55
66
  // Tooltip on hover
56
- tag.addEventListener('mouseenter', (e) => {
67
+ tag.addEventListener('mouseenter', () => {
57
68
  const tooltip = monomerLib.getTooltip(helmType, symbol);
58
69
  ui.tooltip.show(tooltip, tag.getBoundingClientRect().left, tag.getBoundingClientRect().bottom + 16);
59
70
  });
@@ -61,6 +72,7 @@ export async function showMonomerSelectionDialog(
61
72
 
62
73
  tagsHost.appendChild(tag);
63
74
  }
75
+ updateCountLabel();
64
76
  }
65
77
 
66
78
  function addMonomer(symbol: string): void {
@@ -73,6 +85,18 @@ export async function showMonomerSelectionDialog(
73
85
  inputEl.focus();
74
86
  }
75
87
 
88
+ function addMonomers(symbols: string[]): void {
89
+ let added = false;
90
+ for (const symbol of symbols) {
91
+ if (!selectedMonomers.includes(symbol)) {
92
+ selectedMonomers.push(symbol);
93
+ added = true;
94
+ }
95
+ }
96
+ if (added)
97
+ renderTags();
98
+ }
99
+
76
100
  function hideMenu(): void {
77
101
  if (currentMenu) {
78
102
  currentMenu.hide();
@@ -222,14 +246,105 @@ export async function showMonomerSelectionDialog(
222
246
  }
223
247
  });
224
248
 
249
+ // --- Bulk add: from monomer library ---
250
+ const librarySection = ui.div([], {style: {marginTop: '8px'}});
251
+ if (libHelper) {
252
+ const libraryInput = ui.input.choice('Add from library', {items: [] as string[], nullable: true}) as DG.ChoiceInput<string>;
253
+ const libraryStatus = ui.divText('', {style: {fontSize: '11px', color: 'var(--green-2)', marginLeft: '8px', minHeight: '16px'}});
254
+
255
+ // Load library names asynchronously
256
+ libHelper.getAvaliableLibraryNames().then((libNames) => {
257
+ libraryInput.items = libNames;
258
+ });
259
+
260
+ libraryInput.onChanged.subscribe(async () => {
261
+ const libName = libraryInput.value;
262
+ if (!libName)
263
+ return;
264
+
265
+ libraryStatus.textContent = 'Loading...';
266
+ try {
267
+ const lib = await libHelper.readSingleLibraryByName(libName);
268
+ if (lib) {
269
+ const symbols = lib.getMonomerSymbolsByType(polymerType);
270
+ const before = selectedMonomers.length;
271
+ addMonomers(symbols);
272
+ const added = selectedMonomers.length - before;
273
+ libraryStatus.textContent = `Added ${added} monomer(s) from "${libName}"`;
274
+ } else {
275
+ libraryStatus.textContent = `Library "${libName}" not found`;
276
+ }
277
+ } catch (err: any) {
278
+ libraryStatus.textContent = `Error loading library`;
279
+ }
280
+ // Clear the selector after use
281
+ libraryInput.value = null as any;
282
+ setTimeout(() => { libraryStatus.textContent = ''; }, 4000);
283
+ });
284
+
285
+ librarySection.appendChild(ui.divV([libraryInput.root, libraryStatus]));
286
+ }
287
+
288
+ // --- Bulk add: from monomer collection ---
289
+ const collectionSection = ui.div([], {style: {marginTop: '4px'}});
290
+ if (libHelper) {
291
+ const collectionInput = ui.input.choice('Add from collection', {items: [] as string[], nullable: true}) as DG.ChoiceInput<string>;
292
+ const collectionStatus = ui.divText('', {style: {fontSize: '11px', color: 'var(--green-2)', marginLeft: '8px', minHeight: '16px'}});
293
+
294
+ // Load collection names asynchronously
295
+ libHelper.listMonomerCollections().then((collectionNames) => {
296
+ collectionInput.items = collectionNames;
297
+ });
298
+
299
+ collectionInput.onChanged.subscribe(async () => {
300
+ const collectionName = collectionInput.value;
301
+ if (!collectionName)
302
+ return;
303
+
304
+ collectionStatus.textContent = 'Loading...';
305
+ try {
306
+ const collection = await libHelper.readMonomerCollection(collectionName);
307
+ const symbols = collection.monomerSymbols ?? [];
308
+ const before = selectedMonomers.length;
309
+ addMonomers(symbols);
310
+ const added = selectedMonomers.length - before;
311
+ const displayName = collectionName.replace(/\.json$/, '');
312
+ collectionStatus.textContent = `Added ${added} monomer(s) from "${displayName}"`;
313
+ } catch (err: any) {
314
+ collectionStatus.textContent = `Error loading collection`;
315
+ }
316
+ // Clear the selector after use
317
+ collectionInput.value = null as any;
318
+ setTimeout(() => { collectionStatus.textContent = ''; }, 4000);
319
+ });
320
+
321
+ collectionSection.appendChild(ui.divV([collectionInput.root, collectionStatus]));
322
+ }
323
+
324
+ // --- Clear all button ---
325
+ const clearBtn = ui.button('Clear all', () => {
326
+ selectedMonomers.length = 0;
327
+ renderTags();
328
+ });
329
+ clearBtn.style.fontSize = '11px';
330
+ clearBtn.style.marginTop = '4px';
331
+
225
332
  renderTags();
226
333
 
227
- const dlg = ui.dialog({title: 'Select Monomers', showFooter: true})
228
- .add(ui.div([input.root, tagsHost], {style: {minWidth: '350px', minHeight: '200px'}}))
334
+ // --- Dialog layout ---
335
+ const contentDiv = ui.div([
336
+ input.root,
337
+ librarySection,
338
+ collectionSection,
339
+ ui.divH([countLabel, clearBtn], {style: {justifyContent: 'space-between', alignItems: 'center'}}),
340
+ tagsHost,
341
+ ], {style: {minWidth: '400px', minHeight: '250px'}});
342
+
343
+ const _dlg = ui.dialog({title: 'Select Monomers', showFooter: true})
344
+ .add(contentDiv)
229
345
  .onOK(() => { resolve(selectedMonomers); })
230
346
  .onCancel(() => { resolve(null); })
231
347
  .show({resizable: true});
232
- // dlg.root.addEventListener('close', () => { hideMenu(); });
233
348
 
234
349
  inputEl.focus();
235
350
  setTimeout(() => { showSuggestions(); }, 0);
@@ -8,7 +8,6 @@ export enum PolyToolEnumeratorTypes {
8
8
  Single = 'single',
9
9
  Parallel = 'parallel',
10
10
  Matrix = 'matrix',
11
- Library = 'library',
12
11
  }
13
12
 
14
13
  export type PolyToolEnumeratorType = typeof PolyToolEnumeratorTypes[keyof typeof PolyToolEnumeratorTypes];