@fy-/fws-vue 2.2.63 → 2.2.64
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/components/fws/UserFlow.vue +192 -128
- package/components/ui/DefaultInput.vue +6 -5
- package/package.json +1 -1
|
@@ -219,161 +219,225 @@ onMounted(async () => {
|
|
|
219
219
|
<form
|
|
220
220
|
v-if="!completed"
|
|
221
221
|
class="fws-login w-full"
|
|
222
|
+
aria-labelledby="login-title"
|
|
222
223
|
@submit.prevent="userFlow()"
|
|
223
224
|
>
|
|
224
|
-
<!--
|
|
225
|
-
<div
|
|
225
|
+
<!-- Message / Header -->
|
|
226
|
+
<div
|
|
227
|
+
v-if="responseMessage"
|
|
228
|
+
class="fws-login__header mb-4"
|
|
229
|
+
>
|
|
226
230
|
<h2
|
|
227
|
-
|
|
228
|
-
class="text-lg text-fv-neutral-700 dark:text-fv-neutral-300
|
|
231
|
+
id="login-title"
|
|
232
|
+
class="text-lg font-medium text-fv-neutral-700 dark:text-fv-neutral-300"
|
|
229
233
|
>
|
|
230
234
|
{{ responseMessage }}
|
|
231
235
|
</h2>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
:key="`${field.label}oauth`"
|
|
257
|
-
class="h-12 w-12 block p-2 mr-3"
|
|
258
|
-
:alt="field.info.Name"
|
|
259
|
-
:src="field.button.logo"
|
|
260
|
-
>
|
|
261
|
-
<div>
|
|
262
|
-
{{
|
|
263
|
-
$t("user_flow_signin_with", {
|
|
264
|
-
provider: field.name,
|
|
265
|
-
})
|
|
266
|
-
}}
|
|
267
|
-
</div>
|
|
268
|
-
</a>
|
|
269
|
-
</template>
|
|
270
|
-
<button
|
|
271
|
-
type="button"
|
|
272
|
-
class="flex items-center gap-2 justify-start btn neutral defaults w-full mx-auto !font-semibold"
|
|
273
|
-
@click="
|
|
274
|
-
() => {
|
|
275
|
-
showEmail = true;
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<!-- OAuth providers section -->
|
|
239
|
+
<div v-if="hasOauth && !showEmail" class="fws-login__oauth space-y-3">
|
|
240
|
+
<div
|
|
241
|
+
v-for="field of responseFields"
|
|
242
|
+
v-show="field.type && field.type === 'oauth2' && field.button"
|
|
243
|
+
:key="field.id"
|
|
244
|
+
>
|
|
245
|
+
<button
|
|
246
|
+
type="button"
|
|
247
|
+
class="flex w-full items-center justify-start gap-3 px-4 py-2.5 rounded-lg border border-fv-neutral-200 dark:border-fv-neutral-700
|
|
248
|
+
transition-all duration-200 hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-fv-neutral-800
|
|
249
|
+
focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600"
|
|
250
|
+
:style="`background: ${
|
|
251
|
+
field.button['background-color']
|
|
252
|
+
}; color: ${$getContrastingTextColor(
|
|
253
|
+
field.button['background-color'],
|
|
254
|
+
)}`"
|
|
255
|
+
:aria-label="`${$t('user_flow_signin_with', { provider: field.name })}`"
|
|
256
|
+
@click="
|
|
257
|
+
() => {
|
|
258
|
+
if (field.info.Button_Extra?.trigger) {
|
|
259
|
+
doTrigger(field);
|
|
276
260
|
}
|
|
277
|
-
|
|
261
|
+
else {
|
|
262
|
+
userFlow({ initial: true, oauth: field.id });
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
"
|
|
266
|
+
>
|
|
267
|
+
<img
|
|
268
|
+
:key="`${field.label}oauth`"
|
|
269
|
+
class="h-6 w-6 flex-shrink-0"
|
|
270
|
+
:alt="field.info.Name"
|
|
271
|
+
:src="field.button.logo"
|
|
278
272
|
>
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
273
|
+
<span class="text-base font-medium">
|
|
274
|
+
{{ $t("user_flow_signin_with", { provider: field.name }) }}
|
|
275
|
+
</span>
|
|
276
|
+
</button>
|
|
277
|
+
</div>
|
|
278
|
+
|
|
279
|
+
<div class="relative my-6">
|
|
280
|
+
<div class="absolute inset-0 flex items-center">
|
|
281
|
+
<div class="w-full border-t border-fv-neutral-200 dark:border-fv-neutral-700" />
|
|
288
282
|
</div>
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
283
|
+
<div class="relative flex justify-center text-sm">
|
|
284
|
+
<span class="px-2 bg-white dark:bg-fv-neutral-800 text-fv-neutral-500 dark:text-fv-neutral-400">
|
|
285
|
+
{{ $t("user_flow_or") }}
|
|
286
|
+
</span>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
|
|
290
|
+
<button
|
|
291
|
+
type="button"
|
|
292
|
+
class="flex w-full items-center justify-start gap-3 px-4 py-2.5 rounded-lg border border-fv-neutral-200 dark:border-fv-neutral-700
|
|
293
|
+
bg-white dark:bg-fv-neutral-700 text-fv-neutral-800 dark:text-white
|
|
294
|
+
hover:bg-fv-neutral-50 dark:hover:bg-fv-neutral-650 transition-all duration-200
|
|
295
|
+
hover:shadow-sm focus:outline-none focus:ring-2 focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600"
|
|
296
|
+
aria-label="Sign in with email"
|
|
297
|
+
@click="showEmail = true"
|
|
293
298
|
>
|
|
294
|
-
<
|
|
295
|
-
|
|
299
|
+
<EnvelopeIcon class="h-6 w-6 text-fv-primary-500 dark:text-fv-primary-400 flex-shrink-0" />
|
|
300
|
+
<span class="text-base font-medium">
|
|
301
|
+
{{ $t("user_flow_signin_with", { provider: $t("user_flow_provider_email_cta") }) }}
|
|
302
|
+
</span>
|
|
303
|
+
</button>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<!-- Form fields section -->
|
|
307
|
+
<div
|
|
308
|
+
v-if="forceAction || (showEmail && initial) || !initial"
|
|
309
|
+
class="fws-login__form space-y-4"
|
|
310
|
+
>
|
|
311
|
+
<template v-if="responseFields && responseFields.length > 0">
|
|
312
|
+
<!-- Labels and text elements -->
|
|
313
|
+
<template v-for="field of responseFields" :key="field.label">
|
|
314
|
+
<div
|
|
315
|
+
v-if="field.type === 'label'"
|
|
316
|
+
class="mb-2"
|
|
317
|
+
>
|
|
296
318
|
<h3
|
|
297
|
-
|
|
298
|
-
class="
|
|
299
|
-
:class="
|
|
319
|
+
class="text-sm"
|
|
320
|
+
:class="[
|
|
300
321
|
field.style === 'error'
|
|
301
|
-
? '
|
|
302
|
-
: ''
|
|
303
|
-
"
|
|
322
|
+
? 'p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 font-medium'
|
|
323
|
+
: 'text-fv-neutral-600 dark:text-fv-neutral-400',
|
|
324
|
+
]"
|
|
304
325
|
>
|
|
305
|
-
<a
|
|
306
|
-
field.
|
|
307
|
-
|
|
308
|
-
|
|
326
|
+
<a
|
|
327
|
+
v-if="field.link"
|
|
328
|
+
:href="field.link"
|
|
329
|
+
class="text-fv-primary-600 dark:text-fv-primary-400 hover:underline focus:outline-none focus:ring-2 focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600 rounded"
|
|
330
|
+
>
|
|
331
|
+
{{ field.label }}
|
|
332
|
+
</a>
|
|
333
|
+
<span v-else v-html="field.label" />
|
|
309
334
|
</h3>
|
|
335
|
+
</div>
|
|
310
336
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
v-if="field.name"
|
|
325
|
-
:id="field.name"
|
|
326
|
-
ref="inputs"
|
|
327
|
-
v-model="formData[field.name]"
|
|
328
|
-
:label="field.label"
|
|
329
|
-
:mask="field.mask"
|
|
330
|
-
class="mt-3"
|
|
331
|
-
:placeholder="
|
|
332
|
-
field.name === 'name' ? 'John Doe' : field.label
|
|
333
|
-
"
|
|
334
|
-
:error="fieldsError[field.name]"
|
|
335
|
-
:type="field.type"
|
|
336
|
-
:req="responseReq.includes(field.name)"
|
|
337
|
-
:autocomplete="autocompleteValue(field.name)"
|
|
338
|
-
/>
|
|
339
|
-
</template>
|
|
340
|
-
</template>
|
|
341
|
-
<template v-if="field.type === 'checkbox'">
|
|
337
|
+
<!-- Input fields -->
|
|
338
|
+
<template v-if="field.cat === 'input'">
|
|
339
|
+
<template
|
|
340
|
+
v-if="
|
|
341
|
+
field.type === 'text'
|
|
342
|
+
|| field.type === 'password'
|
|
343
|
+
|| field.type === 'email'
|
|
344
|
+
|| field.type === 'mask'
|
|
345
|
+
|| field.type === 'tel'
|
|
346
|
+
|| field.type === 'number'
|
|
347
|
+
|| field.type === 'phone'
|
|
348
|
+
"
|
|
349
|
+
>
|
|
342
350
|
<DefaultInput
|
|
343
351
|
v-if="field.name"
|
|
344
352
|
:id="field.name"
|
|
345
|
-
|
|
346
|
-
|
|
353
|
+
ref="inputs"
|
|
354
|
+
v-model="formData[field.name]"
|
|
347
355
|
:label="field.label"
|
|
356
|
+
:mask="field.mask"
|
|
357
|
+
:placeholder="
|
|
358
|
+
field.name === 'name' ? 'John Doe' : field.label
|
|
359
|
+
"
|
|
348
360
|
:error="fieldsError[field.name]"
|
|
349
361
|
:type="field.type"
|
|
350
362
|
:req="responseReq.includes(field.name)"
|
|
351
|
-
:
|
|
363
|
+
:autocomplete="autocompleteValue(field.name)"
|
|
352
364
|
/>
|
|
353
365
|
</template>
|
|
354
366
|
</template>
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
>{{ $t("recover_pwd_link") }}</a>
|
|
370
|
-
</div>
|
|
371
|
-
<button class="btn primary medium mt-4">
|
|
372
|
-
{{ $t("cta_login_next") }}
|
|
373
|
-
</button>
|
|
367
|
+
|
|
368
|
+
<!-- Checkbox inputs -->
|
|
369
|
+
<template v-if="field.type === 'checkbox'">
|
|
370
|
+
<DefaultInput
|
|
371
|
+
v-if="field.name"
|
|
372
|
+
:id="field.name"
|
|
373
|
+
v-model:checkbox-value="formData[field.name]"
|
|
374
|
+
:label="field.label"
|
|
375
|
+
:error="fieldsError[field.name]"
|
|
376
|
+
:type="field.type"
|
|
377
|
+
:req="responseReq.includes(field.name)"
|
|
378
|
+
:link-icon="field.link"
|
|
379
|
+
/>
|
|
380
|
+
</template>
|
|
374
381
|
</template>
|
|
375
|
-
|
|
382
|
+
|
|
383
|
+
<!-- Error message -->
|
|
384
|
+
<div
|
|
385
|
+
v-if="responseError && responseError.token"
|
|
386
|
+
class="p-3 rounded-lg bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 text-sm font-medium"
|
|
387
|
+
role="alert"
|
|
388
|
+
v-html="$t(responseError.token)"
|
|
389
|
+
/>
|
|
390
|
+
|
|
391
|
+
<!-- Password recovery link -->
|
|
392
|
+
<div
|
|
393
|
+
v-if="responseReq.includes('password') && 0"
|
|
394
|
+
class="text-right my-2"
|
|
395
|
+
>
|
|
396
|
+
<button
|
|
397
|
+
type="button"
|
|
398
|
+
class="text-fv-primary-600 dark:text-fv-primary-400 text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-fv-primary-500 rounded"
|
|
399
|
+
@click="
|
|
400
|
+
() => {
|
|
401
|
+
eventBus.emit('ResetPasswordModal', true);
|
|
402
|
+
pwdRecoverMailSent = false;
|
|
403
|
+
}
|
|
404
|
+
"
|
|
405
|
+
>
|
|
406
|
+
{{ $t("recover_pwd_link") }}
|
|
407
|
+
</button>
|
|
408
|
+
</div>
|
|
409
|
+
|
|
410
|
+
<!-- Submit button -->
|
|
411
|
+
<button
|
|
412
|
+
type="submit"
|
|
413
|
+
class="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-lg shadow-sm
|
|
414
|
+
text-white bg-fv-primary-600 hover:bg-fv-primary-700 dark:bg-fv-primary-700 dark:hover:bg-fv-primary-800
|
|
415
|
+
focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-fv-primary-500 dark:focus:ring-fv-primary-600
|
|
416
|
+
dark:focus:ring-offset-fv-neutral-800 font-medium transition-all duration-200"
|
|
417
|
+
aria-label="Continue"
|
|
418
|
+
>
|
|
419
|
+
{{ $t("cta_login_next") }}
|
|
420
|
+
</button>
|
|
421
|
+
</template>
|
|
376
422
|
</div>
|
|
377
423
|
</form>
|
|
378
424
|
</ClientOnly>
|
|
379
425
|
</template>
|
|
426
|
+
|
|
427
|
+
<style scoped>
|
|
428
|
+
.fws-login {
|
|
429
|
+
@apply transition-all duration-300;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.fws-login__oauth button,
|
|
433
|
+
.fws-login__form button[type="submit"] {
|
|
434
|
+
@apply transition-all duration-200;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
@media (max-width: 640px) {
|
|
438
|
+
.fws-login__oauth,
|
|
439
|
+
.fws-login__form {
|
|
440
|
+
@apply px-0;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
</style>
|
|
@@ -187,7 +187,7 @@ defineExpose({ focus, blur, getInputRef })
|
|
|
187
187
|
:name="id"
|
|
188
188
|
:class="{
|
|
189
189
|
'error': checkErrors,
|
|
190
|
-
'bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg block w-full dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-
|
|
190
|
+
'bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm rounded-lg block w-full dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-300 dark:text-white transition-all duration-200': type !== 'range',
|
|
191
191
|
'p-2.5': type !== 'range',
|
|
192
192
|
'focus:border-fv-primary-500 dark:focus:border-fv-primary-500': !checkErrors,
|
|
193
193
|
'focus:ring-2 focus:ring-fv-primary-300 dark:focus:ring-fv-primary-800 focus:ring-opacity-50': type !== 'range',
|
|
@@ -288,7 +288,7 @@ defineExpose({ focus, blur, getInputRef })
|
|
|
288
288
|
:aria-invalid="checkErrors ? 'true' : 'false'"
|
|
289
289
|
class="block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50 rounded-lg
|
|
290
290
|
border border-fv-neutral-300 focus:ring-2 focus:ring-fv-primary-300 focus:border-fv-primary-500
|
|
291
|
-
dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-
|
|
291
|
+
dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-300
|
|
292
292
|
dark:text-white dark:focus:ring-fv-primary-800 dark:focus:border-fv-primary-500
|
|
293
293
|
transition-colors duration-200 shadow-sm"
|
|
294
294
|
@focus="handleFocus"
|
|
@@ -332,7 +332,7 @@ defineExpose({ focus, blur, getInputRef })
|
|
|
332
332
|
:aria-invalid="checkErrors ? 'true' : 'false'"
|
|
333
333
|
class="block p-2.5 w-full text-sm text-fv-neutral-900 bg-fv-neutral-50
|
|
334
334
|
rounded-lg border border-fv-neutral-300 focus:ring-2 focus:ring-fv-primary-300 focus:border-fv-primary-500
|
|
335
|
-
dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-
|
|
335
|
+
dark:bg-fv-neutral-700 dark:border-fv-neutral-600 dark:placeholder-fv-neutral-300
|
|
336
336
|
dark:text-white dark:focus:ring-fv-primary-800 dark:focus:border-fv-primary-500
|
|
337
337
|
transition-colors duration-200 shadow-sm min-h-[100px]"
|
|
338
338
|
@focus="handleFocus"
|
|
@@ -375,7 +375,7 @@ defineExpose({ focus, blur, getInputRef })
|
|
|
375
375
|
class="appearance-none bg-fv-neutral-50 border border-fv-neutral-300 text-fv-neutral-900 text-sm
|
|
376
376
|
rounded-lg focus:ring-2 focus:ring-fv-primary-300 focus:border-fv-primary-500
|
|
377
377
|
block w-full p-2.5 dark:bg-fv-neutral-700 dark:border-fv-neutral-600
|
|
378
|
-
dark:placeholder-fv-neutral-
|
|
378
|
+
dark:placeholder-fv-neutral-300 dark:text-white dark:focus:ring-fv-primary-800
|
|
379
379
|
dark:focus:border-fv-primary-500 shadow-sm transition-colors duration-200 pr-10"
|
|
380
380
|
@focus="handleFocus"
|
|
381
381
|
@blur="handleBlur"
|
|
@@ -577,6 +577,7 @@ input, select, textarea, input[type="range"]::-webkit-slider-thumb, input[type="
|
|
|
577
577
|
input::placeholder,
|
|
578
578
|
textarea::placeholder,
|
|
579
579
|
select::placeholder {
|
|
580
|
-
@apply text-fv-neutral-400 dark:text-fv-neutral-
|
|
580
|
+
@apply text-fv-neutral-400 dark:text-fv-neutral-300;
|
|
581
|
+
opacity: 0.8;
|
|
581
582
|
}
|
|
582
583
|
</style>
|