@jvs-milkdown/components 1.2.0 → 1.2.2

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 (139) hide show
  1. package/lib/code-block/index.js +37 -2
  2. package/lib/code-block/index.js.map +1 -1
  3. package/lib/image-block/index.js +722 -137
  4. package/lib/image-block/index.js.map +1 -1
  5. package/lib/table-block/index.js +67 -44
  6. package/lib/table-block/index.js.map +1 -1
  7. package/lib/tsconfig.tsbuildinfo +1 -1
  8. package/package.json +10 -10
  9. package/src/code-block/config.ts +4 -0
  10. package/src/code-block/view/components/code-block.tsx +24 -0
  11. package/src/code-block/view/node-view.ts +15 -0
  12. package/src/image-block/config.ts +10 -0
  13. package/src/image-block/schema.ts +16 -0
  14. package/src/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.tsx +14 -0
  15. package/src/image-block/view/components/image-block.tsx +40 -0
  16. package/src/image-block/view/components/image-viewer.tsx +667 -98
  17. package/src/image-block/view/index.ts +42 -0
  18. package/src/table-block/view/component.tsx +31 -14
  19. package/src/table-block/view/operation.ts +49 -30
  20. package/lib/__internal__/components/icon.d.ts +0 -24
  21. package/lib/__internal__/components/icon.d.ts.map +0 -1
  22. package/lib/__internal__/components/image-input.d.ts +0 -17
  23. package/lib/__internal__/components/image-input.d.ts.map +0 -1
  24. package/lib/__internal__/keep-alive.d.ts +0 -2
  25. package/lib/__internal__/keep-alive.d.ts.map +0 -1
  26. package/lib/__internal__/meta.d.ts +0 -3
  27. package/lib/__internal__/meta.d.ts.map +0 -1
  28. package/lib/__tests__/setup.d.ts +0 -2
  29. package/lib/__tests__/setup.d.ts.map +0 -1
  30. package/lib/code-block/config.d.ts +0 -23
  31. package/lib/code-block/config.d.ts.map +0 -1
  32. package/lib/code-block/index.d.ts +0 -5
  33. package/lib/code-block/index.d.ts.map +0 -1
  34. package/lib/code-block/view/components/code-block.d.ts +0 -16
  35. package/lib/code-block/view/components/code-block.d.ts.map +0 -1
  36. package/lib/code-block/view/components/copy-button.d.ts +0 -9
  37. package/lib/code-block/view/components/copy-button.d.ts.map +0 -1
  38. package/lib/code-block/view/components/language-picker.d.ts +0 -5
  39. package/lib/code-block/view/components/language-picker.d.ts.map +0 -1
  40. package/lib/code-block/view/components/preview-panel.d.ts +0 -9
  41. package/lib/code-block/view/components/preview-panel.d.ts.map +0 -1
  42. package/lib/code-block/view/index.d.ts +0 -3
  43. package/lib/code-block/view/index.d.ts.map +0 -1
  44. package/lib/code-block/view/loader.d.ts +0 -13
  45. package/lib/code-block/view/loader.d.ts.map +0 -1
  46. package/lib/code-block/view/node-view.d.ts +0 -40
  47. package/lib/code-block/view/node-view.d.ts.map +0 -1
  48. package/lib/image-block/config.d.ts +0 -16
  49. package/lib/image-block/config.d.ts.map +0 -1
  50. package/lib/image-block/convert-plugin.d.ts +0 -2
  51. package/lib/image-block/convert-plugin.d.ts.map +0 -1
  52. package/lib/image-block/index.d.ts +0 -9
  53. package/lib/image-block/index.d.ts.map +0 -1
  54. package/lib/image-block/paste-rule.d.ts +0 -2
  55. package/lib/image-block/paste-rule.d.ts.map +0 -1
  56. package/lib/image-block/remark-plugin.d.ts +0 -2
  57. package/lib/image-block/remark-plugin.d.ts.map +0 -1
  58. package/lib/image-block/schema.d.ts +0 -3
  59. package/lib/image-block/schema.d.ts.map +0 -1
  60. package/lib/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.d.ts +0 -2
  61. package/lib/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.d.ts.map +0 -1
  62. package/lib/image-block/view/components/image-block.d.ts +0 -19
  63. package/lib/image-block/view/components/image-block.d.ts.map +0 -1
  64. package/lib/image-block/view/components/image-viewer.d.ts +0 -3
  65. package/lib/image-block/view/components/image-viewer.d.ts.map +0 -1
  66. package/lib/image-block/view/index.d.ts +0 -3
  67. package/lib/image-block/view/index.d.ts.map +0 -1
  68. package/lib/image-inline/components/image-inline.d.ts +0 -18
  69. package/lib/image-inline/components/image-inline.d.ts.map +0 -1
  70. package/lib/image-inline/config.d.ts +0 -11
  71. package/lib/image-inline/config.d.ts.map +0 -1
  72. package/lib/image-inline/index.d.ts +0 -5
  73. package/lib/image-inline/index.d.ts.map +0 -1
  74. package/lib/image-inline/view.d.ts +0 -3
  75. package/lib/image-inline/view.d.ts.map +0 -1
  76. package/lib/index.d.ts +0 -2
  77. package/lib/index.d.ts.map +0 -1
  78. package/lib/link-tooltip/command.d.ts +0 -2
  79. package/lib/link-tooltip/command.d.ts.map +0 -1
  80. package/lib/link-tooltip/configure.d.ts +0 -3
  81. package/lib/link-tooltip/configure.d.ts.map +0 -1
  82. package/lib/link-tooltip/edit/component.d.ts +0 -11
  83. package/lib/link-tooltip/edit/component.d.ts.map +0 -1
  84. package/lib/link-tooltip/edit/edit-configure.d.ts +0 -3
  85. package/lib/link-tooltip/edit/edit-configure.d.ts.map +0 -1
  86. package/lib/link-tooltip/edit/edit-view.d.ts +0 -15
  87. package/lib/link-tooltip/edit/edit-view.d.ts.map +0 -1
  88. package/lib/link-tooltip/index.d.ts +0 -7
  89. package/lib/link-tooltip/index.d.ts.map +0 -1
  90. package/lib/link-tooltip/preview/component.d.ts +0 -11
  91. package/lib/link-tooltip/preview/component.d.ts.map +0 -1
  92. package/lib/link-tooltip/preview/preview-configure.d.ts +0 -3
  93. package/lib/link-tooltip/preview/preview-configure.d.ts.map +0 -1
  94. package/lib/link-tooltip/preview/preview-view.d.ts +0 -14
  95. package/lib/link-tooltip/preview/preview-view.d.ts.map +0 -1
  96. package/lib/link-tooltip/slices.d.ts +0 -34
  97. package/lib/link-tooltip/slices.d.ts.map +0 -1
  98. package/lib/link-tooltip/tooltips.d.ts +0 -3
  99. package/lib/link-tooltip/tooltips.d.ts.map +0 -1
  100. package/lib/link-tooltip/utils.d.ts +0 -14
  101. package/lib/link-tooltip/utils.d.ts.map +0 -1
  102. package/lib/list-item-block/component.d.ts +0 -19
  103. package/lib/list-item-block/component.d.ts.map +0 -1
  104. package/lib/list-item-block/config.d.ts +0 -13
  105. package/lib/list-item-block/config.d.ts.map +0 -1
  106. package/lib/list-item-block/index.d.ts +0 -6
  107. package/lib/list-item-block/index.d.ts.map +0 -1
  108. package/lib/list-item-block/view.d.ts +0 -3
  109. package/lib/list-item-block/view.d.ts.map +0 -1
  110. package/lib/table-block/config.d.ts +0 -8
  111. package/lib/table-block/config.d.ts.map +0 -1
  112. package/lib/table-block/dnd/calc-drag-over.d.ts +0 -3
  113. package/lib/table-block/dnd/calc-drag-over.d.ts.map +0 -1
  114. package/lib/table-block/dnd/create-drag-handler.d.ts +0 -5
  115. package/lib/table-block/dnd/create-drag-handler.d.ts.map +0 -1
  116. package/lib/table-block/dnd/drag-over-handler.d.ts +0 -3
  117. package/lib/table-block/dnd/drag-over-handler.d.ts.map +0 -1
  118. package/lib/table-block/dnd/prepare-dnd-context.d.ts +0 -3
  119. package/lib/table-block/dnd/prepare-dnd-context.d.ts.map +0 -1
  120. package/lib/table-block/dnd/preview.d.ts +0 -3
  121. package/lib/table-block/dnd/preview.d.ts.map +0 -1
  122. package/lib/table-block/index.d.ts +0 -5
  123. package/lib/table-block/index.d.ts.map +0 -1
  124. package/lib/table-block/view/component.d.ts +0 -16
  125. package/lib/table-block/view/component.d.ts.map +0 -1
  126. package/lib/table-block/view/drag.d.ts +0 -10
  127. package/lib/table-block/view/drag.d.ts.map +0 -1
  128. package/lib/table-block/view/index.d.ts +0 -2
  129. package/lib/table-block/view/index.d.ts.map +0 -1
  130. package/lib/table-block/view/operation.d.ts +0 -13
  131. package/lib/table-block/view/operation.d.ts.map +0 -1
  132. package/lib/table-block/view/pointer.d.ts +0 -7
  133. package/lib/table-block/view/pointer.d.ts.map +0 -1
  134. package/lib/table-block/view/types.d.ts +0 -28
  135. package/lib/table-block/view/types.d.ts.map +0 -1
  136. package/lib/table-block/view/utils.d.ts +0 -12
  137. package/lib/table-block/view/utils.d.ts.map +0 -1
  138. package/lib/table-block/view/view.d.ts +0 -22
  139. package/lib/table-block/view/view.d.ts.map +0 -1
