@eightshift/frontend-libs-tailwind 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/.husky/pre-commit +0 -0
  2. package/CHANGELOG.md +20 -1
  3. package/blocks/init/assets/fonts/fraunces-italic-latin-extended.woff2 +0 -0
  4. package/blocks/init/assets/fonts/fraunces-italic-latin.woff2 +0 -0
  5. package/blocks/init/assets/fonts/fraunces-latin-extended.woff2 +0 -0
  6. package/blocks/init/assets/fonts/fraunces-latin.woff2 +0 -0
  7. package/blocks/init/assets/fonts/noto-sans-italic-latin-extended.woff2 +0 -0
  8. package/blocks/init/assets/fonts/noto-sans-italic-latin.woff2 +0 -0
  9. package/blocks/init/assets/fonts/noto-sans-latin-extended.woff2 +0 -0
  10. package/blocks/init/assets/fonts/noto-sans-latin.woff2 +0 -0
  11. package/blocks/init/src/Blocks/assets/scripts/shared.js +1 -3
  12. package/blocks/init/src/Blocks/assets/styles/application-blocks-frontend.css +0 -3
  13. package/blocks/init/src/Blocks/assets/styles/editor/editor-overrides.css +1 -1
  14. package/blocks/init/src/Blocks/assets/styles/fonts.css +90 -0
  15. package/blocks/init/src/Blocks/assets/styles/tailwind.css +1 -5
  16. package/blocks/init/src/Blocks/components/admin-theme-options/assets-admin/pages/parts.js +1 -0
  17. package/blocks/init/src/Blocks/components/button/components/button-editor.js +1 -5
  18. package/blocks/init/src/Blocks/components/button/components/button-options.js +2 -21
  19. package/blocks/init/src/Blocks/components/button/manifest.json +8 -8
  20. package/blocks/init/src/Blocks/components/card/components/card-editor.js +1 -2
  21. package/blocks/init/src/Blocks/components/card/components/card-options.js +0 -1
  22. package/blocks/init/src/Blocks/components/heading/components/heading-editor.js +1 -5
  23. package/blocks/init/src/Blocks/components/image/components/image-editor.js +1 -7
  24. package/blocks/init/src/Blocks/components/image/components/image-options.js +3 -17
  25. package/blocks/init/src/Blocks/components/list/components/list-options.js +1 -3
  26. package/blocks/init/src/Blocks/components/load-more/assets/load-more.js +1 -2
  27. package/blocks/init/src/Blocks/components/load-more/components/load-more-options.js +1 -0
  28. package/blocks/init/src/Blocks/components/modal/assets/index.js +7 -9
  29. package/blocks/init/src/Blocks/components/paragraph/components/paragraph-options.js +1 -3
  30. package/blocks/init/src/Blocks/components/paragraph/manifest.json +14 -16
  31. package/blocks/init/src/Blocks/components/post-header/post-header.php +1 -1
  32. package/blocks/init/src/Blocks/components/share/assets/index.js +1 -5
  33. package/blocks/init/src/Blocks/components/share/components/share-editor.js +7 -4
  34. package/blocks/init/src/Blocks/components/share/components/share-options.js +2 -11
  35. package/blocks/init/src/Blocks/components/video/components/video-editor.js +2 -4
  36. package/blocks/init/src/Blocks/components/video/components/video-options.js +5 -27
  37. package/blocks/init/src/Blocks/custom/accordion/assets/index.js +1 -1
  38. package/blocks/init/src/Blocks/custom/accordion/components/accordion-editor.js +6 -1
  39. package/blocks/init/src/Blocks/custom/carousel/assets/pagination.js +3 -8
  40. package/blocks/init/src/Blocks/custom/column/components/column-editor.js +4 -1
  41. package/blocks/init/src/Blocks/custom/column/components/column-options.js +5 -12
  42. package/blocks/init/src/Blocks/custom/columns/components/columns-editor.js +2 -6
  43. package/blocks/init/src/Blocks/custom/featured-content/components/featured-content-options.js +18 -30
  44. package/blocks/init/src/Blocks/custom/featured-content/partials/cards.php +5 -5
  45. package/blocks/init/src/Blocks/custom/group/components/group-editor.js +1 -3
  46. package/blocks/init/src/Blocks/custom/heading/heading-transforms.js +1 -0
  47. package/blocks/init/src/Blocks/custom/map/assets/map-controller.js +0 -1
  48. package/blocks/init/src/Blocks/custom/map/components/map-components.js +3 -3
  49. package/blocks/init/src/Blocks/custom/map/components/map-editor.js +2 -12
  50. package/blocks/init/src/Blocks/custom/map/components/map-options.js +10 -46
  51. package/blocks/init/src/Blocks/custom/paragraph/paragraph-transforms.js +1 -0
  52. package/blocks/init/src/Blocks/custom/site-footer/components/site-footer-options.js +1 -3
  53. package/blocks/init/src/Blocks/custom/table-of-contents/components/table-of-contents-editor.js +1 -1
  54. package/blocks/init/src/Blocks/manifest.json +22 -4
  55. package/blocks/init/src/Blocks/wrapper/components/wrapper-options.js +4 -19
  56. package/blocks/init/src/Blocks/wrapper/wrapper.js +1 -4
  57. package/linters/base.config.mjs +1 -1
  58. package/linters/eslint.config.mjs +1 -2
  59. package/linters/stylelint.config.js +9 -13
  60. package/package.json +92 -92
  61. package/schemas/block.json +4 -0
  62. package/schemas/component.json +4 -0
  63. package/scripts/components/block-inserter.js +8 -14
  64. package/scripts/components/file-picker.js +42 -39
  65. package/scripts/components/index.js +1 -0
  66. package/scripts/components/link-section-editor.js +6 -2
  67. package/scripts/components/picker-placeholder.js +109 -0
  68. package/scripts/components/server-side-render.js +2 -4
  69. package/scripts/components/settings/settings.js +3 -14
  70. package/scripts/components/settings/use-theme-options.js +2 -2
  71. package/scripts/editor/attributes.js +3 -9
  72. package/scripts/editor/colors.js +43 -41
  73. package/scripts/editor/editor.js +9 -16
  74. package/scripts/editor/fetch.js +26 -19
  75. package/scripts/editor/hooks.js +1 -0
  76. package/scripts/editor/options.js +2 -4
  77. package/scripts/editor/registration.js +51 -128
  78. package/scripts/editor/tailwindcss.js +118 -37
  79. package/scripts/helpers/breakpoints.js +3 -8
  80. package/scripts/helpers/cookies.js +2 -1
  81. package/scripts/helpers/index.js +1 -7
  82. package/scripts/index.js +2 -0
  83. package/scripts/plugins/yoast-seo.js +2 -3
  84. package/linters/ignore-gitignored.mjs +0 -9
