@webikon/webentor-core 0.9.12
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/.husky/pre-commit +40 -0
- package/.prettierrc.js +5 -0
- package/CHANGELOG.md +88 -0
- package/LICENCE.md +7 -0
- package/README.md +26 -0
- package/core-js/_alpine.ts +20 -0
- package/core-js/_slider.ts +232 -0
- package/core-js/_utils.ts +126 -0
- package/core-js/blocks-components/block-appender.tsx +36 -0
- package/core-js/blocks-components/button.tsx +424 -0
- package/core-js/blocks-components/custom-image-sizes-panel.tsx +197 -0
- package/core-js/blocks-components/index.ts +4 -0
- package/core-js/blocks-components/typography-picker-select.tsx +31 -0
- package/core-js/blocks-filters/_filter-core-typography.tsx +108 -0
- package/core-js/blocks-filters/_slider-settings.tsx +283 -0
- package/core-js/blocks-filters/index.ts +3 -0
- package/core-js/blocks-filters/responsive-settings/components/DisabledSliderInfo.tsx +10 -0
- package/core-js/blocks-filters/responsive-settings/constants.ts +11 -0
- package/core-js/blocks-filters/responsive-settings/index.tsx +196 -0
- package/core-js/blocks-filters/responsive-settings/settings/block-link/index.ts +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/block-link/panel.tsx +47 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/index.tsx +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/properties.ts +27 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border/settings.tsx +310 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/index.tsx +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/properties.ts +31 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/settings.tsx +211 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/index.ts +1 -0
- package/core-js/blocks-filters/responsive-settings/settings/border/panel.tsx +54 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/properties.ts +167 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/display/settings.tsx +73 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/properties.ts +187 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/settings.tsx +131 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/index.ts +2 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/properties.ts +187 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/grid/settings.tsx +132 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/index.ts +4 -0
- package/core-js/blocks-filters/responsive-settings/settings/container/panel.tsx +92 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/index.ts +3 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/panel.tsx +45 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/properties.ts +74 -0
- package/core-js/blocks-filters/responsive-settings/settings/spacing/settings.tsx +85 -0
- package/core-js/blocks-filters/responsive-settings/types/index.ts +68 -0
- package/core-js/blocks-filters/responsive-settings/utils.ts +321 -0
- package/core-js/blocks-utils/_use-block-parent.ts +27 -0
- package/core-js/blocks-utils/_use-post-types.ts +43 -0
- package/core-js/blocks-utils/_use-taxonomies.ts +29 -0
- package/core-js/blocks-utils/index.ts +3 -0
- package/core-js/config/webentor-config.ts +718 -0
- package/core-js/index.ts +14 -0
- package/core-js/types/_block-components.ts +7 -0
- package/core-js/types/_webentor-config.ts +182 -0
- package/package.json +98 -0
- package/resources/blocks/e-accordion/block.json +34 -0
- package/resources/blocks/e-accordion/e-accordion.block.tsx +125 -0
- package/resources/blocks/e-accordion/script.ts +1 -0
- package/resources/blocks/e-accordion/style.css +8 -0
- package/resources/blocks/e-accordion-group/block.json +56 -0
- package/resources/blocks/e-accordion-group/e-accordion-group.block.tsx +99 -0
- package/resources/blocks/e-breadcrumbs/block.json +41 -0
- package/resources/blocks/e-breadcrumbs/e-breadcrumbs.block.tsx +53 -0
- package/resources/blocks/e-button/block.json +32 -0
- package/resources/blocks/e-button/e-button.block.tsx +55 -0
- package/resources/blocks/e-gallery/block.json +90 -0
- package/resources/blocks/e-gallery/e-gallery.block.tsx +316 -0
- package/resources/blocks/e-icon-picker/block.json +37 -0
- package/resources/blocks/e-icon-picker/e-icon-picker.block.tsx +230 -0
- package/resources/blocks/e-icon-picker/style.css +17 -0
- package/resources/blocks/e-image/block.json +78 -0
- package/resources/blocks/e-image/e-image.block.tsx +331 -0
- package/resources/blocks/e-picker-query-loop/block.json +25 -0
- package/resources/blocks/e-picker-query-loop/e-picker-query-loop.block.tsx +189 -0
- package/resources/blocks/e-post-template/block.json +25 -0
- package/resources/blocks/e-post-template/e-post-template.block.tsx +100 -0
- package/resources/blocks/e-query-loop/block.json +36 -0
- package/resources/blocks/e-query-loop/constants.tsx +8 -0
- package/resources/blocks/e-query-loop/e-query-loop.block.tsx +270 -0
- package/resources/blocks/e-query-loop/taxonomy-controls.tsx +184 -0
- package/resources/blocks/e-slider/block.json +42 -0
- package/resources/blocks/e-slider/e-slider.block.tsx +100 -0
- package/resources/blocks/e-svg/block.json +37 -0
- package/resources/blocks/e-svg/e-svg.block.tsx +156 -0
- package/resources/blocks/e-tab-container/block.json +49 -0
- package/resources/blocks/e-tab-container/e-tab-container.block.tsx +123 -0
- package/resources/blocks/e-table/block.json +30 -0
- package/resources/blocks/e-table/e-table.block.tsx +120 -0
- package/resources/blocks/e-table/script.ts +48 -0
- package/resources/blocks/e-table-cell/block.json +40 -0
- package/resources/blocks/e-table-cell/e-table-cell.block.tsx +180 -0
- package/resources/blocks/e-table-row/block.json +28 -0
- package/resources/blocks/e-table-row/e-table-row.block.tsx +118 -0
- package/resources/blocks/e-tabs/block.json +27 -0
- package/resources/blocks/e-tabs/e-tabs.block.tsx +90 -0
- package/resources/blocks/l-404/block.json +51 -0
- package/resources/blocks/l-404/l-404.block.tsx +75 -0
- package/resources/blocks/l-flexible-container/block.json +34 -0
- package/resources/blocks/l-flexible-container/l-flexible-container.block.tsx +97 -0
- package/resources/blocks/l-footer/block.json +23 -0
- package/resources/blocks/l-footer/l-footer.block.tsx +51 -0
- package/resources/blocks/l-formatted-content/block.json +28 -0
- package/resources/blocks/l-formatted-content/l-formatted-content.block.tsx +97 -0
- package/resources/blocks/l-header/block.json +26 -0
- package/resources/blocks/l-header/l-header.block.tsx +100 -0
- package/resources/blocks/l-mobile-nav/block.json +15 -0
- package/resources/blocks/l-mobile-nav/l-mobile-nav.block.tsx +56 -0
- package/resources/blocks/l-mobile-nav/style.css +54 -0
- package/resources/blocks/l-nav-menu/block.json +27 -0
- package/resources/blocks/l-nav-menu/l-nav-menu.block.tsx +109 -0
- package/resources/blocks/l-nav-menu/style.css +134 -0
- package/resources/blocks/l-post-card/block.json +13 -0
- package/resources/blocks/l-post-card/l-post-card.block.tsx +52 -0
- package/resources/blocks/l-section/block.json +89 -0
- package/resources/blocks/l-section/l-section.block.tsx +316 -0
- package/resources/blocks/l-site-logo/block.json +15 -0
- package/resources/blocks/l-site-logo/l-site-logo.block.tsx +54 -0
- package/resources/core-components/slider/slider.script.ts +11 -0
- package/resources/core-components/slider/slider.style.css +134 -0
- package/resources/scripts/editor.ts +29 -0
- package/resources/styles/app.css +21 -0
- package/resources/styles/common/_editor.css +86 -0
- package/resources/styles/common/_form.css +83 -0
- package/resources/styles/common/_global.css +73 -0
- package/resources/styles/common/_theme.css +75 -0
- package/resources/styles/common/_utilities.css +33 -0
- package/resources/styles/common/_wordpress.css +110 -0
- package/resources/styles/components/_table.css +102 -0
- package/resources/styles/editor.css +16 -0
- package/resources/styles/partials/.gitkeep +0 -0
- package/resources/styles/partials/_header.css +21 -0
- package/resources/styles/partials/_pagination.css +35 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
# Skip install on CI
|
|
4
|
+
[ -n "$CI" ] && exit 0
|
|
5
|
+
|
|
6
|
+
# Check if any TypeScript, JavaScript, CSS files, or package files are staged for commit
|
|
7
|
+
if git diff --cached --name-only | grep -E '\.(ts|tsx|js|jsx|css|scss|sass|less)$|package\.json$|pnpm-lock\.yaml$' > /dev/null; then
|
|
8
|
+
echo "🔨 TypeScript/JavaScript/CSS/Package files detected, running pnpm build..."
|
|
9
|
+
|
|
10
|
+
# Run the build process
|
|
11
|
+
pnpm build
|
|
12
|
+
|
|
13
|
+
# Check if build was successful
|
|
14
|
+
if [ $? -ne 0 ]; then
|
|
15
|
+
echo "❌ Build failed! Commit aborted."
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
echo "✅ Build completed successfully!"
|
|
20
|
+
|
|
21
|
+
# Check if there are any changes in the public/ folder
|
|
22
|
+
if [ -n "$(git status --porcelain public/)" ]; then
|
|
23
|
+
echo "📦 Found changes in public/ folder, adding to commit..."
|
|
24
|
+
|
|
25
|
+
# Add all changes in public/ folder to the current commit
|
|
26
|
+
git add public/
|
|
27
|
+
|
|
28
|
+
# Show what was added
|
|
29
|
+
echo "📋 Added files to commit:"
|
|
30
|
+
git status --porcelain public/ | sed 's/^/ /'
|
|
31
|
+
|
|
32
|
+
echo "✅ Public folder changes have been automatically added to this commit!"
|
|
33
|
+
else
|
|
34
|
+
echo "ℹ️ No changes detected in public/ folder."
|
|
35
|
+
fi
|
|
36
|
+
else
|
|
37
|
+
echo "ℹ️ No TypeScript/JavaScript/CSS/Package files changed, skipping build."
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
echo "🚀 Proceeding with commit..."
|
package/.prettierrc.js
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Webentor Core Changelog
|
|
2
|
+
|
|
3
|
+
## DEV
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## 0.9.12
|
|
7
|
+
|
|
8
|
+
- Add `webentor.core.button.output` filter
|
|
9
|
+
- Allow picking up multiple post types in Query Loop block
|
|
10
|
+
- Add e-button HTML Element setting
|
|
11
|
+
- Fix webentorConfig safelist
|
|
12
|
+
- Fix image object-fit defaults
|
|
13
|
+
- Fix useParentBlock hook to get proper parent block
|
|
14
|
+
- Adjust responsive settings to be conditioned by parent block
|
|
15
|
+
- Fix Table block cell colspan
|
|
16
|
+
- Fix button url escaping & show conditional
|
|
17
|
+
- Fix Vite blocks build on Windows Herd
|
|
18
|
+
- **BREAKING**: Fix accordion collapse animation - if you customized accordion blade view, adjust its content wrapper
|
|
19
|
+
- Fix l-404 block button
|
|
20
|
+
- Fix $anchor passed variable in inner blocks
|
|
21
|
+
|
|
22
|
+
## 0.9.11
|
|
23
|
+
|
|
24
|
+
- Fix husky install
|
|
25
|
+
- Add missing `wbtr:` prefixes in blocks edit
|
|
26
|
+
- Fix rendering in REST API request
|
|
27
|
+
- Refactor custom size settings into separate React component
|
|
28
|
+
- Improve block classes rendering conditions
|
|
29
|
+
- Improve block assets registering, so they can be overriden in the theme
|
|
30
|
+
- Allow picking up multiple post types in Picker Query Loop block
|
|
31
|
+
- NEW: Add basic `webentor-config`, which can be included in the theme, export `spacing`
|
|
32
|
+
- NEW: Add flexbox, grid and background image settings to **Section block**
|
|
33
|
+
- NEW: Add `webentor/e-gallery` block
|
|
34
|
+
- NEW: Add hooks `webentor/skip_render_block_blade` and `webentor/slider/view/swiper_params`
|
|
35
|
+
- NEW: Add `loop` and `slider_id` settings to **Slider block**
|
|
36
|
+
- NEW: Add flex/grid item order settings
|
|
37
|
+
- NEW: Add JS events `e_tabs_nav_initialized`, `e_tabs_nav_item_clicked`, `e_accordion_btn_clicked`
|
|
38
|
+
- NEW: Add components BEM classes
|
|
39
|
+
- NEW: Add `aspect-ratio` settings to `e-image` block.
|
|
40
|
+
- **BREAKING**: Add `aspect-ratio` config to `webentor-config.ts`
|
|
41
|
+
- **BREAKING:**: Change view paths for Blade `blocks` and `core-components`. Now these folder names doesn't need to be included in the path when including views from them.
|
|
42
|
+
- Replace `core-components.button.button` and `core-components.slider.slider` with `button.button` and `slider.slider`
|
|
43
|
+
- If you included blocks as `blocks.blockName.view`, remove `blocks.` and leave just `blockName.view`
|
|
44
|
+
- Fix slider pagination styles
|
|
45
|
+
- Update deps
|
|
46
|
+
- Fix publicDir Vite error
|
|
47
|
+
- Remove Button asPill parameter
|
|
48
|
+
|
|
49
|
+
## 0.9.10
|
|
50
|
+
|
|
51
|
+
- Add ability to select icon in Button Block
|
|
52
|
+
- Fix condition to render flex/grid item classes depending on parent display setting
|
|
53
|
+
|
|
54
|
+
## 0.9.9
|
|
55
|
+
|
|
56
|
+
- **BREAKING:** Move slider styles to `@layer components`
|
|
57
|
+
- Add more slider view classes
|
|
58
|
+
- Remove empty styles folders
|
|
59
|
+
- Add opacity to hidden FC blocks instead of hiding them entirely
|
|
60
|
+
|
|
61
|
+
## 0.9.8
|
|
62
|
+
|
|
63
|
+
- Add `pnpm`
|
|
64
|
+
- Update node deps
|
|
65
|
+
- **BREAKING:** Rename npm package to `@webikon/webentor-core`
|
|
66
|
+
- **BREAKING:** Include `build/` assets
|
|
67
|
+
|
|
68
|
+
## 0.9.7
|
|
69
|
+
|
|
70
|
+
- Fix empty content in WP REST API response
|
|
71
|
+
|
|
72
|
+
## 0.9.6
|
|
73
|
+
|
|
74
|
+
- Add Icon Picker block
|
|
75
|
+
- Update deps
|
|
76
|
+
|
|
77
|
+
## 0.9.5
|
|
78
|
+
|
|
79
|
+
- Add new border & border radius responsive settings, applied to Flexible Content, Section and Image
|
|
80
|
+
- Add Picker Query Loop block
|
|
81
|
+
- (BREAKING) Remove old Image block border and rounded setting which are replaced by border responsive settings
|
|
82
|
+
|
|
83
|
+
## 0.9.4
|
|
84
|
+
|
|
85
|
+
- Bundle `core-js` package
|
|
86
|
+
- Add Button component extension hooks
|
|
87
|
+
- Add Vite build plugin
|
|
88
|
+
- Update deps
|
package/LICENCE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) Webikon s.r.o.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# webentor-core
|
|
2
|
+
|
|
3
|
+
Reusable Webentor core functionality for PHP and JS runtimes.
|
|
4
|
+
|
|
5
|
+
## Packages
|
|
6
|
+
|
|
7
|
+
- Composer: `webikon/webentor-core`
|
|
8
|
+
- npm: `@webikon/webentor-core`
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
- PHP >= 8.2
|
|
13
|
+
- Node >= 20
|
|
14
|
+
- pnpm >= 10
|
|
15
|
+
|
|
16
|
+
## Development
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
composer install
|
|
20
|
+
pnpm install
|
|
21
|
+
pnpm build
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Linting
|
|
25
|
+
|
|
26
|
+
Core consumes shared presets from `@webikon/webentor-configs` to keep lint behavior aligned across repositories.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import collapse from '@alpinejs/collapse';
|
|
2
|
+
import Alpine from 'alpinejs';
|
|
3
|
+
|
|
4
|
+
// Initialize Alpine if it's not already initialized
|
|
5
|
+
const AlpineInstance = window.Alpine || Alpine;
|
|
6
|
+
if (!window.Alpine) {
|
|
7
|
+
// Make Alpine globally available
|
|
8
|
+
window.Alpine = Alpine;
|
|
9
|
+
|
|
10
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
11
|
+
AlpineInstance.start();
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
document.addEventListener('alpine:init', () => {
|
|
16
|
+
// Register default plugins
|
|
17
|
+
AlpineInstance.plugin(collapse);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export { AlpineInstance as Alpine };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { __ } from '@wordpress/i18n';
|
|
2
|
+
import Swiper from 'swiper/bundle';
|
|
3
|
+
|
|
4
|
+
import { debounce, throttle } from './_utils';
|
|
5
|
+
|
|
6
|
+
type BreakpointConfig = Swiper & {
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
class SliderComponent {
|
|
11
|
+
private element: HTMLElement;
|
|
12
|
+
private params: Swiper & {
|
|
13
|
+
breakpoints: Record<string, BreakpointConfig>;
|
|
14
|
+
autoplayControl: boolean;
|
|
15
|
+
};
|
|
16
|
+
private swiper: Swiper | null;
|
|
17
|
+
private container: HTMLElement;
|
|
18
|
+
private breakpoints: Record<string, BreakpointConfig> | null;
|
|
19
|
+
private autoplayButton: HTMLElement | null;
|
|
20
|
+
private timerSeconds: HTMLElement | null;
|
|
21
|
+
private timerCircle: HTMLElement | null;
|
|
22
|
+
private autoplayControlEnabled: boolean;
|
|
23
|
+
private resizeHandler?: () => void;
|
|
24
|
+
|
|
25
|
+
constructor(element, params) {
|
|
26
|
+
this.element = element;
|
|
27
|
+
this.params = params;
|
|
28
|
+
this.swiper = null;
|
|
29
|
+
this.container = element.querySelector('.js-swiper-container');
|
|
30
|
+
this.breakpoints = null;
|
|
31
|
+
|
|
32
|
+
const { breakpoints, autoplayControl } = this.params;
|
|
33
|
+
this.breakpoints = breakpoints;
|
|
34
|
+
|
|
35
|
+
this.autoplayButton = this.element.querySelector('.js-autoplay-btn');
|
|
36
|
+
this.timerSeconds = this.element.querySelector('.js-slider-timer-seconds');
|
|
37
|
+
this.timerCircle = this.element.querySelector('.js-slider-timer-circle');
|
|
38
|
+
this.autoplayControlEnabled = autoplayControl;
|
|
39
|
+
|
|
40
|
+
this.initSwiper();
|
|
41
|
+
this.addResizeListener();
|
|
42
|
+
this.addBreakpointChecker();
|
|
43
|
+
this.breakpointChecker = this.breakpointChecker.bind(this);
|
|
44
|
+
|
|
45
|
+
if (this.autoplayControlEnabled && this.autoplayButton) {
|
|
46
|
+
this.autoplayButton.addEventListener('click', () =>
|
|
47
|
+
this.toggleAutoplay(),
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
initSwiper() {
|
|
53
|
+
this.breakpointChecker();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
getSwiper() {
|
|
57
|
+
return this.swiper;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addResizeListener() {
|
|
61
|
+
this.resizeHandler = () => {
|
|
62
|
+
this.breakpointChecker();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
window.addEventListener('resize', debounce(this.resizeHandler, 300));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
breakpointChecker() {
|
|
69
|
+
const currentBreakpoint = this.getCurrentBreakpoint(window.innerWidth);
|
|
70
|
+
|
|
71
|
+
if (currentBreakpoint && currentBreakpoint.enabled) {
|
|
72
|
+
this.enableSwiper();
|
|
73
|
+
} else {
|
|
74
|
+
this.destroySwiper();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
addBreakpointChecker() {
|
|
79
|
+
this.breakpointChecker();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
enableSwiper() {
|
|
83
|
+
if (this.swiper) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.element.classList.add('slider-enabled');
|
|
88
|
+
|
|
89
|
+
// Find all direct child elements of ".js-slider-wrapper"
|
|
90
|
+
const sliderWrapperChildren =
|
|
91
|
+
this.element.querySelector('.js-slider-wrapper').children;
|
|
92
|
+
|
|
93
|
+
// Add "swiper-slide" class to each child element
|
|
94
|
+
for (const child of sliderWrapperChildren) {
|
|
95
|
+
child.classList.add('swiper-slide');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// this.recalculateSlidesWidth();
|
|
99
|
+
|
|
100
|
+
this.swiper = new Swiper(this.container, {
|
|
101
|
+
...this.params,
|
|
102
|
+
on: {
|
|
103
|
+
init: (swiper) => {
|
|
104
|
+
this.fixInitialSlideCalculation(swiper);
|
|
105
|
+
|
|
106
|
+
if (this.autoplayControlEnabled) {
|
|
107
|
+
this.updateAutoplayButtonState(swiper);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
autoplayTimeLeft: (swiper, time, progress) => {
|
|
111
|
+
if (this.autoplayControlEnabled) {
|
|
112
|
+
this.timerCircle.style.setProperty(
|
|
113
|
+
'--slider-timer-progress',
|
|
114
|
+
1 - progress,
|
|
115
|
+
);
|
|
116
|
+
this.timerSeconds.textContent = `${Math.ceil(time / 1000)}s`;
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
autoplayResume: (swiper) => {
|
|
120
|
+
if (this.autoplayControlEnabled) {
|
|
121
|
+
this.updateAutoplayButtonState(swiper);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
resize: throttle(this.fixInitialSlideCalculation, 100),
|
|
125
|
+
...this.params.on,
|
|
126
|
+
},
|
|
127
|
+
navigation: {
|
|
128
|
+
nextEl: this.element.querySelector('.js-slider-button-next'),
|
|
129
|
+
prevEl: this.element.querySelector('.js-slider-button-prev'),
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Ensure that slidesPerGroupSkip is defined
|
|
134
|
+
if (this.swiper.params.slidesPerGroupSkip === undefined) {
|
|
135
|
+
this.swiper.params.slidesPerGroupSkip = 0;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
destroySwiper() {
|
|
140
|
+
if (!this.swiper) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Remove the "swiper-slide" class from all direct child elements of ".js-slider-wrapper"
|
|
145
|
+
const sliderWrapperChildren =
|
|
146
|
+
this.element.querySelector('.js-slider-wrapper').children;
|
|
147
|
+
for (const child of sliderWrapperChildren) {
|
|
148
|
+
child.classList.remove('swiper-slide');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.element.classList.remove('slider-enabled');
|
|
152
|
+
|
|
153
|
+
this.swiper.destroy(true, true);
|
|
154
|
+
this.swiper = undefined;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Get current breakpoint by iterating over the breakpoint and finding the first one that is bigger than the current width but smaller than the next breakpoint
|
|
158
|
+
getCurrentBreakpoint(width) {
|
|
159
|
+
let currentBreakpoint = 0;
|
|
160
|
+
|
|
161
|
+
for (const breakpoint in this.breakpoints) {
|
|
162
|
+
if (width > parseInt(breakpoint)) {
|
|
163
|
+
currentBreakpoint = parseInt(breakpoint);
|
|
164
|
+
} else {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return this.breakpoints[currentBreakpoint];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
recalculateSlidesWidth() {
|
|
173
|
+
const wrapper = this.element.querySelector('.js-slider-wrapper');
|
|
174
|
+
|
|
175
|
+
if (!wrapper) return;
|
|
176
|
+
|
|
177
|
+
const slides = Array.from(wrapper.children);
|
|
178
|
+
|
|
179
|
+
if (slides.length === 0) return;
|
|
180
|
+
|
|
181
|
+
// Get the dynamically calculated gap
|
|
182
|
+
const gap = parseInt(window.getComputedStyle(wrapper).gap);
|
|
183
|
+
|
|
184
|
+
// Return early if the gap is zero
|
|
185
|
+
if (gap === 0) return;
|
|
186
|
+
|
|
187
|
+
const maxWidth = `calc(100% - ${gap}px)`;
|
|
188
|
+
const translateX = `${gap / 2}px`;
|
|
189
|
+
|
|
190
|
+
slides.forEach((slide) => {
|
|
191
|
+
slide.style.maxWidth = maxWidth;
|
|
192
|
+
slide.style.transform = `translateX(${translateX})`;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Swiper incorrectly calculates initial slide when using loop and centered slides
|
|
197
|
+
// See: https://github.com/nolimits4web/swiper/issues/7216
|
|
198
|
+
fixInitialSlideCalculation(swiper) {
|
|
199
|
+
if (swiper.params.centeredSlides) {
|
|
200
|
+
swiper.slideToLoop(0, 0);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
toggleAutoplay() {
|
|
205
|
+
if (this.swiper) {
|
|
206
|
+
if (this.swiper.autoplay.running && !this.swiper.autoplay.paused) {
|
|
207
|
+
this.swiper.autoplay.pause();
|
|
208
|
+
} else {
|
|
209
|
+
this.swiper.autoplay.resume();
|
|
210
|
+
}
|
|
211
|
+
this.updateAutoplayButtonState(this.swiper);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
updateAutoplayButtonState(swiper) {
|
|
216
|
+
if (this.autoplayButton) {
|
|
217
|
+
this.autoplayButton.setAttribute(
|
|
218
|
+
'aria-label',
|
|
219
|
+
swiper?.autoplay.running && !swiper?.autoplay.paused
|
|
220
|
+
? __('Pause autoplay', 'webentor')
|
|
221
|
+
: __('Start autoplay', 'webentor'),
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
this.element.classList.toggle(
|
|
225
|
+
'is-playing',
|
|
226
|
+
swiper?.autoplay.running && !swiper?.autoplay.paused,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Also export Swiper for external use
|
|
232
|
+
export { SliderComponent, Swiper };
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immutably sets a value inside an object. Like `lodash#set`, but returning a
|
|
3
|
+
* new object. Treats nullish initial values as empty objects. Clones any
|
|
4
|
+
* nested objects. Supports arrays, too.
|
|
5
|
+
*
|
|
6
|
+
* @param {Object} object Object to set a value in.
|
|
7
|
+
* @param {number|string|Array} path Path in the object to modify.
|
|
8
|
+
* @param {*} value New value to set.
|
|
9
|
+
* @return {Object} Cloned object with the new value set.
|
|
10
|
+
*/
|
|
11
|
+
export function setImmutably(
|
|
12
|
+
object: object,
|
|
13
|
+
path: number | string | Array<any>,
|
|
14
|
+
value: any,
|
|
15
|
+
): object {
|
|
16
|
+
// Normalize path
|
|
17
|
+
path = Array.isArray(path) ? [...path] : [path];
|
|
18
|
+
|
|
19
|
+
// Shallowly clone the base of the object
|
|
20
|
+
object = Array.isArray(object) ? [...object] : { ...object };
|
|
21
|
+
|
|
22
|
+
const leaf = path.pop();
|
|
23
|
+
|
|
24
|
+
// Traverse object from root to leaf, shallowly cloning at each level
|
|
25
|
+
let prev = object;
|
|
26
|
+
for (const key of path) {
|
|
27
|
+
const lvl = prev[key];
|
|
28
|
+
prev = prev[key] = Array.isArray(lvl) ? [...lvl] : { ...lvl };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
prev[leaf] = value;
|
|
32
|
+
|
|
33
|
+
return object;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Debounce functions for better performance
|
|
38
|
+
* Source: https://www.joshwcomeau.com/snippets/javascript/debounce/
|
|
39
|
+
*
|
|
40
|
+
* @param {Function} fn The function to debounce
|
|
41
|
+
* @param {number} wait The time, in milliseconds, to wait before calling the function
|
|
42
|
+
* @return {Function} The debounced function
|
|
43
|
+
*/
|
|
44
|
+
export const debounce = (callback, wait = 50) => {
|
|
45
|
+
let timeoutId = null;
|
|
46
|
+
return (...args) => {
|
|
47
|
+
window.clearTimeout(timeoutId);
|
|
48
|
+
timeoutId = window.setTimeout(() => {
|
|
49
|
+
callback(...args);
|
|
50
|
+
}, wait);
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Throttle a function so that it is only called once within a given time interval.
|
|
56
|
+
*
|
|
57
|
+
* @param {Function} fn - The function to throttle
|
|
58
|
+
* @param {Number} wait - The time interval, in milliseconds, to wait between calls to the function
|
|
59
|
+
* @return {Function} - Returns a throttled version of the original function
|
|
60
|
+
*/
|
|
61
|
+
export function throttle(fn, wait = 20) {
|
|
62
|
+
let time = Date.now();
|
|
63
|
+
return function (...args) {
|
|
64
|
+
if (time + wait - Date.now() < 0) {
|
|
65
|
+
fn(...args);
|
|
66
|
+
time = Date.now();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Convert a string to camelCase
|
|
73
|
+
*
|
|
74
|
+
* @param {string} text - The string to convert
|
|
75
|
+
* @return {string} The camelCase string
|
|
76
|
+
*/
|
|
77
|
+
export function camelize(text: string) {
|
|
78
|
+
const a = text
|
|
79
|
+
.toLowerCase()
|
|
80
|
+
.replace(/[-_\s.]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));
|
|
81
|
+
return a.substring(0, 1).toLowerCase() + a.substring(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if an object is empty
|
|
86
|
+
*
|
|
87
|
+
* @param {Object} obj - The object to check
|
|
88
|
+
* @return {boolean} True if the object is empty, false otherwise
|
|
89
|
+
*/
|
|
90
|
+
export function isEmpty(obj: object) {
|
|
91
|
+
for (const prop in obj) {
|
|
92
|
+
if (Object.hasOwn(obj, prop)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get color slug by color hex value.
|
|
102
|
+
* Usually we don't want to save hex value from WP color palette, we want to save slug.
|
|
103
|
+
*
|
|
104
|
+
* @param colors - Colors array
|
|
105
|
+
* @param color - Color string
|
|
106
|
+
* @returns Color slug
|
|
107
|
+
*/
|
|
108
|
+
export const getColorSlugByColor = (
|
|
109
|
+
colors: { color: string; slug: string }[],
|
|
110
|
+
color: string,
|
|
111
|
+
) => {
|
|
112
|
+
return colors.find((c: any) => c.color === color)?.slug;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Get color by slug.
|
|
117
|
+
* This is the opposite of getColorSlugByColor.
|
|
118
|
+
* We want to use hex value for ColorPallete control, but we saved it as slug.
|
|
119
|
+
*
|
|
120
|
+
* @param colors - Colors array
|
|
121
|
+
* @param slug - Color slug
|
|
122
|
+
* @returns Color string
|
|
123
|
+
*/
|
|
124
|
+
export const getColorBySlug = (colors: any, slug: string) => {
|
|
125
|
+
return colors.find((color: any) => color.slug === slug)?.color;
|
|
126
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Inserter } from '@wordpress/block-editor';
|
|
2
|
+
import { Button, IconType } from '@wordpress/components';
|
|
3
|
+
|
|
4
|
+
type WebentorBlockAppenderProps = {
|
|
5
|
+
rootClientId: string | null;
|
|
6
|
+
text: string;
|
|
7
|
+
icon?: IconType;
|
|
8
|
+
variant?: 'primary' | 'secondary' | 'tertiary';
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Block appender component with customizable button.
|
|
13
|
+
*/
|
|
14
|
+
export const WebentorBlockAppender: React.FC<WebentorBlockAppenderProps> = ({
|
|
15
|
+
rootClientId,
|
|
16
|
+
text,
|
|
17
|
+
icon,
|
|
18
|
+
variant,
|
|
19
|
+
}) => {
|
|
20
|
+
return (
|
|
21
|
+
<Inserter
|
|
22
|
+
rootClientId={rootClientId}
|
|
23
|
+
renderToggle={({ onToggle }) => (
|
|
24
|
+
<Button
|
|
25
|
+
className="webentor-block-appender"
|
|
26
|
+
onClick={onToggle}
|
|
27
|
+
// disabled={disabled}
|
|
28
|
+
icon={icon ?? 'plus'}
|
|
29
|
+
text={text}
|
|
30
|
+
variant={variant ?? 'secondary'}
|
|
31
|
+
/>
|
|
32
|
+
)}
|
|
33
|
+
isAppender
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|