PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.3.2
Block Animations, Motion & Scroll Effects – Ghost Kit v3.3.2
3.7.2 3.7.1 3.7.0 3.6.1 trunk 1.6.3 2.25.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.5.0 3.5.1 3.6.0
ghostkit / gutenberg / extend / frame / shadow / index.js

index.js in Block Animations, Motion & Scroll Effects – Ghost Kit 3.3.2, at gutenberg/extend/frame/shadow/index.js

257 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 __experimentalToolsPanelItem as ExperimentalToolsPanelItem,
3 __stableToolsPanelItem as StableToolsPanelItem,
4 BaseControl,
5 Tooltip,
6 } from '@wordpress/components';
7 import { useEffect, useState } from '@wordpress/element';
8 import { addFilter } from '@wordpress/hooks';
9 import { __ } from '@wordpress/i18n';
10
11 import ColorPicker from '../../../components/color-picker';
12 import ElementStateToggle from '../../../components/element-state-toggle';
13 import InputDrag from '../../../components/input-drag';
14 import InputGroup from '../../../components/input-group';
15 import ResponsiveToggle from '../../../components/responsive-toggle';
16 import useResponsive from '../../../hooks/use-responsive';
17 import useStyles from '../../../hooks/use-styles';
18 import arrayMove from '../../../utils/array-move';
19 import { maybeDecode } from '../../../utils/encode-decode';
20
21 const ToolsPanelItem = StableToolsPanelItem || ExperimentalToolsPanelItem;
22
23 import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
24
25 const hoverSelector = '&:hover';
26
27 /**
28 * Add `px` suffix to number string.
29 *
30 * @param {string} str string.
31 *
32 * @return {string} string with pixels.
33 */
34 function addPixelsToString(str) {
35 // add pixels.
36 if (typeof str === 'string' && str !== '0' && /^[0-9.-]*$/.test(str)) {
37 str += 'px';
38 }
39
40 return str;
41 }
42
43 function parseShadowString(str) {
44 if (str) {
45 let parsedShadow = maybeDecode(str).split(/ (?![^(]*\))/);
46
47 if (parsedShadow && parsedShadow.length === 5) {
48 // Is first item color.
49 if (/^(#|rgb|hsl)/.test(parsedShadow[0])) {
50 parsedShadow = arrayMove(parsedShadow, 0, 5);
51 }
52
53 return parsedShadow;
54 }
55 }
56
57 return false;
58 }
59
60 /**
61 * Component
62 *
63 * @param props
64 */
65 function FrameShadowTools(props) {
66 const [isHover, setIsHover] = useState(false);
67
68 const { getStyle, hasStyle, setStyles, resetStyles } = useStyles(props);
69 const { device, allDevices } = useResponsive();
70
71 const [x, setX] = useState();
72 const [y, setY] = useState();
73 const [blur, setBlur] = useState();
74 const [spread, setSpread] = useState();
75 const [color, setColor] = useState();
76
77 // Prepare current shadow state.
78 useEffect(() => {
79 const parsedShadow = parseShadowString(
80 getStyle('box-shadow', device, isHover && hoverSelector)
81 );
82
83 if (parsedShadow && parsedShadow.length === 5) {
84 setX(parsedShadow[0]);
85 setY(parsedShadow[1]);
86 setBlur(parsedShadow[2]);
87 setSpread(parsedShadow[3]);
88 setColor(parsedShadow[4]);
89 } else {
90 setX(undefined);
91 setY(undefined);
92 setBlur(undefined);
93 setSpread(undefined);
94 setColor(undefined);
95 }
96 // eslint-disable-next-line react-hooks/exhaustive-deps
97 }, [device, isHover]);
98
99 // Update shadow.
100 useEffect(() => {
101 if (
102 typeof x === 'undefined' &&
103 typeof y === 'undefined' &&
104 typeof blur === 'undefined' &&
105 typeof spread === 'undefined' &&
106 typeof color === 'undefined'
107 ) {
108 // Reset.
109 if (getStyle('box-shadow', device, isHover && hoverSelector)) {
110 setStyles(
111 {
112 'box-shadow': undefined,
113 },
114 device,
115 isHover && hoverSelector
116 );
117 }
118
119 return;
120 }
121
122 setStyles(
123 {
124 'box-shadow': `${addPixelsToString(x || 0)} ${addPixelsToString(
125 y || 0
126 )} ${addPixelsToString(blur || 0)} ${addPixelsToString(
127 spread || 0
128 )} ${color || '#000'}`,
129 },
130 device,
131 isHover && hoverSelector
132 );
133 // eslint-disable-next-line react-hooks/exhaustive-deps
134 }, [x, y, blur, spread, color]);
135
136 let hasShadow = false;
137
138 ['', ...Object.keys(allDevices)].forEach((thisDevice) => {
139 hasShadow =
140 hasShadow ||
141 hasStyle('box-shadow', thisDevice) ||
142 hasStyle('box-shadow', thisDevice, hoverSelector);
143 });
144
145 const baseControlLabel = (
146 <>
147 {__('Shadow', 'ghostkit')}
148 <ResponsiveToggle
149 checkActive={(checkMedia) => {
150 return hasStyle(
151 'box-shadow',
152 checkMedia,
153 isHover && hoverSelector
154 );
155 }}
156 />
157 <ElementStateToggle
158 isHover={isHover}
159 onChange={() => {
160 setIsHover(!isHover);
161 }}
162 checkActive={() => {
163 return hasStyle('box-shadow', device, hoverSelector);
164 }}
165 />
166 </>
167 );
168
169 return (
170 <ToolsPanelItem
171 label={__('Shadow', 'ghostkit')}
172 hasValue={() => !!hasShadow}
173 onDeselect={() => {
174 resetStyles(['box-shadow'], true, ['', '&:hover']);
175
176 setX(undefined);
177 setY(undefined);
178 setBlur(undefined);
179 setSpread(undefined);
180 setColor(undefined);
181 }}
182 isShownByDefault={false}
183 >
184 <BaseControl id={baseControlLabel} label={baseControlLabel}>
185 <div className="ghostkit-control-box-shadow">
186 <Tooltip text={__('Color', 'ghostkit')}>
187 <div>
188 <ColorPicker
189 value={color}
190 onChange={(val) => {
191 setColor(val);
192 }}
193 alpha
194 />
195 </div>
196 </Tooltip>
197 <InputGroup>
198 <InputDrag
199 help={__('X', 'ghostkit')}
200 value={x}
201 onChange={(val) => {
202 setX(val || 0);
203 }}
204 autoComplete="off"
205 />
206 <InputDrag
207 help={__('Y', 'ghostkit')}
208 value={y}
209 onChange={(val) => {
210 setY(val || 0);
211 }}
212 autoComplete="off"
213 />
214 <InputDrag
215 help={__('Blur', 'ghostkit')}
216 value={blur}
217 onChange={(val) => {
218 setBlur(val || 0);
219 }}
220 autoComplete="off"
221 />
222 <InputDrag
223 help={__('Spread', 'ghostkit')}
224 value={spread}
225 onChange={(val) => {
226 setSpread(val || 0);
227 }}
228 autoComplete="off"
229 />
230 </InputGroup>
231 </div>
232 </BaseControl>
233 </ToolsPanelItem>
234 );
235 }
236
237 addFilter(
238 'ghostkit.extension.frame.tools',
239 'ghostkit/extension/frame/tools/shadow',
240 (children, { props }) => {
241 const hasShadowSupport =
242 hasBlockSupport(props.name, ['ghostkit', 'frame', 'shadow']) ||
243 getBlockSupport(props.name, ['ghostkit', 'frame']) === true;
244
245 if (!hasShadowSupport) {
246 return children;
247 }
248
249 return (
250 <>
251 {children}
252 <FrameShadowTools {...props} />
253 </>
254 );
255 }
256 );
257