@everymatrix/pam-login 0.0.1

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 (56) hide show
  1. package/dist/cjs/app-globals-3a1e7e63.js +5 -0
  2. package/dist/cjs/index-c5001c3e.js +1227 -0
  3. package/dist/cjs/index.cjs.js +10 -0
  4. package/dist/cjs/loader.cjs.js +15 -0
  5. package/dist/cjs/pam-login-45f1f99f.js +22332 -0
  6. package/dist/cjs/pam-login.cjs.js +25 -0
  7. package/dist/cjs/pam-login_2.cjs.entry.js +175 -0
  8. package/dist/collection/collection-manifest.json +19 -0
  9. package/dist/collection/components/pam-login/index.js +1 -0
  10. package/dist/collection/components/pam-login/pam-login.css +206 -0
  11. package/dist/collection/components/pam-login/pam-login.js +723 -0
  12. package/dist/collection/index.js +1 -0
  13. package/dist/collection/utils/locale.utils.js +271 -0
  14. package/dist/collection/utils/types.js +1 -0
  15. package/dist/esm/app-globals-0f993ce5.js +3 -0
  16. package/dist/esm/index-a126c540.js +1200 -0
  17. package/dist/esm/index.js +2 -0
  18. package/dist/esm/loader.js +11 -0
  19. package/dist/esm/pam-login-f43d7eb6.js +22330 -0
  20. package/dist/esm/pam-login.js +20 -0
  21. package/dist/esm/pam-login_2.entry.js +170 -0
  22. package/dist/index.cjs.js +1 -0
  23. package/dist/index.js +1 -0
  24. package/dist/pam-login/index.esm.js +1 -0
  25. package/dist/pam-login/p-83cb37b3.js +2 -0
  26. package/dist/pam-login/p-c6405762.js +2655 -0
  27. package/dist/pam-login/p-e1255160.js +1 -0
  28. package/dist/pam-login/p-e23846e0.entry.js +1 -0
  29. package/dist/pam-login/pam-login.esm.js +1 -0
  30. package/dist/stencil.config.dev.js +19 -0
  31. package/dist/stencil.config.js +18 -0
  32. package/dist/storybook/main.js +43 -0
  33. package/dist/storybook/preview.js +9 -0
  34. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/libs/common/src/storybook/storybook-utils.d.ts +39 -0
  35. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/packages/stencil/pam-login/stencil.config.d.ts +2 -0
  36. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/packages/stencil/pam-login/stencil.config.dev.d.ts +2 -0
  37. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/packages/stencil/pam-login/storybook/main.d.ts +3 -0
  38. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/packages/stencil/pam-login/storybook/preview.d.ts +70 -0
  39. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/tools/plugins/index.d.ts +3 -0
  40. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/tools/plugins/stencil-clean-deps-plugin.d.ts +5 -0
  41. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/tools/plugins/vite-chunk-plugin.d.ts +6 -0
  42. package/dist/types/Users/raul.vasile/workspace/everymatrix/widgets-monorepo/packages/stencil/pam-login/.stencil/tools/plugins/vite-clean-deps-plugin.d.ts +4 -0
  43. package/dist/types/components/pam-login/index.d.ts +1 -0
  44. package/dist/types/components/pam-login/pam-login.d.ts +200 -0
  45. package/dist/types/components.d.ts +149 -0
  46. package/dist/types/index.d.ts +1 -0
  47. package/dist/types/stencil-public-runtime.d.ts +1674 -0
  48. package/dist/types/utils/locale.utils.d.ts +2 -0
  49. package/dist/types/utils/types.d.ts +6 -0
  50. package/loader/cdn.js +1 -0
  51. package/loader/index.cjs.js +1 -0
  52. package/loader/index.d.ts +24 -0
  53. package/loader/index.es2017.js +1 -0
  54. package/loader/index.js +2 -0
  55. package/loader/package.json +11 -0
  56. package/package.json +26 -0
