@talrace/ngx-noder 0.0.43 → 0.0.45

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 (45) hide show
  1. package/assets/i18n/noder.en.json +7 -1
  2. package/assets/i18n/noder.es.json +7 -1
  3. package/assets/i18n/noder.ru.json +7 -1
  4. package/fesm2022/talrace-ngx-noder.mjs +1194 -384
  5. package/fesm2022/talrace-ngx-noder.mjs.map +1 -1
  6. package/lib/apart-components/editor-ruler/editor-ruler.component.d.ts +9 -2
  7. package/lib/apart-components/editor-search-bar/editor-search-bar.component.d.ts +1 -0
  8. package/lib/apart-components/editor-toolbar/shared/enums/tab-alignment.enum.d.ts +7 -0
  9. package/lib/apart-components/tab-settings-dialog/tab-settings-dialog.component.d.ts +33 -0
  10. package/lib/editor/components/edges/edge-element.model.d.ts +3 -2
  11. package/lib/editor/components/edges/edge.component.d.ts +3 -1
  12. package/lib/editor/components/edges/edges.d.ts +9 -6
  13. package/lib/editor/components/external-element/external.component.d.ts +2 -0
  14. package/lib/editor/components/shared/abstract/base.component.d.ts +5 -2
  15. package/lib/editor/components/shared/enums/line-styles.enum.d.ts +36 -0
  16. package/lib/editor/components/shared/enums/positions.enum.d.ts +9 -0
  17. package/lib/editor/components/tab/tab.component.d.ts +1 -3
  18. package/lib/editor/components/tab/tab.helper.d.ts +2 -1
  19. package/lib/editor/components/table/components/table-cell.component.d.ts +6 -2
  20. package/lib/editor/components/table/helpers/table-cell.helper.d.ts +7 -0
  21. package/lib/editor/content/display-data/display-data.d.ts +1 -1
  22. package/lib/editor/display/custom-element-info.model.d.ts +8 -0
  23. package/lib/editor/display/layers/edges.layer.d.ts +1 -1
  24. package/lib/editor/display/layers/highlight.layer.d.ts +2 -0
  25. package/lib/editor/display/layers/layer.config.d.ts +1 -0
  26. package/lib/editor/display/layers/search-highlight.layer.d.ts +5 -1
  27. package/lib/editor/display/render-changes.interface.d.ts +1 -0
  28. package/lib/editor/display/render-changes.model.d.ts +1 -0
  29. package/lib/editor/display/renderer.d.ts +7 -1
  30. package/lib/editor/display/virtual.renderer.d.ts +6 -1
  31. package/lib/editor/execution/edit.session.d.ts +5 -2
  32. package/lib/editor/execution/editor.d.ts +4 -2
  33. package/lib/editor/execution/regulator.service.d.ts +3 -1
  34. package/lib/editor/gadgets/search/custom-element-search-result.model.d.ts +9 -0
  35. package/lib/editor/gadgets/search/search-result-location.model.d.ts +8 -0
  36. package/lib/editor/gadgets/search/search-result.model.d.ts +8 -0
  37. package/lib/editor/gadgets/search/search.d.ts +20 -8
  38. package/lib/editor/gadgets/search/table-location.interface.d.ts +6 -0
  39. package/lib/editor/interaction/editor.service.d.ts +10 -3
  40. package/lib/models/generated/form-interfaces/tab-setting-form.interface.d.ts +5 -0
  41. package/lib/models/generated/paragraph-style.model.d.ts +2 -0
  42. package/lib/models/generated/tab-setting.model.d.ts +5 -0
  43. package/package.json +1 -1
  44. package/public-api.d.ts +2 -0
  45. package/lib/editor/gadgets/search/search-result.interface.d.ts +0 -5
@@ -1,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Directive, Injectable, inject, ChangeDetectorRef, HostBinding, Input, Component, ChangeDetectionStrategy, ViewChild, InjectionToken, createComponent, EventEmitter, Output, HostListener, input, signal, computed, effect, NgModule, Inject } from '@angular/core';
2
+ import { Directive, Injectable, signal, inject, ChangeDetectorRef, HostBinding, Input, Component, ChangeDetectionStrategy, ViewChild, InjectionToken, createComponent, EventEmitter, Output, HostListener, Inject, input, computed, effect, NgModule } from '@angular/core';
3
3
  import { Subject, BehaviorSubject, fromEvent, throttleTime, take, filter, debounceTime, distinctUntilChanged, startWith, takeUntil, tap, map, catchError } from 'rxjs';
4
- import * as i1$1 from '@angular/common/http';
4
+ import * as i1$2 from '@angular/common/http';
5
5
  import { HttpHeaders } from '@angular/common/http';
6
6
  import * as i3 from '@angular/common';
7
7
  import { CommonModule, AsyncPipe } from '@angular/common';
@@ -24,10 +24,14 @@ import { ComponentPortal } from '@angular/cdk/portal';
24
24
  import * as i1 from '@angular/cdk/overlay';
25
25
  import { OverlayConfig } from '@angular/cdk/overlay';
26
26
  import * as i5$3 from '@angular/cdk/clipboard';
27
+ import * as i1$1 from '@angular/material/dialog';
28
+ import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
29
+ import { marker } from '@biesbjerg/ngx-translate-extract-marker';
30
+ import * as i7 from '@angular/material/select';
31
+ import { MatSelectModule } from '@angular/material/select';
32
+ import * as i3$2 from '@angular/material/core';
27
33
  import * as i8 from '@angular/material/sidenav';
28
34
  import { MatSidenavModule } from '@angular/material/sidenav';
