funda-ui 4.5.680 → 4.5.682

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 (35) hide show
  1. package/DragDropList/index.css +188 -0
  2. package/DragDropList/index.d.ts +43 -0
  3. package/DragDropList/index.js +1589 -0
  4. package/MultipleSelect/index.css +237 -144
  5. package/MultipleSelect/index.d.ts +23 -10
  6. package/MultipleSelect/index.js +2242 -1225
  7. package/README.md +3 -1
  8. package/Utils/useBoundedDrag.d.ts +127 -0
  9. package/Utils/useBoundedDrag.js +382 -0
  10. package/Utils/useDragDropPosition.d.ts +169 -0
  11. package/Utils/useDragDropPosition.js +456 -0
  12. package/all.d.ts +1 -0
  13. package/all.js +1 -0
  14. package/lib/cjs/DragDropList/index.d.ts +43 -0
  15. package/lib/cjs/DragDropList/index.js +1589 -0
  16. package/lib/cjs/MultipleSelect/index.d.ts +23 -10
  17. package/lib/cjs/MultipleSelect/index.js +2242 -1225
  18. package/lib/cjs/Utils/useBoundedDrag.d.ts +127 -0
  19. package/lib/cjs/Utils/useBoundedDrag.js +382 -0
  20. package/lib/cjs/Utils/useDragDropPosition.d.ts +169 -0
  21. package/lib/cjs/Utils/useDragDropPosition.js +456 -0
  22. package/lib/cjs/index.d.ts +1 -0
  23. package/lib/cjs/index.js +1 -0
  24. package/lib/css/DragDropList/index.css +188 -0
  25. package/lib/css/MultipleSelect/index.css +237 -144
  26. package/lib/esm/DragDropList/index.scss +245 -0
  27. package/lib/esm/DragDropList/index.tsx +493 -0
  28. package/lib/esm/MultipleSelect/index.scss +288 -183
  29. package/lib/esm/MultipleSelect/index.tsx +304 -166
  30. package/lib/esm/MultipleSelect/utils/func.ts +21 -1
  31. package/lib/esm/Utils/hooks/useBoundedDrag.tsx +303 -0
  32. package/lib/esm/Utils/hooks/useDragDropPosition.tsx +420 -0
  33. package/lib/esm/index.js +1 -0
  34. package/package.json +1 -1
  35. package/lib/esm/MultipleSelect/ItemList.tsx +0 -323
@@ -1,14 +1,12 @@
1
1
  import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
2
2
 
3
+ import DragDropList from 'funda-dragdrop-list';
4
+
3
5
 
4
6
  import useComId from 'funda-utils/dist/cjs/useComId';
5
7
  import {
6
8
  isJSON
7
9
  } from 'funda-utils/dist/cjs/initDefaultOptions';
8
- import {
9
- addTreeDepth,
10
- addTreeIndent,
11
- } from 'funda-utils/dist/cjs/tree';
12
10
  import {
13
11
  extractContentsOfBrackets
14
12
  } from 'funda-utils/dist/cjs/extract';
@@ -22,12 +20,20 @@ import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
22
20
 
23
21
 
24
22
 
25
- import { multiSelControlOptionExist, uniqueArr } from './utils/func';
26
- import ItemList from './ItemList';
23
+ import { multiSelControlOptionExist, uniqueArr, uniqueOpt } from './utils/func';
27
24
 
28
25
 
29
26
  export interface OptionConfig {
30
- [propName: string]: string | number | boolean | Function;
27
+ id: number;
28
+ parentId?: number;
29
+ label: string;
30
+ listItemLabel: string;
31
+ value: string;
32
+ queryString: string;
33
+ depth?: number;
34
+ children?: OptionConfig[];
35
+ disabled?: boolean;
36
+ extendedContent?: React.ReactNode;
31
37
  }
32
38
 
33
39
 
