@douyinfe/semi-foundation 2.43.0-alpha.0 → 2.43.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.
@@ -395,7 +395,6 @@ $module: #{$prefix}-cascader;
395
395
  padding-right: $spacing-cascader_option-paddingRight;
396
396
  }
397
397
 
398
-
399
398
  .#{$module}-option-list {
400
399
  box-sizing: border-box;
401
400
  display: inline-block;
@@ -28,12 +28,6 @@ export interface BasicData {
28
28
  pathData?: BasicCascaderData[]
29
29
  }
30
30
 
31
- export interface Virtualize {
32
- itemSize: number;
33
- height?: number | string;
34
- width?: number | string
35
- }
36
-
37
31
  export interface BasicEntities {
38
32
  [idx: string]: BasicEntity
39
33
  }
@@ -163,7 +157,6 @@ export interface BasicCascaderProps {
163
157
  leafOnly?: boolean;
164
158
  enableLeafClick?: boolean;
165
159
  preventScroll?: boolean;
166
- virtualizeInSearch?: Virtualize;
167
160
  onClear?: () => void;
168
161
  triggerRender?: (props: BasicTriggerRenderProps) => any;
169
162
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -395,7 +395,6 @@ $module: #{$prefix}-cascader;
395
395
  padding-right: $spacing-cascader_option-paddingRight;
396
396
  }
397
397
 
398
-
399
398
  .#{$module}-option-list {
400
399
  box-sizing: border-box;
401
400
  display: inline-block;
@@ -6,11 +6,6 @@ export interface BasicData {
6
6
  searchText: any[];
7
7
  pathData?: BasicCascaderData[];
8
8
  }
9
- export interface Virtualize {
10
- itemSize: number;
11
- height?: number | string;
12
- width?: number | string;
13
- }
14
9
  export interface BasicEntities {
15
10
  [idx: string]: BasicEntity;
16
11
  }
@@ -110,7 +105,6 @@ export interface BasicCascaderProps {
110
105
  leafOnly?: boolean;
111
106
  enableLeafClick?: boolean;
112
107
  preventScroll?: boolean;
113
- virtualizeInSearch?: Virtualize;
114
108
  onClear?: () => void;
115
109
  triggerRender?: (props: BasicTriggerRenderProps) => any;
116
110
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -41,10 +41,15 @@ class TagInputFoundation extends _foundation.default {
41
41
  }
42
42
  };
43
43
  this.handleInputCompositionStart = e => {
44
+ const {
45
+ maxLength
46
+ } = this.getProps();
47
+ if (!(0, _isNumber2.default)(maxLength)) {
48
+ return;
49
+ }
44
50
  this._adapter.setEntering(true);
45
51
  };
