@squeditor/squeditor-framework 1.0.2 → 1.0.4

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 (33) hide show
  1. package/README.md +22 -31
  2. package/package.json +1 -1
  3. package/php/functions.php +45 -0
  4. package/project-template/package.json +3 -1
  5. package/project-template/squeditor.config.js +21 -9
  6. package/project-template/src/assets/js/_slider_dynamic.js +2 -0
  7. package/project-template/src/assets/js/gsap-init.js +28 -1
  8. package/project-template/src/assets/js/main.js +1 -0
  9. package/project-template/src/assets/js/modules/splide-init.js +207 -0
  10. package/project-template/src/assets/js/modules/swiper-init.js +216 -0
  11. package/project-template/src/assets/js/uikit-components.js +27 -21
  12. package/project-template/src/assets/scss/_base.scss +0 -9
  13. package/project-template/src/assets/scss/_components.scss +107 -2
  14. package/project-template/src/assets/scss/_swiper.scss +30 -0
  15. package/project-template/src/assets/scss/main.scss +2 -1
  16. package/project-template/src/assets/scss/themes/_two.scss +95 -0
  17. package/project-template/src/assets/static/images/og-default.png +0 -0
  18. package/project-template/src/assets/static/images/placeholder.png +0 -0
  19. package/project-template/src/index.php +5 -5
  20. package/project-template/src/init.php +38 -2
  21. package/project-template/src/page-templates/head.php +9 -1
  22. package/project-template/src/slider-test.php +87 -0
  23. package/project-template/src/template-parts/header.php +11 -11
  24. package/project-template/tailwind.config.js +29 -1
  25. package/scripts/build-components.js +78 -1
  26. package/scripts/copy-static.js +26 -0
  27. package/scripts/dev-router.php +10 -1
  28. package/scripts/dev.js +30 -1
  29. package/scripts/package-customer.js +52 -21
  30. package/scripts/package-dist.js +1 -1
  31. package/scripts/scaffold.js +4 -3
  32. package/scripts/snapshot.js +134 -33
  33. package/scripts/utils/resolve-pages.js +47 -0
