@secretstache/wordpress-gutenberg 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +4 -0
- package/build/index.js +8 -2
- package/build/index.js.map +1 -1
- package/package.json +5 -3
- package/src/components/ColorPaletteControl.js +24 -0
- package/src/components/DataQueryControls.js +51 -0
- package/src/components/DividersControl.js +74 -0
- package/src/components/IconPicker.js +73 -0
- package/src/components/ImageActions.js +59 -0
- package/src/components/LinkControl.js +30 -0
- package/src/components/MediaPicker.js +179 -0
- package/src/components/MediaTypeControl.js +54 -0
- package/src/components/ResourcesWrapper.js +46 -0
- package/src/components/ResponsiveSpacingControl.js +74 -0
- package/src/components/SortableSelect.js +60 -0
- package/src/components/SpacingControl.js +119 -0
- package/src/components/index.js +12 -0
- package/src/hooks/index.js +11 -0
- package/src/hooks/useAccordionItem.js +51 -0
- package/src/hooks/useAllowedBlocks.js +25 -0
- package/src/hooks/useBlockTabsData.js +90 -0
- package/src/hooks/useChildBlockPosition.js +31 -0
- package/src/hooks/useColorChange.js +12 -0
- package/src/hooks/useDataQuery.js +45 -0
- package/src/hooks/useParentBlock.js +57 -0
- package/src/hooks/usePreviewToggle.js +32 -0
- package/src/hooks/useSlider.js +24 -0
- package/src/hooks/useThemeColors.js +19 -0
- package/src/hooks/useUpdateAttribute.js +4 -0
- package/src/index.js +6 -0
- package/src/styles/_animation-file-renderer.scss +11 -0
- package/src/styles/_editor-base.scss +56 -0
- package/src/styles/_icon-picker.scss +4 -0
- package/src/styles/_image-wrapper.scss +59 -0
- package/src/styles/_link-control.scss +6 -0
- package/src/styles/_media-picker.scss +20 -0
- package/src/styles/_new-child-btn.scss +15 -0
- package/src/styles/_responsive-spacing.scss +30 -0
- package/src/styles/_root-block-appender.scss +40 -0
- package/src/styles/_sortable-select.scss +5 -0
- package/src/styles/styles.scss +12 -0
- package/src/utils/attributes.js +224 -0
- package/src/utils/constants.js +17 -0
- package/src/utils/helpers.js +175 -0
- package/src/utils/index.js +6 -0
- package/src/utils/rootBlock/README.md +71 -0
- package/src/utils/rootBlock/hideRootBlockForInlineInserter.js +13 -0
- package/src/utils/rootBlock/hideRootBlockForOtherBlocks.js +32 -0
- package/src/utils/rootBlock/index.js +4 -0
- package/src/utils/rootBlock/initRootBlockAppender.js +45 -0
- package/src/utils/rootBlock/setRootBlock.js +32 -0
- package/src/utils/waitForContainer/README.md +40 -0
- package/src/utils/waitForContainer/index.js +25 -0
- /package/build/{index.css → styles.css} +0 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@secretstache/wordpress-gutenberg",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.1",
|
4
4
|
"description": "",
|
5
5
|
"author": "Secret Stache",
|
6
6
|
"license": "GPL-2.0-or-later",
|
@@ -14,7 +14,8 @@
|
|
14
14
|
"main": "build/index.js",
|
15
15
|
"module": "build/index.es.js",
|
16
16
|
"files": [
|
17
|
-
"build"
|
17
|
+
"build",
|
18
|
+
"src"
|
18
19
|
],
|
19
20
|
"type": "module",
|
20
21
|
"scripts": {
|
@@ -50,18 +51,19 @@
|
|
50
51
|
"rollup-plugin-postcss": "^4.0.2"
|
51
52
|
},
|
52
53
|
"dependencies": {
|
54
|
+
"classnames": "^2.5.1",
|
53
55
|
"es-toolkit": "^1.12.0",
|
54
56
|
"react-select": "5.7.5",
|
55
57
|
"react-sortable-hoc": "2.0.0",
|
56
58
|
"slugify": "^1.6.6"
|
57
59
|
},
|
58
60
|
"peerDependencies": {
|
59
|
-
"@wordpress/dom-ready": "^4.3.0",
|
60
61
|
"@wordpress/api-fetch": "^6.52.0",
|
61
62
|
"@wordpress/block-editor": "^12.22.0",
|
62
63
|
"@wordpress/blocks": "^12.34.0",
|
63
64
|
"@wordpress/components": "^27.2.0",
|
64
65
|
"@wordpress/data": "^9.24.0",
|
66
|
+
"@wordpress/dom-ready": "^4.3.0",
|
65
67
|
"@wordpress/element": "^5.32.0",
|
66
68
|
"@wordpress/hooks": "^3.57.0",
|
67
69
|
"@wordpress/icons": "^9.45.0",
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { BaseControl, ColorPalette } from '@wordpress/components';
|
2
|
+
import { useThemeColors, useColorChange } from '../hooks';
|
3
|
+
|
4
|
+
export const ColorPaletteControl = ({
|
5
|
+
label = 'Color',
|
6
|
+
value,
|
7
|
+
attributeName,
|
8
|
+
setAttributes,
|
9
|
+
allowedColors,
|
10
|
+
}) => {
|
11
|
+
const colors = useThemeColors(allowedColors);
|
12
|
+
const onColorChange = useColorChange(colors, setAttributes);
|
13
|
+
|
14
|
+
return (
|
15
|
+
<BaseControl label={label}>
|
16
|
+
<ColorPalette
|
17
|
+
colors={colors}
|
18
|
+
value={value}
|
19
|
+
disableCustomColors={true}
|
20
|
+
onChange={(colorValue) => onColorChange(colorValue, attributeName)}
|
21
|
+
/>
|
22
|
+
</BaseControl>
|
23
|
+
);
|
24
|
+
};
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import { RadioControl } from '@wordpress/components';
|
2
|
+
|
3
|
+
// TODO: add support of curated posts, categories; consider merging with the useDataQuery hook
|
4
|
+
export const DataQueryControls = (props) => {
|
5
|
+
const {
|
6
|
+
dataSourceLabel = 'Data Source',
|
7
|
+
dataSource,
|
8
|
+
onDataSourceChange,
|
9
|
+
|
10
|
+
queryTypeLabel = 'Query',
|
11
|
+
queryType,
|
12
|
+
onQueryTypeChange,
|
13
|
+
|
14
|
+
settings,
|
15
|
+
} = props;
|
16
|
+
|
17
|
+
const sourcesList = settings
|
18
|
+
.filter((source) => source?.value && source?.label)
|
19
|
+
.map((source) => ({ label: source.label, value: source.value }));
|
20
|
+
|
21
|
+
const queriesList = settings.find((source) => source.value === dataSource)?.queries || [];
|
22
|
+
|
23
|
+
const hasSources = sourcesList && sourcesList?.length > 0;
|
24
|
+
const hasQueries = queriesList && queriesList?.length > 0;
|
25
|
+
|
26
|
+
return (
|
27
|
+
<>
|
28
|
+
{
|
29
|
+
hasSources && (
|
30
|
+
<RadioControl
|
31
|
+
label={dataSourceLabel}
|
32
|
+
selected={dataSource}
|
33
|
+
options={sourcesList}
|
34
|
+
onChange={onDataSourceChange}
|
35
|
+
/>
|
36
|
+
)
|
37
|
+
}
|
38
|
+
|
39
|
+
{
|
40
|
+
hasQueries && (
|
41
|
+
<RadioControl
|
42
|
+
label={queryTypeLabel}
|
43
|
+
selected={queryType}
|
44
|
+
options={queriesList}
|
45
|
+
onChange={onQueryTypeChange}
|
46
|
+
/>
|
47
|
+
)
|
48
|
+
}
|
49
|
+
</>
|
50
|
+
)
|
51
|
+
}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import { SelectControl, ToggleControl } from '@wordpress/components';
|
2
|
+
import { useEffect, useState } from '@wordpress/element';
|
3
|
+
|
4
|
+
export const DividersControl = ({
|
5
|
+
topDividers = [],
|
6
|
+
bottomDividers = [],
|
7
|
+
value = { topDivider: '', bottomDivider: '', isIncludeLine: false },
|
8
|
+
hasLine = true,
|
9
|
+
onChange,
|
10
|
+
}) => {
|
11
|
+
const hasTop = topDividers && topDividers?.length > 0;
|
12
|
+
const hasBottom = bottomDividers && bottomDividers?.length > 0;
|
13
|
+
|
14
|
+
const [ topDivider, setTopDivider ] = useState(value?.topDivider || '');
|
15
|
+
const [ bottomDivider, setBottomDivider ] = useState(value?.bottomDivider || '');
|
16
|
+
const [ isIncludeLine, setIsIncludeLine ] = useState(value?.isIncludeLine || false);
|
17
|
+
|
18
|
+
useEffect(() => {
|
19
|
+
onChange({
|
20
|
+
topDivider,
|
21
|
+
bottomDivider,
|
22
|
+
isIncludeLine,
|
23
|
+
});
|
24
|
+
}, [ topDivider, bottomDivider, isIncludeLine ]);
|
25
|
+
|
26
|
+
return (
|
27
|
+
<>
|
28
|
+
{
|
29
|
+
hasTop && (
|
30
|
+
<SelectControl
|
31
|
+
label="Top Divider"
|
32
|
+
value={topDivider}
|
33
|
+
onChange={(topDivider) => setTopDivider(topDivider)}
|
34
|
+
options={[
|
35
|
+
{
|
36
|
+
label: 'None',
|
37
|
+
value: ''
|
38
|
+
},
|
39
|
+
...topDividers,
|
40
|
+
]}
|
41
|
+
|
42
|
+
/>
|
43
|
+
)
|
44
|
+
}
|
45
|
+
|
46
|
+
{
|
47
|
+
hasBottom && (
|
48
|
+
<SelectControl
|
49
|
+
label="Bottom Divider"
|
50
|
+
value={bottomDivider}
|
51
|
+
onChange={(bottomDivider) => setBottomDivider(bottomDivider)}
|
52
|
+
options={[
|
53
|
+
{
|
54
|
+
label: 'None',
|
55
|
+
value: ''
|
56
|
+
},
|
57
|
+
...bottomDividers,
|
58
|
+
]}
|
59
|
+
/>
|
60
|
+
)
|
61
|
+
}
|
62
|
+
|
63
|
+
{
|
64
|
+
hasLine && (
|
65
|
+
<ToggleControl
|
66
|
+
label="Include Vertical Line leading from this block to the next"
|
67
|
+
checked={isIncludeLine}
|
68
|
+
onChange={() => setIsIncludeLine((prevState) => !prevState)}
|
69
|
+
/>
|
70
|
+
)
|
71
|
+
}
|
72
|
+
</>
|
73
|
+
);
|
74
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import {
|
2
|
+
MediaPlaceholder,
|
3
|
+
MediaUpload,
|
4
|
+
MediaUploadCheck,
|
5
|
+
} from '@wordpress/block-editor';
|
6
|
+
import { Button, Icon } from '@wordpress/components';
|
7
|
+
import { edit as editIcon, trash as trashIcon } from '@wordpress/icons';
|
8
|
+
|
9
|
+
export const IconPicker = ({ imageId, imageUrl, imageAlt, svgCode, onSelect, onRemove }) => {
|
10
|
+
const hasImage = imageId && imageUrl;
|
11
|
+
const isSvg = hasImage && svgCode;
|
12
|
+
|
13
|
+
return (
|
14
|
+
<MediaUploadCheck>
|
15
|
+
<MediaUpload
|
16
|
+
onSelect={onSelect}
|
17
|
+
allowedTypes={['image']}
|
18
|
+
value={imageId}
|
19
|
+
render={({ open }) => {
|
20
|
+
return hasImage ? (
|
21
|
+
<div className="bc-image-wrapper">
|
22
|
+
{hasImage && (
|
23
|
+
isSvg ? (
|
24
|
+
<div
|
25
|
+
className="svg-container"
|
26
|
+
dangerouslySetInnerHTML={{ __html: svgCode }}
|
27
|
+
/>
|
28
|
+
) : (
|
29
|
+
<img src={imageUrl} alt={imageAlt || 'icon'} />
|
30
|
+
)
|
31
|
+
)}
|
32
|
+
|
33
|
+
<div className="bc-image-wrapper__actions">
|
34
|
+
<Button
|
35
|
+
className="bc-image-wrapper__btn bc-image-wrapper__replace-btn"
|
36
|
+
type="button"
|
37
|
+
onClick={open}
|
38
|
+
>
|
39
|
+
<Icon
|
40
|
+
icon={editIcon}
|
41
|
+
size={20}
|
42
|
+
className="bc-image-wrapper__btn-icon"
|
43
|
+
/>
|
44
|
+
</Button>
|
45
|
+
|
46
|
+
<Button
|
47
|
+
className="bc-image-wrapper__btn bc-image-wrapper__remove-btn"
|
48
|
+
type="button"
|
49
|
+
onClick={onRemove}
|
50
|
+
>
|
51
|
+
<Icon
|
52
|
+
icon={trashIcon}
|
53
|
+
size={20}
|
54
|
+
className="bc-image-wrapper__btn-icon"
|
55
|
+
/>
|
56
|
+
</Button>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
<div className="bc-image-wrapper__overlay" />
|
60
|
+
</div>
|
61
|
+
) : (
|
62
|
+
<MediaPlaceholder
|
63
|
+
icon="format-image"
|
64
|
+
onSelect={onSelect}
|
65
|
+
allowedTypes={['image', 'image/svg+xml']}
|
66
|
+
labels={{ title: 'Icon Image' }}
|
67
|
+
/>
|
68
|
+
);
|
69
|
+
}}
|
70
|
+
/>
|
71
|
+
</MediaUploadCheck>
|
72
|
+
);
|
73
|
+
};
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import { MediaUpload, MediaUploadCheck, MediaPlaceholder } from '@wordpress/block-editor';
|
2
|
+
import { Button } from '@wordpress/components';
|
3
|
+
|
4
|
+
export const ImageActions = ({
|
5
|
+
imageId,
|
6
|
+
imageUrl,
|
7
|
+
imageAlt,
|
8
|
+
placeholder = false,
|
9
|
+
onSelectImage,
|
10
|
+
onRemoveImage,
|
11
|
+
className = '',
|
12
|
+
}) => {
|
13
|
+
const hasImage = imageId && imageUrl;
|
14
|
+
|
15
|
+
return (
|
16
|
+
<MediaUploadCheck>
|
17
|
+
<MediaUpload
|
18
|
+
onSelect={onSelectImage}
|
19
|
+
allowedTypes={['image']}
|
20
|
+
value={imageId}
|
21
|
+
render={({ open }) => {
|
22
|
+
return hasImage ? (
|
23
|
+
<div className={`bc-image-wrapper ${className}`}>
|
24
|
+
<img src={imageUrl} alt={imageAlt} onClick={open} />
|
25
|
+
<div className="bc-image-wrapper__actions">
|
26
|
+
<Button
|
27
|
+
className="bc-image-wrapper__btn bc-image-wrapper__replace-btn"
|
28
|
+
type="button"
|
29
|
+
onClick={open}
|
30
|
+
>
|
31
|
+
Replace
|
32
|
+
</Button>
|
33
|
+
<Button
|
34
|
+
className="bc-image-wrapper__btn bc-image-wrapper__remove-btn"
|
35
|
+
type="button"
|
36
|
+
onClick={onRemoveImage}
|
37
|
+
>
|
38
|
+
Remove
|
39
|
+
</Button>
|
40
|
+
</div>
|
41
|
+
<div className="bc-image-wrapper__overlay" />
|
42
|
+
</div>
|
43
|
+
) : placeholder ? (
|
44
|
+
<MediaPlaceholder
|
45
|
+
className="media-placeholder"
|
46
|
+
icon="format-image"
|
47
|
+
onSelect={onSelectImage}
|
48
|
+
allowedTypes={['image']}
|
49
|
+
labels={{
|
50
|
+
title: 'Image',
|
51
|
+
instructions: 'Upload an image file or pick one from your media library.',
|
52
|
+
}}
|
53
|
+
/>
|
54
|
+
) : null;
|
55
|
+
}}
|
56
|
+
/>
|
57
|
+
</MediaUploadCheck>
|
58
|
+
);
|
59
|
+
};
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { BaseControl, CheckboxControl } from '@wordpress/components';
|
2
|
+
import { URLInput } from '@wordpress/block-editor';
|
3
|
+
import { useUpdateAttribute } from '../hooks';
|
4
|
+
|
5
|
+
export const LinkControl = ({
|
6
|
+
url = { value: '#', attrName: 'linkSource' },
|
7
|
+
isOpenInNewTab = { value: false, attrName: 'linkIsOpenInNewTab'},
|
8
|
+
setAttributes,
|
9
|
+
label = 'Source',
|
10
|
+
}) => {
|
11
|
+
const updateAttribute = useUpdateAttribute(setAttributes);
|
12
|
+
|
13
|
+
return (
|
14
|
+
<>
|
15
|
+
<BaseControl label={label}>
|
16
|
+
<URLInput
|
17
|
+
className="bc-url-input"
|
18
|
+
value={url.value}
|
19
|
+
onChange={(newUrl) => setAttributes({ [url.attrName]: newUrl })}
|
20
|
+
/>
|
21
|
+
</BaseControl>
|
22
|
+
|
23
|
+
<CheckboxControl
|
24
|
+
checked={isOpenInNewTab.value}
|
25
|
+
label="Open in a new tab"
|
26
|
+
onChange={(newIsOpenInNewTab) => setAttributes({ [isOpenInNewTab.attrName]: newIsOpenInNewTab })}
|
27
|
+
/>
|
28
|
+
</>
|
29
|
+
);
|
30
|
+
};
|
@@ -0,0 +1,179 @@
|
|
1
|
+
import { Button, Icon as WPIcon } from '@wordpress/components';
|
2
|
+
import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor';
|
3
|
+
import { page as pageIcon } from '@wordpress/icons';
|
4
|
+
|
5
|
+
import { MEDIA_TYPES } from '../utils/index.js';
|
6
|
+
|
7
|
+
export const BCImageRenderer = ({
|
8
|
+
imageId,
|
9
|
+
imageUrl,
|
10
|
+
onImageClick,
|
11
|
+
onRemoveClick,
|
12
|
+
onSelectClick,
|
13
|
+
}) => {
|
14
|
+
return imageId && imageUrl ? (
|
15
|
+
<>
|
16
|
+
<div className="bc-selected-media-wrapper">
|
17
|
+
<img
|
18
|
+
src={imageUrl}
|
19
|
+
className="bc-selected-media bc-selected-media--image"
|
20
|
+
alt="Selected Image"
|
21
|
+
onClick={onImageClick}
|
22
|
+
/>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<Button
|
26
|
+
className="bc-remove-btn"
|
27
|
+
onClick={onRemoveClick}
|
28
|
+
isSecondary
|
29
|
+
isDestructive
|
30
|
+
>
|
31
|
+
Remove Image
|
32
|
+
</Button>
|
33
|
+
</>
|
34
|
+
) : (
|
35
|
+
<Button
|
36
|
+
variant="secondary"
|
37
|
+
onClick={onSelectClick}
|
38
|
+
className="bc-select-btn"
|
39
|
+
>
|
40
|
+
Select Image
|
41
|
+
</Button>
|
42
|
+
);
|
43
|
+
};
|
44
|
+
|
45
|
+
export const BCVideoRenderer = ({
|
46
|
+
videoId,
|
47
|
+
videoUrl,
|
48
|
+
onRemoveClick,
|
49
|
+
onSelectClick,
|
50
|
+
}) => {
|
51
|
+
return videoId && videoUrl ? (
|
52
|
+
<>
|
53
|
+
<div className="bc-selected-media-wrapper">
|
54
|
+
<video src={videoUrl} className="bc-selected-media bc-selected-media--video" controls />
|
55
|
+
</div>
|
56
|
+
|
57
|
+
<Button
|
58
|
+
className="bc-remove-btn"
|
59
|
+
onClick={onRemoveClick}
|
60
|
+
isSecondary
|
61
|
+
isDestructive
|
62
|
+
>
|
63
|
+
Remove Video
|
64
|
+
</Button>
|
65
|
+
</>
|
66
|
+
) : (
|
67
|
+
<Button
|
68
|
+
variant="secondary"
|
69
|
+
onClick={onSelectClick}
|
70
|
+
className="bc-select-btn"
|
71
|
+
>
|
72
|
+
Select Video
|
73
|
+
</Button>
|
74
|
+
);
|
75
|
+
};
|
76
|
+
|
77
|
+
export const BCAnimationRenderer = ({
|
78
|
+
animationFileId,
|
79
|
+
animationFileUrl,
|
80
|
+
animationFileName,
|
81
|
+
onSelectClick,
|
82
|
+
onRemoveClick,
|
83
|
+
}) => {
|
84
|
+
return animationFileId && animationFileUrl ? (
|
85
|
+
<>
|
86
|
+
<div className="bc-animation-block-json-file" onClick={onSelectClick}>
|
87
|
+
<WPIcon icon={pageIcon} size={36}/>
|
88
|
+
<span>{animationFileName}</span>
|
89
|
+
</div>
|
90
|
+
<Button
|
91
|
+
variant="secondary"
|
92
|
+
isDestructive
|
93
|
+
className="bc-remove-btn"
|
94
|
+
onClick={onRemoveClick}
|
95
|
+
>
|
96
|
+
Remove File
|
97
|
+
</Button>
|
98
|
+
</>
|
99
|
+
) : (
|
100
|
+
<Button variant="secondary" onClick={onSelectClick}>
|
101
|
+
Select File
|
102
|
+
</Button>
|
103
|
+
)
|
104
|
+
};
|
105
|
+
|
106
|
+
// TODO: find better name
|
107
|
+
export const BCMediaPicker = ({
|
108
|
+
mediaId,
|
109
|
+
mediaUrl,
|
110
|
+
mediaFileName = '',
|
111
|
+
onSelect,
|
112
|
+
onRemove,
|
113
|
+
type = MEDIA_TYPES.IMAGE,
|
114
|
+
...other
|
115
|
+
}) => {
|
116
|
+
if (type === MEDIA_TYPES.IMAGE) {
|
117
|
+
return (
|
118
|
+
<MediaUploadCheck>
|
119
|
+
<MediaUpload
|
120
|
+
onSelect={onSelect}
|
121
|
+
allowedTypes={['image', 'image/svg+xml']}
|
122
|
+
accept="image/*"
|
123
|
+
value={mediaId}
|
124
|
+
render={({ open }) => (
|
125
|
+
<BCImageRenderer
|
126
|
+
imageId={mediaId}
|
127
|
+
imageUrl={mediaUrl}
|
128
|
+
onImageClick={open}
|
129
|
+
onSelectClick={open}
|
130
|
+
onRemoveClick={onRemove}
|
131
|
+
/>
|
132
|
+
)}
|
133
|
+
{ ...other }
|
134
|
+
/>
|
135
|
+
</MediaUploadCheck>
|
136
|
+
);
|
137
|
+
} else if (type === MEDIA_TYPES.VIDEO) {
|
138
|
+
return (
|
139
|
+
<MediaUploadCheck>
|
140
|
+
<MediaUpload
|
141
|
+
onSelect={onSelect}
|
142
|
+
allowedTypes={['video']}
|
143
|
+
value={mediaId}
|
144
|
+
render={({ open }) => (
|
145
|
+
<BCVideoRenderer
|
146
|
+
videoId={mediaId}
|
147
|
+
videoUrl={mediaUrl}
|
148
|
+
onSelectClick={open}
|
149
|
+
onRemoveClick={onRemove}
|
150
|
+
/>
|
151
|
+
)}
|
152
|
+
{ ...other }
|
153
|
+
/>
|
154
|
+
</MediaUploadCheck>
|
155
|
+
);
|
156
|
+
} else if (type === MEDIA_TYPES.ANIMATION) {
|
157
|
+
return (
|
158
|
+
<MediaUploadCheck>
|
159
|
+
<MediaUpload
|
160
|
+
onSelect={onSelect}
|
161
|
+
allowedTypes={['application/json', 'text/plain', 'application/lottie']}
|
162
|
+
value={mediaId}
|
163
|
+
render={({ open }) => (
|
164
|
+
<BCAnimationRenderer
|
165
|
+
animationFileId={mediaId}
|
166
|
+
animationFileUrl={mediaUrl}
|
167
|
+
animationFileName={mediaFileName}
|
168
|
+
onSelectClick={open}
|
169
|
+
onRemoveClick={onRemove}
|
170
|
+
/>
|
171
|
+
)}
|
172
|
+
{...other}
|
173
|
+
/>
|
174
|
+
</MediaUploadCheck>
|
175
|
+
);
|
176
|
+
} else {
|
177
|
+
throw new Error('Unrecognized media type.');
|
178
|
+
}
|
179
|
+
};
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import { useState } from '@wordpress/element';
|
2
|
+
import { SelectControl } from '@wordpress/components';
|
3
|
+
|
4
|
+
import { BCMediaPicker } from './MediaPicker.js';
|
5
|
+
import { MEDIA_TYPE_LABELS} from '../utils/index.js';
|
6
|
+
|
7
|
+
export const MediaTypeControl = (props) => {
|
8
|
+
const {
|
9
|
+
mediaTypes = [],
|
10
|
+
mediaId,
|
11
|
+
mediaUrl,
|
12
|
+
mediaFileName = '',
|
13
|
+
mediaOnSelect,
|
14
|
+
mediaOnRemove,
|
15
|
+
} = props;
|
16
|
+
|
17
|
+
const [ selectedMediaType, setSelectedMediaType ] = useState(mediaTypes?.[0]);
|
18
|
+
|
19
|
+
const mediaTypesOptions = mediaTypes
|
20
|
+
?.filter((type) => MEDIA_TYPE_LABELS[type]) // Ensure it's an allowed type
|
21
|
+
?.map((type) => ({
|
22
|
+
label: MEDIA_TYPE_LABELS[type],
|
23
|
+
value: type,
|
24
|
+
}));
|
25
|
+
|
26
|
+
return (
|
27
|
+
<>
|
28
|
+
{
|
29
|
+
// TODO: add custom label
|
30
|
+
mediaTypes && (
|
31
|
+
<SelectControl
|
32
|
+
label="Media Type"
|
33
|
+
value={selectedMediaType}
|
34
|
+
onChange={(mediaType) => setSelectedMediaType(mediaType)}
|
35
|
+
options={mediaTypesOptions}
|
36
|
+
/>
|
37
|
+
)
|
38
|
+
}
|
39
|
+
|
40
|
+
{
|
41
|
+
selectedMediaType && (
|
42
|
+
<BCMediaPicker
|
43
|
+
mediaId={mediaId}
|
44
|
+
mediaUrl={mediaUrl}
|
45
|
+
mediaFileName={mediaFileName}
|
46
|
+
type={selectedMediaType}
|
47
|
+
onSelect={mediaOnSelect}
|
48
|
+
onRemove={mediaOnRemove}
|
49
|
+
/>
|
50
|
+
)
|
51
|
+
}
|
52
|
+
</>
|
53
|
+
);
|
54
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
import { Notice, Placeholder, Spinner } from '@wordpress/components';
|
2
|
+
|
3
|
+
const EmptyNotice = ({
|
4
|
+
message = 'No resources were found matching your criteria. Please try to adjust the query.'
|
5
|
+
}) => (
|
6
|
+
<Notice status="info" isDismissible={false}>
|
7
|
+
<p>{message}</p>
|
8
|
+
</Notice>
|
9
|
+
);
|
10
|
+
|
11
|
+
const LoadingSpinner = () => <Spinner className="bc-spinner" />;
|
12
|
+
|
13
|
+
const PlaceholderContent = ({
|
14
|
+
icon = 'info-outline',
|
15
|
+
instructions = 'Please configure the block in the sidebar.',
|
16
|
+
...restProps
|
17
|
+
}) => (
|
18
|
+
<Placeholder
|
19
|
+
icon={icon}
|
20
|
+
instructions={instructions}
|
21
|
+
{...restProps}
|
22
|
+
/>
|
23
|
+
);
|
24
|
+
|
25
|
+
export const ResourcesWrapper = ({
|
26
|
+
isLoading,
|
27
|
+
isEmpty,
|
28
|
+
isPlaceholder,
|
29
|
+
emptyMessage,
|
30
|
+
placeholderProps = {},
|
31
|
+
children,
|
32
|
+
}) => {
|
33
|
+
if (isLoading) {
|
34
|
+
return <LoadingSpinner />;
|
35
|
+
}
|
36
|
+
|
37
|
+
if (isEmpty) {
|
38
|
+
return <EmptyNotice message={emptyMessage} />;
|
39
|
+
}
|
40
|
+
|
41
|
+
if (isPlaceholder) {
|
42
|
+
return <PlaceholderContent {...placeholderProps} />;
|
43
|
+
}
|
44
|
+
|
45
|
+
return children;
|
46
|
+
};
|