@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
- function zoomImage(transform, ratio, geometry, centerX = geometry.viewportWidth / 2, centerY = geometry.viewportHeight / 2, touch = false) {
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 scale = Math.min(50, touch ? Math.max(.01, transform.scale * ratio) : Math.max(1, transform.scale * ratio));
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.5, Math.max(1 / 1.5, Math.exp(-delta / 100)));
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) * .5;
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 < 1) return {
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: 1
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 = initialImageTransform();
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 < MAX_SCALE,
802
- canZoomOut: ready && transform.scale > 1
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
- publish(snapshot());
839
+ flush();
809
840
  };
810
841
  const emitNextFrame = () => {
811
842
  cancelPublish ??= host.frame(() => {
812
843
  cancelPublish = void 0;
813
- publish(snapshot());
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 = initialImageTransform();
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") transform = zoomImage(transform, ratio, box, x, y, touch);
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 < 1) {
833
- transform = {
872
+ if (transform.scale < limits.min) {
873
+ apply({
834
874
  ...transform,
835
875
  x: 0,
836
876
  y: 0,
837
- scale: 1
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
- transform = reboundImage(transform, box, {
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
- } else finishClosing();
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(ZOOM_STEP);
930
- else if (name === "zoomOut") zoom(1 / ZOOM_STEP);
931
- else if (name === "rotateLeft") transform = {
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") transform = {
1012
+ }, name);
1013
+ else if (name === "rotateRight") apply({
936
1014
  ...transform,
937
1015
  rotate: transform.rotate + 90
938
- };
939
- else if (name === "flipX") transform = {
1016
+ }, name);
1017
+ else if (name === "flipX") apply({
940
1018
  ...transform,
941
1019
  flipX: !transform.flipX
942
- };
943
- else if (name === "flipY") transform = {
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) transform = {
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 !== 1) transform = {
1098
+ if (transform.scale !== baseScale) apply({
1021
1099
  ...transform,
1022
1100
  x: 0,
1023
1101
  y: 0,
1024
- scale: 1
1025
- };
1026
- else zoom(ZOOM_STEP, x, y);
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
  }