@formicoidea/labre-core 0.50.0 → 0.52.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.
Files changed (210) hide show
  1. package/dist/_pkgs/affine-block-attachment/asset-picker.d.ts +24 -0
  2. package/dist/_pkgs/affine-block-attachment/asset-picker.js +87 -0
  3. package/dist/_pkgs/affine-block-attachment/configs/slash-menu.js +3 -20
  4. package/dist/_pkgs/affine-block-attachment/index.d.ts +1 -0
  5. package/dist/_pkgs/affine-block-attachment/index.js +1 -0
  6. package/dist/_pkgs/affine-block-attachment/utils.d.ts +9 -1
  7. package/dist/_pkgs/affine-block-attachment/utils.js +9 -0
  8. package/dist/_pkgs/affine-block-bookmark/adapters/markdown/markdown.js +14 -1
  9. package/dist/_pkgs/affine-block-bookmark/adapters/notion-html.js +5 -1
  10. package/dist/_pkgs/affine-block-database/adapters/markdown.js +5 -3
  11. package/dist/_pkgs/affine-block-embed/common/adapters/html.js +5 -3
  12. package/dist/_pkgs/affine-block-embed/common/adapters/markdown.js +11 -0
  13. package/dist/_pkgs/affine-block-frame/frame-template.d.ts +58 -0
  14. package/dist/_pkgs/affine-block-frame/frame-template.js +207 -0
  15. package/dist/_pkgs/affine-block-frame/frame-toolbar.js +19 -3
  16. package/dist/_pkgs/affine-block-frame/index.d.ts +1 -0
  17. package/dist/_pkgs/affine-block-frame/index.js +1 -0
  18. package/dist/_pkgs/affine-block-frame/translations.d.ts +7 -0
  19. package/dist/_pkgs/affine-block-frame/translations.js +16 -1
  20. package/dist/_pkgs/affine-block-frame/view.js +6 -0
  21. package/dist/_pkgs/affine-block-image/asset-picker.d.ts +63 -0
  22. package/dist/_pkgs/affine-block-image/asset-picker.js +183 -0
  23. package/dist/_pkgs/affine-block-image/commands/insert-images.d.ts +5 -0
  24. package/dist/_pkgs/affine-block-image/commands/insert-images.js +8 -8
  25. package/dist/_pkgs/affine-block-image/components/page-image-block.d.ts +11 -0
  26. package/dist/_pkgs/affine-block-image/components/page-image-block.js +81 -12
  27. package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +9 -0
  28. package/dist/_pkgs/affine-block-image/configs/replace-action.js +27 -0
  29. package/dist/_pkgs/affine-block-image/configs/toolbar.js +6 -0
  30. package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +46 -0
  31. package/dist/_pkgs/affine-block-image/crop/crop-controller.js +104 -0
  32. package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +70 -0
  33. package/dist/_pkgs/affine-block-image/crop/crop-math.js +141 -0
  34. package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +57 -0
  35. package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +343 -0
  36. package/dist/_pkgs/affine-block-image/crop/crop-toolbar.d.ts +12 -0
  37. package/dist/_pkgs/affine-block-image/crop/crop-toolbar.js +78 -0
  38. package/dist/_pkgs/affine-block-image/crop/write-crop.d.ts +16 -0
  39. package/dist/_pkgs/affine-block-image/crop/write-crop.js +57 -0
  40. package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +4 -1
  41. package/dist/_pkgs/affine-block-image/effects.js +2 -0
  42. package/dist/_pkgs/affine-block-image/image-block.d.ts +2 -0
  43. package/dist/_pkgs/affine-block-image/image-block.js +2 -0
  44. package/dist/_pkgs/affine-block-image/image-edgeless-block.d.ts +2 -0
  45. package/dist/_pkgs/affine-block-image/image-edgeless-block.js +36 -8
  46. package/dist/_pkgs/affine-block-image/image-resize-manager.js +15 -0
  47. package/dist/_pkgs/affine-block-image/index.d.ts +1 -0
  48. package/dist/_pkgs/affine-block-image/index.js +1 -0
  49. package/dist/_pkgs/affine-block-image/translations.d.ts +15 -0
  50. package/dist/_pkgs/affine-block-image/translations.js +43 -0
  51. package/dist/_pkgs/affine-block-image/utils.d.ts +13 -0
  52. package/dist/_pkgs/affine-block-image/utils.js +10 -1
  53. package/dist/_pkgs/affine-block-root/clipboard/page-clipboard.js +5 -0
  54. package/dist/_pkgs/affine-block-root/commands/page-export-commands.d.ts +2 -0
  55. package/dist/_pkgs/affine-block-root/commands/page-export-commands.js +71 -0
  56. package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
  57. package/dist/_pkgs/affine-block-root/index.js +1 -0
  58. package/dist/_pkgs/affine-block-root/view.js +8 -0
  59. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/capability.d.ts +30 -0
  60. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/capability.js +44 -0
  61. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/colors.d.ts +26 -0
  62. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/colors.js +82 -0
  63. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/command.d.ts +18 -0
  64. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/command.js +91 -0
  65. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/index.d.ts +3 -0
  66. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/index.js +3 -0
  67. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/writer.d.ts +50 -0
  68. package/dist/_pkgs/affine-block-surface/extensions/drawio-export/writer.js +732 -0
  69. package/dist/_pkgs/affine-block-surface/extensions/export-manager/draw-image-block.d.ts +12 -0
  70. package/dist/_pkgs/affine-block-surface/extensions/export-manager/draw-image-block.js +15 -0
  71. package/dist/_pkgs/affine-block-surface/extensions/export-manager/export-manager.js +7 -1
  72. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.d.ts +7 -1
  73. package/dist/_pkgs/affine-block-surface/extensions/export-svg/command.js +60 -1
  74. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.d.ts +2 -2
  75. package/dist/_pkgs/affine-block-surface/extensions/export-svg/index.js +2 -2
  76. package/dist/_pkgs/affine-block-surface/extensions/export-svg/marker-version.d.ts +6 -0
  77. package/dist/_pkgs/affine-block-surface/extensions/export-svg/marker-version.js +8 -0
  78. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.d.ts +28 -1
  79. package/dist/_pkgs/affine-block-surface/extensions/export-svg/render.js +66 -6
  80. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.d.ts +2 -7
  81. package/dist/_pkgs/affine-block-surface/extensions/export-svg/svg-context.js +2 -6
  82. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +2 -0
  83. package/dist/_pkgs/affine-block-surface/extensions/index.js +2 -0
  84. package/dist/_pkgs/affine-block-surface/extensions/interchange-export.d.ts +84 -0
  85. package/dist/_pkgs/affine-block-surface/extensions/interchange-export.js +150 -0
  86. package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +24 -2
  87. package/dist/_pkgs/affine-block-surface/extensions/interchange.d.ts +23 -2
  88. package/dist/_pkgs/affine-block-surface/extensions/interchange.js +4 -1
  89. package/dist/_pkgs/affine-block-surface/extensions/legend-role.d.ts +18 -0
  90. package/dist/_pkgs/affine-block-surface/extensions/legend-role.js +20 -0
  91. package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +2 -19
  92. package/dist/_pkgs/affine-block-surface/extensions/legend.js +2 -18
  93. package/dist/_pkgs/affine-block-surface/extensions/svg-sanitize.d.ts +67 -0
  94. package/dist/_pkgs/affine-block-surface/extensions/svg-sanitize.js +235 -0
  95. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.d.ts +1 -0
  96. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch-translations.js +9 -0
  97. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.d.ts +17 -13
  98. package/dist/_pkgs/affine-block-surface/extensions/svg-sketch.js +52 -80
  99. package/dist/_pkgs/affine-block-surface/extensions/xml-element.d.ts +98 -0
  100. package/dist/_pkgs/affine-block-surface/extensions/xml-element.js +261 -0
  101. package/dist/_pkgs/affine-block-surface/extensions/xml-reader.d.ts +238 -0
  102. package/dist/_pkgs/affine-block-surface/extensions/xml-reader.js +570 -0
  103. package/dist/_pkgs/affine-block-surface/framework-background/def.js +1 -1
  104. package/dist/_pkgs/affine-block-surface/index.d.ts +1 -0
  105. package/dist/_pkgs/affine-block-surface/index.js +1 -0
  106. package/dist/_pkgs/affine-block-surface/interchange-headless.d.ts +29 -0
  107. package/dist/_pkgs/affine-block-surface/interchange-headless.js +32 -0
  108. package/dist/_pkgs/affine-block-surface/view.js +22 -2
  109. package/dist/_pkgs/affine-block-table/adapters/utils.js +24 -1
  110. package/dist/_pkgs/affine-gfx-note/toolbar/note-menu.js +5 -8
  111. package/dist/_pkgs/affine-gfx-template/contribute.d.ts +14 -4
  112. package/dist/_pkgs/affine-gfx-template/contribute.js +47 -6
  113. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +7 -2
  114. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +14 -40
  115. package/dist/_pkgs/affine-gfx-template/toolbar/resolve-name.d.ts +1 -1
  116. package/dist/_pkgs/affine-gfx-template/toolbar/resolve-name.js +1 -1
  117. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.d.ts +4 -4
  118. package/dist/_pkgs/affine-gfx-template/toolbar/template-panel.js +9 -9
  119. package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +2 -4
  120. package/dist/_pkgs/affine-gfx-template/translations.d.ts +5 -0
  121. package/dist/_pkgs/affine-gfx-template/translations.js +9 -0
  122. package/dist/_pkgs/affine-inline-footnote/adapters/markdown/inline-delta.js +6 -0
  123. package/dist/_pkgs/affine-inline-footnote/adapters/markdown/markdown-inline.js +7 -0
  124. package/dist/_pkgs/affine-inline-link/adapters/html/html-inline.js +4 -1
  125. package/dist/_pkgs/affine-inline-link/adapters/html/inline-delta.js +3 -1
  126. package/dist/_pkgs/affine-inline-link/adapters/markdown/inline-delta.js +4 -1
  127. package/dist/_pkgs/affine-inline-link/adapters/notion-html/html-inline.js +2 -1
  128. package/dist/_pkgs/affine-inline-link/link-node/affine-link.d.ts +7 -0
  129. package/dist/_pkgs/affine-inline-link/link-node/affine-link.js +37 -0
  130. package/dist/_pkgs/affine-inline-link/link-node/index.d.ts +1 -0
  131. package/dist/_pkgs/affine-inline-link/link-node/index.js +1 -0
  132. package/dist/_pkgs/affine-inline-link/link-node/propose-views.d.ts +22 -0
  133. package/dist/_pkgs/affine-inline-link/link-node/propose-views.js +59 -0
  134. package/dist/_pkgs/affine-model/blocks/image/image-crop.d.ts +48 -0
  135. package/dist/_pkgs/affine-model/blocks/image/image-crop.js +78 -0
  136. package/dist/_pkgs/affine-model/blocks/image/image-model.d.ts +6 -0
  137. package/dist/_pkgs/affine-model/blocks/image/image-model.js +2 -0
  138. package/dist/_pkgs/affine-model/blocks/image/index.d.ts +1 -0
  139. package/dist/_pkgs/affine-model/blocks/image/index.js +1 -0
  140. package/dist/_pkgs/affine-model/consts/shape.d.ts +2 -0
  141. package/dist/_pkgs/affine-model/consts/shape.js +5 -0
  142. package/dist/_pkgs/affine-model/elements/bpmn/consts.d.ts +31 -0
  143. package/dist/_pkgs/affine-model/elements/bpmn/consts.js +31 -0
  144. package/dist/_pkgs/affine-model/elements/bpmn/index.d.ts +1 -0
  145. package/dist/_pkgs/affine-model/elements/bpmn/index.js +1 -0
  146. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +0 -25
  147. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +1 -25
  148. package/dist/_pkgs/affine-model/elements/shape/shape.d.ts +0 -2
  149. package/dist/_pkgs/affine-model/elements/shape/shape.js +1 -2
  150. package/dist/_pkgs/affine-model/elements/uml/consts.d.ts +133 -0
  151. package/dist/_pkgs/affine-model/elements/uml/consts.js +107 -0
  152. package/dist/_pkgs/affine-model/elements/uml/diagram.d.ts +1 -79
  153. package/dist/_pkgs/affine-model/elements/uml/diagram.js +1 -53
  154. package/dist/_pkgs/affine-model/elements/uml/fragment.d.ts +0 -15
  155. package/dist/_pkgs/affine-model/elements/uml/fragment.js +1 -15
  156. package/dist/_pkgs/affine-model/elements/uml/index.d.ts +1 -0
  157. package/dist/_pkgs/affine-model/elements/uml/index.js +1 -0
  158. package/dist/_pkgs/affine-model/elements/uml/partition.d.ts +0 -20
  159. package/dist/_pkgs/affine-model/elements/uml/partition.js +1 -20
  160. package/dist/_pkgs/affine-model/elements/uml/region.d.ts +0 -11
  161. package/dist/_pkgs/affine-model/elements/uml/region.js +1 -11
  162. package/dist/_pkgs/affine-model/headless.d.ts +19 -0
  163. package/dist/_pkgs/affine-model/headless.js +19 -0
  164. package/dist/_pkgs/affine-shared/headless.d.ts +10 -0
  165. package/dist/_pkgs/affine-shared/headless.js +10 -0
  166. package/dist/_pkgs/affine-shared/services/asset-picker-service.d.ts +63 -0
  167. package/dist/_pkgs/affine-shared/services/asset-picker-service.js +20 -0
  168. package/dist/_pkgs/affine-shared/services/frame-template-service.d.ts +83 -0
  169. package/dist/_pkgs/affine-shared/services/frame-template-service.js +17 -0
  170. package/dist/_pkgs/affine-shared/services/index.d.ts +3 -0
  171. package/dist/_pkgs/affine-shared/services/index.js +3 -0
  172. package/dist/_pkgs/affine-shared/services/thread-marks-service.d.ts +69 -0
  173. package/dist/_pkgs/affine-shared/services/thread-marks-service.js +20 -0
  174. package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +6 -0
  175. package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +10 -0
  176. package/dist/_pkgs/affine-widget-drag-handle/watchers/drag-event-watcher.js +8 -3
  177. package/dist/_pkgs/affine-widget-keyboard-toolbar/config.js +4 -16
  178. package/dist/_pkgs/affine-widget-linked-doc/transformers/html.d.ts +7 -0
  179. package/dist/_pkgs/affine-widget-linked-doc/transformers/html.js +25 -24
  180. package/dist/_pkgs/affine-widget-linked-doc/transformers/index.d.ts +1 -1
  181. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.d.ts +7 -0
  182. package/dist/_pkgs/affine-widget-linked-doc/transformers/markdown.js +26 -25
  183. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.d.ts +23 -0
  184. package/dist/_pkgs/affine-widget-linked-doc/transformers/utils.js +14 -0
  185. package/dist/_pkgs/affine-widget-thread-marks/effects.d.ts +1 -0
  186. package/dist/_pkgs/affine-widget-thread-marks/effects.js +4 -0
  187. package/dist/_pkgs/affine-widget-thread-marks/excerpt.d.ts +19 -0
  188. package/dist/_pkgs/affine-widget-thread-marks/excerpt.js +68 -0
  189. package/dist/_pkgs/affine-widget-thread-marks/index.d.ts +5 -0
  190. package/dist/_pkgs/affine-widget-thread-marks/index.js +8 -0
  191. package/dist/_pkgs/affine-widget-thread-marks/toolbar.d.ts +49 -0
  192. package/dist/_pkgs/affine-widget-thread-marks/toolbar.js +108 -0
  193. package/dist/_pkgs/affine-widget-thread-marks/translations.d.ts +9 -0
  194. package/dist/_pkgs/affine-widget-thread-marks/translations.js +11 -0
  195. package/dist/_pkgs/affine-widget-thread-marks/view.d.ts +12 -0
  196. package/dist/_pkgs/affine-widget-thread-marks/view.js +25 -0
  197. package/dist/_pkgs/affine-widget-thread-marks/widget.d.ts +51 -0
  198. package/dist/_pkgs/affine-widget-thread-marks/widget.js +214 -0
  199. package/dist/commands.js +5 -2
  200. package/dist/extensions/view.js +2 -0
  201. package/dist/host-panels.d.ts +24 -1
  202. package/dist/host-panels.js +61 -10
  203. package/dist/interchange.d.ts +1 -0
  204. package/dist/interchange.js +1 -0
  205. package/dist/model/headless.d.ts +1 -0
  206. package/dist/model/headless.js +1 -0
  207. package/dist/shared/headless.d.ts +1 -0
  208. package/dist/shared/headless.js +1 -0
  209. package/dist/translations.js +10 -1
  210. package/package.json +13 -1
