@wallarm-org/design-system 4.4.0 → 4.5.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/dist/components/ImageCropper/ImageCropper.d.ts +16 -0
- package/dist/components/ImageCropper/ImageCropper.js +360 -0
- package/dist/components/ImageCropper/ImageCropperContext.d.ts +7 -0
- package/dist/components/ImageCropper/ImageCropperContext.js +17 -0
- package/dist/components/ImageCropper/ImageCropperGrid.d.ts +7 -0
- package/dist/components/ImageCropper/ImageCropperGrid.js +83 -0
- package/dist/components/ImageCropper/ImageCropperImage.d.ts +6 -0
- package/dist/components/ImageCropper/ImageCropperImage.js +150 -0
- package/dist/components/ImageCropper/ImageCropperProvider.d.ts +37 -0
- package/dist/components/ImageCropper/ImageCropperProvider.js +46 -0
- package/dist/components/ImageCropper/ImageCropperSelection.d.ts +7 -0
- package/dist/components/ImageCropper/ImageCropperSelection.js +91 -0
- package/dist/components/ImageCropper/ImageCropperViewport.d.ts +9 -0
- package/dist/components/ImageCropper/ImageCropperViewport.js +135 -0
- package/dist/components/ImageCropper/index.d.ts +9 -0
- package/dist/components/ImageCropper/index.js +6 -0
- package/dist/components/ImageCropper/lib/exportCrop.d.ts +9 -0
- package/dist/components/ImageCropper/lib/exportCrop.js +20 -0
- package/dist/components/ImageCropper/lib/geometry.d.ts +23 -0
- package/dist/components/ImageCropper/lib/geometry.js +19 -0
- package/dist/components/ImageCropper/useCropperMachine.d.ts +9 -0
- package/dist/components/ImageCropper/useCropperMachine.js +60 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/metadata/components.json +1544 -2
- package/package.json +2 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { c } from "react/compiler-runtime";
|
|
2
|
+
import { createContext, useContext, useLayoutEffect } from "react";
|
|
3
|
+
const ImageCropperProvider = /*#__PURE__*/ createContext(null);
|
|
4
|
+
const useImageCropperInternal = ()=>{
|
|
5
|
+
const context = useContext(ImageCropperProvider);
|
|
6
|
+
if (!context) throw new Error("ImageCropper parts must be rendered inside ImageCropper.");
|
|
7
|
+
return context;
|
|
8
|
+
};
|
|
9
|
+
const useImageCropperPartId = (part, id)=>{
|
|
10
|
+
const $ = c(5);
|
|
11
|
+
const { setPartIds } = useImageCropperInternal();
|
|
12
|
+
let t0;
|
|
13
|
+
let t1;
|
|
14
|
+
if ($[0] !== id || $[1] !== part || $[2] !== setPartIds) {
|
|
15
|
+
t0 = ()=>{
|
|
16
|
+
setPartIds((current)=>{
|
|
17
|
+
if (current[part] === id) return current;
|
|
18
|
+
return {
|
|
19
|
+
...current,
|
|
20
|
+
[part]: id
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
return ()=>{
|
|
24
|
+
setPartIds((current_0)=>current_0[part] === id ? {
|
|
25
|
+
...current_0,
|
|
26
|
+
[part]: void 0
|
|
27
|
+
} : current_0);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
t1 = [
|
|
31
|
+
part,
|
|
32
|
+
id,
|
|
33
|
+
setPartIds
|
|
34
|
+
];
|
|
35
|
+
$[0] = id;
|
|
36
|
+
$[1] = part;
|
|
37
|
+
$[2] = setPartIds;
|
|
38
|
+
$[3] = t0;
|
|
39
|
+
$[4] = t1;
|
|
40
|
+
} else {
|
|
41
|
+
t0 = $[3];
|
|
42
|
+
t1 = $[4];
|
|
43
|
+
}
|
|
44
|
+
useLayoutEffect(t0, t1);
|
|
45
|
+
};
|
|
46
|
+
export { ImageCropperProvider, useImageCropperInternal, useImageCropperPartId };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FC, HTMLAttributes, Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId.js';
|
|
3
|
+
export interface ImageCropperSelectionProps extends HTMLAttributes<HTMLDivElement>, TestableProps {
|
|
4
|
+
ref?: Ref<HTMLDivElement>;
|
|
5
|
+
}
|
|
6
|
+
/** The keyboard/pointer target representing the fixed crop frame. */
|
|
7
|
+
export declare const ImageCropperSelection: FC<ImageCropperSelectionProps>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { c } from "react/compiler-runtime";
|
|
3
|
+
import { ImageCropper } from "@ark-ui/react/image-cropper";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
import { useTestId } from "../../utils/testId.js";
|
|
6
|
+
import { useImageCropperInternal, useImageCropperPartId } from "./ImageCropperProvider.js";
|
|
7
|
+
const ImageCropperSelection = (t0)=>{
|
|
8
|
+
const $ = c(24);
|
|
9
|
+
let className;
|
|
10
|
+
let id;
|
|
11
|
+
let onPointerDownCapture;
|
|
12
|
+
let props;
|
|
13
|
+
let ref;
|
|
14
|
+
let testIdProp;
|
|
15
|
+
if ($[0] !== t0) {
|
|
16
|
+
({ ref, id, className, onPointerDownCapture, "data-testid": testIdProp, ...props } = t0);
|
|
17
|
+
$[0] = t0;
|
|
18
|
+
$[1] = className;
|
|
19
|
+
$[2] = id;
|
|
20
|
+
$[3] = onPointerDownCapture;
|
|
21
|
+
$[4] = props;
|
|
22
|
+
$[5] = ref;
|
|
23
|
+
$[6] = testIdProp;
|
|
24
|
+
} else {
|
|
25
|
+
className = $[1];
|
|
26
|
+
id = $[2];
|
|
27
|
+
onPointerDownCapture = $[3];
|
|
28
|
+
props = $[4];
|
|
29
|
+
ref = $[5];
|
|
30
|
+
testIdProp = $[6];
|
|
31
|
+
}
|
|
32
|
+
const { api, selection } = useImageCropperInternal();
|
|
33
|
+
const testId = useTestId("selection", testIdProp);
|
|
34
|
+
useImageCropperPartId("selection", id);
|
|
35
|
+
const t1 = api.ready ? 0 : -1;
|
|
36
|
+
const t2 = !api.ready || void 0;
|
|
37
|
+
const t3 = props["aria-label"] ?? "Position image";
|
|
38
|
+
const t4 = selection.value;
|
|
39
|
+
const t5 = selection.max;
|
|
40
|
+
const t6 = props["aria-valuetext"] ?? selection.text;
|
|
41
|
+
let t7;
|
|
42
|
+
if ($[7] !== api.ready || $[8] !== onPointerDownCapture) {
|
|
43
|
+
t7 = (event)=>{
|
|
44
|
+
onPointerDownCapture?.(event);
|
|
45
|
+
if (api.ready && !event.defaultPrevented && 0 === event.button && false !== event.isPrimary) event.currentTarget.focus({
|
|
46
|
+
preventScroll: true
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
$[7] = api.ready;
|
|
50
|
+
$[8] = onPointerDownCapture;
|
|
51
|
+
$[9] = t7;
|
|
52
|
+
} else t7 = $[9];
|
|
53
|
+
let t8;
|
|
54
|
+
if ($[10] !== className) {
|
|
55
|
+
t8 = cn("outline-none focus-visible:ring-3 focus-visible:ring-inset focus-visible:ring-focus-primary", className);
|
|
56
|
+
$[10] = className;
|
|
57
|
+
$[11] = t8;
|
|
58
|
+
} else t8 = $[11];
|
|
59
|
+
let t9;
|
|
60
|
+
if ($[12] !== props || $[13] !== ref || $[14] !== selection.max || $[15] !== selection.value || $[16] !== t1 || $[17] !== t2 || $[18] !== t3 || $[19] !== t6 || $[20] !== t7 || $[21] !== t8 || $[22] !== testId) {
|
|
61
|
+
t9 = /*#__PURE__*/ jsx(ImageCropper.Selection, {
|
|
62
|
+
...props,
|
|
63
|
+
ref: ref,
|
|
64
|
+
tabIndex: t1,
|
|
65
|
+
"aria-disabled": t2,
|
|
66
|
+
"aria-label": t3,
|
|
67
|
+
"aria-valuenow": t4,
|
|
68
|
+
"aria-valuemax": t5,
|
|
69
|
+
"aria-valuetext": t6,
|
|
70
|
+
onPointerDownCapture: t7,
|
|
71
|
+
"data-slot": "image-cropper-selection",
|
|
72
|
+
"data-testid": testId,
|
|
73
|
+
className: t8
|
|
74
|
+
});
|
|
75
|
+
$[12] = props;
|
|
76
|
+
$[13] = ref;
|
|
77
|
+
$[14] = selection.max;
|
|
78
|
+
$[15] = selection.value;
|
|
79
|
+
$[16] = t1;
|
|
80
|
+
$[17] = t2;
|
|
81
|
+
$[18] = t3;
|
|
82
|
+
$[19] = t6;
|
|
83
|
+
$[20] = t7;
|
|
84
|
+
$[21] = t8;
|
|
85
|
+
$[22] = testId;
|
|
86
|
+
$[23] = t9;
|
|
87
|
+
} else t9 = $[23];
|
|
88
|
+
return t9;
|
|
89
|
+
};
|
|
90
|
+
ImageCropperSelection.displayName = "ImageCropperSelection";
|
|
91
|
+
export { ImageCropperSelection };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type FC, type HTMLAttributes, type Ref } from 'react';
|
|
2
|
+
import { type TestableProps } from '../../utils/testId.js';
|
|
3
|
+
export interface ImageCropperViewportProps extends HTMLAttributes<HTMLDivElement>, TestableProps {
|
|
4
|
+
/** Styles the visible crop frame. Set its width; height follows outputSize's aspect ratio. */
|
|
5
|
+
className?: string;
|
|
6
|
+
/** Ref and native event/analytics attributes target the actual interactive viewport. */
|
|
7
|
+
ref?: Ref<HTMLDivElement>;
|
|
8
|
+
}
|
|
9
|
+
export declare const ImageCropperViewport: FC<ImageCropperViewportProps>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { c } from "react/compiler-runtime";
|
|
3
|
+
import { useLayoutEffect, useState } from "react";
|
|
4
|
+
import { ImageCropper } from "@ark-ui/react/image-cropper";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { useTestId } from "../../utils/testId.js";
|
|
7
|
+
import { useImageCropperInternal, useImageCropperPartId } from "./ImageCropperProvider.js";
|
|
8
|
+
const ImageCropperViewport = (t0)=>{
|
|
9
|
+
const $ = c(31);
|
|
10
|
+
let children;
|
|
11
|
+
let className;
|
|
12
|
+
let id;
|
|
13
|
+
let props;
|
|
14
|
+
let ref;
|
|
15
|
+
let style;
|
|
16
|
+
let testIdProp;
|
|
17
|
+
if ($[0] !== t0) {
|
|
18
|
+
({ ref, id, className, children, style, "data-testid": testIdProp, ...props } = t0);
|
|
19
|
+
$[0] = t0;
|
|
20
|
+
$[1] = children;
|
|
21
|
+
$[2] = className;
|
|
22
|
+
$[3] = id;
|
|
23
|
+
$[4] = props;
|
|
24
|
+
$[5] = ref;
|
|
25
|
+
$[6] = style;
|
|
26
|
+
$[7] = testIdProp;
|
|
27
|
+
} else {
|
|
28
|
+
children = $[1];
|
|
29
|
+
className = $[2];
|
|
30
|
+
id = $[3];
|
|
31
|
+
props = $[4];
|
|
32
|
+
ref = $[5];
|
|
33
|
+
style = $[6];
|
|
34
|
+
testIdProp = $[7];
|
|
35
|
+
}
|
|
36
|
+
const { outputSize, viewportSize, setFrameSize } = useImageCropperInternal();
|
|
37
|
+
const [frame, setFrame] = useState(null);
|
|
38
|
+
const testId = useTestId("viewport", testIdProp);
|
|
39
|
+
const frameTestId = useTestId("frame");
|
|
40
|
+
useImageCropperPartId("viewport", id);
|
|
41
|
+
let t1;
|
|
42
|
+
let t2;
|
|
43
|
+
if ($[8] !== frame || $[9] !== setFrameSize) {
|
|
44
|
+
t1 = ()=>{
|
|
45
|
+
if (!frame) return;
|
|
46
|
+
const measure = ()=>{
|
|
47
|
+
const { width, height } = frame.getBoundingClientRect();
|
|
48
|
+
setFrameSize((current)=>current.width === width && current.height === height ? current : {
|
|
49
|
+
width,
|
|
50
|
+
height
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
measure();
|
|
54
|
+
const observer = new ResizeObserver(measure);
|
|
55
|
+
observer.observe(frame);
|
|
56
|
+
return ()=>observer.disconnect();
|
|
57
|
+
};
|
|
58
|
+
t2 = [
|
|
59
|
+
frame,
|
|
60
|
+
setFrameSize
|
|
61
|
+
];
|
|
62
|
+
$[8] = frame;
|
|
63
|
+
$[9] = setFrameSize;
|
|
64
|
+
$[10] = t1;
|
|
65
|
+
$[11] = t2;
|
|
66
|
+
} else {
|
|
67
|
+
t1 = $[10];
|
|
68
|
+
t2 = $[11];
|
|
69
|
+
}
|
|
70
|
+
useLayoutEffect(t1, t2);
|
|
71
|
+
let t3;
|
|
72
|
+
if ($[12] !== className) {
|
|
73
|
+
t3 = cn("relative w-[240px] max-w-full overflow-hidden rounded-12 bg-bg-surface-2", className);
|
|
74
|
+
$[12] = className;
|
|
75
|
+
$[13] = t3;
|
|
76
|
+
} else t3 = $[13];
|
|
77
|
+
const t4 = outputSize.width / outputSize.height;
|
|
78
|
+
let t5;
|
|
79
|
+
if ($[14] !== t4) {
|
|
80
|
+
t5 = {
|
|
81
|
+
aspectRatio: t4
|
|
82
|
+
};
|
|
83
|
+
$[14] = t4;
|
|
84
|
+
$[15] = t5;
|
|
85
|
+
} else t5 = $[15];
|
|
86
|
+
let t6;
|
|
87
|
+
if ($[16] !== style || $[17] !== viewportSize.height || $[18] !== viewportSize.width) {
|
|
88
|
+
t6 = {
|
|
89
|
+
...style,
|
|
90
|
+
width: viewportSize.width,
|
|
91
|
+
height: viewportSize.height
|
|
92
|
+
};
|
|
93
|
+
$[16] = style;
|
|
94
|
+
$[17] = viewportSize.height;
|
|
95
|
+
$[18] = viewportSize.width;
|
|
96
|
+
$[19] = t6;
|
|
97
|
+
} else t6 = $[19];
|
|
98
|
+
let t7;
|
|
99
|
+
if ($[20] !== children || $[21] !== props || $[22] !== ref || $[23] !== t6 || $[24] !== testId) {
|
|
100
|
+
t7 = /*#__PURE__*/ jsx(ImageCropper.Viewport, {
|
|
101
|
+
...props,
|
|
102
|
+
ref: ref,
|
|
103
|
+
"data-slot": "image-cropper-viewport",
|
|
104
|
+
"data-testid": testId,
|
|
105
|
+
className: "absolute! top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 cursor-grab data-panning:cursor-grabbing",
|
|
106
|
+
style: t6,
|
|
107
|
+
children: children
|
|
108
|
+
});
|
|
109
|
+
$[20] = children;
|
|
110
|
+
$[21] = props;
|
|
111
|
+
$[22] = ref;
|
|
112
|
+
$[23] = t6;
|
|
113
|
+
$[24] = testId;
|
|
114
|
+
$[25] = t7;
|
|
115
|
+
} else t7 = $[25];
|
|
116
|
+
let t8;
|
|
117
|
+
if ($[26] !== frameTestId || $[27] !== t3 || $[28] !== t5 || $[29] !== t7) {
|
|
118
|
+
t8 = /*#__PURE__*/ jsx("div", {
|
|
119
|
+
ref: setFrame,
|
|
120
|
+
"data-slot": "image-cropper-frame",
|
|
121
|
+
"data-testid": frameTestId,
|
|
122
|
+
className: t3,
|
|
123
|
+
style: t5,
|
|
124
|
+
children: t7
|
|
125
|
+
});
|
|
126
|
+
$[26] = frameTestId;
|
|
127
|
+
$[27] = t3;
|
|
128
|
+
$[28] = t5;
|
|
129
|
+
$[29] = t7;
|
|
130
|
+
$[30] = t8;
|
|
131
|
+
} else t8 = $[30];
|
|
132
|
+
return t8;
|
|
133
|
+
};
|
|
134
|
+
ImageCropperViewport.displayName = "ImageCropperViewport";
|
|
135
|
+
export { ImageCropperViewport };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { ImageCropper, type ImageCropperProps } from './ImageCropper.js';
|
|
2
|
+
export { ImageCropperContext, type ImageCropperContextProps } from './ImageCropperContext.js';
|
|
3
|
+
export { ImageCropperGrid, type ImageCropperGridProps } from './ImageCropperGrid.js';
|
|
4
|
+
export { ImageCropperImage, type ImageCropperImageProps } from './ImageCropperImage.js';
|
|
5
|
+
export type { ImageCropperApi } from './ImageCropperProvider.js';
|
|
6
|
+
export { ImageCropperSelection, type ImageCropperSelectionProps } from './ImageCropperSelection.js';
|
|
7
|
+
export { ImageCropperViewport, type ImageCropperViewportProps } from './ImageCropperViewport.js';
|
|
8
|
+
export type { ImageCropperExportOptions } from './lib/exportCrop.js';
|
|
9
|
+
export type { ImageCropperSize } from './lib/geometry.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ImageCropper } from "./ImageCropper.js";
|
|
2
|
+
export { ImageCropperContext } from "./ImageCropperContext.js";
|
|
3
|
+
export { ImageCropperGrid } from "./ImageCropperGrid.js";
|
|
4
|
+
export { ImageCropperImage } from "./ImageCropperImage.js";
|
|
5
|
+
export { ImageCropperSelection } from "./ImageCropperSelection.js";
|
|
6
|
+
export { ImageCropperViewport } from "./ImageCropperViewport.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ImageCropperRect, type ImageCropperSize } from './geometry.js';
|
|
2
|
+
export interface ImageCropperExportOptions {
|
|
3
|
+
/** Defaults to lossless PNG. Browser support determines WebP availability. */
|
|
4
|
+
type?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
5
|
+
/** Encoding quality for JPEG or WebP, between 0 and 1. */
|
|
6
|
+
quality?: number;
|
|
7
|
+
}
|
|
8
|
+
/** Draw directly from the original bitmap, avoiding intermediate lossy encodings. */
|
|
9
|
+
export declare const exportCrop: (image: HTMLImageElement, crop: ImageCropperRect, outputSize: ImageCropperSize, { type, quality }?: ImageCropperExportOptions) => Promise<Blob | null>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { validateOutputSize } from "./geometry.js";
|
|
2
|
+
const exportCrop = async (image, crop, outputSize, { type = 'image/png', quality = 0.92 } = {})=>{
|
|
3
|
+
validateOutputSize(outputSize);
|
|
4
|
+
if (!image.complete || !image.naturalWidth || !image.naturalHeight || crop.width <= 0 || crop.height <= 0) return null;
|
|
5
|
+
try {
|
|
6
|
+
const canvas = image.ownerDocument.createElement('canvas');
|
|
7
|
+
canvas.width = outputSize.width;
|
|
8
|
+
canvas.height = outputSize.height;
|
|
9
|
+
if (canvas.width !== outputSize.width || canvas.height !== outputSize.height) return null;
|
|
10
|
+
const context = canvas.getContext('2d');
|
|
11
|
+
if (!context) return null;
|
|
12
|
+
context.imageSmoothingEnabled = true;
|
|
13
|
+
context.imageSmoothingQuality = 'high';
|
|
14
|
+
context.drawImage(image, crop.x, crop.y, crop.width, crop.height, 0, 0, outputSize.width, outputSize.height);
|
|
15
|
+
return await new Promise((resolve)=>canvas.toBlob(resolve, type, quality));
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export { exportCrop };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Pixel dimensions. Export sizes must be positive integers. */
|
|
2
|
+
export interface ImageCropperSize {
|
|
3
|
+
width: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ImageCropperRect extends ImageCropperSize {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const validateOutputSize: ({ width, height }: ImageCropperSize) => void;
|
|
11
|
+
/** Ark's pan bounds assume the image fills its viewport; keep that viewport at the source aspect. */
|
|
12
|
+
export declare const getCropperGeometry: (source: ImageCropperSize, frame: ImageCropperSize) => {
|
|
13
|
+
viewport: {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
};
|
|
17
|
+
crop: {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const validateOutputSize = ({ width, height })=>{
|
|
2
|
+
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width <= 0 || height <= 0) throw new RangeError('ImageCropper outputSize must contain positive integer dimensions.');
|
|
3
|
+
};
|
|
4
|
+
const getCropperGeometry = (source, frame)=>{
|
|
5
|
+
const scale = Math.max(frame.width / source.width, frame.height / source.height);
|
|
6
|
+
const viewport = {
|
|
7
|
+
width: source.width * scale,
|
|
8
|
+
height: source.height * scale
|
|
9
|
+
};
|
|
10
|
+
return {
|
|
11
|
+
viewport,
|
|
12
|
+
crop: {
|
|
13
|
+
x: (viewport.width - frame.width) / 2,
|
|
14
|
+
y: (viewport.height - frame.height) / 2,
|
|
15
|
+
...frame
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export { getCropperGeometry, validateOutputSize };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { UseImageCropperProps } from '@ark-ui/react/image-cropper';
|
|
2
|
+
import * as imageCropper from '@zag-js/image-cropper';
|
|
3
|
+
/**
|
|
4
|
+
* Zag 1.43.3's zoom prop only initializes/watches internal state. Keep rejected controlled
|
|
5
|
+
* edits transactional: its zoom callback runs before the proposed pan offset is committed,
|
|
6
|
+
* so capture that offset and restore both fields before paint when the owner rejects zoom.
|
|
7
|
+
* Accepted edits retain native wheel/pinch anchoring; no gesture logic is duplicated here.
|
|
8
|
+
*/
|
|
9
|
+
export declare const useCropperMachine: (props: UseImageCropperProps) => imageCropper.Api<import("@zag-js/react").PropTypes>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { c } from "react/compiler-runtime";
|
|
2
|
+
import { useId, useLayoutEffect, useRef } from "react";
|
|
3
|
+
import { useEnvironmentContext } from "@ark-ui/react/environment";
|
|
4
|
+
import { useLocaleContext } from "@ark-ui/react/locale";
|
|
5
|
+
import { normalizeProps, useMachine } from "@zag-js/react";
|
|
6
|
+
import * as __rspack_external__zag_js_image_cropper_79feded1 from "@zag-js/image-cropper";
|
|
7
|
+
const useCropperMachine = (props)=>{
|
|
8
|
+
const $ = c(9);
|
|
9
|
+
const id = useId();
|
|
10
|
+
const { dir } = useLocaleContext();
|
|
11
|
+
const { getRootNode } = useEnvironmentContext();
|
|
12
|
+
const pendingOffset = useRef(null);
|
|
13
|
+
const restoring = useRef(false);
|
|
14
|
+
const service = useMachine(__rspack_external__zag_js_image_cropper_79feded1.machine, {
|
|
15
|
+
id,
|
|
16
|
+
dir,
|
|
17
|
+
getRootNode,
|
|
18
|
+
...props,
|
|
19
|
+
onZoomChange: (details)=>{
|
|
20
|
+
if (restoring.current || details.zoom === props.zoom) return;
|
|
21
|
+
if (void 0 !== props.zoom && null === pendingOffset.current) pendingOffset.current = {
|
|
22
|
+
...service.context.get("offset")
|
|
23
|
+
};
|
|
24
|
+
props.onZoomChange?.(details);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
const api = __rspack_external__zag_js_image_cropper_79feded1.connect(service, normalizeProps);
|
|
28
|
+
let t0;
|
|
29
|
+
if ($[0] !== api.zoom || $[1] !== pendingOffset || $[2] !== props.zoom || $[3] !== service) {
|
|
30
|
+
t0 = ()=>{
|
|
31
|
+
if (void 0 !== props.zoom && api.zoom !== props.zoom && pendingOffset.current) {
|
|
32
|
+
restoring.current = true;
|
|
33
|
+
service.context.set("zoom", props.zoom);
|
|
34
|
+
service.context.set("offset", pendingOffset.current);
|
|
35
|
+
restoring.current = false;
|
|
36
|
+
}
|
|
37
|
+
pendingOffset.current = null;
|
|
38
|
+
};
|
|
39
|
+
$[0] = api.zoom;
|
|
40
|
+
$[1] = pendingOffset;
|
|
41
|
+
$[2] = props.zoom;
|
|
42
|
+
$[3] = service;
|
|
43
|
+
$[4] = t0;
|
|
44
|
+
} else t0 = $[4];
|
|
45
|
+
let t1;
|
|
46
|
+
if ($[5] !== api.zoom || $[6] !== props.zoom || $[7] !== service) {
|
|
47
|
+
t1 = [
|
|
48
|
+
api.zoom,
|
|
49
|
+
props.zoom,
|
|
50
|
+
service
|
|
51
|
+
];
|
|
52
|
+
$[5] = api.zoom;
|
|
53
|
+
$[6] = props.zoom;
|
|
54
|
+
$[7] = service;
|
|
55
|
+
$[8] = t1;
|
|
56
|
+
} else t1 = $[8];
|
|
57
|
+
useLayoutEffect(t0, t1);
|
|
58
|
+
return api;
|
|
59
|
+
};
|
|
60
|
+
export { useCropperMachine };
|
package/dist/index.d.ts
CHANGED
|
@@ -52,6 +52,7 @@ export { FormatDateTime, type FormatDateTimeProps } from './components/FormatDat
|
|
|
52
52
|
export { FormatNumber, type FormatNumberProps } from './components/FormatNumber/index.js';
|
|
53
53
|
export { Heading, type HeadingProps } from './components/Heading/index.js';
|
|
54
54
|
export { HTTP_METHOD_COLOR, HTTP_METHODS, HttpMethod, type HttpMethodName, type HttpMethodProps, } from './components/HttpMethod/index.js';
|
|
55
|
+
export { ImageCropper, type ImageCropperApi, ImageCropperContext, type ImageCropperContextProps, type ImageCropperExportOptions, ImageCropperGrid, type ImageCropperGridProps, ImageCropperImage, type ImageCropperImageProps, type ImageCropperProps, ImageCropperSelection, type ImageCropperSelectionProps, type ImageCropperSize, ImageCropperViewport, type ImageCropperViewportProps, } from './components/ImageCropper/index.js';
|
|
55
56
|
export { Indicator, type IndicatorProps } from './components/Indicator/index.js';
|
|
56
57
|
export { InlineEdit, type InlineEditActivationMode, type InlineEditContextValue, InlineEditControl, type InlineEditControlProps, InlineEditDate, type InlineEditDateProps, InlineEditDateTime, type InlineEditDateTimeProps, InlineEditError, type InlineEditErrorProps, InlineEditInput, type InlineEditInputProps, InlineEditNumber, type InlineEditNumberProps, InlineEditPreview, InlineEditPreviewIcon, type InlineEditPreviewIconProps, type InlineEditPreviewProps, InlineEditPreviewValue, type InlineEditPreviewValueProps, type InlineEditProps, InlineEditSelect, type InlineEditSelectProps, type InlineEditStatus, type InlineEditSubmitMode, InlineEditTextarea, type InlineEditTextareaProps, InlineEditTime, type InlineEditTimeProps, toCalendarDateValue, toReactAriaDateValue, useInlineEdit, useInlineEditSubmitMode, withMinuteGranularity, } from './components/InlineEdit/index.js';
|
|
57
58
|
export { Input, type InputProps } from './components/Input/index.js';
|
package/dist/index.js
CHANGED
|
@@ -41,6 +41,7 @@ export { FormatDateTime } from "./components/FormatDateTime/index.js";
|
|
|
41
41
|
export { FormatNumber } from "./components/FormatNumber/index.js";
|
|
42
42
|
export { Heading } from "./components/Heading/index.js";
|
|
43
43
|
export { HTTP_METHODS, HTTP_METHOD_COLOR, HttpMethod } from "./components/HttpMethod/index.js";
|
|
44
|
+
export { ImageCropper, ImageCropperContext, ImageCropperGrid, ImageCropperImage, ImageCropperSelection, ImageCropperViewport } from "./components/ImageCropper/index.js";
|
|
44
45
|
export { Indicator } from "./components/Indicator/index.js";
|
|
45
46
|
export { InlineEdit, InlineEditControl, InlineEditDate, InlineEditDateTime, InlineEditError, InlineEditInput, InlineEditNumber, InlineEditPreview, InlineEditPreviewIcon, InlineEditPreviewValue, InlineEditSelect, InlineEditTextarea, InlineEditTime, toCalendarDateValue, toReactAriaDateValue, useInlineEdit, useInlineEditSubmitMode, withMinuteGranularity } from "./components/InlineEdit/index.js";
|
|
46
47
|
export { Input } from "./components/Input/index.js";
|