@pictor-sdk/ui 0.1.0 → 0.2.0
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 +76 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +74 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +1 -0
- package/src/panels/LayoutPanel.tsx +11 -5
- package/src/panels/layoutMath.ts +86 -32
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ photo and video editor SDK for React Native. Public APIs are pre-1.0 and experim
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
10
|
```sh
|
|
11
|
-
pnpm add @pictor-sdk/ui@0.
|
|
11
|
+
pnpm add @pictor-sdk/ui@0.2.0
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
Install the package's declared peer dependencies in your app. Keep React, React Native,
|
|
@@ -21,6 +21,17 @@ of device verification on every supported version/platform.
|
|
|
21
21
|
|
|
22
22
|
## Documentation and contributing
|
|
23
23
|
|
|
24
|
+
### Story Layout in 0.2.0
|
|
25
|
+
|
|
26
|
+
Upgrade `@pictor-sdk/core`, `@pictor-sdk/skia` and `@pictor-sdk/ui` together.
|
|
27
|
+
`layoutCellBounds('6grid')` supplies a two-column, three-row grid;
|
|
28
|
+
`fitImageToLayoutCell(cell, document.size, intrinsic, { zoom, center })` returns
|
|
29
|
+
the fixed-cell transform, source crop and `pixelSnap` flag. Apply all three in
|
|
30
|
+
one history batch. Zoom and pan change the crop, not the layer's cell bounds.
|
|
31
|
+
See the [host integration guide](https://github.com/zahidhasanaunto/pictor/blob/main/docs/STORY-LAYOUT.md).
|
|
32
|
+
|
|
33
|
+
### Project links
|
|
34
|
+
|
|
24
35
|
- [Repository and example app](https://github.com/zahidhasanaunto/pictor)
|
|
25
36
|
- [Public API inventory](https://github.com/zahidhasanaunto/pictor/blob/main/docs/API-SURFACE.md)
|
|
26
37
|
- [Release and contributor guide](https://github.com/zahidhasanaunto/pictor/blob/main/docs/RELEASING.md)
|
package/dist/index.d.mts
CHANGED
|
@@ -758,7 +758,7 @@ declare function LayersPanel(): React__default.JSX.Element;
|
|
|
758
758
|
declare function LayoutPanel(): React__default.JSX.Element;
|
|
759
759
|
|
|
760
760
|
/** The bundled multi-photo arrangements, by cell count and split direction. */
|
|
761
|
-
type LayoutPreset = '1' | '2v' | '2h' | '3v' | '4grid';
|
|
761
|
+
type LayoutPreset = '1' | '2v' | '2h' | '3v' | '4grid' | '6grid';
|
|
762
762
|
/** One slot in a layout: where its photo sits, in normalized document units. */
|
|
763
763
|
interface LayoutCell {
|
|
764
764
|
/** centre + scale in normalized document units */
|
|
@@ -773,6 +773,38 @@ interface LayoutCell {
|
|
|
773
773
|
* canvas size works.
|
|
774
774
|
*/
|
|
775
775
|
declare function layoutCells(preset: LayoutPreset, _doc: Size): LayoutCell[];
|
|
776
|
+
/**
|
|
777
|
+
* Axis-aligned cell rectangles, row-major, normalized to document width/height.
|
|
778
|
+
* x/y are TOP-LEFT coordinates, unlike the centres in legacy LayoutCell.
|
|
779
|
+
* Returns fresh rectangles; no document aspect ratio is assumed.
|
|
780
|
+
*/
|
|
781
|
+
declare function layoutCellBounds(preset: LayoutPreset): Rect[];
|
|
782
|
+
/** Source-window controls; pan is a source-space crop centre, not a layer translation. */
|
|
783
|
+
interface LayoutCropOptions {
|
|
784
|
+
/** Magnification relative to crop-to-fill. Clamped to [1, 32]; default 1. */
|
|
785
|
+
zoom?: number;
|
|
786
|
+
/** Desired source-normalized crop centre; clamped so the crop stays in the source. */
|
|
787
|
+
center?: {
|
|
788
|
+
x: number;
|
|
789
|
+
y: number;
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
/** Crop and complete transform to apply together in one history batch. */
|
|
793
|
+
interface LayoutImageFit {
|
|
794
|
+
crop: Rect;
|
|
795
|
+
transform: Transform;
|
|
796
|
+
/** Apply to ImageLayerData together with crop for seam-free cell edges. */
|
|
797
|
+
pixelSnap: true;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Fill a fixed cell without bleed. Zoom/pan alter only the source crop, never
|
|
801
|
+
* the cell bounds. intrinsic must describe the decoded, orientation-corrected
|
|
802
|
+
* source. Recompute after source replacement or document resize.
|
|
803
|
+
* Throws RangeError for non-finite controls, invalid sizes or out-of-document cells.
|
|
804
|
+
* Apply transform with layer/transform and crop + pixelSnap with layer/patchData in one batch.
|
|
805
|
+
* General layer gestures must not subsequently move/rotate/scale a fixed cell.
|
|
806
|
+
*/
|
|
807
|
+
declare function fitImageToLayoutCell(cell: Rect, documentSize: Size, intrinsic: Size, options?: LayoutCropOptions): LayoutImageFit;
|
|
776
808
|
/** The transform patch that moves a layer into a cell, leaving its other fields alone. */
|
|
777
809
|
declare function cellToTransformPatch(cell: LayoutCell): Partial<Transform>;
|
|
778
810
|
|
|
@@ -830,4 +862,4 @@ declare function UiStateProvider({ children }: {
|
|
|
830
862
|
/** Read and write one key of the ephemeral UI state. Throws outside an `<Editor>`. */
|
|
831
863
|
declare function useUiState<T>(key: string, fallback: T): [T, (value: T) => void];
|
|
832
864
|
|
|
833
|
-
export { type AddPhotoController, type AddPhotoControllerOptions, AddPhotoPanel, AdjustPanel, type BrushConfig, CanvasStage, type CanvasStageProps, CropGestureSurface, type CropGestureSurfaceProps, CropGrid, CropPanel, DEFAULT_BRUSH, type DrawController, DrawPanel, DrawingSurface, Editor, EditorGestures, type EditorGesturesProps, type EditorProps, type EditorSlots, type EditorTheme, FilterStrip, type GestureController, type GestureControllerOptions, type GestureMetrics, type GestureSnapEvent, type GestureSurfaceKind, type HostCallbacks, HostCallbacksProvider, InteractionGuides, type InteractionGuidesProps, InteractionProvider, InvalidImageResultError, LayerGestureSurface, type LayerGestureSurfaceProps, LayersPanel, type LayoutCell, LayoutPanel, type LayoutPreset, MediaPanel, type PartialTheme, STRAIGHTEN_LIMIT, Slider, type SliderProps, type StickerAsset, StickerPanel, StoryMediaGestureSurface, type StoryMediaGestureSurfaceProps, StraightenRuler, type StraightenRulerProps, TextComposer, TextComposerHost, type TextComposerProps, TextPanel, type TextSessionController, ThemeContext, ToolPanelHost, ToolRail, TopBar, type TopBarProps, UiStateProvider, type UiStateStore, type UseTextSessionOptions, canvasSizeForAspect, cellToTransformPatch, centeredCropForAspect, createAddPhotoController, createDrawController, createGestureController, createUiStateStore, defaultTheme, layoutCells, mergeSlots, mergeTheme, radiansToStraighten, resolveGestureSurface, resolvePanel, straightenToRadians, useBaseImageLayer, useBaseMediaLayer, useHostCallbacks, useInteractionState, useTargetImageLayer, useTextSession, useTheme, useUiState };
|
|
865
|
+
export { type AddPhotoController, type AddPhotoControllerOptions, AddPhotoPanel, AdjustPanel, type BrushConfig, CanvasStage, type CanvasStageProps, CropGestureSurface, type CropGestureSurfaceProps, CropGrid, CropPanel, DEFAULT_BRUSH, type DrawController, DrawPanel, DrawingSurface, Editor, EditorGestures, type EditorGesturesProps, type EditorProps, type EditorSlots, type EditorTheme, FilterStrip, type GestureController, type GestureControllerOptions, type GestureMetrics, type GestureSnapEvent, type GestureSurfaceKind, type HostCallbacks, HostCallbacksProvider, InteractionGuides, type InteractionGuidesProps, InteractionProvider, InvalidImageResultError, LayerGestureSurface, type LayerGestureSurfaceProps, LayersPanel, type LayoutCell, type LayoutCropOptions, type LayoutImageFit, LayoutPanel, type LayoutPreset, MediaPanel, type PartialTheme, STRAIGHTEN_LIMIT, Slider, type SliderProps, type StickerAsset, StickerPanel, StoryMediaGestureSurface, type StoryMediaGestureSurfaceProps, StraightenRuler, type StraightenRulerProps, TextComposer, TextComposerHost, type TextComposerProps, TextPanel, type TextSessionController, ThemeContext, ToolPanelHost, ToolRail, TopBar, type TopBarProps, UiStateProvider, type UiStateStore, type UseTextSessionOptions, canvasSizeForAspect, cellToTransformPatch, centeredCropForAspect, createAddPhotoController, createDrawController, createGestureController, createUiStateStore, defaultTheme, fitImageToLayoutCell, layoutCellBounds, layoutCells, mergeSlots, mergeTheme, radiansToStraighten, resolveGestureSurface, resolvePanel, straightenToRadians, useBaseImageLayer, useBaseMediaLayer, useHostCallbacks, useInteractionState, useTargetImageLayer, useTextSession, useTheme, useUiState };
|
package/dist/index.d.ts
CHANGED
|
@@ -758,7 +758,7 @@ declare function LayersPanel(): React__default.JSX.Element;
|
|
|
758
758
|
declare function LayoutPanel(): React__default.JSX.Element;
|
|
759
759
|
|
|
760
760
|
/** The bundled multi-photo arrangements, by cell count and split direction. */
|
|
761
|
-
type LayoutPreset = '1' | '2v' | '2h' | '3v' | '4grid';
|
|
761
|
+
type LayoutPreset = '1' | '2v' | '2h' | '3v' | '4grid' | '6grid';
|
|
762
762
|
/** One slot in a layout: where its photo sits, in normalized document units. */
|
|
763
763
|
interface LayoutCell {
|
|
764
764
|
/** centre + scale in normalized document units */
|
|
@@ -773,6 +773,38 @@ interface LayoutCell {
|
|
|
773
773
|
* canvas size works.
|
|
774
774
|
*/
|
|
775
775
|
declare function layoutCells(preset: LayoutPreset, _doc: Size): LayoutCell[];
|
|
776
|
+
/**
|
|
777
|
+
* Axis-aligned cell rectangles, row-major, normalized to document width/height.
|
|
778
|
+
* x/y are TOP-LEFT coordinates, unlike the centres in legacy LayoutCell.
|
|
779
|
+
* Returns fresh rectangles; no document aspect ratio is assumed.
|
|
780
|
+
*/
|
|
781
|
+
declare function layoutCellBounds(preset: LayoutPreset): Rect[];
|
|
782
|
+
/** Source-window controls; pan is a source-space crop centre, not a layer translation. */
|
|
783
|
+
interface LayoutCropOptions {
|
|
784
|
+
/** Magnification relative to crop-to-fill. Clamped to [1, 32]; default 1. */
|
|
785
|
+
zoom?: number;
|
|
786
|
+
/** Desired source-normalized crop centre; clamped so the crop stays in the source. */
|
|
787
|
+
center?: {
|
|
788
|
+
x: number;
|
|
789
|
+
y: number;
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
/** Crop and complete transform to apply together in one history batch. */
|
|
793
|
+
interface LayoutImageFit {
|
|
794
|
+
crop: Rect;
|
|
795
|
+
transform: Transform;
|
|
796
|
+
/** Apply to ImageLayerData together with crop for seam-free cell edges. */
|
|
797
|
+
pixelSnap: true;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Fill a fixed cell without bleed. Zoom/pan alter only the source crop, never
|
|
801
|
+
* the cell bounds. intrinsic must describe the decoded, orientation-corrected
|
|
802
|
+
* source. Recompute after source replacement or document resize.
|
|
803
|
+
* Throws RangeError for non-finite controls, invalid sizes or out-of-document cells.
|
|
804
|
+
* Apply transform with layer/transform and crop + pixelSnap with layer/patchData in one batch.
|
|
805
|
+
* General layer gestures must not subsequently move/rotate/scale a fixed cell.
|
|
806
|
+
*/
|
|
807
|
+
declare function fitImageToLayoutCell(cell: Rect, documentSize: Size, intrinsic: Size, options?: LayoutCropOptions): LayoutImageFit;
|
|
776
808
|
/** The transform patch that moves a layer into a cell, leaving its other fields alone. */
|
|
777
809
|
declare function cellToTransformPatch(cell: LayoutCell): Partial<Transform>;
|
|
778
810
|
|
|
@@ -830,4 +862,4 @@ declare function UiStateProvider({ children }: {
|
|
|
830
862
|
/** Read and write one key of the ephemeral UI state. Throws outside an `<Editor>`. */
|
|
831
863
|
declare function useUiState<T>(key: string, fallback: T): [T, (value: T) => void];
|
|
832
864
|
|
|
833
|
-
export { type AddPhotoController, type AddPhotoControllerOptions, AddPhotoPanel, AdjustPanel, type BrushConfig, CanvasStage, type CanvasStageProps, CropGestureSurface, type CropGestureSurfaceProps, CropGrid, CropPanel, DEFAULT_BRUSH, type DrawController, DrawPanel, DrawingSurface, Editor, EditorGestures, type EditorGesturesProps, type EditorProps, type EditorSlots, type EditorTheme, FilterStrip, type GestureController, type GestureControllerOptions, type GestureMetrics, type GestureSnapEvent, type GestureSurfaceKind, type HostCallbacks, HostCallbacksProvider, InteractionGuides, type InteractionGuidesProps, InteractionProvider, InvalidImageResultError, LayerGestureSurface, type LayerGestureSurfaceProps, LayersPanel, type LayoutCell, LayoutPanel, type LayoutPreset, MediaPanel, type PartialTheme, STRAIGHTEN_LIMIT, Slider, type SliderProps, type StickerAsset, StickerPanel, StoryMediaGestureSurface, type StoryMediaGestureSurfaceProps, StraightenRuler, type StraightenRulerProps, TextComposer, TextComposerHost, type TextComposerProps, TextPanel, type TextSessionController, ThemeContext, ToolPanelHost, ToolRail, TopBar, type TopBarProps, UiStateProvider, type UiStateStore, type UseTextSessionOptions, canvasSizeForAspect, cellToTransformPatch, centeredCropForAspect, createAddPhotoController, createDrawController, createGestureController, createUiStateStore, defaultTheme, layoutCells, mergeSlots, mergeTheme, radiansToStraighten, resolveGestureSurface, resolvePanel, straightenToRadians, useBaseImageLayer, useBaseMediaLayer, useHostCallbacks, useInteractionState, useTargetImageLayer, useTextSession, useTheme, useUiState };
|
|
865
|
+
export { type AddPhotoController, type AddPhotoControllerOptions, AddPhotoPanel, AdjustPanel, type BrushConfig, CanvasStage, type CanvasStageProps, CropGestureSurface, type CropGestureSurfaceProps, CropGrid, CropPanel, DEFAULT_BRUSH, type DrawController, DrawPanel, DrawingSurface, Editor, EditorGestures, type EditorGesturesProps, type EditorProps, type EditorSlots, type EditorTheme, FilterStrip, type GestureController, type GestureControllerOptions, type GestureMetrics, type GestureSnapEvent, type GestureSurfaceKind, type HostCallbacks, HostCallbacksProvider, InteractionGuides, type InteractionGuidesProps, InteractionProvider, InvalidImageResultError, LayerGestureSurface, type LayerGestureSurfaceProps, LayersPanel, type LayoutCell, type LayoutCropOptions, type LayoutImageFit, LayoutPanel, type LayoutPreset, MediaPanel, type PartialTheme, STRAIGHTEN_LIMIT, Slider, type SliderProps, type StickerAsset, StickerPanel, StoryMediaGestureSurface, type StoryMediaGestureSurfaceProps, StraightenRuler, type StraightenRulerProps, TextComposer, TextComposerHost, type TextComposerProps, TextPanel, type TextSessionController, ThemeContext, ToolPanelHost, ToolRail, TopBar, type TopBarProps, UiStateProvider, type UiStateStore, type UseTextSessionOptions, canvasSizeForAspect, cellToTransformPatch, centeredCropForAspect, createAddPhotoController, createDrawController, createGestureController, createUiStateStore, defaultTheme, fitImageToLayoutCell, layoutCellBounds, layoutCells, mergeSlots, mergeTheme, radiansToStraighten, resolveGestureSurface, resolvePanel, straightenToRadians, useBaseImageLayer, useBaseMediaLayer, useHostCallbacks, useInteractionState, useTargetImageLayer, useTextSession, useTheme, useUiState };
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,8 @@ __export(index_exports, {
|
|
|
73
73
|
createGestureController: () => createGestureController,
|
|
74
74
|
createUiStateStore: () => createUiStateStore,
|
|
75
75
|
defaultTheme: () => defaultTheme,
|
|
76
|
+
fitImageToLayoutCell: () => fitImageToLayoutCell,
|
|
77
|
+
layoutCellBounds: () => layoutCellBounds,
|
|
76
78
|
layoutCells: () => layoutCells,
|
|
77
79
|
mergeSlots: () => mergeSlots,
|
|
78
80
|
mergeTheme: () => mergeTheme,
|
|
@@ -2829,38 +2831,70 @@ var import_react_native16 = require("react-native");
|
|
|
2829
2831
|
|
|
2830
2832
|
// src/panels/layoutMath.ts
|
|
2831
2833
|
function layoutCells(preset, _doc) {
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
return [{ x: 0.5, y: 0.5, scale: 1 }];
|
|
2834
|
+
return layoutCellBounds(preset).map((cell) => ({
|
|
2835
|
+
x: (cell.x / cell.width + 0.5) * cell.width,
|
|
2836
|
+
y: (cell.y / cell.height + 0.5) * cell.height,
|
|
2837
|
+
scale: cell.width
|
|
2838
|
+
}));
|
|
2839
|
+
}
|
|
2840
|
+
function layoutCellBounds(preset) {
|
|
2841
|
+
const dimensions = {
|
|
2842
|
+
"1": [1, 1],
|
|
2843
|
+
"2v": [1, 2],
|
|
2844
|
+
"2h": [2, 1],
|
|
2845
|
+
"3v": [1, 3],
|
|
2846
|
+
"4grid": [2, 2],
|
|
2847
|
+
"6grid": [2, 3]
|
|
2848
|
+
};
|
|
2849
|
+
const grid = dimensions[preset];
|
|
2850
|
+
if (!grid) throw new RangeError("Unknown layout preset");
|
|
2851
|
+
const [columns, rows] = grid;
|
|
2852
|
+
return Array.from({ length: columns * rows }, (_, index) => ({
|
|
2853
|
+
x: index % columns / columns,
|
|
2854
|
+
y: Math.floor(index / columns) / rows,
|
|
2855
|
+
width: 1 / columns,
|
|
2856
|
+
height: 1 / rows
|
|
2857
|
+
}));
|
|
2858
|
+
}
|
|
2859
|
+
function fitImageToLayoutCell(cell, documentSize, intrinsic, options = {}) {
|
|
2860
|
+
for (const size of [documentSize, intrinsic]) {
|
|
2861
|
+
if (![size.width, size.height].every((v) => Number.isFinite(v) && v > 0)) {
|
|
2862
|
+
throw new RangeError("Layout sizes must be finite and positive");
|
|
2862
2863
|
}
|
|
2863
2864
|
}
|
|
2865
|
+
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) {
|
|
2866
|
+
throw new RangeError("Layout cell must lie inside the document");
|
|
2867
|
+
}
|
|
2868
|
+
const zoom = options.zoom ?? 1;
|
|
2869
|
+
const center = options.center ?? { x: 0.5, y: 0.5 };
|
|
2870
|
+
if (![zoom, center.x, center.y].every(Number.isFinite)) {
|
|
2871
|
+
throw new RangeError("Layout controls must be finite");
|
|
2872
|
+
}
|
|
2873
|
+
const base = centeredCropForAspect(
|
|
2874
|
+
intrinsic,
|
|
2875
|
+
cell.width * documentSize.width / (cell.height * documentSize.height)
|
|
2876
|
+
);
|
|
2877
|
+
const factor = Math.max(1, Math.min(32, zoom));
|
|
2878
|
+
const width = base.width / factor;
|
|
2879
|
+
const height = base.height / factor;
|
|
2880
|
+
return {
|
|
2881
|
+
pixelSnap: true,
|
|
2882
|
+
crop: {
|
|
2883
|
+
x: Math.max(0, Math.min(1 - width, center.x - width / 2)),
|
|
2884
|
+
y: Math.max(0, Math.min(1 - height, center.y - height / 2)),
|
|
2885
|
+
width,
|
|
2886
|
+
height
|
|
2887
|
+
},
|
|
2888
|
+
transform: {
|
|
2889
|
+
x: cell.x + cell.width / 2,
|
|
2890
|
+
y: cell.y + cell.height / 2,
|
|
2891
|
+
scale: cell.width,
|
|
2892
|
+
rotation: 0,
|
|
2893
|
+
anchor: { x: 0.5, y: 0.5 },
|
|
2894
|
+
flipX: false,
|
|
2895
|
+
flipY: false
|
|
2896
|
+
}
|
|
2897
|
+
};
|
|
2864
2898
|
}
|
|
2865
2899
|
function cellToTransformPatch(cell) {
|
|
2866
2900
|
return { x: cell.x, y: cell.y, scale: cell.scale, rotation: 0 };
|
|
@@ -2873,17 +2907,23 @@ var PRESETS = [
|
|
|
2873
2907
|
{ id: "2v", label: "2 rows" },
|
|
2874
2908
|
{ id: "2h", label: "2 cols" },
|
|
2875
2909
|
{ id: "3v", label: "3 rows" },
|
|
2876
|
-
{ id: "4grid", label: "Grid" }
|
|
2910
|
+
{ id: "4grid", label: "Grid" },
|
|
2911
|
+
{ id: "6grid", label: "6 grid" }
|
|
2877
2912
|
];
|
|
2878
2913
|
function LayoutPanel() {
|
|
2879
2914
|
const { document, dispatch } = (0, import_core18.useEditor)();
|
|
2880
2915
|
const theme = useTheme();
|
|
2881
2916
|
const apply = (preset) => {
|
|
2882
|
-
const cells =
|
|
2917
|
+
const cells = layoutCellBounds(preset);
|
|
2883
2918
|
const images = document.layers.filter((l) => l.type === "image");
|
|
2919
|
+
const fits = images.slice(0, cells.length).map((layer, i) => ({
|
|
2920
|
+
layer,
|
|
2921
|
+
fit: fitImageToLayoutCell(cells[i], document.size, layer.data.intrinsic)
|
|
2922
|
+
}));
|
|
2884
2923
|
dispatch({ type: "history/beginBatch", label: "layout" });
|
|
2885
|
-
|
|
2886
|
-
dispatch({ type: "layer/transform", id: layer.id, patch:
|
|
2924
|
+
fits.forEach(({ layer, fit }) => {
|
|
2925
|
+
dispatch({ type: "layer/transform", id: layer.id, patch: fit.transform });
|
|
2926
|
+
dispatch({ type: "layer/patchData", id: layer.id, patch: { crop: fit.crop, pixelSnap: fit.pixelSnap } });
|
|
2887
2927
|
});
|
|
2888
2928
|
dispatch({ type: "history/endBatch" });
|
|
2889
2929
|
};
|
|
@@ -4601,6 +4641,8 @@ function TextPanel() {
|
|
|
4601
4641
|
createGestureController,
|
|
4602
4642
|
createUiStateStore,
|
|
4603
4643
|
defaultTheme,
|
|
4644
|
+
fitImageToLayoutCell,
|
|
4645
|
+
layoutCellBounds,
|
|
4604
4646
|
layoutCells,
|
|
4605
4647
|
mergeSlots,
|
|
4606
4648
|
mergeTheme,
|