devexpress-richedit 25.1.12 → 25.1.13

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 (53) hide show
  1. package/bin/gulpfile.js +6 -9
  2. package/bin/index-custom.js +1 -1
  3. package/bin/localization-builder.js +1 -1
  4. package/bin/nspell-index.js +1 -1
  5. package/bin/nspell.webpack.config.js +1 -1
  6. package/bin/webpack-externals.js +1 -1
  7. package/bin/webpack.config.js +1 -1
  8. package/dist/dx.richedit.d.ts +1 -1
  9. package/dist/dx.richedit.js +392 -185
  10. package/dist/dx.richedit.min.js +3 -3
  11. package/index.d.ts +1 -1
  12. package/index.js +1 -1
  13. package/lib/client/client-rich-edit.js +2 -2
  14. package/lib/client/document-processor/processor.d.ts +1 -0
  15. package/lib/client/document-processor/processor.js +11 -0
  16. package/lib/common/canvas/canvas-manager.d.ts +1 -1
  17. package/lib/common/canvas/canvas-manager.js +7 -3
  18. package/lib/common/canvas/double-tap-detector.d.ts +10 -0
  19. package/lib/common/canvas/double-tap-detector.js +28 -0
  20. package/lib/common/canvas/renderes/common/document-renderer.js +1 -1
  21. package/lib/common/commands/floating-objects/floating-object-drag-drop-change-position-command.js +5 -1
  22. package/lib/common/commands/text/clipboard-commands.d.ts +0 -1
  23. package/lib/common/commands/text/clipboard-commands.js +1 -5
  24. package/lib/common/commands/text/drag-drop-commands.js +2 -0
  25. package/lib/common/layout/main-structures/layout-row.d.ts +2 -1
  26. package/lib/common/layout/main-structures/layout-row.js +1 -0
  27. package/lib/common/layout-formatter/row/formatter.js +4 -1
  28. package/lib/common/layout-formatter/row/result.js +12 -4
  29. package/lib/common/layout-formatter/row/size-engine/row-height-calculator.js +20 -11
  30. package/lib/common/layout-formatter/row/size-engine/row-height-state.d.ts +2 -1
  31. package/lib/common/layout-formatter/row/size-engine/row-height-state.js +7 -2
  32. package/lib/common/layout-formatter/row/utils/line-spacing-calculator.d.ts +4 -3
  33. package/lib/common/layout-formatter/row/utils/line-spacing-calculator.js +16 -14
  34. package/lib/common/layout-formatter/table/borders/border-helper.js +4 -4
  35. package/lib/common/mouse-handler/mouse-handler/mouse-handler-default-state.d.ts +1 -0
  36. package/lib/common/mouse-handler/mouse-handler/mouse-handler-default-state.js +6 -4
  37. package/lib/common/ui/ruler/controls/divisions.d.ts +1 -0
  38. package/lib/common/ui/ruler/controls/divisions.js +4 -0
  39. package/lib/common/ui/ruler/controls/indent/first-line.d.ts +4 -2
  40. package/lib/common/ui/ruler/controls/indent/first-line.js +8 -0
  41. package/lib/common/ui/ruler/controls/indent/left.d.ts +4 -3
  42. package/lib/common/ui/ruler/controls/indent/left.js +10 -8
  43. package/lib/common/ui/ruler/controls/indent/right.d.ts +3 -1
  44. package/lib/common/ui/ruler/controls/indent/right.js +8 -0
  45. package/lib/common/ui/ruler/controls/tab/tab.d.ts +3 -0
  46. package/lib/common/ui/ruler/controls/tab/tab.js +12 -1
  47. package/lib/common/ui/ruler/controls/table.d.ts +4 -1
  48. package/lib/common/ui/ruler/controls/table.js +12 -0
  49. package/lib/common/ui/ruler/layout-recalculation-guard.d.ts +12 -0
  50. package/lib/common/ui/ruler/layout-recalculation-guard.js +23 -0
  51. package/lib/common/ui/ruler/manager.d.ts +3 -0
  52. package/lib/common/ui/ruler/manager.js +29 -0
  53. package/package.json +6 -4