29
- import * as i1$2 from '@angular/material/dialog';
30
- import { MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog';
31
35
  import { TranslateHttpLoader } from '@ngx-translate/http-loader';
32
36
  import * as i4$1 from '@angular/material/menu';
33
37
  import { MatMenuModule } from '@angular/material/menu';
@@ -36,9 +40,6 @@ import { MatExpansionModule } from '@angular/material/expansion';
36
40
  import * as i2$1 from '@angular/platform-browser';
37
41
  import * as i2$2 from '@angular/material/autocomplete';
38
42
  import { MatAutocompleteModule } from '@angular/material/autocomplete';
39
- import * as i8$1 from '@angular/material/select';
40
- import { MatSelectModule } from '@angular/material/select';
41
- import * as i3$2 from '@angular/material/core';
42
43
  import * as i5$4 from 'ngx-colors';
43
44
  import { NgxColorsModule } from 'ngx-colors';
44
45
  import * as i3$3 from '@angular/material/button-toggle';
@@ -153,7 +154,8 @@ const DEFAULT_PARAGRAPH_STYLE = new ParagraphStyleModel({
153
154
  numberingLevel: null,
154
155
  contextualSpacing: false,
155
156
  beforeAutospacing: false,
156
- afterAutospacing: false
157
+ afterAutospacing: false,
158
+ tabSettings: []
157
159
  });
158
160
  const DEFAULT_HEADINGS = [
159
161
  new HeadingModel({
@@ -390,6 +392,94 @@ class FormatStyleHelper {
390
392
  }
391
393
  }
392
394
 
395
+ class FontMetrics {
396
+ static { this.storageKey = 'metrics'; }
397
+ static { this.versionKey = 'editorVersion'; }
398
+ /**
399
+ * Key value pairs for calculated sizes of char symbols in HTML element
400
+ */
401
+ static { this.metrics = JSON.parse(localStorage.getItem(this.storageKey)) || {}; }
402
+ /**
403
+ * Key value pairs for identifiers and font strings
404
+ */
405
+ static { this.fontStringMap = {}; }
406
+ static checkVersion(version) {
407
+ let identifier = localStorage.getItem(this.versionKey);
408
+ if (identifier === version) {
409
+ return;
410
+ }
411
+ localStorage.removeItem(this.storageKey);
412
+ localStorage.setItem(this.versionKey, version);
413
+ }
414
+ static measureCharSize(ch, contentStyle) {
415
+ let identifier = this.fontStringMap[contentStyle];
416
+ if (!identifier) {
417
+ identifier = contentStyle.split(' ').join('_');
418
+ this.fontStringMap[contentStyle] = identifier;
419
+ }
420
+ this.metrics[identifier] ??= {};
421
+ if (!this.metrics[identifier][ch] || isNaN(this.metrics[identifier][ch].font)) {
422
+ this.metrics[identifier][ch] = this.calculateCanvas(ch, contentStyle);
423
+ localStorage.setItem(this.storageKey, JSON.stringify(this.metrics));
424
+ }
425
+ return this.metrics[identifier][ch];
426
+ }
427
+ static calculateCanvas(ch, contentStyle) {
428
+ this.canvasNode ||= document.createElement('canvas');
429
+ const fontBaseLine = this.fontBaseline(contentStyle, ch);
430
+ const context = this.canvasNode.getContext('2d');
431
+ context.font = contentStyle;
432
+ const textMetrics = context.measureText(ch);
433
+ return {
434
+ width: textMetrics.width,
435
+ height: textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent,
436
+ baseline: fontBaseLine.baseline,
437
+ content: fontBaseLine.content,
438
+ font: fontBaseLine.font,
439
+ line: fontBaseLine.line,
440
+ multiplier: fontBaseLine.multiplier,
441
+ ascent: textMetrics.fontBoundingBoxAscent,
442
+ descent: textMetrics.fontBoundingBoxDescent
443
+ };
444
+ }
445
+ static fontBaseline(contentStyle, text) {
446
+ const container = document.body;
447
+ this.measureDiv ||= document.createElement('div');
448
+ this.strut ||= document.createElement('span');
449
+ if (text === ' ') {
450
+ text = 'X';
451
+ }
452
+ this.measureDiv.style.font = contentStyle;
453
+ this.measureDiv.style.lineHeight = '1';
454
+ this.measureDiv.style.position = 'absolute';
455
+ this.measureDiv.style.visibility = 'hidden';
456
+ this.measureDiv.style.margin = '0';
457
+ this.measureDiv.style.padding = '0';
458
+ this.measureDiv.innerHTML = text;
459
+ this.strut.style.fontSize = '0';
460
+ this.strut.style.verticalAlign = 'baseline';
461
+ this.strut.style.padding = '0 10px';
462
+ this.measureDiv.classList.add('font-baseline');
463
+ this.measureDiv.appendChild(this.strut);
464
+ container.appendChild(this.measureDiv);
465
+ const computedStyle = window.getComputedStyle(this.measureDiv);
466
+ const fontSize = parseFloat(computedStyle.fontSize);
467
+ const baselineHeight = fontSize - this.strut.offsetTop;
468
+ const strutHeight = this.measureDiv.offsetHeight;
469
+ const lineHeight = parseFloat(computedStyle.lineHeight) || this.measureDiv.offsetHeight;
470
+ this.measureDiv.parentNode.removeChild(this.measureDiv);
471
+ this.measureDiv.innerHTML = '';
472
+ this.strut.innerHTML = '';
473
+ return {
474
+ baseline: baselineHeight,
475
+ content: strutHeight,
476
+ font: fontSize,
477
+ line: lineHeight,
478
+ multiplier: fontSize / baselineHeight
479
+ };
480
+ }
481
+ }
482
+
393
483
  class ElementDataModel {
394
484
  constructor(id, guid, type) {
395
485
  this.id = id;
@@ -506,6 +596,7 @@ class EditorService {
506
596
  this._rightMarginPageFormat$ = new Subject();
507
597
  this._firstLinePosition$ = new Subject();
508
598
  this._leftIndentParagraph$ = new Subject();
599
+ this._tabSettings$ = new Subject();
509
600
  this._rightIndentParagraph$ = new Subject();
510
601
  this._paragraphStyle$ = new BehaviorSubject(new ParagraphStyleModel());
511
602
  }
@@ -723,12 +814,18 @@ class EditorService {
723
814
  get leftIndentParagraph$() {
724
815
  return this._leftIndentParagraph$.asObservable();
725
816
  }
817
+ get tabSettings$() {
818
+ return this._tabSettings$.asObservable();
819
+ }
726
820
  get rightIndentParagraph$() {
727
821
  return this._rightIndentParagraph$.asObservable();
728
822
  }
729
823
  get paragraphStyle$() {
730
824
  return this._paragraphStyle$.asObservable();
731
825
  }
826
+ tabSettings(value) {
827
+ this._tabSettings$.next(value);
828
+ }
732
829
  applyFirstLinePosition(value) {
733
830
  this._firstLinePosition$.next(value);
734
831
  }
@@ -823,20 +920,20 @@ class EditorService {
823
920
  disableSelection() {
824
921
  this._disableSelection$.next();
825
922
  }
826
- openElementSidenav(component, model, contentWidth) {
827
- this._toggleSidenav$.next({ open: true, component, data: { model, contentWidth } });
923
+ openElementSidenav(component, model, contentWidth, focus) {
924
+ this._toggleSidenav$.next({ open: true, component, focus, data: { model, contentWidth } });
828
925
  }
829
- openSidenav(component) {
830
- this._toggleSidenav$.next({ open: true, component });
926
+ openSidenav(component, focus) {
927
+ this._toggleSidenav$.next({ open: true, component, focus });
831
928
  }
832
929
  closeSidenav() {
833
- this._toggleSidenav$.next({ open: false, component: null });
930
+ this._toggleSidenav$.next({ open: false, component: null, focus: false });
834
931
  }
835
932
  changedTableSize(insertIndex, sessionId) {
836
933
  this._changedTableSize$.next({ insertIndex, sessionId });
837
934
  }
838
- changedEdgeSize(edgeType, pageType) {
839
- this._changedEdgeSize$.next({ edgeType, pageType });
935
+ changedEdgeSize(edgeType, pageType, pageWidth, pageHeight) {
936
+ this._changedEdgeSize$.next({ edgeType, pageType, pageWidth, pageHeight });
840
937
  }
841
938
  imageLoaded(sessionId) {
842
939
  this._imageLoaded$.next(sessionId);
@@ -947,6 +1044,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
947
1044
  class BaseNoderComponent extends DestroyComponent {
948
1045
  constructor() {
949
1046
  super(...arguments);
1047
+ this.height = signal(0);
1048
+ this.width = signal(0);
950
1049
  this._isFocused = false;
951
1050
  this.cdr = inject(ChangeDetectorRef);
952
1051
  this.editorService = inject(EditorService);
@@ -975,6 +1074,12 @@ class BaseNoderComponent extends DestroyComponent {
975
1074
  requestStyle() {
976
1075
  this.editorService.receiveTextStyle(this);
977
1076
  }
1077
+ searchComponent(_) {
1078
+ return 0;
1079
+ }
1080
+ getSearchResultLocations() {
1081
+ return [];
1082
+ }
978
1083
  rerender() {
979
1084
  this.editorService.rerender(this.insertIndex);
980
1085
  }
@@ -1003,16 +1108,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
1003
1108
  }] } });
1004
1109
 
1005
1110
  class ExternalComponent extends BaseNoderComponent {
1111
+ constructor() {
1112
+ super(...arguments);
1113
+ this.focusSidenav = true;
1114
+ }
1115
+ skipSidenav() {
1116
+ return this.editorService.isViewOnly;
1117
+ }
1006
1118
  focus() {
1007
1119
  super.focus();
1008
- if (this.editorService.isViewOnly) {
1120
+ if (this.skipSidenav()) {
1009
1121
  return;
1010
1122
  }
1011
- this.editorService.openElementSidenav(this.sidenavComponent, this.content, this.contentWidth);
1123
+ this.editorService.openElementSidenav(this.sidenavComponent, this.content, this.contentWidth, this.focusSidenav);
1012
1124
  }
1013
1125
  blur() {
1014
1126
  super.blur();
1015
- if (this.editorService.isViewOnly) {
1127
+ if (this.skipSidenav()) {
1016
1128
  return;
1017
1129
  }
1018
1130
  this.editorService.closeSidenav();
@@ -1266,6 +1378,12 @@ class CreateEdgesModel {
1266
1378
  }
1267
1379
  }
1268
1380
 
1381
+ class CustomElementSearchResult {
1382
+ constructor(init) {
1383
+ Object.assign(this, init);
1384
+ }
1385
+ }
1386
+
1269
1387
  class DeleteModel {
1270
1388
  constructor(fields) {
1271
1389
  if (fields) {
@@ -5222,11 +5340,11 @@ class EdgeElementModel {
5222
5340
  }
5223
5341
  Object.assign(this, fields);
5224
5342
  }
5225
- isNotCopy(type, pageType) {
5226
- return this.edgeType === type && this.pageType === pageType && this.isOrigin;
5343
+ isNotCopy(type, pageType, pageWidth) {
5344
+ return this.edgeType === type && this.pageType === pageType && this.pageWidth === pageWidth && this.isOrigin;
5227
5345
  }
5228
- isCopy(type, pageType) {
5229
- return this.edgeType === type && this.pageType === pageType && !this.isOrigin;
5346
+ isCopy(type, pageType, pageWidth) {
5347
+ return this.edgeType === type && this.pageType === pageType && this.pageWidth === pageWidth && !this.isOrigin;
5230
5348
  }
5231
5349
  isWithin(start, end) {
5232
5350
  return this.container.offsetTop < end && this.container.offsetTop + this.container.offsetHeight > start;
@@ -5484,14 +5602,14 @@ class EdgesLayer {
5484
5602
  this.element.className = 'noder-layer noder-edges-layer';
5485
5603
  this.parentElement.appendChild(this.element);
5486
5604
  }
5487
- updateSingle(type, pageType) {
5605
+ updateSingle(type, pageType, pageWidth) {
5488
5606
  const pages = [];
5489
- let index = this.elements.findIndex(x => x.isCopy(type, pageType));
5607
+ let index = this.elements.findIndex(x => x.isCopy(type, pageType, pageWidth));
5490
5608
  while (index !== -1) {
5491
5609
  pages.push(this.elements[index].page);
5492
5610
  DomHelper.removeElement(this.elements[index].container);
5493
5611
  this.elements.splice(index, 1);
5494
- index = this.elements.findIndex(x => x.isCopy(type, pageType));
5612
+ index = this.elements.findIndex(x => x.isCopy(type, pageType, pageWidth));
5495
5613
  }
5496
5614
  const start = -this.element.offsetTop;
5497
5615
  const end = start + this.parentElement.clientHeight;
@@ -5503,7 +5621,7 @@ class EdgesLayer {
5503
5621
  this.renderPageFooterComponent(page, start, end);
5504
5622
  }
5505
5623
  }
5506
- let origin = this.elements.find(x => x.isNotCopy(type, pageType));
5624
+ let origin = this.elements.find(x => x.isNotCopy(type, pageType, pageWidth));
5507
5625
  if (origin) {
5508
5626
  const edge = this.session.customComponents.edges.getComponentByPageType(pageType, type);
5509
5627
  const height = this.session.customComponents.edges.getComponentHeight(edge.instance);
@@ -5536,7 +5654,7 @@ class EdgesLayer {
5536
5654
  while (removeIndex !== -1) {
5537
5655
  const element = this.elements[removeIndex];
5538
5656
  if (element.isOrigin) {
5539
- const copy = this.elements.find(x => x.isCopy(element.edgeType, element.pageType));
5657
+ const copy = this.elements.find(x => x.isCopy(element.edgeType, element.pageType, element.pageWidth));
5540
5658
  if (copy) {
5541
5659
  copy.substitute(element);
5542
5660
  }
@@ -5559,7 +5677,8 @@ class EdgesLayer {
5559
5677
  return paragraphTop + this.session.displayData.calculateHeightForPage(page - 1);
5560
5678
  }
5561
5679
  renderPageHeaderComponent(page, start, end) {
5562
- const header = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Header);
5680
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5681
+ const header = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Header, pageFormat.pageWidth);
5563
5682
  if (header) {
5564
5683
  const height = this.session.customComponents.edges.getComponentHeight(header.instance);
5565
5684
  const edgeTop = this.getEdgeTop(0, page);
@@ -5570,11 +5689,11 @@ class EdgesLayer {
5570
5689
  }
5571
5690
  }
5572
5691
  renderPageFooterComponent(page, start, end) {
5573
- const footer = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Footer);
5574
- const pageFormat = this.session.displayData.getPageFormatByPageNumber(page);
5692
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5693
+ const footer = this.session.customComponents.edges.getComponentByPage(page, EdgeType.Footer, pageFormat.pageWidth);
5575
5694
  if (footer) {
5576
5695
  const height = this.session.customComponents.edges.getComponentHeight(footer.instance);
5577
- const topOffset = pageFormat.pageFormatModel.pageHeight - height;
5696
+ const topOffset = pageFormat.pageHeight - height;
5578
5697
  const edgeTop = this.getEdgeTop(topOffset, page);
5579
5698
  if (edgeTop > end || edgeTop + height < start) {
5580
5699
  return;
@@ -5584,24 +5703,30 @@ class EdgesLayer {
5584
5703
  }
5585
5704
  renderEdgeComponent(component, edgeHeight, page, edgeTop) {
5586
5705
  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;
5706
+ const pageFormat = this.session.displayData.getPageFormatByPageNumber(page).pageFormatModel;
5707
+ const offsetForLittlePages = (this.session.displayData.maxPageWidth - pageFormat.pageWidth) / 2;
5589
5708
  DomHelper.setStyle(container.style, 'height', `${edgeHeight}px`);
5590
5709
  DomHelper.setStyle(container.style, 'top', `${edgeTop}px`);
5591
5710
  DomHelper.setStyle(container.style, 'margin-left', `${offsetForLittlePages}px`);
5592
5711
  DomHelper.setStyle(container.style, 'margin-right', `${offsetForLittlePages}px`);
5593
5712
  const componentElement = component.hostView.rootNodes[0];
5594
5713
  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));
5714
+ edge.width = pageFormat.pageWidth;
5715
+ const isOrigin = !this.elements.some(x => x.isNotCopy(edge.type, edge.model.pageType, pageFormat.pageWidth));
5598
5716
  const element = isOrigin ? componentElement : componentElement.cloneNode(true);
5599
5717
  container.appendChild(element);
5600
5718
  this.element.appendChild(container);
5601
- const model = new EdgeElementModel({ page, container, pageType: edge.model.pageType, edgeType: edge.type, isOrigin });
5719
+ const model = new EdgeElementModel({
5720
+ page,
5721
+ container,
5722
+ pageType: edge.model.pageType,
5723
+ edgeType: edge.type,
5724
+ isOrigin,
5725
+ pageWidth: pageFormat.pageWidth
5726
+ });
5602
5727
  this.elements.push(model);
5603
5728
  if (!isOrigin) {
5604
- element.onmouseenter = () => model.replace(this.elements.find(x => x.isNotCopy(model.edgeType, model.pageType)));
5729
+ element.onmouseenter = () => model.replace(this.elements.find(x => x.isNotCopy(model.edgeType, model.pageType, pageFormat.pageWidth)));
5605
5730
  }
5606
5731
  }
5607
5732
  }
@@ -6208,7 +6333,8 @@ class PrintRenderer {
6208
6333
  maxHeight,
6209
6334
  offset: 0,
6210
6335
  pages,
6211
- scrollTop: 0
6336
+ scrollTop: 0,
6337
+ isVisible: true
6212
6338
  };
6213
6339
  }
6214
6340
  createContent() {
@@ -6708,72 +6834,128 @@ class SaveCommandsHelper {
6708
6834
  }
6709
6835
  }
6710
6836
 
6711
- class Search {
6712
- constructor() {
6713
- this.term = '';
6837
+ class CustomElementInfo {
6838
+ constructor(init) {
6839
+ Object.assign(this, init);
6840
+ }
6841
+ }
6842
+
6843
+ class SearchResult {
6844
+ constructor(init) {
6845
+ Object.assign(this, init);
6846
+ }
6847
+ }
6848
+
6849
+ class SessionModel {
6850
+ constructor(session, renderer, sessionId, parentSessionId, source) {
6851
+ this.session = session;
6852
+ this.renderer = renderer;
6853
+ this.sessionId = sessionId;
6854
+ this.parentSessionId = parentSessionId;
6855
+ this.source = source;
6714
6856
  }
6857
+ }
6858
+
6859
+ class Search {
6715
6860
  get currentMatchIndex() {
6716
6861
  return this.currentIndex + 1;
6717
6862
  }
6718
6863
  get currentMatch() {
6719
6864
  return this.currentIndex < 0 ? null : this.allMatches[this.currentIndex];
6720
6865
  }
6721
- setSearchTerm(term) {
6722
- this.term = term;
6866
+ constructor(editorService) {
6867
+ this.editorService = editorService;
6868
+ this.term = '';
6723
6869
  }
6724
- findAll(sessions) {
6870
+ findAll(sessions, term) {
6725
6871
  this.allMatches = [];
6872
+ this.searchedSessionIds = [];
6873
+ this.danglingSessions = [];
6874
+ this.tables = [];
6875
+ this.term = term;
6876
+ if (!term?.length) {
6877
+ for (const session of sessions) {
6878
+ session.renderer.updateSearchHighlights([]);
6879
+ session.renderer.updateActiveSearchHighlight(null);
6880
+ session.renderer.updateCustomElementHighlights([]);
6881
+ }
6882
+ this.editorService.setSearchResultCount(0);
6883
+ return;
6884
+ }
6726
6885
  this.assembleRegExp(this.term);
6727
6886
  if (!this.regex) {
6728
6887
  return;
6729
6888
  }
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
- }
6889
+ const mainSession = sessions[0];
6890
+ this.searchContent(mainSession, sessions);
6891
+ const unsearchedSessions = sessions.filter(x => !this.searchedSessionIds.includes(x.sessionId));
6892
+ for (const session of unsearchedSessions) {
6893
+ if (this.tables.some(x => x.tableSessions.includes(session.sessionId))) {
6894
+ continue;
6740
6895
  }
6741
- renderer.updateSearchHighlights(sessionHighlights);
6896
+ this.danglingSessions.push(session.sessionId);
6897
+ this.searchContent(session, sessions, 'outsideMainSession');
6742
6898
  }
6899
+ this.editorService.setSearchResultCount(this.allMatches.length);
6743
6900
  if (!this.allMatches.length) {
6744
6901
  this.currentIndex = -1;
6745
- return;
6746
6902
  }
6747
- this.currentIndex = this.currentIndex > this.allMatches.length - 1 ? this.allMatches.length - 1 : this.currentIndex;
6903
+ else {
6904
+ this.currentIndex = this.currentIndex > this.allMatches.length - 1 ? this.allMatches.length - 1 : this.currentIndex;
6905
+ }
6906
+ this.updateActiveSearchHighlight(sessions);
6748
6907
  }
6749
- goNext(selection, currentSessionId) {
6908
+ goNext(selection, currentSessionId, sessions) {
6750
6909
  if (!this.allMatches?.length) {
6751
6910
  return;
6752
6911
  }
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;
6912
+ const resultsAtCursor = this.allMatches.reduce((acc, match, index) => {
6913
+ if (match.sessionId === currentSessionId && match.range.contains(selection.cursor)) {
6914
+ acc.push(index);
6915
+ }
6916
+ return acc;
6917
+ }, []);
6918
+ if (resultsAtCursor.length) {
6919
+ const nextResultIndex = resultsAtCursor.findIndex(x => x === this.currentIndex) + 1;
6920
+ if (nextResultIndex < resultsAtCursor.length) {
6921
+ this.currentIndex = resultsAtCursor[nextResultIndex];
6922
+ }
6923
+ else {
6924
+ const nextIndex = resultsAtCursor[resultsAtCursor.length - 1] + 1;
6925
+ this.currentIndex = nextIndex > this.allMatches.length - 1 ? 0 : nextIndex;
6926
+ }
6927
+ this.updateActiveSearchHighlight(sessions);
6928
+ return;
6929
+ }
6930
+ const nextIndex = this.findNextAfterCursor(selection.cursor, currentSessionId);
6931
+ this.currentIndex = nextIndex < 0 ? 0 : nextIndex;
6932
+ this.updateActiveSearchHighlight(sessions);
6759
6933
  }
6760
- goPrevious(selection, currentSessionId) {
6934
+ goPrevious(selection, currentSessionId, sessions) {
6761
6935
  if (!this.allMatches?.length) {
6762
6936
  return;
6763
6937
  }
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;
6938
+ const resultsAtCursor = this.allMatches.reduce((acc, match, index) => {
6939
+ if (match.sessionId === currentSessionId && match.range.contains(selection.cursor)) {
6940
+ acc.push(index);
6941
+ }
6942
+ return acc;
6943
+ }, []);
6944
+ if (resultsAtCursor.length) {
6945
+ const nextResultIndex = resultsAtCursor.findIndex(x => x === this.currentIndex) - 1;
6946
+ if (nextResultIndex >= 0) {
6947
+ this.currentIndex = resultsAtCursor[nextResultIndex];
6948
+ }
6949
+ else {
6950
+ const nextIndex = resultsAtCursor[0] - 1;
6951
+ this.currentIndex = nextIndex < 0 ? this.allMatches.length - 1 : nextIndex;
6774
6952
  }
6953
+ this.updateActiveSearchHighlight(sessions);
6954
+ return;
6775
6955
  }
6956
+ const prevIndex = this.findPreviousBeforeCursor(selection.cursor, currentSessionId);
6776
6957
  this.currentIndex = prevIndex >= 0 ? prevIndex : this.allMatches.length - 1;
6958
+ this.updateActiveSearchHighlight(sessions);
6777
6959
  }
6778
6960
  assembleRegExp(term) {
6779
6961
  if (!term) {
@@ -6787,6 +6969,204 @@ class Search {
6787
6969
  this.regex = null;
6788
6970
  }
6789
6971
  }
6972
+ searchContent(currentSession, allSessions, mainSessionPosition = null) {
6973
+ this.searchedSessionIds.push(currentSession.sessionId);
6974
+ const sessionHighlights = [];
6975
+ const customElementHighlights = [];
6976
+ for (let i = 0; i < currentSession.session.displayData.paragraphs.length; i++) {
6977
+ const paragraph = currentSession.session.displayData.paragraphs[i];
6978
+ const paragraphTables = this.checkForTables(paragraph, currentSession, allSessions, i);
6979
+ const paragraphCustomElements = this.checkForCustomElements(paragraph, currentSession);
6980
+ const matches = paragraph.content.matchAll(this.regex);
6981
+ const paragraphMatches = [];
6982
+ for (const match of matches) {
6983
+ paragraphMatches.push({ index: match.index, content: match });
6984
+ }
6985
+ const paragraphContent = [...paragraphTables, ...paragraphCustomElements, ...paragraphMatches].sort((x, y) => x.index - y.index);
6986
+ for (const container of paragraphContent) {
6987
+ if (container.content instanceof BaseNoderComponent) {
6988
+ const parentRange = new Range(new CursorParagraph(i, container.index), new CursorParagraph(i, container.index + 1));
6989
+ const customElementMatches = container.content.searchComponent(this.regex);
6990
+ for (let matchIndex = 0; matchIndex < customElementMatches; matchIndex++) {
6991
+ this.allMatches.push(new CustomElementSearchResult({
6992
+ sessionId: currentSession.sessionId,
6993
+ range: parentRange,
6994
+ mainSessionPosition: mainSessionPosition ?? new CursorParagraph(i, container.index),
6995
+ index: matchIndex
6996
+ }));
6997
+ customElementHighlights.push(new CustomElementInfo({ index: matchIndex, parentRange }));
6998
+ }
6999
+ continue;
7000
+ }
7001
+ if (Array.isArray(container.content) && container.content.every(x => x instanceof SessionModel)) {
7002
+ for (const session of container.content) {
7003
+ this.searchContent(session, allSessions, mainSessionPosition ?? new CursorParagraph(i, container.index));
7004
+ }
7005
+ continue;
7006
+ }
7007
+ const match = container.content;
7008
+ if (paragraphTables.some(x => x.index >= match.index && x.index <= match.index + match[0].length) ||
7009
+ paragraphCustomElements.some(x => x.index >= match.index && x.index <= match.index + match[0].length)) {
7010
+ continue;
7011
+ }
7012
+ const range = new Range(new CursorParagraph(i, match.index), new CursorParagraph(i, match.index + match[0].length));
7013
+ this.allMatches.push(new SearchResult({
7014
+ sessionId: currentSession.sessionId,
7015
+ range,
7016
+ mainSessionPosition: mainSessionPosition ?? new CursorParagraph(i, match.index)
7017
+ }));
7018
+ sessionHighlights.push(range);
7019
+ }
7020
+ }
7021
+ currentSession.renderer.updateSearchHighlights(sessionHighlights);
7022
+ currentSession.renderer.updateCustomElementHighlights(customElementHighlights);
7023
+ }
7024
+ checkForTables(paragraph, currentSession, allSessions, paragraphIndex) {
7025
+ const result = [];
7026
+ const paragraphTables = currentSession.session.displayData.customComponents.tables.filter(x => x.instance.content.insertIndex >= paragraph.startIndex &&
7027
+ x.instance.content.insertIndex <= paragraph.startIndex + paragraph.content.length);
7028
+ for (const table of paragraphTables) {
7029
+ const tableSessions = [];
7030
+ for (const session of allSessions) {
7031
+ const parentTable = session.renderer.container.closest('app-nod-table');
7032
+ if (parentTable && parentTable === table.location.nativeElement) {
7033
+ tableSessions.push(session);
7034
+ }
7035
+ }
7036
+ this.tables.push({
7037
+ sessionId: currentSession.sessionId,
7038
+ tableSessions: tableSessions.map(x => x.sessionId),
7039
+ row: paragraphIndex,
7040
+ col: table.instance.content.insertIndex - paragraph.startIndex
7041
+ });
7042
+ result.push({ index: table.instance.content.insertIndex - paragraph.startIndex, content: tableSessions });
7043
+ }
7044
+ return result;
7045
+ }
7046
+ checkForCustomElements(paragraph, currentSession) {
7047
+ const result = [];
7048
+ const customElements = currentSession.session.displayData.customComponents.customElements.filter(x => x.instance.content.insertIndex >= paragraph.startIndex &&
7049
+ x.instance.content.insertIndex <= paragraph.startIndex + paragraph.content.length);
7050
+ for (const element of customElements) {
7051
+ if (element.instance instanceof BaseNoderComponent) {
7052
+ result.push({ index: element.instance.content.insertIndex - paragraph.startIndex, content: element.instance });
7053
+ }
7054
+ }
7055
+ return result;
7056
+ }
7057
+ findNextAfterCursor(startCursor, sessionId) {
7058
+ const closestResultCurrentSession = this.allMatches.find(x => (x.sessionId === sessionId && x.range.start.row === startCursor.row && x.range.start.column >= startCursor.column) ||
7059
+ (x.sessionId === sessionId && x.range.start.row > startCursor.row));
7060
+ if (closestResultCurrentSession) {
7061
+ const tablesBeforeClosestResultCurrentSession = this.tables.filter(x => (x.sessionId === sessionId && x.row > startCursor.row && x.row < closestResultCurrentSession.range.start.row) ||
7062
+ (x.sessionId === sessionId &&
7063
+ x.row === startCursor.row &&
7064
+ x.row < closestResultCurrentSession.range.start.row &&
7065
+ x.col > startCursor.column) ||
7066
+ (x.sessionId === sessionId &&
7067
+ x.row === closestResultCurrentSession.range.start.row &&
7068
+ x.col < closestResultCurrentSession.range.start.column));
7069
+ if (!tablesBeforeClosestResultCurrentSession.length) {
7070
+ return this.allMatches.indexOf(closestResultCurrentSession);
7071
+ }
7072
+ const tableSessions = tablesBeforeClosestResultCurrentSession.flatMap(x => x.tableSessions);
7073
+ for (const session of tableSessions) {
7074
+ const result = this.findNextAfterCursor(new CursorParagraph(0, 0), session);
7075
+ if (result >= 0) {
7076
+ return result;
7077
+ }
7078
+ }
7079
+ }
7080
+ const tablesAfterCursor = this.tables.filter(x => (x.sessionId === sessionId && x.row === startCursor.row && x.col >= startCursor.column) ||
7081
+ (x.sessionId === sessionId && x.row > startCursor.row));
7082
+ const tableSessions = tablesAfterCursor.flatMap(x => x.tableSessions);
7083
+ for (const session of tableSessions) {
7084
+ const result = this.findNextAfterCursor(new CursorParagraph(0, 0), session);
7085
+ if (result >= 0) {
7086
+ return result;
7087
+ }
7088
+ }
7089
+ const table = this.tables.find(x => x.tableSessions.includes(sessionId));
7090
+ if (table) {
7091
+ const nextSessionIndex = table.tableSessions.findIndex(x => x === sessionId) + 1;
7092
+ if (nextSessionIndex < table.tableSessions.length) {
7093
+ return this.findNextAfterCursor(new CursorParagraph(0, 0), table.tableSessions[nextSessionIndex]);
7094
+ }
7095
+ return this.findNextAfterCursor(new CursorParagraph(table.row + 1, table.col + 1), table.sessionId);
7096
+ }
7097
+ if (this.danglingSessions.length) {
7098
+ const danglingSessionsIndex = this.danglingSessions.indexOf(sessionId);
7099
+ const nextSessionIndex = danglingSessionsIndex + 1;
7100
+ if (nextSessionIndex < this.danglingSessions.length) {
7101
+ return this.findNextAfterCursor(new CursorParagraph(0, 0), this.danglingSessions[nextSessionIndex]);
7102
+ }
7103
+ }
7104
+ return -1;
7105
+ }
7106
+ findPreviousBeforeCursor(startCursor, sessionId) {
7107
+ const closestResultCurrentSession = this.allMatches.findLast(x => (x.sessionId === sessionId && x.range.start.row === startCursor.row && x.range.start.column < startCursor.column) ||
7108
+ (x.sessionId === sessionId && x.range.start.row < startCursor.row));
7109
+ if (closestResultCurrentSession) {
7110
+ const tablesAfterClosestResultCurrentSession = this.tables.filter(x => (x.sessionId === sessionId && x.row < startCursor.row && x.row > closestResultCurrentSession.range.start.row) ||
7111
+ (x.sessionId === sessionId &&
7112
+ x.row === startCursor.row &&
7113
+ x.row > closestResultCurrentSession.range.start.row &&
7114
+ x.col < startCursor.column) ||
7115
+ (x.sessionId === sessionId &&
7116
+ x.row === closestResultCurrentSession.range.start.row &&
7117
+ x.col > closestResultCurrentSession.range.start.column));
7118
+ if (!tablesAfterClosestResultCurrentSession.length) {
7119
+ return this.allMatches.indexOf(closestResultCurrentSession);
7120
+ }
7121
+ const tableSessions = tablesAfterClosestResultCurrentSession.flatMap(x => x.tableSessions);
7122
+ for (const session of tableSessions.toReversed()) {
7123
+ const result = this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), session);
7124
+ if (result >= 0) {
7125
+ return result;
7126
+ }
7127
+ }
7128
+ }
7129
+ const tablesBeforeCursor = this.tables.filter(x => (x.sessionId === sessionId && x.row === startCursor.row && x.col < startCursor.column) ||
7130
+ (x.sessionId === sessionId && x.row < startCursor.row));
7131
+ const tableSessions = tablesBeforeCursor.flatMap(x => x.tableSessions);
7132
+ for (const session of tableSessions.toReversed()) {
7133
+ const result = this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), session);
7134
+ if (result >= 0) {
7135
+ return result;
7136
+ }
7137
+ }
7138
+ const table = this.tables.find(x => x.tableSessions.includes(sessionId));
7139
+ if (table) {
7140
+ const currentSessionIndex = table.tableSessions.findIndex(x => x === sessionId);
7141
+ if (currentSessionIndex > 0) {
7142
+ return this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), table.tableSessions[currentSessionIndex - 1]);
7143
+ }
7144
+ return this.findPreviousBeforeCursor(new CursorParagraph(table.row - 1, table.col - 1), table.sessionId);
7145
+ }
7146
+ if (this.danglingSessions.length) {
7147
+ const currentSessionIndex = this.danglingSessions.indexOf(sessionId);
7148
+ if (currentSessionIndex > 0) {
7149
+ return this.findPreviousBeforeCursor(new CursorParagraph(Infinity, Infinity), this.danglingSessions[currentSessionIndex - 1]);
7150
+ }
7151
+ }
7152
+ return -1;
7153
+ }
7154
+ updateActiveSearchHighlight(sessions) {
7155
+ this.editorService.setCurrentSearchResultIndex(this.currentMatchIndex);
7156
+ for (const session of sessions) {
7157
+ if (this.currentMatch && session.sessionId === this.currentMatch.sessionId) {
7158
+ const range = this.currentMatch instanceof CustomElementSearchResult
7159
+ ? new CustomElementInfo({
7160
+ index: this.currentMatch.index,
7161
+ parentRange: this.currentMatch.range
7162
+ })
7163
+ : this.currentMatch.range;
7164
+ session.renderer.updateActiveSearchHighlight(range);
7165
+ continue;
7166
+ }
7167
+ session.renderer.updateActiveSearchHighlight(null);
7168
+ }
7169
+ }
6790
7170
  }
6791
7171
 
6792
7172
  class Selection {
@@ -7253,6 +7633,7 @@ class Editor {
7253
7633
  this.edgeElementTagName = 'APP-NOD-EDGE';
7254
7634
  this.imageTagName = 'APP-NOD-IMAGE';
7255
7635
  this.subscriptions = [];
7636
+ this.emojiRegex = /\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u{200D}\p{Extended_Pictographic})*/gu;
7256
7637
  this.isRerenderSubscriptionOpen = true;
7257
7638
  this.rerenderResize = () => {
7258
7639
  this.mainRenderer.onResize(true);
@@ -7279,8 +7660,8 @@ class Editor {
7279
7660
  this.initResizeListener();
7280
7661
  this.focus();
7281
7662
  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());
7663
+ this.search = new Search(editorService);
7664
+ 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.applyTabSettingsSubscription(), this.commandCreatedForEdges());
7284
7665
  }
7285
7666
  destroy() {
7286
7667
  this.subscriptions.forEach(s => s?.unsubscribe());
@@ -7332,13 +7713,14 @@ class Editor {
7332
7713
  this.removeSelected();
7333
7714
  }
7334
7715
  insert(text) {
7716
+ const sanitizedText = text.replace(this.emojiRegex, ' ');
7335
7717
  if (this.selection.isEmpty) {
7336
7718
  const textStyle = ContentStyleHelper.combineTextStyles(null, this.editorService.styles);
7337
- this.insertText(text, textStyle);
7719
+ this.insertText(sanitizedText, textStyle);
7338
7720
  }
7339
7721
  else {
7340
7722
  const index = ContentHelper.paragraphPositionToDocumentIndex(this.session.displayData.paragraphs, this.selection.range.start);
7341
- const insertText = new InsertTextModel({ insertIndex: index, text });
7723
+ const insertText = new InsertTextModel({ insertIndex: index, text: sanitizedText });
7342
7724
  this.replaceBy(new ReplaceModel({ insertText }));
7343
7725
  }
7344
7726
  }
@@ -7461,6 +7843,7 @@ class Editor {
7461
7843
  let lastRow = this.selection.cursor.row === endPoint.row ? endPoint.row : Infinity;
7462
7844
  this.renderer.updateLines(this.selection.cursor.row, lastRow);
7463
7845
  this.renderer.updateCursor();
7846
+ this.onContentChange();
7464
7847
  this.rerenderMarker();
7465
7848
  }
7466
7849
  replaceBy(model) {
@@ -7586,45 +7969,27 @@ class Editor {
7586
7969
  });
7587
7970
  }
7588
7971
  }
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
- }
7972
+ find(term) {
7973
+ this.search.findAll(this.regulatorService.sessions, term);
7609
7974
  }
7610
7975
  findNext() {
7611
7976
  if (!this.search.allMatches?.length) {
7612
7977
  return;
7613
7978
  }
7614
- this.search.goNext(this.selection, this.regulatorService.currentSession.sessionId);
7979
+ this.search.goNext(this.selection, this.regulatorService.currentSession.sessionId, this.regulatorService.sessions);
7615
7980
  this.setCursorAtSearchResult();
7616
- this.updateActiveSearchHighlight();
7617
7981
  }
7618
7982
  findPrevious() {
7619
7983
  if (!this.search.allMatches?.length) {
7620
7984
  return;
7621
7985
  }
7622
- this.search.goPrevious(this.selection, this.regulatorService.currentSession.sessionId);
7623
- this.updateActiveSearchHighlight();
7986
+ this.search.goPrevious(this.selection, this.regulatorService.currentSession.sessionId, this.regulatorService.sessions);
7624
7987
  this.setCursorAtSearchResult();
7625
7988
  }
7626
7989
  replace() {
7627
- if (!this.search.allMatches?.length || this.search.term === this.replaceTerm) {
7990
+ if (!this.search.currentMatch ||
7991
+ this.search.term === this.replaceTerm ||
7992
+ this.search.currentMatch instanceof CustomElementSearchResult) {
7628
7993
  return;
7629
7994
  }
7630
7995
  if (this.replaceTerm) {
@@ -7638,14 +8003,17 @@ class Editor {
7638
8003
  const replaceModel = new ReplaceModel({ insertText, delete: deleteModel });
7639
8004
  this.saveReplaceToHistory(this.search.currentMatch.range, replaceModel);
7640
8005
  const endPosition = this.session.replace(replaceModel);
7641
- this.onDocumentChange(new Range(this.search.currentMatch.range.start, endPosition));
8006
+ const range = new Range(this.search.currentMatch.range.start, endPosition);
8007
+ let lastRow = range.start.row === range.end.row ? range.end.row : Infinity;
8008
+ this.renderer.updateLines(range.start.row, lastRow);
7642
8009
  }
7643
8010
  else {
7644
8011
  const range = this.search.currentMatch.range;
7645
8012
  this.saveRemoveToHistory(range);
7646
8013
  this.session.remove(range);
7647
8014
  }
7648
- this.find(this.search.term);
8015
+ this.onContentChange();
8016
+ this.findNext();
7649
8017
  }
7650
8018
  undo() {
7651
8019
  const undo = this.history.popUndoOperation();
@@ -8361,7 +8729,7 @@ class Editor {
8361
8729
  const scalingRatio = this.customPageWidth ? ScalingHelper.getRatio(this.customPageWidth, pageWidth) : 1;
8362
8730
  this.editorService.setPageFormat(this.model.pageFormats[0]);
8363
8731
  this.editorService.paragraphStyle(this.model.paragraphs[0].paragraphStyle);
8364
- this.regulatorService.addMainSession(this.model, pageWidth, scalingRatio, this.container);
8732
+ this.regulatorService.addMainSession(this.model, scalingRatio, this.container);
8365
8733
  }
8366
8734
  onSelectionChange() {
8367
8735
  this.session.applyToolbarStyles();
@@ -8369,6 +8737,7 @@ class Editor {
8369
8737
  if (this.selection.isEmpty) {
8370
8738
  this.renderer.updateCursor();
8371
8739
  }
8740
+ this.regulatorService.updateCursorPosition();
8372
8741
  this.editorService.setHasSelection(!this.selection.isEmpty);
8373
8742
  const position = this.mainSession.displayData.positionToIndex(this.selection.selectedRange.start);
8374
8743
  const pageFormat = this.mainSession.displayData.getPageFormatAtPosition(position);
@@ -8577,7 +8946,10 @@ class Editor {
8577
8946
  }
8578
8947
  searchOptionSubscriptions() {
8579
8948
  return [
8580
- this.editorService.searchTerm$.subscribe(searchTerm => this.find(searchTerm, true)),
8949
+ this.editorService.searchTerm$.subscribe(searchTerm => {
8950
+ this.find(searchTerm);
8951
+ this.findNext();
8952
+ }),
8581
8953
  this.editorService.searchNext$.subscribe(() => this.findNext()),
8582
8954
  this.editorService.searchPrevious$.subscribe(() => this.findPrevious())
8583
8955
  ];
@@ -8624,6 +8996,9 @@ class Editor {
8624
8996
  applyLeftIndentParagraphSubscription() {
8625
8997
  return this.editorService.leftIndentParagraph$.subscribe(indentLeft => this.applyParagraphsMargin({ indentLeft }));
8626
8998
  }
8999
+ applyTabSettingsSubscription() {
9000
+ return this.editorService.tabSettings$.subscribe(tabSettings => this.applyParagraphsMargin({ tabSettings }));
9001
+ }
8627
9002
  setImageStyleSubscription() {
8628
9003
  return this.editorService.setImageStyle$.subscribe(image => this.applyImageStyles(image));
8629
9004
  }
@@ -8674,8 +9049,10 @@ class Editor {
8674
9049
  });
8675
9050
  }
8676
9051
  changedEdgeSizeSubscription() {
8677
- return this.editorService.changedEdgeSize$.subscribe(({ edgeType, pageType }) => {
8678
- this.mainSession.displayData.pagesFormat.forEach(x => x.updatePageVerticalData(edgeType, pageType));
9052
+ return this.editorService.changedEdgeSize$.subscribe(event => {
9053
+ this.mainSession.displayData.pagesFormat
9054
+ .filter(x => x.pageFormatModel.pageWidth === event.pageWidth)
9055
+ .forEach(x => x.updatePageVerticalData(event.edgeType, event.pageType));
8679
9056
  this.mainSession.displayData.processParagraphsProperties(0);
8680
9057
  });
8681
9058
  }
@@ -8819,6 +9196,11 @@ class Editor {
8819
9196
  this.clipboardData = data;
8820
9197
  });
8821
9198
  }
9199
+ commandCreatedForEdges() {
9200
+ return this.commandsService.createCommand$
9201
+ .pipe(filter(x => !!x.targets.find(y => !!y.edgeData)))
9202
+ .subscribe(() => this.regulatorService.forceUpdateDataForEdges());
9203
+ }
8822
9204
  updateEdgeSubscription() {
8823
9205
  return this.editorService.updateEdges$.subscribe(sessionId => {
8824
9206
  let existed = this.mainSession.customComponents.edges.headersComponents.findIndex(x => x.instance.sessionId === sessionId);
@@ -8853,7 +9235,7 @@ class Editor {
8853
9235
  });
8854
9236
  this.selection.navigateFileStart();
8855
9237
  this.isRerenderSubscriptionOpen = false;
8856
- this.regulatorService.addMainSession(this.model, pageWidth, scalingRatio, this.container);
9238
+ this.regulatorService.addMainSession(this.model, scalingRatio, this.container);
8857
9239
  this.isRerenderSubscriptionOpen = true;
8858
9240
  this.textInput = new TextInput(this.mainRenderer.container);
8859
9241
  this.mainRenderer.textarea = this.textInput.input;
@@ -8873,27 +9255,14 @@ class Editor {
8873
9255
  changeCellsWidth(rows, widthScale) {
8874
9256
  rows.forEach(row => row.cells.forEach(cell => (cell.width = Math.round(cell.width / widthScale))));
8875
9257
  }
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
9258
  setCursorAtSearchResult() {
9259
+ if (this.search.currentMatch.mainSessionPosition !== 'outsideMainSession') {
9260
+ this.mainRenderer.scrollCursorIntoView(this.search.currentMatch.mainSessionPosition, 0.5);
9261
+ }
8893
9262
  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);
9263
+ const sessionModel = this.regulatorService.getSessionModel(this.search.currentMatch.sessionId);
9264
+ sessionModel.session.selection.placeCursor(this.search.currentMatch.range.start);
9265
+ this.renderer.updateCursor();
8897
9266
  }
8898
9267
  }
8899
9268
 
@@ -8908,6 +9277,7 @@ class EditorSearchBarComponent {
8908
9277
  this.isReplace = false;
8909
9278
  this.searchResultCount$ = editorService.searchResultCount$;
8910
9279
  this.searchResultIndex$ = editorService.currentSearchResultIndex$;
9280
+ this.isViewOnly$ = editorService.isViewOnly$;
8911
9281
  }
8912
9282
  ngOnInit() {
8913
9283
  this.searchControl.valueChanges
@@ -8919,6 +9289,9 @@ class EditorSearchBarComponent {
8919
9289
  this.editorService.dialogSearchTerm$
8920
9290
  .pipe(distinctUntilChanged(), takeUntilDestroyed(this.destroyRef))
8921
9291
  .subscribe(x => this.searchControl.setValue(x));
9292
+ this.isViewOnly$
9293
+ .pipe(filter(x => x), takeUntilDestroyed(this.destroyRef))
9294
+ .subscribe(() => (this.isReplace = false));
8922
9295
  }
8923
9296
  ngOnDestroy() {
8924
9297
  this.editorService.setNewSearchTerm('');
@@ -8945,7 +9318,7 @@ class EditorSearchBarComponent {
8945
9318
  this.editorService.replaceCurrentSearchResult();
8946
9319
  }
8947
9320
  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 }); }
9321
+ 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
9322
  }
8950
9323
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: EditorSearchBarComponent, decorators: [{
8951
9324
  type: Component,
@@ -8958,7 +9331,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
8958
9331
  MatTooltipModule,
8959
9332
  ReactiveFormsModule,
8960
9333
  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"] }]
9334
+ ], 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
9335
  }], ctorParameters: () => [{ type: EditorService }, { type: i0.DestroyRef }], propDecorators: { searchInput: [{
8963
9336
  type: ViewChild,
8964
9337
  args: ['searchInput']
@@ -8967,94 +9340,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
8967
9340
  const EXTERNAL_ELEMENT_SIDENAV = new InjectionToken('EXTERNAL_ELEMENT_SIDENAV');
8968
9341
  const EXTERNAL_ELEMENT_SERVICE = new InjectionToken('EXTERNAL_ELEMENT_SERVICE');
8969
9342
 
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
9343
  class ComponentService {
9059
9344
  constructor(applicationRef, injector) {
9060
9345
  this.applicationRef = applicationRef;
@@ -9416,6 +9701,7 @@ class NoderTableCellComponent {
9416
9701
  this.regulatorService = regulatorService;
9417
9702
  this.isHighlighted = false;
9418
9703
  this.resizerBorder = ResizerSide;
9704
+ this.isVisible = false;
9419
9705
  this.pagesCountChangedHandler = (event) => {
9420
9706
  if (this._allParagraphsHeight === event.pageHeight) {
9421
9707
  return;
@@ -9424,9 +9710,14 @@ class NoderTableCellComponent {
9424
9710
  this.heightChanged(this.rowIndex, this.cellIndex, event.pageHeight);
9425
9711
  };
9426
9712
  }
9713
+ ngAfterViewInit() {
9714
+ this.intersectionObserver = this.initializeIntersectionObserver();
9715
+ this.intersectionObserver.observe(this.container.nativeElement);
9716
+ }
9427
9717
  ngOnDestroy() {
9428
9718
  this.session?.displayData.removeEventListener('pagesCountChanged', this.pagesCountChangedHandler);
9429
9719
  this.regulatorService.removeSession(this.sessionId);
9720
+ this.intersectionObserver?.disconnect();
9430
9721
  }
9431
9722
  initialize() {
9432
9723
  const marginModel = new MarginModel({
@@ -9458,6 +9749,22 @@ class NoderTableCellComponent {
9458
9749
  addEventListeners() {
9459
9750
  this.session.displayData.addEventListener('pagesCountChanged', this.pagesCountChangedHandler);
9460
9751
  }
9752
+ initializeIntersectionObserver() {
9753
+ const options = {
9754
+ root: null,
9755
+ rootMargin: '50px',
9756
+ threshold: 0.01
9757
+ };
9758
+ return new IntersectionObserver(entries => {
9759
+ entries.forEach(entry => {
9760
+ const wasVisible = this.isVisible;
9761
+ this.isVisible = entry.isIntersecting;
9762
+ if (this.isVisible !== wasVisible) {
9763
+ this.renderer.setVisibility(this.isVisible);
9764
+ }
9765
+ });
9766
+ }, options);
9767
+ }
9461
9768
  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
9769
  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
9770
  }
@@ -9503,6 +9810,144 @@ class RowDataModel {
9503
9810
  }
9504
9811
  }
9505
9812
 
9813
+ var LineStyles;
9814
+ (function (LineStyles) {
9815
+ LineStyles[LineStyles["SolidLine"] = 0] = "SolidLine";
9816
+ LineStyles[LineStyles["RoundDot"] = 1] = "RoundDot";
9817
+ LineStyles[LineStyles["SquareDot"] = 2] = "SquareDot";
9818
+ LineStyles[LineStyles["Dash"] = 3] = "Dash";
9819
+ LineStyles[LineStyles["DashDot"] = 4] = "DashDot";
9820
+ LineStyles[LineStyles["LongDash"] = 5] = "LongDash";
9821
+ LineStyles[LineStyles["LongDashDot"] = 6] = "LongDashDot";
9822
+ LineStyles[LineStyles["LongDashDotDot"] = 7] = "LongDashDotDot";
9823
+ LineStyles[LineStyles["Single"] = 8] = "Single";
9824
+ LineStyles[LineStyles["Thick"] = 9] = "Thick";
9825
+ LineStyles[LineStyles["Double"] = 10] = "Double";
9826
+ LineStyles[LineStyles["Dotted"] = 11] = "Dotted";
9827
+ LineStyles[LineStyles["Dashed"] = 12] = "Dashed";
9828
+ LineStyles[LineStyles["DotDash"] = 13] = "DotDash";
9829
+ LineStyles[LineStyles["DotDotDash"] = 14] = "DotDotDash";
9830
+ LineStyles[LineStyles["Triple"] = 15] = "Triple";
9831
+ LineStyles[LineStyles["ThinThickSmallGap"] = 16] = "ThinThickSmallGap";
9832
+ LineStyles[LineStyles["ThickThinSmallGap"] = 17] = "ThickThinSmallGap";
9833
+ LineStyles[LineStyles["ThinThickThinSmallGap"] = 18] = "ThinThickThinSmallGap";
9834
+ LineStyles[LineStyles["ThinThickMediumGap"] = 19] = "ThinThickMediumGap";
9835
+ LineStyles[LineStyles["ThickThinMediumGap"] = 20] = "ThickThinMediumGap";
9836
+ LineStyles[LineStyles["ThinThickThinMediumGap"] = 21] = "ThinThickThinMediumGap";
9837
+ LineStyles[LineStyles["ThinThickLargeGap"] = 22] = "ThinThickLargeGap";
9838
+ LineStyles[LineStyles["ThickThinLargeGap"] = 23] = "ThickThinLargeGap";
9839
+ LineStyles[LineStyles["ThinThickThinLargeGap"] = 24] = "ThinThickThinLargeGap";
9840
+ LineStyles[LineStyles["Wave"] = 25] = "Wave";
9841
+ LineStyles[LineStyles["DoubleWave"] = 26] = "DoubleWave";
9842
+ LineStyles[LineStyles["DashSmallGap"] = 27] = "DashSmallGap";
9843
+ LineStyles[LineStyles["DashDotStroked"] = 28] = "DashDotStroked";
9844
+ LineStyles[LineStyles["ThreeDEmboss"] = 29] = "ThreeDEmboss";
9845
+ LineStyles[LineStyles["ThreeDEngrave"] = 30] = "ThreeDEngrave";
9846
+ LineStyles[LineStyles["Outset"] = 31] = "Outset";
9847
+ LineStyles[LineStyles["Inset"] = 32] = "Inset";
9848
+ LineStyles[LineStyles["Nil"] = 33] = "Nil";
9849
+ })(LineStyles || (LineStyles = {}));
9850
+
9851
+ var Positions;
9852
+ (function (Positions) {
9853
+ Positions[Positions["Top"] = 0] = "Top";
9854
+ Positions[Positions["Right"] = 1] = "Right";
9855
+ Positions[Positions["Bottom"] = 2] = "Bottom";
9856
+ Positions[Positions["Left"] = 3] = "Left";
9857
+ Positions[Positions["All"] = 4] = "All";
9858
+ Positions[Positions["InsideHorizontal"] = 5] = "InsideHorizontal";
9859
+ Positions[Positions["InsideVertical"] = 6] = "InsideVertical";
9860
+ })(Positions || (Positions = {}));
9861
+
9862
+ class TableCellHelper {
9863
+ static setCellBorders(cell, borders) {
9864
+ if (!borders?.length || !cell) {
9865
+ return;
9866
+ }
9867
+ borders.forEach(x => {
9868
+ const style = this.getBorderStyle(x);
9869
+ this.setCellBorder(cell, x.position, style);
9870
+ });
9871
+ }
9872
+ static getBorderStyle(border) {
9873
+ if (border.lineStyle === LineStyles.Nil) {
9874
+ return 'none';
9875
+ }
9876
+ let style = `${border.width}pt`;
9877
+ if (border.lineStyle) {
9878
+ style += ` ${this.getBorderLineStyle(border.lineStyle)}`;
9879
+ }
9880
+ if (border.color && border.color !== 'auto') {
9881
+ style += ` ${border.color}`;
9882
+ }
9883
+ return style;
9884
+ }
9885
+ static getBorderLineStyle(lineStyle) {
9886
+ switch (lineStyle) {
9887
+ case LineStyles.RoundDot:
9888
+ case LineStyles.SquareDot:
9889
+ case LineStyles.Dotted:
9890
+ return 'dotted';
9891
+ case LineStyles.Dash:
9892
+ case LineStyles.Dashed:
9893
+ case LineStyles.LongDash:
9894
+ case LineStyles.DashSmallGap:
9895
+ case LineStyles.DashDot:
9896
+ case LineStyles.LongDashDot:
9897
+ case LineStyles.DotDash:
9898
+ case LineStyles.DashDotStroked:
9899
+ case LineStyles.LongDashDotDot:
9900
+ case LineStyles.DotDotDash:
9901
+ return 'dashed';
9902
+ case LineStyles.Double:
9903
+ case LineStyles.DoubleWave:
9904
+ return 'double';
9905
+ case LineStyles.Wave:
9906
+ return 'wavy'; // wavy is supported in some browsers
9907
+ case LineStyles.ThreeDEmboss:
9908
+ case LineStyles.ThreeDEngrave:
9909
+ return 'ridge'; // approximate replacement for 3D effects
9910
+ case LineStyles.Outset:
9911
+ return 'outset';
9912
+ case LineStyles.Inset:
9913
+ return 'inset';
9914
+ case LineStyles.Nil:
9915
+ return 'none';
9916
+ case LineStyles.ThinThickSmallGap: // complex combined styles are not supported
9917
+ case LineStyles.ThickThinSmallGap:
9918
+ case LineStyles.ThinThickThinSmallGap:
9919
+ case LineStyles.ThinThickMediumGap:
9920
+ case LineStyles.ThickThinMediumGap:
9921
+ case LineStyles.ThinThickThinMediumGap:
9922
+ case LineStyles.ThinThickLargeGap:
9923
+ case LineStyles.ThickThinLargeGap:
9924
+ case LineStyles.ThinThickThinLargeGap:
9925
+ case LineStyles.Triple: // triple not support in css, set solid as default
9926
+ case LineStyles.Single:
9927
+ case LineStyles.SolidLine:
9928
+ case LineStyles.Thick:
9929
+ default:
9930
+ return 'solid';
9931
+ }
9932
+ }
9933
+ static setCellBorder(cell, position, style) {
9934
+ switch (position) {
9935
+ case Positions.Top:
9936
+ cell.style.borderTop = style;
9937
+ break;
9938
+ case Positions.Bottom:
9939
+ cell.style.borderBottom = style;
9940
+ break;
9941
+ case Positions.Left:
9942
+ cell.style.borderLeft = style;
9943
+ break;
9944
+ case Positions.Right:
9945
+ cell.style.borderRight = style;
9946
+ break;
9947
+ }
9948
+ }
9949
+ }
9950
+
9506
9951
  class SelectionRangeModel {
9507
9952
  constructor(rowIndexes, cellIndexes) {
9508
9953
  this.rowIndexes = rowIndexes;
@@ -10102,7 +10547,7 @@ class NoderTableComponent extends BaseNoderComponent {
10102
10547
  const cellWidth = this.getCellWidth(tableRow, cellIndex, absoluteCellIndex);
10103
10548
  if (tableRow.cells[cellIndex].widthType === 'pct') {
10104
10549
  tableRow.cells[cellIndex].widthType = 'dxa';
10105
- return (cellWidth * this.width) / 5000; // 5000 is equal to 100% in docx units of measurement
10550
+ return (cellWidth * this.width()) / 5000; // 5000 is equal to 100% in docx units of measurement
10106
10551
  }
10107
10552
  return ScalingHelper.scale(cellWidth, this.generalProperties.scalingRatio);
10108
10553
  }
@@ -10128,7 +10573,7 @@ class NoderTableComponent extends BaseNoderComponent {
10128
10573
  this.initialize();
10129
10574
  }
10130
10575
  insertRows(rowsCount, targetIndex) {
10131
- this.width = this.getTableWidth();
10576
+ this.width.set(this.getTableWidth());
10132
10577
  let rowIndex = 0;
10133
10578
  while (rowIndex < rowsCount) {
10134
10579
  const targetRowIndex = targetIndex + rowIndex;
@@ -10169,6 +10614,9 @@ class NoderTableComponent extends BaseNoderComponent {
10169
10614
  continue;
10170
10615
  }
10171
10616
  const cell = this.tableEl.rows[rowIndex].insertCell(currentTargetIndex);
10617
+ if (this.table.rows[rowIndex].cells[modelCellIndex].borders) {
10618
+ TableCellHelper.setCellBorders(cell, this.table.rows[rowIndex].cells[modelCellIndex].borders);
10619
+ }
10172
10620
  const componentRef = this.componentService.generateAndAttachComponent(cell, NoderTableCellComponent, {
10173
10621
  table: this.table,
10174
10622
  cell: this.table.rows[rowIndex].cells[modelCellIndex],
@@ -10300,20 +10748,20 @@ class NoderTableComponent extends BaseNoderComponent {
10300
10748
  bordersHeight += this.borderSize;
10301
10749
  }
10302
10750
  }
10303
- this.height = rowsHeight + bordersHeight;
10751
+ this.height.set(rowsHeight + bordersHeight);
10304
10752
  }
10305
10753
  processSplit(leftSpaceOnPage, spaceBetweenPagesContent, contentHeight) {
10306
10754
  this.removeSplits();
10307
- if (leftSpaceOnPage >= this.height) {
10308
- return { splitsCount: 0, tableHeight: this.height, leftHeight: 0 };
10755
+ if (leftSpaceOnPage >= this.height()) {
10756
+ return { splitsCount: 0, tableHeight: this.height(), leftHeight: 0 };
10309
10757
  }
10310
10758
  if (leftSpaceOnPage < this.rowMatrix[0].height) {
10311
- return { splitsCount: 1, tableHeight: this.height, leftHeight: this.height };
10759
+ return { splitsCount: 1, tableHeight: this.height(), leftHeight: this.height() };
10312
10760
  }
10313
10761
  return this.splitTable(leftSpaceOnPage, spaceBetweenPagesContent, contentHeight);
10314
10762
  }
10315
10763
  splitTable(leftSpaceOnPage, spaceBetweenPagesContent, contentHeight) {
10316
- let leftHeight = 0, tableHeightWithSplits = this.height, rowIndex = 0;
10764
+ let leftHeight = 0, tableHeightWithSplits = this.height(), rowIndex = 0;
10317
10765
  while (rowIndex < this.rowMatrix.length) {
10318
10766
  let { index, rowsHeight } = this.getRowIndexByHeight(rowIndex, leftSpaceOnPage);
10319
10767
  rowIndex = index;
@@ -10621,8 +11069,8 @@ class PageFormat {
10621
11069
  }
10622
11070
  const pageTypes = this.customComponents.edges.getUniquePageTypes();
10623
11071
  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);
11072
+ const headerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Header, this.pageFormatModel.pageWidth);
11073
+ const footerHeight = this.customComponents.edges.getComponentHeightByPageType(pageType, EdgeType.Footer, this.pageFormatModel.pageWidth);
10626
11074
  const marginTop = Math.max(headerHeight, this.pageFormatModel.marginTop);
10627
11075
  const marginBottom = Math.max(footerHeight, this.pageFormatModel.marginBottom);
10628
11076
  return new PageVerticalDataModel({
@@ -10635,7 +11083,7 @@ class PageFormat {
10635
11083
  }
10636
11084
  updatePageVerticalData(edgeType, pageType) {
10637
11085
  const pageVerticalData = this.pagesVerticalData.find(x => x.pageType === pageType);
10638
- const componentHeight = this.customComponents.edges.getComponentHeightByType(pageType, edgeType);
11086
+ const componentHeight = this.customComponents.edges.getComponentHeightByType(pageType, edgeType, this.pageFormatModel.pageWidth);
10639
11087
  if (edgeType === EdgeType.Header) {
10640
11088
  pageVerticalData.marginTop =
10641
11089
  componentHeight > this.pageFormatModel.marginTop ? componentHeight : this.pageFormatModel.marginTop;
@@ -10685,7 +11133,7 @@ class TextLineInfo {
10685
11133
  this.paddingLeft = indent.left + (diff - indent.left - indent.right) / 2 + (indent.hanging - indent.firstLine) / 2;
10686
11134
  break;
10687
11135
  case Alignment$1.right:
10688
- this.paddingLeft = diff - indent.right;
11136
+ this.paddingLeft = diff - indent.right + indent.hanging - indent.firstLine;
10689
11137
  break;
10690
11138
  default:
10691
11139
  this.paddingLeft = indent.left;
@@ -10807,9 +11255,20 @@ class ParagraphStyleHelper {
10807
11255
  }
10808
11256
  }
10809
11257
 
11258
+ var TabAlignment;
11259
+ (function (TabAlignment) {
11260
+ TabAlignment[TabAlignment["Left"] = 0] = "Left";
11261
+ TabAlignment[TabAlignment["Center"] = 1] = "Center";
11262
+ TabAlignment[TabAlignment["Right"] = 2] = "Right";
11263
+ TabAlignment[TabAlignment["Decimal"] = 3] = "Decimal";
11264
+ TabAlignment[TabAlignment["Bar"] = 4] = "Bar";
11265
+ })(TabAlignment || (TabAlignment = {}));
11266
+
10810
11267
  class TabHelper {
10811
- static calculateTabWidth(rowWidth, defaultTabWidth) {
10812
- return defaultTabWidth - (rowWidth % defaultTabWidth);
11268
+ static calculateTabWidth(rowWidth, defaultTabWidth, tabSettings) {
11269
+ const tabs = tabSettings ?? [];
11270
+ const nextSetting = tabs.find(x => x.position > rowWidth);
11271
+ return nextSetting ? nextSetting.position - rowWidth : defaultTabWidth - (rowWidth % defaultTabWidth);
10813
11272
  }
10814
11273
  }
10815
11274
 
@@ -10837,13 +11296,11 @@ class DisplayData extends EventEmitting {
10837
11296
  this.pagesFormat = [];
10838
11297
  this.allPagesHeight = 0;
10839
11298
  this.tabTokens = [];
10840
- this.paragraphs = this.splitByParagraphs(this.model.content).map(x => new ParagraphInfoModel({ content: x }));
10841
- this.pagesFormat = pageFormatModels.map(x => new PageFormat(x, pagesSpace, customComponents));
11299
+ this.updateDataForModel();
10842
11300
  }
10843
- recreatePageFormatsNotMainSession(width) {
10844
- this.pagesFormat = [
10845
- new PageFormat(new PageFormatModel({ ...this.pagesFormat[0].pageFormatModel, pageWidth: width }), this.pagesSpace, this.customComponents)
10846
- ];
11301
+ updateDataForModel() {
11302
+ this.paragraphs = this.splitByParagraphs(this.model.content).map(x => new ParagraphInfoModel({ content: x }));
11303
+ this.pagesFormat = this.pageFormatModels.map(x => new PageFormat(x, this.pagesSpace, this.customComponents));
10847
11304
  }
10848
11305
  insertText(position, text) {
10849
11306
  const endPoint = this.insertTextAndReturnEndCursorPosition(text, position);
@@ -11052,7 +11509,11 @@ class DisplayData extends EventEmitting {
11052
11509
  this.allPagesHeight += (lastPageNumber - firstPageNumber + 1) * (pageHeight + this.pagesSpace) + this.pagesSpace;
11053
11510
  });
11054
11511
  const lastPageNumber = this.paragraphs[this.paragraphs.length - 1].paragraphSettings.lastPageNumber;
11055
- this.emit('pagesCountChanged', { pagesCount: lastPageNumber, pageHeight: this.allPagesHeight + 2 * this.pagesSpace });
11512
+ this.emit('pagesCountChanged', {
11513
+ pagesCount: lastPageNumber,
11514
+ pageHeight: this.allPagesHeight + 2 * this.pagesSpace,
11515
+ pageWidth: this.pagesFormat[0].pageFormatModel.pageWidth // variable needed only for headers and footers (in headers and footers only 1 pageFormat)
11516
+ });
11056
11517
  }
11057
11518
  getAllParagraphsHeight() {
11058
11519
  return this.paragraphs.reduce((sum, x) => sum + x.paragraphSettings.height, 0);
@@ -11170,8 +11631,7 @@ class DisplayData extends EventEmitting {
11170
11631
  }
11171
11632
  const startIndex = tabIndex;
11172
11633
  while (this.customComponents.tabs[tabIndex] && this.customComponents.tabs[tabIndex].instance.insertIndex <= paragraphLastIndex) {
11173
- this.customComponents.tabs[tabIndex].instance.width = this.tabTokens[tabIndex - startIndex].width;
11174
- this.customComponents.tabs[tabIndex].instance.height = this.tabTokens[tabIndex - startIndex].font;
11634
+ this.customComponents.tabs[tabIndex].instance.applySize(this.tabTokens[tabIndex - startIndex].width, this.tabTokens[tabIndex - startIndex].font);
11175
11635
  tabIndex++;
11176
11636
  }
11177
11637
  return tabIndex;
@@ -11206,7 +11666,7 @@ class DisplayData extends EventEmitting {
11206
11666
  if (!tokens.length) {
11207
11667
  tokens.push(...this.getEmptyDisplayTokens(model, this.paragraphs[paragraphIndex].startIndex + index));
11208
11668
  }
11209
- let wrapLimit = this.computeWrapIndex(tokens, pageFormat.contentWidth, this.generalProperties.defaultTabWidth);
11669
+ let wrapLimit = this.computeWrapIndex(tokens, pageFormat.contentWidth, this.generalProperties.defaultTabWidth, model.paragraphs[paragraphIndex].paragraphStyle.tabSettings);
11210
11670
  if (tokens[tokens.length - 1].isPageBreak && wrapLimit === tokens.length && this.paragraphs.length > paragraphIndex + 1) {
11211
11671
  wrapLimit = 0;
11212
11672
  }
@@ -11609,7 +12069,7 @@ class DisplayData extends EventEmitting {
11609
12069
  /**
11610
12070
  * Computes wrap index based on max row width
11611
12071
  */
11612
- computeWrapIndex(displayTokens, contentWidth, defaultTabWidth) {
12072
+ computeWrapIndex(displayTokens, contentWidth, defaultTabWidth, tabSettings) {
11613
12073
  if (!displayTokens[0]) {
11614
12074
  return 0;
11615
12075
  }
@@ -11622,13 +12082,46 @@ class DisplayData extends EventEmitting {
11622
12082
  displayTokens[0].indentHanging || 0;
11623
12083
  const maxRowWidth = contentWidth - indent;
11624
12084
  let sum = 0;
12085
+ let prevTabIndex = null;
12086
+ let tabCenter = null;
12087
+ let prevTabAlignment = TabAlignment.Left;
11625
12088
  for (let i = 0; i < displayTokens.length; i++) {
11626
12089
  const token = displayTokens[i];
11627
12090
  const prevToken = i > 0 ? displayTokens[i - 1] : null;
11628
12091
  if (token.isTab) {
11629
- token.width = TabHelper.calculateTabWidth(sum, defaultTabWidth);
12092
+ const tabs = tabSettings ?? [];
12093
+ const nextSettingIndex = tabs.findIndex(x => x.position > sum);
12094
+ const tokenWidth = TabHelper.calculateTabWidth(sum, defaultTabWidth, tabSettings);
12095
+ if (nextSettingIndex >= 0 && tabs[nextSettingIndex].alignment === TabAlignment.Center) {
12096
+ prevTabAlignment = TabAlignment.Center;
12097
+ tabCenter = { stringWidth: 0, tokenWidth };
12098
+ token.width = tokenWidth;
12099
+ }
12100
+ else {
12101
+ prevTabAlignment = nextSettingIndex >= 0 ? tabs[nextSettingIndex].alignment : TabAlignment.Left;
12102
+ token.width = tokenWidth;
12103
+ tabCenter = null;
12104
+ }
12105
+ prevTabIndex = i;
12106
+ }
12107
+ if (prevTabAlignment === TabAlignment.Center && !token.isTab && tabCenter.stringWidth < tabCenter.tokenWidth) {
12108
+ const tokenWidth = token.width / 2;
12109
+ displayTokens[prevTabIndex].width -= tokenWidth;
12110
+ tabCenter.stringWidth += tokenWidth;
12111
+ sum += tokenWidth;
12112
+ }
12113
+ else if (prevTabAlignment === TabAlignment.Right && !token.isTab && displayTokens[prevTabIndex].width !== 0) {
12114
+ if (displayTokens[prevTabIndex].width - token.width < 0) {
12115
+ sum += token.width - displayTokens[prevTabIndex].width;
12116
+ displayTokens[prevTabIndex].width = 0;
12117
+ }
12118
+ else {
12119
+ displayTokens[prevTabIndex].width -= token.width;
12120
+ }
12121
+ }
12122
+ else {
12123
+ sum += token.width;
11630
12124
  }
11631
- sum += token.width;
11632
12125
  if (sum >= maxRowWidth) {
11633
12126
  return i > 0 ? i - 1 : 0;
11634
12127
  }
@@ -11784,18 +12277,20 @@ class NoderEdgeComponent extends DestroyComponent {
11784
12277
  this.translateService = translateService;
11785
12278
  this.cdr = cdr;
11786
12279
  this.initialized = false;
12280
+ this.isVisible = false;
11787
12281
  this.pagesCountChangedHandler = (event) => {
11788
12282
  if (this._height === event.pageHeight) {
11789
12283
  return;
11790
12284
  }
11791
12285
  this._height = event.pageHeight;
11792
12286
  this.applyHeight();
11793
- this.editorService.changedEdgeSize(this.type, this.model.pageType);
12287
+ this.editorService.changedEdgeSize(this.type, this.model.pageType, event.pageWidth, this._height);
11794
12288
  };
11795
12289
  }
11796
12290
  ngOnDestroy() {
11797
12291
  this.session?.displayData.removeEventListener('pagesCountChanged', this.pagesCountChangedHandler);
11798
12292
  this.regulatorService.removeSession(this.sessionId);
12293
+ this.intersectionObserver?.disconnect();
11799
12294
  super.ngOnDestroy();
11800
12295
  }
11801
12296
  initialize() {
@@ -11814,14 +12309,8 @@ class NoderEdgeComponent extends DestroyComponent {
11814
12309
  this.edgeNameByType = this.getEdgeNameByType();
11815
12310
  this.cdr.detectChanges();
11816
12311
  });
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 });
12312
+ this.intersectionObserver = this.initializeIntersectionObserver();
12313
+ this.intersectionObserver.observe(this.container.nativeElement);
11825
12314
  }
11826
12315
  enterEditMode() {
11827
12316
  DomHelper.addCssClass(this.container.nativeElement, this.editModeClass);
@@ -11864,6 +12353,22 @@ class NoderEdgeComponent extends DestroyComponent {
11864
12353
  const height = this.contentHeight > maxHeight ? maxHeight : this.contentHeight;
11865
12354
  DomHelper.setStyle(this.typeContainer.nativeElement.style, this.typeContainerPosition, `${height}px`);
11866
12355
  }
12356
+ initializeIntersectionObserver() {
12357
+ const options = {
12358
+ root: null,
12359
+ rootMargin: '50px',
12360
+ threshold: 0.01
12361
+ };
12362
+ return new IntersectionObserver(entries => {
12363
+ entries.forEach(entry => {
12364
+ const wasVisible = this.isVisible;
12365
+ this.isVisible = entry.isIntersecting;
12366
+ if (this.isVisible !== wasVisible) {
12367
+ this.renderer.setVisibility(this.isVisible);
12368
+ }
12369
+ });
12370
+ }, options);
12371
+ }
11867
12372
  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
12373
  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
12374
  }
@@ -11893,10 +12398,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
11893
12398
  }] } });
11894
12399
 
11895
12400
  class Edges {
11896
- constructor(componentService, headers, footers, margins, pageWidth, parentSessionId, generalProperties) {
12401
+ constructor(componentService, headers, footers, margins, pageFormats, parentSessionId, generalProperties) {
11897
12402
  this.componentService = componentService;
11898
12403
  this.margins = margins;
11899
- this.pageWidth = pageWidth;
12404
+ this.pageFormats = pageFormats;
11900
12405
  this.parentSessionId = parentSessionId;
11901
12406
  this.generalProperties = generalProperties;
11902
12407
  this.headersComponents = [];
@@ -11913,23 +12418,19 @@ class Edges {
11913
12418
  }
11914
12419
  }
11915
12420
  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,
12421
+ this.headersComponents.push(...this.createEdgesByPageFormats(headerModel, new MarginModel({ ...this.margins, bottom: 0 }), EdgeType.Header, false));
12422
+ this.footersComponents.push(...this.createEdgesByPageFormats(footerModel, new MarginModel({ ...this.margins, top: 0 }), EdgeType.Footer, false));
12423
+ }
12424
+ createEdgesByPageFormats(model, margins, type, isEvenEdgesExist) {
12425
+ const uniqueWidth = new Set(this.pageFormats.map(x => x.pageWidth));
12426
+ return Array.from(uniqueWidth).map(width => this.componentService.generateComponent(NoderEdgeComponent, {
12427
+ model,
12428
+ margins,
12429
+ type,
12430
+ width,
11930
12431
  generalProperties: this.generalProperties,
11931
12432
  parentSessionId: this.parentSessionId,
11932
- isEvenEdgesExist: false
12433
+ isEvenEdgesExist
11933
12434
  }));
11934
12435
  }
11935
12436
  removeEdges(pageType) {
@@ -11941,21 +12442,22 @@ class Edges {
11941
12442
  getTypeBySessionId(sessionId) {
11942
12443
  let component = this.headersComponents.find(x => x.instance.sessionId === sessionId);
11943
12444
  if (component) {
11944
- return { type: EdgeType.Header, pageType: component.instance.model.pageType };
12445
+ return { type: EdgeType.Header, pageType: component.instance.model.pageType, pageWidth: component.instance.width };
11945
12446
  }
11946
12447
  component = this.footersComponents.find(x => x.instance.sessionId === sessionId);
11947
- return { type: EdgeType.Footer, pageType: component.instance.model.pageType };
12448
+ return { type: EdgeType.Footer, pageType: component.instance.model.pageType, pageWidth: component.instance.width };
11948
12449
  }
11949
- getComponentByPage(page, type) {
12450
+ getComponentByPage(page, type, pageWidth) {
11950
12451
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11951
- return this.getComponent(components, page);
12452
+ return this.getComponents(components, page).find(x => x.instance.width === pageWidth);
11952
12453
  }
11953
12454
  getComponentByPageType(pageType, type) {
11954
12455
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11955
12456
  return components.find(x => x.instance.model.pageType === pageType);
11956
12457
  }
11957
- getComponentHeightByPageType(pageType, type) {
11958
- const component = this.getComponentByPageType(pageType, type);
12458
+ getComponentHeightByPageType(pageType, type, pageWidth) {
12459
+ const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
12460
+ const component = components.find(x => x.instance.model.pageType === pageType && x.instance.width === pageWidth);
11959
12461
  if (!component) {
11960
12462
  return 0;
11961
12463
  }
@@ -11967,9 +12469,9 @@ class Edges {
11967
12469
  const height = instance.contentHeight;
11968
12470
  return height > this.generalProperties.maxEdgeHeight ? this.generalProperties.maxEdgeHeight : height;
11969
12471
  }
11970
- getComponentHeightByType(pageType, type) {
12472
+ getComponentHeightByType(pageType, type, pageWidth) {
11971
12473
  const components = type === EdgeType.Header ? this.headersComponents : this.footersComponents;
11972
- const height = components.find(x => x.instance.model.pageType === pageType)?.instance.contentHeight ?? 0;
12474
+ const height = components.find(x => x.instance.model.pageType === pageType && x.instance.width === pageWidth)?.instance.contentHeight ?? 0;
11973
12475
  return height > this.generalProperties.maxEdgeHeight ? this.generalProperties.maxEdgeHeight : height;
11974
12476
  }
11975
12477
  toggleEditMode(isEdit) {
@@ -12013,26 +12515,21 @@ class Edges {
12013
12515
  return 1;
12014
12516
  return 0;
12015
12517
  })) {
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);
12518
+ resultComponents.push(...this.createEdgesByPageFormats(model, margins, type, isEvenEdgesExist));
12026
12519
  }
12027
12520
  return resultComponents;
12028
12521
  }
12029
- getComponent(edgeComponents, page) {
12030
- const defaultComponent = edgeComponents.find(x => x.instance.model.pageType === PageType.Default);
12522
+ getComponents(edgeComponents, page) {
12523
+ const defaultComponent = edgeComponents.filter(x => x.instance.model.pageType === PageType.Default);
12524
+ let targetType = PageType.Default;
12031
12525
  if (page === 1) {
12032
- return edgeComponents.find(x => x.instance.model.pageType === PageType.First) || defaultComponent;
12526
+ targetType = PageType.First;
12033
12527
  }
12034
- const targetType = page % 2 === 0 ? PageType.Even : PageType.Default;
12035
- return edgeComponents.find(x => x.instance.model.pageType === targetType) || defaultComponent;
12528
+ else if (page % 2 === 0) {
12529
+ targetType = PageType.Even;
12530
+ }
12531
+ const edges = edgeComponents.filter(x => x.instance.model.pageType === targetType);
12532
+ return edges.length > 0 ? edges : defaultComponent;
12036
12533
  }
12037
12534
  }
12038
12535
 
@@ -12329,7 +12826,7 @@ class NoderImageComponent extends BaseNoderComponent {
12329
12826
  this.content = val;
12330
12827
  }
12331
12828
  get size() {
12332
- return { width: this.width, height: this.height };
12829
+ return { width: this.width(), height: this.height() };
12333
12830
  }
12334
12831
  constructor(elementRef, apiService) {
12335
12832
  super();
@@ -12339,8 +12836,8 @@ class NoderImageComponent extends BaseNoderComponent {
12339
12836
  }
12340
12837
  initialize() {
12341
12838
  const url = this.image.content?.replace('/api/', '') ?? '';
12342
- this.height = ScalingHelper.scale(this.image.height, this.generalProperties.scalingRatio);
12343
- this.width = ScalingHelper.scale(this.image.width, this.generalProperties.scalingRatio);
12839
+ this.height.set(ScalingHelper.scale(this.image.height, this.generalProperties.scalingRatio));
12840
+ this.width.set(ScalingHelper.scale(this.image.width, this.generalProperties.scalingRatio));
12344
12841
  this.apiService.getFile(url).subscribe(x => {
12345
12842
  const fileSource = URL.createObjectURL(x);
12346
12843
  const image = this.createImage(fileSource);
@@ -12354,8 +12851,8 @@ class NoderImageComponent extends BaseNoderComponent {
12354
12851
  this.editorService.changeImageStyle(resizedImage);
12355
12852
  }
12356
12853
  resize(size) {
12357
- this.width = size.width;
12358
- this.height = size.height;
12854
+ this.width.set(size.width);
12855
+ this.height.set(size.height);
12359
12856
  this.isCanvas ? this.resizeCanvas(size) : this.resizeImage(size);
12360
12857
  this.cdr.markForCheck();
12361
12858
  }
@@ -12373,8 +12870,8 @@ class NoderImageComponent extends BaseNoderComponent {
12373
12870
  }
12374
12871
  createImage(fileSource) {
12375
12872
  const imageEl = document.createElement('img');
12376
- imageEl.width = this.width;
12377
- imageEl.height = this.height;
12873
+ imageEl.width = this.width();
12874
+ imageEl.height = this.height();
12378
12875
  imageEl.draggable = false;
12379
12876
  imageEl.src = fileSource;
12380
12877
  return imageEl;
@@ -12405,25 +12902,22 @@ class NoderTabComponent extends BaseNoderComponent {
12405
12902
  this.content = val;
12406
12903
  }
12407
12904
  initialize() {
12408
- this.calculateProperties();
12905
+ this.applySize(this.tab.width, this.tab.fontSize);
12409
12906
  }
12410
- calculateProperties() {
12411
- this.height = this.tab.fontSize;
12412
- this.width = ScalingHelper.scale(this.tab.width, this.generalProperties.scalingRatio);
12907
+ applySize(width, font) {
12908
+ this.height.set(font);
12909
+ this.width.set(ScalingHelper.scale(width, this.generalProperties.scalingRatio));
12413
12910
  }
12414
12911
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTabComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
12415
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: NoderTabComponent, isStandalone: false, selector: "app-nod-tab", host: { properties: { "style.width.px": "this.width", "style.fontSize.pt": "this.height" } }, usesInheritance: true, ngImport: i0, template: "&emsp;\n", styles: [":host{position:relative;outline:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
12912
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: NoderTabComponent, isStandalone: false, selector: "app-nod-tab", host: { properties: { "style.width.px": "width()", "style.fontSize.pt": "height()" } }, usesInheritance: true, ngImport: i0, template: "&emsp;\n", styles: [":host{position:relative;outline:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
12416
12913
  }
12417
12914
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTabComponent, decorators: [{
12418
12915
  type: Component,
12419
- args: [{ selector: 'app-nod-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "&emsp;\n", styles: [":host{position:relative;outline:none}\n"] }]
12420
- }], propDecorators: { width: [{
12421
- type: HostBinding,
12422
- args: ['style.width.px']
12423
- }], height: [{
12424
- type: HostBinding,
12425
- args: ['style.fontSize.pt']
12426
- }] } });
12916
+ args: [{ selector: 'app-nod-tab', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, host: {
12917
+ '[style.width.px]': 'width()',
12918
+ '[style.fontSize.pt]': 'height()'
12919
+ }, template: "&emsp;\n", styles: [":host{position:relative;outline:none}\n"] }]
12920
+ }] });
12427
12921
 
12428
12922
  const CHARS = [
12429
12923
  // eslint-disable-next-line prettier/prettier
@@ -12456,7 +12950,7 @@ class EditSession {
12456
12950
  get scrollBarHeight() {
12457
12951
  return this.scrollBar?.element.clientHeight ?? 0; // only main session is scrollable
12458
12952
  }
12459
- constructor(displayData, sessionId, customContentService, model, selection, generalProperties, editorService, customComponents, type, scrollBar) {
12953
+ constructor(displayData, sessionId, customContentService, model, selection, generalProperties, editorService, customComponents, type, scrollBar, edgeType) {
12460
12954
  this.displayData = displayData;
12461
12955
  this.sessionId = sessionId;
12462
12956
  this.customContentService = customContentService;
@@ -12467,6 +12961,7 @@ class EditSession {
12467
12961
  this.customComponents = customComponents;
12468
12962
  this.type = type;
12469
12963
  this.scrollBar = scrollBar;
12964
+ this.edgeType = edgeType;
12470
12965
  this.tokenRe = new RegExp('^[' + UnicodeHelper.wordChars + '\\$_]+', 'g');
12471
12966
  this.nonTokenRe = new RegExp('^(?:[^' + UnicodeHelper.wordChars + '\\$_]|\\s])+', 'g');
12472
12967
  }
@@ -13085,6 +13580,10 @@ class EditSession {
13085
13580
  OperationsHelper.removeEdges(document.headers, document.footers, pageType);
13086
13581
  this.customComponents.edges.removeEdges(pageType);
13087
13582
  }
13583
+ updateDisplayData() {
13584
+ this.displayData.updateDataForModel();
13585
+ this.displayData.updateNextLineIndexes(0, this.displayData.paragraphs.length - 1);
13586
+ }
13088
13587
  }
13089
13588
 
13090
13589
  class GeneralPropertiesModel {
@@ -13216,7 +13715,8 @@ class RenderChangesModel {
13216
13715
  this.scroll ||
13217
13716
  this.size ||
13218
13717
  this.text ||
13219
- this.dragAndDrop);
13718
+ this.dragAndDrop ||
13719
+ this.visibilityChanged);
13220
13720
  }
13221
13721
  constructor(fields) {
13222
13722
  this.cursor = false;
@@ -13229,6 +13729,7 @@ class RenderChangesModel {
13229
13729
  this.size = false;
13230
13730
  this.text = false;
13231
13731
  this.dragAndDrop = false;
13732
+ this.visibilityChanged = false;
13232
13733
  if (!fields) {
13233
13734
  return;
13234
13735
  }
@@ -13361,6 +13862,16 @@ class HighlightLayer {
13361
13862
  const left = rangeInfo.leftPos;
13362
13863
  this.renderHighlight(this.getMarkerStyle(height, width, top, left), cssClass);
13363
13864
  }
13865
+ drawCustomElementHighlight(elementInfo, cssClass, screenParentRange) {
13866
+ const elementIndex = this.session.displayData.paragraphs[elementInfo.parentRange.start.row].startIndex + elementInfo.parentRange.start.column;
13867
+ const element = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === elementIndex);
13868
+ if (!element) {
13869
+ return;
13870
+ }
13871
+ const top = this.getTop(screenParentRange.start.row);
13872
+ const info = this.getRangeInfo(this.session, screenParentRange);
13873
+ this.renderHighlight(this.getMarkerStyle(elementInfo.location.height, elementInfo.location.width, top + elementInfo.location.top, info.leftPos + elementInfo.location.left), cssClass);
13874
+ }
13364
13875
  getRangeInfo(session, range) {
13365
13876
  const start = range.start;
13366
13877
  const end = range.end;
@@ -13383,34 +13894,43 @@ class SearchHighlightLayer extends HighlightLayer {
13383
13894
  this.className = 'noder-highlight';
13384
13895
  this.selectedClassName = 'noder-selected-highlight';
13385
13896
  this.markers = [];
13897
+ this.customElementsRanges = [];
13386
13898
  }
13387
13899
  update(config) {
13388
- if (!config) {
13900
+ if (!config?.isVisible) {
13389
13901
  return;
13390
13902
  }
13391
13903
  this.config = config;
13392
13904
  this.selectionIndex = 0;
13905
+ this.getVisibleCustomElementResults(config);
13393
13906
  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);
13907
+ if (this.active instanceof Range) {
13908
+ const screenRange = this.active.toScreenRange(this.session);
13909
+ if (!screenRange.isEmpty &&
13910
+ (!config.visibleRange ||
13911
+ (screenRange.start.row >= config.visibleRange.startScreenLine &&
13912
+ screenRange.end.row <= config.visibleRange.endScreenLine))) {
13913
+ if (screenRange.isSingleLine) {
13914
+ this.drawSingleLineMarker(screenRange, this.selectedClassName);
13915
+ }
13916
+ else {
13917
+ this.drawMultiLineMarker(screenRange, this.selectedClassName);
13918
+ }
13404
13919
  }
13405
13920
  }
13921
+ else {
13922
+ this.updateActiveResult();
13923
+ const screenParentRange = this.active.parentRange.toScreenRange(this.session);
13924
+ this.drawCustomElementHighlight(this.active, this.selectedClassName, screenParentRange);
13925
+ }
13406
13926
  }
13407
- if (this.markers) {
13927
+ if (this.markers?.length) {
13408
13928
  const ranges = this.markers
13409
13929
  .map(x => x.toScreenRange(this.session))
13410
13930
  .filter(x => !x.isEmpty &&
13411
13931
  (!config.visibleRange ||
13412
13932
  (x.start.row >= config.visibleRange.startScreenLine && x.end.row <= config.visibleRange.endScreenLine)) &&
13413
- !x.isEqual(this.active));
13933
+ ((this.active instanceof Range && !x.isEqual(this.active)) || !(this.active instanceof Range)));
13414
13934
  for (const range of ranges) {
13415
13935
  if (!range.isEmpty) {
13416
13936
  if (range.isSingleLine) {
@@ -13422,12 +13942,80 @@ class SearchHighlightLayer extends HighlightLayer {
13422
13942
  }
13423
13943
  }
13424
13944
  }
13945
+ if (this.customElementsRanges?.length) {
13946
+ for (const element of this.customElementsRanges) {
13947
+ if (!element.location ||
13948
+ (this.active &&
13949
+ this.active instanceof CustomElementInfo &&
13950
+ this.active.parentRange.isEqual(element.parentRange) &&
13951
+ this.active.location.isEqual(element.location))) {
13952
+ continue;
13953
+ }
13954
+ const screenParentRange = element.parentRange.toScreenRange(this.session);
13955
+ if (!config.visibleRange ||
13956
+ (screenParentRange.start.row >= config.visibleRange.startScreenLine &&
13957
+ screenParentRange.end.row <= config.visibleRange.endScreenLine)) {
13958
+ this.drawCustomElementHighlight(element, this.className, screenParentRange);
13959
+ }
13960
+ }
13961
+ }
13425
13962
  if (this.selectionIndex !== -1) {
13426
13963
  while (this.selectionIndex < this.element.childElementCount) {
13427
13964
  this.element.removeChild(this.element.lastChild);
13428
13965
  }
13429
13966
  }
13430
13967
  }
13968
+ getVisibleCustomElementResults(config) {
13969
+ if (!this.customElementsRanges?.length) {
13970
+ return;
13971
+ }
13972
+ const groupedByParentRange = [];
13973
+ for (const element of this.customElementsRanges) {
13974
+ if (element.location) {
13975
+ continue;
13976
+ }
13977
+ const existingGroup = groupedByParentRange.find(group => group.range.isEqual(element.parentRange));
13978
+ if (existingGroup) {
13979
+ existingGroup.elements.push(element);
13980
+ }
13981
+ else {
13982
+ groupedByParentRange.push({
13983
+ range: element.parentRange,
13984
+ elements: [element]
13985
+ });
13986
+ }
13987
+ }
13988
+ if (!groupedByParentRange.length) {
13989
+ return;
13990
+ }
13991
+ for (const group of groupedByParentRange) {
13992
+ const screenParentRange = group.range.toScreenRange(this.session);
13993
+ if (config.visibleRange &&
13994
+ (screenParentRange.start.row < config.visibleRange.startScreenLine ||
13995
+ screenParentRange.end.row > config.visibleRange.endScreenLine)) {
13996
+ continue;
13997
+ }
13998
+ const insertIndex = this.session.displayData.paragraphs[group.range.start.row].startIndex + group.range.start.column;
13999
+ const customElement = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === insertIndex);
14000
+ const newLocations = customElement.instance.getSearchResultLocations();
14001
+ if (!newLocations?.length) {
14002
+ continue;
14003
+ }
14004
+ for (let i = 0; i < newLocations.length; i++) {
14005
+ group.elements.find(x => x.index === i).location = newLocations[i];
14006
+ }
14007
+ }
14008
+ }
14009
+ updateActiveResult() {
14010
+ if (this.active instanceof CustomElementInfo && !this.active.location) {
14011
+ const active = this.customElementsRanges.find(x => this.active instanceof CustomElementInfo &&
14012
+ x.index === this.active.index &&
14013
+ x.parentRange.isEqual(this.active.parentRange));
14014
+ if (active) {
14015
+ this.active.location = active.location;
14016
+ }
14017
+ }
14018
+ }
13431
14019
  }
13432
14020
 
13433
14021
  class SelectionLayer extends HighlightLayer {
@@ -13483,8 +14071,10 @@ class Renderer extends EventEmitting {
13483
14071
  endLine: 0,
13484
14072
  endScreenLine: 0,
13485
14073
  endScreenFullLine: 0
13486
- }
14074
+ },
14075
+ isVisible: false
13487
14076
  };
14077
+ this.isVisible = false;
13488
14078
  this.changes = new RenderChangesModel();
13489
14079
  this.textareaSize = {
13490
14080
  height: 1,
@@ -13512,7 +14102,13 @@ class Renderer extends EventEmitting {
13512
14102
  return;
13513
14103
  }
13514
14104
  // 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) {
14105
+ if (changes.full ||
14106
+ changes.size ||
14107
+ changes.text ||
14108
+ changes.lines ||
14109
+ changes.scroll ||
14110
+ changes.search ||
14111
+ changes.visibilityChanged) {
13516
14112
  changes.apply(this.computeLayerConfig());
13517
14113
  DomHelper.translate(this.content, 0, -this.layerConfig.offset);
13518
14114
  DomHelper.setStyle(this.content.style, 'width', `${this.layerConfig.width}px`);
@@ -13538,6 +14134,9 @@ class Renderer extends EventEmitting {
13538
14134
  if (changes.dragAndDrop) {
13539
14135
  this.renderDragAndDropSelection();
13540
14136
  }
14137
+ if (changes.visibilityChanged) {
14138
+ this.renderSearchHighlights();
14139
+ }
13541
14140
  this.session.onRendered();
13542
14141
  }
13543
14142
  /**
@@ -13586,11 +14185,13 @@ class Renderer extends EventEmitting {
13586
14185
  this.loop.schedule({ search: true });
13587
14186
  }
13588
14187
  }
14188
+ updateCustomElementHighlights(ranges) {
14189
+ this.searchHighlightLayer.customElementsRanges = ranges;
14190
+ this.loop.schedule({ search: true });
14191
+ }
13589
14192
  updateActiveSearchHighlight(active) {
13590
- if (!this.searchHighlightLayer.active?.isEqual(active)) {
13591
- this.searchHighlightLayer.active = active;
13592
- this.loop.schedule({ search: true });
13593
- }
14193
+ this.searchHighlightLayer.active = active;
14194
+ this.loop.schedule({ search: true });
13594
14195
  }
13595
14196
  updateDragAndDropSelection(range) {
13596
14197
  if (range.isEmpty && this.dragAndDropSelectionLayer.marker) {
@@ -13609,12 +14210,24 @@ class Renderer extends EventEmitting {
13609
14210
  this.dragAndDropSelectionLayer.marker = null;
13610
14211
  this.loop.schedule({ dragAndDrop: true });
13611
14212
  }
14213
+ setVisibility(isVisible) {
14214
+ if (this.isVisible !== isVisible) {
14215
+ this.isVisible = isVisible;
14216
+ this.loop.schedule({ visibilityChanged: true });
14217
+ }
14218
+ }
13612
14219
  /**
13613
14220
  * Triggers a full update of the text, for all the rows.
13614
14221
  **/
13615
14222
  updateText() {
13616
14223
  this.loop.schedule({ text: true });
13617
14224
  }
14225
+ updateTextAndCursor() {
14226
+ this.loop.schedule({ text: true, cursor: true });
14227
+ }
14228
+ updateMarker() {
14229
+ this.loop.schedule({ marker: true });
14230
+ }
13618
14231
  updateCursor() {
13619
14232
  this.loop.schedule({ cursor: true });
13620
14233
  }
@@ -13686,7 +14299,8 @@ class Renderer extends EventEmitting {
13686
14299
  contentRange: new DistanceModel({ start: 0, end: displayData.paragraphs.filter(x => x.paragraphSettings).length - 1 }),
13687
14300
  maxHeight,
13688
14301
  offset: 0,
13689
- scrollTop: this.session.scrollTop
14302
+ scrollTop: this.session.scrollTop,
14303
+ isVisible: this.isVisible
13690
14304
  };
13691
14305
  return changes;
13692
14306
  }
@@ -13787,16 +14401,6 @@ class ScrollBar {
13787
14401
  }
13788
14402
  }
13789
14403
 
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
14404
  class VirtualRenderer {
13801
14405
  get cursorLayer() {
13802
14406
  return this.renderer.cursorLayer;
@@ -13850,7 +14454,13 @@ class VirtualRenderer {
13850
14454
  return;
13851
14455
  }
13852
14456
  // 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) {
14457
+ if (changes.full ||
14458
+ changes.size ||
14459
+ changes.text ||
14460
+ changes.lines ||
14461
+ changes.scroll ||
14462
+ changes.search ||
14463
+ changes.visibilityChanged) {
13854
14464
  changes.apply(this.computeLayerConfig());
13855
14465
  DomHelper.translate(this.renderer.content, 0, -this.layerConfig.offset);
13856
14466
  DomHelper.setStyle(this.renderer.content.style, 'width', `${this.layerConfig.width}px`);
@@ -13880,6 +14490,9 @@ class VirtualRenderer {
13880
14490
  if (changes.dragAndDrop) {
13881
14491
  this.renderDragAndDropSelection();
13882
14492
  }
14493
+ if (changes.visibilityChanged) {
14494
+ this.renderSearchHighlights();
14495
+ }
13883
14496
  }
13884
14497
  /**
13885
14498
  * Triggers a resize of the editor
@@ -13946,6 +14559,9 @@ class VirtualRenderer {
13946
14559
  updateSearchHighlights(ranges) {
13947
14560
  this.renderer.updateSearchHighlights(ranges);
13948
14561
  }
14562
+ updateCustomElementHighlights(ranges) {
14563
+ this.renderer.updateCustomElementHighlights(ranges);
14564
+ }
13949
14565
  updateActiveSearchHighlight(active) {
13950
14566
  this.renderer.updateActiveSearchHighlight(active);
13951
14567
  }
@@ -13961,9 +14577,18 @@ class VirtualRenderer {
13961
14577
  updateText() {
13962
14578
  this.renderer.updateText();
13963
14579
  }
14580
+ updateTextAndCursor() {
14581
+ this.renderer.updateTextAndCursor();
14582
+ }
14583
+ updateMarker() {
14584
+ this.renderer.updateMarker();
14585
+ }
13964
14586
  updateCursor() {
13965
14587
  this.renderer.updateCursor();
13966
14588
  }
14589
+ setVisibility(isVisible) {
14590
+ this.renderer.setVisibility(isVisible);
14591
+ }
13967
14592
  scrollSelectionIntoView(anchor, lead, offset) {
13968
14593
  // first scroll anchor into view then scroll lead into view
13969
14594
  this.scrollCursorIntoView(anchor, offset);
@@ -14048,7 +14673,8 @@ class VirtualRenderer {
14048
14673
  offset: 0,
14049
14674
  visibleRange,
14050
14675
  scrollTop: this.scrollBar.scrollTop,
14051
- pages: visibleRange.pages
14676
+ pages: visibleRange.pages,
14677
+ isVisible: true
14052
14678
  };
14053
14679
  return changes;
14054
14680
  }
@@ -14167,17 +14793,19 @@ class CustomContentService {
14167
14793
  }
14168
14794
  getTokenFromComponent(component, lineInfo, displayValue, isFirst, size) {
14169
14795
  let height = size.height;
14170
- if (component.instance.height > size.height) {
14796
+ if (component.instance.height() > size.height) {
14171
14797
  height =
14172
- component.instance instanceof NoderImageComponent ? component.instance.height + size.descent : component.instance.height;
14798
+ component.instance instanceof NoderImageComponent
14799
+ ? component.instance.height() + size.descent
14800
+ : component.instance.height();
14173
14801
  }
14174
14802
  return new DisplayToken({
14175
- width: component.instance.width,
14803
+ width: component.instance.width(),
14176
14804
  height,
14177
14805
  baseline: 0,
14178
14806
  content: 0,
14179
14807
  font: size.font,
14180
- ascent: component.instance.height ?? size.height,
14808
+ ascent: component.instance.height() ?? size.height,
14181
14809
  descent: 0,
14182
14810
  line: 0,
14183
14811
  lineSpacing: lineInfo.lineSpacing,
@@ -14223,7 +14851,7 @@ class RegulatorService {
14223
14851
  this.sessions = [];
14224
14852
  this.sessionIdIncrement = 0;
14225
14853
  }
14226
- addMainSession(model, pageWidth, scalingRatio, container) {
14854
+ addMainSession(model, scalingRatio, container) {
14227
14855
  const sessionId = ++this.sessionIdIncrement;
14228
14856
  const defaultPageFormat = model.pageFormats[model.pageFormats?.length - 1];
14229
14857
  const properties = new GeneralPropertiesModel({
@@ -14242,7 +14870,7 @@ class RegulatorService {
14242
14870
  footer: defaultPageFormat.marginFooter > 0 ? defaultPageFormat.marginFooter : 0
14243
14871
  });
14244
14872
  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);
14873
+ const edges = new Edges(this.componentService, model.headers, model.footers, edgesMargins, model.pageFormats, sessionId, properties);
14246
14874
  properties.numberingInfo = {};
14247
14875
  const customComponents = { images: [], tables: [], tabs: [], customElements: [], edges: edges };
14248
14876
  const displayData = new DisplayData(model, properties, sessionId, model.pageFormats, DocumentInfo.pagesSpace, customComponents, this.customContentService, this.editorService);
@@ -14275,7 +14903,7 @@ class RegulatorService {
14275
14903
  const sessionId = ++this.sessionIdIncrement;
14276
14904
  const customComponents = { images: [], tables: [], tabs: [], customElements: [], edges: null };
14277
14905
  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');
14906
+ const session = new EditSession(displayData, sessionId, this.customContentService, component.model, this.selection, component.generalProperties, this.editorService, customComponents, 'edge', null, component.type);
14279
14907
  const renderer = new Renderer(component.container.nativeElement, session);
14280
14908
  const source = new EdgeSessionSourceModel(component.model.pageType, component.type);
14281
14909
  const newSession = new SessionModel(session, renderer, sessionId, component.parentSessionId, source);
@@ -14317,11 +14945,44 @@ class RegulatorService {
14317
14945
  setCurrentSession(session) {
14318
14946
  const previous = this.currentSession;
14319
14947
  this.selection.clearSelection();
14320
- this.currentSession.renderer.hideCursor();
14948
+ if (this.currentSession.session.isEdge()) {
14949
+ this.sessions.forEach(x => {
14950
+ if (x.session.edgeType === this.currentSession.session.edgeType) {
14951
+ x.renderer.hideCursor();
14952
+ }
14953
+ });
14954
+ }
14955
+ else {
14956
+ this.currentSession.renderer.hideCursor();
14957
+ }
14321
14958
  this.currentSession.renderer.updateSelection(this.selection.selectedRange);
14322
14959
  this.currentSession = session;
14323
- this.currentSession.renderer.showCursor();
14324
- this.arrangeEdgesForSessionChange(previous.session, session.session);
14960
+ if (session.session.isEdge()) {
14961
+ this.sessions.forEach(x => {
14962
+ if (x.session.edgeType === session.session.edgeType) {
14963
+ x.renderer.showCursor();
14964
+ this.arrangeEdgesForSessionChange(previous.session, x.session);
14965
+ }
14966
+ });
14967
+ }
14968
+ else {
14969
+ this.currentSession.renderer.showCursor();
14970
+ this.arrangeEdgesForSessionChange(previous.session, session.session);
14971
+ }
14972
+ }
14973
+ updateCursorPosition() {
14974
+ if (!this.currentSession.session.isEdge()) {
14975
+ return;
14976
+ }
14977
+ this.sessions.forEach(x => {
14978
+ if (x.session.edgeType === this.currentSession.session.edgeType) {
14979
+ x.renderer.updateSelection(this.selection.selectedRange);
14980
+ if (this.selection.isEmpty) {
14981
+ x.renderer.updateCursor();
14982
+ }
14983
+ x.renderer.updateMarker();
14984
+ }
14985
+ });
14325
14986
  }
14326
14987
  getSessionModel(sessionId) {
14327
14988
  return this.sessions.find(x => x.sessionId === sessionId);
@@ -14378,8 +15039,19 @@ class RegulatorService {
14378
15039
  }
14379
15040
  arrangeEdgeChange(sessionId) {
14380
15041
  const edgeSessionId = this.getEdgeSessionId(sessionId);
14381
- const { type, pageType } = this.mainSession.session.customComponents.edges.getTypeBySessionId(edgeSessionId);
14382
- this.mainSession.renderer.edgesLayer.updateSingle(type, pageType);
15042
+ const { type, pageType, pageWidth } = this.mainSession.session.customComponents.edges.getTypeBySessionId(edgeSessionId);
15043
+ this.mainSession.renderer.edgesLayer.updateSingle(type, pageType, pageWidth);
15044
+ }
15045
+ forceUpdateDataForEdges() {
15046
+ if (this.currentSession.session.isEdge()) {
15047
+ return;
15048
+ }
15049
+ this.sessions.forEach(x => {
15050
+ if (x.session.isEdge() && x.session.edgeType === this.currentSession.session.edgeType) {
15051
+ x.session.updateDisplayData();
15052
+ x.renderer.updateTextAndCursor();
15053
+ }
15054
+ });
14383
15055
  }
14384
15056
  getEdgeSessionId(sessionId) {
14385
15057
  let session = this.getSession(sessionId);
@@ -14447,10 +15119,83 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
14447
15119
  type: Injectable
14448
15120
  }] });
14449
15121
 
15122
+ class TabSettingModel {
15123
+ constructor(fields) {
15124
+ if (fields) {
15125
+ Object.assign(this, fields);
15126
+ }
15127
+ }
15128
+ }
15129
+
15130
+ class TabSettingsDialogComponent {
15131
+ constructor(data, ref, fb) {
15132
+ this.data = data;
15133
+ this.ref = ref;
15134
+ this.fb = fb;
15135
+ this.modal = true;
15136
+ this.alignments = [
15137
+ { title: marker('NODER.LABEL.LEFT'), type: TabAlignment.Left },
15138
+ { title: marker('NODER.LABEL.CENTER'), type: TabAlignment.Center },
15139
+ { title: marker('NODER.LABEL.RIGHT'), type: TabAlignment.Right }
15140
+ ];
15141
+ this.form = this.fb.group({
15142
+ tabs: this.fb.array(this.data.tabs.map(x => this.createTabGroup(x)))
15143
+ });
15144
+ }
15145
+ tabsArray() {
15146
+ return this.form.get('tabs');
15147
+ }
15148
+ onRemove(index) {
15149
+ this.tabsArray().removeAt(index);
15150
+ }
15151
+ onClose() {
15152
+ this.ref.close();
15153
+ }
15154
+ onSave() {
15155
+ const result = this.tabsArray()
15156
+ .value.filter(x => x.position !== null)
15157
+ .map(v => new TabSettingModel({ position: v.position, alignment: v.alignment }));
15158
+ this.ref.close(result);
15159
+ }
15160
+ onAddTab() {
15161
+ const group = this.createTabGroup({ position: 0, alignment: TabAlignment.Left });
15162
+ this.tabsArray().push(group);
15163
+ }
15164
+ createTabGroup(tab) {
15165
+ return this.fb.group({
15166
+ position: new FormControl(tab.position, { nonNullable: true, validators: [Validators.required] }),
15167
+ alignment: new FormControl(tab.alignment, { nonNullable: true, validators: [Validators.required] })
15168
+ });
15169
+ }
15170
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: TabSettingsDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$1.MatDialogRef }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
15171
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: TabSettingsDialogComponent, isStandalone: true, selector: "app-nod-tab-settings-dialog", host: { properties: { "class.noder-modal": "this.modal" } }, ngImport: i0, template: "<div class=\"columns\">\n <span class=\"position\">{{ 'NODER.LABEL.POSITION' | translate }}</span>\n <span class=\"alignment\">{{ 'NODER.LABEL.ALIGNMENT' | translate }}</span>\n</div>\n<form\n [formGroup]=\"form\"\n class=\"form\">\n <div\n class=\"tabs\"\n formArrayName=\"tabs\">\n @for (tabCtrl of tabsArray().controls; let i = $index; track i) {\n <div\n class=\"item\"\n [formGroupName]=\"i\">\n <div class=\"tab\">\n <mat-form-field class=\"position\">\n <input\n matInput\n type=\"number\"\n formControlName=\"position\" />\n </mat-form-field>\n <mat-form-field class=\"alignment\">\n <mat-select formControlName=\"alignment\">\n @for (alignment of alignments; track alignment) {\n <mat-option [value]=\"alignment.type\">\n {{ alignment.title | translate }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button\n id=\"tab-setting-dialog-delete-btn\"\n mat-icon-button\n type=\"button\"\n (click)=\"onRemove(i)\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-delete\"></mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n</form>\n<div class=\"tab-actions\">\n <button\n id=\"tab-setting-dialog-add-btn\"\n mat-stroked-button\n (click)=\"onAddTab()\">\n {{ 'NODER.LABEL.ADD' | translate }}\n </button>\n <button\n id=\"tab-setting-dialog-clear-all-btn\"\n mat-stroked-button\n (click)=\"tabsArray().clear()\">\n {{ 'NODER.LABEL.CLEAR_ALL' | translate }}\n </button>\n</div>\n<div class=\"actions\">\n <button\n id=\"tab-setting-dialog-cancel-btn\"\n mat-stroked-button\n (click)=\"onClose()\">\n {{ 'NODER.LABEL.CANCEL' | translate }}\n </button>\n <button\n id=\"tab-setting-dialog-ok-btn\"\n mat-stroked-button\n (click)=\"onSave()\">\n {{ 'NODER.LABEL.SAVE' | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:550px;width:360px;padding:20px 0 20px 20px;gap:20px}.tabs{flex:1;overflow:hidden auto;display:flex;flex-direction:column}.form{height:350px;display:flex}.item{display:flex}.tab{display:flex;flex:1;gap:20px}.mat-mdc-form-field{width:120px}.columns{display:flex;gap:30%}.columns .position,.columns .alignment{font-weight:700}.tab-actions{display:flex;justify-content:start;gap:10px}.actions{display:flex;justify-content:end;gap:10px;margin-right:20px}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { 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: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15172
+ }
15173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: TabSettingsDialogComponent, decorators: [{
15174
+ type: Component,
15175
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, imports: [
15176
+ MatDialogModule,
15177
+ MatFormFieldModule,
15178
+ MatButtonModule,
15179
+ MatIconModule,
15180
+ TranslateModule,
15181
+ MatSelectModule,
15182
+ FormsModule,
15183
+ ReactiveFormsModule,
15184
+ MatInputModule
15185
+ ], selector: 'app-nod-tab-settings-dialog', template: "<div class=\"columns\">\n <span class=\"position\">{{ 'NODER.LABEL.POSITION' | translate }}</span>\n <span class=\"alignment\">{{ 'NODER.LABEL.ALIGNMENT' | translate }}</span>\n</div>\n<form\n [formGroup]=\"form\"\n class=\"form\">\n <div\n class=\"tabs\"\n formArrayName=\"tabs\">\n @for (tabCtrl of tabsArray().controls; let i = $index; track i) {\n <div\n class=\"item\"\n [formGroupName]=\"i\">\n <div class=\"tab\">\n <mat-form-field class=\"position\">\n <input\n matInput\n type=\"number\"\n formControlName=\"position\" />\n </mat-form-field>\n <mat-form-field class=\"alignment\">\n <mat-select formControlName=\"alignment\">\n @for (alignment of alignments; track alignment) {\n <mat-option [value]=\"alignment.type\">\n {{ alignment.title | translate }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button\n id=\"tab-setting-dialog-delete-btn\"\n mat-icon-button\n type=\"button\"\n (click)=\"onRemove(i)\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-delete\"></mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n</form>\n<div class=\"tab-actions\">\n <button\n id=\"tab-setting-dialog-add-btn\"\n mat-stroked-button\n (click)=\"onAddTab()\">\n {{ 'NODER.LABEL.ADD' | translate }}\n </button>\n <button\n id=\"tab-setting-dialog-clear-all-btn\"\n mat-stroked-button\n (click)=\"tabsArray().clear()\">\n {{ 'NODER.LABEL.CLEAR_ALL' | translate }}\n </button>\n</div>\n<div class=\"actions\">\n <button\n id=\"tab-setting-dialog-cancel-btn\"\n mat-stroked-button\n (click)=\"onClose()\">\n {{ 'NODER.LABEL.CANCEL' | translate }}\n </button>\n <button\n id=\"tab-setting-dialog-ok-btn\"\n mat-stroked-button\n (click)=\"onSave()\">\n {{ 'NODER.LABEL.SAVE' | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:550px;width:360px;padding:20px 0 20px 20px;gap:20px}.tabs{flex:1;overflow:hidden auto;display:flex;flex-direction:column}.form{height:350px;display:flex}.item{display:flex}.tab{display:flex;flex:1;gap:20px}.mat-mdc-form-field{width:120px}.columns{display:flex;gap:30%}.columns .position,.columns .alignment{font-weight:700}.tab-actions{display:flex;justify-content:start;gap:10px}.actions{display:flex;justify-content:end;gap:10px;margin-right:20px}\n"] }]
15186
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
15187
+ type: Inject,
15188
+ args: [MAT_DIALOG_DATA]
15189
+ }] }, { type: i1$1.MatDialogRef }, { type: i2.FormBuilder }], propDecorators: { modal: [{
15190
+ type: HostBinding,
15191
+ args: ['class.noder-modal']
15192
+ }] } });
15193
+
14450
15194
  class EditorRulerComponent {
14451
15195
  constructor() {
14452
15196
  this.unit = input.required();
14453
15197
  this.editorService = inject(EditorService);
15198
+ this.dialog = inject(MatDialog);
14454
15199
  this.defaultPaddingCm = 2.5;
14455
15200
  this.pageWidth$ = this.editorService.pageFormat$.pipe(distinctUntilChanged(), tap(x => {
14456
15201
  this.recalcGeometry(x.pageWidth);
@@ -14462,26 +15207,27 @@ class EditorRulerComponent {
14462
15207
  this.snapCm = 0.25;
14463
15208
  this.pxPerCm = 37.8; // 96dpi / 2.54
14464
15209
  this.pxPerInch = 96;
14465
- this.firstLine = signal(this.defaultPaddingCm * this.pxPerCm);
14466
- this.leftIndent = signal(this.defaultPaddingCm * this.pxPerCm);
15210
+ this.firstLine = signal(Math.floor(this.defaultPaddingCm * this.pxPerCm));
15211
+ this.leftIndent = signal(Math.floor(this.defaultPaddingCm * this.pxPerCm));
14467
15212
  this.rightIndent = signal(0);
14468
15213
  this.leftIndentPx = computed(() => this.leftIndent() + this.leftMarginPageFormatPx());
14469
15214
  this.firstLinePx = computed(() => this.firstLine() + this.leftIndentPx());
14470
15215
  this.rightIndentPx = computed(() => this.rightMarginPageFormatPx() - this.rightIndent());
14471
- this.leftMarginPageFormatPx = signal(this.defaultPaddingCm * this.pxPerCm);
15216
+ this.leftMarginPageFormatPx = signal(Math.floor(this.defaultPaddingCm * this.pxPerCm));
14472
15217
  this.rightMarginPageFormatPx = signal(0);
14473
15218
  this.guideX = signal(0);
14474
15219
  this.showGuide = signal(false);
15220
+ this.tabSettings = signal([]);
14475
15221
  this.containerWidthPx = 0;
14476
15222
  this.ticks = [];
14477
15223
  this.dragging = null;
14478
15224
  this.dragOffsetX = 0;
14479
- this.onMove = (ev) => {
15225
+ this.onMove = (event) => {
14480
15226
  if (!this.dragging) {
14481
15227
  return;
14482
15228
  }
14483
- ev.preventDefault();
14484
- const pointX = this.getClientX(ev);
15229
+ event.preventDefault();
15230
+ const pointX = this.getClientX(event);
14485
15231
  const rect = this.rulerContainer.nativeElement.getBoundingClientRect();
14486
15232
  let x = pointX - rect.left - this.dragOffsetX;
14487
15233
  if (x < -1 || x > this.containerWidthPx) {
@@ -14503,6 +15249,9 @@ class EditorRulerComponent {
14503
15249
  else if (this.dragging === 'rightIndent') {
14504
15250
  this.rightIndent.set(this.rightMarginPageFormatPx() - x);
14505
15251
  }
15252
+ else if (this.dragging === 'tabs') {
15253
+ this.tabSettings()[this.draggableTabIndex].position = x - this.leftMarginPageFormatPx();
15254
+ }
14506
15255
  this.guideX.set(x);
14507
15256
  };
14508
15257
  this.onUp = () => {
@@ -14521,6 +15270,14 @@ class EditorRulerComponent {
14521
15270
  else if (this.dragging === 'rightMarginPageFormat') {
14522
15271
  this.editorService.applyRightMarginPageFormat(Math.round(this.containerWidthPx - this.rightMarginPageFormatPx()));
14523
15272
  }
15273
+ else if (this.dragging === 'tabs') {
15274
+ this.editorService.tabSettings(this.tabSettings()
15275
+ .sort((a, b) => a.position - b.position)
15276
+ .map(x => new TabSettingModel({
15277
+ alignment: x.alignment,
15278
+ position: Math.floor(x.position)
15279
+ })));
15280
+ }
14524
15281
  this.dragging = null;
14525
15282
  this.showGuide.set(false);
14526
15283
  window.removeEventListener('mousemove', this.onMove);
@@ -14528,6 +15285,9 @@ class EditorRulerComponent {
14528
15285
  window.removeEventListener('touchmove', this.onMove);
14529
15286
  window.removeEventListener('touchend', this.onUp);
14530
15287
  };
15288
+ this.editorService.paragraphStyle$
15289
+ .pipe(takeUntilDestroyed(), distinctUntilChanged(), filter(x => !!x.tabSettings), map(x => x.tabSettings?.map(y => new TabSettingModel({ alignment: y.alignment, position: y.position })) ?? []))
15290
+ .subscribe(x => this.tabSettings.set(x));
14531
15291
  this.editorService.paragraphStyle$.pipe(takeUntilDestroyed()).subscribe(x => {
14532
15292
  this.firstLine.set(x.indentHanging ? -x.indentHanging : x.indentFirstLine);
14533
15293
  this.leftIndent.set(x.indentLeft);
@@ -14545,6 +15305,31 @@ class EditorRulerComponent {
14545
15305
  this.recalcGeometry();
14546
15306
  this.buildTicksCm();
14547
15307
  }
15308
+ onOpenDialog() {
15309
+ const tabs = this.tabSettings().map(x => {
15310
+ const position = this.unit() === 'inch' ? this.pxToInch(x.position) : this.pxToCm(x.position);
15311
+ return new TabSettingModel({ position, alignment: x.alignment });
15312
+ });
15313
+ this.dialog
15314
+ .open(TabSettingsDialogComponent, {
15315
+ autoFocus: false,
15316
+ restoreFocus: false,
15317
+ data: { tabs, unit: this.unit() }
15318
+ })
15319
+ .afterClosed()
15320
+ .pipe(filter(x => !!x))
15321
+ .subscribe((x) => {
15322
+ const convertedTabs = x.map(y => {
15323
+ const position = this.unit() === 'inch' ? this.inchToPx(y.position) : this.cmToPx(y.position);
15324
+ return new TabSettingModel({
15325
+ alignment: y.alignment,
15326
+ position: Math.floor(position)
15327
+ });
15328
+ });
15329
+ this.tabSettings.set(convertedTabs);
15330
+ this.editorService.tabSettings(convertedTabs.sort((a, b) => a.position - b.position));
15331
+ });
15332
+ }
14548
15333
  recalcGeometry(width = null) {
14549
15334
  this.containerWidthPx = width ?? this.rulerContainer.nativeElement.getBoundingClientRect().width;
14550
15335
  }
@@ -14633,9 +15418,17 @@ class EditorRulerComponent {
14633
15418
  }
14634
15419
  this.ticks = ticks;
14635
15420
  }
14636
- startDrag(ev, target) {
14637
- ev.preventDefault();
14638
- const pointX = this.getClientX(ev);
15421
+ addTab(event) {
15422
+ const position = this.getClientX(event) - this.rulerContainer.nativeElement.getBoundingClientRect().left - this.leftMarginPageFormatPx();
15423
+ this.tabSettings.update(x => {
15424
+ x.push(new TabSettingModel({ alignment: TabAlignment.Left, position }));
15425
+ return x;
15426
+ });
15427
+ this.startDrag(event, 'tabs', this.tabSettings().length - 1);
15428
+ }
15429
+ startDrag(event, target, tabIndex) {
15430
+ event.preventDefault();
15431
+ const pointX = this.getClientX(event);
14639
15432
  const rect = this.rulerContainer.nativeElement.getBoundingClientRect();
14640
15433
  this.dragging = target;
14641
15434
  if (target === 'leftMarginPageFormat') {
@@ -14653,6 +15446,10 @@ class EditorRulerComponent {
14653
15446
  else if (target === 'rightIndent') {
14654
15447
  this.dragOffsetX = pointX - rect.left - this.rightIndentPx();
14655
15448
  }
15449
+ else if (target === 'tabs') {
15450
+ this.draggableTabIndex = tabIndex;
15451
+ this.dragOffsetX = pointX - rect.left - this.tabSettings()[tabIndex].position - this.leftMarginPageFormatPx();
15452
+ }
14656
15453
  this.showGuide.set(true);
14657
15454
  this.guideX.set(this.getCurrentDraggedPx());
14658
15455
  window.addEventListener('mousemove', this.onMove);
@@ -14678,14 +15475,16 @@ class EditorRulerComponent {
14678
15475
  return this.leftIndentPx();
14679
15476
  case 'rightIndent':
14680
15477
  return this.rightIndentPx();
15478
+ case 'tabs':
15479
+ return this.tabSettings()[this.draggableTabIndex].position + this.leftMarginPageFormatPx();
14681
15480
  }
14682
15481
  }
14683
15482
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: EditorRulerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14684
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: EditorRulerComponent, isStandalone: true, selector: "app-nod-editor-ruler", inputs: { unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "rulerContainer", first: true, predicate: ["rulerContainer"], descendants: true, static: true }], ngImport: i0, template: "<div\n class=\"ruler-container\"\n [style.width.px]=\"pageWidth$ | async\"\n #rulerContainer>\n <div\n class=\"left-area\"\n [style.width.px]=\"leftMarginPageFormatPx()\"></div>\n <div\n class=\"right-area\"\n [style.width.px]=\"containerWidthPx - rightMarginPageFormatPx()\"></div>\n <div\n class=\"separator left-page-format\"\n [style.left.px]=\"leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'leftMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'leftMarginPageFormat')\"></div>\n <div\n class=\"separator right-page-format\"\n [style.left.px]=\"rightMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'rightMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'rightMarginPageFormat')\"></div>\n\n <div class=\"ruler-track\">\n @for (tick of ticks; track tick) {\n <div\n class=\"tick\"\n [style.left.px]=\"tick.position\"\n [class.major]=\"tick.major\"\n [class.half]=\"tick.half\">\n @if (tick.label !== null) {\n <span class=\"label\">\n {{ tick.label }}\n </span>\n }\n </div>\n }\n </div>\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"leftIndentPx()\"\n (mousedown)=\"startDrag($event, 'leftIndent')\"\n (touchstart)=\"startDrag($event, 'leftIndent')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-down\"\n class=\"paragraph-marker\"\n [style.left.px]=\"firstLinePx()\"\n (mousedown)=\"startDrag($event, 'first')\"\n (touchstart)=\"startDrag($event, 'first')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"rightIndentPx()\"\n (mousedown)=\"startDrag($event, 'rightIndent')\"\n (touchstart)=\"startDrag($event, 'rightIndent')\" />\n @if (showGuide()) {\n <div\n class=\"drag-guide\"\n [style.left.px]=\"guideX()\"></div>\n }\n</div>\n", styles: [":host{display:flex;width:100%;height:22px;justify-content:center;align-items:center}.ruler-container{position:relative;height:18px;border-bottom-width:1px;border-bottom-style:solid;border-top-width:1px;border-top-style:solid;-webkit-user-select:none;user-select:none}.ruler-track{position:absolute;left:0;right:0;bottom:0;height:18px;overflow:hidden}.tick{position:absolute;top:50%;transform:translateY(-50%);width:1px;height:4px}.major{height:0}.half{height:8px}.label{position:absolute;top:50%;transform:translate(-50%,-50%);font-size:10px}mat-icon{position:absolute;width:17px;height:17px;font-size:18px;font-weight:700;cursor:grab;z-index:2;transform:translate(-50%)}.drag-guide{position:absolute;height:2000px;top:10px;width:1px;z-index:9999;pointer-events:none;will-change:left}.paragraph-marker{top:-6px;z-index:2}.page-marker{bottom:-6px;z-index:2}.left-area,.right-area,.separator{position:absolute;height:18px}.separator{width:5px;transform:translate(-50%);background-color:transparent;cursor:ew-resize;z-index:2}.left-area{left:0}.right-area{right:0}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15483
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: EditorRulerComponent, isStandalone: true, selector: "app-nod-editor-ruler", inputs: { unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "rulerContainer", first: true, predicate: ["rulerContainer"], descendants: true, static: true }], ngImport: i0, template: "<div\n class=\"ruler-container\"\n [style.width.px]=\"pageWidth$ | async\"\n #rulerContainer>\n <div\n class=\"left-area\"\n [style.width.px]=\"leftMarginPageFormatPx()\"></div>\n <div\n class=\"right-area\"\n [style.width.px]=\"containerWidthPx - rightMarginPageFormatPx()\"></div>\n <div\n class=\"separator left-page-format\"\n [style.left.px]=\"leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'leftMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'leftMarginPageFormat')\"></div>\n <div\n class=\"separator right-page-format\"\n [style.left.px]=\"rightMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'rightMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'rightMarginPageFormat')\"></div>\n\n <div\n class=\"ruler-track\"\n (mousedown)=\"addTab($event)\"\n (touchstart)=\"addTab($event)\"\n (dblclick)=\"onOpenDialog()\">\n @for (tick of ticks; track tick) {\n <div\n class=\"tick\"\n [style.left.px]=\"tick.position\"\n [class.major]=\"tick.major\"\n [class.half]=\"tick.half\">\n @if (tick.label !== null) {\n <span class=\"label\">\n {{ tick.label }}\n </span>\n }\n </div>\n }\n </div>\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"leftIndentPx()\"\n (mousedown)=\"startDrag($event, 'leftIndent')\"\n (touchstart)=\"startDrag($event, 'leftIndent')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-down\"\n class=\"paragraph-marker\"\n [style.left.px]=\"firstLinePx()\"\n (mousedown)=\"startDrag($event, 'first')\"\n (touchstart)=\"startDrag($event, 'first')\" />\n @for (tabSetting of tabSettings(); track tabSetting; let index = $index) {\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"tabSetting.position + this.leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'tabs', index)\"\n (touchstart)=\"startDrag($event, 'tabs', index)\"\n (dblclick)=\"onOpenDialog()\" />\n }\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"rightIndentPx()\"\n (mousedown)=\"startDrag($event, 'rightIndent')\"\n (touchstart)=\"startDrag($event, 'rightIndent')\" />\n @if (showGuide()) {\n <div\n class=\"drag-guide\"\n [style.left.px]=\"guideX()\"></div>\n }\n</div>\n", styles: [":host{display:flex;width:100%;height:22px;justify-content:center;align-items:center}.ruler-container{position:relative;height:18px;border-bottom-width:1px;border-bottom-style:solid;border-top-width:1px;border-top-style:solid;-webkit-user-select:none;user-select:none}.ruler-track{position:absolute;left:0;right:0;bottom:0;height:18px;overflow:hidden}.tick{position:absolute;top:50%;transform:translateY(-50%);width:1px;height:4px}.major{height:0}.half{height:8px}.label{position:absolute;top:50%;transform:translate(-50%,-50%);font-size:10px}mat-icon{position:absolute;width:17px;height:17px;font-size:18px;font-weight:700;cursor:grab;z-index:2;transform:translate(-50%)}.drag-guide{position:absolute;height:2000px;top:10px;width:1px;z-index:9999;pointer-events:none;will-change:left}.paragraph-marker{top:-6px;z-index:2}.page-marker{bottom:-6px;z-index:2}.left-area,.right-area,.separator{position:absolute;height:18px}.separator{width:5px;transform:translate(-50%);background-color:transparent;cursor:ew-resize;z-index:2}.left-area{left:0}.right-area{right:0}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14685
15484
  }
14686
15485
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: EditorRulerComponent, decorators: [{
14687
15486
  type: Component,
14688
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-nod-editor-ruler', imports: [MatIconModule, AsyncPipe], template: "<div\n class=\"ruler-container\"\n [style.width.px]=\"pageWidth$ | async\"\n #rulerContainer>\n <div\n class=\"left-area\"\n [style.width.px]=\"leftMarginPageFormatPx()\"></div>\n <div\n class=\"right-area\"\n [style.width.px]=\"containerWidthPx - rightMarginPageFormatPx()\"></div>\n <div\n class=\"separator left-page-format\"\n [style.left.px]=\"leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'leftMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'leftMarginPageFormat')\"></div>\n <div\n class=\"separator right-page-format\"\n [style.left.px]=\"rightMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'rightMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'rightMarginPageFormat')\"></div>\n\n <div class=\"ruler-track\">\n @for (tick of ticks; track tick) {\n <div\n class=\"tick\"\n [style.left.px]=\"tick.position\"\n [class.major]=\"tick.major\"\n [class.half]=\"tick.half\">\n @if (tick.label !== null) {\n <span class=\"label\">\n {{ tick.label }}\n </span>\n }\n </div>\n }\n </div>\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"leftIndentPx()\"\n (mousedown)=\"startDrag($event, 'leftIndent')\"\n (touchstart)=\"startDrag($event, 'leftIndent')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-down\"\n class=\"paragraph-marker\"\n [style.left.px]=\"firstLinePx()\"\n (mousedown)=\"startDrag($event, 'first')\"\n (touchstart)=\"startDrag($event, 'first')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"rightIndentPx()\"\n (mousedown)=\"startDrag($event, 'rightIndent')\"\n (touchstart)=\"startDrag($event, 'rightIndent')\" />\n @if (showGuide()) {\n <div\n class=\"drag-guide\"\n [style.left.px]=\"guideX()\"></div>\n }\n</div>\n", styles: [":host{display:flex;width:100%;height:22px;justify-content:center;align-items:center}.ruler-container{position:relative;height:18px;border-bottom-width:1px;border-bottom-style:solid;border-top-width:1px;border-top-style:solid;-webkit-user-select:none;user-select:none}.ruler-track{position:absolute;left:0;right:0;bottom:0;height:18px;overflow:hidden}.tick{position:absolute;top:50%;transform:translateY(-50%);width:1px;height:4px}.major{height:0}.half{height:8px}.label{position:absolute;top:50%;transform:translate(-50%,-50%);font-size:10px}mat-icon{position:absolute;width:17px;height:17px;font-size:18px;font-weight:700;cursor:grab;z-index:2;transform:translate(-50%)}.drag-guide{position:absolute;height:2000px;top:10px;width:1px;z-index:9999;pointer-events:none;will-change:left}.paragraph-marker{top:-6px;z-index:2}.page-marker{bottom:-6px;z-index:2}.left-area,.right-area,.separator{position:absolute;height:18px}.separator{width:5px;transform:translate(-50%);background-color:transparent;cursor:ew-resize;z-index:2}.left-area{left:0}.right-area{right:0}\n"] }]
15487
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'app-nod-editor-ruler', imports: [MatIconModule, AsyncPipe], template: "<div\n class=\"ruler-container\"\n [style.width.px]=\"pageWidth$ | async\"\n #rulerContainer>\n <div\n class=\"left-area\"\n [style.width.px]=\"leftMarginPageFormatPx()\"></div>\n <div\n class=\"right-area\"\n [style.width.px]=\"containerWidthPx - rightMarginPageFormatPx()\"></div>\n <div\n class=\"separator left-page-format\"\n [style.left.px]=\"leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'leftMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'leftMarginPageFormat')\"></div>\n <div\n class=\"separator right-page-format\"\n [style.left.px]=\"rightMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'rightMarginPageFormat')\"\n (touchstart)=\"startDrag($event, 'rightMarginPageFormat')\"></div>\n\n <div\n class=\"ruler-track\"\n (mousedown)=\"addTab($event)\"\n (touchstart)=\"addTab($event)\"\n (dblclick)=\"onOpenDialog()\">\n @for (tick of ticks; track tick) {\n <div\n class=\"tick\"\n [style.left.px]=\"tick.position\"\n [class.major]=\"tick.major\"\n [class.half]=\"tick.half\">\n @if (tick.label !== null) {\n <span class=\"label\">\n {{ tick.label }}\n </span>\n }\n </div>\n }\n </div>\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"leftIndentPx()\"\n (mousedown)=\"startDrag($event, 'leftIndent')\"\n (touchstart)=\"startDrag($event, 'leftIndent')\" />\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-down\"\n class=\"paragraph-marker\"\n [style.left.px]=\"firstLinePx()\"\n (mousedown)=\"startDrag($event, 'first')\"\n (touchstart)=\"startDrag($event, 'first')\" />\n @for (tabSetting of tabSettings(); track tabSetting; let index = $index) {\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"tabSetting.position + this.leftMarginPageFormatPx()\"\n (mousedown)=\"startDrag($event, 'tabs', index)\"\n (touchstart)=\"startDrag($event, 'tabs', index)\"\n (dblclick)=\"onOpenDialog()\" />\n }\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-field-up\"\n class=\"page-marker\"\n [style.left.px]=\"rightIndentPx()\"\n (mousedown)=\"startDrag($event, 'rightIndent')\"\n (touchstart)=\"startDrag($event, 'rightIndent')\" />\n @if (showGuide()) {\n <div\n class=\"drag-guide\"\n [style.left.px]=\"guideX()\"></div>\n }\n</div>\n", styles: [":host{display:flex;width:100%;height:22px;justify-content:center;align-items:center}.ruler-container{position:relative;height:18px;border-bottom-width:1px;border-bottom-style:solid;border-top-width:1px;border-top-style:solid;-webkit-user-select:none;user-select:none}.ruler-track{position:absolute;left:0;right:0;bottom:0;height:18px;overflow:hidden}.tick{position:absolute;top:50%;transform:translateY(-50%);width:1px;height:4px}.major{height:0}.half{height:8px}.label{position:absolute;top:50%;transform:translate(-50%,-50%);font-size:10px}mat-icon{position:absolute;width:17px;height:17px;font-size:18px;font-weight:700;cursor:grab;z-index:2;transform:translate(-50%)}.drag-guide{position:absolute;height:2000px;top:10px;width:1px;z-index:9999;pointer-events:none;will-change:left}.paragraph-marker{top:-6px;z-index:2}.page-marker{bottom:-6px;z-index:2}.left-area,.right-area,.separator{position:absolute;height:18px}.separator{width:5px;transform:translate(-50%);background-color:transparent;cursor:ew-resize;z-index:2}.left-area{left:0}.right-area{right:0}\n"] }]
14689
15488
  }], ctorParameters: () => [], propDecorators: { rulerContainer: [{
14690
15489
  type: ViewChild,
14691
15490
  args: ['rulerContainer', { static: true }]
@@ -14746,6 +15545,7 @@ class EditorComponent {
14746
15545
  this.sidenavComponentRef = this.componentService.createComponent(data.component, data?.data);
14747
15546
  this.componentService.attachComponent(this.sidenavContainer.nativeElement, this.sidenavComponentRef);
14748
15547
  if (!this.sidenav.opened) {
15548
+ this.sidenav.autoFocus = data.focus;
14749
15549
  this.sidenav.open().catch(() => {
14750
15550
  // continue regardless of error
14751
15551
  });
@@ -14900,7 +15700,7 @@ class NoderTranslateLoader extends TranslateHttpLoader {
14900
15700
  getTranslation(lang) {
14901
15701
  return super.getTranslation(lang).pipe(catchError(() => super.getTranslation('en')));
14902
15702
  }
14903
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTranslateLoader, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
15703
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTranslateLoader, deps: [{ token: i1$2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
14904
15704
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTranslateLoader, providedIn: 'root' }); }
14905
15705
  }
14906
15706
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: NoderTranslateLoader, decorators: [{
@@ -14908,7 +15708,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
14908
15708
  args: [{
14909
15709
  providedIn: 'root'
14910
15710
  }]
14911
- }], ctorParameters: () => [{ type: i1$1.HttpClient }] });
15711
+ }], ctorParameters: () => [{ type: i1$2.HttpClient }] });
14912
15712
 
14913
15713
  var Mode;
14914
15714
  (function (Mode) {
@@ -15064,7 +15864,7 @@ class ToolbarCoreService {
15064
15864
  }
15065
15865
  openBurgerMenu() {
15066
15866
  this.mode = EditorToolbarMode.Menu;
15067
- this.editorService.openSidenav(MenuDropdownsMobileComponent);
15867
+ this.editorService.openSidenav(MenuDropdownsMobileComponent, true);
15068
15868
  }
15069
15869
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ToolbarCoreService, deps: [{ token: EditorService }], target: i0.ɵɵFactoryTarget.Injectable }); }
15070
15870
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ToolbarCoreService }); }
@@ -16895,7 +17695,7 @@ class PageSetupComponent {
16895
17695
  return customPageSize;
16896
17696
  }
16897
17697
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: PageSetupComponent, deps: [{ token: EditorService }, { token: ToolbarCoreService }, { token: i3$1.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
16898
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: PageSetupComponent, isStandalone: true, selector: "app-nod-page-setup", viewQueries: [{ propertyName: "pageSizeForm", first: true, predicate: ["pageSizeForm"], descendants: true }], ngImport: i0, template: "<div class=\"title\">\n <mat-icon\n fontSet=\"noder-icon\"\n (click)=\"onClose()\"\n fontIcon=\"icon-arrow-forward\" />\n <span>{{ 'NODER.LABEL.PAGE_SETUP' | translate }}</span>\n</div>\n<form #pageSizeForm=\"ngForm\">\n <div class=\"content\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.APPLY_TO' | translate }}</mat-label>\n <mat-select [(value)]=\"selectedDocumentArea\">\n <mat-option [value]=\"documentAreas.WholeDocument\">{{ 'NODER.LABEL.WHOLE_DOCUMENT' | translate }}</mat-option>\n <mat-option [value]=\"documentAreas.ThisSection\">{{ 'NODER.LABEL.THIS_SECTION' | translate }}</mat-option>\n @if (hasSelection$ | async) {\n <mat-option [value]=\"documentAreas.SelectedText\">{{ 'NODER.LABEL.SELECTED_TEXT' | translate }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"orientation\">\n <div class=\"label\">{{ 'NODER.LABEL.ORIENTATION' | translate }}</div>\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"pageSize.orientation\"\n name=\"orientation\"\n (change)=\"onPageOrientationChanged()\">\n <mat-radio-button [value]=\"pageOrientations.Portrait\">\n <span>{{ 'NODER.LABEL.PORTRAIT' | translate }}</span>\n </mat-radio-button>\n <mat-radio-button [value]=\"pageOrientations.Landscape\">\n <span>{{ 'NODER.LABEL.LANDSCAPE' | translate }}</span>\n </mat-radio-button>\n </mat-radio-group>\n </div>\n <div class=\"page-format\">\n <div class=\"page-format-tile\">\n <div class=\"label\">{{ 'NODER.LABEL.PAGE_FORMAT' | translate }}</div>\n <div class=\"checkbox-area\">\n <div class=\"checkbox-label\">{{ 'NODER.LABEL.CUSTOM_SIZE' | translate }}</div>\n <mat-checkbox\n [checked]=\"pageSize.isCustom\"\n (change)=\"toggleCustomSize($event)\" />\n </div>\n </div>\n @if (!pageSize.isCustom) {\n <div class=\"page-size\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SIZE' | translate }}</mat-label>\n <mat-select\n [(value)]=\"pageSizeName\"\n (selectionChange)=\"onPageSizeChange()\">\n @for (option of pageSizes; track option) {\n <mat-option [value]=\"option.name\">\n <div class=\"size-option\">\n <span class=\"option-name\">{{ option.name + ' ' }}</span>\n <span class=\"option-size\">{{ option.size }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n } @else {\n <div class=\"page-custom-size\">\n <mat-form-field\n appearance=\"outline\"\n class=\"size-unit\">\n <mat-label>{{ 'NODER.LABEL.MEASURE' | translate }}</mat-label>\n <mat-select\n [(ngModel)]=\"pageSize.unit\"\n name=\"unit\"\n (valueChange)=\"onUnitChanged($event)\">\n <mat-option [value]=\"sizeUnits.Millimeters\">{{ 'NODER.LABEL.MILLIMETERS' | translate }}</mat-option>\n <mat-option [value]=\"sizeUnits.Inches\">{{ 'NODER.LABEL.INCHES' | translate }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"size-panel\">\n <mat-form-field\n appearance=\"outline\"\n class=\"custom-width\">\n <mat-label>{{ ('NODER.LABEL.WIDTH' | translate) + currentUnit }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"pageSize.customWidth\"\n name=\"customWidth\" />\n </mat-form-field>\n <button\n mat-button\n (click)=\"onIncrementWidth()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-add\"></mat-icon>\n </button>\n <button\n mat-button\n (click)=\"onDecrementWidth()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-remove\"></mat-icon>\n </button>\n </div>\n <div class=\"size-panel\">\n <mat-form-field\n appearance=\"outline\"\n class=\"custom-height\">\n <mat-label>{{ ('NODER.LABEL.HEIGHT' | translate) + currentUnit }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"pageSize.customHeight\"\n name=\"customHeight\" />\n </mat-form-field>\n <button\n mat-button\n (click)=\"onIncrementHeight()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-add\"></mat-icon>\n </button>\n <button\n mat-button\n (click)=\"onDecrementHeight()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-remove\"></mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n <div class=\"actions\">\n <button\n mat-stroked-button\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\" />\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n (click)=\"onApply()\"\n [disabled]=\"pageSizeForm.pristine\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\" />\n </button>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;width:400px}.title{margin:12px 16px;height:32px;display:flex;align-items:center;gap:8px}.title span{overflow:hidden;text-overflow:ellipsis;font-size:16px;font-style:normal;font-weight:500;line-height:normal}.content{display:flex;flex-direction:column;height:100%;overflow:hidden;padding:8px 16px 0;gap:24px}.actions{display:flex;justify-content:flex-end;margin:0 16px 16px;gap:10px}.actions .mdc-button{width:32px;height:32px;min-width:32px;padding:0}.actions .mdc-button .mat-icon{margin-right:0;margin-left:0}.orientation{display:flex;flex-direction:column;align-items:flex-start;gap:8px}.orientation mat-radio-group{display:flex;width:100%;gap:16px}.label{font-size:14px;font-style:normal;font-weight:400;line-height:normal}.page-format{display:flex;flex-direction:column;gap:16px}.page-format-tile{display:flex;align-items:center;justify-content:space-between}.page-format-tile .checkbox-area{display:flex;align-items:center}.checkbox-label{font-size:12px;font-style:normal;font-weight:400;line-height:normal}.custom-width,.custom-height,.size-unit{width:120px}.page-custom-size{display:flex;flex-direction:column}.size-panel{display:flex;gap:10px}.size-panel .mdc-button{width:40px;height:40px;min-width:40px;padding:0}.size-panel .mdc-button .mat-icon{margin-right:0;margin-left:0}.size-option{display:flex;flex-direction:column}.option-name{font-weight:400}.option-size{font-size:12px}form{display:flex;flex-direction:column;flex:1}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { 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: "ngmodule", type: MatFormFieldModule }, { 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: 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: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i10.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i12.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i12.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
17698
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.5", type: PageSetupComponent, isStandalone: true, selector: "app-nod-page-setup", viewQueries: [{ propertyName: "pageSizeForm", first: true, predicate: ["pageSizeForm"], descendants: true }], ngImport: i0, template: "<div class=\"title\">\n <mat-icon\n fontSet=\"noder-icon\"\n (click)=\"onClose()\"\n fontIcon=\"icon-arrow-forward\" />\n <span>{{ 'NODER.LABEL.PAGE_SETUP' | translate }}</span>\n</div>\n<form #pageSizeForm=\"ngForm\">\n <div class=\"content\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.APPLY_TO' | translate }}</mat-label>\n <mat-select [(value)]=\"selectedDocumentArea\">\n <mat-option [value]=\"documentAreas.WholeDocument\">{{ 'NODER.LABEL.WHOLE_DOCUMENT' | translate }}</mat-option>\n <mat-option [value]=\"documentAreas.ThisSection\">{{ 'NODER.LABEL.THIS_SECTION' | translate }}</mat-option>\n @if (hasSelection$ | async) {\n <mat-option [value]=\"documentAreas.SelectedText\">{{ 'NODER.LABEL.SELECTED_TEXT' | translate }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n <div class=\"orientation\">\n <div class=\"label\">{{ 'NODER.LABEL.ORIENTATION' | translate }}</div>\n <mat-radio-group\n aria-label=\"Select an option\"\n [(ngModel)]=\"pageSize.orientation\"\n name=\"orientation\"\n (change)=\"onPageOrientationChanged()\">\n <mat-radio-button [value]=\"pageOrientations.Portrait\">\n <span>{{ 'NODER.LABEL.PORTRAIT' | translate }}</span>\n </mat-radio-button>\n <mat-radio-button [value]=\"pageOrientations.Landscape\">\n <span>{{ 'NODER.LABEL.LANDSCAPE' | translate }}</span>\n </mat-radio-button>\n </mat-radio-group>\n </div>\n <div class=\"page-format\">\n <div class=\"page-format-tile\">\n <div class=\"label\">{{ 'NODER.LABEL.PAGE_FORMAT' | translate }}</div>\n <div class=\"checkbox-area\">\n <div class=\"checkbox-label\">{{ 'NODER.LABEL.CUSTOM_SIZE' | translate }}</div>\n <mat-checkbox\n [checked]=\"pageSize.isCustom\"\n (change)=\"toggleCustomSize($event)\" />\n </div>\n </div>\n @if (!pageSize.isCustom) {\n <div class=\"page-size\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.SIZE' | translate }}</mat-label>\n <mat-select\n [(value)]=\"pageSizeName\"\n (selectionChange)=\"onPageSizeChange()\">\n @for (option of pageSizes; track option) {\n <mat-option [value]=\"option.name\">\n <div class=\"size-option\">\n <span class=\"option-name\">{{ option.name + ' ' }}</span>\n <span class=\"option-size\">{{ option.size }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n } @else {\n <div class=\"page-custom-size\">\n <mat-form-field\n appearance=\"outline\"\n class=\"size-unit\">\n <mat-label>{{ 'NODER.LABEL.MEASURE' | translate }}</mat-label>\n <mat-select\n [(ngModel)]=\"pageSize.unit\"\n name=\"unit\"\n (valueChange)=\"onUnitChanged($event)\">\n <mat-option [value]=\"sizeUnits.Millimeters\">{{ 'NODER.LABEL.MILLIMETERS' | translate }}</mat-option>\n <mat-option [value]=\"sizeUnits.Inches\">{{ 'NODER.LABEL.INCHES' | translate }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"size-panel\">\n <mat-form-field\n appearance=\"outline\"\n class=\"custom-width\">\n <mat-label>{{ ('NODER.LABEL.WIDTH' | translate) + currentUnit }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"pageSize.customWidth\"\n name=\"customWidth\" />\n </mat-form-field>\n <button\n mat-button\n (click)=\"onIncrementWidth()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-add\"></mat-icon>\n </button>\n <button\n mat-button\n (click)=\"onDecrementWidth()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-remove\"></mat-icon>\n </button>\n </div>\n <div class=\"size-panel\">\n <mat-form-field\n appearance=\"outline\"\n class=\"custom-height\">\n <mat-label>{{ ('NODER.LABEL.HEIGHT' | translate) + currentUnit }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"pageSize.customHeight\"\n name=\"customHeight\" />\n </mat-form-field>\n <button\n mat-button\n (click)=\"onIncrementHeight()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-add\"></mat-icon>\n </button>\n <button\n mat-button\n (click)=\"onDecrementHeight()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-remove\"></mat-icon>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n <div class=\"actions\">\n <button\n mat-stroked-button\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\" />\n </button>\n <button\n mat-flat-button\n color=\"primary\"\n (click)=\"onApply()\"\n [disabled]=\"pageSizeForm.pristine\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\" />\n </button>\n </div>\n</form>\n", styles: [":host{display:flex;flex-direction:column;height:100%;width:400px}.title{margin:12px 16px;height:32px;display:flex;align-items:center;gap:8px}.title span{overflow:hidden;text-overflow:ellipsis;font-size:16px;font-style:normal;font-weight:500;line-height:normal}.content{display:flex;flex-direction:column;height:100%;overflow:hidden;padding:8px 16px 0;gap:24px}.actions{display:flex;justify-content:flex-end;margin:0 16px 16px;gap:10px}.actions .mdc-button{width:32px;height:32px;min-width:32px;padding:0}.actions .mdc-button .mat-icon{margin-right:0;margin-left:0}.orientation{display:flex;flex-direction:column;align-items:flex-start;gap:8px}.orientation mat-radio-group{display:flex;width:100%;gap:16px}.label{font-size:14px;font-style:normal;font-weight:400;line-height:normal}.page-format{display:flex;flex-direction:column;gap:16px}.page-format-tile{display:flex;align-items:center;justify-content:space-between}.page-format-tile .checkbox-area{display:flex;align-items:center}.checkbox-label{font-size:12px;font-style:normal;font-weight:400;line-height:normal}.custom-width,.custom-height,.size-unit{width:120px}.page-custom-size{display:flex;flex-direction:column}.size-panel{display:flex;gap:10px}.size-panel .mdc-button{width:40px;height:40px;min-width:40px;padding:0}.size-panel .mdc-button .mat-icon{margin-right:0;margin-left:0}.size-option{display:flex;flex-direction:column}.option-name{font-weight:400}.option-size{font-size:12px}form{display:flex;flex-direction:column;flex:1}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { 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: "ngmodule", type: MatFormFieldModule }, { 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: 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: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i7.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i3$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i10.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i12.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i12.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
16899
17699
  }
16900
17700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: PageSetupComponent, decorators: [{
16901
17701
  type: Component,
@@ -16965,7 +17765,8 @@ class RevisionHelper {
16965
17765
  beforeAutospacing: paragraphStyle.beforeAutospacing ?? DEFAULT_PARAGRAPH_STYLE.beforeAutospacing,
16966
17766
  afterAutospacing: paragraphStyle.afterAutospacing ?? DEFAULT_PARAGRAPH_STYLE.afterAutospacing,
16967
17767
  numberingId: paragraphStyle.numberingId ?? DEFAULT_PARAGRAPH_STYLE.numberingId,
16968
- numberingLevel: paragraphStyle.numberingLevel ?? DEFAULT_PARAGRAPH_STYLE.numberingLevel
17768
+ numberingLevel: paragraphStyle.numberingLevel ?? DEFAULT_PARAGRAPH_STYLE.numberingLevel,
17769
+ tabSettings: paragraphStyle.tabSettings ?? DEFAULT_PARAGRAPH_STYLE.tabSettings
16969
17770
  });
16970
17771
  }
16971
17772
  static getEmptyDocxModel() {
@@ -17045,8 +17846,8 @@ class AddLinkDialogComponent {
17045
17846
  }
17046
17847
  this.dialogRef.close({ text: this.form.controls.text.value, link: this.form.controls.link.value });
17047
17848
  }
17048
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: AddLinkDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
17049
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: AddLinkDialogComponent, isStandalone: true, selector: "app-nod-add-link-dialog", host: { listeners: { "keydown.esc": "onClose()", "keydown.enter": "onApply()" }, properties: { "class.noder-modal": "this.modal" } }, ngImport: i0, template: "<div mat-dialog-title>{{ 'NODER.LABEL.ADD_LINK' | translate }}</div>\n<div\n mat-dialog-content\n [formGroup]=\"form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.TEXT' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.text\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_TEXT_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.LINK' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.link\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_LINK_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n</div>\n<div mat-dialog-actions>\n <button\n mat-button\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\" />\n {{ 'NODER.LABEL.CANCEL' | translate }}\n </button>\n <button\n mat-raised-button\n color=\"primary\"\n class=\"apply-btn\"\n [disabled]=\"form.invalid\"\n (click)=\"onApply()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\" />\n {{ 'NODER.LABEL.APPLY' | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:300px;width:430px;overflow:hidden}:host ::ng-deep .mdc-text-field--outlined{--mdc-outlined-text-field-container-shape: 12px;height:48px}:host ::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-top:12px}.mat-mdc-dialog-title{font-weight:600;padding-top:5px}mat-form-field{width:100%}.mat-mdc-dialog-content{padding-top:10px!important;padding-bottom:0}.mat-mdc-dialog-actions{display:flex;justify-content:center;padding-top:5px;height:40px;margin-bottom:30px}.mat-mdc-dialog-actions button{width:30%;height:100%;letter-spacing:1px;border-radius:8px;text-transform:uppercase}.mat-mdc-dialog-actions button .apply-btn{font-weight:400}.mat-mdc-dialog-actions button .mat-icon{font-size:24px;height:24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { 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: "directive", type: i5$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "ngmodule", type: ReactiveFormsModule }, { 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: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
17849
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: AddLinkDialogComponent, deps: [{ token: i1$1.MatDialogRef }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
17850
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: AddLinkDialogComponent, isStandalone: true, selector: "app-nod-add-link-dialog", host: { listeners: { "keydown.esc": "onClose()", "keydown.enter": "onApply()" }, properties: { "class.noder-modal": "this.modal" } }, ngImport: i0, template: "<div mat-dialog-title>{{ 'NODER.LABEL.ADD_LINK' | translate }}</div>\n<div\n mat-dialog-content\n [formGroup]=\"form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.TEXT' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.text\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_TEXT_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.LINK' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.link\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_LINK_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n</div>\n<div mat-dialog-actions>\n <button\n mat-button\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\" />\n {{ 'NODER.LABEL.CANCEL' | translate }}\n </button>\n <button\n mat-raised-button\n color=\"primary\"\n class=\"apply-btn\"\n [disabled]=\"form.invalid\"\n (click)=\"onApply()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\" />\n {{ 'NODER.LABEL.APPLY' | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:300px;width:430px;overflow:hidden}:host ::ng-deep .mdc-text-field--outlined{--mdc-outlined-text-field-container-shape: 12px;height:48px}:host ::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-top:12px}.mat-mdc-dialog-title{font-weight:600;padding-top:5px}mat-form-field{width:100%}.mat-mdc-dialog-content{padding-top:10px!important;padding-bottom:0}.mat-mdc-dialog-actions{display:flex;justify-content:center;padding-top:5px;height:40px;margin-bottom:30px}.mat-mdc-dialog-actions button{width:30%;height:100%;letter-spacing:1px;border-radius:8px;text-transform:uppercase}.mat-mdc-dialog-actions button .apply-btn{font-weight:400}.mat-mdc-dialog-actions button .mat-icon{font-size:24px;height:24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1$1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1$1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { 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: "directive", type: i5$1.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { 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: "ngmodule", type: ReactiveFormsModule }, { 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: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
17050
17851
  }
17051
17852
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: AddLinkDialogComponent, decorators: [{
17052
17853
  type: Component,
@@ -17060,7 +17861,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
17060
17861
  ReactiveFormsModule,
17061
17862
  TranslateModule
17062
17863
  ], selector: 'app-nod-add-link-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div mat-dialog-title>{{ 'NODER.LABEL.ADD_LINK' | translate }}</div>\n<div\n mat-dialog-content\n [formGroup]=\"form\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.TEXT' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.text\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_TEXT_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ 'NODER.LABEL.LINK' | translate }}</mat-label>\n <input\n matInput\n [formControl]=\"form.controls.link\"\n required />\n <mat-error>{{ 'NODER.LABEL.THE_LINK_IS_REQUIRED' | translate }}.</mat-error>\n </mat-form-field>\n</div>\n<div mat-dialog-actions>\n <button\n mat-button\n (click)=\"onClose()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\" />\n {{ 'NODER.LABEL.CANCEL' | translate }}\n </button>\n <button\n mat-raised-button\n color=\"primary\"\n class=\"apply-btn\"\n [disabled]=\"form.invalid\"\n (click)=\"onApply()\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\" />\n {{ 'NODER.LABEL.APPLY' | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;height:300px;width:430px;overflow:hidden}:host ::ng-deep .mdc-text-field--outlined{--mdc-outlined-text-field-container-shape: 12px;height:48px}:host ::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-top:12px}.mat-mdc-dialog-title{font-weight:600;padding-top:5px}mat-form-field{width:100%}.mat-mdc-dialog-content{padding-top:10px!important;padding-bottom:0}.mat-mdc-dialog-actions{display:flex;justify-content:center;padding-top:5px;height:40px;margin-bottom:30px}.mat-mdc-dialog-actions button{width:30%;height:100%;letter-spacing:1px;border-radius:8px;text-transform:uppercase}.mat-mdc-dialog-actions button .apply-btn{font-weight:400}.mat-mdc-dialog-actions button .mat-icon{font-size:24px;height:24px}\n"] }]
17063
- }], ctorParameters: () => [{ type: i1$2.MatDialogRef }, { type: i2.FormBuilder }], propDecorators: { modal: [{
17864
+ }], ctorParameters: () => [{ type: i1$1.MatDialogRef }, { type: i2.FormBuilder }], propDecorators: { modal: [{
17064
17865
  type: HostBinding,
17065
17866
  args: ['class.noder-modal']
17066
17867
  }], onClose: [{
@@ -17111,7 +17912,7 @@ class ConfirmDialogComponent {
17111
17912
  onClose(status) {
17112
17913
  this.ref.close(status);
17113
17914
  }
17114
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ConfirmDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$2.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
17915
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ConfirmDialogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1$1.MatDialogRef }], target: i0.ɵɵFactoryTarget.Component }); }
17115
17916
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.5", type: ConfirmDialogComponent, isStandalone: true, selector: "app-nod-confirm-dialog", host: { properties: { "class.noder-modal": "this.modal" } }, ngImport: i0, template: "<p class=\"title\">{{ data.title ? data.title : ('NODER.LABEL.CONFIRMATION' | translate) }}</p>\n<div class=\"content\">\n <p>{{ data.message }}</p>\n</div>\n<div class=\"actions\">\n <button\n id=\"confirm-dialog-cancel-btn\"\n mat-button\n (click)=\"onClose(false)\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-cancel-thin\"></mat-icon>\n {{ data.cancel ? data.cancel : ('NODER.LABEL.CANCEL' | translate) }}\n </button>\n <button\n id=\"confirm-dialog-confirm-btn\"\n mat-raised-button\n class=\"delete-btn\"\n color=\"primary\"\n (click)=\"onClose(true)\">\n <mat-icon\n fontSet=\"noder-icon\"\n fontIcon=\"icon-done-thin\"></mat-icon>\n {{ data.confirm ? data.confirm : ('NODER.LABEL.DELETE' | translate) }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column;min-width:400px;max-width:440px;min-height:208px}.title{font-size:18px;font-weight:700;text-transform:capitalize;padding:24px 24px 12px;margin:0;border-bottom-width:1px;border-bottom-style:solid}.content{display:flex;flex:1;font-size:16px;line-height:20px;padding:20px 24px 16px}.content p{margin:0;overflow:hidden;text-overflow:ellipsis}.actions{display:flex;justify-content:center;margin-bottom:24px;gap:8px}.actions button{height:40px;width:120px;text-transform:uppercase}.actions button mat-icon{font-size:24px;height:24px;width:24px}.actions button .mat-button-toggle-label-content{padding:0 2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { 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: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3$1.TranslatePipe, name: "translate" }] }); }
17116
17917
  }
17117
17918
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImport: i0, type: ConfirmDialogComponent, decorators: [{
@@ -17120,11 +17921,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
17120
17921
  }], ctorParameters: () => [{ type: undefined, decorators: [{
17121
17922
  type: Inject,
17122
17923
  args: [MAT_DIALOG_DATA]
17123
- }] }, { type: i1$2.MatDialogRef }], propDecorators: { modal: [{
17924
+ }] }, { type: i1$1.MatDialogRef }], propDecorators: { modal: [{
17124
17925
  type: HostBinding,
17125
17926
  args: ['class.noder-modal']
17126
17927
  }] } });
17127
17928
 
17929
+ class SearchResultLocation {
17930
+ constructor(init) {
17931
+ Object.assign(this, init);
17932
+ }
17933
+ isEqual(other) {
17934
+ return this.width === other.width && this.height === other.height && this.top === other.top && this.left === other.left;
17935
+ }
17936
+ }
17937
+
17128
17938
  class DocumentNameModel {
17129
17939
  constructor(fields) {
17130
17940
  if (fields) {
@@ -17186,5 +17996,5 @@ class OperationModel {
17186
17996
  * Generated bundle index. Do not edit.
17187
17997
  */
17188
17998
 
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 };
17999
+ 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
18000
  //# sourceMappingURL=talrace-ngx-noder.mjs.map