@masters-union/union-stack 0.3.12 → 0.3.14
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.
- package/dist/cdn/loader.v1.global.js +2 -2
- package/dist/cdn/loader.v1.global.js.map +1 -1
- package/dist/{chunk-BLZGF6JP.cjs → chunk-24FXFOLY.cjs} +3 -3
- package/dist/{chunk-BLZGF6JP.cjs.map → chunk-24FXFOLY.cjs.map} +1 -1
- package/dist/{chunk-UPKEFUU6.js → chunk-A6QABSM5.js} +3 -3
- package/dist/{chunk-UPKEFUU6.js.map → chunk-A6QABSM5.js.map} +1 -1
- package/dist/{chunk-XGSFHZSI.js → chunk-LOOZO22K.js} +3 -3
- package/dist/{chunk-XGSFHZSI.js.map → chunk-LOOZO22K.js.map} +1 -1
- package/dist/{chunk-45FKUCRN.cjs → chunk-P32VSH6B.cjs} +7 -7
- package/dist/{chunk-45FKUCRN.cjs.map → chunk-P32VSH6B.cjs.map} +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.js +3 -3
- package/dist/node.cjs +7 -7
- package/dist/node.js +1 -1
- package/dist/picker.cjs +73 -54
- package/dist/picker.cjs.map +1 -1
- package/dist/picker.js +73 -54
- package/dist/picker.js.map +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.js +2 -2
- package/package.json +1 -1
package/dist/picker.cjs
CHANGED
|
@@ -662,8 +662,6 @@ var ImageEditor = class {
|
|
|
662
662
|
constructor(opts) {
|
|
663
663
|
this.opts = opts;
|
|
664
664
|
this.cropBox = null;
|
|
665
|
-
// What's currently rendered to the user, sized to fit MAX_DISPLAY.
|
|
666
|
-
this.displayScale = 1;
|
|
667
665
|
// Tracks whether the working canvas has transparency (post-circle), so
|
|
668
666
|
// export() can pick PNG vs JPEG correctly.
|
|
669
667
|
this.hasAlpha = false;
|
|
@@ -675,12 +673,13 @@ var ImageEditor = class {
|
|
|
675
673
|
this.dragStart = null;
|
|
676
674
|
this.onPointerMove = (e) => {
|
|
677
675
|
if (!this.dragKind || !this.dragStart || !this.cropRect) return;
|
|
678
|
-
const
|
|
679
|
-
const
|
|
676
|
+
const m = this.canvasMetrics();
|
|
677
|
+
const dx = (e.clientX - this.dragStart.px) / (m.scaleX || 1);
|
|
678
|
+
const dy = (e.clientY - this.dragStart.py) / (m.scaleY || 1);
|
|
680
679
|
const start = this.dragStart.rect;
|
|
681
|
-
const maxW = this.
|
|
682
|
-
const maxH = this.
|
|
683
|
-
const min =
|
|
680
|
+
const maxW = this.working.width;
|
|
681
|
+
const maxH = this.working.height;
|
|
682
|
+
const min = this.minCropImg();
|
|
684
683
|
if (this.aspect && this.dragKind !== "move") {
|
|
685
684
|
switch (this.dragKind) {
|
|
686
685
|
case "se":
|
|
@@ -876,7 +875,6 @@ var ImageEditor = class {
|
|
|
876
875
|
const dh = Math.max(1, Math.round(wh * scale));
|
|
877
876
|
this.displayCanvas.width = dw;
|
|
878
877
|
this.displayCanvas.height = dh;
|
|
879
|
-
this.displayScale = scale;
|
|
880
878
|
const ctx = this.displayCanvas.getContext("2d");
|
|
881
879
|
if (!ctx) return;
|
|
882
880
|
ctx.clearRect(0, 0, dw, dh);
|
|
@@ -895,43 +893,44 @@ var ImageEditor = class {
|
|
|
895
893
|
this.mode = "crop";
|
|
896
894
|
this.cropTool.dataset.active = "true";
|
|
897
895
|
this.cropTool.innerHTML = `${ICON.check} <span>Apply crop</span>`;
|
|
898
|
-
const
|
|
899
|
-
const
|
|
896
|
+
const iw = this.working.width;
|
|
897
|
+
const ih = this.working.height;
|
|
900
898
|
if (this.aspect) {
|
|
901
899
|
const a = this.aspect;
|
|
902
|
-
|
|
900
|
+
const minImg = this.minCropImg();
|
|
901
|
+
let w = iw;
|
|
903
902
|
let h = w / a;
|
|
904
|
-
if (h >
|
|
905
|
-
h =
|
|
903
|
+
if (h > ih) {
|
|
904
|
+
h = ih;
|
|
906
905
|
w = h * a;
|
|
907
906
|
}
|
|
908
907
|
w = w * 0.9;
|
|
909
908
|
h = w / a;
|
|
910
|
-
if (w <
|
|
911
|
-
w =
|
|
909
|
+
if (w < minImg) {
|
|
910
|
+
w = minImg;
|
|
912
911
|
h = w / a;
|
|
913
912
|
}
|
|
914
|
-
if (h <
|
|
915
|
-
h =
|
|
913
|
+
if (h < minImg) {
|
|
914
|
+
h = minImg;
|
|
916
915
|
w = h * a;
|
|
917
916
|
}
|
|
918
|
-
if (w >
|
|
919
|
-
w =
|
|
917
|
+
if (w > iw) {
|
|
918
|
+
w = iw;
|
|
920
919
|
h = w / a;
|
|
921
920
|
}
|
|
922
|
-
if (h >
|
|
923
|
-
h =
|
|
921
|
+
if (h > ih) {
|
|
922
|
+
h = ih;
|
|
924
923
|
w = h * a;
|
|
925
924
|
}
|
|
926
925
|
this.cropRect = {
|
|
927
|
-
x: Math.round((
|
|
928
|
-
y: Math.round((
|
|
926
|
+
x: Math.round((iw - w) / 2),
|
|
927
|
+
y: Math.round((ih - h) / 2),
|
|
929
928
|
w,
|
|
930
929
|
h
|
|
931
930
|
};
|
|
932
931
|
} else {
|
|
933
|
-
const inset = Math.round(Math.min(
|
|
934
|
-
this.cropRect = { x: inset, y: inset, w:
|
|
932
|
+
const inset = Math.round(Math.min(iw, ih) * 0.1);
|
|
933
|
+
this.cropRect = { x: inset, y: inset, w: iw - inset * 2, h: ih - inset * 2 };
|
|
935
934
|
}
|
|
936
935
|
this.renderCropBox();
|
|
937
936
|
const locked = this.aspect !== null;
|
|
@@ -966,28 +965,28 @@ var ImageEditor = class {
|
|
|
966
965
|
}
|
|
967
966
|
// Push the current crop frame size (in image/output pixels) into the inputs,
|
|
968
967
|
// skipping whichever the user is actively editing so we don't fight typing.
|
|
968
|
+
// cropRect is already in image px, so this is a direct read.
|
|
969
969
|
syncCropDimsInputs() {
|
|
970
970
|
if (!this.cropRect || !this.widthInput || !this.heightInput) return;
|
|
971
|
-
const
|
|
972
|
-
const
|
|
973
|
-
const hImg = Math.max(1, Math.round(this.cropRect.h / s));
|
|
971
|
+
const wImg = Math.max(1, Math.round(this.cropRect.w));
|
|
972
|
+
const hImg = Math.max(1, Math.round(this.cropRect.h));
|
|
974
973
|
if (document.activeElement !== this.widthInput) this.widthInput.value = String(wImg);
|
|
975
974
|
if (document.activeElement !== this.heightInput) this.heightInput.value = String(hImg);
|
|
976
975
|
}
|
|
977
|
-
// Free-form only: resize the crop frame from a typed pixel dimension.
|
|
978
|
-
// at the frame's current top-left and clamped to the
|
|
976
|
+
// Free-form only: resize the crop frame from a typed output-pixel dimension.
|
|
977
|
+
// Anchored at the frame's current top-left and clamped to the image + min size.
|
|
979
978
|
onDimInput(axis) {
|
|
980
979
|
if (this.aspect !== null || !this.cropRect) return;
|
|
981
|
-
const s = this.displayScale || 1;
|
|
982
980
|
const input = axis === "w" ? this.widthInput : this.heightInput;
|
|
983
981
|
const valImg = parseInt(input.value, 10);
|
|
984
982
|
if (!Number.isFinite(valImg) || valImg <= 0) return;
|
|
983
|
+
const min = this.minCropImg();
|
|
985
984
|
if (axis === "w") {
|
|
986
|
-
const maxW = this.
|
|
987
|
-
this.cropRect = { ...this.cropRect, w: clamp(
|
|
985
|
+
const maxW = this.working.width - this.cropRect.x;
|
|
986
|
+
this.cropRect = { ...this.cropRect, w: clamp(valImg, min, maxW) };
|
|
988
987
|
} else {
|
|
989
|
-
const maxH = this.
|
|
990
|
-
this.cropRect = { ...this.cropRect, h: clamp(
|
|
988
|
+
const maxH = this.working.height - this.cropRect.y;
|
|
989
|
+
this.cropRect = { ...this.cropRect, h: clamp(valImg, min, maxH) };
|
|
991
990
|
}
|
|
992
991
|
this.updateCropBox();
|
|
993
992
|
}
|
|
@@ -1010,16 +1009,35 @@ var ImageEditor = class {
|
|
|
1010
1009
|
this.cropBox = box;
|
|
1011
1010
|
this.updateCropBox();
|
|
1012
1011
|
}
|
|
1012
|
+
// The crop rect is stored in IMAGE (working-canvas / output) pixels — the same
|
|
1013
|
+
// space we ultimately crop in — so the on-screen selection always matches the
|
|
1014
|
+
// pixels we extract, regardless of how CSS scales the displayed canvas. These
|
|
1015
|
+
// metrics convert between image px and the canvas's live on-screen size.
|
|
1016
|
+
canvasMetrics() {
|
|
1017
|
+
const c = this.displayCanvas.getBoundingClientRect();
|
|
1018
|
+
const w = this.canvasWrap.getBoundingClientRect();
|
|
1019
|
+
return {
|
|
1020
|
+
scaleX: c.width / (this.working.width || 1),
|
|
1021
|
+
// CSS px per image px
|
|
1022
|
+
scaleY: c.height / (this.working.height || 1),
|
|
1023
|
+
offX: c.left - w.left,
|
|
1024
|
+
// canvas offset inside wrap
|
|
1025
|
+
offY: c.top - w.top
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
// Minimum crop size in IMAGE px, sized so the handles stay ~MIN_CROP px apart
|
|
1029
|
+
// on screen no matter how zoomed the canvas is.
|
|
1030
|
+
minCropImg() {
|
|
1031
|
+
const { scaleX } = this.canvasMetrics();
|
|
1032
|
+
return scaleX > 0 ? MIN_CROP / scaleX : MIN_CROP;
|
|
1033
|
+
}
|
|
1013
1034
|
updateCropBox() {
|
|
1014
1035
|
if (!this.cropBox || !this.cropRect) return;
|
|
1015
|
-
const
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
this.cropBox.style.
|
|
1020
|
-
this.cropBox.style.top = `${top}px`;
|
|
1021
|
-
this.cropBox.style.width = `${this.cropRect.w}px`;
|
|
1022
|
-
this.cropBox.style.height = `${this.cropRect.h}px`;
|
|
1036
|
+
const m = this.canvasMetrics();
|
|
1037
|
+
this.cropBox.style.left = `${m.offX + this.cropRect.x * m.scaleX}px`;
|
|
1038
|
+
this.cropBox.style.top = `${m.offY + this.cropRect.y * m.scaleY}px`;
|
|
1039
|
+
this.cropBox.style.width = `${this.cropRect.w * m.scaleX}px`;
|
|
1040
|
+
this.cropBox.style.height = `${this.cropRect.h * m.scaleY}px`;
|
|
1023
1041
|
this.syncCropDimsInputs();
|
|
1024
1042
|
}
|
|
1025
1043
|
// ---- drag handlers (crop) ----------------------------------------------
|
|
@@ -1037,12 +1055,13 @@ var ImageEditor = class {
|
|
|
1037
1055
|
// the ratio exact; both are clamped so the rect stays on-canvas.
|
|
1038
1056
|
lockedRectFromDrag(anchorX, anchorY, desiredW, signX, signY) {
|
|
1039
1057
|
const a = this.aspect;
|
|
1040
|
-
const maxW = this.
|
|
1041
|
-
const maxH = this.
|
|
1042
|
-
|
|
1058
|
+
const maxW = this.working.width;
|
|
1059
|
+
const maxH = this.working.height;
|
|
1060
|
+
const min = this.minCropImg();
|
|
1061
|
+
let w = Math.max(min, desiredW);
|
|
1043
1062
|
let h = w / a;
|
|
1044
|
-
if (h <
|
|
1045
|
-
h =
|
|
1063
|
+
if (h < min) {
|
|
1064
|
+
h = min;
|
|
1046
1065
|
w = h * a;
|
|
1047
1066
|
}
|
|
1048
1067
|
const roomX = signX > 0 ? maxW - anchorX : anchorX;
|
|
@@ -1059,11 +1078,10 @@ var ImageEditor = class {
|
|
|
1059
1078
|
this.exitCropMode();
|
|
1060
1079
|
return;
|
|
1061
1080
|
}
|
|
1062
|
-
const
|
|
1063
|
-
const
|
|
1064
|
-
const
|
|
1065
|
-
const
|
|
1066
|
-
const sh = Math.round(this.cropRect.h / s);
|
|
1081
|
+
const sx = clamp(Math.round(this.cropRect.x), 0, this.working.width - 1);
|
|
1082
|
+
const sy = clamp(Math.round(this.cropRect.y), 0, this.working.height - 1);
|
|
1083
|
+
const sw = clamp(Math.round(this.cropRect.w), 1, this.working.width - sx);
|
|
1084
|
+
const sh = clamp(Math.round(this.cropRect.h), 1, this.working.height - sy);
|
|
1067
1085
|
const next = document.createElement("canvas");
|
|
1068
1086
|
next.width = sw;
|
|
1069
1087
|
next.height = sh;
|
|
@@ -1128,6 +1146,7 @@ var ImageEditor = class {
|
|
|
1128
1146
|
// ---- apply --------------------------------------------------------------
|
|
1129
1147
|
async applyAndClose() {
|
|
1130
1148
|
this.applyBtn.disabled = true;
|
|
1149
|
+
if (this.mode === "crop") this.applyCrop();
|
|
1131
1150
|
try {
|
|
1132
1151
|
const file = await this.exportFile();
|
|
1133
1152
|
this.opts.onApply(file);
|
|
@@ -1386,10 +1405,10 @@ var Picker = class {
|
|
|
1386
1405
|
this.$urlSource = this.renderUrlSource();
|
|
1387
1406
|
body.appendChild(this.$urlSource);
|
|
1388
1407
|
}
|
|
1389
|
-
this.activateSource(sources[0] ?? "device");
|
|
1390
1408
|
this.$list = el2("div", "us-file-list");
|
|
1391
1409
|
body.appendChild(this.$list);
|
|
1392
1410
|
panel.appendChild(body);
|
|
1411
|
+
this.activateSource(sources[0] ?? "device");
|
|
1393
1412
|
const autoUpload = this.opts.autoUpload === true;
|
|
1394
1413
|
const actions = el2("div", "us-actions");
|
|
1395
1414
|
this.$summary = el2("div", "us-actions-summary", "");
|