PluginProbe
Block Animations, Motion & Scroll Effects – Ghost Kit / 3.4.1
Block Animations, Motion & Scroll Effects – Ghost Kit v3.4.1
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 / blocks / countdown / edit.js

edit.js in Block Animations, Motion & Scroll Effects – Ghost Kit 3.4.1, at gutenberg/blocks/countdown/edit.js

323 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import classnames from 'classnames/dedupe';
2
3 import ColorPicker from '../../components/color-picker';
4 import DateTimePicker from '../../components/date-time-picker';
5 import RangeControl from '../../components/range-control';
6 import countDownApi from './api';
7 import { TIMEZONELESS_FORMAT } from './constants';
8
9 const { GHOSTKIT, luxon } = window;
10
11 import {
12 BlockControls,
13 InspectorControls,
14 useBlockProps,
15 useInnerBlocksProps,
16 } from '@wordpress/block-editor';
17 import {
18 PanelBody,
19 SelectControl,
20 ToolbarButton,
21 ToolbarGroup,
22 } from '@wordpress/components';
23 import { useSelect } from '@wordpress/data';
24 import { useEffect, useRef, useState } from '@wordpress/element';
25 import { applyFilters } from '@wordpress/hooks';
26 import { __ } from '@wordpress/i18n';
27
28 /**
29 * Block Edit function.
30 *
31 * @param props
32 */
33 export default function BlockEdit(props) {
34 const { attributes, setAttributes, clientId } = props;
35 const {
36 date,
37 units,
38 unitsAlign,
39 numberFontSize,
40 labelFontSize,
41 numberColor,
42 labelColor,
43 } = attributes;
44
45 let { className = '' } = props;
46
47 function parseData(newDate, newUnits) {
48 const formattedDate =
49 luxon.DateTime.fromISO(newDate).toFormat(TIMEZONELESS_FORMAT);
50 const currentDate = new Date(
51 luxon.DateTime.now()
52 .setZone(GHOSTKIT.timezone)
53 .toFormat(TIMEZONELESS_FORMAT)
54 );
55
56 const apiData = countDownApi(
57 new Date(formattedDate),
58 currentDate,
59 newUnits,
60 0
61 );
62
63 return {
64 formattedDate,
65 delay: countDownApi.getDelay(newUnits),
66 ...apiData,
67 };
68 }
69
70 const [dateData, setDateData] = useState(
71 date ? parseData(date, units) : false
72 );
73 const interval = useRef(false);
74
75 const { isSelectedBlockInRoot } = useSelect(
76 (select) => {
77 const { isBlockSelected, hasSelectedInnerBlock } =
78 select('core/block-editor');
79
80 return {
81 isSelectedBlockInRoot:
82 isBlockSelected(clientId) ||
83 hasSelectedInnerBlock(clientId, true),
84 };
85 },
86 [clientId]
87 );
88
89 function updateDate(newDate, newUnits) {
90 const data = parseData(newDate, newUnits);
91
92 setDateData(data);
93
94 if (data.formattedDate !== date) {
95 setAttributes({
96 date: data.formattedDate,
97 });
98 }
99 }
100
101 // Mount.
102 useEffect(() => {
103 // generate date.
104 if (!date) {
105 const today = new Date();
106 const newDate = new Date();
107 newDate.setDate(today.getDate() + 1);
108
109 const formattedDate =
110 luxon.DateTime.fromJSDate(newDate).toFormat(
111 TIMEZONELESS_FORMAT
112 );
113
114 updateDate(formattedDate, units);
115 } else {
116 updateDate(date, units);
117 }
118 // eslint-disable-next-line react-hooks/exhaustive-deps
119 }, []);
120
121 // Changed date data and run interval.
122 useEffect(() => {
123 clearInterval(interval.current);
124
125 if (!dateData) {
126 return;
127 }
128
129 interval.current = setInterval(() => {
130 if (!date || !units || !units.length) {
131 return;
132 }
133
134 const data = parseData(date, units);
135
136 setDateData(data);
137 }, dateData.delay);
138 // eslint-disable-next-line react-hooks/exhaustive-deps
139 }, [dateData]);
140
141 className = classnames(
142 'ghostkit-countdown',
143 unitsAlign && `ghostkit-countdown-units-align-${unitsAlign}`,
144 className
145 );
146
147 className = applyFilters('ghostkit.editor.className', className, props);
148
149 const blockProps = useBlockProps({ className });
150 const innerBlockProps = useInnerBlocksProps(
151 { className: 'ghostkit-countdown-expire-action-content' },
152 {
153 template: [
154 [
155 'core/paragraph',
156 {
157 content: __(
158 'This countdown has been ended already!',
159 'ghostkit'
160 ),
161 },
162 ],
163 ],
164 templateLock: false,
165 }
166 );
167
168 return (
169 <>
170 <InspectorControls>
171 <PanelBody>
172 <DateTimePicker
173 label={__('End Date', 'ghostkit')}
174 value={date}
175 onChange={(value) => updateDate(value, units)}
176 />
177 <SelectControl
178 label={__('Display Units', 'ghostkit')}
179 value={units}
180 onChange={(value) => {
181 setAttributes({ units: value });
182 updateDate(date, value);
183 }}
184 multiple
185 options={[
186 {
187 label: __('Years', 'ghostkit'),
188 value: 'years',
189 },
190 {
191 label: __('Months', 'ghostkit'),
192 value: 'months',
193 },
194 {
195 label: __('Weeks', 'ghostkit'),
196 value: 'weeks',
197 },
198 {
199 label: __('Days', 'ghostkit'),
200 value: 'days',
201 },
202 {
203 label: __('Hours', 'ghostkit'),
204 value: 'hours',
205 },
206 {
207 label: __('Minutes', 'ghostkit'),
208 value: 'minutes',
209 },
210 {
211 label: __('Seconds', 'ghostkit'),
212 value: 'seconds',
213 },
214 ]}
215 __next40pxDefaultSize
216 __nextHasNoMarginBottom
217 />
218 </PanelBody>
219 <PanelBody>
220 <RangeControl
221 label={__('Number Font Size', 'ghostkit')}
222 value={numberFontSize}
223 onChange={(value) =>
224 setAttributes({ numberFontSize: value })
225 }
226 beforeIcon="editor-textcolor"
227 afterIcon="editor-textcolor"
228 allowCustomMax
229 __next40pxDefaultSize
230 __nextHasNoMarginBottom
231 />
232 <RangeControl
233 label={__('Label Font Size', 'ghostkit')}
234 value={labelFontSize}
235 onChange={(value) =>
236 setAttributes({ labelFontSize: value })
237 }
238 beforeIcon="editor-textcolor"
239 afterIcon="editor-textcolor"
240 allowCustomMax
241 __next40pxDefaultSize
242 __nextHasNoMarginBottom
243 />
244 <ColorPicker
245 label={__('Number Color', 'ghostkit')}
246 value={numberColor}
247 onChange={(val) => setAttributes({ numberColor: val })}
248 alpha
249 />
250 <ColorPicker
251 label={__('Label Color', 'ghostkit')}
252 value={labelColor}
253 onChange={(val) => setAttributes({ labelColor: val })}
254 alpha
255 />
256 </PanelBody>
257 </InspectorControls>
258 <BlockControls>
259 <ToolbarGroup>
260 <ToolbarButton
261 icon="align-left"
262 title={__('Units Align Left', 'ghostkit')}
263 onClick={() => setAttributes({ unitsAlign: 'left' })}
264 isActive={unitsAlign === 'left'}
265 />
266 <ToolbarButton
267 icon="align-center"
268 title={__('Units Align Center', 'ghostkit')}
269 onClick={() => setAttributes({ unitsAlign: 'center' })}
270 isActive={unitsAlign === 'center'}
271 />
272 <ToolbarButton
273 icon="align-right"
274 title={__('Units Align Right', 'ghostkit')}
275 onClick={() => setAttributes({ unitsAlign: 'right' })}
276 isActive={unitsAlign === 'right'}
277 />
278 </ToolbarGroup>
279 </BlockControls>
280 <div {...blockProps}>
281 {units.map((unitName) => {
282 let formattedUnit = false;
283
284 if (dateData && typeof dateData[unitName] !== 'undefined') {
285 const isEnd = dateData.value >= 0;
286
287 formattedUnit = countDownApi.formatUnit(
288 isEnd ? 0 : dateData[unitName],
289 unitName
290 );
291 }
292
293 return (
294 <div
295 key={unitName}
296 className={classnames(
297 'ghostkit-countdown-unit',
298 `ghostkit-countdown-unit-${unitName}`
299 )}
300 >
301 <span className="ghostkit-countdown-unit-number">
302 {formattedUnit ? formattedUnit.number : '00'}
303 </span>
304 <span className="ghostkit-countdown-unit-label">
305 {formattedUnit ? formattedUnit.label : unitName}
306 </span>
307 </div>
308 );
309 })}
310 </div>
311 {isSelectedBlockInRoot ? (
312 <div className="ghostkit-countdown-expire-action">
313 <div className="ghostkit-countdown-expire-action-label">
314 {__('Display content after expiration:', 'ghostkit')}
315 </div>
316
317 <div {...innerBlockProps} />
318 </div>
319 ) : null}
320 </>
321 );
322 }
323