@jvs-milkdown/components 1.2.29 → 1.2.30

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.
@@ -796,12 +796,6 @@ const ImageViewer = defineComponent({
796
796
  window.addEventListener("pointermove", onResizeHandlePointerMove);
797
797
  window.addEventListener("pointerup", onResizeHandlePointerUp);
798
798
  };
799
- const borderStyleOptions = [
800
- { label: "none", value: "none" },
801
- { label: "solid", value: "solid" },
802
- { label: "dashed", value: "dashed" },
803
- { label: "dotted", value: "dotted" }
804
- ];
805
799
  const onToggleCropPanel = (e) => {
806
800
  e.preventDefault();
807
801
  e.stopPropagation();
@@ -813,11 +807,295 @@ const ImageViewer = defineComponent({
813
807
  startCropping();
814
808
  }
815
809
  };
816
- const onToggleBorderPanel = (e) => {
810
+ const onToggleBorder = (e) => {
811
+ var _a2;
817
812
  e.preventDefault();
818
813
  e.stopPropagation();
819
814
  if (readonly.value) return;
820
- showBorderPanel.value = !showBorderPanel.value;
815
+ const isSolid = borderStyle.value === "solid" && ((_a2 = borderWidth.value) != null ? _a2 : 0) === 1;
816
+ if (isSolid) {
817
+ setAttr("borderStyle", "none");
818
+ setAttr("borderWidth", 0);
819
+ } else {
820
+ setAttr("borderStyle", "solid");
821
+ setAttr("borderWidth", 1);
822
+ if (!borderColor.value) {
823
+ setAttr("borderColor", "#000000");
824
+ }
825
+ }
826
+ };
827
+ const openLightbox = (images, startIndex) => {
828
+ var _a2;
829
+ let currentIndex = startIndex;
830
+ let scale = 1;
831
+ let rotate = 0;
832
+ const doc = ((_a2 = wrapperRef.value) == null ? void 0 : _a2.ownerDocument) || document;
833
+ const overlay = doc.createElement("div");
834
+ overlay.style.position = "fixed";
835
+ overlay.style.inset = "0";
836
+ overlay.style.backgroundColor = "rgba(0, 0, 0, 0.5)";
837
+ overlay.style.zIndex = "99999";
838
+ overlay.style.display = "flex";
839
+ overlay.style.flexDirection = "column";
840
+ overlay.style.alignItems = "center";
841
+ overlay.style.justifyContent = "center";
842
+ overlay.style.userSelect = "none";
843
+ const imgContainer = doc.createElement("div");
844
+ imgContainer.style.position = "relative";
845
+ imgContainer.style.display = "flex";
846
+ imgContainer.style.alignItems = "center";
847
+ imgContainer.style.justifyContent = "center";
848
+ imgContainer.style.maxWidth = "90%";
849
+ imgContainer.style.maxHeight = "80%";
850
+ const img = doc.createElement("img");
851
+ img.src = images[currentIndex] || "";
852
+ img.style.maxWidth = "100%";
853
+ img.style.maxHeight = "100%";
854
+ img.style.objectFit = "contain";
855
+ img.style.borderRadius = "4px";
856
+ img.style.transition = "transform 0.2s ease-out, opacity 0.2s ease-out";
857
+ imgContainer.appendChild(img);
858
+ const applyTransform = () => {
859
+ img.style.transform = `scale(${scale}) rotate(${rotate}deg)`;
860
+ };
861
+ const createArrow = (direction) => {
862
+ const arrow = doc.createElement("div");
863
+ arrow.style.position = "absolute";
864
+ arrow.style.top = "50%";
865
+ arrow.style.transform = "translateY(-50%)";
866
+ arrow.style.width = "48px";
867
+ arrow.style.height = "48px";
868
+ arrow.style.borderRadius = "50%";
869
+ arrow.style.backgroundColor = "rgba(0, 0, 0, 0.4)";
870
+ arrow.style.backdropFilter = "blur(8px)";
871
+ arrow.style.webkitBackdropFilter = "blur(8px)";
872
+ arrow.style.color = "#ffffff";
873
+ arrow.style.display = "flex";
874
+ arrow.style.alignItems = "center";
875
+ arrow.style.justifyContent = "center";
876
+ arrow.style.cursor = "pointer";
877
+ arrow.style.transition = "background-color 0.2s, transform 0.2s";
878
+ arrow.style.zIndex = "15";
879
+ const chevronSvg = direction === "left" ? `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>` : `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>`;
880
+ arrow.innerHTML = chevronSvg;
881
+ if (direction === "left") {
882
+ arrow.style.left = "24px";
883
+ } else {
884
+ arrow.style.right = "24px";
885
+ }
886
+ arrow.addEventListener("mouseenter", () => {
887
+ arrow.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
888
+ arrow.style.transform = "translateY(-50%) scale(1.05)";
889
+ });
890
+ arrow.addEventListener("mouseleave", () => {
891
+ arrow.style.backgroundColor = "rgba(0, 0, 0, 0.4)";
892
+ arrow.style.transform = "translateY(-50%) scale(1)";
893
+ });
894
+ return arrow;
895
+ };
896
+ const leftArrow = createArrow("left");
897
+ const rightArrow = createArrow("right");
898
+ overlay.appendChild(leftArrow);
899
+ overlay.appendChild(rightArrow);
900
+ const updateArrowsVisibility = () => {
901
+ leftArrow.style.display = currentIndex > 0 ? "flex" : "none";
902
+ rightArrow.style.display = currentIndex < images.length - 1 ? "flex" : "none";
903
+ };
904
+ const showImage = (index) => {
905
+ if (index < 0 || index >= images.length) return;
906
+ currentIndex = index;
907
+ scale = 1;
908
+ rotate = 0;
909
+ img.style.transform = `scale(0.95) rotate(0deg)`;
910
+ img.style.opacity = "0.5";
911
+ setTimeout(() => {
912
+ img.src = images[currentIndex] || "";
913
+ img.style.transform = `scale(1) rotate(0deg)`;
914
+ img.style.opacity = "1";
915
+ }, 150);
916
+ updateArrowsVisibility();
917
+ updateIndicator();
918
+ };
919
+ leftArrow.addEventListener("click", (e) => {
920
+ e.stopPropagation();
921
+ showImage(currentIndex - 1);
922
+ });
923
+ rightArrow.addEventListener("click", (e) => {
924
+ e.stopPropagation();
925
+ showImage(currentIndex + 1);
926
+ });
927
+ const bottomContainer = doc.createElement("div");
928
+ bottomContainer.style.position = "absolute";
929
+ bottomContainer.style.bottom = "24px";
930
+ bottomContainer.style.left = "50%";
931
+ bottomContainer.style.transform = "translateX(-50%)";
932
+ bottomContainer.style.display = "flex";
933
+ bottomContainer.style.flexDirection = "column";
934
+ bottomContainer.style.alignItems = "center";
935
+ bottomContainer.style.gap = "12px";
936
+ bottomContainer.style.zIndex = "15";
937
+ const indicator = doc.createElement("div");
938
+ indicator.style.color = "#ffffff";
939
+ indicator.style.fontSize = "14px";
940
+ indicator.style.fontFamily = "system-ui, sans-serif";
941
+ indicator.style.fontWeight = "500";
942
+ const updateIndicator = () => {
943
+ indicator.textContent = `${currentIndex + 1} / ${images.length}`;
944
+ };
945
+ updateIndicator();
946
+ updateArrowsVisibility();
947
+ const pillToolbar = doc.createElement("div");
948
+ pillToolbar.style.display = "flex";
949
+ pillToolbar.style.alignItems = "center";
950
+ pillToolbar.style.gap = "8px";
951
+ pillToolbar.style.padding = "6px 12px";
952
+ pillToolbar.style.backgroundColor = "rgba(0, 0, 0, 0.6)";
953
+ pillToolbar.style.backdropFilter = "blur(12px)";
954
+ pillToolbar.style.webkitBackdropFilter = "blur(12px)";
955
+ pillToolbar.style.borderRadius = "24px";
956
+ pillToolbar.style.border = "1px solid rgba(255, 255, 255, 0.1)";
957
+ pillToolbar.style.boxShadow = "0 8px 32px rgba(0, 0, 0, 0.3)";
958
+ const createPillButton = (svgContent, btnTitle, onClickHandler) => {
959
+ const btn = doc.createElement("div");
960
+ btn.style.width = "32px";
961
+ btn.style.height = "32px";
962
+ btn.style.borderRadius = "50%";
963
+ btn.style.display = "flex";
964
+ btn.style.alignItems = "center";
965
+ btn.style.justifyContent = "center";
966
+ btn.style.cursor = "pointer";
967
+ btn.style.color = "#ffffff";
968
+ btn.style.transition = "background-color 0.2s, transform 0.1s";
969
+ btn.title = btnTitle;
970
+ btn.innerHTML = svgContent;
971
+ btn.addEventListener("mouseenter", () => {
972
+ btn.style.backgroundColor = "rgba(255, 255, 255, 0.15)";
973
+ });
974
+ btn.addEventListener("mouseleave", () => {
975
+ btn.style.backgroundColor = "transparent";
976
+ });
977
+ btn.addEventListener("click", (e) => {
978
+ e.stopPropagation();
979
+ onClickHandler();
980
+ });
981
+ return btn;
982
+ };
983
+ const zoomOutSvg = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
984
+ const zoomInSvg = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line><line x1="11" y1="8" x2="11" y2="14"></line><line x1="8" y1="11" x2="14" y2="11"></line></svg>`;
985
+ const resetSvg = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"></path></svg>`;
986
+ const rotateLeftSvg = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><polyline points="3 3 3 8 8 8"></polyline></svg>`;
987
+ const rotateRightSvg = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path><polyline points="21 3 21 8 16 8"></polyline></svg>`;
988
+ const btnZoomOut = createPillButton(zoomOutSvg, "\u7F29\u5C0F", () => {
989
+ scale = Math.max(0.2, Number((scale - 0.2).toFixed(2)));
990
+ applyTransform();
991
+ });
992
+ const btnZoomIn = createPillButton(zoomInSvg, "\u653E\u5927", () => {
993
+ scale = Math.min(5, Number((scale + 0.2).toFixed(2)));
994
+ applyTransform();
995
+ });
996
+ const btnReset = createPillButton(resetSvg, "\u8FD8\u539F", () => {
997
+ scale = 1;
998
+ rotate = 0;
999
+ applyTransform();
1000
+ });
1001
+ const btnRotateLeft = createPillButton(rotateLeftSvg, "\u5411\u5DE6\u65CB\u8F6C", () => {
1002
+ rotate -= 90;
1003
+ applyTransform();
1004
+ });
1005
+ const btnRotateRight = createPillButton(
1006
+ rotateRightSvg,
1007
+ "\u5411\u53F3\u65CB\u8F6C",
1008
+ () => {
1009
+ rotate += 90;
1010
+ applyTransform();
1011
+ }
1012
+ );
1013
+ pillToolbar.appendChild(btnZoomOut);
1014
+ pillToolbar.appendChild(btnZoomIn);
1015
+ pillToolbar.appendChild(btnReset);
1016
+ pillToolbar.appendChild(btnRotateLeft);
1017
+ pillToolbar.appendChild(btnRotateRight);
1018
+ bottomContainer.appendChild(indicator);
1019
+ bottomContainer.appendChild(pillToolbar);
1020
+ const closeBtn = doc.createElement("div");
1021
+ closeBtn.style.position = "absolute";
1022
+ closeBtn.style.top = "24px";
1023
+ closeBtn.style.right = "24px";
1024
+ closeBtn.style.width = "40px";
1025
+ closeBtn.style.height = "40px";
1026
+ closeBtn.style.borderRadius = "50%";
1027
+ closeBtn.style.color = "#ffffff";
1028
+ closeBtn.style.display = "flex";
1029
+ closeBtn.style.alignItems = "center";
1030
+ closeBtn.style.justifyContent = "center";
1031
+ closeBtn.style.cursor = "pointer";
1032
+ closeBtn.style.fontSize = "28px";
1033
+ closeBtn.style.transition = "background-color 0.2s";
1034
+ closeBtn.style.zIndex = "15";
1035
+ closeBtn.innerHTML = "&times;";
1036
+ closeBtn.addEventListener("mouseenter", () => {
1037
+ closeBtn.style.backgroundColor = "rgba(255, 255, 255, 0.1)";
1038
+ });
1039
+ closeBtn.addEventListener("mouseleave", () => {
1040
+ closeBtn.style.backgroundColor = "transparent";
1041
+ });
1042
+ const closeLightbox = () => {
1043
+ doc.removeEventListener("keydown", handleKeyDown);
1044
+ overlay.style.opacity = "0";
1045
+ overlay.style.transition = "opacity 0.2s ease-out";
1046
+ setTimeout(() => {
1047
+ overlay.remove();
1048
+ }, 200);
1049
+ };
1050
+ closeBtn.addEventListener("click", (e) => {
1051
+ e.stopPropagation();
1052
+ closeLightbox();
1053
+ });
1054
+ overlay.addEventListener("click", () => {
1055
+ closeLightbox();
1056
+ });
1057
+ const handleKeyDown = (e) => {
1058
+ if (e.key === "Escape") {
1059
+ closeLightbox();
1060
+ } else if (e.key === "ArrowLeft" && currentIndex > 0) {
1061
+ showImage(currentIndex - 1);
1062
+ } else if (e.key === "ArrowRight" && currentIndex < images.length - 1) {
1063
+ showImage(currentIndex + 1);
1064
+ }
1065
+ };
1066
+ doc.addEventListener("keydown", handleKeyDown);
1067
+ overlay.appendChild(closeBtn);
1068
+ overlay.appendChild(imgContainer);
1069
+ overlay.appendChild(bottomContainer);
1070
+ overlay.style.opacity = "0";
1071
+ overlay.style.transition = "opacity 0.2s ease-out";
1072
+ doc.body.appendChild(overlay);
1073
+ requestAnimationFrame(() => {
1074
+ overlay.style.opacity = "1";
1075
+ });
1076
+ };
1077
+ const onImageDoubleClick = (e) => {
1078
+ var _a2;
1079
+ e.preventDefault();
1080
+ e.stopPropagation();
1081
+ const currentImg = imageRef.value;
1082
+ const currentSrc = currentImg ? currentImg.src : src.value;
1083
+ const rootNode = ((_a2 = wrapperRef.value) == null ? void 0 : _a2.getRootNode()) || document;
1084
+ const allImageElements = rootNode.querySelectorAll("img");
1085
+ const images = [];
1086
+ allImageElements.forEach((img) => {
1087
+ if (img.closest(".milkdown-document-cover, .milkdown-document-header")) {
1088
+ return;
1089
+ }
1090
+ if (img.src && !images.includes(img.src)) {
1091
+ images.push(img.src);
1092
+ }
1093
+ });
1094
+ if (images.length === 0 && currentSrc) {
1095
+ images.push(currentSrc);
1096
+ }
1097
+ const startIndex = currentSrc ? images.indexOf(currentSrc) : 0;
1098
+ openLightbox(images, startIndex >= 0 ? startIndex : 0);
821
1099
  };
822
1100
  const closePanels = () => {
823
1101
  showBorderPanel.value = false;
@@ -938,7 +1216,7 @@ const ImageViewer = defineComponent({
938
1216
  cropDragType = "";
939
1217
  };
940
1218
  return () => {
941
- var _a2, _b, _c, _d, _e, _f, _g, _h;
1219
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
942
1220
  const currentBorderStyle = (_a2 = borderStyle.value) != null ? _a2 : "none";
943
1221
  const currentBorderWidth = localBorderWidth.value !== null ? localBorderWidth.value : (_b = borderWidth.value) != null ? _b : 0;
944
1222
  const currentBorderColor = localBorderColor.value !== null ? localBorderColor.value : (_c = borderColor.value) != null ? _c : "#000000";
@@ -1040,87 +1318,11 @@ const ImageViewer = defineComponent({
1040
1318
  config.borderIcon ? /* @__PURE__ */ h(
1041
1319
  "div",
1042
1320
  {
1043
- class: "image-toolbar-item",
1321
+ class: `image-toolbar-item ${borderStyle.value === "solid" && ((_i = borderWidth.value) != null ? _i : 0) >= 1 ? "active" : ""}`,
1044
1322
  title: "\u8FB9\u6846",
1045
- onClick: onToggleBorderPanel
1323
+ onClick: onToggleBorder
1046
1324
  },
1047
1325
  /* @__PURE__ */ h(Icon, { icon: config.borderIcon })
1048
- ) : null,
1049
- showBorderPanel.value ? /* @__PURE__ */ h(
1050
- "div",
1051
- {
1052
- class: "setting-panel border-panel",
1053
- draggable: "true",
1054
- onClick: (e) => e.stopPropagation(),
1055
- onMousedown: (e) => e.stopPropagation(),
1056
- onPointerdown: (e) => e.stopPropagation(),
1057
- onDragstart: (e) => {
1058
- e.preventDefault();
1059
- e.stopPropagation();
1060
- }
1061
- },
1062
- /* @__PURE__ */ h("div", { class: "setting-panel-title" }, "\u8FB9\u6846\u8BBE\u7F6E"),
1063
- /* @__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(
1064
- "div",
1065
- {
1066
- class: `border-style-option ${currentBorderStyle === opt.value ? "active" : ""}`,
1067
- onClick: (e) => {
1068
- e.stopPropagation();
1069
- setAttr("borderStyle", opt.value);
1070
- }
1071
- },
1072
- opt.label === "none" ? "\u65E0" : opt.label === "solid" ? "\u5B9E\u7EBF" : opt.label === "dashed" ? "\u865A\u7EBF" : "\u70B9\u7EBF"
1073
- )))),
1074
- currentBorderStyle !== "none" ? /* @__PURE__ */ h("div", { class: "setting-row" }, /* @__PURE__ */ h("span", { class: "setting-label" }, "\u5BBD\u5EA6"), /* @__PURE__ */ h(
1075
- "input",
1076
- {
1077
- draggable: "true",
1078
- type: "range",
1079
- min: "1",
1080
- max: "10",
1081
- value: currentBorderWidth,
1082
- onInput: (e) => {
1083
- const target = e.target;
1084
- localBorderWidth.value = Number(target.value);
1085
- },
1086
- onChange: (e) => {
1087
- const target = e.target;
1088
- setAttr("borderWidth", Number(target.value));
1089
- localBorderWidth.value = null;
1090
- },
1091
- onClick: (e) => e.stopPropagation(),
1092
- onMousedown: (e) => e.stopPropagation(),
1093
- onPointerdown: (e) => e.stopPropagation(),
1094
- onDragstart: (e) => {
1095
- e.preventDefault();
1096
- e.stopPropagation();
1097
- }
1098
- }
1099
- ), /* @__PURE__ */ h("span", { class: "setting-value" }, currentBorderWidth, "px")) : null,
1100
- currentBorderStyle !== "none" ? /* @__PURE__ */ h("div", { class: "setting-row" }, /* @__PURE__ */ h("span", { class: "setting-label" }, "\u989C\u8272"), /* @__PURE__ */ h(
1101
- "input",
1102
- {
1103
- draggable: "true",
1104
- type: "color",
1105
- value: currentBorderColor,
1106
- onInput: (e) => {
1107
- const target = e.target;
1108
- localBorderColor.value = target.value;
1109
- },
1110
- onChange: (e) => {
1111
- const target = e.target;
1112
- setAttr("borderColor", target.value);
1113
- localBorderColor.value = null;
1114
- },
1115
- onClick: (e) => e.stopPropagation(),
1116
- onMousedown: (e) => e.stopPropagation(),
1117
- onPointerdown: (e) => e.stopPropagation(),
1118
- onDragstart: (e) => {
1119
- e.preventDefault();
1120
- e.stopPropagation();
1121
- }
1122
- }
1123
- )) : null
1124
1326
  ) : null
1125
1327
  ) : null, /* @__PURE__ */ h(
1126
1328
  "div",
@@ -1128,7 +1330,8 @@ const ImageViewer = defineComponent({
1128
1330
  class: `image-wrapper${isCropping.value ? " cropping" : ""}`,
1129
1331
  ref: wrapperRef,
1130
1332
  style: wrapperStyle,
1131
- onClick: closePanels
1333
+ onClick: closePanels,
1334
+ onDblclick: onImageDoubleClick
1132
1335
  },
1133
1336
  cropClipStyle ? /* @__PURE__ */ h("div", { class: "crop-clip", style: cropClipStyle }, /* @__PURE__ */ h(
1134
1337
  "img",