@@ -0,0 +1,723 @@
1
+ import { h } from "@stencil/core";
2
+ import { setClientStyling, setClientStylingURL, setStreamStyling } from "../../../../../../../../libs/common/src/styling/index";
3
+ import { getTranslations, translate } from "../../utils/locale.utils";
4
+ import "@vaadin/combo-box";
5
+ import "../../../../../ui-skeleton/dist/types/index";
6
+ export class PamLogin {
7
+ constructor() {
8
+ /**
9
+ * Fetch phone prefixes from the API
10
+ */
11
+ this.getPrefixOptions = () => {
12
+ const url = new URL('v1/player/validPhoneCodes', this.endpoint);
13
+ return new Promise((resolve) => {
14
+ fetch(url.href)
15
+ .then((res) => res.json())
16
+ .then((res) => {
17
+ this.prefixOptions = res.phoneCodes.map(code => {
18
+ return { label: code.Prefix, value: code.Prefix };
19
+ });
20
+ resolve();
21
+ });
22
+ });
23
+ };
24
+ /**
25
+ * Handle autofilling of credentials from a dispatched event
26
+ */
27
+ this.handleAutofillCredentials = (e) => {
28
+ this.contactValue = e.detail.userNameEmail;
29
+ this.passwordValue = e.detail.userPassword;
30
+ this.handleLogin();
31
+ };
32
+ /**
33
+ * Get login token from password-management service
34
+ */
35
+ this.getLoginToken = () => {
36
+ const url = new URL('api/v1/players/password-management/auth/password/verify', this.endpoint);
37
+ const headers = {
38
+ 'Content-Type': 'application/json'
39
+ };
40
+ if (this.captchaData.isEnabled) {
41
+ headers['X-Captcha-Response'] = this.captchaData.token;
42
+ }
43
+ const body = {
44
+ contact: this.contactValue,
45
+ password: this.passwordValue
46
+ };
47
+ const options = {
48
+ method: 'POST',
49
+ headers,
50
+ body: JSON.stringify(body),
51
+ };
52
+ return new Promise((resolve, reject) => {
53
+ fetch(url.href, options)
54
+ .then((res) => res.json())
55
+ .then((res) => {
56
+ if (res.token) {
57
+ return resolve(res.token);
58
+ }
59
+ else {
60
+ return reject('Token not received from the API call');
61
+ }
62
+ });
63
+ });
64
+ };
65
+ /**
66
+ * Function to send legislation login request
67
+ */
68
+ this.loginPlayer = (token) => {
69
+ const url = new URL('api/v2/gm/legislation/login', this.endpoint);
70
+ const headers = {
71
+ 'Content-Type': 'application/json'
72
+ };
73
+ const body = {
74
+ token,
75
+ method: 'login'
76
+ };
77
+ const options = {
78
+ method: 'POST',
79
+ headers,
80
+ body: JSON.stringify(body),
81
+ };
82
+ return new Promise((resolve, reject) => {
83
+ fetch(url.href, options)
84
+ .then((res) => res.json(), (err) => reject(err))
85
+ .then((res) => {
86
+ if (res.sessionId && res.playerId) {
87
+ return resolve(res);
88
+ }
89
+ else {
90
+ const err = res;
91
+ return reject(err);
92
+ }
93
+ });
94
+ });
95
+ };
96
+ /**
97
+ * Handle login process
98
+ */
99
+ this.handleLogin = () => {
100
+ this.isLoading = true;
101
+ this.getLoginToken()
102
+ .then((token) => {
103
+ this.loginPlayer(token)
104
+ .then((res) => {
105
+ window.postMessage({ type: 'UserSessionID', session: res.sessionId, userid: res.playerId }, window.location.href);
106
+ window.postMessage({ type: 'WidgetNotification', data: { type: 'success', message: translate('successMessage', this.lang) } }, window.location.href);
107
+ this.apiErrorMessage = '';
108
+ })
109
+ .catch((err) => {
110
+ console.error(`Legislation login failed: ${err.message}`, err.errors);
111
+ this.apiErrorMessage = translate('genericError', this.lang);
112
+ this.sendErrorNotification(this.apiErrorMessage);
113
+ })
114
+ .finally(() => this.isLoading = false);
115
+ })
116
+ .catch((err) => {
117
+ console.error(err);
118
+ this.apiErrorMessage = translate('genericError', this.lang);
119
+ this.sendErrorNotification(this.apiErrorMessage);
120
+ this.isLoading = false;
121
+ });
122
+ this.dispatchUpdateLoginCredentialsEvent();
123
+ };
124
+ /**
125
+ * Handle input changes for username/email and password
126
+ *
127
+ * @param event - input event
128
+ * @param location - 'user' | 'phone' | 'password'
129
+ */
130
+ this.handleInputChange = (event, location) => {
131
+ const inputValue = event.target.value;
132
+ switch (location) {
133
+ case 'user':
134
+ this.contactValue = inputValue;
135
+ this.isContactValid = this.validate('user', this.contactValue);
136
+ break;
137
+ case 'phone':
138
+ this.contactValue = inputValue;
139
+ this.isContactValid = this.validate('phone', this.contactValue);
140
+ break;
141
+ case 'prefix':
142
+ this.prefixValue = inputValue;
143
+ this.isContactValid = this.validate('phone', this.contactValue);
144
+ break;
145
+ case 'password':
146
+ this.passwordValue = inputValue;
147
+ this.isPasswordValid = this.validate('password', inputValue);
148
+ break;
149
+ }
150
+ };
151
+ // this partially applies the location to avoid constructing an anonymous function in jsx, i.e. (e)=>handleInputChange(e,location), which would be needed for 2 args
152
+ this.handleInputChangePartial = (location) => (e) => this.handleInputChange(e, location);
153
+ /**
154
+ * Validate input based on the specific regex
155
+ *
156
+ * @param useRuleFor - 'user' | 'phone' | 'password'
157
+ * @param input - input value to validate
158
+ */
159
+ this.validate = (useRuleFor, input) => {
160
+ let regex;
161
+ switch (useRuleFor) {
162
+ case 'user':
163
+ regex = new RegExp(this.userEmailRegex, this.userEmailRegexOptions);
164
+ return input.length <= 3 || regex.test(input);
165
+ case 'phone':
166
+ regex = new RegExp(this.userPhoneRegex, this.userPhoneRegexOptions);
167
+ return input.length <= 3 || regex.test(input) && Boolean(this.prefixValue);
168
+ case 'password':
169
+ regex = new RegExp(this.passwordRegex, this.passwordRegexOptions);
170
+ return input.length <= 3 || regex.test(input);
171
+ }
172
+ };
173
+ this.isSubmitDisabled = () => {
174
+ return ((!this.isContactValid || !this.contactValue || (this.loginByPhoneNumber === 'true' && !this.prefixValue))
175
+ || !this.passwordValue
176
+ || !this.isPasswordValid) || this.isLoading
177
+ || (this.captchaData.isEnabled && !this.captchaData.token);
178
+ };
179
+ this.handleSubmit = (e) => {
180
+ if (e.key === 'Enter' && !this.isSubmitDisabled()) {
181
+ this.handleLogin();
182
+ }
183
+ };
184
+ /**
185
+ * Toggle password
186
+ */
187
+ this.togglePassword = () => {
188
+ this.isPasswordVisible = !this.isPasswordVisible;
189
+ };
190
+ /**
191
+ * Reset password
192
+ */
193
+ this.resetPassword = () => {
194
+ window.postMessage({ type: "NavForgotPassword" }, window.location.href);
195
+ };
196
+ this.endpoint = '';
197
+ this.lang = 'en';
198
+ this.clientStyling = '';
199
+ this.clientStylingUrl = '';
200
+ this.mbSource = undefined;
201
+ this.translationUrl = '';
202
+ this.passwordReset = 'false';
203
+ this.userEmailRegex = undefined;
204
+ this.userEmailRegexOptions = 'i';
205
+ this.userPhoneRegex = undefined;
206
+ this.userPhoneRegexOptions = '';
207
+ this.passwordRegex = undefined;
208
+ this.passwordRegexOptions = '';
209
+ this.loginByPhoneNumber = 'false';
210
+ this.isLoading = false;
211
+ this.contactValue = '';
212
+ this.passwordValue = '';
213
+ this.prefixValue = '';
214
+ this.prefixOptions = undefined;
215
+ this.isContactValid = true;
216
+ this.isPasswordValid = true;
217
+ this.isPasswordVisible = false;
218
+ this.apiErrorMessage = '';
219
+ this.captchaData = {
220
+ isEnabled: true,
221
+ token: '',
222
+ provider: '',
223
+ siteKey: ''
224
+ };
225
+ }
226
+ /**
227
+ * Watch for changes in the translation URL and fetch new translations
228
+ */
229
+ handleNewTranslations() {
230
+ getTranslations(this.translationUrl);
231
+ }
232
+ /**
233
+ * Watch for changes in the client styling and apply the new styling
234
+ *
235
+ * @param newValue - new client styling
236
+ * @param oldValue - previous client styling
237
+ */
238
+ handleClientStylingChange(newValue, oldValue) {
239
+ if (newValue != oldValue) {
240
+ setClientStyling(this.stylingContainer, this.clientStyling);
241
+ }
242
+ }
243
+ /**
244
+ * Watch for changes in the client styling URL and fetch the new CSS
245
+ *
246
+ * @param newValue - new client styling URL
247
+ * @param oldValue - previous client styling URL
248
+ */
249
+ handleClientStylingUrlChange(newValue, oldValue) {
250
+ if (newValue != oldValue) {
251
+ if (this.clientStylingUrl)
252
+ setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
253
+ }
254
+ }
255
+ /**
256
+ * Lifecycle method: Fetch translations on component load
257
+ */
258
+ async componentWillLoad() {
259
+ if (this.loginByPhoneNumber === 'true') {
260
+ await this.getPrefixOptions();
261
+ }
262
+ if (this.translationUrl.length > 2) {
263
+ await getTranslations(this.translationUrl);
264
+ }
265
+ this.getLoginConfig()
266
+ .then(() => this.appendCaptchaScript(), (err) => {
267
+ console.error(err);
268
+ this.apiErrorMessage = translate('configError', this.lang);
269
+ this.sendErrorNotification(this.apiErrorMessage);
270
+ });
271
+ }
272
+ /**
273
+ * Lifecycle method: Set up event listeners after the component is rendered
274
+ */
275
+ componentDidLoad() {
276
+ if (this.stylingContainer) {
277
+ if (window.emMessageBus != undefined) {
278
+ setStreamStyling(this.stylingContainer, `${this.mbSource}.Style`, this.stylingSubscription);
279
+ }
280
+ else {
281
+ if (this.clientStyling)
282
+ setClientStyling(this.stylingContainer, this.clientStyling);
283
+ if (this.clientStylingUrl)
284
+ setClientStylingURL(this.stylingContainer, this.clientStylingUrl);
285
+ }
286
+ }
287
+ window.addEventListener('LoginCredentials', this.handleAutofillCredentials);
288
+ window.postMessage({ type: 'UserLoginDidLoad' });
289
+ }
290
+ /**
291
+ * Lifecycle method: Clean up event listeners when the component is removed
292
+ */
293
+ disconnectedCallback() {
294
+ this.stylingSubscription && this.stylingSubscription.unsubscribe();
295
+ window.removeEventListener('LoginCredentials', this.handleAutofillCredentials);
296
+ }
297
+ /**
298
+ * Fetches the login configuration from the backend API.
299
+ *
300
+ * @returns A Promise that resolves once the configuration is fetched and set.
301
+ */
302
+ getLoginConfig() {
303
+ const url = new URL('/api/v1/players/password-management/auth/password/config', this.endpoint);
304
+ return new Promise((resolve, reject) => {
305
+ fetch(url.href)
306
+ .then((res) => {
307
+ if (!res.ok) {
308
+ throw new Error(`HTTP error! Status: ${res.status}`);
309
+ }
310
+ return res.json();
311
+ })
312
+ .then((res) => {
313
+ const { captcha } = res;
314
+ if (captcha && typeof captcha.provider === 'string') {
315
+ captcha.provider = captcha.provider.toLowerCase();
316
+ }
317
+ this.captchaData = Object.assign({}, captcha);
318
+ resolve();
319
+ })
320
+ .catch((err) => {
321
+ console.error('Error fetching login configuration:', err);
322
+ reject(err);
323
+ });
324
+ });
325
+ }
326
+ /**
327
+ * Handles the integration of CAPTCHA based on the login configuration.
328
+ * Dynamically injects the necessary CAPTCHA script if enabled.
329
+ */
330
+ handleCaptcha() {
331
+ const { isEnabled, provider, siteKey } = this.captchaData;
332
+ if (!isEnabled || !['cloudflare', 'google'].includes(provider)) {
333
+ return;
334
+ }
335
+ switch (provider) {
336
+ case 'cloudflare':
337
+ window.turnstile.render('#turnstileContainer', {
338
+ sitekey: siteKey,
339
+ theme: 'light',
340
+ callback: this.captchaCallback.bind(this),
341
+ });
342
+ return;
343
+ case 'google':
344
+ window.grecaptcha.ready(() => {
345
+ window.grecaptcha.render('googleContainer', {
346
+ sitekey: siteKey,
347
+ callback: this.captchaCallback.bind(this),
348
+ theme: 'light'
349
+ });
350
+ });
351
+ return;
352
+ }
353
+ }
354
+ /**
355
+ * Common callback function for CAPTCHA response handling.
356
+ * @param token CAPTCHA response token.
357
+ */
358
+ captchaCallback(token) {
359
+ this.captchaData.token = token;
360
+ this.captchaData = Object.assign({}, this.captchaData); // Needed to tell Stencil something was changed
361
+ }
362
+ /**
363
+ * Dynamically loads the Turnstile script and renders CAPTCHA when ready.
364
+ * @param src - The URL of the CAPTCHA script to load.
365
+ * @param captcha - The CAPTCHA configuration.
366
+ */
367
+ appendCaptchaScript() {
368
+ const { isEnabled, provider } = this.captchaData;
369
+ if (!isEnabled) {
370
+ return;
371
+ }
372
+ const script = document.createElement('script');
373
+ switch (provider) {
374
+ case 'cloudflare':
375
+ script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js';
376
+ break;
377
+ case 'google':
378
+ script.src = 'https://www.google.com/recaptcha/api.js';
379
+ break;
380
+ }
381
+ script.onload = this.handleCaptcha.bind(this);
382
+ document.head.appendChild(script);
383
+ }
384
+ /**
385
+ * Send error notification as a post message
386
+ */
387
+ sendErrorNotification(errorMessage) {
388
+ window.postMessage({ type: 'HasError', error: errorMessage }, window.location.href);
389
+ window.postMessage({
390
+ type: 'WidgetNotification', data: {
391
+ type: 'error',
392
+ message: errorMessage
393
+ }
394
+ }, window.location.href);
395
+ }
396
+ /**
397
+ * Dispatch event to notify about login credential updates
398
+ */
399
+ dispatchUpdateLoginCredentialsEvent() {
400
+ if (this.apiErrorMessage) {
401
+ return;
402
+ }
403
+ this.updateLoginCredentialsEvent = new CustomEvent("UpdateLoginCredentials", {
404
+ bubbles: true,
405
+ detail: {
406
+ userNameEmail: this.contactValue,
407
+ userPassword: this.passwordValue
408
+ }
409
+ });
410
+ window.dispatchEvent(this.updateLoginCredentialsEvent);
411
+ }
412
+ ;
413
+ /**
414
+ * Render function
415
+ */
416
+ render() {
417
+ const visibilityIcon = h("span", { key: 'bb874e46d790f8a76529b2f4ee0ccb2ea49ace3e', class: "InputIcon" }, this.isPasswordVisible
418
+ ? h("svg", { onClick: () => this.togglePassword(), class: "TogglePasswordVisibility", part: "TogglePasswordVisibility", xmlns: "http://www.w3.org/2000/svg", width: "18.844", height: "12.887", viewBox: "0 0 18.844 12.887" }, h("g", { transform: "translate(-110.856 -23.242)" }, h("circle", { class: "PasswordVisibilityIcon", cx: "0.05", cy: "0.05", r: "0.05", transform: "translate(121.017 31.148)" }), h("g", { transform: "translate(117.499 27.37)" }, h("path", { class: "PasswordVisibilityIcon", d: "M147.413,43.174a2.774,2.774,0,0,0-3.229-3.943Z", transform: "translate(-142.164 -39.123)" }), h("path", { class: "PasswordVisibilityIcon", d: "M137.031,43.1a2.778,2.778,0,0,0,3.447,4.209Z", transform: "translate(-136.413 -42.068)" })), h("g", { transform: "translate(110.856 24.899)" }, h("path", { class: "PasswordVisibilityIcon", d: "M122.538,42.061a7.043,7.043,0,0,1-2.325.53,10.373,10.373,0,0,1-4.393-1.482,36.509,36.509,0,0,1-3.873-2.391.13.13,0,0,1,0-.208,44.141,44.141,0,0,1,3.873-2.651c.394-.233.768-.437,1.13-.622l-.686-.838c-.322.167-.651.347-.99.55a37.989,37.989,0,0,0-3.977,2.729,1.21,1.21,0,0,0-.442.962,1.1,1.1,0,0,0,.494.936,34.416,34.416,0,0,0,3.977,2.469,11.468,11.468,0,0,0,4.886,1.611,8.427,8.427,0,0,0,3.039-.725Z", transform: "translate(-110.856 -33.157)" }), h("path", { class: "PasswordVisibilityIcon", d: "M149.119,34.14a45.875,45.875,0,0,0-4.055-2.729,20.541,20.541,0,0,0-2.547-1.248,5.6,5.6,0,0,0-4.79-.017l.7.856a5.254,5.254,0,0,1,1.672-.346,10.072,10.072,0,0,1,4.445,1.663,34.132,34.132,0,0,1,3.925,2.651.13.13,0,0,1,0,.208,40.2,40.2,0,0,1-3.925,2.391c-.179.092-.352.176-.525.26l.684.835c.1-.054.2-.1.309-.159a36.356,36.356,0,0,0,4.055-2.469,1.067,1.067,0,0,0,.52-.936A1.159,1.159,0,0,0,149.119,34.14Z", transform: "translate(-130.743 -29.617)" })), h("rect", { class: "PasswordVisibilityIcon", width: "0.972", height: "15.861", rx: "0.486", transform: "translate(114.827 23.858) rotate(-39.315)" })))
419
+ : h("svg", { onClick: () => this.togglePassword(), class: "TogglePasswordVisibility PasswordVisible", part: "TogglePasswordVisibility", xmlns: "http://www.w3.org/2000/svg", width: "18.843", height: "10.5", viewBox: "0 0 18.843 10.5" }, h("g", { transform: "translate(-14.185 -27.832)" }, h("path", { class: "PasswordVisibilityIcon", d: "M23.541,38.332a11.467,11.467,0,0,1-4.886-1.611,34.413,34.413,0,0,1-3.976-2.469,1.1,1.1,0,0,1-.494-.936,1.21,1.21,0,0,1,.442-.962A37.986,37.986,0,0,1,18.6,29.625a16.06,16.06,0,0,1,2.521-1.248,6.862,6.862,0,0,1,2.417-.546,6.862,6.862,0,0,1,2.417.546,20.541,20.541,0,0,1,2.547,1.248,45.872,45.872,0,0,1,4.054,2.729,1.159,1.159,0,0,1,.468.962,1.067,1.067,0,0,1-.52.936,36.353,36.353,0,0,1-4.054,2.469A11.2,11.2,0,0,1,23.541,38.332Zm0-9.46a9.813,9.813,0,0,0-4.392,1.663,44.138,44.138,0,0,0-3.873,2.651.13.13,0,0,0,0,.208,36.5,36.5,0,0,0,3.873,2.391,10.372,10.372,0,0,0,4.392,1.481,11.051,11.051,0,0,0,4.444-1.481,40.2,40.2,0,0,0,3.925-2.391.13.13,0,0,0,0-.208h0a34.132,34.132,0,0,0-3.925-2.651A10.072,10.072,0,0,0,23.541,28.872Z", transform: "translate(0)" }), h("circle", { class: "PasswordVisibilityIcon", cx: "2.779", cy: "2.779", r: "2.779", transform: "translate(20.827 30.303)" }))));
420
+ const loginForm = (h("div", { key: '3822128fa2d495e22cfe6487b92a59074edc207b', class: "FormBox" }, h("div", { key: 'b492b35e0496d783bee08268de7da92de188e7b2', class: "FormValue", onKeyDown: this.handleSubmit }, this.loginByPhoneNumber === 'true'
421
+ ? h("div", { class: (this.isContactValid && !this.apiErrorMessage) ? 'InputBox' : 'InputBox InputInvalidBox' }, h("div", { class: "PhoneInputBox" }, h("div", { class: "PrefixBox" }, h("vaadin-combo-box", { items: this.prefixOptions, value: this.prefixValue, onChange: this.handleInputChangePartial('prefix') }), h("label", { class: (this.prefixValue ? 'FieldFilledIn' : '') + ' ' + (this.isContactValid ? '' : 'FieldInvalid') }, translate('userPrefix', this.lang))), h("div", { class: "PhoneBox" }, h("input", { type: "text", placeholder: '', value: this.contactValue, onFocus: this.handleInputChangePartial('phone'), onInput: this.handleInputChangePartial('phone'), autocapitalize: "none", required: true }), h("label", { class: (this.contactValue ? 'FieldFilledIn' : '') + ' ' + (this.isContactValid ? '' : 'FieldInvalid') }, translate('userPhone', this.lang)))), !this.isContactValid &&
422
+ h("p", { class: "CredentialsError" }, translate('userPhoneError', this.lang)))
423
+ : h("div", { class: this.isContactValid ? 'InputBox' : 'InputBox InputInvalidBox' }, h("input", { type: "text", placeholder: '', value: this.contactValue, onInput: this.handleInputChangePartial('user'), autocapitalize: "none", required: true }), h("label", { class: (this.contactValue ? 'FieldFilledIn' : '') + ' ' + (this.isContactValid ? '' : 'FieldInvalid') }, translate('userEmail', this.lang)), !this.isContactValid &&
424
+ h("p", { class: "CredentialsError" }, translate('userEmailError', this.lang))), h("div", { key: '941ccdbbdffadfa763255f6d035d11e25f95bca9', class: this.isPasswordValid ? 'InputBox' : 'InputBox InputInvalidBox' }, visibilityIcon, h("input", { key: '40e370bf348dc25c9c9b951cc8bef83ce2ee7c72', type: this.isPasswordVisible ? "text" : "password", placeholder: '', value: this.passwordValue, onInput: this.handleInputChangePartial('password'), autocapitalize: "none", required: true }), h("label", { key: 'c6c86c450654d495d0022dd123d20ded3426fccf', class: (this.passwordValue ? 'FieldFilledIn' : '') + ' ' + (this.isPasswordValid ? '' : 'FieldInvalid') }, translate('password', this.lang)), this.isPasswordValid ||
425
+ h("p", { key: '98cd887991ab13215cdeba0d74deaef1f74bd61a', class: "CredentialsError" }, translate('userPasswordError', this.lang))), this.passwordReset == 'true' &&
426
+ h("div", { key: 'ccb6a014b9238dc1b43ee6d7fcbde0f6ad65a974', class: "ForgotPassword" }, h("button", { key: 'c07e6292964c9ffaf18f84b3fb639168bfe69711', onClick: this.resetPassword }, translate('forgotPassword', this.lang))), this.captchaData.isEnabled && this.captchaData.provider === 'cloudflare' &&
427
+ h("slot", { key: '873d1144706d713f38e87d7413dc65bea89eaf07', name: "turnstile" }), this.captchaData.isEnabled && this.captchaData.provider === 'google' &&
428
+ h("slot", { key: '2e88c7d908719ad03c32feb39c2782b6a53fa3e6', name: "google" }), h("button", { key: '16f1ce841ea0797a2a53fa88283e9504b149674b', disabled: this.isSubmitDisabled(), class: "SubmitCredentials", onClick: this.handleLogin }, translate('login', this.lang)), this.apiErrorMessage &&
429
+ h("p", { key: '6bfaca1c1894113134d8112bf0245c4fe8f539ff', class: "CredentialsError" }, this.apiErrorMessage))));
430
+ const skeleton = (h("div", { key: '6a5bdd7a73a48735fb7893846d18eab4cb5cd15d', class: "LoadingSkeleton" }, h("form", { key: '56909c222a4a5c01e00033183c49bac967fdd704', class: "Form" }, h("section", { key: 'aa5fb3aeccaa92b2dbaded30bc91f27d5fc88995', class: "FieldsSection" }, h("div", { key: '2232d21237018605d4dc5be187a2f5ef6dcbfdff', class: "FieldContainer" }, h("div", { key: 'b6ba71f89fae3edf9c8fbfc74a77b75287c12fcc', class: "FieldTitle" }, h("ui-skeleton", { key: '9237a050a5eec7ecb28d20e8e9af148ea5991474', structure: "title", width: "auto", height: "20px" })), h("ui-skeleton", { key: '7f1bcda4723e9f6f24dad602bff1480e122624da', structure: "rectangle", width: "auto", height: "35px" })), h("div", { key: 'ff6c82b4e37d9b796fecd9ca4c919a70ab1ed4ab', class: "FieldContainer" }, h("div", { key: 'a85bf5caf0db9b8ad12a475014f71d975a5114ed', class: "FieldTitle" }, h("ui-skeleton", { key: 'fe0600c8fa0564724b10203bf72c929566fcba54', structure: "title", width: "auto", height: "20px" })), h("ui-skeleton", { key: 'f59b2ccdbb812f8941e22bfae8f788f2bc821898', structure: "rectangle", width: "auto", height: "35px" }))), h("section", { key: '8b337059fb6bb2566c173ba5a2a6139b7a5a0d29', class: "ButtonsSection" }, h("div", { key: 'a5d537f7724c07b069cdf74b223237d140f51193', class: "Button" }, h("ui-skeleton", { key: 'ea24ff03ffb93d4d41a8617c6e2d16b6c94dc060', structure: "rectangle", width: "auto", height: "50px" }))))));
431
+ return (h("section", { key: '91eba8645bb65ce5871683189547dd9afcfb8e4a', ref: el => this.stylingContainer = el }, !this.isLoading ? skeleton : loginForm));
432
+ }
433
+ static get is() { return "pam-login"; }
434
+ static get encapsulation() { return "shadow"; }
435
+ static get originalStyleUrls() {
436
+ return {
437
+ "$": ["pam-login.scss"]
438
+ };
439
+ }
440
+ static get styleUrls() {
441
+ return {
442
+ "$": ["pam-login.css"]
443
+ };
444
+ }
445
+ static get properties() {
446
+ return {
447
+ "endpoint": {
448
+ "type": "string",
449
+ "mutable": false,
450
+ "complexType": {
451
+ "original": "string",
452
+ "resolved": "string",
453
+ "references": {}
454
+ },
455
+ "required": false,
456
+ "optional": false,
457
+ "docs": {
458
+ "tags": [],
459
+ "text": "API endpoint URL for login requests"
460
+ },
461
+ "attribute": "endpoint",
462
+ "reflect": true,
463
+ "defaultValue": "''"
464
+ },
465
+ "lang": {
466
+ "type": "string",
467
+ "mutable": true,
468
+ "complexType": {
469
+ "original": "string",
470
+ "resolved": "string",
471
+ "references": {}
472
+ },
473
+ "required": false,
474
+ "optional": false,
475
+ "docs": {
476
+ "tags": [],
477
+ "text": "Language code for translations (default is 'en')"
478
+ },
479
+ "attribute": "lang",
480
+ "reflect": true,
481
+ "defaultValue": "'en'"
482
+ },
483
+ "clientStyling": {
484
+ "type": "string",
485
+ "mutable": false,
486
+ "complexType": {
487
+ "original": "string",
488
+ "resolved": "string",
489
+ "references": {}
490
+ },
491
+ "required": false,
492
+ "optional": false,
493
+ "docs": {
494
+ "tags": [],
495
+ "text": "Inline CSS styling provided by the client"
496
+ },
497
+ "attribute": "client-styling",
498
+ "reflect": true,
499
+ "defaultValue": "''"
500
+ },
501
+ "clientStylingUrl": {
502
+ "type": "string",
503
+ "mutable": false,
504
+ "complexType": {
505
+ "original": "string",
506
+ "resolved": "string",
507
+ "references": {}
508
+ },
509
+ "required": false,
510
+ "optional": false,
511
+ "docs": {
512
+ "tags": [],
513
+ "text": "URL to load additional CSS styling"
514
+ },
515
+ "attribute": "client-styling-url",
516
+ "reflect": true,
517
+ "defaultValue": "''"
518
+ },
519
+ "mbSource": {
520
+ "type": "string",
521
+ "mutable": false,
522
+ "complexType": {
523
+ "original": "string",
524
+ "resolved": "string",
525
+ "references": {}
526
+ },
527
+ "required": false,
528
+ "optional": false,
529
+ "docs": {
530
+ "tags": [],
531
+ "text": "The source identifier for message bus styling.\nThis is used to apply styles dynamically from a stream."
532
+ },
533
+ "attribute": "mb-source",
534
+ "reflect": true
535
+ },
536
+ "translationUrl": {
537
+ "type": "string",
538
+ "mutable": false,
539
+ "complexType": {
540
+ "original": "string",
541
+ "resolved": "string",
542
+ "references": {}
543
+ },
544
+ "required": false,
545
+ "optional": false,
546
+ "docs": {
547
+ "tags": [],
548
+ "text": "URL for fetching translations"
549
+ },
550
+ "attribute": "translation-url",
551
+ "reflect": true,
552
+ "defaultValue": "''"
553
+ },
554
+ "passwordReset": {
555
+ "type": "string",
556
+ "mutable": false,
557
+ "complexType": {
558
+ "original": "string",
559
+ "resolved": "string",
560
+ "references": {}
561
+ },
562
+ "required": false,
563
+ "optional": false,
564
+ "docs": {
565
+ "tags": [],
566
+ "text": "Flag indicating whether the password reset feature is enabled"
567
+ },
568
+ "attribute": "password-reset",
569
+ "reflect": true,
570
+ "defaultValue": "'false'"
571
+ },
572
+ "userEmailRegex": {
573
+ "type": "string",
574
+ "mutable": false,
575
+ "complexType": {
576
+ "original": "string",
577
+ "resolved": "string",
578
+ "references": {}
579
+ },
580
+ "required": false,
581
+ "optional": false,
582
+ "docs": {
583
+ "tags": [],
584
+ "text": "Regular expression for validating the user email"
585
+ },
586
+ "attribute": "user-email-regex",
587
+ "reflect": true
588
+ },
589
+ "userEmailRegexOptions": {
590
+ "type": "string",
591
+ "mutable": false,
592
+ "complexType": {
593
+ "original": "string",
594
+ "resolved": "string",
595
+ "references": {}
596
+ },
597
+ "required": false,
598
+ "optional": false,
599
+ "docs": {
600
+ "tags": [],
601
+ "text": "Regex options for user email validation"
602
+ },
603
+ "attribute": "user-email-regex-options",
604
+ "reflect": true,
605
+ "defaultValue": "'i'"
606
+ },
607
+ "userPhoneRegex": {
608
+ "type": "string",
609
+ "mutable": false,
610
+ "complexType": {
611
+ "original": "string",
612
+ "resolved": "string",
613
+ "references": {}
614
+ },
615
+ "required": false,
616
+ "optional": false,
617
+ "docs": {
618
+ "tags": [],
619
+ "text": "User phone regex"
620
+ },
621
+ "attribute": "user-phone-regex",
622
+ "reflect": true
623
+ },
624
+ "userPhoneRegexOptions": {
625
+ "type": "string",
626
+ "mutable": false,
627
+ "complexType": {
628
+ "original": "string",
629
+ "resolved": "string",
630
+ "references": {}
631
+ },
632
+ "required": false,
633
+ "optional": false,
634
+ "docs": {
635
+ "tags": [],
636
+ "text": "User phone regex options"
637
+ },
638
+ "attribute": "user-phone-regex-options",
639
+ "reflect": true,
640
+ "defaultValue": "''"
641
+ },
642
+ "passwordRegex": {
643
+ "type": "string",
644
+ "mutable": false,
645
+ "complexType": {
646
+ "original": "string",
647
+ "resolved": "string",
648
+ "references": {}
649
+ },
650
+ "required": false,
651
+ "optional": false,
652
+ "docs": {
653
+ "tags": [],
654
+ "text": "Regular expression for validating the password"
655
+ },
656
+ "attribute": "password-regex",
657
+ "reflect": true
658
+ },
659
+ "passwordRegexOptions": {
660
+ "type": "string",
661
+ "mutable": false,
662
+ "complexType": {
663
+ "original": "string",
664
+ "resolved": "string",
665
+ "references": {}
666
+ },
667
+ "required": false,
668
+ "optional": false,
669
+ "docs": {
670
+ "tags": [],
671
+ "text": "Regex options for password validation"
672
+ },
673
+ "attribute": "password-regex-options",
674
+ "reflect": true,
675
+ "defaultValue": "''"
676
+ },
677
+ "loginByPhoneNumber": {
678
+ "type": "string",
679
+ "mutable": false,
680
+ "complexType": {
681
+ "original": "string",
682
+ "resolved": "string",
683
+ "references": {}
684
+ },
685
+ "required": false,
686
+ "optional": false,
687
+ "docs": {
688
+ "tags": [],
689
+ "text": "If set to true, login will be done by phone number, else by username/email"
690
+ },
691
+ "attribute": "login-by-phone-number",
692
+ "reflect": true,
693
+ "defaultValue": "'false'"
694
+ }
695
+ };
696
+ }
697
+ static get states() {
698
+ return {
699
+ "isLoading": {},
700
+ "contactValue": {},
701
+ "passwordValue": {},
702
+ "prefixValue": {},
703
+ "prefixOptions": {},
704
+ "isContactValid": {},
705
+ "isPasswordValid": {},
706
+ "isPasswordVisible": {},
707
+ "apiErrorMessage": {},
708
+ "captchaData": {}
709
+ };
710
+ }
711
+ static get watchers() {
712
+ return [{
713
+ "propName": "translationUrl",
714
+ "methodName": "handleNewTranslations"
715
+ }, {
716
+ "propName": "clientStyling",
717
+ "methodName": "handleClientStylingChange"
718
+ }, {
719
+ "propName": "clientStylingUrl",
720
+ "methodName": "handleClientStylingUrlChange"
721
+ }];
722
+ }
723
+ }