base-js-sw 1.0.8 → 1.0.10
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/components/ImagePicker.js +28 -19
- package/components/LinkPicker.js +93 -23
- package/package.json +1 -1
|
@@ -91,6 +91,7 @@ export const ImagePicker = ({
|
|
|
91
91
|
setAttributes={setAttributes}
|
|
92
92
|
imageRef={imageRef}
|
|
93
93
|
buttonText={buttonText}
|
|
94
|
+
crop={showCrop ? undefined : false}
|
|
94
95
|
/>
|
|
95
96
|
)}
|
|
96
97
|
</div>
|
|
@@ -144,9 +145,13 @@ export const ImagePickerPreview = ({
|
|
|
144
145
|
imageElementWrapperClass = blockClass + '__image-wrapper';
|
|
145
146
|
}
|
|
146
147
|
|
|
147
|
-
let imagecrop
|
|
148
|
-
if (
|
|
149
|
-
imagecrop =
|
|
148
|
+
let imagecrop;
|
|
149
|
+
if (crop === false) {
|
|
150
|
+
imagecrop = '0';
|
|
151
|
+
} else if (typeof imageObject.crop === 'string' && imageObject.crop !== '') {
|
|
152
|
+
imagecrop = imageObject.crop === '0' ? '0' : imageObject.crop.replace(/\s+/g, '-');
|
|
153
|
+
} else {
|
|
154
|
+
imagecrop = '1';
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
let imageOptionsString = `images/width=${width},height=${height},crop=${imagecrop}`;
|
|
@@ -198,6 +203,7 @@ export const ImagePickerPreview = ({
|
|
|
198
203
|
replaceText=''
|
|
199
204
|
removeText=''
|
|
200
205
|
imageId={imageObject.id}
|
|
206
|
+
crop={crop}
|
|
201
207
|
/>
|
|
202
208
|
</MediaUploadCheck>
|
|
203
209
|
) : ( // No image
|
|
@@ -206,6 +212,7 @@ export const ImagePickerPreview = ({
|
|
|
206
212
|
setAttributes={setAttributes}
|
|
207
213
|
imageRef={imageRef}
|
|
208
214
|
buttonText={buttonText}
|
|
215
|
+
crop={crop}
|
|
209
216
|
/>
|
|
210
217
|
)}
|
|
211
218
|
</div>
|
|
@@ -213,11 +220,11 @@ export const ImagePickerPreview = ({
|
|
|
213
220
|
};
|
|
214
221
|
|
|
215
222
|
// ============= Image Controls (appear over image within editor)
|
|
216
|
-
export const EditImageButtons = ({ componentClass, setAttributes, replaceText, removeText, imageRef, imageId }) => {
|
|
223
|
+
export const EditImageButtons = ({ componentClass, setAttributes, replaceText, removeText, imageRef, imageId, crop }) => {
|
|
217
224
|
return (
|
|
218
225
|
<MediaUpload
|
|
219
226
|
title={'Icon'}
|
|
220
|
-
onSelect={(media) => updateImageAttr(setAttributes, media, imageRef)}
|
|
227
|
+
onSelect={(media) => updateImageAttr(setAttributes, media, imageRef, crop)}
|
|
221
228
|
allowedTypes={['image']}
|
|
222
229
|
value={imageId}
|
|
223
230
|
render={({ open }) => (
|
|
@@ -236,7 +243,7 @@ export const EditImageButtons = ({ componentClass, setAttributes, replaceText, r
|
|
|
236
243
|
className={componentClass + "__edit-button"}
|
|
237
244
|
isDestructive
|
|
238
245
|
onClick={(media) => {
|
|
239
|
-
updateImageAttr(setAttributes, false, imageRef)
|
|
246
|
+
updateImageAttr(setAttributes, false, imageRef, crop)
|
|
240
247
|
}}
|
|
241
248
|
icon="remove"
|
|
242
249
|
>
|
|
@@ -248,10 +255,7 @@ export const EditImageButtons = ({ componentClass, setAttributes, replaceText, r
|
|
|
248
255
|
)
|
|
249
256
|
}
|
|
250
257
|
|
|
251
|
-
export const UploadImageButton = ({ componentClass, setAttributes, imageRef, buttonText }) => {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
258
|
+
export const UploadImageButton = ({ componentClass, setAttributes, imageRef, buttonText, crop }) => {
|
|
255
259
|
return (
|
|
256
260
|
<MediaUploadCheck>
|
|
257
261
|
<MediaUpload
|
|
@@ -287,20 +291,25 @@ const updateImageAttr = (
|
|
|
287
291
|
setAttributes,
|
|
288
292
|
media = false,
|
|
289
293
|
imageRef,
|
|
294
|
+
crop = 'center center'
|
|
290
295
|
) => {
|
|
291
|
-
|
|
292
296
|
imageRef ??= 'imageObject';
|
|
293
297
|
|
|
294
|
-
let newImageUrl = media ? media.sizes
|
|
298
|
+
let newImageUrl = media ? (media.sizes?.full?.url || media.url) : '';
|
|
295
299
|
|
|
300
|
+
let newImage = {
|
|
301
|
+
id: media ? media.id : 0,
|
|
302
|
+
url: newImageUrl,
|
|
303
|
+
alt: media ? media.alt : '',
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
if (crop === false) {
|
|
307
|
+
newImage.crop = '0';
|
|
308
|
+
} else {
|
|
309
|
+
newImage.crop = typeof crop === 'string' ? crop : 'center center';
|
|
310
|
+
}
|
|
296
311
|
|
|
297
312
|
setAttributes({
|
|
298
|
-
[imageRef]:
|
|
299
|
-
id: media.id,
|
|
300
|
-
url: newImageUrl,
|
|
301
|
-
alt: media.alt,
|
|
302
|
-
crop: 'center center'
|
|
303
|
-
},
|
|
313
|
+
[imageRef]: newImage,
|
|
304
314
|
});
|
|
305
315
|
};
|
|
306
|
-
|
package/components/LinkPicker.js
CHANGED
|
@@ -1,7 +1,51 @@
|
|
|
1
1
|
import { __experimentalLinkControl as LinkControl } from '@wordpress/blockEditor';
|
|
2
|
+
import { Icon, Tooltip } from '@wordpress/components';
|
|
3
|
+
import { external, update } from '@wordpress/icons';
|
|
2
4
|
import { safeDecodeURI } from '@wordpress/url';
|
|
3
5
|
import { useState, useEffect } from 'react';
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
const linkPickerStyles = `
|
|
8
|
+
.base-js-link-picker {
|
|
9
|
+
width: 100%;
|
|
10
|
+
max-width: 100%;
|
|
11
|
+
min-width: 0;
|
|
12
|
+
overflow-x: hidden;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.base-js-link-picker .block-editor-link-control {
|
|
16
|
+
width: 100%;
|
|
17
|
+
max-width: 100% !important;
|
|
18
|
+
min-width: 0 !important;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.base-js-link-picker .block-editor-link-control__search-input {
|
|
22
|
+
margin: 0 !important;
|
|
23
|
+
min-width: 0 !important;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.base-js-link-picker .components-input-control__container {
|
|
27
|
+
width: 90% !important;
|
|
28
|
+
max-width: 100%;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.base-js-link-picker__status {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
gap: 8px;
|
|
35
|
+
margin-top: 12px;
|
|
36
|
+
color: #757575;
|
|
37
|
+
cursor: help;
|
|
38
|
+
font-size: 13px;
|
|
39
|
+
line-height: 1.4;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.base-js-link-picker__status svg {
|
|
43
|
+
flex: 0 0 auto;
|
|
44
|
+
color: inherit;
|
|
45
|
+
fill: currentColor;
|
|
46
|
+
stroke: currentColor;
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
5
49
|
|
|
6
50
|
export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
7
51
|
// Get the current link object based on linkRef or fallback to an empty object
|
|
@@ -13,6 +57,12 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
13
57
|
const [localUrl, setLocalUrl] = useState(url || '');
|
|
14
58
|
const [localId, setLocalId] = useState(id || '');
|
|
15
59
|
const [localLinkTarget, setLocalLinkTarget] = useState(opensInNewTab);
|
|
60
|
+
const isInternalPost = Boolean(localId);
|
|
61
|
+
const hasLinkData = Boolean(localUrl || localId);
|
|
62
|
+
const statusLabel = isInternalPost ? 'Dynamic WordPress link' : 'External link';
|
|
63
|
+
const statusTooltip = isInternalPost
|
|
64
|
+
? 'This is a dynamic link to a page within the website. If the page’s URL changes it will update automatically'
|
|
65
|
+
: 'This is a static link and does not auto-update.';
|
|
16
66
|
|
|
17
67
|
// Effect to update attributes when the local state changes
|
|
18
68
|
useEffect(() => {
|
|
@@ -26,40 +76,60 @@ export const LinkPicker = ({ setAttributes, at, linkRef = 'link' }) => {
|
|
|
26
76
|
}, [localUrl, localId, localLinkTarget]); // Trigger whenever the URL, ID, or target changes
|
|
27
77
|
|
|
28
78
|
const handleLinkChange = (updatedValue) => {
|
|
29
|
-
|
|
30
|
-
const
|
|
79
|
+
const { url, opensInNewTab, id } = updatedValue;
|
|
80
|
+
const nextUrl = url || '';
|
|
81
|
+
const isPostSelection = Boolean(id);
|
|
31
82
|
|
|
32
83
|
// Update ID or URL depending on whether it's an internal post or an external link/anchor
|
|
33
|
-
if (
|
|
84
|
+
if (isPostSelection) {
|
|
34
85
|
// Internal post, use ID
|
|
35
86
|
setLocalId(id);
|
|
36
|
-
setLocalUrl(
|
|
87
|
+
setLocalUrl(nextUrl);
|
|
37
88
|
} else {
|
|
38
89
|
// External or anchor link, use URL
|
|
39
|
-
setLocalUrl(
|
|
90
|
+
setLocalUrl(nextUrl);
|
|
40
91
|
setLocalId(''); // Clear the ID since we are using the URL
|
|
41
92
|
}
|
|
42
93
|
|
|
43
94
|
// Update the new tab option
|
|
44
|
-
setLocalLinkTarget(opensInNewTab);
|
|
95
|
+
setLocalLinkTarget(Boolean(opensInNewTab));
|
|
45
96
|
};
|
|
46
97
|
|
|
47
98
|
return (
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
99
|
+
<div className="base-js-link-picker">
|
|
100
|
+
<style>{linkPickerStyles}</style>
|
|
101
|
+
<div className="base-js-link-picker__control">
|
|
102
|
+
<LinkControl
|
|
103
|
+
value={{ url: localUrl, opensInNewTab: localLinkTarget, id: localId }}
|
|
104
|
+
onChange={(updatedValue) => {
|
|
105
|
+
handleLinkChange(updatedValue);
|
|
106
|
+
}}
|
|
107
|
+
onBlur={() => {
|
|
108
|
+
// Save on blur to ensure the value is saved when clicking away
|
|
109
|
+
setAttributes({
|
|
110
|
+
[linkRef]: {
|
|
111
|
+
url: localId ? '' : localUrl ? encodeURI(safeDecodeURI(localUrl)) : '',
|
|
112
|
+
linkTarget: localLinkTarget ? '_blank' : undefined,
|
|
113
|
+
id: localId ? localId : undefined,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
}}
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
{hasLinkData && (
|
|
120
|
+
<div className="base-js-link-picker__status-wrapper">
|
|
121
|
+
<Tooltip text={statusTooltip}>
|
|
122
|
+
<div
|
|
123
|
+
className="base-js-link-picker__status"
|
|
124
|
+
tabIndex={0}
|
|
125
|
+
aria-label={statusTooltip}
|
|
126
|
+
>
|
|
127
|
+
<Icon icon={isInternalPost ? update : external} size={18} />
|
|
128
|
+
<span>{statusLabel}</span>
|
|
129
|
+
</div>
|
|
130
|
+
</Tooltip>
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
64
134
|
);
|
|
65
135
|
};
|