@@ -0,0 +1,104 @@
1
+ import { readImageCrop, } from '../../affine-model/index.js';
2
+ import { Bound } from '../../global/gfx/index.js';
3
+ import { computed, signal } from '@preact/signals-core';
4
+ import { html, nothing } from 'lit';
5
+ import { styleMap } from 'lit/directives/style-map.js';
6
+ import { maskRatio, presetCrop, WHOLE_IMAGE, wholeImageFrame, } from './crop-math.js';
7
+ import { writeImageCrop } from './write-crop.js';
8
+ /**
9
+ * The « Rogner » state of one image block (ADR 0037), shared by the page and
10
+ * the canvas components: which preset the crop frame is open on, if any, and
11
+ * the gestures that write. The frame is local UI and never stored.
12
+ */
13
+ export class ImageCropController {
14
+ constructor(_block, _onCanvas) {
15
+ this._block = _block;
16
+ this._onCanvas = _onCanvas;
17
+ /** The mask the crop frame is open on, `null` when it is closed. */
18
+ this.editing$ = signal(null);
19
+ this.crop$ = computed(() => readImageCrop(this._block.model.props.crop$.value));
20
+ }
21
+ /**
22
+ * The source's proportions: the loaded `<img>`'s pixel size, else what the
23
+ * block stores. Only the ratio matters to the crop, and an SVG without an
24
+ * intrinsic size loads with none: a canvas box is the cropped share of the
25
+ * whole picture, a page `width`/`height` is the whole picture.
26
+ */
27
+ natural() {
28
+ const img = this._block.querySelector('img.drag-target');
29
+ if (img?.naturalWidth && img.naturalHeight) {
30
+ return { width: img.naturalWidth, height: img.naturalHeight };
31
+ }
32
+ const { model } = this._block;
33
+ const crop = this.crop$.peek() ?? WHOLE_IMAGE;
34
+ if (this._onCanvas) {
35
+ const bound = Bound.deserialize(model.xywh);
36
+ if (bound.w <= 0 || bound.h <= 0)
37
+ return null;
38
+ return { width: bound.w / crop.w, height: bound.h / crop.h };
39
+ }
40
+ const { width, height } = model.props;
41
+ return width && height ? { width, height } : null;
42
+ }
43
+ /**
44
+ * Open the frame on a preset. A ratio preset first writes its largest
45
+ * centred window — unless the crop already uses that preset, which keeps
46
+ * the author's adjustment. Free opens on the current crop and writes
47
+ * nothing until a drag.
48
+ */
49
+ choose(mask) {
50
+ const { model } = this._block;
51
+ if (model.store.readonly)
52
+ return;
53
+ if (mask !== 'free' && this.crop$.peek()?.mask !== mask) {
54
+ const natural = this.natural();
55
+ if (!natural)
56
+ return;
57
+ this.commit(presetCrop(mask, natural.width, natural.height), mask);
58
+ }
59
+ this.editing$.value = mask;
60
+ }
61
+ commit(rect, mask = this.editing$.peek() ?? 'free') {
62
+ return writeImageCrop(this._block.model, rect, mask, this._onCanvas);
63
+ }
64
+ /** « Image d'origine »: removes the crop; the bytes never changed. */
65
+ restoreOriginal() {
66
+ this.editing$.value = null;
67
+ return writeImageCrop(this._block.model, undefined, 'free', this._onCanvas);
68
+ }
69
+ stop() {
70
+ this.editing$.value = null;
71
+ }
72
+ /** The frame, or nothing when it is closed or the page is readonly. */
73
+ renderOverlay(src, rotate = 0) {
74
+ const mask = this.editing$.value;
75
+ if (mask === null || !src || this._block.model.store.readonly) {
76
+ return nothing;
77
+ }
78
+ const crop = this.crop$.value ?? WHOLE_IMAGE;
79
+ const natural = this.natural();
80
+ const ratio = natural
81
+ ? maskRatio(mask, natural.width, natural.height)
82
+ : null;
83
+ return html `<affine-image-crop-overlay
84
+ data-testid="image-crop-overlay"
85
+ style=${styleMap(wholeImageFrame(crop))}
86
+ .src=${src}
87
+ .crop=${crop}
88
+ .ratio=${ratio}
89
+ .rotate=${rotate}
90
+ .onCommit=${(rect) => {
91
+ this.commit(rect);
92
+ }}
93
+ .onExit=${() => this.stop()}
94
+ ></affine-image-crop-overlay>`;
95
+ }
96
+ }
97
+ /** Inline styles of an `<img>` showing `crop` of its source in its box. */
98
+ export function croppedImageStyle(crop) {
99
+ return styleMap({
100
+ position: 'absolute',
101
+ maxWidth: 'none',
102
+ ...wholeImageFrame(crop),
103
+ });
104
+ }
@@ -0,0 +1,70 @@
1
+ import { type ImageCrop, type ImageCropMask } from '../../affine-model/index.js';
2
+ /** A crop rectangle without its mask, normalised to the source (ADR 0037). */
3
+ export type CropRect = Pick<ImageCrop, 'x' | 'y' | 'w' | 'h'>;
4
+ export type CropCorner = 'nw' | 'ne' | 'sw' | 'se';
5
+ export declare const WHOLE_IMAGE: CropRect;
6
+ /**
7
+ * The normalised `w / h` a mask holds on a source of this size, or `null`
8
+ * when the crop is free or the size is unknown. A 16:9 window on a portrait
9
+ * photo is much wider in normalised units than in pixels.
10
+ */
11
+ export declare function maskRatio(mask: ImageCropMask, naturalWidth: number, naturalHeight: number): number | null;
12
+ /**
13
+ * The largest centred rectangle of the mask's ratio: what choosing a preset
14
+ * writes before the author adjusts it. Free is the whole image.
15
+ */
16
+ export declare function presetCrop(mask: ImageCropMask, naturalWidth: number, naturalHeight: number): CropRect;
17
+ /** The window dragged by a normalised delta, kept inside the image. */
18
+ export declare function moveCrop(start: CropRect, dx: number, dy: number): CropRect;
19
+ /**
20
+ * The window resized by dragging one corner, the opposite corner pinned.
21
+ * With a ratio `k` (normalised `w / h`), the window grows to cover the pointer
22
+ * and then shrinks to fit the image, so it never leaves the source.
23
+ */
24
+ export declare function resizeCrop(start: CropRect, corner: CropCorner, dx: number, dy: number, k: number | null): CropRect;
25
+ export declare function sameCropRect(a: CropRect, b: CropRect): boolean;
26
+ /**
27
+ * The canvas box once the crop changes from `from` to `to`, for a block whose
28
+ * box shows `from`: the picture keeps its scale and the kept part stays where
29
+ * it was on the canvas. The box rotates about its centre (`rotate` degrees,
30
+ * CSS direction), so the shift is rotated before it is applied.
31
+ */
32
+ export declare function cropBoundFor(bound: {
33
+ x: number;
34
+ y: number;
35
+ w: number;
36
+ h: number;
37
+ }, rotate: number, from: CropRect, to: CropRect): {
38
+ x: number;
39
+ y: number;
40
+ w: number;
41
+ h: number;
42
+ };
43
+ /**
44
+ * The stored page `width`/`height` of a cropped image whose window was
45
+ * resized to `box`: the WHOLE picture's size (ADR 0037), never the window's.
46
+ * The height follows the source's proportions when they are known; an SVG
47
+ * with no intrinsic size, or a picture not loaded yet, scales the window's
48
+ * own height instead — writing the window itself would shrink the image on
49
+ * every resize.
50
+ */
51
+ export declare function wholeImageSize(box: {
52
+ w: number;
53
+ h: number;
54
+ }, crop: CropRect, natural: {
55
+ width: number;
56
+ height: number;
57
+ } | null): {
58
+ width: number;
59
+ height: number;
60
+ };
61
+ /**
62
+ * Where the WHOLE source sits relative to a box showing `crop`, as CSS
63
+ * percentages of that box: the cropped `<img>` and the crop frame both use it.
64
+ */
65
+ export declare function wholeImageFrame(crop: CropRect): {
66
+ left: string;
67
+ top: string;
68
+ width: string;
69
+ height: string;
70
+ };
@@ -0,0 +1,141 @@
1
+ import { IMAGE_CROP_MIN_SIDE, } from '../../affine-model/index.js';
2
+ export const WHOLE_IMAGE = { x: 0, y: 0, w: 1, h: 1 };
3
+ /** Width over height, in source pixels, each preset keeps. */
4
+ const MASK_RATIOS = {
5
+ '16:9': 16 / 9,
6
+ '4:3': 4 / 3,
7
+ '1:1': 1,
8
+ };
9
+ const EPSILON = 1e-6;
10
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
11
+ /**
12
+ * The normalised `w / h` a mask holds on a source of this size, or `null`
13
+ * when the crop is free or the size is unknown. A 16:9 window on a portrait
14
+ * photo is much wider in normalised units than in pixels.
15
+ */
16
+ export function maskRatio(mask, naturalWidth, naturalHeight) {
17
+ if (mask === 'free' || naturalWidth <= 0 || naturalHeight <= 0)
18
+ return null;
19
+ return (MASK_RATIOS[mask] * naturalHeight) / naturalWidth;
20
+ }
21
+ /**
22
+ * The largest centred rectangle of the mask's ratio: what choosing a preset
23
+ * writes before the author adjusts it. Free is the whole image.
24
+ */
25
+ export function presetCrop(mask, naturalWidth, naturalHeight) {
26
+ const k = maskRatio(mask, naturalWidth, naturalHeight);
27
+ if (k === null)
28
+ return WHOLE_IMAGE;
29
+ let w = k;
30
+ let h = 1;
31
+ if (w > 1) {
32
+ w = 1;
33
+ h = 1 / k;
34
+ }
35
+ return { x: (1 - w) / 2, y: (1 - h) / 2, w, h };
36
+ }
37
+ /** The window dragged by a normalised delta, kept inside the image. */
38
+ export function moveCrop(start, dx, dy) {
39
+ return {
40
+ ...start,
41
+ x: clamp(start.x + dx, 0, 1 - start.w),
42
+ y: clamp(start.y + dy, 0, 1 - start.h),
43
+ };
44
+ }
45
+ /**
46
+ * The window resized by dragging one corner, the opposite corner pinned.
47
+ * With a ratio `k` (normalised `w / h`), the window grows to cover the pointer
48
+ * and then shrinks to fit the image, so it never leaves the source.
49
+ */
50
+ export function resizeCrop(start, corner, dx, dy, k) {
51
+ const west = corner === 'nw' || corner === 'sw';
52
+ const north = corner === 'nw' || corner === 'ne';
53
+ const anchorX = west ? start.x + start.w : start.x;
54
+ const anchorY = north ? start.y + start.h : start.y;
55
+ const pointerX = (west ? start.x : start.x + start.w) + dx;
56
+ const pointerY = (north ? start.y : start.y + start.h) + dy;
57
+ const maxW = west ? anchorX : 1 - anchorX;
58
+ const maxH = north ? anchorY : 1 - anchorY;
59
+ const min = IMAGE_CROP_MIN_SIDE;
60
+ let w = clamp(west ? anchorX - pointerX : pointerX - anchorX, min, maxW);
61
+ let h = clamp(north ? anchorY - pointerY : pointerY - anchorY, min, maxH);
62
+ if (k !== null) {
63
+ if (w / k > h)
64
+ h = w / k;
65
+ else
66
+ w = h * k;
67
+ if (w > maxW) {
68
+ w = maxW;
69
+ h = w / k;
70
+ }
71
+ if (h > maxH) {
72
+ h = maxH;
73
+ w = h * k;
74
+ }
75
+ if (w < min) {
76
+ w = min;
77
+ h = w / k;
78
+ }
79
+ if (h < min) {
80
+ h = min;
81
+ w = h * k;
82
+ }
83
+ }
84
+ return {
85
+ x: west ? anchorX - w : anchorX,
86
+ y: north ? anchorY - h : anchorY,
87
+ w,
88
+ h,
89
+ };
90
+ }
91
+ export function sameCropRect(a, b) {
92
+ return (Math.abs(a.x - b.x) < EPSILON &&
93
+ Math.abs(a.y - b.y) < EPSILON &&
94
+ Math.abs(a.w - b.w) < EPSILON &&
95
+ Math.abs(a.h - b.h) < EPSILON);
96
+ }
97
+ /**
98
+ * The canvas box once the crop changes from `from` to `to`, for a block whose
99
+ * box shows `from`: the picture keeps its scale and the kept part stays where
100
+ * it was on the canvas. The box rotates about its centre (`rotate` degrees,
101
+ * CSS direction), so the shift is rotated before it is applied.
102
+ */
103
+ export function cropBoundFor(bound, rotate, from, to) {
104
+ const scaleX = bound.w / from.w;
105
+ const scaleY = bound.h / from.h;
106
+ const w = to.w * scaleX;
107
+ const h = to.h * scaleY;
108
+ const dx = (to.x - from.x) * scaleX + w / 2 - bound.w / 2;
109
+ const dy = (to.y - from.y) * scaleY + h / 2 - bound.h / 2;
110
+ const t = (rotate * Math.PI) / 180;
111
+ const cx = bound.x + bound.w / 2 + dx * Math.cos(t) - dy * Math.sin(t);
112
+ const cy = bound.y + bound.h / 2 + dx * Math.sin(t) + dy * Math.cos(t);
113
+ return { x: cx - w / 2, y: cy - h / 2, w, h };
114
+ }
115
+ /**
116
+ * The stored page `width`/`height` of a cropped image whose window was
117
+ * resized to `box`: the WHOLE picture's size (ADR 0037), never the window's.
118
+ * The height follows the source's proportions when they are known; an SVG
119
+ * with no intrinsic size, or a picture not loaded yet, scales the window's
120
+ * own height instead — writing the window itself would shrink the image on
121
+ * every resize.
122
+ */
123
+ export function wholeImageSize(box, crop, natural) {
124
+ const width = box.w / crop.w;
125
+ return {
126
+ width,
127
+ height: natural ? (width * natural.height) / natural.width : box.h / crop.h,
128
+ };
129
+ }
130
+ /**
131
+ * Where the WHOLE source sits relative to a box showing `crop`, as CSS
132
+ * percentages of that box: the cropped `<img>` and the crop frame both use it.
133
+ */
134
+ export function wholeImageFrame(crop) {
135
+ return {
136
+ left: `${(-crop.x / crop.w) * 100}%`,
137
+ top: `${(-crop.y / crop.h) * 100}%`,
138
+ width: `${100 / crop.w}%`,
139
+ height: `${100 / crop.h}%`,
140
+ };
141
+ }
@@ -0,0 +1,57 @@
1
+ import { LitElement, type PropertyValues } from 'lit';
2
+ import { type CropRect } from './crop-math.js';
3
+ declare const ImageCropOverlay_base: typeof LitElement & import("../../global/utils/types.js").Constructor<import("../../global/lit/with-disposable.js").DisposableClass>;
4
+ /**
5
+ * The crop frame (ADR 0037): the WHOLE source, laid over the block at the
6
+ * place it would occupy uncropped (the parent sizes this element with
7
+ * `wholeImageFrame`), dimmed outside the window being edited.
8
+ *
9
+ * Dragging the window moves it, dragging a corner resizes it, the ratio held
10
+ * when `ratio` is set. The draft lives here while the pointer is down; the
11
+ * release hands it to `onCommit` once — one gesture, one write, one undo
12
+ * step, decided by the caller (`writeImageCrop`).
13
+ *
14
+ * Pointer events never reach the editor while the frame is open: a press on
15
+ * the frame would otherwise start a canvas drag or a page selection. Escape,
16
+ * Enter or a press anywhere else calls `onExit`.
17
+ */
18
+ export declare class ImageCropOverlay extends ImageCropOverlay_base {
19
+ static styles: import("lit").CSSResult;
20
+ accessor src: string;
21
+ /** The stored crop the frame opens on; the whole image when uncropped. */
22
+ accessor crop: CropRect;
23
+ /** Normalised `w / h` to hold while resizing, `null` for a free crop. */
24
+ accessor ratio: number | null;
25
+ /** The block's rotation in degrees (canvas only), for pointer deltas. */
26
+ accessor rotate: number;
27
+ accessor onCommit: (rect: CropRect) => void;
28
+ accessor onExit: () => void;
29
+ accessor draft: CropRect;
30
+ private _dragging;
31
+ /** Removes the listeners of the gesture in progress, if any. */
32
+ private _releaseGesture;
33
+ private readonly _stop;
34
+ private readonly _onOutsidePointer;
35
+ private readonly _onKeydown;
36
+ /**
37
+ * The document-wide listeners (a press elsewhere, Escape, Enter) live only
38
+ * as long as this element: the frame is rendered while it is open and
39
+ * removed when it closes, which disposes them.
40
+ */
41
+ connectedCallback(): void;
42
+ willUpdate(changed: PropertyValues<this>): void;
43
+ /**
44
+ * Client pixels per layout pixel, read from the rendered box: the canvas
45
+ * zoom and any CSS scale, without asking the viewport. The bounding box of
46
+ * a rotated element is wider than the element, hence the trigonometry.
47
+ */
48
+ private _geometry;
49
+ private _startGesture;
50
+ render(): import("lit-html").TemplateResult<1>;
51
+ }
52
+ declare global {
53
+ interface HTMLElementTagNameMap {
54
+ 'affine-image-crop-overlay': ImageCropOverlay;
55
+ }
56
+ }
57
+ export {};