@@ -0,0 +1,216 @@
1
+ import Swiper from 'swiper';
2
+ import { Navigation, Pagination, Autoplay, Parallax, Thumbs, EffectFade, FreeMode } from 'swiper/modules';
3
+
4
+ // Swiper CSS is handled separately by build-components.js → slider.min.css
5
+
6
+ function splitTopLevel(str, delimiters = [';', ',']) {
7
+ const result = [];
8
+ let current = '';
9
+ let braceDepth = 0;
10
+
11
+ for (let i = 0; i < str.length; i++) {
12
+ const char = str[i];
13
+ if (char === '{') braceDepth++;
14
+ if (char === '}') braceDepth--;
15
+
16
+ if (braceDepth === 0 && delimiters.includes(char)) {
17
+ result.push(current);
18
+ current = '';
19
+ } else {
20
+ current += char;
21
+ }
22
+ }
23
+ if (current) result.push(current);
24
+ return result;
25
+ }
26
+
27
+ /**
28
+ * Parses a string like "slidesPerView: 1; md: {slidesPerView: 3}; loop: true"
29
+ * into a valid JavaScript object.
30
+ */
31
+ function parseSwiperOptions(optionString) {
32
+ if (!optionString) return {};
33
+
34
+ const options = {};
35
+ const statements = splitTopLevel(optionString, [';', ',']);
36
+
37
+ statements.forEach(statement => {
38
+ statement = statement.trim();
39
+ if (!statement) return;
40
+
41
+ const firstColon = statement.indexOf(':');
42
+ if (firstColon > -1) {
43
+ const key = statement.slice(0, firstColon).trim();
44
+ let rawValue = statement.slice(firstColon + 1).trim();
45
+
46
+ // Handle nested objects
47
+ if (rawValue.startsWith('{') && rawValue.endsWith('}')) {
48
+ const innerString = rawValue.slice(1, -1);
49
+ options[key] = parseSwiperOptions(innerString);
50
+ } else {
51
+ options[key] = parsePrimitive(rawValue);
52
+ }
53
+ }
54
+ });
55
+
56
+ return options;
57
+ }
58
+
59
+ function parsePrimitive(val) {
60
+ if (val === 'true') return true;
61
+ if (val === 'false') return false;
62
+ if (val === 'null') return null;
63
+
64
+ // Check if it's a number
65
+ if (!isNaN(vanillaParseFloat(val))) {
66
+ return vanillaParseFloat(val);
67
+ }
68
+
69
+ // Remove wrapping quotes if they exist
70
+ if ((val.startsWith("'") && val.endsWith("'")) || (val.startsWith('"') && val.endsWith('"'))) {
71
+ return val.slice(1, -1);
72
+ }
73
+
74
+ return val;
75
+ }
76
+
77
+ function vanillaParseFloat(val) {
78
+ if(typeof val === 'string' && val.trim() === '') return NaN;
79
+ return Number(val);
80
+ }
81
+
82
+ /**
83
+ * Maps Tailwind breakpoints to Swiper breakpoints
84
+ */
85
+ function mapBreakpoints(options) {
86
+ const swiperBreakpoints = {};
87
+ const tailwindScreens = {
88
+ 'sm': 640,
89
+ 'md': 768,
90
+ 'lg': 1024,
91
+ 'xl': 1280,
92
+ '2xl': 1536
93
+ };
94
+
95
+ let hasBreakpoints = false;
96
+
97
+ // 1. Move root-level 'sm', 'md' directly into swiperBreakpoints
98
+ Object.keys(tailwindScreens).forEach(screen => {
99
+ if (options[screen]) {
100
+ hasBreakpoints = true;
101
+ swiperBreakpoints[tailwindScreens[screen]] = options[screen];
102
+ delete options[screen]; // Remove from root options
103
+ }
104
+ });
105
+
106
+ // 2. Process nested options.breakpoints if it exists
107
+ if (options.breakpoints) {
108
+ hasBreakpoints = true;
109
+ Object.keys(options.breakpoints).forEach(key => {
110
+ if (tailwindScreens[key]) {
111
+ swiperBreakpoints[tailwindScreens[key]] = options.breakpoints[key];
112
+ } else {
113
+ swiperBreakpoints[key] = options.breakpoints[key];
114
+ }
115
+ });
116
+ }
117
+
118
+ if (hasBreakpoints && Object.keys(swiperBreakpoints).length > 0) {
119
+ options.breakpoints = swiperBreakpoints;
120
+ }
121
+
122
+ return options;
123
+ }
124
+
125
+ /**
126
+ * Initializes Swiper instance for a single element
127
+ */
128
+ function initSwiperElement(el) {
129
+ // Prevent double initialization
130
+ if (el.swiper) return;
131
+
132
+ const rawOptions = el.getAttribute('data-sq-swiper') || '';
133
+ let parsedOptions = parseSwiperOptions(rawOptions);
134
+ parsedOptions = mapBreakpoints(parsedOptions);
135
+
136
+ // Default Configuration
137
+ const config = {
138
+ modules: [Navigation, Pagination, Autoplay, Parallax, Thumbs, EffectFade, FreeMode],
139
+ speed: 600,
140
+ // Optional navigation
141
+ navigation: {},
142
+ // Optional pagination
143
+ pagination: {
144
+ clickable: true
145
+ },
146
+ ...parsedOptions
147
+ };
148
+
149
+ // Apply custom detached navigation if specified
150
+ if (parsedOptions.navNext || parsedOptions.navPrev) {
151
+ config.navigation = {
152
+ nextEl: parsedOptions.navNext || null,
153
+ prevEl: parsedOptions.navPrev || null
154
+ };
155
+ // Clean up root
156
+ delete config.navNext;
157
+ delete config.navPrev;
158
+ }
159
+
160
+ // Apply custom detached pagination if specified
161
+ if (parsedOptions.paginationEl) {
162
+ config.pagination = {
163
+ el: parsedOptions.paginationEl,
164
+ clickable: true,
165
+ type: parsedOptions.paginationType || 'bullets'
166
+ };
167
+ delete config.paginationEl;
168
+ delete config.paginationType;
169
+ }
170
+
171
+ // Handle Thumbs Gallery synchronization
172
+ if (parsedOptions.thumbs) {
173
+ const thumbTarget = document.querySelector(parsedOptions.thumbs);
174
+ if (thumbTarget) {
175
+ // First, ensure the thumb target is initialized
176
+ if (!thumbTarget.swiper) {
177
+ initSwiperElement(thumbTarget);
178
+ }
179
+ config.thumbs = {
180
+ swiper: thumbTarget.swiper
181
+ };
182
+ }
183
+ }
184
+
185
+ // Ensure slider has basic class structure required by CSS
186
+ if (!el.classList.contains('swiper')) {
187
+ el.classList.add('swiper');
188
+ }
189
+
190
+ const wrapper = el.querySelector(':scope > div');
191
+ if (wrapper && !wrapper.classList.contains('swiper-wrapper')) {
192
+ wrapper.classList.add('swiper-wrapper');
193
+ }
194
+
195
+ const slides = wrapper ? wrapper.children : el.children;
196
+ Array.from(slides).forEach(slide => {
197
+ if (!slide.classList.contains('swiper-slide')) {
198
+ slide.classList.add('swiper-slide');
199
+ }
200
+ });
201
+
202
+ // Initialize!
203
+ new Swiper(el, config);
204
+ }
205
+
206
+ /**
207
+ * Global Initialization
208
+ */
209
+ export function initSwiper() {
210
+ const swipers = document.querySelectorAll('[data-sq-swiper]');
211
+ swipers.forEach(initSwiperElement);
212
+ }
213
+
214
+ document.addEventListener('DOMContentLoaded', () => {
215
+ initSwiper();
216
+ });