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.
Files changed (246) hide show
  1. package/BackToTop/index.css +34 -0
  2. package/BackToTop/index.d.ts +11 -0
  3. package/BackToTop/index.js +458 -0
  4. package/CascadingSelect/index.css +159 -0
  5. package/CascadingSelect/index.d.ts +56 -0
  6. package/CascadingSelect/index.js +958 -0
  7. package/CascadingSelectE2E/index.css +159 -0
  8. package/CascadingSelectE2E/index.d.ts +60 -0
  9. package/CascadingSelectE2E/index.js +1126 -0
  10. package/Checkbox/index.d.ts +30 -0
  11. package/Checkbox/index.js +226 -0
  12. package/ColorPicker/index.css +38 -0
  13. package/ColorPicker/index.d.ts +27 -0
  14. package/ColorPicker/index.js +246 -0
  15. package/DigitalClock/index.d.ts +7 -0
  16. package/DigitalClock/index.js +208 -0
  17. package/DropdownMenu/index.css +127 -0
  18. package/DropdownMenu/index.d.ts +37 -0
  19. package/DropdownMenu/index.js +237 -0
  20. package/DynamicFields/index.d.ts +26 -0
  21. package/DynamicFields/index.js +412 -0
  22. package/File/index.d.ts +36 -0
  23. package/File/index.js +473 -0
  24. package/Input/index.d.ts +42 -0
  25. package/Input/index.js +286 -0
  26. package/LiveSearch/index.d.ts +37 -0
  27. package/LiveSearch/index.js +1195 -0
  28. package/ModalDialog/index.d.ts +60 -0
  29. package/ModalDialog/index.js +725 -0
  30. package/ModeSwitch/index.d.ts +17 -0
  31. package/ModeSwitch/index.js +202 -0
  32. package/MultiFuncSelect/index.css +178 -0
  33. package/MultiFuncSelect/index.d.ts +67 -0
  34. package/MultiFuncSelect/index.js +1826 -0
  35. package/MultilevelDropdownMenu/index.css +35 -0
  36. package/MultilevelDropdownMenu/index.d.ts +25 -0
  37. package/MultilevelDropdownMenu/index.js +464 -0
  38. package/Pagination/index.d.ts +49 -0
  39. package/Pagination/index.js +341 -0
  40. package/README.md +108 -0
  41. package/Radio/index.d.ts +31 -0
  42. package/Radio/index.js +246 -0
  43. package/RangeSlider/index.css +149 -0
  44. package/RangeSlider/index.d.ts +21 -0
  45. package/RangeSlider/index.js +730 -0
  46. package/ScrollReveal/index.css +23 -0
  47. package/ScrollReveal/index.d.ts +21 -0
  48. package/ScrollReveal/index.js +216 -0
  49. package/Scrollbar/index.css +168 -0
  50. package/Scrollbar/index.d.ts +15 -0
  51. package/Scrollbar/index.js +605 -0
  52. package/SearchBar/index.d.ts +32 -0
  53. package/SearchBar/index.js +246 -0
  54. package/Select/index.d.ts +34 -0
  55. package/Select/index.js +331 -0
  56. package/ShowMoreLess/index.css +23 -0
  57. package/ShowMoreLess/index.d.ts +30 -0
  58. package/ShowMoreLess/index.js +202 -0
  59. package/Switch/index.d.ts +29 -0
  60. package/Switch/index.js +211 -0
  61. package/Table/index.css +533 -0
  62. package/Table/index.d.ts +25 -0
  63. package/Table/index.js +2113 -0
  64. package/Tabs/index.d.ts +3 -0
  65. package/Tabs/index.js +323 -0
  66. package/TagInput/index.css +90 -0
  67. package/TagInput/index.d.ts +28 -0
  68. package/TagInput/index.js +370 -0
  69. package/Textarea/index.d.ts +30 -0
  70. package/Textarea/index.js +242 -0
  71. package/Toast/index.css +95 -0
  72. package/Toast/index.d.ts +35 -0
  73. package/Toast/index.js +340 -0
  74. package/Tooltip/index.css +240 -0
  75. package/Tooltip/index.d.ts +19 -0
  76. package/Tooltip/index.js +200 -0
  77. package/Tree/index.css +225 -0
  78. package/Tree/index.d.ts +37 -0
  79. package/Tree/index.js +1406 -0
  80. package/all.d.ts +33 -0
  81. package/all.js +35 -0
  82. package/lib/cjs/BackToTop/index.d.ts +11 -0
  83. package/lib/cjs/BackToTop/index.js +458 -0
  84. package/lib/cjs/CascadingSelect/index.d.ts +56 -0
  85. package/lib/cjs/CascadingSelect/index.js +958 -0
  86. package/lib/cjs/CascadingSelectE2E/index.d.ts +60 -0
  87. package/lib/cjs/CascadingSelectE2E/index.js +1126 -0
  88. package/lib/cjs/Checkbox/index.d.ts +30 -0
  89. package/lib/cjs/Checkbox/index.js +226 -0
  90. package/lib/cjs/ColorPicker/index.d.ts +27 -0
  91. package/lib/cjs/ColorPicker/index.js +246 -0
  92. package/lib/cjs/DigitalClock/index.d.ts +7 -0
  93. package/lib/cjs/DigitalClock/index.js +208 -0
  94. package/lib/cjs/DropdownMenu/index.d.ts +37 -0
  95. package/lib/cjs/DropdownMenu/index.js +237 -0
  96. package/lib/cjs/DynamicFields/index.d.ts +26 -0
  97. package/lib/cjs/DynamicFields/index.js +412 -0
  98. package/lib/cjs/File/index.d.ts +36 -0
  99. package/lib/cjs/File/index.js +473 -0
  100. package/lib/cjs/Input/index.d.ts +42 -0
  101. package/lib/cjs/Input/index.js +286 -0
  102. package/lib/cjs/LiveSearch/index.d.ts +37 -0
  103. package/lib/cjs/LiveSearch/index.js +1195 -0
  104. package/lib/cjs/ModalDialog/index.d.ts +60 -0
  105. package/lib/cjs/ModalDialog/index.js +725 -0
  106. package/lib/cjs/ModeSwitch/index.d.ts +17 -0
  107. package/lib/cjs/ModeSwitch/index.js +202 -0
  108. package/lib/cjs/MultiFuncSelect/index.d.ts +67 -0
  109. package/lib/cjs/MultiFuncSelect/index.js +1826 -0
  110. package/lib/cjs/MultilevelDropdownMenu/index.d.ts +25 -0
  111. package/lib/cjs/MultilevelDropdownMenu/index.js +464 -0
  112. package/lib/cjs/Pagination/index.d.ts +49 -0
  113. package/lib/cjs/Pagination/index.js +341 -0
  114. package/lib/cjs/Radio/index.d.ts +31 -0
  115. package/lib/cjs/Radio/index.js +246 -0
  116. package/lib/cjs/RangeSlider/index.d.ts +21 -0
  117. package/lib/cjs/RangeSlider/index.js +730 -0
  118. package/lib/cjs/ScrollReveal/index.d.ts +21 -0
  119. package/lib/cjs/ScrollReveal/index.js +216 -0
  120. package/lib/cjs/Scrollbar/index.d.ts +15 -0
  121. package/lib/cjs/Scrollbar/index.js +605 -0
  122. package/lib/cjs/SearchBar/index.d.ts +32 -0
  123. package/lib/cjs/SearchBar/index.js +246 -0
  124. package/lib/cjs/Select/index.d.ts +34 -0
  125. package/lib/cjs/Select/index.js +331 -0
  126. package/lib/cjs/ShowMoreLess/index.d.ts +30 -0
  127. package/lib/cjs/ShowMoreLess/index.js +202 -0
  128. package/lib/cjs/Switch/index.d.ts +29 -0
  129. package/lib/cjs/Switch/index.js +211 -0
  130. package/lib/cjs/Table/index.d.ts +25 -0
  131. package/lib/cjs/Table/index.js +2113 -0
  132. package/lib/cjs/Tabs/index.d.ts +3 -0
  133. package/lib/cjs/Tabs/index.js +323 -0
  134. package/lib/cjs/TagInput/index.d.ts +28 -0
  135. package/lib/cjs/TagInput/index.js +370 -0
  136. package/lib/cjs/Textarea/index.d.ts +30 -0
  137. package/lib/cjs/Textarea/index.js +242 -0
  138. package/lib/cjs/Toast/index.d.ts +35 -0
  139. package/lib/cjs/Toast/index.js +340 -0
  140. package/lib/cjs/Tooltip/index.d.ts +19 -0
  141. package/lib/cjs/Tooltip/index.js +200 -0
  142. package/lib/cjs/Tree/index.d.ts +37 -0
  143. package/lib/cjs/Tree/index.js +1406 -0
  144. package/lib/cjs/index.d.ts +33 -0
  145. package/lib/cjs/index.js +35 -0
  146. package/lib/css/BackToTop/index.css +34 -0
  147. package/lib/css/CascadingSelect/index.css +159 -0
  148. package/lib/css/CascadingSelectE2E/index.css +159 -0
  149. package/lib/css/ColorPicker/index.css +38 -0
  150. package/lib/css/DropdownMenu/index.css +127 -0
  151. package/lib/css/MultiFuncSelect/index.css +178 -0
  152. package/lib/css/MultilevelDropdownMenu/index.css +35 -0
  153. package/lib/css/RangeSlider/index.css +149 -0
  154. package/lib/css/ScrollReveal/index.css +23 -0
  155. package/lib/css/Scrollbar/index.css +168 -0
  156. package/lib/css/ShowMoreLess/index.css +23 -0
  157. package/lib/css/Table/index.css +533 -0
  158. package/lib/css/TagInput/index.css +90 -0
  159. package/lib/css/Toast/index.css +95 -0
  160. package/lib/css/Tooltip/index.css +240 -0
  161. package/lib/css/Tree/index.css +225 -0
  162. package/lib/esm/BackToTop/index.scss +47 -0
  163. package/lib/esm/BackToTop/index.tsx +182 -0
  164. package/lib/esm/BackToTop/utils/easing.js +200 -0
  165. package/lib/esm/BackToTop/utils/performance.js +52 -0
  166. package/lib/esm/CascadingSelect/Group.tsx +39 -0
  167. package/lib/esm/CascadingSelect/index.scss +214 -0
  168. package/lib/esm/CascadingSelect/index.tsx +922 -0
  169. package/lib/esm/CascadingSelect/utils/performance.js +52 -0
  170. package/lib/esm/CascadingSelectE2E/Group.tsx +39 -0
  171. package/lib/esm/CascadingSelectE2E/index.scss +214 -0
  172. package/lib/esm/CascadingSelectE2E/index.tsx +1091 -0
  173. package/lib/esm/CascadingSelectE2E/utils/performance.js +52 -0
  174. package/lib/esm/Checkbox/index.tsx +160 -0
  175. package/lib/esm/ColorPicker/index.scss +48 -0
  176. package/lib/esm/ColorPicker/index.tsx +187 -0
  177. package/lib/esm/DigitalClock/index.tsx +72 -0
  178. package/lib/esm/DigitalClock/utils/useInterval.js +43 -0
  179. package/lib/esm/DropdownMenu/Option.tsx +27 -0
  180. package/lib/esm/DropdownMenu/index.scss +180 -0
  181. package/lib/esm/DropdownMenu/index.tsx +148 -0
  182. package/lib/esm/DynamicFields/index.tsx +386 -0
  183. package/lib/esm/File/index.tsx +302 -0
  184. package/lib/esm/Input/index.tsx +233 -0
  185. package/lib/esm/LiveSearch/index.tsx +582 -0
  186. package/lib/esm/LiveSearch/utils/performance.js +52 -0
  187. package/lib/esm/LiveSearch/utils/useThrottle.js +36 -0
  188. package/lib/esm/ModalDialog/index.tsx +479 -0
  189. package/lib/esm/ModalDialog/plugins/BSL/bodyScrollLock.es6.js +262 -0
  190. package/lib/esm/ModalDialog/plugins/BSL/index.ts +2 -0
  191. package/lib/esm/ModeSwitch/index.tsx +82 -0
  192. package/lib/esm/MultiFuncSelect/index.scss +269 -0
  193. package/lib/esm/MultiFuncSelect/index.tsx +1597 -0
  194. package/lib/esm/MultiFuncSelect/utils/performance.js +52 -0
  195. package/lib/esm/MultiFuncSelect/utils/tree.js +103 -0
  196. package/lib/esm/MultiFuncSelect/utils/useThrottle.js +36 -0
  197. package/lib/esm/MultilevelDropdownMenu/MenuList.tsx +230 -0
  198. package/lib/esm/MultilevelDropdownMenu/index.scss +75 -0
  199. package/lib/esm/MultilevelDropdownMenu/index.tsx +71 -0
  200. package/lib/esm/MultilevelDropdownMenu/utils/dom.js +81 -0
  201. package/lib/esm/Pagination/index.tsx +230 -0
  202. package/lib/esm/Pagination/pagination-navigators.tsx +60 -0
  203. package/lib/esm/Radio/index.tsx +201 -0
  204. package/lib/esm/RangeSlider/index.scss +184 -0
  205. package/lib/esm/RangeSlider/index.tsx +223 -0
  206. package/lib/esm/ScrollReveal/index.scss +27 -0
  207. package/lib/esm/ScrollReveal/index.tsx +146 -0
  208. package/lib/esm/Scrollbar/index.scss +217 -0
  209. package/lib/esm/Scrollbar/index.tsx +497 -0
  210. package/lib/esm/Scrollbar/utils/performance.js +52 -0
  211. package/lib/esm/SearchBar/index.tsx +181 -0
  212. package/lib/esm/Select/index.tsx +276 -0
  213. package/lib/esm/ShowMoreLess/index.scss +27 -0
  214. package/lib/esm/ShowMoreLess/index.tsx +144 -0
  215. package/lib/esm/Switch/index.tsx +143 -0
  216. package/lib/esm/Table/TableColgroup.tsx +29 -0
  217. package/lib/esm/Table/TableField.tsx +40 -0
  218. package/lib/esm/Table/TableFieldRow.tsx +212 -0
  219. package/lib/esm/Table/TableHeaders.tsx +146 -0
  220. package/lib/esm/Table/TableRow.tsx +127 -0
  221. package/lib/esm/Table/TableSummaries.tsx +36 -0
  222. package/lib/esm/Table/index.scss +364 -0
  223. package/lib/esm/Table/index.tsx +576 -0
  224. package/lib/esm/Table/table-utils.ts +65 -0
  225. package/lib/esm/Table/utils/dom.js +81 -0
  226. package/lib/esm/Table/utils/performance.js +52 -0
  227. package/lib/esm/Tabs/TabList.tsx +42 -0
  228. package/lib/esm/Tabs/TabPanel.tsx +34 -0
  229. package/lib/esm/Tabs/Tabs.tsx +232 -0
  230. package/lib/esm/Tabs/index.tsx +3 -0
  231. package/lib/esm/TagInput/index.scss +125 -0
  232. package/lib/esm/TagInput/index.tsx +314 -0
  233. package/lib/esm/Textarea/index.tsx +178 -0
  234. package/lib/esm/Toast/Item.tsx +75 -0
  235. package/lib/esm/Toast/index.scss +120 -0
  236. package/lib/esm/Toast/index.tsx +249 -0
  237. package/lib/esm/Tooltip/index.scss +327 -0
  238. package/lib/esm/Tooltip/index.tsx +142 -0
  239. package/lib/esm/Tree/TreeList.tsx +503 -0
  240. package/lib/esm/Tree/index.scss +375 -0
  241. package/lib/esm/Tree/index.tsx +301 -0
  242. package/lib/esm/Tree/init-height.tsx +27 -0
  243. package/lib/esm/Tree/utils/convert-tree.js +29 -0
  244. package/lib/esm/Tree/utils/dom.js +81 -0
  245. package/lib/esm/index.js +31 -0
  246. package/package.json +40 -0
