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

317 lines 7.1 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 />
216 </PanelBody>
217 <PanelBody>
218 <RangeControl
219 label={__('Number Font Size', 'ghostkit')}
220 value={numberFontSize}
221 onChange={(value) =>
222 setAttributes({ numberFontSize: value })
223 }
224 beforeIcon="editor-textcolor"
225 afterIcon="editor-textcolor"
226 allowCustomMax
227 />
228 <RangeControl
229 label={__('Label Font Size', 'ghostkit')}
230 value={labelFontSize}
231 onChange={(value) =>
232 setAttributes({ labelFontSize: value })
233 }
234 beforeIcon="editor-textcolor"
235 afterIcon="editor-textcolor"
236 allowCustomMax
237 />
238 <ColorPicker
239 label={__('Number Color', 'ghostkit')}
240 value={numberColor}
241 onChange={(val) => setAttributes({ numberColor: val })}
242 alpha
243 />
244 <ColorPicker
245 label={__('Label Color', 'ghostkit')}
246 value={labelColor}
247 onChange={(val) => setAttributes({ labelColor: val })}
248 alpha
249 />
250 </PanelBody>
251 </InspectorControls>
252 <BlockControls>
253 <ToolbarGroup>
254 <ToolbarButton
255 icon="align-left"
256 title={__('Units Align Left', 'ghostkit')}
257 onClick={() => setAttributes({ unitsAlign: 'left' })}
258 isActive={unitsAlign === 'left'}
259 />
260 <ToolbarButton
261 icon="align-center"
262 title={__('Units Align Center', 'ghostkit')}
263 onClick={() => setAttributes({ unitsAlign: 'center' })}
264 isActive={unitsAlign === 'center'}
265 />
266 <ToolbarButton
267 icon="align-right"
268 title={__('Units Align Right', 'ghostkit')}
269 onClick={() => setAttributes({ unitsAlign: 'right' })}
270 isActive={unitsAlign === 'right'}
271 />
272 </ToolbarGroup>
273 </BlockControls>
274 <div {...blockProps}>
275 {units.map((unitName) => {
276 let formattedUnit = false;
277
278 if (dateData && typeof dateData[unitName] !== 'undefined') {
279 const isEnd = dateData.value >= 0;
280
281 formattedUnit = countDownApi.formatUnit(
282 isEnd ? 0 : dateData[unitName],
283 unitName
284 );
285 }
286
287 return (
288 <div
289 key={unitName}
290 className={classnames(
291 'ghostkit-countdown-unit',
292 `ghostkit-countdown-unit-${unitName}`
293 )}
294 >
295 <span className="ghostkit-countdown-unit-number">
296 {formattedUnit ? formattedUnit.number : '00'}
297 </span>
298 <span className="ghostkit-countdown-unit-label">
299 {formattedUnit ? formattedUnit.label : unitName}
300 </span>
301 </div>
302 );
303 })}
304 </div>
305 {isSelectedBlockInRoot ? (
306 <div className="ghostkit-countdown-expire-action">
307 <div className="ghostkit-countdown-expire-action-label">
308 {__('Display content after expiration:', 'ghostkit')}
309 </div>
310
311 <div {...innerBlockProps} />
312 </div>
313 ) : null}
314 </>
315 );
316 }
317