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,1597 @@
|
|
|
1
|
+
import React, { useId, useEffect, useState, useRef, forwardRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { debounce } from './utils/performance';
|
|
4
|
+
import useThrottle from './utils/useThrottle';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
flatTree,
|
|
9
|
+
addTreeDepth,
|
|
10
|
+
addTreeIndent
|
|
11
|
+
} from './utils/tree';
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
declare module 'react' {
|
|
15
|
+
interface ReactI18NextChildren<T> {
|
|
16
|
+
children?: any;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type MultiFuncSelectOptionChangeFnType = (arg1: any, arg2: any, arg3: any) => void;
|
|
21
|
+
|
|
22
|
+
interface MultiSelectDataConfig {
|
|
23
|
+
values: string[] | number[];
|
|
24
|
+
labels: string[] | number[];
|
|
25
|
+
queryStrings: string[] | number[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface OptionConfig {
|
|
29
|
+
label: any;
|
|
30
|
+
value: any;
|
|
31
|
+
queryString: string | number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
interface MultiSelectConfig {
|
|
36
|
+
valid: boolean;
|
|
37
|
+
selectAll: boolean;
|
|
38
|
+
selectAllLabel?: string;
|
|
39
|
+
data: MultiSelectDataConfig | null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
type MultiFuncSelectProps = {
|
|
44
|
+
wrapperClassName?: string;
|
|
45
|
+
controlClassName?: string;
|
|
46
|
+
multiSelect?: MultiSelectConfig;
|
|
47
|
+
value?: string;
|
|
48
|
+
label?: React.ReactNode | string;
|
|
49
|
+
name?: string;
|
|
50
|
+
disabled?: any;
|
|
51
|
+
required?: any;
|
|
52
|
+
readOnly?: any;
|
|
53
|
+
placeholder?: string;
|
|
54
|
+
options?: OptionConfig[] | string;
|
|
55
|
+
hierarchical?: boolean;
|
|
56
|
+
indentation?: string;
|
|
57
|
+
winWidth?: string | Function;
|
|
58
|
+
doubleIndent?: boolean;
|
|
59
|
+
controlArrow?: React.ReactNode;
|
|
60
|
+
fetchTrigger?: boolean;
|
|
61
|
+
fetchTriggerForDefaultData?: MultiSelectDataConfig | null;
|
|
62
|
+
/** Set the depth value of the control to control the display of the pop-up layer appear above.
|
|
63
|
+
* Please set it when multiple controls are used at the same time. */
|
|
64
|
+
depth?: number;
|
|
65
|
+
/** Incoming data, you can set the third parameter of `onFetch` */
|
|
66
|
+
data?: any;
|
|
67
|
+
/** -- */
|
|
68
|
+
id?: string;
|
|
69
|
+
style?: React.CSSProperties;
|
|
70
|
+
tabIndex?: number;
|
|
71
|
+
[key: `data-${string}`]: string | undefined;
|
|
72
|
+
fetchNoneInfo?: string;
|
|
73
|
+
fetchUpdate?: boolean;
|
|
74
|
+
fetchFuncAsync?: any;
|
|
75
|
+
fetchFuncMethod?: string;
|
|
76
|
+
fetchFuncMethodParams?: any[];
|
|
77
|
+
fetchCallback?: (data: any) => void;
|
|
78
|
+
onFetch?: (e: any, e2: any, value: string, data: any, incomingData: string | null | undefined) => void;
|
|
79
|
+
onLoad?: (e: any, e2: any, value: string | null | undefined ) => void;
|
|
80
|
+
onSelect?: (data: any) => void;
|
|
81
|
+
onChange?: MultiFuncSelectOptionChangeFnType | null;
|
|
82
|
+
onBlur?: (e: any) => void;
|
|
83
|
+
onFocus?: (e: any) => void;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const MultiFuncSelect = forwardRef((props: MultiFuncSelectProps, ref: any) => {
|
|
87
|
+
const {
|
|
88
|
+
wrapperClassName,
|
|
89
|
+
controlClassName,
|
|
90
|
+
multiSelect,
|
|
91
|
+
disabled,
|
|
92
|
+
required,
|
|
93
|
+
value,
|
|
94
|
+
label,
|
|
95
|
+
name,
|
|
96
|
+
readOnly,
|
|
97
|
+
placeholder,
|
|
98
|
+
id,
|
|
99
|
+
options,
|
|
100
|
+
hierarchical,
|
|
101
|
+
indentation,
|
|
102
|
+
doubleIndent,
|
|
103
|
+
style,
|
|
104
|
+
depth,
|
|
105
|
+
controlArrow,
|
|
106
|
+
winWidth,
|
|
107
|
+
tabIndex,
|
|
108
|
+
fetchTrigger,
|
|
109
|
+
fetchTriggerForDefaultData,
|
|
110
|
+
fetchNoneInfo,
|
|
111
|
+
fetchUpdate,
|
|
112
|
+
fetchFuncAsync,
|
|
113
|
+
fetchFuncMethod,
|
|
114
|
+
fetchFuncMethodParams,
|
|
115
|
+
data,
|
|
116
|
+
fetchCallback,
|
|
117
|
+
onFetch,
|
|
118
|
+
onLoad,
|
|
119
|
+
onSelect,
|
|
120
|
+
onChange,
|
|
121
|
+
onBlur,
|
|
122
|
+
onFocus,
|
|
123
|
+
...attributes
|
|
124
|
+
} = props;
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
const WIN_WIDTH = typeof winWidth === 'function' ? winWidth() : winWidth ? winWidth : 'auto';
|
|
128
|
+
const INDENT_PLACEHOLDER = doubleIndent ? ` ` : ` `;
|
|
129
|
+
const INDENT_LAST_PLACEHOLDER = `${typeof indentation !== 'undefined' && indentation !== '' ? `${indentation} ` : ''}`;
|
|
130
|
+
const uniqueID = useId().replace(/\:/g, "-");
|
|
131
|
+
const idRes = id || uniqueID;
|
|
132
|
+
const rootRef = useRef<any>(null);
|
|
133
|
+
const rootSingleRef = useRef<any>(null);
|
|
134
|
+
const rootMultiRef = useRef<any>(null);
|
|
135
|
+
const selectInputRef = useRef<any>(null);
|
|
136
|
+
const valueInputRef = useRef<any>(null);
|
|
137
|
+
const listRef = useRef<any>(null);
|
|
138
|
+
const listContentRef = useRef<any>(null);
|
|
139
|
+
const optionsRes = options ? isJSON( options ) ? JSON.parse( options as string ) : options : [];
|
|
140
|
+
const windowScrollUpdate = debounce(handleScrollEvent, 500);
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
// return a array of options
|
|
144
|
+
let optionsDataInit: OptionConfig[] = optionsRes;
|
|
145
|
+
|
|
146
|
+
//
|
|
147
|
+
const [orginalData, setOrginalData] = useState<OptionConfig[]>(optionsDataInit);
|
|
148
|
+
const [optionsData, setOptionsData] = useState<OptionConfig[]>(optionsDataInit);
|
|
149
|
+
const [hasErr, setHasErr] = useState<boolean>(false);
|
|
150
|
+
const [controlLabel, setControlLabel] = useState<string | undefined>('');
|
|
151
|
+
const [controlValue, setControlValue] = useState<string | undefined>('');
|
|
152
|
+
const [controlTempValue, setControlTempValue] = useState<string | null>(null);
|
|
153
|
+
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
154
|
+
const [listContentHeight, setListContentHeight] = useState<number>(0);
|
|
155
|
+
const [incomingData, setIncomingData] = useState<string | null | undefined>(null);
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
// Multiple selection
|
|
159
|
+
const MULTI_SEL_VALID = multiSelect ? multiSelect.valid : false;
|
|
160
|
+
const [controlArr, setControlArr] = useState<any>({
|
|
161
|
+
labels: [],
|
|
162
|
+
values: []
|
|
163
|
+
});
|
|
164
|
+
const [itemSelectedAll, setItemSelectedAll] = useState<boolean>(false);
|
|
165
|
+
const multiSelControlOptionExist = (arr: any[], val: any) => arr.map((v: any) => v.toString()).includes(val.toString());
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
//performance
|
|
169
|
+
const handleChangeFetchSafe = useThrottle((val: any) => {
|
|
170
|
+
|
|
171
|
+
let _orginalData: OptionConfig[] = [];
|
|
172
|
+
const update = (inputData: any) => {
|
|
173
|
+
const filterRes = (data: any[]) => {
|
|
174
|
+
return inputData.filter((item: any) => {
|
|
175
|
+
if (
|
|
176
|
+
(
|
|
177
|
+
item.queryString.split(',').some((l: any) => l.charAt(0) === val.toLowerCase()) ||
|
|
178
|
+
item.queryString.split(',').some((l: any) => l.replace(/ /g, '').indexOf(val.toLowerCase()) >= 0) ||
|
|
179
|
+
item.label.toLowerCase().indexOf(val.toLowerCase()) >= 0
|
|
180
|
+
) &&
|
|
181
|
+
val != ''
|
|
182
|
+
) {
|
|
183
|
+
return true;
|
|
184
|
+
} else {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
setOptionsData(filterRes);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
if ( fetchUpdate ) {
|
|
194
|
+
|
|
195
|
+
handleFetch(val).then((response: any) => {
|
|
196
|
+
_orginalData = response;
|
|
197
|
+
update(_orginalData);
|
|
198
|
+
});
|
|
199
|
+
} else {
|
|
200
|
+
_orginalData = orginalData;
|
|
201
|
+
update(_orginalData);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
}, 150, [optionsData]);
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Format indent value
|
|
211
|
+
* @param {String|Array} str
|
|
212
|
+
* @returns {String|Array}
|
|
213
|
+
*/
|
|
214
|
+
function formatIndentVal(str: any) {
|
|
215
|
+
const reVar = new RegExp(INDENT_LAST_PLACEHOLDER, 'g');
|
|
216
|
+
if (Array.isArray(str)) {
|
|
217
|
+
return str.map((s: string) => s.replace(reVar,'').replace(/\ /ig,''));
|
|
218
|
+
} else {
|
|
219
|
+
return str.replace(reVar,'').replace(/\ /ig,'');
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Array unique
|
|
227
|
+
* @param {Array} str
|
|
228
|
+
* @returns {Array}
|
|
229
|
+
*/
|
|
230
|
+
function unique(arr: any[]) {
|
|
231
|
+
return Array.from(new Set(arr));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Remove html tag content
|
|
237
|
+
* @param {string} str
|
|
238
|
+
* @returns {string}
|
|
239
|
+
*/
|
|
240
|
+
function stripHTML(str: string) {
|
|
241
|
+
return str.replace(/<\/?[^>]+(>|$)(.*?)<\/?[^>]+(>|$)/ig, '');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Remove a specific item from an array
|
|
247
|
+
* @param {array} arr
|
|
248
|
+
* @param {string} value
|
|
249
|
+
* @returns {array}
|
|
250
|
+
*/
|
|
251
|
+
function removeItemOnce(arr: any[], value: string | number) {
|
|
252
|
+
const arrFormat = arr.map((v: any) => v.toString());
|
|
253
|
+
const index = arrFormat.indexOf(value.toString());
|
|
254
|
+
if (index > -1) {
|
|
255
|
+
arrFormat.splice(index, 1);
|
|
256
|
+
}
|
|
257
|
+
return arrFormat;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Remove multiple items from an array
|
|
262
|
+
* @param {array} arr
|
|
263
|
+
* @param {array} value
|
|
264
|
+
* @returns {array}
|
|
265
|
+
*/
|
|
266
|
+
function removeItems(arr: any[], value: any[]) {
|
|
267
|
+
const arrFormat = arr.map((v: any) => v.toString());
|
|
268
|
+
const valueFormat = value.map((v: any) => v.toString());
|
|
269
|
+
return arrFormat.filter((v: any) => {
|
|
270
|
+
return !valueFormat.includes(v);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Check if an element is in the viewport
|
|
277
|
+
* @param {HTMLElement} elem
|
|
278
|
+
* @returns {boolean}
|
|
279
|
+
*/
|
|
280
|
+
function isInViewport(elem: HTMLElement) {
|
|
281
|
+
const bounding = elem.getBoundingClientRect();
|
|
282
|
+
return (
|
|
283
|
+
bounding.top >= 0 &&
|
|
284
|
+
bounding.left >= 0 &&
|
|
285
|
+
bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
|
|
286
|
+
bounding.right <= (window.innerWidth || document.documentElement.clientWidth)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
function handleScrollEvent() {
|
|
292
|
+
getPlacement(listRef.current, true);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
//
|
|
297
|
+
function getPlacement(el: HTMLElement, restorePos: boolean = false) {
|
|
298
|
+
|
|
299
|
+
if ( el === null ) return;
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
const PLACEMENT_TOP = 'top-0';
|
|
303
|
+
const PLACEMENT_BOTTOMEND = 'bottom-0';
|
|
304
|
+
const PLACEMENT_RIGHT = 'end-0';
|
|
305
|
+
const PLACEMENT_LEFT = 'start-0';
|
|
306
|
+
|
|
307
|
+
const elTop = el.getBoundingClientRect().top;
|
|
308
|
+
const elSpacing = 50 + selectInputRef.current.clientHeight*3;
|
|
309
|
+
const elMinWindowSpacing = selectInputRef.current.clientHeight*2;
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
//restore position
|
|
313
|
+
if ( restorePos ) {
|
|
314
|
+
if ( isInViewport(el) ) {
|
|
315
|
+
el.classList.remove(PLACEMENT_BOTTOMEND);
|
|
316
|
+
el.style.removeProperty('bottom');
|
|
317
|
+
}
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if ( listContentRef.current === null ) return;
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
// STEP 0:
|
|
325
|
+
// save content height (Suitable for initial data with unchanged open options)
|
|
326
|
+
let _contentHeight = el.offsetHeight;
|
|
327
|
+
if ( listContentHeight === 0 ) {
|
|
328
|
+
setListContentHeight(el.offsetHeight);
|
|
329
|
+
} else {
|
|
330
|
+
_contentHeight = listContentHeight;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
// STEP 1:
|
|
335
|
+
// If the content exceeds the height of the window, first limit height and add scrollbar
|
|
336
|
+
let maxHeight = window.innerHeight - elSpacing;
|
|
337
|
+
if ( maxHeight < selectInputRef.current.clientHeight ) maxHeight = elMinWindowSpacing;
|
|
338
|
+
|
|
339
|
+
if ( _contentHeight > 0 && (_contentHeight > maxHeight) ) {
|
|
340
|
+
|
|
341
|
+
const newH = maxHeight - (elTop > window.innerHeight/2 ? 0 : elTop) + elMinWindowSpacing;
|
|
342
|
+
|
|
343
|
+
// default position
|
|
344
|
+
listContentRef.current.style.height = newH + 'px';
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
// if it's on top
|
|
348
|
+
if ( newH > maxHeight ) {
|
|
349
|
+
listContentRef.current.style.height = elTop - elMinWindowSpacing + 'px';
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
// Adjust the overall height to fit the wrapper
|
|
354
|
+
const _displayedItems = listContentRef.current.querySelectorAll('.list-group-item');
|
|
355
|
+
const _displayedHeight = _displayedItems[0].clientHeight * _displayedItems.length;
|
|
356
|
+
if ( _displayedHeight < listRef.current.clientHeight ) {
|
|
357
|
+
listContentRef.current.style.height = _displayedHeight + 'px';
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
//
|
|
361
|
+
listContentRef.current.style.overflowY = 'auto';
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
} else {
|
|
366
|
+
listContentRef.current.style.height = 'auto';
|
|
367
|
+
listContentRef.current.style.overflowY = 'inherit';
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
// STEP 2:
|
|
372
|
+
// Adjust position
|
|
373
|
+
if ( !isInViewport(el) ) {
|
|
374
|
+
el.classList.add(PLACEMENT_BOTTOMEND);
|
|
375
|
+
el.style.setProperty('bottom', selectInputRef.current.clientHeight + 5 + 'px', "important");
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
// STEP 3:
|
|
381
|
+
// It is on top when no scrollbars have been added
|
|
382
|
+
if ( !isInViewport(el) ) {
|
|
383
|
+
if ( el.getBoundingClientRect().top < 0 ) {
|
|
384
|
+
listContentRef.current.style.height = _contentHeight + el.getBoundingClientRect().top - elMinWindowSpacing + 'px';
|
|
385
|
+
listContentRef.current.style.overflowY = 'auto';
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
// Determine whether it is in JSON format
|
|
395
|
+
function isJSON( str: any ){
|
|
396
|
+
|
|
397
|
+
if ( typeof(str) === 'string' && str.length > 0 ) {
|
|
398
|
+
|
|
399
|
+
if ( str.replace( /\"\"/g, '' ).replace( /\,/g, '' ) == '[{}]' ) {
|
|
400
|
+
return false;
|
|
401
|
+
} else {
|
|
402
|
+
|
|
403
|
+
if (/^[\],:{}\s]*$/.test( str.replace(/\\["\\\/bfnrtu]/g, '@' ).
|
|
404
|
+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
|
405
|
+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
406
|
+
|
|
407
|
+
return true;
|
|
408
|
+
|
|
409
|
+
}else{
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
} else {
|
|
416
|
+
|
|
417
|
+
if (
|
|
418
|
+
typeof(str) === 'object' &&
|
|
419
|
+
Object.prototype.toString.call(str) === '[object Object]' &&
|
|
420
|
+
! str.length
|
|
421
|
+
) {
|
|
422
|
+
return true;
|
|
423
|
+
} else {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
function adjustMultiControlContainerHeight() {
|
|
433
|
+
setTimeout(() => {
|
|
434
|
+
rootSingleRef.current.style.height = rootMultiRef.current.clientHeight + 'px';
|
|
435
|
+
selectInputRef.current.style.height = rootMultiRef.current.clientHeight + 'px';
|
|
436
|
+
},0);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
async function fetchData(params: any, inputDefaultValue: any, init: boolean = true) {
|
|
441
|
+
|
|
442
|
+
// get incoming options from `data-options` of component
|
|
443
|
+
// It is usually used for complex cascading `<MultiFuncSelect />` components
|
|
444
|
+
const incomingOptionsData = valueInputRef.current.dataset.options;
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
// Determine whether the default value is user query input or default input
|
|
448
|
+
const defaultValue = init ? inputDefaultValue : '';
|
|
449
|
+
|
|
450
|
+
if ( typeof fetchFuncAsync === 'object' ) {
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
const response: any = await fetchFuncAsync[`${fetchFuncMethod}`](...params.split(','));
|
|
454
|
+
let _ORGIN_DATA = response.data;
|
|
455
|
+
|
|
456
|
+
// reset data structure
|
|
457
|
+
if (typeof (fetchCallback) === 'function') {
|
|
458
|
+
_ORGIN_DATA = fetchCallback(_ORGIN_DATA);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Determine whether the data structure matches
|
|
462
|
+
if ( _ORGIN_DATA.length > 0 && typeof _ORGIN_DATA[0].value === 'undefined' ) {
|
|
463
|
+
console.warn( 'The data structure does not match, please refer to the example in the component documentation.' );
|
|
464
|
+
setHasErr(true);
|
|
465
|
+
_ORGIN_DATA = [];
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
// STEP 1: ===========
|
|
470
|
+
// get incoming options from `data-options` of component
|
|
471
|
+
if ( typeof incomingOptionsData !== 'undefined' ) {
|
|
472
|
+
_ORGIN_DATA = JSON.parse( incomingOptionsData );
|
|
473
|
+
|
|
474
|
+
// set value if the attribute `data-options` of component exists, only valid for single selection (it may be an empty array)
|
|
475
|
+
if (typeof defaultValue !== 'undefined' && defaultValue !== '') valueInputRef.current.dataset.value = defaultValue;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
// STEP 2: ===========
|
|
480
|
+
// Set hierarchical categories ( with sub-categories )
|
|
481
|
+
if ( hierarchical ) {
|
|
482
|
+
addTreeDepth(_ORGIN_DATA);
|
|
483
|
+
_ORGIN_DATA = flatTree(_ORGIN_DATA);
|
|
484
|
+
addTreeIndent(_ORGIN_DATA, INDENT_PLACEHOLDER, INDENT_LAST_PLACEHOLDER, 'label');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
// STEP 3: ===========
|
|
491
|
+
// value & label must be initialized
|
|
492
|
+
let filterRes: any = [];
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
if ( fetchTrigger ) {
|
|
496
|
+
|
|
497
|
+
// If a manual action is used to trigger the request
|
|
498
|
+
if ( typeof fetchTriggerForDefaultData !== 'undefined' && fetchTriggerForDefaultData !== null && typeof fetchTriggerForDefaultData?.values[0] !== 'undefined' ) {
|
|
499
|
+
filterRes = [{
|
|
500
|
+
value: fetchTriggerForDefaultData?.values[0],
|
|
501
|
+
label: fetchTriggerForDefaultData?.labels[0],
|
|
502
|
+
queryString: fetchTriggerForDefaultData?.queryStrings[0]
|
|
503
|
+
}];
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
} else {
|
|
507
|
+
const filterResQueryValue = _ORGIN_DATA.filter((item: any) => item.value == defaultValue );
|
|
508
|
+
const filterResQueryLabel = _ORGIN_DATA.filter((item: any) => item.label == defaultValue );
|
|
509
|
+
|
|
510
|
+
filterRes = filterResQueryValue;
|
|
511
|
+
if ( filterResQueryValue.length === 0 ) filterRes = filterResQueryLabel;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
// STEP 4: ===========
|
|
517
|
+
// ++++++++++++++++++++
|
|
518
|
+
// Single selection
|
|
519
|
+
// ++++++++++++++++++++
|
|
520
|
+
if ( typeof defaultValue === 'undefined' || defaultValue === '' ) { // Do not use `init`, otherwise the query will revert to the default value if there is no value
|
|
521
|
+
setControlValue('');
|
|
522
|
+
setControlLabel('');
|
|
523
|
+
} else {
|
|
524
|
+
if ( filterRes.length > 0 ) {
|
|
525
|
+
setControlValue(filterRes[0].value);
|
|
526
|
+
setControlLabel(formatIndentVal(filterRes[0].label) as string);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
// ++++++++++++++++++++
|
|
533
|
+
// Multiple selection
|
|
534
|
+
// ++++++++++++++++++++
|
|
535
|
+
if ( MULTI_SEL_VALID ) {
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
if ( (typeof defaultValue === 'undefined' || defaultValue === '') && init ) {
|
|
539
|
+
setControlArr({
|
|
540
|
+
labels: [],
|
|
541
|
+
values: []
|
|
542
|
+
});
|
|
543
|
+
setItemSelectedAll(false);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if ( typeof defaultValue !== 'undefined' && defaultValue !== '' && multiSelect?.data !== null ) {
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
// initialize default values of Multiple selection
|
|
550
|
+
const _currentData: any = multiSelect?.data;
|
|
551
|
+
|
|
552
|
+
setControlArr({
|
|
553
|
+
labels: _currentData.labels,
|
|
554
|
+
values: _currentData.values,
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
//
|
|
559
|
+
const _values: string[] = defaultValue.split(',');
|
|
560
|
+
_values.forEach((_value: string, _index: number) => {
|
|
561
|
+
|
|
562
|
+
if ( !multiSelControlOptionExist(_currentData.values, _value) && typeof _currentData.values[_index] !== 'undefined' ) {
|
|
563
|
+
|
|
564
|
+
let filterRes: any = [];
|
|
565
|
+
filterRes = [{
|
|
566
|
+
value: _currentData.values[_index],
|
|
567
|
+
label: _currentData.labels[_index],
|
|
568
|
+
queryString: _currentData.queryStrings[_index]
|
|
569
|
+
}];
|
|
570
|
+
|
|
571
|
+
setControlArr((prevState: any) => {
|
|
572
|
+
return {
|
|
573
|
+
labels: unique([...prevState.labels, typeof filterRes[0] !== 'undefined' ? filterRes[0].label : ''].filter((v: any) => v !== '')),
|
|
574
|
+
values: unique([...prevState.values, typeof filterRes[0] !== 'undefined' ? filterRes[0].value : ''].filter((v: any) => v !== ''))
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
// Appropriate multi-item container height
|
|
585
|
+
adjustMultiControlContainerHeight();
|
|
586
|
+
|
|
587
|
+
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
|
|
594
|
+
// STEP 5: ===========
|
|
595
|
+
//
|
|
596
|
+
setOptionsData(_ORGIN_DATA); // data must be initialized
|
|
597
|
+
|
|
598
|
+
//
|
|
599
|
+
setOrginalData(_ORGIN_DATA);
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
// STEP 6: ===========
|
|
603
|
+
//
|
|
604
|
+
onFetch?.(selectInputRef.current, valueInputRef.current, defaultValue, _ORGIN_DATA, incomingData);
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
//
|
|
608
|
+
return _ORGIN_DATA;
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
} else {
|
|
612
|
+
|
|
613
|
+
|
|
614
|
+
// STEP 1: ===========
|
|
615
|
+
// get incoming options from `data-options` of component
|
|
616
|
+
if ( typeof incomingOptionsData !== 'undefined' ) {
|
|
617
|
+
optionsDataInit = JSON.parse( incomingOptionsData );
|
|
618
|
+
|
|
619
|
+
// set value if the attribute `data-options` of component exists, only valid for single selection (it may be an empty array)
|
|
620
|
+
if (typeof defaultValue !== 'undefined' && defaultValue !== '') valueInputRef.current.dataset.value = defaultValue;
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
|
|
625
|
+
// STEP 2: ===========
|
|
626
|
+
// Set hierarchical categories ( with sub-categories )
|
|
627
|
+
if ( hierarchical ) {
|
|
628
|
+
addTreeDepth(optionsDataInit);
|
|
629
|
+
optionsDataInit = flatTree(optionsDataInit);
|
|
630
|
+
addTreeIndent(optionsDataInit, INDENT_PLACEHOLDER, INDENT_LAST_PLACEHOLDER, 'label');
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
// STEP 3: ===========
|
|
636
|
+
// value & label must be initialized
|
|
637
|
+
let filterRes: any = [];
|
|
638
|
+
const filterResQueryValue = optionsDataInit.filter((item: any) => item.value == defaultValue );
|
|
639
|
+
const filterResQueryLabel = optionsDataInit.filter((item: any) => item.label == defaultValue );
|
|
640
|
+
|
|
641
|
+
filterRes = filterResQueryValue;
|
|
642
|
+
if ( filterResQueryValue.length === 0 ) filterRes = filterResQueryLabel;
|
|
643
|
+
|
|
644
|
+
// STEP 4: ===========
|
|
645
|
+
// ++++++++++++++++++++
|
|
646
|
+
// Single selection
|
|
647
|
+
// ++++++++++++++++++++
|
|
648
|
+
if ( typeof defaultValue === 'undefined' || defaultValue === '' ) { // Do not use `init`, otherwise the query will revert to the default value if there is no value
|
|
649
|
+
setControlValue('');
|
|
650
|
+
setControlLabel('');
|
|
651
|
+
} else {
|
|
652
|
+
if ( filterRes.length > 0 ) {
|
|
653
|
+
setControlValue(filterRes[0].value);
|
|
654
|
+
setControlLabel(formatIndentVal(filterRes[0].label));
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
// ++++++++++++++++++++
|
|
662
|
+
// Multiple selection
|
|
663
|
+
// ++++++++++++++++++++
|
|
664
|
+
if ( MULTI_SEL_VALID ) {
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
if ( (typeof defaultValue === 'undefined' || defaultValue === '') && init ) {
|
|
668
|
+
setControlArr({
|
|
669
|
+
labels: [],
|
|
670
|
+
values: []
|
|
671
|
+
});
|
|
672
|
+
setItemSelectedAll(false);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
if ( typeof defaultValue !== 'undefined' && defaultValue !== '' && multiSelect?.data !== null ) {
|
|
676
|
+
|
|
677
|
+
// initialize default values of Multiple selection
|
|
678
|
+
const _currentData: any = multiSelect?.data;
|
|
679
|
+
|
|
680
|
+
setControlArr({
|
|
681
|
+
labels: _currentData.labels,
|
|
682
|
+
values: _currentData.values,
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
//
|
|
687
|
+
const _values: string[] = typeof defaultValue !== 'undefined' ? defaultValue.split(',') : [];
|
|
688
|
+
_values.forEach((_value: string, _index: number) => {
|
|
689
|
+
|
|
690
|
+
if ( !multiSelControlOptionExist(_currentData.values, _value) && typeof _currentData.values[_index] !== 'undefined' ) {
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
let filterRes: any = [];
|
|
694
|
+
filterRes = [{
|
|
695
|
+
value: _currentData.values[_index],
|
|
696
|
+
label: _currentData.labels[_index],
|
|
697
|
+
queryString: _currentData.queryStrings[_index]
|
|
698
|
+
}];
|
|
699
|
+
|
|
700
|
+
setControlArr((prevState: any) => {
|
|
701
|
+
return {
|
|
702
|
+
labels: unique([...prevState.labels, typeof filterRes[0] !== 'undefined' ? filterRes[0].label : ''].filter((v: any) => v !== '')),
|
|
703
|
+
values: unique([...prevState.values, typeof filterRes[0] !== 'undefined' ? filterRes[0].value : ''].filter((v: any) => v !== ''))
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
// Appropriate multi-item container height
|
|
712
|
+
adjustMultiControlContainerHeight();
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
// STEP 5: ===========
|
|
720
|
+
//
|
|
721
|
+
setOptionsData(optionsDataInit); // data must be initialized
|
|
722
|
+
|
|
723
|
+
//
|
|
724
|
+
setOrginalData(optionsDataInit);
|
|
725
|
+
|
|
726
|
+
// STEP 6: ===========
|
|
727
|
+
//
|
|
728
|
+
onFetch?.(selectInputRef.current, valueInputRef.current, defaultValue, optionsDataInit, incomingData);
|
|
729
|
+
|
|
730
|
+
//
|
|
731
|
+
return optionsDataInit;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
function cancel() {
|
|
738
|
+
// hide list
|
|
739
|
+
setIsOpen(false);
|
|
740
|
+
|
|
741
|
+
// restore data
|
|
742
|
+
setOptionsData(orginalData);
|
|
743
|
+
|
|
744
|
+
// update temporary value
|
|
745
|
+
setControlTempValue(null);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function activate() {
|
|
749
|
+
|
|
750
|
+
// show list
|
|
751
|
+
setIsOpen(true);
|
|
752
|
+
|
|
753
|
+
// restore data
|
|
754
|
+
setOptionsData(orginalData);
|
|
755
|
+
|
|
756
|
+
// update temporary value
|
|
757
|
+
setControlTempValue('');
|
|
758
|
+
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function rootWrapperSwitch() {
|
|
762
|
+
// remove active styles from the root container and activate current wrapper
|
|
763
|
+
[].slice.call(document.querySelectorAll('.multifunc-select__wrapper')).forEach((node: any) => {
|
|
764
|
+
node.classList.remove('active', 'focus');
|
|
765
|
+
});
|
|
766
|
+
rootRef.current.classList.add('active', 'focus');
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
async function handleSelect(el: any, dataInput: any = false, valueArr: any[] = [], labelArr: any[] = []) {
|
|
771
|
+
|
|
772
|
+
if ( typeof el === 'undefined' ) return;
|
|
773
|
+
|
|
774
|
+
let index: number | undefined | string;
|
|
775
|
+
|
|
776
|
+
// get incoming options from `data-options` of component
|
|
777
|
+
// It is usually used for complex cascading `<MultiFuncSelect />` components
|
|
778
|
+
const incomingOptionsData = valueInputRef.current.dataset.options;
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
// cancel
|
|
782
|
+
if ( !(MULTI_SEL_VALID && isOpen) ) {
|
|
783
|
+
cancel();
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
//remove focus style
|
|
787
|
+
if ( !(MULTI_SEL_VALID && isOpen) ) {
|
|
788
|
+
rootRef.current.classList.remove('focus');
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
// update value * label
|
|
793
|
+
if ( dataInput ) {
|
|
794
|
+
|
|
795
|
+
// using keyboard
|
|
796
|
+
const _data = JSON.parse(dataInput);
|
|
797
|
+
const _value = _data.value;
|
|
798
|
+
const _label = _data.label;
|
|
799
|
+
|
|
800
|
+
// ++++++++++++++++++++
|
|
801
|
+
// Single selection
|
|
802
|
+
// ++++++++++++++++++++
|
|
803
|
+
setControlValue(_value);
|
|
804
|
+
setControlLabel(formatIndentVal(_label));
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
// set value if the attribute `data-options` of component exists, only valid for single selection (it may be an empty array)
|
|
808
|
+
if ( typeof incomingOptionsData !== 'undefined' ) {
|
|
809
|
+
valueInputRef.current.dataset.value = _value;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
// ++++++++++++++++++++
|
|
814
|
+
// Multiple selection
|
|
815
|
+
// ++++++++++++++++++++
|
|
816
|
+
let currentControlValueArr: any[] = JSON.parse(JSON.stringify(valueArr));
|
|
817
|
+
let currentControlLabelArr: any[] = JSON.parse(JSON.stringify(labelArr));
|
|
818
|
+
|
|
819
|
+
if ( MULTI_SEL_VALID ) {
|
|
820
|
+
|
|
821
|
+
if ( multiSelControlOptionExist(valueArr, _value) ) {
|
|
822
|
+
|
|
823
|
+
setControlArr((prevState: any) => {
|
|
824
|
+
|
|
825
|
+
// update temporary value
|
|
826
|
+
setControlTempValue(prevState.labels.length >= 0 ? null : prevState.labels.join(','));
|
|
827
|
+
|
|
828
|
+
return {
|
|
829
|
+
labels: removeItemOnce(prevState.labels, formatIndentVal(_label)),
|
|
830
|
+
values: removeItemOnce(prevState.values, _value)
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
currentControlValueArr = removeItemOnce(currentControlValueArr, _value);
|
|
836
|
+
currentControlLabelArr = removeItemOnce(currentControlLabelArr, formatIndentVal(_label));
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
} else {
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
setControlArr((prevState: any) => {
|
|
844
|
+
|
|
845
|
+
// update temporary value
|
|
846
|
+
setControlTempValue(prevState.labels.length >= 0 ? null : prevState.labels.join(','));
|
|
847
|
+
|
|
848
|
+
return {
|
|
849
|
+
labels: [...prevState.labels, formatIndentVal(_label)],
|
|
850
|
+
values: [...prevState.values, _value]
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
currentControlValueArr.push(_value);
|
|
855
|
+
currentControlLabelArr.push(_label);
|
|
856
|
+
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
// Appropriate multi-item container height
|
|
860
|
+
adjustMultiControlContainerHeight();
|
|
861
|
+
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
//
|
|
865
|
+
if ( typeof(onChange) === 'function' ) {
|
|
866
|
+
onChange?.(selectInputRef.current, valueInputRef.current, !MULTI_SEL_VALID ? optionsData[index as never] : {labels: currentControlLabelArr.map((v: any) => v.toString()), values: currentControlValueArr.map((v: any) => v.toString())});
|
|
867
|
+
|
|
868
|
+
//
|
|
869
|
+
selectInputRef.current.blur();
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
} else {
|
|
873
|
+
|
|
874
|
+
index = typeof el.currentTarget !== 'undefined' ? el.currentTarget.dataset.index : el.dataset.index;
|
|
875
|
+
|
|
876
|
+
const _value = optionsData[index as never].value;
|
|
877
|
+
const _label = optionsData[index as never].label;
|
|
878
|
+
|
|
879
|
+
// ++++++++++++++++++++
|
|
880
|
+
// Single selection
|
|
881
|
+
// ++++++++++++++++++++
|
|
882
|
+
setControlValue(_value);
|
|
883
|
+
setControlLabel(formatIndentVal(_label));
|
|
884
|
+
|
|
885
|
+
// set value if the attribute `data-options` of component exists, only valid for single selection (it may be an empty array)
|
|
886
|
+
if ( typeof incomingOptionsData !== 'undefined' ) {
|
|
887
|
+
valueInputRef.current.dataset.value = _value;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
|
|
891
|
+
// ++++++++++++++++++++
|
|
892
|
+
// Multiple selection
|
|
893
|
+
// ++++++++++++++++++++
|
|
894
|
+
let currentControlValueArr: any[] = JSON.parse(JSON.stringify(controlArr.values));
|
|
895
|
+
let currentControlLabelArr: any[] = JSON.parse(JSON.stringify(controlArr.labels));
|
|
896
|
+
|
|
897
|
+
if ( MULTI_SEL_VALID ) {
|
|
898
|
+
|
|
899
|
+
if ( multiSelControlOptionExist(controlArr.values, _value) ) {
|
|
900
|
+
|
|
901
|
+
setControlArr((prevState: any) => {
|
|
902
|
+
|
|
903
|
+
// update temporary value
|
|
904
|
+
setControlTempValue(prevState.labels.length >= 0 ? null : prevState.labels.join(','));
|
|
905
|
+
|
|
906
|
+
return {
|
|
907
|
+
labels: removeItemOnce(prevState.labels, formatIndentVal(_label)),
|
|
908
|
+
values: removeItemOnce(prevState.values, _value)
|
|
909
|
+
}
|
|
910
|
+
});
|
|
911
|
+
|
|
912
|
+
currentControlValueArr = removeItemOnce(currentControlValueArr, _value);
|
|
913
|
+
currentControlLabelArr = removeItemOnce(currentControlLabelArr, formatIndentVal(_label));
|
|
914
|
+
|
|
915
|
+
} else {
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
setControlArr((prevState: any) => {
|
|
919
|
+
|
|
920
|
+
// update temporary value
|
|
921
|
+
setControlTempValue(prevState.labels.length >= 0 ? null : prevState.labels.join(','));
|
|
922
|
+
|
|
923
|
+
return {
|
|
924
|
+
labels: [...prevState.labels, formatIndentVal(_label)],
|
|
925
|
+
values: [...prevState.values, _value]
|
|
926
|
+
}
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
currentControlValueArr.push(_value);
|
|
931
|
+
currentControlLabelArr.push(_label);
|
|
932
|
+
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
// Appropriate multi-item container height
|
|
937
|
+
adjustMultiControlContainerHeight();
|
|
938
|
+
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
//
|
|
942
|
+
if ( typeof(onChange) === 'function' ) {
|
|
943
|
+
onChange?.(selectInputRef.current, valueInputRef.current, !MULTI_SEL_VALID ? optionsData[index as never] : {labels: currentControlLabelArr.map((v: any) => v.toString()), values: currentControlValueArr.map((v: any) => v.toString())});
|
|
944
|
+
|
|
945
|
+
//
|
|
946
|
+
selectInputRef.current.blur();
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
function handleSelectAll(event: any) {
|
|
956
|
+
event.preventDefault();
|
|
957
|
+
|
|
958
|
+
const onChangeSelectAll = (labelsArr: string[], valuesArr: string[]) => {
|
|
959
|
+
if ( typeof(onChange) === 'function' ) {
|
|
960
|
+
onChange?.(selectInputRef.current, valueInputRef.current, {labels: labelsArr.map((v: any) => v.toString()), values: valuesArr.map((v: any) => v.toString())});
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
//
|
|
964
|
+
selectInputRef.current.blur();
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
setItemSelectedAll((prevState) => {
|
|
969
|
+
|
|
970
|
+
if ( !prevState ) {
|
|
971
|
+
|
|
972
|
+
|
|
973
|
+
setControlArr((prevData: any) => {
|
|
974
|
+
|
|
975
|
+
const currentControlValueArr = [...prevData.values, ...optionsData.map((v: any) => v.value)].filter((item: any, index: number, arr: any[]) => arr.indexOf(item, 0) === index );
|
|
976
|
+
const currentControlLabelArr = [...formatIndentVal(prevData.labels), ...formatIndentVal(optionsData.map((v: any) => v.label))].filter((item: any, index: number, arr: any[]) => arr.indexOf(item, 0) === index );
|
|
977
|
+
|
|
978
|
+
//
|
|
979
|
+
onChangeSelectAll(currentControlLabelArr, currentControlValueArr);
|
|
980
|
+
|
|
981
|
+
return {
|
|
982
|
+
labels: currentControlLabelArr,
|
|
983
|
+
values: currentControlValueArr
|
|
984
|
+
}
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
} else {
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
setControlArr((prevData: any) => {
|
|
993
|
+
|
|
994
|
+
const currentControlValueArr = removeItems(prevData.values, optionsData.map((v: any) => v.value));
|
|
995
|
+
const currentControlLabelArr = removeItems(formatIndentVal(prevData.labels), formatIndentVal(optionsData.map((v: any) => v.label)));
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
//
|
|
999
|
+
onChangeSelectAll(currentControlLabelArr, currentControlValueArr);
|
|
1000
|
+
|
|
1001
|
+
return {
|
|
1002
|
+
labels: currentControlLabelArr,
|
|
1003
|
+
values: currentControlValueArr
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
return !prevState;
|
|
1010
|
+
} );
|
|
1011
|
+
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
function handleMultiControlItemRemove(event: any) {
|
|
1016
|
+
event.preventDefault();
|
|
1017
|
+
|
|
1018
|
+
const valueToRemove = String(event.currentTarget.dataset.item);
|
|
1019
|
+
const getCurrentIndex = controlArr.values.findIndex((item: any) => item.toString() === valueToRemove );
|
|
1020
|
+
|
|
1021
|
+
let currentControlValueArr: any[] = JSON.parse(JSON.stringify(controlArr.values));
|
|
1022
|
+
let currentControlLabelArr: any[] = JSON.parse(JSON.stringify(controlArr.labels));
|
|
1023
|
+
|
|
1024
|
+
const _value = valueToRemove;
|
|
1025
|
+
const _label = controlArr.labels[getCurrentIndex];
|
|
1026
|
+
|
|
1027
|
+
|
|
1028
|
+
setControlArr((prevState: any) => {
|
|
1029
|
+
|
|
1030
|
+
// update temporary value
|
|
1031
|
+
setControlTempValue(prevState.labels.length >= 0 ? null : prevState.labels.join(','));
|
|
1032
|
+
|
|
1033
|
+
return {
|
|
1034
|
+
labels: removeItemOnce(prevState.labels, formatIndentVal(_label)),
|
|
1035
|
+
values: removeItemOnce(prevState.values, _value)
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
currentControlValueArr = removeItemOnce(currentControlValueArr, _value);
|
|
1040
|
+
currentControlLabelArr = removeItemOnce(currentControlLabelArr, formatIndentVal(_label));
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
// Appropriate multi-item container height
|
|
1044
|
+
adjustMultiControlContainerHeight();
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
//
|
|
1048
|
+
if ( typeof(onChange) === 'function' ) {
|
|
1049
|
+
onChange?.(selectInputRef.current, valueInputRef.current, {labels: currentControlLabelArr.map((v: any) => v.toString()), values: currentControlValueArr.map((v: any) => v.toString())});
|
|
1050
|
+
|
|
1051
|
+
//
|
|
1052
|
+
selectInputRef.current.blur();
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
function handleShowList() {
|
|
1060
|
+
|
|
1061
|
+
//
|
|
1062
|
+
rootWrapperSwitch();
|
|
1063
|
+
|
|
1064
|
+
//
|
|
1065
|
+
if ( !isOpen ) {
|
|
1066
|
+
activate();
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
// window position
|
|
1070
|
+
setTimeout( ()=> {
|
|
1071
|
+
getPlacement(listRef.current);
|
|
1072
|
+
}, 0 );
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
|
|
1078
|
+
async function handleFetch(inputVal: any = null) {
|
|
1079
|
+
|
|
1080
|
+
// data init
|
|
1081
|
+
const searchStr: string = typeof inputVal === 'string' ? inputVal : (controlTempValue || controlTempValue === '' ? controlTempValue : '');
|
|
1082
|
+
const _oparams: any[] = fetchFuncMethodParams || [];
|
|
1083
|
+
const _params: any[] = _oparams.map((item: any) => item !== '$QUERY_STRING' ? item : searchStr);
|
|
1084
|
+
|
|
1085
|
+
// if empty
|
|
1086
|
+
if ( searchStr.replace(/\s/g, "") === '' ) return [];
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
const res = await fetchData((_params).join(','), value, false);
|
|
1091
|
+
return res;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
function handleComposition(event: any) {
|
|
1097
|
+
if (event.type === 'compositionstart' || event.type === 'compositionend') {
|
|
1098
|
+
//fire change method to update for Chrome v53
|
|
1099
|
+
handleChange(event);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
function handleChange(event: any) {
|
|
1104
|
+
const val = event.target.value;
|
|
1105
|
+
|
|
1106
|
+
// update temporary value
|
|
1107
|
+
setControlTempValue(val);
|
|
1108
|
+
|
|
1109
|
+
//
|
|
1110
|
+
if ( val.replace(/\s/g, "") === '' ) {
|
|
1111
|
+
// No elements found. Consider changing the search query.
|
|
1112
|
+
// restore data
|
|
1113
|
+
setOptionsData(orginalData);
|
|
1114
|
+
} else {
|
|
1115
|
+
handleChangeFetchSafe(val);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// window position
|
|
1119
|
+
setTimeout( ()=> {
|
|
1120
|
+
getPlacement(listRef.current);
|
|
1121
|
+
}, 0 );
|
|
1122
|
+
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
//
|
|
1126
|
+
function handleFocus(event: any) {
|
|
1127
|
+
|
|
1128
|
+
rootRef.current.classList.add('focus');
|
|
1129
|
+
|
|
1130
|
+
// update temporary value
|
|
1131
|
+
setControlTempValue('');
|
|
1132
|
+
|
|
1133
|
+
//
|
|
1134
|
+
onFocus?.(event);
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
function handleBlur(event: any) {
|
|
1138
|
+
|
|
1139
|
+
//remove focus style
|
|
1140
|
+
if ( !(MULTI_SEL_VALID && isOpen) ) {
|
|
1141
|
+
rootRef.current.classList.remove('focus');
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
setTimeout(() => {
|
|
1145
|
+
|
|
1146
|
+
// cancel
|
|
1147
|
+
if ( !(MULTI_SEL_VALID && isOpen) ) {
|
|
1148
|
+
cancel();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
onBlur?.(event);
|
|
1152
|
+
}, 300);
|
|
1153
|
+
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
function handleClose(event: any) {
|
|
1159
|
+
if (event.target.closest(`.${wrapperClassName || wrapperClassName === '' ? wrapperClassName : 'multifunc-select__wrapper'}`) === null) {
|
|
1160
|
+
// cancel
|
|
1161
|
+
cancel();
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
function generateInputFocusStr() {
|
|
1167
|
+
return controlTempValue || controlTempValue === '' ? (controlTempValue.length === 0 ? '|' : controlTempValue) : (placeholder || '');
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
|
|
1171
|
+
function optionFocus(type: string) {
|
|
1172
|
+
|
|
1173
|
+
return new Promise(function (resolve) {
|
|
1174
|
+
|
|
1175
|
+
// Determine the "active" class name to avoid listening to other unused components of the same type
|
|
1176
|
+
if ( listRef.current === null || !rootRef.current.classList.contains('active') ) return;
|
|
1177
|
+
|
|
1178
|
+
if ( fetchTrigger ) return;
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
const options = [].slice.call(listRef.current.querySelectorAll('.list-group-item'));
|
|
1182
|
+
const currentIndex = options.findIndex((e) => e === listRef.current.querySelector('.list-group-item.active'));
|
|
1183
|
+
|
|
1184
|
+
|
|
1185
|
+
// get the next element in the list, "%" will loop around to 0
|
|
1186
|
+
let nextIndex;
|
|
1187
|
+
if ( type === 'increase' ) {
|
|
1188
|
+
nextIndex = currentIndex + 1 % options.length;
|
|
1189
|
+
} else {
|
|
1190
|
+
nextIndex = (currentIndex < 0 ? options.length : currentIndex) - 1 % options.length;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
|
|
1194
|
+
//only one
|
|
1195
|
+
if ( options.length === 1 ) nextIndex = 0;
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
if ( !isNaN(nextIndex) ) {
|
|
1199
|
+
options.forEach( (node: any, index: number) => {
|
|
1200
|
+
node?.classList.remove('active');
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
const targetOption = options[nextIndex] as HTMLElement;
|
|
1204
|
+
if ( typeof targetOption !== 'undefined' && !targetOption.classList.contains('no-match') ) {
|
|
1205
|
+
targetOption.classList.add('active');
|
|
1206
|
+
resolve(targetOption);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
}
|
|
1210
|
+
});
|
|
1211
|
+
|
|
1212
|
+
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
|
|
1217
|
+
|
|
1218
|
+
useEffect(() => {
|
|
1219
|
+
|
|
1220
|
+
|
|
1221
|
+
// Call a function when the component has been rendered completely
|
|
1222
|
+
//--------------
|
|
1223
|
+
onLoad?.(selectInputRef.current, valueInputRef.current, value);
|
|
1224
|
+
|
|
1225
|
+
|
|
1226
|
+
// update incoming data
|
|
1227
|
+
//--------------
|
|
1228
|
+
setIncomingData(data);
|
|
1229
|
+
|
|
1230
|
+
// data init
|
|
1231
|
+
//--------------
|
|
1232
|
+
const _oparams: any[] = fetchFuncMethodParams || [];
|
|
1233
|
+
const _params: any[] = _oparams.map((item: any) => item !== '$QUERY_STRING' ? item : (fetchTrigger ? '-' : ''));
|
|
1234
|
+
fetchData((_params).join(','), value);
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
// If you use the dynamic form assignment (such as document.getElementById(xxx).value),
|
|
1238
|
+
// you need to judge the value of the input obtained by using the macrotask "setInterval()"
|
|
1239
|
+
let timer: any = null;
|
|
1240
|
+
let initTimes: number = 0;
|
|
1241
|
+
let hasValue: boolean = false;
|
|
1242
|
+
timer = setInterval( () => {
|
|
1243
|
+
if ( initTimes > 5 || hasValue ) {
|
|
1244
|
+
clearInterval(timer);
|
|
1245
|
+
} else {
|
|
1246
|
+
|
|
1247
|
+
// get value if the attribute `data-value` of component exists
|
|
1248
|
+
// Using `<DynamicFields />` will assign values according to `data-value`
|
|
1249
|
+
const incomingOptionsData = valueInputRef.current.dataset.options;
|
|
1250
|
+
if ( valueInputRef.current !== null && typeof incomingOptionsData !== 'undefined' && typeof valueInputRef.current.dataset.value !== 'undefined' && valueInputRef.current.dataset.value !== '') {
|
|
1251
|
+
fetchData((_params).join(','), valueInputRef.current.dataset.value);
|
|
1252
|
+
hasValue = true;
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
//
|
|
1256
|
+
if ( valueInputRef.current !== null && valueInputRef.current.value !== '' && ( typeof value === 'undefined' || value === '' ) ) {
|
|
1257
|
+
fetchData((_params).join(','), valueInputRef.current.value);
|
|
1258
|
+
hasValue = true;
|
|
1259
|
+
}
|
|
1260
|
+
initTimes++;
|
|
1261
|
+
|
|
1262
|
+
}
|
|
1263
|
+
}, 500);
|
|
1264
|
+
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
// keyboard listener
|
|
1268
|
+
//--------------
|
|
1269
|
+
const listener = async (event: any) => {
|
|
1270
|
+
|
|
1271
|
+
let res: any = null;
|
|
1272
|
+
|
|
1273
|
+
if (event.code === "Enter" || event.code === "NumpadEnter") {
|
|
1274
|
+
|
|
1275
|
+
// Determine the "active" class name to avoid listening to other unused components of the same type
|
|
1276
|
+
if ( listRef.current === null || !rootRef.current.classList.contains('active') ) return;
|
|
1277
|
+
|
|
1278
|
+
if ( fetchTrigger ) {
|
|
1279
|
+
handleFetch();
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
if ( listRef.current !== null ) {
|
|
1284
|
+
const currentData = await listRef.current.dataset.data;
|
|
1285
|
+
if ( typeof currentData !== 'undefined' ) {
|
|
1286
|
+
|
|
1287
|
+
const currentControlValueArr: any[] = [];
|
|
1288
|
+
const currentControlLabelArr: any[] = [];
|
|
1289
|
+
|
|
1290
|
+
const options = [].slice.call(listRef.current.querySelectorAll('.list-group-item:not(.no-match)'));
|
|
1291
|
+
options.forEach((node: any) => {
|
|
1292
|
+
node.classList.remove('active');
|
|
1293
|
+
|
|
1294
|
+
if ( node.classList.contains('item-selected') ) {
|
|
1295
|
+
currentControlValueArr.push(node.dataset.value);
|
|
1296
|
+
currentControlLabelArr.push(node.dataset.label)
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
});
|
|
1300
|
+
|
|
1301
|
+
handleSelect(null, currentData, currentControlValueArr, currentControlLabelArr);
|
|
1302
|
+
|
|
1303
|
+
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
|
|
1311
|
+
switch (event.code) {
|
|
1312
|
+
case "ArrowLeft":
|
|
1313
|
+
// Left pressed
|
|
1314
|
+
break;
|
|
1315
|
+
case "ArrowRight":
|
|
1316
|
+
// Right pressed
|
|
1317
|
+
break;
|
|
1318
|
+
case "ArrowUp":
|
|
1319
|
+
// Up pressed
|
|
1320
|
+
res = await optionFocus('decrease');
|
|
1321
|
+
break;
|
|
1322
|
+
case "ArrowDown":
|
|
1323
|
+
// Down pressed
|
|
1324
|
+
res = await optionFocus('increase');
|
|
1325
|
+
break;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// temporary data
|
|
1329
|
+
if ( res !== null ) listRef.current.dataset.data = JSON.stringify({
|
|
1330
|
+
value: res.dataset.value,
|
|
1331
|
+
label: res.dataset.label,
|
|
1332
|
+
queryString: res.dataset.querystring
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
|
|
1337
|
+
};
|
|
1338
|
+
|
|
1339
|
+
document.removeEventListener("keydown", listener);
|
|
1340
|
+
document.addEventListener("keydown", listener);
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
|
|
1344
|
+
//--------------
|
|
1345
|
+
document.removeEventListener('pointerdown', handleClose);
|
|
1346
|
+
document.addEventListener('pointerdown', handleClose);
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
|
|
1350
|
+
|
|
1351
|
+
// Add function to the element that should be used as the scrollable area.
|
|
1352
|
+
//--------------
|
|
1353
|
+
window.removeEventListener('scroll', windowScrollUpdate);
|
|
1354
|
+
window.removeEventListener('touchmove', windowScrollUpdate);
|
|
1355
|
+
window.addEventListener('scroll', windowScrollUpdate);
|
|
1356
|
+
window.addEventListener('touchmove', windowScrollUpdate);
|
|
1357
|
+
// windowScrollUpdate();
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
return () => {
|
|
1361
|
+
document.removeEventListener("keydown", listener);
|
|
1362
|
+
document.removeEventListener('pointerdown', handleClose);
|
|
1363
|
+
window.removeEventListener('scroll', windowScrollUpdate);
|
|
1364
|
+
window.removeEventListener('touchmove', windowScrollUpdate);
|
|
1365
|
+
|
|
1366
|
+
//
|
|
1367
|
+
clearInterval(timer);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
}, [value, options, data]);
|
|
1371
|
+
|
|
1372
|
+
|
|
1373
|
+
return (
|
|
1374
|
+
<>
|
|
1375
|
+
|
|
1376
|
+
{label ? <><div className="multifunc-select__label"><label htmlFor={`label-${idRes}`} className="form-label">{label}</label></div></> : null}
|
|
1377
|
+
|
|
1378
|
+
<div id={`multifunc-select__wrapper-${idRes}`} className={`multifunc-select__wrapper ${wrapperClassName || wrapperClassName === '' ? wrapperClassName : 'mb-3 position-relative'} ${MULTI_SEL_VALID ? 'multiple-selection' : ''} ${isOpen ? 'active focus' : ''}`} ref={rootRef}>
|
|
1379
|
+
|
|
1380
|
+
{/*
|
|
1381
|
+
// ++++++++++++++++++++
|
|
1382
|
+
// Single selection Control (includes result container)
|
|
1383
|
+
// ++++++++++++++++++++
|
|
1384
|
+
*/}
|
|
1385
|
+
<div ref={rootSingleRef} className="position-relative">
|
|
1386
|
+
<input
|
|
1387
|
+
ref={(node) => {
|
|
1388
|
+
selectInputRef.current = node;
|
|
1389
|
+
if (typeof ref === 'function') {
|
|
1390
|
+
ref(node);
|
|
1391
|
+
} else if (ref) {
|
|
1392
|
+
ref.current = node;
|
|
1393
|
+
}
|
|
1394
|
+
}}
|
|
1395
|
+
tabIndex={tabIndex || 0}
|
|
1396
|
+
type="text"
|
|
1397
|
+
id={`label-${idRes}`}
|
|
1398
|
+
|
|
1399
|
+
// Don't use "name", it's just a container to display the label
|
|
1400
|
+
data-name={name?.match(/(\[.*?\])/gi) ? `${name.split('[')[0]}-label[]` : `${name}-label`}
|
|
1401
|
+
data-select
|
|
1402
|
+
placeholder={placeholder || ''}
|
|
1403
|
+
className={controlClassName || controlClassName === '' ? controlClassName : "form-control"}
|
|
1404
|
+
onFocus={handleFocus}
|
|
1405
|
+
onBlur={handleBlur}
|
|
1406
|
+
onClick={handleShowList}
|
|
1407
|
+
onChange={handleChange}
|
|
1408
|
+
onCompositionStart={handleComposition}
|
|
1409
|
+
onCompositionUpdate={handleComposition}
|
|
1410
|
+
onCompositionEnd={handleComposition}
|
|
1411
|
+
disabled={disabled || null}
|
|
1412
|
+
required={required || null}
|
|
1413
|
+
readOnly={readOnly || null}
|
|
1414
|
+
value={controlTempValue || controlTempValue === '' ? controlTempValue : (MULTI_SEL_VALID ? formatIndentVal(controlArr.labels).map((v: any) => stripHTML(v)).join(',') : stripHTML(controlLabel as never))} // do not use `defaultValue`
|
|
1415
|
+
|
|
1416
|
+
style={{cursor: 'pointer', borderBottomWidth: MULTI_SEL_VALID? '0' : '1px', ...style}}
|
|
1417
|
+
autoComplete='off'
|
|
1418
|
+
{...attributes}
|
|
1419
|
+
/>
|
|
1420
|
+
|
|
1421
|
+
<input
|
|
1422
|
+
ref={valueInputRef}
|
|
1423
|
+
type="hidden"
|
|
1424
|
+
id={idRes}
|
|
1425
|
+
name={name}
|
|
1426
|
+
value={MULTI_SEL_VALID ? controlArr.values.join(',') : controlValue} // do not use `defaultValue`
|
|
1427
|
+
{...attributes}
|
|
1428
|
+
/>
|
|
1429
|
+
|
|
1430
|
+
|
|
1431
|
+
<span className="arrow position-absolute top-0 end-0 me-2 mt-1" style={{translate: 'all .2s', transform: isOpen ? 'rotate(180deg) translateY(-4px)' : 'rotate(0) translateY(0)', pointerEvents: 'none', display: fetchTrigger ? 'none' : 'inline-block'}}>
|
|
1432
|
+
{controlArrow ? controlArrow : <svg width="10px" height="10px" viewBox="0 -4.5 20 20">
|
|
1433
|
+
<g stroke="none" strokeWidth="1" fill="none">
|
|
1434
|
+
<g transform="translate(-180.000000, -6684.000000)" className="arrow-fill-g" fill="#a5a5a5">
|
|
1435
|
+
<g transform="translate(56.000000, 160.000000)">
|
|
1436
|
+
<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">
|
|
1437
|
+
</path>
|
|
1438
|
+
</g>
|
|
1439
|
+
</g>
|
|
1440
|
+
</g>
|
|
1441
|
+
</svg>}
|
|
1442
|
+
</span>
|
|
1443
|
+
|
|
1444
|
+
|
|
1445
|
+
{fetchTrigger ? <>
|
|
1446
|
+
<span className="multifunc-select-multi__control-searchbtn position-absolute top-0 end-0">
|
|
1447
|
+
<button type="button" className={'btn border-end-0 rounded-pill'} onClick={handleFetch}>
|
|
1448
|
+
<svg width="1em" height="1em" fill="#a5a5a5" viewBox="0 0 16 16">
|
|
1449
|
+
<path d="M12.027 9.92L16 13.95 14 16l-4.075-3.976A6.465 6.465 0 0 1 6.5 13C2.91 13 0 10.083 0 6.5 0 2.91 2.917 0 6.5 0 10.09 0 13 2.917 13 6.5a6.463 6.463 0 0 1-.973 3.42zM1.997 6.452c0 2.48 2.014 4.5 4.5 4.5 2.48 0 4.5-2.015 4.5-4.5 0-2.48-2.015-4.5-4.5-4.5-2.48 0-4.5 2.014-4.5 4.5z" fillRule="evenodd" />
|
|
1450
|
+
</svg>
|
|
1451
|
+
</button>
|
|
1452
|
+
|
|
1453
|
+
</span>
|
|
1454
|
+
</> : null}
|
|
1455
|
+
|
|
1456
|
+
|
|
1457
|
+
|
|
1458
|
+
</div>
|
|
1459
|
+
|
|
1460
|
+
|
|
1461
|
+
{/*
|
|
1462
|
+
// ++++++++++++++++++++
|
|
1463
|
+
// Multiple selection Control
|
|
1464
|
+
// ++++++++++++++++++++
|
|
1465
|
+
*/}
|
|
1466
|
+
{MULTI_SEL_VALID ? <div ref={rootMultiRef} className="multifunc-select-multi__wrapper">
|
|
1467
|
+
|
|
1468
|
+
<div className="multifunc-select-multi__control-wrapper">
|
|
1469
|
+
<div>
|
|
1470
|
+
<ul className="multifunc-select-multi__list">
|
|
1471
|
+
|
|
1472
|
+
{controlArr.labels.map((item: any, index: number) => (
|
|
1473
|
+
<li key={index}>
|
|
1474
|
+
{stripHTML(item)}
|
|
1475
|
+
|
|
1476
|
+
<a href="#" tabIndex={-1} onClick={handleMultiControlItemRemove} data-item={controlArr.values[index]}><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>
|
|
1477
|
+
</li>
|
|
1478
|
+
))}
|
|
1479
|
+
|
|
1480
|
+
<li className={`multifunc-select-multi__list-item-placeholder ${typeof placeholder === 'undefined' || placeholder === '' ? 'hide' : ''}`}>
|
|
1481
|
+
<span className={`multifunc-select-multi__control-blinking-cursor ${generateInputFocusStr() === placeholder && placeholder !== '' && typeof placeholder !== 'undefined' ? 'control-placeholder' : ''} ${generateInputFocusStr() === '|' ? 'animated' : ''}`}>
|
|
1482
|
+
{generateInputFocusStr()}
|
|
1483
|
+
</span>
|
|
1484
|
+
</li>
|
|
1485
|
+
</ul>
|
|
1486
|
+
|
|
1487
|
+
</div>
|
|
1488
|
+
|
|
1489
|
+
</div>
|
|
1490
|
+
|
|
1491
|
+
<span className="arrow position-absolute top-0 end-0 me-2 mt-1" style={{ translate: 'all .2s', transform: isOpen ? 'rotate(180deg) translateY(-4px)' : 'rotate(0) translateY(0)', pointerEvents: 'none', display: fetchTrigger ? 'none' : 'inline-block' }}>
|
|
1492
|
+
{controlArrow ? controlArrow : <svg width="10px" height="10px" viewBox="0 -4.5 20 20">
|
|
1493
|
+
<g stroke="none" strokeWidth="1" fill="none">
|
|
1494
|
+
<g transform="translate(-180.000000, -6684.000000)" className="arrow-fill-g" fill="#a5a5a5">
|
|
1495
|
+
<g transform="translate(56.000000, 160.000000)">
|
|
1496
|
+
<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">
|
|
1497
|
+
</path>
|
|
1498
|
+
</g>
|
|
1499
|
+
</g>
|
|
1500
|
+
</g>
|
|
1501
|
+
</svg>}
|
|
1502
|
+
</span>
|
|
1503
|
+
|
|
1504
|
+
|
|
1505
|
+
{fetchTrigger ? <>
|
|
1506
|
+
<span className="multifunc-select-multi__control-searchbtn position-absolute top-0 end-0">
|
|
1507
|
+
<button type="button" className={'btn border-end-0 rounded-pill'} onClick={handleFetch}>
|
|
1508
|
+
<svg width="1em" height="1em" fill="#a5a5a5" viewBox="0 0 16 16">
|
|
1509
|
+
<path d="M12.027 9.92L16 13.95 14 16l-4.075-3.976A6.465 6.465 0 0 1 6.5 13C2.91 13 0 10.083 0 6.5 0 2.91 2.917 0 6.5 0 10.09 0 13 2.917 13 6.5a6.463 6.463 0 0 1-.973 3.42zM1.997 6.452c0 2.48 2.014 4.5 4.5 4.5 2.48 0 4.5-2.015 4.5-4.5 0-2.48-2.015-4.5-4.5-4.5-2.48 0-4.5 2.014-4.5 4.5z" fillRule="evenodd" />
|
|
1510
|
+
</svg>
|
|
1511
|
+
</button>
|
|
1512
|
+
|
|
1513
|
+
</span>
|
|
1514
|
+
</> : null}
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
</div> : null}
|
|
1518
|
+
|
|
1519
|
+
|
|
1520
|
+
|
|
1521
|
+
|
|
1522
|
+
{optionsData && !hasErr ? <>
|
|
1523
|
+
<div ref={listRef} className={`list-group position-absolute border shadow small ${winWidth ? '' : 'w-100'}`} style={{ marginTop: '0.2rem', zIndex: (depth ? depth : 100), width: WIN_WIDTH}} role="tablist">
|
|
1524
|
+
|
|
1525
|
+
{controlTempValue !== null && optionsData.length === 0 ? <>
|
|
1526
|
+
<button tabIndex={-1} type="button" className="list-group-item list-group-item-action no-match" disabled>{fetchNoneInfo || 'No match yet'}</button>
|
|
1527
|
+
</> : <>
|
|
1528
|
+
<div className="rounded" style={{backgroundColor: 'var(--bs-list-group-bg)'}} ref={listContentRef}>
|
|
1529
|
+
|
|
1530
|
+
{MULTI_SEL_VALID ? <>
|
|
1531
|
+
<button tabIndex={-1} type="button" className="list-group-item list-group-item-action border-start-0 border-end-0 text-secondary bg-light multifunc-select-multi__control-select-all" role="tab" style={{display: multiSelect?.selectAll ? 'block' : 'none'}}>
|
|
1532
|
+
<a tabIndex={-1} href="#" onClick={handleSelectAll} className="btn btn-secondary" dangerouslySetInnerHTML={{
|
|
1533
|
+
__html: `${multiSelect?.selectAllLabel || 'Select all options'}`
|
|
1534
|
+
}}></a>
|
|
1535
|
+
</button>
|
|
1536
|
+
</> : null}
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
{optionsData ? optionsData.map((item, index) => {
|
|
1540
|
+
const startItemBorder = index === 0 ? 'border-top-0' : '';
|
|
1541
|
+
const endItemBorder = index === optionsData.length - 1 ? 'border-bottom-0' : '';
|
|
1542
|
+
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
if (!MULTI_SEL_VALID) {
|
|
1546
|
+
|
|
1547
|
+
// ++++++++++++++++++++
|
|
1548
|
+
// Single selection
|
|
1549
|
+
// ++++++++++++++++++++
|
|
1550
|
+
return <button tabIndex={-1} onClick={handleSelect} type="button" data-index={index} key={index} className={`list-group-item list-group-item-action border-start-0 border-end-0 ${startItemBorder} ${endItemBorder} border-bottom-0`} data-value={`${item.value}`} data-label={`${item.label}`} data-querystring={`${item.queryString}`} role="tab" dangerouslySetInnerHTML={{
|
|
1551
|
+
__html: item.label
|
|
1552
|
+
}}></button>
|
|
1553
|
+
|
|
1554
|
+
} else {
|
|
1555
|
+
|
|
1556
|
+
// ++++++++++++++++++++
|
|
1557
|
+
// Multiple selection
|
|
1558
|
+
// ++++++++++++++++++++
|
|
1559
|
+
const itemSelected = multiSelControlOptionExist(controlArr.values, item.value) ? true : false;
|
|
1560
|
+
|
|
1561
|
+
return <button tabIndex={-1} onClick={handleSelect} type="button" data-index={index} key={index} className={`list-group-item list-group-item-action border-start-0 border-end-0 ${startItemBorder} ${endItemBorder} border-bottom-0 ${itemSelected ? 'list-group-item-secondary item-selected' : ''}`} data-value={`${item.value}`} data-label={`${item.label}`} data-querystring={`${item.queryString}`} role="tab">
|
|
1562
|
+
<var className="d-inline-block me-1 ">
|
|
1563
|
+
{!itemSelected ? <svg width="1.2em" height="1.2em" viewBox="0 0 24 24" fill="none">
|
|
1564
|
+
<path id="Vector" d="M4 7.2002V16.8002C4 17.9203 4 18.4801 4.21799 18.9079C4.40973 19.2842 4.71547 19.5905 5.0918 19.7822C5.5192 20 6.07899 20 7.19691 20H16.8031C17.921 20 18.48 20 18.9074 19.7822C19.2837 19.5905 19.5905 19.2842 19.7822 18.9079C20 18.4805 20 17.9215 20 16.8036V7.19691C20 6.07899 20 5.5192 19.7822 5.0918C19.5905 4.71547 19.2837 4.40973 18.9074 4.21799C18.4796 4 17.9203 4 16.8002 4H7.2002C6.08009 4 5.51962 4 5.0918 4.21799C4.71547 4.40973 4.40973 4.71547 4.21799 5.0918C4 5.51962 4 6.08009 4 7.2002Z" stroke="#000000" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
|
|
1565
|
+
</svg> : <svg width="1.2em" height="1.2em" fill="#000000" viewBox="0 0 24 24"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" /></svg>}
|
|
1566
|
+
|
|
1567
|
+
</var>
|
|
1568
|
+
<span dangerouslySetInnerHTML={{
|
|
1569
|
+
__html: item.label
|
|
1570
|
+
}}></span>
|
|
1571
|
+
</button>
|
|
1572
|
+
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
|
|
1576
|
+
}) : null}
|
|
1577
|
+
|
|
1578
|
+
</div>
|
|
1579
|
+
|
|
1580
|
+
</>}
|
|
1581
|
+
|
|
1582
|
+
|
|
1583
|
+
</div>
|
|
1584
|
+
|
|
1585
|
+
</> : null}
|
|
1586
|
+
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
</div>
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
</>
|
|
1594
|
+
)
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
export default MultiFuncSelect;
|