@talrace/ngx-noder 0.0.43 → 0.0.44

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.
Files changed (33) hide show
  1. package/fesm2022/talrace-ngx-noder.mjs +925 -303
  2. package/fesm2022/talrace-ngx-noder.mjs.map +1 -1
  3. package/lib/apart-components/editor-search-bar/editor-search-bar.component.d.ts +1 -0
  4. package/lib/editor/components/edges/edge-element.model.d.ts +3 -2
  5. package/lib/editor/components/edges/edge.component.d.ts +3 -1
  6. package/lib/editor/components/edges/edges.d.ts +9 -6
  7. package/lib/editor/components/shared/abstract/base.component.d.ts +3 -0
  8. package/lib/editor/components/shared/enums/line-styles.enum.d.ts +36 -0
  9. package/lib/editor/components/shared/enums/positions.enum.d.ts +9 -0
  10. package/lib/editor/components/table/components/table-cell.component.d.ts +6 -2
  11. package/lib/editor/components/table/helpers/table-cell.helper.d.ts +7 -0
  12. package/lib/editor/content/display-data/display-data.d.ts +1 -0
  13. package/lib/editor/display/custom-element-info.model.d.ts +8 -0
  14. package/lib/editor/display/layers/edges.layer.d.ts +1 -1
  15. package/lib/editor/display/layers/highlight.layer.d.ts +2 -0
  16. package/lib/editor/display/layers/layer.config.d.ts +1 -0
  17. package/lib/editor/display/layers/search-highlight.layer.d.ts +5 -1
  18. package/lib/editor/display/render-changes.interface.d.ts +1 -0
  19. package/lib/editor/display/render-changes.model.d.ts +1 -0
  20. package/lib/editor/display/renderer.d.ts +7 -1
  21. package/lib/editor/display/virtual.renderer.d.ts +6 -1
  22. package/lib/editor/execution/edit.session.d.ts +5 -2
  23. package/lib/editor/execution/editor.d.ts +3 -2
  24. package/lib/editor/execution/regulator.service.d.ts +3 -1
  25. package/lib/editor/gadgets/search/custom-element-search-result.model.d.ts +9 -0
  26. package/lib/editor/gadgets/search/search-result-location.model.d.ts +8 -0
  27. package/lib/editor/gadgets/search/search-result.model.d.ts +8 -0
  28. package/lib/editor/gadgets/search/search.d.ts +20 -8
  29. package/lib/editor/gadgets/search/table-location.interface.d.ts +6 -0
  30. package/lib/editor/interaction/editor.service.d.ts +3 -1
  31. package/package.json +1 -1
  32. package/public-api.d.ts +2 -0
  33. package/lib/editor/gadgets/search/search-result.interface.d.ts +0 -5
@@ -390,6 +390,94 @@ class FormatStyleHelper {
390
390
  }
391
391
  }
392
392
 
