pixel-react 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
  3. package/lib/components/MultiSelect/MultiSelectTypes.d.ts +2 -0
  4. package/lib/components/MultiSelect/dropdownTypes.d.ts +2 -0
  5. package/lib/index.d.ts +3 -1
  6. package/lib/index.esm.js +502 -2317
  7. package/lib/index.esm.js.map +1 -1
  8. package/lib/index.js +502 -2318
  9. package/lib/index.js.map +1 -1
  10. package/lib/tsconfig.tsbuildinfo +1 -1
  11. package/lib/utils/compareArrays/compareArrays.d.ts +11 -0
  12. package/lib/utils/compareArrays/compareArrays.stories.d.ts +6 -0
  13. package/lib/utils/compareObjects/compareObjects.d.ts +2 -0
  14. package/lib/utils/compareObjects/compareObjects.stories.d.ts +6 -0
  15. package/lib/utils/debounce/debounce.d.ts +6 -0
  16. package/lib/utils/debounce/debounce.stories.d.ts +6 -0
  17. package/lib/utils/find/findAndInsert.d.ts +7 -0
  18. package/lib/utils/find/findAndInsert.stories.d.ts +7 -0
  19. package/lib/utils/throttle/throttle.d.ts +6 -0
  20. package/lib/utils/throttle/throttle.stories.d.ts +6 -0
  21. package/package.json +3 -1
  22. package/rollup.config.mjs +7 -5
  23. package/src/assets/icons/filter.svg +5 -0
  24. package/src/components/Icon/iconList.ts +2 -0
  25. package/src/components/MultiSelect/Dropdown.scss +27 -16
  26. package/src/components/MultiSelect/Dropdown.tsx +51 -28
  27. package/src/components/MultiSelect/MultiSelect.stories.tsx +9 -5
  28. package/src/components/MultiSelect/MultiSelect.tsx +4 -0
  29. package/src/components/MultiSelect/MultiSelectTypes.ts +2 -0
  30. package/src/components/MultiSelect/dropdownTypes.ts +2 -0
  31. package/src/index.ts +1 -4
  32. package/src/utils/checkEmpty/checkEmpty.stories.tsx +1 -1
  33. package/src/utils/checkEmpty/checkEmpty.ts +21 -7
  34. package/src/utils/compareArrays/compareArrays.stories.tsx +62 -0
  35. package/src/utils/compareArrays/compareArrays.ts +31 -0
  36. package/src/utils/compareObjects/compareObjects.stories.tsx +51 -0
  37. package/src/utils/compareObjects/compareObjects.ts +53 -0
  38. package/src/utils/debounce/debounce.stories.tsx +81 -0
  39. package/src/utils/debounce/debounce.ts +28 -0
  40. package/src/utils/find/findAndInsert.stories.tsx +119 -0
  41. package/src/utils/find/findAndInsert.ts +49 -0
  42. package/src/utils/throttle/throttle.stories.tsx +100 -0
  43. package/src/utils/throttle/throttle.ts +33 -0
  44. package/vite.config.js +1 -17