@@ -0,0 +1,1091 @@
1
+ import React, { useId, useEffect, useState, useRef } from 'react';
2
+
3
+ import { debounce } from './utils/performance';
4
+
5
+ import Group from './Group';
6
+
7
+
8
+
9
+
10
+ declare module 'react' {
11
+ interface ReactI18NextChildren<T> {
12
+ children?: any;
13
+ }
14
+ }
15
+
16
+
17
+ type CascadingSelectE2EOptionChangeFnType = (input: any, currentData: any, index: any, depth: any, value: any) => void;
18
+
19
+
20
+ interface fetchArrayConfig {
21
+ fetchFuncAsync?: any | undefined;
22
+ fetchFuncMethod?: string | undefined;
23
+ fetchFuncMethodParams?: any[] | undefined;
24
+ fetchCallback?: (data: any) => void;
25
+ }
26
+
27
+ type CascadingSelectE2EProps = {
28
+ wrapperClassName?: string;
29
+ controlClassName?: string;
30
+ value?: string;
31
+ label?: React.ReactNode | string;
32
+ name?: string;
33
+ placeholder?: string;
34
+ disabled?: any;
35
+ required?: any;
36
+ /** Set headers for each column group */
37
+ columnTitle?: any[];
38
+ /** Set whether to use "label" or "value" for the value of this form, they will be separated by commas, such as `Text 1,Text 1_1,Text 1_1_1` or `1,1_1,1_1_1`.
39
+ * Optional values: `label`, `value`
40
+ */
41
+ valueType?: string;
42
+ /** Whether to display the close button. */
43
+ showCloseBtn?: boolean;
44
+ /** Set the depth value of the control to control the display of the pop-up layer appear above.
45
+ * Please set it when multiple controls are used at the same time. */
46
+ depth?: number;
47
+ /** Set a loader component to show while the component waits for the next load of data.
48
+ * e.g. `<span>Loading...</span>` or any fancy loader element */
49
+ loader?: React.ReactNode;
50
+ /** Whether to show breadcrumb result */
51
+ displayResult?: boolean;
52
+ /** Set an arrow of breadcrumb result */
53
+ displayResultArrow?: React.ReactNode;
54
+ /** Set an arrow of control */
55
+ controlArrow?: React.ReactNode;
56
+ /** Specify a class for this Node. */
57
+ triggerClassName?: string;
58
+ /** Set a piece of text or HTML code for the trigger */
59
+ triggerContent?: React.ReactNode;
60
+ /** Configuration for multiple requests */
61
+ fetchArray?: fetchArrayConfig[];
62
+ /** -- */
63
+ id?: string;
64
+ style?: React.CSSProperties;
65
+ tabIndex?: number;
66
+ [key: `data-${string}`]: string | undefined;
67
+ onFetch?: (data: any, childrenData: any) => void;
68
+ onChange?: CascadingSelectE2EOptionChangeFnType | null;
69
+ onBlur?: (e: any) => void;
70
+ onFocus?: (e: any) => void;
71
+ };
72
+
73
+
74
+ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
75
+ const {
76
+ wrapperClassName,
77
+ controlClassName,
78
+ disabled,
79
+ required,
80
+ value,
81
+ label,
82
+ placeholder,
83
+ name,
84
+ id,
85
+ columnTitle,
86
+ depth,
87
+ loader,
88
+ displayResult,
89
+ displayResultArrow,
90
+ controlArrow,
91
+ valueType,
92
+ showCloseBtn,
93
+ style,
94
+ tabIndex,
95
+ triggerClassName,
96
+ triggerContent,
97
+ fetchArray,
98
+ onFetch,
99
+ onChange,
100
+ onBlur,
101
+ onFocus,
102
+ ...attributes
103
+ } = props;
104
+
105
+
106
+ const uniqueID = useId();
107
+ const idRes = id || uniqueID;
108
+ const rootRef = useRef<any>(null);
109
+ const valRef = useRef<any>(null);
110
+ const listRef = useRef<any>(null);
111
+
112
+
113
+ // current data depth (GLOBAL)
114
+ const [currentDataDepth, setCurrentDataDepth] = useState<number>(0);
115
+
116
+ // all data from fetched data (GLOBAL)
117
+ const [allData, setAllData] = useState<any[]>([]);
118
+
119
+ // options data (GLOBAL)
120
+ const [optData, setOptData] = useState<any[]>([]);
121
+
122
+
123
+
124
+ const [dictionaryData, setDictionaryData] = useState<any[]>([]);
125
+ const [loading, setLoading] = useState<boolean>(false);
126
+ const [columnTitleData, setColumnTitleData] = useState<any[]>([]);
127
+ const [hasErr, setHasErr] = useState<boolean>(false);
128
+ const [firstDataFeched, setFirstDataFeched] = useState<boolean>(false);
129
+ const [changedVal, setChangedVal] = useState<string>(value || '');
130
+ const windowScrollUpdate = debounce(handleScrollEvent, 500);
131
+
132
+
133
+
134
+ //for variable
135
+ const [data, setData] = useState<any[]>([]);
136
+ const [selectedData, setSelectedData] = useState<any>({
137
+ labels: [],
138
+ values: [],
139
+ queryIds: []
140
+ });
141
+ const [isShow, setIsShow] = useState<boolean>(false);
142
+
143
+
144
+
145
+ /**
146
+ * Check if an element is in the viewport
147
+ * @param {HTMLElement} elem
148
+ * @returns {boolean}
149
+ */
150
+ function isInViewport(elem: HTMLElement) {
151
+ const bounding = elem.getBoundingClientRect();
152
+ return (
153
+ bounding.top >= 0 &&
154
+ bounding.left >= 0 &&
155
+ bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
156
+ bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
157
+ );
158
+ }
159
+
160
+
161
+ function handleScrollEvent() {
162
+ getPlacement(listRef.current, true);
163
+ }
164
+
165
+
166
+ //
167
+ function getPlacement(el: HTMLElement, restorePos: boolean = false) {
168
+
169
+ if ( el === null ) return;
170
+
171
+
172
+ const PLACEMENT_TOP = 'top-0';
173
+ const PLACEMENT_BOTTOMEND = 'bottom-0';
174
+ const PLACEMENT_RIGHT = 'end-0';
175
+ const PLACEMENT_LEFT = 'start-0';
176
+
177
+
178
+ //restore position
179
+ if ( restorePos ) {
180
+ if ( isInViewport(el) ) {
181
+ el.classList.remove(PLACEMENT_BOTTOMEND);
182
+ el.style.removeProperty('bottom');
183
+ }
184
+ return;
185
+ }
186
+
187
+
188
+ // Adjust position
189
+ if ( !isInViewport(el) ) {
190
+ el.classList.add(PLACEMENT_BOTTOMEND);
191
+ el.style.setProperty('bottom', -1 + 'px', "important");
192
+ }
193
+
194
+
195
+ }
196
+
197
+
198
+
199
+
200
+ async function fetchData(_fetchArray: any, params: string, dataDepth: number, parentId: number = 0) {
201
+
202
+ const fetchFuncAsync = _fetchArray.fetchFuncAsync;
203
+ const fetchFuncMethod = _fetchArray.fetchFuncMethod;
204
+ const fetchCallback = _fetchArray.fetchCallback;
205
+
206
+
207
+ if (typeof fetchFuncAsync === 'object') {
208
+
209
+ //
210
+ setLoading(true);
211
+
212
+ const response: any = await fetchFuncAsync[`${fetchFuncMethod}`](...params.split(','));
213
+ let _ORGIN_DATA: any[] = response.data;
214
+ let _TEMP_ALL_DATA: any[] = [];
215
+
216
+ // loading
217
+ setLoading(false);
218
+
219
+ if (typeof _ORGIN_DATA[0] === 'undefined') return;
220
+
221
+ // reset data structure
222
+ if (typeof (fetchCallback) === 'function') {
223
+ _ORGIN_DATA = fetchCallback(_ORGIN_DATA);
224
+ }
225
+
226
+
227
+ // Determine whether the data structure matches
228
+ if ( _ORGIN_DATA.length > 0 && typeof _ORGIN_DATA[0].id === 'undefined') {
229
+ console.warn('The data structure does not match, please refer to the example in the component documentation.');
230
+ setHasErr(true);
231
+ _ORGIN_DATA = [];
232
+ }
233
+
234
+ // add data depth
235
+ _ORGIN_DATA.forEach((item: any) => {
236
+ item.depth = dataDepth;
237
+ });
238
+
239
+
240
+ if (dataDepth === 0) {
241
+
242
+ // STEP 1: ===========
243
+ // all data from fetched data
244
+ _TEMP_ALL_DATA = JSON.parse(JSON.stringify(_ORGIN_DATA));
245
+ setAllData(_TEMP_ALL_DATA);
246
+
247
+ // STEP 2: ===========
248
+ // dictionary data (orginal)
249
+ setDictionaryData(_TEMP_ALL_DATA);
250
+
251
+
252
+ }
253
+ if (dataDepth > 0) {
254
+
255
+ // STEP 1: ===========
256
+ // all data from fetched data
257
+ _TEMP_ALL_DATA = allData;
258
+ addChildrenOpt(_TEMP_ALL_DATA, parentId, _ORGIN_DATA);
259
+
260
+ // STEP 2: ===========
261
+ // dictionary data (orginal)
262
+ setDictionaryData(_TEMP_ALL_DATA);
263
+
264
+
265
+ }
266
+
267
+
268
+ // STEP 3: ===========
269
+ // Add an empty item to each list to support empty item selection
270
+ const _EMPTY_SUPPORTED_DATA = JSON.parse(JSON.stringify(_TEMP_ALL_DATA));
271
+ addEmptyOpt(_EMPTY_SUPPORTED_DATA, 0);
272
+
273
+
274
+
275
+ // STEP 4: ===========
276
+ // Turn the data of each group into an array
277
+ let _temp_optData;
278
+ if (dataDepth === 0) {
279
+
280
+ _temp_optData = [_EMPTY_SUPPORTED_DATA];
281
+ setOptData(_temp_optData);
282
+ setData(_temp_optData);
283
+ }
284
+
285
+ if (dataDepth > 0) {
286
+ _temp_optData = data;
287
+
288
+ // Add an empty item to each list to support empty item selection
289
+ addEmptyOpt(_ORGIN_DATA, 0);
290
+
291
+ const childList = _ORGIN_DATA;
292
+ _temp_optData[dataDepth] = childList;
293
+
294
+ setOptData(_temp_optData);
295
+ setData(optData);
296
+ }
297
+
298
+
299
+ // STEP 5: ===========
300
+ //
301
+ onFetch?.(_EMPTY_SUPPORTED_DATA, _ORGIN_DATA);
302
+
303
+ return [_ORGIN_DATA, _EMPTY_SUPPORTED_DATA];
304
+
305
+
306
+ } else {
307
+ return [];
308
+ }
309
+
310
+
311
+ }
312
+
313
+
314
+ //
315
+ function doFetch(dataDepthMax: boolean, dataDepth: number = 0, parentId: number = 0, emptyAction: boolean = false) {
316
+
317
+ // if empty selection is selected
318
+ if (emptyAction) return;
319
+
320
+ // If the depth is max, no more requests
321
+ if (dataDepthMax) return;
322
+
323
+ // other
324
+ if ( typeof fetchArray![dataDepth] === 'undefined' ) return new Promise((resolve, reject) => resolve([[],[]]) );
325
+
326
+ // data fetch action
327
+ const _oparams: any[] = fetchArray![dataDepth].fetchFuncMethodParams || [];
328
+ const _params: any[] = _oparams.map((item: any) => item !== '$QUERY_ID' ? item : parentId);
329
+ return fetchData(fetchArray![dataDepth], (_params).join(','), dataDepth, parentId);
330
+ }
331
+
332
+
333
+
334
+ function handleFocus(event: any) {
335
+ rootRef.current.classList.add('focus');
336
+
337
+ //
338
+ handleDisplayOptions(null);
339
+
340
+ //
341
+ onFocus?.(event);
342
+ }
343
+
344
+
345
+ function handleBlur(event: any) {
346
+
347
+ //----
348
+ //remove focus style
349
+ rootRef.current.classList.remove('focus');
350
+
351
+
352
+ //
353
+ onBlur?.(event);
354
+ }
355
+
356
+
357
+
358
+ /**
359
+ * If clicked on outside of element
360
+ */
361
+ function handleClickOutside(event: any) {
362
+
363
+ // svg element
364
+ if ( typeof event.target.className === 'object' ) return;
365
+
366
+ if (
367
+ event.target.className != '' && (
368
+ event.target.className.indexOf('cascading-select-e2e__wrapper') < 0 &&
369
+ event.target.className.indexOf('form-control') < 0 &&
370
+ event.target.className.indexOf('cascading-select-e2e__trigger') < 0 &&
371
+ event.target.className.indexOf('cascading-select-e2e__items') < 0 &&
372
+ event.target.className.indexOf('cascading-select-e2e__opt') < 0
373
+ )
374
+ ) {
375
+
376
+ setIsShow(false);
377
+
378
+ }
379
+ }
380
+
381
+ function handleDisplayOptions(event: any) {
382
+ if ( event ) event.preventDefault();
383
+
384
+ setIsShow(true);
385
+
386
+ // Execute the fetch task
387
+ if (!firstDataFeched) {
388
+ setLoading(true);
389
+ setFirstDataFeched(true);
390
+ doFetch(false, currentDataDepth, 0, false);
391
+ }
392
+
393
+ // window position
394
+ setTimeout( ()=> {
395
+ getPlacement(listRef.current);
396
+ }, 0 );
397
+
398
+ }
399
+
400
+
401
+ function handleClickItem(e: any, resValue: any, index: number, level: number) {
402
+
403
+ const dataDepthMax: boolean = resValue.depth === fetchArray!.length - 1;
404
+ const parentId: number = e.currentTarget.dataset.query;
405
+ const emptyAction: boolean = resValue.id.toString().indexOf('$EMPTY_ID_') < 0 ? false : true;
406
+
407
+
408
+ // update data depth
409
+ //////////////////////////////////////////
410
+ setCurrentDataDepth(resValue.depth + 1);
411
+ setCurrentDataDepth((prevState) => {
412
+ const _currentDataDepth = resValue.depth + 1;
413
+
414
+ // Execute the fetch task
415
+ //////////////////////////////////////////
416
+ doFetch(dataDepthMax, _currentDataDepth, parentId, emptyAction);
417
+
418
+ return _currentDataDepth;
419
+
420
+ });
421
+
422
+ // update value
423
+ //////////////////////////////////////////
424
+ const inputVal = updateValue(dictionaryData, resValue.id, level);
425
+
426
+ // callback
427
+ //////////////////////////////////////////
428
+ if (typeof (onChange) === 'function') {
429
+ onChange(valRef.current, resValue, index, level, inputVal);
430
+ }
431
+
432
+
433
+ // update data
434
+ //////////////////////////////////////////
435
+ const newData: any = data; // such as: [Array(6), Array(3)]
436
+
437
+ // All the elements from start(array.length - start) to the end of the array will be deleted.
438
+ newData.splice(level + 1);
439
+
440
+ // active status
441
+ if (resValue.children) {
442
+ const childList = resValue.children;
443
+ markAllItems(childList);
444
+ newData[level + 1] = childList;
445
+ }
446
+
447
+ markCurrent(newData[level], index);
448
+
449
+
450
+ // close modal
451
+ //////////////////////////////////////////
452
+ if (dataDepthMax && resValue.id.toString().indexOf('$EMPTY_ID_') < 0) {
453
+ setIsShow(false);
454
+
455
+ // update data depth
456
+ setCurrentDataDepth(0);
457
+ }
458
+
459
+
460
+ }
461
+
462
+
463
+
464
+ /**
465
+ * Active the selected item
466
+ * @param arr
467
+ * @param index
468
+ * @returns
469
+ */
470
+ function markCurrent(arr: any[], index: number) {
471
+
472
+ // click an item
473
+ //////////////////////////////////////////
474
+ for (let i = 0; i < arr.length; i++) {
475
+ if (i === index) {
476
+ arr[i].current = true;
477
+ } else {
478
+ arr[i].current = false;
479
+ }
480
+ }
481
+
482
+ // return result
483
+ //////////////////////////////////////////
484
+ return arr;
485
+ }
486
+
487
+ /**
488
+ * Deactivate all items
489
+ * @param arr
490
+ * @returns
491
+ */
492
+ function markAllItems(arr: any[]) {
493
+ for (let i = 0; i < arr.length; i++) {
494
+ arr[i].current = false;
495
+ if (arr[i].children) markAllItems(arr[i].children);
496
+ }
497
+ }
498
+
499
+
500
+
501
+ function updateValue(arr: any[], targetVal: any, level: number | boolean = false) {
502
+
503
+ const inputEl: any = valRef.current;
504
+ let _valueData: any, _labelData: any, _queryIdsData: any;
505
+
506
+ if (targetVal.toString().indexOf('$EMPTY_ID_') >= 0) {
507
+
508
+ // If clearing the current column
509
+ //////////////////////////////////////////
510
+ _valueData = selectedData.values;
511
+ _labelData = selectedData.labels;
512
+ _queryIdsData = selectedData.queryIds;
513
+
514
+ // update result to input
515
+ _valueData.splice(level);
516
+ _labelData.splice(level);
517
+ _queryIdsData.splice(level);
518
+
519
+ //
520
+ setSelectedData({
521
+ labels: _labelData,
522
+ values: _valueData,
523
+ queryIds: _queryIdsData,
524
+ });
525
+
526
+
527
+ } else {
528
+
529
+ // click an item
530
+ //////////////////////////////////////////
531
+ //search JSON key that contains specific string
532
+ const _labels = queryResultOfJSON(arr, targetVal, 'value');
533
+ const _values = queryResultOfJSON(arr, targetVal, 'key');
534
+ const _queryIds = queryResultOfJSON(arr, targetVal, 'query');
535
+
536
+ // update result to input
537
+ _valueData = _values ? _values.map((item: any) => item) : [];
538
+ _labelData = _labels ? _labels.map((item: any) => item) : [];
539
+ _queryIdsData = _queryIds ? _queryIds.map((item: any) => item) : [];
540
+
541
+ //
542
+ setSelectedData({
543
+ labels: _labelData,
544
+ values: _valueData,
545
+ queryIds: _queryIdsData,
546
+ });
547
+
548
+
549
+
550
+ }
551
+
552
+
553
+ // update selected data
554
+ //////////////////////////////////////////
555
+ const inputVal_0 = _valueData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)!.join(',');
556
+ const inputVal_1 = _labelData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)!.join(',');
557
+
558
+ if (valueType === 'value') {
559
+ if (inputEl !== null) setChangedVal(inputVal_0);
560
+ } else {
561
+ if (inputEl !== null) setChangedVal(inputVal_1);
562
+ }
563
+
564
+ return {
565
+ 0: inputVal_0,
566
+ 1: inputVal_1
567
+ }
568
+
569
+ }
570
+
571
+ function initDefaultValue(defaultValue: any) {
572
+
573
+
574
+ // change the value to trigger component rendering
575
+ if ( typeof defaultValue === 'undefined' || defaultValue === '' ) {
576
+ setSelectedData({
577
+ labels: [],
578
+ values: [],
579
+ queryIds: []
580
+ });
581
+
582
+ setAllData([]);
583
+ setDictionaryData([]);
584
+ setOptData([]);
585
+ setData([]);
586
+ setChangedVal('');
587
+ setFirstDataFeched(false);
588
+ return;
589
+ } else {
590
+ setChangedVal(defaultValue);
591
+ }
592
+
593
+
594
+ //
595
+ setFirstDataFeched(true);
596
+ doFetch(false, 0, 0, false)?.then((firstColResponse: any) => {
597
+
598
+
599
+ const _ORGIN_DATA: any[] = firstColResponse[0];
600
+ const _CHILDREN_DATA: any[] = firstColResponse[1];
601
+ let activedIndex: any;
602
+ const allFetch: any[] = [];
603
+
604
+ const rowQueryAttr: string = valueType === 'value' ? 'id' : 'name';
605
+ const targetVal: any = defaultValue.match(/(\[.*?\])/gi)!.map((item: any, i: number) => defaultValue.split(',')[i].replace(item, ''));
606
+ const queryIds: any = defaultValue.match(/[^\[]+(?=(\[ \])|\])/gi);
607
+
608
+ //
609
+ let _TEMP_ALL_DATA: any[] = [];
610
+
611
+ //
612
+ const _allColumnsData: any[] = [];
613
+ const _allLables: any[] = [];
614
+ const _allValues: any[] = [];
615
+
616
+
617
+ // loop over each column
618
+ //////////////////////////////////////////
619
+ for (let col = 0; col <= targetVal.length; col++) {
620
+
621
+ if (col === 0) {
622
+
623
+ // STEP 1: ===========
624
+ //active item from current column
625
+ const newData: any[] = JSON.parse(JSON.stringify(_CHILDREN_DATA));
626
+ activedIndex = _CHILDREN_DATA.findIndex((item: any) => {
627
+ return item[rowQueryAttr].toString() === targetVal[col].toString();
628
+ });
629
+
630
+ markAllItems(newData);
631
+ markCurrent(newData, activedIndex);
632
+
633
+
634
+ // STEP 2: ===========
635
+ // all data from fetched data
636
+ _TEMP_ALL_DATA = _ORGIN_DATA;
637
+
638
+ // STEP 3: ===========
639
+ // dictionary data (orginal)
640
+ // Same as the `STEP 2`
641
+
642
+
643
+ // STEP 4: ===========
644
+ // update result data
645
+ if ( activedIndex !== -1 ) {
646
+ _allLables.push(newData[activedIndex].name);
647
+ _allValues.push(newData[activedIndex].id);
648
+ }
649
+
650
+ _allColumnsData.push(newData);
651
+
652
+
653
+
654
+ }
655
+
656
+ if (col > 0) {
657
+ allFetch.push(doFetch(false, col, queryIds[col - 1], false));
658
+ }
659
+
660
+
661
+
662
+ }
663
+
664
+ // fetch all columns except the first
665
+ //////////////////////////////////////////
666
+ Promise.all(allFetch).then((values) => {
667
+
668
+ values.filter((v: any) => typeof v !== 'undefined').forEach((colResponse: any, i: number) => {
669
+
670
+ const _CURRENT_COL_DATA: any[] = colResponse[0];
671
+ const curDepth: number = i+1;
672
+
673
+ // STEP 1: ===========
674
+ //active item from current column
675
+ const newData: any[] = JSON.parse(JSON.stringify(_CURRENT_COL_DATA));
676
+ activedIndex = newData.findIndex((item: any) => {
677
+ if ( typeof targetVal[curDepth] !== 'undefined' ) {
678
+ return item[rowQueryAttr].toString() === targetVal[curDepth].toString();
679
+ }
680
+ });
681
+
682
+ markAllItems(newData);
683
+ markCurrent(newData, activedIndex);
684
+
685
+ // STEP 2: ===========
686
+ // all data from fetched data
687
+ if ( typeof values[curDepth] !== 'undefined') {
688
+ const childList = values[curDepth][0];
689
+ newData[activedIndex].children = childList;
690
+ }
691
+
692
+ _TEMP_ALL_DATA.forEach((item: any) => {
693
+ if (item.id === queryIds[i]) item.children = newData;
694
+ });
695
+
696
+
697
+ // STEP 3: ===========
698
+ // dictionary data (orginal)
699
+ setDictionaryData(newData);
700
+
701
+
702
+ // STEP 4: ===========
703
+ // update result data
704
+ if ( activedIndex !== -1 ) {
705
+ _allLables.push(newData[activedIndex].name);
706
+ _allValues.push(newData[activedIndex].id);
707
+ }
708
+
709
+ _allColumnsData.push(newData);
710
+
711
+
712
+ return true;
713
+
714
+ });
715
+
716
+
717
+ // STEP 5: ===========
718
+ // all data from fetched data
719
+ setAllData(_TEMP_ALL_DATA);
720
+
721
+ // STEP 6: ===========
722
+ // dictionary data (orginal)
723
+ setDictionaryData(_TEMP_ALL_DATA);
724
+
725
+
726
+ // STEP 7: ===========
727
+ //update data
728
+ setOptData(_allColumnsData);
729
+ setData(_allColumnsData);
730
+
731
+
732
+ // STEP 8: ===========
733
+ //Set a default value
734
+ setSelectedData({
735
+ labels: _allLables,
736
+ values: _allValues,
737
+ queryIds: queryIds,
738
+ });
739
+
740
+ });
741
+
742
+
743
+
744
+ });
745
+
746
+
747
+ }
748
+
749
+
750
+
751
+ function fillColumnTitle() {
752
+
753
+ const dataDepth = fetchArray!.length;
754
+ const oldColumnTitleData = columnTitle ? columnTitle : [];
755
+ const newColumnTitleData = new Array(dataDepth)?.fill('');
756
+ oldColumnTitleData!.forEach((item: any, index: number) => {
757
+ newColumnTitleData[index] = item;
758
+ });
759
+
760
+ //
761
+ if (oldColumnTitleData.length > dataDepth) {
762
+ newColumnTitleData.splice(dataDepth, oldColumnTitleData.length - dataDepth);
763
+ }
764
+
765
+ setColumnTitleData(newColumnTitleData);
766
+ }
767
+
768
+
769
+ function addChildrenOpt(obj: any[], parentId: number, childrenData: any[]) {
770
+
771
+ obj.forEach((item: any) => {
772
+ if (item.id === parentId) item.children = childrenData;
773
+
774
+ if (item.children) {
775
+ addChildrenOpt(item.children, parentId, childrenData);
776
+ }
777
+ });
778
+ }
779
+
780
+
781
+ function addEmptyOpt(obj: any[], index: number) {
782
+
783
+ index++;
784
+
785
+ obj.unshift({
786
+ id: "$EMPTY_ID_" + index,
787
+ name: "",
788
+ depth: obj.length === 0 ? 0 : obj[0].depth
789
+ });
790
+
791
+ obj.forEach((item: any, depth: number) => {
792
+ if (item.children) {
793
+ addEmptyOpt(item.children, index * (depth + 1));
794
+ }
795
+ });
796
+ }
797
+
798
+
799
+ function queryResultOfJSON(data: any[], targetVal: any, returnType: string) {
800
+
801
+ let callbackValueNested: any[] = [];
802
+ let lastFirstLevelName = '';
803
+ let loop = true;
804
+ let resDepth = 0;
805
+ const rowQueryAttr = 'id';
806
+
807
+ const getIndexOf = function (arr: any[], val: any) {
808
+ for (let i = 0; i < arr.length; i++) {
809
+ if (arr[i][rowQueryAttr].toString() === val.toString()) return i;
810
+ }
811
+ return -1;
812
+ };
813
+
814
+
815
+ const searchJsonStr = function (list: any[], depth?: any) {
816
+
817
+ // `depth` is very important, it is used to accurately judge the final result
818
+ if (typeof (depth) === 'undefined') {
819
+ depth = 0;
820
+ } else {
821
+ depth++;
822
+ }
823
+
824
+ for (let i = 0; i < list.length; i++) {
825
+
826
+ const row = list[i];
827
+ let callbackValue: any;
828
+
829
+ if (returnType === 'key') callbackValue = row[rowQueryAttr].toString();
830
+ if (returnType === 'value') callbackValue = row.name.toString();
831
+ if (returnType === 'query') callbackValue = typeof row.queryId !== 'undefined' ? row.queryId.toString() : '';
832
+
833
+
834
+ if (loop) {
835
+ // get first-level item
836
+ if (getIndexOf(data, row[rowQueryAttr]) !== -1) {
837
+ callbackValueNested.push(callbackValue as never);
838
+ lastFirstLevelName = callbackValue;
839
+ }
840
+
841
+ // get child-level item
842
+ if (row.children) {
843
+ callbackValueNested.push(callbackValue as never);
844
+ }
845
+
846
+ }
847
+
848
+
849
+ //check the value
850
+ if (row[rowQueryAttr].toString() === targetVal.toString()) {
851
+ callbackValueNested.push(callbackValue as never);
852
+ loop = false;
853
+ resDepth = depth;
854
+ break;
855
+ }
856
+
857
+ // Note: Recursion must be placed here
858
+ if (loop) {
859
+ if (row.children) {
860
+ searchJsonStr(row.children, depth);
861
+ }
862
+ }
863
+
864
+
865
+ }
866
+
867
+
868
+ }
869
+ searchJsonStr(data);
870
+
871
+
872
+ // (1) Remove duplicate values
873
+ //------------------------------------------
874
+ callbackValueNested = callbackValueNested.filter(function (item, index, arr) {
875
+ return arr.indexOf(item, 0) === index;
876
+ });
877
+
878
+
879
+ // (2) Delete needless first-level
880
+ //------------------------------------------
881
+ let resAll = callbackValueNested.slice(callbackValueNested.indexOf(lastFirstLevelName as never), callbackValueNested.length)
882
+
883
+
884
+ // (3) Returns result
885
+ //------------------------------------------
886
+ if (resAll.length > 1) {
887
+ // Get first-level item
888
+ resAll.splice(1);
889
+
890
+ // Get child-level item
891
+ let resChild = callbackValueNested.slice(-resDepth); // Get the last elements in reverse
892
+
893
+ // Combine
894
+ resAll = resAll.concat(resChild);
895
+
896
+ }
897
+
898
+ return resAll;
899
+
900
+ }
901
+
902
+ function displayInfo() {
903
+
904
+
905
+ return selectedData!.labels ? selectedData!.labels.map((item: any, i: number, arr: any[]) => {
906
+ if (arr.length - 1 === i) {
907
+ return (
908
+ <div key={i}>
909
+ <span dangerouslySetInnerHTML={{
910
+ __html: item
911
+ }}></span>
912
+ </div>
913
+ )
914
+ } else {
915
+ return (
916
+ <div key={i}>
917
+ <span dangerouslySetInnerHTML={{
918
+ __html: item
919
+ }}></span>
920
+ {arrowGenerator()}
921
+ </div>
922
+ )
923
+ }
924
+ }) : '';
925
+
926
+ }
927
+
928
+ function arrowGenerator() {
929
+ return displayResultArrow ? displayResultArrow : <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>;
930
+ }
931
+
932
+
933
+ useEffect(() => {
934
+
935
+
936
+ // column titles
937
+ //--------------
938
+ fillColumnTitle();
939
+
940
+ // Initialize default value (request parameters for each level)
941
+ //--------------
942
+ initDefaultValue(value);
943
+
944
+ // If you use the dynamic form assignment (such as document.getElementById(xxx).value),
945
+ // you need to judge the value of the input obtained by using the macrotask "setInterval()"
946
+ let timer: any = null;
947
+ let initTimes: number = 0;
948
+ let hasValue: boolean = false;
949
+ timer = setInterval( () => {
950
+ if ( initTimes > 5 || hasValue ) {
951
+ clearInterval(timer);
952
+ } else {
953
+ if ( valRef.current !== null && valRef.current.value !== '' && ( typeof value === 'undefined' || value === '' ) ) {
954
+ initDefaultValue(valRef.current.value);
955
+ hasValue = true;
956
+ }
957
+ initTimes++;
958
+
959
+ }
960
+ }, 500);
961
+
962
+
963
+
964
+ //
965
+ //--------------
966
+ document.removeEventListener('pointerdown', handleClickOutside);
967
+ document.addEventListener('pointerdown', handleClickOutside);
968
+
969
+
970
+ // Add function to the element that should be used as the scrollable area.
971
+ //--------------
972
+ window.removeEventListener('scroll', windowScrollUpdate);
973
+ window.removeEventListener('touchmove', windowScrollUpdate);
974
+ window.addEventListener('scroll', windowScrollUpdate);
975
+ window.addEventListener('touchmove', windowScrollUpdate);
976
+ windowScrollUpdate();
977
+
978
+
979
+ return () => {
980
+ document.removeEventListener('pointerdown', handleClickOutside);
981
+ window.removeEventListener('scroll', windowScrollUpdate);
982
+ window.removeEventListener('touchmove', windowScrollUpdate);
983
+
984
+ //
985
+ clearInterval(timer);
986
+ }
987
+
988
+
989
+ }, [value]);
990
+
991
+ return (
992
+ <>
993
+
994
+ <div className={wrapperClassName || wrapperClassName === '' ? `cascading-select-e2e__wrapper ${wrapperClassName}` : `cascading-select-e2e__wrapper mb-3 position-relative`} ref={rootRef}>
995
+ {label ? <><label htmlFor={idRes} className="form-label">{label}</label></> : null}
996
+
997
+ {triggerContent ? <>
998
+ <div className={triggerClassName ? `cascading-select-e2e__trigger ${triggerClassName}` : `cascading-select-e2e__trigger d-inline w-auto`} onClick={handleDisplayOptions}>{triggerContent}</div>
999
+ </> : null}
1000
+
1001
+
1002
+ <div className="cascading-select-e2e" style={{ zIndex: (depth ? depth : 100) }}>
1003
+
1004
+ {isShow && !hasErr ? (
1005
+ <div ref={listRef} className="cascading-select-e2e__items shadow">
1006
+ <ul>
1007
+ {loading ? <><div className="position-absolute top-0 start-0 mt-1 mx-1">{loader}</div></> : null}
1008
+ {showCloseBtn ? <a href="#" tabIndex={-1} onClick={(e)=> {
1009
+ e.preventDefault();
1010
+ setIsShow(false);
1011
+ }} className="cascading-select-e2e__close position-absolute top-0 end-0 mt-0 mx-1"><svg width="10px" height="10px" viewBox="0 0 1024 1024"><path fill="#000" d="M195.2 195.2a64 64 0 0 1 90.496 0L512 421.504 738.304 195.2a64 64 0 0 1 90.496 90.496L602.496 512 828.8 738.304a64 64 0 0 1-90.496 90.496L512 602.496 285.696 828.8a64 64 0 0 1-90.496-90.496L421.504 512 195.2 285.696a64 64 0 0 1 0-90.496z"/></svg></a> : null}
1012
+
1013
+
1014
+
1015
+ {data.map((item: any, level: number) => {
1016
+ return (
1017
+ <li key={level}>
1018
+ <Group
1019
+ level={level}
1020
+ columnTitle={columnTitleData}
1021
+ data={item}
1022
+ selectEv={(e, value, index) => handleClickItem(e, value, index, level)}
1023
+ />
1024
+ </li>
1025
+ )
1026
+ })}
1027
+ </ul>
1028
+
1029
+ </div>
1030
+ ) : null}
1031
+
1032
+
1033
+ </div>
1034
+
1035
+ <div className="cascading-select-e2e__val" onClick={handleDisplayOptions}>
1036
+
1037
+
1038
+ {displayResult ? (selectedData!.labels && selectedData!.labels.length > 0 ? <div className="cascading-select-e2e__result">{displayInfo()}</div> : null) : null}
1039
+
1040
+ <input
1041
+ ref={valRef}
1042
+ id={idRes}
1043
+ name={name}
1044
+ className={controlClassName || controlClassName === '' ? controlClassName : "form-control"}
1045
+ placeholder={placeholder}
1046
+ value={changedVal} // placeholder will not change if defaultValue is used
1047
+ onFocus={handleFocus}
1048
+ onBlur={handleBlur}
1049
+ disabled={disabled || null}
1050
+ required={required || null}
1051
+ style={style}
1052
+ tabIndex={tabIndex || 0}
1053
+ readOnly
1054
+ {...attributes}
1055
+ />
1056
+
1057
+ {isShow ? <div
1058
+ className="cascading-select-e2e__closemask"
1059
+ onClick={(e)=> {
1060
+ e.preventDefault();
1061
+ setIsShow(false);
1062
+ }}></div> : null}
1063
+
1064
+
1065
+ <span className="arrow" style={{pointerEvents: 'none'}}>
1066
+ {controlArrow ? controlArrow : <svg width="10px" height="10px" viewBox="0 -4.5 20 20">
1067
+ <g stroke="none" strokeWidth="1" fill="none">
1068
+ <g transform="translate(-180.000000, -6684.000000)" className="arrow-fill-g" fill="#a5a5a5">
1069
+ <g transform="translate(56.000000, 160.000000)">
1070
+ <path d="M144,6525.39 L142.594,6524 L133.987,6532.261 L133.069,6531.38 L133.074,6531.385 L125.427,6524.045 L124,6525.414 C126.113,6527.443 132.014,6533.107 133.987,6535 C135.453,6533.594 134.024,6534.965 144,6525.39">
1071
+ </path>
1072
+ </g>
1073
+ </g>
1074
+ </g>
1075
+ </svg>}
1076
+ </span>
1077
+
1078
+ </div>
1079
+
1080
+
1081
+
1082
+
1083
+
1084
+ </div>
1085
+
1086
+
1087
+ </>
1088
+ )
1089
+ };
1090
+
1091
+ export default CascadingSelectE2E;