393
+ class FontMetrics {
394
+ static { this.storageKey = 'metrics'; }
395
+ static { this.versionKey = 'editorVersion'; }
396
+ /**
397
+ * Key value pairs for calculated sizes of char symbols in HTML element
398
+ */
399
+ static { this.metrics = JSON.parse(localStorage.getItem(this.storageKey)) || {}; }
400
+ /**
401
+ * Key value pairs for identifiers and font strings
402
+ */
403
+ static { this.fontStringMap = {}; }
404
+ static checkVersion(version) {
405
+ let identifier = localStorage.getItem(this.versionKey);
406
+ if (identifier === version) {
407
+ return;
408
+ }
409
+ localStorage.removeItem(this.storageKey);
410
+ localStorage.setItem(this.versionKey, version);
411
+ }
412
+ static measureCharSize(ch, contentStyle) {
413
+ let identifier = this.fontStringMap[contentStyle];
414
+ if (!identifier) {
415
+ identifier = contentStyle.split(' ').join('_');
416
+ this.fontStringMap[contentStyle] = identifier;
417
+ }
418
+ this.metrics[identifier] ??= {};
419
+ if (!this.metrics[identifier][ch] || isNaN(this.metrics[identifier][ch].font)) {
420
+ this.metrics[identifier][ch] = this.calculateCanvas(ch, contentStyle);
421
+ localStorage.setItem(this.storageKey, JSON.stringify(this.metrics));
422
+ }
423
+ return this.metrics[identifier][ch];
424
+ }
425
+ static calculateCanvas(ch, contentStyle) {
426
+ this.canvasNode ||= document.createElement('canvas');
427
+ const fontBaseLine = this.fontBaseline(contentStyle, ch);
428
+ const context = this.canvasNode.getContext('2d');
429
+ context.font = contentStyle;
430
+ const textMetrics = context.measureText(ch);
431
+ return {
432
+ width: textMetrics.width,
433
+ height: textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent,
434
+ baseline: fontBaseLine.baseline,
435
+ content: fontBaseLine.content,
436
+ font: fontBaseLine.font,
437
+ line: fontBaseLine.line,
438
+ multiplier: fontBaseLine.multiplier,
439
+ ascent: textMetrics.fontBoundingBoxAscent,
440
+ descent: textMetrics.fontBoundingBoxDescent
441
+ };
442
+ }
443
+ static fontBaseline(contentStyle, text) {
444
+ const container = document.body;
445
+ this.measureDiv ||= document.createElement('div');
446
+ this.strut ||= document.createElement('span');
447
+ if (text === ' ') {
448
+ text = 'X';
449
+ }
450
+ this.measureDiv.style.font = contentStyle;
451
+ this.measureDiv.style.lineHeight = '1';
452
+ this.measureDiv.style.position = 'absolute';
453
+ this.measureDiv.style.visibility = 'hidden';
454
+ this.measureDiv.style.margin = '0';
455
+ this.measureDiv.style.padding = '0';
456
+ this.measureDiv.innerHTML = text;
457
+ this.strut.style.fontSize = '0';
458
+ this.strut.style.verticalAlign = 'baseline';
459
+ this.strut.style.padding = '0 10px';
460
+ this.measureDiv.classList.add('font-baseline');
461
+ this.measureDiv.appendChild(this.strut);
462
+ container.appendChild(this.measureDiv);
463
+ const computedStyle = window.getComputedStyle(this.measureDiv);
464
+ const fontSize = parseFloat(computedStyle.fontSize);
465
+ const baselineHeight = fontSize - this.strut.offsetTop;
466
+ const strutHeight = this.measureDiv.offsetHeight;
467
+ const lineHeight = parseFloat(computedStyle.lineHeight) || this.measureDiv.offsetHeight;
468
+ this.measureDiv.parentNode.removeChild(this.measureDiv);
469
+ this.measureDiv.innerHTML = '';
470
+ this.strut.innerHTML = '';
471
+ return {
472
+ baseline: baselineHeight,
473
+ content: strutHeight,
474
+ font: fontSize,
475
+ line: lineHeight,
476
+ multiplier: fontSize / baselineHeight
477
+ };
478
+ }
479
+ }
480
+
393
481
  class ElementDataModel {
394
482
  constructor(id, guid, type) {
395
483
  this.id = id;
@@ -835,8 +923,8 @@ class EditorService {
835
923
  changedTableSize(insertIndex, sessionId) {
836
924
  this._changedTableSize$.next({ insertIndex, sessionId });
837
925
  }
838
- changedEdgeSize(edgeType, pageType) {
839
- this._changedEdgeSize$.next({ edgeType, pageType });
926
+ changedEdgeSize(edgeType, pageType, pageWidth, pageHeight) {
927
+ this._changedEdgeSize$.next({ edgeType, pageType, pageWidth, pageHeight });
840
928
  }
841
929
  imageLoaded(sessionId) {
842
930
  this._imageLoaded$.next(sessionId);
@@ -975,6 +1063,12 @@ class BaseNoderComponent extends DestroyComponent {
975
1063
  requestStyle() {
976
1064
  this.editorService.receiveTextStyle(this);
977
1065
  }
1066
+ searchComponent(_) {
1067
+ return 0;
1068
+ }
1069
+ getSearchResultLocations() {
1070
+ return [];
1071
+ }
978
1072
  rerender() {
979
1073
  this.editorService.rerender(this.insertIndex);
980
1074
  }
@@ -1266,6 +1360,12 @@ class CreateEdgesModel {
1266
1360
  }
1267
1361
  }
1268
1362
 
1363
+ class CustomElementSearchResult {
1364
+ constructor(init) {
1365
+ Object.assign(this, init);
1366
+ }
1367
+ }
1368
+
1269
1369
  class DeleteModel {
1270
1370
  constructor(fields) {
1271
1371
  if (fields) {
@@ -5222,11 +5322,11 @@ class EdgeElementModel {
5222
5322
  }
5223
5323
  Object.assign(this, fields);
5224
5324
  }
5225
- isNotCopy(type, pageType) {
5226
- return this.edgeType === type && this.pageType === pageType && this.isOrigin;
5325
+ isNotCopy(type, pageType, pageWidth) {
5326
+ return this.edgeType === type && this.pageType === pageType && this.pageWidth === pageWidth && this.isOrigin;
5227
5327
  }
5228
- isCopy(type, pageType) {
5229
- return this.edgeType === type && this.pageType === pageType && !this.isOrigin;
5328
+ isCopy(type, pageType, pageWidth) {
5329
+ return this.edgeType === type && this.pageType === pageType && this.pageWidth === pageWidth && !this.isOrigin;
5230
5330
  }
5231
5331
  isWithin(start, end) {
5232
5332
  return this.container.offsetTop < end && this.container.offsetTop + this.container.offsetHeight > start;
@@ -5484,14 +5584,14 @@ class EdgesLayer {
5484
5584
  this.element.className = 'noder-layer noder-edges-layer';
5485
5585
  this.parentElement.appendChild(this.element);
5486
5586
  }
5487
- updateSingle(type, pageType) {
5587
+ updateSingle(type, pageType, pageWidth) {
5488
5588
  const pages = [];
5489
- let index = this.elements.findIndex(x => x.isCopy(type, pageType));
5589
+ let index = this.elements.findIndex(x => x.isCopy(type, pageType, pageWidth));
5490
5590
  while (index !== -1) {
5491
5591
  pages.push(this.elements[index].page);
5492
5592
  DomHelper.removeElement(this.elements[index].container);
5493
5593
  this.elements.splice(index, 1);
5494
- index = this.elements.findIndex(x => x.isCopy(type, pageType));
5594
+ index = this.elements.findIndex(x => x.isCopy(type, pageType, pageWidth));
5495
5595
  }
5496
5596
  const start = -this.element.offsetTop;
5497
5597
  const end = start + this.parentElement.clientHeight;
@@ -5503,7 +5603,7 @@ class EdgesLayer {
5503
5603
  this.renderPageFooterComponent(page, start, end);
5504
5604
  }
5505
5605
  }
5506
- let origin = this.elements.find(x => x.isNotCopy(type, pageType));
5606
+ let origin = this.elements.find(x => x.isNotCopy(type, pageType, pageWidth));
5507
5607
  if (origin) {
5508
5608
  const edge = this.session.customComponents.edges.getComponentByPageType(pageType, type);
5509
5609
  const height = this.session.customComponents.edges.getComponentHeight(edge.instance);
@@ -5536,7 +5636,7 @@ class EdgesLayer {
5536
5636
  while (removeIndex !== -1) {
5537
5637
  const element = this.elements[removeIndex];
5538
5638
  if (element.isOrigin) {
5539
- const copy = this.elements.find(x => x.isCopy(element.edgeType, element.pageType));
5639
+ const copy = this.elements.find(x => x.isCopy(element.edgeType, element.pageType, element.pageWidth));
5540
5640
  if (copy) {
5541
5641
  copy.substitute(element);
5542
5642
  }
@@ -5559,7 +5659,8 @@ class EdgesLayer {
5559
5659
  return paragraphTop + this.session.displayData.calculateHeightForPage(page - 1);
5560
5660
  }
5561
5661
  renderPageHeaderComponent(page, start, end) {
5562
- const header = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Header);
5662
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5663
+ const header = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Header, pageFormat.pageWidth);
5563
5664
  if (header) {
5564
5665
  const height = this.session.customComponents.edges.getComponentHeight(header.instance);
5565
5666
  const edgeTop = this.getEdgeTop(0, page);
@@ -5570,11 +5671,11 @@ class EdgesLayer {
5570
5671
  }
5571
5672
  }
5572
5673
  renderPageFooterComponent(page, start, end) {
5573
- const footer = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Footer);
5574
- const pageFormat = this.session.displayData.getPageFormatByPageNumber(page);
5674
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5675
+ const footer = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Footer, pageFormat.pageWidth);
5575
5676
  if (footer) {
5576
5677
  const height = this.session.customComponents.edges.getComponentHeight(footer.instance);
5577
- const topOffset = pageFormat.pageFormatModel.pageHeight - height;
5678
+ const topOffset = pageFormat.pageHeight - height;
5578
5679
  const edgeTop = this.getEdgeTop(topOffset, page);
5579
5680
  if (edgeTop > end || edgeTop + height < start) {
5580
5681
  return;
@@ -5584,24 +5685,30 @@ class EdgesLayer {
5584
5685
  }
5585
5686
  renderEdgeComponent(component, edgeHeight, page, edgeTop) {
5586
5687
  const container = RenderingHelper.createDivContainer('noder-edge-group');
5587
- const pageFormat = this.session.displayData.getPageFormatByPageNumber(page);
5588
- const offsetForLittlePages = (this.session.displayData.maxPageWidth - pageFormat.pageFormatModel.pageWidth) / 2;
5688
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5689
+ const offsetForLittlePages = (this.session.displayData.maxPageWidth - pageFormat.pageWidth) / 2;
5589
5690
  DomHelper.setStyle(container.style, 'height', `${edgeHeight}px`);
5590
5691
  DomHelper.setStyle(container.style, 'top', `${edgeTop}px`);
5591
5692
  DomHelper.setStyle(container.style, 'margin-left', `${offsetForLittlePages}px`);
5592
5693
  DomHelper.setStyle(container.style, 'margin-right', `${offsetForLittlePages}px`);
5593
5694
  const componentElement = component.hostView.rootNodes[0];
5594
5695
  const edge = component.instance;
5595
- edge.setPageWidth(pageFormat.pageFormatModel.pageWidth);
5596
- edge.width = pageFormat.pageFormatModel.pageWidth;
5597
- const isOrigin = !this.elements.some(x => x.isNotCopy(edge.type, edge.model.pageType));
5696
+ edge.width = pageFormat.pageWidth;
5697
+ const isOrigin = !this.elements.some(x => x.isNotCopy(edge.type, edge.model.pageType, pageFormat.pageWidth));
5598
5698
  const element = isOrigin ? componentElement : componentElement.cloneNode(true);
5599
5699
  container.appendChild(element);
5600
5700
  this.element.appendChild(container);
5601
- const model = new EdgeElementModel({ page, container, pageType: edge.model.pageType, edgeType: edge.type, isOrigin });
5701
+ const model = new EdgeElementModel({
5702
+ page,
5703
+ container,
5704
+ pageType: edge.model.pageType,
5705
+ edgeType: edge.type,
5706
+ isOrigin,
5707
+ pageWidth: pageFormat.pageWidth
5708
+ });
5602
5709
  this.elements.push(model);
5603
5710
  if (!isOrigin) {
5604
- element.onmouseenter = () => model.replace(this.elements.find(x => x.isNotCopy(model.edgeType, model.pageType)));
5711
+ element.onmouseenter = () => model.replace(this.elements.find(x => x.isNotCopy(model.edgeType, model.pageType, pageFormat.pageWidth)));
5605
5712
  }
5606
5713
  }
5607
5714
  }
@@ -6208,7 +6315,8 @@ class PrintRenderer {
6208
6315
  maxHeight,
6209
6316
  offset: 0,
6210
6317
  pages,
6211
- scrollTop: 0
6318
+ scrollTop: 0,
6319
+ isVisible: true
6212
6320
  };
6213
6321
  }
6214
6322
  createContent() {
@@ -6708,72 +6816,128 @@ class SaveCommandsHelper {
6708
6816
  }
6709
6817
  }
6710
6818
 
6711
- class Search {
6712
- constructor() {
6713
- this.term = '';
6819
+ class CustomElementInfo {
6820
+ constructor(init) {
6821
+ Object.assign(this, init);
6822
+ }
6823
+ }
6824
+
6825
+ class SearchResult {
6826
+ constructor(init) {
6827
+ Object.assign(this, init);
6828
+ }
6829
+ }
6830
+
6831
+ class SessionModel {
6832
+ constructor(session, renderer, sessionId, parentSessionId, source) {
6833
+ this.session = session;
6834
+ this.renderer = renderer;
6835
+ this.sessionId = sessionId;
6836
+ this.parentSessionId = parentSessionId;
6837
+ this.source = source;
6714
6838
  }
6839
+ }
6840
+
6841
+ class Search {
6715
6842
  get currentMatchIndex() {
6716
6843
  return this.currentIndex + 1;
6717
6844
  }
6718
6845
  get currentMatch() {
6719
6846
  return this.currentIndex < 0 ? null : this.allMatches[this.currentIndex];
6720
6847
  }
6721
- setSearchTerm(term) {
6722
- this.term = term;
6848
+ constructor(editorService) {
6849
+ this.editorService = editorService;
6850
+ this.term = '';
6723
6851
  }
6724
- findAll(sessions) {
6852
+ findAll(sessions, term) {
6725
6853
  this.allMatches = [];
6854
+ this.searchedSessionIds = [];
6855
+ this.danglingSessions = [];
6856
+ this.tables = [];
6857
+ this.term = term;
6858
+ if (!term?.length) {
6859
+ for (const session of sessions) {
6860
+ session.renderer.updateSearchHighlights([]);
6861
+ session.renderer.updateActiveSearchHighlight(null);
6862
+ session.renderer.updateCustomElementHighlights([]);
6863
+ }
6864
+ this.editorService.setSearchResultCount(0);
6865
+ return;
6866
+ }
6726
6867
  this.assembleRegExp(this.term);
6727
6868
  if (!this.regex) {
6728
6869
  return;
6729
6870
  }
6730
- for (const { session, sessionId, renderer } of sessions) {
6731
- const sessionHighlights = [];
6732
- for (let i = 0; i < session.displayData.paragraphs.length; i++) {
6733
- const paragraph = session.displayData.paragraphs[i];
6734
- const matches = paragraph.content.matchAll(this.regex);
6735
- for (const match of matches) {
6736
- const range = new Range(new CursorParagraph(i, match.index), new CursorParagraph(i, match.index + match[0].length));
6737
- this.allMatches.push({ sessionId, range });
6738
- sessionHighlights.push(range);
6739
- }
6871
+ const mainSession = sessions[0];
6872
+ this.searchContent(mainSession, sessions);
6873
+ const unsearchedSessions = sessions.filter(x => !this.searchedSessionIds.includes(x.sessionId));
6874
+ for (const session of unsearchedSessions) {
6875
+ if (this.tables.some(x => x.tableSessions.includes(session.sessionId))) {
6876
+ continue;
6740
6877
  }
6741
- renderer.updateSearchHighlights(sessionHighlights);
6878
+ this.danglingSessions.push(session.sessionId);
6879
+ this.searchContent(session, sessions, 'outsideMainSession');
6742
6880
  }
6881
+ this.editorService.setSearchResultCount(this.allMatches.length);
6743
6882
  if (!this.allMatches.length) {
6744
6883
  this.currentIndex = -1;
6745
- return;
6746
6884
  }
6747
- this.currentIndex = this.currentIndex > this.allMatches.length - 1 ? this.allMatches.length - 1 : this.currentIndex;
6885
+ else {
6886
+ this.currentIndex = this.currentIndex > this.allMatches.length - 1 ? this.allMatches.length - 1 : this.currentIndex;
6887
+ }
6888
+ this.updateActiveSearchHighlight(sessions);
6748
6889
  }
6749
- goNext(selection, currentSessionId) {
6890
+ goNext(selection, currentSessionId, sessions) {
6750
6891
  if (!this.allMatches?.length) {
6751
6892
  return;
6752
6893
  }
6753
- let newIndex = this.allMatches.findIndex(x => (x.sessionId === currentSessionId &&
6754
- x.range.start.row === selection.cursor.row &&
6755
- x.range.start.column > selection.cursor.column) ||
6756
- (x.sessionId === currentSessionId && x.range.start.row > selection.cursor.row) ||
6757
- x.sessionId > currentSessionId);
6758
- this.currentIndex = newIndex < 0 ? 0 : newIndex;
6894
+ const resultsAtCursor = this.allMatches.reduce((acc, match, index) => {
6895
+ if (match.sessionId === currentSessionId && match.range.contains(selection.cursor)) {
6896
+ acc.push(index);
6897
+ }
6898
+ return acc;
6899
+ }, []);
6900
+ if (resultsAtCursor.length) {
6901
+ const nextResultIndex = resultsAtCursor.findIndex(x => x === this.currentIndex) + 1;
6902
+ if (nextResultIndex < resultsAtCursor.length) {
6903
+ this.currentIndex = resultsAtCursor[nextResultIndex];
6904
+ }
6905
+ else {
6906
+ const nextIndex = resultsAtCursor[resultsAtCursor.length - 1] + 1;
6907
+ this.currentIndex = nextIndex > this.allMatches.length - 1 ? 0 : nextIndex;
6908
+ }
6909
+ this.updateActiveSearchHighlight(sessions);
6910
+ return;
6911
+ }
6912
+ const nextIndex = this.findNextAfterCursor(selection.cursor, currentSessionId);
6913
+ this.currentIndex = nextIndex < 0 ? 0 : nextIndex;
6914
+ this.updateActiveSearchHighlight(sessions);
6759
6915
  }
6760
- goPrevious(selection, currentSessionId) {
6916
+ goPrevious(selection, currentSessionId, sessions) {
6761
6917
  if (!this.allMatches?.length) {
6762
6918
  return;
6763
6919
  }
6764
- let prevIndex = -1;
6765
- for (let i = this.allMatches.length - 1; i >= 0; i--) {
6766
- const match = this.allMatches[i];
6767
- if ((match.sessionId === currentSessionId &&
6768
- match.range.start.row === selection.cursor.row &&
6769
- match.range.start.column < selection.cursor.column) ||
6770
- (match.sessionId === currentSessionId && match.range.start.row < selection.cursor.row) ||
6771
- match.sessionId < currentSessionId) {
6772
- prevIndex = i;
6773
- break;
6920
+ const resultsAtCursor = this.allMatches.reduce((acc, match, index) => {
6921
+ if (match.sessionId === currentSessionId && match.range.contains(selection.cursor)) {
6922
+ acc.push(index);
6923
+ }
6924
+ return acc;
6925
+ }, []);
6926
+ if (resultsAtCursor.length) {
6927
+ const nextResultIndex = resultsAtCursor.findIndex(x => x === this.currentIndex) - 1;
6928
+ if (nextResultIndex >= 0) {
6929
+ this.currentIndex = resultsAtCursor[nextResultIndex];
6930
+ }
6931
+ else {
6932
+ const nextIndex = resultsAtCursor[0] - 1;
6933
+ this.currentIndex = nextIndex < 0 ? this.allMatches.length - 1 : nextIndex;
6774
6934
  }
6935
+ this.updateActiveSearchHighlight(sessions);
6936
+ return;
6775
6937
  }
6938
+ const prevIndex = this.findPreviousBeforeCursor(selection.cursor, currentSessionId);
6776
6939
  this.currentIndex = prevIndex >= 0 ? prevIndex : this.allMatches.length - 1;
6940
+ this.updateActiveSearchHighlight(sessions);
6777
6941
  }
6778
6942
  assembleRegExp(term) {
6779
6943
  if (!term) {
@@ -6787,6 +6951,203 @@ class Search {
6787
6951
  this.regex = null;
6788
6952
  }
6789
6953
  }
6954
+ searchContent(currentSession, allSessions, mainSessionPosition = null) {
6955
+ this.searchedSessionIds.push(currentSession.sessionId);
6956
+ const sessionHighlights = [];
6957
+ const customElementHighlights = [];
6958
+ for (let i = 0; i < currentSession.session.displayData.paragraphs.length; i++) {
6959
+ const paragraph = currentSession.session.displayData.paragraphs[i];
6960
+ const paragraphTables = this.checkForTables(paragraph, currentSession, allSessions, i);
6961
+ const paragraphCustomElements = this.checkForCustomElements(paragraph, currentSession);
6962
+ const matches = paragraph.content.matchAll(this.regex);
6963
+ const paragraphMatches = [];
6964
+ for (const match of matches) {
6965
+ paragraphMatches.push({ index: match.index, content: match });
6966
+ }
6967
+ const paragraphContent = [...paragraphTables, ...paragraphCustomElements, ...paragraphMatches].sort((x, y) => x.index - y.index);
6968
+ for (const container of paragraphContent) {
6969
+ if (container.content instanceof BaseNoderComponent) {
6970
+ const parentRange = new Range(new CursorParagraph(i, container.index), new CursorParagraph(i, container.index + 1));
6971
+ const customElementMatches = container.content.searchComponent(this.regex);
6972
+ for (let matchIndex = 0; matchIndex < customElementMatches; matchIndex++) {
6973
+ this.allMatches.push(new CustomElementSearchResult({
6974
+ sessionId: currentSession.sessionId,
6975
+ range: parentRange,
6976
+ mainSessionPosition: mainSessionPosition ?? new CursorParagraph(i, container.index)
6977
+ }));
6978
+ customElementHighlights.push(new CustomElementInfo({ index: matchIndex, parentRange }));
6979
+ }
6980
+ continue;
6981
+ }
6982
+ if (Array.isArray(container.content) && container.content.every(x => x instanceof SessionModel)) {
6983
+ for (const session of container.content) {
6984
+ this.searchContent(session, allSessions, mainSessionPosition ?? new CursorParagraph(i, container.index));
6985
+ }
6986
+ continue;
6987
+ }
6988
+ const match = container.content;
6989
+ if (paragraphTables.some(x => x.index >= match.index && x.index <= match.index + match[0].length) ||
6990
+ paragraphCustomElements.some(x => x.index >= match.index && x.index <= match.index + match[0].length)) {
6991
+ continue;
6992
+ }
6993
+ const range = new Range(new CursorParagraph(i, match.index), new CursorParagraph(i, match.index + match[0].length));
6994
+ this.allMatches.push(new SearchResult({
6995
+ sessionId: currentSession.sessionId,
6996
+ range,
6997
+ mainSessionPosition: mainSessionPosition ?? new CursorParagraph(i, match.index)
6998
+ }));
6999
+ sessionHighlights.push(range);
7000
+ }
7001
+ }
7002
+ currentSession.renderer.updateSearchHighlights(sessionHighlights);
7003
+ currentSession.renderer.updateCustomElementHighlights(customElementHighlights);
7004
+ }
7005
+ checkForTables(paragraph, currentSession, allSessions, paragraphIndex) {
7006
+ const result = [];
7007
+ const paragraphTables = currentSession.session.displayData.customComponents.tables.filter(x => x.instance.content.insertIndex >= paragraph.startIndex &&
7008
+ x.instance.content.insertIndex <= paragraph.startIndex + paragraph.content.length);
7009
+ for (const table of paragraphTables) {
7010
+ const tableSessions = [];
7011
+ for (const session of allSessions) {
7012
+ const parentTable = session.renderer.container.closest('app-nod-table');
7013
+ if (parentTable && parentTable === table.location.nativeElement) {
7014
+ tableSessions.push(session);
7015
+ }
7016
+ }
7017
+ this.tables.push({
7018
+ sessionId: currentSession.sessionId,
7019
+ tableSessions: tableSessions.map(x => x.sessionId),
7020
+ row: paragraphIndex,
7021
+ col: table.instance.content.insertIndex - paragraph.startIndex
7022
+ });
7023
+ result.push({ index: table.instance.content.insertIndex - paragraph.startIndex, content: tableSessions });
7024
+ }
7025
+ return result;
7026
+ }
7027
+ checkForCustomElements(paragraph, currentSession) {
7028
+ const result = [];
7029
+ const customElements = currentSession.session.displayData.customComponents.customElements.filter(x => x.instance.content.insertIndex >= paragraph.startIndex &&
7030
+ x.instance.content.insertIndex <= paragraph.startIndex + paragraph.content.length);
7031
+ for (const element of customElements) {
7032
+ if (element.instance instanceof BaseNoderComponent) {
7033
+ result.push({ index: element.instance.content.insertIndex - paragraph.startIndex, content: element.instance });
7034
+ }
7035
+ }
7036
+ return result;
7037
+ }
7038
+ findNextAfterCursor(startCursor, sessionId) {
7039
+ const closestResultCurrentSession = this.allMatches.find(x => (x.sessionId === sessionId && x.range.start.row === startCursor.row && x.range.start.column >= startCursor.column) ||
7040
+ (x.sessionId === sessionId && x.range.start.row > startCursor.row));
7041
+ if (closestResultCurrentSession) {
7042
+ const tablesBeforeClosestResultCurrentSession = this.tables.filter(x => (x.sessionId === sessionId && x.row > startCursor.row && x.row < closestResultCurrentSession.range.start.row) ||
7043
+ (x.sessionId === sessionId &&
7044
+ x.row === startCursor.row &&
7045
+ x.row < closestResultCurrentSession.range.start.row &&
7046
+ x.col > startCursor.column) ||
7047
+ (x.sessionId === sessionId &&
7048
+ x.row === closestResultCurrentSession.range.start.row &&
7049
+ x.col < closestResultCurrentSession.range.start.column));
7050
+ if (!tablesBeforeClosestResultCurrentSession.length) {
7051
+ return this.allMatches.indexOf(closestResultCurrentSession);
7052
+ }
7053
+ const tableSessions = tablesBeforeClosestResultCurrentSession.flatMap(x => x.tableSessions);
7054
+ for (const session of tableSessions) {
7055
+ const result = this.findNextAfterCursor(new CursorParagraph(0, 0), session);
7056
+ if (result >= 0) {
7057
+ return result;
7058
+ }
7059
+ }
7060
+ }
7061
+ const tablesAfterCursor = this.tables.filter(x => (x.sessionId === sessionId && x.row === startCursor.row && x.col >= startCursor.column) ||
7062
+ (x.sessionId === sessionId && x.row > startCursor.row));
7063
+ const tableSessions = tablesAfterCursor.flatMap(x => x.tableSessions);
7064
+ for (const session of tableSessions) {
7065
+ const result = this.findNextAfterCursor(new CursorParagraph(0, 0), session);
7066
+ if (result >= 0) {
7067
+ return result;
7068
+ }
7069
+ }
7070
+ const table = this.tables.find(x => x.tableSessions.includes(sessionId));
7071
+ if (table) {
7072
+ const nextSessionIndex = table.tableSessions.findIndex(x => x === sessionId) + 1;
7073
+ if (nextSessionIndex < table.tableSessions.length) {
7074
+ return this.findNextAfterCursor(new CursorParagraph(0, 0), table.tableSessions[nextSessionIndex]);
7075
+ }
7076
+ return this.findNextAfterCursor(new CursorParagraph(table.row + 1, table.col + 1), table.sessionId);
7077
+ }
7078
+ if (this.danglingSessions.length) {
7079
+ const danglingSessionsIndex = this.danglingSessions.indexOf(sessionId);
7080
+ const nextSessionIndex = danglingSessionsIndex + 1;
7081
+ if (nextSessionIndex < this.danglingSessions.length) {
7082
+ return this.findNextAfterCursor(new CursorParagraph(0, 0), this.danglingSessions[nextSessionIndex]);
7083
+ }
7084
+ }
7085
+ return -1;
7086
+ }
7087
+ findPreviousBeforeCursor(startCursor, sessionId) {
7088
+ const closestResultCurrentSession = this.allMatches.findLast(x => (x.sessionId === sessionId && x.range.start.row === startCursor.row && x.range.start.column < startCursor.column) ||
7089
+ (x.sessionId === sessionId && x.range.start.row < startCursor.row));
7090
+ if (closestResultCurrentSession) {
7091
+ const tablesAfterClosestResultCurrentSession = this.tables.filter(x => (x.sessionId === sessionId && x.row < startCursor.row && x.row > closestResultCurrentSession.range.start.row) ||
7092
+ (x.sessionId === sessionId &&
7093
+ x.row === startCursor.row &&
7094
+ x.row > closestResultCurrentSession.range.start.row &&
7095
+ x.col < startCursor.column) ||
7096
+ (x.sessionId === sessionId &&
7097
+ x.row === closestResultCurrentSession.range.start.row &&
7098
+ x.col > closestResultCurrentSession.range.start.column));
7099
+ if (!tablesAfterClosestResultCurrentSession.length) {
7100
+ return this.allMatches.indexOf(closestResultCurrentSession);
7101
+ }
7102
+ const tableSessions = tablesAfterClosestResultCurrentSession.flatMap(x => x.tableSessions);
7103
+ for (const session of tableSessions.toReversed()) {
7104
+ const result = this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), session);
7105
+ if (result >= 0) {
7106
+ return result;
7107
+ }
7108
+ }
7109
+ }
7110
+ const tablesBeforeCursor = this.tables.filter(x => (x.sessionId === sessionId && x.row === startCursor.row && x.col < startCursor.column) ||
7111
+ (x.sessionId === sessionId && x.row < startCursor.row));
7112
+ const tableSessions = tablesBeforeCursor.flatMap(x => x.tableSessions);
7113
+ for (const session of tableSessions.toReversed()) {
7114
+ const result = this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), session);
7115
+ if (result >= 0) {
7116
+ return result;
7117
+ }
7118
+ }
7119
+ const table = this.tables.find(x => x.tableSessions.includes(sessionId));
7120
+ if (table) {
7121
+ const currentSessionIndex = table.tableSessions.findIndex(x => x === sessionId);
7122
+ if (currentSessionIndex > 0) {
7123
+ return this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), table.tableSessions[currentSessionIndex - 1]);
7124
+ }
7125
+ return this.findPreviousBeforeCursor(new CursorParagraph(table.row - 1, table.col - 1), table.sessionId);
7126
+ }
7127
+ if (this.danglingSessions.length) {
7128
+ const currentSessionIndex = this.danglingSessions.indexOf(sessionId);
7129
+ if (currentSessionIndex > 0) {
7130
+ return this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), this.danglingSessions[currentSessionIndex - 1]);
7131
+ }
7132
+ }
7133
+ return -1;
7134
+ }
7135
+ updateActiveSearchHighlight(sessions) {
7136
+ this.editorService.setCurrentSearchResultIndex(this.currentMatchIndex);
7137
+ for (const session of sessions) {
7138
+ if (this.currentMatch && session.sessionId === this.currentMatch.sessionId) {
7139
+ const range = this.currentMatch instanceof CustomElementSearchResult
7140
+ ? new CustomElementInfo({
7141
+ index: this.currentMatch.index,
7142
+ parentRange: this.currentMatch.range
7143
+ })
7144
+ : this.currentMatch.range;
7145
+ session.renderer.updateActiveSearchHighlight(range);
7146
+ continue;
7147
+ }
7148
+ session.renderer.updateActiveSearchHighlight(null);
7149
+ }
7150
+ }
6790
7151
  }
6791
7152
 
6792
7153
  class Selection {
@@ -7253,6 +7614,7 @@ class Editor {
7253
7614
  this.edgeElementTagName = 'APP-NOD-EDGE';
7254
7615
  this.imageTagName = 'APP-NOD-IMAGE';
7255
7616
  this.subscriptions = [];
7617
+ this.emojiRegex = /\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u{200D}\p{Extended_Pictographic})*/gu;
7256
7618
  this.isRerenderSubscriptionOpen = true;
7257
7619
  this.rerenderResize = () => {
7258
7620
  this.mainRenderer.onResize(true);
@@ -7279,8 +7641,8 @@ class Editor {
7279
7641
  this.initResizeListener();
7280
7642
  this.focus();
7281
7643
  this.session.applyToolbarStyles();
7282
- this.search = new Search();
7283
- this.subscriptions.push(this.changedEdgeSizeSubscription(), this.changedEdgeSubscription(), this.changedTableSizeSubscription(), this.clipboardDataSubscription(), this.copySelectedSubscription(), this.createCustomComponentSubscription(), this.cutSelectedSubscription(), this.disableSelectionSubscription(), this.endMousePressSubscription(), this.imageLoadedSubscription(), this.insertBreakSubscription(), this.insertImageSubscription(), this.insertLinkSubscription(), this.insertTableColumnsSubscription(), this.insertTableRowsSubscription(), this.insertTableSubscription(), this.insertTextSubscription(), this.pasteFromClipboardSubscription(), this.printSubscription(), this.redoSubscription(), this.removeLeftSubscription(), this.removeNumberingsSubscription(), this.removeRightSubscription(), this.removeSelectedSubscription(), this.removeTableColumnsSubscription(), this.removeTableRowsSubscription(), this.removeTableSubscription(), this.rerenderSubscription(), this.resizeTableColumnsSubscription(), ...this.searchOptionSubscriptions(), ...this.replaceSubscription(), this.selectAllSubscription(), this.setImageStyleSubscription(), this.setNumberingTemplateTypeSubscription(), this.setParagraphStylesSubscription(), this.setTextStylesSubscription(), this.undoSubscription(), this.updateEdgeSubscription(), this.viewOnlyModeSubscription(), this.applyPageFormatSubscription(), this.applyRightMarginPageFormatSubscription(), this.applyLeftMarginPageFormatSubscription(), this.insertPageFormatSubscription(), this.applyDocumentPageFormatSubscription(), this.dragMoveSubscription(), this.dragDropSubscription(), this.applyFirstLinePositionSubscription(), this.applyRightIndentParagraphSubscription(), this.applyLeftIndentParagraphSubscription());
7644
+ this.search = new Search(editorService);
7645
+ this.subscriptions.push(this.changedEdgeSizeSubscription(), this.changedEdgeSubscription(), this.changedTableSizeSubscription(), this.clipboardDataSubscription(), this.copySelectedSubscription(), this.createCustomComponentSubscription(), this.cutSelectedSubscription(), this.disableSelectionSubscription(), this.endMousePressSubscription(), this.imageLoadedSubscription(), this.insertBreakSubscription(), this.insertImageSubscription(), this.insertLinkSubscription(), this.insertTableColumnsSubscription(), this.insertTableRowsSubscription(), this.insertTableSubscription(), this.insertTextSubscription(), this.pasteFromClipboardSubscription(), this.printSubscription(), this.redoSubscription(), this.removeLeftSubscription(), this.removeNumberingsSubscription(), this.removeRightSubscription(), this.removeSelectedSubscription(), this.removeTableColumnsSubscription(), this.removeTableRowsSubscription(), this.removeTableSubscription(), this.rerenderSubscription(), this.resizeTableColumnsSubscription(), ...this.searchOptionSubscriptions(), ...this.replaceSubscription(), this.selectAllSubscription(), this.setImageStyleSubscription(), this.setNumberingTemplateTypeSubscription(), this.setParagraphStylesSubscription(), this.setTextStylesSubscription(), this.undoSubscription(), this.updateEdgeSubscription(), this.viewOnlyModeSubscription(), this.applyPageFormatSubscription(), this.applyRightMarginPageFormatSubscription(), this.applyLeftMarginPageFormatSubscription(), this.insertPageFormatSubscription(), this.applyDocumentPageFormatSubscription(), this.dragMoveSubscription(), this.dragDropSubscription(), this.applyFirstLinePositionSubscription(), this.applyRightIndentParagraphSubscription(), this.applyLeftIndentParagraphSubscription(), this.commandCreatedForEdges());
7284
7646
  }
7285
7647
  destroy() {
7286
7648
  this.subscriptions.forEach(s => s?.unsubscribe());
@@ -7332,13 +7694,14 @@ class Editor {
7332
7694
  this.removeSelected();
7333
7695
  }
7334
7696
  insert(text) {
7697
+ const sanitizedText = text.replace(this.emojiRegex, ' ');
7335
7698
  if (this.selection.isEmpty) {
7336
7699
  const textStyle = ContentStyleHelper.combineTextStyles(null, this.editorService.styles);
7337
- this.insertText(text, textStyle);
7700
+ this.insertText(sanitizedText, textStyle);
7338
7701
  }
7339
7702
  else {
7340
7703
  const index = ContentHelper.paragraphPositionToDocumentIndex(this.session.displayData.paragraphs, this.selection.range.start);
7341
- const insertText = new InsertTextModel({ insertIndex: index, text });
7704
+ const insertText = new InsertTextModel({ insertIndex: index, text: sanitizedText });
7342
7705
  this.replaceBy(new ReplaceModel({ insertText }));
7343
7706
  }
7344
7707
  }
@@ -7461,6 +7824,7 @@ class Editor {
7461
7824
  let lastRow = this.selection.cursor.row === endPoint.row ? endPoint.row : Infinity;
7462
7825
  this.renderer.updateLines(this.selection.cursor.row, lastRow);
7463
7826
  this.renderer.updateCursor();
7827
+ this.onContentChange();
7464
7828
  this.rerenderMarker();
7465
7829
  }
7466
7830
  replaceBy(model) {
@@ -7586,45 +7950,27 @@ class Editor {
7586
7950
  });
7587
7951
  }
7588
7952
  }
7589
- find(term, focusNext = false) {
7590
- this.search.setSearchTerm(term);
7591
- if (!term?.length) {
7592
- for (const session of this.regulatorService.sessions) {
7593
- session.renderer.updateSearchHighlights([]);
7594
- session.renderer.updateActiveSearchHighlight(null);
7595
- }
7596
- this.editorService.setSearchResultCount(0);
7597
- return;
7598
- }
7599
- this.search.findAll(this.regulatorService.sessions);
7600
- this.editorService.setSearchResultCount(this.search.allMatches.length);
7601
- if (focusNext && this.search.allMatches?.length) {
7602
- this.search.goNext(this.selection, this.regulatorService.currentSession.sessionId);
7603
- this.updateActiveSearchHighlight();
7604
- this.mainRenderer.scrollCursorIntoView(new CursorParagraph(this.search.currentMatch.range.start.row, this.search.currentMatch.range.start.column));
7605
- }
7606
- else {
7607
- this.updateActiveSearchHighlight();
7608
- }
7953
+ find(term) {
7954
+ this.search.findAll(this.regulatorService.sessions, term);
7609
7955
  }
7610
7956
  findNext() {
7611
7957
  if (!this.search.allMatches?.length) {
7612
7958
  return;
7613
7959
  }
7614
- this.search.goNext(this.selection, this.regulatorService.currentSession.sessionId);
7960
+ this.search.goNext(this.selection, this.regulatorService.currentSession.sessionId, this.regulatorService.sessions);
7615
7961
  this.setCursorAtSearchResult();
7616
- this.updateActiveSearchHighlight();
7617
7962
  }
7618
7963
  findPrevious() {
7619
7964
  if (!this.search.allMatches?.length) {
7620
7965
  return;
7621
7966
  }
7622
- this.search.goPrevious(this.selection, this.regulatorService.currentSession.sessionId);
7623
- this.updateActiveSearchHighlight();
7967
+ this.search.goPrevious(this.selection, this.regulatorService.currentSession.sessionId, this.regulatorService.sessions);
7624
7968
  this.setCursorAtSearchResult();
7625
7969
  }
7626
7970
  replace() {
7627
- if (!this.search.allMatches?.length || this.search.term === this.replaceTerm) {
7971
+ if (!this.search.currentMatch ||
7972
+ this.search.term === this.replaceTerm ||
7973
+ this.search.currentMatch instanceof CustomElementSearchResult) {
7628
7974
  return;
7629
7975
  }
7630
7976
  if (this.replaceTerm) {
@@ -7638,14 +7984,17 @@ class Editor {
7638
7984
  const replaceModel = new ReplaceModel({ insertText, delete: deleteModel });
7639
7985
  this.saveReplaceToHistory(this.search.currentMatch.range, replaceModel);
7640
7986
  const endPosition = this.session.replace(replaceModel);
7641
- this.onDocumentChange(new Range(this.search.currentMatch.range.start, endPosition));
7987
+ const range = new Range(this.search.currentMatch.range.start, endPosition);
7988
+ let lastRow = range.start.row === range.end.row ? range.end.row : Infinity;
7989
+ this.renderer.updateLines(range.start.row, lastRow);
7642
7990
  }
7643
7991
  else {
7644
7992
  const range = this.search.currentMatch.range;
7645
7993
  this.saveRemoveToHistory(range);
7646
7994
  this.session.remove(range);
7647
7995
  }
7648
- this.find(this.search.term);
7996
+ this.onContentChange();
7997
+ this.findNext();
7649
7998
  }
7650
7999
  undo() {
7651
8000
  const undo = this.history.popUndoOperation();
@@ -8361,7 +8710,7 @@ class Editor {
8361
8710
  const scalingRatio = this.customPageWidth ? ScalingHelper.getRatio(this.customPageWidth, pageWidth) : 1;
8362
8711
  this.editorService.setPageFormat(this.model.pageFormats[0]);
8363
8712
  this.editorService.paragraphStyle(this.model.paragraphs[0].paragraphStyle);
8364
- this.regulatorService.addMainSession(this.model, pageWidth, scalingRatio, this.container);
8713
+ this.regulatorService.addMainSession(this.model, scalingRatio, this.container);
8365
8714
  }
8366
8715
  onSelectionChange() {
8367
8716
  this.session.applyToolbarStyles();
@@ -8369,6 +8718,7 @@ class Editor {
8369
8718
  if (this.selection.isEmpty) {
8370
8719
  this.renderer.updateCursor();
8371
8720
  }
8721
+ this.regulatorService.updateCursorPosition();
8372
8722
  this.editorService.setHasSelection(!this.selection.isEmpty);
8373
8723
  const position = this.mainSession.displayData.positionToIndex(this.selection.selectedRange.start);
8374
8724
  const pageFormat = this.mainSession.displayData.getPageFormatAtPosition(position);
@@ -8577,7 +8927,10 @@ class Editor {
8577
8927
  }
8578
8928
  searchOptionSubscriptions() {
8579
8929
  return [
8580
- this.editorService.searchTerm$.subscribe(searchTerm => this.find(searchTerm, true)),
8930
+ this.editorService.searchTerm$.subscribe(searchTerm => {
8931
+ this.find(searchTerm);
8932
+ this.findNext();
8933
+ }),
8581
8934
  this.editorService.searchNext$.subscribe(() => this.findNext()),
8582
8935
  this.editorService.searchPrevious$.subscribe(() => this.findPrevious())
8583
8936
  ];
@@ -8674,8 +9027,10 @@ class Editor {
8674
9027
  });
8675
9028
  }
8676
9029
  changedEdgeSizeSubscription() {
8677
- return this.editorService.changedEdgeSize$.subscribe(({ edgeType, pageType }) => {
8678
- this.mainSession.displayData.pagesFormat.forEach(x => x.updatePageVerticalData(edgeType, pageType));
9030
+ return this.editorService.changedEdgeSize$.subscribe(event => {
9031
+ this.mainSession.displayData.pagesFormat
9032
+ .filter(x => x.pageFormatModel.pageWidth === event.pageWidth)
9033
+ .forEach(x => x.updatePageVerticalData(event.edgeType, event.pageType));
8679
9034
  this.mainSession.displayData.processParagraphsProperties(0);
8680
9035
  });
8681
9036
  }
@@ -8819,6 +9174,11 @@ class Editor {
8819
9174
  this.clipboardData = data;
8820
9175
  });
8821
9176
  }
9177
+ commandCreatedForEdges() {
9178
+ return this.commandsService.createCommand$
9179
+ .pipe(filter(x => !!x.targets.find(y => !!y.edgeData)))
9180
+ .subscribe(() => this.regulatorService.forceUpdateDataForEdges());
9181
+ }
8822
9182
  updateEdgeSubscription() {
8823
9183
  return this.editorService.updateEdges$.subscribe(sessionId => {
8824
9184
  let existed = this.mainSession.customComponents.edges.headersComponents.findIndex(x => x.instance.sessionId === sessionId);
@@ -8853,7 +9213,7 @@ class Editor {
8853
9213
  });
8854
9214
  this.selection.navigateFileStart();
8855
9215
  this.isRerenderSubscriptionOpen = false;
8856
- this.regulatorService.addMainSession(this.model, pageWidth, scalingRatio, this.container);
9216
+ this.regulatorService.addMainSession(this.model, scalingRatio, this.container);
8857
9217
  this.isRerenderSubscriptionOpen = true;
8858
9218
  this.textInput = new TextInput(this.mainRenderer.container);
8859
9219
  this.mainRenderer.textarea = this.textInput.input;
@@ -8873,27 +9233,14 @@ class Editor {
8873
9233
  changeCellsWidth(rows, widthScale) {
8874
9234
  rows.forEach(row => row.cells.forEach(cell => (cell.width = Math.round(cell.width / widthScale))));
8875
9235
  }
8876
- updateActiveSearchHighlight() {
8877
- this.editorService.setCurrentSearchResultIndex(this.search.currentMatchIndex);
8878
- if (!this.search.currentMatch) {
8879
- for (const session of this.regulatorService.sessions) {
8880
- session.renderer.updateActiveSearchHighlight(null);
8881
- }
8882
- return;
8883
- }
8884
- for (const session of this.regulatorService.sessions) {
8885
- if (session.sessionId === this.search.currentMatch.sessionId) {
8886
- session.renderer.updateActiveSearchHighlight(this.search.currentMatch.range);
8887
- continue;
8888
- }
8889
- session.renderer.updateActiveSearchHighlight(null);
8890
- }
8891
- }
8892
9236
  setCursorAtSearchResult() {
9237
+ if (this.search.currentMatch.mainSessionPosition !== 'outsideMainSession') {
9238
+ this.mainRenderer.scrollCursorIntoView(this.search.currentMatch.mainSessionPosition, 0.5);
9239
+ }
8893
9240
  this.regulatorService.setCurrentSessionById(this.search.currentMatch.sessionId);
8894
- const resultCursor = new CursorParagraph(this.search.currentMatch.range.start.row, this.search.currentMatch.range.start.column);
8895
- this.selection.placeCursor(resultCursor);
8896
- this.mainRenderer.scrollCursorIntoView(resultCursor);
9241
+ const sessionModel = this.regulatorService.getSessionModel(this.search.currentMatch.sessionId);
9242
+ sessionModel.session.selection.placeCursor(this.search.currentMatch.range.start);
9243
+ this.renderer.updateCursor();
8897
9244
  }
8898
9245
  }
8899
9246
 
@@ -8908,6 +9255,7 @@ class EditorSearchBarComponent {
8908
9255
  this.isReplace = false;
8909
9256
  this.searchResultCount$ = editorService.searchResultCount$;
8910
9257
  this.searchResultIndex$ = editorService.currentSearchResultIndex$;
9258
+ this.isViewOnly$ = editorService.isViewOnly$;
8911
9259
  }
8912
9260
  ngOnInit() {
8913
9261
  this.searchControl.valueChanges
@@ -8919,6 +9267,9 @@ class EditorSearchBarComponent {
8919
9267
  this.editorService.dialogSearchTerm$
8920
9268
  .pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
8921
9269
  .subscribe(x => this.searchControl.setValue(x));
9270
+ this.isViewOnly$
9271
+ .pipe(filter(x => x), takeUntilDestroyed(this.destroyRef))
9272
+ .subscribe(() => (this.isReplace = false));
8922
9273
  }
8923
9274
  ngOnDestroy() {
8924
9275
  this.editorService.setNewSearchTerm('');
@@ -8945,7 +9296,7 @@ class EditorSearchBarComponent {
8945
9296
  this.editorService.replaceCurrentSearchResult();
8946
9297
  }
8947
9298
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: EditorSearchBarComponent, deps: [{ token: EditorService }, { token: i0.DestroyRef }], target: i0.ɵɵFactoryTarget.Component }); }
8948
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: EditorSearchBarComponent, isStandalone: true, selector: "app-nod-editor-search-bar", providers: [ExternalElementService], viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "@let searchResultCount = searchResultCount$ | async;\n@let searchResultIndex = searchResultIndex$ | async;\n<div class=\"line search-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SEARCH_FOR' | translate }}</mat-label>\n <input\n matInput\n #searchInput\n [formControl]=\"searchControl\"\n (keydown.enter)=\"findNext()\" />\n </mat-form-field>\n <div>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findPrev()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onleft\"></mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findNext()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onright\"></mat-icon>\n </button>\n </div>\n</div>\n<div\n class=\"replace-form\"\n *ngIf=\"isReplace\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.REPLACE_WITH' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"replaceControl\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n (keydown.enter)=\"replace()\" />\n </mat-form-field>\n <button\n type=\"button\"\n mat-button\n (click)=\"replace()\">\n {{ 'NODER.LABEL.REPLACE' | translate }}\n </button>\n</div>\n<div class=\"search-options\">\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Toggle Replace Mode\"\n (click)=\"setReplace()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"{{ isReplace ? 'icon-arrow-up' : 'icon-arrow-down' }}\"></mat-icon>\n </button>\n <div class=\"counter\">\n @if (searchResultCount) {\n <span>\n {{ 'NODER.COMPLEX_LABEL.OF_COUNTER' | translate: { current: searchResultIndex, total: searchResultCount ?? 0 } }}\n </span>\n } @else {\n <span>{{ 'NODER.LABEL.NO_RESULTS' | translate }}</span>\n }\n </div>\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"'NODER.LABEL.CLOSE' | translate\"\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\"></mat-icon>\n </button>\n</div>\n", styles: [":host{min-height:56px;max-width:100%;display:block;font-size:10px;border-style:solid;border-radius:0 0 4px 4px;border-width:1px;border-top:none}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.close-icon{position:absolute;right:1px;top:1px}.search-form,.replace-form,.search-options{margin:8px 6px 0 0;display:flex;gap:8px}mat-form-field{padding-left:10px}.mdc-button{font-size:12px;padding:0 8px;min-width:unset}.search-options{line-height:40px}.search-options .counter{text-align:center;flex:1}.mat-mdc-input-element{font-size:10px}.replace-form .mdc-button{width:80px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9299
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: EditorSearchBarComponent, isStandalone: true, selector: "app-nod-editor-search-bar", providers: [ExternalElementService], viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "@let searchResultCount = searchResultCount$ | async;\n@let searchResultIndex = searchResultIndex$ | async;\n@let isViewOnly = isViewOnly$ | async;\n<div class=\"line search-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SEARCH_FOR' | translate }}</mat-label>\n <input\n matInput\n #searchInput\n [formControl]=\"searchControl\"\n (keydown.enter)=\"findNext()\" />\n </mat-form-field>\n <div>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findPrev()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onleft\"></mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findNext()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onright\"></mat-icon>\n </button>\n </div>\n</div>\n@if (isReplace) {\n <div class=\"replace-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.REPLACE_WITH' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"replaceControl\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n (keydown.enter)=\"replace()\" />\n </mat-form-field>\n <button\n type=\"button\"\n mat-button\n (click)=\"replace()\">\n {{ 'NODER.LABEL.REPLACE' | translate }}\n </button>\n </div>\n}\n<div class=\"search-options\">\n <button\n type=\"button\"\n [disabled]=\"isViewOnly\"\n mat-icon-button\n matTooltip=\"Toggle Replace Mode\"\n (click)=\"setReplace()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"{{ isReplace ? 'icon-arrow-up' : 'icon-arrow-down' }}\"></mat-icon>\n </button>\n <div class=\"counter\">\n @if (searchResultCount) {\n <span>\n {{ 'NODER.COMPLEX_LABEL.OF_COUNTER' | translate: { current: searchResultIndex, total: searchResultCount ?? 0 } }}\n </span>\n } @else {\n <span>{{ 'NODER.LABEL.NO_RESULTS' | translate }}</span>\n }\n </div>\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"'NODER.LABEL.CLOSE' | translate\"\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\"></mat-icon>\n </button>\n</div>\n", styles: [":host{min-height:56px;max-width:100%;display:block;font-size:10px;border-style:solid;border-radius:0 0 4px 4px;border-width:1px;border-top:none}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.close-icon{position:absolute;right:1px;top:1px}.search-form,.replace-form,.search-options{margin:8px 6px 0 0;display:flex;gap:8px}mat-form-field{padding-left:10px}.mdc-button{font-size:12px;padding:0 8px;min-width:unset}.search-options{line-height:40px}.search-options .counter{text-align:center;flex:1}.mat-mdc-input-element{font-size:10px}.replace-form .mdc-button{width:80px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i5$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
8949
9300
  }
8950
9301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: EditorSearchBarComponent, decorators: [{
8951
9302
  type: Component,
@@ -8958,7 +9309,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
8958
9309
  MatTooltipModule,
8959
9310
  ReactiveFormsModule,
8960
9311
  TranslateModule
8961
- ], providers: [ExternalElementService], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-nod-editor-search-bar', template: "@let searchResultCount = searchResultCount$ | async;\n@let searchResultIndex = searchResultIndex$ | async;\n<div class=\"line search-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SEARCH_FOR' | translate }}</mat-label>\n <input\n matInput\n #searchInput\n [formControl]=\"searchControl\"\n (keydown.enter)=\"findNext()\" />\n </mat-form-field>\n <div>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findPrev()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onleft\"></mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findNext()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onright\"></mat-icon>\n </button>\n </div>\n</div>\n<div\n class=\"replace-form\"\n *ngIf=\"isReplace\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.REPLACE_WITH' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"replaceControl\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n (keydown.enter)=\"replace()\" />\n </mat-form-field>\n <button\n type=\"button\"\n mat-button\n (click)=\"replace()\">\n {{ 'NODER.LABEL.REPLACE' | translate }}\n </button>\n</div>\n<div class=\"search-options\">\n <button\n type=\"button\"\n mat-icon-button\n matTooltip=\"Toggle Replace Mode\"\n (click)=\"setReplace()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"{{ isReplace ? 'icon-arrow-up' : 'icon-arrow-down' }}\"></mat-icon>\n </button>\n <div class=\"counter\">\n @if (searchResultCount) {\n <span>\n {{ 'NODER.COMPLEX_LABEL.OF_COUNTER' | translate: { current: searchResultIndex, total: searchResultCount ?? 0 } }}\n </span>\n } @else {\n <span>{{ 'NODER.LABEL.NO_RESULTS' | translate }}</span>\n }\n </div>\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"'NODER.LABEL.CLOSE' | translate\"\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\"></mat-icon>\n </button>\n</div>\n", styles: [":host{min-height:56px;max-width:100%;display:block;font-size:10px;border-style:solid;border-radius:0 0 4px 4px;border-width:1px;border-top:none}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.close-icon{position:absolute;right:1px;top:1px}.search-form,.replace-form,.search-options{margin:8px 6px 0 0;display:flex;gap:8px}mat-form-field{padding-left:10px}.mdc-button{font-size:12px;padding:0 8px;min-width:unset}.search-options{line-height:40px}.search-options .counter{text-align:center;flex:1}.mat-mdc-input-element{font-size:10px}.replace-form .mdc-button{width:80px}\n"] }]
9312
+ ], providers: [ExternalElementService], changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-nod-editor-search-bar', template: "@let searchResultCount = searchResultCount$ | async;\n@let searchResultIndex = searchResultIndex$ | async;\n@let isViewOnly = isViewOnly$ | async;\n<div class=\"line search-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SEARCH_FOR' | translate }}</mat-label>\n <input\n matInput\n #searchInput\n [formControl]=\"searchControl\"\n (keydown.enter)=\"findNext()\" />\n </mat-form-field>\n <div>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findPrev()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onleft\"></mat-icon>\n </button>\n <button\n type=\"button\"\n mat-icon-button\n (click)=\"findNext()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-arrow-onright\"></mat-icon>\n </button>\n </div>\n</div>\n@if (isReplace) {\n <div class=\"replace-form\">\n <mat-form-field\n color=\"accent\"\n floatLabel=\"auto\"\n appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.REPLACE_WITH' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"replaceControl\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n (keydown.enter)=\"replace()\" />\n </mat-form-field>\n <button\n type=\"button\"\n mat-button\n (click)=\"replace()\">\n {{ 'NODER.LABEL.REPLACE' | translate }}\n </button>\n </div>\n}\n<div class=\"search-options\">\n <button\n type=\"button\"\n [disabled]=\"isViewOnly\"\n mat-icon-button\n matTooltip=\"Toggle Replace Mode\"\n (click)=\"setReplace()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"{{ isReplace ? 'icon-arrow-up' : 'icon-arrow-down' }}\"></mat-icon>\n </button>\n <div class=\"counter\">\n @if (searchResultCount) {\n <span>\n {{ 'NODER.COMPLEX_LABEL.OF_COUNTER' | translate: { current: searchResultIndex, total: searchResultCount ?? 0 } }}\n </span>\n } @else {\n <span>{{ 'NODER.LABEL.NO_RESULTS' | translate }}</span>\n }\n </div>\n <button\n type=\"button\"\n mat-icon-button\n [matTooltip]=\"'NODER.LABEL.CLOSE' | translate\"\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\"></mat-icon>\n </button>\n</div>\n", styles: [":host{min-height:56px;max-width:100%;display:block;font-size:10px;border-style:solid;border-radius:0 0 4px 4px;border-width:1px;border-top:none}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.close-icon{position:absolute;right:1px;top:1px}.search-form,.replace-form,.search-options{margin:8px 6px 0 0;display:flex;gap:8px}mat-form-field{padding-left:10px}.mdc-button{font-size:12px;padding:0 8px;min-width:unset}.search-options{line-height:40px}.search-options .counter{text-align:center;flex:1}.mat-mdc-input-element{font-size:10px}.replace-form .mdc-button{width:80px}\n"] }]
8962
9313
  }], ctorParameters: () => [{ type: EditorService }, { type: i0.DestroyRef }], propDecorators: { searchInput: [{
8963
9314
  type: ViewChild,
8964
9315
  args: ['searchInput']
@@ -8967,94 +9318,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
8967
9318
  const EXTERNAL_ELEMENT_SIDENAV = new InjectionToken('EXTERNAL_ELEMENT_SIDENAV');
8968
9319
  const EXTERNAL_ELEMENT_SERVICE = new InjectionToken('EXTERNAL_ELEMENT_SERVICE');
8969
9320
 
8970
- class FontMetrics {
8971
- static { this.storageKey = 'metrics'; }
8972
- static { this.versionKey = 'editorVersion'; }
8973
- /**
8974
- * Key value pairs for calculated sizes of char symbols in HTML element
8975
- */
8976
- static { this.metrics = JSON.parse(localStorage.getItem(this.storageKey)) || {}; }
8977
- /**
8978
- * Key value pairs for identifiers and font strings
8979
- */
8980
- static { this.fontStringMap = {}; }
8981
- static checkVersion(version) {
8982
- let identifier = localStorage.getItem(this.versionKey);
8983
- if (identifier === version) {
8984
- return;
8985
- }
8986
- localStorage.removeItem(this.storageKey);
8987
- localStorage.setItem(this.versionKey, version);
8988
- }
8989
- static measureCharSize(ch, contentStyle) {
8990
- let identifier = this.fontStringMap[contentStyle];
8991
- if (!identifier) {
8992
- identifier = contentStyle.split(' ').join('_');
8993
- this.fontStringMap[contentStyle] = identifier;
8994
- }
8995
- this.metrics[identifier] ??= {};
8996
- if (!this.metrics[identifier][ch] || isNaN(this.metrics[identifier][ch].font)) {
8997
- this.metrics[identifier][ch] = this.calculateCanvas(ch, contentStyle);
8998
- localStorage.setItem(this.storageKey, JSON.stringify(this.metrics));
8999
- }
9000
- return this.metrics[identifier][ch];
9001
- }
9002
- static calculateCanvas(ch, contentStyle) {
9003
- this.canvasNode ||= document.createElement('canvas');
9004
- const fontBaseLine = this.fontBaseline(contentStyle, ch);
9005
- const context = this.canvasNode.getContext('2d');
9006
- context.font = contentStyle;
9007
- const textMetrics = context.measureText(ch);
9008
- return {
9009
- width: textMetrics.width,
9010
- height: textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent,
9011
- baseline: fontBaseLine.baseline,
9012
- content: fontBaseLine.content,
9013
- font: fontBaseLine.font,
9014
- line: fontBaseLine.line,
9015
- multiplier: fontBaseLine.multiplier,
9016
- ascent: textMetrics.fontBoundingBoxAscent,
9017
- descent: textMetrics.fontBoundingBoxDescent
9018
- };
9019
- }
9020
- static fontBaseline(contentStyle, text) {
9021
- const container = document.body;
9022
- this.measureDiv ||= document.createElement('div');
9023
- this.strut ||= document.createElement('span');
9024
- if (text === ' ') {
9025
- text = 'X';
9026
- }
9027
- this.measureDiv.style.font = contentStyle;
9028
- this.measureDiv.style.lineHeight = '1';
9029
- this.measureDiv.style.position = 'absolute';
9030
- this.measureDiv.style.visibility = 'hidden';
9031
- this.measureDiv.style.margin = '0';
9032
- this.measureDiv.style.padding = '0';
9033
- this.measureDiv.innerHTML = text;
9034
- this.strut.style.fontSize = '0';
9035
- this.strut.style.verticalAlign = 'baseline';
9036
- this.strut.style.padding = '0 10px';
9037
- this.measureDiv.classList.add('font-baseline');
9038
- this.measureDiv.appendChild(this.strut);
9039
- container.appendChild(this.measureDiv);
9040
- const computedStyle = window.getComputedStyle(this.measureDiv);
9041
- const fontSize = parseFloat(computedStyle.fontSize);
9042
- const baselineHeight = fontSize - this.strut.offsetTop;
9043
- const strutHeight = this.measureDiv.offsetHeight;
9044
- const lineHeight = parseFloat(computedStyle.lineHeight) || this.measureDiv.offsetHeight;
9045
- this.measureDiv.parentNode.removeChild(this.measureDiv);
9046
- this.measureDiv.innerHTML = '';
9047
- this.strut.innerHTML = '';
9048
- return {
9049
- baseline: baselineHeight,
9050
- content: strutHeight,
9051
- font: fontSize,
9052
- line: lineHeight,
9053
- multiplier: fontSize / baselineHeight
9054
- };
9055
- }
9056
- }
9057
-
9058
9321
  class ComponentService {
9059
9322
  constructor(applicationRef, injector) {
9060
9323
  this.applicationRef = applicationRef;
@@ -9416,6 +9679,7 @@ class NoderTableCellComponent {
9416
9679
  this.regulatorService = regulatorService;
9417
9680
  this.isHighlighted = false;
9418
9681
  this.resizerBorder = ResizerSide;
9682
+ this.isVisible = false;
9419
9683
  this.pagesCountChangedHandler = (event) => {
9420
9684
  if (this._allParagraphsHeight === event.pageHeight) {
9421
9685
  return;
@@ -9424,9 +9688,14 @@ class NoderTableCellComponent {
9424
9688
  this.heightChanged(this.rowIndex, this.cellIndex, event.pageHeight);
9425
9689
  };
9426
9690
  }
9691
+ ngAfterViewInit() {
9692
+ this.intersectionObserver = this.initializeIntersectionObserver();
9693
+ this.intersectionObserver.observe(this.container.nativeElement);
9694
+ }
9427
9695
  ngOnDestroy() {
9428
9696
  this.session?.displayData.removeEventListener('pagesCountChanged', this.pagesCountChangedHandler);
9429
9697
  this.regulatorService.removeSession(this.sessionId);
9698
+ this.intersectionObserver?.disconnect();
9430
9699
  }
9431
9700
  initialize() {
9432
9701
  const marginModel = new MarginModel({
@@ -9458,6 +9727,22 @@ class NoderTableCellComponent {
9458
9727
  addEventListeners() {
9459
9728
  this.session.displayData.addEventListener('pagesCountChanged', this.pagesCountChangedHandler);
9460
9729
  }
9730
+ initializeIntersectionObserver() {
9731
+ const options = {
9732
+ root: null,
9733
+ rootMargin: '50px',
9734
+ threshold: 0.01
9735
+ };
9736
+ return new IntersectionObserver(entries => {
9737
+ entries.forEach(entry => {
9738
+ const wasVisible = this.isVisible;
9739
+ this.isVisible = entry.isIntersecting;
9740
+ if (this.isVisible !== wasVisible) {
9741
+ this.renderer.setVisibility(this.isVisible);
9742
+ }
9743
+ });
9744
+ }, options);
9745
+ }
9461
9746
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTableCellComponent, deps: [{ token: EditorService }, { token: RegulatorService }], target: i0.ɵɵFactoryTarget.Component }); }
9462
9747
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: NoderTableCellComponent, isStandalone: false, selector: "app-nod-table-cell", inputs: { table: "table", cell: "cell", rowIndex: "rowIndex", cellIndex: "cellIndex", columnIndex: "columnIndex", width: "width", parentSessionId: "parentSessionId", generalProperties: "generalProperties", heightChanged: "heightChanged", startResizing: "startResizing" }, host: { properties: { "class.highlighted": "this.isHighlighted", "attr.data-session-id": "this.sessionId" } }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }], ngImport: i0, template: "<div\n *ngIf=\"cellIndex === 0\"\n class=\"resizer left-border\"\n (mousedown)=\"onStartResizing($event, resizerBorder.Left)\"></div>\n<div\n #container\n class=\"edit-container\"></div>\n<div class=\"highlight-container\"></div>\n<div\n class=\"resizer right-border\"\n (mousedown)=\"onStartResizing($event, resizerBorder.Right)\"></div>\n", styles: [".highlight-container{visibility:hidden;position:absolute;width:100%;height:100%;background-color:#5ea8f766;pointer-events:none;overflow:hidden}:host{display:flex;position:relative;min-height:19px;height:100%;background:transparent}:host.highlighted .highlight-container{visibility:visible}.edit-container{min-height:1px;overflow:hidden}.left-border{left:-6px}.resizer{cursor:col-resize;width:11px;height:100%;position:absolute;z-index:1}.right-border{right:-6px}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
9463
9748
  }
@@ -9503,6 +9788,144 @@ class RowDataModel {
9503
9788
  }
9504
9789
  }
9505
9790
 
9791
+ var LineStyles;
9792
+ (function (LineStyles) {
9793
+ LineStyles[LineStyles["SolidLine"] = 0] = "SolidLine";
9794
+ LineStyles[LineStyles["RoundDot"] = 1] = "RoundDot";
9795
+ LineStyles[LineStyles["SquareDot"] = 2] = "SquareDot";
9796
+ LineStyles[LineStyles["Dash"] = 3] = "Dash";
9797
+ LineStyles[LineStyles["DashDot"] = 4] = "DashDot";
9798
+ LineStyles[LineStyles["LongDash"] = 5] = "LongDash";
9799
+ LineStyles[LineStyles["LongDashDot"] = 6] = "LongDashDot";
9800
+ LineStyles[LineStyles["LongDashDotDot"] = 7] = "LongDashDotDot";
9801
+ LineStyles[LineStyles["Single"] = 8] = "Single";
9802
+ LineStyles[LineStyles["Thick"] = 9] = "Thick";
9803
+ LineStyles[LineStyles["Double"] = 10] = "Double";
9804
+ LineStyles[LineStyles["Dotted"] = 11] = "Dotted";
9805
+ LineStyles[LineStyles["Dashed"] = 12] = "Dashed";
9806
+ LineStyles[LineStyles["DotDash"] = 13] = "DotDash";
9807
+ LineStyles[LineStyles["DotDotDash"] = 14] = "DotDotDash";
9808
+ LineStyles[LineStyles["Triple"] = 15] = "Triple";
9809
+ LineStyles[LineStyles["ThinThickSmallGap"] = 16] = "ThinThickSmallGap";
9810
+ LineStyles[LineStyles["ThickThinSmallGap"] = 17] = "ThickThinSmallGap";
9811
+ LineStyles[LineStyles["ThinThickThinSmallGap"] = 18] = "ThinThickThinSmallGap";
9812
+ LineStyles[LineStyles["ThinThickMediumGap"] = 19] = "ThinThickMediumGap";
9813
+ LineStyles[LineStyles["ThickThinMediumGap"] = 20] = "ThickThinMediumGap";
9814
+ LineStyles[LineStyles["ThinThickThinMediumGap"] = 21] = "ThinThickThinMediumGap";
9815
+ LineStyles[LineStyles["ThinThickLargeGap"] = 22] = "ThinThickLargeGap";
9816
+ LineStyles[LineStyles["ThickThinLargeGap"] = 23] = "ThickThinLargeGap";
9817
+ LineStyles[LineStyles["ThinThickThinLargeGap"] = 24] = "ThinThickThinLargeGap";
9818
+ LineStyles[LineStyles["Wave"] = 25] = "Wave";
9819
+ LineStyles[LineStyles["DoubleWave"] = 26] = "DoubleWave";
9820
+ LineStyles[LineStyles["DashSmallGap"] = 27] = "DashSmallGap";
9821
+ LineStyles[LineStyles["DashDotStroked"] = 28] = "DashDotStroked";
9822
+ LineStyles[LineStyles["ThreeDEmboss"] = 29] = "ThreeDEmboss";
9823
+ LineStyles[LineStyles["ThreeDEngrave"] = 30] = "ThreeDEngrave";
9824
+ LineStyles[LineStyles["Outset"] = 31] = "Outset";
9825
+ LineStyles[LineStyles["Inset"] = 32] = "Inset";
9826
+ LineStyles[LineStyles["Nil"] = 33] = "Nil";
9827
+ })(LineStyles || (LineStyles = {}));
9828
+
9829
+ var Positions;
9830
+ (function (Positions) {
9831
+ Positions[Positions["Top"] = 0] = "Top";
9832
+ Positions[Positions["Right"] = 1] = "Right";
9833
+ Positions[Positions["Bottom"] = 2] = "Bottom";
9834
+ Positions[Positions["Left"] = 3] = "Left";
9835
+ Positions[Positions["All"] = 4] = "All";
9836
+ Positions[Positions["InsideHorizontal"] = 5] = "InsideHorizontal";
9837
+ Positions[Positions["InsideVertical"] = 6] = "InsideVertical";
9838
+ })(Positions || (Positions = {}));
9839
+
9840
+ class TableCellHelper {
9841
+ static setCellBorders(cell, borders) {
9842
+ if (!borders?.length || !cell) {
9843
+ return;
9844
+ }
9845
+ borders.forEach(x => {
9846
+ const style = this.getBorderStyle(x);
9847
+ this.setCellBorder(cell, x.position, style);
9848
+ });
9849
+ }
9850
+ static getBorderStyle(border) {
9851
+ if (border.lineStyle === LineStyles.Nil) {
9852
+ return 'none';
9853
+ }
9854
+ let style = `${border.width}pt`;
9855
+ if (border.lineStyle) {
9856
+ style += ` ${this.getBorderLineStyle(border.lineStyle)}`;
9857
+ }
9858
+ if (border.color && border.color !== 'auto') {
9859
+ style += ` ${border.color}`;
9860
+ }
9861
+ return style;
9862
+ }
9863
+ static getBorderLineStyle(lineStyle) {
9864
+ switch (lineStyle) {
9865
+ case LineStyles.RoundDot:
9866
+ case LineStyles.SquareDot:
9867
+ case LineStyles.Dotted:
9868
+ return 'dotted';
9869
+ case LineStyles.Dash:
9870
+ case LineStyles.Dashed:
9871
+ case LineStyles.LongDash:
9872
+ case LineStyles.DashSmallGap:
9873
+ case LineStyles.DashDot:
9874
+ case LineStyles.LongDashDot:
9875
+ case LineStyles.DotDash:
9876
+ case LineStyles.DashDotStroked:
9877
+ case LineStyles.LongDashDotDot:
9878
+ case LineStyles.DotDotDash:
9879
+ return 'dashed';
9880
+ case LineStyles.Double:
9881
+ case LineStyles.DoubleWave:
9882
+ return 'double';
9883
+ case LineStyles.Wave:
9884
+ return 'wavy'; // wavy is supported in some browsers
9885
+ case LineStyles.ThreeDEmboss:
9886
+ case LineStyles.ThreeDEngrave:
9887
+ return 'ridge'; // approximate replacement for 3D effects
9888
+ case LineStyles.Outset:
9889
+ return 'outset';
9890
+ case LineStyles.Inset:
9891
+ return 'inset';
9892
+ case LineStyles.Nil:
9893
+ return 'none';
9894
+ case LineStyles.ThinThickSmallGap: // complex combined styles are not supported
9895
+ case LineStyles.ThickThinSmallGap:
9896
+ case LineStyles.ThinThickThinSmallGap:
9897
+ case LineStyles.ThinThickMediumGap:
9898
+ case LineStyles.ThickThinMediumGap:
9899
+ case LineStyles.ThinThickThinMediumGap:
9900
+ case LineStyles.ThinThickLargeGap:
9901
+ case LineStyles.ThickThinLargeGap:
9902
+ case LineStyles.ThinThickThinLargeGap:
9903
+ case LineStyles.Triple: // triple not support in css, set solid as default
9904
+ case LineStyles.Single:
9905
+ case LineStyles.SolidLine:
9906
+ case LineStyles.Thick:
9907
+ default:
9908
+ return 'solid';
9909
+ }
9910
+ }
9911
+ static setCellBorder(cell, position, style) {
9912
+ switch (position) {
9913
+ case Positions.Top:
9914
+ cell.style.borderTop = style;
9915
+ break;
9916
+ case Positions.Bottom:
9917
+ cell.style.borderBottom = style;
9918
+ break;
9919
+ case Positions.Left:
9920
+ cell.style.borderLeft = style;
9921
+ break;
9922
+ case Positions.Right:
9923
+ cell.style.borderRight = style;
9924
+ break;
9925
+ }
9926
+ }
9927
+ }
9928
+
9506
9929
  class SelectionRangeModel {
9507
9930
  constructor(rowIndexes, cellIndexes) {
9508
9931
  this.rowIndexes = rowIndexes;
@@ -10169,6 +10592,9 @@ class NoderTableComponent extends BaseNoderComponent {
10169
10592
  continue;
10170
10593
  }
10171
10594
  const cell = this.tableEl.rows[rowIndex].insertCell(currentTargetIndex);
10595
+ if (this.table.rows[rowIndex].cells[modelCellIndex].borders) {
10596
+ TableCellHelper.setCellBorders(cell, this.table.rows[rowIndex].cells[modelCellIndex].borders);
10597
+ }
10172
10598
  const componentRef = this.componentService.generateAndAttachComponent(cell, NoderTableCellComponent, {
10173
10599
  table: this.table,
10174
10600
  cell: this.table.rows[rowIndex].cells[modelCellIndex],
@@ -10621,8 +11047,8 @@ class PageFormat {
10621
11047
  }
10622
11048
  const pageTypes = this.customComponents.edges.getUniquePageTypes();
10623
11049
  this.pagesVerticalData = pageTypes.map(pageType => {
10624
- const headerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Header);
10625
- const footerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Footer);
11050
+ const headerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Header, this.pageFormatModel.pageWidth);
11051
+ const footerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Footer, this.pageFormatModel.pageWidth);
10626
11052
  const marginTop = Math.max(headerHeight, this.pageFormatModel.marginTop);
10627
11053
  const marginBottom = Math.max(footerHeight, this.pageFormatModel.marginBottom);
10628
11054
  return new PageVerticalDataModel({
@@ -10635,7 +11061,7 @@ class PageFormat {
10635
11061
  }
10636
11062
  updatePageVerticalData(edgeType, pageType) {
10637
11063
  const pageVerticalData = this.pagesVerticalData.find(x => x.pageType === pageType);
10638
- const componentHeight = this.customComponents.edges.getComponentHeightByType(pageType, edgeType);
11064
+ const componentHeight = this.customComponents.edges.getComponentHeightByType(pageType, edgeType, this.pageFormatModel.pageWidth);
10639
11065
  if (edgeType === EdgeType.Header) {
10640
11066
  pageVerticalData.marginTop =
10641
11067
  componentHeight > this.pageFormatModel.marginTop ? componentHeight : this.pageFormatModel.marginTop;
@@ -10685,7 +11111,7 @@ class TextLineInfo {
10685
11111
  this.paddingLeft = indent.left + (diff - indent.left - indent.right) / 2 + (indent.hanging - indent.firstLine) / 2;
10686
11112
  break;
10687
11113
  case Alignment$1.right:
10688
- this.paddingLeft = diff - indent.right;
11114
+ this.paddingLeft = diff - indent.right + indent.hanging - indent.firstLine;
10689
11115
  break;
10690
11116
  default:
10691
11117
  this.paddingLeft = indent.left;
@@ -10837,8 +11263,11 @@ class DisplayData extends EventEmitting {
10837
11263
  this.pagesFormat = [];
10838
11264
  this.allPagesHeight = 0;
10839
11265
  this.tabTokens = [];
11266
+ this.updateDataForModel();
11267
+ }
11268
+ updateDataForModel() {
10840
11269
  this.paragraphs = this.splitByParagraphs(this.model.content).map(x => new ParagraphInfoModel({ content: x }));
10841
- this.pagesFormat = pageFormatModels.map(x => new PageFormat(x, pagesSpace, customComponents));
11270
+ this.pagesFormat = this.pageFormatModels.map(x => new PageFormat(x, this.pagesSpace, this.customComponents));
10842
11271
  }
10843
11272
  recreatePageFormatsNotMainSession(width) {
10844
11273
  this.pagesFormat = [
@@ -11052,7 +11481,11 @@ class DisplayData extends EventEmitting {
11052
11481
  this.allPagesHeight += (lastPageNumber - firstPageNumber + 1) * (pageHeight + this.pagesSpace) + this.pagesSpace;
11053
11482
  });
11054
11483
  const lastPageNumber = this.paragraphs[this.paragraphs.length - 1].paragraphSettings.lastPageNumber;
11055
- this.emit('pagesCountChanged', { pagesCount: lastPageNumber, pageHeight: this.allPagesHeight + 2 * this.pagesSpace });
11484
+ this.emit('pagesCountChanged', {
11485
+ pagesCount: lastPageNumber,
11486
+ pageHeight: this.allPagesHeight + 2 * this.pagesSpace,
11487
+ pageWidth: this.pagesFormat[0].pageFormatModel.pageWidth // variable needed only for headers and footers (in headers and footers only 1 pageFormat)
11488
+ });
11056
11489
  }
11057
11490
  getAllParagraphsHeight() {
11058
11491
  return this.paragraphs.reduce((sum, x) => sum + x.paragraphSettings.height, 0);
@@ -11784,18 +12217,20 @@ class NoderEdgeComponent extends DestroyComponent {
11784
12217
  this.translateService = translateService;
11785
12218
  this.cdr = cdr;
11786
12219
  this.initialized = false;
12220
+ this.isVisible = false;
11787
12221
  this.pagesCountChangedHandler = (event) => {
11788
12222
  if (this._height === event.pageHeight) {
11789
12223
  return;
11790
12224
  }
11791
12225
  this._height = event.pageHeight;
11792
12226
  this.applyHeight();
11793
- this.editorService.changedEdgeSize(this.type, this.model.pageType);
12227
+ this.editorService.changedEdgeSize(this.type, this.model.pageType, event.pageWidth, this._height);
11794
12228
  };
11795
12229
  }
11796
12230
  ngOnDestroy() {
11797
12231
  this.session?.displayData.removeEventListener('pagesCountChanged', this.pagesCountChangedHandler);
11798
12232
  this.regulatorService.removeSession(this.sessionId);
12233
+ this.intersectionObserver?.disconnect();
11799
12234
  super.ngOnDestroy();
11800
12235
  }
11801
12236
  initialize() {
@@ -11814,14 +12249,8 @@ class NoderEdgeComponent extends DestroyComponent {
11814
12249
  this.edgeNameByType = this.getEdgeNameByType();
11815
12250
  this.cdr.detectChanges();
11816
12251
  });
11817
- }
11818
- setPageWidth(width) {
11819
- if (width === this.width) {
11820
- return;
11821
- }
11822
- this.session.displayData.recreatePageFormatsNotMainSession(width);
11823
- this.session.rerender(0);
11824
- this.edgeSession.renderer.loop.schedule({ full: true });
12252
+ this.intersectionObserver = this.initializeIntersectionObserver();
12253
+ this.intersectionObserver.observe(this.container.nativeElement);
11825
12254
  }
11826
12255
  enterEditMode() {
11827
12256
  DomHelper.addCssClass(this.container.nativeElement, this.editModeClass);
@@ -11864,6 +12293,22 @@ class NoderEdgeComponent extends DestroyComponent {
11864
12293
  const height = this.contentHeight > maxHeight ? maxHeight : this.contentHeight;
11865
12294
  DomHelper.setStyle(this.typeContainer.nativeElement.style, this.typeContainerPosition, `${height}px`);
11866
12295
  }
12296
+ initializeIntersectionObserver() {
12297
+ const options = {
12298
+ root: null,
12299
+ rootMargin: '50px',
12300
+ threshold: 0.01
12301
+ };
12302
+ return new IntersectionObserver(entries => {
12303
+ entries.forEach(entry => {
12304
+ const wasVisible = this.isVisible;
12305
+ this.isVisible = entry.isIntersecting;
12306
+ if (this.isVisible !== wasVisible) {
12307
+ this.renderer.setVisibility(this.isVisible);
12308
+ }
12309
+ });
12310
+ }, options);
12311
+ }
11867
12312
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderEdgeComponent, deps: [{ token: RegulatorService }, { token: EditorService }, { token: i3$1.TranslateService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
11868
12313
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: NoderEdgeComponent, isStandalone: false, selector: "app-nod-edge", inputs: { model: "model", generalProperties: "generalProperties", margins: "margins", width: "width", parentSessionId: "parentSessionId", isEvenEdgesExist: "isEvenEdgesExist", type: "type" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "typeContainer", first: true, predicate: ["locationType"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<div\n #container\n class=\"edit-container\"></div>\n<div\n #locationType\n class=\"location-type\">\n <span>{{ edgeNameByType }}</span>\n</div>\n", styles: [":host{height:100%;width:100%;background:transparent;display:block}.location-type{position:absolute;height:auto;width:auto;font-size:9pt;color:#333;background-color:#f2f2f2;border:1px solid #838282;border-radius:2px;padding:4px;margin-left:5px;z-index:2}.header-edit-mode{border-bottom:1px dashed #838282}.footer-edit-mode{border-top:1px dashed #838282}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11869
12314
  }
@@ -11893,10 +12338,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
11893
12338
  }] } });
11894
12339
 
11895
12340
  class Edges {
11896
- constructor(componentService, headers, footers, margins, pageWidth, parentSessionId, generalProperties) {
12341
+ constructor(componentService, headers, footers, margins, pageFormats, parentSessionId, generalProperties) {
11897
12342
  this.componentService = componentService;
11898
12343
  this.margins = margins;
11899
- this.pageWidth = pageWidth;
12344
+ this.pageFormats = pageFormats;
11900
12345
  this.parentSessionId = parentSessionId;
11901
12346
  this.generalProperties = generalProperties;
11902
12347
  this.headersComponents = [];
@@ -11913,23 +12358,19 @@ class Edges {
11913
12358
  }
11914
12359
  }
11915
12360
  createEdges(headerModel, footerModel) {
11916
- this.headersComponents.push(this.componentService.generateComponent(NoderEdgeComponent, {
11917
- model: headerModel,
11918
- margins: new MarginModel({ ...this.margins, bottom: 0 }),
11919
- type: EdgeType.Header,
11920
- width: this.pageWidth,
11921
- generalProperties: this.generalProperties,
11922
- parentSessionId: this.parentSessionId,
11923
- isEvenEdgesExist: false
11924
- }));
11925
- this.footersComponents.push(this.componentService.generateComponent(NoderEdgeComponent, {
11926
- model: footerModel,
11927
- margins: new MarginModel({ ...this.margins, top: 0 }),
11928
- type: EdgeType.Footer,
11929
- width: this.pageWidth,
12361
+ this.headersComponents.push(...this.createEdgesByPageFormats(headerModel, new MarginModel({ ...this.margins, bottom: 0 }), EdgeType.Header, false));
12362
+ this.footersComponents.push(...this.createEdgesByPageFormats(footerModel, new MarginModel({ ...this.margins, top: 0 }), EdgeType.Footer, false));
12363
+ }
12364
+ createEdgesByPageFormats(model, margins, type, isEvenEdgesExist) {
12365
+ const uniqueWidth = new Set(this.pageFormats.map(x => x.pageWidth));
12366
+ return Array.from(uniqueWidth).map(width => this.componentService.generateComponent(NoderEdgeComponent, {
12367
+ model,
12368
+ margins,
12369
+ type,
12370
+ width,
11930
12371
  generalProperties: this.generalProperties,
11931
12372
  parentSessionId: this.parentSessionId,
11932
- isEvenEdgesExist: false
12373
+ isEvenEdgesExist
11933
12374
  }));
11934
12375
  }
11935
12376
  removeEdges(pageType) {
@@ -11941,21 +12382,22 @@ class Edges {
11941
12382
  getTypeBySessionId(sessionId) {
11942
12383
  let component = this.headersComponents.find(x => x.instance.sessionId === sessionId);
11943
12384
  if (component) {
11944
- return { type: EdgeType.Header, pageType: component.instance.model.pageType };
12385
+ return { type: EdgeType.Header, pageType: component.instance.model.pageType, pageWidth: component.instance.width };
11945
12386
  }
11946
12387
  component = this.footersComponents.find(x => x.instance.sessionId === sessionId);
11947
- return { type: EdgeType.Footer, pageType: component.instance.model.pageType };
12388
+ return { type: EdgeType.Footer, pageType: component.instance.model.pageType, pageWidth: component.instance.width };
11948
12389
  }
11949
- getComponentByPage(page, type) {
12390
+ getComponentByPage(page, type, pageWidth) {
11950
12391
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11951
- return this.getComponent(components, page);
12392
+ return this.getComponents(components, page).find(x => x.instance.width === pageWidth);
11952
12393
  }
11953
12394
  getComponentByPageType(pageType, type) {
11954
12395
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11955
12396
  return components.find(x => x.instance.model.pageType === pageType);
11956
12397
  }
11957
- getComponentHeightByPageType(pageType, type) {
11958
- const component = this.getComponentByPageType(pageType, type);
12398
+ getComponentHeightByPageType(pageType, type, pageWidth) {
12399
+ const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
12400
+ const component = components.find(x => x.instance.model.pageType === pageType && x.instance.width === pageWidth);
11959
12401
  if (!component) {
11960
12402
  return 0;
11961
12403
  }
@@ -11967,9 +12409,9 @@ class Edges {
11967
12409
  const height = instance.contentHeight;
11968
12410
  return height > this.generalProperties.maxEdgeHeight ? this.generalProperties.maxEdgeHeight : height;
11969
12411
  }
11970
- getComponentHeightByType(pageType, type) {
12412
+ getComponentHeightByType(pageType, type, pageWidth) {
11971
12413
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11972
- const height = components.find(x => x.instance.model.pageType === pageType)?.instance.contentHeight ?? 0;
12414
+ const height = components.find(x => x.instance.model.pageType === pageType && x.instance.width === pageWidth)?.instance.contentHeight ?? 0;
11973
12415
  return height > this.generalProperties.maxEdgeHeight ? this.generalProperties.maxEdgeHeight : height;
11974
12416
  }
11975
12417
  toggleEditMode(isEdit) {
@@ -12013,26 +12455,21 @@ class Edges {
12013
12455
  return 1;
12014
12456
  return 0;
12015
12457
  })) {
12016
- const componentRef = this.componentService.generateComponent(NoderEdgeComponent, {
12017
- model,
12018
- margins,
12019
- type,
12020
- width: this.pageWidth,
12021
- generalProperties: this.generalProperties,
12022
- parentSessionId: this.parentSessionId,
12023
- isEvenEdgesExist
12024
- });
12025
- resultComponents.push(componentRef);
12458
+ resultComponents.push(...this.createEdgesByPageFormats(model, margins, type, isEvenEdgesExist));
12026
12459
  }
12027
12460
  return resultComponents;
12028
12461
  }
12029
- getComponent(edgeComponents, page) {
12030
- const defaultComponent = edgeComponents.find(x => x.instance.model.pageType === PageType.Default);
12462
+ getComponents(edgeComponents, page) {
12463
+ const defaultComponent = edgeComponents.filter(x => x.instance.model.pageType === PageType.Default);
12464
+ let targetType = PageType.Default;
12031
12465
  if (page === 1) {
12032
- return edgeComponents.find(x => x.instance.model.pageType === PageType.First) || defaultComponent;
12466
+ targetType = PageType.First;
12033
12467
  }
12034
- const targetType = page % 2 === 0 ? PageType.Even : PageType.Default;
12035
- return edgeComponents.find(x => x.instance.model.pageType === targetType) || defaultComponent;
12468
+ else if (page % 2 === 0) {
12469
+ targetType = PageType.Even;
12470
+ }
12471
+ const edges = edgeComponents.filter(x => x.instance.model.pageType === targetType);
12472
+ return edges.length > 0 ? edges : defaultComponent;
12036
12473
  }
12037
12474
  }
12038
12475
 
@@ -12456,7 +12893,7 @@ class EditSession {
12456
12893
  get scrollBarHeight() {
12457
12894
  return this.scrollBar?.element.clientHeight ?? 0; // only main session is scrollable
12458
12895
  }
12459
- constructor(displayData, sessionId, customContentService, model, selection, generalProperties, editorService, customComponents, type, scrollBar) {
12896
+ constructor(displayData, sessionId, customContentService, model, selection, generalProperties, editorService, customComponents, type, scrollBar, edgeType) {
12460
12897
  this.displayData = displayData;
12461
12898
  this.sessionId = sessionId;
12462
12899
  this.customContentService = customContentService;
@@ -12467,6 +12904,7 @@ class EditSession {
12467
12904
  this.customComponents = customComponents;
12468
12905
  this.type = type;
12469
12906
  this.scrollBar = scrollBar;
12907
+ this.edgeType = edgeType;
12470
12908
  this.tokenRe = new RegExp('^[' + UnicodeHelper.wordChars + '\\$_]+', 'g');
12471
12909
  this.nonTokenRe = new RegExp('^(?:[^' + UnicodeHelper.wordChars + '\\$_]|\\s])+', 'g');
12472
12910
  }
@@ -13085,6 +13523,10 @@ class EditSession {
13085
13523
  OperationsHelper.removeEdges(document.headers, document.footers, pageType);
13086
13524
  this.customComponents.edges.removeEdges(pageType);
13087
13525
  }
13526
+ updateDisplayData() {
13527
+ this.displayData.updateDataForModel();
13528
+ this.displayData.updateNextLineIndexes(0, this.displayData.paragraphs.length - 1);
13529
+ }
13088
13530
  }
13089
13531
 
13090
13532
  class GeneralPropertiesModel {
@@ -13216,7 +13658,8 @@ class RenderChangesModel {
13216
13658
  this.scroll ||
13217
13659
  this.size ||
13218
13660
  this.text ||
13219
- this.dragAndDrop);
13661
+ this.dragAndDrop ||
13662
+ this.visibilityChanged);
13220
13663
  }
13221
13664
  constructor(fields) {
13222
13665
  this.cursor = false;
@@ -13229,6 +13672,7 @@ class RenderChangesModel {
13229
13672
  this.size = false;
13230
13673
  this.text = false;
13231
13674
  this.dragAndDrop = false;
13675
+ this.visibilityChanged = false;
13232
13676
  if (!fields) {
13233
13677
  return;
13234
13678
  }
@@ -13361,6 +13805,16 @@ class HighlightLayer {
13361
13805
  const left = rangeInfo.leftPos;
13362
13806
  this.renderHighlight(this.getMarkerStyle(height, width, top, left), cssClass);
13363
13807
  }
13808
+ drawCustomElementHighlight(elementInfo, cssClass, screenParentRange) {
13809
+ const elementIndex = this.session.displayData.paragraphs[elementInfo.parentRange.start.row].startIndex + elementInfo.parentRange.start.column;
13810
+ const element = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === elementIndex);
13811
+ if (!element) {
13812
+ return;
13813
+ }
13814
+ const top = this.getTop(screenParentRange.start.row);
13815
+ const info = this.getRangeInfo(this.session, screenParentRange);
13816
+ this.renderHighlight(this.getMarkerStyle(elementInfo.location.height, elementInfo.location.width, top + elementInfo.location.top, info.leftPos + elementInfo.location.left), cssClass);
13817
+ }
13364
13818
  getRangeInfo(session, range) {
13365
13819
  const start = range.start;
13366
13820
  const end = range.end;
@@ -13383,34 +13837,43 @@ class SearchHighlightLayer extends HighlightLayer {
13383
13837
  this.className = 'noder-highlight';
13384
13838
  this.selectedClassName = 'noder-selected-highlight';
13385
13839
  this.markers = [];
13840
+ this.customElementsRanges = [];
13386
13841
  }
13387
13842
  update(config) {
13388
- if (!config) {
13843
+ if (!config?.isVisible) {
13389
13844
  return;
13390
13845
  }
13391
13846
  this.config = config;
13392
13847
  this.selectionIndex = 0;
13848
+ this.getVisibleCustomElementResults(config);
13393
13849
  if (this.active) {
13394
- const screenRange = this.active.toScreenRange(this.session);
13395
- if (!screenRange.isEmpty &&
13396
- (!config.visibleRange ||
13397
- (screenRange.start.row >= config.visibleRange.startScreenLine &&
13398
- screenRange.end.row <= config.visibleRange.endScreenLine))) {
13399
- if (screenRange.isSingleLine) {
13400
- this.drawSingleLineMarker(screenRange, this.selectedClassName);
13401
- }
13402
- else {
13403
- this.drawMultiLineMarker(screenRange, this.selectedClassName);
13850
+ if (this.active instanceof Range) {
13851
+ const screenRange = this.active.toScreenRange(this.session);
13852
+ if (!screenRange.isEmpty &&
13853
+ (!config.visibleRange ||
13854
+ (screenRange.start.row >= config.visibleRange.startScreenLine &&
13855
+ screenRange.end.row <= config.visibleRange.endScreenLine))) {
13856
+ if (screenRange.isSingleLine) {
13857
+ this.drawSingleLineMarker(screenRange, this.selectedClassName);
13858
+ }
13859
+ else {
13860
+ this.drawMultiLineMarker(screenRange, this.selectedClassName);
13861
+ }
13404
13862
  }
13405
13863
  }
13864
+ else {
13865
+ this.updateActiveResult();
13866
+ const screenParentRange = this.active.parentRange.toScreenRange(this.session);
13867
+ this.drawCustomElementHighlight(this.active, this.selectedClassName, screenParentRange);
13868
+ }
13406
13869
  }
13407
- if (this.markers) {
13870
+ if (this.markers?.length) {
13408
13871
  const ranges = this.markers
13409
13872
  .map(x => x.toScreenRange(this.session))
13410
13873
  .filter(x => !x.isEmpty &&
13411
13874
  (!config.visibleRange ||
13412
13875
  (x.start.row >= config.visibleRange.startScreenLine && x.end.row <= config.visibleRange.endScreenLine)) &&
13413
- !x.isEqual(this.active));
13876
+ ((this.active instanceof Range && !x.isEqual(this.active)) || !(this.active instanceof Range)));
13414
13877
  for (const range of ranges) {
13415
13878
  if (!range.isEmpty) {
13416
13879
  if (range.isSingleLine) {
@@ -13422,12 +13885,80 @@ class SearchHighlightLayer extends HighlightLayer {
13422
13885
  }
13423
13886
  }
13424
13887
  }
13888
+ if (this.customElementsRanges?.length) {
13889
+ for (const element of this.customElementsRanges) {
13890
+ if (!element.location ||
13891
+ (this.active &&
13892
+ this.active instanceof CustomElementInfo &&
13893
+ this.active.parentRange.isEqual(element.parentRange) &&
13894
+ this.active.location.isEqual(element.location))) {
13895
+ continue;
13896
+ }
13897
+ const screenParentRange = element.parentRange.toScreenRange(this.session);
13898
+ if (!config.visibleRange ||
13899
+ (screenParentRange.start.row >= config.visibleRange.startScreenLine &&
13900
+ screenParentRange.end.row <= config.visibleRange.endScreenLine)) {
13901
+ this.drawCustomElementHighlight(element, this.className, screenParentRange);
13902
+ }
13903
+ }
13904
+ }
13425
13905
  if (this.selectionIndex !== -1) {
13426
13906
  while (this.selectionIndex < this.element.childElementCount) {
13427
13907
  this.element.removeChild(this.element.lastChild);
13428
13908
  }
13429
13909
  }
13430
13910
  }
13911
+ getVisibleCustomElementResults(config) {
13912
+ if (!this.customElementsRanges?.length) {
13913
+ return;
13914
+ }
13915
+ const groupedByParentRange = [];
13916
+ for (const element of this.customElementsRanges) {
13917
+ if (element.location) {
13918
+ continue;
13919
+ }
13920
+ const existingGroup = groupedByParentRange.find(group => group.range.isEqual(element.parentRange));
13921
+ if (existingGroup) {
13922
+ existingGroup.elements.push(element);
13923
+ }
13924
+ else {
13925
+ groupedByParentRange.push({
13926
+ range: element.parentRange,
13927
+ elements: [element]
13928
+ });
13929
+ }
13930
+ }
13931
+ if (!groupedByParentRange.length) {
13932
+ return;
13933
+ }
13934
+ for (const group of groupedByParentRange) {
13935
+ const screenParentRange = group.range.toScreenRange(this.session);
13936
+ if (config.visibleRange &&
13937
+ (screenParentRange.start.row < config.visibleRange.startScreenLine ||
13938
+ screenParentRange.end.row > config.visibleRange.endScreenLine)) {
13939
+ continue;
13940
+ }
13941
+ const insertIndex = this.session.displayData.paragraphs[group.range.start.row].startIndex + group.range.start.column;
13942
+ const customElement = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === insertIndex);
13943
+ const newLocations = customElement.instance.getSearchResultLocations();
13944
+ if (!newLocations?.length) {
13945
+ continue;
13946
+ }
13947
+ for (let i = 0; i < newLocations.length; i++) {
13948
+ group.elements.find(x => x.index === i).location = newLocations[i];
13949
+ }
13950
+ }
13951
+ }
13952
+ updateActiveResult() {
13953
+ if (this.active instanceof CustomElementInfo && !this.active.location) {
13954
+ const active = this.customElementsRanges.find(x => this.active instanceof CustomElementInfo &&
13955
+ x.index === this.active.index &&
13956
+ x.parentRange.isEqual(this.active.parentRange));
13957
+ if (active) {
13958
+ this.active.location = active.location;
13959
+ }
13960
+ }
13961
+ }
13431
13962
  }
13432
13963
 
13433
13964
  class SelectionLayer extends HighlightLayer {
@@ -13483,8 +14014,10 @@ class Renderer extends EventEmitting {
13483
14014
  endLine: 0,
13484
14015
  endScreenLine: 0,
13485
14016
  endScreenFullLine: 0
13486
- }
14017
+ },
14018
+ isVisible: false
13487
14019
  };
14020
+ this.isVisible = false;
13488
14021
  this.changes = new RenderChangesModel();
13489
14022
  this.textareaSize = {
13490
14023
  height: 1,
@@ -13512,7 +14045,13 @@ class Renderer extends EventEmitting {
13512
14045
  return;
13513
14046
  }
13514
14047
  // text, scrolling and resize changes can cause the view port size to change
13515
- if (changes.full || changes.size || changes.text || changes.lines || changes.scroll) {
14048
+ if (changes.full ||
14049
+ changes.size ||
14050
+ changes.text ||
14051
+ changes.lines ||
14052
+ changes.scroll ||
14053
+ changes.search ||
14054
+ changes.visibilityChanged) {
13516
14055
  changes.apply(this.computeLayerConfig());
13517
14056
  DomHelper.translate(this.content, 0, -this.layerConfig.offset);
13518
14057
  DomHelper.setStyle(this.content.style, 'width', `${this.layerConfig.width}px`);
@@ -13538,6 +14077,9 @@ class Renderer extends EventEmitting {
13538
14077
  if (changes.dragAndDrop) {
13539
14078
  this.renderDragAndDropSelection();
13540
14079
  }
14080
+ if (changes.visibilityChanged) {
14081
+ this.renderSearchHighlights();
14082
+ }
13541
14083
  this.session.onRendered();
13542
14084
  }
13543
14085
  /**
@@ -13586,11 +14128,13 @@ class Renderer extends EventEmitting {
13586
14128
  this.loop.schedule({ search: true });
13587
14129
  }
13588
14130
  }
14131
+ updateCustomElementHighlights(ranges) {
14132
+ this.searchHighlightLayer.customElementsRanges = ranges;
14133
+ this.loop.schedule({ search: true });
14134
+ }
13589
14135
  updateActiveSearchHighlight(active) {
13590
- if (!this.searchHighlightLayer.active?.isEqual(active)) {
13591
- this.searchHighlightLayer.active = active;
13592
- this.loop.schedule({ search: true });
13593
- }
14136
+ this.searchHighlightLayer.active = active;
14137
+ this.loop.schedule({ search: true });
13594
14138
  }
13595
14139
  updateDragAndDropSelection(range) {
13596
14140
  if (range.isEmpty && this.dragAndDropSelectionLayer.marker) {
@@ -13609,12 +14153,24 @@ class Renderer extends EventEmitting {
13609
14153
  this.dragAndDropSelectionLayer.marker = null;
13610
14154
  this.loop.schedule({ dragAndDrop: true });
13611
14155
  }
14156
+ setVisibility(isVisible) {
14157
+ if (this.isVisible !== isVisible) {
14158
+ this.isVisible = isVisible;
14159
+ this.loop.schedule({ visibilityChanged: true });
14160
+ }
14161
+ }
13612
14162
  /**
13613
14163
  * Triggers a full update of the text, for all the rows.
13614
14164
  **/
13615
14165
  updateText() {
13616
14166
  this.loop.schedule({ text: true });
13617
14167
  }
14168
+ updateTextAndCursor() {
14169
+ this.loop.schedule({ text: true, cursor: true });
14170
+ }
14171
+ updateMarker() {
14172
+ this.loop.schedule({ marker: true });
14173
+ }
13618
14174
  updateCursor() {
13619
14175
  this.loop.schedule({ cursor: true });
13620
14176
  }
@@ -13686,7 +14242,8 @@ class Renderer extends EventEmitting {
13686
14242
  contentRange: new DistanceModel({ start: 0, end: displayData.paragraphs.filter(x => x.paragraphSettings).length - 1 }),
13687
14243
  maxHeight,
13688
14244
  offset: 0,
13689
- scrollTop: this.session.scrollTop
14245
+ scrollTop: this.session.scrollTop,
14246
+ isVisible: this.isVisible
13690
14247
  };
13691
14248
  return changes;
13692
14249
  }
@@ -13787,16 +14344,6 @@ class ScrollBar {
13787
14344
  }
13788
14345
  }
13789
14346
 
13790
- class SessionModel {
13791
- constructor(session, renderer, sessionId, parentSessionId, source) {
13792
- this.session = session;
13793
- this.renderer = renderer;
13794
- this.sessionId = sessionId;
13795
- this.parentSessionId = parentSessionId;
13796
- this.source = source;
13797
- }
13798
- }
13799
-
13800
14347
  class VirtualRenderer {
13801
14348
  get cursorLayer() {
13802
14349
  return this.renderer.cursorLayer;
@@ -13850,7 +14397,13 @@ class VirtualRenderer {
13850
14397
  return;
13851
14398
  }
13852
14399
  // text, scrolling and resize changes can cause the view port size to change
13853
- if (changes.full || changes.size || changes.text || changes.lines || changes.scroll) {
14400
+ if (changes.full ||
14401
+ changes.size ||
14402
+ changes.text ||
14403
+ changes.lines ||
14404
+ changes.scroll ||
14405
+ changes.search ||
14406
+ changes.visibilityChanged) {
13854
14407
  changes.apply(this.computeLayerConfig());
13855
14408
  DomHelper.translate(this.renderer.content, 0, -this.layerConfig.offset);
13856
14409
  DomHelper.setStyle(this.renderer.content.style, 'width', `${this.layerConfig.width}px`);
@@ -13880,6 +14433,9 @@ class VirtualRenderer {
13880
14433
  if (changes.dragAndDrop) {
13881
14434
  this.renderDragAndDropSelection();
13882
14435
  }
14436
+ if (changes.visibilityChanged) {
14437
+ this.renderSearchHighlights();
14438
+ }
13883
14439
  }
13884
14440
  /**
13885
14441
  * Triggers a resize of the editor
@@ -13946,6 +14502,9 @@ class VirtualRenderer {
13946
14502
  updateSearchHighlights(ranges) {
13947
14503
  this.renderer.updateSearchHighlights(ranges);
13948
14504
  }
14505
+ updateCustomElementHighlights(ranges) {
14506
+ this.renderer.updateCustomElementHighlights(ranges);
14507
+ }
13949
14508
  updateActiveSearchHighlight(active) {
13950
14509
  this.renderer.updateActiveSearchHighlight(active);
13951
14510
  }
@@ -13961,9 +14520,18 @@ class VirtualRenderer {
13961
14520
  updateText() {
13962
14521
  this.renderer.updateText();
13963
14522
  }
14523
+ updateTextAndCursor() {
14524
+ this.renderer.updateTextAndCursor();
14525
+ }
14526
+ updateMarker() {
14527
+ this.renderer.updateMarker();
14528
+ }
13964
14529
  updateCursor() {
13965
14530
  this.renderer.updateCursor();
13966
14531
  }
14532
+ setVisibility(isVisible) {
14533
+ this.renderer.setVisibility(isVisible);
14534
+ }
13967
14535
  scrollSelectionIntoView(anchor, lead, offset) {
13968
14536
  // first scroll anchor into view then scroll lead into view
13969
14537
  this.scrollCursorIntoView(anchor, offset);
@@ -14048,7 +14616,8 @@ class VirtualRenderer {
14048
14616
  offset: 0,
14049
14617
  visibleRange,
14050
14618
  scrollTop: this.scrollBar.scrollTop,
14051
- pages: visibleRange.pages
14619
+ pages: visibleRange.pages,
14620
+ isVisible: true
14052
14621
  };
14053
14622
  return changes;
14054
14623
  }
@@ -14223,7 +14792,7 @@ class RegulatorService {
14223
14792
  this.sessions = [];
14224
14793
  this.sessionIdIncrement = 0;
14225
14794
  }
14226
- addMainSession(model, pageWidth, scalingRatio, container) {
14795
+ addMainSession(model, scalingRatio, container) {
14227
14796
  const sessionId = ++this.sessionIdIncrement;
14228
14797
  const defaultPageFormat = model.pageFormats[model.pageFormats?.length - 1];
14229
14798
  const properties = new GeneralPropertiesModel({
@@ -14242,7 +14811,7 @@ class RegulatorService {
14242
14811
  footer: defaultPageFormat.marginFooter > 0 ? defaultPageFormat.marginFooter : 0
14243
14812
  });
14244
14813
  const edgesMargins = new MarginModel({ ...pageMargin, top: pageMargin.header, bottom: pageMargin.footer });
14245
- const edges = new Edges(this.componentService, model.headers, model.footers, edgesMargins, pageWidth, sessionId, properties);
14814
+ const edges = new Edges(this.componentService, model.headers, model.footers, edgesMargins, model.pageFormats, sessionId, properties);
14246
14815
  properties.numberingInfo = {};
14247
14816
  const customComponents = { images: [], tables: [], tabs: [], customElements: [], edges: edges };
14248
14817
  const displayData = new DisplayData(model, properties, sessionId, model.pageFormats, DocumentInfo.pagesSpace, customComponents, this.customContentService, this.editorService);
@@ -14275,7 +14844,7 @@ class RegulatorService {
14275
14844
  const sessionId = ++this.sessionIdIncrement;
14276
14845
  const customComponents = { images: [], tables: [], tabs: [], customElements: [], edges: null };
14277
14846
  const displayData = new DisplayData(component.model, component.generalProperties, sessionId, this.getPageFormats(component.margins, component.width), 0, customComponents, this.customContentService, this.editorService);
14278
- const session = new EditSession(displayData, sessionId, this.customContentService, component.model, this.selection, component.generalProperties, this.editorService, customComponents, 'edge');
14847
+ const session = new EditSession(displayData, sessionId, this.customContentService, component.model, this.selection, component.generalProperties, this.editorService, customComponents, 'edge', null, component.type);
14279
14848
  const renderer = new Renderer(component.container.nativeElement, session);
14280
14849
  const source = new EdgeSessionSourceModel(component.model.pageType, component.type);
14281
14850
  const newSession = new SessionModel(session, renderer, sessionId, component.parentSessionId, source);
@@ -14317,11 +14886,44 @@ class RegulatorService {
14317
14886
  setCurrentSession(session) {
14318
14887
  const previous = this.currentSession;
14319
14888
  this.selection.clearSelection();
14320
- this.currentSession.renderer.hideCursor();
14889
+ if (this.currentSession.session.isEdge()) {
14890
+ this.sessions.forEach(x => {
14891
+ if (x.session.edgeType === this.currentSession.session.edgeType) {
14892
+ x.renderer.hideCursor();
14893
+ }
14894
+ });
14895
+ }
14896
+ else {
14897
+ this.currentSession.renderer.hideCursor();
14898
+ }
14321
14899
  this.currentSession.renderer.updateSelection(this.selection.selectedRange);
14322
14900
  this.currentSession = session;
14323
- this.currentSession.renderer.showCursor();
14324
- this.arrangeEdgesForSessionChange(previous.session, session.session);
14901
+ if (session.session.isEdge()) {
14902
+ this.sessions.forEach(x => {
14903
+ if (x.session.edgeType === session.session.edgeType) {
14904
+ x.renderer.showCursor();
14905
+ this.arrangeEdgesForSessionChange(previous.session, x.session);
14906
+ }
14907
+ });
14908
+ }
14909
+ else {
14910
+ this.currentSession.renderer.showCursor();
14911
+ this.arrangeEdgesForSessionChange(previous.session, session.session);
14912
+ }
14913
+ }
14914
+ updateCursorPosition() {
14915
+ if (!this.currentSession.session.isEdge()) {
14916
+ return;
14917
+ }
14918
+ this.sessions.forEach(x => {
14919
+ if (x.session.edgeType === this.currentSession.session.edgeType) {
14920
+ x.renderer.updateSelection(this.selection.selectedRange);
14921
+ if (this.selection.isEmpty) {
14922
+ x.renderer.updateCursor();
14923
+ }
14924
+ x.renderer.updateMarker();
14925
+ }
14926
+ });
14325
14927
  }
14326
14928
  getSessionModel(sessionId) {
14327
14929
  return this.sessions.find(x => x.sessionId === sessionId);
@@ -14378,8 +14980,19 @@ class RegulatorService {
14378
14980
  }
14379
14981
  arrangeEdgeChange(sessionId) {
14380
14982
  const edgeSessionId = this.getEdgeSessionId(sessionId);
14381
- const { type, pageType } = this.mainSession.session.customComponents.edges.getTypeBySessionId(edgeSessionId);
14382
- this.mainSession.renderer.edgesLayer.updateSingle(type, pageType);
14983
+ const { type, pageType, pageWidth } = this.mainSession.session.customComponents.edges.getTypeBySessionId(edgeSessionId);
14984
+ this.mainSession.renderer.edgesLayer.updateSingle(type, pageType, pageWidth);
14985
+ }
14986
+ forceUpdateDataForEdges() {
14987
+ if (this.currentSession.session.isEdge()) {
14988
+ return;
14989
+ }
14990
+ this.sessions.forEach(x => {
14991
+ if (x.session.isEdge() && x.session.edgeType === this.currentSession.session.edgeType) {
14992
+ x.session.updateDisplayData();
14993
+ x.renderer.updateTextAndCursor();
14994
+ }
14995
+ });
14383
14996
  }
14384
14997
  getEdgeSessionId(sessionId) {
14385
14998
  let session = this.getSession(sessionId);
@@ -17125,6 +17738,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
17125
17738
  args: ['class.noder-modal']
17126
17739
  }] } });
17127
17740
 
17741
+ class SearchResultLocation {
17742
+ constructor(init) {
17743
+ Object.assign(this, init);
17744
+ }
17745
+ isEqual(other) {
17746
+ return this.width === other.width && this.height === other.height && this.top === other.top && this.left === other.left;
17747
+ }
17748
+ }
17749
+
17128
17750
  class DocumentNameModel {
17129
17751
  constructor(fields) {
17130
17752
  if (fields) {
@@ -17186,5 +17808,5 @@ class OperationModel {
17186
17808
  * Generated bundle index. Do not edit.
17187
17809
  */
17188
17810
 
17189
- export { AddLinkDialogComponent, AddLinkMobileComponent, Alignment, BaseNoderComponent, BreakTypes, CommandModel, CommandType, CommandsService, ConfirmDialogComponent, DEFAULT_BACKGROUND_COLOR, DEFAULT_EDGE_MAX_HEIGHT_MULTIPLIER, DEFAULT_FONT_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_HEADINGS, DEFAULT_HEADING_STYLE_ID, DEFAULT_PARAGRAPH_STYLE, DEFAULT_TAB_WIDTH, DEFAULT_TEXT_STYLE, DEFAULT_TOOLBAR_STYLES, DefaultImageApiService, DestroyComponent, DocumentInfo, DocumentModel, DocumentNameModel, DocxModel, DomHelper, EditorComponent, EditorMobileToolbarComponent, EditorModule, EditorService, EditorTitleComponent, EditorTitleMobileComponent, EditorToolbarComponent, EditorToolbarMode, EditorToolbarModule, EditorToolbarService, ElementDataModel, ElementModel, ExternalComponent, ExternalElementModel, ExternalElementService, FileSourceModel, FormatStyleHelper, HYPERLINK_FONT_COLOR, HYPERLINK_HEADING_STYLE_ID, ImageApiService, ImageDataModel, LastDocumentRevisionModel, MenuDropdownsComponent, MenuDropdownsMobileComponent, Mode, NEW_LINE_MARKUP, NoderTranslateLoader, NumberingLevelModel, OperationModel, OperationsHistoryInfoModel, PageSetupComponent, PageType, ParagraphStyleModel, RevisionHelper, RevisionModel, TextFormatMobileComponent, TextStyleModel, ToolbarActionsComponent };
17811
+ export { AddLinkDialogComponent, AddLinkMobileComponent, Alignment, BaseNoderComponent, BreakTypes, CommandModel, CommandType, CommandsService, ConfirmDialogComponent, DEFAULT_BACKGROUND_COLOR, DEFAULT_EDGE_MAX_HEIGHT_MULTIPLIER, DEFAULT_FONT_COLOR, DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_HEADINGS, DEFAULT_HEADING_STYLE_ID, DEFAULT_PARAGRAPH_STYLE, DEFAULT_TAB_WIDTH, DEFAULT_TEXT_STYLE, DEFAULT_TOOLBAR_STYLES, DefaultImageApiService, DestroyComponent, DocumentInfo, DocumentModel, DocumentNameModel, DocxModel, DomHelper, EditorComponent, EditorMobileToolbarComponent, EditorModule, EditorService, EditorTitleComponent, EditorTitleMobileComponent, EditorToolbarComponent, EditorToolbarMode, EditorToolbarModule, EditorToolbarService, ElementDataModel, ElementModel, ExternalComponent, ExternalElementModel, ExternalElementService, FileSourceModel, FontMetrics, FormatStyleHelper, HYPERLINK_FONT_COLOR, HYPERLINK_HEADING_STYLE_ID, ImageApiService, ImageDataModel, LastDocumentRevisionModel, MenuDropdownsComponent, MenuDropdownsMobileComponent, Mode, NEW_LINE_MARKUP, NoderTranslateLoader, NumberingLevelModel, OperationModel, OperationsHistoryInfoModel, PageSetupComponent, PageType, ParagraphStyleModel, RevisionHelper, RevisionModel, SearchResultLocation, TextFormatMobileComponent, TextStyleModel, ToolbarActionsComponent };
17190
17812
  //# sourceMappingURL=talrace-ngx-noder.mjs.map