@@ -6,12 +6,13 @@ export declare class RulerLeftIndentDragHandle extends RulerBaseIndentControl {
6
6
  private topElement;
7
7
  private bodyElement;
8
8
  private isActionLeftIndent;
9
- readonly leftCorrection: number;
10
- private readonly _heightOfProtrudingPart;
9
+ leftCorrection: number;
10
+ private _heightOfProtrudingPart;
11
11
  get heightOfProtrudingPart(): number;
12
12
  protected getRootClassName(): string;
13
13
  constructor(modelData: RulerModelData, controls: RulerControls);
14
- private adjustByTop;
14
+ recalculateLayout(): void;
15
+ private applyLayout;
15
16
  protected getModelState(): RulerModelState;
16
17
  updateView(): void;
17
18
  protected canHandle(source: HTMLElement): boolean;
@@ -25,23 +25,25 @@ export class RulerLeftIndentDragHandle extends RulerBaseIndentControl {
25
25
  this.rootElement.appendChild(this.topElement);
26
26
  this.rootElement.appendChild(this.bodyElement);
27
27
  this.controls.ruler.rootElement.appendChild(this.rootElement);
28
- this.adjustByTop();
28
+ this.bodyElement.title = this.modelData.titles.leftIndent;
29
+ this.topElement.title = this.modelData.titles.hangingIndent;
30
+ this.applyLayout();
31
+ }
32
+ recalculateLayout() {
33
+ this.applyLayout();
34
+ if (this.modelData.showLeftIndent)
35
+ this.rootElement.style.left = this.viewState + RULLER_NUMBER_CORRECTION - this.leftCorrection + "px";
36
+ }
37
+ applyLayout() {
29
38
  const mainElementWidth = this.topElement.offsetWidth;
30
39
  this.bodyElement.style.width = mainElementWidth + "px";
31
40
  const style = this.rootElement.style;
32
41
  style.height = SizeUtils.getOffsetHeight(this.topElement) + SizeUtils.getOffsetHeight(this.bodyElement) + "px";
33
42
  style.width = mainElementWidth + "px";
34
43
  style.marginTop = this.controls.divisions.height / 2 + "px";
35
- this.bodyElement.title = this.modelData.titles.leftIndent;
36
- this.topElement.title = this.modelData.titles.hangingIndent;
37
44
  this.leftCorrection = Math.round(SizeUtils.getOffsetWidth(this.rootElement) / 2);
38
45
  this._heightOfProtrudingPart = SizeUtils.getOffsetHeight(this.rootElement) - this.controls.divisions.height / 2;
39
46
  }
40
- adjustByTop() {
41
- const mainElementHeight = SizeUtils.getOffsetHeight(this.rootElement);
42
- const divisionsControlHeight = this.controls.divisions.height;
43
- this.rootElement.style.marginTop = (mainElementHeight - divisionsControlHeight) / 2 + "px";
44
- }
45
47
  getModelState() {
46
48
  const state = this.modelData.commandManager.getCommand(RichEditClientCommand.RulerParagraphLeftIndents).getState();
47
49
  return new RulerModelState(state.value.hanging, state.enabled, this.modelData);
@@ -4,9 +4,11 @@ import { RulerModelState } from '../base';
4
4
  import { RulerBaseIndentControl } from './base';
5
5
  export declare class RulerRightIndentDragHandle extends RulerBaseIndentControl {
6
6
  get viewStateRelativeLeft(): number;
7
- private readonly leftCorrection;
7
+ private leftCorrection;
8
8
  protected getRootClassName(): string;
9
9
  constructor(modelData: RulerModelData, controls: RulerControls);
10
+ recalculateLayout(): void;
11
+ private applyLayout;
10
12
  private adjustByTop;
11
13
  protected getModelState(): RulerModelState;
12
14
  updateView(): void;
@@ -19,6 +19,14 @@ export class RulerRightIndentDragHandle extends RulerBaseIndentControl {
19
19
  this.rootElement.innerHTML = template;
20
20
  this.rootElement.title = this.modelData.titles.rightIndent;
21
21
  this.controls.ruler.rootElement.appendChild(this.rootElement);
22
+ this.applyLayout();
23
+ }
24
+ recalculateLayout() {
25
+ this.applyLayout();
26
+ if (this.modelData.showRightIndent)
27
+ this.rootElement.style.right = this.viewState + RULLER_NUMBER_CORRECTION - this.leftCorrection + "px";
28
+ }
29
+ applyLayout() {
22
30
  this.adjustByTop();
23
31
  this.leftCorrection = Math.round(this.rootElement.offsetWidth / 2);
24
32
  }
@@ -21,6 +21,7 @@ export declare class RulerTabsControl extends RulerMultiControl<RulerTabControl,
21
21
  private tabAction;
22
22
  private newTab;
23
23
  private deleteTab;
24
+ recalculateSubControlLayouts(): void;
24
25
  protected getModelState(): RulerTabsControlState;
25
26
  updateView(): void;
26
27
  protected createSubControl(): RulerTabControl;
@@ -44,6 +45,8 @@ declare class RulerTabControl {
44
45
  protected controls: RulerControls;
45
46
  protected shadow: RulerShadow | null;
46
47
  constructor(modelData: RulerModelData, controls: RulerControls);
48
+ recalculateLayout(): void;
49
+ private applyLayout;
47
50
  dispose(): void;
48
51
  setVisible(visible: boolean): void;
49
52
  canHandle(source: HTMLElement): boolean;
@@ -50,6 +50,10 @@ export class RulerTabsControl extends RulerMultiControl {
50
50
  this.newTab = null;
51
51
  this.deleteTab = false;
52
52
  }
53
+ recalculateSubControlLayouts() {
54
+ for (const control of this.subControls)
55
+ control.recalculateLayout();
56
+ }
53
57
  getModelState() {
54
58
  this.modelData.showTabs = this.modelData.commandManager.getCommand(RichEditClientCommand.InsertTabRuler).getState().enabled;
55
59
  if (this.modelData.showTabs) {
@@ -197,7 +201,14 @@ class RulerTabControl {
197
201
  this.rootElement = DocumentRenderer.renderContainer(modelData.styles.tab.className + " " + RulerTabUtils.getSpriteClassName(this.viewState.align, modelData.styles));
198
202
  this.applyTemplate();
199
203
  controls.ruler.rootElement.appendChild(this.rootElement);
200
- this.rootElement.style.marginTop = (controls.divisions.height - this.rootElement.offsetHeight) + "px";
204
+ this.applyLayout();
205
+ }
206
+ recalculateLayout() {
207
+ this.applyLayout();
208
+ this.rootElement.style.left = this.viewState.position - this.leftCorrection + RULLER_NUMBER_CORRECTION + "px";
209
+ }
210
+ applyLayout() {
211
+ this.rootElement.style.marginTop = (this.controls.divisions.height - this.rootElement.offsetHeight) + "px";
201
212
  this.setCorrection();
202
213
  }
203
214
  dispose() {
@@ -18,6 +18,7 @@ export declare class RulerTableColumnViewState {
18
18
  clone(): RulerTableColumnViewState;
19
19
  }
20
20
  export declare class RulerTablesControl extends RulerMultiControl<RulerTableColumnState, RulerTableModelState, RulerTableColumnViewState> {
21
+ recalculateSubControlLayouts(): void;
21
22
  protected getModelState(): RulerTableModelState;
22
23
  updateView(): void;
23
24
  protected createSubControl(): RulerTableColumnState;
@@ -29,9 +30,11 @@ declare class RulerTableColumnState {
29
30
  private rootElement;
30
31
  private separatorElement;
31
32
  private viewState;
32
- private readonly corectionValue;
33
+ private corectionValue;
33
34
  private readonly controls;
34
35
  constructor(modelData: RulerModelData, controls: RulerControls);
36
+ recalculateLayout(): void;
37
+ private applyLayout;
35
38
  dispose(): void;
36
39
  showShadow(): void;
37
40
  hideShadow(): void;
@@ -35,6 +35,10 @@ export class RulerTableColumnViewState {
35
35
  }
36
36
  }
37
37
  export class RulerTablesControl extends RulerMultiControl {
38
+ recalculateSubControlLayouts() {
39
+ for (const control of this.subControls)
40
+ control.recalculateLayout();
41
+ }
38
42
  getModelState() {
39
43
  const state = this.modelData.commandManager.getCommand(RichEditClientCommand.RulerTableColumnSeparators).getState();
40
44
  return state.enabled ?
@@ -102,6 +106,14 @@ class RulerTableColumnState {
102
106
  this.separatorElement.innerHTML = template;
103
107
  this.rootElement.appendChild(this.separatorElement);
104
108
  controls.ruler.rootElement.appendChild(this.rootElement);
109
+ this.applyLayout();
110
+ }
111
+ recalculateLayout() {
112
+ this.applyLayout();
113
+ if (this.viewState)
114
+ this.separatorElement.style.left = this.viewState.rightMarginOfPrevColumn - this.corectionValue + "px";
115
+ }
116
+ applyLayout() {
105
117
  this.corectionValue = Math.floor(this.separatorElement.offsetWidth / 2);
106
118
  }
107
119
  dispose() {
@@ -0,0 +1,12 @@
1
+ export declare const DEFAULT_SVG_SIZE = 300;
2
+ export interface LayoutRecalculationGuardTarget {
3
+ readonly rootElement: HTMLElement;
4
+ }
5
+ export interface LayoutRecalculationGuardOptions {
6
+ divisions: LayoutRecalculationGuardTarget;
7
+ leftIndent: LayoutRecalculationGuardTarget;
8
+ divisionsHeight: number;
9
+ leftIndentWidth: number;
10
+ onHealthy: () => void;
11
+ }
12
+ export declare function installLayoutRecalculationGuard(options: LayoutRecalculationGuardOptions): ResizeObserver | null;
@@ -0,0 +1,23 @@
1
+ export const DEFAULT_SVG_SIZE = 300;
2
+ export function installLayoutRecalculationGuard(options) {
3
+ const { divisions, leftIndent, divisionsHeight, leftIndentWidth, onHealthy } = options;
4
+ const isSuspicious = divisionsHeight === 0 || leftIndentWidth >= DEFAULT_SVG_SIZE;
5
+ if (!isSuspicious)
6
+ return null;
7
+ const targets = [divisions.rootElement, leftIndent.rootElement];
8
+ const initialSizes = targets.map(el => ({ width: el.offsetWidth, height: el.offsetHeight }));
9
+ const observer = new ResizeObserver(() => {
10
+ const hasRealChange = targets.some((el, i) => {
11
+ const w = el.offsetWidth;
12
+ const h = el.offsetHeight;
13
+ const changed = w !== initialSizes[i].width || h !== initialSizes[i].height;
14
+ return changed && (w > 0 || h > 0);
15
+ });
16
+ if (!hasRealChange)
17
+ return;
18
+ observer.disconnect();
19
+ onHealthy();
20
+ });
21
+ targets.forEach(el => observer.observe(el));
22
+ return observer;
23
+ }
@@ -37,9 +37,12 @@ export declare class RulerControls {
37
37
  readonly modelData: RulerModelData;
38
38
  readonly divisionInfo: DivisionInfo;
39
39
  private moveStepSize;
40
+ private layoutRecalculationObserver;
40
41
  get paragraphLeftPosition(): number;
41
42
  get paragraphRightPosition(): number;
42
43
  constructor(canvas: HTMLDivElement, modelData: RulerModelData);
44
+ private setupLayoutRecalculationGuard;
45
+ recalculateLayout(): void;
43
46
  calculateMoveStepSize(): void;
44
47
  updateZoomLevel(): void;
45
48
  dispose(): void;
@@ -19,6 +19,7 @@ import { RulerWrapper } from './controls/wrapper';
19
19
  import { RulerMouseEventsManager } from './events/mouse';
20
20
  import { RulerViewElementScrollManager } from './events/scroll';
21
21
  import { RulerMouseHandler } from './mouse-handler';
22
+ import { installLayoutRecalculationGuard } from './layout-recalculation-guard';
22
23
  export class RulerControls {
23
24
  get paragraphLeftPosition() {
24
25
  let pos = this.leftMargin.currModelState.modelValue + this.columns.currModelState.activeColumn.leftPos;
@@ -41,6 +42,7 @@ export class RulerControls {
41
42
  constructor(canvas, modelData) {
42
43
  this.mouseEventsManager = new RulerMouseEventsManager();
43
44
  this.viewElementScrollManager = new RulerViewElementScrollManager();
45
+ this.layoutRecalculationObserver = null;
44
46
  this.canvas = canvas;
45
47
  this.modelData = modelData;
46
48
  this.divisionInfo = DivisionInfo.create(modelData.unitType, this.modelData.innerClientProperties.viewsSettings);
@@ -64,6 +66,29 @@ export class RulerControls {
64
66
  this.mouseHandler = new RulerMouseHandler(modelData, this);
65
67
  this.mouseEventsManager.addListener(this.mouseHandler);
66
68
  this.viewElementScrollManager.addListener(this.ruler, this.canvas);
69
+ this.setupLayoutRecalculationGuard();
70
+ }
71
+ setupLayoutRecalculationGuard() {
72
+ this.layoutRecalculationObserver = installLayoutRecalculationGuard({
73
+ divisions: this.divisions,
74
+ leftIndent: this.leftIndent,
75
+ divisionsHeight: this.divisions.height,
76
+ leftIndentWidth: this.leftIndent.leftCorrection * 2,
77
+ onHealthy: () => {
78
+ this.layoutRecalculationObserver = null;
79
+ this.recalculateLayout();
80
+ },
81
+ });
82
+ }
83
+ recalculateLayout() {
84
+ this.divisions.recalculateLayout();
85
+ this.leftIndent.recalculateLayout();
86
+ this.firstLineIndent.recalculateLayout();
87
+ this.rightIndent.recalculateLayout();
88
+ this.tabs.recalculateSubControlLayouts();
89
+ this.tables.recalculateSubControlLayouts();
90
+ this.ruler.init();
91
+ this.tabTypeBox.adjust();
67
92
  }
68
93
  calculateMoveStepSize() {
69
94
  this.moveStepSize = this.modelData.unitType == RichEditUnit.Inch ? this.divisionInfo.stepSize / 2 : this.divisionInfo.stepSize;
@@ -72,6 +97,10 @@ export class RulerControls {
72
97
  this.divisionInfo.updateZoomLevel();
73
98
  }
74
99
  dispose() {
100
+ if (this.layoutRecalculationObserver) {
101
+ this.layoutRecalculationObserver.disconnect();
102
+ this.layoutRecalculationObserver = null;
103
+ }
75
104
  this.lineControl.dispose();
76
105
  this.wrapper.dispose();
77
106
  this.ruler.dispose();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devexpress-richedit",
3
- "version": "25.1.12",
3
+ "version": "25.1.13",
4
4
  "homepage": "https://www.devexpress.com/",
5
5
  "bugs": "https://www.devexpress.com/support/",
6
6
  "author": "Developer Express Inc.",
@@ -11,19 +11,21 @@
11
11
  "build-nspell": "webpack --mode production --config=bin/nspell.webpack.config.js"
12
12
  },
13
13
  "peerDependencies": {
14
- "devextreme": "25.1.12",
15
- "devextreme-dist": "25.1.12"
14
+ "devextreme": "25.1.13",
15
+ "devextreme-dist": "25.1.13"
16
16
  },
17
17
  "devDependencies": {
18
18
  "dictionary-en": "3.2.0",
19
19
  "gulp": "^5.0.1",
20
+ "gulp-concat": "^2.6.1",
21
+ "gulp-clean-css": "^4.3.0",
20
22
  "nspell": "2.1.5",
21
23
  "terser-webpack-plugin": "5.3.10",
22
24
  "webpack": "5.89.0",
23
25
  "webpack-cli": "5.1.4"
24
26
  },
25
27
  "dependencies": {
26
- "@devexpress/utils": "^2.1.1",
28
+ "@devexpress/utils": "^2.1.2",
27
29
  "@types/pdfkit": "0.13.3",
28
30
  "jszip": "~3.10.1",
29
31
  "pdfkit": "0.14.0",