@douyinfe/semi-foundation 2.25.0 → 2.25.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.
@@ -2,7 +2,7 @@ declare const cssClasses: {
2
2
  PREFIX: string;
3
3
  };
4
4
  declare const strings: {
5
- BOUNDARY_SET: string[];
5
+ BOUNDARY_SET: ("end" | "start")[];
6
6
  POSITION_SET: string[];
7
7
  MODE_SET: string[];
8
8
  MODE_MAP: {
@@ -10,8 +10,8 @@ declare const strings: {
10
10
  SCROLL: string;
11
11
  };
12
12
  BOUNDARY_MAP: {
13
- START: string;
14
- END: string;
13
+ readonly START: "start";
14
+ readonly END: "end";
15
15
  };
16
16
  OVERFLOW_DIR: {
17
17
  NONE: number;
@@ -19,5 +19,7 @@ declare const strings: {
19
19
  SHRINK: number;
20
20
  };
21
21
  };
22
- declare const numbers: {};
22
+ declare const numbers: {
23
+ MINIMUM_HTML_ELEMENT_WIDTH: number;
24
+ };
23
25
  export { cssClasses, strings, numbers };
@@ -33,5 +33,7 @@ const strings = {
33
33
  OVERFLOW_DIR
34
34
  };
35
35
  exports.strings = strings;
36
- const numbers = {};
36
+ const numbers = {
37
+ MINIMUM_HTML_ELEMENT_WIDTH: 4
38
+ };
37
39
  exports.numbers = numbers;
@@ -3,6 +3,7 @@ export interface OverflowListAdapter extends DefaultAdapter {
3
3
  updateStates: (state: any) => void;
4
4
  updateVisibleState: (visible: Map<string, boolean>) => void;
5
5
  notifyIntersect: (res: any) => void;
6
+ getItemSizeMap: () => Map<string, number>;
6
7
  }
7
8
  declare class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
8
9
  constructor(adapter: OverflowListAdapter);
@@ -10,6 +11,7 @@ declare class OverflowListFoundation extends BaseFoundation<OverflowListAdapter>
10
11
  isScrollMode: () => boolean;
11
12
  getOverflowItem(): Array<Array<Record<string, any>>>;
12
13
  handleIntersect(entries: Array<IntersectionObserverEntry>): void;
13
- handlePartition(growing: number): void;
14
+ getReversedItems: () => any;
15
+ handleCollapseOverflow(): void;
14
16
  }
15
17
  export default OverflowListFoundation;
@@ -29,6 +29,13 @@ class OverflowListFoundation extends _foundation.default {
29
29
  } = this.getProps();
30
30
  return renderMode === 'scroll';
31
31
  };
32
+
33
+ this.getReversedItems = () => {
34
+ const {
35
+ items
36
+ } = this.getProps();
37
+ return (0, _cloneDeep2.default)(items).reverse();
38
+ };
32
39
  }
33
40
 
