uibee 1.4.2 → 1.5.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 CHANGED
@@ -3,21 +3,13 @@
3
3
 
4
4
  This package includes shared components, functions and hooks for reuse across Login projects.
5
5
 
6
- ## Installation
6
+ ## Getting Started
7
7
 
8
8
  ```bash
9
- # Clone the repository
10
- git clone git@github.com:Login-Linjeforening-for-IT/uibee.git
11
- cd uibee
12
-
13
9
  # Install dependencies
14
10
  npm install
15
- ```
16
11
 
17
- ## Usage
18
-
19
- ```bash
20
- # Start the development server
12
+ # Build the project
21
13
  npm run build
22
14
  ```
23
15
 
package/dist/globals.css CHANGED
@@ -8,10 +8,14 @@
8
8
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
9
9
  "Courier New", monospace;
10
10
  --color-red-300: oklch(80.8% 0.114 19.571);
11
+ --color-red-500: oklch(63.7% 0.237 25.331);
12
+ --color-red-700: oklch(50.5% 0.213 27.518);
13
+ --color-red-800: oklch(44.4% 0.177 26.899);
11
14
  --color-yellow-300: oklch(90.5% 0.182 98.111);
12
15
  --color-green-300: oklch(87.1% 0.15 154.449);
13
16
  --color-blue-300: oklch(80.9% 0.105 251.813);
14
17
  --spacing: 0.25rem;
18
+ --container-3xs: 16rem;
15
19
  --container-xs: 20rem;
16
20
  --container-sm: 24rem;
17
21
  --container-md: 28rem;
@@ -25,6 +29,8 @@
25
29
  --font-weight-bold: 700;
26
30
  --font-weight-extrabold: 800;
27
31
  --tracking-tight: -0.025em;
32
+ --radius-sm: 0.25rem;
33
+ --radius-md: 0.375rem;
28
34
  --radius-lg: 0.5rem;
29
35
  --radius-xl: 0.75rem;
30
36
  --default-transition-duration: 150ms;
@@ -36,6 +42,7 @@
36
42
  --color-login-800: #181818;
37
43
  --color-login-700: #1a1a1a;
38
44
  --color-login-600: #212121;
45
+ --color-login-200: #727272;
39
46
  --color-login-100: #b0b0b0;
40
47
  --color-login-50: #ededed;
41
48
  }
@@ -189,18 +196,65 @@
189
196
  }
190
197
  }
