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 / tabs / edit.js

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

254 lines 5.7 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 {
4 RichText,
5 useBlockProps,
6 useInnerBlocksProps,
7 } from '@wordpress/block-editor';
8 import { createBlock } from '@wordpress/blocks';
9 import { Button, Tooltip } from '@wordpress/components';
10 import { useDispatch, useSelect } from '@wordpress/data';
11 import { applyFilters } from '@wordpress/hooks';
12 import { __ } from '@wordpress/i18n';
13
14 import RemoveButton from '../../components/remove-button';
15 import getUniqueSlug from '../../utils/get-unique-slug';
16 import EditBlockControls from './edit/block-controls';
17 import EditInspectorControls from './edit/inspector-controls';
18
19 /**
20 * Block Edit Class.
21 *
22 * @param props
23 */
24 export default function BlockEdit(props) {
25 const { attributes, setAttributes, clientId } = props;
26 let { className = '' } = props;
27
28 const {
29 tabActive,
30 buttonsVerticalAlign,
31 buttonsAlign,
32 tabsData = [],
33 } = attributes;
34
35 const { getBlocks, block, isSelectedBlockInRoot } = useSelect((select) => {
36 const {
37 getBlock,
38 getBlocks: selectGetBlocks,
39 isBlockSelected,
40 hasSelectedInnerBlock,
41 } = select('core/block-editor');
42
43 return {
44 getBlocks: selectGetBlocks,
45 block: getBlock(clientId),
46 isSelectedBlockInRoot:
47 isBlockSelected(clientId) ||
48 hasSelectedInnerBlock(clientId, true),
49 };
50 });
51
52 const { updateBlockAttributes, removeBlock, replaceInnerBlocks } =
53 useDispatch('core/block-editor');
54
55 /**
56 * Returns the layouts configuration for a given number of tabs.
57 *
58 * @param {number} attributes tabs attributes.
59 *
60 * @return {Object[]} Tabs layout configuration.
61 */
62 const getTabsTemplate = () => {
63 return tabsData.map((tabData) => ['ghostkit/tabs-tab-v2', tabData]);
64 };
65
66 const getTabs = () => {
67 return block.innerBlocks;
68 };
69
70 const changeLabel = (value, i) => {
71 const tabs = getTabs();
72
73 if (tabs[i]) {
74 const newSlug = getUniqueSlug(`tab ${value}`, tabs[i].clientId);
75
76 const newTabsData = tabsData.map((oldTabData, newIndex) => {
77 if (i === newIndex) {
78 return {
79 ...oldTabData,
80 ...{
81 title: value,
82 slug: newSlug,
83 },
84 };
85 }
86
87 return oldTabData;
88 });
89
90 setAttributes({
91 tabActive: newSlug,
92 tabsData: newTabsData,
93 });
94 updateBlockAttributes(tabs[i].clientId, {
95 slug: newSlug,
96 });
97 }
98 };
99
100 const removeTab = (i) => {
101 if (block.innerBlocks.length <= 1) {
102 removeBlock(block.clientId);
103 } else if (block.innerBlocks[i]) {
104 removeBlock(block.innerBlocks[i].clientId);
105
106 if (tabsData[i]) {
107 const newTabsData = [...tabsData];
108 newTabsData.splice(i, 1);
109
110 const innerBlocks = [...getBlocks(block.clientId)];
111 innerBlocks.splice(i, 1);
112
113 replaceInnerBlocks(block.clientId, innerBlocks, false);
114
115 setAttributes({
116 tabsData: newTabsData,
117 });
118 }
119 }
120 };
121
122 className = classnames(
123 className,
124 'ghostkit-tabs',
125 buttonsVerticalAlign && 'ghostkit-tabs-buttons-vertical'
126 );
127
128 className = applyFilters('ghostkit.editor.className', className, props);
129
130 const blockProps = useBlockProps({
131 className,
132 });
133 const innerBlockProps = useInnerBlocksProps(
134 { className: 'ghostkit-tabs-content' },
135 {
136 template: getTabsTemplate(),
137 templateLock: 'all',
138 allowedBlocks: ['ghostkit/tabs-tab-v2'],
139 }
140 );
141
142 return (
143 <>
144 <EditBlockControls
145 attributes={attributes}
146 setAttributes={setAttributes}
147 />
148 <EditInspectorControls
149 attributes={attributes}
150 setAttributes={setAttributes}
151 />
152
153 <div {...blockProps}>
154 <div
155 className={classnames(
156 'ghostkit-tabs-buttons',
157 `ghostkit-tabs-buttons-align-${buttonsAlign}`
158 )}
159 role="tablist"
160 aria-orientation={
161 buttonsVerticalAlign ? 'vertical' : 'horizontal'
162 }
163 >
164 {tabsData.map((tabData, i) => {
165 const { slug, title } = tabData;
166 const selected = tabActive === slug;
167 const tabName = `tab_button_${i}`;
168
169 return (
170 <div
171 id={`${slug}-button`}
172 className={classnames(
173 'ghostkit-tabs-buttons-item',
174 selected &&
175 'ghostkit-tabs-buttons-item-active'
176 )}
177 role="tab"
178 key={tabName}
179 >
180 <RichText
181 tagName="span"
182 placeholder={__('Tab label', 'ghostkit')}
183 value={title}
184 onFocus={() =>
185 setAttributes({ tabActive: slug })
186 }
187 onChange={(value) => {
188 changeLabel(value, i);
189 }}
190 withoutInteractiveFormatting
191 />
192 <RemoveButton
193 show={isSelectedBlockInRoot}
194 tooltipText={__('Remove tab?', 'ghostkit')}
195 onRemove={() => {
196 removeTab(i);
197 }}
198 />
199 </div>
200 );
201 })}
202 {isSelectedBlockInRoot ? (
203 <Tooltip text={__('Add Tab', 'ghostkit')}>
204 <Button
205 icon={
206 <svg
207 xmlns="http://www.w3.org/2000/svg"
208 viewBox="0 0 24 24"
209 width="24"
210 height="24"
211 role="img"
212 focusable="false"
213 >
214 <path d="M18 11.2h-5.2V6h-1.6v5.2H6v1.6h5.2V18h1.6v-5.2H18z" />
215 </svg>
216 }
217 onClick={() => {
218 const newTabsData = [...tabsData];
219 const newDataLength = tabsData.length + 1;
220
221 newTabsData.push({
222 slug: `tab-${newDataLength}`,
223 title: `Tab ${newDataLength}`,
224 });
225
226 const newBlock = createBlock(
227 'ghostkit/tabs-tab-v2',
228 {
229 slug: `tab-${newDataLength}`,
230 title: `Tab ${newDataLength}`,
231 }
232 );
233
234 let innerBlocks = getBlocks(clientId);
235 innerBlocks = [...innerBlocks, newBlock];
236
237 replaceInnerBlocks(
238 clientId,
239 innerBlocks,
240 false
241 );
242
243 setAttributes({ tabsData: newTabsData });
244 }}
245 />
246 </Tooltip>
247 ) : null}
248 </div>
249 <div {...innerBlockProps} />
250 </div>
251 </>
252 );
253 }
254