@@ -0,0 +1,51 @@
1
+ import { compareObjects } from './compareObjects'; // Adjust the import path as necessary
2
+
3
+ export default {
4
+ title: 'Utils/compareObjects',
5
+ component: compareObjects,
6
+ };
7
+
8
+ export const Default = () => {
9
+ const testCases = [
10
+ {
11
+ obj1: { a: 1, b: [2, { c: 3 }] },
12
+ obj2: { a: 1, b: [2, { c: 3 }] },
13
+ expected: true,
14
+ },
15
+ {
16
+ obj1: { a: 1, b: [2, { c: 3 }] },
17
+ obj2: { a: 1, b: [3, 2] },
18
+ expected: false,
19
+ },
20
+ {
21
+ obj1: { a: 1, b: { c: 2 } },
22
+ obj2: { a: 1, b: { c: 2 } },
23
+ expected: true,
24
+ },
25
+ {
26
+ obj1: { a: 1, b: { c: 2 } },
27
+ obj2: { a: 1, b: { c: 3 } },
28
+ expected: false,
29
+ },
30
+ { obj1: null, obj2: null, expected: true },
31
+ { obj1: { a: null }, obj2: { a: null }, expected: true },
32
+ { obj1: { a: 1 }, obj2: { a: null }, expected: false },
33
+ { obj1: {}, obj2: {}, expected: true },
34
+ { obj1: { a: 0 }, obj2: { a: 0 }, expected: true },
35
+ { obj1: { a: 0 }, obj2: { a: 1 }, expected: false },
36
+ ];
37
+
38
+ return (
39
+ <div>
40
+ <h1>
41
+ <u>compareObjects(obj1, obj2)</u> - true / false
42
+ </h1>
43
+ {testCases.map(({ obj1, obj2, expected }, index) => (
44
+ <div key={index}>
45
+ compareObjects({JSON.stringify(obj1)}, {JSON.stringify(obj2)}) -
46
+ {compareObjects(obj1, obj2) === expected ? ' True' : ' False'}
47
+ </div>
48
+ ))}
49
+ </div>
50
+ );
51
+ };
@@ -0,0 +1,53 @@
1
+ // Define a type for any object
2
+ export type AnyObject = Record<string, unknown>;
3
+
4
+ export const compareObjects = (
5
+ obj1: AnyObject | null,
6
+ obj2: AnyObject | null
7
+ ): boolean => {
8
+ // Check if both are strictly equal (handles primitive types and same reference)
9
+ if (obj1 === obj2) return true;
10
+
11
+ // Check if either is null or not an object
12
+ if (
13
+ obj1 == null ||
14
+ obj2 == null ||
15
+ typeof obj1 !== 'object' ||
16
+ typeof obj2 !== 'object'
17
+ ) {
18
+ return false;
19
+ }
20
+
21
+ // Handle array comparison
22
+ const isArray1 = Array.isArray(obj1);
23
+ const isArray2 = Array.isArray(obj2);
24
+ if (isArray1 !== isArray2) return false; // One is an array, the other is not
25
+
26
+ // Create arrays of keys for both objects
27
+ const keys1 = isArray1 ? obj1 : Object.keys(obj1);
28
+ const keys2 = isArray2 ? obj2 : Object.keys(obj2);
29
+
30
+ // Check if the number of keys is different
31
+ if (keys1.length !== keys2.length) return false;
32
+
33
+ // Create a Set for keys2 for O(1) lookups (only for objects)
34
+ if (!isArray1) {
35
+ const keysSet2 = new Set<string>(keys2 as string[]);
36
+
37
+ // Check each key and value
38
+ return keys1.every((key) => {
39
+ return (
40
+ keysSet2.has(key) &&
41
+ compareObjects(
42
+ obj1[key] as AnyObject | null,
43
+ obj2[key] as AnyObject | null
44
+ )
45
+ );
46
+ });
47
+ } else {
48
+ // If arrays, compare elements directly
49
+ return keys1.every((item, index) =>
50
+ compareObjects(item as AnyObject | null, keys2[index] as AnyObject | null)
51
+ );
52
+ }
53
+ };
@@ -0,0 +1,81 @@
1
+ import { debounce } from './debounce'; // Adjust the import path as necessary
2
+
3
+ export default {
4
+ title: 'Utils/debounce',
5
+ component: debounce,
6
+ };
7
+
8
+ export const Default = () => {
9
+ const testCases = [
10
+ {
11
+ description: 'Basic function call',
12
+ expectedOutput: 'Function called! (after delay)',
13
+ delay: 300,
14
+ setup: () => {
15
+ const debouncedFunc = debounce(
16
+ () => console.log('Function called!'),
17
+ 300
18
+ );
19
+ debouncedFunc(); // Call the debounced function
20
+ },
21
+ code: `const debouncedFunc = debounce(() => console.log('Function called!'), 300);\ndebouncedFunc();`,
22
+ },
23
+ {
24
+ description: 'Rapid calls within delay',
25
+ expectedOutput: 'Debounced call! (only once after delay)',
26
+ delay: 500,
27
+ setup: () => {
28
+ const debouncedFunc = debounce(
29
+ () => console.log('Debounced call!'),
30
+ 500
31
+ );
32
+ for (let i = 0; i < 5; i++) {
33
+ debouncedFunc(); // Call the debounced function multiple times
34
+ }
35
+ },
36
+ code: `const debouncedFunc = debounce(() => console.log('Debounced call!'), 500);\nfor (let i = 0; i < 5; i++) {\n debouncedFunc();\n}`,
37
+ },
38
+ {
39
+ description: 'Cancel debounced function',
40
+ expectedOutput: 'Function should not be called if canceled',
41
+ delay: 200,
42
+ setup: () => {
43
+ const debouncedFunc = debounce(
44
+ () => console.log('Should not be called!'),
45
+ 200
46
+ );
47
+ debouncedFunc(); // Call the debounced function
48
+ debouncedFunc.cancel(); // Cancel the function
49
+ },
50
+ code: `const debouncedFunc = debounce(() => console.log('Should not be called!'), 200);\ndebouncedFunc();\ndebouncedFunc.cancel();`,
51
+ },
52
+ ];
53
+
54
+ return (
55
+ <div>
56
+ <h1>
57
+ <u>debounce(function, delay)</u> - Demonstrating debounce functionality
58
+ </h1>
59
+ {testCases.map(
60
+ ({ description, expectedOutput, delay, setup, code }, index) => (
61
+ <div key={index}>
62
+ <h3>{description}</h3>
63
+ <button
64
+ onClick={() => {
65
+ setup(); // Run the setup for the test case
66
+ setTimeout(() => {
67
+ console.log(expectedOutput);
68
+ }, delay + 100); // Wait a bit longer than the delay to check output
69
+ }}
70
+ >
71
+ Run Test
72
+ </button>
73
+ <pre>
74
+ <code>{code}</code>
75
+ </pre>
76
+ </div>
77
+ )
78
+ )}
79
+ </div>
80
+ );
81
+ };
@@ -0,0 +1,28 @@
1
+ type Callback = (...args: any[]) => void;
2
+
3
+ // Export the DebouncedFunction interface to make it publicly accessible
4
+ export interface DebouncedFunction extends Function {
5
+ cancel: () => void;
6
+ }
7
+
8
+ export const debounce = (func: Callback, delay: number): DebouncedFunction => {
9
+ let timeoutId: ReturnType<typeof setTimeout> | null = null;
10
+
11
+ const debounced: DebouncedFunction = function (this: any, ...args: any[]) {
12
+ // Clear the previous timeout if it exists
13
+ if (timeoutId) clearTimeout(timeoutId);
14
+
15
+ // Set a new timeout
16
+ timeoutId = setTimeout(() => {
17
+ func.apply(this, args);
18
+ }, delay);
19
+ };
20
+
21
+ // Method to cancel the debounced function
22
+ debounced.cancel = () => {
23
+ if (timeoutId) clearTimeout(timeoutId);
24
+ timeoutId = null;
25
+ };
26
+
27
+ return debounced;
28
+ };
@@ -0,0 +1,119 @@
1
+ // findAndInsert.stories.tsx
2
+ import { useState } from 'react';
3
+ import { findAndInsert, AnyObject } from './findAndInsert';
4
+
5
+ export default {
6
+ title: 'Utils/findAndInsert',
7
+ component: findAndInsert,
8
+ };
9
+
10
+ const initialData: AnyObject[] = [
11
+ { id: 1, name: 'Object 1' },
12
+ {
13
+ id: 2,
14
+ name: 'Object 2',
15
+ children: [
16
+ { id: 3, name: 'Child 1', children: [{ id: 5, name: 'SubChild 1' }] },
17
+ { id: 4, name: 'Child 2' },
18
+ ],
19
+ },
20
+ ];
21
+
22
+ export const InteractivePlayground = () => {
23
+ const [data, setData] = useState<AnyObject[]>(initialData);
24
+ const [selectedId, setSelectedId] = useState<number | null>(null);
25
+ const [newEntryName, setNewEntryName] = useState<string>('New Object');
26
+ const [insertPosition, setInsertPosition] = useState<
27
+ 'above' | 'below' | 'replace'
28
+ >('below');
29
+
30
+ const handleInsert = () => {
31
+ if (selectedId !== null) {
32
+ const newEntry = { id: Date.now(), name: newEntryName };
33
+ const result = findAndInsert(
34
+ data,
35
+ 'id',
36
+ selectedId,
37
+ newEntry,
38
+ insertPosition,
39
+ 'children'
40
+ );
41
+ if (result) {
42
+ setData(result.updatedArray);
43
+ } else {
44
+ alert('Item not found in nested structure');
45
+ }
46
+ }
47
+ };
48
+
49
+ const generateOptions = (
50
+ data: AnyObject[],
51
+ prefix = ''
52
+ ): { id: number; label: string }[] => {
53
+ const options: { id: number; label: string }[] = [];
54
+ function recurse(items: AnyObject[], levelPrefix: string) {
55
+ items.forEach((item) => {
56
+ options.push({
57
+ id: item.id,
58
+ label: `${levelPrefix}${item.name} (ID: ${item.id})`,
59
+ });
60
+ if (item.children) recurse(item.children, `${levelPrefix}- `);
61
+ });
62
+ }
63
+ recurse(data, prefix);
64
+ return options;
65
+ };
66
+
67
+ const options = generateOptions(data);
68
+
69
+ return (
70
+ <div>
71
+ <h1>Interactive Playground for findAndInsert</h1>
72
+ <label htmlFor="targetId">Select Object:</label>
73
+ <select
74
+ id="targetId"
75
+ onChange={(e) => setSelectedId(Number(e.target.value))}
76
+ value={selectedId !== null ? selectedId : ''}
77
+ >
78
+ <option value="" disabled>
79
+ Select an object
80
+ </option>
81
+ {options.map((option) => (
82
+ <option key={option.id} value={option.id}>
83
+ {option.label}
84
+ </option>
85
+ ))}
86
+ </select>
87
+
88
+ <div>
89
+ <label htmlFor="newEntryName">New Entry Name:</label>
90
+ <input
91
+ type="text"
92
+ id="newEntryName"
93
+ value={newEntryName}
94
+ onChange={(e) => setNewEntryName(e.target.value)}
95
+ />
96
+ </div>
97
+
98
+ <div>
99
+ <label htmlFor="insertPosition">Insert Position:</label>
100
+ <select
101
+ id="insertPosition"
102
+ value={insertPosition}
103
+ onChange={(e) =>
104
+ setInsertPosition(e.target.value as 'above' | 'below' | 'replace')
105
+ }
106
+ >
107
+ <option value="above">Above</option>
108
+ <option value="below">Below</option>
109
+ <option value="replace">Replace</option>
110
+ </select>
111
+ </div>
112
+
113
+ <button onClick={handleInsert}>Insert Entry</button>
114
+
115
+ <h2>Current Data:</h2>
116
+ <pre>{JSON.stringify(data, null, 2)}</pre>
117
+ </div>
118
+ );
119
+ };
@@ -0,0 +1,49 @@
1
+ // findAndInsert.ts
2
+ export type AnyObject = { id: number; [key: string]: any };
3
+
4
+ export function findAndInsert<T extends AnyObject>(
5
+ data: T[],
6
+ key: keyof T,
7
+ targetId: number,
8
+ newEntry: T,
9
+ insertPosition: 'above' | 'below' | 'replace',
10
+ childrenKey: string = 'children' // Allow dynamic key for nested children
11
+ ): { updatedArray: T[] } | null {
12
+ function recursiveSearch(items: T[]): { updatedArray: T[] } | null {
13
+ for (let i = 0; i < items.length; i++) {
14
+ const item = items[i];
15
+
16
+ // Check if the item matches the target id
17
+ if (item && item[key] === targetId) {
18
+ const updatedItems = [...items];
19
+
20
+ if (insertPosition === 'replace') {
21
+ updatedItems[i] = newEntry; // Replace the current item
22
+ } else {
23
+ // Insert above or below
24
+ updatedItems.splice(
25
+ insertPosition === 'above' ? i : i + 1,
26
+ 0,
27
+ newEntry
28
+ );
29
+ }
30
+
31
+ return { updatedArray: updatedItems };
32
+ }
33
+
34
+ // Dynamically check nested children using the `childrenKey`
35
+ if (item && item[childrenKey] && Array.isArray(item[childrenKey])) {
36
+ const result = recursiveSearch(item[childrenKey] as T[]);
37
+ if (result) {
38
+ return {
39
+ updatedArray: items.map((x, idx) =>
40
+ idx === i ? { ...x, [childrenKey]: result.updatedArray } : x
41
+ ),
42
+ };
43
+ }
44
+ }
45
+ }
46
+ return null;
47
+ }
48
+ return recursiveSearch(data);
49
+ }
@@ -0,0 +1,100 @@
1
+ import { throttle } from './throttle'; // Adjust the import path as necessary
2
+
3
+ export default {
4
+ title: 'Utils/throttle',
5
+ component: throttle,
6
+ };
7
+
8
+ export const Default = () => {
9
+ const testCases = [
10
+ {
11
+ description: 'Basic function call',
12
+ expectedOutput: 'Function called! (at most once every 300ms)',
13
+ limit: 300,
14
+ setup: () => {
15
+ const throttledFunc = throttle(
16
+ () => console.log('Function called!'),
17
+ 300
18
+ );
19
+ for (let i = 0; i < 5; i++) {
20
+ throttledFunc(); // Call the throttled function multiple times
21
+ }
22
+ },
23
+ code: `const throttledFunc = throttle(() => console.log('Function called!'), 300);\nfor (let i = 0; i < 5; i++) {\n throttledFunc();\n}`,
24
+ },
25
+ {
26
+ description: 'Throttling with rapid calls',
27
+ expectedOutput: 'Function called! (at most once every 500ms)',
28
+ limit: 500,
29
+ setup: () => {
30
+ const throttledFunc = throttle(
31
+ () => console.log('Throttled call!'),
32
+ 500
33
+ );
34
+ for (let i = 0; i < 10; i++) {
35
+ throttledFunc(); // Call the throttled function rapidly
36
+ }
37
+ },
38
+ code: `const throttledFunc = throttle(() => console.log('Throttled call!'), 500);\nfor (let i = 0; i < 10; i++) {\n throttledFunc();\n}`,
39
+ },
40
+ {
41
+ description: 'Cancel throttled function',
42
+ expectedOutput: 'Function should not be called if canceled',
43
+ limit: 200,
44
+ setup: () => {
45
+ const throttledFunc = throttle(
46
+ () => console.log('Should not be called!'),
47
+ 200
48
+ );
49
+ throttledFunc(); // Call the throttled function
50
+ throttledFunc.cancel(); // Cancel the function
51
+ },
52
+ code: `const throttledFunc = throttle(() => console.log('Should not be called!'), 200);\nthrottledFunc();\nthrottledFunc.cancel();`,
53
+ },
54
+ {
55
+ description: 'Scroll event handling',
56
+ expectedOutput: 'Scroll event handled (at most once every 400ms)',
57
+ limit: 400,
58
+ setup: () => {
59
+ const throttledScroll = throttle(
60
+ () => console.log('Scroll event handled'),
61
+ 400
62
+ );
63
+
64
+ // Simulating rapid scroll events
65
+ for (let i = 0; i < 10; i++) {
66
+ throttledScroll(); // Simulate scroll event
67
+ }
68
+ },
69
+ code: `const throttledScroll = throttle(() => console.log('Scroll event handled'), 400);\nfor (let i = 0; i < 10; i++) {\n throttledScroll();\n}`,
70
+ },
71
+ ];
72
+
73
+ return (
74
+ <div>
75
+ <h1>
76
+ <u>throttle(function, limit)</u> - Demonstrating throttle functionality
77
+ </h1>
78
+ {testCases.map(
79
+ ({ description, expectedOutput, limit, setup, code }, index) => (
80
+ <div key={index}>
81
+ <h3>{description}</h3>
82
+ <button
83
+ onClick={() => {
84
+ setup(); // Run the setup for the test case
85
+ setTimeout(() => {
86
+ console.log(expectedOutput);
87
+ }, limit + 100); // Wait a bit longer than the limit to check output
88
+ }}
89
+ >
90
+ Run Test
91
+ </button>
92
+ <pre>
93
+ <code>{code}</code>
94
+ </pre>
95
+ </div>
96
+ )
97
+ )}
98
+ </div>
99
+ );
100
+ };
@@ -0,0 +1,33 @@
1
+ type Callback = (...args: any[]) => void;
2
+
3
+ export interface ThrottledFunction extends Function {
4
+ cancel: () => void;
5
+ }
6
+
7
+ export const throttle = (func: Callback, limit: number): ThrottledFunction => {
8
+ let lastFunc: ReturnType<typeof setTimeout> | null;
9
+ let lastRan: number | null = null;
10
+
11
+ const throttled: ThrottledFunction = function (this: any, ...args: any[]) {
12
+ const context = this;
13
+ if (lastRan === null || Date.now() - lastRan >= limit) {
14
+ func.apply(context, args);
15
+ lastRan = Date.now();
16
+ } else {
17
+ if (lastFunc) clearTimeout(lastFunc);
18
+ lastFunc = setTimeout(() => {
19
+ func.apply(context, args);
20
+ lastRan = Date.now();
21
+ }, limit - (Date.now() - lastRan));
22
+ }
23
+ };
24
+
25
+ // Method to cancel the throttled function
26
+ throttled.cancel = () => {
27
+ if (lastFunc) clearTimeout(lastFunc);
28
+ lastFunc = null;
29
+ lastRan = null;
30
+ };
31
+
32
+ return throttled;
33
+ };
package/vite.config.js CHANGED
@@ -4,27 +4,11 @@ import svgrPlugin from 'vite-plugin-svgr';
4
4
 
5
5
  export default {
6
6
  plugins: [
7
- react(),
7
+ react({ fastRefresh: false }),
8
8
  svgrPlugin({
9
9
  svgrOptions: {
10
10
  icon: true,
11
11
  },
12
12
  }),
13
13
  ],
14
-
15
- // resolve: {
16
- // alias: {
17
- // '@components': path.resolve(__dirname, './src/components'),
18
- // '@styles': path.resolve(__dirname, './src/assets/styles'),
19
- // '@icons': path.resolve(__dirname, './src/assets/icons'),
20
- // },
21
- // },
22
-
23
- // css: {
24
- // preprocessorOptions: {
25
- // scss: {
26
- // additionalData: `@import "./src/assets/styles/_colors.scss";`,
27
- // },
28
- // },
29
- // },
30
14
  };