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