react-restyle-components 0.1.59 → 0.1.60

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 (79) hide show
  1. package/lib/package.json +4 -5
  2. package/package.json +5 -6
  3. package/src/App.css +38 -0
  4. package/src/App.test.tsx +9 -0
  5. package/src/App.tsx +26 -0
  6. package/src/core-components/atoms/buttons/button.stories.tsx +42 -0
  7. package/src/core-components/atoms/buttons/buttons.component.tsx +33 -0
  8. package/src/core-components/atoms/buttons/buttons.test.tsx +13 -0
  9. package/src/core-components/atoms/check-box/checkBox.component.tsx +54 -0
  10. package/src/core-components/atoms/check-box/checkBox.stories.tsx +29 -0
  11. package/src/core-components/atoms/check-box/checkBox.test.tsx +11 -0
  12. package/src/core-components/atoms/date-picker/date-picker.component.tsx +60 -0
  13. package/src/core-components/atoms/date-picker/date-picker.stories.tsx +23 -0
  14. package/src/core-components/atoms/date-picker/date-picker.test.tsx +17 -0
  15. package/src/core-components/atoms/form/form.component.tsx +604 -0
  16. package/src/core-components/atoms/form/form.test.tsx +120 -0
  17. package/src/core-components/atoms/icons/icons.component.tsx +65 -0
  18. package/src/core-components/atoms/icons/icons.stories.tsx +24 -0
  19. package/src/core-components/atoms/icons/icons.test.tsx +15 -0
  20. package/src/core-components/atoms/input/input-otp.component.tsx +107 -0
  21. package/src/core-components/atoms/input/input-otp.styles.css +35 -0
  22. package/src/core-components/atoms/input/input-pin.component.tsx +144 -0
  23. package/src/core-components/atoms/input/input-pin.stories.tsx +25 -0
  24. package/src/core-components/atoms/input/input-pin.test.tsx +30 -0
  25. package/src/core-components/atoms/input/input.component.tsx +74 -0
  26. package/src/core-components/atoms/input/input.stories.tsx +26 -0
  27. package/src/core-components/atoms/input/input.styles.css +35 -0
  28. package/src/core-components/atoms/input/input.test.tsx +32 -0
  29. package/src/core-components/atoms/input-dropdown/input-dropdown.component.tsx +91 -0
  30. package/src/core-components/atoms/input-dropdown/input-dropdown.stories.tsx +22 -0
  31. package/src/core-components/atoms/input-dropdown/input-dropdown.test.tsx +16 -0
  32. package/src/core-components/atoms/loader/loader.component.tsx +78 -0
  33. package/src/core-components/atoms/loader/loader.stories.tsx +18 -0
  34. package/src/core-components/atoms/loader/loader.test.tsx +9 -0
  35. package/src/core-components/atoms/radio/radio.component.tsx +48 -0
  36. package/src/core-components/atoms/radio/radio.stories.tsx +27 -0
  37. package/src/core-components/atoms/radio/radio.test.tsx +11 -0
  38. package/src/core-components/atoms/stepper/stepper.component.tsx +72 -0
  39. package/src/core-components/atoms/stepper/stepper.stories.tsx +23 -0
  40. package/src/core-components/atoms/stepper/stepper.test.tsx +14 -0
  41. package/src/core-components/atoms/tabs/tabs.component.tsx +41 -0
  42. package/src/core-components/atoms/tabs/tabs.stories.tsx +27 -0
  43. package/src/core-components/atoms/tabs/tabs.test.tsx +19 -0
  44. package/src/core-components/atoms/timer/timer.component.tsx +89 -0
  45. package/src/core-components/atoms/timer/timer.test.tsx +16 -0
  46. package/src/core-components/atoms/tooltip/tooltip.component.test.tsx +10 -0
  47. package/src/core-components/atoms/tooltip/tooltip.component.tsx +54 -0
  48. package/src/core-components/atoms/tooltip/tooltip.stories.tsx +18 -0
  49. package/src/core-components/index.ts +21 -0
  50. package/src/core-components/molecules/auto-complete-filter-multiple-select-multiple-fields-display/auto-complete-filter-multiple-select-multiple-fields-display.component.test.tsx +18 -0
  51. package/src/core-components/molecules/auto-complete-filter-multiple-select-multiple-fields-display/auto-complete-filter-multiple-select-multiple-fields-display.component.tsx +182 -0
  52. package/src/core-components/molecules/auto-complete-filter-multiple-select-multiple-fields-display/auto-complete-filter-multiple-select-multiple-fields-display.stories.tsx +55 -0
  53. package/src/core-components/molecules/auto-complete-filter-single-select-multiple-fields-display/auto-complete-filter-single-select-multiple-fields-display.component.test.tsx +23 -0
  54. package/src/core-components/molecules/auto-complete-filter-single-select-multiple-fields-display/auto-complete-filter-single-select-multiple-fields-display.component.tsx +190 -0
  55. package/src/core-components/molecules/auto-complete-filter-single-select-multiple-fields-display/auto-complete-filter-single-select-multiple-fields-display.stories.tsx +35 -0
  56. package/src/core-components/molecules/css-multiline-input/css-multiline-input.component.tsx +135 -0
  57. package/src/core-components/molecules/css-multiline-input/css-multiline-input.stories.tsx +18 -0
  58. package/src/core-components/molecules/css-multiline-input/css-multiline-input.test.tsx +11 -0
  59. package/src/core-components/molecules/css-multiline-input/css-properties.ts +177 -0
  60. package/src/core-utils/index.ts +1 -0
  61. package/src/core-utils/unit-test.utils.tsx +12 -0
  62. package/src/custom.d.ts +4 -0
  63. package/src/index.css +17 -0
  64. package/src/index.ts +1 -0
  65. package/src/index.tsx +18 -0
  66. package/src/library/assets/svg/DownArrow.svg +14 -0
  67. package/src/library/assets/svg/UpArrow.svg +14 -0
  68. package/src/library/assets/svg/checkedBox.svg +14 -0
  69. package/src/library/assets/svg/checkedRadio.svg +13 -0
  70. package/src/library/assets/svg/datePicker.svg +3 -0
  71. package/src/library/assets/svg/index.ts +38 -0
  72. package/src/library/assets/svg/timer copy.svg +3 -0
  73. package/src/library/assets/svg/timer.svg +3 -0
  74. package/src/library/assets/svg/unCheckbox.svg +3 -0
  75. package/src/library/assets/svg/uncheckRadio.svg +3 -0
  76. package/src/logo.svg +1 -0
  77. package/src/react-app-env.d.ts +1 -0
  78. package/src/reportWebVitals.ts +16 -0
  79. package/src/setupTests.ts +5 -0