@@ -1,24 +1,6 @@
1
1
  import { __, sprintf } from '@wordpress/i18n';
2
- import {
3
- getOption,
4
- checkAttr,
5
- getAttrKey,
6
- FileSelector,
7
- getHiddenOptions,
8
- MediaPicker,
9
- } from '@eightshift/frontend-libs-tailwind/scripts';
10
- import {
11
- AnimatedVisibility,
12
- BaseControl,
13
- Expandable,
14
- InputField,
15
- Notice,
16
- OptionSelect,
17
- Repeater,
18
- RepeaterItem,
19
- Spacer,
20
- Toggle,
21
- } from '@eightshift/ui-components';
2
+ import { getOption, checkAttr, getAttrKey, FileSelector, getHiddenOptions, MediaPicker } from '@eightshift/frontend-libs-tailwind/scripts';
3
+ import { AnimatedVisibility, BaseControl, Expandable, InputField, Notice, OptionSelect, Repeater, RepeaterItem, Spacer, Toggle } from '@eightshift/ui-components';
22
4
  import { icons } from '@eightshift/ui-components/icons';
23
5
  import manifest from '../manifest.json';
24
6
 
@@ -49,6 +31,7 @@ export const VideoOptions = (attributes) => {
49
31
  case 'chapters':
50
32
  return icons.videoChapters;
51
33
  }
34
+
52
35
  return icons.emptyRect;
53
36
  };
54
37
 
@@ -126,10 +109,7 @@ export const VideoOptions = (attributes) => {
126
109
  <Notice
127
110
  type='warning'
128
111
  label={__('Video plays automatically, with sound, and without controls', '%g_textdomain%')}
129
- subtitle={__(
130
- 'This will bother most users and is an accessibility issue. Consider changing some of the options.',
131
- '%g_textdomain%',
132
- )}
112
+ subtitle={__('This will bother most users and is an accessibility issue. Consider changing some of the options.', '%g_textdomain%')}
133
113
  icon={icons.a11yWarning}
134
114
  alignIconToTitle
135
115
  />
@@ -155,9 +135,7 @@ export const VideoOptions = (attributes) => {
155
135
  return (
156
136
  <RepeaterItem
157
137
  icon={getTrackIcon(kind)}
158
- label={
159
- label ? sprintf(__('Track %d', '%g_textdomain%'), index + 1) : __('New track', '%g_textdomain%')
160
- }
138
+ label={label ? sprintf(__('Track %d', '%g_textdomain%'), index + 1) : __('New track', '%g_textdomain%')}
161
139
  subtitle={label}
162
140
  >
163
141
  <FileSelector
@@ -28,7 +28,7 @@ domReady(async () => {
28
28
  activeElement = trigger;
29
29
  }
30
30
 
31
- const expanded = trigger.getAttribute('aria-expanded') === 'true' ?? false;
31
+ const expanded = (trigger.getAttribute('aria-expanded') ?? 'false') === 'true';
32
32
  trigger.setAttribute('aria-expanded', !expanded);
33
33
  target.hidden = expanded;
34
34
  });
@@ -13,5 +13,10 @@ export const AccordionEditor = ({ clientId }) => {
13
13
  ),
14
14
  });
15
15
 
16
- return <div {...innerBlocksProps} className='space-y-0 *:!m-0' />;
16
+ return (
17
+ <div
18
+ {...innerBlocksProps}
19
+ className='space-y-0 *:!m-0'
20
+ />
21
+ );
17
22
  };
@@ -8,11 +8,11 @@ export const addPagination = (emblaApi, dotsNode) => {
8
8
 
9
9
  dotNodes = emblaApi.scrollSnapList().map((_, index) => {
10
10
  const elem = document.createElement('button');
11
- elem.className =
12
- 'size-2.5 rounded-full border border-gray-500 transition hover:scale-105 focus:outline-none focus-visible:ring focus-visible:ring-navy-500/30';
11
+ elem.className = 'size-2.5 rounded-full border border-gray-500 transition hover:scale-105 focus:outline-none focus-visible:ring focus-visible:ring-navy-500/30';
13
12
 
14
13
  elem.addEventListener('click', () => emblaApi.scrollTo(index), false);
15
14
  dotsNode.appendChild(elem);
15
+
16
16
  return elem;
17
17
  });
18
18
  };
