@pictor-sdk/ui 0.1.0 → 0.2.1
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/README.md +12 -1
- package/dist/index.d.mts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +82 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +80 -38
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/gestures/LayerGestureSurface.tsx +7 -4
- package/src/index.ts +1 -0
- package/src/panels/LayoutPanel.tsx +11 -5
- package/src/panels/layoutMath.ts +86 -32
package/dist/index.mjs
CHANGED
|
@@ -745,10 +745,12 @@ function LayerGestureSurface({ onSnap }) {
|
|
|
745
745
|
);
|
|
746
746
|
const aspect = document.size.height / document.size.width;
|
|
747
747
|
const [measureVersion, setMeasureVersion] = useState2(0);
|
|
748
|
-
useEffect2(
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
748
|
+
useEffect2(() => {
|
|
749
|
+
const refresh = () => setMeasureVersion((v) => v + 1);
|
|
750
|
+
const unsubscribe = renderer.textMeasures.subscribe(refresh);
|
|
751
|
+
refresh();
|
|
752
|
+
return unsubscribe;
|
|
753
|
+
}, [renderer]);
|
|
752
754
|
const hitCandidates = useMemo5(
|
|
753
755
|
() => document.layers.map((layer, index) => ({ layer, index })).filter(
|
|
754
756
|
({ layer, index }) => !layer.hidden && !layer.locked && isDirectManipulationLayer(layer, index, profile.interaction?.layers)
|
|
@@ -2795,38 +2797,70 @@ import { Pressable as Pressable7, ScrollView as ScrollView6, Text as Text10 } fr
|
|
|
2795
2797
|
|
|
2796
2798
|
// src/panels/layoutMath.ts
|
|
2797
2799
|
function layoutCells(preset, _doc) {
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
return [{ x: 0.5, y: 0.5, scale: 1 }];
|
|
2800
|
+
return layoutCellBounds(preset).map((cell) => ({
|
|
2801
|
+
x: (cell.x / cell.width + 0.5) * cell.width,
|
|
2802
|
+
y: (cell.y / cell.height + 0.5) * cell.height,
|
|
2803
|
+
scale: cell.width
|
|
2804
|
+
}));
|
|
2805
|
+
}
|
|
2806
|
+
function layoutCellBounds(preset) {
|
|
2807
|
+
const dimensions = {
|
|
2808
|
+
"1": [1, 1],
|
|
2809
|
+
"2v": [1, 2],
|
|
2810
|
+
"2h": [2, 1],
|
|
2811
|
+
"3v": [1, 3],
|
|
2812
|
+
"4grid": [2, 2],
|
|
2813
|
+
"6grid": [2, 3]
|
|
2814
|
+
};
|
|
2815
|
+
const grid = dimensions[preset];
|
|
2816
|
+
if (!grid) throw new RangeError("Unknown layout preset");
|
|
2817
|
+
const [columns, rows] = grid;
|
|
2818
|
+
return Array.from({ length: columns * rows }, (_, index) => ({
|
|
2819
|
+
x: index % columns / columns,
|
|
2820
|
+
y: Math.floor(index / columns) / rows,
|
|
2821
|
+
width: 1 / columns,
|
|
2822
|
+
height: 1 / rows
|
|
2823
|
+
}));
|
|
2824
|
+
}
|
|
2825
|
+
function fitImageToLayoutCell(cell, documentSize, intrinsic, options = {}) {
|
|
2826
|
+
for (const size of [documentSize, intrinsic]) {
|
|
2827
|
+
if (![size.width, size.height].every((v) => Number.isFinite(v) && v > 0)) {
|
|
2828
|
+
throw new RangeError("Layout sizes must be finite and positive");
|
|
2828
2829
|
}
|
|
2829
2830
|
}
|
|
2831
|
+
if (![cell.x, cell.y, cell.width, cell.height].every(Number.isFinite) || cell.x < 0 || cell.y < 0 || cell.width <= 0 || cell.height <= 0 || cell.x + cell.width > 1 + 1e-12 || cell.y + cell.height > 1 + 1e-12) {
|
|
2832
|
+
throw new RangeError("Layout cell must lie inside the document");
|
|
2833
|
+
}
|
|
2834
|
+
const zoom = options.zoom ?? 1;
|
|
2835
|
+
const center = options.center ?? { x: 0.5, y: 0.5 };
|
|
2836
|
+
if (![zoom, center.x, center.y].every(Number.isFinite)) {
|
|
2837
|
+
throw new RangeError("Layout controls must be finite");
|
|
2838
|
+
}
|
|
2839
|
+
const base = centeredCropForAspect(
|
|
2840
|
+
intrinsic,
|
|
2841
|
+
cell.width * documentSize.width / (cell.height * documentSize.height)
|
|
2842
|
+
);
|
|
2843
|
+
const factor = Math.max(1, Math.min(32, zoom));
|
|
2844
|
+
const width = base.width / factor;
|
|
2845
|
+
const height = base.height / factor;
|
|
2846
|
+
return {
|
|
2847
|
+
pixelSnap: true,
|
|
2848
|
+
crop: {
|
|
2849
|
+
x: Math.max(0, Math.min(1 - width, center.x - width / 2)),
|
|
2850
|
+
y: Math.max(0, Math.min(1 - height, center.y - height / 2)),
|
|
2851
|
+
width,
|
|
2852
|
+
height
|
|
2853
|
+
},
|
|
2854
|
+
transform: {
|
|
2855
|
+
x: cell.x + cell.width / 2,
|
|
2856
|
+
y: cell.y + cell.height / 2,
|
|
2857
|
+
scale: cell.width,
|
|
2858
|
+
rotation: 0,
|
|
2859
|
+
anchor: { x: 0.5, y: 0.5 },
|
|
2860
|
+
flipX: false,
|
|
2861
|
+
flipY: false
|
|
2862
|
+
}
|
|
2863
|
+
};
|
|
2830
2864
|
}
|
|
2831
2865
|
function cellToTransformPatch(cell) {
|
|
2832
2866
|
return { x: cell.x, y: cell.y, scale: cell.scale, rotation: 0 };
|
|
@@ -2839,17 +2873,23 @@ var PRESETS = [
|
|
|
2839
2873
|
{ id: "2v", label: "2 rows" },
|
|
2840
2874
|
{ id: "2h", label: "2 cols" },
|
|
2841
2875
|
{ id: "3v", label: "3 rows" },
|
|
2842
|
-
{ id: "4grid", label: "Grid" }
|
|
2876
|
+
{ id: "4grid", label: "Grid" },
|
|
2877
|
+
{ id: "6grid", label: "6 grid" }
|
|
2843
2878
|
];
|
|
2844
2879
|
function LayoutPanel() {
|
|
2845
2880
|
const { document, dispatch } = useEditor13();
|
|
2846
2881
|
const theme = useTheme();
|
|
2847
2882
|
const apply = (preset) => {
|
|
2848
|
-
const cells =
|
|
2883
|
+
const cells = layoutCellBounds(preset);
|
|
2849
2884
|
const images = document.layers.filter((l) => l.type === "image");
|
|
2885
|
+
const fits = images.slice(0, cells.length).map((layer, i) => ({
|
|
2886
|
+
layer,
|
|
2887
|
+
fit: fitImageToLayoutCell(cells[i], document.size, layer.data.intrinsic)
|
|
2888
|
+
}));
|
|
2850
2889
|
dispatch({ type: "history/beginBatch", label: "layout" });
|
|
2851
|
-
|
|
2852
|
-
dispatch({ type: "layer/transform", id: layer.id, patch:
|
|
2890
|
+
fits.forEach(({ layer, fit }) => {
|
|
2891
|
+
dispatch({ type: "layer/transform", id: layer.id, patch: fit.transform });
|
|
2892
|
+
dispatch({ type: "layer/patchData", id: layer.id, patch: { crop: fit.crop, pixelSnap: fit.pixelSnap } });
|
|
2853
2893
|
});
|
|
2854
2894
|
dispatch({ type: "history/endBatch" });
|
|
2855
2895
|
};
|
|
@@ -4624,6 +4664,8 @@ export {
|
|
|
4624
4664
|
createGestureController,
|
|
4625
4665
|
createUiStateStore,
|
|
4626
4666
|
defaultTheme,
|
|
4667
|
+
fitImageToLayoutCell,
|
|
4668
|
+
layoutCellBounds,
|
|
4627
4669
|
layoutCells,
|
|
4628
4670
|
mergeSlots,
|
|
4629
4671
|
mergeTheme,
|