46
52
  this.handleInputCompositionEnd = e => {
47
- this._adapter.setEntering(false);
48
53
  const {
49
54
  value
50
55
  } = e.target;
@@ -53,27 +58,31 @@ class TagInputFoundation extends _foundation.default {
53
58
  onInputExceed,
54
59
  separator
55
60
  } = this.getProps();
61
+ if (!(0, _isNumber2.default)(maxLength)) {
62
+ return;
63
+ }
64
+ this._adapter.setEntering(false);
56
65
  let allowChange = true;
57
- const {
58
- inputValue
59
- } = this.getStates();
60
- if ((0, _isNumber2.default)(maxLength)) {
61
- const inputArr = (0, _getSplitedArray.default)(inputValue, separator);
62
- let index = 0;
63
- for (; index < inputArr.length; index++) {
64
- if (inputArr[index].length > maxLength) {
65
- allowChange = false;
66
- (0, _isFunction2.default)(onInputExceed) && onInputExceed(value);
67
- break;
68
- }
66
+ const inputArr = (0, _getSplitedArray.default)(value, separator);
67
+ let index = 0;
68
+ for (; index < inputArr.length; index++) {
69
+ if (inputArr[index].length > maxLength) {
70
+ allowChange = false;
71
+ (0, _isFunction2.default)(onInputExceed) && onInputExceed(value);
72
+ break;
69
73
  }
70
- if (!allowChange) {
71
- const newInputArr = inputArr.slice(0, index);
72
- if (index < inputArr.length) {
73
- newInputArr.push(inputArr[index].slice(0, maxLength));
74
- }
75
- this._adapter.setInputValue(newInputArr.join(separator));
74
+ }
75
+ if (!allowChange) {
76
+ const newInputArr = inputArr.slice(0, index);
77
+ if (index < inputArr.length) {
78
+ newInputArr.push(inputArr[index].slice(0, maxLength));
76
79
  }
80
+ this._adapter.setInputValue(newInputArr.join(separator));
81
+ } else {
82
+ // Why does it need to be updated here instead of in onChange when the value meets the maxLength limit?
83
+ // Because in firefox, the state change in InputCompositionEnd causes onChange to not be triggered after
84
+ // the composition input completes input.
85
+ this._adapter.setInputValue(value);
77
86
  }
78
87
  };
79
88
  /**
@@ -111,6 +111,8 @@ export interface BasicRenderFullLabelProps {
111
111
  expanded: boolean;
112
112
  loading: boolean;
113
113
  };
114
+ filtered: boolean | undefined;
115
+ searchWord: string | undefined;
114
116
  }
115
117
  export interface BasicSearchRenderProps {
116
118
  className: string;
@@ -73,9 +73,14 @@ export interface UploadAdapter<P = Record<string, any>, S = Record<string, any>>
73
73
  notifyPreviewClick: (file: any) => void;
74
74
  notifyDrop: (e: any, files: Array<File>, fileList: Array<BaseFileItem>) => void;
75
75
  notifyAcceptInvalid: (invalidFiles: Array<File>) => void;
76
+ registerPastingHandler: (cb?: (params?: any) => void) => void;
77
+ unRegisterPastingHandler: () => void;
78
+ isMac: () => boolean;
79
+ notifyPastingError: (error: Error | PermissionStatus) => void;
76
80
  }
77
81
  declare class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<UploadAdapter<P, S>, P, S> {
78
82
  constructor(adapter: UploadAdapter<P, S>);
83
+ init(): void;
79
84
  destroy(): void;
80
85
  getError({ action, xhr, message, fileName }: {
81
86
  action: string;
@@ -163,5 +168,9 @@ declare class UploadFoundation<P = Record<string, any>, S = Record<string, any>>
163
168
  checkFileFormat(accept: string, file: File): boolean;
164
169
  retry(fileItem: BaseFileItem): void;
165
170
  handlePreviewClick(fileItem: BaseFileItem): void;
171
+ readFileFromClipboard(clipboardItems: any): void;
172
+ handlePasting(e: any): void;
173
+ bindPastingHandler(): void;
174
+ unbindPastingHandler(): void;
166
175
  }
167
176
  export default UploadFoundation;
@@ -51,8 +51,24 @@ class UploadFoundation extends _foundation.default {
51
51
  constructor(adapter) {
52
52
  super(Object.assign({}, adapter));
53
53
  }
54
+ init() {
55
+ const {
56
+ disabled,
57
+ addOnPasting
58
+ } = this.getProps();
59
+ if (addOnPasting && !disabled) {
60
+ this.bindPastingHandler();
61
+ }
62
+ }
54
63
  destroy() {
64
+ const {
65
+ disabled,
66
+ addOnPasting
67
+ } = this.getProps();
55
68
  this.releaseMemory();
69
+ if (addOnPasting && !disabled) {
70
+ this.unbindPastingHandler();
71
+ }
56
72
  }
57
73
  getError(_ref) {
58
74
  let {
@@ -912,6 +928,56 @@ class UploadFoundation extends _foundation.default {
912
928
  handlePreviewClick(fileItem) {
913
929
  this._adapter.notifyPreviewClick(fileItem);
914
930
  }
931
+ readFileFromClipboard(clipboardItems) {
932
+ for (const clipboardItem of clipboardItems) {
933
+ for (const type of clipboardItem.types) {
934
+ // types maybe: text/plain, image/png, text/html
935
+ if (type.startsWith('image')) {
936
+ clipboardItem.getType(type).then(blob => {
937
+ return blob.arrayBuffer();
938
+ }).then(buffer => {
939
+ const format = type.split('/')[1];
940
+ const file = new File([buffer], `upload.${format}`, {
941
+ type
942
+ });
943
+ this.handleChange([file]);
944
+ });
945
+ }
946
+ }
947
+ }
948
+ }
949
+ handlePasting(e) {
950
+ const isMac = this._adapter.isMac();
951
+ const isCombineKeydown = isMac ? e.metaKey : e.ctrlKey;
952
+ if (isCombineKeydown && e.code === 'KeyV' && e.target === document.body) {
953
+ // https://github.com/microsoft/TypeScript/issues/33923
954
+ const permissionName = "clipboard-read";
955
+ // The main thread should not be blocked by clipboard, so callback writing is required here. No await here
956
+ navigator.permissions.query({
957
+ name: permissionName
958
+ }).then(result => {
959
+ console.log(result);
960
+ if (result.state === 'granted' || result.state === 'prompt') {
961
+ // user has authorized or will authorize
962
+ navigator.clipboard.read().then(clipboardItems => {
963
+ // Process the data read from the pasteboard
964
+ // Check the returned data type to determine if it is image data, and process accordingly
965
+ this.readFileFromClipboard(clipboardItems);
966
+ });
967
+ } else {
968
+ this._adapter.notifyPastingError(result);
969
+ }
970
+ }).catch(error => {
971
+ this._adapter.notifyPastingError(error);
972
+ });
973
+ }
974
+ }
975
+ bindPastingHandler() {
976
+ this._adapter.registerPastingHandler(event => this.handlePasting(event));
977
+ }
978
+ unbindPastingHandler() {
979
+ this._adapter.unRegisterPastingHandler();
980
+ }
915
981
  }
916
982
  var _default = UploadFoundation;
917
983
  exports.default = _default;
@@ -395,7 +395,6 @@ $module: #{$prefix}-cascader;
395
395
  padding-right: $spacing-cascader_option-paddingRight;
396
396
  }
397
397
 
398
-
399
398
  .#{$module}-option-list {
400
399
  box-sizing: border-box;
401
400
  display: inline-block;
@@ -6,11 +6,6 @@ export interface BasicData {
6
6
  searchText: any[];
7
7
  pathData?: BasicCascaderData[];
8
8
  }
9
- export interface Virtualize {
10
- itemSize: number;
11
- height?: number | string;
12
- width?: number | string;
13
- }
14
9
  export interface BasicEntities {
15
10
  [idx: string]: BasicEntity;
16
11
  }
@@ -110,7 +105,6 @@ export interface BasicCascaderProps {
110
105
  leafOnly?: boolean;
111
106
  enableLeafClick?: boolean;
112
107
  preventScroll?: boolean;
113
- virtualizeInSearch?: Virtualize;
114
108
  onClear?: () => void;
115
109
  triggerRender?: (props: BasicTriggerRenderProps) => any;
116
110
  onListScroll?: (e: any, panel: BasicScrollPanelProps) => void;
@@ -34,10 +34,15 @@ class TagInputFoundation extends BaseFoundation {
34
34
  }
35
35
  };
36
36
  this.handleInputCompositionStart = e => {
37
+ const {
38
+ maxLength
39
+ } = this.getProps();
40
+ if (!_isNumber(maxLength)) {
41
+ return;
42
+ }
37
43
  this._adapter.setEntering(true);
38
44
  };
39
45
  this.handleInputCompositionEnd = e => {
40
- this._adapter.setEntering(false);
41
46
  const {
42
47
  value
43
48
  } = e.target;
@@ -46,27 +51,31 @@ class TagInputFoundation extends BaseFoundation {
46
51
  onInputExceed,
47
52
  separator
48
53
  } = this.getProps();
54
+ if (!_isNumber(maxLength)) {
55
+ return;
56
+ }
57
+ this._adapter.setEntering(false);
49
58
  let allowChange = true;
50
- const {
51
- inputValue
52
- } = this.getStates();
53
- if (_isNumber(maxLength)) {
54
- const inputArr = getSplitedArray(inputValue, separator);
55
- let index = 0;
56
- for (; index < inputArr.length; index++) {
57
- if (inputArr[index].length > maxLength) {
58
- allowChange = false;
59
- _isFunction(onInputExceed) && onInputExceed(value);
60
- break;
61
- }
59
+ const inputArr = getSplitedArray(value, separator);
60
+ let index = 0;
61
+ for (; index < inputArr.length; index++) {
62
+ if (inputArr[index].length > maxLength) {
63
+ allowChange = false;
64
+ _isFunction(onInputExceed) && onInputExceed(value);
65
+ break;
62
66
  }
63
- if (!allowChange) {
64
- const newInputArr = inputArr.slice(0, index);
65
- if (index < inputArr.length) {
66
- newInputArr.push(inputArr[index].slice(0, maxLength));
67
- }
68
- this._adapter.setInputValue(newInputArr.join(separator));
67
+ }
68
+ if (!allowChange) {
69
+ const newInputArr = inputArr.slice(0, index);
70
+ if (index < inputArr.length) {
71
+ newInputArr.push(inputArr[index].slice(0, maxLength));
69
72
  }
73
+ this._adapter.setInputValue(newInputArr.join(separator));
74
+ } else {
75
+ // Why does it need to be updated here instead of in onChange when the value meets the maxLength limit?
76
+ // Because in firefox, the state change in InputCompositionEnd causes onChange to not be triggered after
77
+ // the composition input completes input.
78
+ this._adapter.setInputValue(value);
70
79
  }
71
80
  };
72
81
  /**
@@ -111,6 +111,8 @@ export interface BasicRenderFullLabelProps {
111
111
  expanded: boolean;
112
112
  loading: boolean;
113
113
  };
114
+ filtered: boolean | undefined;
115
+ searchWord: string | undefined;
114
116
  }
115
117
  export interface BasicSearchRenderProps {
116
118
  className: string;
@@ -73,9 +73,14 @@ export interface UploadAdapter<P = Record<string, any>, S = Record<string, any>>
73
73
  notifyPreviewClick: (file: any) => void;
74
74
  notifyDrop: (e: any, files: Array<File>, fileList: Array<BaseFileItem>) => void;
75
75
  notifyAcceptInvalid: (invalidFiles: Array<File>) => void;
76
+ registerPastingHandler: (cb?: (params?: any) => void) => void;
77
+ unRegisterPastingHandler: () => void;
78
+ isMac: () => boolean;
79
+ notifyPastingError: (error: Error | PermissionStatus) => void;
76
80
  }
77
81
  declare class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<UploadAdapter<P, S>, P, S> {
78
82
  constructor(adapter: UploadAdapter<P, S>);
83
+ init(): void;
79
84
  destroy(): void;
80
85
  getError({ action, xhr, message, fileName }: {
81
86
  action: string;
@@ -163,5 +168,9 @@ declare class UploadFoundation<P = Record<string, any>, S = Record<string, any>>
163
168
  checkFileFormat(accept: string, file: File): boolean;
164
169
  retry(fileItem: BaseFileItem): void;
165
170
  handlePreviewClick(fileItem: BaseFileItem): void;
171
+ readFileFromClipboard(clipboardItems: any): void;
172
+ handlePasting(e: any): void;
173
+ bindPastingHandler(): void;
174
+ unbindPastingHandler(): void;
166
175
  }
167
176
  export default UploadFoundation;
@@ -44,8 +44,24 @@ class UploadFoundation extends BaseFoundation {
44
44
  constructor(adapter) {
45
45
  super(Object.assign({}, adapter));
46
46
  }
47
+ init() {
48
+ const {
49
+ disabled,
50
+ addOnPasting
51
+ } = this.getProps();
52
+ if (addOnPasting && !disabled) {
53
+ this.bindPastingHandler();
54
+ }
55
+ }
47
56
  destroy() {
57
+ const {
58
+ disabled,
59
+ addOnPasting
60
+ } = this.getProps();
48
61
  this.releaseMemory();
62
+ if (addOnPasting && !disabled) {
63
+ this.unbindPastingHandler();
64
+ }
49
65
  }
50
66
  getError(_ref) {
51
67
  let {
@@ -905,5 +921,55 @@ class UploadFoundation extends BaseFoundation {
905
921
  handlePreviewClick(fileItem) {
906
922
  this._adapter.notifyPreviewClick(fileItem);
907
923
  }
924
+ readFileFromClipboard(clipboardItems) {
925
+ for (const clipboardItem of clipboardItems) {
926
+ for (const type of clipboardItem.types) {
927
+ // types maybe: text/plain, image/png, text/html
928
+ if (type.startsWith('image')) {
929
+ clipboardItem.getType(type).then(blob => {
930
+ return blob.arrayBuffer();
931
+ }).then(buffer => {
932
+ const format = type.split('/')[1];
933
+ const file = new File([buffer], `upload.${format}`, {
934
+ type
935
+ });
936
+ this.handleChange([file]);
937
+ });
938
+ }
939
+ }
940
+ }
941
+ }
942
+ handlePasting(e) {
943
+ const isMac = this._adapter.isMac();
944
+ const isCombineKeydown = isMac ? e.metaKey : e.ctrlKey;
945
+ if (isCombineKeydown && e.code === 'KeyV' && e.target === document.body) {
946
+ // https://github.com/microsoft/TypeScript/issues/33923
947
+ const permissionName = "clipboard-read";
948
+ // The main thread should not be blocked by clipboard, so callback writing is required here. No await here
949
+ navigator.permissions.query({
950
+ name: permissionName
951
+ }).then(result => {
952
+ console.log(result);
953
+ if (result.state === 'granted' || result.state === 'prompt') {
954
+ // user has authorized or will authorize
955
+ navigator.clipboard.read().then(clipboardItems => {
956
+ // Process the data read from the pasteboard
957
+ // Check the returned data type to determine if it is image data, and process accordingly
958
+ this.readFileFromClipboard(clipboardItems);
959
+ });
960
+ } else {
961
+ this._adapter.notifyPastingError(result);
962
+ }
963
+ }).catch(error => {
964
+ this._adapter.notifyPastingError(error);
965
+ });
966
+ }
967
+ }
968
+ bindPastingHandler() {
969
+ this._adapter.registerPastingHandler(event => this.handlePasting(event));
970
+ }
971
+ unbindPastingHandler() {
972
+ this._adapter.unRegisterPastingHandler();
973
+ }
908
974
  }
909
975
  export default UploadFoundation;
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.43.0-alpha.0",
3
+ "version": "2.43.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build:lib": "node ./scripts/compileLib.js",
7
7
  "prepublishOnly": "npm run build:lib"
8
8
  },
9
9
  "dependencies": {
10
- "@douyinfe/semi-animation": "2.43.0-alpha.0",
10
+ "@douyinfe/semi-animation": "2.43.0",
11
11
  "async-validator": "^3.5.0",
12
12
  "classnames": "^2.2.6",
13
13
  "date-fns": "^2.29.3",
@@ -23,7 +23,7 @@
23
23
  "*.scss",
24
24
  "*.css"
25
25
  ],
26
- "gitHead": "fcc62b3fcb6a4247854f4a81471cef9259ffc284",
26
+ "gitHead": "aa918000b24c716c67439b47d1e7fdf5707d30ff",
27
27
  "devDependencies": {
28
28
  "@babel/plugin-transform-runtime": "^7.15.8",
29
29
  "@babel/preset-env": "^7.15.8",
@@ -66,36 +66,45 @@ class TagInputFoundation extends BaseFoundation<TagInputAdapter> {
66
66
  };
67
67
 
68
68
  handleInputCompositionStart = (e: any) => {
69
+ const { maxLength } = this.getProps();
70
+ if (!isNumber(maxLength)) {
71
+ return;
72
+ }
69
73
  this._adapter.setEntering(true);
70
74
  }
71
75
 
72
76
  handleInputCompositionEnd = (e: any) => {
73
- this._adapter.setEntering(false);
74
77
  const { value } = e.target;
75
78
  const {
76
79
  maxLength,
77
80
  onInputExceed,
78
81
  separator
79
82
  } = this.getProps();
83
+ if (!isNumber(maxLength)) {
84
+ return;
85
+ }
86
+ this._adapter.setEntering(false);
80
87
  let allowChange = true;
81
- const { inputValue } = this.getStates();
82
- if (isNumber(maxLength)) {
83
- const inputArr = getSplitedArray(inputValue, separator);
84
- let index = 0;
85
- for (; index < inputArr.length; index++) {
86
- if (inputArr[index].length > maxLength) {
87
- allowChange = false;
88
- isFunction(onInputExceed) && onInputExceed(value);
89
- break;
90
- }
88
+ const inputArr = getSplitedArray(value, separator);
89
+ let index = 0;
90
+ for (; index < inputArr.length; index++) {
91
+ if (inputArr[index].length > maxLength) {
92
+ allowChange = false;
93
+ isFunction(onInputExceed) && onInputExceed(value);
94
+ break;
91
95
  }
92
- if (!allowChange) {
93
- const newInputArr = inputArr.slice(0, index);
94
- if (index < inputArr.length) {
95
- newInputArr.push(inputArr[index].slice(0, maxLength));
96
- }
97
- this._adapter.setInputValue(newInputArr.join(separator));
96
+ }
97
+ if (!allowChange) {
98
+ const newInputArr = inputArr.slice(0, index);
99
+ if (index < inputArr.length) {
100
+ newInputArr.push(inputArr[index].slice(0, maxLength));
98
101
  }
102
+ this._adapter.setInputValue(newInputArr.join(separator));
103
+ } else {
104
+ // Why does it need to be updated here instead of in onChange when the value meets the maxLength limit?
105
+ // Because in firefox, the state change in InputCompositionEnd causes onChange to not be triggered after
106
+ // the composition input completes input.
107
+ this._adapter.setInputValue(value);
99
108
  }
100
109
  }
101
110
 
@@ -156,7 +156,11 @@ export interface BasicRenderFullLabelProps {
156
156
  expanded: boolean;
157
157
  /* Is it unfolding */
158
158
  loading: boolean
159
- }
159
+ };
160
+ /* Whether the node meets the search conditions */
161
+ filtered: boolean | undefined;
162
+ /* Current search box input */
163
+ searchWord: string | undefined
160
164
  }