34
41
  getOverflowItem() {
@@ -95,54 +102,68 @@ class OverflowListFoundation extends _foundation.default {
95
102
  this._adapter.notifyIntersect(res);
96
103
  }
97
104
 
98
- handlePartition(growing) {
105
+ handleCollapseOverflow() {
106
+ const {
107
+ minVisibleItems,
108
+ collapseFrom
109
+ } = this.getProps();
99
110
  const {
100
- direction,
101
- overflow,
102
- lastOverflowCount,
103
- visible
111
+ overflowWidth,
112
+ containerWidth,
113
+ pivot: statePivot,
114
+ overflowStatus
104
115
  } = this.getStates();
105
116
  const {
106
- minVisibleItems,
107
- collapseFrom,
108
- items
117
+ items,
118
+ onOverflow
109
119
  } = this.getProps();
110
- let updateState = {};
120
+ let itemWidths = overflowWidth,
121
+ _pivot = 0;
122
+ let overflowed = false;
111
123
 
112
- if (growing === OverflowDirection.NONE) {
113
- updateState = {
114
- direction: OverflowDirection.NONE
115
- };
116
- }
124
+ for (const size of this._adapter.getItemSizeMap().values()) {
125
+ itemWidths += size; // 触发overflow
117
126
 
118
- if (growing === OverflowDirection.GROW) {
119
- const updatedOverflowCount = direction === OverflowDirection.NONE ? overflow.length : lastOverflowCount;
120
- updateState = {
121
- direction: OverflowDirection.GROW,
122
- lastOverflowCount: updatedOverflowCount,
123
- overflow: [],
124
- visible: items
125
- };
126
- }
127
+ if (itemWidths > containerWidth) {
128
+ overflowed = true;
129
+ break;
130
+ } // 顺利遍历完整个列表,说明不存在overflow,直接渲染全部
127
131
 
128
- if (growing === OverflowDirection.SHRINK && visible.length > minVisibleItems) {
129
- const collapseFromStart = collapseFrom === Boundary.START;
130
- const newVisible = visible.slice();
131
- const next = collapseFromStart ? newVisible.shift() : newVisible.pop();
132
-
133
- if (next !== undefined) {
134
- updateState = {
135
- // set SHRINK mode unless a GROW is already in progress.
136
- // GROW shows all items then shrinks until it settles, so we
137
- // preserve the fact that the original trigger was a GROW.
138
- direction: direction !== OverflowDirection.GROW ? OverflowDirection.SHRINK : direction,
139
- overflow: collapseFromStart ? [...overflow, next] : [next, ...overflow],
140
- visible: newVisible
141
- };
132
+
133
+ if (_pivot === items.length - 1) {
134
+ this._adapter.updateStates({
135
+ overflowStatus: "normal",
136
+ pivot: items.length - 1,
137
+ visible: items,
138
+ overflow: []
139
+ });
140
+
141
+ break;
142
142
  }
143
+
144
+ _pivot++;
143
145
  }
144
146
 
145
- this._adapter.updateStates(updateState);
147
+ if (overflowed) {
148
+ const pivot = Math.max(minVisibleItems, _pivot);
149
+ const isCollapseFromStart = collapseFrom === Boundary.START;
150
+ const visible = isCollapseFromStart ? this.getReversedItems().slice(0, pivot).reverse() : items.slice(0, pivot);
151
+ const overflow = isCollapseFromStart ? this.getReversedItems().slice(pivot).reverse() : items.slice(pivot);
152
+
153
+ this._adapter.updateStates({
154
+ overflowStatus: "overflowed",
155
+ pivot: pivot,
156
+ visible,
157
+ overflow
158
+ }); // trigger onOverflow
159
+
160
+
161
+ if (statePivot !== pivot) {
162
+ onOverflow(overflow);
163
+ }
164
+
165
+ return;
166
+ }
146
167
  }
147
168
 
148
169
  }
@@ -2,7 +2,7 @@ declare const cssClasses: {
2
2
  PREFIX: string;
3
3
  };
4
4
  declare const strings: {
5
- BOUNDARY_SET: string[];
5
+ BOUNDARY_SET: ("end" | "start")[];
6
6
  POSITION_SET: string[];
7
7
  MODE_SET: string[];
8
8
  MODE_MAP: {
@@ -10,8 +10,8 @@ declare const strings: {
10
10
  SCROLL: string;
11
11
  };
12
12
  BOUNDARY_MAP: {
13
- START: string;
14
- END: string;
13
+ readonly START: "start";
14
+ readonly END: "end";
15
15
  };
16
16
  OVERFLOW_DIR: {
17
17
  NONE: number;
@@ -19,5 +19,7 @@ declare const strings: {
19
19
  SHRINK: number;
20
20
  };
21
21
  };
22
- declare const numbers: {};
22
+ declare const numbers: {
23
+ MINIMUM_HTML_ELEMENT_WIDTH: number;
24
+ };
23
25
  export { cssClasses, strings, numbers };
@@ -23,5 +23,7 @@ const strings = {
23
23
  BOUNDARY_MAP,
24
24
  OVERFLOW_DIR
25
25
  };
26
- const numbers = {};
26
+ const numbers = {
27
+ MINIMUM_HTML_ELEMENT_WIDTH: 4
28
+ };
27
29
  export { cssClasses, strings, numbers };
@@ -3,6 +3,7 @@ export interface OverflowListAdapter extends DefaultAdapter {
3
3
  updateStates: (state: any) => void;
4
4
  updateVisibleState: (visible: Map<string, boolean>) => void;
5
5
  notifyIntersect: (res: any) => void;
6
+ getItemSizeMap: () => Map<string, number>;
6
7
  }
7
8
  declare class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
8
9
  constructor(adapter: OverflowListAdapter);
@@ -10,6 +11,7 @@ declare class OverflowListFoundation extends BaseFoundation<OverflowListAdapter>
10
11
  isScrollMode: () => boolean;
11
12
  getOverflowItem(): Array<Array<Record<string, any>>>;
12
13
  handleIntersect(entries: Array<IntersectionObserverEntry>): void;
13
- handlePartition(growing: number): void;
14
+ getReversedItems: () => any;
15
+ handleCollapseOverflow(): void;
14
16
  }
15
17
  export default OverflowListFoundation;
@@ -16,6 +16,13 @@ class OverflowListFoundation extends BaseFoundation {
16
16
  } = this.getProps();
17
17
  return renderMode === 'scroll';
18
18
  };
19
+
20
+ this.getReversedItems = () => {
21
+ const {
22
+ items
23
+ } = this.getProps();
24
+ return _cloneDeep(items).reverse();
25
+ };
19
26
  }
20
27
 
21
28
  getOverflowItem() {
@@ -84,54 +91,68 @@ class OverflowListFoundation extends BaseFoundation {
84
91
  this._adapter.notifyIntersect(res);
85
92
  }
86
93
 
87
- handlePartition(growing) {
94
+ handleCollapseOverflow() {
95
+ const {
96
+ minVisibleItems,
97
+ collapseFrom
98
+ } = this.getProps();
88
99
  const {
89
- direction,
90
- overflow,
91
- lastOverflowCount,
92
- visible
100
+ overflowWidth,
101
+ containerWidth,
102
+ pivot: statePivot,
103
+ overflowStatus
93
104
  } = this.getStates();
94
105
  const {
95
- minVisibleItems,
96
- collapseFrom,
97
- items
106
+ items,
107
+ onOverflow
98
108
  } = this.getProps();
99
- let updateState = {};
109
+ let itemWidths = overflowWidth,
110
+ _pivot = 0;
111
+ let overflowed = false;
100
112
 
101
- if (growing === OverflowDirection.NONE) {
102
- updateState = {
103
- direction: OverflowDirection.NONE
104
- };
105
- }
113
+ for (const size of this._adapter.getItemSizeMap().values()) {
114
+ itemWidths += size; // 触发overflow
106
115
 
107
- if (growing === OverflowDirection.GROW) {
108
- const updatedOverflowCount = direction === OverflowDirection.NONE ? overflow.length : lastOverflowCount;
109
- updateState = {
110
- direction: OverflowDirection.GROW,
111
- lastOverflowCount: updatedOverflowCount,
112
- overflow: [],
113
- visible: items
114
- };
115
- }
116
+ if (itemWidths > containerWidth) {
117
+ overflowed = true;
118
+ break;
119
+ } // 顺利遍历完整个列表,说明不存在overflow,直接渲染全部
116
120
 
117
- if (growing === OverflowDirection.SHRINK && visible.length > minVisibleItems) {
118
- const collapseFromStart = collapseFrom === Boundary.START;
119
- const newVisible = visible.slice();
120
- const next = collapseFromStart ? newVisible.shift() : newVisible.pop();
121
-
122
- if (next !== undefined) {
123
- updateState = {
124
- // set SHRINK mode unless a GROW is already in progress.
125
- // GROW shows all items then shrinks until it settles, so we
126
- // preserve the fact that the original trigger was a GROW.
127
- direction: direction !== OverflowDirection.GROW ? OverflowDirection.SHRINK : direction,
128
- overflow: collapseFromStart ? [...overflow, next] : [next, ...overflow],
129
- visible: newVisible
130
- };
121
+
122
+ if (_pivot === items.length - 1) {
123
+ this._adapter.updateStates({
124
+ overflowStatus: "normal",
125
+ pivot: items.length - 1,
126
+ visible: items,
127
+ overflow: []
128
+ });
129
+
130
+ break;
131
131
  }
132
+
133
+ _pivot++;
132
134
  }
133
135
 
134
- this._adapter.updateStates(updateState);
136
+ if (overflowed) {
137
+ const pivot = Math.max(minVisibleItems, _pivot);
138
+ const isCollapseFromStart = collapseFrom === Boundary.START;
139
+ const visible = isCollapseFromStart ? this.getReversedItems().slice(0, pivot).reverse() : items.slice(0, pivot);
140
+ const overflow = isCollapseFromStart ? this.getReversedItems().slice(pivot).reverse() : items.slice(pivot);
141
+
142
+ this._adapter.updateStates({
143
+ overflowStatus: "overflowed",
144
+ pivot: pivot,
145
+ visible,
146
+ overflow
147
+ }); // trigger onOverflow
148
+
149
+
150
+ if (statePivot !== pivot) {
151
+ onOverflow(overflow);
152
+ }
153
+
154
+ return;
155
+ }
135
156
  }
136
157
 
137
158
  }
@@ -14,7 +14,7 @@ const MODE_MAP = {
14
14
  const BOUNDARY_MAP = {
15
15
  START: 'start',
16
16
  END: 'end',
17
- };
17
+ } as const;
18
18
 
19
19
  const OVERFLOW_DIR = {
20
20
  NONE: 0,
@@ -31,7 +31,9 @@ const strings = {
31
31
  OVERFLOW_DIR
32
32
  };
33
33
 
34
- const numbers = {};
34
+ const numbers = {
35
+ MINIMUM_HTML_ELEMENT_WIDTH: 4
36
+ };
35
37
 
36
38
  export {
37
39
  cssClasses,
@@ -7,7 +7,8 @@ const OverflowDirection = strings.OVERFLOW_DIR;
7
7
  export interface OverflowListAdapter extends DefaultAdapter {
8
8
  updateStates: (state: any) => void;
9
9
  updateVisibleState: (visible: Map<string, boolean>) => void;
10
- notifyIntersect: (res: any) => void
10
+ notifyIntersect: (res: any) => void;
11
+ getItemSizeMap: ()=>Map<string, number>
11
12
  }
12
13
 
13
14
  class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
@@ -29,6 +30,7 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
29
30
  if (!this.isScrollMode()) {
30
31
  return overflow;
31
32
  }
33
+
32
34
  const visibleStateArr = items.map(({ key }: { key: string }) => Boolean(visibleState.get(key)));
33
35
  const visibleStart = visibleStateArr.indexOf(true);
34
36
  const visibleEnd = visibleStateArr.lastIndexOf(true);
@@ -71,38 +73,52 @@ class OverflowListFoundation extends BaseFoundation<OverflowListAdapter> {
71
73
  this._adapter.notifyIntersect(res);
72
74
  }
73
75
 
74
- handlePartition(growing: number): void {
75
- const { direction, overflow, lastOverflowCount, visible } = this.getStates();
76
- const { minVisibleItems, collapseFrom, items } = this.getProps();
77
- let updateState = {};
78
- if (growing === OverflowDirection.NONE) {
79
- updateState = { direction: OverflowDirection.NONE };
80
- }
81
- if (growing === OverflowDirection.GROW) {
82
- const updatedOverflowCount = direction === OverflowDirection.NONE ? overflow.length : lastOverflowCount;
83
- updateState = {
84
- direction: OverflowDirection.GROW,
85
- lastOverflowCount: updatedOverflowCount,
86
- overflow: [],
87
- visible: items,
88
- };
76
+ getReversedItems = ()=>{
77
+ const { items } = this.getProps();
78
+ return cloneDeep(items).reverse();
79
+ }
80
+ handleCollapseOverflow(){
81
+ const { minVisibleItems, collapseFrom } = this.getProps();
82
+ const { overflowWidth, containerWidth, pivot: statePivot, overflowStatus } = this.getStates();
83
+ const { items, onOverflow } = this.getProps();
84
+ let itemWidths = overflowWidth, _pivot = 0;
85
+ let overflowed = false;
86
+ for (const size of this._adapter.getItemSizeMap().values()) {
87
+ itemWidths += size;
88
+ // 触发overflow
89
+ if (itemWidths > containerWidth) {
90
+ overflowed = true;
91
+ break;
92
+ }
93
+ // 顺利遍历完整个列表,说明不存在overflow,直接渲染全部
94
+ if (_pivot === items.length - 1) {
95
+ this._adapter.updateStates({
96
+ overflowStatus: "normal",
97
+ pivot: items.length - 1,
98
+ visible: items,
99
+ overflow: []
100
+ });
101
+ break;
102
+ }
103
+ _pivot++;
89
104
  }
90
- if (growing === OverflowDirection.SHRINK && visible.length > minVisibleItems) {
91
- const collapseFromStart = collapseFrom === Boundary.START;
92
- const newVisible = visible.slice();
93
- const next = collapseFromStart ? newVisible.shift() : newVisible.pop();
94
- if (next !== undefined) {
95
- updateState = {
96
- // set SHRINK mode unless a GROW is already in progress.
97
- // GROW shows all items then shrinks until it settles, so we
98
- // preserve the fact that the original trigger was a GROW.
99
- direction: direction !== OverflowDirection.GROW ? OverflowDirection.SHRINK : direction,
100
- overflow: collapseFromStart ? [...overflow, next] : [next, ...overflow],
101
- visible: newVisible
102
- };
105
+ if (overflowed) {
106
+ const pivot = Math.max(minVisibleItems, _pivot);
107
+ const isCollapseFromStart = collapseFrom === Boundary.START;
108
+ const visible = isCollapseFromStart ? this.getReversedItems().slice(0, pivot).reverse() : items.slice(0, pivot);
109
+ const overflow = isCollapseFromStart ? this.getReversedItems().slice(pivot).reverse() : items.slice(pivot);
110
+ this._adapter.updateStates({
111
+ overflowStatus: "overflowed",
112
+ pivot: pivot,
113
+ visible,
114
+ overflow,
115
+ });
116
+ // trigger onOverflow
117
+ if (statePivot !== pivot){
118
+ onOverflow(overflow);
103
119
  }
120
+ return;
104
121
  }
105
- this._adapter.updateStates(updateState);
106
122
  }
107
123
 
108
124
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@douyinfe/semi-foundation",
3
- "version": "2.25.0",
3
+ "version": "2.25.1",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build:lib": "node ./scripts/compileLib.js",
@@ -23,7 +23,7 @@
23
23
  "*.scss",
24
24
  "*.css"
25
25
  ],
26
- "gitHead": "3c2ec566acd956095fc502690245c9a502251357",
26
+ "gitHead": "571a51134e49bec30e4412b4eacd45dd35d3849f",
27
27
  "devDependencies": {
28
28
  "@babel/plugin-transform-runtime": "^7.15.8",
29
29
  "@babel/preset-env": "^7.15.8",