@douyinfe/semi-foundation 2.16.1 → 2.17.0-beta.0

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 (70) hide show
  1. package/collapse/collapse.scss +8 -0
  2. package/collapse/variables.scss +1 -0
  3. package/datePicker/constants.ts +1 -0
  4. package/datePicker/datePicker.scss +335 -17
  5. package/datePicker/foundation.ts +2 -0
  6. package/datePicker/monthsGridFoundation.ts +4 -1
  7. package/datePicker/rtl.scss +6 -6
  8. package/datePicker/variables.scss +58 -6
  9. package/datePicker/yearAndMonthFoundation.ts +4 -0
  10. package/lib/cjs/collapse/collapse.css +6 -0
  11. package/lib/cjs/collapse/collapse.scss +8 -0
  12. package/lib/cjs/collapse/variables.scss +1 -0
  13. package/lib/cjs/datePicker/constants.d.ts +1 -0
  14. package/lib/cjs/datePicker/constants.js +1 -0
  15. package/lib/cjs/datePicker/datePicker.css +267 -27
  16. package/lib/cjs/datePicker/datePicker.scss +335 -17
  17. package/lib/cjs/datePicker/foundation.d.ts +2 -0
  18. package/lib/cjs/datePicker/monthsGridFoundation.d.ts +5 -1
  19. package/lib/cjs/datePicker/rtl.scss +6 -6
  20. package/lib/cjs/datePicker/variables.scss +58 -6
  21. package/lib/cjs/datePicker/yearAndMonthFoundation.d.ts +5 -0
  22. package/lib/cjs/select/foundation.d.ts +11 -0
  23. package/lib/cjs/select/foundation.js +188 -44
  24. package/lib/cjs/select/select.css +5 -5
  25. package/lib/cjs/select/select.scss +9 -6
  26. package/lib/cjs/tagInput/foundation.d.ts +11 -0
  27. package/lib/cjs/tagInput/foundation.js +47 -1
  28. package/lib/cjs/tagInput/tagInput.css +11 -0
  29. package/lib/cjs/tagInput/tagInput.scss +17 -0
  30. package/lib/cjs/tagInput/variables.scss +2 -0
  31. package/lib/cjs/tooltip/foundation.js +13 -5
  32. package/lib/cjs/transfer/foundation.d.ts +0 -1
  33. package/lib/cjs/transfer/foundation.js +3 -11
  34. package/lib/cjs/utils/arrayMove.d.ts +1 -0
  35. package/lib/cjs/utils/arrayMove.js +21 -0
  36. package/lib/es/collapse/collapse.css +6 -0
  37. package/lib/es/collapse/collapse.scss +8 -0
  38. package/lib/es/collapse/variables.scss +1 -0
  39. package/lib/es/datePicker/constants.d.ts +1 -0
  40. package/lib/es/datePicker/constants.js +1 -0
  41. package/lib/es/datePicker/datePicker.css +267 -27
  42. package/lib/es/datePicker/datePicker.scss +335 -17
  43. package/lib/es/datePicker/foundation.d.ts +2 -0
  44. package/lib/es/datePicker/monthsGridFoundation.d.ts +5 -1
  45. package/lib/es/datePicker/rtl.scss +6 -6
  46. package/lib/es/datePicker/variables.scss +58 -6
  47. package/lib/es/datePicker/yearAndMonthFoundation.d.ts +5 -0
  48. package/lib/es/select/foundation.d.ts +11 -0
  49. package/lib/es/select/foundation.js +187 -44
  50. package/lib/es/select/select.css +5 -5
  51. package/lib/es/select/select.scss +9 -6
  52. package/lib/es/tagInput/foundation.d.ts +11 -0
  53. package/lib/es/tagInput/foundation.js +46 -1
  54. package/lib/es/tagInput/tagInput.css +11 -0
  55. package/lib/es/tagInput/tagInput.scss +17 -0
  56. package/lib/es/tagInput/variables.scss +2 -0
  57. package/lib/es/tooltip/foundation.js +13 -5
  58. package/lib/es/transfer/foundation.d.ts +0 -1
  59. package/lib/es/transfer/foundation.js +3 -12
  60. package/lib/es/utils/arrayMove.d.ts +1 -0
  61. package/lib/es/utils/arrayMove.js +9 -0
  62. package/package.json +2 -2
  63. package/select/foundation.ts +149 -36
  64. package/select/select.scss +9 -6
  65. package/tagInput/foundation.ts +39 -0
  66. package/tagInput/tagInput.scss +17 -0
  67. package/tagInput/variables.scss +2 -0
  68. package/tooltip/foundation.ts +8 -5
  69. package/transfer/foundation.ts +2 -6
  70. package/utils/arrayMove.ts +5 -0
