@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,167 @@
1
+ <script setup lang="ts">
2
+ import { HelpersPlugin } from '../../plugins/filters';
3
+ import useContentStore from '../../stores/content.store';
4
+ import useMainStore from '../../stores/main.store';
5
+ import useUserStore from '../../stores/user.store';
6
+ import type { BasicData, Content, ContentWithPositions, GenericData } from '@lilaquadrat/interfaces';
7
+ import type { SDKResponse } from '@lilaquadrat/sdk';
8
+ import { distributeGenericData, generateDataWithContent, hardCopy, prepareContent } from '@lilaquadrat/studio';
9
+ import { ref, computed, watch, onServerPrefetch, onBeforeMount } from 'vue';
10
+ import { useRoute } from 'vue-router';
11
+
12
+ const props = defineProps<{
13
+ type: 'footer' | 'navigation'
14
+ }>();
15
+ const store = useMainStore();
16
+ const userStore = useUserStore();
17
+ const contentStore = useContentStore();
18
+ const route = useRoute();
19
+ const data = ref<SDKResponse<BasicData<Content>>>();
20
+ const dataMerged = ref<ContentWithPositions>();
21
+ const loading = ref<number>(0);
22
+ const error = ref<boolean>(false);
23
+ const typeCache = ref<string>();
24
+ const contentType = computed(() => route.meta.contentType as 'public' | 'members');
25
+ const isLocked = computed(() => contentType.value == 'members' && userStore.locked?.length);
26
+
27
+ watch(route, () => getContent());
28
+ watch(() => userStore.locked, () => {
29
+
30
+ if(!userStore.locked) {
31
+ getContent();
32
+ }
33
+
34
+ });
35
+
36
+ onBeforeMount(async () => await getContent());
37
+ onServerPrefetch(() => getStoreContent());
38
+
39
+ function getStoreContent () {
40
+
41
+ const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
42
+ const storeContent = contentStore.findByFilename(contentId);
43
+
44
+ if(!storeContent) return;
45
+
46
+ data.value = {
47
+ data : storeContent,
48
+ status: 200,
49
+ };
50
+
51
+ loading.value = 200;
52
+
53
+ dataMerged.value = mergeContent(data.value.data);
54
+
55
+ }
56
+
57
+ async function getContent () {
58
+
59
+ getStoreContent();
60
+
61
+ const contentId = HelpersPlugin.getFilename(route.meta.contentType as 'public' | 'members', props.type);
62
+
63
+ if(data.value?.data?.id === contentId) {
64
+
65
+ return;
66
+
67
+ }
68
+
69
+ if(isLocked.value) {
70
+
71
+ loading.value = 0;
72
+ error.value = true;
73
+
74
+ return;
75
+ }
76
+
77
+ if(contentType.value !== typeCache.value) {
78
+
79
+ loading.value = 0;
80
+ error.value = false;
81
+ data.value = undefined;
82
+
83
+ }
84
+
85
+ const storeData = contentStore.findByFilename(contentId);
86
+
87
+ if(storeData) {
88
+
89
+ data.value = {data: storeData, status: 200};
90
+ loading.value = 200;
91
+ return;
92
+
93
+ }
94
+
95
+ // get content only if there is a difference between the current and the needed content
96
+ if (data.value?.data?.id !== contentId && loading.value === 0) {
97
+
98
+ loading.value = 100;
99
+
100
+ try {
101
+
102
+ data.value = await store.getContent({filename: contentId}, contentType.value) as SDKResponse<BasicData<Content>>;
103
+ loading.value = data.value.status;
104
+
105
+ } catch (e: any) {
106
+
107
+ data.value = undefined;
108
+ error.value = true;
109
+ loading.value = e?.response?.status;
110
+
111
+ }
112
+
113
+ if(data.value?.status === 403 || data.value?.status === 401) {
114
+
115
+ error.value = true;
116
+ loading.value = data.value?.status;
117
+ data.value = undefined;
118
+
119
+ }
120
+
121
+ typeCache.value = route.meta.contentType as string;
122
+
123
+ }
124
+
125
+ if(data.value) {
126
+
127
+ dataMerged.value = mergeContent(data.value?.data);
128
+
129
+ } else {
130
+
131
+ dataMerged.value = undefined;
132
+
133
+ }
134
+
135
+ }
136
+
137
+ function mergeContent (baseContent: BasicData<Content>) {
138
+
139
+ if(baseContent) {
140
+
141
+ const safeData = hardCopy(baseContent);
142
+
143
+ if(safeData.modules) {
144
+ /**
145
+ * content without generic data is the normal case for a static page, and
146
+ * generateDataWithContent reads Object.keys of what it is given - so it
147
+ * throws on undefined instead of returning nothing
148
+ */
149
+ if(safeData.genericData) {
150
+
151
+ distributeGenericData(safeData.modules, generateDataWithContent(safeData.genericData as GenericData));
152
+
153
+ }
154
+ }
155
+
156
+ return prepareContent(safeData);
157
+
158
+ }
159
+
160
+ return undefined;
161
+
162
+ }
163
+
164
+ </script>
165
+ <template>
166
+ <lila-content-module v-if="dataMerged" :content="dataMerged" />
167
+ </template>
@@ -0,0 +1,71 @@
1
+ <script setup lang="ts">
2
+ import { useResize } from '../../plugins/resize';
3
+ import { onMounted } from 'vue';
4
+
5
+ const {plugin} = useResize();
6
+
7
+ onMounted(() => plugin.getMediaQuery());
8
+
9
+ </script>
10
+ <template>
11
+ <section id="mediadetection" class="mediadetection">
12
+ <div class="mobile" />
13
+ <div class="tablet" />
14
+ <div class="desktop" />
15
+ <div class="wide" />
16
+ </section>
17
+ </template>
18
+ <style lang="less" scoped>
19
+ .mediadetection {
20
+
21
+ .tablet,
22
+ .desktop,
23
+ .wide {
24
+ display: none;
25
+ }
26
+
27
+ .mobile {
28
+ display: block;
29
+ }
30
+
31
+ @media @tablet {
32
+
33
+ .mobile,
34
+ .desktop,
35
+ .wide {
36
+ display: none;
37
+ }
38
+
39
+ .tablet {
40
+ display: block
41
+ }
42
+ }
43
+
44
+ @media @desktop {
45
+
46
+ .mobile,
47
+ .tablet,
48
+ .wide {
49
+ display: none;
50
+ }
51
+
52
+ .desktop {
53
+ display: block;
54
+ }
55
+ }
56
+
57
+ @media @wide {
58
+
59
+ .mobile,
60
+ .tablet,
61
+ .desktop {
62
+ display: none;
63
+ }
64
+
65
+ .wide {
66
+ display: block
67
+ }
68
+ }
69
+
70
+ }
71
+ </style>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ import QRCode from 'qrcode';
3
+ import { ref, onMounted } from 'vue';
4
+
5
+ const props = defineProps<{
6
+ content: string
7
+ }>();
8
+ const qrCanvas = ref<HTMLCanvasElement | null>(null);
9
+
10
+ onMounted(() => {
11
+
12
+ renderQRCode();
13
+
14
+ });
15
+
16
+ const renderQRCode = () => {
17
+
18
+ if (qrCanvas.value) {
19
+
20
+ QRCode.toCanvas(qrCanvas.value, props.content, {
21
+ errorCorrectionLevel: 'M',
22
+ margin : 5,
23
+ width : 250,
24
+ })
25
+
26
+ }
27
+
28
+ };
29
+
30
+ </script>
31
+ <template>
32
+ <div class="qrcode">
33
+ <canvas ref="qrCanvas" />
34
+ </div>
35
+ </template>
package/src/customs.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { HelpersPlugin } from './plugins/filters'
2
+ import type {formatCurrency} from './plugins/currency'
3
+
4
+ export {}
5
+
6
+ declare module 'vue' {
7
+ interface ComponentCustomProperties {
8
+ $currency: typeof formatCurrency
9
+ $helpers: typeof HelpersPlugin
10
+ $replacer: (content: string) => string | undefined
11
+ }
12
+ }
package/src/env.d.ts ADDED
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,27 @@
1
+ import ShopifyGraphQLAPI from './shopify.provider';
2
+ import type PaymentProvider from '../interfaces/PaymentProvider.interface';
3
+ import StripePaymentProvider from './stripe.provider';
4
+
5
+ export default function PaymentProviderFactory (type: 'internal' | 'shopify' | 'stripe', config?: Record<string, string>): PaymentProvider {
6
+
7
+ let newProvider: PaymentProvider;
8
+
9
+ if(type === 'shopify') {
10
+
11
+ if(!config?.store || !config.token) throw new Error('PAYMENT_CONFIG_MISSING');
12
+
13
+ newProvider = new ShopifyGraphQLAPI(config.store, config.token);
14
+
15
+ } else if(type === 'stripe') {
16
+
17
+ newProvider = new StripePaymentProvider();
18
+
19
+ } else {
20
+
21
+ throw new Error('NO_PAYMENT_PROVIDER');
22
+
23
+ }
24
+
25
+ return newProvider;
26
+
27
+ }
@@ -0,0 +1,100 @@
1
+ export class Dom {
2
+
3
+ bindings: {event: string, element: any, func: EventListenerOrEventListenerObject}[];
4
+
5
+ constructor () {
6
+
7
+ this.bindings = [];
8
+
9
+ }
10
+
11
+ on (events: string, selector: string, func: EventListener) {
12
+
13
+ const splitEvents = events.split(' ');
14
+ const selectedElement = this.getElement(selector);
15
+
16
+ splitEvents.forEach((event) => {
17
+
18
+ this.bindings.push({ event, element: selectedElement, func });
19
+ selectedElement.addEventListener(event, func);
20
+
21
+ });
22
+
23
+ }
24
+
25
+ onElement (events: string, element: HTMLElement, func: EventListener) {
26
+
27
+ const splitEvents = events.split(' ');
28
+
29
+ splitEvents.forEach((event) => {
30
+
31
+ this.bindings.push({ event, element, func });
32
+ element.addEventListener(event, func);
33
+
34
+ });
35
+
36
+ }
37
+
38
+ off (events: string, selector: string) {
39
+
40
+ const splitEvents = events.split(' ');
41
+ const selectedElement = this.getElement(selector);
42
+ let item;
43
+
44
+ splitEvents.forEach((event) => {
45
+
46
+ item = this.bindings.find((e) => event === e.event && e.element === selectedElement);
47
+
48
+ if(!item) return;
49
+
50
+ this.bindings.splice(this.bindings.indexOf(item), 1);
51
+
52
+ selectedElement.removeEventListener(event, item.func);
53
+
54
+ });
55
+
56
+ }
57
+
58
+ destroyBindings () {
59
+
60
+ this.bindings.forEach((e) => {
61
+
62
+ e.element.removeEventListener(e.event, e.func);
63
+
64
+ });
65
+
66
+ this.bindings = [];
67
+
68
+ }
69
+
70
+ getElement (selector: string) {
71
+
72
+ let selectedElement: Document | HTMLElement;
73
+
74
+ if (selector.length > 0) {
75
+
76
+ selectedElement = document.querySelector(selector) as HTMLElement;
77
+
78
+ } else {
79
+
80
+ selectedElement = document;
81
+
82
+ }
83
+
84
+ return selectedElement;
85
+
86
+ }
87
+
88
+ // set title (title: string) {
89
+
90
+ // document.title = title
91
+ // ? `${title} ${this.store.settings?.title?.short}`
92
+ // : this.store.settings?.title?.full;
93
+
94
+ // }
95
+
96
+ }
97
+
98
+ const dom = new Dom();
99
+
100
+ export default dom;