@lingxiteam/ebe-utils 0.4.0 → 0.4.1

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.
@@ -1,7 +1,7 @@
1
1
  import { Select as AntdSelect, Tag } from 'antd';
2
- import type { SelectProps } from 'antd/es/select';
2
+ import type { SelectProps, DefaultOptionType } from 'antd/es/select';
3
3
  import { CheckOutlined } from '@lingxiteam/icons';
4
- import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
4
+ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
5
5
  import { renderCommonList } from '../utils/renderReadOnly';
6
6
  import { useFuncExpExecute } from '../utils/hooks/useFuncExpExecute';
7
7
  import { FormFields, getFieldsProps, useCommonImperativeHandle, useForm } from '../utils';
@@ -14,6 +14,7 @@ import { CHECK_ALL_VALUE, handleFormValue, isLabelInValue, localFilterOption, ge
14
14
  import CustomModule from '../utils/CustomModule';
15
15
  import { EngineBaseProps } from '@lingxiteam/types';
16
16
  import { isEqual } from 'lodash';
17
+ import useDoubleClick from '../utils/hooks/useDoubleClick';
17
18
 
18
19
 
19
20
  export interface MySelectProps extends EngineBaseProps {
@@ -71,6 +72,7 @@ export interface MySelectProps extends EngineBaseProps {
71
72
  * 是否输入触发,默认fasel,也就是回车键触发, 为true的时候表示实时搜索
72
73
  */
73
74
  isInputSearch?: boolean;
75
+ localFilterType?: 'default' | 'label' | 'value';
74
76
  }
75
77
 
76
78
  interface WrapperSelectProps {
@@ -85,6 +87,7 @@ const WrapperSelect: React.FC<WrapperSelectProps> = ({ children }) =>
85
87
 
86
88
 
87
89
  const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
90
+ console.log('Select', props);
88
91
  const {
89
92
  value: originValue,
90
93
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -134,10 +137,10 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
134
137
  labelKey = 'label',
135
138
  valueKey = 'value',
136
139
  mode,
140
+ localFilterType,
137
141
  $$componentItem,
138
142
  ...restProps
139
143
  } = props;
140
-
141
144
  const defaultValue = useMemo(() => {
142
145
  if ((_defaultValue === null || _defaultValue === '') && mode === 'multiple') {
143
146
  return undefined;
@@ -190,7 +193,7 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
190
193
  formFieldsRef,
191
194
  readOnly,
192
195
  } = useCommonImperativeHandle(ref, props, {
193
- clearValue: [],
196
+ clearValue: mode === 'multiple' ? [] : undefined,
194
197
  getSelectedData: () => {
195
198
  return getChangeSelectData(dataSource, value, mode);
196
199
  },
@@ -267,7 +270,7 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
267
270
  defaultActiveFirstOption: false,
268
271
  showSearch: true,
269
272
  optionFilterProp: 'children',
270
- filterOption: localFilterOption,
273
+ filterOption: (inputValue, option) => localFilterOption(inputValue, option, localFilterType),
271
274
  onSearch: handleLocalSearch,
272
275
  };
273
276
  }
@@ -304,7 +307,29 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
304
307
  };
305
308
  }
306
309
  return {};
307
- }, [filter, dataState]);
310
+ }, [filter, dataState, localFilterType]);
311
+
312
+ const filterSort = useCallback((optionA: DefaultOptionType, optionB: DefaultOptionType) => {
313
+ const getScore = (option: any) => {
314
+ const label = String(option?.children || option?.label || '').toLowerCase();
315
+ const value = String(option?.value || '').toLowerCase();
316
+ const search = searchTextRef.current?.toLowerCase() || '';
317
+
318
+ // 匹配位置越靠前,排名越前
319
+ if (localFilterType === 'label') {
320
+ return label.indexOf(search);
321
+ } if (localFilterType === 'value') {
322
+ return value.indexOf(search);
323
+ }
324
+
325
+ return Math.min(
326
+ label.includes(search) ? label.indexOf(search) : Infinity,
327
+ value.includes(search) ? value.indexOf(search) : Infinity
328
+ );
329
+ };
330
+
331
+ return getScore(optionA) - getScore(optionB);
332
+ }, [localFilterType]);
308
333
 
