funda-ui 1.0.272
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.
- package/BackToTop/index.css +34 -0
- package/BackToTop/index.d.ts +11 -0
- package/BackToTop/index.js +458 -0
- package/CascadingSelect/index.css +159 -0
- package/CascadingSelect/index.d.ts +56 -0
- package/CascadingSelect/index.js +958 -0
- package/CascadingSelectE2E/index.css +159 -0
- package/CascadingSelectE2E/index.d.ts +60 -0
- package/CascadingSelectE2E/index.js +1126 -0
- package/Checkbox/index.d.ts +30 -0
- package/Checkbox/index.js +226 -0
- package/ColorPicker/index.css +38 -0
- package/ColorPicker/index.d.ts +27 -0
- package/ColorPicker/index.js +246 -0
- package/DigitalClock/index.d.ts +7 -0
- package/DigitalClock/index.js +208 -0
- package/DropdownMenu/index.css +127 -0
- package/DropdownMenu/index.d.ts +37 -0
- package/DropdownMenu/index.js +237 -0
- package/DynamicFields/index.d.ts +26 -0
- package/DynamicFields/index.js +412 -0
- package/File/index.d.ts +36 -0
- package/File/index.js +473 -0
- package/Input/index.d.ts +42 -0
- package/Input/index.js +286 -0
- package/LiveSearch/index.d.ts +37 -0
- package/LiveSearch/index.js +1195 -0
- package/ModalDialog/index.d.ts +60 -0
- package/ModalDialog/index.js +725 -0
- package/ModeSwitch/index.d.ts +17 -0
- package/ModeSwitch/index.js +202 -0
- package/MultiFuncSelect/index.css +178 -0
- package/MultiFuncSelect/index.d.ts +67 -0
- package/MultiFuncSelect/index.js +1826 -0
- package/MultilevelDropdownMenu/index.css +35 -0
- package/MultilevelDropdownMenu/index.d.ts +25 -0
- package/MultilevelDropdownMenu/index.js +464 -0
- package/Pagination/index.d.ts +49 -0
- package/Pagination/index.js +341 -0
- package/README.md +108 -0
- package/Radio/index.d.ts +31 -0
- package/Radio/index.js +246 -0
- package/RangeSlider/index.css +149 -0
- package/RangeSlider/index.d.ts +21 -0
- package/RangeSlider/index.js +730 -0
- package/ScrollReveal/index.css +23 -0
- package/ScrollReveal/index.d.ts +21 -0
- package/ScrollReveal/index.js +216 -0
- package/Scrollbar/index.css +168 -0
- package/Scrollbar/index.d.ts +15 -0
- package/Scrollbar/index.js +605 -0
- package/SearchBar/index.d.ts +32 -0
- package/SearchBar/index.js +246 -0
- package/Select/index.d.ts +34 -0
- package/Select/index.js +331 -0
- package/ShowMoreLess/index.css +23 -0
- package/ShowMoreLess/index.d.ts +30 -0
- package/ShowMoreLess/index.js +202 -0
- package/Switch/index.d.ts +29 -0
- package/Switch/index.js +211 -0
- package/Table/index.css +533 -0
- package/Table/index.d.ts +25 -0
- package/Table/index.js +2113 -0
- package/Tabs/index.d.ts +3 -0
- package/Tabs/index.js +323 -0
- package/TagInput/index.css +90 -0
- package/TagInput/index.d.ts +28 -0
- package/TagInput/index.js +370 -0
- package/Textarea/index.d.ts +30 -0
- package/Textarea/index.js +242 -0
- package/Toast/index.css +95 -0
- package/Toast/index.d.ts +35 -0
- package/Toast/index.js +340 -0
- package/Tooltip/index.css +240 -0
- package/Tooltip/index.d.ts +19 -0
- package/Tooltip/index.js +200 -0
- package/Tree/index.css +225 -0
- package/Tree/index.d.ts +37 -0
- package/Tree/index.js +1406 -0
- package/all.d.ts +33 -0
- package/all.js +35 -0
- package/lib/cjs/BackToTop/index.d.ts +11 -0
- package/lib/cjs/BackToTop/index.js +458 -0
- package/lib/cjs/CascadingSelect/index.d.ts +56 -0
- package/lib/cjs/CascadingSelect/index.js +958 -0
- package/lib/cjs/CascadingSelectE2E/index.d.ts +60 -0
- package/lib/cjs/CascadingSelectE2E/index.js +1126 -0
- package/lib/cjs/Checkbox/index.d.ts +30 -0
- package/lib/cjs/Checkbox/index.js +226 -0
- package/lib/cjs/ColorPicker/index.d.ts +27 -0
- package/lib/cjs/ColorPicker/index.js +246 -0
- package/lib/cjs/DigitalClock/index.d.ts +7 -0
- package/lib/cjs/DigitalClock/index.js +208 -0
- package/lib/cjs/DropdownMenu/index.d.ts +37 -0
- package/lib/cjs/DropdownMenu/index.js +237 -0
- package/lib/cjs/DynamicFields/index.d.ts +26 -0
- package/lib/cjs/DynamicFields/index.js +412 -0
- package/lib/cjs/File/index.d.ts +36 -0
- package/lib/cjs/File/index.js +473 -0
- package/lib/cjs/Input/index.d.ts +42 -0
- package/lib/cjs/Input/index.js +286 -0
- package/lib/cjs/LiveSearch/index.d.ts +37 -0
- package/lib/cjs/LiveSearch/index.js +1195 -0
- package/lib/cjs/ModalDialog/index.d.ts +60 -0
- package/lib/cjs/ModalDialog/index.js +725 -0
- package/lib/cjs/ModeSwitch/index.d.ts +17 -0
- package/lib/cjs/ModeSwitch/index.js +202 -0
- package/lib/cjs/MultiFuncSelect/index.d.ts +67 -0
- package/lib/cjs/MultiFuncSelect/index.js +1826 -0
- package/lib/cjs/MultilevelDropdownMenu/index.d.ts +25 -0
- package/lib/cjs/MultilevelDropdownMenu/index.js +464 -0
- package/lib/cjs/Pagination/index.d.ts +49 -0
- package/lib/cjs/Pagination/index.js +341 -0
- package/lib/cjs/Radio/index.d.ts +31 -0
- package/lib/cjs/Radio/index.js +246 -0
- package/lib/cjs/RangeSlider/index.d.ts +21 -0
- package/lib/cjs/RangeSlider/index.js +730 -0
- package/lib/cjs/ScrollReveal/index.d.ts +21 -0
- package/lib/cjs/ScrollReveal/index.js +216 -0
- package/lib/cjs/Scrollbar/index.d.ts +15 -0
- package/lib/cjs/Scrollbar/index.js +605 -0
- package/lib/cjs/SearchBar/index.d.ts +32 -0
- package/lib/cjs/SearchBar/index.js +246 -0
- package/lib/cjs/Select/index.d.ts +34 -0
- package/lib/cjs/Select/index.js +331 -0
- package/lib/cjs/ShowMoreLess/index.d.ts +30 -0
- package/lib/cjs/ShowMoreLess/index.js +202 -0
- package/lib/cjs/Switch/index.d.ts +29 -0
- package/lib/cjs/Switch/index.js +211 -0
- package/lib/cjs/Table/index.d.ts +25 -0
- package/lib/cjs/Table/index.js +2113 -0
- package/lib/cjs/Tabs/index.d.ts +3 -0
- package/lib/cjs/Tabs/index.js +323 -0
- package/lib/cjs/TagInput/index.d.ts +28 -0
- package/lib/cjs/TagInput/index.js +370 -0
- package/lib/cjs/Textarea/index.d.ts +30 -0
- package/lib/cjs/Textarea/index.js +242 -0
- package/lib/cjs/Toast/index.d.ts +35 -0
- package/lib/cjs/Toast/index.js +340 -0
- package/lib/cjs/Tooltip/index.d.ts +19 -0
- package/lib/cjs/Tooltip/index.js +200 -0
- package/lib/cjs/Tree/index.d.ts +37 -0
- package/lib/cjs/Tree/index.js +1406 -0
- package/lib/cjs/index.d.ts +33 -0
- package/lib/cjs/index.js +35 -0
- package/lib/css/BackToTop/index.css +34 -0
- package/lib/css/CascadingSelect/index.css +159 -0
- package/lib/css/CascadingSelectE2E/index.css +159 -0
- package/lib/css/ColorPicker/index.css +38 -0
- package/lib/css/DropdownMenu/index.css +127 -0
- package/lib/css/MultiFuncSelect/index.css +178 -0
- package/lib/css/MultilevelDropdownMenu/index.css +35 -0
- package/lib/css/RangeSlider/index.css +149 -0
- package/lib/css/ScrollReveal/index.css +23 -0
- package/lib/css/Scrollbar/index.css +168 -0
- package/lib/css/ShowMoreLess/index.css +23 -0
- package/lib/css/Table/index.css +533 -0
- package/lib/css/TagInput/index.css +90 -0
- package/lib/css/Toast/index.css +95 -0
- package/lib/css/Tooltip/index.css +240 -0
- package/lib/css/Tree/index.css +225 -0
- package/lib/esm/BackToTop/index.scss +47 -0
- package/lib/esm/BackToTop/index.tsx +182 -0
- package/lib/esm/BackToTop/utils/easing.js +200 -0
- package/lib/esm/BackToTop/utils/performance.js +52 -0
- package/lib/esm/CascadingSelect/Group.tsx +39 -0
- package/lib/esm/CascadingSelect/index.scss +214 -0
- package/lib/esm/CascadingSelect/index.tsx +922 -0
- package/lib/esm/CascadingSelect/utils/performance.js +52 -0
- package/lib/esm/CascadingSelectE2E/Group.tsx +39 -0
- package/lib/esm/CascadingSelectE2E/index.scss +214 -0
- package/lib/esm/CascadingSelectE2E/index.tsx +1091 -0
- package/lib/esm/CascadingSelectE2E/utils/performance.js +52 -0
- package/lib/esm/Checkbox/index.tsx +160 -0
- package/lib/esm/ColorPicker/index.scss +48 -0
- package/lib/esm/ColorPicker/index.tsx +187 -0
- package/lib/esm/DigitalClock/index.tsx +72 -0
- package/lib/esm/DigitalClock/utils/useInterval.js +43 -0
- package/lib/esm/DropdownMenu/Option.tsx +27 -0
- package/lib/esm/DropdownMenu/index.scss +180 -0
- package/lib/esm/DropdownMenu/index.tsx +148 -0
- package/lib/esm/DynamicFields/index.tsx +386 -0
- package/lib/esm/File/index.tsx +302 -0
- package/lib/esm/Input/index.tsx +233 -0
- package/lib/esm/LiveSearch/index.tsx +582 -0
- package/lib/esm/LiveSearch/utils/performance.js +52 -0
- package/lib/esm/LiveSearch/utils/useThrottle.js +36 -0
- package/lib/esm/ModalDialog/index.tsx +479 -0
- package/lib/esm/ModalDialog/plugins/BSL/bodyScrollLock.es6.js +262 -0
- package/lib/esm/ModalDialog/plugins/BSL/index.ts +2 -0
- package/lib/esm/ModeSwitch/index.tsx +82 -0
- package/lib/esm/MultiFuncSelect/index.scss +269 -0
- package/lib/esm/MultiFuncSelect/index.tsx +1597 -0
- package/lib/esm/MultiFuncSelect/utils/performance.js +52 -0
- package/lib/esm/MultiFuncSelect/utils/tree.js +103 -0
- package/lib/esm/MultiFuncSelect/utils/useThrottle.js +36 -0
- package/lib/esm/MultilevelDropdownMenu/MenuList.tsx +230 -0
- package/lib/esm/MultilevelDropdownMenu/index.scss +75 -0
- package/lib/esm/MultilevelDropdownMenu/index.tsx +71 -0
- package/lib/esm/MultilevelDropdownMenu/utils/dom.js +81 -0
- package/lib/esm/Pagination/index.tsx +230 -0
- package/lib/esm/Pagination/pagination-navigators.tsx +60 -0
- package/lib/esm/Radio/index.tsx +201 -0
- package/lib/esm/RangeSlider/index.scss +184 -0
- package/lib/esm/RangeSlider/index.tsx +223 -0
- package/lib/esm/ScrollReveal/index.scss +27 -0
- package/lib/esm/ScrollReveal/index.tsx +146 -0
- package/lib/esm/Scrollbar/index.scss +217 -0
- package/lib/esm/Scrollbar/index.tsx +497 -0
- package/lib/esm/Scrollbar/utils/performance.js +52 -0
- package/lib/esm/SearchBar/index.tsx +181 -0
- package/lib/esm/Select/index.tsx +276 -0
- package/lib/esm/ShowMoreLess/index.scss +27 -0
- package/lib/esm/ShowMoreLess/index.tsx +144 -0
- package/lib/esm/Switch/index.tsx +143 -0
- package/lib/esm/Table/TableColgroup.tsx +29 -0
- package/lib/esm/Table/TableField.tsx +40 -0
- package/lib/esm/Table/TableFieldRow.tsx +212 -0
- package/lib/esm/Table/TableHeaders.tsx +146 -0
- package/lib/esm/Table/TableRow.tsx +127 -0
- package/lib/esm/Table/TableSummaries.tsx +36 -0
- package/lib/esm/Table/index.scss +364 -0
- package/lib/esm/Table/index.tsx +576 -0
- package/lib/esm/Table/table-utils.ts +65 -0
- package/lib/esm/Table/utils/dom.js +81 -0
- package/lib/esm/Table/utils/performance.js +52 -0
- package/lib/esm/Tabs/TabList.tsx +42 -0
- package/lib/esm/Tabs/TabPanel.tsx +34 -0
- package/lib/esm/Tabs/Tabs.tsx +232 -0
- package/lib/esm/Tabs/index.tsx +3 -0
- package/lib/esm/TagInput/index.scss +125 -0
- package/lib/esm/TagInput/index.tsx +314 -0
- package/lib/esm/Textarea/index.tsx +178 -0
- package/lib/esm/Toast/Item.tsx +75 -0
- package/lib/esm/Toast/index.scss +120 -0
- package/lib/esm/Toast/index.tsx +249 -0
- package/lib/esm/Tooltip/index.scss +327 -0
- package/lib/esm/Tooltip/index.tsx +142 -0
- package/lib/esm/Tree/TreeList.tsx +503 -0
- package/lib/esm/Tree/index.scss +375 -0
- package/lib/esm/Tree/index.tsx +301 -0
- package/lib/esm/Tree/init-height.tsx +27 -0
- package/lib/esm/Tree/utils/convert-tree.js +29 -0
- package/lib/esm/Tree/utils/dom.js +81 -0
- package/lib/esm/index.js +31 -0
- package/package.json +40 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Debounce
|
|
4
|
+
*
|
|
5
|
+
* @param {Function} fn - A function to be executed within the time limit.
|
|
6
|
+
* @param {Number} limit - Waiting time.
|
|
7
|
+
* @return {Function} - Returns a new function.
|
|
8
|
+
*/
|
|
9
|
+
function debounce( fn, limit = 300 ) {
|
|
10
|
+
let timer;
|
|
11
|
+
return function() {
|
|
12
|
+
|
|
13
|
+
//Every time this returned function is called, the timer is cleared to ensure that fn is not executed
|
|
14
|
+
clearTimeout(timer);
|
|
15
|
+
|
|
16
|
+
// When the returned function is called for the last time (that is the user stops a continuous operation)
|
|
17
|
+
// Execute fn after another delay milliseconds
|
|
18
|
+
timer = setTimeout(function() {
|
|
19
|
+
fn.apply(this, arguments);
|
|
20
|
+
}, limit);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Throttle
|
|
30
|
+
*
|
|
31
|
+
* @param {Function} fn - A function to be executed within the time limit.
|
|
32
|
+
* @param {Number} limit - Waiting time.
|
|
33
|
+
* @return {Function} - Returns a new function.
|
|
34
|
+
*/
|
|
35
|
+
function throttle( fn, limit = 300 ) {
|
|
36
|
+
let waiting = false;
|
|
37
|
+
return function () {
|
|
38
|
+
if (!waiting) {
|
|
39
|
+
fn.apply(this, arguments);
|
|
40
|
+
waiting = true;
|
|
41
|
+
setTimeout(function () {
|
|
42
|
+
waiting = false;
|
|
43
|
+
}, limit);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
module.exports = {
|
|
50
|
+
debounce,
|
|
51
|
+
throttle
|
|
52
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert Tree
|
|
3
|
+
* @param {Array} arr - Flat array
|
|
4
|
+
* @param {?String | ?Number} parentId - Parent id
|
|
5
|
+
* @param {?String} keyId - Key value of id.
|
|
6
|
+
* @param {?String} keyParentId - Key value of parent id.
|
|
7
|
+
* @returns Array
|
|
8
|
+
*/
|
|
9
|
+
function convertTree(arr, parentId = '', keyId = 'id', keyParentId = 'parent_id') {
|
|
10
|
+
|
|
11
|
+
if( !parentId ) {
|
|
12
|
+
|
|
13
|
+
// If there is no parent id (when recursing for the first time), all parents will be queried
|
|
14
|
+
return arr.filter(item => !item[keyParentId]).map(item => {
|
|
15
|
+
// Query all child nodes by parent node ID
|
|
16
|
+
item.children = convertTree(arr, item[keyId], keyId, keyParentId);
|
|
17
|
+
return item;
|
|
18
|
+
})
|
|
19
|
+
} else {
|
|
20
|
+
return arr.filter(item => item[keyParentId] === parentId).map(item => {
|
|
21
|
+
// Query all child nodes by parent node ID
|
|
22
|
+
item.children = convertTree(arr, item[keyId], keyId, keyParentId);
|
|
23
|
+
return item;
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Flat tree
|
|
31
|
+
* @param {Array} arr - Hierarchical array
|
|
32
|
+
* @returns Array
|
|
33
|
+
*/
|
|
34
|
+
function flatTree(arr) {
|
|
35
|
+
const flatData = ({...rest}) => {
|
|
36
|
+
const { children = [] } = rest;
|
|
37
|
+
return [{...rest}, ...children.flatMap(flatData)];
|
|
38
|
+
};
|
|
39
|
+
let result = arr.flatMap(flatData);
|
|
40
|
+
|
|
41
|
+
//remove children from item
|
|
42
|
+
result = result.map((item) => {
|
|
43
|
+
delete item.children;
|
|
44
|
+
return item;
|
|
45
|
+
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Add depth to each item in the tree
|
|
54
|
+
* @param {Array} arr - Hierarchical array
|
|
55
|
+
* @param {?String | ?Number} parentId - Parent id
|
|
56
|
+
* @param {?String} keyId - Key value of id.
|
|
57
|
+
* @param {?String} keyParentId - Key value of parent id.
|
|
58
|
+
* @param {?Number} depth - Depth of the item.
|
|
59
|
+
* @returns
|
|
60
|
+
*/
|
|
61
|
+
function addTreeDepth(arr, parentId = '', keyId = 'id', keyParentId = 'parent_id', depth = 0) {
|
|
62
|
+
arr.forEach((item) => {
|
|
63
|
+
item.depth = depth;
|
|
64
|
+
// Query all child nodes by parent node ID
|
|
65
|
+
if (item.children && item.children.length > 0) {
|
|
66
|
+
addTreeDepth(item.children, item[keyId], keyId, keyParentId, ++depth);
|
|
67
|
+
} else {
|
|
68
|
+
depth = 0;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Add indent placeholder
|
|
77
|
+
* @param {Array} arr - Flat array
|
|
78
|
+
* @param {?String} placeholder - String of placeholder
|
|
79
|
+
* @param {?String} lastPlaceholder - Last String of placeholder
|
|
80
|
+
* @param {?String} keyName - Key value of name.
|
|
81
|
+
* @returns Array
|
|
82
|
+
*/
|
|
83
|
+
function addTreeIndent(arr, placeholder = ' ', lastPlaceholder = '', keyName = 'label') {
|
|
84
|
+
arr.forEach((item) => {
|
|
85
|
+
let indent = '';
|
|
86
|
+
if (item.depth) {
|
|
87
|
+
Array(item.depth).fill(0).forEach((k, i) => {
|
|
88
|
+
indent += placeholder;
|
|
89
|
+
if (i === item.depth-1) {
|
|
90
|
+
item[keyName] = indent + lastPlaceholder + item[keyName];
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = {
|
|
98
|
+
convertTree,
|
|
99
|
+
flatTree,
|
|
100
|
+
addTreeDepth,
|
|
101
|
+
addTreeIndent
|
|
102
|
+
};
|
|
103
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Limiting the rate of execution
|
|
3
|
+
*
|
|
4
|
+
* @usage:
|
|
5
|
+
|
|
6
|
+
const App = () => {
|
|
7
|
+
const [count, setCount] = useState(0);
|
|
8
|
+
const handleClick = useThrottle(() => setCount(count + 1), 500, [count]);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className="app">
|
|
12
|
+
<button onClick={handleClick}>click</button>
|
|
13
|
+
<p>click {count} time</p>
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
import { useRef, useCallback } from "react";
|
|
20
|
+
|
|
21
|
+
const useThrottle = (fn, delay, dependence) => {
|
|
22
|
+
const ref = useRef({ lastTime: 0 });
|
|
23
|
+
|
|
24
|
+
return useCallback((...args) => {
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
|
|
27
|
+
if (now - ref.current.lastTime >= delay) {
|
|
28
|
+
fn(...args);
|
|
29
|
+
ref.current.lastTime = now;
|
|
30
|
+
}
|
|
31
|
+
}, dependence);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
export default useThrottle;
|
|
36
|
+
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { getNextSiblings } from './utils/dom';
|
|
4
|
+
|
|
5
|
+
/* Recursively nested components to traverse nodes
|
|
6
|
+
-------------------------------------------------*/
|
|
7
|
+
type MenuListProps = {
|
|
8
|
+
alternateCollapse?: boolean;
|
|
9
|
+
first?: boolean;
|
|
10
|
+
arrow?: React.ReactNode;
|
|
11
|
+
childClassName?: string;
|
|
12
|
+
data: any[any];
|
|
13
|
+
routerPath?: string;
|
|
14
|
+
onSelect?: (e: any, val: any) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function MenuList(props: MenuListProps) {
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
alternateCollapse,
|
|
21
|
+
first,
|
|
22
|
+
arrow,
|
|
23
|
+
childClassName,
|
|
24
|
+
data,
|
|
25
|
+
routerPath,
|
|
26
|
+
onSelect
|
|
27
|
+
} = props;
|
|
28
|
+
|
|
29
|
+
const rootRef = useRef<any>(null);
|
|
30
|
+
const currentPath = routerPath ? routerPath : '';
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const activeClass = (el: any, mode: string, classname: string = 'active') => {
|
|
35
|
+
if ( mode === 'add' ) {
|
|
36
|
+
el.classList.add(classname);
|
|
37
|
+
} else {
|
|
38
|
+
el.classList.remove(classname);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const closeChild = (hyperlink: HTMLElement, ul: HTMLAllCollection) => {
|
|
43
|
+
if ( ul.length === 0 ) return;
|
|
44
|
+
|
|
45
|
+
activeClass(hyperlink, 'remove');
|
|
46
|
+
hyperlink.setAttribute('aria-expanded', 'false');
|
|
47
|
+
activeClass(hyperlink.parentNode, 'remove');
|
|
48
|
+
|
|
49
|
+
//to close
|
|
50
|
+
[].slice.call(ul).forEach(function(element: any){
|
|
51
|
+
element.style.maxHeight = 0;
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const openChild = (hyperlink: HTMLElement, ul: HTMLAllCollection) => {
|
|
56
|
+
if ( ul.length === 0 ) return;
|
|
57
|
+
|
|
58
|
+
activeClass(hyperlink, 'add');
|
|
59
|
+
hyperlink.setAttribute('aria-expanded', 'true');
|
|
60
|
+
activeClass(hyperlink.parentNode, 'add');
|
|
61
|
+
|
|
62
|
+
// init <ul> height
|
|
63
|
+
[].slice.call(ul).forEach(function(el: any){
|
|
64
|
+
if ( typeof el.querySelectorAll('li')[0] !== 'undefined' ) {
|
|
65
|
+
const calcH = el.querySelectorAll('li').length * el.querySelectorAll('li')[0].scrollHeight;
|
|
66
|
+
el.style.maxHeight = `${calcH}px`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
function handleClick(e: any) {
|
|
76
|
+
e.preventDefault();
|
|
77
|
+
const hyperlink = e.currentTarget;
|
|
78
|
+
const url = hyperlink.getAttribute('href');
|
|
79
|
+
const subElement = getNextSiblings(hyperlink, 'ul');
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
// route switching
|
|
83
|
+
//=====================
|
|
84
|
+
onSelect?.(e, {
|
|
85
|
+
isRouter: hyperlink.dataset.router,
|
|
86
|
+
slug: hyperlink.dataset.slug,
|
|
87
|
+
link: hyperlink.dataset.link
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
// hide child if expandedLink doesn't exist, on the contrary
|
|
92
|
+
//=====================
|
|
93
|
+
if ( hyperlink.getAttribute('aria-expanded') === 'false' || hyperlink.getAttribute('aria-expanded') === null ) {
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
//Hide all other siblings of the selected <ul>
|
|
97
|
+
if ( alternateCollapse ) {
|
|
98
|
+
[].slice.call(rootRef.current.children).forEach(function(li: any){
|
|
99
|
+
|
|
100
|
+
activeClass(li, 'remove');
|
|
101
|
+
|
|
102
|
+
const _li = li.firstChild;
|
|
103
|
+
activeClass(_li, 'remove');
|
|
104
|
+
_li.setAttribute('aria-expanded', false);
|
|
105
|
+
|
|
106
|
+
[].slice.call(getNextSiblings(_li, 'ul')).forEach(function(element: any){
|
|
107
|
+
element.style.maxHeight = 0;
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
//open current
|
|
114
|
+
openChild(hyperlink, subElement as never);
|
|
115
|
+
|
|
116
|
+
} else {
|
|
117
|
+
|
|
118
|
+
//close current
|
|
119
|
+
closeChild(hyperlink, subElement as never);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
// active current item
|
|
125
|
+
//=====================
|
|
126
|
+
if ( (currentPath === url || currentPath.indexOf(url.replace(/\/[\d]+\.html|\.html/ig,'')) >= 0 && url !== '/') ) {
|
|
127
|
+
activeClass(e.target, 'add');
|
|
128
|
+
activeClass(e.target.parentElement, 'add');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function arrowGenerator() {
|
|
135
|
+
return arrow ? arrow : <svg viewBox="0 0 22 22" width="8px"><path d="m345.44 248.29l-194.29 194.28c-12.359 12.365-32.397 12.365-44.75 0-12.354-12.354-12.354-32.391 0-44.744l171.91-171.91-171.91-171.9c-12.354-12.359-12.354-32.394 0-44.748 12.354-12.359 32.391-12.359 44.75 0l194.29 194.28c6.177 6.18 9.262 14.271 9.262 22.366 0 8.099-3.091 16.196-9.267 22.373" transform="matrix(.03541-.00013.00013.03541 2.98 3.02)" fill="#a5a5a5" /></svg>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
// Activate current item
|
|
143
|
+
//=====================
|
|
144
|
+
const allItems = rootRef.current ? [].slice.call(document.querySelectorAll(`.${childClassName} a`)).map( (item: any) => {
|
|
145
|
+
return {
|
|
146
|
+
href: item.getAttribute('href'),
|
|
147
|
+
el: item,
|
|
148
|
+
actived: item.parentNode.classList?.contains('active') ? true : false,
|
|
149
|
+
expandedLink: document.body.contains(item.parentNode.parentNode.previousSibling) ? item.parentNode.parentNode.previousSibling : false
|
|
150
|
+
}
|
|
151
|
+
} ) : [];
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
allItems.forEach( (hyperlink: any) => {
|
|
155
|
+
|
|
156
|
+
// Expand the currently active item by default
|
|
157
|
+
if ( hyperlink.actived ) {
|
|
158
|
+
|
|
159
|
+
hyperlink.el.setAttribute('aria-expanded', 'true');
|
|
160
|
+
|
|
161
|
+
if ( hyperlink.expandedLink ) {
|
|
162
|
+
const expandedLink: any = hyperlink.expandedLink; // <a>
|
|
163
|
+
activeClass(expandedLink.parentNode, 'add');
|
|
164
|
+
expandedLink.setAttribute('aria-expanded', true);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
// init <ul> height
|
|
169
|
+
const ul = getNextSiblings(hyperlink.el, 'ul');
|
|
170
|
+
[].slice.call(ul).forEach(function(el: any){
|
|
171
|
+
if ( typeof el.querySelectorAll('li')[0] !== 'undefined' ) {
|
|
172
|
+
const calcH = el.querySelectorAll('li').length * el.querySelectorAll('li')[0].scrollHeight;
|
|
173
|
+
el.style.maxHeight = `${calcH}px`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
}, [data]);
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
if ( data ) {
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<>
|
|
188
|
+
<ul className={childClassName} ref={rootRef} style={!first ? {maxHeight: '0px'} : {}}>
|
|
189
|
+
|
|
190
|
+
{data.map((item: any, i: number) => {
|
|
191
|
+
|
|
192
|
+
const _matchPath = currentPath === item.link || currentPath.indexOf(item.link.replace(/\/[\d]+\.html|\.html/ig, '')) >= 0 && item.link !== '/';
|
|
193
|
+
|
|
194
|
+
if (item.heading) return (
|
|
195
|
+
<li className="nav-item" key={i}>
|
|
196
|
+
<a tabIndex={-1} className="nav-link disabled" href="#" aria-disabled="true" data-router="false" data-link={item.link} data-slug={item.slug}>
|
|
197
|
+
{item.icon ? item.icon.indexOf('</svg>') < 0 ? <><i className={item.icon}></i> </> : <var dangerouslySetInnerHTML={{ __html: `${item.icon}` }} /> : null}<i dangerouslySetInnerHTML={{ __html: `${item.title}` }}></i>
|
|
198
|
+
</a>
|
|
199
|
+
</li>
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<li key={i} className={item.active ? `nav-item active` : (_matchPath ? `nav-item active` : 'nav-item')}>
|
|
204
|
+
<a tabIndex={-1} title={item.title} className={item.active ? `nav-link active` : (_matchPath ? `nav-link active` : 'nav-link')} href={item.link === '#' ? `${item.link}-${i}` : item.link} onClick={handleClick} data-router={item.link.indexOf('#') >= 0 || item.link.indexOf('http') >= 0 ? 'false' : 'true'} data-link={item.link} data-slug={item.slug}>
|
|
205
|
+
{item.icon ? item.icon.indexOf('</svg>') < 0 ? <><i className={item.icon}></i> </> : <var dangerouslySetInnerHTML={{ __html: `${item.icon}` }} /> : null}<i dangerouslySetInnerHTML={{ __html: `${item.title}` }}></i>
|
|
206
|
+
{item.children ? <span className="arrow">{arrowGenerator()}</span> : ''}
|
|
207
|
+
</a>
|
|
208
|
+
{item.children && <MenuList
|
|
209
|
+
data={item.children}
|
|
210
|
+
first={false}
|
|
211
|
+
arrow={arrow}
|
|
212
|
+
onSelect={onSelect}
|
|
213
|
+
routerPath={routerPath}
|
|
214
|
+
/>}
|
|
215
|
+
</li>
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
})}
|
|
219
|
+
</ul>
|
|
220
|
+
|
|
221
|
+
</>
|
|
222
|
+
)
|
|
223
|
+
} else {
|
|
224
|
+
return (
|
|
225
|
+
<></>
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/* ======================================================
|
|
2
|
+
<!-- Multi-level Dropdown Menu -->
|
|
3
|
+
/* ====================================================== */
|
|
4
|
+
|
|
5
|
+
.navbar-nav {
|
|
6
|
+
|
|
7
|
+
a {
|
|
8
|
+
position: relative;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.arrow {
|
|
12
|
+
transition: .1s ease-in-out;
|
|
13
|
+
display: inline-block;
|
|
14
|
+
text-align: center;
|
|
15
|
+
position: absolute;
|
|
16
|
+
right: 0.5em;
|
|
17
|
+
top: 1.5em;
|
|
18
|
+
transform: translateY(-50%) rotate(0deg);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
li {
|
|
22
|
+
|
|
23
|
+
position: relative;
|
|
24
|
+
|
|
25
|
+
i {
|
|
26
|
+
font-style: normal;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
> a {
|
|
30
|
+
|
|
31
|
+
&:hover {
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&.active {
|
|
36
|
+
|
|
37
|
+
> .arrow {
|
|
38
|
+
transform: translateY(-50%) rotate(90deg);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
&.active > a {
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
> li {
|
|
54
|
+
|
|
55
|
+
ul {
|
|
56
|
+
transition: max-height 0.25s ease;
|
|
57
|
+
overflow: hidden;
|
|
58
|
+
position: relative;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
> li:not(.active) {
|
|
63
|
+
|
|
64
|
+
ul {
|
|
65
|
+
max-height: 0;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
> li ul ul {
|
|
71
|
+
margin-top: auto;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React, { useState, useEffect, useId, memo } from 'react';
|
|
2
|
+
|
|
3
|
+
import MenuList from './MenuList';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
declare module 'react' {
|
|
7
|
+
interface ReactI18NextChildren<T> {
|
|
8
|
+
children?: any;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type MultilevelDropdownMenuProps = {
|
|
13
|
+
/** Mutually exclusive alternate expansion between the first levels */
|
|
14
|
+
alternateCollapse?: boolean;
|
|
15
|
+
/** set an arrow */
|
|
16
|
+
arrow?: React.ReactNode;
|
|
17
|
+
/** The class name of the navbar. */
|
|
18
|
+
navbarClassName?: string;
|
|
19
|
+
/** The class name of the child on <ul>. */
|
|
20
|
+
childClassName?: string;
|
|
21
|
+
/** Specify data of Cascading DropDown List as a JSON string format. */
|
|
22
|
+
data?: any[any];
|
|
23
|
+
/** Pass the current routing path into. It is used to determine whether to activate */
|
|
24
|
+
routerPath?: string;
|
|
25
|
+
/** -- */
|
|
26
|
+
id?: string;
|
|
27
|
+
onSelect?: (e: any, val: any) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const MultilevelDropdownMenu = (props: MultilevelDropdownMenuProps) => {
|
|
32
|
+
const {
|
|
33
|
+
alternateCollapse,
|
|
34
|
+
arrow,
|
|
35
|
+
navbarClassName,
|
|
36
|
+
childClassName,
|
|
37
|
+
routerPath,
|
|
38
|
+
data,
|
|
39
|
+
id,
|
|
40
|
+
onSelect
|
|
41
|
+
} = props;
|
|
42
|
+
|
|
43
|
+
const uniqueID = useId();
|
|
44
|
+
const idRes = id || uniqueID;
|
|
45
|
+
const [val, setVal] = useState<any>(null);
|
|
46
|
+
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
setVal(data);
|
|
49
|
+
}, [data]);
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
|
|
55
|
+
<nav id={idRes} className={navbarClassName ? navbarClassName : "navbar"}>
|
|
56
|
+
<MenuList
|
|
57
|
+
alternateCollapse={alternateCollapse}
|
|
58
|
+
first={true}
|
|
59
|
+
arrow={arrow}
|
|
60
|
+
data={val}
|
|
61
|
+
childClassName={childClassName || 'navbar-nav'}
|
|
62
|
+
onSelect={onSelect}
|
|
63
|
+
routerPath={routerPath}
|
|
64
|
+
/>
|
|
65
|
+
</nav>
|
|
66
|
+
|
|
67
|
+
</>
|
|
68
|
+
)
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default memo(MultilevelDropdownMenu);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dom Utilities
|
|
3
|
+
* @param {HTMLElement} el - Element
|
|
4
|
+
* @param {?String} filter - A filter string
|
|
5
|
+
* @returns HtmlElementCollection
|
|
6
|
+
*/
|
|
7
|
+
function matches(el, filter) {
|
|
8
|
+
if (el && el.nodeType === 1) {
|
|
9
|
+
if (filter) {
|
|
10
|
+
return el.matches(filter);
|
|
11
|
+
}
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// the next siblings
|
|
18
|
+
function getNextSiblings(el, filter = false || '') {
|
|
19
|
+
const sibs = [];
|
|
20
|
+
while (el = el.nextSibling) {
|
|
21
|
+
if (matches(el, filter)) {
|
|
22
|
+
sibs.push(el);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return sibs;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// previous siblings
|
|
29
|
+
function getPreviousSiblings(el, filter = false || '') {
|
|
30
|
+
const sibs = [];
|
|
31
|
+
while (el = el.previousSibling) {
|
|
32
|
+
if (matches(el, filter)) {
|
|
33
|
+
sibs.push(el);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return sibs;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// parent and get all the siblings
|
|
40
|
+
function getAllSiblings(el, filter = false || '') {
|
|
41
|
+
const sibs = [];
|
|
42
|
+
el = el.parentNode.firstChild;
|
|
43
|
+
while (el = el.nextSibling) {
|
|
44
|
+
if (matches(el, filter)) {
|
|
45
|
+
sibs.push(el);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return sibs;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// all parent nodes
|
|
52
|
+
function getParents(el, filter = false || '') {
|
|
53
|
+
const parents = [];
|
|
54
|
+
while (el = el.parentNode) {
|
|
55
|
+
if (matches(el, filter)) {
|
|
56
|
+
parents.push(el);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return parents;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// all child nodes
|
|
63
|
+
function getChildren(el, filter = false || '', all = []) {
|
|
64
|
+
all.push(...el.childNodes);
|
|
65
|
+
for (const child of el.childNodes) {
|
|
66
|
+
getChildren(child, filter, all);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const res = all.filter( item => matches(item, filter) );
|
|
70
|
+
return res;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
module.exports = {
|
|
75
|
+
getNextSiblings,
|
|
76
|
+
getPreviousSiblings,
|
|
77
|
+
getAllSiblings,
|
|
78
|
+
getParents,
|
|
79
|
+
getChildren
|
|
80
|
+
}
|
|
81
|
+
|