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

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

254 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 RichText,
3 useBlockProps,
4 useInnerBlocksProps,
5 } from '@wordpress/block-editor';
6 import { createBlock } from '@wordpress/blocks';
7 import { Button, Tooltip } from '@wordpress/components';
8 import { useDispatch, useSelect } from '@wordpress/data';
9 import { applyFilters } from '@wordpress/hooks';
10 import { __ } from '@wordpress/i18n';
11 import classnames from 'classnames/dedupe';
12
13 import RemoveButton from '../../components/remove-button';
14 import getUniqueSlug from '../../utils/get-unique-slug';
15 import EditBlockControls from './edit/block-controls';
16 import EditInspectorControls from './edit/inspector-controls';
17
18 /**
19 * Block Edit Class.
20 *
21 * @param props
22 */
23 export default function BlockEdit(props) {
24 const { attributes, setAttributes, clientId } = props;
25 let { className = '' } = props;
26
27 const {
28 tabActive,
29 buttonsVerticalAlign,
30 buttonsAlign,
31 tabsData = [],
32 } = attributes;
33
34 const { getBlocks, block, isSelectedBlockInRoot } = useSelect((select) => {
35 const {
36 getBlock,
37 getBlocks: selectGetBlocks,
38 isBlockSelected,
39 hasSelectedInnerBlock,
40 } = select('core/block-editor');
41
42 return {
43 getBlocks: selectGetBlocks,
44 block: getBlock(clientId),
45 isSelectedBlockInRoot:
46 isBlockSelected(clientId) ||
47 hasSelectedInnerBlock(clientId, true),
48 };
49 });
50
51 const { updateBlockAttributes, removeBlock, replaceInnerBlocks } =
52 useDispatch('core/block-editor');
53
54 /**
55 * Returns the layouts configuration for a given number of tabs.
56 *
57 * @param {number} attributes tabs attributes.
58 *
59 * @return {Object[]} Tabs layout configuration.
60 */
61 const getTabsTemplate = () => {
62 return tabsData.map((tabData) => ['ghostkit/tabs-tab-v2', tabData]);
63 };
64
65 const getTabs = () => {
66 return block.innerBlocks;
67 };
68
69 const changeLabel = (value, i) => {
70 const tabs = getTabs();
71
72 if (tabs[i]) {
73 const newSlug = getUniqueSlug(`tab ${value}`, tabs[i].clientId);
74
75 const newTabsData = tabsData.map((oldTabData, newIndex) => {
76 if (i === newIndex) {
77 return {
78 ...oldTabData,
79 ...{
80 title: value,
81 slug: newSlug,
82 },
83 };
84 }
85
86 return oldTabData;
87 });
88
89 setAttributes({
90 tabActive: newSlug,
91 tabsData: newTabsData,
92 });
93 updateBlockAttributes(tabs[i].clientId, {
94 slug: newSlug,
95 });
96 }
97 };
98
99 const removeTab = (i) => {
100 if (block.innerBlocks.length <= 1) {
101 removeBlock(block.clientId);
102 } else if (block.innerBlocks[i]) {
103 removeBlock(block.innerBlocks[i].clientId);
104
105 if (tabsData[i]) {
106 const newTabsData = [...tabsData];
107 newTabsData.splice(i, 1);
108
109 const innerBlocks = [...getBlocks(block.clientId)];
110 innerBlocks.splice(i, 1);
111
112 replaceInnerBlocks(block.clientId, innerBlocks, false);
113
114 setAttributes({
115 tabsData: newTabsData,
116 });
117 }
118 }
119 };
120
121 className = classnames(
122 className,
123 'ghostkit-tabs',
124 buttonsVerticalAlign && 'ghostkit-tabs-buttons-vertical'
125 );
126
127 className = applyFilters('ghostkit.editor.className', className, props);
128
129 const blockProps = useBlockProps({
130 className,
131 });
132 const innerBlockProps = useInnerBlocksProps(
133 { className: 'ghostkit-tabs-content' },
134 {
135 template: getTabsTemplate(),
136 templateLock: 'all',
137 allowedBlocks: ['ghostkit/tabs-tab-v2'],
138 }
139 );
140
141 return (
142 <>
143 <EditBlockControls
144 attributes={attributes}
145 setAttributes={setAttributes}
146 />
147 <EditInspectorControls
148 attributes={attributes}
149 setAttributes={setAttributes}
150 />
151
152 <div {...blockProps}>
153 <div
154 className={classnames(
155 'ghostkit-tabs-buttons',
156 `ghostkit-tabs-buttons-align-${buttonsAlign}`
157 )}
158 role="tablist"
159 aria-orientation={
160 buttonsVerticalAlign ? 'vertical' : 'horizontal'
161 }
162 >
163 {tabsData.map((tabData, i) => {
164 const { slug, title } = tabData;
165 const selected = tabActive === slug;
166 const tabName = `tab_button_${i}`;
167
168 return (
169 // biome-ignore lint/a11y/useFocusableInteractive: focus inside the editor belongs to the nested RichText, not to the tab wrapper.
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