@@ -9,25 +9,25 @@ import { h, defineComponent, ref, Fragment as Fragment$2, createApp, watchEffect
9
9
  import clsx from 'clsx';
10
10
  import { customAlphabet } from 'nanoid';
11
11
 
12
- var __defProp$3 = Object.defineProperty;
13
- var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
14
- var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
15
- var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
16
- var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
- var __spreadValues$3 = (a, b) => {
12
+ var __defProp$4 = Object.defineProperty;
13
+ var __getOwnPropSymbols$4 = Object.getOwnPropertySymbols;
14
+ var __hasOwnProp$4 = Object.prototype.hasOwnProperty;
15
+ var __propIsEnum$4 = Object.prototype.propertyIsEnumerable;
16
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
+ var __spreadValues$4 = (a, b) => {
18
18
  for (var prop in b || (b = {}))
19
- if (__hasOwnProp$3.call(b, prop))
20
- __defNormalProp$3(a, prop, b[prop]);
21
- if (__getOwnPropSymbols$3)
22
- for (var prop of __getOwnPropSymbols$3(b)) {
23
- if (__propIsEnum$3.call(b, prop))
24
- __defNormalProp$3(a, prop, b[prop]);
19
+ if (__hasOwnProp$4.call(b, prop))
20
+ __defNormalProp$4(a, prop, b[prop]);
21
+ if (__getOwnPropSymbols$4)
22
+ for (var prop of __getOwnPropSymbols$4(b)) {
23
+ if (__propIsEnum$4.call(b, prop))
24
+ __defNormalProp$4(a, prop, b[prop]);
25
25
  }
26
26
  return a;
27
27
  };
28
28
  function withMeta(plugin, meta) {
29
29
  Object.assign(plugin, {
30
- meta: __spreadValues$3({
30
+ meta: __spreadValues$4({
31
31
  package: "@jvs-milkdown/components"
32
32
  }, meta)
33
33
  });
@@ -37,6 +37,11 @@ function withMeta(plugin, meta) {
37
37
  const defaultImageBlockConfig = {
38
38
  imageIcon: "\u{1F30C}",
39
39
  captionIcon: "\u{1F4AC}",
40
+ cropIcon: "\u2702\uFE0F",
41
+ borderIcon: "\u{1F532}",
42
+ confirmIcon: "\u2713",
43
+ cancelIcon: "\u2715",
44
+ resetCropIcon: "\u21A9",
40
45
  uploadButton: "Upload file",
41
46
  confirmButton: "Confirm \u23CE",
42
47
  uploadPlaceholderText: "or paste the image link ...",
@@ -52,19 +57,19 @@ withMeta(imageBlockConfig, {
52
57
  group: "ImageBlock"
53
58
  });
54
59
 
55
- var __defProp$2 = Object.defineProperty;
56
- var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
57
- var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
58
- var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
59
- var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
60
- var __spreadValues$2 = (a, b) => {
60
+ var __defProp$3 = Object.defineProperty;
61
+ var __getOwnPropSymbols$3 = Object.getOwnPropertySymbols;
62
+ var __hasOwnProp$3 = Object.prototype.hasOwnProperty;
63
+ var __propIsEnum$3 = Object.prototype.propertyIsEnumerable;
64
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
65
+ var __spreadValues$3 = (a, b) => {
61
66
  for (var prop in b || (b = {}))
62
- if (__hasOwnProp$2.call(b, prop))
63
- __defNormalProp$2(a, prop, b[prop]);
64
- if (__getOwnPropSymbols$2)
65
- for (var prop of __getOwnPropSymbols$2(b)) {
66
- if (__propIsEnum$2.call(b, prop))
67
- __defNormalProp$2(a, prop, b[prop]);
67
+ if (__hasOwnProp$3.call(b, prop))
68
+ __defNormalProp$3(a, prop, b[prop]);
69
+ if (__getOwnPropSymbols$3)
70
+ for (var prop of __getOwnPropSymbols$3(b)) {
71
+ if (__propIsEnum$3.call(b, prop))
72
+ __defNormalProp$3(a, prop, b[prop]);
68
73
  }
69
74
  return a;
70
75
  };
@@ -83,19 +88,35 @@ const imageBlockSchema = $nodeSchema("image-block", () => {
83
88
  src: { default: "", validate: "string" },
84
89
  caption: { default: "", validate: "string" },
85
90
  ratio: { default: 1, validate: "number" },
86
- align: { default: null }
91
+ align: { default: null },
92
+ cropRatio: { default: "free", validate: "string" },
93
+ cropTop: { default: 0, validate: "number" },
94
+ cropLeft: { default: 0, validate: "number" },
95
+ cropWidth: { default: 1, validate: "number" },
96
+ cropHeight: { default: 1, validate: "number" },
97
+ borderWidth: { default: 0, validate: "number" },
98
+ borderColor: { default: "#000000", validate: "string" },
99
+ borderStyle: { default: "none", validate: "string" }
87
100
  },
88
101
  parseDOM: [
89
102
  {
90
103
  tag: `img[data-type="${IMAGE_DATA_TYPE}"]`,
91
104
  getAttrs: (dom) => {
92
- var _a;
105
+ var _a, _b, _c, _d, _e, _f;
93
106
  if (!(dom instanceof HTMLElement)) throw expectDomTypeError(dom);
94
107
  return {
95
108
  src: dom.getAttribute("src") || "",
96
109
  caption: dom.getAttribute("caption") || "",
97
110
  ratio: Number((_a = dom.getAttribute("ratio")) != null ? _a : 1),
98
- align: dom.getAttribute("align") || null
111
+ align: dom.getAttribute("align") || null,
112
+ cropRatio: dom.getAttribute("cropRatio") || "free",
113
+ cropTop: Number((_b = dom.getAttribute("cropTop")) != null ? _b : 0),
114
+ cropLeft: Number((_c = dom.getAttribute("cropLeft")) != null ? _c : 0),
115
+ cropWidth: Number((_d = dom.getAttribute("cropWidth")) != null ? _d : 1),
116
+ cropHeight: Number((_e = dom.getAttribute("cropHeight")) != null ? _e : 1),
117
+ borderWidth: Number((_f = dom.getAttribute("borderWidth")) != null ? _f : 0),
118
+ borderColor: dom.getAttribute("borderColor") || "#000000",
119
+ borderStyle: dom.getAttribute("borderStyle") || "none"
99
120
  };
100
121
  }
101
122
  },
@@ -112,7 +133,7 @@ const imageBlockSchema = $nodeSchema("image-block", () => {
112
133
  }
113
134
  }
114
135
  ],
115
- toDOM: (node) => ["img", __spreadValues$2({ "data-type": IMAGE_DATA_TYPE }, node.attrs)],
136
+ toDOM: (node) => ["img", __spreadValues$3({ "data-type": IMAGE_DATA_TYPE }, node.attrs)],
116
137
  parseMarkdown: {
117
138
  match: ({ type }) => type === "image-block",
118
139
  runner: (state, node, type) => {
@@ -146,21 +167,21 @@ withMeta(imageBlockSchema.node, {
146
167
  group: "ImageBlock"
147
168
  });
148
169
 
149
- var __defProp$1 = Object.defineProperty;
170
+ var __defProp$2 = Object.defineProperty;
150
171
  var __defProps = Object.defineProperties;
151
172
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
152
- var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
153
- var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
154
- var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
155
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
156
- var __spreadValues$1 = (a, b) => {
173
+ var __getOwnPropSymbols$2 = Object.getOwnPropertySymbols;
174
+ var __hasOwnProp$2 = Object.prototype.hasOwnProperty;
175
+ var __propIsEnum$2 = Object.prototype.propertyIsEnumerable;
176
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
177
+ var __spreadValues$2 = (a, b) => {
157
178
  for (var prop in b || (b = {}))
158
- if (__hasOwnProp$1.call(b, prop))
159
- __defNormalProp$1(a, prop, b[prop]);
160
- if (__getOwnPropSymbols$1)
161
- for (var prop of __getOwnPropSymbols$1(b)) {
162
- if (__propIsEnum$1.call(b, prop))
163
- __defNormalProp$1(a, prop, b[prop]);
179
+ if (__hasOwnProp$2.call(b, prop))
180
+ __defNormalProp$2(a, prop, b[prop]);
181
+ if (__getOwnPropSymbols$2)
182
+ for (var prop of __getOwnPropSymbols$2(b)) {
183
+ if (__propIsEnum$2.call(b, prop))
184
+ __defNormalProp$2(a, prop, b[prop]);
164
185
  }
165
186
  return a;
166
187
  };
@@ -266,7 +287,7 @@ const imageBlockConvertPlugin = $prose((ctx) => {
266
287
  const nodeAtPos = $pos.nodeAfter;
267
288
  if (nodeAtPos && nodeAtPos.type.name === "image-block" && nodeAtPos.attrs.src === src) {
268
289
  view.dispatch(
269
- view.state.tr.setNodeMarkup(pos, void 0, __spreadProps(__spreadValues$1({}, nodeAtPos.attrs), {
290
+ view.state.tr.setNodeMarkup(pos, void 0, __spreadProps(__spreadValues$2({}, nodeAtPos.attrs), {
270
291
  src: uploadedUrl
271
292
  })).setMeta(pluginKey, { uploaded: true })
272
293
  );
@@ -579,54 +600,91 @@ const ImageInput = defineComponent({
579
600
  }
580
601
  });
581
602
 
603
+ var __defProp$1 = Object.defineProperty;
604
+ var __getOwnPropSymbols$1 = Object.getOwnPropertySymbols;
605
+ var __hasOwnProp$1 = Object.prototype.hasOwnProperty;
606
+ var __propIsEnum$1 = Object.prototype.propertyIsEnumerable;
607
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
608
+ var __spreadValues$1 = (a, b) => {
609
+ for (var prop in b || (b = {}))
610
+ if (__hasOwnProp$1.call(b, prop))
611
+ __defNormalProp$1(a, prop, b[prop]);
612
+ if (__getOwnPropSymbols$1)
613
+ for (var prop of __getOwnPropSymbols$1(b)) {
614
+ if (__propIsEnum$1.call(b, prop))
615
+ __defNormalProp$1(a, prop, b[prop]);
616
+ }
617
+ return a;
618
+ };
582
619
  keepAlive(h, Fragment$2);
620
+ const ratioMap = {
621
+ "1:1": 1,
622
+ "4:3": 4 / 3,
623
+ "3:2": 3 / 2,
624
+ "16:9": 16 / 9
625
+ };
583
626
  const ImageViewer = defineComponent({
584
627
  props: {
585
- src: {
586
- type: Object,
587
- required: true
588
- },
589
- caption: {
590
- type: Object,
591
- required: true
592
- },
593
- ratio: {
594
- type: Object,
595
- required: true
596
- },
597
- align: {
598
- type: Object,
599
- required: true
600
- },
601
- selected: {
602
- type: Object,
603
- required: true
604
- },
605
- readonly: {
606
- type: Object,
607
- required: true
608
- },
609
- setAttr: {
610
- type: Function,
611
- required: true
612
- },
613
- config: {
614
- type: Object,
615
- required: true
616
- }
628
+ src: { type: Object, required: true },
629
+ caption: { type: Object, required: true },
630
+ ratio: { type: Object, required: true },
631
+ align: { type: Object, required: true },
632
+ cropRatio: { type: Object, required: true },
633
+ cropTop: { type: Object, required: true },
634
+ cropLeft: { type: Object, required: true },
635
+ cropWidth: { type: Object, required: true },
636
+ cropHeight: { type: Object, required: true },
637
+ borderWidth: { type: Object, required: true },
638
+ borderColor: { type: Object, required: true },
639
+ borderStyle: { type: Object, required: true },
640
+ selected: { type: Object, required: true },
641
+ readonly: { type: Object, required: true },
642
+ setAttr: { type: Function, required: true },
643
+ config: { type: Object, required: true }
617
644
  },
618
- setup({ src, caption, ratio, readonly, setAttr, config }) {
645
+ setup({
646
+ src,
647
+ caption,
648
+ ratio,
649
+ readonly,
650
+ setAttr,
651
+ config,
652
+ cropRatio,
653
+ cropTop,
654
+ cropLeft,
655
+ cropWidth,
656
+ cropHeight,
657
+ borderWidth,
658
+ borderColor,
659
+ borderStyle
660
+ }) {
619
661
  var _a;
620
662
  const imageRef = ref();
663
+ const wrapperRef = ref();
621
664
  const showCaption = ref(Boolean((_a = caption.value) == null ? void 0 : _a.length));
622
665
  const timer = ref(0);
666
+ const showBorderPanel = ref(false);
667
+ const isCropping = ref(false);
668
+ const baseDisplayW = ref(0);
669
+ const baseDisplayH = ref(0);
670
+ const liveRatio = ref(null);
671
+ const localBorderWidth = ref(null);
672
+ const localBorderColor = ref(null);
673
+ const localCrop = ref({ top: 0, left: 0, width: 1, height: 1 });
623
674
  let resizeDir = "";
624
675
  let startY = 0;
625
676
  let startX = 0;
626
677
  let startHeight = 0;
627
678
  let startWidth = 0;
679
+ const isCropped = () => {
680
+ var _a2, _b, _c, _d;
681
+ const t = (_a2 = cropTop.value) != null ? _a2 : 0;
682
+ const l = (_b = cropLeft.value) != null ? _b : 0;
683
+ const w = (_c = cropWidth.value) != null ? _c : 1;
684
+ const h2 = (_d = cropHeight.value) != null ? _d : 1;
685
+ return t > 1e-3 || l > 1e-3 || w < 0.999 || h2 < 0.999;
686
+ };
628
687
  const onImageLoad = () => {
629
- var _a2;
630
688
  const image = imageRef.value;
631
689
  if (!image) return;
632
690
  const host = image.closest(".milkdown-image-block");
@@ -637,14 +695,16 @@ const ImageViewer = defineComponent({
637
695
  maxWidth = config.maxWidth;
638
696
  const height = image.naturalHeight;
639
697
  const width = image.naturalWidth;
640
- let transformedHeight = width < maxWidth ? height : maxWidth * (height / width);
641
- if (config.maxHeight && transformedHeight > config.maxHeight)
698
+ if (!height || !width) return;
699
+ const aspect = width / height;
700
+ let transformedWidth = width < maxWidth ? width : maxWidth;
701
+ let transformedHeight = transformedWidth / aspect;
702
+ if (config.maxHeight && transformedHeight > config.maxHeight) {
642
703
  transformedHeight = config.maxHeight;
643
- const h2 = (transformedHeight * ((_a2 = ratio.value) != null ? _a2 : 1)).toFixed(2);
644
- image.dataset.origin = transformedHeight.toFixed(2);
645
- image.dataset.height = h2;
646
- image.style.height = `${h2}px`;
647
- if (config.maxWidth) image.style.maxWidth = `${config.maxWidth}px`;
704
+ transformedWidth = transformedHeight * aspect;
705
+ }
706
+ baseDisplayH.value = transformedHeight;
707
+ baseDisplayW.value = transformedWidth;
648
708
  };
649
709
  const onToggleCaption = (e) => {
650
710
  e.preventDefault();
@@ -670,9 +730,8 @@ const ImageViewer = defineComponent({
670
730
  setAttr("caption", value);
671
731
  };
672
732
  const onResizeHandlePointerMove = (e) => {
733
+ var _a2;
673
734
  e.preventDefault();
674
- const image = imageRef.value;
675
- if (!image) return;
676
735
  const deltaY = e.clientY - startY;
677
736
  const deltaX = e.clientX - startX;
678
737
  const aspect = startHeight / (startWidth || 1);
@@ -684,82 +743,532 @@ const ImageViewer = defineComponent({
684
743
  dhX = -deltaX * aspect;
685
744
  }
686
745
  const dh = Math.abs(dhX) > Math.abs(dhY) ? dhX : dhY;
687
- let height = startHeight + dh;
688
- if (height < 20) height = 20;
689
- if (config.maxHeight && height > config.maxHeight)
690
- height = config.maxHeight;
691
- const h2 = Number(height).toFixed(2);
692
- image.dataset.height = h2;
693
- image.style.height = `${h2}px`;
746
+ let newWrapperHeight = startHeight + dh;
747
+ let newWrapperWidth = newWrapperHeight * (startWidth / (startHeight || 1));
748
+ if (newWrapperHeight < 20) {
749
+ newWrapperHeight = 20;
750
+ newWrapperWidth = newWrapperHeight * (startWidth / (startHeight || 1));
751
+ }
752
+ if (newWrapperWidth < 20) {
753
+ newWrapperWidth = 20;
754
+ newWrapperHeight = newWrapperWidth / (startWidth / (startHeight || 1));
755
+ }
756
+ const image = imageRef.value;
757
+ const host = image == null ? void 0 : image.closest(".milkdown-image-block");
758
+ const hostWidth = host == null ? void 0 : host.getBoundingClientRect().width;
759
+ const maxW = config.maxWidth && hostWidth ? Math.min(config.maxWidth, hostWidth) : hostWidth || Infinity;
760
+ if (newWrapperWidth > maxW) {
761
+ newWrapperWidth = maxW;
762
+ newWrapperHeight = newWrapperWidth / (startWidth / (startHeight || 1));
763
+ }
764
+ if (config.maxHeight && newWrapperHeight > config.maxHeight) {
765
+ newWrapperHeight = config.maxHeight;
766
+ }
767
+ const cHeight = isCropped() && !isCropping.value ? (_a2 = cropHeight.value) != null ? _a2 : 1 : 1;
768
+ const newBaseHeight = newWrapperHeight / cHeight;
769
+ const newRatio = newBaseHeight / (baseDisplayH.value || 1);
770
+ liveRatio.value = Number(newRatio.toFixed(2));
694
771
  };
695
772
  const onResizeHandlePointerUp = () => {
696
773
  window.removeEventListener("pointermove", onResizeHandlePointerMove);
697
774
  window.removeEventListener("pointerup", onResizeHandlePointerUp);
698
- const image = imageRef.value;
699
- if (!image) return;
700
- const originHeight = Number(image.dataset.origin);
701
- const currentHeight = Number(image.dataset.height);
702
- const ratio2 = Number.parseFloat(
703
- Number(currentHeight / originHeight).toFixed(2)
704
- );
705
- if (Number.isNaN(ratio2)) return;
706
- setAttr("ratio", ratio2);
775
+ if (liveRatio.value !== null) {
776
+ setAttr("ratio", liveRatio.value);
777
+ liveRatio.value = null;
778
+ }
707
779
  };
708
780
  const onResizeHandlePointerDown = (e, dir) => {
781
+ var _a2;
709
782
  if (readonly.value) return;
710
783
  e.preventDefault();
711
784
  e.stopPropagation();
712
785
  resizeDir = dir;
713
786
  startY = e.clientY;
714
787
  startX = e.clientX;
715
- const image = imageRef.value;
716
- if (image) {
717
- startHeight = image.getBoundingClientRect().height;
718
- startWidth = image.getBoundingClientRect().width;
788
+ const wrapper = wrapperRef.value;
789
+ if (wrapper) {
790
+ startHeight = wrapper.getBoundingClientRect().height;
791
+ startWidth = wrapper.getBoundingClientRect().width;
719
792
  }
793
+ liveRatio.value = (_a2 = ratio.value) != null ? _a2 : 1;
720
794
  window.addEventListener("pointermove", onResizeHandlePointerMove);
721
795
  window.addEventListener("pointerup", onResizeHandlePointerUp);
722
796
  };
723
- return () => {
724
- return /* @__PURE__ */ h(Fragment$2, null, /* @__PURE__ */ h("div", { class: "image-wrapper" }, /* @__PURE__ */ h("div", { class: "operation" }, /* @__PURE__ */ h("div", { class: "operation-item", onPointerdown: onToggleCaption }, /* @__PURE__ */ h(Icon, { icon: config.captionIcon }))), /* @__PURE__ */ h(
725
- "img",
726
- {
727
- ref: imageRef,
728
- "data-type": IMAGE_DATA_TYPE,
729
- onLoad: onImageLoad,
730
- src: src.value,
731
- alt: caption.value,
732
- onError: (e) => {
733
- var _a2;
734
- return Promise.resolve((_a2 = config.onImageLoadError) == null ? void 0 : _a2.call(config, e)).catch(() => {
735
- });
797
+ const borderStyleOptions = [
798
+ { label: "none", value: "none" },
799
+ { label: "solid", value: "solid" },
800
+ { label: "dashed", value: "dashed" },
801
+ { label: "dotted", value: "dotted" }
802
+ ];
803
+ const onToggleCropPanel = (e) => {
804
+ e.preventDefault();
805
+ e.stopPropagation();
806
+ if (readonly.value) return;
807
+ showBorderPanel.value = false;
808
+ if (isCropping.value) {
809
+ isCropping.value = false;
810
+ } else {
811
+ startCropping();
812
+ }
813
+ };
814
+ const onToggleBorderPanel = (e) => {
815
+ e.preventDefault();
816
+ e.stopPropagation();
817
+ if (readonly.value) return;
818
+ showBorderPanel.value = !showBorderPanel.value;
819
+ };
820
+ const closePanels = () => {
821
+ showBorderPanel.value = false;
822
+ };
823
+ const startCropping = () => {
824
+ var _a2, _b, _c, _d;
825
+ localCrop.value = {
826
+ top: (_a2 = cropTop.value) != null ? _a2 : 0,
827
+ left: (_b = cropLeft.value) != null ? _b : 0,
828
+ width: (_c = cropWidth.value) != null ? _c : 1,
829
+ height: (_d = cropHeight.value) != null ? _d : 1
830
+ };
831
+ isCropping.value = true;
832
+ };
833
+ const applyCrop = () => {
834
+ setAttr("cropTop", localCrop.value.top);
835
+ setAttr("cropLeft", localCrop.value.left);
836
+ setAttr("cropWidth", localCrop.value.width);
837
+ setAttr("cropHeight", localCrop.value.height);
838
+ isCropping.value = false;
839
+ };
840
+ const cancelCrop = () => {
841
+ isCropping.value = false;
842
+ };
843
+ const resetCrop = () => {
844
+ setAttr("cropTop", 0);
845
+ setAttr("cropLeft", 0);
846
+ setAttr("cropWidth", 1);
847
+ setAttr("cropHeight", 1);
848
+ };
849
+ let cropDragType = "";
850
+ let cropStartX = 0;
851
+ let cropStartY = 0;
852
+ let cropStartBox = { top: 0, left: 0, width: 1, height: 1 };
853
+ const onCropBoxPointerDown = (e, type) => {
854
+ e.preventDefault();
855
+ e.stopPropagation();
856
+ cropDragType = type;
857
+ cropStartX = e.clientX;
858
+ cropStartY = e.clientY;
859
+ cropStartBox = __spreadValues$1({}, localCrop.value);
860
+ window.addEventListener("pointermove", onCropBoxPointerMove);
861
+ window.addEventListener("pointerup", onCropBoxPointerUp);
862
+ };
863
+ const onCropBoxPointerMove = (e) => {
864
+ var _a2;
865
+ const wrapper = wrapperRef.value;
866
+ if (!wrapper) return;
867
+ const rect = wrapper.getBoundingClientRect();
868
+ if (!rect.width || !rect.height) return;
869
+ const dx = (e.clientX - cropStartX) / rect.width;
870
+ const dy = (e.clientY - cropStartY) / rect.height;
871
+ const ar = ratioMap[(_a2 = cropRatio.value) != null ? _a2 : "free"];
872
+ let box = __spreadValues$1({}, cropStartBox);
873
+ if (cropDragType === "move") {
874
+ box.left = Math.max(0, Math.min(1 - box.width, cropStartBox.left + dx));
875
+ box.top = Math.max(0, Math.min(1 - box.height, cropStartBox.top + dy));
876
+ } else {
877
+ const isLeft = cropDragType === "nw" || cropDragType === "sw" || cropDragType === "w";
878
+ const isTop = cropDragType === "nw" || cropDragType === "ne" || cropDragType === "n";
879
+ const isRight = cropDragType === "ne" || cropDragType === "se" || cropDragType === "e";
880
+ const isBottom = cropDragType === "sw" || cropDragType === "se" || cropDragType === "s";
881
+ const isHorizontal = cropDragType === "n" || cropDragType === "s";
882
+ const isVertical = cropDragType === "e" || cropDragType === "w";
883
+ let newLeft = cropStartBox.left;
884
+ let newTop = cropStartBox.top;
885
+ let newWidth = cropStartBox.width;
886
+ let newHeight = cropStartBox.height;
887
+ if (isLeft) {
888
+ newWidth = cropStartBox.width - dx;
889
+ newLeft = cropStartBox.left + dx;
890
+ } else if (isRight) {
891
+ newWidth = cropStartBox.width + dx;
892
+ }
893
+ if (isTop) {
894
+ newHeight = cropStartBox.height - dy;
895
+ newTop = cropStartBox.top + dy;
896
+ } else if (isBottom) {
897
+ newHeight = cropStartBox.height + dy;
898
+ }
899
+ if (ar && !isHorizontal && !isVertical) {
900
+ const cropPixelW = newWidth * rect.width;
901
+ const desiredH = cropPixelW / ar / rect.height;
902
+ if (isTop) {
903
+ newTop = newTop + newHeight - desiredH;
736
904
  }
905
+ newHeight = desiredH;
737
906
  }
738
- ), /* @__PURE__ */ h(
739
- "div",
740
- {
741
- class: "image-resize-handle top-left",
742
- onPointerdown: (e) => onResizeHandlePointerDown(e, "top-left")
907
+ if (newWidth < 0.05) newWidth = 0.05;
908
+ if (newHeight < 0.05) newHeight = 0.05;
909
+ if (newLeft < 0) {
910
+ newWidth += newLeft;
911
+ newLeft = 0;
743
912
  }
744
- ), /* @__PURE__ */ h(
745
- "div",
746
- {
747
- class: "image-resize-handle top-right",
748
- onPointerdown: (e) => onResizeHandlePointerDown(e, "top-right")
913
+ if (newTop < 0) {
914
+ newHeight += newTop;
915
+ newTop = 0;
916
+ }
917
+ if (newLeft + newWidth > 1) newWidth = 1 - newLeft;
918
+ if (newTop + newHeight > 1) newHeight = 1 - newTop;
919
+ box = { left: newLeft, top: newTop, width: newWidth, height: newHeight };
920
+ }
921
+ localCrop.value = box;
922
+ };
923
+ const onCropBoxPointerUp = () => {
924
+ window.removeEventListener("pointermove", onCropBoxPointerMove);
925
+ window.removeEventListener("pointerup", onCropBoxPointerUp);
926
+ cropDragType = "";
927
+ };
928
+ return () => {
929
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
930
+ const currentBorderStyle = (_a2 = borderStyle.value) != null ? _a2 : "none";
931
+ const currentBorderWidth = localBorderWidth.value !== null ? localBorderWidth.value : (_b = borderWidth.value) != null ? _b : 0;
932
+ const currentBorderColor = localBorderColor.value !== null ? localBorderColor.value : (_c = borderColor.value) != null ? _c : "#000000";
933
+ const cTop = (_d = cropTop.value) != null ? _d : 0;
934
+ const cLeft = (_e = cropLeft.value) != null ? _e : 0;
935
+ const cWidth = (_f = cropWidth.value) != null ? _f : 1;
936
+ const cHeight = (_g = cropHeight.value) != null ? _g : 1;
937
+ const cropped = isCropped();
938
+ const borderStyleStr = currentBorderStyle !== "none" && currentBorderWidth > 0 ? `${currentBorderWidth}px ${currentBorderStyle} ${currentBorderColor}` : void 0;
939
+ const currentRatio = liveRatio.value !== null ? liveRatio.value : (_h = ratio.value) != null ? _h : 1;
940
+ let baseW = baseDisplayW.value * currentRatio;
941
+ let baseH = baseDisplayH.value * currentRatio;
942
+ const image = imageRef.value;
943
+ const host = image == null ? void 0 : image.closest(".milkdown-image-block");
944
+ const hostWidth = host == null ? void 0 : host.getBoundingClientRect().width;
945
+ const maxW = config.maxWidth && hostWidth ? Math.min(config.maxWidth, hostWidth) : hostWidth || Infinity;
946
+ const visibleW = isCropping.value ? baseW : cropped ? baseW * cWidth : baseW;
947
+ if (visibleW > maxW && maxW > 0) {
948
+ const scale = maxW / visibleW;
949
+ baseW = baseW * scale;
950
+ baseH = baseH * scale;
951
+ }
952
+ const cropPxW = baseW * cWidth;
953
+ const cropPxH = baseH * cHeight;
954
+ const cropPxL = baseW * cLeft;
955
+ const cropPxT = baseH * cTop;
956
+ const wrapperStyle = {
957
+ minWidth: "20px",
958
+ minHeight: "20px",
959
+ border: !isCropping.value ? borderStyleStr != null ? borderStyleStr : "" : ""
960
+ };
961
+ if (cropped && !isCropping.value && cropPxW > 0 && cropPxH > 0) {
962
+ wrapperStyle.width = `${cropPxW}px`;
963
+ wrapperStyle.height = `${cropPxH}px`;
964
+ }
965
+ const cropClipStyle = cropped && !isCropping.value && baseW > 0 && baseH > 0 ? {
966
+ width: `${cropPxW}px`,
967
+ height: `${cropPxH}px`,
968
+ overflow: "hidden"
969
+ } : null;
970
+ const imgStyle = {
971
+ minWidth: "0px",
972
+ minHeight: "0px"
973
+ };
974
+ if (cropped && !isCropping.value && baseW > 0 && baseH > 0) {
975
+ imgStyle.width = `${baseW}px`;
976
+ imgStyle.height = `${baseH}px`;
977
+ imgStyle.maxWidth = "none";
978
+ imgStyle.marginLeft = `${-cropPxL}px`;
979
+ imgStyle.marginTop = `${-cropPxT}px`;
980
+ } else {
981
+ if (baseH > 0 && baseW > 0) {
982
+ imgStyle.width = `${baseW}px`;
983
+ imgStyle.height = `${baseH}px`;
984
+ if (config.maxWidth) imgStyle.maxWidth = `${config.maxWidth}px`;
749
985
  }
750
- ), /* @__PURE__ */ h(
986
+ }
987
+ return /* @__PURE__ */ h(Fragment$2, null, !isCropping.value ? /* @__PURE__ */ h(
751
988
  "div",
752
989
  {
753
- class: "image-resize-handle bottom-left",
754
- onPointerdown: (e) => onResizeHandlePointerDown(e, "bottom-left")
755
- }
756
- ), /* @__PURE__ */ h(
990
+ class: "image-toolbar",
991
+ onClick: (e) => e.stopPropagation(),
992
+ onMousedown: (e) => e.stopPropagation(),
993
+ onDragstart: (e) => {
994
+ e.preventDefault();
995
+ e.stopPropagation();
996
+ }
997
+ },
998
+ /* @__PURE__ */ h(
999
+ "div",
1000
+ {
1001
+ class: "image-toolbar-item",
1002
+ title: "\u6807\u9898",
1003
+ onClick: onToggleCaption
1004
+ },
1005
+ /* @__PURE__ */ h(Icon, { icon: config.captionIcon })
1006
+ ),
1007
+ config.cropIcon ? /* @__PURE__ */ h(
1008
+ "div",
1009
+ {
1010
+ class: "image-toolbar-item",
1011
+ title: "\u88C1\u526A",
1012
+ onClick: onToggleCropPanel
1013
+ },
1014
+ /* @__PURE__ */ h(Icon, { icon: config.cropIcon })
1015
+ ) : null,
1016
+ cropped ? /* @__PURE__ */ h(
1017
+ "div",
1018
+ {
1019
+ class: "image-toolbar-item",
1020
+ title: "\u6062\u590D\u88C1\u526A",
1021
+ onClick: (e) => {
1022
+ e.stopPropagation();
1023
+ resetCrop();
1024
+ }
1025
+ },
1026
+ /* @__PURE__ */ h(Icon, { icon: (_i = config.resetCropIcon) != null ? _i : "\u21A9" })
1027
+ ) : null,
1028
+ config.borderIcon ? /* @__PURE__ */ h(
1029
+ "div",
1030
+ {
1031
+ class: "image-toolbar-item",
1032
+ title: "\u8FB9\u6846",
1033
+ onClick: onToggleBorderPanel
1034
+ },
1035
+ /* @__PURE__ */ h(Icon, { icon: config.borderIcon })
1036
+ ) : null,
1037
+ showBorderPanel.value ? /* @__PURE__ */ h(
1038
+ "div",
1039
+ {
1040
+ class: "setting-panel border-panel",
1041
+ draggable: "true",
1042
+ onClick: (e) => e.stopPropagation(),
1043
+ onMousedown: (e) => e.stopPropagation(),
1044
+ onPointerdown: (e) => e.stopPropagation(),
1045
+ onDragstart: (e) => {
1046
+ e.preventDefault();
1047
+ e.stopPropagation();
1048
+ }
1049
+ },
1050
+ /* @__PURE__ */ h("div", { class: "setting-panel-title" }, "\u8FB9\u6846\u8BBE\u7F6E"),
1051
+ /* @__PURE__ */ h("div", { class: "setting-row" }, /* @__PURE__ */ h("span", { class: "setting-label" }, "\u6837\u5F0F"), /* @__PURE__ */ h("div", { class: "border-style-options" }, borderStyleOptions.map((opt) => /* @__PURE__ */ h(
1052
+ "div",
1053
+ {
1054
+ class: `border-style-option ${currentBorderStyle === opt.value ? "active" : ""}`,
1055
+ onClick: (e) => {
1056
+ e.stopPropagation();
1057
+ setAttr("borderStyle", opt.value);
1058
+ }
1059
+ },
1060
+ opt.label === "none" ? "\u65E0" : opt.label === "solid" ? "\u5B9E\u7EBF" : opt.label === "dashed" ? "\u865A\u7EBF" : "\u70B9\u7EBF"
1061
+ )))),
1062
+ currentBorderStyle !== "none" ? /* @__PURE__ */ h("div", { class: "setting-row" }, /* @__PURE__ */ h("span", { class: "setting-label" }, "\u5BBD\u5EA6"), /* @__PURE__ */ h(
1063
+ "input",
1064
+ {
1065
+ draggable: "true",
1066
+ type: "range",
1067
+ min: "1",
1068
+ max: "10",
1069
+ value: currentBorderWidth,
1070
+ onInput: (e) => {
1071
+ const target = e.target;
1072
+ localBorderWidth.value = Number(target.value);
1073
+ },
1074
+ onChange: (e) => {
1075
+ const target = e.target;
1076
+ setAttr("borderWidth", Number(target.value));
1077
+ localBorderWidth.value = null;
1078
+ },
1079
+ onClick: (e) => e.stopPropagation(),
1080
+ onMousedown: (e) => e.stopPropagation(),
1081
+ onPointerdown: (e) => e.stopPropagation(),
1082
+ onDragstart: (e) => {
1083
+ e.preventDefault();
1084
+ e.stopPropagation();
1085
+ }
1086
+ }
1087
+ ), /* @__PURE__ */ h("span", { class: "setting-value" }, currentBorderWidth, "px")) : null,
1088
+ currentBorderStyle !== "none" ? /* @__PURE__ */ h("div", { class: "setting-row" }, /* @__PURE__ */ h("span", { class: "setting-label" }, "\u989C\u8272"), /* @__PURE__ */ h(
1089
+ "input",
1090
+ {
1091
+ draggable: "true",
1092
+ type: "color",
1093
+ value: currentBorderColor,
1094
+ onInput: (e) => {
1095
+ const target = e.target;
1096
+ localBorderColor.value = target.value;
1097
+ },
1098
+ onChange: (e) => {
1099
+ const target = e.target;
1100
+ setAttr("borderColor", target.value);
1101
+ localBorderColor.value = null;
1102
+ },
1103
+ onClick: (e) => e.stopPropagation(),
1104
+ onMousedown: (e) => e.stopPropagation(),
1105
+ onPointerdown: (e) => e.stopPropagation(),
1106
+ onDragstart: (e) => {
1107
+ e.preventDefault();
1108
+ e.stopPropagation();
1109
+ }
1110
+ }
1111
+ )) : null
1112
+ ) : null
1113
+ ) : null, /* @__PURE__ */ h(
757
1114
  "div",
758
1115
  {
759
- class: "image-resize-handle bottom-right",
760
- onPointerdown: (e) => onResizeHandlePointerDown(e, "bottom-right")
761
- }
762
- )), showCaption.value && /* @__PURE__ */ h(
1116
+ class: `image-wrapper${isCropping.value ? " cropping" : ""}`,
1117
+ ref: wrapperRef,
1118
+ style: wrapperStyle,
1119
+ onClick: closePanels
1120
+ },
1121
+ cropClipStyle ? /* @__PURE__ */ h("div", { class: "crop-clip", style: cropClipStyle }, /* @__PURE__ */ h(
1122
+ "img",
1123
+ {
1124
+ draggable: "false",
1125
+ ref: imageRef,
1126
+ "data-type": IMAGE_DATA_TYPE,
1127
+ onLoad: onImageLoad,
1128
+ src: src.value,
1129
+ alt: caption.value,
1130
+ style: imgStyle,
1131
+ onError: (e) => {
1132
+ var _a3;
1133
+ return Promise.resolve((_a3 = config.onImageLoadError) == null ? void 0 : _a3.call(config, e)).catch(
1134
+ () => {
1135
+ }
1136
+ );
1137
+ }
1138
+ }
1139
+ )) : /* @__PURE__ */ h(
1140
+ "img",
1141
+ {
1142
+ draggable: "false",
1143
+ ref: imageRef,
1144
+ "data-type": IMAGE_DATA_TYPE,
1145
+ onLoad: onImageLoad,
1146
+ src: src.value,
1147
+ alt: caption.value,
1148
+ style: imgStyle,
1149
+ onError: (e) => {
1150
+ var _a3;
1151
+ return Promise.resolve((_a3 = config.onImageLoadError) == null ? void 0 : _a3.call(config, e)).catch(() => {
1152
+ });
1153
+ }
1154
+ }
1155
+ ),
1156
+ isCropping.value ? /* @__PURE__ */ h("div", { class: "crop-overlay", onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ h(
1157
+ "div",
1158
+ {
1159
+ class: "crop-box",
1160
+ style: {
1161
+ top: `${(localCrop.value.top * 100).toFixed(2)}%`,
1162
+ left: `${(localCrop.value.left * 100).toFixed(2)}%`,
1163
+ width: `${(localCrop.value.width * 100).toFixed(2)}%`,
1164
+ height: `${(localCrop.value.height * 100).toFixed(2)}%`
1165
+ },
1166
+ onPointerdown: (e) => onCropBoxPointerDown(e, "move")
1167
+ },
1168
+ /* @__PURE__ */ h("div", { class: "crop-grid" }, /* @__PURE__ */ h("div", { class: "crop-grid-line horizontal first" }), /* @__PURE__ */ h("div", { class: "crop-grid-line horizontal second" }), /* @__PURE__ */ h("div", { class: "crop-grid-line vertical first" }), /* @__PURE__ */ h("div", { class: "crop-grid-line vertical second" })),
1169
+ /* @__PURE__ */ h(
1170
+ "div",
1171
+ {
1172
+ class: "crop-handle nw",
1173
+ onPointerdown: (e) => onCropBoxPointerDown(e, "nw")
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ h(
1177
+ "div",
1178
+ {
1179
+ class: "crop-handle ne",
1180
+ onPointerdown: (e) => onCropBoxPointerDown(e, "ne")
1181
+ }
1182
+ ),
1183
+ /* @__PURE__ */ h(
1184
+ "div",
1185
+ {
1186
+ class: "crop-handle sw",
1187
+ onPointerdown: (e) => onCropBoxPointerDown(e, "sw")
1188
+ }
1189
+ ),
1190
+ /* @__PURE__ */ h(
1191
+ "div",
1192
+ {
1193
+ class: "crop-handle se",
1194
+ onPointerdown: (e) => onCropBoxPointerDown(e, "se")
1195
+ }
1196
+ ),
1197
+ /* @__PURE__ */ h(
1198
+ "div",
1199
+ {
1200
+ class: "crop-handle n",
1201
+ onPointerdown: (e) => onCropBoxPointerDown(e, "n")
1202
+ }
1203
+ ),
1204
+ /* @__PURE__ */ h(
1205
+ "div",
1206
+ {
1207
+ class: "crop-handle s",
1208
+ onPointerdown: (e) => onCropBoxPointerDown(e, "s")
1209
+ }
1210
+ ),
1211
+ /* @__PURE__ */ h(
1212
+ "div",
1213
+ {
1214
+ class: "crop-handle e",
1215
+ onPointerdown: (e) => onCropBoxPointerDown(e, "e")
1216
+ }
1217
+ ),
1218
+ /* @__PURE__ */ h(
1219
+ "div",
1220
+ {
1221
+ class: "crop-handle w",
1222
+ onPointerdown: (e) => onCropBoxPointerDown(e, "w")
1223
+ }
1224
+ )
1225
+ ), /* @__PURE__ */ h("div", { class: "crop-toolbar" }, /* @__PURE__ */ h(
1226
+ "div",
1227
+ {
1228
+ class: "crop-toolbar-btn",
1229
+ onClick: (e) => {
1230
+ e.stopPropagation();
1231
+ applyCrop();
1232
+ }
1233
+ },
1234
+ /* @__PURE__ */ h(Icon, { icon: (_j = config.confirmIcon) != null ? _j : "\u2713" })
1235
+ ), /* @__PURE__ */ h(
1236
+ "div",
1237
+ {
1238
+ class: "crop-toolbar-btn",
1239
+ onClick: (e) => {
1240
+ e.stopPropagation();
1241
+ cancelCrop();
1242
+ }
1243
+ },
1244
+ /* @__PURE__ */ h(Icon, { icon: (_k = config.cancelIcon) != null ? _k : "\u2715" })
1245
+ ))) : null,
1246
+ !isCropping.value ? /* @__PURE__ */ h(Fragment$2, null, /* @__PURE__ */ h(
1247
+ "div",
1248
+ {
1249
+ class: "image-resize-handle top-left",
1250
+ onPointerdown: (e) => onResizeHandlePointerDown(e, "top-left")
1251
+ }
1252
+ ), /* @__PURE__ */ h(
1253
+ "div",
1254
+ {
1255
+ class: "image-resize-handle top-right",
1256
+ onPointerdown: (e) => onResizeHandlePointerDown(e, "top-right")
1257
+ }
1258
+ ), /* @__PURE__ */ h(
1259
+ "div",
1260
+ {
1261
+ class: "image-resize-handle bottom-left",
1262
+ onPointerdown: (e) => onResizeHandlePointerDown(e, "bottom-left")
1263
+ }
1264
+ ), /* @__PURE__ */ h(
1265
+ "div",
1266
+ {
1267
+ class: "image-resize-handle bottom-right",
1268
+ onPointerdown: (e) => onResizeHandlePointerDown(e, "bottom-right")
1269
+ }
1270
+ )) : null
1271
+ ), showCaption.value && /* @__PURE__ */ h(
763
1272
  "input",
764
1273
  {
765
1274
  draggable: "true",
@@ -813,6 +1322,38 @@ const MilkdownImageBlock = defineComponent({
813
1322
  type: Object,
814
1323
  required: true
815
1324
  },
1325
+ cropRatio: {
1326
+ type: Object,
1327
+ required: true
1328
+ },
1329
+ cropTop: {
1330
+ type: Object,
1331
+ required: true
1332
+ },
1333
+ cropLeft: {
1334
+ type: Object,
1335
+ required: true
1336
+ },
1337
+ cropWidth: {
1338
+ type: Object,
1339
+ required: true
1340
+ },
1341
+ cropHeight: {
1342
+ type: Object,
1343
+ required: true
1344
+ },
1345
+ borderWidth: {
1346
+ type: Object,
1347
+ required: true
1348
+ },
1349
+ borderColor: {
1350
+ type: Object,
1351
+ required: true
1352
+ },
1353
+ borderStyle: {
1354
+ type: Object,
1355
+ required: true
1356
+ },
816
1357
  selected: {
817
1358
  type: Object,
818
1359
  required: true
@@ -864,6 +1405,14 @@ const imageBlockView = $view(
864
1405
  const caption = ref(initialNode.attrs.caption);
865
1406
  const ratio = ref(initialNode.attrs.ratio);
866
1407
  const align = ref(initialNode.attrs.align);
1408
+ const cropRatio = ref(initialNode.attrs.cropRatio);
1409
+ const cropTop = ref(initialNode.attrs.cropTop);
1410
+ const cropLeft = ref(initialNode.attrs.cropLeft);
1411
+ const cropWidth = ref(initialNode.attrs.cropWidth);
1412
+ const cropHeight = ref(initialNode.attrs.cropHeight);
1413
+ const borderWidth = ref(initialNode.attrs.borderWidth);
1414
+ const borderColor = ref(initialNode.attrs.borderColor);
1415
+ const borderStyle = ref(initialNode.attrs.borderStyle);
867
1416
  const selected = ref(false);
868
1417
  const readonly = ref(!view.editable);
869
1418
  const setAttr = (attr, value) => {
@@ -884,6 +1433,14 @@ const imageBlockView = $view(
884
1433
  caption,
885
1434
  ratio,
886
1435
  align,
1436
+ cropRatio,
1437
+ cropTop,
1438
+ cropLeft,
1439
+ cropWidth,
1440
+ cropHeight,
1441
+ borderWidth,
1442
+ borderColor,
1443
+ borderStyle,
887
1444
  selected,
888
1445
  readonly,
889
1446
  setAttr,
@@ -903,6 +1460,18 @@ const imageBlockView = $view(
903
1460
  const disposeAlignWatcher = watchEffect(() => {
904
1461
  dom.dataset.align = align.value || "center";
905
1462
  });
1463
+ const disposeCropWatcher = watchEffect(() => {
1464
+ dom.dataset.cropRatio = cropRatio.value || "free";
1465
+ });
1466
+ const disposeBorderWatcher = watchEffect(() => {
1467
+ var _a, _b, _c;
1468
+ const w = (_a = borderWidth.value) != null ? _a : 0;
1469
+ const c = (_b = borderColor.value) != null ? _b : "#000000";
1470
+ const s = (_c = borderStyle.value) != null ? _c : "none";
1471
+ dom.dataset.borderWidth = String(w);
1472
+ dom.dataset.borderColor = c;
1473
+ dom.dataset.borderStyle = s;
1474
+ });
906
1475
  const proxyDomURL = config.proxyDomURL;
907
1476
  const bindAttrs = (node) => {
908
1477
  if (!proxyDomURL) {
@@ -920,6 +1489,14 @@ const imageBlockView = $view(
920
1489
  ratio.value = node.attrs.ratio;
921
1490
  caption.value = node.attrs.caption;
922
1491
  align.value = node.attrs.align;
1492
+ cropRatio.value = node.attrs.cropRatio;
1493
+ cropTop.value = node.attrs.cropTop;
1494
+ cropLeft.value = node.attrs.cropLeft;
1495
+ cropWidth.value = node.attrs.cropWidth;
1496
+ cropHeight.value = node.attrs.cropHeight;
1497
+ borderWidth.value = node.attrs.borderWidth;
1498
+ borderColor.value = node.attrs.borderColor;
1499
+ borderStyle.value = node.attrs.borderStyle;
923
1500
  readonly.value = !view.editable;
924
1501
  };
925
1502
  bindAttrs(initialNode);
@@ -932,7 +1509,13 @@ const imageBlockView = $view(
932
1509
  return true;
933
1510
  },
934
1511
  stopEvent: (e) => {
1512
+ var _a;
935
1513
  if (e.target instanceof HTMLInputElement) return true;
1514
+ if (e.target instanceof HTMLElement && e.target.tagName === "INPUT")
1515
+ return true;
1516
+ const target = e.target;
1517
+ if ((_a = target.closest) == null ? void 0 : _a.call(target, ".setting-panel, .image-toolbar, .crop-overlay"))
1518
+ return true;
936
1519
  return false;
937
1520
  },
938
1521
  selectNode: () => {
@@ -944,6 +1527,8 @@ const imageBlockView = $view(
944
1527
  destroy: () => {
945
1528
  disposeSelectedWatcher();
946
1529
  disposeAlignWatcher();
1530
+ disposeCropWatcher();
1531
+ disposeBorderWatcher();
947
1532
  app.unmount();
948
1533
  dom.remove();
949
1534
  }