@lilaquadrat/design-core 0.1.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.
Files changed (86) hide show
  1. package/README.md +236 -0
  2. package/html/index.html +25 -0
  3. package/html/index.mail.html +15 -0
  4. package/html/index.server.html +29 -0
  5. package/package.json +148 -0
  6. package/src/client-entry.ts +28 -0
  7. package/src/components/partials/action.partial.vue +30 -0
  8. package/src/components/partials/client-only.partial.vue +11 -0
  9. package/src/components/partials/error.partial.vue +73 -0
  10. package/src/components/partials/main-components.partial.vue +167 -0
  11. package/src/components/partials/mediadetection.partial.vue +71 -0
  12. package/src/components/partials/qrcode.partial.vue +35 -0
  13. package/src/customs.ts +12 -0
  14. package/src/env.d.ts +1 -0
  15. package/src/functions/PaymenyProviderFactory.ts +27 -0
  16. package/src/functions/lila-dom.ts +100 -0
  17. package/src/functions/shopify.provider.ts +378 -0
  18. package/src/functions/stripe.provider.ts +181 -0
  19. package/src/globals.d.ts +19 -0
  20. package/src/index.ts +47 -0
  21. package/src/interfaces/AppState.interface.ts +4 -0
  22. package/src/interfaces/EditorConfiguration.interface.ts +15 -0
  23. package/src/interfaces/EventDeclaration.interface.ts +19 -0
  24. package/src/interfaces/FrontendConfig.interface.ts +42 -0
  25. package/src/interfaces/GenericEvents.interface.ts +6 -0
  26. package/src/interfaces/GenericState.interface.ts +5 -0
  27. package/src/interfaces/IconsPartial.ts +9 -0
  28. package/src/interfaces/IdTokenExtended.interface.ts +7 -0
  29. package/src/interfaces/ModuleBaseProps.interface.ts +8 -0
  30. package/src/interfaces/PaymentProvider.interface.ts +13 -0
  31. package/src/libs/ActionNotice.ts +235 -0
  32. package/src/libs/Models.class.ts +482 -0
  33. package/src/main.ts +84 -0
  34. package/src/mixins/createCookieString.ts +78 -0
  35. package/src/mixins/createModelDeclaration.ts +29 -0
  36. package/src/mixins/createRouter.ts +30 -0
  37. package/src/mixins/date.ts +23 -0
  38. package/src/mixins/formatSize.ts +12 -0
  39. package/src/mixins/getAnchor.ts +14 -0
  40. package/src/mixins/getRoutes.ts +50 -0
  41. package/src/mixins/hasSlotContent.ts +32 -0
  42. package/src/mixins/hooks.ts +104 -0
  43. package/src/mixins/loadComponents.ts +107 -0
  44. package/src/mixins/logger.ts +32 -0
  45. package/src/mixins/replaceVariables.ts +19 -0
  46. package/src/mixins/scroll.ts +83 -0
  47. package/src/models/Address.model.ts +24 -0
  48. package/src/models/Contact.model.ts +22 -0
  49. package/src/models.ts +2 -0
  50. package/src/plugins/auth.ts +121 -0
  51. package/src/plugins/currency.ts +26 -0
  52. package/src/plugins/events.ts +156 -0
  53. package/src/plugins/filters.ts +43 -0
  54. package/src/plugins/inview.ts +351 -0
  55. package/src/plugins/replacer.ts +18 -0
  56. package/src/plugins/resize.ts +128 -0
  57. package/src/plugins/signupFlow.ts +89 -0
  58. package/src/plugins/traceable.ts +53 -0
  59. package/src/plugins/translations.ts +29 -0
  60. package/src/plugins/youtube.ts +80 -0
  61. package/src/routes.ts +132 -0
  62. package/src/server-entry.ts +113 -0
  63. package/src/stores/calls.store.ts +33 -0
  64. package/src/stores/cart.store.ts +186 -0
  65. package/src/stores/content.store.ts +83 -0
  66. package/src/stores/editor.store.ts +27 -0
  67. package/src/stores/files.store.ts +166 -0
  68. package/src/stores/main.store.ts +184 -0
  69. package/src/stores/user.store.ts +124 -0
  70. package/src/translations/de.ts +138 -0
  71. package/src/views/content.view.vue +219 -0
  72. package/src/views/download.view.vue +143 -0
  73. package/src/views/editor.view.vue +243 -0
  74. package/src/views/login.view.vue +82 -0
  75. package/src/views/signup-account.view.vue +64 -0
  76. package/tooling/cypress/config.ts +80 -0
  77. package/tooling/cypress/generate-manifest.js +5 -0
  78. package/tooling/cypress/manifest-utils.mjs +40 -0
  79. package/tooling/cypress/run-parallel.mjs +77 -0
  80. package/tooling/cypress/support/commands.ts +436 -0
  81. package/tooling/cypress/support/e2e.ts +17 -0
  82. package/tooling/eslint.config.js +223 -0
  83. package/tooling/preview.plugin.ts +134 -0
  84. package/tooling/ssr-test/index.mjs +391 -0
  85. package/tooling/stylelint.config.mjs +24 -0
  86. package/tooling/vite.ts +246 -0
