@ai-markdown/core 3.4.0 → 3.4.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.
|
@@ -696,9 +696,14 @@ function imageTransformStyle(transform) {
|
|
|
696
696
|
const { x, y, scale, rotate, flipX, flipY } = transform;
|
|
697
697
|
return `translate3d(${x}px, ${y}px, 0) scale3d(${flipX ? "-" : ""}${scale}, ${flipY ? "-" : ""}${scale}, 1) rotate(${rotate}deg)`;
|
|
698
698
|
}
|
|
699
|
-
|
|
699
|
+
const DEFAULT_SCALE_LIMITS = {
|
|
700
|
+
min: 1,
|
|
701
|
+
max: 50
|
|
702
|
+
};
|
|
703
|
+
function zoomImage(transform, ratio, geometry, centerX = geometry.viewportWidth / 2, centerY = geometry.viewportHeight / 2, touch = false, limits = DEFAULT_SCALE_LIMITS) {
|
|
700
704
|
if (!Number.isFinite(ratio) || ratio <= 0) return transform;
|
|
701
|
-
const
|
|
705
|
+
const floor = touch ? .01 : limits.min;
|
|
706
|
+
const scale = Math.min(limits.max, Math.max(floor, transform.scale * ratio));
|
|
702
707
|
const difference = scale / transform.scale - 1;
|
|
703
708
|
let x = transform.x - difference * (centerX - transform.x - geometry.left - geometry.width / 2);
|
|
704
709
|
let y = transform.y - difference * (centerY - transform.y - geometry.top - geometry.height / 2);
|
|
@@ -710,19 +715,19 @@ function zoomImage(transform, ratio, geometry, centerX = geometry.viewportWidth
|
|
|
710
715
|
scale
|
|
711
716
|
};
|
|
712
717
|
}
|
|
713
|
-
function imageWheelRatio(delta, mode = 0, pinch = false) {
|
|
718
|
+
function imageWheelRatio(delta, mode = 0, pinch = false, step = .5) {
|
|
714
719
|
if (!Number.isFinite(delta) || delta === 0) return 1;
|
|
715
|
-
if (pinch) return Math.min(1
|
|
720
|
+
if (pinch) return Math.min(1 + step, Math.max(1 / (1 + step), Math.exp(-delta / 100)));
|
|
716
721
|
const pixels = mode === 1 ? delta * 100 / 3 : mode === 2 ? delta * 100 : delta;
|
|
717
|
-
const ratio = 1 + Math.min(Math.abs(pixels / 100), 1) *
|
|
722
|
+
const ratio = 1 + Math.min(Math.abs(pixels / 100), 1) * step;
|
|
718
723
|
return pixels > 0 ? 1 / ratio : ratio;
|
|
719
724
|
}
|
|
720
|
-
function reboundImage(transform, geometry, bounds) {
|
|
721
|
-
if (transform.scale <
|
|
725
|
+
function reboundImage(transform, geometry, bounds, minScale = 1) {
|
|
726
|
+
if (transform.scale < minScale) return {
|
|
722
727
|
...transform,
|
|
723
728
|
x: 0,
|
|
724
729
|
y: 0,
|
|
725
|
-
scale:
|
|
730
|
+
scale: minScale
|
|
726
731
|
};
|
|
727
732
|
const rotated = transform.rotate % 180 !== 0;
|
|
728
733
|
const width = (rotated ? geometry.height : geometry.width) * transform.scale;
|
|
@@ -754,9 +759,8 @@ function imagePinchCenter(oldA, oldB, a, b) {
|
|
|
754
759
|
y: oldA.y + ratio * (oldB.y - oldA.y)
|
|
755
760
|
};
|
|
756
761
|
}
|
|
757
|
-
const ZOOM_STEP = 1.5;
|
|
758
|
-
const MAX_SCALE = 50;
|
|
759
762
|
const CLOSE_MS = 300;
|
|
763
|
+
const positive = (value, fallback) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
760
764
|
const closedState = Object.freeze({
|
|
761
765
|
phase: "closed",
|
|
762
766
|
items: Object.freeze([]),
|
|
@@ -765,19 +769,34 @@ const closedState = Object.freeze({
|
|
|
765
769
|
transform: initialImageTransform(),
|
|
766
770
|
status: "loading",
|
|
767
771
|
moving: false,
|
|
772
|
+
movable: true,
|
|
773
|
+
origin: void 0,
|
|
768
774
|
canPrevious: false,
|
|
769
775
|
canNext: false,
|
|
770
776
|
canZoomIn: false,
|
|
771
777
|
canZoomOut: false
|
|
772
778
|
});
|
|
773
779
|
function createImagePreviewController(host, publish, options = {}) {
|
|
780
|
+
const limits = {
|
|
781
|
+
min: positive(options.minScale, 1),
|
|
782
|
+
max: 0
|
|
783
|
+
};
|
|
784
|
+
limits.max = Math.max(limits.min, positive(options.maxScale, 50));
|
|
785
|
+
const baseScale = Math.min(limits.max, Math.max(limits.min, 1));
|
|
786
|
+
const scaleStep = positive(options.scaleStep, .5);
|
|
787
|
+
const movable = options.movable ?? true;
|
|
788
|
+
const wheelZoom = options.wheel ?? true;
|
|
774
789
|
let phase = "closed";
|
|
775
790
|
let items = [];
|
|
776
791
|
let selected;
|
|
777
792
|
let current = -1;
|
|
778
|
-
let transform =
|
|
793
|
+
let transform = {
|
|
794
|
+
...initialImageTransform(),
|
|
795
|
+
scale: baseScale
|
|
796
|
+
};
|
|
779
797
|
let status = "loading";
|
|
780
798
|
let moving = false;
|
|
799
|
+
let origin;
|
|
781
800
|
let unsubscribe;
|
|
782
801
|
let cancelPublish;
|
|
783
802
|
let cancelOpening;
|
|
@@ -796,23 +815,40 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
796
815
|
transform,
|
|
797
816
|
status,
|
|
798
817
|
moving,
|
|
818
|
+
movable,
|
|
819
|
+
origin,
|
|
799
820
|
canPrevious: current > 0,
|
|
800
821
|
canNext: current < items.length - 1,
|
|
801
|
-
canZoomIn: ready && transform.scale <
|
|
802
|
-
canZoomOut: ready && transform.scale >
|
|
822
|
+
canZoomIn: ready && transform.scale < limits.max,
|
|
823
|
+
canZoomOut: ready && transform.scale > limits.min
|
|
803
824
|
};
|
|
804
825
|
};
|
|
826
|
+
let reported;
|
|
827
|
+
const flush = () => {
|
|
828
|
+
publish(snapshot());
|
|
829
|
+
const action = reported;
|
|
830
|
+
reported = void 0;
|
|
831
|
+
if (action) options.onTransform?.({
|
|
832
|
+
transform,
|
|
833
|
+
action
|
|
834
|
+
});
|
|
835
|
+
};
|
|
805
836
|
const emit = () => {
|
|
806
837
|
cancelPublish?.();
|
|
807
838
|
cancelPublish = void 0;
|
|
808
|
-
|
|
839
|
+
flush();
|
|
809
840
|
};
|
|
810
841
|
const emitNextFrame = () => {
|
|
811
842
|
cancelPublish ??= host.frame(() => {
|
|
812
843
|
cancelPublish = void 0;
|
|
813
|
-
|
|
844
|
+
flush();
|
|
814
845
|
});
|
|
815
846
|
};
|
|
847
|
+
const apply = (next, action) => {
|
|
848
|
+
if (next.x === transform.x && next.y === transform.y && next.scale === transform.scale && next.rotate === transform.rotate && next.flipX === transform.flipX && next.flipY === transform.flipY) return;
|
|
849
|
+
transform = next;
|
|
850
|
+
reported = action;
|
|
851
|
+
};
|
|
816
852
|
const endGesture = () => {
|
|
817
853
|
pointers.clear();
|
|
818
854
|
grip = void 0;
|
|
@@ -820,22 +856,26 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
820
856
|
moving = false;
|
|
821
857
|
};
|
|
822
858
|
const startImage = () => {
|
|
823
|
-
transform =
|
|
859
|
+
transform = {
|
|
860
|
+
...initialImageTransform(),
|
|
861
|
+
scale: baseScale
|
|
862
|
+
};
|
|
863
|
+
reported = void 0;
|
|
824
864
|
status = "loading";
|
|
825
865
|
endGesture();
|
|
826
866
|
};
|
|
827
|
-
const zoom = (ratio, x, y, touch = false) => {
|
|
867
|
+
const zoom = (action, ratio, x, y, touch = false) => {
|
|
828
868
|
const box = host.geometry();
|
|
829
|
-
if (box && status === "ready")
|
|
869
|
+
if (box && status === "ready") apply(zoomImage(transform, ratio, box, x, y, touch, limits), action);
|
|
830
870
|
};
|
|
831
871
|
const rebound = () => {
|
|
832
|
-
if (transform.scale <
|
|
833
|
-
|
|
872
|
+
if (transform.scale < limits.min) {
|
|
873
|
+
apply({
|
|
834
874
|
...transform,
|
|
835
875
|
x: 0,
|
|
836
876
|
y: 0,
|
|
837
|
-
scale:
|
|
838
|
-
};
|
|
877
|
+
scale: limits.min
|
|
878
|
+
}, "rebound");
|
|
839
879
|
return;
|
|
840
880
|
}
|
|
841
881
|
const box = host.geometry();
|
|
@@ -843,18 +883,28 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
843
883
|
const turned = transform.rotate % 180 !== 0;
|
|
844
884
|
const width = (turned ? box.height : box.width) * transform.scale;
|
|
845
885
|
const height = (turned ? box.width : box.height) * transform.scale;
|
|
846
|
-
|
|
886
|
+
apply(reboundImage(transform, box, {
|
|
847
887
|
left: box.left + box.width / 2 + transform.x - width / 2,
|
|
848
888
|
top: box.top + box.height / 2 + transform.y - height / 2
|
|
849
|
-
});
|
|
889
|
+
}, limits.min), "rebound");
|
|
890
|
+
};
|
|
891
|
+
const anchorOf = (id) => {
|
|
892
|
+
const point = host.anchor?.(id);
|
|
893
|
+
return point && Number.isFinite(point.x) && Number.isFinite(point.y) ? {
|
|
894
|
+
x: point.x,
|
|
895
|
+
y: point.y
|
|
896
|
+
} : void 0;
|
|
850
897
|
};
|
|
851
898
|
const finishClosing = () => {
|
|
852
899
|
closeTimer = void 0;
|
|
853
900
|
phase = "closed";
|
|
854
901
|
items = [];
|
|
855
902
|
selected = void 0;
|
|
903
|
+
origin = void 0;
|
|
856
904
|
current = -1;
|
|
905
|
+
reported = void 0;
|
|
857
906
|
emit();
|
|
907
|
+
options.afterOpenChange?.(false);
|
|
858
908
|
};
|
|
859
909
|
const close = () => {
|
|
860
910
|
if (phase === "closed" || phase === "closing") return;
|
|
@@ -863,20 +913,36 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
863
913
|
unsubscribe?.();
|
|
864
914
|
unsubscribe = void 0;
|
|
865
915
|
endGesture();
|
|
916
|
+
reported = void 0;
|
|
917
|
+
origin = selected ? anchorOf(selected) : void 0;
|
|
866
918
|
phase = "closing";
|
|
919
|
+
const info = {
|
|
920
|
+
current,
|
|
921
|
+
item: items[current]
|
|
922
|
+
};
|
|
867
923
|
const duration = typeof options.closeDuration === "function" ? options.closeDuration() : options.closeDuration ?? CLOSE_MS;
|
|
868
924
|
if (duration > 0) {
|
|
869
925
|
emit();
|
|
870
926
|
closeTimer = setTimeout(finishClosing, duration);
|
|
871
|
-
|
|
927
|
+
options.onOpenChange?.(false, info);
|
|
928
|
+
} else try {
|
|
929
|
+
options.onOpenChange?.(false, info);
|
|
930
|
+
} finally {
|
|
931
|
+
if (phase === "closing") finishClosing();
|
|
932
|
+
}
|
|
872
933
|
};
|
|
873
934
|
const go = (delta) => {
|
|
874
935
|
const target = current + delta;
|
|
875
936
|
if (phase === "closed" || phase === "closing" || target < 0 || target >= items.length || target === current) return;
|
|
937
|
+
const previous = current;
|
|
938
|
+
const { x, y, scale, rotate, flipX, flipY } = transform;
|
|
939
|
+
const transformed = x !== 0 || y !== 0 || scale !== baseScale || rotate !== 0 || flipX || flipY;
|
|
876
940
|
current = target;
|
|
877
941
|
selected = items[target].id;
|
|
878
942
|
startImage();
|
|
943
|
+
if (transformed) reported = delta < 0 ? "prev" : "next";
|
|
879
944
|
emit();
|
|
945
|
+
options.onChange?.(current, previous);
|
|
880
946
|
};
|
|
881
947
|
const follow = (gallery) => {
|
|
882
948
|
const next = gallery.items();
|
|
@@ -900,6 +966,7 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
900
966
|
items = list;
|
|
901
967
|
current = index;
|
|
902
968
|
selected = id;
|
|
969
|
+
origin = anchorOf(id);
|
|
903
970
|
startImage();
|
|
904
971
|
unsubscribe = gallery.subscribe(() => follow(gallery));
|
|
905
972
|
if (phase === "open") {
|
|
@@ -907,15 +974,26 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
907
974
|
return true;
|
|
908
975
|
}
|
|
909
976
|
cancelOpening = void 0;
|
|
977
|
+
const starting = phase !== "opening";
|
|
910
978
|
phase = "opening";
|
|
911
979
|
emit();
|
|
912
980
|
cancelOpening = host.frame(() => {
|
|
981
|
+
const measured = selected ? anchorOf(selected) : void 0;
|
|
982
|
+
if (measured?.x !== origin?.x || measured?.y !== origin?.y) {
|
|
983
|
+
origin = measured;
|
|
984
|
+
emit();
|
|
985
|
+
}
|
|
913
986
|
cancelOpening = host.frame(() => {
|
|
914
987
|
cancelOpening = void 0;
|
|
915
988
|
phase = "open";
|
|
916
989
|
emit();
|
|
990
|
+
options.afterOpenChange?.(true);
|
|
917
991
|
});
|
|
918
992
|
});
|
|
993
|
+
if (starting) options.onOpenChange?.(true, {
|
|
994
|
+
current,
|
|
995
|
+
item: items[current]
|
|
996
|
+
});
|
|
919
997
|
return true;
|
|
920
998
|
},
|
|
921
999
|
close,
|
|
@@ -926,24 +1004,24 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
926
1004
|
if (name === "prev") return go(-1);
|
|
927
1005
|
if (name === "next") return go(1);
|
|
928
1006
|
if (status !== "ready") return;
|
|
929
|
-
if (name === "zoomIn") zoom(
|
|
930
|
-
else if (name === "zoomOut") zoom(1 /
|
|
931
|
-
else if (name === "rotateLeft")
|
|
1007
|
+
if (name === "zoomIn") zoom(name, 1 + scaleStep);
|
|
1008
|
+
else if (name === "zoomOut") zoom(name, 1 / (1 + scaleStep));
|
|
1009
|
+
else if (name === "rotateLeft") apply({
|
|
932
1010
|
...transform,
|
|
933
1011
|
rotate: transform.rotate - 90
|
|
934
|
-
};
|
|
935
|
-
else if (name === "rotateRight")
|
|
1012
|
+
}, name);
|
|
1013
|
+
else if (name === "rotateRight") apply({
|
|
936
1014
|
...transform,
|
|
937
1015
|
rotate: transform.rotate + 90
|
|
938
|
-
};
|
|
939
|
-
else if (name === "flipX")
|
|
1016
|
+
}, name);
|
|
1017
|
+
else if (name === "flipX") apply({
|
|
940
1018
|
...transform,
|
|
941
1019
|
flipX: !transform.flipX
|
|
942
|
-
};
|
|
943
|
-
else if (name === "flipY")
|
|
1020
|
+
}, name);
|
|
1021
|
+
else if (name === "flipY") apply({
|
|
944
1022
|
...transform,
|
|
945
1023
|
flipY: !transform.flipY
|
|
946
|
-
};
|
|
1024
|
+
}, name);
|
|
947
1025
|
emit();
|
|
948
1026
|
},
|
|
949
1027
|
loaded() {
|
|
@@ -958,7 +1036,7 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
958
1036
|
emit();
|
|
959
1037
|
},
|
|
960
1038
|
pointerDown(pointer) {
|
|
961
|
-
if (phase !== "open" && phase !== "opening" || status !== "ready") return false;
|
|
1039
|
+
if (!movable || phase !== "open" && phase !== "opening" || status !== "ready") return false;
|
|
962
1040
|
if (pointer.button !== void 0 && pointer.button !== 0) return false;
|
|
963
1041
|
if (pointers.size >= 2 && !pointers.has(pointer.id)) return false;
|
|
964
1042
|
pointers.set(pointer.id, {
|
|
@@ -985,12 +1063,12 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
985
1063
|
const [a, b] = [...pointers.values()];
|
|
986
1064
|
const span = Math.hypot(before[0].x - before[1].x, before[0].y - before[1].y);
|
|
987
1065
|
const center = imagePinchCenter(before[0], before[1], a, b);
|
|
988
|
-
if (span > 0) zoom(Math.hypot(a.x - b.x, a.y - b.y) / span, center.x, center.y, true);
|
|
989
|
-
} else if (grip)
|
|
1066
|
+
if (span > 0) zoom("pinch", Math.hypot(a.x - b.x, a.y - b.y) / span, center.x, center.y, true);
|
|
1067
|
+
} else if (grip) apply({
|
|
990
1068
|
...transform,
|
|
991
1069
|
x: pointer.x - grip.x,
|
|
992
1070
|
y: pointer.y - grip.y
|
|
993
|
-
};
|
|
1071
|
+
}, "move");
|
|
994
1072
|
displaced = true;
|
|
995
1073
|
emitNextFrame();
|
|
996
1074
|
},
|
|
@@ -1010,20 +1088,20 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
1010
1088
|
emit();
|
|
1011
1089
|
},
|
|
1012
1090
|
wheel(input) {
|
|
1013
|
-
if (phase !== "open" || status !== "ready" || !input.deltaY) return false;
|
|
1014
|
-
zoom(imageWheelRatio(input.deltaY, input.mode, input.pinch), input.x, input.y);
|
|
1091
|
+
if (!wheelZoom || phase !== "open" || status !== "ready" || !input.deltaY) return false;
|
|
1092
|
+
zoom("wheel", imageWheelRatio(input.deltaY, input.mode, input.pinch, scaleStep), input.x, input.y);
|
|
1015
1093
|
emitNextFrame();
|
|
1016
1094
|
return true;
|
|
1017
1095
|
},
|
|
1018
1096
|
doubleClick(x, y) {
|
|
1019
1097
|
if (phase !== "open" || status !== "ready") return;
|
|
1020
|
-
if (transform.scale !==
|
|
1098
|
+
if (transform.scale !== baseScale) apply({
|
|
1021
1099
|
...transform,
|
|
1022
1100
|
x: 0,
|
|
1023
1101
|
y: 0,
|
|
1024
|
-
scale:
|
|
1025
|
-
};
|
|
1026
|
-
else zoom(
|
|
1102
|
+
scale: baseScale
|
|
1103
|
+
}, "doubleClick");
|
|
1104
|
+
else zoom("doubleClick", 1 + scaleStep, x, y);
|
|
1027
1105
|
emit();
|
|
1028
1106
|
},
|
|
1029
1107
|
key(key) {
|
|
@@ -1043,7 +1121,9 @@ function createImagePreviewController(host, publish, options = {}) {
|
|
|
1043
1121
|
phase = "closed";
|
|
1044
1122
|
items = [];
|
|
1045
1123
|
selected = void 0;
|
|
1124
|
+
origin = void 0;
|
|
1046
1125
|
current = -1;
|
|
1126
|
+
reported = void 0;
|
|
1047
1127
|
}
|
|
1048
1128
|
};
|
|
1049
1129
|
}
|