@formicoidea/labre-core 0.58.0 → 0.59.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/architecture/code.c4 +94 -65
- package/architecture/domain.c4 +11 -5
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.js +18 -13
- package/dist/_pkgs/affine-block-callout/adapters/markdown.js +4 -1
- package/dist/_pkgs/affine-block-code/adapters/html.js +1 -1
- package/dist/_pkgs/affine-block-code/adapters/markdown/preprocessor.js +13 -1
- package/dist/_pkgs/affine-block-code/adapters/notion-html.js +1 -1
- package/dist/_pkgs/affine-block-code/code-block.d.ts +17 -2
- package/dist/_pkgs/affine-block-code/code-block.js +28 -23
- package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +17 -4
- package/dist/_pkgs/affine-block-code/code-toolbar/components/preview-button.js +1 -1
- package/dist/_pkgs/affine-block-data-view/data-source.js +12 -5
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-image/asset-picker.d.ts +23 -2
- package/dist/_pkgs/affine-block-image/asset-picker.js +52 -12
- package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +8 -5
- package/dist/_pkgs/affine-block-image/configs/replace-action.js +8 -8
- package/dist/_pkgs/affine-block-image/configs/toolbar.js +2 -1
- package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-image/crop/crop-controller.js +40 -2
- package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +22 -0
- package/dist/_pkgs/affine-block-image/crop/crop-math.js +55 -2
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +17 -3
- package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +64 -6
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +20 -14
- package/dist/_pkgs/affine-block-image/image-block.js +1 -0
- package/dist/_pkgs/affine-block-image/image-edgeless-block.js +3 -0
- package/dist/_pkgs/affine-block-image/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-image/index.js +2 -0
- package/dist/_pkgs/affine-block-image/replace/commands.d.ts +68 -0
- package/dist/_pkgs/affine-block-image/replace/commands.js +200 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.d.ts +44 -0
- package/dist/_pkgs/affine-block-image/replace/replace-model.js +168 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.d.ts +21 -0
- package/dist/_pkgs/affine-block-image/replace/toolbar.js +159 -0
- package/dist/_pkgs/affine-block-image/translations.d.ts +15 -2
- package/dist/_pkgs/affine-block-image/translations.js +35 -2
- package/dist/_pkgs/affine-block-image/utils.d.ts +7 -0
- package/dist/_pkgs/affine-block-image/utils.js +13 -0
- package/dist/_pkgs/affine-block-image/view.js +7 -0
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.d.ts +14 -5
- package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.js +18 -11
- package/dist/_pkgs/affine-block-note/config.d.ts +9 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.d.ts +3 -2
- package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.js +8 -5
- package/dist/_pkgs/affine-block-paragraph/adapters/markdown.js +11 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.d.ts +17 -0
- package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.js +123 -0
- package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +82 -65
- package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +2 -0
- package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
- package/dist/_pkgs/affine-block-root/index.js +1 -0
- package/dist/_pkgs/affine-block-root/translations.d.ts +6 -0
- package/dist/_pkgs/affine-block-root/translations.js +10 -0
- package/dist/_pkgs/affine-block-root/view.js +6 -1
- package/dist/_pkgs/affine-block-surface/commands/index.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/commands/index.js +1 -1
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.d.ts +9 -0
- package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.js +21 -12
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.d.ts +33 -0
- package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +53 -0
- package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +2 -1
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.d.ts +104 -0
- package/dist/_pkgs/affine-block-surface/framework-background/band-widths.js +156 -0
- package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +87 -4
- package/dist/_pkgs/affine-block-surface/framework-background/def.js +26 -7
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.d.ts +58 -0
- package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.js +110 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/index.js +3 -0
- package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +12 -2
- package/dist/_pkgs/affine-block-surface/framework-background/labels.js +29 -5
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.d.ts +14 -0
- package/dist/_pkgs/affine-block-surface/framework-background/measure-text.js +31 -0
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.d.ts +14 -1
- package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +84 -31
- package/dist/_pkgs/affine-block-table/adapters/html.js +26 -14
- package/dist/_pkgs/affine-block-table/adapters/utils.d.ts +1 -0
- package/dist/_pkgs/affine-block-table/adapters/utils.js +23 -5
- package/dist/_pkgs/affine-block-table/header-menu.d.ts +13 -0
- package/dist/_pkgs/affine-block-table/header-menu.js +25 -0
- package/dist/_pkgs/affine-block-table/selection-controller.d.ts +15 -0
- package/dist/_pkgs/affine-block-table/selection-controller.js +62 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.d.ts +7 -0
- package/dist/_pkgs/affine-block-table/table-cell-css.js +10 -0
- package/dist/_pkgs/affine-block-table/table-cell.d.ts +8 -0
- package/dist/_pkgs/affine-block-table/table-cell.js +35 -3
- package/dist/_pkgs/affine-block-table/table-data-manager.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/table-data-manager.js +44 -3
- package/dist/_pkgs/affine-block-table/translations.d.ts +14 -0
- package/dist/_pkgs/affine-block-table/translations.js +22 -0
- package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.d.ts +2 -2
- package/dist/_pkgs/affine-gfx-template/builtin/other.d.ts +4 -0
- package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.d.ts +81 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/build.js +276 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.d.ts +126 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.js +101 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.d.ts +8 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/index.js +27 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.d.ts +83 -0
- package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.js +674 -0
- package/dist/_pkgs/affine-gfx-template/contribute.js +12 -17
- package/dist/_pkgs/affine-gfx-template/make-snapshot.d.ts +14 -2
- package/dist/_pkgs/affine-gfx-template/make-snapshot.js +6 -2
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +12 -0
- package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +48 -0
- package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +15 -1
- package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +33 -37
- package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +6 -0
- package/dist/_pkgs/affine-gfx-template/translations.d.ts +94 -0
- package/dist/_pkgs/affine-gfx-template/translations.js +441 -2
- package/dist/_pkgs/affine-model/blocks/table/table-model.d.ts +4 -0
- package/dist/_pkgs/affine-model/blocks/table/table-model.js +4 -0
- package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +46 -3
- package/dist/_pkgs/affine-model/elements/bpmn/node.js +47 -4
- package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +20 -0
- package/dist/_pkgs/affine-model/elements/bpmn/pool.js +33 -4
- package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +3 -16
- package/dist/_pkgs/affine-shared/services/edit-props-store.js +16 -16
- package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
- package/dist/_pkgs/affine-shared/services/editor-setting-service.js +4 -0
- package/dist/_pkgs/affine-shared/services/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/services/index.js +1 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.d.ts +33 -0
- package/dist/_pkgs/affine-shared/services/invisible-characters.js +63 -0
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.d.ts +0 -9
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.js +3 -9
- package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -0
- package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +4 -3
- package/dist/_pkgs/affine-shared/services/telemetry-service/types.d.ts +11 -0
- package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/utils/index.js +1 -0
- package/dist/_pkgs/affine-shared/utils/invisible-characters.d.ts +42 -0
- package/dist/_pkgs/affine-shared/utils/invisible-characters.js +81 -0
- package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-toolbar.js +13 -2
- package/dist/_pkgs/data-view/view-presets/table/pc/header/column-header.js +6 -0
- package/dist/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.js +5 -2
- package/dist/_pkgs/std/clipboard/clipboard.d.ts +15 -1
- package/dist/_pkgs/std/clipboard/clipboard.js +18 -0
- package/dist/_pkgs/std/inline/components/embed-gap.js +1 -1
- package/dist/_pkgs/std/inline/components/v-line.js +1 -1
- package/dist/_pkgs/std/inline/components/v-text.d.ts +15 -2
- package/dist/_pkgs/std/inline/components/v-text.js +147 -15
- package/dist/_pkgs/std/inline/consts.d.ts +5 -0
- package/dist/_pkgs/std/inline/consts.js +5 -0
- package/dist/_pkgs/std/inline/utils/index.d.ts +1 -0
- package/dist/_pkgs/std/inline/utils/index.js +1 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.d.ts +57 -0
- package/dist/_pkgs/std/inline/utils/invisible-characters.js +162 -0
- package/dist/_pkgs/std/inline/utils/point-conversion.js +3 -3
- package/dist/_pkgs/std/inline/utils/text.d.ts +8 -0
- package/dist/_pkgs/std/inline/utils/text.js +11 -2
- package/dist/_pkgs/store/model/store/crud.d.ts +28 -0
- package/dist/_pkgs/store/model/store/crud.js +97 -30
- package/dist/_pkgs/store/model/store/query.js +3 -2
- package/dist/_pkgs/store/model/store/store.d.ts +21 -0
- package/dist/_pkgs/store/model/store/store.js +88 -21
- package/dist/_pkgs/store/transformer/transformer.d.ts +46 -0
- package/dist/_pkgs/store/transformer/transformer.js +72 -0
- package/dist/commands.js +6 -1
- package/dist/translations.js +2 -0
- package/package.json +3 -4
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readImageCrop, } from '../../affine-model/index.js';
|
|
2
2
|
import { Bound } from '../../global/gfx/index.js';
|
|
3
|
+
import { GfxControllerIdentifier } from '../../std/gfx/index.js';
|
|
3
4
|
import { computed, signal } from '@preact/signals-core';
|
|
4
5
|
import { html, nothing } from 'lit';
|
|
5
6
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
@@ -9,6 +10,14 @@ import { writeImageCrop } from './write-crop.js';
|
|
|
9
10
|
* The « Rogner » state of one image block (ADR 0037), shared by the page and
|
|
10
11
|
* the canvas components: which preset the crop frame is open on, if any, and
|
|
11
12
|
* the gestures that write. The frame is local UI and never stored.
|
|
13
|
+
*
|
|
14
|
+
* On the canvas the open frame owns the pointer and the wheel: the image is
|
|
15
|
+
* selected in EDITING state, which hides the selected-rect handles that
|
|
16
|
+
* would otherwise sit on the frame's corners, and the viewport is locked,
|
|
17
|
+
* so the wheel zooms the picture inside the frame rather than the canvas.
|
|
18
|
+
* Both are taken by one open path and given back by one `stop`, whatever
|
|
19
|
+
* closes the frame (Escape, Enter, a press elsewhere, the toolbar, the block
|
|
20
|
+
* leaving the DOM, the selection moving elsewhere), so they cannot drift.
|
|
12
21
|
*/
|
|
13
22
|
export class ImageCropController {
|
|
14
23
|
constructor(_block, _onCanvas) {
|
|
@@ -17,6 +26,8 @@ export class ImageCropController {
|
|
|
17
26
|
/** The mask the crop frame is open on, `null` when it is closed. */
|
|
18
27
|
this.editing$ = signal(null);
|
|
19
28
|
this.crop$ = computed(() => readImageCrop(this._block.model.props.crop$.value));
|
|
29
|
+
/** Gives the canvas back; set while the frame is open on the canvas. */
|
|
30
|
+
this._release = null;
|
|
20
31
|
}
|
|
21
32
|
/**
|
|
22
33
|
* The source's proportions: the loaded `<img>`'s pixel size, else what the
|
|
@@ -56,17 +67,44 @@ export class ImageCropController {
|
|
|
56
67
|
return;
|
|
57
68
|
this.commit(presetCrop(mask, natural.width, natural.height), mask);
|
|
58
69
|
}
|
|
70
|
+
this._open(mask);
|
|
71
|
+
}
|
|
72
|
+
_open(mask) {
|
|
59
73
|
this.editing$.value = mask;
|
|
74
|
+
if (!this._onCanvas || this._release)
|
|
75
|
+
return;
|
|
76
|
+
const { selection, viewport } = this._block.std.get(GfxControllerIdentifier);
|
|
77
|
+
const { id, store } = this._block.model;
|
|
78
|
+
const wasLocked = viewport.locked;
|
|
79
|
+
viewport.locked = true;
|
|
80
|
+
selection.set({ elements: [id], editing: true });
|
|
81
|
+
// Another selection (a shortcut, the selection pane, a peer's undo
|
|
82
|
+
// removing the block) closes the frame instead of leaving it orphaned.
|
|
83
|
+
const watch = selection.slots.updated.subscribe(() => {
|
|
84
|
+
if (!selection.editing || !selection.has(id))
|
|
85
|
+
this.stop();
|
|
86
|
+
});
|
|
87
|
+
this._release = () => {
|
|
88
|
+
watch.unsubscribe();
|
|
89
|
+
viewport.locked = wasLocked;
|
|
90
|
+
if (selection.editing && selection.has(id) && store.hasBlock(id)) {
|
|
91
|
+
selection.set({ elements: [id], editing: false });
|
|
92
|
+
}
|
|
93
|
+
};
|
|
60
94
|
}
|
|
61
95
|
commit(rect, mask = this.editing$.peek() ?? 'free') {
|
|
62
96
|
return writeImageCrop(this._block.model, rect, mask, this._onCanvas);
|
|
63
97
|
}
|
|
64
98
|
/** « Image d'origine »: removes the crop; the bytes never changed. */
|
|
65
99
|
restoreOriginal() {
|
|
66
|
-
this.
|
|
100
|
+
this.stop();
|
|
67
101
|
return writeImageCrop(this._block.model, undefined, 'free', this._onCanvas);
|
|
68
102
|
}
|
|
103
|
+
/** Closes the frame and gives the canvas back; harmless when closed. */
|
|
69
104
|
stop() {
|
|
105
|
+
const release = this._release;
|
|
106
|
+
this._release = null;
|
|
107
|
+
release?.();
|
|
70
108
|
this.editing$.value = null;
|
|
71
109
|
}
|
|
72
110
|
/** The frame, or nothing when it is closed or the page is readonly. */
|
|
@@ -88,7 +126,7 @@ export class ImageCropController {
|
|
|
88
126
|
.ratio=${ratio}
|
|
89
127
|
.rotate=${rotate}
|
|
90
128
|
.onCommit=${(rect) => {
|
|
91
|
-
this.commit(rect);
|
|
129
|
+
this.commit(rect, mask);
|
|
92
130
|
}}
|
|
93
131
|
.onExit=${() => this.stop()}
|
|
94
132
|
></affine-image-crop-overlay>`;
|
|
@@ -14,6 +14,13 @@ export declare function maskRatio(mask: ImageCropMask, naturalWidth: number, nat
|
|
|
14
14
|
* writes before the author adjusts it. Free is the whole image.
|
|
15
15
|
*/
|
|
16
16
|
export declare function presetCrop(mask: ImageCropMask, naturalWidth: number, naturalHeight: number): CropRect;
|
|
17
|
+
/**
|
|
18
|
+
* The largest centred rectangle whose width over height, in SOURCE PIXELS, is
|
|
19
|
+
* `ratio`: a preset's window, and the cut a shape's box makes in the picture
|
|
20
|
+
* that replaces it (ADR 0044). The whole image when the size or the ratio is
|
|
21
|
+
* unknown.
|
|
22
|
+
*/
|
|
23
|
+
export declare function ratioCrop(ratio: number, naturalWidth: number, naturalHeight: number): CropRect;
|
|
17
24
|
/** The window dragged by a normalised delta, kept inside the image. */
|
|
18
25
|
export declare function moveCrop(start: CropRect, dx: number, dy: number): CropRect;
|
|
19
26
|
/**
|
|
@@ -22,6 +29,21 @@ export declare function moveCrop(start: CropRect, dx: number, dy: number): CropR
|
|
|
22
29
|
* and then shrinks to fit the image, so it never leaves the source.
|
|
23
30
|
*/
|
|
24
31
|
export declare function resizeCrop(start: CropRect, corner: CropCorner, dx: number, dy: number, k: number | null): CropRect;
|
|
32
|
+
/** Scale of the window per 100 units of wheel `deltaY`. */
|
|
33
|
+
export declare const CROP_WHEEL_STEP = 1.05;
|
|
34
|
+
/**
|
|
35
|
+
* The window's scale for one wheel event: below 1 when the wheel turns up
|
|
36
|
+
* (`deltaY < 0`), which shrinks the window and so zooms into the picture.
|
|
37
|
+
*/
|
|
38
|
+
export declare function cropWheelFactor(deltaY: number): number;
|
|
39
|
+
/**
|
|
40
|
+
* The window scaled by `factor` about a point of the source (`px`, `py`,
|
|
41
|
+
* normalised): that point stays under the pointer. The aspect is `k`
|
|
42
|
+
* (normalised `w / h`) when a mask holds one, else the window's own; the
|
|
43
|
+
* window never outgrows the image nor shrinks below the minimum side, and is
|
|
44
|
+
* then pushed back inside the image.
|
|
45
|
+
*/
|
|
46
|
+
export declare function zoomCrop(start: CropRect, factor: number, px: number, py: number, k: number | null): CropRect;
|
|
25
47
|
export declare function sameCropRect(a: CropRect, b: CropRect): boolean;
|
|
26
48
|
/**
|
|
27
49
|
* The canvas box once the crop changes from `from` to `to`, for a block whose
|
|
@@ -23,9 +23,21 @@ export function maskRatio(mask, naturalWidth, naturalHeight) {
|
|
|
23
23
|
* writes before the author adjusts it. Free is the whole image.
|
|
24
24
|
*/
|
|
25
25
|
export function presetCrop(mask, naturalWidth, naturalHeight) {
|
|
26
|
-
|
|
27
|
-
if (k === null)
|
|
26
|
+
if (mask === 'free')
|
|
28
27
|
return WHOLE_IMAGE;
|
|
28
|
+
return ratioCrop(MASK_RATIOS[mask], naturalWidth, naturalHeight);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The largest centred rectangle whose width over height, in SOURCE PIXELS, is
|
|
32
|
+
* `ratio`: a preset's window, and the cut a shape's box makes in the picture
|
|
33
|
+
* that replaces it (ADR 0044). The whole image when the size or the ratio is
|
|
34
|
+
* unknown.
|
|
35
|
+
*/
|
|
36
|
+
export function ratioCrop(ratio, naturalWidth, naturalHeight) {
|
|
37
|
+
if (!(ratio > 0) || naturalWidth <= 0 || naturalHeight <= 0) {
|
|
38
|
+
return WHOLE_IMAGE;
|
|
39
|
+
}
|
|
40
|
+
const k = (ratio * naturalHeight) / naturalWidth;
|
|
29
41
|
let w = k;
|
|
30
42
|
let h = 1;
|
|
31
43
|
if (w > 1) {
|
|
@@ -88,6 +100,47 @@ export function resizeCrop(start, corner, dx, dy, k) {
|
|
|
88
100
|
h,
|
|
89
101
|
};
|
|
90
102
|
}
|
|
103
|
+
/** Scale of the window per 100 units of wheel `deltaY`. */
|
|
104
|
+
export const CROP_WHEEL_STEP = 1.05;
|
|
105
|
+
/** At most this many steps per wheel event: a fast flick stays readable. */
|
|
106
|
+
const CROP_WHEEL_MAX_STEPS = 3;
|
|
107
|
+
/**
|
|
108
|
+
* The window's scale for one wheel event: below 1 when the wheel turns up
|
|
109
|
+
* (`deltaY < 0`), which shrinks the window and so zooms into the picture.
|
|
110
|
+
*/
|
|
111
|
+
export function cropWheelFactor(deltaY) {
|
|
112
|
+
const steps = clamp(deltaY / 100, -CROP_WHEEL_MAX_STEPS, CROP_WHEEL_MAX_STEPS);
|
|
113
|
+
return CROP_WHEEL_STEP ** steps;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The window scaled by `factor` about a point of the source (`px`, `py`,
|
|
117
|
+
* normalised): that point stays under the pointer. The aspect is `k`
|
|
118
|
+
* (normalised `w / h`) when a mask holds one, else the window's own; the
|
|
119
|
+
* window never outgrows the image nor shrinks below the minimum side, and is
|
|
120
|
+
* then pushed back inside the image.
|
|
121
|
+
*/
|
|
122
|
+
export function zoomCrop(start, factor, px, py, k) {
|
|
123
|
+
const ratio = k ?? start.w / start.h;
|
|
124
|
+
const min = IMAGE_CROP_MIN_SIDE;
|
|
125
|
+
let w = start.w * factor;
|
|
126
|
+
let h = w / ratio;
|
|
127
|
+
// Fit inside the image first, then grow to the minimum: a ratio too
|
|
128
|
+
// extreme for both keeps the minimum, as `resizeCrop` does.
|
|
129
|
+
const shrink = Math.min(1, 1 / w, 1 / h);
|
|
130
|
+
w *= shrink;
|
|
131
|
+
h *= shrink;
|
|
132
|
+
const grow = Math.max(1, min / w, min / h);
|
|
133
|
+
w *= grow;
|
|
134
|
+
h *= grow;
|
|
135
|
+
const sx = w / start.w;
|
|
136
|
+
const sy = h / start.h;
|
|
137
|
+
return {
|
|
138
|
+
x: clamp(px - (px - start.x) * sx, 0, Math.max(0, 1 - w)),
|
|
139
|
+
y: clamp(py - (py - start.y) * sy, 0, Math.max(0, 1 - h)),
|
|
140
|
+
w,
|
|
141
|
+
h,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
91
144
|
export function sameCropRect(a, b) {
|
|
92
145
|
return (Math.abs(a.x - b.x) < EPSILON &&
|
|
93
146
|
Math.abs(a.y - b.y) < EPSILON &&
|
|
@@ -11,9 +11,17 @@ declare const ImageCropOverlay_base: typeof LitElement & import("../../global/ut
|
|
|
11
11
|
* release hands it to `onCommit` once — one gesture, one write, one undo
|
|
12
12
|
* step, decided by the caller (`writeImageCrop`).
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
* the
|
|
16
|
-
*
|
|
14
|
+
* The wheel over the frame zooms the picture inside it: it scales the window
|
|
15
|
+
* about the pointer, the ratio held, inside the image. One scroll is one
|
|
16
|
+
* write: the draft is handed to `onCommit` once the wheel has been quiet for
|
|
17
|
+
* a moment, or at once when a drag starts or the frame is left by Escape,
|
|
18
|
+
* Enter or a press elsewhere. A frame closed by anything else (the toolbar,
|
|
19
|
+
* the block leaving) drops a scroll still pending rather than write after it.
|
|
20
|
+
*
|
|
21
|
+
* Pointer and wheel events never reach the editor while the frame is open: a
|
|
22
|
+
* press on the frame would otherwise start a canvas drag or a page
|
|
23
|
+
* selection, a wheel would zoom or scroll the canvas. Escape, Enter or a
|
|
24
|
+
* press anywhere else calls `onExit`.
|
|
17
25
|
*/
|
|
18
26
|
export declare class ImageCropOverlay extends ImageCropOverlay_base {
|
|
19
27
|
static styles: import("lit").CSSResult;
|
|
@@ -28,11 +36,17 @@ export declare class ImageCropOverlay extends ImageCropOverlay_base {
|
|
|
28
36
|
accessor onExit: () => void;
|
|
29
37
|
accessor draft: CropRect;
|
|
30
38
|
private _dragging;
|
|
39
|
+
/** The pending end of a wheel gesture, `null` when none is under way. */
|
|
40
|
+
private _wheelTimer;
|
|
31
41
|
/** Removes the listeners of the gesture in progress, if any. */
|
|
32
42
|
private _releaseGesture;
|
|
33
43
|
private readonly _stop;
|
|
34
44
|
private readonly _onOutsidePointer;
|
|
35
45
|
private readonly _onKeydown;
|
|
46
|
+
/** Ends the wheel gesture under way, if any, with its one write. */
|
|
47
|
+
private _commitWheel;
|
|
48
|
+
private _dropWheel;
|
|
49
|
+
private readonly _onWheel;
|
|
36
50
|
/**
|
|
37
51
|
* The document-wide listeners (a press elsewhere, Escape, Enter) live only
|
|
38
52
|
* as long as this element: the frame is rendered while it is open and
|
|
@@ -38,8 +38,10 @@ import { css, html, LitElement } from 'lit';
|
|
|
38
38
|
import { property, state } from 'lit/decorators.js';
|
|
39
39
|
import { repeat } from 'lit/directives/repeat.js';
|
|
40
40
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
41
|
-
import { moveCrop, resizeCrop, WHOLE_IMAGE, } from './crop-math.js';
|
|
41
|
+
import { cropWheelFactor, moveCrop, resizeCrop, WHOLE_IMAGE, zoomCrop, } from './crop-math.js';
|
|
42
42
|
const CORNERS = ['nw', 'ne', 'sw', 'se'];
|
|
43
|
+
/** Quiet time after the last wheel event that ends one wheel gesture. */
|
|
44
|
+
const WHEEL_COMMIT_DELAY_MS = 150;
|
|
43
45
|
const rectStyle = (rect) => styleMap({
|
|
44
46
|
left: `${rect.x * 100}%`,
|
|
45
47
|
top: `${rect.y * 100}%`,
|
|
@@ -56,9 +58,17 @@ const rectStyle = (rect) => styleMap({
|
|
|
56
58
|
* release hands it to `onCommit` once — one gesture, one write, one undo
|
|
57
59
|
* step, decided by the caller (`writeImageCrop`).
|
|
58
60
|
*
|
|
59
|
-
*
|
|
60
|
-
* the
|
|
61
|
-
*
|
|
61
|
+
* The wheel over the frame zooms the picture inside it: it scales the window
|
|
62
|
+
* about the pointer, the ratio held, inside the image. One scroll is one
|
|
63
|
+
* write: the draft is handed to `onCommit` once the wheel has been quiet for
|
|
64
|
+
* a moment, or at once when a drag starts or the frame is left by Escape,
|
|
65
|
+
* Enter or a press elsewhere. A frame closed by anything else (the toolbar,
|
|
66
|
+
* the block leaving) drops a scroll still pending rather than write after it.
|
|
67
|
+
*
|
|
68
|
+
* Pointer and wheel events never reach the editor while the frame is open: a
|
|
69
|
+
* press on the frame would otherwise start a canvas drag or a page
|
|
70
|
+
* selection, a wheel would zoom or scroll the canvas. Escape, Enter or a
|
|
71
|
+
* press anywhere else calls `onExit`.
|
|
62
72
|
*/
|
|
63
73
|
let ImageCropOverlay = (() => {
|
|
64
74
|
let _classSuper = WithDisposable(LitElement);
|
|
@@ -94,12 +104,15 @@ let ImageCropOverlay = (() => {
|
|
|
94
104
|
this.#onExit_accessor_storage = (__runInitializers(this, _onCommit_extraInitializers), __runInitializers(this, _onExit_initializers, () => { }));
|
|
95
105
|
this.#draft_accessor_storage = (__runInitializers(this, _onExit_extraInitializers), __runInitializers(this, _draft_initializers, WHOLE_IMAGE));
|
|
96
106
|
this._dragging = (__runInitializers(this, _draft_extraInitializers), false);
|
|
107
|
+
/** The pending end of a wheel gesture, `null` when none is under way. */
|
|
108
|
+
this._wheelTimer = null;
|
|
97
109
|
/** Removes the listeners of the gesture in progress, if any. */
|
|
98
110
|
this._releaseGesture = null;
|
|
99
111
|
this._stop = (event) => event.stopPropagation();
|
|
100
112
|
this._onOutsidePointer = (event) => {
|
|
101
113
|
if (event.composedPath().includes(this))
|
|
102
114
|
return;
|
|
115
|
+
this._commitWheel();
|
|
103
116
|
this.onExit();
|
|
104
117
|
};
|
|
105
118
|
this._onKeydown = (event) => {
|
|
@@ -107,8 +120,31 @@ let ImageCropOverlay = (() => {
|
|
|
107
120
|
return;
|
|
108
121
|
event.preventDefault();
|
|
109
122
|
event.stopPropagation();
|
|
123
|
+
this._commitWheel();
|
|
110
124
|
this.onExit();
|
|
111
125
|
};
|
|
126
|
+
this._onWheel = (event) => {
|
|
127
|
+
event.preventDefault();
|
|
128
|
+
event.stopPropagation();
|
|
129
|
+
if (this._dragging)
|
|
130
|
+
return;
|
|
131
|
+
const { width, height, cos, sin, scale } = this._geometry();
|
|
132
|
+
if (width <= 0 || height <= 0)
|
|
133
|
+
return;
|
|
134
|
+
// The pointer in the source's normalised coordinates: the frame is the
|
|
135
|
+
// whole source, possibly rotated about its centre.
|
|
136
|
+
const box = this.getBoundingClientRect();
|
|
137
|
+
const cdx = event.clientX - (box.left + box.width / 2);
|
|
138
|
+
const cdy = event.clientY - (box.top + box.height / 2);
|
|
139
|
+
const px = ((cdx * cos + cdy * sin) / scale + width / 2) / width;
|
|
140
|
+
const py = ((-cdx * sin + cdy * cos) / scale + height / 2) / height;
|
|
141
|
+
// A line or page delta (Firefox) counts as one full step per unit.
|
|
142
|
+
const deltaY = event.deltaMode === 0 ? event.deltaY : event.deltaY * 100;
|
|
143
|
+
this.draft = zoomCrop(this.draft, cropWheelFactor(deltaY), Math.min(Math.max(px, 0), 1), Math.min(Math.max(py, 0), 1), this.ratio);
|
|
144
|
+
if (this._wheelTimer !== null)
|
|
145
|
+
clearTimeout(this._wheelTimer);
|
|
146
|
+
this._wheelTimer = setTimeout(() => this._commitWheel(), WHEEL_COMMIT_DELAY_MS);
|
|
147
|
+
};
|
|
112
148
|
}
|
|
113
149
|
static {
|
|
114
150
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
@@ -229,6 +265,20 @@ let ImageCropOverlay = (() => {
|
|
|
229
265
|
#draft_accessor_storage;
|
|
230
266
|
get draft() { return this.#draft_accessor_storage; }
|
|
231
267
|
set draft(value) { this.#draft_accessor_storage = value; }
|
|
268
|
+
/** Ends the wheel gesture under way, if any, with its one write. */
|
|
269
|
+
_commitWheel() {
|
|
270
|
+
if (this._wheelTimer === null)
|
|
271
|
+
return;
|
|
272
|
+
clearTimeout(this._wheelTimer);
|
|
273
|
+
this._wheelTimer = null;
|
|
274
|
+
this.onCommit(this.draft);
|
|
275
|
+
}
|
|
276
|
+
_dropWheel() {
|
|
277
|
+
if (this._wheelTimer === null)
|
|
278
|
+
return;
|
|
279
|
+
clearTimeout(this._wheelTimer);
|
|
280
|
+
this._wheelTimer = null;
|
|
281
|
+
}
|
|
232
282
|
/**
|
|
233
283
|
* The document-wide listeners (a press elsewhere, Escape, Enter) live only
|
|
234
284
|
* as long as this element: the frame is rendered while it is open and
|
|
@@ -237,15 +287,22 @@ let ImageCropOverlay = (() => {
|
|
|
237
287
|
connectedCallback() {
|
|
238
288
|
super.connectedCallback();
|
|
239
289
|
this.disposables.add(() => this._releaseGesture?.());
|
|
290
|
+
this.disposables.add(() => this._dropWheel());
|
|
240
291
|
this.disposables.addFromEvent(this, 'pointerdown', this._stop);
|
|
241
292
|
this.disposables.addFromEvent(this, 'click', this._stop);
|
|
242
293
|
this.disposables.addFromEvent(this, 'dblclick', this._stop);
|
|
294
|
+
this.disposables.addFromEvent(this, 'wheel', this._onWheel, {
|
|
295
|
+
passive: false,
|
|
296
|
+
});
|
|
243
297
|
this.disposables.addFromEvent(document, 'pointerdown', this._onOutsidePointer, true);
|
|
244
298
|
this.disposables.addFromEvent(document, 'keydown', this._onKeydown, true);
|
|
245
299
|
}
|
|
246
300
|
willUpdate(changed) {
|
|
247
|
-
if (changed.has('crop')
|
|
248
|
-
|
|
301
|
+
if (!changed.has('crop') || this._dragging)
|
|
302
|
+
return;
|
|
303
|
+
// A crop written meanwhile (a preset, a peer) wins over a pending scroll.
|
|
304
|
+
this._dropWheel();
|
|
305
|
+
this.draft = this.crop;
|
|
249
306
|
}
|
|
250
307
|
/**
|
|
251
308
|
* Client pixels per layout pixel, read from the rendered box: the canvas
|
|
@@ -267,6 +324,7 @@ let ImageCropOverlay = (() => {
|
|
|
267
324
|
return;
|
|
268
325
|
event.preventDefault();
|
|
269
326
|
event.stopPropagation();
|
|
327
|
+
this._commitWheel();
|
|
270
328
|
const start = this.draft;
|
|
271
329
|
const originX = event.clientX;
|
|
272
330
|
const originY = event.clientY;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { type ClipboardConfigCreationContext, EdgelessClipboardConfig, type PreparedClipboardBlock } from '../affine-block-surface/index.js';
|
|
2
2
|
import { type BlockSnapshot } from '../store/index.js';
|
|
3
3
|
export declare class EdgelessClipboardImageConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static readonly key = "affine:image";
|
|
5
|
-
|
|
5
|
+
prepare(image: BlockSnapshot): Promise<PreparedClipboardBlock | null>;
|
|
6
|
+
createBlock(image: BlockSnapshot, context: ClipboardConfigCreationContext): Promise<string | null>;
|
|
6
7
|
}
|
|
@@ -1,25 +1,31 @@
|
|
|
1
|
-
import { EdgelessClipboardConfig } from '../affine-block-surface/index.js';
|
|
1
|
+
import { EdgelessClipboardConfig, } from '../affine-block-surface/index.js';
|
|
2
2
|
import {} from '../store/index.js';
|
|
3
3
|
export class EdgelessClipboardImageConfig extends EdgelessClipboardConfig {
|
|
4
4
|
static { this.key = 'affine:image'; }
|
|
5
|
-
async
|
|
5
|
+
async prepare(image) {
|
|
6
6
|
const { xywh, rotate, sourceId, size, width, height, caption, crop } = image.props;
|
|
7
7
|
if (!this.surface)
|
|
8
8
|
return null;
|
|
9
9
|
if (!(await this.std.workspace.blobSync.get(sourceId))) {
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
const surfaceId = this.surface.model.id;
|
|
13
|
+
return {
|
|
14
|
+
write: () => this.crud.addBlock('affine:image', {
|
|
15
|
+
caption,
|
|
16
|
+
sourceId,
|
|
17
|
+
xywh,
|
|
18
|
+
rotate,
|
|
19
|
+
size,
|
|
20
|
+
width,
|
|
21
|
+
height,
|
|
22
|
+
// The box above is the cropped one: without its crop the copy
|
|
23
|
+
// would stretch the whole picture into it (ADR 0037).
|
|
24
|
+
crop,
|
|
25
|
+
}, surfaceId),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
createBlock(image, context) {
|
|
29
|
+
return this.createPreparedBlock(image, context);
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -148,6 +148,7 @@ let ImageBlockComponent = (() => {
|
|
|
148
148
|
this.resourceController.setEngine(this.std.store.blobSync);
|
|
149
149
|
this.disposables.add(this.resourceController.subscribe());
|
|
150
150
|
this.disposables.add(this.resourceController);
|
|
151
|
+
this.disposables.add(() => this.cropController.stop());
|
|
151
152
|
this.disposables.add(this.model.props.sourceId$.subscribe(() => {
|
|
152
153
|
this.refreshData();
|
|
153
154
|
}));
|
|
@@ -133,6 +133,9 @@ let ImageEdgelessBlockComponent = (() => {
|
|
|
133
133
|
this.resourceController.setEngine(this.std.store.blobSync);
|
|
134
134
|
this.disposables.add(this.resourceController.subscribe());
|
|
135
135
|
this.disposables.add(this.resourceController);
|
|
136
|
+
// A crop frame left open would keep the canvas locked and the image in
|
|
137
|
+
// editing state after the block is gone (ADR 0037, 2026-10-27).
|
|
138
|
+
this.disposables.add(() => this.cropController.stop());
|
|
136
139
|
this.disposables.add(this.model.props.sourceId$.subscribe(() => {
|
|
137
140
|
this.refreshData();
|
|
138
141
|
}));
|
|
@@ -6,6 +6,8 @@ export * from './image-block.js';
|
|
|
6
6
|
export * from './image-edgeless-block.js';
|
|
7
7
|
export * from './image-service.js';
|
|
8
8
|
export * from './image-spec.js';
|
|
9
|
+
export { imageReplaceCommands, REPLACE_IMAGE_WITH_IMAGE, REPLACE_IMAGE_WITH_SHAPE, REPLACE_SHAPE_WITH_IMAGE, } from './replace/commands.js';
|
|
10
|
+
export { replaceImageWithShape, replaceShapeWithImage, } from './replace/replace-model.js';
|
|
9
11
|
export * from './turbo/image-layout-handler.js';
|
|
10
12
|
export * from './turbo/image-painter.worker.js';
|
|
11
13
|
export { addImages, addSiblingImageBlocks, downloadImageBlob } from './utils.js';
|
|
@@ -6,6 +6,8 @@ export * from './image-block.js';
|
|
|
6
6
|
export * from './image-edgeless-block.js';
|
|
7
7
|
export * from './image-service.js';
|
|
8
8
|
export * from './image-spec.js';
|
|
9
|
+
export { imageReplaceCommands, REPLACE_IMAGE_WITH_IMAGE, REPLACE_IMAGE_WITH_SHAPE, REPLACE_SHAPE_WITH_IMAGE, } from './replace/commands.js';
|
|
10
|
+
export { replaceImageWithShape, replaceShapeWithImage, } from './replace/replace-model.js';
|
|
9
11
|
export * from './turbo/image-layout-handler.js';
|
|
10
12
|
export * from './turbo/image-painter.worker.js';
|
|
11
13
|
export { addImages, addSiblingImageBlocks, downloadImageBlob } from './utils.js';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ImageBlockModel, ShapeType } from '../../affine-model/index.js';
|
|
2
|
+
import type { AnyCommandDescriptor, BlockStdScope, CommandDescriptor } from '../../std/index.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
/**
|
|
5
|
+
* The replace commands (ADR 0044), `owner: 'core'`: a shape and an image
|
|
6
|
+
* belong to no framework. Registered from the image view extension, so they
|
|
7
|
+
* go with the `image` flag; the toolbar entries invoke them through
|
|
8
|
+
* `runCommand`, so the refusal, the one undo step and the telemetry live
|
|
9
|
+
* here, once.
|
|
10
|
+
*
|
|
11
|
+
* They EMIT FROM THEIR BODY (listed in `registry.unit.spec.ts`'s
|
|
12
|
+
* self-emitting commands): `CommandDescriptor.telemetry` maps onto the
|
|
13
|
+
* framework creation events, and whether anything was replaced is a fact of
|
|
14
|
+
* the invocation — a cancelled file chooser replaces nothing.
|
|
15
|
+
*/
|
|
16
|
+
export declare const replaceElementParams: z.ZodObject<{
|
|
17
|
+
elementId: z.ZodOptional<z.ZodString>;
|
|
18
|
+
}, "strip", z.ZodTypeAny, {
|
|
19
|
+
elementId?: string | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
elementId?: string | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type ReplaceElementParams = z.infer<typeof replaceElementParams>;
|
|
24
|
+
/**
|
|
25
|
+
* « Replace with shape » takes the shape picked in its sub-menu (ADR 0044,
|
|
26
|
+
* amendment of 2026-10-27). Both optional: absent, a plain rectangle, so the
|
|
27
|
+
* palette and the agent keep the v1 behaviour.
|
|
28
|
+
*/
|
|
29
|
+
export declare const replaceWithShapeParams: z.ZodObject<{
|
|
30
|
+
elementId: z.ZodOptional<z.ZodString>;
|
|
31
|
+
} & {
|
|
32
|
+
shapeType: z.ZodOptional<z.ZodNativeEnum<typeof ShapeType>>;
|
|
33
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
radius?: number | undefined;
|
|
36
|
+
shapeType?: ShapeType | undefined;
|
|
37
|
+
elementId?: string | undefined;
|
|
38
|
+
}, {
|
|
39
|
+
radius?: number | undefined;
|
|
40
|
+
shapeType?: ShapeType | undefined;
|
|
41
|
+
elementId?: string | undefined;
|
|
42
|
+
}>;
|
|
43
|
+
export type ReplaceWithShapeParams = z.infer<typeof replaceWithShapeParams>;
|
|
44
|
+
/** The shape the command would replace, or `null`. */
|
|
45
|
+
export declare function replaceableShape(std: BlockStdScope, params?: unknown): import("../../affine-model/index.js").ShapeElementModel | null;
|
|
46
|
+
/** The canvas image the command would replace, or `null`. */
|
|
47
|
+
export declare function replaceableImage(std: BlockStdScope, params?: unknown): ImageBlockModel | null;
|
|
48
|
+
/**
|
|
49
|
+
* The canvas image whose PICTURE the command would swap, or `null`. Looser
|
|
50
|
+
* than {@link replaceableImage}: the block stays (same id, caption and
|
|
51
|
+
* comments kept), so a captioned image may change its picture; a locked one
|
|
52
|
+
* may not.
|
|
53
|
+
*/
|
|
54
|
+
export declare function replaceablePicture(std: BlockStdScope, params?: unknown): ImageBlockModel | null;
|
|
55
|
+
export declare const REPLACE_SHAPE_WITH_IMAGE = "canvas.shape.replaceWithImage";
|
|
56
|
+
export declare const REPLACE_IMAGE_WITH_SHAPE = "canvas.image.replaceWithShape";
|
|
57
|
+
export declare const REPLACE_IMAGE_WITH_IMAGE = "canvas.image.replaceWithImage";
|
|
58
|
+
export declare const replaceShapeWithImageCommand: CommandDescriptor<ReplaceElementParams>;
|
|
59
|
+
export declare const replaceImageWithShapeCommand: CommandDescriptor<ReplaceWithShapeParams>;
|
|
60
|
+
/**
|
|
61
|
+
* « Replace with image » on a canvas IMAGE (ADR 0044, amendment of
|
|
62
|
+
* 2026-10-27): another picture in the same block, from the host's library
|
|
63
|
+
* when there is one, from the system file chooser otherwise — so the entry
|
|
64
|
+
* exists without a host. The block keeps its id, corner, width and caption
|
|
65
|
+
* (`replaceImageSource`); it reports `ElementReplaced { image → image }`.
|
|
66
|
+
*/
|
|
67
|
+
export declare const replaceImageWithImageCommand: CommandDescriptor<ReplaceElementParams>;
|
|
68
|
+
export declare const imageReplaceCommands: AnyCommandDescriptor[];
|