@eightshift/frontend-libs-tailwind 1.0.0
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.
- package/.gitattributes +37 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/CONTRIBUTING.md +17 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +10 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +10 -0
- package/.github/ISSUE_TEMPLATE/question.md +10 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +11 -0
- package/.github/workflows/ci.yml +31 -0
- package/.husky/pre-commit +1 -0
- package/.prettierrc +14 -0
- package/.stylelintrc +4 -0
- package/CHANGELOG.md +13 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/blocks/init/assets/application-admin.js +10 -0
- package/blocks/init/assets/application.js +13 -0
- package/blocks/init/assets/images/index.js +5 -0
- package/blocks/init/assets/scripts/application-admin.js +7 -0
- package/blocks/init/assets/scripts/application.js +3 -0
- package/blocks/init/assets/scripts/theme-colors.js +39 -0
- package/blocks/init/assets/styles/application-admin.css +6 -0
- package/blocks/init/assets/styles/application.css +3 -0
- package/blocks/init/src/Blocks/assets/application-blocks-editor.js +14 -0
- package/blocks/init/src/Blocks/assets/application-blocks-frontend.js +13 -0
- package/blocks/init/src/Blocks/assets/application-blocks.js +9 -0
- package/blocks/init/src/Blocks/assets/scripts/application-blocks-editor.js +65 -0
- package/blocks/init/src/Blocks/assets/scripts/application-blocks-frontend.js +24 -0
- package/blocks/init/src/Blocks/assets/scripts/link-section-editor.js +258 -0
- package/blocks/init/src/Blocks/assets/scripts/shared.js +25 -0
- package/blocks/init/src/Blocks/assets/styles/application-blocks-editor.css +15 -0
- package/blocks/init/src/Blocks/assets/styles/application-blocks-frontend.css +12 -0
- package/blocks/init/src/Blocks/assets/styles/application-blocks.css +0 -0
- package/blocks/init/src/Blocks/assets/styles/editor/editor-overrides.css +15 -0
- package/blocks/init/src/Blocks/assets/styles/tailwind.css +34 -0
- package/blocks/init/src/Blocks/components/admin-theme-options/admin-theme-options.php +20 -0
- package/blocks/init/src/Blocks/components/admin-theme-options/assets-admin/index.js +36 -0
- package/blocks/init/src/Blocks/components/admin-theme-options/assets-admin/pages/parts.js +55 -0
- package/blocks/init/src/Blocks/components/admin-theme-options/manifest.json +5 -0
- package/blocks/init/src/Blocks/components/button/assets/index.js +22 -0
- package/blocks/init/src/Blocks/components/button/button.php +77 -0
- package/blocks/init/src/Blocks/components/button/components/button-editor.js +40 -0
- package/blocks/init/src/Blocks/components/button/components/button-options.js +135 -0
- package/blocks/init/src/Blocks/components/button/manifest.json +299 -0
- package/blocks/init/src/Blocks/components/card/card.php +42 -0
- package/blocks/init/src/Blocks/components/card/components/card-editor.js +39 -0
- package/blocks/init/src/Blocks/components/card/components/card-options.js +56 -0
- package/blocks/init/src/Blocks/components/card/manifest.json +111 -0
- package/blocks/init/src/Blocks/components/head/head.php +52 -0
- package/blocks/init/src/Blocks/components/head/manifest.json +17 -0
- package/blocks/init/src/Blocks/components/heading/components/heading-editor.js +30 -0
- package/blocks/init/src/Blocks/components/heading/components/heading-options.js +62 -0
- package/blocks/init/src/Blocks/components/heading/heading.php +45 -0
- package/blocks/init/src/Blocks/components/heading/manifest.json +76 -0
- package/blocks/init/src/Blocks/components/hero/components/hero-editor.js +42 -0
- package/blocks/init/src/Blocks/components/hero/components/hero-options.js +100 -0
- package/blocks/init/src/Blocks/components/hero/hero.php +45 -0
- package/blocks/init/src/Blocks/components/hero/manifest.json +96 -0
- package/blocks/init/src/Blocks/components/icon/components/icon-editor.js +23 -0
- package/blocks/init/src/Blocks/components/icon/components/icon-options.js +65 -0
- package/blocks/init/src/Blocks/components/icon/icon.php +34 -0
- package/blocks/init/src/Blocks/components/icon/manifest.json +1234 -0
- package/blocks/init/src/Blocks/components/image/components/image-editor.js +65 -0
- package/blocks/init/src/Blocks/components/image/components/image-options.js +111 -0
- package/blocks/init/src/Blocks/components/image/image.php +62 -0
- package/blocks/init/src/Blocks/components/image/manifest.json +125 -0
- package/blocks/init/src/Blocks/components/list/components/list-editor.js +30 -0
- package/blocks/init/src/Blocks/components/list/components/list-options.js +62 -0
- package/blocks/init/src/Blocks/components/list/list.php +32 -0
- package/blocks/init/src/Blocks/components/list/manifest.json +127 -0
- package/blocks/init/src/Blocks/components/load-more/assets/index.js +19 -0
- package/blocks/init/src/Blocks/components/load-more/assets/load-more.js +147 -0
- package/blocks/init/src/Blocks/components/load-more/components/load-more-editor.js +14 -0
- package/blocks/init/src/Blocks/components/load-more/components/load-more-options.js +18 -0
- package/blocks/init/src/Blocks/components/load-more/load-more.php +47 -0
- package/blocks/init/src/Blocks/components/load-more/manifest.json +39 -0
- package/blocks/init/src/Blocks/components/modal/assets/index.js +27 -0
- package/blocks/init/src/Blocks/components/modal/manifest.json +48 -0
- package/blocks/init/src/Blocks/components/modal/modal.php +46 -0
- package/blocks/init/src/Blocks/components/paragraph/components/paragraph-editor.js +40 -0
- package/blocks/init/src/Blocks/components/paragraph/components/paragraph-options.js +48 -0
- package/blocks/init/src/Blocks/components/paragraph/manifest.json +83 -0
- package/blocks/init/src/Blocks/components/paragraph/paragraph.php +33 -0
- package/blocks/init/src/Blocks/components/post-header/manifest.json +5 -0
- package/blocks/init/src/Blocks/components/post-header/post-header.php +24 -0
- package/blocks/init/src/Blocks/components/quote/components/quote-editor.js +53 -0
- package/blocks/init/src/Blocks/components/quote/components/quote-options.js +29 -0
- package/blocks/init/src/Blocks/components/quote/manifest.json +47 -0
- package/blocks/init/src/Blocks/components/quote/quote.php +49 -0
- package/blocks/init/src/Blocks/components/share/assets/index.js +39 -0
- package/blocks/init/src/Blocks/components/share/components/share-editor.js +25 -0
- package/blocks/init/src/Blocks/components/share/components/share-options.js +112 -0
- package/blocks/init/src/Blocks/components/share/manifest.json +72 -0
- package/blocks/init/src/Blocks/components/share/share.php +66 -0
- package/blocks/init/src/Blocks/components/tracking-before-body-end/manifest.json +5 -0
- package/blocks/init/src/Blocks/components/tracking-before-body-end/tracking-before-body-end.php +9 -0
- package/blocks/init/src/Blocks/components/tracking-head/manifest.json +5 -0
- package/blocks/init/src/Blocks/components/tracking-head/tracking-head.php +9 -0
- package/blocks/init/src/Blocks/components/video/components/video-editor.js +74 -0
- package/blocks/init/src/Blocks/components/video/components/video-options.js +280 -0
- package/blocks/init/src/Blocks/components/video/manifest.json +116 -0
- package/blocks/init/src/Blocks/components/video/video.php +72 -0
- package/blocks/init/src/Blocks/custom/accordion/accordion-block.js +15 -0
- package/blocks/init/src/Blocks/custom/accordion/accordion.php +28 -0
- package/blocks/init/src/Blocks/custom/accordion/assets/index.js +37 -0
- package/blocks/init/src/Blocks/custom/accordion/components/accordion-editor.js +17 -0
- package/blocks/init/src/Blocks/custom/accordion/components/accordion-options.js +18 -0
- package/blocks/init/src/Blocks/custom/accordion/manifest.json +32 -0
- package/blocks/init/src/Blocks/custom/accordion-item/accordion-item-block.js +19 -0
- package/blocks/init/src/Blocks/custom/accordion-item/accordion-item.php +46 -0
- package/blocks/init/src/Blocks/custom/accordion-item/components/accordion-item-editor.js +60 -0
- package/blocks/init/src/Blocks/custom/accordion-item/manifest.json +69 -0
- package/blocks/init/src/Blocks/custom/button/button-block.js +13 -0
- package/blocks/init/src/Blocks/custom/button/button.php +11 -0
- package/blocks/init/src/Blocks/custom/button/components/button-editor.js +12 -0
- package/blocks/init/src/Blocks/custom/button/components/button-options.js +12 -0
- package/blocks/init/src/Blocks/custom/button/manifest.json +18 -0
- package/blocks/init/src/Blocks/custom/card/card-block.js +13 -0
- package/blocks/init/src/Blocks/custom/card/card.php +11 -0
- package/blocks/init/src/Blocks/custom/card/components/card-editor.js +12 -0
- package/blocks/init/src/Blocks/custom/card/components/card-options.js +15 -0
- package/blocks/init/src/Blocks/custom/card/manifest.json +18 -0
- package/blocks/init/src/Blocks/custom/carousel/assets/index.js +46 -0
- package/blocks/init/src/Blocks/custom/carousel/assets/navigation.js +31 -0
- package/blocks/init/src/Blocks/custom/carousel/assets/pagination.js +39 -0
- package/blocks/init/src/Blocks/custom/carousel/carousel-block.js +21 -0
- package/blocks/init/src/Blocks/custom/carousel/carousel.php +61 -0
- package/blocks/init/src/Blocks/custom/carousel/components/carousel-editor.js +25 -0
- package/blocks/init/src/Blocks/custom/carousel/components/carousel-options.js +47 -0
- package/blocks/init/src/Blocks/custom/carousel/manifest.json +130 -0
- package/blocks/init/src/Blocks/custom/column/column-block.js +21 -0
- package/blocks/init/src/Blocks/custom/column/column-hooks.js +32 -0
- package/blocks/init/src/Blocks/custom/column/column.php +21 -0
- package/blocks/init/src/Blocks/custom/column/components/column-editor.js +19 -0
- package/blocks/init/src/Blocks/custom/column/components/column-options.js +579 -0
- package/blocks/init/src/Blocks/custom/column/manifest.json +625 -0
- package/blocks/init/src/Blocks/custom/columns/columns-block.js +20 -0
- package/blocks/init/src/Blocks/custom/columns/columns.php +21 -0
- package/blocks/init/src/Blocks/custom/columns/components/columns-editor.js +81 -0
- package/blocks/init/src/Blocks/custom/columns/components/columns-options.js +104 -0
- package/blocks/init/src/Blocks/custom/columns/manifest.json +555 -0
- package/blocks/init/src/Blocks/custom/featured-content/components/featured-content-editor.js +28 -0
- package/blocks/init/src/Blocks/custom/featured-content/components/featured-content-options.js +239 -0
- package/blocks/init/src/Blocks/custom/featured-content/featured-content-block.js +13 -0
- package/blocks/init/src/Blocks/custom/featured-content/featured-content.php +139 -0
- package/blocks/init/src/Blocks/custom/featured-content/manifest.json +131 -0
- package/blocks/init/src/Blocks/custom/featured-content/partials/cards.php +39 -0
- package/blocks/init/src/Blocks/custom/group/components/group-editor.js +8 -0
- package/blocks/init/src/Blocks/custom/group/group-block.js +14 -0
- package/blocks/init/src/Blocks/custom/group/group.php +10 -0
- package/blocks/init/src/Blocks/custom/group/manifest.json +32 -0
- package/blocks/init/src/Blocks/custom/heading/components/heading-editor.js +15 -0
- package/blocks/init/src/Blocks/custom/heading/components/heading-options.js +38 -0
- package/blocks/init/src/Blocks/custom/heading/heading-block.js +13 -0
- package/blocks/init/src/Blocks/custom/heading/heading-transforms.js +25 -0
- package/blocks/init/src/Blocks/custom/heading/heading.php +15 -0
- package/blocks/init/src/Blocks/custom/heading/manifest.json +79 -0
- package/blocks/init/src/Blocks/custom/hero/components/hero-editor.js +12 -0
- package/blocks/init/src/Blocks/custom/hero/components/hero-options.js +14 -0
- package/blocks/init/src/Blocks/custom/hero/hero-block.js +13 -0
- package/blocks/init/src/Blocks/custom/hero/hero.php +11 -0
- package/blocks/init/src/Blocks/custom/hero/manifest.json +17 -0
- package/blocks/init/src/Blocks/custom/image/components/image-editor.js +12 -0
- package/blocks/init/src/Blocks/custom/image/components/image-options.js +14 -0
- package/blocks/init/src/Blocks/custom/image/image-block.js +13 -0
- package/blocks/init/src/Blocks/custom/image/image.php +11 -0
- package/blocks/init/src/Blocks/custom/image/manifest.json +105 -0
- package/blocks/init/src/Blocks/custom/list/components/list-editor.js +14 -0
- package/blocks/init/src/Blocks/custom/list/components/list-options.js +39 -0
- package/blocks/init/src/Blocks/custom/list/list-block.js +13 -0
- package/blocks/init/src/Blocks/custom/list/list.php +15 -0
- package/blocks/init/src/Blocks/custom/list/manifest.json +58 -0
- package/blocks/init/src/Blocks/custom/map/assets/index.js +20 -0
- package/blocks/init/src/Blocks/custom/map/assets/map-controller.js +42 -0
- package/blocks/init/src/Blocks/custom/map/assets/utils.js +161 -0
- package/blocks/init/src/Blocks/custom/map/components/map-components.js +403 -0
- package/blocks/init/src/Blocks/custom/map/components/map-editor.js +56 -0
- package/blocks/init/src/Blocks/custom/map/components/map-options.js +557 -0
- package/blocks/init/src/Blocks/custom/map/manifest.json +79 -0
- package/blocks/init/src/Blocks/custom/map/map-block.js +13 -0
- package/blocks/init/src/Blocks/custom/map/map.php +52 -0
- package/blocks/init/src/Blocks/custom/map/styles.css +2 -0
- package/blocks/init/src/Blocks/custom/modal/components/modal-editor.js +90 -0
- package/blocks/init/src/Blocks/custom/modal/manifest.json +51 -0
- package/blocks/init/src/Blocks/custom/modal/modal-block.js +14 -0
- package/blocks/init/src/Blocks/custom/modal/modal.php +20 -0
- package/blocks/init/src/Blocks/custom/paragraph/components/paragraph-editor.js +41 -0
- package/blocks/init/src/Blocks/custom/paragraph/components/paragraph-options.js +38 -0
- package/blocks/init/src/Blocks/custom/paragraph/manifest.json +79 -0
- package/blocks/init/src/Blocks/custom/paragraph/paragraph-block.js +13 -0
- package/blocks/init/src/Blocks/custom/paragraph/paragraph-transforms.js +45 -0
- package/blocks/init/src/Blocks/custom/paragraph/paragraph.php +15 -0
- package/blocks/init/src/Blocks/custom/quote/components/quote-editor.js +12 -0
- package/blocks/init/src/Blocks/custom/quote/components/quote-options.js +14 -0
- package/blocks/init/src/Blocks/custom/quote/manifest.json +17 -0
- package/blocks/init/src/Blocks/custom/quote/quote-block.js +13 -0
- package/blocks/init/src/Blocks/custom/quote/quote.php +13 -0
- package/blocks/init/src/Blocks/custom/share/components/share-editor.js +6 -0
- package/blocks/init/src/Blocks/custom/share/components/share-options.js +12 -0
- package/blocks/init/src/Blocks/custom/share/manifest.json +19 -0
- package/blocks/init/src/Blocks/custom/share/share-block.js +13 -0
- package/blocks/init/src/Blocks/custom/share/share.php +11 -0
- package/blocks/init/src/Blocks/custom/site-footer/components/site-footer-editor.js +57 -0
- package/blocks/init/src/Blocks/custom/site-footer/components/site-footer-options.js +106 -0
- package/blocks/init/src/Blocks/custom/site-footer/manifest.json +73 -0
- package/blocks/init/src/Blocks/custom/site-footer/site-footer-block.js +13 -0
- package/blocks/init/src/Blocks/custom/site-footer/site-footer.php +72 -0
- package/blocks/init/src/Blocks/custom/site-navigation/assets/index.js +9 -0
- package/blocks/init/src/Blocks/custom/site-navigation/components/site-navigation-editor.js +42 -0
- package/blocks/init/src/Blocks/custom/site-navigation/components/site-navigation-options.js +73 -0
- package/blocks/init/src/Blocks/custom/site-navigation/manifest.json +77 -0
- package/blocks/init/src/Blocks/custom/site-navigation/site-navigation-block.js +13 -0
- package/blocks/init/src/Blocks/custom/site-navigation/site-navigation.php +99 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/assets/index.js +58 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/components/table-of-contents-editor.js +38 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/components/table-of-contents-options.js +32 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/manifest.json +48 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/table-of-contents-block.js +13 -0
- package/blocks/init/src/Blocks/custom/table-of-contents/table-of-contents.php +31 -0
- package/blocks/init/src/Blocks/custom/video/components/video-editor.js +6 -0
- package/blocks/init/src/Blocks/custom/video/components/video-options.js +12 -0
- package/blocks/init/src/Blocks/custom/video/manifest.json +105 -0
- package/blocks/init/src/Blocks/custom/video/video-block.js +13 -0
- package/blocks/init/src/Blocks/custom/video/video.php +22 -0
- package/blocks/init/src/Blocks/manifest.json +14 -0
- package/blocks/init/src/Blocks/variations/card-simple/manifest.json +17 -0
- package/blocks/init/src/Blocks/wrapper/components/wrapper-editor.js +12 -0
- package/blocks/init/src/Blocks/wrapper/components/wrapper-options.js +348 -0
- package/blocks/init/src/Blocks/wrapper/manifest.json +450 -0
- package/blocks/init/src/Blocks/wrapper/styles-editor.css +13 -0
- package/blocks/init/src/Blocks/wrapper/styles.css +19 -0
- package/blocks/init/src/Blocks/wrapper/wrapper.js +30 -0
- package/blocks/init/src/Blocks/wrapper/wrapper.php +34 -0
- package/eslint.config.mjs +3 -0
- package/linters/base.config.mjs +81 -0
- package/linters/eslint.config.mjs +4 -0
- package/linters/ignore-gitignored.mjs +9 -0
- package/linters/stylelint.config.js +146 -0
- package/package.json +93 -0
- package/readme/packages.md +74 -0
- package/schemas/block.json +302 -0
- package/schemas/component.json +240 -0
- package/schemas/globalManifest.json +73 -0
- package/schemas/variation.json +83 -0
- package/scripts/components/block-inserter.js +70 -0
- package/scripts/components/file-picker.js +243 -0
- package/scripts/components/index.js +6 -0
- package/scripts/components/link-section-editor.js +319 -0
- package/scripts/components/media-picker.js +86 -0
- package/scripts/components/server-side-render.js +37 -0
- package/scripts/components/settings/settings.js +48 -0
- package/scripts/components/settings/use-theme-options.js +52 -0
- package/scripts/editor/attributes.js +304 -0
- package/scripts/editor/colors.js +64 -0
- package/scripts/editor/editor.js +139 -0
- package/scripts/editor/fetch.js +102 -0
- package/scripts/editor/hooks.js +44 -0
- package/scripts/editor/index.js +11 -0
- package/scripts/editor/options.js +152 -0
- package/scripts/editor/registration.js +901 -0
- package/scripts/editor/store.js +213 -0
- package/scripts/editor/tailwindcss.js +224 -0
- package/scripts/editor/utility.js +47 -0
- package/scripts/helpers/breakpoints.js +48 -0
- package/scripts/helpers/cookies.js +65 -0
- package/scripts/helpers/dynamic-import.js +19 -0
- package/scripts/helpers/index.js +11 -0
- package/scripts/index.js +22 -0
- package/scripts/plugins/index.js +3 -0
- package/scripts/plugins/yoast-seo.js +70 -0
- package/webpack/base.mjs +138 -0
- package/webpack/helpers.mjs +67 -0
- package/webpack/index.mjs +52 -0
- package/webpack/production.mjs +60 -0
- package/webpack/project.mjs +55 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Based on https://developer.wordpress.org/news/2024/03/26/how-to-use-wordpress-react-components-for-plugin-pages/
|
|
2
|
+
|
|
3
|
+
import { Toaster } from 'sonner';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import { Button, HStack } from '@eightshift/ui-components';
|
|
6
|
+
import { icons } from '@eightshift/ui-components/icons';
|
|
7
|
+
import { createContext } from '@wordpress/element';
|
|
8
|
+
import { clsx } from '@eightshift/ui-components/utilities';
|
|
9
|
+
import { useThemeOptions } from './use-theme-options';
|
|
10
|
+
|
|
11
|
+
export const EsThemeOptionsContext = createContext(null);
|
|
12
|
+
|
|
13
|
+
export const ThemeOptionsPage = ({
|
|
14
|
+
title = __('Theme options', '%g_textdomain%'),
|
|
15
|
+
children,
|
|
16
|
+
settingName = 'eightshift-theme-options',
|
|
17
|
+
}) => {
|
|
18
|
+
const themeOptions = useThemeOptions(settingName);
|
|
19
|
+
const { isLoading, saveSettings } = themeOptions;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<EsThemeOptionsContext.Provider value={themeOptions}>
|
|
23
|
+
<Toaster richColors />
|
|
24
|
+
<div
|
|
25
|
+
className={clsx(
|
|
26
|
+
'es-uic-space-y-4',
|
|
27
|
+
isLoading && 'es-uic-pointer-events-none es-uic-opacity-60'
|
|
28
|
+
)}
|
|
29
|
+
>
|
|
30
|
+
<HStack className='es-uic-justify-between'>
|
|
31
|
+
<h1>{title}</h1>
|
|
32
|
+
|
|
33
|
+
<Button
|
|
34
|
+
onPress={() => saveSettings()}
|
|
35
|
+
disabled={isLoading}
|
|
36
|
+
icon={isLoading ? icons.moreH : icons.save}
|
|
37
|
+
>
|
|
38
|
+
{isLoading
|
|
39
|
+
? __('Saving...', '%g_textdomain%')
|
|
40
|
+
: __('Save', '%g_textdomain%')}
|
|
41
|
+
</Button>
|
|
42
|
+
</HStack>
|
|
43
|
+
|
|
44
|
+
{children}
|
|
45
|
+
</div>
|
|
46
|
+
</EsThemeOptionsContext.Provider>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { __ } from '@wordpress/i18n';
|
|
2
|
+
import { useState, useEffect } from '@wordpress/element';
|
|
3
|
+
import { toast } from 'sonner';
|
|
4
|
+
import apiFetch from '@wordpress/api-fetch';
|
|
5
|
+
|
|
6
|
+
export const useThemeOptions = (settingName) => {
|
|
7
|
+
const [settings, setSettings] = useState();
|
|
8
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
9
|
+
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
apiFetch({ path: '/wp/v2/settings' }).then((settings) => {
|
|
12
|
+
setSettings(settings?.[settingName]);
|
|
13
|
+
});
|
|
14
|
+
}, []);
|
|
15
|
+
|
|
16
|
+
const saveSettings = async () => {
|
|
17
|
+
setIsLoading(true);
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await apiFetch({
|
|
21
|
+
path: '/wp/v2/settings',
|
|
22
|
+
method: 'POST',
|
|
23
|
+
data: {
|
|
24
|
+
[settingName]: settings,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
toast.success(__('Saved successfully', '%g_textdomain%'));
|
|
29
|
+
} catch (error) {
|
|
30
|
+
toast.error(__('Something went wrong while saving', '%g_textdomain%'), {
|
|
31
|
+
description: error.message,
|
|
32
|
+
});
|
|
33
|
+
} finally {
|
|
34
|
+
setIsLoading(false);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const updateSettings = (modified) => {
|
|
39
|
+
setSettings((prev) => ({
|
|
40
|
+
...prev,
|
|
41
|
+
...modified,
|
|
42
|
+
}));
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
isLoading,
|
|
47
|
+
settings,
|
|
48
|
+
saveSettings,
|
|
49
|
+
setSettings,
|
|
50
|
+
updateSettings,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { camelCase, isEmpty, lowerFirst, upperFirst } from '@eightshift/ui-components/utilities';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sets attributes on all `innerBlocks`. This value will be stored in the Block editor store and set to a block.
|
|
5
|
+
*
|
|
6
|
+
* @param {function} select State function.
|
|
7
|
+
* @param {string} clientId Unique block ID from block editor.
|
|
8
|
+
* @param {object} attributesObject Object of attributes to apply.
|
|
9
|
+
* @param {array} exclude Array of block names to exclude.
|
|
10
|
+
*
|
|
11
|
+
* @access public
|
|
12
|
+
*
|
|
13
|
+
* @returns {void}
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```js
|
|
17
|
+
* import { useSelect } from '@wordpress/data';
|
|
18
|
+
*
|
|
19
|
+
* useSelect((select) => {
|
|
20
|
+
* overrideInnerBlockAttributes(
|
|
21
|
+
* select,
|
|
22
|
+
* props.clientId,
|
|
23
|
+
* {
|
|
24
|
+
* wrapperUse: false,
|
|
25
|
+
* wrapperNoControls: true,
|
|
26
|
+
* }
|
|
27
|
+
* );
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export const overrideInnerBlockAttributes = (select, clientId, attributesObject = {}, exclude = []) => {
|
|
32
|
+
const { getBlock } = select('core/block-editor');
|
|
33
|
+
|
|
34
|
+
const block = getBlock(clientId);
|
|
35
|
+
|
|
36
|
+
block.innerBlocks.map((item) => {
|
|
37
|
+
const {
|
|
38
|
+
attributes,
|
|
39
|
+
name,
|
|
40
|
+
} = item;
|
|
41
|
+
|
|
42
|
+
if (!exclude.includes(name)) {
|
|
43
|
+
for (const attribute in attributesObject) {
|
|
44
|
+
if (Object.prototype.hasOwnProperty.call(attributesObject, attribute)) {
|
|
45
|
+
if (attribute !== attributes[attribute]) {
|
|
46
|
+
attributes[attribute] = attributesObject[attribute];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return item;
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check if attribute exist in attributes list and add default value if not.
|
|
58
|
+
* This is used because Block editor will not output attributes that don't have default value.
|
|
59
|
+
*
|
|
60
|
+
* @param {string} key - Key to check.
|
|
61
|
+
* @param {array} attributes - Array of attributes.
|
|
62
|
+
* @param {object} manifest - Components/blocks manifest.json
|
|
63
|
+
* @param {boolean} [undefinedAllowed=false] - Allowed detection of undefined values.
|
|
64
|
+
*
|
|
65
|
+
* @access public
|
|
66
|
+
*
|
|
67
|
+
* @return {mixed} Based on the attribute type.
|
|
68
|
+
* Boolean - false
|
|
69
|
+
* String - ''
|
|
70
|
+
* Object - {}
|
|
71
|
+
* Array - []
|
|
72
|
+
*
|
|
73
|
+
* Manifest:
|
|
74
|
+
* ```js
|
|
75
|
+
* {
|
|
76
|
+
* "attributes": {
|
|
77
|
+
* "buttonUse": {
|
|
78
|
+
* "type": "boolean"
|
|
79
|
+
* },
|
|
80
|
+
* },
|
|
81
|
+
* "buttonContent": {
|
|
82
|
+
* "type": "string"
|
|
83
|
+
* },
|
|
84
|
+
* }
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* Usage:
|
|
89
|
+
* ```js
|
|
90
|
+
* checkAttr('buttonUse', attributes, manifest);
|
|
91
|
+
* checkAttr('buttonContent', attributes, manifest);
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* Output:
|
|
95
|
+
* ```js
|
|
96
|
+
* false
|
|
97
|
+
* ''
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export const checkAttr = (key, attributes, manifest, undefinedAllowed = false) => {
|
|
101
|
+
// Get the correct key for the check in the attributes object.
|
|
102
|
+
const newKey = getAttrKey(key, attributes, manifest);
|
|
103
|
+
|
|
104
|
+
// If key exists in the attributes object, just return that key value.
|
|
105
|
+
if (Object.prototype.hasOwnProperty.call(attributes, newKey)) {
|
|
106
|
+
return attributes[newKey];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check current component attributes.
|
|
110
|
+
const manifestKey = manifest.attributes[key];
|
|
111
|
+
|
|
112
|
+
let tipOutput = '';
|
|
113
|
+
|
|
114
|
+
if ('components' in manifest) {
|
|
115
|
+
tipOutput = ' If you are using additional components, check if you used the correct block/component prefix in your attribute name.';
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Bailout if key is missing.
|
|
119
|
+
if (typeof manifestKey === 'undefined') {
|
|
120
|
+
if ('blockName' in manifest) {
|
|
121
|
+
throw Error(`${key} key does not exist in the ${manifest.blockName} block manifest. Please check your implementation.${tipOutput}`);
|
|
122
|
+
} else {
|
|
123
|
+
throw Error(`${key} key does not exist in the ${manifest.componentName} component manifest. Please check your implementation.${tipOutput}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// If undefinedAllowed is true and attribute is missing default just return undefined to be able to unset attribute in block editor.
|
|
128
|
+
if (!Object.prototype.hasOwnProperty.call(manifestKey, 'default') && undefinedAllowed) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Check type.
|
|
133
|
+
const defaultType = manifestKey.type;
|
|
134
|
+
|
|
135
|
+
let defaultValue;
|
|
136
|
+
|
|
137
|
+
// Output "default values" if none are defined.
|
|
138
|
+
switch (defaultType) {
|
|
139
|
+
case 'boolean':
|
|
140
|
+
defaultValue = Object.prototype.hasOwnProperty.call(manifestKey, 'default') ? manifestKey.default : false;
|
|
141
|
+
break;
|
|
142
|
+
case 'array':
|
|
143
|
+
defaultValue = Object.prototype.hasOwnProperty.call(manifestKey, 'default') ? manifestKey.default : [];
|
|
144
|
+
break;
|
|
145
|
+
case 'object':
|
|
146
|
+
defaultValue = Object.prototype.hasOwnProperty.call(manifestKey, 'default') ? manifestKey.default : {};
|
|
147
|
+
break;
|
|
148
|
+
default:
|
|
149
|
+
defaultValue = Object.prototype.hasOwnProperty.call(manifestKey, 'default') ? manifestKey.default : '';
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return defaultValue;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check if attributes key has prefix and outputs the correct attribute name.
|
|
158
|
+
*
|
|
159
|
+
* @param {string} key - Key to check.
|
|
160
|
+
* @param {array} attributes - Array of attributes.
|
|
161
|
+
* @param {object} manifest - Components/blocks manifest.json
|
|
162
|
+
*
|
|
163
|
+
* @access public
|
|
164
|
+
*
|
|
165
|
+
* @return string
|
|
166
|
+
*/
|
|
167
|
+
export const getAttrKey = (key, attributes, manifest) => {
|
|
168
|
+
// Just skip if attribute is wrapper.
|
|
169
|
+
if (key.includes('wrapper')) {
|
|
170
|
+
return key;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Skip if using this helper in block.
|
|
174
|
+
if (typeof manifest?.blockName !== 'undefined') {
|
|
175
|
+
return key;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// If missing prefix or prefix is empty return key.
|
|
179
|
+
if (typeof attributes?.prefix === 'undefined' || attributes?.prefix === '') {
|
|
180
|
+
return key;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// No need to test if this is block or component because on top level block there is no prefix.
|
|
184
|
+
// If there is a prefix, remove the attribute component name prefix and replace it with the new prefix.
|
|
185
|
+
return key.replace(camelCase(manifest.componentName), attributes.prefix);
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Output only attributes that are used in the component and remove everything else.
|
|
190
|
+
*
|
|
191
|
+
* @param {string} newName - *New* key to use to rename attributes.
|
|
192
|
+
* @param {object} attributes - Attributes from the block/component.
|
|
193
|
+
* @param {object} [manual={}] - Object of attributes to change key and merge to the original output.
|
|
194
|
+
*
|
|
195
|
+
* @access public
|
|
196
|
+
*
|
|
197
|
+
* @returns {object}
|
|
198
|
+
*
|
|
199
|
+
* Manifest:
|
|
200
|
+
* ```js
|
|
201
|
+
* const attributes = {
|
|
202
|
+
* buttonColor: 'red',
|
|
203
|
+
* buttonSize: 'big',
|
|
204
|
+
* buttonIcon: 'blue',
|
|
205
|
+
* blockName: 'button',
|
|
206
|
+
* wrapperSize: 'big',
|
|
207
|
+
* wrapperType: 'normal',
|
|
208
|
+
* };
|
|
209
|
+
* ```
|
|
210
|
+
*
|
|
211
|
+
* Usage:
|
|
212
|
+
* ```js
|
|
213
|
+
* {...props('button', attributes)}
|
|
214
|
+
* ```
|
|
215
|
+
*
|
|
216
|
+
* Output:
|
|
217
|
+
* ```js
|
|
218
|
+
* {
|
|
219
|
+
* buttonColor: 'red',
|
|
220
|
+
* buttonSize: 'big',
|
|
221
|
+
* buttonIcon: 'blue',
|
|
222
|
+
* blockName: 'button',
|
|
223
|
+
* };
|
|
224
|
+
* ```
|
|
225
|
+
*
|
|
226
|
+
* Additional keys that are passed are defined in the includes array.
|
|
227
|
+
*/
|
|
228
|
+
export const props = (newName, attributes, manual = {}) => {
|
|
229
|
+
|
|
230
|
+
const output = {};
|
|
231
|
+
|
|
232
|
+
// Check which attributes we need to include.
|
|
233
|
+
const includes = [
|
|
234
|
+
'blockName',
|
|
235
|
+
'blockClientId',
|
|
236
|
+
'blockTopLevelId',
|
|
237
|
+
'blockFullName',
|
|
238
|
+
'blockClass',
|
|
239
|
+
'blockJsClass',
|
|
240
|
+
'componentJsClass',
|
|
241
|
+
'selectorClass',
|
|
242
|
+
'additionalClass',
|
|
243
|
+
'setAttributes',
|
|
244
|
+
'uniqueWrapperId',
|
|
245
|
+
'options',
|
|
246
|
+
'clientId',
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
// Check if in test mode and use different setting.
|
|
250
|
+
const blockName = process.env.NODE_ENV === 'test' ? attributes.blockName.default : attributes.blockName;
|
|
251
|
+
|
|
252
|
+
// Populate prefix key for recursive checks of attribute names.
|
|
253
|
+
const prefix = (typeof attributes.prefix === 'undefined') ? camelCase(blockName) : attributes['prefix'];
|
|
254
|
+
|
|
255
|
+
// Set component prefix.
|
|
256
|
+
if (prefix === '') {
|
|
257
|
+
output['prefix'] = camelCase(newName);
|
|
258
|
+
} else {
|
|
259
|
+
output['prefix'] = `${prefix}${upperFirst(camelCase(newName))}`;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Iterate over attributes.
|
|
263
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
264
|
+
|
|
265
|
+
// Includes attributes from iteration.
|
|
266
|
+
if (includes.includes(key)) {
|
|
267
|
+
Object.assign(output, { [key]: value });
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// If attribute starts with the prefix key leave it in the object if not remove it.
|
|
272
|
+
if (key.startsWith(output['prefix'])) {
|
|
273
|
+
Object.assign(output, { [key]: value });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Check if you have manual object and prepare the attribute keys and merge them with the original attributes for output.
|
|
278
|
+
if (!isEmpty(manual)) {
|
|
279
|
+
// Iterate manual attributes.
|
|
280
|
+
for (let [key, value] of Object.entries(manual)) {
|
|
281
|
+
|
|
282
|
+
// Includes attributes from iteration.
|
|
283
|
+
if (includes.includes(key)) {
|
|
284
|
+
Object.assign(output, { [key]: value });
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Remove the current component name from the attribute name.
|
|
289
|
+
const newKey = key.replace(`${lowerFirst(camelCase(newName))}`, '');
|
|
290
|
+
|
|
291
|
+
// Remove the old key.
|
|
292
|
+
delete manual[key];
|
|
293
|
+
|
|
294
|
+
// // Add new key to the output with prepared attribute name.
|
|
295
|
+
Object.assign(manual, { [`${output['prefix']}${newKey}`]: value });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Merge manual and output objects to one.
|
|
299
|
+
Object.assign(output, manual);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Return the original attribute for optimization purposes.
|
|
303
|
+
return output;
|
|
304
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useSelect } from '@wordpress/data';
|
|
2
|
+
import { STORE_NAME } from './store';
|
|
3
|
+
import { upperFirst } from '@eightshift/ui-components/utilities';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns colors from the global stores from the theme.
|
|
7
|
+
*
|
|
8
|
+
* @access public
|
|
9
|
+
*
|
|
10
|
+
* @returns {object}
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* ```js
|
|
14
|
+
* getPaletteColors()
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export const getPaletteColors = () => useSelect((select) => {
|
|
18
|
+
const colors = select(STORE_NAME).getSettings().globalVariables.colors;
|
|
19
|
+
|
|
20
|
+
return colors.reduce(
|
|
21
|
+
(obj, item) => ({
|
|
22
|
+
...obj,
|
|
23
|
+
[item.slug]: item,
|
|
24
|
+
}),
|
|
25
|
+
{}
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const getColorData = (themeColors) => Object.entries(themeColors ?? {})?.reduce((curr, [name, value]) => {
|
|
30
|
+
if (name === 'current') {
|
|
31
|
+
return curr;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (name === 'transparent') {
|
|
35
|
+
return [
|
|
36
|
+
...curr,
|
|
37
|
+
{
|
|
38
|
+
name: 'Transparent',
|
|
39
|
+
slug: 'transparent',
|
|
40
|
+
color: '#00000000',
|
|
41
|
+
}
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (typeof value === 'string') {
|
|
46
|
+
return [
|
|
47
|
+
...curr,
|
|
48
|
+
{
|
|
49
|
+
name: upperFirst(name),
|
|
50
|
+
slug: name,
|
|
51
|
+
color: value,
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return [
|
|
57
|
+
...curr,
|
|
58
|
+
...Object.entries(value).map(([shade, color]) => ({
|
|
59
|
+
name: `${upperFirst(name)} ${shade}`,
|
|
60
|
+
slug: `${name}-${shade}`,
|
|
61
|
+
color,
|
|
62
|
+
})),
|
|
63
|
+
];
|
|
64
|
+
}, []) ?? [];
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { dispatch } from '@wordpress/data';
|
|
3
|
+
import { InspectorControls, BlockControls } from '@wordpress/block-editor';
|
|
4
|
+
import { ContainerPanel } from '@eightshift/ui-components';
|
|
5
|
+
import { upperFirst } from '@eightshift/ui-components/utilities';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Given a block's client ID and an attribute key, locks post saving in Gutenberg.
|
|
9
|
+
* A lock is created under the name undefined-lock-[blockClientId]-[attributeKey],
|
|
10
|
+
* meaning that a lock can be created for each attribute key of each block.
|
|
11
|
+
* Multiple locks can be present and all of them have to be removed before saving is unlocked.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} blockClientId A block's client ID
|
|
14
|
+
* @param {string} attributeKey The attribute key
|
|
15
|
+
*
|
|
16
|
+
* @access public
|
|
17
|
+
*
|
|
18
|
+
* @returns {void}
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```js
|
|
22
|
+
* lockPostEditing(clientId, getAttrKey('headingContent', attributes, manifest), value);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const lockPostEditing = (blockClientId, attributeKey) => {
|
|
26
|
+
dispatch('core/editor').lockPostSaving(`undefined-lock-${blockClientId}-${attributeKey}`);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Given a block's client ID and an attribute key, unlocks post saving in Gutenberg.
|
|
31
|
+
* A lock is created under the name undefined-lock-[blockClientId]-[attributeKey],
|
|
32
|
+
* meaning that a lock can be created for each attribute key of each block.
|
|
33
|
+
* Multiple locks can be present and all of them have to be removed before saving is unlocked.
|
|
34
|
+
*
|
|
35
|
+
* @param {string} blockClientId A block's client ID
|
|
36
|
+
* @param {string} attributeKey The attribute key
|
|
37
|
+
*
|
|
38
|
+
* @access public
|
|
39
|
+
*
|
|
40
|
+
* @returns {void}
|
|
41
|
+
*
|
|
42
|
+
* Usage:
|
|
43
|
+
* ```js
|
|
44
|
+
* unlockPostEditing(clientId, getAttrKey('headingContent', attributes, manifest), value);
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const unlockPostEditing = (blockClientId, attributeKey) => {
|
|
48
|
+
dispatch('core/editor').unlockPostSaving(`undefined-lock-${blockClientId}-${attributeKey}`);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Given a block's client ID, attribute key and new value, creates a lock, locks post saving in Gutenberg
|
|
53
|
+
* if the value is undefined, null or an empty string and unlocks that attribute's lock otherwise.
|
|
54
|
+
*
|
|
55
|
+
* A lock is created under the name undefined-lock-[blockClientId]-[attributeKey],
|
|
56
|
+
* meaning that a lock can be created for each attribute key of each block.
|
|
57
|
+
* Multiple locks can be present and all of them have to be removed before saving is unlocked.
|
|
58
|
+
*
|
|
59
|
+
* @param {string} blockClientId A block's client ID
|
|
60
|
+
* @param {string} attributeKey The attribute key
|
|
61
|
+
*
|
|
62
|
+
* @access public
|
|
63
|
+
*
|
|
64
|
+
* @returns {void}
|
|
65
|
+
*
|
|
66
|
+
* Usage:
|
|
67
|
+
* ```js
|
|
68
|
+
* onChange={(value) => {
|
|
69
|
+
* setAttributes({ [getAttrKey('headingContent', attributes, manifest)]: value });
|
|
70
|
+
* lockIfUndefined(clientId, getAttrKey('headingContent', attributes, manifest), value);
|
|
71
|
+
* }}
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export const lockIfUndefined = (blockClientId, attributeKey, value) => {
|
|
75
|
+
if (typeof value === 'undefined' || value === null || value === '') {
|
|
76
|
+
lockPostEditing(blockClientId, attributeKey);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
unlockPostEditing(blockClientId, attributeKey);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Initialize the block context with all necessary data
|
|
84
|
+
*
|
|
85
|
+
* @component
|
|
86
|
+
* @param {Object} props - Component props.
|
|
87
|
+
* @param {JSX.Element?} [props.options] - Options component
|
|
88
|
+
* @param {JSX.Element?} [props.toolbar] - Toolbar component
|
|
89
|
+
* @param {JSX.Element?} [props.editor] - Editor component
|
|
90
|
+
* @param {boolean} [props.noOptionsContainer] - If `true`, the options component will not be wrapped in a container.
|
|
91
|
+
* @param {string} props.title - Block name. Will fall back to a name generated from the `blockName` attribute.
|
|
92
|
+
*
|
|
93
|
+
* @returns {JSX.Element} The GutenbergBlock component.
|
|
94
|
+
*
|
|
95
|
+
* @access public
|
|
96
|
+
* @since 1.0.0
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* <GutenbergBlock
|
|
100
|
+
* {...props}
|
|
101
|
+
* options={OptionsComponent}
|
|
102
|
+
* editor={EditorComponent}
|
|
103
|
+
* />
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
export const GutenbergBlock = (props) => {
|
|
107
|
+
const {
|
|
108
|
+
options: OptionsComponent,
|
|
109
|
+
toolbar: ToolbarComponent,
|
|
110
|
+
editor: EditorComponent,
|
|
111
|
+
noOptionsContainer = false,
|
|
112
|
+
title,
|
|
113
|
+
} = props;
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<>
|
|
117
|
+
{OptionsComponent &&
|
|
118
|
+
<InspectorControls>
|
|
119
|
+
{!noOptionsContainer &&
|
|
120
|
+
<ContainerPanel title={title ?? upperFirst(props?.attributes?.blockName)}>
|
|
121
|
+
<OptionsComponent {...props} />
|
|
122
|
+
</ContainerPanel>
|
|
123
|
+
}
|
|
124
|
+
{noOptionsContainer && <OptionsComponent {...props} />}
|
|
125
|
+
</InspectorControls>
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
{ToolbarComponent &&
|
|
129
|
+
<BlockControls>
|
|
130
|
+
<ToolbarComponent {...props} />
|
|
131
|
+
</BlockControls>
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
{EditorComponent &&
|
|
135
|
+
<EditorComponent {...props} />
|
|
136
|
+
}
|
|
137
|
+
</>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { unescapeHTML } from '@eightshift/ui-components/utilities';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns a function that fetches data from WordPress REST API.
|
|
5
|
+
*
|
|
6
|
+
* @param {string} endpoint - Endpoint to fetch from.
|
|
7
|
+
* @param {Object} options - Additional options.
|
|
8
|
+
* @param {Function} [options.processId] - Function to process the ID. `(itemData: Object) => id: string | Number`
|
|
9
|
+
* @param {Function} [options.processLabel] - Function to process the label. `(itemData: Object) => label: string`
|
|
10
|
+
* @param {Function} [options.processMetadata] - Function to process the metadata. `(itemData: Object) => metadata: Object`
|
|
11
|
+
* @param {number} [options.perPage=30] - Number of items to fetch per page.
|
|
12
|
+
* @param {string} [options.urlBase='<origin>/wp-json'] - Base URL for the API.
|
|
13
|
+
* @param {string} [options.routePrefix='wp/v2'] - Route prefix for the API.
|
|
14
|
+
* @param {string} [options.fields='id,title'] - A comma-separated list of field names to fetch from the API. Good to include as it makes the query faster and the output terser.
|
|
15
|
+
* @param {SearchColumnsConfig} [options.searchColumns] - Allows narrowing the search scope.
|
|
16
|
+
* @param {boolean} [options.noUnescapeTitle] - If `true`, the post title will not unescape HTML entities.
|
|
17
|
+
*
|
|
18
|
+
* @returns {Function} The `(searchText, [abortSignal]) => Promise` function.
|
|
19
|
+
*
|
|
20
|
+
* @typedef {'post_title' | 'post_excerpt' | 'post_content'} SearchColumnsConfig
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const fetchFn = getFetchWpApi('pages');
|
|
24
|
+
* const data = await fetchFn('search text');
|
|
25
|
+
* const json = await data.json();
|
|
26
|
+
*
|
|
27
|
+
* console.log(json);
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* <LinkInput
|
|
31
|
+
* value={buttonUrl}
|
|
32
|
+
* onChange={({url}) => setAttributes({ [getAttrKey('buttonUrl', attributes, manifest)]: url })}
|
|
33
|
+
* fetchSuggestions={getFetchWpApi('search')}
|
|
34
|
+
* />
|
|
35
|
+
*
|
|
36
|
+
*/
|
|
37
|
+
export function fetchFromWpRest(endpoint, options = {}) {
|
|
38
|
+
const {
|
|
39
|
+
processId = ({ id }) => id,
|
|
40
|
+
processLabel = ({ title }) => unescapeHTML(title),
|
|
41
|
+
processMetadata = () => null,
|
|
42
|
+
perPage = 30,
|
|
43
|
+
urlBase = `${window.location.origin}/wp-json`,
|
|
44
|
+
routePrefix = 'wp/v2',
|
|
45
|
+
fields = 'id,title',
|
|
46
|
+
searchColumns,
|
|
47
|
+
noUnescapeTitle = false,
|
|
48
|
+
...params
|
|
49
|
+
} = options;
|
|
50
|
+
|
|
51
|
+
return async (searchText = '', abortSignal) => {
|
|
52
|
+
const url = new URL(`${urlBase}/${routePrefix}/${endpoint}/`);
|
|
53
|
+
|
|
54
|
+
url.searchParams.append('per_page', perPage);
|
|
55
|
+
|
|
56
|
+
if (fields?.length > 0) {
|
|
57
|
+
url.searchParams.append('_fields', fields);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (searchColumns?.length > 0) {
|
|
61
|
+
url.searchParams.append('search_columns', Array.isArray(searchColumns) ? searchColumns.join(',') : searchColumns);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (Object.keys(params).length > 0) {
|
|
65
|
+
for (const [key, value] of Object.entries(params)) {
|
|
66
|
+
url.searchParams.append(key, value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (searchText?.length > 0) {
|
|
71
|
+
url.searchParams.append('search', searchText);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const newData = await fetch(url.toString(), {
|
|
75
|
+
signal: abortSignal,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const newDataJson = await newData.json();
|
|
79
|
+
|
|
80
|
+
return [...newDataJson].map((item) => {
|
|
81
|
+
return {
|
|
82
|
+
label: noUnescapeTitle ? unescapeHTML(processLabel(item)) : processLabel(item),
|
|
83
|
+
value: processId(item),
|
|
84
|
+
metadata: processMetadata(item),
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export const wpSearchRoute = fetchFromWpRest('search', {
|
|
91
|
+
processId: ({ url }) => url,
|
|
92
|
+
processLabel: ({ title }) => title,
|
|
93
|
+
processMetadata: ({ type, subtype }) => ({ type, subtype }),
|
|
94
|
+
additionalParam: {
|
|
95
|
+
type: 'post',
|
|
96
|
+
_locale: 'user',
|
|
97
|
+
per_page: 5,
|
|
98
|
+
},
|
|
99
|
+
noCache: true,
|
|
100
|
+
searchColumns: 'post_title',
|
|
101
|
+
fields: 'id,title,type,subtype,url',
|
|
102
|
+
});
|