@webiny/app-file-manager 6.1.0-beta.0 → 6.1.0-beta.2
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/package.json +18 -21
- package/components/ImageEditor/ImageEditor.d.ts +0 -45
- package/components/ImageEditor/ImageEditor.js +0 -214
- package/components/ImageEditor/ImageEditor.js.map +0 -1
- package/components/ImageEditor/ImageEditorDialog.d.ts +0 -16
- package/components/ImageEditor/ImageEditorDialog.js +0 -53
- package/components/ImageEditor/ImageEditorDialog.js.map +0 -1
- package/components/ImageEditor/index.d.ts +0 -1
- package/components/ImageEditor/index.js +0 -3
- package/components/ImageEditor/index.js.map +0 -1
- package/components/ImageEditor/toolbar/crop.d.ts +0 -4
- package/components/ImageEditor/toolbar/crop.js +0 -67
- package/components/ImageEditor/toolbar/crop.js.map +0 -1
- package/components/ImageEditor/toolbar/filter.d.ts +0 -3
- package/components/ImageEditor/toolbar/filter.js +0 -167
- package/components/ImageEditor/toolbar/filter.js.map +0 -1
- package/components/ImageEditor/toolbar/flip.d.ts +0 -4
- package/components/ImageEditor/toolbar/flip.js +0 -94
- package/components/ImageEditor/toolbar/flip.js.map +0 -1
- package/components/ImageEditor/toolbar/index.d.ts +0 -4
- package/components/ImageEditor/toolbar/index.js +0 -6
- package/components/ImageEditor/toolbar/index.js.map +0 -1
- package/components/ImageEditor/toolbar/rotate.d.ts +0 -4
- package/components/ImageEditor/toolbar/rotate.js +0 -93
- package/components/ImageEditor/toolbar/rotate.js.map +0 -1
- package/components/ImageEditor/toolbar/types.d.ts +0 -32
- package/components/ImageEditor/toolbar/types.js +0 -3
- package/components/ImageEditor/toolbar/types.js.map +0 -1
- package/modules/FileManagerRenderer/FileActions/FileDetails/EditImage.d.ts +0 -2
- package/modules/FileManagerRenderer/FileActions/FileDetails/EditImage.js +0 -106
- package/modules/FileManagerRenderer/FileActions/FileDetails/EditImage.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/app-file-manager",
|
|
3
|
-
"version": "6.1.0-beta.
|
|
3
|
+
"version": "6.1.0-beta.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -14,33 +14,30 @@
|
|
|
14
14
|
"@apollo/react-components": "3.1.5",
|
|
15
15
|
"@apollo/react-hooks": "3.1.5",
|
|
16
16
|
"@types/react": "18.2.79",
|
|
17
|
-
"@webiny/admin-ui": "6.1.0-beta.
|
|
18
|
-
"@webiny/app": "6.1.0-beta.
|
|
19
|
-
"@webiny/app-aco": "6.1.0-beta.
|
|
20
|
-
"@webiny/app-admin": "6.1.0-beta.
|
|
21
|
-
"@webiny/app-headless-cms": "6.1.0-beta.
|
|
22
|
-
"@webiny/app-headless-cms-common": "6.1.0-beta.
|
|
23
|
-
"@webiny/app-websockets": "6.1.0-beta.
|
|
24
|
-
"@webiny/error": "6.1.0-beta.
|
|
25
|
-
"@webiny/form": "6.1.0-beta.
|
|
26
|
-
"@webiny/icons": "6.1.0-beta.
|
|
27
|
-
"@webiny/plugins": "6.1.0-beta.
|
|
28
|
-
"@webiny/react-composition": "6.1.0-beta.
|
|
29
|
-
"@webiny/react-properties": "6.1.0-beta.
|
|
30
|
-
"@webiny/utils": "6.1.0-beta.
|
|
31
|
-
"@webiny/validation": "6.1.0-beta.
|
|
17
|
+
"@webiny/admin-ui": "6.1.0-beta.2",
|
|
18
|
+
"@webiny/app": "6.1.0-beta.2",
|
|
19
|
+
"@webiny/app-aco": "6.1.0-beta.2",
|
|
20
|
+
"@webiny/app-admin": "6.1.0-beta.2",
|
|
21
|
+
"@webiny/app-headless-cms": "6.1.0-beta.2",
|
|
22
|
+
"@webiny/app-headless-cms-common": "6.1.0-beta.2",
|
|
23
|
+
"@webiny/app-websockets": "6.1.0-beta.2",
|
|
24
|
+
"@webiny/error": "6.1.0-beta.2",
|
|
25
|
+
"@webiny/form": "6.1.0-beta.2",
|
|
26
|
+
"@webiny/icons": "6.1.0-beta.2",
|
|
27
|
+
"@webiny/plugins": "6.1.0-beta.2",
|
|
28
|
+
"@webiny/react-composition": "6.1.0-beta.2",
|
|
29
|
+
"@webiny/react-properties": "6.1.0-beta.2",
|
|
30
|
+
"@webiny/utils": "6.1.0-beta.2",
|
|
31
|
+
"@webiny/validation": "6.1.0-beta.2",
|
|
32
32
|
"apollo-cache": "1.3.5",
|
|
33
33
|
"apollo-client": "2.6.10",
|
|
34
34
|
"apollo-link": "1.2.14",
|
|
35
35
|
"apollo-utilities": "1.3.4",
|
|
36
36
|
"bytes": "3.1.2",
|
|
37
|
-
"cropperjs": "1.6.2",
|
|
38
|
-
"dataurl-to-blob": "0.0.1",
|
|
39
37
|
"dayjs": "1.11.20",
|
|
40
38
|
"dot-prop-immutable": "2.1.1",
|
|
41
39
|
"graphql": "16.13.2",
|
|
42
40
|
"graphql-tag": "2.12.6",
|
|
43
|
-
"load-script": "2.0.0",
|
|
44
41
|
"lodash": "4.17.23",
|
|
45
42
|
"mime": "4.1.0",
|
|
46
43
|
"minimatch": "10.2.4",
|
|
@@ -56,7 +53,7 @@
|
|
|
56
53
|
},
|
|
57
54
|
"devDependencies": {
|
|
58
55
|
"@svgr/webpack": "8.1.0",
|
|
59
|
-
"@webiny/build-tools": "6.1.0-beta.
|
|
56
|
+
"@webiny/build-tools": "6.1.0-beta.2",
|
|
60
57
|
"rimraf": "6.1.3",
|
|
61
58
|
"typescript": "5.9.3",
|
|
62
59
|
"vitest": "4.1.2"
|
|
@@ -65,5 +62,5 @@
|
|
|
65
62
|
"access": "public",
|
|
66
63
|
"directory": "dist"
|
|
67
64
|
},
|
|
68
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "7174b414a55fc1c3f4cf38abab69dba5109e7765"
|
|
69
66
|
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { ImageEditorTool, ToolbarTool } from "./toolbar/types.js";
|
|
3
|
-
interface RenderPropArgs {
|
|
4
|
-
render: () => React.ReactNode;
|
|
5
|
-
getCanvasDataUrl: () => string;
|
|
6
|
-
activeTool: ImageEditorTool | null;
|
|
7
|
-
applyActiveTool: () => Promise<void>;
|
|
8
|
-
cancelActiveTool: () => Promise<void>;
|
|
9
|
-
}
|
|
10
|
-
interface ImageEditorPropsPropsOptions {
|
|
11
|
-
autoEnable: boolean;
|
|
12
|
-
}
|
|
13
|
-
interface ImageEditorProps {
|
|
14
|
-
src: string;
|
|
15
|
-
tools: ToolbarTool[];
|
|
16
|
-
options?: {
|
|
17
|
-
flip: ImageEditorPropsPropsOptions;
|
|
18
|
-
filter: ImageEditorPropsPropsOptions;
|
|
19
|
-
crop: ImageEditorPropsPropsOptions;
|
|
20
|
-
rotate: ImageEditorPropsPropsOptions;
|
|
21
|
-
};
|
|
22
|
-
onToolActivate?: () => void;
|
|
23
|
-
onToolDeactivate?: () => void;
|
|
24
|
-
children?: (props: RenderPropArgs) => React.ReactNode;
|
|
25
|
-
}
|
|
26
|
-
interface ImageEditorState {
|
|
27
|
-
tool: ImageEditorTool | null;
|
|
28
|
-
src: string;
|
|
29
|
-
}
|
|
30
|
-
declare class ImageEditor extends React.Component<ImageEditorProps, ImageEditorState> {
|
|
31
|
-
static defaultProps: Partial<ImageEditorProps>;
|
|
32
|
-
state: ImageEditorState;
|
|
33
|
-
canvas: React.RefObject<HTMLCanvasElement>;
|
|
34
|
-
image?: HTMLImageElement;
|
|
35
|
-
componentDidMount(): void;
|
|
36
|
-
private readonly updateCanvas;
|
|
37
|
-
private readonly activateTool;
|
|
38
|
-
private readonly deactivateTool;
|
|
39
|
-
readonly getCanvasDataUrl: () => string;
|
|
40
|
-
private readonly applyActiveTool;
|
|
41
|
-
private readonly cancelActiveTool;
|
|
42
|
-
private readonly getToolOptions;
|
|
43
|
-
render(): React.ReactNode;
|
|
44
|
-
}
|
|
45
|
-
export { ImageEditor };
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Button } from "@webiny/admin-ui";
|
|
3
|
-
import { flip, filter, crop, rotate } from "./toolbar/index.js";
|
|
4
|
-
import loadScript from "load-script";
|
|
5
|
-
const toolbar = {
|
|
6
|
-
flip,
|
|
7
|
-
filter,
|
|
8
|
-
crop,
|
|
9
|
-
rotate
|
|
10
|
-
};
|
|
11
|
-
const initScripts = () => {
|
|
12
|
-
return new Promise(resolve => {
|
|
13
|
-
// @ts-expect-error
|
|
14
|
-
if (window.Caman) {
|
|
15
|
-
return resolve();
|
|
16
|
-
}
|
|
17
|
-
return loadScript("https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.min.js", resolve);
|
|
18
|
-
});
|
|
19
|
-
};
|
|
20
|
-
class ImageEditor extends React.Component {
|
|
21
|
-
static defaultProps = {
|
|
22
|
-
tools: ["crop", "flip", "rotate", "filter"]
|
|
23
|
-
};
|
|
24
|
-
state = {
|
|
25
|
-
tool: null,
|
|
26
|
-
src: ""
|
|
27
|
-
};
|
|
28
|
-
canvas = /*#__PURE__*/React.createRef();
|
|
29
|
-
componentDidMount() {
|
|
30
|
-
initScripts().then(() => {
|
|
31
|
-
this.updateCanvas();
|
|
32
|
-
setTimeout(() => {
|
|
33
|
-
const {
|
|
34
|
-
options
|
|
35
|
-
} = this.props;
|
|
36
|
-
if (!options || typeof options !== "object") {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
for (const key in options) {
|
|
40
|
-
const option = options[key];
|
|
41
|
-
if (option.autoEnable === true) {
|
|
42
|
-
const tool = toolbar[key];
|
|
43
|
-
tool && this.activateTool(tool);
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}, 250);
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
updateCanvas = () => {
|
|
51
|
-
const {
|
|
52
|
-
src
|
|
53
|
-
} = this.props;
|
|
54
|
-
this.image = new window.Image();
|
|
55
|
-
const canvas = this.canvas.current;
|
|
56
|
-
if (canvas) {
|
|
57
|
-
this.image.onload = () => {
|
|
58
|
-
if (this.image) {
|
|
59
|
-
canvas.width = this.image.width;
|
|
60
|
-
canvas.height = this.image.height;
|
|
61
|
-
const ctx = canvas.getContext("2d");
|
|
62
|
-
ctx.drawImage(this.image, 0, 0);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
this.image.src = src;
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
activateTool = tool => {
|
|
69
|
-
if (typeof tool === "string") {
|
|
70
|
-
tool = toolbar[tool];
|
|
71
|
-
}
|
|
72
|
-
this.setState({
|
|
73
|
-
tool
|
|
74
|
-
}, () => {
|
|
75
|
-
const tt = tool;
|
|
76
|
-
typeof tt.onActivate === "function" && tt.onActivate({
|
|
77
|
-
canvas: this.canvas,
|
|
78
|
-
options: this.getToolOptions(tt)
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
};
|
|
82
|
-
deactivateTool = () => {
|
|
83
|
-
this.setState({
|
|
84
|
-
tool: null
|
|
85
|
-
});
|
|
86
|
-
};
|
|
87
|
-
getCanvasDataUrl = () => {
|
|
88
|
-
const canvas = this.canvas.current;
|
|
89
|
-
if (canvas) {
|
|
90
|
-
const {
|
|
91
|
-
src
|
|
92
|
-
} = this.props;
|
|
93
|
-
if (src.startsWith("data:image/jpeg;")) {
|
|
94
|
-
return canvas.toDataURL("image/jpeg", 1.0);
|
|
95
|
-
}
|
|
96
|
-
return canvas.toDataURL();
|
|
97
|
-
}
|
|
98
|
-
return "";
|
|
99
|
-
};
|
|
100
|
-
applyActiveTool = async () => {
|
|
101
|
-
const {
|
|
102
|
-
tool
|
|
103
|
-
} = this.state;
|
|
104
|
-
if (!tool) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
if (tool.apply) {
|
|
108
|
-
await tool.apply({
|
|
109
|
-
canvas: this.canvas
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
this.deactivateTool();
|
|
113
|
-
};
|
|
114
|
-
cancelActiveTool = async () => {
|
|
115
|
-
const {
|
|
116
|
-
tool
|
|
117
|
-
} = this.state;
|
|
118
|
-
if (!tool) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (tool.cancel) {
|
|
122
|
-
await tool.cancel({
|
|
123
|
-
canvas: this.canvas
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
this.deactivateTool();
|
|
127
|
-
};
|
|
128
|
-
getToolOptions = tool => {
|
|
129
|
-
const {
|
|
130
|
-
options
|
|
131
|
-
} = this.props;
|
|
132
|
-
if (!options || typeof options !== "object") {
|
|
133
|
-
return {};
|
|
134
|
-
}
|
|
135
|
-
return options[tool.name] || {};
|
|
136
|
-
};
|
|
137
|
-
render() {
|
|
138
|
-
const {
|
|
139
|
-
src,
|
|
140
|
-
tools,
|
|
141
|
-
children
|
|
142
|
-
} = this.props;
|
|
143
|
-
const {
|
|
144
|
-
tool
|
|
145
|
-
} = this.state;
|
|
146
|
-
const editor = /*#__PURE__*/React.createElement("div", {
|
|
147
|
-
className: "w-full h-full flex flex-col gap-md overflow-hidden"
|
|
148
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
149
|
-
className: "flex justify-center items-center w-full"
|
|
150
|
-
}, tools.map(key => {
|
|
151
|
-
const tool = toolbar[key];
|
|
152
|
-
if (!tool) {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
156
|
-
key: key,
|
|
157
|
-
className: this.state.tool ? "opacity-50 cursor pointer-events-none" : ""
|
|
158
|
-
}, tool.icon({
|
|
159
|
-
activateTool: () => this.activateTool(tool)
|
|
160
|
-
}));
|
|
161
|
-
})), /*#__PURE__*/React.createElement("div", {
|
|
162
|
-
className: "w-full"
|
|
163
|
-
}, tool ? /*#__PURE__*/React.createElement(React.Fragment, null, typeof tool.renderForm === "function" && tool.renderForm({
|
|
164
|
-
options: this.getToolOptions(tool),
|
|
165
|
-
image: this.image,
|
|
166
|
-
canvas: this.canvas
|
|
167
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
168
|
-
className: "flex justify-center gap-sm mt-sm"
|
|
169
|
-
}, /*#__PURE__*/React.createElement(Button, {
|
|
170
|
-
variant: "secondary",
|
|
171
|
-
text: "Cancel",
|
|
172
|
-
"data-testid": "button-cancel",
|
|
173
|
-
onClick: () => {
|
|
174
|
-
this.cancelActiveTool();
|
|
175
|
-
}
|
|
176
|
-
}), /*#__PURE__*/React.createElement(Button, {
|
|
177
|
-
variant: "primary",
|
|
178
|
-
text: "Apply",
|
|
179
|
-
"data-testid": "button-apply",
|
|
180
|
-
onClick: () => {
|
|
181
|
-
this.applyActiveTool();
|
|
182
|
-
}
|
|
183
|
-
}))) : /*#__PURE__*/React.createElement("div", {
|
|
184
|
-
className: "text-center"
|
|
185
|
-
}, "Select a tool to start working on your image.")), /*#__PURE__*/React.createElement("div", {
|
|
186
|
-
className: "flex justify-center items-center w-full bg-neutral-dimmed rounded-md overflow-hidden",
|
|
187
|
-
style: {
|
|
188
|
-
height: "calc(100vh - 256px)"
|
|
189
|
-
}
|
|
190
|
-
}, /*#__PURE__*/React.createElement("canvas", {
|
|
191
|
-
key: src,
|
|
192
|
-
id: "canvas",
|
|
193
|
-
style: {
|
|
194
|
-
maxWidth: "100%",
|
|
195
|
-
maxHeight: "100%"
|
|
196
|
-
},
|
|
197
|
-
ref: this.canvas
|
|
198
|
-
})));
|
|
199
|
-
if (typeof children === "function") {
|
|
200
|
-
return children({
|
|
201
|
-
render: () => editor,
|
|
202
|
-
// canvas: this.canvas,
|
|
203
|
-
getCanvasDataUrl: this.getCanvasDataUrl,
|
|
204
|
-
activeTool: this.state.tool,
|
|
205
|
-
applyActiveTool: this.applyActiveTool,
|
|
206
|
-
cancelActiveTool: this.cancelActiveTool
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
return editor;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
export { ImageEditor };
|
|
213
|
-
|
|
214
|
-
//# sourceMappingURL=ImageEditor.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","Button","flip","filter","crop","rotate","loadScript","toolbar","initScripts","Promise","resolve","window","Caman","ImageEditor","Component","defaultProps","tools","state","tool","src","canvas","createRef","componentDidMount","then","updateCanvas","setTimeout","options","props","key","option","autoEnable","activateTool","image","Image","current","onload","width","height","ctx","getContext","drawImage","setState","tt","onActivate","getToolOptions","deactivateTool","getCanvasDataUrl","startsWith","toDataURL","applyActiveTool","apply","cancelActiveTool","cancel","name","render","children","editor","createElement","className","map","icon","Fragment","renderForm","variant","text","onClick","style","id","maxWidth","maxHeight","ref","activeTool"],"sources":["ImageEditor.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button } from \"@webiny/admin-ui\";\nimport { flip, filter, crop, rotate } from \"./toolbar/index.js\";\nimport type { ImageEditorTool, ToolbarTool } from \"./toolbar/types.js\";\nimport loadScript from \"load-script\";\n\nconst toolbar = {\n flip,\n filter,\n crop,\n rotate\n};\n\nconst initScripts = (): Promise<string> => {\n return new Promise((resolve: any) => {\n // @ts-expect-error\n if (window.Caman) {\n return resolve();\n }\n return loadScript(\n \"https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.min.js\",\n resolve\n );\n });\n};\n\ninterface RenderPropArgs {\n render: () => React.ReactNode;\n getCanvasDataUrl: () => string;\n activeTool: ImageEditorTool | null;\n applyActiveTool: () => Promise<void>;\n cancelActiveTool: () => Promise<void>;\n}\n\ninterface ImageEditorPropsPropsOptions {\n autoEnable: boolean;\n}\n\ninterface ImageEditorProps {\n src: string;\n tools: ToolbarTool[];\n options?: {\n flip: ImageEditorPropsPropsOptions;\n filter: ImageEditorPropsPropsOptions;\n crop: ImageEditorPropsPropsOptions;\n rotate: ImageEditorPropsPropsOptions;\n };\n onToolActivate?: () => void;\n onToolDeactivate?: () => void;\n children?: (props: RenderPropArgs) => React.ReactNode;\n}\n\ninterface ImageEditorState {\n tool: ImageEditorTool | null;\n src: string;\n}\n\nclass ImageEditor extends React.Component<ImageEditorProps, ImageEditorState> {\n static defaultProps: Partial<ImageEditorProps> = {\n tools: [\"crop\", \"flip\", \"rotate\", \"filter\"]\n };\n\n public override state: ImageEditorState = {\n tool: null,\n src: \"\"\n };\n\n public canvas = React.createRef<HTMLCanvasElement>();\n public image?: HTMLImageElement;\n\n public override componentDidMount() {\n initScripts().then(() => {\n this.updateCanvas();\n setTimeout(() => {\n const { options } = this.props;\n if (!options || typeof options !== \"object\") {\n return;\n }\n for (const key in options) {\n const option = options[key as ToolbarTool];\n if (option.autoEnable === true) {\n const tool: ImageEditorTool | null = toolbar[key as ToolbarTool];\n tool && this.activateTool(tool);\n break;\n }\n }\n }, 250);\n });\n }\n\n private readonly updateCanvas = (): void => {\n const { src } = this.props;\n this.image = new window.Image();\n const canvas = this.canvas.current;\n if (canvas) {\n this.image.onload = () => {\n if (this.image) {\n canvas.width = this.image.width;\n canvas.height = this.image.height;\n const ctx = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n ctx.drawImage(this.image, 0, 0);\n }\n };\n\n this.image.src = src;\n }\n };\n\n private readonly activateTool = (tool: ToolbarTool | ImageEditorTool): void => {\n if (typeof tool === \"string\") {\n tool = toolbar[tool];\n }\n\n this.setState({ tool }, () => {\n const tt = tool as ImageEditorTool;\n typeof tt.onActivate === \"function\" &&\n tt.onActivate({ canvas: this.canvas, options: this.getToolOptions(tt) });\n });\n };\n\n private readonly deactivateTool = (): void => {\n this.setState({\n tool: null\n });\n };\n\n public readonly getCanvasDataUrl = (): string => {\n const canvas = this.canvas.current as HTMLCanvasElement;\n if (canvas) {\n const { src } = this.props;\n if (src.startsWith(\"data:image/jpeg;\")) {\n return canvas.toDataURL(\"image/jpeg\", 1.0);\n }\n\n return canvas.toDataURL();\n }\n\n return \"\";\n };\n\n private readonly applyActiveTool = async (): Promise<void> => {\n const { tool } = this.state;\n if (!tool) {\n return;\n }\n\n if (tool.apply) {\n await tool.apply({\n canvas: this.canvas\n });\n }\n this.deactivateTool();\n };\n\n private readonly cancelActiveTool = async (): Promise<void> => {\n const { tool } = this.state;\n if (!tool) {\n return;\n }\n\n if (tool.cancel) {\n await tool.cancel({\n canvas: this.canvas\n });\n }\n this.deactivateTool();\n };\n\n private readonly getToolOptions = (\n tool: ImageEditorTool\n ): Partial<ImageEditorPropsPropsOptions> => {\n const { options } = this.props;\n if (!options || typeof options !== \"object\") {\n return {};\n }\n\n return options[tool.name as ToolbarTool] || {};\n };\n\n public override render(): React.ReactNode {\n const { src, tools, children } = this.props;\n const { tool } = this.state;\n const editor = (\n <div className={\"w-full h-full flex flex-col gap-md overflow-hidden\"}>\n <div className={\"flex justify-center items-center w-full\"}>\n {tools.map(key => {\n const tool: ImageEditorTool = toolbar[key];\n if (!tool) {\n return null;\n }\n\n return (\n <div\n key={key}\n className={\n this.state.tool ? \"opacity-50 cursor pointer-events-none\" : \"\"\n }\n >\n {tool.icon({\n activateTool: () => this.activateTool(tool)\n })}\n </div>\n );\n })}\n </div>\n <div className={\"w-full\"}>\n {tool ? (\n <>\n {typeof tool.renderForm === \"function\" &&\n tool.renderForm({\n options: this.getToolOptions(tool as ImageEditorTool),\n image: this.image as HTMLImageElement,\n canvas: this.canvas\n })}\n\n <div className={\"flex justify-center gap-sm mt-sm\"}>\n <Button\n variant={\"secondary\"}\n text={\"Cancel\"}\n data-testid=\"button-cancel\"\n onClick={() => {\n this.cancelActiveTool();\n }}\n />\n <Button\n variant={\"primary\"}\n text={\"Apply\"}\n data-testid=\"button-apply\"\n onClick={() => {\n this.applyActiveTool();\n }}\n />\n </div>\n </>\n ) : (\n <div className={\"text-center\"}>\n Select a tool to start working on your image.\n </div>\n )}\n </div>\n <div\n className={\n \"flex justify-center items-center w-full bg-neutral-dimmed rounded-md overflow-hidden\"\n }\n style={{ height: \"calc(100vh - 256px)\" }}\n >\n <canvas\n key={src}\n id={\"canvas\"}\n style={{ maxWidth: \"100%\", maxHeight: \"100%\" }}\n ref={this.canvas as React.Ref<any>}\n />\n </div>\n </div>\n );\n\n if (typeof children === \"function\") {\n return children({\n render: () => editor,\n // canvas: this.canvas,\n getCanvasDataUrl: this.getCanvasDataUrl,\n activeTool: this.state.tool,\n applyActiveTool: this.applyActiveTool,\n cancelActiveTool: this.cancelActiveTool\n });\n }\n\n return editor;\n }\n}\n\nexport { ImageEditor };\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
interface ImageEditorDialogProps {
|
|
3
|
-
dialogZIndex?: number;
|
|
4
|
-
onClose?: () => void;
|
|
5
|
-
open?: boolean;
|
|
6
|
-
/**
|
|
7
|
-
* We would need to drill down a lot to give correct options.
|
|
8
|
-
* TODO: figure out some other way.
|
|
9
|
-
*/
|
|
10
|
-
options?: any;
|
|
11
|
-
src?: string;
|
|
12
|
-
onAccept: (src: string) => void;
|
|
13
|
-
"data-testid"?: string;
|
|
14
|
-
}
|
|
15
|
-
export declare const ImageEditorDialog: (props: ImageEditorDialogProps) => React.JSX.Element;
|
|
16
|
-
export {};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import { ImageEditor } from "./ImageEditor.js";
|
|
3
|
-
import { Dialog, OverlayLoader } from "@webiny/admin-ui";
|
|
4
|
-
export const ImageEditorDialog = props => {
|
|
5
|
-
const {
|
|
6
|
-
src,
|
|
7
|
-
options,
|
|
8
|
-
onAccept,
|
|
9
|
-
onClose,
|
|
10
|
-
open,
|
|
11
|
-
dialogZIndex,
|
|
12
|
-
...dialogProps
|
|
13
|
-
} = props;
|
|
14
|
-
const imageEditor = /*#__PURE__*/React.createRef();
|
|
15
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
16
|
-
const onSave = async () => {
|
|
17
|
-
try {
|
|
18
|
-
setIsSaving(true);
|
|
19
|
-
const url = imageEditor.current ? imageEditor.current.getCanvasDataUrl() : "";
|
|
20
|
-
await onAccept(url);
|
|
21
|
-
} catch (e) {
|
|
22
|
-
console.log(e);
|
|
23
|
-
} finally {
|
|
24
|
-
setIsSaving(false);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
return /*#__PURE__*/React.createElement(Dialog, Object.assign({
|
|
28
|
-
style: {
|
|
29
|
-
zIndex: dialogZIndex
|
|
30
|
-
},
|
|
31
|
-
title: "Edit Image",
|
|
32
|
-
size: "full",
|
|
33
|
-
open: open,
|
|
34
|
-
onClose: onClose
|
|
35
|
-
}, dialogProps, {
|
|
36
|
-
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Dialog.CancelAction, null), /*#__PURE__*/React.createElement(Dialog.ConfirmAction, {
|
|
37
|
-
text: "Save",
|
|
38
|
-
"data-testid": "dialog-accept",
|
|
39
|
-
onClick: onSave,
|
|
40
|
-
disabled: isSaving
|
|
41
|
-
}))
|
|
42
|
-
}), isSaving && /*#__PURE__*/React.createElement(OverlayLoader, {
|
|
43
|
-
text: "Creating a new version of the image"
|
|
44
|
-
}), /*#__PURE__*/React.createElement(ImageEditor, {
|
|
45
|
-
ref: imageEditor,
|
|
46
|
-
src: src,
|
|
47
|
-
options: options
|
|
48
|
-
}, ({
|
|
49
|
-
render
|
|
50
|
-
}) => render()));
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
//# sourceMappingURL=ImageEditorDialog.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","useState","ImageEditor","Dialog","OverlayLoader","ImageEditorDialog","props","src","options","onAccept","onClose","open","dialogZIndex","dialogProps","imageEditor","createRef","isSaving","setIsSaving","onSave","url","current","getCanvasDataUrl","e","console","log","createElement","Object","assign","style","zIndex","title","size","actions","Fragment","CancelAction","ConfirmAction","text","onClick","disabled","ref","render"],"sources":["ImageEditorDialog.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { ImageEditor } from \"./ImageEditor.js\";\nimport { Dialog, OverlayLoader } from \"@webiny/admin-ui\";\n\ninterface ImageEditorDialogProps {\n dialogZIndex?: number;\n onClose?: () => void;\n open?: boolean;\n /**\n * We would need to drill down a lot to give correct options.\n * TODO: figure out some other way.\n */\n options?: any;\n src?: string;\n onAccept: (src: string) => void;\n \"data-testid\"?: string;\n}\n\nexport const ImageEditorDialog = (props: ImageEditorDialogProps) => {\n const { src, options, onAccept, onClose, open, dialogZIndex, ...dialogProps } = props;\n const imageEditor = React.createRef<ImageEditor>();\n const [isSaving, setIsSaving] = useState(false);\n\n const onSave = async () => {\n try {\n setIsSaving(true);\n const url = imageEditor.current ? imageEditor.current.getCanvasDataUrl() : \"\";\n await onAccept(url);\n } catch (e) {\n console.log(e);\n } finally {\n setIsSaving(false);\n }\n };\n\n return (\n <Dialog\n style={{ zIndex: dialogZIndex }}\n title={\"Edit Image\"}\n size={\"full\"}\n open={open}\n onClose={onClose}\n {...dialogProps}\n actions={\n <>\n <Dialog.CancelAction />\n <Dialog.ConfirmAction\n text={\"Save\"}\n data-testid=\"dialog-accept\"\n onClick={onSave}\n disabled={isSaving}\n />\n </>\n }\n >\n {isSaving && <OverlayLoader text={\"Creating a new version of the image\"} />}\n <ImageEditor ref={imageEditor} src={src} options={options}>\n {({ render }) => render()}\n </ImageEditor>\n </Dialog>\n );\n};\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,QAAQ,QAAQ,OAAO;AACvC,SAASC,WAAW;AACpB,SAASC,MAAM,EAAEC,aAAa,QAAQ,kBAAkB;AAgBxD,OAAO,MAAMC,iBAAiB,GAAIC,KAA6B,IAAK;EAChE,MAAM;IAAEC,GAAG;IAAEC,OAAO;IAAEC,QAAQ;IAAEC,OAAO;IAAEC,IAAI;IAAEC,YAAY;IAAE,GAAGC;EAAY,CAAC,GAAGP,KAAK;EACrF,MAAMQ,WAAW,gBAAGd,KAAK,CAACe,SAAS,CAAc,CAAC;EAClD,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAGhB,QAAQ,CAAC,KAAK,CAAC;EAE/C,MAAMiB,MAAM,GAAG,MAAAA,CAAA,KAAY;IACvB,IAAI;MACAD,WAAW,CAAC,IAAI,CAAC;MACjB,MAAME,GAAG,GAAGL,WAAW,CAACM,OAAO,GAAGN,WAAW,CAACM,OAAO,CAACC,gBAAgB,CAAC,CAAC,GAAG,EAAE;MAC7E,MAAMZ,QAAQ,CAACU,GAAG,CAAC;IACvB,CAAC,CAAC,OAAOG,CAAC,EAAE;MACRC,OAAO,CAACC,GAAG,CAACF,CAAC,CAAC;IAClB,CAAC,SAAS;MACNL,WAAW,CAAC,KAAK,CAAC;IACtB;EACJ,CAAC;EAED,oBACIjB,KAAA,CAAAyB,aAAA,CAACtB,MAAM,EAAAuB,MAAA,CAAAC,MAAA;IACHC,KAAK,EAAE;MAAEC,MAAM,EAAEjB;IAAa,CAAE;IAChCkB,KAAK,EAAE,YAAa;IACpBC,IAAI,EAAE,MAAO;IACbpB,IAAI,EAAEA,IAAK;IACXD,OAAO,EAAEA;EAAQ,GACbG,WAAW;IACfmB,OAAO,eACHhC,KAAA,CAAAyB,aAAA,CAAAzB,KAAA,CAAAiC,QAAA,qBACIjC,KAAA,CAAAyB,aAAA,CAACtB,MAAM,CAAC+B,YAAY,MAAE,CAAC,eACvBlC,KAAA,CAAAyB,aAAA,CAACtB,MAAM,CAACgC,aAAa;MACjBC,IAAI,EAAE,MAAO;MACb,eAAY,eAAe;MAC3BC,OAAO,EAAEnB,MAAO;MAChBoB,QAAQ,EAAEtB;IAAS,CACtB,CACH;EACL,IAEAA,QAAQ,iBAAIhB,KAAA,CAAAyB,aAAA,CAACrB,aAAa;IAACgC,IAAI,EAAE;EAAsC,CAAE,CAAC,eAC3EpC,KAAA,CAAAyB,aAAA,CAACvB,WAAW;IAACqC,GAAG,EAAEzB,WAAY;IAACP,GAAG,EAAEA,GAAI;IAACC,OAAO,EAAEA;EAAQ,GACrD,CAAC;IAAEgC;EAAO,CAAC,KAAKA,MAAM,CAAC,CACf,CACT,CAAC;AAEjB,CAAC","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./ImageEditor.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./ImageEditor.js\";\n"],"mappings":"AAAA","ignoreList":[]}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { IconButton, Tooltip } from "@webiny/admin-ui";
|
|
3
|
-
import { ReactComponent as CropIcon } from "@webiny/icons/crop.svg";
|
|
4
|
-
import Cropper from "cropperjs";
|
|
5
|
-
import "cropperjs/dist/cropper.css";
|
|
6
|
-
let cropper = undefined;
|
|
7
|
-
const renderForm = () => {
|
|
8
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
9
|
-
style: {
|
|
10
|
-
textAlign: "center"
|
|
11
|
-
}
|
|
12
|
-
}, "Click and drag to crop a portion of the image. Hold Shift to persist aspect ratio.");
|
|
13
|
-
};
|
|
14
|
-
const tool = {
|
|
15
|
-
name: "crop",
|
|
16
|
-
icon({
|
|
17
|
-
activateTool
|
|
18
|
-
}) {
|
|
19
|
-
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
20
|
-
side: "bottom",
|
|
21
|
-
content: "Crop",
|
|
22
|
-
trigger: /*#__PURE__*/React.createElement(IconButton, {
|
|
23
|
-
variant: "ghost",
|
|
24
|
-
icon: /*#__PURE__*/React.createElement(CropIcon, null),
|
|
25
|
-
onClick: () => activateTool("crop"),
|
|
26
|
-
"data-testid": "crop-item"
|
|
27
|
-
})
|
|
28
|
-
});
|
|
29
|
-
},
|
|
30
|
-
renderForm,
|
|
31
|
-
onActivate: ({
|
|
32
|
-
canvas,
|
|
33
|
-
options
|
|
34
|
-
}) => {
|
|
35
|
-
cropper = new Cropper(canvas.current, options);
|
|
36
|
-
},
|
|
37
|
-
cancel: () => cropper && cropper.destroy(),
|
|
38
|
-
apply: ({
|
|
39
|
-
canvas
|
|
40
|
-
}) => {
|
|
41
|
-
return new Promise(resolve => {
|
|
42
|
-
if (!cropper) {
|
|
43
|
-
resolve();
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
const current = canvas.current;
|
|
47
|
-
const src = cropper.getCroppedCanvas().toDataURL();
|
|
48
|
-
if (current) {
|
|
49
|
-
const image = new window.Image();
|
|
50
|
-
const ctx = current.getContext("2d");
|
|
51
|
-
image.onload = () => {
|
|
52
|
-
ctx.drawImage(image, 0, 0);
|
|
53
|
-
current.width = image.width;
|
|
54
|
-
current.height = image.height;
|
|
55
|
-
ctx.drawImage(image, 0, 0);
|
|
56
|
-
resolve();
|
|
57
|
-
};
|
|
58
|
-
image.src = src;
|
|
59
|
-
}
|
|
60
|
-
cropper.destroy();
|
|
61
|
-
cropper = undefined;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
export default tool;
|
|
66
|
-
|
|
67
|
-
//# sourceMappingURL=crop.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","IconButton","Tooltip","ReactComponent","CropIcon","Cropper","cropper","undefined","renderForm","createElement","style","textAlign","tool","name","icon","activateTool","side","content","trigger","variant","onClick","onActivate","canvas","options","current","cancel","destroy","apply","Promise","resolve","src","getCroppedCanvas","toDataURL","image","window","Image","ctx","getContext","onload","drawImage","width","height"],"sources":["crop.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ImageEditorTool } from \"./types.js\";\nimport { IconButton, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as CropIcon } from \"@webiny/icons/crop.svg\";\nimport Cropper from \"cropperjs\";\nimport \"cropperjs/dist/cropper.css\";\n\nlet cropper: Cropper | undefined = undefined;\n\nconst renderForm = () => {\n return (\n <div style={{ textAlign: \"center\" }}>\n Click and drag to crop a portion of the image. Hold Shift to persist aspect ratio.\n </div>\n );\n};\n\nconst tool: ImageEditorTool = {\n name: \"crop\",\n icon({ activateTool }) {\n return (\n <Tooltip\n side={\"bottom\"}\n content={\"Crop\"}\n trigger={\n <IconButton\n variant={\"ghost\"}\n icon={<CropIcon />}\n onClick={() => activateTool(\"crop\")}\n data-testid={\"crop-item\"}\n />\n }\n />\n );\n },\n renderForm,\n onActivate: ({ canvas, options }) => {\n cropper = new Cropper(canvas.current as HTMLCanvasElement, options);\n },\n cancel: () => cropper && cropper.destroy(),\n apply: ({ canvas }) => {\n return new Promise((resolve: any) => {\n if (!cropper) {\n resolve();\n return;\n }\n\n const current = canvas.current;\n const src = cropper.getCroppedCanvas().toDataURL();\n if (current) {\n const image = new window.Image();\n const ctx = current.getContext(\"2d\") as CanvasRenderingContext2D;\n image.onload = () => {\n ctx.drawImage(image, 0, 0);\n current.width = image.width;\n current.height = image.height;\n\n ctx.drawImage(image, 0, 0);\n resolve();\n };\n image.src = src;\n }\n\n cropper.destroy();\n cropper = undefined;\n });\n }\n};\n\nexport default tool;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,SAASC,UAAU,EAAEC,OAAO,QAAQ,kBAAkB;AACtD,SAASC,cAAc,IAAIC,QAAQ,QAAQ,wBAAwB;AACnE,OAAOC,OAAO,MAAM,WAAW;AAC/B,OAAO,4BAA4B;AAEnC,IAAIC,OAA4B,GAAGC,SAAS;AAE5C,MAAMC,UAAU,GAAGA,CAAA,KAAM;EACrB,oBACIR,KAAA,CAAAS,aAAA;IAAKC,KAAK,EAAE;MAAEC,SAAS,EAAE;IAAS;EAAE,GAAC,oFAEhC,CAAC;AAEd,CAAC;AAED,MAAMC,IAAqB,GAAG;EAC1BC,IAAI,EAAE,MAAM;EACZC,IAAIA,CAAC;IAAEC;EAAa,CAAC,EAAE;IACnB,oBACIf,KAAA,CAAAS,aAAA,CAACP,OAAO;MACJc,IAAI,EAAE,QAAS;MACfC,OAAO,EAAE,MAAO;MAChBC,OAAO,eACHlB,KAAA,CAAAS,aAAA,CAACR,UAAU;QACPkB,OAAO,EAAE,OAAQ;QACjBL,IAAI,eAAEd,KAAA,CAAAS,aAAA,CAACL,QAAQ,MAAE,CAAE;QACnBgB,OAAO,EAAEA,CAAA,KAAML,YAAY,CAAC,MAAM,CAAE;QACpC,eAAa;MAAY,CAC5B;IACJ,CACJ,CAAC;EAEV,CAAC;EACDP,UAAU;EACVa,UAAU,EAAEA,CAAC;IAAEC,MAAM;IAAEC;EAAQ,CAAC,KAAK;IACjCjB,OAAO,GAAG,IAAID,OAAO,CAACiB,MAAM,CAACE,OAAO,EAAuBD,OAAO,CAAC;EACvE,CAAC;EACDE,MAAM,EAAEA,CAAA,KAAMnB,OAAO,IAAIA,OAAO,CAACoB,OAAO,CAAC,CAAC;EAC1CC,KAAK,EAAEA,CAAC;IAAEL;EAAO,CAAC,KAAK;IACnB,OAAO,IAAIM,OAAO,CAAEC,OAAY,IAAK;MACjC,IAAI,CAACvB,OAAO,EAAE;QACVuB,OAAO,CAAC,CAAC;QACT;MACJ;MAEA,MAAML,OAAO,GAAGF,MAAM,CAACE,OAAO;MAC9B,MAAMM,GAAG,GAAGxB,OAAO,CAACyB,gBAAgB,CAAC,CAAC,CAACC,SAAS,CAAC,CAAC;MAClD,IAAIR,OAAO,EAAE;QACT,MAAMS,KAAK,GAAG,IAAIC,MAAM,CAACC,KAAK,CAAC,CAAC;QAChC,MAAMC,GAAG,GAAGZ,OAAO,CAACa,UAAU,CAAC,IAAI,CAA6B;QAChEJ,KAAK,CAACK,MAAM,GAAG,MAAM;UACjBF,GAAG,CAACG,SAAS,CAACN,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;UAC1BT,OAAO,CAACgB,KAAK,GAAGP,KAAK,CAACO,KAAK;UAC3BhB,OAAO,CAACiB,MAAM,GAAGR,KAAK,CAACQ,MAAM;UAE7BL,GAAG,CAACG,SAAS,CAACN,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;UAC1BJ,OAAO,CAAC,CAAC;QACb,CAAC;QACDI,KAAK,CAACH,GAAG,GAAGA,GAAG;MACnB;MAEAxB,OAAO,CAACoB,OAAO,CAAC,CAAC;MACjBpB,OAAO,GAAGC,SAAS;IACvB,CAAC,CAAC;EACN;AACJ,CAAC;AAED,eAAeK,IAAI","ignoreList":[]}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* When using Caman, we added @ts-expect-error because it does not exist in packages, but it is loaded in packages/ui/src/ImageEditor/ImageEditor.tsx:38.
|
|
3
|
-
* TODO: use some other library to edit images
|
|
4
|
-
*/
|
|
5
|
-
import React from "react";
|
|
6
|
-
import { ReactComponent as FilterIcon } from "@webiny/icons/tune.svg";
|
|
7
|
-
import debounce from "lodash/debounce.js";
|
|
8
|
-
import { Button, Grid, IconButton, Slider, Tooltip } from "@webiny/admin-ui";
|
|
9
|
-
const sliders = [{
|
|
10
|
-
key: "brightness",
|
|
11
|
-
label: "Brightness",
|
|
12
|
-
min: -100
|
|
13
|
-
}, {
|
|
14
|
-
key: "vibrance",
|
|
15
|
-
label: "Vibrance",
|
|
16
|
-
min: -100
|
|
17
|
-
}, {
|
|
18
|
-
key: "hue",
|
|
19
|
-
label: "Hue",
|
|
20
|
-
min: -100
|
|
21
|
-
}, {
|
|
22
|
-
key: "gamma",
|
|
23
|
-
label: "Gamma"
|
|
24
|
-
}, {
|
|
25
|
-
key: "clip",
|
|
26
|
-
label: "Clip"
|
|
27
|
-
}, {
|
|
28
|
-
key: "stackBlur",
|
|
29
|
-
label: "Blur"
|
|
30
|
-
}, {
|
|
31
|
-
key: "contrast",
|
|
32
|
-
label: "Contrast",
|
|
33
|
-
min: -100
|
|
34
|
-
}, {
|
|
35
|
-
key: "saturation",
|
|
36
|
-
label: "Saturation",
|
|
37
|
-
min: -100
|
|
38
|
-
}, {
|
|
39
|
-
key: "exposure",
|
|
40
|
-
label: "Exposure",
|
|
41
|
-
min: -100
|
|
42
|
-
}, {
|
|
43
|
-
key: "sepia",
|
|
44
|
-
label: "Sepia"
|
|
45
|
-
}, {
|
|
46
|
-
key: "noise",
|
|
47
|
-
label: "Noise"
|
|
48
|
-
}, {
|
|
49
|
-
key: "sharpen",
|
|
50
|
-
label: "Sharpen"
|
|
51
|
-
}];
|
|
52
|
-
class RenderForm extends React.Component {
|
|
53
|
-
state = {
|
|
54
|
-
processing: false,
|
|
55
|
-
values: {}
|
|
56
|
-
};
|
|
57
|
-
componentDidMount() {
|
|
58
|
-
this.resetFiltersValues();
|
|
59
|
-
}
|
|
60
|
-
applyFilters = debounce(() => {
|
|
61
|
-
const {
|
|
62
|
-
canvas
|
|
63
|
-
} = this.props;
|
|
64
|
-
const {
|
|
65
|
-
values
|
|
66
|
-
} = this.state;
|
|
67
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
68
|
-
const component = this;
|
|
69
|
-
|
|
70
|
-
// @ts-expect-error
|
|
71
|
-
Caman(canvas.current, function () {
|
|
72
|
-
// @ts-expect-error
|
|
73
|
-
this.revert(false);
|
|
74
|
-
Object.keys(values).forEach(
|
|
75
|
-
// @ts-expect-error
|
|
76
|
-
key => values[key] !== 0 && this[key] && this[key](values[key]));
|
|
77
|
-
// @ts-expect-error
|
|
78
|
-
this.render();
|
|
79
|
-
component.setState({
|
|
80
|
-
processing: false
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
}, 200);
|
|
84
|
-
resetFiltersValues = () => {
|
|
85
|
-
this.setState(state => {
|
|
86
|
-
sliders.reduce((output, current) => {
|
|
87
|
-
state.values[current.key] = 0;
|
|
88
|
-
return output;
|
|
89
|
-
}, {});
|
|
90
|
-
return state;
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
render() {
|
|
94
|
-
return /*#__PURE__*/React.createElement(Grid, null, /*#__PURE__*/React.createElement(React.Fragment, null, sliders.map(props => /*#__PURE__*/React.createElement(Grid.Column, {
|
|
95
|
-
span: 4,
|
|
96
|
-
key: props.key
|
|
97
|
-
}, /*#__PURE__*/React.createElement(Slider, Object.assign({
|
|
98
|
-
value: Number(this.state.values[props.key]),
|
|
99
|
-
min: 0,
|
|
100
|
-
max: 100,
|
|
101
|
-
disabled: this.state.processing,
|
|
102
|
-
onValueChange: value => {
|
|
103
|
-
this.setState(state => {
|
|
104
|
-
const values = {
|
|
105
|
-
...state.values
|
|
106
|
-
};
|
|
107
|
-
values[props.key] = value;
|
|
108
|
-
return {
|
|
109
|
-
...state,
|
|
110
|
-
processing: true,
|
|
111
|
-
values
|
|
112
|
-
};
|
|
113
|
-
}, this.applyFilters);
|
|
114
|
-
}
|
|
115
|
-
}, props))))), /*#__PURE__*/React.createElement(Grid.Column, {
|
|
116
|
-
span: 12,
|
|
117
|
-
className: "text-center"
|
|
118
|
-
}, /*#__PURE__*/React.createElement(Button, {
|
|
119
|
-
text: "Reset filters",
|
|
120
|
-
variant: "secondary",
|
|
121
|
-
onClick: () => {
|
|
122
|
-
this.setState({
|
|
123
|
-
processing: true
|
|
124
|
-
}, () => {
|
|
125
|
-
this.resetFiltersValues();
|
|
126
|
-
this.applyFilters();
|
|
127
|
-
this.setState({
|
|
128
|
-
processing: false
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
})));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const tool = {
|
|
136
|
-
name: "filter",
|
|
137
|
-
icon({
|
|
138
|
-
activateTool
|
|
139
|
-
}) {
|
|
140
|
-
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
141
|
-
trigger: /*#__PURE__*/React.createElement(IconButton, {
|
|
142
|
-
variant: "ghost",
|
|
143
|
-
icon: /*#__PURE__*/React.createElement(FilterIcon, null),
|
|
144
|
-
onClick: () => activateTool("filter"),
|
|
145
|
-
"data-testid": "filter-item"
|
|
146
|
-
}),
|
|
147
|
-
content: "Filter"
|
|
148
|
-
});
|
|
149
|
-
},
|
|
150
|
-
renderForm(props) {
|
|
151
|
-
return /*#__PURE__*/React.createElement(RenderForm, props);
|
|
152
|
-
},
|
|
153
|
-
cancel: ({
|
|
154
|
-
canvas
|
|
155
|
-
}) => {
|
|
156
|
-
// @ts-expect-error
|
|
157
|
-
Caman(canvas.current, function () {
|
|
158
|
-
// @ts-expect-error
|
|
159
|
-
this.revert(false);
|
|
160
|
-
// @ts-expect-error
|
|
161
|
-
this.render();
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
export default tool;
|
|
166
|
-
|
|
167
|
-
//# sourceMappingURL=filter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","ReactComponent","FilterIcon","debounce","Button","Grid","IconButton","Slider","Tooltip","sliders","key","label","min","RenderForm","Component","state","processing","values","componentDidMount","resetFiltersValues","applyFilters","canvas","props","component","Caman","current","revert","Object","keys","forEach","render","setState","reduce","output","createElement","Fragment","map","Column","span","assign","value","Number","max","disabled","onValueChange","className","text","variant","onClick","tool","name","icon","activateTool","trigger","content","renderForm","cancel"],"sources":["filter.tsx"],"sourcesContent":["/**\n * When using Caman, we added @ts-expect-error because it does not exist in packages, but it is loaded in packages/ui/src/ImageEditor/ImageEditor.tsx:38.\n * TODO: use some other library to edit images\n */\nimport React from \"react\";\nimport { ReactComponent as FilterIcon } from \"@webiny/icons/tune.svg\";\nimport debounce from \"lodash/debounce.js\";\nimport { Button, Grid, IconButton, Slider, Tooltip } from \"@webiny/admin-ui\";\nimport type { ImageEditorTool } from \"./types.js\";\n\ninterface RenderFormState {\n values: Record<string, any>;\n processing: boolean;\n}\n\ninterface RenderFormProps {\n canvas: any;\n renderApplyCancel?: () => void;\n}\n\nconst sliders = [\n {\n key: \"brightness\",\n label: \"Brightness\",\n min: -100\n },\n {\n key: \"vibrance\",\n label: \"Vibrance\",\n min: -100\n },\n {\n key: \"hue\",\n label: \"Hue\",\n min: -100\n },\n {\n key: \"gamma\",\n label: \"Gamma\"\n },\n {\n key: \"clip\",\n label: \"Clip\"\n },\n {\n key: \"stackBlur\",\n label: \"Blur\"\n },\n {\n key: \"contrast\",\n label: \"Contrast\",\n min: -100\n },\n {\n key: \"saturation\",\n label: \"Saturation\",\n min: -100\n },\n {\n key: \"exposure\",\n label: \"Exposure\",\n min: -100\n },\n {\n key: \"sepia\",\n label: \"Sepia\"\n },\n {\n key: \"noise\",\n label: \"Noise\"\n },\n {\n key: \"sharpen\",\n label: \"Sharpen\"\n }\n];\n\nclass RenderForm extends React.Component<RenderFormProps, RenderFormState> {\n public override state: RenderFormState = {\n processing: false,\n values: {}\n };\n\n public override componentDidMount() {\n this.resetFiltersValues();\n }\n\n private readonly applyFilters = debounce(() => {\n const { canvas } = this.props;\n const { values } = this.state;\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const component = this;\n\n // @ts-expect-error\n Caman(canvas.current, function () {\n // @ts-expect-error\n this.revert(false);\n Object.keys(values).forEach(\n // @ts-expect-error\n key => values[key] !== 0 && this[key] && this[key](values[key])\n );\n // @ts-expect-error\n this.render();\n component.setState({ processing: false });\n });\n }, 200);\n\n private readonly resetFiltersValues = () => {\n this.setState(state => {\n sliders.reduce((output, current) => {\n state.values[current.key] = 0;\n return output;\n }, {});\n\n return state;\n });\n };\n\n public override render() {\n return (\n <Grid>\n <>\n {sliders.map(props => (\n <Grid.Column span={4} key={props.key}>\n <Slider\n value={Number(this.state.values[props.key])}\n min={0}\n max={100}\n disabled={this.state.processing}\n onValueChange={(value: number) => {\n this.setState(state => {\n const values = { ...state.values };\n values[props.key] = value;\n\n return { ...state, processing: true, values };\n }, this.applyFilters);\n }}\n {...props}\n />\n </Grid.Column>\n ))}\n </>\n <Grid.Column span={12} className={\"text-center\"}>\n <Button\n text={\"Reset filters\"}\n variant={\"secondary\"}\n onClick={() => {\n this.setState({ processing: true }, () => {\n this.resetFiltersValues();\n this.applyFilters();\n this.setState({ processing: false });\n });\n }}\n />\n </Grid.Column>\n </Grid>\n );\n }\n}\n\nconst tool: ImageEditorTool = {\n name: \"filter\",\n icon({ activateTool }) {\n return (\n <Tooltip\n trigger={\n <IconButton\n variant={\"ghost\"}\n icon={<FilterIcon />}\n onClick={() => activateTool(\"filter\")}\n data-testid={\"filter-item\"}\n />\n }\n content={\"Filter\"}\n />\n );\n },\n renderForm(props) {\n return <RenderForm {...props} />;\n },\n cancel: ({ canvas }) => {\n // @ts-expect-error\n Caman(canvas.current, function () {\n // @ts-expect-error\n this.revert(false);\n // @ts-expect-error\n this.render();\n });\n }\n};\n\nexport default tool;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { Button, IconButton, Tooltip } from "@webiny/admin-ui";
|
|
3
|
-
import { ReactComponent as FlipIcon } from "@webiny/icons/flip.svg";
|
|
4
|
-
import Cropper from "cropperjs";
|
|
5
|
-
import "cropperjs/dist/cropper.css";
|
|
6
|
-
let cropper;
|
|
7
|
-
const flipped = {
|
|
8
|
-
x: 1,
|
|
9
|
-
y: 1
|
|
10
|
-
};
|
|
11
|
-
const renderForm = () => {
|
|
12
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
13
|
-
className: "flex justify-center gap-sm"
|
|
14
|
-
}, /*#__PURE__*/React.createElement(Button, {
|
|
15
|
-
text: "FlipX",
|
|
16
|
-
variant: "secondary",
|
|
17
|
-
onClick: () => {
|
|
18
|
-
if (!cropper) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
flipped.x = flipped.x === 1 ? -1 : 1;
|
|
22
|
-
cropper.scaleX(flipped.x);
|
|
23
|
-
}
|
|
24
|
-
}), /*#__PURE__*/React.createElement(Button, {
|
|
25
|
-
text: "FlipY",
|
|
26
|
-
variant: "secondary",
|
|
27
|
-
onClick: () => {
|
|
28
|
-
if (!cropper) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
flipped.y = flipped.y === 1 ? -1 : 1;
|
|
32
|
-
cropper.scaleY(flipped.y);
|
|
33
|
-
}
|
|
34
|
-
}));
|
|
35
|
-
};
|
|
36
|
-
const tool = {
|
|
37
|
-
name: "flip",
|
|
38
|
-
icon({
|
|
39
|
-
activateTool
|
|
40
|
-
}) {
|
|
41
|
-
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
42
|
-
side: "bottom",
|
|
43
|
-
content: "Flip",
|
|
44
|
-
trigger: /*#__PURE__*/React.createElement(IconButton, {
|
|
45
|
-
variant: "ghost",
|
|
46
|
-
icon: /*#__PURE__*/React.createElement(FlipIcon, null),
|
|
47
|
-
onClick: () => activateTool("flip"),
|
|
48
|
-
"data-testid": "flip-item"
|
|
49
|
-
})
|
|
50
|
-
});
|
|
51
|
-
},
|
|
52
|
-
renderForm,
|
|
53
|
-
cancel: () => cropper && cropper.destroy(),
|
|
54
|
-
onActivate: ({
|
|
55
|
-
canvas
|
|
56
|
-
}) => {
|
|
57
|
-
cropper = new Cropper(canvas.current, {
|
|
58
|
-
background: false,
|
|
59
|
-
modal: false,
|
|
60
|
-
guides: false,
|
|
61
|
-
dragMode: "none",
|
|
62
|
-
highlight: false,
|
|
63
|
-
autoCrop: false
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
apply: ({
|
|
67
|
-
canvas
|
|
68
|
-
}) => {
|
|
69
|
-
return new Promise(resolve => {
|
|
70
|
-
if (!cropper) {
|
|
71
|
-
resolve();
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const current = canvas.current;
|
|
75
|
-
const src = cropper.getCroppedCanvas().toDataURL();
|
|
76
|
-
if (current) {
|
|
77
|
-
const image = new window.Image();
|
|
78
|
-
const ctx = current.getContext("2d");
|
|
79
|
-
image.onload = () => {
|
|
80
|
-
ctx.drawImage(image, 0, 0);
|
|
81
|
-
current.width = image.width;
|
|
82
|
-
current.height = image.height;
|
|
83
|
-
ctx.drawImage(image, 0, 0);
|
|
84
|
-
resolve();
|
|
85
|
-
};
|
|
86
|
-
image.src = src;
|
|
87
|
-
}
|
|
88
|
-
cropper.destroy();
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
export default tool;
|
|
93
|
-
|
|
94
|
-
//# sourceMappingURL=flip.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","Button","IconButton","Tooltip","ReactComponent","FlipIcon","Cropper","cropper","flipped","x","y","renderForm","createElement","className","text","variant","onClick","scaleX","scaleY","tool","name","icon","activateTool","side","content","trigger","cancel","destroy","onActivate","canvas","current","background","modal","guides","dragMode","highlight","autoCrop","apply","Promise","resolve","src","getCroppedCanvas","toDataURL","image","window","Image","ctx","getContext","onload","drawImage","width","height"],"sources":["flip.tsx"],"sourcesContent":["import React from \"react\";\nimport { Button, IconButton, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as FlipIcon } from \"@webiny/icons/flip.svg\";\nimport Cropper from \"cropperjs\";\nimport \"cropperjs/dist/cropper.css\";\nimport type { ImageEditorTool } from \"./types.js\";\n\nlet cropper: Cropper;\n\nconst flipped = { x: 1, y: 1 };\n\nconst renderForm = () => {\n return (\n <div className={\"flex justify-center gap-sm\"}>\n <Button\n text={\"FlipX\"}\n variant={\"secondary\"}\n onClick={() => {\n if (!cropper) {\n return;\n }\n\n flipped.x = flipped.x === 1 ? -1 : 1;\n cropper.scaleX(flipped.x);\n }}\n />\n <Button\n text={\"FlipY\"}\n variant={\"secondary\"}\n onClick={() => {\n if (!cropper) {\n return;\n }\n\n flipped.y = flipped.y === 1 ? -1 : 1;\n cropper.scaleY(flipped.y);\n }}\n />\n </div>\n );\n};\n\nconst tool: ImageEditorTool = {\n name: \"flip\",\n icon({ activateTool }) {\n return (\n <Tooltip\n side={\"bottom\"}\n content={\"Flip\"}\n trigger={\n <IconButton\n variant={\"ghost\"}\n icon={<FlipIcon />}\n onClick={() => activateTool(\"flip\")}\n data-testid={\"flip-item\"}\n />\n }\n />\n );\n },\n renderForm,\n cancel: () => cropper && cropper.destroy(),\n onActivate: ({ canvas }) => {\n cropper = new Cropper(canvas.current as HTMLCanvasElement, {\n background: false,\n modal: false,\n guides: false,\n dragMode: \"none\",\n highlight: false,\n autoCrop: false\n });\n },\n apply: ({ canvas }) => {\n return new Promise((resolve: any) => {\n if (!cropper) {\n resolve();\n return;\n }\n\n const current = canvas.current;\n const src = cropper.getCroppedCanvas().toDataURL();\n if (current) {\n const image = new window.Image();\n const ctx = current.getContext(\"2d\") as CanvasRenderingContext2D;\n image.onload = () => {\n ctx.drawImage(image, 0, 0);\n current.width = image.width;\n current.height = image.height;\n\n ctx.drawImage(image, 0, 0);\n resolve();\n };\n image.src = src;\n }\n\n cropper.destroy();\n });\n }\n};\n\nexport default tool;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["default","crop","flip","filter","rotate"],"sources":["index.ts"],"sourcesContent":["export { default as crop } from \"./crop.js\";\nexport { default as flip } from \"./flip.js\";\nexport { default as filter } from \"./filter.js\";\nexport { default as rotate } from \"./rotate.js\";\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,IAAI;AACxB,SAASD,OAAO,IAAIE,IAAI;AACxB,SAASF,OAAO,IAAIG,MAAM;AAC1B,SAASH,OAAO,IAAII,MAAM","ignoreList":[]}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { IconButton, Slider, Tooltip } from "@webiny/admin-ui";
|
|
3
|
-
import { ReactComponent as RotateRight } from "@webiny/icons/rotate_right.svg";
|
|
4
|
-
import Cropper from "cropperjs";
|
|
5
|
-
import "cropperjs/dist/cropper.css";
|
|
6
|
-
let cropper;
|
|
7
|
-
class RenderForm extends React.Component {
|
|
8
|
-
state = {
|
|
9
|
-
rangeInput: 0
|
|
10
|
-
};
|
|
11
|
-
render() {
|
|
12
|
-
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Slider, {
|
|
13
|
-
label: "Range Input",
|
|
14
|
-
value: Number(this.state.rangeInput),
|
|
15
|
-
min: 0,
|
|
16
|
-
max: 360,
|
|
17
|
-
step: 10,
|
|
18
|
-
onValueChange: value => {
|
|
19
|
-
this.setState({
|
|
20
|
-
rangeInput: value
|
|
21
|
-
}, async () => {
|
|
22
|
-
if (cropper) {
|
|
23
|
-
cropper.rotateTo(parseInt(String(value), 10));
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
const tool = {
|
|
31
|
-
name: "rotate",
|
|
32
|
-
icon({
|
|
33
|
-
activateTool
|
|
34
|
-
}) {
|
|
35
|
-
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
36
|
-
side: "bottom",
|
|
37
|
-
content: "Rotate",
|
|
38
|
-
trigger: /*#__PURE__*/React.createElement(IconButton, {
|
|
39
|
-
variant: "ghost",
|
|
40
|
-
icon: /*#__PURE__*/React.createElement(RotateRight, null),
|
|
41
|
-
onClick: () => activateTool("rotate"),
|
|
42
|
-
"data-testid": "rotate-item"
|
|
43
|
-
})
|
|
44
|
-
});
|
|
45
|
-
},
|
|
46
|
-
renderForm(props) {
|
|
47
|
-
return /*#__PURE__*/React.createElement(RenderForm, props);
|
|
48
|
-
},
|
|
49
|
-
onActivate: ({
|
|
50
|
-
canvas
|
|
51
|
-
}) => {
|
|
52
|
-
/**
|
|
53
|
-
* We can safely cast canvas.current as HTMLCanvasElement
|
|
54
|
-
*/
|
|
55
|
-
cropper = new Cropper(canvas.current, {
|
|
56
|
-
background: false,
|
|
57
|
-
modal: false,
|
|
58
|
-
guides: false,
|
|
59
|
-
dragMode: "none",
|
|
60
|
-
highlight: false,
|
|
61
|
-
autoCrop: false
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
cancel: () => cropper && cropper.destroy(),
|
|
65
|
-
apply: ({
|
|
66
|
-
canvas
|
|
67
|
-
}) => {
|
|
68
|
-
return new Promise(resolve => {
|
|
69
|
-
if (!cropper) {
|
|
70
|
-
resolve();
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const current = canvas.current;
|
|
74
|
-
const src = cropper.getCroppedCanvas().toDataURL();
|
|
75
|
-
if (current) {
|
|
76
|
-
const image = new window.Image();
|
|
77
|
-
const ctx = current.getContext("2d");
|
|
78
|
-
image.onload = () => {
|
|
79
|
-
ctx.drawImage(image, 0, 0);
|
|
80
|
-
current.width = image.width;
|
|
81
|
-
current.height = image.height;
|
|
82
|
-
ctx.drawImage(image, 0, 0);
|
|
83
|
-
};
|
|
84
|
-
image.src = src;
|
|
85
|
-
resolve();
|
|
86
|
-
}
|
|
87
|
-
cropper.destroy();
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
export default tool;
|
|
92
|
-
|
|
93
|
-
//# sourceMappingURL=rotate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","IconButton","Slider","Tooltip","ReactComponent","RotateRight","Cropper","cropper","RenderForm","Component","state","rangeInput","render","createElement","label","value","Number","min","max","step","onValueChange","setState","rotateTo","parseInt","String","tool","name","icon","activateTool","side","content","trigger","variant","onClick","renderForm","props","onActivate","canvas","current","background","modal","guides","dragMode","highlight","autoCrop","cancel","destroy","apply","Promise","resolve","src","getCroppedCanvas","toDataURL","image","window","Image","ctx","getContext","onload","drawImage","width","height"],"sources":["rotate.tsx"],"sourcesContent":["import React from \"react\";\nimport { IconButton, Slider, Tooltip } from \"@webiny/admin-ui\";\nimport { ReactComponent as RotateRight } from \"@webiny/icons/rotate_right.svg\";\nimport type { ImageEditorTool } from \"./types.js\";\n\nimport Cropper from \"cropperjs\";\nimport \"cropperjs/dist/cropper.css\";\n\nlet cropper: Cropper;\n\nclass RenderForm extends React.Component<any, any> {\n public override state = {\n rangeInput: 0\n };\n\n public override render() {\n return (\n <div>\n <Slider\n label={\"Range Input\"}\n value={Number(this.state.rangeInput)}\n min={0}\n max={360}\n step={10}\n onValueChange={(value: number) => {\n this.setState({ rangeInput: value }, async () => {\n if (cropper) {\n cropper.rotateTo(parseInt(String(value), 10));\n }\n });\n }}\n />\n </div>\n );\n }\n}\n\nconst tool: ImageEditorTool = {\n name: \"rotate\",\n icon({ activateTool }) {\n return (\n <Tooltip\n side={\"bottom\"}\n content={\"Rotate\"}\n trigger={\n <IconButton\n variant={\"ghost\"}\n icon={<RotateRight />}\n onClick={() => activateTool(\"rotate\")}\n data-testid={\"rotate-item\"}\n />\n }\n />\n );\n },\n renderForm(props) {\n return <RenderForm {...props} />;\n },\n onActivate: ({ canvas }) => {\n /**\n * We can safely cast canvas.current as HTMLCanvasElement\n */\n cropper = new Cropper(canvas.current as HTMLCanvasElement, {\n background: false,\n modal: false,\n guides: false,\n dragMode: \"none\",\n highlight: false,\n autoCrop: false\n });\n },\n cancel: () => cropper && cropper.destroy(),\n apply: ({ canvas }) => {\n return new Promise((resolve: any) => {\n if (!cropper) {\n resolve();\n return;\n }\n\n const current = canvas.current;\n const src = cropper.getCroppedCanvas().toDataURL();\n if (current) {\n const image = new window.Image();\n const ctx = current.getContext(\"2d\") as CanvasRenderingContext2D;\n image.onload = () => {\n ctx.drawImage(image, 0, 0);\n current.width = image.width;\n current.height = image.height;\n\n ctx.drawImage(image, 0, 0);\n };\n image.src = src;\n resolve();\n }\n\n cropper.destroy();\n });\n }\n};\n\nexport default tool;\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,UAAU,EAAEC,MAAM,EAAEC,OAAO,QAAQ,kBAAkB;AAC9D,SAASC,cAAc,IAAIC,WAAW,QAAQ,gCAAgC;AAG9E,OAAOC,OAAO,MAAM,WAAW;AAC/B,OAAO,4BAA4B;AAEnC,IAAIC,OAAgB;AAEpB,MAAMC,UAAU,SAASR,KAAK,CAACS,SAAS,CAAW;EAC/BC,KAAK,GAAG;IACpBC,UAAU,EAAE;EAChB,CAAC;EAEeC,MAAMA,CAAA,EAAG;IACrB,oBACIZ,KAAA,CAAAa,aAAA,2BACIb,KAAA,CAAAa,aAAA,CAACX,MAAM;MACHY,KAAK,EAAE,aAAc;MACrBC,KAAK,EAAEC,MAAM,CAAC,IAAI,CAACN,KAAK,CAACC,UAAU,CAAE;MACrCM,GAAG,EAAE,CAAE;MACPC,GAAG,EAAE,GAAI;MACTC,IAAI,EAAE,EAAG;MACTC,aAAa,EAAGL,KAAa,IAAK;QAC9B,IAAI,CAACM,QAAQ,CAAC;UAAEV,UAAU,EAAEI;QAAM,CAAC,EAAE,YAAY;UAC7C,IAAIR,OAAO,EAAE;YACTA,OAAO,CAACe,QAAQ,CAACC,QAAQ,CAACC,MAAM,CAACT,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;UACjD;QACJ,CAAC,CAAC;MACN;IAAE,CACL,CACA,CAAC;EAEd;AACJ;AAEA,MAAMU,IAAqB,GAAG;EAC1BC,IAAI,EAAE,QAAQ;EACdC,IAAIA,CAAC;IAAEC;EAAa,CAAC,EAAE;IACnB,oBACI5B,KAAA,CAAAa,aAAA,CAACV,OAAO;MACJ0B,IAAI,EAAE,QAAS;MACfC,OAAO,EAAE,QAAS;MAClBC,OAAO,eACH/B,KAAA,CAAAa,aAAA,CAACZ,UAAU;QACP+B,OAAO,EAAE,OAAQ;QACjBL,IAAI,eAAE3B,KAAA,CAAAa,aAAA,CAACR,WAAW,MAAE,CAAE;QACtB4B,OAAO,EAAEA,CAAA,KAAML,YAAY,CAAC,QAAQ,CAAE;QACtC,eAAa;MAAc,CAC9B;IACJ,CACJ,CAAC;EAEV,CAAC;EACDM,UAAUA,CAACC,KAAK,EAAE;IACd,oBAAOnC,KAAA,CAAAa,aAAA,CAACL,UAAU,EAAK2B,KAAQ,CAAC;EACpC,CAAC;EACDC,UAAU,EAAEA,CAAC;IAAEC;EAAO,CAAC,KAAK;IACxB;AACR;AACA;IACQ9B,OAAO,GAAG,IAAID,OAAO,CAAC+B,MAAM,CAACC,OAAO,EAAuB;MACvDC,UAAU,EAAE,KAAK;MACjBC,KAAK,EAAE,KAAK;MACZC,MAAM,EAAE,KAAK;MACbC,QAAQ,EAAE,MAAM;MAChBC,SAAS,EAAE,KAAK;MAChBC,QAAQ,EAAE;IACd,CAAC,CAAC;EACN,CAAC;EACDC,MAAM,EAAEA,CAAA,KAAMtC,OAAO,IAAIA,OAAO,CAACuC,OAAO,CAAC,CAAC;EAC1CC,KAAK,EAAEA,CAAC;IAAEV;EAAO,CAAC,KAAK;IACnB,OAAO,IAAIW,OAAO,CAAEC,OAAY,IAAK;MACjC,IAAI,CAAC1C,OAAO,EAAE;QACV0C,OAAO,CAAC,CAAC;QACT;MACJ;MAEA,MAAMX,OAAO,GAAGD,MAAM,CAACC,OAAO;MAC9B,MAAMY,GAAG,GAAG3C,OAAO,CAAC4C,gBAAgB,CAAC,CAAC,CAACC,SAAS,CAAC,CAAC;MAClD,IAAId,OAAO,EAAE;QACT,MAAMe,KAAK,GAAG,IAAIC,MAAM,CAACC,KAAK,CAAC,CAAC;QAChC,MAAMC,GAAG,GAAGlB,OAAO,CAACmB,UAAU,CAAC,IAAI,CAA6B;QAChEJ,KAAK,CAACK,MAAM,GAAG,MAAM;UACjBF,GAAG,CAACG,SAAS,CAACN,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;UAC1Bf,OAAO,CAACsB,KAAK,GAAGP,KAAK,CAACO,KAAK;UAC3BtB,OAAO,CAACuB,MAAM,GAAGR,KAAK,CAACQ,MAAM;UAE7BL,GAAG,CAACG,SAAS,CAACN,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9B,CAAC;QACDA,KAAK,CAACH,GAAG,GAAGA,GAAG;QACfD,OAAO,CAAC,CAAC;MACb;MAEA1C,OAAO,CAACuC,OAAO,CAAC,CAAC;IACrB,CAAC,CAAC;EACN;AACJ,CAAC;AAED,eAAerB,IAAI","ignoreList":[]}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type React from "react";
|
|
2
|
-
export type ToolbarTool = "crop" | "flip" | "rotate" | "filter";
|
|
3
|
-
interface RenderFormParams {
|
|
4
|
-
canvas: React.RefObject<HTMLCanvasElement | null>;
|
|
5
|
-
image: HTMLImageElement;
|
|
6
|
-
renderApplyCancel?: () => void;
|
|
7
|
-
options?: {
|
|
8
|
-
[key: string]: any;
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
interface OnActivateParams {
|
|
12
|
-
options: any;
|
|
13
|
-
canvas: React.RefObject<HTMLCanvasElement | null>;
|
|
14
|
-
}
|
|
15
|
-
interface IconParams {
|
|
16
|
-
activateTool: (tool: ToolbarTool) => void;
|
|
17
|
-
}
|
|
18
|
-
interface ApplyParams {
|
|
19
|
-
canvas: React.RefObject<HTMLCanvasElement | null>;
|
|
20
|
-
}
|
|
21
|
-
interface CancelParams {
|
|
22
|
-
canvas: React.RefObject<HTMLCanvasElement | null>;
|
|
23
|
-
}
|
|
24
|
-
export interface ImageEditorTool {
|
|
25
|
-
name: string;
|
|
26
|
-
apply?: (params: ApplyParams) => void;
|
|
27
|
-
cancel?: (params: CancelParams) => void;
|
|
28
|
-
onActivate?: (params: OnActivateParams) => void;
|
|
29
|
-
icon: (params: IconParams) => React.ReactElement<any>;
|
|
30
|
-
renderForm?: (params: RenderFormParams) => React.ReactNode;
|
|
31
|
-
}
|
|
32
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type React from \"react\";\n\nexport type ToolbarTool = \"crop\" | \"flip\" | \"rotate\" | \"filter\";\n\ninterface RenderFormParams {\n canvas: React.RefObject<HTMLCanvasElement | null>;\n image: HTMLImageElement;\n renderApplyCancel?: () => void;\n options?: { [key: string]: any };\n}\n\ninterface OnActivateParams {\n options: any;\n canvas: React.RefObject<HTMLCanvasElement | null>;\n}\n\ninterface IconParams {\n activateTool: (tool: ToolbarTool) => void;\n}\n\ninterface ApplyParams {\n canvas: React.RefObject<HTMLCanvasElement | null>;\n}\n\ninterface CancelParams {\n canvas: React.RefObject<HTMLCanvasElement | null>;\n}\n\nexport interface ImageEditorTool {\n name: string;\n apply?: (params: ApplyParams) => void;\n cancel?: (params: CancelParams) => void;\n onActivate?: (params: OnActivateParams) => void;\n icon: (params: IconParams) => React.ReactElement<any>;\n renderForm?: (params: RenderFormParams) => React.ReactNode;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
// @ts-expect-error
|
|
3
|
-
import dataURLtoBlob from "dataurl-to-blob";
|
|
4
|
-
import { ImageEditorDialog } from "../../../../components/ImageEditor/ImageEditorDialog.js";
|
|
5
|
-
import { ReactComponent as EditIcon } from "@webiny/icons/edit.svg";
|
|
6
|
-
import { FileManagerViewConfig, useFile, useFileDetails, useFileManagerApi, useFileManagerView } from "../../../../index.js";
|
|
7
|
-
import { useSnackbar } from "@webiny/app-admin";
|
|
8
|
-
function toDataUrl(url) {
|
|
9
|
-
return new Promise(resolve => {
|
|
10
|
-
const xhr = new window.XMLHttpRequest();
|
|
11
|
-
xhr.onload = function () {
|
|
12
|
-
const reader = new window.FileReader();
|
|
13
|
-
reader.onloadend = function () {
|
|
14
|
-
resolve(reader.result);
|
|
15
|
-
};
|
|
16
|
-
reader.readAsDataURL(xhr.response);
|
|
17
|
-
};
|
|
18
|
-
xhr.open("GET", url);
|
|
19
|
-
xhr.responseType = "blob";
|
|
20
|
-
xhr.send();
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
const initialState = {
|
|
24
|
-
showImageEditor: false,
|
|
25
|
-
dataUrl: null
|
|
26
|
-
};
|
|
27
|
-
const reducer = (state, action) => {
|
|
28
|
-
const next = {
|
|
29
|
-
...state
|
|
30
|
-
};
|
|
31
|
-
switch (action.type) {
|
|
32
|
-
case "setDataUrl":
|
|
33
|
-
next.dataUrl = action.dataUrl;
|
|
34
|
-
next.showImageEditor = true;
|
|
35
|
-
break;
|
|
36
|
-
case "hideImageEditor":
|
|
37
|
-
next.dataUrl = null;
|
|
38
|
-
next.showImageEditor = false;
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
return next;
|
|
42
|
-
};
|
|
43
|
-
const {
|
|
44
|
-
FileDetails
|
|
45
|
-
} = FileManagerViewConfig;
|
|
46
|
-
export const EditImage = () => {
|
|
47
|
-
const {
|
|
48
|
-
file
|
|
49
|
-
} = useFile();
|
|
50
|
-
const {
|
|
51
|
-
canEdit
|
|
52
|
-
} = useFileManagerApi();
|
|
53
|
-
const fileDetails = useFileDetails();
|
|
54
|
-
const {
|
|
55
|
-
uploadFile
|
|
56
|
-
} = useFileManagerView();
|
|
57
|
-
const [state, dispatch] = React.useReducer(reducer, initialState);
|
|
58
|
-
const {
|
|
59
|
-
showSnackbar
|
|
60
|
-
} = useSnackbar();
|
|
61
|
-
if (!file.type.startsWith("image/")) {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Render nothing if the user doesn't have the required permissions for "edit".
|
|
66
|
-
if (!canEdit(file)) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FileDetails.Action.Button, {
|
|
70
|
-
className: "order-last ml-auto",
|
|
71
|
-
label: "Edit image",
|
|
72
|
-
"data-testid": "fm-edit-image-button",
|
|
73
|
-
icon: /*#__PURE__*/React.createElement(EditIcon, null),
|
|
74
|
-
onAction: async () => {
|
|
75
|
-
const dataUrl = await toDataUrl(file.src);
|
|
76
|
-
dispatch({
|
|
77
|
-
type: "setDataUrl",
|
|
78
|
-
dataUrl
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}), /*#__PURE__*/React.createElement(ImageEditorDialog, {
|
|
82
|
-
"data-testid": "fm-image-editor-dialog",
|
|
83
|
-
dialogZIndex: 100,
|
|
84
|
-
open: state.showImageEditor,
|
|
85
|
-
src: state.dataUrl,
|
|
86
|
-
onClose: () => dispatch({
|
|
87
|
-
type: "hideImageEditor"
|
|
88
|
-
}),
|
|
89
|
-
onAccept: async src => {
|
|
90
|
-
const blob = dataURLtoBlob(src);
|
|
91
|
-
blob.name = file.name;
|
|
92
|
-
blob.key = file.key.split("/").pop();
|
|
93
|
-
const newFile = await uploadFile(blob);
|
|
94
|
-
if (newFile) {
|
|
95
|
-
showSnackbar("A new version of the image has been created!");
|
|
96
|
-
dispatch({
|
|
97
|
-
type: "hideImageEditor"
|
|
98
|
-
});
|
|
99
|
-
fileDetails.setFile(newFile);
|
|
100
|
-
fileDetails.close();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}));
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
//# sourceMappingURL=EditImage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["React","dataURLtoBlob","ImageEditorDialog","ReactComponent","EditIcon","FileManagerViewConfig","useFile","useFileDetails","useFileManagerApi","useFileManagerView","useSnackbar","toDataUrl","url","Promise","resolve","xhr","window","XMLHttpRequest","onload","reader","FileReader","onloadend","result","readAsDataURL","response","open","responseType","send","initialState","showImageEditor","dataUrl","reducer","state","action","next","type","FileDetails","EditImage","file","canEdit","fileDetails","uploadFile","dispatch","useReducer","showSnackbar","startsWith","createElement","Fragment","Action","Button","className","label","icon","onAction","src","dialogZIndex","onClose","onAccept","blob","name","key","split","pop","newFile","setFile","close"],"sources":["EditImage.tsx"],"sourcesContent":["import React from \"react\";\n// @ts-expect-error\nimport dataURLtoBlob from \"dataurl-to-blob\";\nimport { ImageEditorDialog } from \"~/components/ImageEditor/ImageEditorDialog.js\";\nimport { ReactComponent as EditIcon } from \"@webiny/icons/edit.svg\";\nimport {\n FileManagerViewConfig,\n useFile,\n useFileDetails,\n useFileManagerApi,\n useFileManagerView\n} from \"~/index.js\";\nimport { useSnackbar } from \"@webiny/app-admin\";\n\nfunction toDataUrl(url: string): Promise<string> {\n return new Promise((resolve: (value: string) => void) => {\n const xhr = new window.XMLHttpRequest();\n xhr.onload = function () {\n const reader = new window.FileReader();\n reader.onloadend = function () {\n resolve(reader.result as string);\n };\n reader.readAsDataURL(xhr.response);\n };\n xhr.open(\"GET\", url);\n xhr.responseType = \"blob\";\n xhr.send();\n });\n}\n\ninterface State {\n showImageEditor: boolean;\n dataUrl: string | null;\n}\n\ninterface Action {\n type: \"setDataUrl\" | \"hideImageEditor\";\n dataUrl?: string | null;\n}\n\nconst initialState: State = {\n showImageEditor: false,\n dataUrl: null\n};\n\nconst reducer = (state: State, action: Action): State => {\n const next: State = { ...state };\n\n switch (action.type) {\n case \"setDataUrl\":\n next.dataUrl = action.dataUrl as string;\n next.showImageEditor = true;\n break;\n case \"hideImageEditor\":\n next.dataUrl = null;\n next.showImageEditor = false;\n break;\n }\n\n return next;\n};\n\nconst { FileDetails } = FileManagerViewConfig;\n\nexport const EditImage = () => {\n const { file } = useFile();\n const { canEdit } = useFileManagerApi();\n const fileDetails = useFileDetails();\n const { uploadFile } = useFileManagerView();\n const [state, dispatch] = React.useReducer(reducer, initialState);\n const { showSnackbar } = useSnackbar();\n\n if (!file.type.startsWith(\"image/\")) {\n return null;\n }\n\n // Render nothing if the user doesn't have the required permissions for \"edit\".\n if (!canEdit(file)) {\n return null;\n }\n\n return (\n <>\n <FileDetails.Action.Button\n className={\"order-last ml-auto\"}\n label={\"Edit image\"}\n data-testid={\"fm-edit-image-button\"}\n icon={<EditIcon />}\n onAction={async () => {\n const dataUrl = await toDataUrl(file.src);\n dispatch({ type: \"setDataUrl\", dataUrl });\n }}\n />\n <ImageEditorDialog\n data-testid={\"fm-image-editor-dialog\"}\n dialogZIndex={100}\n open={state.showImageEditor}\n src={state.dataUrl as string}\n onClose={() => dispatch({ type: \"hideImageEditor\" })}\n onAccept={async src => {\n const blob = dataURLtoBlob(src);\n blob.name = file.name;\n blob.key = file.key.split(\"/\").pop();\n const newFile = await uploadFile(blob);\n\n if (newFile) {\n showSnackbar(\"A new version of the image has been created!\");\n dispatch({ type: \"hideImageEditor\" });\n fileDetails.setFile(newFile);\n fileDetails.close();\n }\n }}\n />\n </>\n );\n};\n"],"mappings":"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","ignoreList":[]}
|