@monolith-forensics/monolith-ui 1.1.0 → 1.1.2

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 (66) hide show
  1. package/package.json +4 -1
  2. package/Button/Button.tsx +0 -382
  3. package/Button/index.ts +0 -2
  4. package/Calendar/Calendar.tsx +0 -376
  5. package/Calendar/CalendarStyles.tsx +0 -180
  6. package/Calendar/calendarHelpers.ts +0 -196
  7. package/Calendar/index.ts +0 -1
  8. package/CheckBox/CheckBox.tsx +0 -61
  9. package/CheckBox/index.ts +0 -1
  10. package/DateInput/DateInput.tsx +0 -717
  11. package/DateInput/index.ts +0 -1
  12. package/DropDownMenu/DropDownMenu.tsx +0 -402
  13. package/DropDownMenu/index.ts +0 -1
  14. package/Error/Error.tsx +0 -51
  15. package/Error/index.ts +0 -1
  16. package/FieldLabel/FieldLabel.tsx +0 -155
  17. package/FieldLabel/index.ts +0 -1
  18. package/FileInputField/FileInputField.tsx +0 -179
  19. package/FileInputField/index.ts +0 -1
  20. package/Flyout/Flyout.tsx +0 -172
  21. package/Flyout/FlyoutHeader.tsx +0 -14
  22. package/Flyout/FlyoutTitle.tsx +0 -10
  23. package/Flyout/index.ts +0 -3
  24. package/FormSection/FormSection.tsx +0 -71
  25. package/FormSection/index.ts +0 -1
  26. package/Grid/Grid.tsx +0 -18
  27. package/Grid/index.ts +0 -1
  28. package/IconButton/IconButton.tsx +0 -27
  29. package/IconButton/index.ts +0 -1
  30. package/Input/Input.tsx +0 -164
  31. package/Input/index.ts +0 -1
  32. package/Modal/Modal.tsx +0 -172
  33. package/Modal/index.ts +0 -1
  34. package/Pill/Pill.tsx +0 -174
  35. package/Pill/index.ts +0 -1
  36. package/SelectBox/SelectBox.tsx +0 -745
  37. package/SelectBox/index.ts +0 -1
  38. package/Switch/Switch.tsx +0 -204
  39. package/Switch/index.ts +0 -1
  40. package/TagBox/TagBox.tsx +0 -694
  41. package/TagBox/TagBoxStyles.tsx +0 -116
  42. package/TagBox/index.ts +0 -1
  43. package/TextArea/TextArea.tsx +0 -92
  44. package/TextArea/index.ts +0 -1
  45. package/TextAreaInput/TextAreaInput.tsx +0 -46
  46. package/TextAreaInput/index.ts +0 -1
  47. package/TextInput/TextInput.tsx +0 -48
  48. package/TextInput/index.ts +0 -1
  49. package/Tooltip/Tooltip.tsx +0 -68
  50. package/Tooltip/index.ts +0 -1
  51. package/core/ArrowButton.tsx +0 -51
  52. package/core/ClearButton.tsx +0 -51
  53. package/core/MonolithThemeProvider.js +0 -16
  54. package/core/StyledContent.tsx +0 -50
  55. package/core/StyledFloatContainer.tsx +0 -7
  56. package/core/Types/Size.ts +0 -3
  57. package/core/Types/Variant.ts +0 -10
  58. package/core/index.ts +0 -6
  59. package/index.ts +0 -22
  60. package/theme/breakpoints.js +0 -11
  61. package/theme/components.js +0 -138
  62. package/theme/index.js +0 -76
  63. package/theme/shadows.js +0 -33
  64. package/theme/typography.js +0 -58
  65. package/theme/variants.js +0 -234
  66. package/tsconfig.json +0 -109