191
198
  @layer utilities {
199
+ .pointer-events-none {
200
+ pointer-events: none;
201
+ }
202
+ .sr-only {
203
+ position: absolute;
204
+ width: 1px;
205
+ height: 1px;
206
+ padding: 0;
207
+ margin: -1px;
208
+ overflow: hidden;
209
+ clip-path: inset(50%);
210
+ white-space: nowrap;
211
+ border-width: 0;
212
+ }
213
+ .absolute {
214
+ position: absolute;
215
+ }
192
216
  .fixed {
193
217
  position: fixed;
194
218
  }
195
219
  .relative {
196
220
  position: relative;
197
221
  }
222
+ .start-2 {
223
+ inset-inline-start: calc(var(--spacing) * 2);
224
+ }
225
+ .top-1\/2 {
226
+ top: calc(1/2 * 100%);
227
+ }
228
+ .top-2 {
229
+ top: calc(var(--spacing) * 2);
230
+ }
231
+ .right-0 {
232
+ right: calc(var(--spacing) * 0);
233
+ }
234
+ .right-1 {
235
+ right: calc(var(--spacing) * 1);
236
+ }
198
237
  .right-4 {
199
238
  right: calc(var(--spacing) * 4);
200
239
  }
201
240
  .bottom-4 {
202
241
  bottom: calc(var(--spacing) * 4);
203
242
  }
243
+ .left-2 {
244
+ left: calc(var(--spacing) * 2);
245
+ }
246
+ .left-12 {
247
+ left: calc(var(--spacing) * 12);
248
+ }
249
+ .z-10 {
250
+ z-index: 10;
251
+ }
252
+ .z-19 {
253
+ z-index: 19;
254
+ }
255
+ .z-20 {
256
+ z-index: 20;
257
+ }
204
258
  .z-50 {
205
259
  z-index: 50;
206
260
  }
@@ -210,21 +264,36 @@
210
264
  .mb-2 {
211
265
  margin-bottom: calc(var(--spacing) * 2);
212
266
  }
267
+ .ml-1 {
268
+ margin-left: calc(var(--spacing) * 1);
269
+ }
270
+ .ml-3 {
271
+ margin-left: calc(var(--spacing) * 3);
272
+ }
213
273
  .line-clamp-3 {
214
274
  overflow: hidden;
215
275
  display: -webkit-box;
216
276
  -webkit-box-orient: vertical;
217
277
  -webkit-line-clamp: 3;
218
278
  }
279
+ .block {
280
+ display: block;
281
+ }
219
282
  .flex {
220
283
  display: flex;
221
284
  }
285
+ .hidden {
286
+ display: none;
287
+ }
222
288
  .inline {
223
289
  display: inline;
224
290
  }
225
291
  .aspect-\[3\/1\] {
226
292
  aspect-ratio: 3/1;
227
293
  }
294
+ .h-4 {
295
+ height: calc(var(--spacing) * 4);
296
+ }
228
297
  .h-6 {
229
298
  height: calc(var(--spacing) * 6);
230
299
  }
@@ -234,36 +303,96 @@
234
303
  .min-h-screen {
235
304
  min-height: 100vh;
236
305
  }
306
+ .w-4 {
307
+ width: calc(var(--spacing) * 4);
308
+ }
309
+ .w-5 {
310
+ width: calc(var(--spacing) * 5);
311
+ }
237
312
  .w-6 {
238
313
  width: calc(var(--spacing) * 6);
239
314
  }
240
315
  .w-10 {
241
316
  width: calc(var(--spacing) * 10);
242
317
  }
318
+ .w-\[calc\(100\%-10px\)\] {
319
+ width: calc(100% - 10px);
320
+ }
321
+ .w-fit {
322
+ width: fit-content;
323
+ }
243
324
  .w-full {
244
325
  width: 100%;
245
326
  }
327
+ .w-max {
328
+ width: max-content;
329
+ }
246
330
  .w-sm {
247
331
  width: var(--container-sm);
248
332
  }
333
+ .max-w-3xs {
334
+ max-width: var(--container-3xs);
335
+ }
249
336
  .max-w-md {
250
337
  max-width: var(--container-md);
251
338
  }
252
339
  .max-w-xs {
253
340
  max-width: var(--container-xs);
254
341
  }
342
+ .min-w-\[6ch\] {
343
+ min-width: 6ch;
344
+ }
345
+ .flex-1 {
346
+ flex: 1;
347
+ }
255
348
  .flex-shrink-0 {
256
349
  flex-shrink: 0;
257
350
  }
351
+ .origin-\[0\] {
352
+ transform-origin: 0;
353
+ }
354
+ .translate-x-4 {
355
+ --tw-translate-x: calc(var(--spacing) * 4);
356
+ translate: var(--tw-translate-x) var(--tw-translate-y);
357
+ }
358
+ .-translate-y-1\/2 {
359
+ --tw-translate-y: calc(calc(1/2 * 100%) * -1);
360
+ translate: var(--tw-translate-x) var(--tw-translate-y);
361
+ }
362
+ .-translate-y-5 {
363
+ --tw-translate-y: calc(var(--spacing) * -5);
364
+ translate: var(--tw-translate-x) var(--tw-translate-y);
365
+ }
366
+ .scale-75 {
367
+ --tw-scale-x: 75%;
368
+ --tw-scale-y: 75%;
369
+ --tw-scale-z: 75%;
370
+ scale: var(--tw-scale-x) var(--tw-scale-y);
371
+ }
372
+ .scale-100 {
373
+ --tw-scale-x: 100%;
374
+ --tw-scale-y: 100%;
375
+ --tw-scale-z: 100%;
376
+ scale: var(--tw-scale-x) var(--tw-scale-y);
377
+ }
258
378
  .transform {
259
379
  transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
260
380
  }
381
+ .cursor-pointer {
382
+ cursor: pointer;
383
+ }
384
+ .appearance-none {
385
+ appearance: none;
386
+ }
261
387
  .flex-col {
262
388
  flex-direction: column;
263
389
  }
264
390
  .flex-col-reverse {
265
391
  flex-direction: column-reverse;
266
392
  }
393
+ .flex-wrap {
394
+ flex-wrap: wrap;
395
+ }
267
396
  .items-center {
268
397
  align-items: center;
269
398
  }
@@ -273,6 +402,12 @@
273
402
  .justify-center {
274
403
  justify-content: center;
275
404
  }
405
+ .gap-0\.5 {
406
+ gap: calc(var(--spacing) * 0.5);
407
+ }
408
+ .gap-1 {
409
+ gap: calc(var(--spacing) * 1);
410
+ }
276
411
  .gap-2 {
277
412
  gap: calc(var(--spacing) * 2);
278
413
  }
@@ -282,18 +417,49 @@
282
417
  .gap-4 {
283
418
  gap: calc(var(--spacing) * 4);
284
419
  }
420
+ .truncate {
421
+ overflow: hidden;
422
+ text-overflow: ellipsis;
423
+ white-space: nowrap;
424
+ }
285
425
  .rounded {
286
426
  border-radius: 0.25rem;
287
427
  }
428
+ .rounded-full {
429
+ border-radius: calc(infinity * 1px);
430
+ }
288
431
  .rounded-lg {
289
432
  border-radius: var(--radius-lg);
290
433
  }
434
+ .rounded-md {
435
+ border-radius: var(--radius-md);
436
+ }
437
+ .rounded-sm {
438
+ border-radius: var(--radius-sm);
439
+ }
291
440
  .rounded-xl {
292
441
  border-radius: var(--radius-xl);
293
442
  }
443
+ .border {
444
+ border-style: var(--tw-border-style);
445
+ border-width: 1px;
446
+ }
447
+ .border-\[0\.10rem\] {
448
+ border-style: var(--tw-border-style);
449
+ border-width: 0.10rem;
450
+ }
451
+ .border-login-200 {
452
+ border-color: var(--color-login-200);
453
+ }
294
454
  .bg-login {
295
455
  background-color: var(--color-login);
296
456
  }
457
+ .bg-login-50 {
458
+ background-color: var(--color-login-50);
459
+ }
460
+ .bg-login-200 {
461
+ background-color: var(--color-login-200);
462
+ }
297
463
  .bg-login-600 {
298
464
  background-color: var(--color-login-600);
299
465
  }
@@ -306,15 +472,33 @@
306
472
  .bg-login-900 {
307
473
  background-color: var(--color-login-900);
308
474
  }
475
+ .bg-transparent {
476
+ background-color: transparent;
477
+ }
478
+ .stroke-3 {
479
+ stroke-width: 3;
480
+ }
309
481
  .object-contain {
310
482
  object-fit: contain;
311
483
  }
484
+ .p-1 {
485
+ padding: calc(var(--spacing) * 1);
486
+ }
312
487
  .p-2 {
313
488
  padding: calc(var(--spacing) * 2);
314
489
  }
315
490
  .p-8 {
316
491
  padding: calc(var(--spacing) * 8);
317
492
  }
493
+ .px-1 {
494
+ padding-inline: calc(var(--spacing) * 1);
495
+ }
496
+ .px-2 {
497
+ padding-inline: calc(var(--spacing) * 2);
498
+ }
499
+ .px-2\.5 {
500
+ padding-inline: calc(var(--spacing) * 2.5);
501
+ }
318
502
  .px-3 {
319
503
  padding-inline: calc(var(--spacing) * 3);
320
504
  }
@@ -324,6 +508,12 @@
324
508
  .px-6 {
325
509
  padding-inline: calc(var(--spacing) * 6);
326
510
  }
511
+ .py-0\.5 {
512
+ padding-block: calc(var(--spacing) * 0.5);
513
+ }
514
+ .py-1 {
515
+ padding-block: calc(var(--spacing) * 1);
516
+ }
327
517
  .py-2 {
328
518
  padding-block: calc(var(--spacing) * 2);
329
519
  }
@@ -333,12 +523,24 @@
333
523
  .py-12 {
334
524
  padding-block: calc(var(--spacing) * 12);
335
525
  }
526
+ .pt-1 {
527
+ padding-top: calc(var(--spacing) * 1);
528
+ }
529
+ .pt-3 {
530
+ padding-top: calc(var(--spacing) * 3);
531
+ }
532
+ .pt-4 {
533
+ padding-top: calc(var(--spacing) * 4);
534
+ }
336
535
  .pr-1 {
337
536
  padding-right: calc(var(--spacing) * 1);
338
537
  }
339
538
  .pb-1 {
340
539
  padding-bottom: calc(var(--spacing) * 1);
341
540
  }
541
+ .pb-2\.5 {
542
+ padding-bottom: calc(var(--spacing) * 2.5);
543
+ }
342
544
  .text-center {
343
545
  text-align: center;
344
546
  }
@@ -397,12 +599,30 @@
397
599
  color: color-mix(in oklab, var(--color-red-300) 70%, transparent);
398
600
  }
