react-core-ts 1.0.2 → 1.0.4

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.
@@ -0,0 +1,522 @@
1
+ body * {
2
+ box-sizing: border-box;
3
+ }
4
+ :root {
5
+ --grey-dark: #4a4a4a;
6
+ --grey-light: #d3d3d3;
7
+ --blue-navy: #001f3f;
8
+ --input-disabled: #a9a9a9;
9
+ --error-light: #f08080;
10
+ --error-extra-light: #fddede;
11
+ --success: #28a745;
12
+ --success-light: #d4edda;
13
+ --blue-light: #add8e6;
14
+ }
15
+ :root {
16
+ --blue-navy: #001f3f;
17
+ --table-hover: #your-hover-color; /* Replace with your actual color code */
18
+ }
19
+
20
+ .custom-spinner {
21
+ width: 24px !important; /* w-6 */
22
+ height: 24px; /* h-6 */
23
+ color: transparent; /* text-table-hover */
24
+ fill: var(--blue-navy); /* fill-blue-navy */
25
+ animation: spin 1s linear infinite; /* animate-spin */
26
+ width: 15px;
27
+ position: relative;
28
+ top: 1px;
29
+ }
30
+
31
+ @keyframes spin {
32
+ 0% {
33
+ transform: rotate(0deg);
34
+ }
35
+ 100% {
36
+ transform: rotate(360deg);
37
+ }
38
+ }
39
+
40
+ .textfield,
41
+ .textfield-big {
42
+ outline: none;
43
+ color: var(--grey-dark);
44
+ border-color: var(--grey-light);
45
+ background-color: white;
46
+ }
47
+
48
+ .textfield:focus,
49
+ .textfield-big:focus {
50
+ border-color: var(--blue-navy);
51
+ }
52
+
53
+ .textfield:disabled,
54
+ .textfield-big:disabled {
55
+ color: var(--input-disabled);
56
+ }
57
+
58
+ .textfield-error,
59
+ .textfield-big-error {
60
+ outline: none;
61
+ color: var(--error-light) !important;
62
+ border-color: var(--error-light) !important;
63
+ background-color: var(--error-extra-light) !important ;
64
+ }
65
+
66
+ .textfield-error::placeholder,
67
+ .textfield-big-error::placeholder {
68
+ color: var(--error-light);
69
+ }
70
+
71
+ .textfield-success {
72
+ outline: none;
73
+ color: var(--success);
74
+ border-color: var(--success);
75
+ background-color: var(--success-light);
76
+ }
77
+
78
+ .textfield-success:focus {
79
+ ring-width: 0;
80
+ }
81
+
82
+ .textfield-success::placeholder {
83
+ color: var(--success);
84
+ }
85
+
86
+ .textfield-editable {
87
+ outline: none;
88
+ color: var(--grey-dark);
89
+ border-color: var(--blue-navy);
90
+ background-color: var(--blue-light);
91
+ }
92
+
93
+ .textfield-editable::placeholder {
94
+ color: var(--grey-dark);
95
+ }
96
+
97
+ .qbs-autocomplete-suggestions {
98
+ position: absolute;
99
+ height: auto;
100
+ width: 100%;
101
+ padding: 8px; /* Corresponding to p-1.5 in Tailwind */
102
+ z-index: 99;
103
+ margin-top: 4px;
104
+ margin-bottom: 0;
105
+ border-radius: 8px;
106
+ background: #fff;
107
+ box-shadow: 0px 8px 20px 0px rgba(0, 0, 0, 0.15);
108
+ }
109
+ .qbs-autocomplete-suggestions.bottom {
110
+ top: 100%; /* Position below the input */
111
+ /* Other styling */
112
+ }
113
+
114
+ .qbs-autocomplete-suggestions.top {
115
+ bottom: 100%; /* Position above the input */
116
+ /* Other styling */
117
+ }
118
+ .qbs-autocomplete-suggestions-item {
119
+ cursor: pointer;
120
+ padding: 6px 8px;
121
+ border-radius: 6px;
122
+ color: #222;
123
+ font-size: 14px;
124
+ font-weight: 500;
125
+ line-height: 20px; /* 142.857% */
126
+ width: 100%;
127
+ display: flex;
128
+ align-items: start;
129
+ gap: 8px;
130
+ }
131
+ .qbs-autocomplete-suggestions-item:hover {
132
+ background: #f8f8f8;
133
+ border-radius: 6px;
134
+ }
135
+
136
+ /* When value.id is equal to suggestion.id */
137
+ .is-selected {
138
+ border-radius: 6px;
139
+ background: var(--neutrals-grey-20, #f4f4f4);
140
+ }
141
+
142
+ /* When value.id is NOT equal to suggestion.id */
143
+ .qbs-autocomplete-suggestions-item .is-not-selected:hover {
144
+ background-color: #f1f5f9; /* Replace with actual color code for 'hover:bg-table-hover' */
145
+ }
146
+
147
+ .qbs-autocomplete-notfound {
148
+ cursor: pointer;
149
+ padding: 6px 8px;
150
+ border-radius: 6px;
151
+ font-size: 12px;
152
+ font-weight: 500;
153
+ }
154
+
155
+ .qbs-autocomplete-close-icon {
156
+ position: absolute;
157
+ top: calc(50% - 7px);
158
+ right: 2px; /* right-1 */
159
+ padding-left: 0.25rem; /* px-1 */
160
+ padding-right: 0.25rem; /* px-1 */
161
+ display: flex;
162
+ justify-content: center;
163
+ align-items: center;
164
+ background-color: white; /* bg-white */
165
+ }
166
+ .qbs-textfield-default {
167
+ width: 100%;
168
+ position: relative;
169
+ padding-right: 8px;
170
+ min-height: 36px;
171
+ height: 36px;
172
+ border-radius: 6px;
173
+ padding-left: 8px;
174
+ border: 1px solid #d6d8dc;
175
+ background: #fff;
176
+ box-sizing: border-box;
177
+ font-size: 14px;
178
+ font-style: normal;
179
+ font-weight: 500;
180
+ line-height: 20px;
181
+ color: #313131;
182
+ }
183
+
184
+ .qbs-textfield-default::placeholder {
185
+ font-size: 14px;
186
+ font-style: normal;
187
+ font-weight: 500;
188
+ line-height: 20px;
189
+ }
190
+
191
+ .qbs-autocomplete-close-icon button:focus-within {
192
+ outline: none;
193
+ }
194
+
195
+ .fullWidth {
196
+ width: 100%;
197
+ }
198
+
199
+ .autoWidth {
200
+ width: auto;
201
+ }
202
+ .icon-button {
203
+ background: transparent;
204
+ border: none;
205
+ display: inline-flex;
206
+ cursor: pointer;
207
+ padding: 0px 1px;
208
+ }
209
+ .labels {
210
+ font-size: 12px;
211
+ }
212
+ .dropdown-search-input {
213
+ min-width: -webkit-fill-available;
214
+ border-radius: 6px;
215
+ border: 1px solid var(--border-card-color-default, #d6d8dc);
216
+ background: var(--surface-input-bg-color-default, #fff);
217
+ color: #313131;
218
+ font-size: 14px;
219
+ height: 36px;
220
+ padding: 0px 8px;
221
+ font-style: normal;
222
+ font-weight: 500;
223
+ line-height: 20px;
224
+ padding-left: 32px;
225
+ }
226
+ .qbs-autocomplete-suggestions-sub {
227
+ position: relative;
228
+ overflow: auto;
229
+ max-height: 192px;
230
+ top: 0;
231
+ display: flex;
232
+ flex-direction: column;
233
+ gap: 4px;
234
+ }
235
+ .qbs-autocomplete-listitem-container {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: 0px;
239
+ }
240
+ ul {
241
+ list-style-type: none;
242
+ }
243
+
244
+ .react-core-ts-search-container {
245
+ display: flex;
246
+ align-items: center;
247
+ gap: var(--spacing-4, 4px);
248
+ align-self: stretch;
249
+ margin-bottom: 4px;
250
+ }
251
+ .selected-item {
252
+ display: flex;
253
+ align-items: center;
254
+ justify-content: space-between;
255
+ padding: 3px 6px;
256
+ margin: 0;
257
+ background-color: #e0e0e0;
258
+ color: #333;
259
+ border-radius: 6px;
260
+ border: 1px solid rgba(231, 100, 88, 0.1);
261
+ background: rgba(231, 100, 88, 0.1);
262
+ font-size: 12px;
263
+ font-style: normal;
264
+ font-weight: 500;
265
+ line-height: 16px;
266
+ color: #e76458;
267
+ gap: 6px;
268
+ height: 22px;
269
+ }
270
+
271
+ .remove-item-btn {
272
+ background-color: transparent;
273
+ border: none;
274
+ color: #e76458;
275
+ cursor: pointer;
276
+ }
277
+
278
+ .remove-item-btn:hover {
279
+ color: #e76458;
280
+ }
281
+
282
+ .selected-items-container {
283
+ display: flex;
284
+ gap: 12px;
285
+ align-items: center;
286
+ position: absolute;
287
+ left: 8px;
288
+ z-index: 99;
289
+ top: 6.5px;
290
+ flex-wrap: wrap;
291
+ }
292
+
293
+ .selected-item-more {
294
+ display: flex;
295
+ align-items: center;
296
+ justify-content: center;
297
+ padding: 3px 8px;
298
+ margin: 0;
299
+ border-radius: 6px;
300
+ background: #c63a3a;
301
+ font-size: 12px;
302
+ font-style: normal;
303
+ font-weight: 500;
304
+ line-height: 16px;
305
+ color: #fff;
306
+ height: 22px;
307
+ }
308
+
309
+ .loadMoreSection {
310
+ margin: 0;
311
+ cursor: pointer;
312
+ display: flex;
313
+ justify-content: flex-start;
314
+ padding: 8px;
315
+ }
316
+ .loadMoreSection p {
317
+ color: #336cfc;
318
+ font-size: 14px;
319
+ font-style: normal;
320
+ font-weight: 500;
321
+ line-height: 20px;
322
+ margin: 0;
323
+ }
324
+ ::-webkit-scrollbar-track {
325
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
326
+ border-radius: 0px;
327
+ background-color: transparent;
328
+ }
329
+
330
+ ::-webkit-scrollbar {
331
+ width: 6px;
332
+ height: 4px;
333
+ background-color: transparent;
334
+ }
335
+
336
+ ::-webkit-scrollbar-thumb {
337
+ border-radius: 100px;
338
+ -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
339
+ background-color: #ddd;
340
+ }
341
+
342
+ .qbs-autocomplete-suggestions-item.is-selected {
343
+ color: #e76458;
344
+ background: #f8f8f8;
345
+ }
346
+
347
+ span.dropdown-search-icon {
348
+ position: absolute;
349
+ left: 8px;
350
+ top: 10px;
351
+ }
352
+
353
+ .dropdown-search-input:focus {
354
+ outline: none;
355
+ border: 1px solid #222;
356
+ }
357
+
358
+ .qbs-autocomplete-checkbox-container {
359
+ gap: 8px;
360
+ padding: 6px 8px;
361
+ align-items: start;
362
+ }
363
+
364
+ .qbs-autocomplete-checkbox-container .qbs-autocomplete-suggestions-item {
365
+ padding: 0;
366
+ pointer-events: none;
367
+ }
368
+
369
+ .qbs-autocomplete-checkbox-container:hover {
370
+ background: #f8f8f8;
371
+ border-radius: 6px;
372
+ }
373
+
374
+ .qbs-autocomplete-checkbox-container.is-selected {
375
+ background: #f8f8f8;
376
+ border-radius: 6px;
377
+ }
378
+
379
+ .qbs-autocomplete-checkbox {
380
+ position: relative;
381
+ display: flex;
382
+ align-items: center;
383
+ justify-content: center;
384
+ }
385
+
386
+ .qbs-autocomplete-checkbox input {
387
+ opacity: 0;
388
+ }
389
+
390
+ .qbs-autocomplete-checkbox input ~ label {
391
+ position: absolute;
392
+ border-radius: 3px;
393
+ border: 1px solid #999696;
394
+ width: 16px;
395
+ height: 16px;
396
+ top: 3px;
397
+ transition: all 0.2s ease;
398
+ cursor: pointer;
399
+ }
400
+
401
+ .qbs-autocomplete-checkbox input ~ label svg {
402
+ opacity: 0;
403
+ transition: all 0.2s ease;
404
+ position: absolute;
405
+ left: 3px;
406
+ top: 3px;
407
+ width: 9px;
408
+ height: 9px;
409
+ }
410
+
411
+ .qbs-autocomplete-checkbox input:checked ~ label {
412
+ transition: all 0.2s ease;
413
+ border-radius: 3px;
414
+ background: #e76458;
415
+ border-color: #e76458;
416
+ }
417
+ .qbs-autocomplete-checkbox input:checked ~ label svg {
418
+ opacity: 1;
419
+ transition: all 0.2s ease;
420
+ }
421
+
422
+ .action_label {
423
+ font-size: 14px;
424
+ color: #4c7ad6;
425
+ }
426
+ /* Tooltip.css */
427
+ /* .tooltip-wrapper {
428
+ position: relative;
429
+ display: inline-block;
430
+ }
431
+
432
+ .tooltip-content {
433
+ visibility: hidden;
434
+ width: max-content;
435
+ background-color: black;
436
+ color: white;
437
+ text-align: center;
438
+ max-width: 150px;
439
+ padding: 5px 10px;
440
+ border-radius: 6px;
441
+ position: absolute;
442
+ z-index: 1;
443
+ bottom: 125%;
444
+ left: 50%;
445
+ transform: translateX(-50%);
446
+ transition: visibility 0.2s ease-in-out;
447
+ }
448
+
449
+ .tooltip-content::after {
450
+ content: '';
451
+ position: absolute;
452
+ top: 100%;
453
+ left: 50%;
454
+ margin-left: -5px;
455
+ border-width: 5px;
456
+ border-style: solid;
457
+ border-color: black transparent transparent transparent;
458
+ }
459
+
460
+ .tooltip-wrapper:hover .tooltip-content {
461
+ visibility: visible;
462
+ } */
463
+ .qbs-table-tooltip {
464
+ position: relative;
465
+ display: contents;
466
+ cursor: pointer;
467
+ }
468
+
469
+ .qbs-table-tooltip .tooltiptext {
470
+ visibility: hidden;
471
+ background-color: #000;
472
+ color: #fff;
473
+ text-align: center;
474
+ padding: 6px;
475
+ border-radius: 4px;
476
+ position: absolute;
477
+ z-index: 9999;
478
+ opacity: 0;
479
+ transition: opacity 0.3s;
480
+ font-size: 14px;
481
+ font-style: normal;
482
+ font-weight: 400;
483
+ line-height: 16px;
484
+ max-width: 300px;
485
+ }
486
+
487
+ .qbs-table-tooltip.up .tooltiptext {
488
+ bottom: 125%;
489
+ left: 0%;
490
+ }
491
+
492
+ .qbs-table-tooltip.down .tooltiptext {
493
+ top: 125%;
494
+ right: 0px;
495
+ left: auto;
496
+ }
497
+
498
+ .qbs-table-tooltip:hover .tooltiptext {
499
+ visibility: visible;
500
+ opacity: 1;
501
+ }
502
+
503
+ .qbs-table-tooltip .tooltiptext::after {
504
+ content: '';
505
+ position: absolute;
506
+ border-width: 5px;
507
+ border-style: solid;
508
+ }
509
+
510
+ .qbs-table-tooltip.up .tooltiptext::after {
511
+ top: 100%;
512
+ left: 50%;
513
+ margin-left: -5px;
514
+ border-color: #000 transparent transparent transparent;
515
+ }
516
+
517
+ .qbs-table-tooltip.down .tooltiptext::after {
518
+ bottom: 100%;
519
+ left: 50%;
520
+ margin-left: -5px;
521
+ border-color: transparent transparent #000 transparent;
522
+ }
@@ -0,0 +1 @@
1
+ @import './components/autocomplete.css';
@@ -0,0 +1,83 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ type ValueProps = {
4
+ [key: string]: string;
5
+ };
6
+
7
+ type UseSuggestionsType = (
8
+ getData: (key?: string, next?: number) => Promise<ValueProps[]>,
9
+ initialData?: ValueProps[],
10
+ dropOpen?: boolean,
11
+ asyncFetch?: boolean,
12
+ paginationEnabled?: boolean,
13
+ initialLoad?: boolean,
14
+ inputValue?: string,
15
+ isMultiple?: boolean,
16
+ setNextPage?: (value: number) => void,
17
+ selectedItems?: any[]
18
+ ) => {
19
+ suggestions: ValueProps[];
20
+ isLoading: boolean;
21
+
22
+ handlePickSuggestions: (
23
+ value?: string,
24
+ next?: number,
25
+ append?: boolean
26
+ ) => Promise<void>;
27
+ };
28
+
29
+ export const useSuggestions: UseSuggestionsType = (
30
+ getData,
31
+ initialData = [],
32
+ dropOpen = false,
33
+ asyncFetch = false,
34
+ paginationEnabled = false,
35
+ initialLoad = false,
36
+ inputValue = '',
37
+ isMultiple,
38
+ setNextPage,
39
+ selectedItems = []
40
+ ) => {
41
+ const [suggestions, setSuggestions] = useState<ValueProps[]>(initialData);
42
+ const [isLoading, setIsLoading] = useState<boolean>(false);
43
+
44
+ const handlePickSuggestions = async (
45
+ value?: string,
46
+ nextPage?: number,
47
+ appendData?: boolean
48
+ ) => {
49
+ setIsLoading(true);
50
+ try {
51
+ const data = await (asyncFetch || initialLoad
52
+ ? getData(value, nextPage)
53
+ : Promise.resolve(initialData));
54
+ if (!data || data?.length === 0) {
55
+ setNextPage(undefined);
56
+ }
57
+ const newSuggestions = appendData ? [...suggestions, ...data] : data;
58
+ setSuggestions(newSuggestions);
59
+ } catch (error) {
60
+ console.error('Error fetching data:', error);
61
+ } finally {
62
+ setIsLoading(false);
63
+ }
64
+ };
65
+
66
+ useEffect(() => {
67
+ if (dropOpen) {
68
+ if (!isMultiple && (!inputValue || suggestions.length === 0)) {
69
+ setNextPage(1);
70
+ handlePickSuggestions('', paginationEnabled ? 1 : undefined);
71
+ } else if (
72
+ isMultiple &&
73
+ (suggestions.length === 0 ||
74
+ !selectedItems ||
75
+ selectedItems?.length === 0)
76
+ ) {
77
+ handlePickSuggestions('', paginationEnabled ? 1 : undefined);
78
+ }
79
+ }
80
+ }, [dropOpen]);
81
+
82
+ return { suggestions, isLoading, handlePickSuggestions };
83
+ };
@@ -0,0 +1,15 @@
1
+ export function debounce<F extends (...args: any[]) => any>(
2
+ fn: F,
3
+ delay: number
4
+ ): (...args: Parameters<F>) => void {
5
+ let timerId: NodeJS.Timeout | null = null;
6
+ return (...args: Parameters<F>): void => {
7
+ if (timerId) {
8
+ clearTimeout(timerId);
9
+ }
10
+ timerId = setTimeout(() => {
11
+ fn(...args);
12
+ timerId = null;
13
+ }, delay);
14
+ };
15
+ }
@@ -0,0 +1,54 @@
1
+ export function deepEqual(value1: any, value2: any): boolean {
2
+ // Check for strict equality first
3
+ if (value1 === value2) {
4
+ return true;
5
+ }
6
+
7
+ // If either is null (but not both), they're not equal
8
+ if (value1 === null || value2 === null) {
9
+ return false;
10
+ }
11
+
12
+ // If types differ, they're not equal
13
+ if (typeof value1 !== typeof value2) {
14
+ return false;
15
+ }
16
+
17
+ // Check objects (including arrays)
18
+ if (typeof value1 === 'object' && typeof value2 === 'object') {
19
+ // Different constructors means they are different objects
20
+ if (value1.constructor !== value2.constructor) {
21
+ return false;
22
+ }
23
+
24
+ if (Array.isArray(value1)) {
25
+ // Array length comparison
26
+ if (value1.length !== value2.length) {
27
+ return false;
28
+ }
29
+ // Deep compare each element
30
+ for (let i = 0; i < value1.length; i++) {
31
+ if (!deepEqual(value1[i], value2[i])) {
32
+ return false;
33
+ }
34
+ }
35
+ return true;
36
+ } else {
37
+ // Compare object keys and values
38
+ const keys1 = Object.keys(value1);
39
+ const keys2 = new Set(Object.keys(value2));
40
+ if (keys1.length !== keys2.size) {
41
+ return false;
42
+ }
43
+ for (const key of keys1) {
44
+ if (!keys2.has(key) || !deepEqual(value1[key], value2[key])) {
45
+ return false;
46
+ }
47
+ }
48
+ return true;
49
+ }
50
+ }
51
+
52
+ // If none of the above, they're not equal
53
+ return false;
54
+ }
@@ -0,0 +1,46 @@
1
+ interface Item {
2
+ [key: string]: string;
3
+ }
4
+
5
+ export const filterSuggestions = (
6
+ data: Item[],
7
+ query: string,
8
+ type: string,
9
+ desc: string,
10
+ inputValue?: string,
11
+ async?: boolean
12
+ ): Item[] => {
13
+ if (
14
+ (type === 'custom_search_select' ||
15
+ type === 'auto_complete' ||
16
+ type === 'auto_suggestion') &&
17
+ !async &&
18
+ query
19
+ ) {
20
+ return data?.filter((item) =>
21
+ item[desc].toLowerCase().includes(query.toLowerCase())
22
+ );
23
+ }
24
+ return sortedArrayData(data, inputValue, desc);
25
+ };
26
+
27
+ const sortedArrayData = (
28
+ filteredData: any[],
29
+ selectedItems: any[] | string,
30
+ desc: any
31
+ ) => {
32
+ return [...filteredData].sort((a, b) => {
33
+ let aIsSelected: boolean;
34
+ let bIsSelected: boolean;
35
+
36
+ if (Array.isArray(selectedItems)) {
37
+ aIsSelected = selectedItems.some((item) => item[desc] === a[desc]);
38
+ bIsSelected = selectedItems.some((item) => item[desc] === b[desc]);
39
+ } else {
40
+ aIsSelected = a[desc] === selectedItems;
41
+ bIsSelected = b[desc] === selectedItems;
42
+ }
43
+
44
+ return (bIsSelected ? 1 : 0) - (aIsSelected ? 1 : 0);
45
+ });
46
+ };