@masters-union/union-stack 0.3.11 → 0.3.12
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 +22 -2
- package/dist/cdn/loader.v1.global.js.map +1 -1
- package/dist/{chunk-NIO443GV.cjs → chunk-45FKUCRN.cjs} +7 -7
- package/dist/{chunk-NIO443GV.cjs.map → chunk-45FKUCRN.cjs.map} +1 -1
- package/dist/{chunk-NOAB2Q4B.cjs → chunk-BLZGF6JP.cjs} +3 -3
- package/dist/{chunk-NOAB2Q4B.cjs.map → chunk-BLZGF6JP.cjs.map} +1 -1
- package/dist/{chunk-SP4HHLZB.js → chunk-UPKEFUU6.js} +3 -3
- package/dist/{chunk-SP4HHLZB.js.map → chunk-UPKEFUU6.js.map} +1 -1
- package/dist/{chunk-Z5PZQVST.js → chunk-XGSFHZSI.js} +3 -3
- package/dist/{chunk-Z5PZQVST.js.map → chunk-XGSFHZSI.js.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 +77 -0
- package/dist/picker.cjs.map +1 -1
- package/dist/picker.js +77 -0
- 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
|
@@ -530,6 +530,26 @@ var BASE_CSS = `
|
|
|
530
530
|
.us-tool svg { width: 13px; height: 13px; }
|
|
531
531
|
.us-tool-spacer { flex: 1; }
|
|
532
532
|
|
|
533
|
+
/* Crop dimension inputs \u2014 live W\xD7H readout, editable for free-form crops. */
|
|
534
|
+
.us-crop-dims {
|
|
535
|
+
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
|
|
536
|
+
padding: 10px 16px 0;
|
|
537
|
+
}
|
|
538
|
+
.us-crop-dims[hidden] { display: none; }
|
|
539
|
+
.us-crop-dims-label {
|
|
540
|
+
font-size: 11px; font-weight: 600; letter-spacing: 0.04em;
|
|
541
|
+
text-transform: uppercase; color: var(--us-muted);
|
|
542
|
+
}
|
|
543
|
+
.us-crop-dim-input {
|
|
544
|
+
width: 76px; appearance: none; text-align: center;
|
|
545
|
+
background: var(--us-overlay); border: 1px solid var(--us-border-strong);
|
|
546
|
+
border-radius: 8px; padding: 5px 8px; min-height: 30px;
|
|
547
|
+
font: inherit; font-size: 12px; color: var(--us-fg);
|
|
548
|
+
}
|
|
549
|
+
.us-crop-dim-input:focus { outline: none; border-color: var(--us-primary); }
|
|
550
|
+
.us-crop-dim-input:read-only { opacity: 0.55; cursor: default; }
|
|
551
|
+
.us-crop-dims-x, .us-crop-dims-unit { color: var(--us-muted); font-size: 12px; }
|
|
552
|
+
|
|
533
553
|
.us-editor-footer {
|
|
534
554
|
display: flex; gap: 8px; justify-content: flex-end;
|
|
535
555
|
padding: 12px 16px;
|
|
@@ -775,6 +795,16 @@ var ImageEditor = class {
|
|
|
775
795
|
this.displayCanvas.className = "us-editor-canvas";
|
|
776
796
|
this.canvasWrap.appendChild(this.displayCanvas);
|
|
777
797
|
this.root.appendChild(this.canvasWrap);
|
|
798
|
+
this.cropDims = el("div", "us-crop-dims");
|
|
799
|
+
this.cropDims.hidden = true;
|
|
800
|
+
this.widthInput = this.makeDimInput("Crop width in pixels", "w");
|
|
801
|
+
this.heightInput = this.makeDimInput("Crop height in pixels", "h");
|
|
802
|
+
this.cropDims.appendChild(el("span", "us-crop-dims-label", "Crop size"));
|
|
803
|
+
this.cropDims.appendChild(this.widthInput);
|
|
804
|
+
this.cropDims.appendChild(el("span", "us-crop-dims-x", "\xD7"));
|
|
805
|
+
this.cropDims.appendChild(this.heightInput);
|
|
806
|
+
this.cropDims.appendChild(el("span", "us-crop-dims-unit", "px"));
|
|
807
|
+
this.root.appendChild(this.cropDims);
|
|
778
808
|
const toolbar = el("div", "us-editor-toolbar");
|
|
779
809
|
this.cropTool = makeTool("Crop", ICON.crop);
|
|
780
810
|
this.cropTool.onclick = () => this.toggleCropMode();
|
|
@@ -904,6 +934,12 @@ var ImageEditor = class {
|
|
|
904
934
|
this.cropRect = { x: inset, y: inset, w: dw - inset * 2, h: dh - inset * 2 };
|
|
905
935
|
}
|
|
906
936
|
this.renderCropBox();
|
|
937
|
+
const locked = this.aspect !== null;
|
|
938
|
+
this.widthInput.readOnly = locked;
|
|
939
|
+
this.heightInput.readOnly = locked;
|
|
940
|
+
this.cropDims.dataset.locked = locked ? "true" : "false";
|
|
941
|
+
this.cropDims.hidden = false;
|
|
942
|
+
this.syncCropDimsInputs();
|
|
907
943
|
}
|
|
908
944
|
exitCropMode() {
|
|
909
945
|
this.mode = "none";
|
|
@@ -914,6 +950,46 @@ var ImageEditor = class {
|
|
|
914
950
|
this.cropBox.remove();
|
|
915
951
|
this.cropBox = null;
|
|
916
952
|
}
|
|
953
|
+
this.cropDims.hidden = true;
|
|
954
|
+
}
|
|
955
|
+
// Build a numeric crop-dimension input. `axis` selects which side it edits.
|
|
956
|
+
makeDimInput(ariaLabel, axis) {
|
|
957
|
+
const input = document.createElement("input");
|
|
958
|
+
input.type = "number";
|
|
959
|
+
input.min = "1";
|
|
960
|
+
input.inputMode = "numeric";
|
|
961
|
+
input.className = "us-crop-dim-input";
|
|
962
|
+
input.setAttribute("aria-label", ariaLabel);
|
|
963
|
+
input.addEventListener("input", () => this.onDimInput(axis));
|
|
964
|
+
input.addEventListener("change", () => this.syncCropDimsInputs());
|
|
965
|
+
return input;
|
|
966
|
+
}
|
|
967
|
+
// Push the current crop frame size (in image/output pixels) into the inputs,
|
|
968
|
+
// skipping whichever the user is actively editing so we don't fight typing.
|
|
969
|
+
syncCropDimsInputs() {
|
|
970
|
+
if (!this.cropRect || !this.widthInput || !this.heightInput) return;
|
|
971
|
+
const s = this.displayScale || 1;
|
|
972
|
+
const wImg = Math.max(1, Math.round(this.cropRect.w / s));
|
|
973
|
+
const hImg = Math.max(1, Math.round(this.cropRect.h / s));
|
|
974
|
+
if (document.activeElement !== this.widthInput) this.widthInput.value = String(wImg);
|
|
975
|
+
if (document.activeElement !== this.heightInput) this.heightInput.value = String(hImg);
|
|
976
|
+
}
|
|
977
|
+
// Free-form only: resize the crop frame from a typed pixel dimension. Anchored
|
|
978
|
+
// at the frame's current top-left and clamped to the canvas + the min size.
|
|
979
|
+
onDimInput(axis) {
|
|
980
|
+
if (this.aspect !== null || !this.cropRect) return;
|
|
981
|
+
const s = this.displayScale || 1;
|
|
982
|
+
const input = axis === "w" ? this.widthInput : this.heightInput;
|
|
983
|
+
const valImg = parseInt(input.value, 10);
|
|
984
|
+
if (!Number.isFinite(valImg) || valImg <= 0) return;
|
|
985
|
+
if (axis === "w") {
|
|
986
|
+
const maxW = this.displayCanvas.width - this.cropRect.x;
|
|
987
|
+
this.cropRect = { ...this.cropRect, w: clamp(Math.round(valImg * s), MIN_CROP, maxW) };
|
|
988
|
+
} else {
|
|
989
|
+
const maxH = this.displayCanvas.height - this.cropRect.y;
|
|
990
|
+
this.cropRect = { ...this.cropRect, h: clamp(Math.round(valImg * s), MIN_CROP, maxH) };
|
|
991
|
+
}
|
|
992
|
+
this.updateCropBox();
|
|
917
993
|
}
|
|
918
994
|
renderCropBox() {
|
|
919
995
|
if (!this.cropRect) return;
|
|
@@ -944,6 +1020,7 @@ var ImageEditor = class {
|
|
|
944
1020
|
this.cropBox.style.top = `${top}px`;
|
|
945
1021
|
this.cropBox.style.width = `${this.cropRect.w}px`;
|
|
946
1022
|
this.cropBox.style.height = `${this.cropRect.h}px`;
|
|
1023
|
+
this.syncCropDimsInputs();
|
|
947
1024
|
}
|
|
948
1025
|
// ---- drag handlers (crop) ----------------------------------------------
|
|
949
1026
|
beginDrag(e, kind) {
|