@@ -0,0 +1,156 @@
1
+ import type GenericEvents from '../interfaces/GenericEvents.interface';
2
+ import type EventDeclaration from '../interfaces/EventDeclaration.interface';
3
+ import { auth } from './auth';
4
+ import useUserStore from '../stores/user.store';
5
+ import useCartStore from '../stores/cart.store';
6
+ import { useTraceable } from './traceable';
7
+ import StudioSDK from '@lilaquadrat/sdk';
8
+ import useMainStore from '../stores/main.store';
9
+ import logger from '../mixins/logger';
10
+ import type { Ref } from 'vue';
11
+
12
+ const eventDeclarations: EventDeclaration[] = [
13
+ {
14
+ id : 'login',
15
+ name : 'Anmelden',
16
+ description: 'löst den Login für Benutzer aus',
17
+ },
18
+ {
19
+ id : 'logout',
20
+ name : 'Abmelden',
21
+ description: 'löst den Logout für Benutzer aus',
22
+ },
23
+ {
24
+ id : 'register',
25
+ name : 'Registrieren',
26
+ description: 'erstellt ein neues Benutzerkonto',
27
+ },
28
+ {
29
+ id : 'resendConfirmationMail',
30
+ name : 'Bestätigungscode erneut senden',
31
+ description : 'Eingeloggte Nutzer',
32
+ confirmRequired: true,
33
+ operation : true,
34
+ feedback : {
35
+ resolved: 'Bestätigungscode wurde versendet',
36
+ rejected: 'Bestätigungscode konnte nicht gesendet werden',
37
+ pending : 'Bestätigungscode wird versendet'
38
+ }
39
+ },
40
+ {
41
+ id : 'refresh_token',
42
+ name : 'Anmeldung aktualisieren',
43
+ description: 'aktualisiert das Authentifizierungstoken für den Benutzer',
44
+ },
45
+ {
46
+ id : 'addToCart',
47
+ name : 'In den Warenkorb legen',
48
+ description : 'fügt das angegebene Produkt dem Warenkorb hinzu',
49
+ additionalData: {
50
+ name : 'shopifyid',
51
+ description: 'die Produkt-ID'
52
+ }
53
+ },
54
+ {
55
+ id : 'scrollToNextModule',
56
+ name : 'Scroll zum nächstes Module',
57
+ description: 'Scrollt zum nächsten Module',
58
+ }
59
+ ];
60
+ const events: GenericEvents = {
61
+ login: () => {
62
+
63
+ const userStore = useUserStore();
64
+
65
+ auth.triggerLogin(userStore.customer?._id, userStore.emailConfirmationCode);
66
+
67
+ },
68
+ logout: () => {
69
+
70
+ auth.triggerLogout();
71
+
72
+ },
73
+ register: () => {
74
+
75
+ const userStore = useUserStore();
76
+
77
+ auth.triggerSignup(userStore.customer?._id, userStore.emailConfirmationCode);
78
+
79
+ },
80
+ addToCart: (product?: string) => {
81
+
82
+ console.log('add to cart', product);
83
+
84
+ if (!product) {
85
+ console.warn('ADD_TO_CART_FAILED_PRODUCT_ID_MISSING');
86
+ return;
87
+ }
88
+
89
+ const cartStore = useCartStore();
90
+
91
+ cartStore.addProduct(product as string);
92
+
93
+ },
94
+ refresh_token: () => {
95
+
96
+ auth.triggerLogin()
97
+
98
+ },
99
+ scrollToNextModule: (additionalData: string | undefined, mouseEvent: MouseEvent) => {
100
+
101
+ const target = mouseEvent.target as HTMLElement;
102
+ const parentModule = target?.closest('.lila-module');
103
+ const nextSibling = parentModule?.nextElementSibling;
104
+
105
+ console.log('scroll to next module');
106
+
107
+ if (nextSibling) {
108
+
109
+ nextSibling.scrollIntoView({
110
+ behavior: 'smooth',
111
+ block : 'center'
112
+ });
113
+
114
+ }
115
+
116
+ },
117
+ resendConfirmationMail: async (additionalData: string | undefined, mouseEvent: MouseEvent, traceId: Ref<string | undefined>) => {
118
+
119
+ const { apiConfig } = useMainStore();
120
+ const { traceable } = useTraceable();
121
+ const sdk = new StudioSDK(apiConfig)
122
+
123
+ return traceable(sdk.members.me.resendConfirmationMail(), traceId);
124
+
125
+ }
126
+ }
127
+
128
+ /**
129
+ * triggers a predefined event
130
+ */
131
+ function triggerEvent (type: keyof typeof events | string, additionalData: string | undefined, mouseEvent: MouseEvent, traceId: Ref<string | undefined>) {
132
+
133
+ const event = events[type as keyof typeof events];
134
+
135
+ if (!event) {
136
+
137
+ console.error('EVENT_MISSING', type, event);
138
+ throw new Error('EVENT_MISSING');
139
+
140
+ }
141
+
142
+ return event(additionalData, mouseEvent, traceId);
143
+
144
+ }
145
+
146
+ const useEvents = () => ({ triggerEvent, eventDeclarations, events })
147
+ const plugin = {
148
+ install: () => {
149
+ logger.plugins('events installed');
150
+ },
151
+ };
152
+
153
+ export default plugin;
154
+ export {
155
+ useEvents
156
+ }
@@ -0,0 +1,43 @@
1
+ import useDate from '../mixins/date';
2
+ import logger from '../mixins/logger';
3
+ import type { App } from 'vue';
4
+
5
+ const HelpersPlugin = {
6
+
7
+ leadingZero (value: string | number, minLength: number) {
8
+ return value.toString().padStart(minLength, '0');
9
+ },
10
+
11
+ getFilename (contentType: 'public' | 'members', path?: string) {
12
+
13
+ const contentIdArray = [];
14
+
15
+ if(!path || path === '/') return 'home';
16
+
17
+ if(contentType === 'members' && path !== '/m' && !path.startsWith('/m/')) contentIdArray.push('m');
18
+
19
+ contentIdArray.push(...path.split('/'));
20
+
21
+ return contentIdArray.filter((single) => single.length).join('/');
22
+
23
+ },
24
+
25
+ date (date: string | Date, format?: string) {
26
+
27
+ return useDate(date).locale('de').format(format || 'DD.MM.YYYY HH:mm');
28
+
29
+ }
30
+
31
+ }
32
+ const plugin = {
33
+ install: (vue: App): void => {
34
+
35
+ vue.config.globalProperties.$helpers = HelpersPlugin;
36
+ logger.plugins('helpers installed')
37
+ },
38
+ };
39
+
40
+ export default plugin;
41
+ export {
42
+ HelpersPlugin
43
+ };
@@ -0,0 +1,351 @@
1
+ import { computed, watch } from 'vue';
2
+ import { ref } from 'vue';
3
+ import { type Ref } from 'vue';
4
+
5
+ class Inview {
6
+
7
+ timeout!: NodeJS.Timeout | undefined;
8
+
9
+ lastScrollingAdjustment = 0;
10
+
11
+ debounceTime: number = 50;
12
+
13
+ isTop = ref<boolean>(false);
14
+
15
+ scrolledEvent: Event;
16
+
17
+ scrolled = ref<number>(0);
18
+
19
+ moduleAdded = ref<number>(0);
20
+
21
+ scrollDirection = ref<'up' | 'down'>();
22
+
23
+ parentElement = ref<HTMLElement>();
24
+
25
+ lastScrollY = 0;
26
+ lastTimestamp = 0;
27
+ scrollVelocity = 0;
28
+
29
+ /**
30
+ * if true we fire an inital scroll event to indicate that scrolling has started without waiting for the debounce
31
+ */
32
+ triggerStart = ref<boolean>(true);
33
+
34
+ safeWindow = computed(() => {
35
+
36
+ if (typeof window === 'undefined') return null;
37
+ if (this.parentElement.value) return this.parentElement.value;
38
+ return window;
39
+
40
+ });
41
+
42
+ scrollY () {
43
+
44
+ if (this.safeWindow.value instanceof Window) {
45
+
46
+ return this.safeWindow.value.scrollY;
47
+
48
+ }
49
+
50
+ if (this.parentElement.value) {
51
+
52
+ return this.parentElement.value.scrollTop;
53
+ }
54
+
55
+ return 0
56
+
57
+ }
58
+
59
+ height () {
60
+
61
+ if (this.safeWindow.value instanceof Window) {
62
+
63
+ return this.safeWindow.value.outerHeight;
64
+
65
+ }
66
+
67
+ if (this.parentElement.value) {
68
+
69
+ return this.parentElement.value.offsetHeight;
70
+ }
71
+
72
+ return 0
73
+
74
+ }
75
+
76
+ constructor () {
77
+
78
+ this.scrolledEvent = new Event('scrolled');
79
+ this.checkIsTop();
80
+
81
+ if (this.safeWindow.value) {
82
+
83
+ this.safeWindow.value?.addEventListener('scroll', () => {
84
+
85
+ this.debounce();
86
+
87
+ });
88
+
89
+ }
90
+
91
+ }
92
+
93
+ setParentElement (element: HTMLElement) {
94
+
95
+ this.parentElement.value = element;
96
+ this.addScrollListener(element);
97
+
98
+ }
99
+
100
+ addScrollListener (element: Element) {
101
+
102
+ element.addEventListener('scroll', () => {
103
+
104
+ const currentTimestamp = performance.now();
105
+ const deltaY = this.scrollY() - this.lastScrollY;
106
+ const deltaTime = currentTimestamp - this.lastTimestamp;
107
+
108
+ // Calculate velocity (pixels per millisecond)
109
+ this.scrollVelocity = Math.abs(deltaY / deltaTime);
110
+
111
+ this.lastScrollY = this.scrollY();
112
+ this.lastTimestamp = currentTimestamp;
113
+
114
+ // console.log(`Scroll Velocity: ${this.scrollVelocity.toFixed(2)} pixels/ms`);
115
+
116
+ this.debounce();
117
+
118
+ });
119
+
120
+ }
121
+
122
+ trigger (isStart?: boolean) {
123
+
124
+ if (!this.safeWindow.value) return;
125
+
126
+ this.checkIsTop();
127
+ this.scrollDirection.value = this.scrolled.value > this.scrollY()
128
+ ? 'down'
129
+ : 'up'
130
+ this.scrolled.value = this.scrollY();
131
+
132
+ this.safeWindow.value?.dispatchEvent(this.scrolledEvent);
133
+ if (!isStart) this.triggerStart.value = true;
134
+
135
+ }
136
+
137
+ checkIsTop () {
138
+
139
+ if (!this.safeWindow.value) return;
140
+
141
+ this.isTop.value = this.scrollY() <= 0
142
+
143
+ }
144
+
145
+ debounce () {
146
+
147
+ /**
148
+ * indicates that the scrolling has begun and fire an inital scrolling event without waiting for the debounce
149
+ */
150
+ if (this.triggerStart.value) {
151
+
152
+ this.triggerStart.value = false;
153
+ this.trigger(true);
154
+
155
+ }
156
+
157
+ clearTimeout(this.timeout);
158
+ this.timeout = setTimeout(() => {
159
+
160
+ this.trigger();
161
+
162
+ }, this.debounceTime);
163
+
164
+ }
165
+
166
+ check (component: HTMLElement, state: Ref<string[]>, options?: { align?: boolean }) {
167
+ const element = component;
168
+ const newState: string[] = [];
169
+
170
+ if (typeof element?.getBoundingClientRect !== 'function') return;
171
+ if (!this.safeWindow.value) return;
172
+
173
+ const viewportHeight = this.height();
174
+ const height = viewportHeight / 2;
175
+ const rect = element.getBoundingClientRect();
176
+ let top = rect.top - height + 10;
177
+ let bottom = rect.bottom - height + 10;
178
+ let visibleHeight = 0;
179
+ let marginToTop = 0;
180
+
181
+ if (this.parentElement.value) {
182
+
183
+ const parentRect = this.parentElement.value.getBoundingClientRect();
184
+ // Adjust top and bottom based on parent element's top and bottom
185
+ const parentTop = parentRect.top;
186
+ const parentBottom = parentRect.bottom;
187
+
188
+ top = rect.top - parentTop - height + 10;
189
+ bottom = rect.bottom - parentTop - height + 10;
190
+
191
+ marginToTop = Math.abs(rect.top - parentTop);
192
+
193
+ // Adjust visibleTop and visibleBottom for parent element
194
+ const visibleTop = Math.max(parentTop, rect.top);
195
+ const visibleBottom = Math.min(parentBottom, rect.bottom);
196
+
197
+ visibleHeight = Math.max(0, visibleBottom - visibleTop);
198
+
199
+ } else {
200
+
201
+ // Original calculations if no parent element is provided
202
+ const visibleTop = Math.max(0, rect.top);
203
+ const visibleBottom = Math.min(rect.bottom, viewportHeight);
204
+
205
+ marginToTop = Math.abs(rect.top);
206
+
207
+ visibleHeight = Math.max(0, visibleBottom - visibleTop);
208
+
209
+ }
210
+
211
+ if (top > 0) {
212
+ newState.push('inview-after');
213
+ }
214
+
215
+ if (top <= 0 && bottom >= 0) {
216
+ newState.push('inview-current');
217
+ }
218
+
219
+ if (bottom < 0) {
220
+ newState.push('inview-before');
221
+ }
222
+
223
+ // Check if more than 30% of the element is visible
224
+ if (visibleHeight / rect.height >= 0.3) {
225
+ newState.push('inview-visible');
226
+ }
227
+
228
+ if (newState.includes('inview-current') && options?.align) {
229
+
230
+ if(!this.lastScrollingAdjustment || Date.now() - this.lastScrollingAdjustment > 1500) {
231
+
232
+ requestAnimationFrame(() => this.adjustScrolling(element, marginToTop));
233
+
234
+ }
235
+
236
+ }
237
+
238
+ state.value.length = 0;
239
+ state.value.push(...newState);
240
+ }
241
+
242
+ checkPreload (component: HTMLElement, state: Ref<boolean>) {
243
+
244
+ const preloadRange = window?.outerHeight * 2;
245
+ const rect = component.getBoundingClientRect();
246
+
247
+ if (rect.bottom > -preloadRange && rect.top < preloadRange) {
248
+
249
+ state.value = true;
250
+
251
+ }
252
+
253
+ }
254
+
255
+ adjustScrolling (component: HTMLElement, top: number) {
256
+
257
+ const offset = this.height() / 10;
258
+
259
+ if (top < offset && top > (offset * -1)) {
260
+
261
+ this.lastScrollingAdjustment = Date.now();
262
+
263
+ component.scrollIntoView({
264
+ behavior: 'smooth',
265
+ });
266
+
267
+ }
268
+
269
+ }
270
+
271
+ moduleRendered () {
272
+
273
+ this.moduleAdded.value++;
274
+
275
+ }
276
+
277
+ }
278
+
279
+ const inview = new Inview();
280
+
281
+ /**
282
+ * the preload option is used to check if the element is in range of two times of the viewport and changes the preload value accordingly
283
+ *
284
+ * without the preload options the inviewState array holds the following values
285
+ ** inview-before - the element is before the viewport
286
+ ** inview-current - the element is centered in the viewport
287
+ ** inview-after - the element is after the viewport
288
+ ** inview-visible - more than 30% of the element are visible in the current viewport, regardless if it is centered or nor
289
+ */
290
+
291
+ export function useInview (element?: Ref<HTMLElement | undefined>, options?: { align?: boolean, preload?: boolean }) {
292
+
293
+ const state = ref<string[]>([]);
294
+ const preload = ref<boolean>(false);
295
+
296
+ if (element) {
297
+
298
+ watch(element, () => {
299
+
300
+ if (element.value) {
301
+
302
+ inview.moduleRendered();
303
+
304
+ if (options?.preload) {
305
+
306
+ inview.checkPreload(element.value, preload);
307
+
308
+ const unwatchPreload = watch(inview.scrolled, () => {
309
+
310
+ if (!element.value) return;
311
+
312
+ inview.checkPreload(element.value as HTMLElement, preload);
313
+
314
+ //unwatch when the preload value is true
315
+ if (preload.value) unwatchPreload();
316
+
317
+ })
318
+
319
+ } else {
320
+
321
+ inview.check(element.value, state, options);
322
+
323
+ watch(inview.scrolled, () => {
324
+
325
+ inview.check(element.value as HTMLElement, state, options)
326
+
327
+ })
328
+
329
+ watch(inview.moduleAdded, () => {
330
+
331
+ requestAnimationFrame(() => {
332
+
333
+ inview.check(element.value as HTMLElement, state, options);
334
+
335
+ })
336
+
337
+ })
338
+
339
+ }
340
+
341
+ }
342
+
343
+ })
344
+
345
+ }
346
+
347
+ return { inviewState: state, scrolled: inview.scrolled, scrollDirection: inview.scrollDirection, preload };
348
+
349
+ }
350
+
351
+ export default inview;
@@ -0,0 +1,18 @@
1
+ import logger from '../mixins/logger';
2
+ import replaceVariables from '../mixins/replaceVariables';
3
+ import useContentStore from '../stores/content.store';
4
+ import useUserStore from '../stores/user.store';
5
+ import type { App } from 'vue';
6
+
7
+ const plugin = {
8
+ install: (vue: App): void => {
9
+
10
+ const contentStore = useContentStore();
11
+ const userStore = useUserStore();
12
+
13
+ vue.config.globalProperties.$replacer = (content: string) => replaceVariables(content, {...contentStore.context, recipient: contentStore.recipient, list: contentStore.list, user: userStore.userData });
14
+ logger.plugins('replacer installed')
15
+ },
16
+ };
17
+
18
+ export default plugin;
@@ -0,0 +1,128 @@
1
+ import logger from '../mixins/logger';
2
+ import { ref, computed } from 'vue';
3
+
4
+ class Resize {
5
+
6
+ timeout: any;
7
+
8
+ debounceTime: number = 50;
9
+
10
+ resizedEvent: Event;
11
+
12
+ mediaEvent: Event;
13
+
14
+ media = ref<string>('mobile');
15
+
16
+ resized = ref<number>(Date.now());
17
+
18
+ realHeight = ref<number>(0);
19
+
20
+ /**
21
+ * if true we fire an inital resized event to indicate that resizing has started without waiting for the debounce
22
+ */
23
+ triggerStart = ref<boolean>(true);
24
+
25
+ safeWindow = computed(() => {
26
+
27
+ if(typeof window === 'undefined') return null;
28
+ return window;
29
+
30
+ });
31
+
32
+ constructor () {
33
+
34
+ this.resizedEvent = new Event('resized');
35
+ this.mediaEvent = new Event('media');
36
+ this.realHeight.value = this.safeWindow.value?.innerHeight || 0;
37
+
38
+ this.getMediaQuery();
39
+
40
+ this.safeWindow.value?.addEventListener('resize', () => this.debounce());
41
+
42
+ }
43
+
44
+ trigger (isStart?: boolean) {
45
+
46
+ this.getMediaQuery();
47
+
48
+ if(this.safeWindow.value) {
49
+
50
+ this.realHeight.value = this.safeWindow.value?.innerHeight;
51
+ }
52
+
53
+ this.resized.value = Date.now();
54
+ this.safeWindow.value?.dispatchEvent(this.resizedEvent);
55
+
56
+ if(!isStart) this.triggerStart.value = true;
57
+
58
+ }
59
+
60
+ getMediaQuery (): void {
61
+
62
+ if(typeof document === 'undefined') return;
63
+
64
+ const element = document.getElementById('mediadetection');
65
+
66
+ if (!element) return;
67
+
68
+ const child = Array.from(element.children).find(child => this.safeWindow.value?.getComputedStyle(child).display === 'block');
69
+
70
+ if (child) {
71
+ const childClass = child.getAttribute('class') as string;
72
+
73
+ if (this.media.value !== childClass) {
74
+
75
+ this.media.value = childClass;
76
+ this.safeWindow.value?.dispatchEvent(this.mediaEvent);
77
+
78
+ } else {
79
+
80
+ this.media.value = childClass;
81
+
82
+ }
83
+ }
84
+ }
85
+
86
+ debounce () {
87
+
88
+ /**
89
+ * indicates that the scrolling has begun and fire an inital scrolling event without waiting for the debounce
90
+ */
91
+ if(this.triggerStart.value) {
92
+
93
+ this.triggerStart.value = false;
94
+ this.trigger(true);
95
+
96
+ }
97
+
98
+ clearTimeout(this.timeout);
99
+ this.timeout = setTimeout(() => {
100
+
101
+ this.trigger();
102
+
103
+ }, this.debounceTime);
104
+
105
+ }
106
+
107
+ }
108
+
109
+ const resize = new Resize();
110
+ const plugin = {
111
+ install: (): void => {
112
+ // this exists only for initialization purposes
113
+ logger.plugins('resize installed');
114
+ },
115
+ };
116
+
117
+ function useResize () {
118
+
119
+ return {realHeight: resize.realHeight, media: resize.media, resized: resize.resized, plugin: resize};
120
+
121
+ }
122
+
123
+ export default plugin;
124
+
125
+ export {
126
+ useResize,
127
+ resize
128
+ };