@secretstache/wordpress-gutenberg 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,269 +0,0 @@
1
- import apiFetch from '@wordpress/api-fetch';
2
- import { useSelect } from '@wordpress/data';
3
- import { useEffect, useRef } from '@wordpress/element';
4
- import slugify from 'slugify';
5
-
6
- export const loadSelectOptions = async (inputValue, postType, mapper = null) => {
7
- const response = await apiFetch({
8
- path: `/wp/v2/${postType}?search=${encodeURIComponent(inputValue)}`,
9
- });
10
-
11
- if (mapper) {
12
- return response?.map(mapper);
13
- } else {
14
- return response?.map((post) => {
15
- // Create a temporary DOM element to decode HTML entities
16
- const tempElement = document.createElement('div');
17
- tempElement.innerHTML = post?.title?.rendered;
18
-
19
- return {
20
- value: post.id,
21
- label: tempElement.textContent || tempElement.innerText || '',
22
- };
23
- });
24
- }
25
- };
26
-
27
- /**
28
- * Hook to find a parent block of a specific type, optionally scoped within a certain root block.
29
- *
30
- * @param {string} selectedBlockId - The clientId of the currently selected block.
31
- * @param {string} parentBlockName - The block type name to search for as a parent.
32
- * @param {Object} options - Optional settings for the search.
33
- * @param {string} [options.rootBlockId] - The clientId of the block to limit the search within. If not provided, searches the entire block tree.
34
- * @param {boolean} [options.includeSelf] - Whether to include the selected block itself if it matches the parentBlockName.
35
- * @returns {Object|null} The matching parent block, or null if none is found.
36
- */
37
- export const useParentBlock = (selectedBlockId, parentBlockName, options = {}) => {
38
- return useSelect((select) => {
39
- const { getBlock, getBlockRootClientId, getBlockHierarchyRootClientId } = select('core/block-editor');
40
-
41
- if (!selectedBlockId) {
42
- return null;
43
- }
44
-
45
- // Destructure with default values to handle optional parameters.
46
- const { rootBlockId = '', includeSelf = false } = options;
47
-
48
- // If rootBlockId is provided, verify the selected block is within its scope.
49
- if (rootBlockId) {
50
- const hierarchyRootClientId = getBlockHierarchyRootClientId(selectedBlockId);
51
- if (hierarchyRootClientId !== rootBlockId) {
52
- return null; // The selected block is out of the scope of the root block.
53
- }
54
- }
55
-
56
- let currentBlockId = selectedBlockId;
57
- let currentBlock = getBlock(currentBlockId);
58
-
59
- // Optionally include the selected block if it matches the target type.
60
- if (includeSelf && currentBlock?.name === parentBlockName) {
61
- return currentBlock;
62
- }
63
-
64
- let parentBlockId = getBlockRootClientId(currentBlockId);
65
- let parentBlock = getBlock(parentBlockId);
66
-
67
- // Traverse up the hierarchy to find the target parent block.
68
- while (parentBlock && (rootBlockId ? parentBlockId !== rootBlockId : true) && parentBlockId) {
69
- if (parentBlock.name === parentBlockName) {
70
- return parentBlock; // Target parent found.
71
- }
72
- currentBlockId = parentBlockId;
73
- parentBlockId = getBlockRootClientId(currentBlockId);
74
- parentBlock = getBlock(parentBlockId);
75
- }
76
-
77
- return null; // No matching parent found within the constraints.
78
- }, [selectedBlockId, parentBlockName, options.rootBlockId, options.includeSelf]);
79
- };
80
-
81
- export const getSlug = (name) => slugify(name, {
82
- replacement: '-',
83
- lower: true,
84
- strict: true,
85
- });
86
-
87
- export const cleanSvgString = (svgString) => {
88
- if (svgString.startsWith('<?xml')) {
89
- const endOfXml = svgString.indexOf('?>');
90
-
91
- if (endOfXml !== -1) {
92
- svgString = svgString.substring(endOfXml + 2);
93
- }
94
- }
95
-
96
- svgString = svgString.trim();
97
-
98
- return svgString;
99
- };
100
-
101
-
102
- const SVG_MIME_TYPE = 'image/svg+xml';
103
-
104
- export const getImage = async (mediaData) => {
105
- const isSvg = mediaData?.mime === SVG_MIME_TYPE || mediaData?.mime_type === SVG_MIME_TYPE;
106
- const imagePayload = {
107
- isSvg,
108
- imageUrl: null,
109
- svgCode: null,
110
- width: mediaData?.width,
111
- height: mediaData?.height,
112
- };
113
-
114
- if (isSvg) {
115
- imagePayload.svgCode = await fetch(mediaData.url).then(response => response.text()).then(cleanSvgString);
116
- } else {
117
- imagePayload.imageUrl = mediaData?.url;
118
- }
119
-
120
- return imagePayload;
121
- };
122
-
123
- export const getPhoneNumber = (phone) => {
124
- if (!phone) return '';
125
-
126
- let formatted = phone;
127
-
128
- const pattern = /^\+\d(\d{3})(\d{3})(\d{4})$/;
129
- const match = phone.match(pattern);
130
-
131
- if (match) {
132
- formatted = `${match[1]}-${match[2]}-${match[3]}`;
133
- }
134
-
135
- return formatted;
136
- };
137
-
138
- export const getLocationAddress = (location) => {
139
- const {
140
- street_number = '',
141
- street_name = '',
142
- city = '',
143
- state_short = '',
144
- post_code = '',
145
- } = location;
146
-
147
- // Start with the street number and name, trimming to remove extra spaces if one is missing
148
- let addressParts = [`${street_number} ${street_name}`.trim()];
149
-
150
- // Add the city with a line break, but only if there is a city name.
151
- if (city) {
152
- addressParts.push(`<br>${city}`);
153
- }
154
-
155
- // Combine state and postal code intelligently, adding only if they exist
156
- let statePostalParts = [];
157
- if (state_short) statePostalParts.push(state_short);
158
- if (post_code) statePostalParts.push(post_code);
159
- let statePostal = statePostalParts.join(' ');
160
-
161
- if (statePostal) {
162
- // Add a comma only if there's something before this part
163
- addressParts.push(`${addressParts.length > 0 ? ', ' : ''}${statePostal}`);
164
- }
165
-
166
- return addressParts.join('');
167
- };
168
-
169
- //for package
170
-
171
- export const useSlider = (isPreview, items, setup) => {
172
- const ref = useRef(null);
173
-
174
- useEffect(() => {
175
- let instance;
176
-
177
- if (isPreview && items?.length && ref?.current) {
178
- instance = setup(ref.current);
179
- }
180
-
181
- return () => {
182
- instance?.destroy();
183
- };
184
- }, [isPreview, items]);
185
-
186
- return ref;
187
- };
188
-
189
-
190
- export const useEntityRecords = (entityType, postType, options) => {
191
- const {
192
- query,
193
- curatedItems,
194
- selectedCategories,
195
- categoryKey,
196
- numberOfItems,
197
- order = 'desc',
198
- orderby = 'date',
199
- } = options;
200
-
201
- const {
202
- records,
203
- isLoading,
204
- } = useSelect((select) => {
205
- const queryArgs = {
206
- order,
207
- orderby,
208
- _embed: true,
209
- };
210
-
211
- // TODO: refactor
212
- if (query?.LATEST_BY_CATEGORY && selectedCategories?.length) {
213
- queryArgs[categoryKey] = selectedCategories.join(',');
214
- } else if (query?.BY_CATEGORY && selectedCategories?.length) {
215
- queryArgs[categoryKey] = selectedCategories.map((category) => category.value).join(',');
216
- } else if (query?.CURATED && curatedItems?.length) {
217
- queryArgs.include = curatedItems.map((item) => item.value);
218
- queryArgs.orderby = 'include';
219
- }
220
-
221
- if (numberOfItems) {
222
- queryArgs.per_page = numberOfItems;
223
- }
224
-
225
- const records = select('core').getEntityRecords(entityType, postType, queryArgs);
226
- const isResolving = select('core/data').isResolving('core', 'getEntityRecords', [entityType, postType, queryArgs]);
227
- const isLoading = isResolving || records === undefined;
228
-
229
- return {
230
- records,
231
- isLoading,
232
- };
233
- }, [query, curatedItems, selectedCategories, categoryKey, numberOfItems, order, orderby]);
234
-
235
- return {
236
- records,
237
- isLoading,
238
- };
239
- };
240
-
241
- export const useThemeColors = (allowedColors = []) => {
242
- return useSelect((select) => {
243
- const { getSettings } = select('core/block-editor');
244
- const colors = getSettings()?.colors;
245
-
246
- return allowedColors.length > 0
247
- ? colors?.filter((color) => allowedColors.includes(color.slug))
248
- : colors;
249
- }, []);
250
- };
251
-
252
- export const useColorChange = (colors, setAttributes) => (colorValue, property) => {
253
- const selectedColor = colors.find(color => color.color === colorValue);
254
-
255
- setAttributes({
256
- [property]: selectedColor
257
- ? {
258
- value: colorValue,
259
- slug: selectedColor.slug,
260
- }
261
- : null,
262
- });
263
- };
264
-
265
- // TODO: refactor fn name
266
- export const useLinkChange = (setAttributes) => (value, property) => {
267
- setAttributes({ [property]: value });
268
- };
269
-