@lilaquadrat/design-core 0.2.1 → 0.3.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/README.md +76 -3
- package/html/index.server.html +1 -8
- package/package.json +54 -54
- package/src/client-entry.ts +8 -8
- package/src/components/partials/error.partial.vue +19 -19
- package/src/components/partials/main-components.partial.vue +75 -70
- package/src/components/partials/qrcode.partial.vue +8 -8
- package/src/functions/AuthProviderFactory.ts +30 -0
- package/src/functions/PaymenyProviderFactory.ts +11 -11
- package/src/functions/auth0.provider.ts +75 -0
- package/src/functions/keycloak.provider.ts +228 -0
- package/src/functions/lila-dom.ts +50 -50
- package/src/functions/shopify.provider.ts +176 -154
- package/src/functions/stripe.provider.ts +120 -108
- package/src/globals.d.ts +1 -2
- package/src/index.ts +9 -7
- package/src/interfaces/AuthCallbackResult.interface.ts +5 -0
- package/src/interfaces/AuthConfig.interface.ts +13 -0
- package/src/interfaces/AuthProvider.interface.ts +15 -0
- package/src/interfaces/FrontendConfig.interface.ts +11 -40
- package/src/interfaces/GenericEvents.interface.ts +1 -1
- package/src/interfaces/IdTokenExtended.interface.ts +13 -4
- package/src/interfaces/PaymentProvider.interface.ts +2 -2
- package/src/interfaces/RenderOptions.interface.ts +12 -0
- package/src/libs/ActionNotice.ts +125 -125
- package/src/libs/Models.class.ts +219 -221
- package/src/main.ts +41 -36
- package/src/mixins/createCookieString.ts +50 -36
- package/src/mixins/createModelDeclaration.ts +22 -19
- package/src/mixins/createRouter.ts +12 -12
- package/src/mixins/date.ts +4 -2
- package/src/mixins/formatSize.ts +5 -5
- package/src/mixins/getAnchor.ts +1 -1
- package/src/mixins/getRoutes.ts +13 -25
- package/src/mixins/hasSlotContent.ts +22 -16
- package/src/mixins/hooks.ts +101 -60
- package/src/mixins/loadComponents.ts +60 -58
- package/src/mixins/logger.ts +17 -13
- package/src/mixins/replaceVariables.ts +10 -8
- package/src/mixins/scroll.ts +61 -45
- package/src/models/Address.model.ts +7 -7
- package/src/models/Contact.model.ts +14 -14
- package/src/plugins/analytics.ts +198 -0
- package/src/plugins/auth.ts +74 -60
- package/src/plugins/currency.ts +10 -10
- package/src/plugins/events.ts +101 -97
- package/src/plugins/filters.ts +21 -18
- package/src/plugins/replacer.ts +7 -6
- package/src/plugins/signupFlow.ts +45 -43
- package/src/plugins/traceable.ts +28 -26
- package/src/plugins/translations.ts +9 -9
- package/src/plugins/youtube.ts +39 -34
- package/src/routes.ts +108 -108
- package/src/server-entry.ts +75 -77
- package/src/stores/calls.store.ts +14 -14
- package/src/stores/cart.store.ts +116 -107
- package/src/stores/content.store.ts +87 -45
- package/src/stores/editor.store.ts +16 -16
- package/src/stores/files.store.ts +72 -72
- package/src/stores/main.store.ts +155 -109
- package/src/stores/user.store.ts +72 -68
- package/src/translations/de.ts +127 -127
- package/src/views/content.view.vue +81 -143
- package/src/views/download.view.vue +25 -23
- package/src/views/editor.view.vue +150 -125
- package/src/views/login.view.vue +35 -36
- package/src/views/signup-account.view.vue +14 -14
- package/tooling/cypress/config.ts +68 -54
- package/tooling/cypress/manifest-utils.mjs +34 -22
- package/tooling/cypress/run-parallel.mjs +41 -35
- package/tooling/cypress/support/commands.ts +458 -300
- package/tooling/eslint.config.js +1 -223
- package/tooling/preview.plugin.js +132 -0
- package/tooling/ssr-test/index.mjs +205 -203
- package/tooling/vite.d.ts +36 -0
- package/tooling/vite.js +234 -0
- package/src/interfaces/EditorConfiguration.interface.ts +0 -15
- package/tooling/preview.plugin.ts +0 -134
- package/tooling/stylelint.config.mjs +0 -24
- package/tooling/vite.ts +0 -260
|
@@ -2,26 +2,26 @@ import ShopifyGraphQLAPI from './shopify.provider';
|
|
|
2
2
|
import type PaymentProvider from '../interfaces/PaymentProvider.interface';
|
|
3
3
|
import StripePaymentProvider from './stripe.provider';
|
|
4
4
|
|
|
5
|
-
export default function PaymentProviderFactory
|
|
5
|
+
export default function PaymentProviderFactory(type: 'internal' | 'shopify' | 'stripe', config?: Record<string, string>): PaymentProvider {
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
let newProvider: PaymentProvider;
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
if(type === 'shopify') {
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
if(!config?.store || !config.token) throw new Error('PAYMENT_CONFIG_MISSING');
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
newProvider = new ShopifyGraphQLAPI(config.store, config.token);
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
} else if(type === 'stripe') {
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
newProvider = new StripePaymentProvider();
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
} else {
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
throw new Error('NO_PAYMENT_PROVIDER');
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
return newProvider;
|
|
26
26
|
|
|
27
27
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Auth0Client, type Auth0ClientOptions } from '@auth0/auth0-spa-js';
|
|
2
|
+
import type AppState from '../interfaces/AppState.interface';
|
|
3
|
+
import type AuthCallbackResult from '../interfaces/AuthCallbackResult.interface';
|
|
4
|
+
import type AuthProvider from '../interfaces/AuthProvider.interface';
|
|
5
|
+
import type IdTokenExtended from '../interfaces/IdTokenExtended.interface';
|
|
6
|
+
|
|
7
|
+
export default class Auth0Provider implements AuthProvider {
|
|
8
|
+
|
|
9
|
+
private readonly auth0: Auth0Client;
|
|
10
|
+
|
|
11
|
+
private readonly returnTo?: string;
|
|
12
|
+
|
|
13
|
+
constructor(options: Auth0ClientOptions) {
|
|
14
|
+
|
|
15
|
+
this.auth0 = new Auth0Client(options);
|
|
16
|
+
|
|
17
|
+
const redirectUri = options.authorizationParams?.redirect_uri;
|
|
18
|
+
|
|
19
|
+
if (redirectUri) this.returnTo = new URL(redirectUri).origin;
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async init(): Promise<void> {}
|
|
24
|
+
|
|
25
|
+
isAuthenticated(): Promise<boolean> {
|
|
26
|
+
|
|
27
|
+
return this.auth0.isAuthenticated();
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getToken(): Promise<string | undefined> {
|
|
32
|
+
|
|
33
|
+
return this.auth0.getTokenSilently({ authorizationParams: { scope: 'openid profile email offline_access' } });
|
|
34
|
+
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
refreshToken(): Promise<string | undefined> {
|
|
38
|
+
|
|
39
|
+
return this.auth0.getTokenSilently({ cacheMode: 'off', authorizationParams: { scope: 'openid profile email offline_access' } });
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getTokenContent(): Promise<IdTokenExtended | undefined> {
|
|
44
|
+
|
|
45
|
+
return this.auth0.getIdTokenClaims();
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
triggerLogin(appState: AppState): Promise<void> {
|
|
50
|
+
|
|
51
|
+
return this.auth0.loginWithRedirect<AppState>({ appState });
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
triggerSignup(appState: AppState): Promise<void> {
|
|
56
|
+
|
|
57
|
+
return this.auth0.loginWithRedirect<AppState>({ appState, authorizationParams: { screen_hint: 'signup' } });
|
|
58
|
+
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
triggerLogout(): Promise<void> {
|
|
62
|
+
|
|
63
|
+
return this.auth0.logout(this.returnTo ? { logoutParams: { returnTo: this.returnTo } } : undefined);
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async handleCallback(): Promise<AuthCallbackResult> {
|
|
68
|
+
|
|
69
|
+
const result = await this.auth0.handleRedirectCallback<AppState>();
|
|
70
|
+
|
|
71
|
+
return { appState: result.appState };
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import Keycloak from 'keycloak-js';
|
|
2
|
+
import type AppState from '../interfaces/AppState.interface';
|
|
3
|
+
import type AuthCallbackResult from '../interfaces/AuthCallbackResult.interface';
|
|
4
|
+
import type AuthConfig from '../interfaces/AuthConfig.interface';
|
|
5
|
+
import type AuthProvider from '../interfaces/AuthProvider.interface';
|
|
6
|
+
import type IdTokenExtended from '../interfaces/IdTokenExtended.interface';
|
|
7
|
+
|
|
8
|
+
const appStateStoragePrefix = 'lila-auth-keycloak:';
|
|
9
|
+
|
|
10
|
+
export default class KeycloakProvider implements AuthProvider {
|
|
11
|
+
|
|
12
|
+
private readonly keycloak: Keycloak;
|
|
13
|
+
|
|
14
|
+
private initialization?: Promise<void>;
|
|
15
|
+
|
|
16
|
+
private initializationError?: Error;
|
|
17
|
+
|
|
18
|
+
private callbackState?: string;
|
|
19
|
+
|
|
20
|
+
private callbackCode?: string;
|
|
21
|
+
|
|
22
|
+
private callbackError?: string;
|
|
23
|
+
|
|
24
|
+
private callbackErrorDescription?: string;
|
|
25
|
+
|
|
26
|
+
private callbackAppState?: AppState;
|
|
27
|
+
|
|
28
|
+
private callbackHandled = false;
|
|
29
|
+
|
|
30
|
+
constructor(private readonly config: Extract<AuthConfig, { type: 'keycloak' }>) {
|
|
31
|
+
|
|
32
|
+
this.keycloak = new Keycloak({ url: config.url, realm: config.realm, clientId: config.clientId });
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
init(): Promise<void> {
|
|
37
|
+
|
|
38
|
+
this.initialization ??= this.initialize();
|
|
39
|
+
|
|
40
|
+
return this.initialization;
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private async initialize(): Promise<void> {
|
|
45
|
+
|
|
46
|
+
const currentUrl = new URL(window.location.href);
|
|
47
|
+
|
|
48
|
+
// Match the SDK's last-value handling when callback parameters are repeated.
|
|
49
|
+
this.callbackState = currentUrl.searchParams.getAll('state').pop() || undefined;
|
|
50
|
+
this.callbackCode = currentUrl.searchParams.getAll('code').pop() || undefined;
|
|
51
|
+
this.callbackError = currentUrl.searchParams.getAll('error').pop() || undefined;
|
|
52
|
+
this.callbackErrorDescription = currentUrl.searchParams.getAll('error_description').pop() || undefined;
|
|
53
|
+
|
|
54
|
+
if (this.callbackState && (this.callbackCode || this.callbackError)) {
|
|
55
|
+
|
|
56
|
+
this.callbackAppState = this.readAppState(this.callbackState);
|
|
57
|
+
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
|
|
62
|
+
await this.keycloak.init({
|
|
63
|
+
// Unconfigured SSO checks redirect the page; callbacks must not fall back to another SSO session either.
|
|
64
|
+
onLoad: this.config.silentCheckSsoRedirectUri && !this.callbackCode && !this.callbackError ? 'check-sso' : undefined,
|
|
65
|
+
redirectUri: currentUrl.href,
|
|
66
|
+
flow: 'standard',
|
|
67
|
+
responseMode: 'query',
|
|
68
|
+
pkceMethod: 'S256',
|
|
69
|
+
scope: this.config.scope || 'openid profile email',
|
|
70
|
+
...(this.config.silentCheckSsoRedirectUri ? {
|
|
71
|
+
silentCheckSsoRedirectUri: this.config.silentCheckSsoRedirectUri,
|
|
72
|
+
silentCheckSsoFallback: false,
|
|
73
|
+
} : {}),
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
} catch (error) {
|
|
77
|
+
|
|
78
|
+
this.initializationError = error instanceof Error ? error : new Error('Keycloak initialization failed', { cause: error });
|
|
79
|
+
|
|
80
|
+
throw this.initializationError;
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async isAuthenticated(): Promise<boolean> {
|
|
87
|
+
|
|
88
|
+
return this.keycloak.authenticated === true;
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async getToken(): Promise<string | undefined> {
|
|
93
|
+
|
|
94
|
+
if (!this.keycloak.authenticated) return undefined;
|
|
95
|
+
|
|
96
|
+
await this.keycloak.updateToken(30);
|
|
97
|
+
|
|
98
|
+
return this.keycloak.token;
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async refreshToken(): Promise<string | undefined> {
|
|
103
|
+
|
|
104
|
+
if (!this.keycloak.authenticated) return undefined;
|
|
105
|
+
|
|
106
|
+
await this.keycloak.updateToken(-1);
|
|
107
|
+
|
|
108
|
+
return this.keycloak.token;
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async getTokenContent(): Promise<IdTokenExtended | undefined> {
|
|
113
|
+
|
|
114
|
+
return this.keycloak.idTokenParsed;
|
|
115
|
+
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
triggerLogin(appState: AppState): Promise<void> {
|
|
119
|
+
|
|
120
|
+
return this.redirectToLogin(appState);
|
|
121
|
+
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
triggerSignup(appState: AppState): Promise<void> {
|
|
125
|
+
|
|
126
|
+
return this.redirectToLogin(appState, 'register');
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async triggerLogout(): Promise<void> {
|
|
131
|
+
|
|
132
|
+
await this.keycloak.logout({ redirectUri: new URL(this.getRedirectUri(), window.location.origin).origin });
|
|
133
|
+
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async handleCallback(): Promise<AuthCallbackResult> {
|
|
137
|
+
|
|
138
|
+
if (this.callbackHandled) throw new Error('Keycloak callback has already been handled');
|
|
139
|
+
|
|
140
|
+
this.callbackHandled = true;
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
|
|
144
|
+
await this.init();
|
|
145
|
+
|
|
146
|
+
if (this.initializationError) throw this.initializationError;
|
|
147
|
+
if (!this.callbackState || (!this.callbackCode && !this.callbackError)) throw new Error('No Keycloak callback available');
|
|
148
|
+
if (this.callbackError) throw new Error(this.callbackErrorDescription || this.callbackError);
|
|
149
|
+
if (!this.keycloak.authenticated) throw new Error('Keycloak callback did not authenticate the user');
|
|
150
|
+
|
|
151
|
+
return { appState: this.callbackAppState };
|
|
152
|
+
|
|
153
|
+
} finally {
|
|
154
|
+
|
|
155
|
+
this.removeAppState();
|
|
156
|
+
this.callbackAppState = undefined;
|
|
157
|
+
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private getRedirectUri(): string {
|
|
163
|
+
|
|
164
|
+
return this.config.redirectUri || new URL('/login-callback', window.location.origin).href;
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private async redirectToLogin(appState: AppState, action?: 'register'): Promise<void> {
|
|
169
|
+
|
|
170
|
+
await this.init();
|
|
171
|
+
|
|
172
|
+
const loginUrl = await this.keycloak.createLoginUrl({ redirectUri: this.getRedirectUri(), action });
|
|
173
|
+
const state = new URL(loginUrl).searchParams.get('state');
|
|
174
|
+
|
|
175
|
+
if (!state) throw new Error('Keycloak login URL is missing OAuth state');
|
|
176
|
+
|
|
177
|
+
window.sessionStorage.setItem(appStateStoragePrefix + state, JSON.stringify(appState));
|
|
178
|
+
window.location.assign(loginUrl);
|
|
179
|
+
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private readAppState(state: string): AppState | undefined {
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
|
|
186
|
+
const stored = window.sessionStorage.getItem(appStateStoragePrefix + state);
|
|
187
|
+
|
|
188
|
+
if (!stored) return undefined;
|
|
189
|
+
|
|
190
|
+
const value: unknown = JSON.parse(stored);
|
|
191
|
+
|
|
192
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) return undefined;
|
|
193
|
+
if ('customerId' in value && typeof value.customerId !== 'string') return undefined;
|
|
194
|
+
if ('emailConfirmationCode' in value && typeof value.emailConfirmationCode !== 'string') return undefined;
|
|
195
|
+
|
|
196
|
+
const appState: AppState = {};
|
|
197
|
+
|
|
198
|
+
if ('customerId' in value && typeof value.customerId === 'string') appState.customerId = value.customerId;
|
|
199
|
+
if ('emailConfirmationCode' in value && typeof value.emailConfirmationCode === 'string') appState.emailConfirmationCode = value.emailConfirmationCode;
|
|
200
|
+
|
|
201
|
+
return appState;
|
|
202
|
+
|
|
203
|
+
} catch {
|
|
204
|
+
|
|
205
|
+
// Unavailable or malformed app state must not bypass the SDK's callback validation.
|
|
206
|
+
return undefined;
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
private removeAppState(): void {
|
|
213
|
+
|
|
214
|
+
if (!this.callbackState || (!this.callbackCode && !this.callbackError)) return;
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
|
|
218
|
+
window.sessionStorage.removeItem(appStateStoragePrefix + this.callbackState);
|
|
219
|
+
|
|
220
|
+
} catch {
|
|
221
|
+
|
|
222
|
+
// Storage restrictions must not hide the authentication result or its original error.
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
}
|
|
@@ -1,97 +1,97 @@
|
|
|
1
1
|
export class Dom {
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
bindings: {event: string, element: any, func: EventListenerOrEventListenerObject}[];
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
constructor() {
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
this.bindings = [];
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
on(events: string, selector: string, func: EventListener) {
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const splitEvents = events.split(' ');
|
|
14
|
+
const selectedElement = this.getElement(selector);
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
splitEvents.forEach((event) => {
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
this.bindings.push({ event, element: selectedElement, func });
|
|
19
|
+
selectedElement.addEventListener(event, func);
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
});
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
onElement(events: string, element: HTMLElement, func: EventListener) {
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
const splitEvents = events.split(' ');
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
splitEvents.forEach((event) => {
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
this.bindings.push({ event, element, func });
|
|
32
|
+
element.addEventListener(event, func);
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
});
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
off(events: string, selector: string) {
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const splitEvents = events.split(' ');
|
|
41
|
+
const selectedElement = this.getElement(selector);
|
|
42
|
+
let item;
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
splitEvents.forEach((event) => {
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
item = this.bindings.find((e) => event === e.event && e.element === selectedElement);
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
if(!item) return;
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
this.bindings.splice(this.bindings.indexOf(item), 1);
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
selectedElement.removeEventListener(event, item.func);
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
});
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
destroyBindings() {
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
this.bindings.forEach((e) => {
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
e.element.removeEventListener(e.event, e.func);
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
});
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
this.bindings = [];
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
}
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
getElement(selector: string) {
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
let selectedElement: Document | HTMLElement;
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
if (selector.length > 0) {
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
selectedElement = document.querySelector(selector) as HTMLElement;
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
} else {
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
selectedElement = document;
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
}
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
return selectedElement;
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
}
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
// set title (title: string) {
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
// document.title = title
|
|
91
|
+
// ? `${title} ${this.store.settings?.title?.short}`
|
|
92
|
+
// : this.store.settings?.title?.full;
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
// }
|
|
95
95
|
|
|
96
96
|
}
|
|
97
97
|
|