@visns-studio/visns-components 5.4.6 → 5.4.8

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.
@@ -1,8 +1,12 @@
1
- /* Profile.module.css */
1
+ /* Profile.module.scss */
2
2
 
3
+ /* Form field label animation */
3
4
  input:not(:placeholder-shown) + .fi__span,
4
5
  textarea:not(:placeholder-shown) + .fi__span,
5
- select:not(:placeholder-shown) + .fi__span {
6
+ select:not(:placeholder-shown) + .fi__span,
7
+ input:focus + .fi__span,
8
+ textarea:focus + .fi__span,
9
+ select:focus + .fi__span {
6
10
  transform: translateY(-40%) translateX(10px) scale(0.9);
7
11
  opacity: 1;
8
12
  padding: 0 0.25rem;
@@ -56,16 +60,6 @@ select:not(:placeholder-shown) + .fi__span {
56
60
  border: 1px solid var(--border-color);
57
61
  box-sizing: border-box;
58
62
  padding: 5px;
59
- margin: 0.5rem 0;
60
- height: auto;
61
- }
62
-
63
- .grid__subnav {
64
- flex: 1;
65
- background: white;
66
- border-radius: var(--br);
67
- box-sizing: border-box;
68
- padding: 5px;
69
63
  margin: 8px 0;
70
64
  height: auto;
71
65
  box-shadow: 0 4px 0 rgba(var(--primary-rgb), 0.05);
@@ -195,6 +189,10 @@ select:not(:placeholder-shown) + .fi__span {
195
189
  padding: 0.35em;
196
190
  position: relative;
197
191
  box-sizing: border-box;
192
+
193
+ @media (max-width: 768px) {
194
+ width: 100%;
195
+ }
198
196
  }
199
197
 
200
198
  .fi__label {
@@ -255,18 +253,46 @@ select:not(:placeholder-shown) + .fi__span {
255
253
  padding: 10px;
256
254
  }
257
255
 
256
+ /* Removed signatureContainer and signatureLabel styles as they're no longer needed */
257
+
258
+ .signaturePadWrapper {
259
+ width: 100%;
260
+ margin-bottom: 0.5rem;
261
+ position: relative;
262
+ z-index: 1;
263
+
264
+ canvas {
265
+ max-width: 100%;
266
+ height: auto !important;
267
+ }
268
+ }
269
+
258
270
  .polActions {
259
271
  position: fixed;
260
272
  bottom: 20px;
261
273
  right: 20px;
262
274
  width: auto;
275
+ display: flex;
276
+ gap: 0.5em;
277
+ z-index: 10;
278
+
279
+ @media (max-width: 768px) {
280
+ position: static;
281
+ margin: 1.5rem 0;
282
+ justify-content: flex-end;
283
+ width: 100%;
284
+ }
263
285
  }
264
286
 
265
287
  .polActions button {
266
- display: block;
267
- float: left;
268
288
  padding: 0.65em 1em;
269
- margin: 0 0.25em;
289
+ margin: 0;
290
+ transition: all 0.2s ease;
291
+
292
+ &:disabled {
293
+ opacity: 0.6;
294
+ cursor: not-allowed;
295
+ }
270
296
  }
271
297
 
272
298
  .btn {
@@ -284,18 +310,441 @@ select:not(:placeholder-shown) + .fi__span {
284
310
  border-radius: var(--br);
285
311
  outline: none;
286
312
  transition: all 0.2s cubic-bezier(0.85, 0, 0.15, 1) 0s;
287
- }
288
313
 
289
- .btn:hover {
290
- color: var(--tertiary-color);
291
- background: var(--secondary-color);
292
- border: 1px solid rgba(var(--secondary-color-rgb), 1.1);
314
+ &:hover:not(:disabled) {
315
+ color: var(--tertiary-color);
316
+ background: var(--secondary-color);
317
+ border: 1px solid rgba(var(--secondary-color-rgb), 1.1);
318
+ }
319
+
320
+ &:disabled {
321
+ opacity: 0.6;
322
+ cursor: not-allowed;
323
+ }
293
324
  }
294
325
 
295
326
  .inputError {
296
327
  border-color: red !important;
297
328
  }
298
329
 
330
+ .loading {
331
+ position: relative;
332
+ cursor: wait;
333
+
334
+ &::after {
335
+ content: '';
336
+ position: absolute;
337
+ width: 1em;
338
+ height: 1em;
339
+ top: 50%;
340
+ right: 0.5em;
341
+ margin-top: -0.5em;
342
+ border: 2px solid rgba(255, 255, 255, 0.5);
343
+ border-top-color: white;
344
+ border-radius: 50%;
345
+ animation: spinner 0.6s linear infinite;
346
+ }
347
+ }
348
+
349
+ @keyframes spinner {
350
+ to {
351
+ transform: rotate(360deg);
352
+ }
353
+ }
354
+
355
+ /* Two-Factor Authentication Styles */
356
+ .twoFactorSection {
357
+ padding: 0.75rem;
358
+ width: 100%;
359
+ display: flex;
360
+ flex-direction: column;
361
+ }
362
+
363
+ .twoFactorStatus {
364
+ margin-bottom: 1.5rem;
365
+
366
+ h3 {
367
+ margin-bottom: 0.75rem;
368
+ font-size: 1rem;
369
+ display: flex;
370
+ align-items: center;
371
+ gap: 0.5rem;
372
+ font-weight: 500;
373
+ }
374
+
375
+ p {
376
+ margin-bottom: 1.25rem;
377
+ line-height: 1.4;
378
+ color: var(--paragraph-color);
379
+ font-size: 0.9rem;
380
+ }
381
+ }
382
+
383
+ .statusEnabled {
384
+ color: #2ecc71;
385
+ font-weight: 500;
386
+ padding: 0.2rem 0.4rem;
387
+ background-color: rgba(46, 204, 113, 0.1);
388
+ border-radius: 4px;
389
+ font-size: 0.85rem;
390
+ }
391
+
392
+ .statusDisabled {
393
+ color: #e74c3c;
394
+ font-weight: 500;
395
+ padding: 0.2rem 0.4rem;
396
+ background-color: rgba(231, 76, 60, 0.1);
397
+ border-radius: 4px;
398
+ font-size: 0.85rem;
399
+ }
400
+
401
+ .confirmedMessage {
402
+ margin: 1rem 0;
403
+ padding: 0.75rem;
404
+ background-color: rgba(46, 204, 113, 0.1);
405
+ border-left: 3px solid #2ecc71;
406
+ border-radius: var(--br);
407
+ color: #333;
408
+ font-size: 0.9rem;
409
+ }
410
+
411
+ .btnPrimary {
412
+ background-color: var(--primary-color);
413
+ color: white;
414
+ font-size: 0.85rem;
415
+ padding: 0.5rem 0.85rem;
416
+
417
+ &:hover:not(:disabled) {
418
+ filter: brightness(90%);
419
+ }
420
+ }
421
+
422
+ .btnSecondary {
423
+ background-color: #f1f1f1;
424
+ color: #333;
425
+ border: 1px solid #ddd;
426
+ font-size: 0.85rem;
427
+ padding: 0.5rem 0.85rem;
428
+
429
+ &:hover:not(:disabled) {
430
+ background-color: #e5e5e5;
431
+ }
432
+ }
433
+
434
+ .btnDanger {
435
+ background-color: #e74c3c;
436
+ color: white;
437
+ font-size: 0.85rem;
438
+ padding: 0.5rem 0.85rem;
439
+
440
+ &:hover:not(:disabled) {
441
+ background-color: #c0392b;
442
+ }
443
+ }
444
+
445
+ .twoFactorSetup {
446
+ margin-top: 1.5rem;
447
+ padding: 1.5rem;
448
+ background-color: white;
449
+ border-radius: var(--br);
450
+ border: 1px solid #e0e0e0;
451
+ box-shadow: 0 3px 8px rgba(0, 0, 0, 0.05);
452
+ width: 100%;
453
+
454
+ h3 {
455
+ margin-bottom: 1.25rem;
456
+ font-size: 1rem;
457
+ font-weight: 500;
458
+ color: var(--primary-color);
459
+ padding-bottom: 0.75rem;
460
+ border-bottom: 1px solid #f0f0f0;
461
+ }
462
+ }
463
+
464
+ .setupSteps {
465
+ margin-left: 0;
466
+ margin-bottom: 1.5rem;
467
+ font-size: 0.9rem;
468
+ counter-reset: step-counter;
469
+ list-style-type: none;
470
+
471
+ li {
472
+ margin-bottom: 1.5rem;
473
+ padding-left: 2.5rem;
474
+ position: relative;
475
+
476
+ &:before {
477
+ content: counter(step-counter);
478
+ counter-increment: step-counter;
479
+ position: absolute;
480
+ left: 0;
481
+ top: 0;
482
+ width: 1.75rem;
483
+ height: 1.75rem;
484
+ background-color: var(--primary-color);
485
+ color: white;
486
+ border-radius: 50%;
487
+ display: flex;
488
+ align-items: center;
489
+ justify-content: center;
490
+ font-size: 0.85rem;
491
+ font-weight: 500;
492
+ }
493
+
494
+ p {
495
+ margin-bottom: 0.75rem;
496
+ font-weight: 500;
497
+ font-size: 0.9rem;
498
+ color: #333;
499
+ }
500
+
501
+ ul {
502
+ margin-left: 0;
503
+ margin-bottom: 1rem;
504
+ list-style-type: none;
505
+ background-color: #f9f9f9;
506
+ padding: 0.75rem 1rem;
507
+ border-radius: var(--br);
508
+ border-left: 3px solid var(--primary-color);
509
+
510
+ li {
511
+ margin-bottom: 0.5rem;
512
+ font-size: 0.85rem;
513
+ padding-left: 0;
514
+ position: relative;
515
+ padding-left: 1rem;
516
+
517
+ &:before {
518
+ content: '•';
519
+ position: absolute;
520
+ left: 0;
521
+ top: 0;
522
+ color: var(--primary-color);
523
+ font-size: 1rem;
524
+ width: auto;
525
+ height: auto;
526
+ background-color: transparent;
527
+ border-radius: 0;
528
+ counter-increment: none;
529
+ }
530
+
531
+ &:last-child {
532
+ margin-bottom: 0;
533
+ }
534
+
535
+ a {
536
+ color: var(--primary-color);
537
+ text-decoration: none;
538
+ font-weight: 500;
539
+
540
+ &:hover {
541
+ text-decoration: underline;
542
+ }
543
+ }
544
+ }
545
+ }
546
+ }
547
+ }
548
+
549
+ .qrCodeContainer {
550
+ display: flex;
551
+ justify-content: center;
552
+ margin: 0.75rem 0;
553
+ padding: 1rem;
554
+ background-color: white;
555
+ border-radius: var(--br);
556
+ border: 1px solid #e0e0e0;
557
+ width: 100%;
558
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
559
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
560
+
561
+ &:hover {
562
+ transform: translateY(-2px);
563
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
564
+ }
565
+ }
566
+
567
+ .qrCodeSvg {
568
+ width: 180px;
569
+ height: 180px;
570
+
571
+ svg {
572
+ width: 100%;
573
+ height: 100%;
574
+ border-radius: 4px;
575
+ }
576
+ }
577
+
578
+ .qrPlaceholder {
579
+ width: 180px;
580
+ height: 180px;
581
+ display: flex;
582
+ align-items: center;
583
+ justify-content: center;
584
+ background-color: #f5f5f5;
585
+ color: #666;
586
+ font-size: 0.85rem;
587
+ border-radius: 4px;
588
+ animation: pulse 1.5s infinite ease-in-out;
589
+ }
590
+
591
+ @keyframes pulse {
592
+ 0% {
593
+ opacity: 0.6;
594
+ }
595
+ 50% {
596
+ opacity: 1;
597
+ }
598
+ 100% {
599
+ opacity: 0.6;
600
+ }
601
+ }
602
+
603
+ .secretKeyContainer {
604
+ display: flex;
605
+ align-items: center;
606
+ margin: 0.75rem 0;
607
+ gap: 0.5rem;
608
+ background-color: #f9f9f9;
609
+ padding: 0.75rem;
610
+ border-radius: var(--br);
611
+ border: 1px solid #e0e0e0;
612
+ width: 100%;
613
+ }
614
+
615
+ .secretKey {
616
+ padding: 0.5rem 0.75rem;
617
+ background-color: white;
618
+ border-radius: var(--br);
619
+ font-family: monospace;
620
+ font-size: 0.85rem;
621
+ letter-spacing: 1px;
622
+ color: #333;
623
+ user-select: all;
624
+ border: 1px solid #ddd;
625
+ flex-grow: 1;
626
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
627
+ }
628
+
629
+ .copyButton {
630
+ padding: 0.4rem 0.75rem;
631
+ background-color: var(--primary-color);
632
+ color: white;
633
+ border: none;
634
+ border-radius: var(--br);
635
+ cursor: pointer;
636
+ font-size: 0.8rem;
637
+ transition: all 0.2s ease;
638
+ display: flex;
639
+ align-items: center;
640
+
641
+ &:hover {
642
+ filter: brightness(90%);
643
+ }
644
+
645
+ &:active {
646
+ transform: translateY(1px);
647
+ }
648
+ }
649
+
650
+ .verificationCodeContainer {
651
+ display: flex;
652
+ align-items: center;
653
+ gap: 0.75rem;
654
+ margin: 0.75rem 0;
655
+ background-color: #f9f9f9;
656
+ padding: 1rem;
657
+ border-radius: var(--br);
658
+ border: 1px solid #e0e0e0;
659
+ width: 100%;
660
+ }
661
+
662
+ .verificationCodeInput {
663
+ padding: 0.75rem;
664
+ font-size: 1.1rem;
665
+ letter-spacing: 4px;
666
+ width: 140px;
667
+ text-align: center;
668
+ border: 1px solid #ddd;
669
+ border-radius: var(--br);
670
+ font-family: monospace;
671
+ font-weight: 600;
672
+ color: #333;
673
+ background-color: white;
674
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
675
+
676
+ &:focus {
677
+ border-color: var(--primary-color);
678
+ outline: none;
679
+ box-shadow: 0 0 0 2px rgba(var(--primary-rgb), 0.1);
680
+ }
681
+
682
+ &::placeholder {
683
+ color: #bbb;
684
+ letter-spacing: 2px;
685
+ }
686
+ }
687
+
688
+ .recoveryCodes {
689
+ margin: 0.75rem 0;
690
+ padding: 1rem;
691
+ background-color: #f9f9f9;
692
+ border-radius: var(--br);
693
+ border: 1px solid #e0e0e0;
694
+ width: 100%;
695
+ }
696
+
697
+ .recoveryCodesContainer {
698
+ display: grid;
699
+ grid-template-columns: repeat(2, 1fr);
700
+ gap: 0.75rem;
701
+ margin-bottom: 1rem;
702
+
703
+ @media (max-width: 768px) {
704
+ grid-template-columns: 1fr;
705
+ }
706
+ }
707
+
708
+ .recoveryCode {
709
+ padding: 0.5rem 0.75rem;
710
+ background-color: white;
711
+ border-radius: var(--br);
712
+ border: 1px solid #ddd;
713
+ font-family: monospace;
714
+ font-size: 0.85rem;
715
+ letter-spacing: 1px;
716
+ color: #333;
717
+ user-select: all;
718
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
719
+ text-align: center;
720
+ }
721
+
722
+ .noRecoveryCodes {
723
+ padding: 1rem;
724
+ text-align: center;
725
+ color: #666;
726
+ font-style: italic;
727
+ font-size: 0.9rem;
728
+ }
729
+
730
+ .recoveryCodesWarning {
731
+ margin-top: 0.75rem;
732
+ padding: 0.75rem;
733
+ background-color: rgba(231, 76, 60, 0.1);
734
+ border-left: 3px solid #e74c3c;
735
+ border-radius: var(--br);
736
+ color: #333;
737
+ font-size: 0.85rem;
738
+ }
739
+
740
+ .setupActions {
741
+ display: flex;
742
+ justify-content: flex-end;
743
+ margin-top: 1.5rem;
744
+ padding-top: 1rem;
745
+ border-top: 1px solid #f0f0f0;
746
+ }
747
+
299
748
  .crmtitle {
300
749
  min-height: auto;
301
750
  padding: 1rem;
@@ -0,0 +1,65 @@
1
+ // Import the Login styles to maintain consistency
2
+ @import './Login.module.scss';
3
+
4
+ // Additional styles specific to the 2FA component
5
+ .instructions {
6
+ text-align: center;
7
+ margin: 0.5rem 0 1.5rem;
8
+ color: var(--paragraph-color);
9
+ font-size: 0.95rem;
10
+ line-height: 1.4;
11
+ }
12
+
13
+ .login {
14
+ h2 {
15
+ text-align: center;
16
+ margin: 0;
17
+ color: var(--heading-color);
18
+ font-weight: 500;
19
+ }
20
+ }
21
+
22
+ // Style for the verification code input
23
+ .formItem {
24
+ input[name='verificationCode'] {
25
+ letter-spacing: 0.25rem;
26
+ font-size: 1.2rem;
27
+ text-align: center;
28
+ }
29
+ }
30
+
31
+ .rememberMeIndicator {
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ margin: 0.75rem auto 0;
36
+ padding: 0.6rem 1rem;
37
+ background-color: rgba(var(--primary-rgb), 0.08);
38
+ border-radius: var(--br);
39
+ border-left: 3px solid var(--primary-color);
40
+ max-width: 80%;
41
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
42
+ transition: all 0.3s ease;
43
+
44
+ &:hover {
45
+ background-color: rgba(var(--primary-rgb), 0.12);
46
+ transform: translateY(-1px);
47
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.08);
48
+ }
49
+
50
+ span {
51
+ font-size: 0.85rem;
52
+ color: var(--primary-color);
53
+ font-weight: 500;
54
+ display: flex;
55
+ align-items: center;
56
+
57
+ &::before {
58
+ content: '✓';
59
+ display: inline-block;
60
+ margin-right: 0.5rem;
61
+ font-weight: bold;
62
+ font-size: 0.9rem;
63
+ }
64
+ }
65
+ }
@@ -17,6 +17,7 @@ import GenericMain from './GenericMain';
17
17
  import Login from '../auth/Login';
18
18
  import Reset from '../auth/Reset';
19
19
  import Verify from '../auth/Verify';
20
+ import TwoFactorAuth from '../auth/TwoFactorAuth';
20
21
 
21
22
  const ProtectedRoute = ({ user, loading, redirectPath = '/login' }) => {
22
23
  const location = useLocation();
@@ -111,6 +112,17 @@ const GenericAuth = ({
111
112
  />
112
113
  }
113
114
  />
115
+ <Route
116
+ path="2fa"
117
+ element={
118
+ <TwoFactorAuthComponent
119
+ loginBg={loginBg}
120
+ logo={logo}
121
+ setIsAuthenticated={setIsAuthenticated}
122
+ setUserProfile={setUserProfile}
123
+ />
124
+ }
125
+ />
114
126
  <Route
115
127
  element={
116
128
  <ProtectedRoute
@@ -174,4 +186,15 @@ const VerifyComponent = React.memo(({ loginBg, logo, setIsAuthenticated }) => (
174
186
  <Verify loginBg={loginBg} logo={logo} setSystemAuth={setIsAuthenticated} />
175
187
  ));
176
188
 
189
+ const TwoFactorAuthComponent = React.memo(
190
+ ({ loginBg, logo, setIsAuthenticated, setUserProfile }) => (
191
+ <TwoFactorAuth
192
+ loginBg={loginBg}
193
+ logo={logo}
194
+ setSystemAuth={setIsAuthenticated}
195
+ setUserProfile={setUserProfile}
196
+ />
197
+ )
198
+ );
199
+
177
200
  export default GenericAuth;