pixel-react 1.0.1 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- package/.yarn/install-state.gz +0 -0
- package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
- package/lib/components/MultiSelect/MultiSelectTypes.d.ts +2 -0
- package/lib/components/MultiSelect/dropdownTypes.d.ts +2 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.esm.js +512 -2327
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +512 -2328
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/compareArrays/compareArrays.d.ts +11 -0
- package/lib/utils/compareArrays/compareArrays.stories.d.ts +6 -0
- package/lib/utils/compareObjects/compareObjects.d.ts +2 -0
- package/lib/utils/compareObjects/compareObjects.stories.d.ts +6 -0
- package/lib/utils/debounce/debounce.d.ts +6 -0
- package/lib/utils/debounce/debounce.stories.d.ts +6 -0
- package/lib/utils/find/findAndInsert.d.ts +7 -0
- package/lib/utils/find/findAndInsert.stories.d.ts +7 -0
- package/lib/utils/throttle/throttle.d.ts +6 -0
- package/lib/utils/throttle/throttle.stories.d.ts +6 -0
- package/package.json +3 -1
- package/rollup.config.mjs +10 -5
- package/src/StyleGuide/ColorPalette/ColorPalette.scss +4 -5
- package/src/StyleGuide/Typography/Typography.scss +4 -5
- package/src/assets/Themes/Theme.scss +7 -191
- package/src/assets/icons/filter.svg +5 -0
- package/src/components/Accordion/Accordion.scss +1 -2
- package/src/components/Button/Button.scss +1 -1
- package/src/components/Charts/DonutChart/DonutChart.scss +1 -1
- package/src/components/Charts/RadialChart/RadialChart.scss +1 -1
- package/src/components/Drawer/Drawer.scss +9 -10
- package/src/components/ExpandableMenu/ExpandableMenu.scss +1 -1
- package/src/components/Icon/Icons.scss +5 -6
- package/src/components/Icon/iconList.ts +2 -0
- package/src/components/MenuOption/MenuOption.scss +1 -1
- package/src/components/MultiSelect/Dropdown.scss +27 -16
- package/src/components/MultiSelect/Dropdown.tsx +51 -28
- package/src/components/MultiSelect/MultiSelect.scss +1 -1
- package/src/components/MultiSelect/MultiSelect.stories.tsx +9 -5
- package/src/components/MultiSelect/MultiSelect.tsx +4 -0
- package/src/components/MultiSelect/MultiSelectTypes.ts +2 -0
- package/src/components/MultiSelect/dropdownTypes.ts +2 -0
- package/src/components/RadioButton/RadioButton.scss +2 -3
- package/src/components/Search/Search.scss +1 -1
- package/src/components/Table/Table.scss +1 -1
- package/src/components/TextArea/Textarea.scss +1 -2
- package/src/components/Toggle/Toggle.scss +5 -4
- package/src/components/Tooltip/Tooltip.scss +1 -1
- package/src/index.ts +1 -4
- package/src/utils/checkEmpty/checkEmpty.stories.tsx +1 -1
- package/src/utils/checkEmpty/checkEmpty.ts +21 -7
- package/src/utils/compareArrays/compareArrays.stories.tsx +62 -0
- package/src/utils/compareArrays/compareArrays.ts +31 -0
- package/src/utils/compareObjects/compareObjects.stories.tsx +51 -0
- package/src/utils/compareObjects/compareObjects.ts +53 -0
- package/src/utils/debounce/debounce.stories.tsx +81 -0
- package/src/utils/debounce/debounce.ts +28 -0
- package/src/utils/find/findAndInsert.stories.tsx +119 -0
- package/src/utils/find/findAndInsert.ts +49 -0
- package/src/utils/throttle/throttle.stories.tsx +100 -0
- package/src/utils/throttle/throttle.ts +33 -0
- package/vite.config.js +8 -16
@@ -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
@@ -11,20 +11,12 @@ export default {
|
|
11
11
|
},
|
12
12
|
}),
|
13
13
|
],
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
// css: {
|
24
|
-
// preprocessorOptions: {
|
25
|
-
// scss: {
|
26
|
-
// additionalData: `@import "./src/assets/styles/_colors.scss";`,
|
27
|
-
// },
|
28
|
-
// },
|
29
|
-
// },
|
14
|
+
css: {
|
15
|
+
preprocessorOptions: {
|
16
|
+
scss: {
|
17
|
+
// This option tells Vite to use Dart Sass for SCSS processing
|
18
|
+
implementation: require('sass'),
|
19
|
+
},
|
20
|
+
},
|
21
|
+
},
|
30
22
|
};
|