package/TagBox/TagBox.tsx DELETED
@@ -1,694 +0,0 @@
1
- import styled from "styled-components";
2
- import { useFloating, flip, offset } from "@floating-ui/react";
3
- import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
4
- import { Input, Tooltip, FieldLabel, Pill } from "..";
5
-
6
- import {
7
- ArrowButton,
8
- ClearButton,
9
- StyledFloatContainer,
10
- StyledContent,
11
- Variant,
12
- Size,
13
- } from "../core";
14
-
15
- const StyledInputContainer = styled.div<{
16
- variant?: Variant;
17
- size?: Size;
18
- }>`
19
- position: relative;
20
- cursor: pointer;
21
-
22
- user-select: none;
23
-
24
- display: flex;
25
- flex-direction: row;
26
- align-items: center;
27
- user-select: none;
28
-
29
- pointer-events: all;
30
- outline: none;
31
-
32
- border-radius: 5px;
33
- transition: border 0.1s ease-in-out;
34
- border: 1px solid
35
- ${({ theme, variant }) => {
36
- switch (variant) {
37
- case "filled":
38
- return "transparent";
39
- case "outlined":
40
- return theme.palette.input.border;
41
- case "text":
42
- return "transparent";
43
- default:
44
- return theme.palette.input.border;
45
- }
46
- }};
47
- font-weight: 500;
48
- color: ${(props) => props.theme.palette.text.primary};
49
- font-size: ${({ size }) =>
50
- size === "xs"
51
- ? "12px"
52
- : size === "sm"
53
- ? "14px"
54
- : size === "md"
55
- ? "16px"
56
- : size === "lg"
57
- ? "18px"
58
- : size === "xl"
59
- ? "20px"
60
- : "12px"};
61
-
62
- width: 100%;
63
- min-height: ${({ size }) =>
64
- size === "xs"
65
- ? "26px"
66
- : size === "sm"
67
- ? "30px"
68
- : size === "md"
69
- ? "36px"
70
- : size === "lg"
71
- ? "42px"
72
- : size === "xl"
73
- ? "50px"
74
- : "26px"};
75
-
76
- &[data-button-right="true"] {
77
- padding-right: 36px;
78
- }
79
-
80
- background-color: ${({ theme, variant }) => {
81
- switch (variant) {
82
- case "filled":
83
- return theme.palette.input.background;
84
- case "outlined":
85
- return theme.palette.input.background;
86
- case "text":
87
- return "transparent";
88
- default:
89
- return theme.palette.input.background;
90
- }
91
- }};
92
-
93
- &[readOnly] {
94
- cursor: pointer;
95
- }
96
-
97
- & [data-has-space="true"] {
98
- padding-left: 4px;
99
- }
100
-
101
- & [data-selected="true"] {
102
- background-color: ${(props) => props.theme.palette.primary.main}50;
103
- }
104
-
105
- &[data-empty="true"] {
106
- color: ${(props) => props.theme.palette.input.placeholder};
107
- div {
108
- color: ${(props) => props.theme.palette.input.placeholder};
109
- }
110
- }
111
-
112
- & [data-default-btn="true"] {
113
- color: ${(props) => props.theme.palette.text.secondary};
114
- div {
115
- color: ${(props) => props.theme.palette.text.secondary};
116
- }
117
- }
118
-
119
- &[data-open="true"] {
120
- border: 1px solid ${(props) => props.theme.palette.primary.main};
121
- }
122
-
123
- &:focus-within {
124
- border: 1px solid ${(props) => props.theme.palette.primary.main};
125
- }
126
-
127
- &:focus {
128
- border: 1px solid ${(props) => props.theme.palette.primary.main};
129
- }
130
- `;
131
-
132
- interface StyledInputProps {
133
- className?: string;
134
- inputRef: React.RefObject<HTMLInputElement>;
135
- [key: string]: React.InputHTMLAttributes<HTMLInputElement> | any;
136
- }
137
-
138
- // styled input with forwardRef
139
- const StyledInput = styled(
140
- ({ className, inputRef, ...props }: StyledInputProps) => {
141
- return (
142
- <Input
143
- ref={inputRef}
144
- className={className + " mfTagBox-input"}
145
- {...props}
146
- />
147
- );
148
- }
149
- )`
150
- &.mfTagBox-input {
151
- pointer-events: all;
152
- outline: none;
153
- background: transparent;
154
- flex: 1;
155
- appearance: none;
156
- border: 0;
157
- color: inherit;
158
-
159
- height: 100%;
160
- width: 100%;
161
-
162
- &:focus {
163
- border: 0;
164
- }
165
- }
166
- `;
167
-
168
- interface GroupTitleProps {
169
- className?: string;
170
- children?: ReactNode;
171
- size?: Size;
172
- }
173
-
174
- const GroupTitle = styled(
175
- ({ className, children, ...props }: GroupTitleProps) => {
176
- return (
177
- <div className={className} {...props}>
178
- <div className="group-line"></div>
179
- <div className="group-label">{children}</div>
180
- <div className="group-line"></div>
181
- </div>
182
- );
183
- }
184
- )`
185
- display: flex;
186
- flex-direction: row;
187
- align-items: center;
188
- justify-content: space-between;
189
- gap: 10px;
190
-
191
- color: ${(props) => props.theme.palette.text.secondary};
192
-
193
- padding: ${({ size }) =>
194
- size === "xs"
195
- ? "2px 8px"
196
- : size === "sm"
197
- ? "4px 10px"
198
- : size === "md"
199
- ? "4px 12px"
200
- : size === "lg"
201
- ? "5px 14px"
202
- : size === "xl"
203
- ? "6px 16px"
204
- : "2px 8px"};
205
-
206
- .group-label {
207
- white-space: nowrap;
208
- overflow: hidden;
209
- text-overflow: ellipsis;
210
- width: fit-content;
211
- min-width: fit-content;
212
-
213
- font-weight: 500;
214
-
215
- font-size: ${({ size }) =>
216
- size === "xs"
217
- ? "11px"
218
- : size === "sm"
219
- ? "13px"
220
- : size === "md"
221
- ? "15px"
222
- : size === "lg"
223
- ? "17px"
224
- : size === "xl"
225
- ? "19px"
226
- : "11px"};
227
- }
228
-
229
- .group-line {
230
- border-top: 1px solid ${(props) => props.theme.palette.divider};
231
- width: 100%;
232
- }
233
- `;
234
-
235
- const PillContainer = styled.div<{
236
- size?: Size;
237
- }>`
238
- display: flex;
239
- align-items: center;
240
- gap: 5px;
241
- flex-wrap: wrap;
242
- flex-grow: 1;
243
-
244
- padding: ${({ size }) =>
245
- size === "xs"
246
- ? "0px 8px"
247
- : size === "sm"
248
- ? "0px 10px"
249
- : size === "md"
250
- ? "0px 12px"
251
- : size === "lg"
252
- ? "0px 14px"
253
- : size === "xl"
254
- ? "0px 16px"
255
- : "0px 8px"};
256
-
257
- padding-top: 5px;
258
-
259
- &[data-empty="true"] {
260
- display: none;
261
- }
262
- `;
263
-
264
- const StyledInnerContainer = styled.div`
265
- display: flex;
266
- flex-direction: column;
267
- width: 100%;
268
-
269
- &[data-button-right="true"] {
270
- padding-right: 30px;
271
- }
272
- `;
273
-
274
- const ExtendedStyledContent = styled(StyledContent)`
275
- overflow-y: auto;
276
- `;
277
-
278
- const StyledItem = styled.div<{
279
- size?: Size;
280
- }>`
281
- line-height: 1;
282
- color: ${(props) => props.theme.palette.text.primary};
283
- border-radius: 3px;
284
- display: flex;
285
- align-items: center;
286
- min-height: 25px;
287
- padding: 7px 10px;
288
- position: relative;
289
- user-select: none;
290
- outline: none;
291
-
292
- cursor: pointer;
293
-
294
- font-family: "Arial", sans-serif;
295
- font-size: ${({ size }) =>
296
- size === "xs"
297
- ? "11px"
298
- : size === "sm"
299
- ? "13px"
300
- : size === "md"
301
- ? "15px"
302
- : size === "lg"
303
- ? "17px"
304
- : size === "xl"
305
- ? "19px"
306
- : "11px"};
307
-
308
- &[data-disabled] {
309
- color: ${(props) => props.theme.palette.text.secondary};
310
- pointer-events: "none";
311
- }
312
-
313
- &:hover {
314
- background-color: ${(props) => props.theme.palette.action.hover};
315
- color: ${(props) => props.theme.palette.text.primary};
316
- }
317
-
318
- &[data-selected="true"] {
319
- display: none;
320
- color: ${(props) => props.theme.palette.primary.main};
321
- }
322
- `;
323
-
324
- type Option = {
325
- label: string;
326
- value: any;
327
- group?: string;
328
- data: any;
329
- };
330
-
331
- interface TagBoxProps {
332
- className?: string;
333
- data?: Option[];
334
- placeholder?: string;
335
- arrow?: boolean;
336
- defaultValue?: Option[];
337
- grouped?: boolean;
338
- searchFn?: (value: string) => void;
339
- onChange?: (value: any[]) => void;
340
- onScroll?: () => void;
341
- onSearch?: (value: string) => void;
342
- onItemAdded?: (value: any) => void;
343
- size?: Size;
344
- variant?: Variant;
345
- width?: string;
346
- allowCustomValue?: boolean;
347
- searchable?: boolean;
348
- clearable?: boolean;
349
- label?: string;
350
- description?: string;
351
- required?: boolean;
352
- error?: string;
353
- loading?: boolean;
354
- renderOption?: (item: Option | string) => ReactNode;
355
- TooltipContent?: (props: { data: any }) => JSX.Element;
356
- }
357
-
358
- const TagBox = styled(
359
- ({
360
- className,
361
- data = [],
362
- placeholder = "Select or enter tags",
363
- arrow = true,
364
- defaultValue = [],
365
- grouped,
366
- searchFn,
367
- onChange,
368
- onScroll,
369
- onSearch,
370
- onItemAdded,
371
- size = "sm",
372
- variant = "filled",
373
- width = "100%",
374
- allowCustomValue = true,
375
- searchable = false,
376
- clearable = false,
377
- label,
378
- description,
379
- required = false,
380
- error,
381
- loading = false,
382
- renderOption,
383
- TooltipContent,
384
- }: TagBoxProps) => {
385
- const isObjectArray = data.length > 0 && data[0]?.label !== undefined;
386
-
387
- const [isOpen, setIsOpen] = useState(false);
388
- const [selectedItems, setSelectedItems] =
389
- useState<(Option | string)[]>(defaultValue);
390
-
391
- const [searchValue, setSearchValue] = useState("");
392
- const inputRef = useRef<HTMLInputElement>(null);
393
- const scrollContainerRef = useRef(null);
394
-
395
- const filteredItems = data
396
- .filter((item: Option | string) => {
397
- const itemValue = (
398
- isObjectArray ? (item as Option).label : item
399
- ) as string;
400
-
401
- return itemValue.toLowerCase().includes(searchValue.toLowerCase());
402
- })
403
- .sort((a, b) => {
404
- if (grouped) {
405
- const aValue = (a as Option).group as string;
406
- const bValue = (b as Option).group as string;
407
- return aValue.localeCompare(bValue);
408
- }
409
- // return current sort order
410
- return 0;
411
- });
412
-
413
- const groupedItems = grouped
414
- ? filteredItems.reduce((acc: any, item: any) => {
415
- if (!item.group) {
416
- item.group = "Other";
417
- }
418
- if (acc[item.group]) {
419
- acc[item.group].push(item);
420
- } else {
421
- acc[item.group] = [item];
422
- }
423
- return acc;
424
- }, {})
425
- : {};
426
-
427
- const groups = grouped
428
- ? Object.keys(groupedItems)
429
- .map((group) => ({
430
- label: group,
431
- items: groupedItems[group],
432
- }))
433
- .sort((a, b) => a.label.localeCompare(b.label))
434
- : [];
435
-
436
- const { refs, floatingStyles, update } = useFloating({
437
- open: isOpen,
438
- onOpenChange: setIsOpen,
439
- placement: "bottom-start",
440
- strategy: "absolute",
441
- // Handle collisions with the viewport
442
- middleware: [flip(), offset(5)],
443
- });
444
-
445
- const toggleOpen = () => {
446
- setIsOpen((prev) => {
447
- if (!prev) {
448
- if (inputRef.current) {
449
- const inputEl = inputRef?.current as HTMLInputElement;
450
- inputEl?.focus?.();
451
- }
452
- }
453
- return !prev;
454
- });
455
- };
456
-
457
- const handleClear = (
458
- e:
459
- | React.MouseEvent<HTMLButtonElement>
460
- | React.ChangeEvent<HTMLInputElement>
461
- | React.ChangeEvent<HTMLTextAreaElement>
462
- ) => {
463
- e.preventDefault();
464
- e.stopPropagation();
465
-
466
- if (inputRef?.current) inputRef.current.value = "";
467
- onChange?.([]);
468
- setSelectedItems([]);
469
- setSearchValue("");
470
- searchFn?.("");
471
- setIsOpen(false);
472
- };
473
-
474
- const handleChangeSelection = useCallback(
475
- (option: Option | string) => {
476
- setSelectedItems((prev) => {
477
- onChange?.([...prev, option]);
478
- return [...prev, option];
479
- });
480
- },
481
- [onChange]
482
- );
483
-
484
- const handleItemClick = (item: Option | string) => {
485
- if (inputRef?.current?.value) inputRef.current.value = "";
486
- setSearchValue("");
487
- handleChangeSelection(item);
488
- };
489
-
490
- const handleRemoveItem = (item: Option | string) => {
491
- setSelectedItems((prev) => {
492
- const newItems = prev.filter((prevItem) =>
493
- isObjectArray
494
- ? (prevItem as Option).value !== (item as Option).value
495
- : prevItem !== item
496
- );
497
- onChange?.(newItems);
498
- return newItems;
499
- });
500
- };
501
-
502
- const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
503
- // Tab key
504
- if (e.key === "Tab") {
505
- setIsOpen(false);
506
- }
507
- };
508
-
509
- // Close on outside click
510
- useEffect(() => {
511
- const close = (e: any) => {
512
- const target = e.target as Node;
513
- const referenceElement = refs?.reference?.current as Node;
514
- const floatingElement = refs?.floating?.current as Node;
515
-
516
- if (
517
- floatingElement && // Check if the floating element exists
518
- target !== referenceElement && // Check if the target is not the reference (input)
519
- !referenceElement.contains(target) && // Check if the target is not inside the reference (input)
520
- !floatingElement.contains(target) // Check if the target is not inside the floating element (content)
521
- ) {
522
- setIsOpen(false);
523
- }
524
- };
525
- document.addEventListener("click", close);
526
- return () => document.removeEventListener("click", close);
527
- }, [refs.floating, refs.reference]);
528
-
529
- // update when selection changes
530
- useEffect(() => {
531
- update();
532
- }, [selectedItems]);
533
-
534
- const referenceEl = refs?.reference?.current as HTMLElement;
535
-
536
- const contentWidth = referenceEl?.getClientRects?.()?.[0]?.width || "100%";
537
-
538
- const scrollEl = scrollContainerRef?.current as HTMLElement | null;
539
-
540
- const scrollActive = scrollEl
541
- ? scrollEl?.scrollHeight > scrollEl?.clientHeight
542
- : false;
543
-
544
- return (
545
- <div className={className + " mfTagBox"}>
546
- {label && (
547
- <FieldLabel
548
- error={error}
549
- asterisk={required}
550
- size={size}
551
- description={description}
552
- >
553
- {label}
554
- </FieldLabel>
555
- )}
556
- <StyledInputContainer
557
- ref={refs.setReference}
558
- onClick={toggleOpen}
559
- size={size}
560
- variant={variant}
561
- onKeyDown={handleKeyDown}
562
- data-open={isOpen}
563
- >
564
- <StyledInnerContainer data-button-right={arrow || clearable}>
565
- <PillContainer size={size} data-empty={selectedItems?.length === 0}>
566
- {selectedItems.map((item: Option | string, index: number) => (
567
- <Pill
568
- key={index}
569
- size="xs"
570
- onRemove={() => handleRemoveItem(item)}
571
- >
572
- {renderOption?.(item) || (
573
- <>{(item as Option)?.label || item}</>
574
- )}
575
- </Pill>
576
- ))}
577
- </PillContainer>
578
- {(searchable || allowCustomValue || selectedItems.length === 0) && (
579
- <StyledInput
580
- inputRef={inputRef}
581
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
582
- if (searchFn !== undefined) {
583
- searchFn?.(e.target.value);
584
- } else {
585
- setSearchValue(e.target.value);
586
- }
587
- update();
588
- }}
589
- placeholder={placeholder}
590
- size={size}
591
- readOnly={!(searchable || allowCustomValue)}
592
- data-button-right={arrow || clearable}
593
- />
594
- )}
595
- </StyledInnerContainer>
596
- {clearable &&
597
- (selectedItems.length > 0 || !!inputRef?.current?.value) ? (
598
- <ClearButton onClick={handleClear} />
599
- ) : arrow ? (
600
- <ArrowButton />
601
- ) : null}
602
- </StyledInputContainer>
603
- {isOpen && (
604
- <StyledFloatContainer
605
- ref={refs.setFloating}
606
- style={floatingStyles}
607
- className="mfFloating"
608
- >
609
- <ExtendedStyledContent
610
- className="mfFloatingContent"
611
- style={{ width: contentWidth, maxWidth: contentWidth }}
612
- variant={variant}
613
- onScroll={onScroll}
614
- data-scroll-active={scrollActive}
615
- data-empty={
616
- filteredItems.length === 0 ||
617
- selectedItems.length === filteredItems.length
618
- }
619
- >
620
- {!loading && grouped
621
- ? groups.map((group, index) => (
622
- <div key={group.label}>
623
- <GroupTitle size={size}>{group.label}</GroupTitle>
624
- {group.items.map((item: Option, index: number) => {
625
- return (
626
- <Tooltip
627
- content={
628
- TooltipContent ? (
629
- <TooltipContent data={item.data} />
630
- ) : null
631
- }
632
- side="left"
633
- >
634
- <StyledItem
635
- key={index}
636
- className="mfFloatingItem"
637
- onClick={(e) => handleItemClick(item)}
638
- data-selected={selectedItems.some(
639
- (selectedItem) =>
640
- (selectedItem as Option).value ===
641
- item?.value || selectedItem === item
642
- )}
643
- size={size}
644
- >
645
- {renderOption?.(item) || (
646
- <>{(item as Option)?.label || item}</>
647
- )}
648
- </StyledItem>
649
- </Tooltip>
650
- );
651
- })}
652
- </div>
653
- ))
654
- : filteredItems.map((item, index) => {
655
- return (
656
- <Tooltip
657
- key={item.value || item}
658
- content={
659
- TooltipContent ? (
660
- <TooltipContent data={item.data} />
661
- ) : null
662
- }
663
- side="left"
664
- >
665
- <StyledItem
666
- key={index}
667
- className="mfFloatingItem"
668
- onClick={(e) => handleItemClick(item)}
669
- data-selected={selectedItems.some(
670
- (selectedItem) =>
671
- (selectedItem as Option).value === item?.value ||
672
- selectedItem === item
673
- )}
674
- size={size}
675
- >
676
- {renderOption?.(item) || (
677
- <>{(item as Option)?.label || item}</>
678
- )}
679
- </StyledItem>
680
- </Tooltip>
681
- );
682
- })}
683
- </ExtendedStyledContent>
684
- </StyledFloatContainer>
685
- )}
686
- </div>
687
- );
688
- }
689
- )`
690
- position: relative;
691
- cursor: pointer;
692
- `;
693
-
694
- export default TagBox;