@@ -0,0 +1,89 @@
1
+ /* eslint-disable react/prop-types */
2
+ /* eslint-disable @typescript-eslint/no-unused-expressions */
3
+ import React, {useEffect, Ref, useState, useImperativeHandle} from 'react';
4
+ import {TimerSVG} from '../../../library/assets/svg';
5
+
6
+ interface TimerProps {
7
+ onClear: () => void;
8
+ }
9
+
10
+ // eslint-disable-next-line react/display-name
11
+ export const Timer = React.forwardRef(
12
+ ({onClear}: TimerProps, ref: Ref<any>) => {
13
+ const width = 15;
14
+ const [minute, setMinute] = useState('00');
15
+ const [second, setSecond] = useState('10');
16
+
17
+ useEffect(() => {
18
+ const sec: number = parseInt(second);
19
+ const min: number = parseInt(minute);
20
+ const countDown = setInterval(() => {
21
+ if (min === 0 && sec === 0) {
22
+ setMinute('00');
23
+ setSecond('00');
24
+ clearInterval(countDown);
25
+ onClear && onClear();
26
+ } else {
27
+ let secondstTmp = (sec - 1).toString();
28
+ if (secondstTmp.length === 1) {
29
+ secondstTmp = '0'.concat(secondstTmp);
30
+ }
31
+ setSecond(secondstTmp);
32
+ if (sec === 0) {
33
+ setSecond('59');
34
+ const m = (min - 1).toString();
35
+ setMinute('0' + m);
36
+ }
37
+ }
38
+ }, 1000);
39
+ return () => {
40
+ clearInterval(countDown);
41
+ };
42
+ });
43
+
44
+ useImperativeHandle(ref, () => ({
45
+ updateState() {
46
+ setMinute('02');
47
+ setSecond('00');
48
+ },
49
+ resetTimer() {
50
+ // eslint-disable-next-line no-console
51
+ const sec: number = parseInt(second);
52
+ const min: number = parseInt(minute === '00' ? '02' : minute);
53
+ const countDown = setInterval(() => {
54
+ // eslint-disable-next-line no-console
55
+ if (min === 0 && sec === 0) {
56
+ setMinute('00');
57
+ setSecond('00');
58
+ clearInterval(countDown);
59
+ onClear && onClear();
60
+ } else {
61
+ let secondstTmp = (sec - 1).toString();
62
+ if (secondstTmp.length === 1) {
63
+ secondstTmp = '0'.concat(secondstTmp);
64
+ }
65
+ setSecond(secondstTmp);
66
+ if (sec === 0) {
67
+ setSecond('59');
68
+ const m = (min - 1).toString();
69
+ setMinute('0' + m);
70
+ }
71
+ }
72
+ }, 1000);
73
+ return () => {
74
+ clearInterval(countDown);
75
+ };
76
+ },
77
+ }));
78
+
79
+ return (
80
+ <div className="flex flex-row items-center">
81
+ <TimerSVG width={width} height={width} fill="#E7503D" />
82
+ <div className="ml-2 flex flex-row">
83
+ <span>{minute}:</span>
84
+ <span>{second}</span>
85
+ </div>
86
+ </div>
87
+ );
88
+ }
89
+ );
@@ -0,0 +1,16 @@
1
+ /* eslint-disable testing-library/await-async-query */
2
+ /* eslint-disable testing-library/prefer-screen-queries */
3
+ /* eslint-disable testing-library/render-result-naming-convention */
4
+ import React from 'react';
5
+ import {render} from '@core-utils';
6
+ import {Timer as TimerComp} from './timer.component';
7
+
8
+ it('render Timer correctly', () => {
9
+ const time = render(<TimerComp onClear={() => {}} />);
10
+ expect(time).toMatchSnapshot();
11
+ });
12
+
13
+ it('render Timer with minute correctly', () => {
14
+ const time = render(<TimerComp onClear={() => {}} />);
15
+ expect(time.findByText('minute')).toBeTruthy();
16
+ });
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import {render} from '@testing-library/react';
3
+ import {Tooltip} from './tooltip.component';
4
+
5
+ describe('Tooltip component', () => {
6
+ it('render tooltip correctly', () => {
7
+ const tooltip = render(<Tooltip />);
8
+ expect(tooltip).toMatchSnapshot();
9
+ });
10
+ });
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import * as Material from '@mui/material';
3
+
4
+ interface TooltipProps {
5
+ tooltipText?: any;
6
+ position?: 'bottom' | 'left' | 'top';
7
+ className?: string;
8
+ children?: any;
9
+ }
10
+
11
+ export const Tooltip: React.FunctionComponent<TooltipProps> = ({
12
+ tooltipText,
13
+ position = 'bottom-start',
14
+ children,
15
+ }) => {
16
+ const positionRef = React.useRef<{x: number; y: number}>({
17
+ x: 0,
18
+ y: 0,
19
+ });
20
+ const popperRef = React.useRef<any>(null);
21
+ const areaRef = React.useRef<HTMLDivElement>(null);
22
+
23
+ const handleMouseMove = (event: React.MouseEvent) => {
24
+ positionRef.current = {x: event.clientX, y: event.clientY};
25
+
26
+ if (popperRef.current != null) {
27
+ popperRef.current.update();
28
+ }
29
+ };
30
+ return (
31
+ <Material.Tooltip
32
+ title={tooltipText}
33
+ placement="bottom-start"
34
+ arrow
35
+ PopperProps={{
36
+ popperRef,
37
+ anchorEl: {
38
+ getBoundingClientRect: () => {
39
+ return new DOMRect(
40
+ positionRef.current.x,
41
+ areaRef.current!.getBoundingClientRect().y + 22,
42
+ 0,
43
+ 0
44
+ );
45
+ },
46
+ },
47
+ }}
48
+ >
49
+ <Material.Box ref={areaRef} onMouseMove={handleMouseMove}>
50
+ {children}
51
+ </Material.Box>
52
+ </Material.Tooltip>
53
+ );
54
+ };
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import type {Meta, StoryObj} from '@storybook/react';
3
+ import {Tooltip} from './tooltip.component';
4
+
5
+ const meta: Meta<typeof Tooltip> = {
6
+ title: 'Design System/Atoms/Tooltip',
7
+ component: Tooltip,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ componentSubtitle: `import { Tooltip } from 'react-restyle-components'`,
11
+ },
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof Tooltip>;
15
+
16
+ export const Primary: Story = {
17
+ args: {},
18
+ };
@@ -0,0 +1,21 @@
1
+ import * as Form from './atoms/form/form.component';
2
+ export * from './atoms/buttons/buttons.component';
3
+ export * from './atoms/check-box/checkBox.component';
4
+ export * from './atoms/date-picker/date-picker.component';
5
+ export * from './atoms/input/input-otp.component';
6
+ export * from './atoms/input/input-pin.component';
7
+ export * from './atoms/input/input.component';
8
+ export * from './atoms/input-dropdown/input-dropdown.component';
9
+ export * from './atoms/loader/loader.component';
10
+ export * from './atoms/radio/radio.component';
11
+ export * from './atoms/stepper/stepper.component';
12
+ export * from './atoms/timer/timer.component';
13
+ export * from './atoms/tooltip/tooltip.component';
14
+ export * from './atoms/icons/icons.component';
15
+ export * from './atoms/tabs/tabs.component';
16
+
17
+ export * from './molecules/css-multiline-input/css-multiline-input.component';
18
+ export * from './molecules/auto-complete-filter-multiple-select-multiple-fields-display/auto-complete-filter-multiple-select-multiple-fields-display.component';
19
+ export * from './molecules/auto-complete-filter-single-select-multiple-fields-display/auto-complete-filter-single-select-multiple-fields-display.component';
20
+
21
+ export {Form};
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import {render} from '@core-utils';
3
+ import {AutoCompleteFilterMultipleSelectMultipleFieldsDisplay} from './auto-complete-filter-multiple-select-multiple-fields-display.component';
4
+
5
+ it('render AutoCompleteFilterMultipleSelectMultipleFieldsDisplay correctly', () => {
6
+ const autoCompleteFilterMultipleSelectMultipleFieldsDisplay = render(
7
+ <AutoCompleteFilterMultipleSelectMultipleFieldsDisplay
8
+ data={[]}
9
+ onUpdate={(item: any) => {
10
+ console.log({item});
11
+ }}
12
+ onSelect={(item: any) => {}}
13
+ />
14
+ );
15
+ expect(
16
+ autoCompleteFilterMultipleSelectMultipleFieldsDisplay
17
+ ).toMatchSnapshot();
18
+ });
@@ -0,0 +1,182 @@
1
+ /* eslint-disable */
2
+ import React, {useState, useEffect, useRef} from 'react';
3
+ import {Icon} from '../..';
4
+
5
+ interface AutoCompleteFilterMultipleSelectMultipleFieldsDisplayProps {
6
+ uniqueField?: string;
7
+ loader?: boolean;
8
+ placeholder?: string;
9
+ data: any;
10
+ hasError?: boolean;
11
+ disable?: boolean;
12
+ isUpperCase?: boolean;
13
+ name?: string;
14
+ onFilter?: (value: string) => void;
15
+ onUpdate: (item: any) => void;
16
+ onSelect: (item: any) => any;
17
+ onBlur?: (e: any) => void;
18
+ }
19
+
20
+ export const AutoCompleteFilterMultipleSelectMultipleFieldsDisplay = ({
21
+ uniqueField = '_id',
22
+ loader = false,
23
+ placeholder = 'Search...',
24
+ data,
25
+ hasError = false,
26
+ disable = false,
27
+ isUpperCase = false,
28
+ name,
29
+ onFilter,
30
+ onUpdate,
31
+ onSelect,
32
+ onBlur,
33
+ }: AutoCompleteFilterMultipleSelectMultipleFieldsDisplayProps) => {
34
+ const [value, setValue] = useState<string>('');
35
+ const [options, setOptions] = useState<any[]>();
36
+ const [originalOptions, setOriginalOptions] = useState<any[]>();
37
+ const [isListOpen, setIsListOpen] = useState<boolean>(false);
38
+
39
+ const useOutsideAlerter = (ref) => {
40
+ useEffect(() => {
41
+ function handleClickOutside(event) {
42
+ if (ref.current && !ref.current.contains(event.target) && isListOpen) {
43
+ if (originalOptions && options) {
44
+ if (isListOpen) {
45
+ onUpdate && onUpdate(data.selected);
46
+ }
47
+ }
48
+ setIsListOpen(false);
49
+ setValue('');
50
+ }
51
+ }
52
+ document.addEventListener('mousedown', handleClickOutside);
53
+ return () => {
54
+ document.removeEventListener('mousedown', handleClickOutside);
55
+ };
56
+ }, [ref, isListOpen]);
57
+ };
58
+
59
+ const wrapperRef = useRef(null);
60
+ useOutsideAlerter(wrapperRef);
61
+ let count = 0;
62
+ const getSelectedItem = (selectedItem: any[], list: any[]) => {
63
+ if (count === 0) {
64
+ const finalList = list?.filter((item, index) => {
65
+ item.selected = false;
66
+ selectedItem && selectedItem.length > 0
67
+ ? selectedItem.find((sItem, index) => {
68
+ if (sItem[uniqueField] === item[uniqueField]) {
69
+ item.selected = true;
70
+ }
71
+ })
72
+ : (item.selected = false);
73
+ count++;
74
+ return item;
75
+ });
76
+ list = finalList;
77
+ }
78
+ return list;
79
+ };
80
+
81
+ useEffect(() => {
82
+ setOriginalOptions(getSelectedItem(data.selected, data.list));
83
+ setOptions(getSelectedItem(data.selected, data.list));
84
+ }, [data, data.selected]);
85
+
86
+ const onChange = (e) => {
87
+ const search = e.target.value;
88
+ setValue(search);
89
+ onFilter && onFilter(search);
90
+ };
91
+
92
+ const onKeyUp = (e) => {
93
+ const charCode = e.which ? e.which : e.keyCode;
94
+ if (charCode === 8) {
95
+ const search = e.target.value;
96
+ onFilter && onFilter(search);
97
+ }
98
+ };
99
+
100
+ return (
101
+ <>
102
+ <div ref={wrapperRef} className="w-full relative">
103
+ <div
104
+ className={`flex items-center leading-4 p-2 focus:outline-none focus:ring w-full shadow-sm sm:text-base border-2 ${
105
+ hasError ? 'border-red' : 'border-gray-300'
106
+ } rounded-md`}
107
+ >
108
+ <input
109
+ placeholder={placeholder}
110
+ disabled={disable}
111
+ name={name}
112
+ value={
113
+ !isListOpen
114
+ ? `${(data.selected && data.selected.length) || 0} Items`
115
+ : isUpperCase
116
+ ? value?.toUpperCase()
117
+ : value
118
+ }
119
+ className={`w-full focus:outline-none bg-none`}
120
+ onKeyUp={onKeyUp}
121
+ onChange={onChange}
122
+ onClick={() => setIsListOpen(true)}
123
+ onBlur={(e) => onBlur && onBlur(e)}
124
+ />
125
+ {/* {loader && <Spinner animation="border" className="mr-2 h-4 w-4" />} */}
126
+ {isListOpen ? (
127
+ <Icon
128
+ nameIcon="FaChevronUp"
129
+ propsIcon={{
130
+ color: '#000000',
131
+ size: 22,
132
+ }}
133
+ />
134
+ ) : (
135
+ <Icon
136
+ nameIcon="FaChevronDown"
137
+ propsIcon={{
138
+ color: '#000000',
139
+ size: 22,
140
+ }}
141
+ />
142
+ )}
143
+ </div>
144
+
145
+ {options && isListOpen
146
+ ? options?.length > 0 && (
147
+ <div
148
+ className="mt-1 absolute bg-gray-100 p-2 rounded-sm z-500"
149
+ style={{zIndex: 80}}
150
+ >
151
+ <ul>
152
+ {options?.map((item, index) => (
153
+ <>
154
+ <li
155
+ key={index}
156
+ className="text-gray-400 flex items-center"
157
+ >
158
+ <input
159
+ type="checkbox"
160
+ checked={item.selected}
161
+ onChange={() => onSelect(item)}
162
+ />{' '}
163
+ <label className="ml-2 mt-1 text-black">
164
+ {data.displayKey
165
+ .map(
166
+ (key) =>
167
+ `${item[key]}
168
+ `
169
+ )
170
+ .join(' - ')}
171
+ </label>
172
+ </li>
173
+ </>
174
+ ))}
175
+ </ul>
176
+ </div>
177
+ )
178
+ : null}
179
+ </div>
180
+ </>
181
+ );
182
+ };
@@ -0,0 +1,55 @@
1
+ import React from 'react';
2
+ import dayjs from 'dayjs';
3
+ import type {Meta, StoryObj} from '@storybook/react';
4
+ import {AutoCompleteFilterMultipleSelectMultipleFieldsDisplay} from './auto-complete-filter-multiple-select-multiple-fields-display.component';
5
+
6
+ const meta: Meta<typeof AutoCompleteFilterMultipleSelectMultipleFieldsDisplay> =
7
+ {
8
+ title:
9
+ 'Design System/Molecules/AutoCompleteFilterMultipleSelectMultipleFieldsDisplay',
10
+ component: AutoCompleteFilterMultipleSelectMultipleFieldsDisplay,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ componentSubtitle: `import { AutoCompleteFilterMultipleSelectMultipleFieldsDisplay } from 'react-restyle-components'`,
14
+ },
15
+ };
16
+ export default meta;
17
+ type Story = StoryObj<
18
+ typeof AutoCompleteFilterMultipleSelectMultipleFieldsDisplay
19
+ >;
20
+
21
+ export const Primary: Story = {
22
+ args: {
23
+ data: {
24
+ list: [
25
+ {
26
+ _id: '66532a99bbfed4eea86eae23',
27
+ code: 82,
28
+ description: 'TEST1',
29
+ libraryCode: 'ABCD',
30
+ },
31
+ {
32
+ _id: '6652b6d8bcef7f713cb547d4',
33
+ code: 81,
34
+ description: 'TEST New',
35
+ libraryCode: 'TEST',
36
+ },
37
+ ],
38
+ selected: [
39
+ {
40
+ _id: '66532a99bbfed4eea86eae23',
41
+ code: 82,
42
+ description: 'TEST1',
43
+ libraryCode: 'ABCD',
44
+ },
45
+ ],
46
+ displayKey: ['libraryCode', 'description'],
47
+ },
48
+ onUpdate: (item) => {
49
+ console.log({item});
50
+ },
51
+ onSelect: (item) => {
52
+ console.log({item});
53
+ },
54
+ },
55
+ };
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import {render} from '@testing-library/react';
3
+ import {AutoCompleteFilterSingleSelectMultiFieldsDisplay} from './auto-complete-filter-single-select-multiple-fields-display.component';
4
+
5
+ describe('AutoCompleteFilterSingleSelectMultiFieldsDisplay component', () => {
6
+ it('render autoCompleteFilterSingleSelectMultiFieldsDisplay correctly', () => {
7
+ const autoCompleteFilterSingleSelectMultiFieldsDisplay = render(
8
+ <AutoCompleteFilterSingleSelectMultiFieldsDisplay
9
+ data={{
10
+ list: [
11
+ {code: 'Lims', name: 'plus'},
12
+ {code: 'Lims', name: 'plus'},
13
+ {code: 'Lims', name: 'plus'},
14
+ ],
15
+ displayKey: ['name'],
16
+ }}
17
+ onSelect={() => jest.fn()}
18
+ onFilter={() => jest.fn()}
19
+ />
20
+ );
21
+ expect(autoCompleteFilterSingleSelectMultiFieldsDisplay).toMatchSnapshot();
22
+ });
23
+ });
@@ -0,0 +1,190 @@
1
+ /* eslint-disable */
2
+ import React, {useState, useEffect, useRef} from 'react';
3
+ import _ from 'lodash';
4
+ import {Icon} from '../..';
5
+
6
+ interface AutoCompleteFilterSingleSelectMultiFieldsDisplayProps {
7
+ loader?: boolean;
8
+ disable?: boolean;
9
+ displayValue?: string;
10
+ placeholder?: string;
11
+ data: any;
12
+ hasError?: boolean;
13
+ className?: string;
14
+ posstion?: string;
15
+ onFilter?: (item: any) => void;
16
+ onSelect?: (item: any) => any;
17
+ onBlur?: (item: any) => any;
18
+ }
19
+
20
+ export const AutoCompleteFilterSingleSelectMultiFieldsDisplay = ({
21
+ disable = false,
22
+ loader = false,
23
+ displayValue = '',
24
+ placeholder = 'Search...',
25
+ data,
26
+ hasError = false,
27
+ className,
28
+ posstion = 'absolute',
29
+ onFilter,
30
+ onSelect,
31
+ onBlur,
32
+ }: AutoCompleteFilterSingleSelectMultiFieldsDisplayProps) => {
33
+ const [value, setValue] = useState<string>(displayValue);
34
+ const [options, setOptions] = useState<any[]>(data.list);
35
+ const [isListOpen, setIsListOpen] = useState<boolean>(false);
36
+ const [filterValue, setFilterValue] = useState<number>();
37
+
38
+ const useOutsideAlerter = (ref) => {
39
+ useEffect(() => {
40
+ function handleClickOutside(event) {
41
+ if (ref.current && !ref.current.contains(event.target) && isListOpen) {
42
+ setIsListOpen(false);
43
+ //setValue('');
44
+ }
45
+ }
46
+ document.addEventListener('mousedown', handleClickOutside);
47
+ return () => {
48
+ document.removeEventListener('mousedown', handleClickOutside);
49
+ };
50
+ }, [ref, isListOpen]);
51
+ };
52
+
53
+ const wrapperRef = useRef(null);
54
+ useOutsideAlerter(wrapperRef);
55
+
56
+ useEffect(() => {
57
+ setOptions(data.list);
58
+ }, [data]);
59
+
60
+ useEffect(() => {
61
+ setValue(displayValue);
62
+ }, [displayValue]);
63
+
64
+ const onChange = (e) => {
65
+ const search = e.target.value?.toUpperCase();
66
+ setValue(search);
67
+ setFilterValue(search);
68
+ onFilter && onFilter(search);
69
+ };
70
+
71
+ const onKeyUp = (e) => {
72
+ const charCode = e.which ? e.which : e.keyCode;
73
+ if (charCode === 8) {
74
+ const search = e.target.value;
75
+ onFilter && onFilter(search);
76
+ }
77
+ };
78
+
79
+ const onKeyDown = (e) => {
80
+ if (e.key === 'Enter' || e.key === 'Tab') {
81
+ if (options.length > 0) {
82
+ const selectedItem = options.find(
83
+ (item) => item.labId === Number(value)
84
+ );
85
+ if (selectedItem) {
86
+ setValue(
87
+ data.displayKey.map((key) => `${selectedItem[key]}`).join(' - ')
88
+ );
89
+ setIsListOpen(false);
90
+ onSelect && onSelect(selectedItem);
91
+ }
92
+ }
93
+ }
94
+ };
95
+
96
+ return (
97
+ <>
98
+ <div ref={wrapperRef} className="w-full relative">
99
+ <div
100
+ className={`flex items-center leading-4 p-2 focus:outline-none focus:ring w-full shadow-sm sm:text-base border-2 ${
101
+ hasError ? 'border-red' : 'border-gray-300'
102
+ } rounded-md dark:text-black`}
103
+ >
104
+ <input
105
+ placeholder={placeholder}
106
+ value={value}
107
+ className={`${className} w-full focus:outline-none bg-none dark:text-black`}
108
+ onKeyUp={onKeyUp}
109
+ onChange={onChange}
110
+ onClick={() => setIsListOpen(true)}
111
+ disabled={disable}
112
+ onMouseDown={() => setValue('')}
113
+ onBlur={(e) => onBlur && onBlur(e)}
114
+ onKeyDown={onKeyDown}
115
+ />
116
+ {/* {loader && <Spinner animation="border" className="mr-2 h-4 w-4" />} */}
117
+ {isListOpen ? (
118
+ <Icon
119
+ nameIcon="FaChevronUp"
120
+ propsIcon={{
121
+ color: '#000000',
122
+ size: 22,
123
+ }}
124
+ />
125
+ ) : (
126
+ <Icon
127
+ nameIcon="FaChevronDown"
128
+ propsIcon={{
129
+ color: '#000000',
130
+ size: 22,
131
+ }}
132
+ />
133
+ )}
134
+ </div>
135
+
136
+ {options && isListOpen
137
+ ? options.length > 0 && (
138
+ <div
139
+ className={`mt-1 absolute w-full bg-gray-100 p-2 rounded-sm `}
140
+ style={{
141
+ zIndex: 500,
142
+ }}
143
+ >
144
+ <ul>
145
+ {options?.map((item, index) => (
146
+ <li
147
+ key={index}
148
+ className="text-gray-400 flex items-center"
149
+ onClick={() => {
150
+ setValue(
151
+ data.displayKey
152
+ .map((key) => `${item[key]}`)
153
+ .join(' - ')
154
+ );
155
+ setIsListOpen(false);
156
+ onSelect && onSelect(item);
157
+ }}
158
+ >
159
+ {' '}
160
+ <label
161
+ className="ml-2 mt-1 text-black"
162
+ style={{
163
+ textOverflow: 'ellipsis',
164
+ minWidth: 0,
165
+ overflow: 'hidden',
166
+ maxWidth: '334px',
167
+ whiteSpace: 'nowrap',
168
+ }}
169
+ title={data.displayKey
170
+ .map((key) => item[key])
171
+ .join(' - ')}
172
+ >
173
+ {data.displayKey
174
+ .map(
175
+ (key) =>
176
+ `${item[key]}
177
+ `
178
+ )
179
+ .join(' - ')}
180
+ </label>
181
+ </li>
182
+ ))}
183
+ </ul>
184
+ </div>
185
+ )
186
+ : null}
187
+ </div>
188
+ </>
189
+ );
190
+ };