@plone-collective/volto-image-editor 1.0.1 → 1.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/.changelog.draft +3 -6
- package/CHANGELOG.md +14 -0
- package/news/.changelog_template.jinja +15 -0
- package/package.json +13 -8
- package/src/components/ImageEditor/Editor/ImageEditor.scss +18 -2
- package/src/components/ImageEditor/Editor/ImageEditor.tsx +14 -2
- package/src/components/ImageEditor/Wrapper/ImageEditorWrapper.scss +6 -4
- package/src/components/ImageEditor/Wrapper/ImageEditorWrapper.tsx +1 -1
- package/src/components/ImageEditor/components/Navigation/Navigation.scss +1 -0
- package/src/components/ImageEditor/components/SettingsModal/SettingsModal.scss +8 -5
- package/src/components/ImageEditor/components/SettingsModal/SettingsModal.tsx +7 -1
- package/src/components/Widgets/FileWidget.tsx +2 -5
- package/src/icons/svg/back.svg +3 -0
- package/src/theme/variables.scss +1 -1
- package/towncrier.toml +7 -2
- package/vitest.config.mjs +13 -0
package/.changelog.draft
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
## 1.0
|
|
1
|
+
## 1.2.0 (2026-10-12)
|
|
2
2
|
|
|
3
|
-
### Feature
|
|
4
|
-
|
|
5
|
-
- Added support for lazyload the widget. @sneridagh
|
|
6
3
|
|
|
7
4
|
### Internal
|
|
8
5
|
|
|
9
|
-
- Fixed
|
|
10
|
-
-
|
|
6
|
+
- Fixed the image being displaced on first edit. @TimoBroeskamp [#27](https://github.com/collective/volto-image-editor/issues/27)
|
|
7
|
+
- Updated the add-on boilerplate to the latest cookieplone-templates frontend add-on template: Volto 19.5.0, pnpm 10, Vitest for unit tests, and updated GitHub workflows. @ericof [#29](https://github.com/collective/volto-image-editor/issues/29)
|
|
11
8
|
|
|
12
9
|
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,20 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 1.2.0 (2026-10-12)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Internal
|
|
15
|
+
|
|
16
|
+
- Fixed the image being displaced on first edit. @TimoBroeskamp [#27](https://github.com/collective/volto-image-editor/issues/27)
|
|
17
|
+
- Updated the add-on boilerplate to the latest cookieplone-templates frontend add-on template: Volto 19.5.0, pnpm 10, Vitest for unit tests, and updated GitHub workflows. @ericof [#29](https://github.com/collective/volto-image-editor/issues/29)
|
|
18
|
+
|
|
19
|
+
## 1.1.0 (2026-10-07)
|
|
20
|
+
|
|
21
|
+
### Internal
|
|
22
|
+
|
|
23
|
+
- Updated according to the figma-design and improved styles for usage with the distributions @TimoBroeskamp
|
|
24
|
+
|
|
11
25
|
## 1.0.1 (2026-03-03)
|
|
12
26
|
|
|
13
27
|
### Feature
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{% if sections[""] %}
|
|
2
|
+
{% for category, val in definitions.items() if category in sections[""] %}
|
|
3
|
+
|
|
4
|
+
### {{ definitions[category]['name'] }}
|
|
5
|
+
|
|
6
|
+
{% for text, values in sections[""][category].items() %}
|
|
7
|
+
- {{ text }} {{ values|join(', ') }}
|
|
8
|
+
{% endfor %}
|
|
9
|
+
|
|
10
|
+
{% endfor %}
|
|
11
|
+
{% else %}
|
|
12
|
+
No significant changes.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
{% endif %}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plone-collective/volto-image-editor",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "An image editor to be used with Plone and Volto.",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"url": "https://github.com/sponsors/plone"
|
|
25
25
|
},
|
|
26
26
|
"bugs": {
|
|
27
|
-
"url": "https://github.com/collective/volto-image-
|
|
27
|
+
"url": "https://github.com/collective/volto-image-editor/issues"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
@@ -33,21 +33,26 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"context-filter-polyfill": "0.3.23",
|
|
35
35
|
"react-advanced-cropper": "0.20.1",
|
|
36
|
-
"@plone/components": "4.
|
|
36
|
+
"@plone/components": "4.2.2"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"advanced-cropper": "~0.17.1",
|
|
40
40
|
"classnames": "*",
|
|
41
|
-
"react": "18.2.0",
|
|
41
|
+
"react": "^18.2.0",
|
|
42
42
|
"react-aria-components": "*",
|
|
43
|
-
"react-dom": "18.2.0"
|
|
44
|
-
"@plone/types": "2.0.0-alpha.14",
|
|
45
|
-
"@plone/registry": "3.0.0-alpha.9"
|
|
43
|
+
"react-dom": "^18.2.0"
|
|
46
44
|
},
|
|
47
45
|
"devDependencies": {
|
|
46
|
+
"@testing-library/react": "^16.2.0",
|
|
48
47
|
"@types/node": "^20.2.5",
|
|
48
|
+
"@types/react": "^18.3.1",
|
|
49
|
+
"@types/react-dom": "^18.3.1",
|
|
49
50
|
"release-it": "^19.0.5",
|
|
50
|
-
"
|
|
51
|
+
"typescript": "^5.7.3",
|
|
52
|
+
"vitest": "^3.1.2",
|
|
53
|
+
"@plone/scripts": "4.0.2",
|
|
54
|
+
"@plone/registry": "3.0.3",
|
|
55
|
+
"@plone/types": "2.1.0"
|
|
51
56
|
},
|
|
52
57
|
"scripts": {
|
|
53
58
|
"i18n": "rm -rf build/messages && NODE_ENV=production i18n --addon",
|
|
@@ -1,10 +1,26 @@
|
|
|
1
|
-
@import '~react-advanced-cropper/dist/style.css';
|
|
2
1
|
@import '../../../theme/variables';
|
|
3
2
|
@import '../../../theme/constants';
|
|
4
3
|
|
|
4
|
+
.image-widget .image-widget-cropper {
|
|
5
|
+
button {
|
|
6
|
+
padding: 20px 0px;
|
|
7
|
+
border: none;
|
|
8
|
+
color: rgba(0, 0, 0, 0.9);
|
|
9
|
+
text-decoration: underline;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ui.grid.image-widget-grid .file-widget-dropzone img {
|
|
14
|
+
margin-top: 0px;
|
|
15
|
+
}
|
|
16
|
+
|
|
5
17
|
.image-editor {
|
|
18
|
+
display: grid;
|
|
6
19
|
width: 100%;
|
|
20
|
+
height: 100%;
|
|
7
21
|
color: $settings-header-color;
|
|
22
|
+
grid-template-columns: 100%;
|
|
23
|
+
grid-template-rows: 1fr 80px;
|
|
8
24
|
|
|
9
25
|
&__preview {
|
|
10
26
|
position: absolute;
|
|
@@ -19,7 +35,7 @@
|
|
|
19
35
|
|
|
20
36
|
&__cropper {
|
|
21
37
|
position: relative;
|
|
22
|
-
height:
|
|
38
|
+
height: 100%;
|
|
23
39
|
max-height: 100vh;
|
|
24
40
|
background: $color-gray-dark;
|
|
25
41
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useRef, useLayoutEffect } from 'react';
|
|
1
|
+
import React, { useState, useRef, useLayoutEffect, useEffect } from 'react';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import {
|
|
4
4
|
Cropper,
|
|
@@ -16,6 +16,9 @@ import { AdjustableCropperBackground } from '@plone-collective/volto-image-edito
|
|
|
16
16
|
import { SettingsModal } from '@plone-collective/volto-image-editor/components/ImageEditor/components/SettingsModal/SettingsModal';
|
|
17
17
|
import type { ImageSettings } from '@plone-collective/volto-image-editor/types/ImageSettings';
|
|
18
18
|
import { ResetIcon } from '@plone-collective/volto-image-editor/icons/ResetIcon';
|
|
19
|
+
// Plain CSS must not go through the SCSS loader chain: resolve-url-loader 5
|
|
20
|
+
// (Volto 19.5) fails the CI build when an upstream loader gives no source map.
|
|
21
|
+
import 'react-advanced-cropper/dist/style.css';
|
|
19
22
|
import './ImageEditor.scss';
|
|
20
23
|
|
|
21
24
|
if (typeof window !== 'undefined') {
|
|
@@ -24,6 +27,7 @@ if (typeof window !== 'undefined') {
|
|
|
24
27
|
|
|
25
28
|
const ImageEditor = ({ src, onImageSave, onCancel }) => {
|
|
26
29
|
const cropperRef = useRef<CropperRef>(null);
|
|
30
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
27
31
|
const previewRef = useRef<CropperPreviewRef>(null);
|
|
28
32
|
|
|
29
33
|
const [mode, setMode] = useState('crop');
|
|
@@ -105,6 +109,14 @@ const ImageEditor = ({ src, onImageSave, onCancel }) => {
|
|
|
105
109
|
return () => clearTimeout(timer);
|
|
106
110
|
}, [src]);
|
|
107
111
|
|
|
112
|
+
useEffect(() => {
|
|
113
|
+
const el = containerRef.current;
|
|
114
|
+
if (!el) return;
|
|
115
|
+
const ro = new ResizeObserver(() => cropperRef.current?.refresh());
|
|
116
|
+
ro.observe(el);
|
|
117
|
+
return () => ro.disconnect();
|
|
118
|
+
}, []);
|
|
119
|
+
|
|
108
120
|
const onSave = () => {
|
|
109
121
|
if (cropperRef.current) {
|
|
110
122
|
const canvas = cropperRef.current.getCanvas();
|
|
@@ -213,7 +225,7 @@ const ImageEditor = ({ src, onImageSave, onCancel }) => {
|
|
|
213
225
|
|
|
214
226
|
return (
|
|
215
227
|
<div className={'image-editor'}>
|
|
216
|
-
<div className="image-editor__cropper">
|
|
228
|
+
<div ref={containerRef} className="image-editor__cropper">
|
|
217
229
|
<Cropper
|
|
218
230
|
src={src}
|
|
219
231
|
ref={cropperRef}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
@import '../../../theme/variables';
|
|
2
2
|
|
|
3
3
|
.react-aria-ModalOverlay {
|
|
4
|
+
z-index: 150;
|
|
4
5
|
.react-aria-Modal.image-cropper-modal {
|
|
5
|
-
width:
|
|
6
|
-
max-width:
|
|
6
|
+
width: 70vw;
|
|
7
|
+
max-width: unset;
|
|
8
|
+
height: 70vh;
|
|
7
9
|
border: 0;
|
|
8
10
|
background-color: $settings-header-bg;
|
|
9
11
|
|
|
10
12
|
.react-aria-Dialog {
|
|
11
|
-
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
12
15
|
align-items: center;
|
|
13
|
-
justify-content: center;
|
|
14
16
|
padding: 0;
|
|
15
17
|
}
|
|
16
18
|
}
|
|
@@ -83,7 +83,7 @@ const ImageEditorWrapper: React.FC<ImageEditorWrapperProps> = ({
|
|
|
83
83
|
<div className={`image-widget ${className || ''}`}>
|
|
84
84
|
<div className="image-widget-cropper">
|
|
85
85
|
<DialogTrigger>
|
|
86
|
-
<Button onPress={() => setOpen(true)}>
|
|
86
|
+
<Button download={false} onPress={() => setOpen(true)}>
|
|
87
87
|
{buttonText || (
|
|
88
88
|
<FormattedMessage id="Edit image" defaultMessage="Edit image" />
|
|
89
89
|
)}
|
|
@@ -33,14 +33,16 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
&__content {
|
|
36
|
-
display:
|
|
36
|
+
display: grid;
|
|
37
37
|
overflow: hidden;
|
|
38
38
|
width: 100%;
|
|
39
|
+
height: 100%;
|
|
39
40
|
max-height: 100%;
|
|
40
|
-
flex-direction: column;
|
|
41
41
|
animation: scaleIn $image-editor-transition-fast ease-out;
|
|
42
42
|
background: $settings-body-bg;
|
|
43
|
-
box-shadow: 0
|
|
43
|
+
box-shadow: 0 0px 60px rgba(0, 0, 0, 0.5);
|
|
44
|
+
grid-template-columns: 100%;
|
|
45
|
+
grid-template-rows: 80px 1fr;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
&__header {
|
|
@@ -60,7 +62,9 @@
|
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
&__close {
|
|
63
|
-
|
|
65
|
+
display: grid;
|
|
66
|
+
align-self: center;
|
|
67
|
+
padding: $image-editor-spacing-sm;
|
|
64
68
|
border: none;
|
|
65
69
|
border-radius: $image-editor-border-radius-sm;
|
|
66
70
|
background: transparent;
|
|
@@ -86,7 +90,6 @@
|
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
&__label {
|
|
89
|
-
display: block;
|
|
90
93
|
margin-bottom: $image-editor-spacing-sm;
|
|
91
94
|
color: $settings-body-color;
|
|
92
95
|
font-size: 14px;
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
RectangleStencilIcon,
|
|
33
33
|
CircleStencilIcon,
|
|
34
34
|
} from '@plone-collective/volto-image-editor/icons/StencilIcons';
|
|
35
|
+
import BackSVG from '@plone/volto/icons/back.svg';
|
|
35
36
|
import './SettingsModal.scss';
|
|
36
37
|
|
|
37
38
|
const messages = defineMessages({
|
|
@@ -205,7 +206,12 @@ export const SettingsModal: FC<Props> = ({
|
|
|
205
206
|
className="image-editor-settings-modal__close"
|
|
206
207
|
onClick={onToggle}
|
|
207
208
|
>
|
|
208
|
-
|
|
209
|
+
<Icon size="base">
|
|
210
|
+
<svg
|
|
211
|
+
{...BackSVG.attributes}
|
|
212
|
+
dangerouslySetInnerHTML={{ __html: BackSVG.content }}
|
|
213
|
+
/>
|
|
214
|
+
</Icon>
|
|
209
215
|
</Button>
|
|
210
216
|
</div>
|
|
211
217
|
|
|
@@ -150,6 +150,8 @@ const FileWidget = (props) => {
|
|
|
150
150
|
<Grid className="image-widget-grid">
|
|
151
151
|
<Grid.Row stretched>
|
|
152
152
|
<Grid.Column stretched width={mainColumnWidth}>
|
|
153
|
+
{isImage && <ImageEditorWrapper value={value} setData={setData} />}
|
|
154
|
+
|
|
153
155
|
<Dropzone
|
|
154
156
|
onDrop={onDrop}
|
|
155
157
|
{...(props.size ? { maxSize: props.size } : {})}
|
|
@@ -225,11 +227,6 @@ const FileWidget = (props) => {
|
|
|
225
227
|
)}
|
|
226
228
|
</div>
|
|
227
229
|
</Grid.Column>
|
|
228
|
-
{isImage && (
|
|
229
|
-
<Grid.Column stretched width="2" className={'image-editor-cta'}>
|
|
230
|
-
<ImageEditorWrapper value={value} setData={setData} />
|
|
231
|
-
</Grid.Column>
|
|
232
|
-
)}
|
|
233
230
|
</Grid.Row>
|
|
234
231
|
</Grid>
|
|
235
232
|
</FormFieldWrapper>
|
package/src/theme/variables.scss
CHANGED
|
@@ -15,7 +15,7 @@ $nav-button-color-hover: $color-black !default;
|
|
|
15
15
|
$nav-button-bg-active: $color-black !default;
|
|
16
16
|
$nav-button-color-active: $color-white !default;
|
|
17
17
|
|
|
18
|
-
$nav-button-close-color: $color-
|
|
18
|
+
$nav-button-close-color: $color-gray-dark !default;
|
|
19
19
|
|
|
20
20
|
$editor-button-bg: $color-gray-dark !default;
|
|
21
21
|
$editor-button-color: $color-white !default;
|
package/towncrier.toml
CHANGED
|
@@ -3,9 +3,9 @@ filename = "CHANGELOG.md"
|
|
|
3
3
|
directory = "news/"
|
|
4
4
|
title_format = "## {version} ({project_date})"
|
|
5
5
|
underlines = ["", "", ""]
|
|
6
|
-
template = "./
|
|
6
|
+
template = "./news/.changelog_template.jinja"
|
|
7
7
|
start_string = "<!-- towncrier release notes start -->\n"
|
|
8
|
-
issue_format = "[#{issue}](https://github.com/collective/volto-image-editor/
|
|
8
|
+
issue_format = "[#{issue}](https://github.com/collective/volto-image-editor/issues/{issue})"
|
|
9
9
|
|
|
10
10
|
[[tool.towncrier.type]]
|
|
11
11
|
directory = "breaking"
|
|
@@ -31,3 +31,8 @@ showcontent = true
|
|
|
31
31
|
directory = "documentation"
|
|
32
32
|
name = "Documentation"
|
|
33
33
|
showcontent = true
|
|
34
|
+
|
|
35
|
+
[[tool.towncrier.type]]
|
|
36
|
+
directory = "tests"
|
|
37
|
+
name = "Tests"
|
|
38
|
+
showcontent = true
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import voltoVitestConfig from '@plone/volto/vitest.config.mjs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
...voltoVitestConfig,
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: {
|
|
9
|
+
'@plone/volto': path.resolve(__dirname, '../../core/packages/volto/src'), // Add paths accordingly
|
|
10
|
+
// 'promise-file-reader': require.resolve('promise-file-reader') // Add to identify dependency from package
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
});
|