@doxi/core 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/collab/port.d.ts +46 -0
- package/dist/collab/port.d.ts.map +1 -0
- package/dist/collab/port.js +11 -0
- package/dist/collab/port.js.map +1 -0
- package/dist/commands/block-commands.d.ts +62 -0
- package/dist/commands/block-commands.d.ts.map +1 -0
- package/dist/commands/block-commands.js +208 -0
- package/dist/commands/block-commands.js.map +1 -0
- package/dist/commands/command.d.ts +13 -0
- package/dist/commands/command.d.ts.map +1 -0
- package/dist/commands/command.js +13 -0
- package/dist/commands/command.js.map +1 -0
- package/dist/commands/edit-commands.d.ts +5 -0
- package/dist/commands/edit-commands.d.ts.map +1 -0
- package/dist/commands/edit-commands.js +147 -0
- package/dist/commands/edit-commands.js.map +1 -0
- package/dist/commands/image-commands.d.ts +31 -0
- package/dist/commands/image-commands.d.ts.map +1 -0
- package/dist/commands/image-commands.js +130 -0
- package/dist/commands/image-commands.js.map +1 -0
- package/dist/commands/index.d.ts +11 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +11 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/keymap.d.ts +34 -0
- package/dist/commands/keymap.d.ts.map +1 -0
- package/dist/commands/keymap.js +84 -0
- package/dist/commands/keymap.js.map +1 -0
- package/dist/commands/link-commands.d.ts +54 -0
- package/dist/commands/link-commands.d.ts.map +1 -0
- package/dist/commands/link-commands.js +151 -0
- package/dist/commands/link-commands.js.map +1 -0
- package/dist/commands/list-commands.d.ts +42 -0
- package/dist/commands/list-commands.d.ts.map +1 -0
- package/dist/commands/list-commands.js +316 -0
- package/dist/commands/list-commands.js.map +1 -0
- package/dist/commands/mark-commands.d.ts +53 -0
- package/dist/commands/mark-commands.d.ts.map +1 -0
- package/dist/commands/mark-commands.js +181 -0
- package/dist/commands/mark-commands.js.map +1 -0
- package/dist/commands/selection-commands.d.ts +3 -0
- package/dist/commands/selection-commands.d.ts.map +1 -0
- package/dist/commands/selection-commands.js +11 -0
- package/dist/commands/selection-commands.js.map +1 -0
- package/dist/commands/table-commands.d.ts +109 -0
- package/dist/commands/table-commands.d.ts.map +1 -0
- package/dist/commands/table-commands.js +884 -0
- package/dist/commands/table-commands.js.map +1 -0
- package/dist/history/history.d.ts +40 -0
- package/dist/history/history.d.ts.map +1 -0
- package/dist/history/history.js +139 -0
- package/dist/history/history.js.map +1 -0
- package/dist/history/index.d.ts +2 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +2 -0
- package/dist/history/index.js.map +1 -0
- package/dist/html/index.d.ts +3 -0
- package/dist/html/index.d.ts.map +1 -0
- package/dist/html/index.js +3 -0
- package/dist/html/index.js.map +1 -0
- package/dist/html/parse.d.ts +4 -0
- package/dist/html/parse.d.ts.map +1 -0
- package/dist/html/parse.js +0 -0
- package/dist/html/parse.js.map +1 -0
- package/dist/html/serialize.d.ts +4 -0
- package/dist/html/serialize.d.ts.map +1 -0
- package/dist/html/serialize.js +75 -0
- package/dist/html/serialize.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/index.d.ts +6 -0
- package/dist/layout/index.d.ts.map +1 -0
- package/dist/layout/index.js +6 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/layout/layout-engine.d.ts +20 -0
- package/dist/layout/layout-engine.d.ts.map +1 -0
- package/dist/layout/layout-engine.js +198 -0
- package/dist/layout/layout-engine.js.map +1 -0
- package/dist/layout/measure.d.ts +9 -0
- package/dist/layout/measure.d.ts.map +1 -0
- package/dist/layout/measure.js +37 -0
- package/dist/layout/measure.js.map +1 -0
- package/dist/layout/split-paragraph.d.ts +28 -0
- package/dist/layout/split-paragraph.d.ts.map +1 -0
- package/dist/layout/split-paragraph.js +122 -0
- package/dist/layout/split-paragraph.js.map +1 -0
- package/dist/layout/split-table.d.ts +46 -0
- package/dist/layout/split-table.d.ts.map +1 -0
- package/dist/layout/split-table.js +84 -0
- package/dist/layout/split-table.js.map +1 -0
- package/dist/layout/types.d.ts +73 -0
- package/dist/layout/types.d.ts.map +1 -0
- package/dist/layout/types.js +36 -0
- package/dist/layout/types.js.map +1 -0
- package/dist/layout/widow-orphan.d.ts +15 -0
- package/dist/layout/widow-orphan.d.ts.map +1 -0
- package/dist/layout/widow-orphan.js +14 -0
- package/dist/layout/widow-orphan.js.map +1 -0
- package/dist/model/content-expr.d.ts +32 -0
- package/dist/model/content-expr.d.ts.map +1 -0
- package/dist/model/content-expr.js +106 -0
- package/dist/model/content-expr.js.map +1 -0
- package/dist/model/fragment.d.ts +17 -0
- package/dist/model/fragment.d.ts.map +1 -0
- package/dist/model/fragment.js +44 -0
- package/dist/model/fragment.js.map +1 -0
- package/dist/model/index.d.ts +10 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/index.js +10 -0
- package/dist/model/index.js.map +1 -0
- package/dist/model/mark.d.ts +35 -0
- package/dist/model/mark.d.ts.map +1 -0
- package/dist/model/mark.js +89 -0
- package/dist/model/mark.js.map +1 -0
- package/dist/model/node-type.d.ts +36 -0
- package/dist/model/node-type.d.ts.map +1 -0
- package/dist/model/node-type.js +14 -0
- package/dist/model/node-type.js.map +1 -0
- package/dist/model/node.d.ts +36 -0
- package/dist/model/node.d.ts.map +1 -0
- package/dist/model/node.js +192 -0
- package/dist/model/node.js.map +1 -0
- package/dist/model/position.d.ts +66 -0
- package/dist/model/position.d.ts.map +1 -0
- package/dist/model/position.js +158 -0
- package/dist/model/position.js.map +1 -0
- package/dist/model/schema.d.ts +28 -0
- package/dist/model/schema.d.ts.map +1 -0
- package/dist/model/schema.js +195 -0
- package/dist/model/schema.js.map +1 -0
- package/dist/model/slice.d.ts +26 -0
- package/dist/model/slice.d.ts.map +1 -0
- package/dist/model/slice.js +56 -0
- package/dist/model/slice.js.map +1 -0
- package/dist/model/table-grid.d.ts +71 -0
- package/dist/model/table-grid.d.ts.map +1 -0
- package/dist/model/table-grid.js +130 -0
- package/dist/model/table-grid.js.map +1 -0
- package/dist/plugin/index.d.ts +3 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +3 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/plugin-key.d.ts +13 -0
- package/dist/plugin/plugin-key.d.ts.map +1 -0
- package/dist/plugin/plugin-key.js +13 -0
- package/dist/plugin/plugin-key.js.map +1 -0
- package/dist/plugin/plugin-state.d.ts +2 -0
- package/dist/plugin/plugin-state.d.ts.map +1 -0
- package/dist/plugin/plugin-state.js +3 -0
- package/dist/plugin/plugin-state.js.map +1 -0
- package/dist/plugin/plugin.d.ts +39 -0
- package/dist/plugin/plugin.d.ts.map +1 -0
- package/dist/plugin/plugin.js +10 -0
- package/dist/plugin/plugin.js.map +1 -0
- package/dist/schema/default.d.ts +163 -0
- package/dist/schema/default.d.ts.map +1 -0
- package/dist/schema/default.js +94 -0
- package/dist/schema/default.js.map +1 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/serialize/index.d.ts +2 -0
- package/dist/serialize/index.d.ts.map +1 -0
- package/dist/serialize/index.js +2 -0
- package/dist/serialize/index.js.map +1 -0
- package/dist/serialize/json.d.ts +15 -0
- package/dist/serialize/json.d.ts.map +1 -0
- package/dist/serialize/json.js +23 -0
- package/dist/serialize/json.js.map +1 -0
- package/dist/state/all-selection.d.ts +11 -0
- package/dist/state/all-selection.d.ts.map +1 -0
- package/dist/state/all-selection.js +17 -0
- package/dist/state/all-selection.js.map +1 -0
- package/dist/state/cell-selection.d.ts +30 -0
- package/dist/state/cell-selection.d.ts.map +1 -0
- package/dist/state/cell-selection.js +38 -0
- package/dist/state/cell-selection.js.map +1 -0
- package/dist/state/editor-state.d.ts +46 -0
- package/dist/state/editor-state.d.ts.map +1 -0
- package/dist/state/editor-state.js +211 -0
- package/dist/state/editor-state.js.map +1 -0
- package/dist/state/index.d.ts +7 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +7 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/node-selection.d.ts +16 -0
- package/dist/state/node-selection.d.ts.map +1 -0
- package/dist/state/node-selection.js +51 -0
- package/dist/state/node-selection.js.map +1 -0
- package/dist/state/selection.d.ts +29 -0
- package/dist/state/selection.d.ts.map +1 -0
- package/dist/state/selection.js +24 -0
- package/dist/state/selection.js.map +1 -0
- package/dist/state/text-selection.d.ts +10 -0
- package/dist/state/text-selection.d.ts.map +1 -0
- package/dist/state/text-selection.js +26 -0
- package/dist/state/text-selection.js.map +1 -0
- package/dist/transform/attr-step.d.ts +16 -0
- package/dist/transform/attr-step.d.ts.map +1 -0
- package/dist/transform/attr-step.js +98 -0
- package/dist/transform/attr-step.js.map +1 -0
- package/dist/transform/index.d.ts +10 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +10 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/transform/mapping.d.ts +44 -0
- package/dist/transform/mapping.d.ts.map +1 -0
- package/dist/transform/mapping.js +101 -0
- package/dist/transform/mapping.js.map +1 -0
- package/dist/transform/mark-step.d.ts +27 -0
- package/dist/transform/mark-step.d.ts.map +1 -0
- package/dist/transform/mark-step.js +146 -0
- package/dist/transform/mark-step.js.map +1 -0
- package/dist/transform/replace-around-step.d.ts +35 -0
- package/dist/transform/replace-around-step.d.ts.map +1 -0
- package/dist/transform/replace-around-step.js +144 -0
- package/dist/transform/replace-around-step.js.map +1 -0
- package/dist/transform/replace-step.d.ts +17 -0
- package/dist/transform/replace-step.d.ts.map +1 -0
- package/dist/transform/replace-step.js +72 -0
- package/dist/transform/replace-step.js.map +1 -0
- package/dist/transform/replace.d.ts +18 -0
- package/dist/transform/replace.d.ts.map +1 -0
- package/dist/transform/replace.js +132 -0
- package/dist/transform/replace.js.map +1 -0
- package/dist/transform/set-page-meta-step.d.ts +42 -0
- package/dist/transform/set-page-meta-step.d.ts.map +1 -0
- package/dist/transform/set-page-meta-step.js +75 -0
- package/dist/transform/set-page-meta-step.js.map +1 -0
- package/dist/transform/step.d.ts +34 -0
- package/dist/transform/step.d.ts.map +1 -0
- package/dist/transform/step.js +23 -0
- package/dist/transform/step.js.map +1 -0
- package/dist/transform/transaction.d.ts +20 -0
- package/dist/transform/transaction.d.ts.map +1 -0
- package/dist/transform/transaction.js +38 -0
- package/dist/transform/transaction.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +5 -0
- package/dist/version.js.map +1 -0
- package/dist/view/cell-drag.d.ts +33 -0
- package/dist/view/cell-drag.d.ts.map +1 -0
- package/dist/view/cell-drag.js +177 -0
- package/dist/view/cell-drag.js.map +1 -0
- package/dist/view/clipboard.d.ts +5 -0
- package/dist/view/clipboard.d.ts.map +1 -0
- package/dist/view/clipboard.js +97 -0
- package/dist/view/clipboard.js.map +1 -0
- package/dist/view/default-renderer.d.ts +3 -0
- package/dist/view/default-renderer.d.ts.map +1 -0
- package/dist/view/default-renderer.js +142 -0
- package/dist/view/default-renderer.js.map +1 -0
- package/dist/view/dom-spec.d.ts +11 -0
- package/dist/view/dom-spec.d.ts.map +1 -0
- package/dist/view/dom-spec.js +32 -0
- package/dist/view/dom-spec.js.map +1 -0
- package/dist/view/editor-view.d.ts +55 -0
- package/dist/view/editor-view.d.ts.map +1 -0
- package/dist/view/editor-view.js +143 -0
- package/dist/view/editor-view.js.map +1 -0
- package/dist/view/image-resize.d.ts +37 -0
- package/dist/view/image-resize.d.ts.map +1 -0
- package/dist/view/image-resize.js +191 -0
- package/dist/view/image-resize.js.map +1 -0
- package/dist/view/index.d.ts +15 -0
- package/dist/view/index.d.ts.map +1 -0
- package/dist/view/index.js +15 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/input-pipeline.d.ts +24 -0
- package/dist/view/input-pipeline.d.ts.map +1 -0
- package/dist/view/input-pipeline.js +226 -0
- package/dist/view/input-pipeline.js.map +1 -0
- package/dist/view/mutation-observer.d.ts +17 -0
- package/dist/view/mutation-observer.d.ts.map +1 -0
- package/dist/view/mutation-observer.js +62 -0
- package/dist/view/mutation-observer.js.map +1 -0
- package/dist/view/page-slots.d.ts +56 -0
- package/dist/view/page-slots.d.ts.map +1 -0
- package/dist/view/page-slots.js +230 -0
- package/dist/view/page-slots.js.map +1 -0
- package/dist/view/paginator.d.ts +17 -0
- package/dist/view/paginator.d.ts.map +1 -0
- package/dist/view/paginator.js +93 -0
- package/dist/view/paginator.js.map +1 -0
- package/dist/view/print.d.ts +42 -0
- package/dist/view/print.d.ts.map +1 -0
- package/dist/view/print.js +70 -0
- package/dist/view/print.js.map +1 -0
- package/dist/view/reconcile.d.ts +16 -0
- package/dist/view/reconcile.d.ts.map +1 -0
- package/dist/view/reconcile.js +158 -0
- package/dist/view/reconcile.js.map +1 -0
- package/dist/view/renderer.d.ts +31 -0
- package/dist/view/renderer.d.ts.map +1 -0
- package/dist/view/renderer.js +89 -0
- package/dist/view/renderer.js.map +1 -0
- package/dist/view/selection-sync.d.ts +35 -0
- package/dist/view/selection-sync.d.ts.map +1 -0
- package/dist/view/selection-sync.js +324 -0
- package/dist/view/selection-sync.js.map +1 -0
- package/dist/view/table-resize.d.ts +41 -0
- package/dist/view/table-resize.d.ts.map +1 -0
- package/dist/view/table-resize.js +216 -0
- package/dist/view/table-resize.js.map +1 -0
- package/package.json +93 -0
- package/styles/base.css +269 -0
- package/styles/dark.css +36 -0
- package/styles/light.css +13 -0
- package/styles/page.css +93 -0
- package/styles/print-a4.css +87 -0
- package/styles/print.css +88 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { HOLE } from './dom-spec.js';
|
|
2
|
+
import { Renderer } from './renderer.js';
|
|
3
|
+
const docRenderer = () => ['div', { class: 'dx-doc' }, HOLE];
|
|
4
|
+
/** Compose inline style fragments for align + lineHeight block attrs. */
|
|
5
|
+
function blockStyleFromAttrs(attrs) {
|
|
6
|
+
const parts = [];
|
|
7
|
+
const align = attrs.align;
|
|
8
|
+
if (align === 'left' || align === 'center' || align === 'right' || align === 'justify') {
|
|
9
|
+
parts.push(`text-align:${align}`);
|
|
10
|
+
}
|
|
11
|
+
const lineHeight = attrs.lineHeight;
|
|
12
|
+
if (typeof lineHeight === 'number' && lineHeight > 0) {
|
|
13
|
+
parts.push(`line-height:${lineHeight}`);
|
|
14
|
+
}
|
|
15
|
+
return parts.length > 0 ? parts.join(';') : undefined;
|
|
16
|
+
}
|
|
17
|
+
const paragraphRenderer = (node) => {
|
|
18
|
+
const style = blockStyleFromAttrs(node.attrs);
|
|
19
|
+
return ['p', style ? { class: 'dx-paragraph', style } : { class: 'dx-paragraph' }, HOLE];
|
|
20
|
+
};
|
|
21
|
+
const headingRenderer = (node) => {
|
|
22
|
+
const level = Math.min(6, Math.max(1, node.attrs.level ?? 1));
|
|
23
|
+
const style = blockStyleFromAttrs(node.attrs);
|
|
24
|
+
return [
|
|
25
|
+
`h${level}`,
|
|
26
|
+
style ? { class: 'dx-heading', style } : { class: 'dx-heading' },
|
|
27
|
+
HOLE,
|
|
28
|
+
];
|
|
29
|
+
};
|
|
30
|
+
const blockquoteRenderer = () => ['blockquote', { class: 'dx-blockquote' }, HOLE];
|
|
31
|
+
const listRenderer = (node) => {
|
|
32
|
+
const tag = node.attrs.ordered ? 'ol' : 'ul';
|
|
33
|
+
return [tag, { class: 'dx-list' }, HOLE];
|
|
34
|
+
};
|
|
35
|
+
const listItemRenderer = () => ['li', { class: 'dx-list-item' }, HOLE];
|
|
36
|
+
const hrRenderer = () => ['hr', { class: 'dx-hr' }];
|
|
37
|
+
const pageBreakRenderer = () => ['div', { class: 'dx-page-break' }];
|
|
38
|
+
const tableRenderer = () => ['table', { class: 'dx-table' }, ['tbody', {}, HOLE]];
|
|
39
|
+
const tableRowRenderer = (node) => {
|
|
40
|
+
const header = node.attrs.header;
|
|
41
|
+
const cls = header ? 'dx-table-row is-header' : 'dx-table-row';
|
|
42
|
+
return ['tr', { class: cls }, HOLE];
|
|
43
|
+
};
|
|
44
|
+
const tableCellRenderer = (node) => {
|
|
45
|
+
const attrs = { class: 'dx-table-cell' };
|
|
46
|
+
const w = node.attrs.widthPx;
|
|
47
|
+
const bg = node.attrs.background;
|
|
48
|
+
const style = [];
|
|
49
|
+
if (typeof w === 'number')
|
|
50
|
+
style.push(`width:${w}px`);
|
|
51
|
+
if (typeof bg === 'string' && bg.length > 0)
|
|
52
|
+
style.push(`background:${bg}`);
|
|
53
|
+
if (style.length)
|
|
54
|
+
attrs.style = style.join(';');
|
|
55
|
+
// Emit colspan/rowspan ONLY when > 1 to keep the DOM clean.
|
|
56
|
+
const colspan = node.attrs.colspan;
|
|
57
|
+
const rowspan = node.attrs.rowspan;
|
|
58
|
+
if (typeof colspan === 'number' && colspan > 1)
|
|
59
|
+
attrs.colspan = String(colspan);
|
|
60
|
+
if (typeof rowspan === 'number' && rowspan > 1)
|
|
61
|
+
attrs.rowspan = String(rowspan);
|
|
62
|
+
return ['td', attrs, HOLE];
|
|
63
|
+
};
|
|
64
|
+
const textRenderer = (node) => node.text;
|
|
65
|
+
const imageRenderer = (node) => {
|
|
66
|
+
const attrs = {
|
|
67
|
+
class: 'dx-image',
|
|
68
|
+
src: node.attrs.src ?? '',
|
|
69
|
+
alt: node.attrs.alt ?? '',
|
|
70
|
+
// tabindex=-1 keeps the image out of the natural tab order while letting
|
|
71
|
+
// selection painting target it without the browser auto-focusing the <img>.
|
|
72
|
+
tabindex: -1,
|
|
73
|
+
};
|
|
74
|
+
const widthPx = node.attrs.widthPx;
|
|
75
|
+
if (typeof widthPx === 'number') {
|
|
76
|
+
attrs.style = `width:${widthPx}px`;
|
|
77
|
+
}
|
|
78
|
+
return ['img', attrs];
|
|
79
|
+
};
|
|
80
|
+
const pageVarRenderer = (node) => {
|
|
81
|
+
// Default ('#') is the placeholder seen when a page_var renders OUTSIDE a
|
|
82
|
+
// header/footer slot (e.g. directly in the doc, or via standalone Renderer
|
|
83
|
+
// tests). The slot controller in `installPageSlots` overrides per-page with
|
|
84
|
+
// the actual page number / total page count.
|
|
85
|
+
const kind = node.attrs.kind ?? '';
|
|
86
|
+
return ['span', { class: 'dx-page-var', 'data-kind': kind }, '#'];
|
|
87
|
+
};
|
|
88
|
+
const boldRenderer = () => ['strong', { class: 'dx-bold' }, HOLE];
|
|
89
|
+
const italicRenderer = () => ['em', { class: 'dx-italic' }, HOLE];
|
|
90
|
+
const underlineRenderer = () => ['u', { class: 'dx-underline' }, HOLE];
|
|
91
|
+
const linkRenderer = (mark) => [
|
|
92
|
+
'a',
|
|
93
|
+
{
|
|
94
|
+
class: 'dx-link',
|
|
95
|
+
href: mark.attrs.href ?? '',
|
|
96
|
+
rel: 'noopener',
|
|
97
|
+
},
|
|
98
|
+
HOLE,
|
|
99
|
+
];
|
|
100
|
+
const colorRenderer = (mark) => [
|
|
101
|
+
'span',
|
|
102
|
+
{ class: 'dx-color', style: `color:${mark.attrs.value ?? 'inherit'}` },
|
|
103
|
+
HOLE,
|
|
104
|
+
];
|
|
105
|
+
const fontSizeRenderer = (mark) => [
|
|
106
|
+
'span',
|
|
107
|
+
{ class: 'dx-font-size', style: `font-size:${mark.attrs.px ?? 16}px` },
|
|
108
|
+
HOLE,
|
|
109
|
+
];
|
|
110
|
+
const fontFamilyRenderer = (mark) => [
|
|
111
|
+
'span',
|
|
112
|
+
{ class: 'dx-font-family', style: `font-family:${mark.attrs.name ?? 'inherit'}` },
|
|
113
|
+
HOLE,
|
|
114
|
+
];
|
|
115
|
+
export const defaultRenderer = new Renderer({
|
|
116
|
+
nodes: {
|
|
117
|
+
doc: docRenderer,
|
|
118
|
+
paragraph: paragraphRenderer,
|
|
119
|
+
heading: headingRenderer,
|
|
120
|
+
blockquote: blockquoteRenderer,
|
|
121
|
+
list: listRenderer,
|
|
122
|
+
list_item: listItemRenderer,
|
|
123
|
+
hr: hrRenderer,
|
|
124
|
+
page_break: pageBreakRenderer,
|
|
125
|
+
table: tableRenderer,
|
|
126
|
+
table_row: tableRowRenderer,
|
|
127
|
+
table_cell: tableCellRenderer,
|
|
128
|
+
text: textRenderer,
|
|
129
|
+
image: imageRenderer,
|
|
130
|
+
page_var: pageVarRenderer,
|
|
131
|
+
},
|
|
132
|
+
marks: {
|
|
133
|
+
bold: boldRenderer,
|
|
134
|
+
italic: italicRenderer,
|
|
135
|
+
underline: underlineRenderer,
|
|
136
|
+
link: linkRenderer,
|
|
137
|
+
color: colorRenderer,
|
|
138
|
+
font_size: fontSizeRenderer,
|
|
139
|
+
font_family: fontFamilyRenderer,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=default-renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-renderer.js","sourceRoot":"","sources":["../../src/view/default-renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type Attrs = Readonly<Record<string, string | number | boolean | null | undefined>> | null;
|
|
2
|
+
export interface DOMSpecElement extends ReadonlyArray<unknown> {
|
|
3
|
+
readonly 0: string;
|
|
4
|
+
readonly 1?: Attrs;
|
|
5
|
+
readonly [index: number]: string | Attrs | DOMSpec | 0 | undefined;
|
|
6
|
+
}
|
|
7
|
+
export type DOMSpec = string | DOMSpecElement;
|
|
8
|
+
export declare const HOLE: 0;
|
|
9
|
+
export declare const HOLE_MARKER_ATTR = "data-dx-content-hole";
|
|
10
|
+
export declare function renderSpec(doc: Document, spec: DOMSpec): Node;
|
|
11
|
+
//# sourceMappingURL=dom-spec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-spec.d.ts","sourceRoot":"","sources":["../../src/view/dom-spec.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,GAAG,IAAI,CAAA;AAKjG,MAAM,WAAW,cAAe,SAAQ,aAAa,CAAC,OAAO,CAAC;IAC5D,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,CAAA;IAClB,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,CAAC,GAAG,SAAS,CAAA;CACnE;AACD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,cAAc,CAAA;AAE7C,eAAO,MAAM,IAAI,GAAa,CAAA;AAC9B,eAAO,MAAM,gBAAgB,yBAAyB,CAAA;AAEtD,wBAAgB,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAa7D"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const HOLE = 0;
|
|
2
|
+
export const HOLE_MARKER_ATTR = 'data-dx-content-hole';
|
|
3
|
+
export function renderSpec(doc, spec) {
|
|
4
|
+
if (typeof spec === 'string')
|
|
5
|
+
return doc.createTextNode(spec);
|
|
6
|
+
const [tag, attrs, ...children] = spec;
|
|
7
|
+
const el = doc.createElement(tag);
|
|
8
|
+
if (attrs)
|
|
9
|
+
applyAttrs(el, attrs);
|
|
10
|
+
for (const child of children) {
|
|
11
|
+
if (child === HOLE) {
|
|
12
|
+
el.setAttribute(HOLE_MARKER_ATTR, '');
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
el.appendChild(renderSpec(doc, child));
|
|
16
|
+
}
|
|
17
|
+
return el;
|
|
18
|
+
}
|
|
19
|
+
function applyAttrs(el, attrs) {
|
|
20
|
+
for (const name of Object.keys(attrs)) {
|
|
21
|
+
const value = attrs[name];
|
|
22
|
+
if (value === null || value === undefined || value === false)
|
|
23
|
+
continue;
|
|
24
|
+
if (value === true) {
|
|
25
|
+
el.setAttribute(name, '');
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
el.setAttribute(name, String(value));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=dom-spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-spec.js","sourceRoot":"","sources":["../../src/view/dom-spec.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,IAAI,GAAG,CAAU,CAAA;AAC9B,MAAM,CAAC,MAAM,gBAAgB,GAAG,sBAAsB,CAAA;AAEtD,MAAM,UAAU,UAAU,CAAC,GAAa,EAAE,IAAa;IACrD,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;IAC7D,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAA;IACtC,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAA;IACjC,IAAI,KAAK;QAAE,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAA;IAChC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAA;YACrC,SAAQ;QACV,CAAC;QACD,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,EAAE,KAAgB,CAAC,CAAC,CAAA;IACnD,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,SAAS,UAAU,CAAC,EAAW,EAAE,KAAyB;IACxD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAA;QACzB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;YAAE,SAAQ;QACtE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC3B,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACtC,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type PageConfig } from '../layout/index.js';
|
|
2
|
+
import type { EditorState } from '../state/editor-state.js';
|
|
3
|
+
import type { Transaction } from '../transform/transaction.js';
|
|
4
|
+
import { type Renderer } from './renderer.js';
|
|
5
|
+
export interface EditorViewProps {
|
|
6
|
+
readonly state: EditorState;
|
|
7
|
+
readonly renderer: Renderer;
|
|
8
|
+
/** Called when the view wants to commit a Transaction. If omitted, view.dispatch throws. */
|
|
9
|
+
dispatchTransaction?(tr: Transaction): void;
|
|
10
|
+
/**
|
|
11
|
+
* Whether the editor root sets contenteditable=true. Default true.
|
|
12
|
+
*/
|
|
13
|
+
readonly editable?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* When set, the view renders in paginated mode: content is broken into
|
|
16
|
+
* fixed-size `.dx-page` containers by the LayoutEngine. v0.2 Phase 8 does
|
|
17
|
+
* a full repaginate on every updateState (no incremental relayout yet).
|
|
18
|
+
* When omitted, the view renders flat (Phase 1–7 behavior, unchanged).
|
|
19
|
+
*/
|
|
20
|
+
readonly paginated?: PageConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Accessible name applied to the editor's contenteditable root as
|
|
23
|
+
* `aria-label`. Screen readers announce this when focus enters the
|
|
24
|
+
* editor. Defaults to "Document editor". Pass a localized string for
|
|
25
|
+
* non-English UIs.
|
|
26
|
+
*/
|
|
27
|
+
readonly ariaLabel?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare class EditorView {
|
|
30
|
+
readonly dom: HTMLElement;
|
|
31
|
+
private currentState;
|
|
32
|
+
private readonly props;
|
|
33
|
+
private mount;
|
|
34
|
+
private lastRenderedDoc;
|
|
35
|
+
private readonly layoutEngine;
|
|
36
|
+
private readonly tableResizeCleanup;
|
|
37
|
+
private readonly cellDragCleanup;
|
|
38
|
+
private readonly imageResizeCleanup;
|
|
39
|
+
private readonly pageSlots;
|
|
40
|
+
constructor(mount: HTMLElement, props: EditorViewProps);
|
|
41
|
+
/** Re-collect the current `.dx-page` elements and (re)mount slot bindings. */
|
|
42
|
+
private syncPageSlots;
|
|
43
|
+
get state(): EditorState;
|
|
44
|
+
updateState(newState: EditorState): void;
|
|
45
|
+
/**
|
|
46
|
+
* Force a full re-render of the current state, bypassing the doc-identity
|
|
47
|
+
* short-circuit in updateState. Used by the MutationObserver safety net to
|
|
48
|
+
* revert unauthorized DOM mutations.
|
|
49
|
+
*/
|
|
50
|
+
forceRender(): void;
|
|
51
|
+
dispatch(tr: Transaction): void;
|
|
52
|
+
destroy(): void;
|
|
53
|
+
private initialRender;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=editor-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-view.d.ts","sourceRoot":"","sources":["../../src/view/editor-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAG9D,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAA;AAOzD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,4FAA4F;IAC5F,mBAAmB,CAAC,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3C;;OAEG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,UAAU,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,qBAAa,UAAU;IACrB,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAA;IACzB,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,eAAe,CAAiD;IACxE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAY;IAC5C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;gBAE1C,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe;IA0BtD,8EAA8E;IAC9E,OAAO,CAAC,aAAa;IAMrB,IAAI,KAAK,IAAI,WAAW,CAA6B;IAErD,WAAW,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAoCxC;;;;OAIG;IACH,WAAW,IAAI,IAAI;IAKnB,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,IAAI;IAO/B,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,aAAa;CAmBtB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { LayoutEngine } from '../layout/index.js';
|
|
2
|
+
import { paginate } from './paginator.js';
|
|
3
|
+
import { reconcile } from './reconcile.js';
|
|
4
|
+
import { renderNode } from './renderer.js';
|
|
5
|
+
import { renderSelection } from './selection-sync.js';
|
|
6
|
+
import { installCellDrag } from './cell-drag.js';
|
|
7
|
+
import { installImageResize } from './image-resize.js';
|
|
8
|
+
import { installPageSlots } from './page-slots.js';
|
|
9
|
+
import { installTableResize } from './table-resize.js';
|
|
10
|
+
export class EditorView {
|
|
11
|
+
dom;
|
|
12
|
+
currentState;
|
|
13
|
+
props;
|
|
14
|
+
mount;
|
|
15
|
+
lastRenderedDoc = null;
|
|
16
|
+
layoutEngine;
|
|
17
|
+
tableResizeCleanup;
|
|
18
|
+
cellDragCleanup;
|
|
19
|
+
imageResizeCleanup;
|
|
20
|
+
pageSlots;
|
|
21
|
+
constructor(mount, props) {
|
|
22
|
+
this.props = props;
|
|
23
|
+
this.mount = mount;
|
|
24
|
+
this.currentState = props.state;
|
|
25
|
+
this.dom = mount.ownerDocument.createElement('div');
|
|
26
|
+
const editable = props.editable !== false;
|
|
27
|
+
this.dom.setAttribute('contenteditable', editable ? 'true' : 'false');
|
|
28
|
+
this.dom.setAttribute('spellcheck', 'true');
|
|
29
|
+
this.dom.setAttribute('role', 'textbox');
|
|
30
|
+
this.dom.setAttribute('aria-multiline', 'true');
|
|
31
|
+
this.dom.setAttribute('aria-label', props.ariaLabel ?? 'Document editor');
|
|
32
|
+
this.dom.className = 'dx-editor';
|
|
33
|
+
mount.appendChild(this.dom);
|
|
34
|
+
this.layoutEngine = props.paginated
|
|
35
|
+
? new LayoutEngine(mount.ownerDocument, props.renderer, props.paginated)
|
|
36
|
+
: null;
|
|
37
|
+
// Page-slots controller is only meaningful in paginated mode — the
|
|
38
|
+
// flat (non-paginated) render path emits no `.dx-page` containers
|
|
39
|
+
// for headers/footers to mount into.
|
|
40
|
+
this.pageSlots = this.layoutEngine ? installPageSlots(this) : null;
|
|
41
|
+
this.initialRender();
|
|
42
|
+
this.tableResizeCleanup = installTableResize(this);
|
|
43
|
+
this.cellDragCleanup = installCellDrag(this);
|
|
44
|
+
this.imageResizeCleanup = installImageResize(this);
|
|
45
|
+
}
|
|
46
|
+
/** Re-collect the current `.dx-page` elements and (re)mount slot bindings. */
|
|
47
|
+
syncPageSlots() {
|
|
48
|
+
if (!this.pageSlots)
|
|
49
|
+
return;
|
|
50
|
+
const pages = Array.from(this.dom.querySelectorAll('.dx-page'));
|
|
51
|
+
this.pageSlots.attach(pages);
|
|
52
|
+
}
|
|
53
|
+
get state() { return this.currentState; }
|
|
54
|
+
updateState(newState) {
|
|
55
|
+
this.currentState = newState;
|
|
56
|
+
if (this.layoutEngine) {
|
|
57
|
+
// Selection-only updates (doc unchanged) must NOT repaginate — the
|
|
58
|
+
// Paginator clears and rebuilds the DOM, which destroys the live DOM
|
|
59
|
+
// selection mid-drag. Without this short-circuit, mouse-drag selection
|
|
60
|
+
// and selection-change dispatches loop-fight each other and selections
|
|
61
|
+
// visually snap back.
|
|
62
|
+
if (this.lastRenderedDoc === newState.doc) {
|
|
63
|
+
// Doc unchanged — selection-only path. Pages weren't rebuilt,
|
|
64
|
+
// so slot DOM is still there; just refresh slot contents in
|
|
65
|
+
// case pageMeta changed via a SetPageMetaStep that didn't
|
|
66
|
+
// touch the doc.
|
|
67
|
+
if (this.pageSlots)
|
|
68
|
+
this.pageSlots.refresh();
|
|
69
|
+
renderSelection(this.dom, this.currentState.selection, this.currentState.doc);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const model = this.layoutEngine.layout(newState.doc);
|
|
73
|
+
paginate(this.dom, newState.doc, model, this.props.renderer);
|
|
74
|
+
this.lastRenderedDoc = newState.doc;
|
|
75
|
+
// Paginator rebuilt page DOM — re-attach slot bindings.
|
|
76
|
+
this.syncPageSlots();
|
|
77
|
+
renderSelection(this.dom, this.currentState.selection, this.currentState.doc);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const oldDoc = this.lastRenderedDoc;
|
|
81
|
+
if (oldDoc && oldDoc !== newState.doc) {
|
|
82
|
+
reconcile(this.dom, oldDoc, newState.doc, this.props.renderer);
|
|
83
|
+
}
|
|
84
|
+
else if (!oldDoc) {
|
|
85
|
+
this.initialRender();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.lastRenderedDoc = newState.doc;
|
|
89
|
+
renderSelection(this.dom, this.currentState.selection, this.currentState.doc);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Force a full re-render of the current state, bypassing the doc-identity
|
|
93
|
+
* short-circuit in updateState. Used by the MutationObserver safety net to
|
|
94
|
+
* revert unauthorized DOM mutations.
|
|
95
|
+
*/
|
|
96
|
+
forceRender() {
|
|
97
|
+
this.lastRenderedDoc = null;
|
|
98
|
+
this.updateState(this.currentState);
|
|
99
|
+
}
|
|
100
|
+
dispatch(tr) {
|
|
101
|
+
if (!this.props.dispatchTransaction) {
|
|
102
|
+
throw new Error('EditorView.dispatch: no dispatchTransaction handler configured');
|
|
103
|
+
}
|
|
104
|
+
this.props.dispatchTransaction(tr);
|
|
105
|
+
}
|
|
106
|
+
destroy() {
|
|
107
|
+
if (this.pageSlots)
|
|
108
|
+
this.pageSlots.destroy();
|
|
109
|
+
this.imageResizeCleanup();
|
|
110
|
+
this.cellDragCleanup();
|
|
111
|
+
this.tableResizeCleanup();
|
|
112
|
+
if (this.layoutEngine)
|
|
113
|
+
this.layoutEngine.destroy();
|
|
114
|
+
if (this.mount) {
|
|
115
|
+
this.mount.removeChild(this.dom);
|
|
116
|
+
this.mount = null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
initialRender() {
|
|
120
|
+
while (this.dom.firstChild)
|
|
121
|
+
this.dom.removeChild(this.dom.firstChild);
|
|
122
|
+
if (this.layoutEngine) {
|
|
123
|
+
const model = this.layoutEngine.layout(this.currentState.doc);
|
|
124
|
+
paginate(this.dom, this.currentState.doc, model, this.props.renderer);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const tree = renderNode(this.dom.ownerDocument, this.props.renderer, this.currentState.doc, -1);
|
|
128
|
+
if (tree.nodeType === 1) {
|
|
129
|
+
const el = tree;
|
|
130
|
+
while (el.firstChild)
|
|
131
|
+
this.dom.appendChild(el.firstChild);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
this.dom.appendChild(tree);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
this.lastRenderedDoc = this.currentState.doc;
|
|
138
|
+
// After the initial paginate emitted pages, mount slot bindings.
|
|
139
|
+
this.syncPageSlots();
|
|
140
|
+
renderSelection(this.dom, this.currentState.selection, this.currentState.doc);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=editor-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-view.js","sourceRoot":"","sources":["../../src/view/editor-view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { EditorView } from './editor-view.js';
|
|
2
|
+
/**
|
|
3
|
+
* Pointer-driven width resize for images.
|
|
4
|
+
*
|
|
5
|
+
* Hot zone: within 8px of the right edge of any `.dx-image`.
|
|
6
|
+
*
|
|
7
|
+
* Strategy (mirrors `installTableResize`):
|
|
8
|
+
* - On pointermove (no drag), set `view.dom.style.cursor = 'ew-resize'` while
|
|
9
|
+
* the pointer hovers in the hot zone.
|
|
10
|
+
* - On pointerdown in the hot zone, capture the starting `clientX`, the
|
|
11
|
+
* image's bounding rect width, the image element, and the image's absolute
|
|
12
|
+
* [open] position in the model (read from a NodeRef attached by the
|
|
13
|
+
* renderer). Set pointer capture on the event target so subsequent
|
|
14
|
+
* pointermoves are routed to this controller exclusively (this also
|
|
15
|
+
* prevents `installCellDrag` from kicking in when the image lives inside a
|
|
16
|
+
* table cell).
|
|
17
|
+
* - During the drag, we mutate the DOM directly — writing
|
|
18
|
+
* `img.style.width = '${newWidth}px'`. Writes are coalesced through
|
|
19
|
+
* `requestAnimationFrame`: multiple pointermoves within one frame produce
|
|
20
|
+
* a single DOM write per frame.
|
|
21
|
+
* - On pointerup, the pending frame is cancelled, the final width is
|
|
22
|
+
* written synchronously, and a single `setImageWidth(imgPos, final)`
|
|
23
|
+
* transaction is dispatched. The post-dispatch render reconciles the DOM
|
|
24
|
+
* to the new model attr value.
|
|
25
|
+
* - On pointercancel, the pending frame is cancelled and the view re-renders
|
|
26
|
+
* from current state (undoing any direct DOM mutations).
|
|
27
|
+
*
|
|
28
|
+
* Coordination with other controllers:
|
|
29
|
+
* - `installCellDrag` (cell-selection) also listens on pointerdown. When the
|
|
30
|
+
* pointerdown lands on an image's right-edge hot zone inside a cell, this
|
|
31
|
+
* controller captures the pointer, so cell-drag's anchor never receives
|
|
32
|
+
* subsequent pointermoves and never escalates to a CellSelection.
|
|
33
|
+
* - `installTableResize` is unaffected — its hot zone is on the cell's right
|
|
34
|
+
* edge, not on any `.dx-image` inside the cell.
|
|
35
|
+
*/
|
|
36
|
+
export declare function installImageResize(view: EditorView): () => void;
|
|
37
|
+
//# sourceMappingURL=image-resize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-resize.d.ts","sourceRoot":"","sources":["../../src/view/image-resize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAGlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,IAAI,CAyK/D"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { setImageWidth } from '../commands/image-commands.js';
|
|
2
|
+
import { getNodeRef } from './renderer.js';
|
|
3
|
+
/**
|
|
4
|
+
* Pointer-driven width resize for images.
|
|
5
|
+
*
|
|
6
|
+
* Hot zone: within 8px of the right edge of any `.dx-image`.
|
|
7
|
+
*
|
|
8
|
+
* Strategy (mirrors `installTableResize`):
|
|
9
|
+
* - On pointermove (no drag), set `view.dom.style.cursor = 'ew-resize'` while
|
|
10
|
+
* the pointer hovers in the hot zone.
|
|
11
|
+
* - On pointerdown in the hot zone, capture the starting `clientX`, the
|
|
12
|
+
* image's bounding rect width, the image element, and the image's absolute
|
|
13
|
+
* [open] position in the model (read from a NodeRef attached by the
|
|
14
|
+
* renderer). Set pointer capture on the event target so subsequent
|
|
15
|
+
* pointermoves are routed to this controller exclusively (this also
|
|
16
|
+
* prevents `installCellDrag` from kicking in when the image lives inside a
|
|
17
|
+
* table cell).
|
|
18
|
+
* - During the drag, we mutate the DOM directly — writing
|
|
19
|
+
* `img.style.width = '${newWidth}px'`. Writes are coalesced through
|
|
20
|
+
* `requestAnimationFrame`: multiple pointermoves within one frame produce
|
|
21
|
+
* a single DOM write per frame.
|
|
22
|
+
* - On pointerup, the pending frame is cancelled, the final width is
|
|
23
|
+
* written synchronously, and a single `setImageWidth(imgPos, final)`
|
|
24
|
+
* transaction is dispatched. The post-dispatch render reconciles the DOM
|
|
25
|
+
* to the new model attr value.
|
|
26
|
+
* - On pointercancel, the pending frame is cancelled and the view re-renders
|
|
27
|
+
* from current state (undoing any direct DOM mutations).
|
|
28
|
+
*
|
|
29
|
+
* Coordination with other controllers:
|
|
30
|
+
* - `installCellDrag` (cell-selection) also listens on pointerdown. When the
|
|
31
|
+
* pointerdown lands on an image's right-edge hot zone inside a cell, this
|
|
32
|
+
* controller captures the pointer, so cell-drag's anchor never receives
|
|
33
|
+
* subsequent pointermoves and never escalates to a CellSelection.
|
|
34
|
+
* - `installTableResize` is unaffected — its hot zone is on the cell's right
|
|
35
|
+
* edge, not on any `.dx-image` inside the cell.
|
|
36
|
+
*/
|
|
37
|
+
export function installImageResize(view) {
|
|
38
|
+
const HOT_ZONE_PX = 8;
|
|
39
|
+
const MIN_WIDTH_PX = 32;
|
|
40
|
+
let drag = null;
|
|
41
|
+
// rAF-coalesced live DOM writes. See `installTableResize` for the matching
|
|
42
|
+
// pattern used by column-resize.
|
|
43
|
+
let pendingFrame = null;
|
|
44
|
+
let pendingWidth = null;
|
|
45
|
+
function getRaf() {
|
|
46
|
+
const win = view.dom.ownerDocument.defaultView;
|
|
47
|
+
if (win && typeof win.requestAnimationFrame === 'function') {
|
|
48
|
+
return {
|
|
49
|
+
request: win.requestAnimationFrame.bind(win),
|
|
50
|
+
cancel: win.cancelAnimationFrame.bind(win),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
request: (cb) => {
|
|
55
|
+
cb(0);
|
|
56
|
+
return 0;
|
|
57
|
+
},
|
|
58
|
+
cancel: () => {
|
|
59
|
+
/* no-op */
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function flushPendingWidth() {
|
|
64
|
+
pendingFrame = null;
|
|
65
|
+
if (!drag || pendingWidth == null)
|
|
66
|
+
return;
|
|
67
|
+
drag.img.style.width = `${pendingWidth}px`;
|
|
68
|
+
}
|
|
69
|
+
function cancelPendingFrame() {
|
|
70
|
+
if (pendingFrame != null) {
|
|
71
|
+
getRaf().cancel(pendingFrame);
|
|
72
|
+
pendingFrame = null;
|
|
73
|
+
}
|
|
74
|
+
pendingWidth = null;
|
|
75
|
+
}
|
|
76
|
+
function findImageWithinHotZone(target, clientX) {
|
|
77
|
+
if (!(target instanceof Element))
|
|
78
|
+
return null;
|
|
79
|
+
const img = target.closest('.dx-image');
|
|
80
|
+
if (!img)
|
|
81
|
+
return null;
|
|
82
|
+
if (!view.dom.contains(img))
|
|
83
|
+
return null;
|
|
84
|
+
const rect = img.getBoundingClientRect();
|
|
85
|
+
if (clientX >= rect.right - HOT_ZONE_PX && clientX <= rect.right + HOT_ZONE_PX) {
|
|
86
|
+
return img;
|
|
87
|
+
}
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
function imagePosFromEl(img) {
|
|
91
|
+
const ref = getNodeRef(img);
|
|
92
|
+
if (!ref || ref.pos < 0)
|
|
93
|
+
return null;
|
|
94
|
+
return ref.pos;
|
|
95
|
+
}
|
|
96
|
+
function onPointerMove(event) {
|
|
97
|
+
if (drag) {
|
|
98
|
+
const delta = event.clientX - drag.startX;
|
|
99
|
+
const newWidth = Math.max(MIN_WIDTH_PX, Math.round(drag.startWidth + delta));
|
|
100
|
+
drag.finalWidth = newWidth;
|
|
101
|
+
pendingWidth = newWidth;
|
|
102
|
+
if (pendingFrame == null) {
|
|
103
|
+
pendingFrame = getRaf().request(flushPendingWidth);
|
|
104
|
+
}
|
|
105
|
+
event.preventDefault();
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const hit = findImageWithinHotZone(event.target, event.clientX);
|
|
109
|
+
if (hit) {
|
|
110
|
+
view.dom.style.cursor = 'ew-resize';
|
|
111
|
+
}
|
|
112
|
+
// NOTE: when not hovering an image hot zone, we don't clear the cursor —
|
|
113
|
+
// installTableResize manages its own cursor state and writes '' when its
|
|
114
|
+
// own hot zone is missed. Both controllers reset the cursor on pointerup
|
|
115
|
+
// and on teardown.
|
|
116
|
+
}
|
|
117
|
+
function onPointerDown(event) {
|
|
118
|
+
if (event.button !== 0)
|
|
119
|
+
return;
|
|
120
|
+
const hit = findImageWithinHotZone(event.target, event.clientX);
|
|
121
|
+
if (!hit)
|
|
122
|
+
return;
|
|
123
|
+
const imgPos = imagePosFromEl(hit);
|
|
124
|
+
if (imgPos == null)
|
|
125
|
+
return;
|
|
126
|
+
const startWidth = hit.getBoundingClientRect().width;
|
|
127
|
+
const captureTarget = event.target instanceof HTMLElement ? event.target : view.dom;
|
|
128
|
+
try {
|
|
129
|
+
captureTarget.setPointerCapture(event.pointerId);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
/* ignore */
|
|
133
|
+
}
|
|
134
|
+
drag = {
|
|
135
|
+
img: hit,
|
|
136
|
+
imgPos,
|
|
137
|
+
startX: event.clientX,
|
|
138
|
+
startWidth,
|
|
139
|
+
pointerId: event.pointerId,
|
|
140
|
+
captureTarget,
|
|
141
|
+
finalWidth: startWidth,
|
|
142
|
+
};
|
|
143
|
+
event.preventDefault();
|
|
144
|
+
}
|
|
145
|
+
function onPointerUp(event) {
|
|
146
|
+
if (!drag)
|
|
147
|
+
return;
|
|
148
|
+
const finished = drag;
|
|
149
|
+
drag = null;
|
|
150
|
+
cancelPendingFrame();
|
|
151
|
+
finished.img.style.width = `${finished.finalWidth}px`;
|
|
152
|
+
try {
|
|
153
|
+
finished.captureTarget.releasePointerCapture(finished.pointerId);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
/* ignore */
|
|
157
|
+
}
|
|
158
|
+
view.dom.style.cursor = '';
|
|
159
|
+
const cmd = setImageWidth(finished.imgPos, finished.finalWidth);
|
|
160
|
+
cmd(view.state, (tr) => view.dispatch(tr));
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
}
|
|
163
|
+
function onPointerCancel(_event) {
|
|
164
|
+
if (!drag)
|
|
165
|
+
return;
|
|
166
|
+
const cancelled = drag;
|
|
167
|
+
drag = null;
|
|
168
|
+
cancelPendingFrame();
|
|
169
|
+
try {
|
|
170
|
+
cancelled.captureTarget.releasePointerCapture(cancelled.pointerId);
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
/* ignore */
|
|
174
|
+
}
|
|
175
|
+
view.dom.style.cursor = '';
|
|
176
|
+
view.forceRender();
|
|
177
|
+
}
|
|
178
|
+
view.dom.addEventListener('pointermove', onPointerMove);
|
|
179
|
+
view.dom.addEventListener('pointerdown', onPointerDown);
|
|
180
|
+
view.dom.addEventListener('pointerup', onPointerUp);
|
|
181
|
+
view.dom.addEventListener('pointercancel', onPointerCancel);
|
|
182
|
+
return () => {
|
|
183
|
+
cancelPendingFrame();
|
|
184
|
+
view.dom.removeEventListener('pointermove', onPointerMove);
|
|
185
|
+
view.dom.removeEventListener('pointerdown', onPointerDown);
|
|
186
|
+
view.dom.removeEventListener('pointerup', onPointerUp);
|
|
187
|
+
view.dom.removeEventListener('pointercancel', onPointerCancel);
|
|
188
|
+
view.dom.style.cursor = '';
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=image-resize.js.map
|