309
334
  const renderGengelContent = (c: any, data: any) => {
310
335
  const {
@@ -597,7 +622,15 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
597
622
 
598
623
  const tagRender = (props: any) => {
599
624
  const { label, closable, onClose } = props;
600
- const { color, backgroundColor } = customRenderLabel?.options || {};
625
+ const { color, backgroundColor, isBaseText, isShallowPrimary, isPrimary } =
626
+ customRenderLabel?.options || {};
627
+ const style: React.CSSProperties = {};
628
+ if (!isBaseText) {
629
+ style.color = color;
630
+ }
631
+ if (!isShallowPrimary && !isPrimary) {
632
+ style.backgroundColor = backgroundColor;
633
+ }
601
634
  return (
602
635
  <Tag
603
636
  className={classNames({
@@ -606,7 +639,7 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
606
639
  darkBackground: customRenderLabel?.type === 'darkBackground',
607
640
  jsx: customRenderLabel?.jsx,
608
641
  })}
609
- style={{ backgroundColor, color }}
642
+ style={style}
610
643
  // color={value}
611
644
  // onMouseDown={onPreventMouseDown}
612
645
  closable={closable}
@@ -617,6 +650,32 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
617
650
  );
618
651
  };
619
652
 
653
+ const selectOnClick = (e: any) => {
654
+ let targetParent = (e?.target as HTMLBaseElement)?.parentNode;
655
+ const curretTarget = e?.currentTarget;
656
+ while (targetParent && targetParent !== curretTarget) {
657
+ targetParent = targetParent.parentNode;
658
+ }
659
+ if (targetParent === curretTarget) {
660
+ setOpen(!open);
661
+ if (open) {
662
+ handleAfterClose();
663
+ }
664
+ }
665
+ // @ts-ignore
666
+ restProps?.onClick?.(e);
667
+ };
668
+
669
+ // 改造兼容双击事件
670
+ const selectClickEvents = useDoubleClick({
671
+ clickName: 'onClick',
672
+ doubleClickName: 'onDoubleClick',
673
+ type: 'Button',
674
+ events: {
675
+ onClick: selectOnClick,
676
+ },
677
+ });
678
+
620
679
  return (
621
680
  <FormFields
622
681
  {...getFieldsProps(props)}
@@ -645,6 +704,8 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
645
704
  tagRender={tagRender}
646
705
  optionLabelProp="label"
647
706
  notFoundContent={searching ? <SpinComp dataState={dataState} /> : renderEmpty}
707
+ filterSort={filterSort}
708
+ {...selectClickEvents}
648
709
  onChange={(v) => {
649
710
  if (filter === 'local' && searchTextRef.current) {
650
711
  // 点击时需要重置过滤条件
@@ -658,21 +719,22 @@ const Select = React.forwardRef<any, MySelectProps>((props, ref) => {
658
719
 
659
720
  handleOnChange(v);
660
721
  }}
661
- onClick={(e) => {
662
- let targetParent = (e?.target as HTMLBaseElement)?.parentNode;
663
- const curretTarget = e?.currentTarget;
664
- while (targetParent && targetParent !== curretTarget) {
665
- targetParent = targetParent.parentNode;
666
- }
667
- if (targetParent === curretTarget) {
668
- setOpen(!open);
669
- if (open) {
670
- handleAfterClose();
671
- }
672
- }
673
- // @ts-ignore
674
- restProps?.onClick?.(e);
675
- }}
722
+ // onClick={(e) => {
723
+ // console.log('单击:', e);
724
+ // let targetParent = (e?.target as HTMLBaseElement)?.parentNode;
725
+ // const curretTarget = e?.currentTarget;
726
+ // while (targetParent && targetParent !== curretTarget) {
727
+ // targetParent = targetParent.parentNode;
728
+ // }
729
+ // if (targetParent === curretTarget) {
730
+ // setOpen(!open);
731
+ // if (open) {
732
+ // handleAfterClose();
733
+ // }
734
+ // }
735
+ // // @ts-ignore
736
+ // restProps?.onClick?.(e);
737
+ // }}
676
738
  onBlur={() => {
677
739
  setOpen(false);
678
740
  handleAfterClose();
@@ -1,5 +1,8 @@
1
+
2
+
1
3
  export const CHECK_ALL_VALUE = 'LING_XI_CHECK_ALL';
2
4
 
5
+
3
6
  const typeFn: any = {
4
7
  string: String,
5
8
  number: Number,
@@ -12,33 +15,70 @@ const typeFn: any = {
12
15
  * @param option
13
16
  * @returns
14
17
  */
15
- export const localFilterOption = (input: string = '', option: any) => {
16
- // 本地支持value和label过滤
17
- let valueFilter = false;
18
+ // export const localFilterOption = (input: string = '', option: any) => {
19
+ // // 本地支持value和label过滤
20
+ // let valueFilter = false;
21
+ // if (option?.value === CHECK_ALL_VALUE) {
22
+ // // 存在全选项时,永远展示
23
+ // return true;
24
+ // }
25
+ // if (option?.value && typeof option?.value === 'string') {
26
+ // valueFilter = option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
27
+ // }
28
+ // if (option?.children && typeof option.children === 'string') {
29
+ // return option?.children?.toLowerCase?.().indexOf(input.toLowerCase()) >= 0 || valueFilter;
30
+ // }
31
+
32
+ // return option?.label?.toLowerCase?.().indexOf(input.toLowerCase()) >= 0 || valueFilter;
33
+ // };
34
+
35
+ const checkInputValue = (input: string = '', value: any) => {
36
+ if (value !== null && value !== undefined) {
37
+ return String(value).toLowerCase().includes(input);
38
+ }
39
+ return false;
40
+ };
41
+
42
+ export const localFilterOption = (input: string = '', option: any, localFilterType?: 'default' | 'label' | 'value') => {
18
43
  if (option?.value === CHECK_ALL_VALUE) {
19
44
  // 存在全选项时,永远展示
20
45
  return true;
21
46
  }
22
- if (option?.value && typeof option?.value === 'string') {
23
- valueFilter = option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0;
24
- }
25
- if (option?.children && typeof option.children === 'string') {
26
- return option?.children?.toLowerCase?.().indexOf(input.toLowerCase()) >= 0 || valueFilter;
27
- }
28
47
 
29
- return option?.label?.toLowerCase?.().indexOf(input.toLowerCase()) >= 0 || valueFilter;
48
+ const inputLower = input.toLowerCase();
49
+
50
+ // 处理 value 过滤
51
+ const valueFilter = checkInputValue(inputLower, option.value);
52
+
53
+ // 处理 label 或 children 过滤
54
+ const childernFilter = option?.children && typeof option.children === 'string' ? checkInputValue(inputLower, option.children) : false;
55
+ const labelFilter = checkInputValue(inputLower, option.label);
56
+
57
+ // 根据 localFilterType 决定返回值
58
+ switch (localFilterType) {
59
+ case 'value':
60
+ return valueFilter;
61
+ case 'label':
62
+ return labelFilter || childernFilter;
63
+ default:
64
+ return labelFilter || childernFilter || valueFilter;
65
+ }
30
66
  };
31
67
 
32
68
  // 判断data类型是不是是labelInValue格式
33
69
  export const isLabelInValue = (data: any) => {
34
70
  if (Object.prototype.toString.call(data) === '[object Object]') {
35
- if (Object.keys(data).includes('label') && (Object.keys(data).includes('value') || Object.keys(data).includes('key'))) {
71
+ if (Object.keys(data).includes('label') &&
72
+ (Object.keys(data).includes('value') || Object.keys(data).includes('key'))) {
36
73
  return true;
37
74
  }
38
75
  } else if (Object.prototype.toString.call(data) === '[object Array]' && data.length) {
39
76
  let isLabelInValueCount = 0;
40
77
  data.forEach((v: any) => {
41
- if (Object.keys(v).includes('label') && (Object.keys(v).includes('value') || Object.keys(v).includes('key'))) {
78
+ if (
79
+ Object.keys(v).includes('label') &&
80
+ (Object.keys(v).includes('value') || Object.keys(v).includes('key'))
81
+ ) {
42
82
  isLabelInValueCount += 1;
43
83
  }
44
84
  });
@@ -83,6 +123,7 @@ export const transformValueType = (v: any, curVal: any) => {
83
123
  return v;
84
124
  };
85
125
 
126
+
86
127
  export const getRules = (min?: number, max?: number, getLocale?: any) => {
87
128
  if (!min && !max) {
88
129
  return [];
@@ -112,7 +153,7 @@ export const getChangeSelectData = (dataSource: any[], val: string[] | Object, m
112
153
  return undefined;
113
154
  }
114
155
  const sltData = dataSource.find((c: any) => c.value?.toString() === v?.toString());
115
- return sltData ? [sltData] : undefined;
156
+ return (sltData ? [sltData] : undefined);
116
157
  };
117
158
 
118
159
  export const getSelectedAllData = (checked: boolean, dataSource: any[], value: any[], max?: number) => {
@@ -157,7 +198,7 @@ export const getSelectedAllData = (checked: boolean, dataSource: any[], value: a
157
198
 
158
199
  // 获取当前列表数据下的全选状态
159
200
  export const checkIfSelectedAll = (dataSource: any[], value: any[], filterValue: string = '') => {
160
- const localFilterData = dataSource.filter((d) => localFilterOption(filterValue, d));
201
+ const localFilterData = dataSource.filter(d => localFilterOption(filterValue, d));
161
202
  if (localFilterData?.length && Array.isArray(value)) {
162
203
  // 如果是多选,value肯定是字符串类型的数组
163
204
  const checkData = localFilterData.filter((f: any) => value.includes(f.value));
@@ -174,7 +215,7 @@ export const checkIfSelectedAll = (dataSource: any[], value: any[], filterValue:
174
215
  * @param labelKey
175
216
  * @returns
176
217
  */
177
- export const handleDataSource = (dataSource: any[], appendDataSoure?: any[] | Object, valueKey?: string, labelKey?: string) => {
218
+ export const handleDataSource = (dataSource: any[], appendDataSoure?: any[] | Object, valueKey?: string, labelKey?: string,) => {
178
219
  const valueKeys: any = [];
179
220
  let newDataSoure: any[] = [];
180
221
  if (Array.isArray(dataSource)) {
@@ -182,7 +223,7 @@ export const handleDataSource = (dataSource: any[], appendDataSoure?: any[] | Ob
182
223
  const label = v?.[labelKey || 'label'];
183
224
  const value = v?.[valueKey || 'value'] || v?.key;
184
225
  if (value) {
185
- // TODO: 为什么 id 是数字就不行??
226
+ // 兼容源码逻辑
186
227
  valueKeys.push(`${value}`);
187
228
  newDataSoure.push({
188
229
  ...v,
@@ -194,7 +235,7 @@ export const handleDataSource = (dataSource: any[], appendDataSoure?: any[] | Ob
194
235
  }
195
236
  let newAppednDataSoure = [];
196
237
  if (Array.isArray(appendDataSoure) && appendDataSoure.length > 0) {
197
- newAppednDataSoure = appendDataSoure.filter((item) => !valueKeys?.includes(item?.[valueKey || 'value'] || item?.key));
238
+ newAppednDataSoure = appendDataSoure.filter(item => !valueKeys?.includes(item?.[valueKey || 'value'] || item?.key));
198
239
  }
199
240
  if (Object.prototype.toString.call(appendDataSoure) === '[object Object]') {
200
241
  newAppednDataSoure = [appendDataSoure].filter((item: any) => !valueKeys?.includes(item?.[valueKey || 'value'] || item?.key));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingxiteam/ebe-utils",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -19,7 +19,7 @@
19
19
  "@babel/types": "^7.12.12",
20
20
  "cac": "^6.7.14",
21
21
  "fs-extra": "9.x",
22
- "@lingxiteam/ebe": "0.4.0"
22
+ "@lingxiteam/ebe": "0.4.1"
23
23
  },
24
24
  "publishConfig": {
25
25
  "access": "public"