399
601
  }
602
+ .text-red-500\/50 {
603
+ color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 50%, transparent);
604
+ @supports (color: color-mix(in lab, red, red)) {
605
+ color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
606
+ }
607
+ }
608
+ .text-red-700 {
609
+ color: var(--color-red-700);
610
+ }
400
611
  .text-yellow-300\/70 {
401
612
  color: color-mix(in srgb, oklch(90.5% 0.182 98.111) 70%, transparent);
402
613
  @supports (color: color-mix(in lab, red, red)) {
403
614
  color: color-mix(in oklab, var(--color-yellow-300) 70%, transparent);
404
615
  }
405
616
  }
617
+ .shadow-md {
618
+ --tw-shadow: 0 4px 6px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 2px 4px -2px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
619
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
620
+ }
621
+ .transition {
622
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
623
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
624
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
625
+ }
406
626
  .transition-all {
407
627
  transition-property: all;
408
628
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
@@ -412,6 +632,71 @@
412
632
  --tw-duration: 200ms;
413
633
  transition-duration: 200ms;
414
634
  }
635
+ .duration-300 {
636
+ --tw-duration: 300ms;
637
+ transition-duration: 300ms;
638
+ }
639
+ .outline-none {
640
+ --tw-outline-style: none;
641
+ outline-style: none;
642
+ }
643
+ .group-\[\.submitPressed\]\:text-red-500\/50 {
644
+ &:is(:where(.group):is(.submitPressed) *) {
645
+ color: color-mix(in srgb, oklch(63.7% 0.237 25.331) 50%, transparent);
646
+ @supports (color: color-mix(in lab, red, red)) {
647
+ color: color-mix(in oklab, var(--color-red-500) 50%, transparent);
648
+ }
649
+ }
650
+ }
651
+ .peer-hover\:block {
652
+ &:is(:where(.peer):hover ~ *) {
653
+ @media (hover: hover) {
654
+ display: block;
655
+ }
656
+ }
657
+ }
658
+ .peer-focus\:top-2 {
659
+ &:is(:where(.peer):focus ~ *) {
660
+ top: calc(var(--spacing) * 2);
661
+ }
662
+ }
663
+ .peer-focus\:w-fit {
664
+ &:is(:where(.peer):focus ~ *) {
665
+ width: fit-content;
666
+ }
667
+ }
668
+ .peer-focus\:-translate-y-5 {
669
+ &:is(:where(.peer):focus ~ *) {
670
+ --tw-translate-y: calc(var(--spacing) * -5);
671
+ translate: var(--tw-translate-x) var(--tw-translate-y);
672
+ }
673
+ }
674
+ .peer-focus\:scale-75 {
675
+ &:is(:where(.peer):focus ~ *) {
676
+ --tw-scale-x: 75%;
677
+ --tw-scale-y: 75%;
678
+ --tw-scale-z: 75%;
679
+ scale: var(--tw-scale-x) var(--tw-scale-y);
680
+ }
681
+ }
682
+ .peer-focus\:px-2 {
683
+ &:is(:where(.peer):focus ~ *) {
684
+ padding-inline: calc(var(--spacing) * 2);
685
+ }
686
+ }
687
+ .after\:content-\[\"_\*\"\] {
688
+ &::after {
689
+ --tw-content: " *";
690
+ content: var(--tw-content);
691
+ }
692
+ }
693
+ .hover\:bg-login-600 {
694
+ &:hover {
695
+ @media (hover: hover) {
696
+ background-color: var(--color-login-600);
697
+ }
698
+ }
699
+ }
415
700
  .hover\:bg-login\/80 {
416
701
  &:hover {
417
702
  @media (hover: hover) {
@@ -422,6 +707,24 @@
422
707
  }
423
708
  }
424
709
  }