@@ -46,11 +52,6 @@ export type MultipleSelectProps = {
46
52
  iconAdd?: React.ReactNode | string;
47
53
  iconRemove?: React.ReactNode | string;
48
54
  unattachedSelect?: boolean;
49
- hierarchical?: boolean;
50
- indentation?: string;
51
- doubleIndent?: boolean;
52
- alternateCollapse?: boolean;
53
- arrow?: React.ReactNode;
54
55
  defaultValue?: string;
55
56
  value?: string;
56
57
  label?: React.ReactNode | string;
@@ -58,7 +59,16 @@ export type MultipleSelectProps = {
58
59
  options?: OptionConfig[] | string;
59
60
  disabled?: any;
60
61
  required?: any;
61
- appendControl?: React.ReactNode;
62
+ /** DragDrop List */
63
+ draggable?: boolean;
64
+ handleHide?: boolean;
65
+ handleIcon?: string;
66
+ handlePos?: 'left' | 'right';
67
+ dragMode?: 'handle' | 'block';
68
+ indentation?: string;
69
+ doubleIndent?: boolean;
70
+ alternateCollapse?: boolean;
71
+ arrow?: React.ReactNode;
62
72
  /** Whether to use square brackets to save result and initialize default value */
63
73
  extractValueByBrackets?: boolean;
64
74
  /** Incoming data, you can set the third parameter of `onFetch` */
@@ -72,9 +82,9 @@ export type MultipleSelectProps = {
72
82
  fetchFuncMethodParams?: any[];
73
83
  fetchCallback?: (data: any) => void;
74
84
  onFetch?: (data: any) => void;
75
- onAddAll?: (e: any, data: any, dataStr: any) => void;
76
- onRemoveAll?: (e: any, data: any, dataStr: any) => void;
77
- onChange?: (e: any, data: any, dataStr: any, currentData: any, type: string) => void;
85
+ onAddAll?: (e: HTMLElement | null, data: any[], dataStr: string, res: any[]) => void;
86
+ onRemoveAll?: (e: HTMLElement | null, data: any[], dataStr: string, res: any[]) => void;
87
+ onChange?: (e: HTMLElement | null, data: any[], dataStr: string, currentData: any, type: string, res: any[]) => void;
78
88
 
79
89
  };
80
90
 
@@ -95,20 +105,23 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
95
105
  iconAdd,
96
106
  iconRemove,
97
107
  unattachedSelect,
98
- hierarchical,
99
- indentation,
100
- doubleIndent,
101
- alternateCollapse,
102
- arrow,
103
108
  options,
104
109
  disabled,
105
110
  required,
106
- appendControl,
107
111
  defaultValue,
108
112
  value,
109
113
  label,
110
114
  name,
111
115
  id,
116
+ draggable = true,
117
+ handleHide = false,
118
+ handleIcon = '☰',
119
+ handlePos = 'left',
120
+ dragMode = 'handle',
121
+ indentation,
122
+ doubleIndent,
123
+ alternateCollapse,
124
+ arrow = <><svg viewBox="0 0 22 22" width="8px"><path d="m345.44 248.29l-194.29 194.28c-12.359 12.365-32.397 12.365-44.75 0-12.354-12.354-12.354-32.391 0-44.744l171.91-171.91-171.91-171.9c-12.354-12.359-12.354-32.394 0-44.748 12.354-12.359 32.391-12.359 44.75 0l194.29 194.28c6.177 6.18 9.262 14.271 9.262 22.366 0 8.099-3.091 16.196-9.267 22.373" transform="matrix(.03541-.00013.00013.03541 2.98 3.02)" fill="#a5a5a5" /></svg></>,
112
125
  extractValueByBrackets,
113
126
  style,
114
127
  data,
@@ -124,58 +137,137 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
124
137
  } = props;
125
138
 
126
139
 
127
- const UN_ATTACHED_SELECT = typeof unattachedSelect === 'undefined' || unattachedSelect === false ? false : true;
140
+ const UNATTACHED_SELECT = typeof unattachedSelect === 'undefined' || unattachedSelect === false ? false : true;
128
141
  const WRAPPER_MIN_H = typeof wrapperMinHeight === 'undefined' ? '' : wrapperMinHeight;
129
142
  const WRAPPER_MIN_W = typeof wrapperMinWidth === 'undefined' ? '' : wrapperMinWidth;
130
- const INDENT_PLACEHOLDER = doubleIndent ? `&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;` : `&nbsp;&nbsp;&nbsp;&nbsp;`;
131
- const INDENT_LAST_PLACEHOLDER = `${typeof indentation !== 'undefined' && indentation !== '' ? `${indentation}&nbsp;&nbsp;` : ''}`;
132
143
  const VALUE_BY_BRACKETS = typeof extractValueByBrackets === 'undefined' ? true : extractValueByBrackets;
133
144
  const uniqueID = useComId();
134
145
  const idRes = id || uniqueID;
135
146
  const rootRef = useRef<any>(null);
136
147
  const inputRef = useRef<any>(null);
137
148
  const availableListRef = useRef<any>(null);
138
- const selectedListRef = useRef<any>(null);
139
149
  const optionsRes = options ? isJSON(options) ? JSON.parse(options as string) : options : [];
140
150
  const [valSelectedData, setValSelectedData] = useState<any[]>([]);
141
151
  const [valSelected, setValSelected] = useState<any[]>([]);
142
152
 
153
+ // temp default value
154
+ const [tempDefaultValue, setTempDefaultValue] = useState<string | undefined>(undefined);
143
155
 
144
156
  // return a array of options
145
157
  let optionsDataInit: OptionConfig[] = optionsRes;
146
158
 
147
-
148
159
  //
149
160
  const [changedSearchVal, setChangedSearchVal] = useState<string>('');
150
161
 
151
162
  //
152
163
  const [dataInit, setDataInit] = useState<OptionConfig[]>(optionsDataInit);
153
164
  const [hasErr, setHasErr] = useState<boolean>(false);
165
+
154
166
 
155
167
 
156
168
  // exposes the following methods
157
-
158
169
  useImperativeHandle(
159
170
  contentRef,
160
171
  () => ({
161
172
  clear: (cb?: any) => {
162
- initDefaultValue('', dataInit);
173
+
174
+ const _params: any[] = fetchFuncMethodParams || [];
175
+ fetchData((_params).join(','), '');
176
+
163
177
  cb?.();
164
178
  },
165
- /*
166
- set([{"label": "Option 1","listItemLabel":"Option 1 (No: 001)","value": "value-1","queryString": "option1"}], () => { console.log('callback') }])
167
- */
168
179
  set: (inputData: any[], cb?: any) => {
169
180
  if (! Array.isArray(inputData)) return;
170
-
171
- initDefaultValue(inputData.map((v: any) => `[${v.value}]`).join(''), dataInit);
181
+
182
+ const _params: any[] = fetchFuncMethodParams || [];
183
+ fetchData((_params).join(','), inputData.map((v: any) => `[${v.value}]`).join(''));
172
184
 
173
185
  cb?.();
174
186
  }
175
187
  }),
176
- [contentRef, dataInit],
188
+ [contentRef],
177
189
  );
178
190
 
191
+ const getExtControll = (index: number, id: number, value: number | string, extendedContent: React.ReactNode, defaultValue: any, forceItemSelected: boolean | undefined = undefined) => {
192
+
193
+
194
+ let itemSelected: boolean = false;
195
+ if (typeof defaultValue !== 'undefined' && defaultValue !== '') {
196
+ const _val = VALUE_BY_BRACKETS ? extractContentsOfBrackets(defaultValue) : defaultValue.trim().replace(/^\,|\,$/g, '').split(',');
197
+
198
+ if (Array.isArray(_val) && _val.includes(String(value))) {
199
+ itemSelected = true;
200
+ }
201
+ }
202
+
203
+ if (typeof forceItemSelected !== 'undefined') itemSelected = forceItemSelected;
204
+
205
+
206
+ return <>
207
+
208
+ <div style={{
209
+ paddingLeft: '1rem',
210
+ width: '100%',
211
+ display: 'flex',
212
+ alignItems: 'center',
213
+ justifyContent: 'end'
214
+ }}>
215
+
216
+ {extendedContent ? <>
217
+ <span className="m-select-v2__ext" id={`m-select-v2__ext-${id}${itemSelected ? '-selected' : ''}`}>
218
+ {extendedContent}
219
+ </span>
220
+ </> : null}
221
+
222
+
223
+ {itemSelected ? <>
224
+ <a href="#" onClick={(e: React.MouseEvent) => {
225
+ e.preventDefault();
226
+ e.stopPropagation();
227
+
228
+ // remove
229
+ removeItem(id);
230
+ }}>
231
+ {iconRemove ? <>{iconRemove}</> : <><svg width="15px" height="15px" viewBox="0 0 24 24" fill="none"><path fillRule="evenodd" clipRule="evenodd" d="M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10ZM8 11a1 1 0 1 0 0 2h8a1 1 0 1 0 0-2H8Z" fill="#000" /></svg></>}
232
+ </a>
233
+
234
+ </> : <>
235
+ <a href="#" onClick={(e: React.MouseEvent) => {
236
+ e.preventDefault();
237
+ e.stopPropagation();
238
+
239
+ // add
240
+ selectItem(id);
241
+ }}>
242
+ {iconAdd ? <>{iconAdd}</> : <><svg width="15px" height="15px" viewBox="0 0 24 24" fill="none"><path d="M12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2ZM16 12.75H12.75V16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16V12.75H8C7.59 12.75 7.25 12.41 7.25 12C7.25 11.59 7.59 11.25 8 11.25H11.25V8C11.25 7.59 11.59 7.25 12 7.25C12.41 7.25 12.75 7.59 12.75 8V11.25H16C16.41 11.25 16.75 11.59 16.75 12C16.75 12.41 16.41 12.75 16 12.75Z" fill="#000" /></svg></>}
243
+ </a>
244
+ </>}
245
+
246
+
247
+ </div>
248
+
249
+ </>
250
+ };
251
+
252
+ const dragdropListDataInit = (data: any[]) => {
253
+ // Add appendControl to list
254
+ data.forEach((item: any, index: number) => {
255
+ item.appendControl = getExtControll(index, item.id, item.value, item.extendedContent, tempDefaultValue);
256
+ });
257
+
258
+
259
+ return data;
260
+ };
261
+ const dragdropListDefaultDataInit = (data: any[]) => {
262
+ // Update appendControl to list
263
+ data.forEach((item: any, index: number) => {
264
+ item.appendControl = getExtControll(index, item.id, item.value, item.extendedContent, tempDefaultValue, false);
265
+ });
266
+
267
+
268
+ return data;
269
+ };
270
+
179
271
 
180
272
  async function fetchData(params: any, inputDefault: any) {
181
273
 
@@ -201,16 +293,12 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
201
293
  }
202
294
 
203
295
 
204
- // Set hierarchical categories ( with sub-categories )
205
- if (hierarchical) {
206
- _ORGIN_DATA = addTreeDepth(_ORGIN_DATA);
207
- addTreeIndent(_ORGIN_DATA, INDENT_PLACEHOLDER, INDENT_LAST_PLACEHOLDER, 'label');
208
- }
209
-
210
-
211
296
  // remove Duplicate objects from JSON Array
212
297
  _ORGIN_DATA = removeArrDuplicateItems(_ORGIN_DATA, 'value');
213
298
 
299
+ // save temporary default value
300
+ setTempDefaultValue(inputDefault);
301
+
214
302
  //
215
303
  setDataInit(_ORGIN_DATA); // data must be initialized
216
304
 
@@ -224,16 +312,12 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
224
312
  return _ORGIN_DATA;
225
313
  } else {
226
314
 
227
- // Set hierarchical categories ( with sub-categories )
228
- if (hierarchical) {
229
- optionsDataInit = addTreeDepth(optionsDataInit);
230
- addTreeIndent(optionsDataInit, INDENT_PLACEHOLDER, INDENT_LAST_PLACEHOLDER, 'label');
231
- }
232
-
233
-
315
+
234
316
  // remove Duplicate objects from JSON Array
235
317
  optionsDataInit = removeArrDuplicateItems(optionsDataInit, 'value');
236
318
 
319
+ // save temporary default value
320
+ setTempDefaultValue(inputDefault);
237
321
 
238
322
  //
239
323
  setDataInit(optionsDataInit); // data must be initialized
@@ -270,10 +354,12 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
270
354
  if (Array.isArray(_val)) {
271
355
 
272
356
  const _initVal = _val.filter((v: any) => v !== '');
357
+
273
358
  setValSelected(_initVal);
274
359
 
360
+
275
361
  // Initialize selected options
276
- if (UN_ATTACHED_SELECT) {
362
+ if (UNATTACHED_SELECT) {
277
363
  setValSelectedData((prevState: OptionConfig[]) => {
278
364
 
279
365
  let _data = [...prevState, ...options.filter((item: any) => {
@@ -282,12 +368,19 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
282
368
 
283
369
  return uniqueArr(_data);
284
370
  });
371
+
372
+
285
373
  } else {
286
374
  setValSelectedData(options.filter((item: any) => {
287
375
  return multiSelControlOptionExist(_initVal, item.value);
288
376
  }));
289
377
  }
290
378
 
379
+ // Initialize default options
380
+ setDataInit(options.filter((item: any) => {
381
+ return !multiSelControlOptionExist(_initVal, item.value);
382
+ }));
383
+
291
384
 
292
385
  } else {
293
386
  setValSelected([]);
@@ -299,127 +392,161 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
299
392
  }
300
393
 
301
394
 
302
- function selectItem(el: HTMLElement) {
303
- if (el === null) return;
395
+ function selectItem(curId: number) {
396
+
304
397
 
398
+ // update default options
399
+ setDataInit((prevState) => {
400
+ const newDefaultData = prevState.filter((item: any) => item.id != curId);
305
401
 
306
- const _li = el;
307
- const _val = _li.dataset.value;
308
- const _listItemLabel = _li.dataset.listItemLabel;
309
- const _label = _listItemLabel === '' ? _li.dataset.label : _listItemLabel;
310
- const _data = typeof _li.dataset.itemdata !== 'undefined' ? JSON.parse(_li.dataset.itemdata) : {};
311
402
 
403
+ const targetData = prevState.find((v: any) => v.id == curId); // !!!from old "dataInit"
404
+ const _data = typeof targetData !== 'undefined' ? targetData : {};
312
405
 
313
- // set selected items
314
- setValSelected((prevState) => {
315
- const newData = JSON.parse(JSON.stringify(prevState));
316
- const index = newData.findIndex((item: string | number) => item == _val);
317
- if (index !== -1) newData.splice(index, 1);
406
+ // update selected data
407
+ setValSelectedData((prevState2: any[]) => {
408
+ const newSelectedData = dragdropListDataInit([...prevState2, _data]);
318
409
 
319
- const _res = (_val) ? Array.from(new Set([...newData, _val])) : newData;
320
- onChange?.(_li, _res, VALUE_BY_BRACKETS ? convertArrToValByBrackets(_res) : _res.join(','), _data, 'add');
410
+ // update selected items
411
+ setValSelected((prevState3) => {
412
+ const newValueData = newSelectedData.map((v: any) => v.value);
413
+ const newValueStr = VALUE_BY_BRACKETS ? convertArrToValByBrackets(newValueData) : newValueData.join(',');
414
+
415
+ onChange?.(document.querySelector(`[data-id="${curId}"]`), newValueData, newValueStr, _data, 'add', newSelectedData);
321
416
 
322
- // hide current item
323
- _li.classList.add('hide');
417
+ // update temporary default value
418
+ setTempDefaultValue(newValueStr);
324
419
 
325
- return _res;
420
+ return newValueData;
421
+ });
422
+
423
+ return uniqueArr(newSelectedData);
424
+ });
425
+
426
+ return uniqueArr(newDefaultData);
326
427
  });
327
428
 
328
429
 
329
- // update selected data
330
- setValSelectedData((prevState) => {
331
- const newData = JSON.parse(JSON.stringify(prevState));
332
- const index = newData.findIndex((item: any) => item.value == _val);
333
- if (index !== -1) newData.splice(index, 1);
334
430
 
335
- const _res = (_val) ? Array.from(new Set([...newData, _data])) : newData;
336
431
 
337
432
 
338
- return _res;
339
- });
340
433
  }
341
434
 
342
- function removeItem(el: HTMLElement) {
343
- if (el === null) return;
435
+ function removeItem(curId: number) {
344
436
 
345
- const _li = el;
346
- const _val = _li.dataset.value;
347
- const _data = typeof _li.dataset.itemdata !== 'undefined' ? JSON.parse(_li.dataset.itemdata) : {};
437
+ // update selected data
438
+ setValSelectedData((prevState: any[]) => {
439
+ const newSelectedData = prevState.filter((item: any) => item.id != curId);
348
440
 
441
+ const targetData = prevState.find((v: any) => v.id == curId); // !!!from old "valSelectedData"
442
+ const _data = typeof targetData !== 'undefined' ? targetData : {};
349
443
 
350
- // set selected items
351
- setValSelected((prevState) => {
352
- const newData = JSON.parse(JSON.stringify(prevState));
353
- const index = newData.findIndex((item: string | number) => item == _val);
354
- if (index !== -1) newData.splice(index, 1);
444
+ // update default options
445
+ setDataInit((prevState2) => {
446
+ const newDefaultData = dragdropListDefaultDataInit([...prevState2, _data]);
447
+ return uniqueArr(newDefaultData);
448
+ });
355
449
 
356
- const _res = newData;
450
+ // update selected items
451
+ setValSelected((prevState3) => {
452
+ const newValueData = newSelectedData.map((v: any) => v.value);
453
+ const newValueStr = VALUE_BY_BRACKETS ? convertArrToValByBrackets(newValueData) : newValueData.join(',');
454
+
455
+ onChange?.(document.querySelector(`[data-id="${curId}"]`), newValueData, newValueStr, _data, 'remove', newSelectedData);
357
456
 
358
- onChange?.(_li, _res, VALUE_BY_BRACKETS ? convertArrToValByBrackets(_res) : _res.join(','), _data, 'remove');
457
+ // update temporary default value
458
+ setTempDefaultValue(newValueStr);
359
459
 
360
- // show current item
361
- if (availableListRef.current) {
362
- const removedItem = availableListRef.current.querySelector(`li[data-value="${_val}"]`);
363
- if (removedItem !== null) removedItem.classList.remove('hide');
364
- }
365
460
 
461
+ return newValueData;
462
+ });
366
463
 
367
- return _res;
464
+ return uniqueArr(newSelectedData);
368
465
  });
369
466
 
370
467
 
371
- // update selected data
372
- setValSelectedData((prevState) => {
373
- const newData = JSON.parse(JSON.stringify(prevState));
374
- const index = newData.findIndex((item: any) => item.value == _val);
375
- if (index !== -1) newData.splice(index, 1);
468
+ }
376
469
 
377
- const _res = newData;
378
470
 
379
- return _res;
380
- });
381
471
 
382
472
 
383
- }
473
+ function handleSelectAll(event: any) {
474
+ event.preventDefault();
475
+ event.stopPropagation();
476
+
477
+
478
+ // update default options
479
+ setDataInit((prevState) => {
480
+ const newDefaultData: any[] = [];
481
+
482
+ // filter the "disabled" option
483
+ const disabledData = prevState.filter((v: any) => v.disabled === true); // !!!from old "dataInit"
484
+ const targetData = prevState.filter((v: any) => typeof v.disabled === 'undefined' || v.disabled === false); // !!!from old "dataInit"
485
+
486
+
487
+ // update selected data
488
+ setValSelectedData((prevState2: any[]) => {
489
+ const newSelectedData = dragdropListDataInit([...prevState2, ...targetData]);
490
+
491
+ // update selected items
492
+ setValSelected((prevState3) => {
493
+ const newValueData = newSelectedData.map((v: any) => v.value);
494
+ const newValueStr = VALUE_BY_BRACKETS ? convertArrToValByBrackets(newValueData) : newValueData.join(',');
495
+
496
+ onChange?.(null, newValueData, newValueStr, null, 'add-all', newSelectedData);
497
+
498
+ // update temporary default value
499
+ setTempDefaultValue(newValueStr);
500
+
501
+ return newValueData;
502
+ });
503
+
504
+ return uniqueArr(newSelectedData);
505
+ });
506
+
507
+ return uniqueArr([...newDefaultData, ...disabledData]);
508
+ });
384
509
 
385
510
 
511
+ }
386
512
 
387
513
 
388
- function handleSelectAll(event: any) {
514
+ function handleRemoveAll(event: any) {
389
515
  event.preventDefault();
390
- if (availableListRef.current === null) return;
516
+ event.stopPropagation();
391
517
 
392
- const items = [].slice.call(availableListRef.current.querySelectorAll('li[data-value]'));
393
- items.forEach((item: any) => {
394
518
 
395
- if (!item.classList.contains('disabled')) {
396
- selectItem(item);
397
- }
519
+ // update selected data
520
+ setValSelectedData((prevState: any[]) => {
521
+ const newSelectedData: any[] = [];
398
522
 
399
- });
523
+ const targetData = prevState; // !!!from old "valSelectedData"
400
524
 
401
- //
402
- onAddAll?.(event, dataInit.map((v: any) => `${v.value}`), VALUE_BY_BRACKETS ? dataInit.map((v: any) => `[${v.value}]`).join('') : dataInit.map((v: any) => v.value).join(''));
525
+ // update default options
526
+ setDataInit((prevState2) => {
527
+ const newDefaultData = dragdropListDefaultDataInit([...prevState2, ...targetData]);
403
528
 
404
-
529
+ return uniqueArr(newDefaultData);
530
+ });
405
531
 
532
+ // update selected items
533
+ setValSelected((prevState3) => {
534
+ const newValueData = newSelectedData.map((v: any) => v.value);
535
+ const newValueStr = VALUE_BY_BRACKETS ? convertArrToValByBrackets(newValueData) : newValueData.join(',');
536
+
537
+ onChange?.(null, newValueData, newValueStr, null, 'remove-all', newSelectedData);
538
+ onRemoveAll?.(event, newValueData, newValueStr, newSelectedData);
406
539
 
407
- }
540
+ // update temporary default value
541
+ setTempDefaultValue(newValueStr);
408
542
 
409
543
 
410
- function handleRemoveAll(event: any) {
411
- event.preventDefault();
412
- if (selectedListRef.current === null) return;
544
+ return newValueData;
545
+ });
413
546
 
414
- const items = [].slice.call(selectedListRef.current.querySelectorAll('li[data-value]'));
415
- items.forEach((item: any) => {
416
- removeItem(item);
547
+ return uniqueArr(newSelectedData);
417
548
  });
418
549
 
419
- //
420
- onRemoveAll?.(event, [], '');
421
-
422
-
423
550
 
424
551
  }
425
552
 
@@ -465,7 +592,6 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
465
592
 
466
593
  useEffect(() => {
467
594
 
468
-
469
595
  // data init
470
596
  //--------------
471
597
  const _params: any[] = fetchFuncMethodParams || [];
@@ -490,18 +616,18 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
490
616
 
491
617
  <div
492
618
  className={combinedCls(
493
- 'm-select__wrapper',
619
+ 'm-select-v2__wrapper',
494
620
  clsWrite(wrapperClassName, 'mb-3')
495
621
  )}
496
622
  ref={rootRef}
497
623
  style={{
498
- minWidth: WRAPPER_MIN_W === '' ? 'var(--m-select-wrapper-min-w)' : WRAPPER_MIN_W,
499
- minHeight: WRAPPER_MIN_H === '' ? 'var(--m-select-wrapper-min-h)' : WRAPPER_MIN_H
624
+ minWidth: WRAPPER_MIN_W === '' ? 'var(--m-select-v2-wrapper-min-w)' : WRAPPER_MIN_W,
625
+ minHeight: WRAPPER_MIN_H === '' ? 'var(--m-select-v2-wrapper-min-h)' : WRAPPER_MIN_H
500
626
  }}
501
627
  >
502
628
 
503
629
  {/* DIVIDING LINE */}
504
- <div className="m-select-diving-line"></div>
630
+ <div className="m-select-v2-diving-line"></div>
505
631
  {/* /DIVIDING LINE */}
506
632
 
507
633
  {/* VALUE INPUT */}
@@ -526,22 +652,22 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
526
652
  {/* /VALUE INPUT */}
527
653
 
528
654
 
529
- <div className="m-select-inner">
655
+ <div className="m-select-v2-inner">
530
656
 
531
657
  {/*
532
658
  // ++++++++++++++++++++
533
659
  // Available Container
534
660
  // ++++++++++++++++++++
535
661
  */}
536
- <div className="m-select__available__container">
537
- <div className="m-select__m-select__item-actions m-select__header">
662
+ <div className="m-select-v2__available__container">
663
+ <div className="m-select-v2__m-select-v2__item-actions m-select-v2__header">
538
664
 
539
665
  {/* SEARCH */}
540
- <div className="m-select__search__container">
666
+ <div className="m-select-v2__search__container">
541
667
  <input
542
668
  type="text"
543
669
  value={changedSearchVal}
544
- className="m-select__search"
670
+ className="m-select-v2__search"
545
671
  onChange={handleChangeSearch}
546
672
  />
547
673
  <i><svg width="0.8em" height="0.8em" fill="#ddd" viewBox="0 0 16 16">
@@ -550,28 +676,28 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
550
676
  </div>
551
677
  {/* /SEARCH */}
552
678
 
553
- <span className="m-select__title" dangerouslySetInnerHTML={{ __html: `${availableHeaderTitle || ''}` }}></span>
679
+ <span className="m-select-v2__title" dangerouslySetInnerHTML={{ __html: `${availableHeaderTitle || ''}` }}></span>
554
680
 
555
- <a href="#" className="m-select__btn--add-all" onClick={handleSelectAll}>{addAllBtnLabel || 'Add all'}</a>
681
+ <a href="#" className="m-select-v2__btn--add-all" onClick={handleSelectAll}>{addAllBtnLabel || 'Add all'}</a>
556
682
  </div>
557
683
 
558
684
 
559
685
 
560
686
  {/* OPTIONS LIST */}
561
- <ItemList
562
- appendControl={appendControl}
563
- root={rootRef.current}
564
- listContainerClassName="m-select__available m-select__options-contentlist"
687
+ <DragDropList
688
+ data={dragdropListDefaultDataInit(dataInit as [])}
689
+ wrapperClassName=""
565
690
  ref={availableListRef}
566
- indentStr={INDENT_LAST_PLACEHOLDER}
567
- valSelected={valSelected}
568
- iconAdd={iconAdd}
569
- onSelect={selectItem}
691
+ prefix="m-select-v2"
692
+ draggable={false}
693
+ handleHide={handleHide}
694
+ handleIcon={handleIcon}
695
+ handlePos={handlePos}
696
+ dragMode={dragMode}
697
+ indentation={indentation}
698
+ doubleIndent={doubleIndent}
570
699
  alternateCollapse={alternateCollapse}
571
- first={true}
572
700
  arrow={arrow}
573
- data={dataInit}
574
- childClassName={childClassName || 'm-select__options-contentlist-custom'}
575
701
  />
576
702
  {/* /OPTIONS LIST */}
577
703
 
@@ -583,30 +709,42 @@ const MultipleSelect = forwardRef((props: MultipleSelectProps, externalRef: any)
583
709
  // Selected Container
584
710
  // ++++++++++++++++++++
585
711
  */}
586
- <div className="m-select__selected__container">
587
- <div className="m-select__m-select__item-actions m-select__header">
588
- <span className="m-select__count" dangerouslySetInnerHTML={{ __html: `${typeof selectedHeaderNote !== 'undefined' ? selectedHeaderNote.replace('{items_num}', valSelectedData.length as never) : ''}` }}></span>
589
- <span className="m-select__title" dangerouslySetInnerHTML={{ __html: `${selectedHeaderTitle || ''}` }}></span>
590
- <a href="#" className="m-select__btn--remove-all" onClick={handleRemoveAll}>{removeAllBtnLabel || 'Remove all'}</a>
712
+ <div className="m-select-v2__selected__container">
713
+ <div className="m-select-v2__m-select-v2__item-actions m-select-v2__header">
714
+ <span className="m-select-v2__count" dangerouslySetInnerHTML={{ __html: `${typeof selectedHeaderNote !== 'undefined' ? selectedHeaderNote.replace('{items_num}', valSelectedData.length as never) : ''}` }}></span>
715
+ <span className="m-select-v2__title" dangerouslySetInnerHTML={{ __html: `${selectedHeaderTitle || ''}` }}></span>
716
+ <a href="#" className="m-select-v2__btn--remove-all" onClick={handleRemoveAll}>{removeAllBtnLabel || 'Remove all'}</a>
591
717
  </div>
592
718
 
593
719
 
594
720
  {/* OPTIONS LIST */}
595
- <ItemList
596
- appendControl={appendControl}
597
- root={rootRef.current}
598
- listContainerClassName="m-select__selected m-select__options-contentlist--sortable m-select__options-contentlist"
599
- ref={selectedListRef}
600
- indentStr={INDENT_LAST_PLACEHOLDER}
601
- valSelected={selectedResultReverse ? valSelected.reverse() : valSelected}
602
- iconRemove={iconRemove}
603
- onSelect={removeItem}
604
- alternateCollapse={alternateCollapse}
605
- first={true}
721
+ <DragDropList
722
+ data={dragdropListDataInit(selectedResultReverse ? valSelectedData.reverse() : valSelectedData)}
723
+ onUpdate={(newData: any[], curId: number) => {
724
+ setValSelectedData(newData);
725
+
726
+ const newValueData = newData.map((v: any) => v.value);
727
+ const newValueStr = VALUE_BY_BRACKETS ? convertArrToValByBrackets(newValueData) : newValueData.join(',');
728
+ const targetData = newData.find((v: any) => v.id == curId); // !!!from old "dataInit"
729
+ const _data = typeof targetData !== 'undefined' ? targetData : {};
730
+
731
+ setValSelected(newData.map((v: any) => v.value));
732
+
733
+ onChange?.(document.querySelector(`[data-id="${curId}"]`), newValueData, newValueStr, _data, 'update', newData);
734
+
735
+ }}
736
+ wrapperClassName=""
737
+ prefix="m-select-v2"
738
+ draggable={draggable}
739
+ handleHide={handleHide}
740
+ handleIcon={handleIcon}
741
+ handlePos={handlePos}
742
+ dragMode={dragMode}
743
+ indentation={indentation}
744
+ doubleIndent={doubleIndent}
745
+ alternateCollapse={false}
606
746
  arrow={arrow}
607
- data={selectedResultReverse ? valSelectedData.reverse() : valSelectedData}
608
- childClassName={clsWrite(childClassName, 'm-select__options-contentlist--custom')}
609
- selected
747
+ hierarchical={false}
610
748
  />
611
749
  {/* /OPTIONS LIST */}
612
750