@@ -7,11 +7,10 @@ import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/insta
7
7
  import _Map from "@babel/runtime-corejs3/core-js-stable/map";
8
8
  import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
9
9
  import _valuesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/values";
10
- import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
11
- import _spliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/splice";
12
10
  import BaseFoundation from '../base/foundation';
13
11
  import { strings } from './constants';
14
- import { _generateGroupedData, _generateTreeData } from './transferUtils'; // eslint-disable-next-line max-len
12
+ import { _generateGroupedData, _generateTreeData } from './transferUtils';
13
+ import arrayMove from '../utils/arrayMove'; // eslint-disable-next-line max-len
15
14
 
16
15
  export default class TransferFoundation extends BaseFoundation {
17
16
  constructor(adapter) {
@@ -275,7 +274,7 @@ export default class TransferFoundation extends BaseFoundation {
275
274
  const selectedItems = this._adapter.getSelected();
276
275
 
277
276
  let selectedArr = [..._valuesInstanceProperty(selectedItems).call(selectedItems)];
278
- selectedArr = this._arrayMove(selectedArr, oldIndex, newIndex);
277
+ selectedArr = arrayMove(selectedArr, oldIndex, newIndex);
279
278
  let newSelectedItems = new _Map();
280
279
 
281
280
  _forEachInstanceProperty(selectedArr).call(selectedArr, option => {
@@ -287,12 +286,4 @@ export default class TransferFoundation extends BaseFoundation {
287
286
  this._notifyChange(newSelectedItems);
288
287
  }
289
288
 
290
- _arrayMove(array, from, to) {
291
- const newArray = _sliceInstanceProperty(array).call(array);
292
-
293
- _spliceInstanceProperty(newArray).call(newArray, to < 0 ? newArray.length + to : to, 0, _spliceInstanceProperty(newArray).call(newArray, from, 1)[0]);
294
-
295
- return newArray;
296
- }
297
-
298
289
  }
@@ -0,0 +1 @@
1
+ export default function arrayMove(array: Array<any>, from: number, to: number): any[];
@@ -0,0 +1,9 @@
1
+ import _sliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/slice";
2
+ import _spliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/splice";
3
+ export default function arrayMove(array, from, to) {
4
+ const newArray = _sliceInstanceProperty(array).call(array);
5
+
6
+ _spliceInstanceProperty(newArray).call(newArray, to < 0 ? newArray.length + to : to, 0, _spliceInstanceProperty(newArray).call(newArray, from, 1)[0]);
7
+
8
+ return newArray;
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.16.1",
3
+ "version": "2.17.0-beta.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build:lib": "node ./scripts/compileLib.js",
@@ -24,7 +24,7 @@
24
24
  "*.scss",
25
25
  "*.css"
26
26
  ],
27
- "gitHead": "3de98e4072b5614d5e41e2ad65f687507563dc7c",
27
+ "gitHead": "471474bb6fe0a743bc3daba532279969cc9374a5",
28
28
  "devDependencies": {
29
29
  "@babel/plugin-proposal-decorators": "^7.15.8",
30
30
  "@babel/plugin-transform-runtime": "^7.15.8",
@@ -7,6 +7,7 @@ import warning from '../utils/warning';
7
7
  import isNullOrUndefined from '../utils/isNullOrUndefined';
8
8
  import { BasicOptionProps } from './optionFoundation';
9
9
  import isEnterPress from '../utils/isEnterPress';
10
+ import { handlePrevent } from '../utils/a11y';
10
11
 
11
12
  export interface SelectAdapter<P = Record<string, any>, S = Record<string, any>> extends DefaultAdapter<P, S> {
12
13
  getTriggerWidth(): number;
@@ -45,6 +46,11 @@ export interface SelectAdapter<P = Record<string, any>, S = Record<string, any>>
45
46
  notifyMouseEnter(event: any): void;
46
47
  updateHovering(isHover: boolean): void;
47
48
  updateScrollTop(index?: number): void;
49
+ getContainer(): any;
50
+ getFocusableElements(node: any): any[];
51
+ getActiveElement(): any;
52
+ setIsFocusInContainer(isFocusInContainer: boolean): void;
53
+ getIsFocusInContainer(): boolean;
48
54
  }
49
55
 
50
56
  type LabelValue = string | number;
@@ -77,11 +83,18 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
77
83
  }
78
84
 
79
85
  focus() {
80
- this._focusTrigger();
81
86
  const isFilterable = this._isFilterable();
87
+ const isMultiple = this._isMultiple();
82
88
  this._adapter.updateFocusState(true);
83
- if (isFilterable) {
89
+ this._adapter.setIsFocusInContainer(false);
90
+ if (isFilterable && isMultiple) {
91
+ // when filter and multiple, only focus input
92
+ this.focusInput();
93
+ } else if (isFilterable && !isMultiple){
94
+ // when filter and not multiple, only show input and focus input
84
95
  this.toggle2SearchInput(true);
96
+ } else {
97
+ this._focusTrigger();
85
98
  }
86
99
  }
87
100
 
@@ -92,7 +105,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
92
105
 
93
106
  destroy() {
94
107
  this._adapter.unregisterClickOutsideHandler();
95
- this.unBindKeyBoardEvent();
108
+ // this.unBindKeyBoardEvent();
96
109
  }
97
110
 
98
111
  _setDropdownWidth() {
@@ -337,6 +350,8 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
337
350
 
338
351
  this._adapter.registerClickOutsideHandler((e: MouseEvent) => {
339
352
  this.close(e);
353
+ this._notifyBlur(e);
354
+ this._adapter.updateFocusState(false);
340
355
  });
341
356
  }
342
357
 
@@ -344,24 +359,27 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
344
359
  if (isShow) {
345
360
  this._adapter.toggleInputShow(isShow, () => this.focusInput());
346
361
  } else {
362
+ // only when choose the option and close the panel, the input can be hide
347
363
  this._adapter.toggleInputShow(isShow, () => undefined);
348
364
  }
349
365
  }
350
366
 
351
367
  close(e?: any) {
368
+ // to support A11y, closing the panel trigger does not necessarily lose focus
352
369
  const isFilterable = this._isFilterable();
353
370
  if (isFilterable) {
354
- this.unBindKeyBoardEvent();
371
+ // this.unBindKeyBoardEvent();
355
372
  this.clearInput();
356
373
  this.toggle2SearchInput(false);
357
374
  }
358
375
 
359
376
  this._adapter.closeMenu();
360
377
  this._adapter.notifyDropdownVisibleChange(false);
361
- this.unBindKeyBoardEvent();
362
- this._notifyBlur(e);
378
+ this._adapter.setIsFocusInContainer(false);
379
+ // this.unBindKeyBoardEvent();
380
+ // this._notifyBlur(e);
363
381
  this._adapter.unregisterClickOutsideHandler();
364
- this._adapter.updateFocusState(false);
382
+ // this._adapter.updateFocusState(false);
365
383
  }
366
384
 
367
385
  onSelect(option: BasicOptionProps, optionIndex: number, event: MouseEvent | KeyboardEvent) {
@@ -378,6 +396,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
378
396
  const isMultiple = this._isMultiple();
379
397
  if (!isMultiple) {
380
398
  this._handleSingleSelect(option, event);
399
+ this._focusTrigger();
381
400
  } else {
382
401
  this._handleMultipleSelect(option, event);
383
402
  }
@@ -519,6 +538,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
519
538
  focusInput() {
520
539
  this._adapter.focusInput();
521
540
  this._adapter.updateFocusState(true);
541
+ this._adapter.setIsFocusInContainer(false);
522
542
  }
523
543
 
524
544
  handleInputChange(sugInput: string) {
@@ -636,9 +656,10 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
636
656
 
637
657
  _handleKeyDown(event: KeyboardEvent) {
638
658
  const key = event.keyCode;
659
+ const { loading, filter, multiple, disabled } = this.getProps();
639
660
  const { isOpen } = this.getStates();
640
- const { loading } = this.getProps();
641
- if (!isOpen || loading) {
661
+
662
+ if (loading || disabled) {
642
663
  return;
643
664
  }
644
665
  switch (key) {
@@ -660,13 +681,30 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
660
681
  case KeyCode.ENTER:
661
682
  // internal-issues:302
662
683
  // prevent trigger form’s submit when use in form
663
- event.preventDefault();
664
- event.stopPropagation();
684
+ handlePrevent(event);
665
685
  this._handleEnterKeyDown(event);
666
686
  break;
667
687
  case KeyCode.ESC:
688
+ isOpen && this.close(event);
689
+ filter && !multiple && this._focusTrigger();
690
+ break;
691
+ case KeyCode.TAB:
692
+ // check if slot have focusable element
693
+ this._handleTabKeyDown(event);
694
+ break;
695
+ default:
696
+ break;
697
+ }
698
+ }
699
+
700
+ handleContainerKeyDown(event: any) {
701
+ // when focus in contanier, handle the key down
702
+ const key = event.keyCode;
703
+ const { isOpen } = this.getStates();
704
+
705
+ switch (key) {
668
706
  case KeyCode.TAB:
669
- this.close(event);
707
+ isOpen && this._handleTabKeyDown(event);
670
708
  break;
671
709
  default:
672
710
  break;
@@ -717,26 +755,91 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
717
755
  }
718
756
 
719
757
  _handleArrowKeyDown(offset: number) {
720
- this._getEnableFocusIndex(offset);
758
+ const { isOpen } = this.getStates();
759
+ isOpen ? this._getEnableFocusIndex(offset) : this.open();
760
+ }
761
+
762
+ _handleTabKeyDown(event: any){
763
+ const { isOpen } = this.getStates();
764
+ this._adapter.updateFocusState(false);
765
+
766
+ if (isOpen){
767
+ const container = this._adapter.getContainer();
768
+ const focusableElements = this._adapter.getFocusableElements(container);
769
+ const focusableNum = focusableElements.length;
770
+
771
+ if (focusableNum > 0){
772
+ // Shift + Tab will move focus backward
773
+ if (event.shiftKey) {
774
+ this._handlePanelOpenShiftTabKeyDown(focusableElements, event);
775
+ } else {
776
+ this._handlePanelOpenTabKeyDown(focusableElements, event);
777
+ }
778
+ } else {
779
+ // there are no focusable elements inside the container, tab to next element and trigger blur
780
+ this.close();
781
+ this._notifyBlur(event);
782
+ }
783
+ } else {
784
+ // tab or shift tab to next element and trigger blur
785
+ this._notifyBlur(event);
786
+ }
787
+ }
788
+
789
+ _handlePanelOpenTabKeyDown(focusableElements: any[], event: any) {
790
+ const activeElement = this._adapter.getActiveElement();
791
+ const isFocusInContainer = this._adapter.getIsFocusInContainer();
792
+ if (!isFocusInContainer){
793
+ // focus in trigger, set next focus to the first element in container
794
+ focusableElements[0].focus();
795
+ this._adapter.setIsFocusInContainer(true);
796
+ handlePrevent(event);
797
+ } else if (activeElement === focusableElements[focusableElements.length - 1]) {
798
+ // focus in the last element in container, focus back to trigger and close panel
799
+ this._focusTrigger();
800
+ this.close();
801
+ handlePrevent(event);
802
+ }
803
+ }
804
+
805
+ _handlePanelOpenShiftTabKeyDown(focusableElements: any[], event: any) {
806
+ const activeElement = this._adapter.getActiveElement();
807
+ const isFocusInContainer = this._adapter.getIsFocusInContainer();
808
+
809
+ if (!isFocusInContainer) {
810
+ // focus in trigger, close the panel, shift tab to previe element and trigger blur
811
+ this.close();
812
+ this._notifyBlur(event);
813
+ } else if (activeElement === focusableElements[0]) {
814
+ // focus in the first element in container, focus back to trigger
815
+ this._focusTrigger();
816
+ this._adapter.setIsFocusInContainer(false);
817
+ handlePrevent(event);
818
+ }
721
819
  }
722
820
 
723
821
  _handleEnterKeyDown(event: KeyboardEvent) {
724
822
  const { isOpen, options, focusIndex } = this.getStates();
725
- if (focusIndex !== -1) {
726
- const visibleOptions = options.filter((item: BasicOptionProps) => item._show);
727
- const { length } = visibleOptions;
728
- // fix issue 1201
729
- if (length <= focusIndex) {
730
- return;
731
- }
732
- if (visibleOptions && length) {
733
- const selectedOption = visibleOptions[focusIndex];
734
- if (selectedOption.disabled) {
823
+ if (!isOpen){
824
+ this.open();
825
+ } else {
826
+ if (focusIndex !== -1) {
827
+ const visibleOptions = options.filter((item: BasicOptionProps) => item._show);
828
+ const { length } = visibleOptions;
829
+ // fix issue 1201
830
+ if (length <= focusIndex) {
735
831
  return;
736
832
  }
737
- this.onSelect(selectedOption, focusIndex, event);
833
+ if (visibleOptions && length) {
834
+ const selectedOption = visibleOptions[focusIndex];
835
+ if (selectedOption.disabled) {
836
+ return;
837
+ }
838
+ this.onSelect(selectedOption, focusIndex, event);
839
+ }
840
+ } else {
841
+ this.close();
738
842
  }
739
- } else if (isOpen) {
740
843
  }
741
844
  }
742
845
 
@@ -856,15 +959,16 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
856
959
  }
857
960
 
858
961
  // Scenes that may trigger blur:
859
- // 1、clickOutSide
860
- // 2、click option / press enter, and then select complete(when multiple is false
861
- // 3、press esc when dropdown list open
962
+ // 1、clickOutSide
963
+ // 2、 tab to next element/ shift tab to previous element
964
+ // 3、[remove when add a11y] click option / press enter, and then select complete(when multiple is false
965
+ // 4、[remove when add a11y] press esc when dropdown list open
862
966
  _notifyBlur(e: FocusEvent) {
863
967
  this._adapter.notifyBlur(e);
864
968
  }
865
969
 
866
970
  // Scenes that may trigger focus:
867
- // 1、click selection
971
+ // 1、click selection
868
972
  _notifyFocus(e: FocusEvent) {
869
973
  this._adapter.notifyFocus(e);
870
974
  }
@@ -910,23 +1014,32 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
910
1014
  this._adapter.notifyListScroll(e);
911
1015
  }
912
1016
 
913
- // handleTriggerFocus(e) {
914
- // console.log('handleTriggerFocus');
915
- // this._adapter.updateFocusState(true);
916
- // }
1017
+ handleTriggerFocus(e) {
1018
+ this.bindKeyBoardEvent();
1019
+ this._adapter.updateFocusState(true);
1020
+ this._adapter.setIsFocusInContainer(false);
1021
+ }
917
1022
 
918
1023
  handleTriggerBlur(e: FocusEvent) {
919
1024
  this._adapter.updateFocusState(false);
920
1025
  const { filter, autoFocus } = this.getProps();
921
1026
  const { isOpen, isFocus } = this.getStates();
922
- // Under normal circumstances, blur will be accompanied by dropdown close, so the notify of blur can be called uniformly in close
923
- // But when autoFocus, because dropdown is not expanded, you need to listen for the trigger's blur and trigger the notify callback
1027
+ // Under normal circumstances, blur will be accompanied by clickOutsideHandler, so the notify of blur can be called uniformly in clickOutsideHandler
1028
+ // But when autoFocus, because clickOutsideHandler is not register, you need to listen for the trigger's blur and trigger the notify callback
924
1029
  if (autoFocus && isFocus && !isOpen) {
925
- // blur when autoFocus & not open dropdown yet
926
1030
  this._notifyBlur(e);
927
1031
  }
928
1032
  }
929
1033
 
1034
+ handleInputBlur(e: any) {
1035
+ const { filter, autoFocus } = this.getProps();
1036
+ const isMultiple = this._isMultiple();
1037
+ if (autoFocus && filter && !isMultiple ) {
1038
+ // under this condition, when input blur, hide the input
1039
+ this.toggle2SearchInput(false);
1040
+ }
1041
+ }
1042
+
930
1043
  selectAll() {
931
1044
  const { options } = this.getStates();
932
1045
  const { onChangeWithObject } = this.getProps();
@@ -27,11 +27,6 @@ $multiple: #{$module}-multiple;
27
27
  border: $width-select-border-hover solid $color-select-border-hover;
28
28
  }
29
29
 
30
- &:active {
31
- background-color: $color-select-bg-active;
32
- border: $width-select-border-active solid $color-select-border-active;
33
- }
34
-
35
30
  &:focus {
36
31
  border: $width-select-border-focus solid $color-select-border-focus;
37
32
  outline: 0;
@@ -59,6 +54,12 @@ $multiple: #{$module}-multiple;
59
54
  background-color: $color-select-bg-default;
60
55
  border: $border-thickness-control-focus solid $color-select_default-border-focus;
61
56
  }
57
+
58
+ // when click the trigger, trigger get the focus state, active style should take effect
59
+ &:active {
60
+ background-color: $color-select-bg-active;
61
+ border: $width-select-border-active solid $color-select-border-active;
62
+ }
62
63
  }
63
64
 
64
65
  &-warning {
@@ -111,7 +112,9 @@ $multiple: #{$module}-multiple;
111
112
  }
112
113
 
113
114
  &:focus {
114
- border: $border-thickness-control-focus solid $color-select_default-border-focus;
115
+ // border: $border-thickness-control-focus solid $color-select_default-border-focus;
116
+ // when select is disabled, the border should not have active color
117
+ border: $border-thickness-control-focus solid transparent;
115
118
  }
116
119
 
117
120
  .#{$module}-selection,
@@ -8,18 +8,28 @@ import {
8
8
  } from 'lodash';
9
9
  import getSplitedArray from './utils/getSplitedArray';
10
10
  import isEnterPress from '../utils/isEnterPress';
11
+ import arrayMove from '../utils/arrayMove';
11
12
 
12
13
  export type TagInputChangeEvent = any;
13
14
  export type TagInputCursorEvent = any;
14
15
  export type TagInputKeyboardEvent = any;
15
16
  export type TagInputMouseEvent = any;
16
17
 
18
+ export interface OnSortEndProps {
19
+ oldIndex: number;
20
+ newIndex: number;
21
+ }
22
+
17
23
  export interface TagInputAdapter extends DefaultAdapter {
18
24
  setInputValue: (inputValue: string) => void;
19
25
  setTagsArray: (tagsArray: string[]) => void;
20
26
  setFocusing: (focusing: boolean) => void;
21
27
  toggleFocusing(focused: boolean): void;
22
28
  setHovering: (hovering: boolean) => void;
29
+ setActive: (active: boolean) => void;
30
+ getClickOutsideHandler: () => any;
31
+ registerClickOutsideHandler: (cb: any) => void;
32
+ unregisterClickOutsideHandler: () => void;
23
33
  notifyBlur: (e: TagInputCursorEvent) => void;
24
34
  notifyFocus: (e: TagInputCursorEvent) => void;
25
35
  notifyInputChange: (v: string, e: TagInputChangeEvent) => void;
@@ -167,6 +177,8 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
167
177
  if (inputValue.length > 0) {
168
178
  this._onInputChange('', e);
169
179
  }
180
+ // Prevent event propagate to TagInput outermost div
181
+ e.stopPropagation();
170
182
  }
171
183
 
172
184
  handleTagClose(index: number) {
@@ -185,6 +197,23 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
185
197
  this._adapter.setHovering(false);
186
198
  }
187
199
 
200
+ handleClick(e?: any) {
201
+ const { disabled } = this.getProps();
202
+ if (disabled) {
203
+ return;
204
+ }
205
+ const clickOutsideHandler = this._adapter.getClickOutsideHandler();
206
+ if (!clickOutsideHandler) {
207
+ this._adapter.setActive(true);
208
+ this._adapter.registerClickOutsideHandler(e => this.clickOutsideCallBack());
209
+ }
210
+ }
211
+
212
+ clickOutsideCallBack() {
213
+ this._adapter.unregisterClickOutsideHandler();
214
+ this._adapter.setActive(false);
215
+ }
216
+
188
217
  handleClickPrefixOrSuffix(e: any) {
189
218
  const { disabled } = this._adapter.getProps();
190
219
  const { isFocus } = this._adapter.getStates();
@@ -227,6 +256,16 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
227
256
  this._adapter.setInputValue(value);
228
257
  this._adapter.notifyInputChange(value, e);
229
258
  }
259
+
260
+ handleSortEnd(callbackProps: OnSortEndProps) {
261
+ const { oldIndex, newIndex } = callbackProps;
262
+ const { tagsArray } = this.getStates();
263
+ const newTagsArray = arrayMove(tagsArray, oldIndex, newIndex);
264
+ if (!this._isControlledComponent()) {
265
+ this._adapter.setTagsArray(newTagsArray);
266
+ }
267
+ this._adapter.notifyTagChange(newTagsArray);
268
+ }
230
269
  }
231
270
 
232
271
  export default TagInputFoundation;
@@ -11,6 +11,19 @@ $module: #{$prefix}-tagInput;
11
11
  width: 100%;
12
12
  box-sizing: border-box;
13
13
 
14
+ &-drag {
15
+
16
+ &-item {
17
+ display: flex;
18
+ align-items: center;
19
+ }
20
+
21
+ &-handler {
22
+ margin-right: $spacing-tagInput_drag_handler-marginRight;
23
+ cursor: move;
24
+ }
25
+ }
26
+
14
27
  &-hover {
15
28
  background-color: $color-tagInput_default-bg-hover;
16
29
  border: $width-tagInput-border-hover $color-tagInput-border-hover solid;
@@ -104,6 +117,10 @@ $module: #{$prefix}-tagInput;
104
117
  margin-bottom: $spacing-tagInput_large-Y;
105
118
  }
106
119
  }
120
+
121
+ &-icon {
122
+ padding-left: $spacing-tagInput_tag_icon_paddingLeft;
123
+ }
107
124
  }
108
125
 
109
126
  &-typo {
@@ -32,6 +32,8 @@ $spacing-tagInput_small-Y: 1px; // 小尺寸标签输入框标签顶部外边距
32
32
  $spacing-tagInput_default-Y: $spacing-super-tight; // 默认尺寸标签输入框标签顶部外边距
33
33
  $spacing-tagInput_large-Y: 3px; // 大尺寸标签输入框标签顶部外边距
34
34
  $spacing-tagInput_wrapper_n_paddingX: $spacing-tight; //标签输入框标签容器水平内边距
35
+ $spacing-tagInput_drag_handler-marginRight: 4px; // 拖拽handler icon的右外边距
36
+ $spacing-tagInput_tag_icon_paddingLeft: 4px; // tag中有handler icon时tag的左内边距
35
37
 
36
38
  $height-tagInput-large: $height-control-large; // 大尺寸标签输入框高度
37
39
  $height-tagInput-default: $height-control-default; // 默认尺寸标签输入框高度
@@ -206,10 +206,12 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
206
206
  };
207
207
  // bind focus to hover trigger for a11y
208
208
  triggerEventSet[eventNames.focus] = () => {
209
- this.delayShow();
209
+ const { disableFocusListener } = this.getProps();
210
+ !disableFocusListener && this.delayShow();
210
211
  };
211
212
  triggerEventSet[eventNames.blur] = () => {
212
- this.delayHide();
213
+ const { disableFocusListener } = this.getProps();
214
+ !disableFocusListener && this.delayHide();
213
215
  };
214
216
 
215
217
  portalEventSet = { ...triggerEventSet };
@@ -856,7 +858,7 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
856
858
  }
857
859
 
858
860
  _handleTriggerKeydown(event: any) {
859
- const { closeOnEsc } = this.getProps();
861
+ const { closeOnEsc, disableArrowKeyDown } = this.getProps();
860
862
  const container = this._adapter.getContainer();
861
863
  const focusableElements = this._adapter.getFocusableElements(container);
862
864
  const focusableNum = focusableElements.length;
@@ -867,10 +869,11 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
867
869
  closeOnEsc && this._handleEscKeyDown(event);
868
870
  break;
869
871
  case "ArrowUp":
870
- focusableNum && this._handleTriggerArrowUpKeydown(focusableElements, event);
872
+ // when disableArrowKeyDown is true, disable tooltip's arrow keyboard event action
873
+ !disableArrowKeyDown && focusableNum && this._handleTriggerArrowUpKeydown(focusableElements, event);
871
874
  break;
872
875
  case "ArrowDown":
873
- focusableNum && this._handleTriggerArrowDownKeydown(focusableElements, event);
876
+ !disableArrowKeyDown && focusableNum && this._handleTriggerArrowDownKeydown(focusableElements, event);
874
877
  break;
875
878
  default:
876
879
  break;
@@ -3,6 +3,7 @@ import BaseFoundation, { DefaultAdapter } from '../base/foundation';
3
3
  import { BasicValue as BasicTreeValue } from '../tree/foundation';
4
4
  import { strings } from './constants';
5
5
  import { _generateGroupedData, _generateTreeData } from './transferUtils';
6
+ import arrayMove from '../utils/arrayMove';
6
7
 
7
8
  export interface BasicDataItem {
8
9
  [x: string]: any;
@@ -217,7 +218,7 @@ export default class TransferFoundation<P = Record<string, any>, S = Record<stri
217
218
  const { oldIndex, newIndex } = callbackProps;
218
219
  const selectedItems = this._adapter.getSelected();
219
220
  let selectedArr = [...selectedItems.values()];
220
- selectedArr = this._arrayMove(selectedArr, oldIndex, newIndex);
221
+ selectedArr = arrayMove(selectedArr, oldIndex, newIndex);
221
222
  let newSelectedItems = new Map();
222
223
  selectedArr.forEach(option => {
223
224
  newSelectedItems = newSelectedItems.set(option.key, option);
@@ -226,9 +227,4 @@ export default class TransferFoundation<P = Record<string, any>, S = Record<stri
226
227
  this._notifyChange(newSelectedItems);
227
228
  }
228
229
 
229
- _arrayMove(array: Array<BasicDataItem>, from: number, to: number) {
230
- const newArray = array.slice();
231
- newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);
232
- return newArray;
233
- }
234
230
  }
@@ -0,0 +1,5 @@
1
+ export default function arrayMove(array: Array<any>, from: number, to: number) {
2
+ const newArray = array.slice();
3
+ newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);
4
+ return newArray;
5
+ }