710
+ .hover\:text-red-800 {
711
+ &:hover {
712
+ @media (hover: hover) {
713
+ color: var(--color-red-800);
714
+ }
715
+ }
716
+ }
717
+ .focus\:border-login-50 {
718
+ &:focus {
719
+ border-color: var(--color-login-50);
720
+ }
721
+ }
722
+ .focus\:ring-0 {
723
+ &:focus {
724
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
725
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
726
+ }
727
+ }
425
728
  .focus\:outline-none {
426
729
  &:focus {
427
730
  --tw-outline-style: none;
@@ -480,6 +783,36 @@ body {
480
783
  background: var(--background);
481
784
  font-family: Arial, Helvetica, sans-serif;
482
785
  }
786
+ @property --tw-translate-x {
787
+ syntax: "*";
788
+ inherits: false;
789
+ initial-value: 0;
790
+ }
791
+ @property --tw-translate-y {
792
+ syntax: "*";
793
+ inherits: false;
794
+ initial-value: 0;
795
+ }
796
+ @property --tw-translate-z {
797
+ syntax: "*";
798
+ inherits: false;
799
+ initial-value: 0;
800
+ }
801
+ @property --tw-scale-x {
802
+ syntax: "*";
803
+ inherits: false;
804
+ initial-value: 1;
805
+ }
806
+ @property --tw-scale-y {
807
+ syntax: "*";
808
+ inherits: false;
809
+ initial-value: 1;
810
+ }
811
+ @property --tw-scale-z {
812
+ syntax: "*";
813
+ inherits: false;
814
+ initial-value: 1;
815
+ }
483
816
  @property --tw-rotate-x {
484
817
  syntax: "*";
485
818
  inherits: false;
@@ -500,6 +833,11 @@ body {
500
833
  syntax: "*";
501
834
  inherits: false;
502
835
  }
836
+ @property --tw-border-style {
837
+ syntax: "*";
838
+ inherits: false;
839
+ initial-value: solid;
840
+ }
503
841
  @property --tw-font-weight {
504
842
  syntax: "*";
505
843
  inherits: false;
@@ -508,21 +846,113 @@ body {
508
846
  syntax: "*";
509
847
  inherits: false;
510
848
  }
849
+ @property --tw-shadow {
850
+ syntax: "*";
851
+ inherits: false;
852
+ initial-value: 0 0 #0000;
853
+ }
854
+ @property --tw-shadow-color {
855
+ syntax: "*";
856
+ inherits: false;
857
+ }
858
+ @property --tw-shadow-alpha {
859
+ syntax: "<percentage>";
860
+ inherits: false;
861
+ initial-value: 100%;
862
+ }
863
+ @property --tw-inset-shadow {
864
+ syntax: "*";
865
+ inherits: false;
866
+ initial-value: 0 0 #0000;
867
+ }
868
+ @property --tw-inset-shadow-color {
869
+ syntax: "*";
870
+ inherits: false;
871
+ }
872
+ @property --tw-inset-shadow-alpha {
873
+ syntax: "<percentage>";
874
+ inherits: false;
875
+ initial-value: 100%;
876
+ }
877
+ @property --tw-ring-color {
878
+ syntax: "*";
879
+ inherits: false;
880
+ }
881
+ @property --tw-ring-shadow {
882
+ syntax: "*";
883
+ inherits: false;
884
+ initial-value: 0 0 #0000;
885
+ }
886
+ @property --tw-inset-ring-color {
887
+ syntax: "*";
888
+ inherits: false;
889
+ }
890
+ @property --tw-inset-ring-shadow {
891
+ syntax: "*";
892
+ inherits: false;
893
+ initial-value: 0 0 #0000;
894
+ }
895
+ @property --tw-ring-inset {
896
+ syntax: "*";
897
+ inherits: false;
898
+ }
899
+ @property --tw-ring-offset-width {
900
+ syntax: "<length>";
901
+ inherits: false;
902
+ initial-value: 0px;
903
+ }
904
+ @property --tw-ring-offset-color {
905
+ syntax: "*";
906
+ inherits: false;
907
+ initial-value: #fff;
908
+ }
909
+ @property --tw-ring-offset-shadow {
910
+ syntax: "*";
911
+ inherits: false;
912
+ initial-value: 0 0 #0000;
913
+ }
511
914
  @property --tw-duration {
512
915
  syntax: "*";
513
916
  inherits: false;
514
917
  }
918
+ @property --tw-content {
919
+ syntax: "*";
920
+ initial-value: "";
921
+ inherits: false;
922
+ }
515
923
  @layer properties {
516
924
  @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
517
925
  *, ::before, ::after, ::backdrop {
926
+ --tw-translate-x: 0;
927
+ --tw-translate-y: 0;
928
+ --tw-translate-z: 0;
929
+ --tw-scale-x: 1;
930
+ --tw-scale-y: 1;
931
+ --tw-scale-z: 1;
518
932
  --tw-rotate-x: initial;
519
933
  --tw-rotate-y: initial;
520
934
  --tw-rotate-z: initial;
521
935
  --tw-skew-x: initial;
522
936
  --tw-skew-y: initial;
937
+ --tw-border-style: solid;
523
938
  --tw-font-weight: initial;
524
939
  --tw-tracking: initial;
940
+ --tw-shadow: 0 0 #0000;
941
+ --tw-shadow-color: initial;
942
+ --tw-shadow-alpha: 100%;
943
+ --tw-inset-shadow: 0 0 #0000;
944
+ --tw-inset-shadow-color: initial;
945
+ --tw-inset-shadow-alpha: 100%;
946
+ --tw-ring-color: initial;
947
+ --tw-ring-shadow: 0 0 #0000;
948
+ --tw-inset-ring-color: initial;
949
+ --tw-inset-ring-shadow: 0 0 #0000;
950
+ --tw-ring-inset: initial;
951
+ --tw-ring-offset-width: 0px;
952
+ --tw-ring-offset-color: #fff;
953
+ --tw-ring-offset-shadow: 0 0 #0000;
525
954
  --tw-duration: initial;
955
+ --tw-content: "";
526
956
  }
527
957
  }
528
958
  }
@@ -1,2 +1,5 @@
1
1
  export { default as LoginPage } from './login/loginPage';
2
2
  export { default as Toaster, addToast } from './toast/toaster';
3
+ export { default as Input } from './inputs/input';
4
+ export { default as SwitchInput } from './inputs/switch';
5
+ export { default as TagInput } from './inputs/tag';
@@ -1,2 +1,6 @@
1
1
  export { default as LoginPage } from './login/loginPage';
2
2
  export { default as Toaster, addToast } from './toast/toaster';
3
+ // Input components
4
+ export { default as Input } from './inputs/input';
5
+ export { default as SwitchInput } from './inputs/switch';
6
+ export { default as TagInput } from './inputs/tag';
@@ -0,0 +1,3 @@
1
+ export default function EraseButton({ setData }: {
2
+ setData: (data: string) => void;
3
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Eraser } from 'lucide-react';
3
+ export default function EraseButton({ setData }) {
4
+ return (_jsx("button", { type: 'button', onClick: () => setData(''), className: 'absolute right-1 cursor-pointer px-2 py-1 bg-login-800 hover:bg-login-600 rounded-md', children: _jsx(Eraser, { className: 'w-5' }) }));
5
+ }
@@ -0,0 +1,14 @@
1
+ import { HTMLInputTypeAttribute } from 'react';
2
+ type InputProps = {
3
+ name: string;
4
+ type: HTMLInputTypeAttribute;
5
+ label: string;
6
+ value?: string | number;
7
+ setValue: (value: string | number) => void;
8
+ className?: string;
9
+ tooltip?: string;
10
+ required?: boolean;
11
+ color?: string;
12
+ };
13
+ export default function Input({ name, type, label, className, tooltip, required, value, setValue, color }: InputProps): import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import ToolTip from './tooltip';
5
+ import Label from './label';
6
+ import EraseButton from './erase';
7
+ export default function Input({ name, type, label, className, tooltip, required, value, setValue, color }) {
8
+ const [hasBlured, setHasBlured] = useState(false);
9
+ return (_jsx("div", { className: `w-full ${className}`, children: _jsxs("div", { className: 'relative flex items-center', children: [_jsx("input", { name: name, type: type, className: 'block bg-login-800 px-2.5 pb-2.5 pt-4 w-full text-sm rounded-lg border-[0.10rem] appearance-none ' +
10
+ 'border-login-200 focus:outline-none focus:ring-0 focus:border-login-50 peer', value: value || '', onChange: (e) => setValue(e.target.value), onFocus: (e) => e.target.showPicker(), onBlur: () => setHasBlured(true), placeholder: '', required: required }), _jsx(Label, { label: label, value: value, required: required, color: color, showRequired: required && !value && hasBlured }), value && _jsx(EraseButton, { setData: setValue }), !value && tooltip && _jsx(ToolTip, { info: tooltip })] }) }));
11
+ }
@@ -0,0 +1,10 @@
1
+ type labelProps = {
2
+ label: string;
3
+ value: any;
4
+ required?: boolean;
5
+ showRequired?: boolean;
6
+ className?: string;
7
+ color?: string;
8
+ };
9
+ export default function Label({ label, value, required, showRequired, className, color }: labelProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ export default function Label({ label, value, required, showRequired, className, color }) {
3
+ return (_jsx("label", { className: 'w-[calc(100%-10px)] truncate pointer-events-none absolute text-sm duration-300 transform z-10 ' +
4
+ 'peer-focus:px-2 peer-focus:top-2 origin-[0] px-2 pt-1 peer-focus:scale-75 peer-focus:-translate-y-5 start-2 ' +
5
+ `${color ? color : 'bg-login-800'} ` +
6
+ `${value ? '-translate-y-5 scale-75 top-2 w-fit '
7
+ : '-translate-y-1/2 scale-100 top-1/2 '
8
+ + 'peer-focus:w-fit '} ${showRequired ? 'text-red-500/50 ' : ''}
9
+ ${!value &&
10
+ required ? 'group-[.submitPressed]:text-red-500/50 ' : ''}
11
+ ${required ? 'after:content-["_*"] ' : ''}
12
+ ${className}`, children: label }));
13
+ }
@@ -0,0 +1,10 @@
1
+ type SwitchProps = {
2
+ name: string;
3
+ label: string;
4
+ value?: boolean;
5
+ setValue: (_: boolean) => void;
6
+ className?: string;
7
+ tooltip?: string;
8
+ };
9
+ export default function Switch({ name, label, value, className, tooltip, setValue }: SwitchProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,7 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import ToolTip from './tooltip';
4
+ export default function Switch({ name, label, value, className, tooltip, setValue }) {
5
+ return (_jsxs("div", { className: `relative w-full flex items-center px-2.5 pb-2.5 pt-3 border-login-200 rounded-lg border-[0.10rem]
6
+ bg-login-800 ${className}`, children: [_jsxs("label", { className: 'flex items-center cursor-pointer', children: [_jsx("input", { type: 'checkbox', name: name, className: 'sr-only', checked: value, onChange: (e) => setValue(e.target.checked) }), _jsx("div", { className: `w-10 h-6 rounded-full p-1 transition ${value ? 'bg-login-50' : 'bg-login-200'}`, children: _jsx("div", { className: `w-4 h-4 bg-login-800 rounded-full shadow-md transform transition ${value ? 'translate-x-4' : ''}` }) })] }), _jsx("span", { className: 'ml-3 text-sm', children: label }), tooltip && _jsx(ToolTip, { info: tooltip })] }));
7
+ }
@@ -0,0 +1,11 @@
1
+ type TagInputProps = {
2
+ name: string;
3
+ label: string;
4
+ value?: string[];
5
+ setValue: (_: string[]) => void;
6
+ className?: string;
7
+ tooltip?: string;
8
+ required?: boolean;
9
+ };
10
+ export default function TagInput({ name, label, value, className, tooltip, required, setValue, }: TagInputProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState } from 'react';
4
+ import ToolTip from './tooltip';
5
+ import Label from './label';
6
+ import EraseButton from './erase';
7
+ import { X } from 'lucide-react';
8
+ export default function TagInput({ name, label, value = [], className, tooltip, required, setValue, }) {
9
+ const original = value;
10
+ const [input, setInput] = useState('');
11
+ const [hasBlured, setHasBlured] = useState(false);
12
+ function addTag(value) {
13
+ const trimmed = value.trim();
14
+ if (trimmed && !value.includes(trimmed)) {
15
+ setValue([...value, trimmed]);
16
+ }
17
+ }
18
+ function removeTag(idx) {
19
+ setValue(value.filter((_, i) => i !== idx));
20
+ }
21
+ function handleKeyDown(e) {
22
+ if ((e.key === 'Enter' || e.key === ',' || e.key === 'Tab') &&
23
+ input.trim()) {
24
+ e.preventDefault();
25
+ addTag(input);
26
+ setInput('');
27
+ }
28
+ if (e.key === 'Backspace' && !input && value.length) {
29
+ setValue(value.slice(0, -1));
30
+ }
31
+ }
32
+ function handleErase() {
33
+ setValue([]);
34
+ setInput('');
35
+ }
36
+ const toRemove = original.filter((tag) => !value.includes(tag));
37
+ const toAdd = value.filter((tag) => !original.includes(tag));
38
+ return (_jsx("div", { className: `w-full ${className}`, children: _jsxs("div", { className: 'relative flex items-center flex-wrap gap-1 ' +
39
+ 'border-[0.10rem] border-login-200 ' +
40
+ 'rounded-lg ' +
41
+ 'px-2.5 pt-3 pb-2.5 bg-login-800', children: [_jsxs("div", { className: 'flex flex-wrap gap-1 items-center w-full', children: [value.map((tag, idx) => (_jsxs("span", { className: 'bg-login-600 text-sm rounded px-2 ' +
42
+ 'py-0.5 flex items-center gap-0.5', children: [tag, _jsx("button", { type: 'button', className: 'ml-1 text-red-700 hover:text-red-800', onClick: () => removeTag(idx), children: _jsx(X, { className: 'h-4 stroke-3' }) })] }, tag + idx))), _jsx("input", { value: input, onChange: (e) => setInput(e.target.value), onKeyDown: handleKeyDown, onBlur: () => setHasBlured(true), className: 'peer flex-1 min-w-[6ch] bg-transparent ' +
43
+ 'outline-none text-sm', autoComplete: 'off', required: required && value.length === 0 }), toRemove.map((tag) => (_jsx("input", { type: 'hidden', name: name + '_remove', value: tag }, tag))), toAdd.map((tag) => (_jsx("input", { type: 'hidden', name: name + '_add', value: tag }, tag))), _jsx(Label, { label: label, value: value.length ? value.join(', ') : '', required: required, showRequired: required && value.length === 0 && hasBlured, className: 'pointer-events-none left-2' })] }), value.length > 0 && _jsx(EraseButton, { setData: handleErase }), value.length === 0 && tooltip && _jsx(ToolTip, { info: tooltip })] }) }));
44
+ }
@@ -0,0 +1,4 @@
1
+ export default function ToolTip({ info, className }: {
2
+ info: string;
3
+ className?: string;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export default function ToolTip({ info, className }) {
3
+ return (_jsxs("div", { className: `absolute z-19 right-0 px-1 flex justify-center ${className}`, children: [_jsx("span", { className: 'peer cursor-pointer rounded-sm px-3 py-1 bg-login-800 hover:bg-login-600', children: "?" }), _jsx("div", { className: 'absolute hidden peer-hover:block p-2 rounded z-20 bg-login-700 border left-12 w-max max-w-3xs', children: info })] }));
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uibee",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Shared components, functions and hooks for reuse across Login projects",
5
5
  "homepage": "https://github.com/Login-Linjeforening-for-IT/uibee#readme",
6
6
  "bugs": {
@@ -1,2 +1,7 @@
1
1
  export { default as LoginPage } from './login/loginPage'
2
- export { default as Toaster, addToast } from './toast/toaster'
2
+ export { default as Toaster, addToast } from './toast/toaster'
3
+
4
+ // Input components
5
+ export { default as Input } from './inputs/input'
6
+ export { default as SwitchInput } from './inputs/switch'
7
+ export { default as TagInput } from './inputs/tag'
@@ -0,0 +1,13 @@
1
+ import { Eraser } from 'lucide-react'
2
+
3
+ export default function EraseButton({ setData }: { setData: (data: string) => void }) {
4
+ return (
5
+ <button
6
+ type='button'
7
+ onClick={() => setData('')}
8
+ className={'absolute right-1 cursor-pointer px-2 py-1 bg-login-800 hover:bg-login-600 rounded-md'}
9
+ >
10
+ <Eraser className='w-5' />
11
+ </button>
12
+ )
13
+ }
@@ -0,0 +1,52 @@
1
+ 'use client'
2
+
3
+ import { HTMLInputTypeAttribute, useState } from 'react'
4
+ import ToolTip from './tooltip'
5
+ import Label from './label'
6
+ import EraseButton from './erase'
7
+
8
+ type InputProps = {
9
+ name: string
10
+ type: HTMLInputTypeAttribute
11
+ label: string
12
+ value?: string | number
13
+ setValue: (value: string | number) => void
14
+ className?: string
15
+ tooltip?: string
16
+ required?: boolean
17
+ color?: string
18
+ }
19
+
20
+ export default function Input({ name, type, label, className, tooltip, required, value, setValue, color }: InputProps) {
21
+ const [hasBlured, setHasBlured] = useState(false)
22
+
23
+ return (
24
+ <div className={`w-full ${className}`}>
25
+ <div className='relative flex items-center'>
26
+ <input
27
+ name={name}
28
+ type={type}
29
+ className={
30
+ 'block bg-login-800 px-2.5 pb-2.5 pt-4 w-full text-sm rounded-lg border-[0.10rem] appearance-none ' +
31
+ 'border-login-200 focus:outline-none focus:ring-0 focus:border-login-50 peer'
32
+ }
33
+ value={value || ''}
34
+ onChange={(e) => setValue(e.target.value)}
35
+ onFocus={(e) => e.target.showPicker()}
36
+ onBlur={() => setHasBlured(true)}
37
+ placeholder=''
38
+ required={required}
39
+ />
40
+ <Label
41
+ label={label}
42
+ value={value}
43
+ required={required}
44
+ color={color}
45
+ showRequired={required && !value && hasBlured}
46
+ />
47
+ {value && <EraseButton setData={setValue} />}
48
+ {!value && tooltip && <ToolTip info={tooltip} />}
49
+ </div>
50
+ </div>
51
+ )
52
+ }
@@ -0,0 +1,31 @@
1
+ type labelProps = {
2
+ label: string
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ value: any
5
+ required?: boolean
6
+ showRequired?: boolean
7
+ className?: string
8
+ color?: string
9
+ }
10
+
11
+ export default function Label({ label, value, required, showRequired, className, color }: labelProps) {
12
+ return (
13
+ <label
14
+ className={
15
+ 'w-[calc(100%-10px)] truncate pointer-events-none absolute text-sm duration-300 transform z-10 ' +
16
+ 'peer-focus:px-2 peer-focus:top-2 origin-[0] px-2 pt-1 peer-focus:scale-75 peer-focus:-translate-y-5 start-2 ' +
17
+ `${color ? color : 'bg-login-800'} ` +
18
+ `${value ? '-translate-y-5 scale-75 top-2 w-fit '
19
+ : '-translate-y-1/2 scale-100 top-1/2 '
20
+ + 'peer-focus:w-fit '
21
+ } ${showRequired ? 'text-red-500/50 ' : ''}
22
+ ${!value &&
23
+ required ? 'group-[.submitPressed]:text-red-500/50 ' : ''}
24
+ ${required ? 'after:content-["_*"] ' : ''}
25
+ ${className}`
26
+ }
27
+ >
28
+ {label}
29
+ </label>
30
+ )
31
+ }
@@ -0,0 +1,39 @@
1
+ 'use client'
2
+
3
+ import ToolTip from './tooltip'
4
+
5
+ type SwitchProps = {
6
+ name: string
7
+ label: string
8
+ value?: boolean
9
+ setValue: (_: boolean) => void
10
+ className?: string
11
+ tooltip?: string
12
+ }
13
+
14
+ export default function Switch({ name, label, value, className, tooltip, setValue }: SwitchProps) {
15
+ return (
16
+ <div className={`relative w-full flex items-center px-2.5 pb-2.5 pt-3 border-login-200 rounded-lg border-[0.10rem]
17
+ bg-login-800 ${className}`}
18
+ >
19
+ <label className='flex items-center cursor-pointer'>
20
+ <input
21
+ type='checkbox'
22
+ name={name}
23
+ className='sr-only'
24
+ checked={value}
25
+ onChange={(e) => setValue(e.target.checked)}
26
+ />
27
+ <div className={`w-10 h-6 rounded-full p-1 transition ${value ? 'bg-login-50' : 'bg-login-200'}`}>
28
+ <div
29
+ className={`w-4 h-4 bg-login-800 rounded-full shadow-md transform transition ${value ? 'translate-x-4' : ''}`}
30
+ />
31
+ </div>
32
+ </label>
33
+ <span className='ml-3 text-sm'>
34
+ {label}
35
+ </span>
36
+ {tooltip && <ToolTip info={tooltip} />}
37
+ </div>
38
+ )
39
+ }
@@ -0,0 +1,137 @@
1
+ 'use client'
2
+
3
+ import { useState, KeyboardEvent } from 'react'
4
+ import ToolTip from './tooltip'
5
+ import Label from './label'
6
+ import EraseButton from './erase'
7
+ import { X } from 'lucide-react'
8
+
9
+ type TagInputProps = {
10
+ name: string
11
+ label: string
12
+ value?: string[]
13
+ setValue: (_: string[]) => void
14
+ className?: string
15
+ tooltip?: string
16
+ required?: boolean
17
+ }
18
+
19
+ export default function TagInput({
20
+ name,
21
+ label,
22
+ value = [],
23
+ className,
24
+ tooltip,
25
+ required,
26
+ setValue,
27
+ }: TagInputProps) {
28
+ const original = value
29
+ const [input, setInput] = useState('')
30
+ const [hasBlured, setHasBlured] = useState(false)
31
+
32
+ function addTag(value: string) {
33
+ const trimmed = value.trim()
34
+ if (trimmed && !value.includes(trimmed)) {
35
+ setValue([...value, trimmed])
36
+ }
37
+ }
38
+
39
+ function removeTag(idx: number) {
40
+ setValue(value.filter((_, i) => i !== idx))
41
+ }
42
+
43
+ function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {
44
+ if (
45
+ (e.key === 'Enter' || e.key === ',' || e.key === 'Tab') &&
46
+ input.trim()
47
+ ) {
48
+ e.preventDefault()
49
+ addTag(input)
50
+ setInput('')
51
+ }
52
+ if (e.key === 'Backspace' && !input && value.length) {
53
+ setValue(value.slice(0, -1))
54
+ }
55
+ }
56
+
57
+ function handleErase() {
58
+ setValue([])
59
+ setInput('')
60
+ }
61
+
62
+ const toRemove = original.filter((tag: string) => !value.includes(tag))
63
+ const toAdd = value.filter((tag: string) => !original.includes(tag))
64
+
65
+ return (
66
+ <div className={`w-full ${className}`}>
67
+ <div
68
+ className={
69
+ 'relative flex items-center flex-wrap gap-1 ' +
70
+ 'border-[0.10rem] border-login-200 ' +
71
+ 'rounded-lg ' +
72
+ 'px-2.5 pt-3 pb-2.5 bg-login-800'
73
+ }
74
+ >
75
+ <div className='flex flex-wrap gap-1 items-center w-full'>
76
+ {value.map((tag, idx) => (
77
+ <span
78
+ key={tag + idx}
79
+ className={
80
+ 'bg-login-600 text-sm rounded px-2 ' +
81
+ 'py-0.5 flex items-center gap-0.5'
82
+ }
83
+ >
84
+ {tag}
85
+ <button
86
+ type='button'
87
+ className='ml-1 text-red-700 hover:text-red-800'
88
+ onClick={() => removeTag(idx)}
89
+ >
90
+ <X className='h-4 stroke-3' />
91
+ </button>
92
+ </span>
93
+ ))}
94
+ <input
95
+ value={input}
96
+ onChange={(e) => setInput(e.target.value)}
97
+ onKeyDown={handleKeyDown}
98
+ onBlur={() => setHasBlured(true)}
99
+ className={
100
+ 'peer flex-1 min-w-[6ch] bg-transparent ' +
101
+ 'outline-none text-sm'
102
+ }
103
+ autoComplete='off'
104
+ required={required && value.length === 0}
105
+ />
106
+ {toRemove.map((tag) => (
107
+ <input
108
+ key={tag}
109
+ type='hidden'
110
+ name={name + '_remove'}
111
+ value={tag}
112
+ />
113
+ ))}
114
+ {toAdd.map((tag) => (
115
+ <input
116
+ key={tag}
117
+ type='hidden'
118
+ name={name + '_add'}
119
+ value={tag}
120
+ />
121
+ ))}
122
+ <Label
123
+ label={label}
124
+ value={value.length ? value.join(', ') : ''}
125
+ required={required}
126
+ showRequired={
127
+ required && value.length === 0 && hasBlured
128
+ }
129
+ className='pointer-events-none left-2'
130
+ />
131
+ </div>
132
+ {value.length > 0 && <EraseButton setData={handleErase} />}
133
+ {value.length === 0 && tooltip && <ToolTip info={tooltip} />}
134
+ </div>
135
+ </div>
136
+ )
137
+ }
@@ -0,0 +1,12 @@
1
+ export default function ToolTip({ info, className }: { info: string; className?: string }) {
2
+ return (
3
+ <div className={`absolute z-19 right-0 px-1 flex justify-center ${className}`}>
4
+ <span className={'peer cursor-pointer rounded-sm px-3 py-1 bg-login-800 hover:bg-login-600'}>
5
+ ?
6
+ </span>
7
+ <div className={'absolute hidden peer-hover:block p-2 rounded z-20 bg-login-700 border left-12 w-max max-w-3xs'}>
8
+ {info}
9
+ </div>
10
+ </div>
11
+ )
12
+ }