161
165
 
162
166
  export interface BasicSearchRenderProps {
@@ -84,7 +84,12 @@ export interface UploadAdapter<P = Record<string, any>, S = Record<string, any>>
84
84
  notifyClear: () => void;
85
85
  notifyPreviewClick: (file: any) => void;
86
86
  notifyDrop: (e: any, files: Array<File>, fileList: Array<BaseFileItem>) => void;
87
- notifyAcceptInvalid: (invalidFiles: Array<File>) => void
87
+ notifyAcceptInvalid: (invalidFiles: Array<File>) => void;
88
+ registerPastingHandler: (cb?: (params?: any) => void) => void;
89
+ unRegisterPastingHandler: () => void;
90
+ isMac: () => boolean;
91
+ notifyPastingError: (error: Error | PermissionStatus) => void
92
+ // notifyPasting: () => void;
88
93
  }
89
94
 
90
95
  class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends BaseFoundation<UploadAdapter<P, S>, P, S> {
@@ -92,8 +97,19 @@ class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends
92
97
  super({ ...adapter });
93
98
  }
94
99
 
100
+ init(): void {
101
+ const { disabled, addOnPasting } = this.getProps();
102
+ if (addOnPasting && !disabled) {
103
+ this.bindPastingHandler();
104
+ }
105
+ }
106
+
95
107
  destroy() {
108
+ const { disabled, addOnPasting } = this.getProps();
96
109
  this.releaseMemory();
110
+ if (addOnPasting && !disabled) {
111
+ this.unbindPastingHandler();
112
+ }
97
113
  }