@@ -26,12 +26,7 @@ export const addPagination = (emblaApi, dotsNode) => {
26
26
  });
27
27
  };
28
28
 
29
- emblaApi
30
- .on('init', addDots)
31
- .on('reInit', addDots)
32
- .on('init', toggleDotBtnsActive)
33
- .on('reInit', toggleDotBtnsActive)
34
- .on('select', toggleDotBtnsActive);
29
+ emblaApi.on('init', addDots).on('reInit', addDots).on('init', toggleDotBtnsActive).on('reInit', toggleDotBtnsActive).on('select', toggleDotBtnsActive);
35
30
 
36
31
  return () => {
37
32
  dotsNode.innerHTML = '';
@@ -9,7 +9,10 @@ export const ColumnEditor = ({ clientId }) => {
9
9
 
10
10
  return (
11
11
  <>
12
- <div {...innerBlocksProps} className='contents *:!m-0' />
12
+ <div
13
+ {...innerBlocksProps}
14
+ className='contents *:!m-0'
15
+ />
13
16
  <BlockInserter
14
17
  small
15
18
  clientId={clientId}
@@ -65,6 +65,7 @@ export const ColumnOptions = ({ attributes, setAttributes }) => {
65
65
  const widthOffsetOptions = generateOptionsFromValue(widthOffsetValue, (value, breakpoint) => {
66
66
  const [_, offset, width] = value.split(',');
67
67
  const numColumns = parseInt(columnsConfig?.[breakpoint] ?? columnsConfig?.['_default']);
68
+
68
69
  return getColumnConfigOutputText(numColumns, parseInt(offset), parseInt(width));
69
70
  });
70
71
 
@@ -208,9 +209,7 @@ export const ColumnOptions = ({ attributes, setAttributes }) => {
208
209
  }
209
210
  icon={icons.gridAutoRows}
210
211
  label={__('Row span', '%g_textdomain%')}
211
- options={generateOptionsFromValue(columnRowSpan, (v) =>
212
- !v ? __('Not set', '%g_textdomain%') : sprintf(_n('1 row', '%d rows', v, '%g_textdomain%'), v),
213
- )}
212
+ options={generateOptionsFromValue(columnRowSpan, (v) => (!v ? __('Not set', '%g_textdomain%') : sprintf(_n('1 row', '%d rows', v, '%g_textdomain%'), v)))}
214
213
  noModeSelect
215
214
  inline
216
215
  {...responsiveData}
@@ -312,9 +311,7 @@ export const ColumnOptions = ({ attributes, setAttributes }) => {
312
311
  setAttributes({ [getAttrKey('columnBackground', attributes, manifest)]: undefined });
313
312
  } else {
314
313
  setAttributes({
315
- [getAttrKey('columnBackground', attributes, manifest)]: Object.keys(
316
- manifest.tailwind.options.columnBackground.twClasses,
317
- ).find((key) => key.startsWith(value)),
314
+ [getAttrKey('columnBackground', attributes, manifest)]: Object.keys(manifest.tailwind.options.columnBackground.twClasses).find((key) => key.startsWith(value)),
318
315
  });
319
316
  }
320
317
  }}
@@ -326,9 +323,7 @@ export const ColumnOptions = ({ attributes, setAttributes }) => {
326
323
  {backgroundType === 'solid' && (
327
324
  <ColorPicker
328
325
  colors={getColorOption('columnBackgroundSolid', manifest)}
329
- onChange={(value) =>
330
- setAttributes({ [getAttrKey('columnBackground', attributes, manifest)]: `solid-${value}` })
331
- }
326
+ onChange={(value) => setAttributes({ [getAttrKey('columnBackground', attributes, manifest)]: `solid-${value}` })}
332
327
  value={columnBackground?.replace('solid-', '')}
333
328
  aria-label={__('Background color', '%g_textdomain%')}
334
329
  />
@@ -365,9 +360,7 @@ export const ColumnOptions = ({ attributes, setAttributes }) => {
365
360
  />
366
361
  <OptionSelect
367
362
  value={columnGradientDirection}
368
- onChange={(value) =>
369
- setAttributes({ [getAttrKey('columnGradientDirection', attributes, manifest)]: value })
370
- }
363
+ onChange={(value) => setAttributes({ [getAttrKey('columnGradientDirection', attributes, manifest)]: value })}
371
364
  options={getOption('columnGradientDirection', attributes, manifest)}
372
365
  wrapperProps={{
373
366
  triggerIcon: <div className={rotationClassName[columnGradientDirection]}>{icons.arrowUpCircle}</div>,
@@ -10,9 +10,7 @@ import manifest from './../manifest.json';
10
10
  export const ColumnsEditor = ({ attributes, setAttributes, clientId }) => {
11
11
  const { title, layoutPresets } = manifest;
12
12
 
13
- const innerBlockCount = useSelect(
14
- (select) => select('core/block-editor').getBlock(clientId).innerBlocks?.length ?? 0,
15
- );
13
+ const innerBlockCount = useSelect((select) => select('core/block-editor').getBlock(clientId).innerBlocks?.length ?? 0);
16
14
 
17
15
  const blockProps = useBlockProps();
18
16
  const innerBlocksProps = useInnerBlocksProps(blockProps, {
@@ -38,9 +36,7 @@ export const ColumnsEditor = ({ attributes, setAttributes, clientId }) => {
38
36
  <Button
39
37
  key={index}
40
38
  onPress={async () => {
41
- const blocksToInsert = blockData.map(({ name: blockName, attributes: blockAttrs }) =>
42
- createBlock(blockName, blockAttrs),
43
- );
39
+ const blocksToInsert = blockData.map(({ name: blockName, attributes: blockAttrs }) => createBlock(blockName, blockAttrs));
44
40
 
45
41
  setAttributes(attrsToSet);
46
42
 
@@ -2,17 +2,7 @@ import { useState } from '@wordpress/element';
2
2
  import { __ } from '@wordpress/i18n';
3
3
  import { getAttrKey, checkAttr, getOption, props, fetchFromWpRest } from '@eightshift/frontend-libs-tailwind/scripts';
4
4
  import { LoadMoreOptions } from '../../../components/load-more/components/load-more-options';
5
- import {
6
- AnimatedVisibility,
7
- AsyncMultiSelect,
8
- BaseControl,
9
- HStack,
10
- NumberPicker,
11
- OptionSelect,
12
- Select,
13
- Spacer,
14
- Toggle,
15
- } from '@eightshift/ui-components';
5
+ import { AnimatedVisibility, AsyncMultiSelect, NumberPicker, OptionSelect, Spacer, Toggle } from '@eightshift/ui-components';
16
6
  import { icons } from '@eightshift/ui-components/icons';
17
7
  import manifest from '../manifest.json';
18
8
 
@@ -36,6 +26,14 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
36
26
  const [useSpecificPosts, setUseSpecificPosts] = useState(featuredContentPosts?.length > 0);
37
27
  const [useSpecificTerms, setUseSpecificTerms] = useState(featuredContentTerms?.length > 0);
38
28
 
29
+ let termsToShow = '';
30
+
31
+ if (featuredContentUseCurrentTerm) {
32
+ termsToShow = 'current';
33
+ } else {
34
+ termsToShow = useSpecificTerms ? 'manual' : 'all';
35
+ }
36
+
39
37
  return (
40
38
  <>
41
39
  <OptionSelect
@@ -98,7 +96,7 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
98
96
  label: __('Select posts to show', '%g_textdomain%'),
99
97
  value: true,
100
98
  disabled: featuredContentExcludeCurrentPost || featuredContentTaxonomy,
101
- subtitle:(featuredContentExcludeCurrentPost || featuredContentTaxonomy) && __('Unavailable when a taxonomy filter is set', '%g_textdomain%')
99
+ subtitle: (featuredContentExcludeCurrentPost || featuredContentTaxonomy) && __('Unavailable when a taxonomy filter is set', '%g_textdomain%'),
102
100
  },
103
101
  ]}
104
102
  type='radiosSegmented'
@@ -114,9 +112,7 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
114
112
  label={__('Exclude current', '%g_textdomain%')}
115
113
  subtitle={__('Best used with blog posts', '%g_textdomain%')}
116
114
  checked={featuredContentExcludeCurrentPost}
117
- onChange={(value) =>
118
- setAttributes({ [getAttrKey('featuredContentExcludeCurrentPost', attributes, manifest)]: value })
119
- }
115
+ onChange={(value) => setAttributes({ [getAttrKey('featuredContentExcludeCurrentPost', attributes, manifest)]: value })}
120
116
  />
121
117
  </AnimatedVisibility>
122
118
 
@@ -126,14 +122,10 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
126
122
  >
127
123
  <AsyncMultiSelect
128
124
  key={featuredContentPostType.value}
129
- help={__(
130
- 'Newest 30 items are shown, others can be selected by searching. If blank, all items are shown.',
131
- '%g_textdomain%',
132
- )}
125
+ help={__('Newest 30 items are shown, others can be selected by searching. If blank, all items are shown.', '%g_textdomain%')}
133
126
  value={featuredContentPosts}
134
127
  loadOptions={fetchFromWpRest(featuredContentPostType?.api, {
135
128
  processLabel: ({ title: { rendered } }) => rendered,
136
- noCache: true,
137
129
  })}
138
130
  onChange={(value) => setAttributes({ [getAttrKey('featuredContentPosts', attributes, manifest)]: value })}
139
131
  reFetchOnSearch
@@ -161,12 +153,10 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
161
153
  setUseSpecificPosts(false);
162
154
  setUseSpecificTerms(false);
163
155
 
164
- const value =
165
- rawValue === '_all' ? allGenericOption : taxonomyOptions.find((option) => option.value === rawValue);
156
+ const value = rawValue === '_all' ? allGenericOption : taxonomyOptions.find((option) => option.value === rawValue);
166
157
 
167
158
  setAttributes({
168
- [getAttrKey('featuredContentTaxonomy', attributes, manifest)]:
169
- value === allGenericOption ? undefined : value,
159
+ [getAttrKey('featuredContentTaxonomy', attributes, manifest)]: value === allGenericOption ? undefined : value,
170
160
  [getAttrKey('featuredContentTerms', attributes, manifest)]: undefined,
171
161
  [getAttrKey('featuredContentUseCurrentTerm', attributes, manifest)]: false,
172
162
  [getAttrKey('featuredContentPosts', attributes, manifest)]: undefined,
@@ -179,7 +169,7 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
179
169
 
180
170
  <OptionSelect
181
171
  aria-label={__('Select terms to show', '%g_textdomain%')}
182
- value={featuredContentUseCurrentTerm ? 'current' : useSpecificTerms ? 'manual' : 'all'}
172
+ value={termsToShow}
183
173
  onChange={(value) => {
184
174
  setUseSpecificTerms(value === 'manual');
185
175
  setAttributes({
@@ -192,6 +182,8 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
192
182
  {
193
183
  label: __('Select terms to show', '%g_textdomain%'),
194
184
  value: 'manual',
185
+ disabled: (featuredContentTaxonomy ?? allGenericOption)?.value === '_all',
186
+ subtitle: (featuredContentTaxonomy ?? allGenericOption)?.value === '_all' && __('Select a taxonomy to enable', '%g_textdomain%'),
195
187
  },
196
188
  {
197
189
  label: __('Show same terms as current post', '%g_textdomain%'),
@@ -208,16 +200,12 @@ export const FeaturedContentOptions = ({ attributes, setAttributes }) => {
208
200
  >
209
201
  <AsyncMultiSelect
210
202
  key={featuredContentTaxonomy?.value}
211
- help={__(
212
- 'Newest 30 items are shown, others can be selected by searching. If blank, all items are shown.',
213
- '%g_textdomain%',
214
- )}
203
+ help={__('Newest 30 items are shown, others can be selected by searching. If blank, all items are shown.', '%g_textdomain%')}
215
204
  value={featuredContentTerms}
216
205
  loadOptions={fetchFromWpRest(featuredContentTaxonomy?.api, {
217
206
  fields: 'id,name',
218
207
  processId: ({ id }) => id,
219
208
  processLabel: ({ name }) => name,
220
- noCache: true,
221
209
  })}
222
210
  onChange={(value) => setAttributes({ [getAttrKey('featuredContentTerms', attributes, manifest)]: value })}
223
211
  reFetchOnSearch
@@ -23,11 +23,11 @@ foreach ($items as $item) {
23
23
  class="group rounded-xl relative overflow-hidden w-full aspect-[0.875] bg-gradient-to-b from-gray-100 to-white shadow-md hover:shadow-lg transition duration-500 hover:duration-1000 border border-gray-200 <?php echo $hasEnterAnimation ? 'animate-in zoom-in-110 fade-in' : ''; ?>"
24
24
  >
25
25
  <?php if (!empty($featuredImage)) { ?>
26
- <img class="absolute inset-0 !size-full object-cover group-hover:scale-105 origin-bottom transition-transform duration-500 group-hover:duration-1000 pointer-events-none select-none" src="<?php echo esc_url($featuredImage); ?>" alt="">
27
- <div class=" absolute inset-0 backdrop-blur [mask-image:_linear-gradient(to_bottom,_transparent_5%,_black_50%)]"></div>
28
- <div class=" absolute inset-0 backdrop-blur-lg [mask-image:_linear-gradient(to_bottom,_transparent_20%,_black_100%)]"></div>
29
- <div class=" absolute inset-0 backdrop-blur-3xl [mask-image:_linear-gradient(to_bottom,_transparent_85%,_black_100%)]"></div>
30
- <div class="absolute inset-0 backdrop-saturate-[125%] backdrop-brightness-150"></div>
26
+ <img class="absolute inset-0 !size-full object-cover group-hover:scale-105 origin-bottom transition-transform duration-500 group-hover:duration-1000 pointer-events-none select-none" src="<?php echo esc_url($featuredImage); ?>" alt="" loading="lazy">
27
+ <div class="absolute inset-0 backdrop-blur [mask-image:_linear-gradient(to_bottom,_transparent_5%,_black_50%)]"></div>
28
+ <div class="absolute inset-0 backdrop-blur-lg [mask-image:_linear-gradient(to_bottom,_transparent_20%,_black_100%)]"></div>
29
+ <div class="absolute inset-0 backdrop-blur-3xl [mask-image:_linear-gradient(to_bottom,_transparent_85%,_black_100%)]"></div>
30
+ <div class="absolute inset-0 backdrop-saturate-[125%] backdrop-brightness-105"></div>
31
31
  <div class="absolute inset-0 bg-black/50 [&+div]:text-white [mask-image:_linear-gradient(to_bottom,_transparent_25%,_black_80%)]"></div>
32
32
  <?php } ?>
33
33
  <div class="flex flex-col justify-end p-6 absolute inset-0 group-hover:scale-[1.025] origin-bottom-left transition-transform duration-500 group-hover:duration-1000">
@@ -2,7 +2,5 @@ import { InnerBlocks } from '@wordpress/block-editor';
2
2
  import { BlockInserter } from '@eightshift/frontend-libs-tailwind/scripts';
3
3
 
4
4
  export const GroupEditor = ({ clientId }) => {
5
- return (
6
- <InnerBlocks renderAppender={() => <BlockInserter clientId={clientId} />} />
7
- );
5
+ return <InnerBlocks renderAppender={() => <BlockInserter clientId={clientId} />} />;
8
6
  };
@@ -10,6 +10,7 @@ export const transforms = {
10
10
  blocks: [`${manifest.namespace}/${manifestParagraph.blockName}`],
11
11
  transform: (attributes) => {
12
12
  let headingAttributes = {};
13
+
13
14
  for (const attribute in attributes) {
14
15
  if (attribute.startsWith('block')) {
15
16
  continue;
@@ -33,7 +33,6 @@ export class MapController {
33
33
  layers: parsedLayers.map((layer) => processMapLayer(layer)),
34
34
  view: view,
35
35
  interactions: OLDefaultInteractions(parsedInteractions).getArray(),
36
- // eslint-disable-next-line no-unused-vars
37
36
  controls: Object.entries(parsedControls)
38
37
  .filter(([_, v]) => v === true)
39
38
  .map(([name]) => processMapInteraction(name)),
@@ -1,6 +1,3 @@
1
- /* eslint-disable consistent-return */
2
- /* eslint-disable react-hooks/exhaustive-deps */
3
-
4
1
  import React, { createContext, useRef, useState, useEffect, useContext } from 'react';
5
2
  import { Map as OLMap, View } from 'ol';
6
3
  import { OSM, Vector as VectorSource, VectorTile as VectorTileSource, XYZ, TileJSON } from 'ol/source';
@@ -140,6 +137,7 @@ export const MapLayer = (props) => {
140
137
  }
141
138
  };
142
139
  }, [map]);
140
+
143
141
  return null;
144
142
  };
145
143
 
@@ -177,6 +175,7 @@ export const MapInteraction = (props) => {
177
175
  }
178
176
  };
179
177
  }, [map]);
178
+
180
179
  return null;
181
180
  };
182
181
 
@@ -251,6 +250,7 @@ export const MapControl = (props) => {
251
250
  }
252
251
  };
253
252
  }, [map]);
253
+
254
254
  return null;
255
255
  };
256
256
 
@@ -1,13 +1,5 @@
1
1
  import { checkAttr } from '@eightshift/frontend-libs-tailwind/scripts';
2
- import {
3
- Interactions,
4
- Layers,
5
- MapInteraction,
6
- OpenLayersMap,
7
- Controls,
8
- MapControl,
9
- processMapLayer,
10
- } from './map-components';
2
+ import { Interactions, Layers, MapInteraction, OpenLayersMap, Controls, MapControl, processMapLayer } from './map-components';
11
3
  import manifest from '../manifest.json';
12
4
 
13
5
  export const MapEditor = ({ attributes }) => {
@@ -25,9 +17,7 @@ export const MapEditor = ({ attributes }) => {
25
17
  center={[mapCenterLon ?? 16.352532, mapCenterLat ?? 46.314045]}
26
18
  zoom={mapZoom}
27
19
  >
28
- <Layers key={mapLayers.map(({ id, type }) => `${id}-${type}`).join(',')}>
29
- {[...mapLayers].reverse().map((layer) => processMapLayer(layer))}
30
- </Layers>
20
+ <Layers key={mapLayers.map(({ id, type }) => `${id}-${type}`).join(',')}>{[...mapLayers].reverse().map((layer) => processMapLayer(layer))}</Layers>
31
21
 
32
22
  <Interactions>
33
23
  <MapInteraction
@@ -111,33 +111,15 @@ export const MapOptions = ({ attributes, setAttributes }) => {
111
111
  {(layer) => {
112
112
  const { type, apiKey, geoJsonUrl, geoJsonId, styleUrl, hidden, updateData } = layer;
113
113
 
114
- const needsApiKey = [
115
- 'mapBoxVector',
116
- 'mapBoxRaster',
117
- 'mapTilerVector',
118
- 'vectorJson',
119
- 'mapTilerRasterXyz',
120
- 'mapTilerRasterJson',
121
- ].includes(type);
122
- // eslint-disable-next-line max-len
123
- const hasMapStyleOptions = [
124
- 'mapBoxVector',
125
- 'mapBoxRaster',
126
- 'mapTilerVector',
127
- 'vectorJson',
128
- 'mapTilerRasterXyz',
129
- 'mapTilerRasterJson',
130
- ].includes(type);
114
+ const needsApiKey = ['mapBoxVector', 'mapBoxRaster', 'mapTilerVector', 'vectorJson', 'mapTilerRasterXyz', 'mapTilerRasterJson'].includes(type);
115
+
116
+ const hasMapStyleOptions = ['mapBoxVector', 'mapBoxRaster', 'mapTilerVector', 'vectorJson', 'mapTilerRasterXyz', 'mapTilerRasterJson'].includes(type);
131
117
 
132
118
  return (
133
119
  <RepeaterItem
134
120
  icon={layer?.type ? layerTypes?.[layer?.type]?.icon ?? icons.mapLayer : icons.layerOff}
135
121
  label={layerTypes?.[type]?.title ?? __('New layer', '%g_textdomain%')}
136
- subtitle={
137
- type === 'geoJson'
138
- ? truncateMiddle(geoJsonUrl?.slice(geoJsonUrl?.lastIndexOf('/') + 1) ?? '', 20)
139
- : layerTypes?.[type]?.subtitle
140
- }
122
+ subtitle={type === 'geoJson' ? truncateMiddle(geoJsonUrl?.slice(geoJsonUrl?.lastIndexOf('/') + 1) ?? '', 20) : layerTypes?.[type]?.subtitle}
141
123
  actions={
142
124
  layer?.type?.length < 1 ? (
143
125
  icons.dummySpacer
@@ -178,30 +160,15 @@ export const MapOptions = ({ attributes, setAttributes }) => {
178
160
  onChange={(value) => updateData({ styleUrl: value })}
179
161
  help={
180
162
  <>
181
- {!type?.startsWith('mapBox') &&
182
- __(
183
- 'Copy the full style URL from MapTiler. Keep the API key inside the URL.',
184
- '%g_textdomain%',
185
- )}
163
+ {!type?.startsWith('mapBox') && __('Copy the full style URL from MapTiler. Keep the API key inside the URL.', '%g_textdomain%')}
186
164
  {type === 'mapBoxVector' && __('Copy the full style URL from Mapbox.', '%g_textdomain%')}
187
- {type === 'mapBoxRaster' &&
188
- // eslint-disable-next-line max-len
189
- __(
190
- 'Copy the full style URL from Mapbox or a Mapbox-compatible source. Keep the access token inside the URL.',
191
- '%g_textdomain%',
192
- )}
165
+ {type === 'mapBoxRaster' && __('Copy the full style URL from Mapbox or a Mapbox-compatible source. Keep the access token inside the URL.', '%g_textdomain%')}
193
166
  <br />
194
167
  <br />
195
168
  {['mapBoxRaster', 'mapTilerVector', 'mapTilerRasterXyz'].includes(type) && (
196
169
  <>
197
170
  <code className='es-bg-transparent es-p-0 es-text-3'>{'{z}/{x}/{y}'}</code>
198
- {
199
- // eslint-disable-next-line max-len
200
- __(
201
- "should be left as they are in the URL; they're needed for the map to work properly.",
202
- '%g_textdomain%',
203
- )
204
- }
171
+ {__("should be left as they are in the URL; they're needed for the map to work properly.", '%g_textdomain%')}
205
172
  <br />
206
173
  <br />
207
174
  </>
@@ -209,8 +176,7 @@ export const MapOptions = ({ attributes, setAttributes }) => {
209
176
  {__('Example', '%g_textdomain%')}:
210
177
  <br />
211
178
  <span className='es-word-break-all'>
212
- {['mapTilerRasterJson', 'vectorJson'].includes(type) &&
213
- 'https://api.maptiler.com/maps/{styleName}/tiles.json?key={apiKey}'}
179
+ {['mapTilerRasterJson', 'vectorJson'].includes(type) && 'https://api.maptiler.com/maps/{styleName}/tiles.json?key={apiKey}'}
214
180
 
215
181
  {type === 'mapTilerVector' && 'https://api.maptiler.com/tiles/v3/{z}/{x}/{y}.pbf?key={apiKey}'}
216
182
 
@@ -222,11 +188,9 @@ export const MapOptions = ({ attributes, setAttributes }) => {
222
188
  </>
223
189
  )}
224
190
 
225
- {type === 'mapBoxRaster' &&
226
- 'https://api.mapbox.com/v4/{tilesetId}/{z}/{x}/{y}[@2x].{imageFormat}?acess_token={apiKey}'}
191
+ {type === 'mapBoxRaster' && 'https://api.mapbox.com/v4/{tilesetId}/{z}/{x}/{y}[@2x].{imageFormat}?acess_token={apiKey}'}
227
192
 
228
- {type === 'mapTilerRasterXyz' &&
229
- 'https://api.maptiler.com/maps/{styleName}/{z}/{x}/{y}.png?key={apiKey}'}
193
+ {type === 'mapTilerRasterXyz' && 'https://api.maptiler.com/maps/{styleName}/{z}/{x}/{y}.png?key={apiKey}'}
230
194
  </span>
231
195
  </>
232
196
  }
@@ -10,6 +10,7 @@ export const transforms = {
10
10
  blocks: [`${globalManifest.namespace}/${manifestHeading.blockName}`],
11
11
  transform: (attributes) => {
12
12
  let paragraphAttributes = {};
13
+
13
14
  for (const attribute in attributes) {
14
15
  if (attribute.startsWith('block')) {
15
16
  continue;
@@ -57,9 +57,7 @@ export const SiteFooterOptions = ({ attributes, setAttributes, randId, setRandId
57
57
  return (
58
58
  <RepeaterItem
59
59
  label={header?.length > 0 ? header : __('New section', '%g_textdomain%')}
60
- subtitle={
61
- items.length > 0 && sprintf(_n('%d link', '%d links', items.length, '%g_textdomain%'), items.length)
62
- }
60
+ subtitle={items.length > 0 && sprintf(_n('%d link', '%d links', items.length, '%g_textdomain%'), items.length)}
63
61
  >
64
62
  <Repeater
65
63
  icon={icons.link}
@@ -31,7 +31,7 @@ export const TableOfContentsEditor = ({ attributes, setAttributes }) => {
31
31
  const DemoTocItem = ({ level, disabled }) => (
32
32
  <div class={clsx('group block select-none py-0.5 focus:outline-none', disabled && 'pointer-events-none opacity-25')}>
33
33
  {level > 1 && <span class='mr-1.5 tracking-tighter text-gray-300'>{'–'.repeat(level - 1)}</span>}
34
- <span class='group-focus-visible:text-navy-50px-0.5 rounded text-sm transition group-hover:bg-navy-100 group-hover:text-navy-950 group-hover:ring-4 group-hover:ring-navy-100 group-focus-visible:bg-navy-950 group-focus-visible:ring-4 group-focus-visible:ring-navy-950'>
34
+ <span class='group-focus-visible:text-navy-50px-0.5 group-hover:bg-navy-100 group-hover:text-navy-950 group-hover:ring-navy-100 group-focus-visible:bg-navy-950 group-focus-visible:ring-navy-950 rounded text-sm transition group-hover:ring-4 group-focus-visible:ring-4'>
35
35
  {sprintf(__('Heading %d', '%g_textdomain%'), level)}
36
36
  </span>
37
37
  </div>
@@ -5,10 +5,28 @@
5
5
  "foreground": "#0F766E",
6
6
  "globalVariables": {
7
7
  "breakpoints": {
8
- "mobile": 27,
9
- "tablet": 80,
10
- "desktop": 90,
11
- "large": 120
8
+ "sm": 40,
9
+ "md": 80,
10
+ "lg": 90,
11
+ "xl": 120
12
+ },
13
+ "breakpointData": {
14
+ "sm": {
15
+ "icon": "screenMobile",
16
+ "label": "Mobile"
17
+ },
18
+ "md": {
19
+ "icon": "screenTablet",
20
+ "label": "Tablet"
21
+ },
22
+ "lg": {
23
+ "icon": "screenDesktop",
24
+ "label": "Desktop"
25
+ },
26
+ "xl": {
27
+ "icon": "screenLarge",
28
+ "label": "Large"
29
+ }
12
30
  }
13
31
  }
14
32
  }
@@ -1,15 +1,6 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
  import { checkAttr, getAttrKey, getOption } from '@eightshift/frontend-libs-tailwind/scripts';
3
- import {
4
- BaseControl,
5
- ButtonGroup,
6
- ColorPicker,
7
- ContainerPanel,
8
- OptionSelect,
9
- Spacer,
10
- Responsive,
11
- InputField,
12
- } from '@eightshift/ui-components';
3
+ import { BaseControl, ButtonGroup, ColorPicker, ContainerPanel, OptionSelect, Spacer, Responsive, InputField } from '@eightshift/ui-components';
13
4
  import { icons } from '@eightshift/ui-components/icons';
14
5
  import { clsx } from '@eightshift/ui-components/utilities';
15
6
  import { getResponsiveData } from '@eightshift/frontend-libs-tailwind/scripts/helpers/breakpoints';
@@ -117,9 +108,7 @@ export const WrapperOptions = ({ attributes, setAttributes }) => {
117
108
  setAttributes({ [getAttrKey('wrapperBackground', attributes, manifest)]: undefined });
118
109
  } else {
119
110
  setAttributes({
120
- [getAttrKey('wrapperBackground', attributes, manifest)]: Object.keys(
121
- manifest.tailwind.options.wrapperBackground.twClasses,
122
- ).find((key) => key.startsWith(value)),
111
+ [getAttrKey('wrapperBackground', attributes, manifest)]: Object.keys(manifest.tailwind.options.wrapperBackground.twClasses).find((key) => key.startsWith(value)),
123
112
  });
124
113
  }
125
114
  }}
@@ -131,9 +120,7 @@ export const WrapperOptions = ({ attributes, setAttributes }) => {
131
120
  {backgroundType === 'solid' && (
132
121
  <ColorPicker
133
122
  colors={getColorOption('wrapperBackgroundSolid', manifest)}
134
- onChange={(value) =>
135
- setAttributes({ [getAttrKey('wrapperBackground', attributes, manifest)]: `solid-${value}` })
136
- }
123
+ onChange={(value) => setAttributes({ [getAttrKey('wrapperBackground', attributes, manifest)]: `solid-${value}` })}
137
124
  value={wrapperBackground?.replace('solid-', '')}
138
125
  aria-label={__('Background color', '%g_textdomain%')}
139
126
  />
@@ -170,9 +157,7 @@ export const WrapperOptions = ({ attributes, setAttributes }) => {
170
157
  />
171
158
  <OptionSelect
172
159
  value={wrapperGradientDirection}
173
- onChange={(value) =>
174
- setAttributes({ [getAttrKey('wrapperGradientDirection', attributes, manifest)]: value })
175
- }
160
+ onChange={(value) => setAttributes({ [getAttrKey('wrapperGradientDirection', attributes, manifest)]: value })}
176
161
  options={getOption('wrapperGradientDirection', attributes, manifest)}
177
162
  wrapperProps={{
178
163
  triggerIcon: <div className={rotationClassName[wrapperGradientDirection]}>{icons.arrowUpCircle}</div>,
@@ -4,10 +4,7 @@ import { WrapperOptions } from './components/wrapper-options';
4
4
 
5
5
  export const Wrapper = (props) => {
6
6
  const {
7
- props: {
8
- setAttributes,
9
- attributes,
10
- },
7
+ props: { setAttributes, attributes },
11
8
  children,
12
9
  } = props;
13
10
 
@@ -6,7 +6,7 @@ import globals from 'globals';
6
6
 
7
7
  export default [
8
8
  {
9
- ignores: ['**/dist/', 'public/'],
9
+ ignores: ['**/dist/', 'public/', 'node_modules/', 'vendor/', 'vendor-prefixed/'],
10
10
  },
11
11
  {
12
12
  files: ['**/*.js', '**/*.jsx'],