funda-ui 4.7.335 → 4.7.445

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 (41) hide show
  1. package/CascadingSelect/index.css +88 -87
  2. package/CascadingSelect/index.d.ts +21 -4
  3. package/CascadingSelect/index.js +209 -53
  4. package/CascadingSelectE2E/index.css +88 -87
  5. package/CascadingSelectE2E/index.d.ts +22 -5
  6. package/CascadingSelectE2E/index.js +233 -69
  7. package/MultipleCheckboxes/index.js +71 -0
  8. package/MultipleSelect/index.js +71 -0
  9. package/Table/index.js +16 -1
  10. package/TagInput/index.js +71 -0
  11. package/Utils/extract.d.ts +39 -1
  12. package/Utils/extract.js +65 -0
  13. package/Utils/useDragDropPosition.d.ts +0 -3
  14. package/Utils/useDragDropPosition.js +0 -3
  15. package/lib/cjs/CascadingSelect/index.d.ts +21 -4
  16. package/lib/cjs/CascadingSelect/index.js +209 -53
  17. package/lib/cjs/CascadingSelectE2E/index.d.ts +22 -5
  18. package/lib/cjs/CascadingSelectE2E/index.js +233 -69
  19. package/lib/cjs/MultipleCheckboxes/index.js +71 -0
  20. package/lib/cjs/MultipleSelect/index.js +71 -0
  21. package/lib/cjs/Table/index.js +16 -1
  22. package/lib/cjs/TagInput/index.js +71 -0
  23. package/lib/cjs/Utils/extract.d.ts +39 -1
  24. package/lib/cjs/Utils/extract.js +65 -0
  25. package/lib/cjs/Utils/useDragDropPosition.d.ts +0 -3
  26. package/lib/cjs/Utils/useDragDropPosition.js +0 -3
  27. package/lib/css/CascadingSelect/index.css +88 -87
  28. package/lib/css/CascadingSelectE2E/index.css +88 -87
  29. package/lib/esm/CascadingSelect/Group.tsx +4 -3
  30. package/lib/esm/CascadingSelect/index.scss +69 -66
  31. package/lib/esm/CascadingSelect/index.tsx +201 -60
  32. package/lib/esm/CascadingSelectE2E/Group.tsx +3 -3
  33. package/lib/esm/CascadingSelectE2E/index.scss +69 -66
  34. package/lib/esm/CascadingSelectE2E/index.tsx +235 -79
  35. package/lib/esm/Table/Table.tsx +1 -0
  36. package/lib/esm/Table/TableCell.tsx +0 -1
  37. package/lib/esm/Table/utils/SortSprite.tsx +3 -0
  38. package/lib/esm/Table/utils/hooks/useTableSort.tsx +16 -1
  39. package/lib/esm/Utils/hooks/useDragDropPosition.tsx +0 -3
  40. package/lib/esm/Utils/libs/extract.ts +77 -3
  41. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState, useRef, useImperativeHandle } from 'react';
1
+ import React, { useEffect, useState, forwardRef, useRef, useImperativeHandle } from 'react';
2
2
 
3
3
  import RootPortal from 'funda-root-portal';
4
4
 
@@ -9,6 +9,8 @@ import {
9
9
  extractorExist,
10
10
  extractContentsOfBraces,
11
11
  extractContentsOfBrackets,
12
+ extractContentsOfMixedCharactersWithBraces,
13
+ extractContentsOfMixedCharactersWithComma
12
14
  } from 'funda-utils/dist/cjs/extract';