98
114
 
99
115
  getError({ action, xhr, message, fileName }: { action: string;xhr: XMLHttpRequest;message?: string;fileName: string }): XhrError {
@@ -847,6 +863,62 @@ class UploadFoundation<P = Record<string, any>, S = Record<string, any>> extends
847
863
  handlePreviewClick(fileItem: BaseFileItem): void {
848
864
  this._adapter.notifyPreviewClick(fileItem);
849
865
  }
866
+
867
+ readFileFromClipboard(clipboardItems) {
868
+ for (const clipboardItem of clipboardItems) {
869
+ for (const type of clipboardItem.types) {
870
+ // types maybe: text/plain, image/png, text/html
871
+ if (type.startsWith('image')) {
872
+ clipboardItem.getType(type).then(blob => {
873
+ return blob.arrayBuffer();
874
+ }).then((buffer) => {
875
+ const format = type.split('/')[1];
876
+ const file = new File([buffer], `upload.${format}`, { type });
877
+ this.handleChange([file]);
878
+ });
879
+ }
880
+ }
881
+ }
882
+ }
883
+
884
+ handlePasting(e: any) {
885
+ const isMac = this._adapter.isMac();
886
+ const isCombineKeydown = isMac ? e.metaKey : e.ctrlKey;
887
+
888
+ if (isCombineKeydown && e.code === 'KeyV' && e.target === document.body) {
889
+ // https://github.com/microsoft/TypeScript/issues/33923
890
+ const permissionName = "clipboard-read" as PermissionName;
891
+ // The main thread should not be blocked by clipboard, so callback writing is required here. No await here
892
+ navigator.permissions
893
+ .query({ name: permissionName })
894
+ .then(result => {
895
+ console.log(result);
896
+ if (result.state === 'granted' || result.state === 'prompt') {
897
+ // user has authorized or will authorize
898
+ navigator.clipboard
899
+ .read()
900
+ .then(clipboardItems => {
901
+ // Process the data read from the pasteboard
902
+ // Check the returned data type to determine if it is image data, and process accordingly
903
+ this.readFileFromClipboard(clipboardItems);
904
+ });
905
+ } else {
906
+ this._adapter.notifyPastingError(result);
907
+ }
908
+ })
909
+ .catch(error => {
910
+ this._adapter.notifyPastingError(error);
911
+ });
912
+ }
913
+ }
914
+
915
+ bindPastingHandler(): void {
916
+ this._adapter.registerPastingHandler((event) => this.handlePasting(event));
917
+ }
918
+
919
+ unbindPastingHandler() {
920
+ this._adapter.unRegisterPastingHandler();
921
+ }
850
922
  }
851
923
 
852
924
  export default UploadFoundation;