13
15
  import {
14
16
  convertArrToValByBraces
@@ -26,12 +28,11 @@ import {
26
28
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
27
29
 
28
30
 
29
-
30
31
  import Group from './Group';
31
32
 
32
33
 
33
34
 
34
- export type CascadingSelectE2EOptionChangeFnType = (input: any, currentData: any, index: any, depth: any, value: any, closeFunc: any) => void;
35
+ export type CascadingSelectE2EOptionChangeFnType = (input: any, currentData: any, index: any, depth: any, value: string, closeFunc: any) => void;
35
36
 
36
37
 
37
38
  export interface fetchArrayConfig {
@@ -49,6 +50,8 @@ export type CascadingSelectE2EProps = {
49
50
  wrapperClassName?: string;
50
51
  controlClassName?: string;
51
52
  controlExClassName?: string;
53
+ controlGroupWrapperClassName?: string;
54
+ controlGroupTextClassName?: string;
52
55
  searchable?: boolean;
53
56
  searchPlaceholder?: string;
54
57
  perColumnHeadersShow?: boolean;
@@ -57,11 +60,18 @@ export type CascadingSelectE2EProps = {
57
60
  label?: React.ReactNode | string;
58
61
  name?: string;
59
62
  placeholder?: string;
63
+ readOnly?: any;
60
64
  disabled?: any;
61
65
  required?: any;
66
+ requiredLabel?: React.ReactNode | string;
67
+ units?: React.ReactNode | string;
68
+ iconLeft?: React.ReactNode | string;
69
+ iconRight?: React.ReactNode | string;
70
+ minLength?: any;
71
+ maxLength?: any;
62
72
  /** Whether to use curly braces to save result and initialize default value */
63
73
  extractValueByBraces?: boolean;
64
- /** Instead of using `parent_id` of response to match child and parent data
74
+ /** Instead of using `queryId` of response to match child and parent data
65
75
  * (very useful for multiple fetch requests with no directly related fields),
66
76
  * this operation will directly use the click event to modify the result. */
67
77
  destroyParentIdMatch?: boolean;
@@ -79,8 +89,8 @@ export type CascadingSelectE2EProps = {
79
89
  /** Set a loader component to show while the component waits for the next load of data.
80
90
  * e.g. `<span>Loading...</span>` or any fancy loader element */
81
91
  loader?: React.ReactNode;
82
- /** Whether to show breadcrumb result */
83
- displayResult?: boolean;
92
+ /** Whether it can be modified in the input box */
93
+ inputable?: boolean;
84
94
  /** Set an arrow of breadcrumb result */
85
95
  displayResultArrow?: React.ReactNode;
86
96
  /** Set an arrow of control */
@@ -104,21 +114,35 @@ export type CascadingSelectE2EProps = {
104
114
  onChange?: CascadingSelectE2EOptionChangeFnType | null;
105
115
  onBlur?: (e: any) => void;
106
116
  onFocus?: (e: any) => void;
117
+ /**
118
+ * Customize the function of formatting the value of the input input box, and the parameters are labels, values, and queryIds
119
+ * Returns a string as the value of the input
120
+ */
121
+ formatInputResult?: (param: Array<{label: string, value: string | number}>) => string;
107
122
  };
108
123
 
109
124
 
110
- const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
125
+ const CascadingSelectE2E = forwardRef((props: CascadingSelectE2EProps, externalRef: any) => {
111
126
  const {
112
127
  popupRef,
113
128
  wrapperClassName,
114
129
  controlClassName,
115
130
  controlExClassName,
131
+ controlGroupWrapperClassName,
132
+ controlGroupTextClassName,
116
133
  searchable = false,
117
134
  searchPlaceholder = '',
118
135
  perColumnHeadersShow = true,
119
136
  exceededSidePosOffset,
137
+ readOnly,
120
138
  disabled,
121
139
  required,
140
+ requiredLabel,
141
+ units,
142
+ iconLeft,
143
+ iconRight,
144
+ minLength,
145
+ maxLength,
122
146
  value,
123
147
  label,
124
148
  placeholder,
@@ -129,7 +153,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
129
153
  columnTitle,
130
154
  depth,
131
155
  loader,
132
- displayResult,
156
+ inputable = false,
133
157
  displayResultArrow,
134
158
  controlArrow,
135
159
  valueType,
@@ -145,6 +169,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
145
169
  onChange,
146
170
  onBlur,
147
171
  onFocus,
172
+ formatInputResult,
148
173
  ...attributes
149
174
  } = props;
150
175
 
@@ -156,12 +181,27 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
156
181
  const uniqueID = useComId();
157
182
  const idRes = id || uniqueID;
158
183
  const rootRef = useRef<any>(null);
159
- const valRef = useRef<any>(null);
184
+ const inputRef = useRef<any>(null);
160
185
  const listRef = useRef<any>(null);
161
186
 
162
187
  // searchable
163
188
  const [columnSearchKeywords, setColumnSearchKeywords] = useState<string[]>([]);
164
189
 
190
+ const propExist = (p: any) => {
191
+ return typeof p !== 'undefined' && p !== null && p !== '';
192
+ };
193
+
194
+ const resultInput = (curData: string[] | number[], curQueryIdsData: string[] | number[]) => {
195
+ return VALUE_BY_BRACES ? convertArrToValByBraces(curData.map((item: any, i: number) => `${item}[${curQueryIdsData[i]}]`)) : curData.map((item: any, i: number) => `${item}[${curQueryIdsData[i]}]`)!.join(',');
196
+ };
197
+
198
+ const resultInputPureText = (inputStr: string) => {
199
+ return VALUE_BY_BRACES ? `{${inputStr}[]}` : `${inputStr}[]`;
200
+
201
+ // value1: {{curLabel[curValue]}[]}
202
+ // value2: curLabel[curValue][]
203
+ };
204
+
165
205
 
166
206
  // exposes the following methods
167
207
  useImperativeHandle(
@@ -210,7 +250,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
210
250
  queryIds: []
211
251
  });
212
252
 
213
- // destroy `parent_id` match
253
+ // destroy `queryId` match
214
254
  const selectedDataByClick = useRef<any>({
215
255
  labels: [],
216
256
  values: [],
@@ -251,20 +291,19 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
251
291
 
252
292
 
253
293
  function popwinPosInit(showAct: boolean = true) {
254
- if (rootRef.current === null || valRef.current === null) return;
294
+ if (rootRef.current === null || inputRef.current === null) return;
255
295
 
256
296
 
257
297
  // update modal position
258
- const _modalRef: any = document.querySelector(`#cas-select-e2e__items-wrapper-${idRes}`);
259
- const _triggerRef: any = valRef.current;
260
- const _triggerXaxisRef: any = rootRef.current;
298
+ const _modalRef: any = document.querySelector(`#casc-select-e2e__items-wrapper-${idRes}`);
299
+ const _triggerRef: any = inputRef.current;
261
300
 
262
301
 
263
302
  // console.log(getAbsolutePositionOfStage(_triggerRef));
264
303
 
265
304
  if (_modalRef === null) return;
266
305
 
267
- const { x } = getAbsolutePositionOfStage(_triggerXaxisRef);
306
+ const { x } = getAbsolutePositionOfStage(_triggerRef);
268
307
  const { y, width, height } = getAbsolutePositionOfStage(_triggerRef);
269
308
  const _triggerBox = _triggerRef.getBoundingClientRect();
270
309
  let targetPos = '';
@@ -341,7 +380,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
341
380
 
342
381
  function popwinPosHide() {
343
382
 
344
- const _modalRef: any = document.querySelector(`#cas-select-e2e__items-wrapper-${idRes}`);
383
+ const _modalRef: any = document.querySelector(`#casc-select-e2e__items-wrapper-${idRes}`);
345
384
 
346
385
  if (_modalRef !== null) {
347
386
  // remove classnames and styles
@@ -357,9 +396,9 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
357
396
  if (listRef.current === null) return;
358
397
 
359
398
  let latestDisplayColIndex: number = 0;
360
- const currentItemsInner: any = listRef.current.querySelector('.cas-select-e2e__items-inner');
399
+ const currentItemsInner: any = listRef.current.querySelector('.casc-select-e2e__items-inner');
361
400
  if (currentItemsInner !== null) {
362
- const colItemsWrapper = [].slice.call(currentItemsInner.querySelectorAll('.cas-select-e2e__items-col'));
401
+ const colItemsWrapper = [].slice.call(currentItemsInner.querySelectorAll('.casc-select-e2e__items-col'));
363
402
  colItemsWrapper.forEach((perCol: any) => {
364
403
  perCol.classList.remove('hide-col');
365
404
  });
@@ -407,6 +446,9 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
407
446
  // show list
408
447
  setIsShow(true);
409
448
 
449
+ // update data depth
450
+ setCurrentDataDepth(0);
451
+
410
452
  // Execute the fetch task
411
453
  if (!firstDataFeched) {
412
454
  setLoading(true);
@@ -611,17 +653,16 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
611
653
 
612
654
  function handleDisplayOptions(event: any) {
613
655
  if (event) event.preventDefault();
614
-
615
- //
656
+ if (isShow) return;
616
657
  activate();
617
-
618
658
  }
619
659
 
620
660
 
621
661
  function handleClickItem(e: any, resValue: any, index: number, level: number, curData: any[]) {
622
662
  e.preventDefault();
623
663
 
624
- const dataDepthMax: boolean = resValue.itemDepth === fetchArray!.length - 1;
664
+ const maxDepth: number = fetchArray!.length - 1;
665
+ const dataDepthMax: boolean = resValue.itemDepth === maxDepth;
625
666
  const parentId: number = e.currentTarget.dataset.query;
626
667
  const emptyAction: boolean = resValue.id.toString().indexOf('$EMPTY_ID_') < 0 ? false : true;
627
668
 
@@ -648,7 +689,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
648
689
 
649
690
  });
650
691
 
651
- return _currentDataDepth;
692
+ return _currentDataDepth > maxDepth ? maxDepth : _currentDataDepth;
652
693
 
653
694
  });
654
695
 
@@ -664,8 +705,15 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
664
705
 
665
706
  // callback
666
707
  //////////////////////////////////////////
667
- if (typeof (onChange) === 'function') {
668
- onChange(valRef.current, resValue, index, level, inputVal, cancel);
708
+ if (typeof onChange === 'function') {
709
+ const curValString = valueType === 'value' ? inputVal[0] : inputVal[1];
710
+ const curValCallback = typeof formatInputResult === 'function' ? formatInputResult(
711
+ VALUE_BY_BRACES
712
+ ? extractContentsOfMixedCharactersWithBraces(curValString)
713
+ : extractContentsOfMixedCharactersWithComma(curValString)
714
+ ) : curValString;
715
+
716
+ onChange(inputRef.current, resValue, index, level, curValCallback, cancel);
669
717
  }
670
718
 
671
719
 
@@ -680,6 +728,12 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
680
728
  // All the elements from start(array.length - start) to the end of the array will be deleted.
681
729
  newData.splice(level + 1);
682
730
 
731
+ // When requesting a return asynchronously, a new column is added only under the currently clicked column,
732
+ // and the previous column cannot be affected.
733
+ // Make sure that subsequent asynchronous requests will only insert new columns towards the level+1 position.
734
+ listData.current = [...newData];
735
+
736
+
683
737
  // active status
684
738
  if (resValue.children) {
685
739
  const childList = resValue.children;
@@ -698,16 +752,14 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
698
752
  //
699
753
  cancel();
700
754
 
701
- // update data depth
702
- setCurrentDataDepth(0);
703
755
  }
704
756
 
705
757
  // active current option with DOM
706
758
  //////////////////////////////////////////
707
- const currentItemsInner: any = e.currentTarget.closest('.cas-select-e2e__items-inner');
759
+ const currentItemsInner: any = e.currentTarget.closest('.casc-select-e2e__items-inner');
708
760
  if (currentItemsInner !== null) {
709
761
  curData.forEach((v: any, col: number) => {
710
- const colItemsWrapper = currentItemsInner.querySelectorAll('.cas-select-e2e__items-col');
762
+ const colItemsWrapper = currentItemsInner.querySelectorAll('.casc-select-e2e__items-col');
711
763
  colItemsWrapper.forEach((perCol: HTMLUListElement) => {
712
764
  const _col = Number(perCol.dataset.col);
713
765
 
@@ -773,7 +825,7 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
773
825
 
774
826
  function updateValue(arr: any[], targetVal: any, level: number | boolean = false) {
775
827
 
776
- const inputEl: any = valRef.current;
828
+ const inputEl: any = inputRef.current;
777
829
  let _valueData: any, _labelData: any, _queryIdsData: any;
778
830
 
779
831
 
@@ -836,8 +888,8 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
836
888
  _queryIdsData = selectedDataByClick.current.queryIds;
837
889
  }
838
890
 
839
- const inputVal_0 = VALUE_BY_BRACES ? convertArrToValByBraces(_valueData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)) : _valueData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)!.join(',');
840
- const inputVal_1 = VALUE_BY_BRACES ? convertArrToValByBraces(_labelData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)) : _labelData.map((item: any, i: number) => `${item}[${_queryIdsData[i]}]`)!.join(',');
891
+ const inputVal_0 = resultInput(_valueData, _queryIdsData);
892
+ const inputVal_1 = resultInput(_labelData, _queryIdsData);
841
893
 
842
894
  if (valueType === 'value') {
843
895
  if (inputEl !== null) setChangedVal(inputVal_0);
@@ -1358,19 +1410,27 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
1358
1410
  }
1359
1411
  }, [listData.current.length]);
1360
1412
 
1413
+ useEffect(() => {
1414
+ return () => {
1415
+ // update data depth
1416
+ setCurrentDataDepth(0);
1417
+ }
1418
+ }, []);
1419
+
1420
+
1361
1421
 
1362
1422
  return (
1363
1423
  <>
1364
1424
 
1365
1425
  <div
1366
- className={clsWrite(wrapperClassName, 'cas-select-e2e__wrapper mb-3 position-relative', `cas-select-e2e__wrapper ${wrapperClassName}`)}
1426
+ className={clsWrite(wrapperClassName, 'casc-select-e2e__wrapper mb-3 position-relative', `casc-select-e2e__wrapper ${wrapperClassName}`)}
1367
1427
  ref={rootRef}
1368
- data-overlay-id={`cas-select-e2e__items-wrapper-${idRes}`}
1428
+ data-overlay-id={`casc-select-e2e__items-wrapper-${idRes}`}
1369
1429
  >
1370
1430
  {label ? <>{typeof label === 'string' ? <label htmlFor={idRes} className="form-label" dangerouslySetInnerHTML={{ __html: `${label}` }}></label> : <label htmlFor={idRes} className="form-label" >{label}</label>}</> : null}
1371
1431
 
1372
1432
  {triggerContent ? <>
1373
- <div className={clsWrite(triggerClassName, 'cas-select-e2e__trigger d-inline w-auto', `cas-select-e2e__trigger ${triggerClassName}`)} onClick={handleDisplayOptions}>{triggerContent}</div>
1433
+ <div className={clsWrite(triggerClassName, 'casc-select-e2e__trigger d-inline w-auto', `casc-select-e2e__trigger ${triggerClassName}`)} onClick={handleDisplayOptions}>{triggerContent}</div>
1374
1434
  </> : null}
1375
1435
 
1376
1436
 
@@ -1378,16 +1438,16 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
1378
1438
  <RootPortal show={true} containerClassName="CascadingSelectE2E">
1379
1439
  <div
1380
1440
  ref={listRef}
1381
- id={`cas-select-e2e__items-wrapper-${idRes}`}
1382
- className="cas-select-e2e__items-wrapper position-absolute border shadow small"
1441
+ id={`casc-select-e2e__items-wrapper-${idRes}`}
1442
+ className="casc-select-e2e__items-wrapper position-absolute border shadow small"
1383
1443
  style={{ zIndex: DEPTH, display: 'none' }}
1384
1444
  >
1385
- <ul className="cas-select-e2e__items-inner">
1386
- {loading ? <><div className="cas-select-e2e__items-loader">{loader || <svg height="12px" width="12px" viewBox="0 0 512 512"><g><path fill="inherit" d="M256,0c-23.357,0-42.297,18.932-42.297,42.288c0,23.358,18.94,42.288,42.297,42.288c23.357,0,42.279-18.93,42.279-42.288C298.279,18.932,279.357,0,256,0z" /><path fill="inherit" d="M256,427.424c-23.357,0-42.297,18.931-42.297,42.288C213.703,493.07,232.643,512,256,512c23.357,0,42.279-18.93,42.279-42.288C298.279,446.355,279.357,427.424,256,427.424z" /><path fill="inherit" d="M74.974,74.983c-16.52,16.511-16.52,43.286,0,59.806c16.52,16.52,43.287,16.52,59.806,0c16.52-16.511,16.52-43.286,0-59.806C118.261,58.463,91.494,58.463,74.974,74.983z" /><path fill="inherit" d="M377.203,377.211c-16.503,16.52-16.503,43.296,0,59.815c16.519,16.52,43.304,16.52,59.806,0c16.52-16.51,16.52-43.295,0-59.815C420.489,360.692,393.722,360.7,377.203,377.211z" /><path fill="inherit" d="M84.567,256c0.018-23.348-18.922-42.279-42.279-42.279c-23.357-0.009-42.297,18.932-42.279,42.288c-0.018,23.348,18.904,42.279,42.279,42.279C65.645,298.288,84.567,279.358,84.567,256z" /><path fill="inherit" d="M469.712,213.712c-23.357,0-42.279,18.941-42.297,42.288c0,23.358,18.94,42.288,42.297,42.297c23.357,0,42.297-18.94,42.279-42.297C512.009,232.652,493.069,213.712,469.712,213.712z" /><path fill="inherit" d="M74.991,377.22c-16.519,16.511-16.519,43.296,0,59.806c16.503,16.52,43.27,16.52,59.789,0c16.52-16.519,16.52-43.295,0-59.815C118.278,360.692,91.511,360.692,74.991,377.22z" /><path fill="inherit" d="M437.026,134.798c16.52-16.52,16.52-43.304,0-59.824c-16.519-16.511-43.304-16.52-59.823,0c-16.52,16.52-16.503,43.295,0,59.815C393.722,151.309,420.507,151.309,437.026,134.798z" /></g></svg>}</div></> : null}
1445
+ <ul className="casc-select-e2e__items-inner">
1446
+ {loading ? <><div className="casc-select-e2e__items-loader">{loader || <svg height="12px" width="12px" viewBox="0 0 512 512"><g><path fill="inherit" d="M256,0c-23.357,0-42.297,18.932-42.297,42.288c0,23.358,18.94,42.288,42.297,42.288c23.357,0,42.279-18.93,42.279-42.288C298.279,18.932,279.357,0,256,0z" /><path fill="inherit" d="M256,427.424c-23.357,0-42.297,18.931-42.297,42.288C213.703,493.07,232.643,512,256,512c23.357,0,42.279-18.93,42.279-42.288C298.279,446.355,279.357,427.424,256,427.424z" /><path fill="inherit" d="M74.974,74.983c-16.52,16.511-16.52,43.286,0,59.806c16.52,16.52,43.287,16.52,59.806,0c16.52-16.511,16.52-43.286,0-59.806C118.261,58.463,91.494,58.463,74.974,74.983z" /><path fill="inherit" d="M377.203,377.211c-16.503,16.52-16.503,43.296,0,59.815c16.519,16.52,43.304,16.52,59.806,0c16.52-16.51,16.52-43.295,0-59.815C420.489,360.692,393.722,360.7,377.203,377.211z" /><path fill="inherit" d="M84.567,256c0.018-23.348-18.922-42.279-42.279-42.279c-23.357-0.009-42.297,18.932-42.279,42.288c-0.018,23.348,18.904,42.279,42.279,42.279C65.645,298.288,84.567,279.358,84.567,256z" /><path fill="inherit" d="M469.712,213.712c-23.357,0-42.279,18.941-42.297,42.288c0,23.358,18.94,42.288,42.297,42.297c23.357,0,42.297-18.94,42.279-42.297C512.009,232.652,493.069,213.712,469.712,213.712z" /><path fill="inherit" d="M74.991,377.22c-16.519,16.511-16.519,43.296,0,59.806c16.503,16.52,43.27,16.52,59.789,0c16.52-16.519,16.52-43.295,0-59.815C118.278,360.692,91.511,360.692,74.991,377.22z" /><path fill="inherit" d="M437.026,134.798c16.52-16.52,16.52-43.304,0-59.824c-16.519-16.511-43.304-16.52-59.823,0c-16.52,16.52-16.503,43.295,0,59.815C393.722,151.309,420.507,151.309,437.026,134.798z" /></g></svg>}</div></> : null}
1387
1447
  {showCloseBtn ? <a href="#" tabIndex={-1} onClick={(e) => {
1388
1448
  e.preventDefault();
1389
1449
  cancel();
1390
- }} className="cas-select-e2e__close position-absolute top-0 end-0 mt-0 mx-1"><svg width="10px" height="10px" viewBox="0 0 1024 1024"><path fill="#000" d="M195.2 195.2a64 64 0 0 1 90.496 0L512 421.504 738.304 195.2a64 64 0 0 1 90.496 90.496L602.496 512 828.8 738.304a64 64 0 0 1-90.496 90.496L512 602.496 285.696 828.8a64 64 0 0 1-90.496-90.496L421.504 512 195.2 285.696a64 64 0 0 1 0-90.496z" /></svg></a> : null}
1450
+ }} className="casc-select-e2e__close position-absolute top-0 end-0 mt-0 mx-1"><svg width="10px" height="10px" viewBox="0 0 1024 1024"><path fill="#000" d="M195.2 195.2a64 64 0 0 1 90.496 0L512 421.504 738.304 195.2a64 64 0 0 1 90.496 90.496L602.496 512 828.8 738.304a64 64 0 0 1-90.496 90.496L512 602.496 285.696 828.8a64 64 0 0 1-90.496-90.496L421.504 512 195.2 285.696a64 64 0 0 1 0-90.496z" /></svg></a> : null}
1391
1451
 
1392
1452
 
1393
1453
 
@@ -1406,12 +1466,12 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
1406
1466
 
1407
1467
 
1408
1468
  return (
1409
- <li key={level} data-col={level} className="cas-select-e2e__items-col">
1469
+ <li key={level} data-col={level} className="casc-select-e2e__items-col">
1410
1470
 
1411
1471
 
1412
1472
  {/* SEARCH BOX */}
1413
1473
  {searchable && (
1414
- <div className="cas-select-e2e__items-col-searchbox">
1474
+ <div className="casc-select-e2e__items-col-searchbox">
1415
1475
  <input
1416
1476
  type="text"
1417
1477
  placeholder={searchPlaceholder}
@@ -1452,45 +1512,141 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
1452
1512
 
1453
1513
 
1454
1514
 
1455
- <div className="cas-select-e2e__val" onClick={handleDisplayOptions}>
1456
-
1457
- {/** REVIEW RESULT */}
1458
- {destroyParentIdMatch ? <>
1459
- {displayResult ? <div className="cas-select-e2e__result">{displayInfo(true)}</div> : null}
1460
- </> : <>
1461
- {displayResult ? <div className="cas-select-e2e__result">{displayInfo(false)}</div> : null}
1462
- </>}
1463
-
1464
-
1465
- <input
1466
- ref={valRef}
1467
- id={idRes}
1468
- data-overlay-id={`cas-select-e2e__items-wrapper-${idRes}`}
1469
- name={name}
1470
- className={combinedCls(
1471
- clsWrite(controlClassName, 'form-control'),
1472
- controlExClassName
1473
- )}
1474
- placeholder={placeholder}
1475
- value={destroyParentIdMatch
1476
- ?
1477
- (valueType === 'value' ? (VALUE_BY_BRACES ? convertArrToValByBraces(selectedDataByClick.current.values.map((item: any, i: number) => `${item}[${selectedDataByClick.current.queryIds[i]}]`)) : selectedDataByClick.current.values.map((item: any, i: number) => `${item}[${selectedDataByClick.current.queryIds[i]}]`)!.join(',')) : (VALUE_BY_BRACES ? convertArrToValByBraces(selectedDataByClick.current.labels.map((item: any, i: number) => `${item}[${selectedDataByClick.current.queryIds[i]}]`)) : selectedDataByClick.current.labels.map((item: any, i: number) => `${item}[${selectedDataByClick.current.queryIds[i]}]`)!.join(',')))
1478
- :
1479
- changedVal
1480
- } // placeholder will not change if defaultValue is used
1481
- onFocus={handleFocus}
1482
- onBlur={handleBlur}
1483
- disabled={disabled || null}
1484
- required={required || null}
1485
- style={style}
1486
- tabIndex={tabIndex || 0}
1487
- readOnly
1488
- {...attributes}
1489
- />
1515
+ <div className={combinedCls(
1516
+ 'casc-select-e2e__val',
1517
+ {
1518
+ 'inputable': inputable,
1519
+ }
1520
+
1521
+ )}
1522
+ onClick={handleDisplayOptions}
1523
+ >
1524
+
1525
+
1526
+ {/* INPIT */}
1527
+ <div className={combinedCls(
1528
+ 'position-relative',
1529
+ clsWrite(controlGroupWrapperClassName, 'input-group'),
1530
+ {
1531
+ 'has-left-content': propExist(iconLeft),
1532
+ 'has-right-content': propExist(iconRight) || propExist(units)
1533
+ }
1534
+
1535
+ )}>
1536
+
1537
+ {propExist(iconLeft) ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconLeft}</span></> : null}
1538
+
1539
+ <div className="input-group-control-container flex-fill position-relative">
1540
+ <input
1541
+ ref={(node) => {
1542
+ inputRef.current = node;
1543
+ if (typeof externalRef === 'function') {
1544
+ externalRef(node);
1545
+ } else if (externalRef) {
1546
+ externalRef.current = node;
1547
+ }
1548
+ }}
1549
+ id={idRes}
1550
+ data-overlay-id={`casc-select-e2e__items-wrapper-${idRes}`}
1551
+ name={name}
1552
+ className={combinedCls(
1553
+ clsWrite(controlClassName, 'form-control'),
1554
+ controlExClassName,
1555
+ {
1556
+ 'rounded': !propExist(iconLeft) && !propExist(iconRight) && !propExist(units),
1557
+ 'rounded-start-0': propExist(iconLeft),
1558
+ 'rounded-end-0': propExist(iconRight) || propExist(units)
1559
+ }
1560
+ )}
1561
+
1562
+ placeholder={placeholder}
1563
+ value={(() => {
1564
+ const curValForamt: string = resultInputPureText(changedVal);
1565
+ let curValCallback: string = '';
1566
+
1567
+ // STEP 1
1568
+ //============
1569
+
1570
+ if (inputable) {
1571
+ curValCallback = curValForamt;
1572
+ } else {
1573
+ curValCallback = destroyParentIdMatch ? (valueType === 'value'
1574
+ ? resultInput(selectedDataByClick.current.values, selectedDataByClick.current.queryIds)
1575
+ : resultInput(selectedDataByClick.current.labels, selectedDataByClick.current.queryIds)
1576
+ ) : curValForamt;
1577
+ }
1578
+
1579
+
1580
+ // STEP 2
1581
+ //============
1582
+ if (typeof formatInputResult === 'function') {
1583
+
1584
+ return formatInputResult(
1585
+ VALUE_BY_BRACES
1586
+ ? extractContentsOfMixedCharactersWithBraces(curValCallback)
1587
+ : extractContentsOfMixedCharactersWithComma(curValCallback)
1588
+ );
1589
+
1590
+ } else {
1591
+ return changedVal;
1592
+ }
1593
+
1594
+
1595
+ })()
1596
+ }
1597
+ // placeholder will not change if defaultValue is used
1598
+ onFocus={handleFocus}
1599
+ onBlur={handleBlur}
1600
+ autoComplete="off"
1601
+ disabled={disabled || null}
1602
+ readOnly={readOnly || null}
1603
+ required={required || null}
1604
+ minLength={minLength || null}
1605
+ maxLength={maxLength || null}
1606
+ style={style}
1607
+ tabIndex={tabIndex || 0}
1608
+ onChange={inputable ? (e) => {
1609
+ setChangedVal(e.target.value);
1610
+ if (typeof onChange === 'function') {
1611
+ onChange(
1612
+ e, // input dom event
1613
+ null, // currentData
1614
+ null, // index
1615
+ null, // depth
1616
+ e.target.value, // value
1617
+ cancel
1618
+ );
1619
+ }
1620
+ } : undefined}
1621
+ {...attributes}
1622
+
1623
+ />
1624
+
1625
+
1626
+
1627
+ {/** REVIEW RESULT */}
1628
+ {destroyParentIdMatch ? <>
1629
+ {!inputable ? <div className="casc-select-e2e__result">{displayInfo(true)}</div> : null}
1630
+ </> : <>
1631
+ {!inputable ? <div className="casc-select-e2e__result">{displayInfo(false)}</div> : null}
1632
+ </>}
1633
+
1490
1634
 
1635
+ {/* Required marking */}
1636
+ {required ? <>{requiredLabel || requiredLabel === '' ? requiredLabel : <span className="position-absolute end-0 top-0 my-2 mx-2 pe-3"><span className="text-danger">*</span></span>}</> : ''}
1637
+
1638
+ </div>
1639
+
1640
+
1641
+ {propExist(units) ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{units}</span></> : null}
1642
+ {propExist(iconRight) ? <><span className={clsWrite(controlGroupTextClassName, 'input-group-text')}>{iconRight}</span></> : null}
1643
+
1644
+ </div>
1645
+ {/* /INPIT */}
1646
+
1491
1647
 
1492
1648
  {isShow ? <div
1493
- className="cas-select-e2e__closemask"
1649
+ className="casc-select-e2e__closemask"
1494
1650
  onClick={(e) => {
1495
1651
  e.preventDefault();
1496
1652
  cancel();
@@ -1521,6 +1677,6 @@ const CascadingSelectE2E = (props: CascadingSelectE2EProps) => {
1521
1677
 
1522
1678
  </>
1523
1679
  )
1524
- };
1680
+ });
1525
1681
 
1526
1682
  export default CascadingSelectE2E;
@@ -5,6 +5,7 @@ import useComId from 'funda-utils/dist/cjs/useComId';
5
5
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
6
6
 
7
7
 
8
+
8
9
  import { TableProvider } from './TableContext';
9
10
  import useTableResponsive from './utils/hooks/useTableResponsive';
10
11
  import useTableDraggable from './utils/hooks/useTableDraggable';
@@ -3,7 +3,6 @@ import React, { forwardRef, useContext } from 'react';
3
3
  import { clsWrite, combinedCls } from 'funda-utils/dist/cjs/cls';
4
4
 
5
5
 
6
-
7
6
  import { TableContext } from './TableContext';
8
7
 
9
8
  import { cellMark, removeCellFocusClassName } from './utils/func';
@@ -7,6 +7,7 @@ export type SortSpriteProps = {
7
7
  fieldType: 'text' | 'number' | 'date';
8
8
  className?: string;
9
9
  icon?: React.ReactNode;
10
+ isReverse?: boolean;
10
11
  onClick?: (e: any) => void;
11
12
  };
12
13
 
@@ -16,6 +17,7 @@ const SortSprite = forwardRef((props: SortSpriteProps, externalRef: any) => {
16
17
  fieldType,
17
18
  className,
18
19
  icon,
20
+ isReverse = false,
19
21
  onClick
20
22
  } = props;
21
23
 
@@ -34,6 +36,7 @@ const SortSprite = forwardRef((props: SortSpriteProps, externalRef: any) => {
34
36
  spyElement: rootRef.current,
35
37
  fieldType: fieldType,
36
38
  onColSort: onColSort,
39
+ isReverse: isReverse,
37
40
  onClick: onClick
38
41
  }, [rootRef]);
39
42
 
@@ -30,6 +30,7 @@ export interface UseTableSortProps {
30
30
  data?: any[];
31
31
  spyElement?: any;
32
32
  fieldType: 'text' | 'number' | 'date';
33
+ isReverse?: boolean;
33
34
  onColSort?: (fetchData: any) => void;
34
35
  onClick?: (e: any) => void;
35
36
  }
@@ -39,6 +40,7 @@ function useTableSort({
39
40
  data,
40
41
  spyElement,
41
42
  fieldType,
43
+ isReverse = false,
42
44
  onColSort,
43
45
  onClick
44
46
  }: UseTableSortProps, deps: any[]) {
@@ -79,14 +81,27 @@ function useTableSort({
79
81
  txt2 = new Date(txt2);
80
82
  }
81
83
 
84
+
82
85
  //add filter class
83
86
  allRows(spyElement).forEach((node: any) => {
84
87
  node.classList.add('newsort');
85
88
  });
86
89
 
90
+
87
91
  setInverse(!inverse);
88
92
 
89
- return txt2 < txt1 ? -1 : txt2 > txt1 ? 1 : 0;
93
+
94
+ // result
95
+ if (filterType == 'text') {
96
+ return isReverse
97
+ ? txt1.localeCompare(txt2, 'zh-CN', { sensitivity: 'base' })
98
+ : txt2.localeCompare(txt1, 'zh-CN', { sensitivity: 'base' });
99
+ } else {
100
+ return isReverse
101
+ ? (txt1 < txt2 ? -1 : txt1 > txt2 ? 1 : 0)
102
+ : (txt2 < txt1 ? -1 : txt2 > txt1 ? 1 : 0);
103
+ }
104
+
90
105
  }
91
106
 
92
107
  targetComparator.sort(sortBy);