@douyinfe/semi-foundation 2.103.0 → 2.104.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.
- package/lib/cjs/modal/modalContentFoundation.js +21 -0
- package/lib/cjs/radio/radio.css +5 -0
- package/lib/cjs/radio/radio.scss +9 -0
- package/lib/cjs/resizable/group/index.d.ts +9 -0
- package/lib/cjs/resizable/group/index.js +18 -0
- package/lib/cjs/timePicker/utils/index.js +2 -1
- package/lib/es/modal/modalContentFoundation.js +21 -0
- package/lib/es/radio/radio.css +5 -0
- package/lib/es/radio/radio.scss +9 -0
- package/lib/es/resizable/group/index.d.ts +9 -0
- package/lib/es/resizable/group/index.js +18 -0
- package/lib/es/timePicker/utils/index.js +2 -1
- package/modal/modalContentFoundation.ts +22 -0
- package/package.json +4 -4
- package/radio/radio.scss +9 -0
- package/resizable/group/index.ts +19 -0
- package/timePicker/utils/index.ts +2 -1
|
@@ -7,6 +7,14 @@ exports.default = void 0;
|
|
|
7
7
|
var _foundation = _interopRequireDefault(require("../base/foundation"));
|
|
8
8
|
var _keyCode = _interopRequireDefault(require("../utils/keyCode"));
|
|
9
9
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
/**
|
|
11
|
+
* Stack of `handleKeyDown` handlers for modals that currently listen on
|
|
12
|
+
* `document`. Every ModalContent registers its own document-level keydown
|
|
13
|
+
* listener, so `stopPropagation()` cannot stop sibling listeners on the same
|
|
14
|
+
* node — one ESC used to close every open dialog. Only the most recently
|
|
15
|
+
* mounted (top-most) listener should respond.
|
|
16
|
+
*/
|
|
17
|
+
const escListenerStack = [];
|
|
10
18
|
class ModalContentFoundation extends _foundation.default {
|
|
11
19
|
constructor(adapter) {
|
|
12
20
|
super(Object.assign(Object.assign({}, ModalContentFoundation.defaultAdapter), adapter));
|
|
@@ -15,6 +23,12 @@ class ModalContentFoundation extends _foundation.default {
|
|
|
15
23
|
closeOnEsc
|
|
16
24
|
} = this.getProps();
|
|
17
25
|
if (closeOnEsc && e.keyCode === _keyCode.default.ESC) {
|
|
26
|
+
// Multiple open modals each registered a document-level keydown
|
|
27
|
+
// listener; only the top-most (most recently mounted) one may
|
|
28
|
+
// close, so a single ESC closes dialogs one at a time.
|
|
29
|
+
if (escListenerStack[escListenerStack.length - 1] !== this.handleKeyDown) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
18
32
|
e.stopPropagation();
|
|
19
33
|
this.close(e);
|
|
20
34
|
return;
|
|
@@ -34,9 +48,16 @@ class ModalContentFoundation extends _foundation.default {
|
|
|
34
48
|
}
|
|
35
49
|
handleKeyDownEventListenerMount() {
|
|
36
50
|
this._adapter.addKeyDownEventListener();
|
|
51
|
+
if (this.getProps().closeOnEsc) {
|
|
52
|
+
escListenerStack.push(this.handleKeyDown);
|
|
53
|
+
}
|
|
37
54
|
}
|
|
38
55
|
handleKeyDownEventListenerUnmount() {
|
|
39
56
|
this._adapter.removeKeyDownEventListener();
|
|
57
|
+
const index = escListenerStack.indexOf(this.handleKeyDown);
|
|
58
|
+
if (index !== -1) {
|
|
59
|
+
escListenerStack.splice(index, 1);
|
|
60
|
+
}
|
|
40
61
|
}
|
|
41
62
|
getMouseState() {
|
|
42
63
|
this._adapter.getMouseState();
|
package/lib/cjs/radio/radio.css
CHANGED
package/lib/cjs/radio/radio.scss
CHANGED
|
@@ -236,6 +236,15 @@ $inner-width: $width-icon-medium;
|
|
|
236
236
|
width: 100%;
|
|
237
237
|
height: 100%;
|
|
238
238
|
font-size: 14px;
|
|
239
|
+
|
|
240
|
+
// #3350: 显式设置 svg 尺寸并 block 化,替代 svg 自带的 width/height="1em"。
|
|
241
|
+
// Safari 对以 em 指定尺寸的内联 SVG 存在渲染偏差,会导致 checked 状态
|
|
242
|
+
// 的白点视觉偏移;100% 让 svg 与图标容器严格同尺寸,无偏移空间。
|
|
243
|
+
svg {
|
|
244
|
+
display: block;
|
|
245
|
+
width: 100%;
|
|
246
|
+
height: 100%;
|
|
247
|
+
}
|
|
239
248
|
}
|
|
240
249
|
}
|
|
241
250
|
}
|
|
@@ -41,7 +41,16 @@ export declare class ResizeGroupFoundation<P = Record<string, any>, S = Record<s
|
|
|
41
41
|
totalMinus: number;
|
|
42
42
|
itemPercentMap: Map<number, number>;
|
|
43
43
|
type?: ResizeEventType;
|
|
44
|
+
sizeInitialized: boolean;
|
|
44
45
|
init(): void;
|
|
46
|
+
/**
|
|
47
|
+
* When the group is initially mounted inside a display:none container, its own size
|
|
48
|
+
* and the handler sizes are all 0, so item sizes are computed with a `- 0px` handler
|
|
49
|
+
* offset and never corrected once the container becomes visible. Recalculate the layout
|
|
50
|
+
* the first time the group becomes measurable. Once it has a valid size, later resizes
|
|
51
|
+
* must NOT re-run initSpace, otherwise the user's manual drag results would be reset. #3336
|
|
52
|
+
*/
|
|
53
|
+
handleGroupResize: () => void;
|
|
45
54
|
get window(): Window | null;
|
|
46
55
|
registerEvents: () => void;
|
|
47
56
|
unregisterEvents: () => void;
|
|
@@ -31,6 +31,21 @@ exports.ResizeItemFoundation = ResizeItemFoundation;
|
|
|
31
31
|
class ResizeGroupFoundation extends _foundation.default {
|
|
32
32
|
constructor(adapter) {
|
|
33
33
|
super(Object.assign({}, adapter));
|
|
34
|
+
// 首次 initSpace 时 group 是否可测量(非 display:none)。
|
|
35
|
+
// Whether the group was measurable (not inside display:none) on the first initSpace run. #3336
|
|
36
|
+
this.sizeInitialized = false;
|
|
37
|
+
/**
|
|
38
|
+
* When the group is initially mounted inside a display:none container, its own size
|
|
39
|
+
* and the handler sizes are all 0, so item sizes are computed with a `- 0px` handler
|
|
40
|
+
* offset and never corrected once the container becomes visible. Recalculate the layout
|
|
41
|
+
* the first time the group becomes measurable. Once it has a valid size, later resizes
|
|
42
|
+
* must NOT re-run initSpace, otherwise the user's manual drag results would be reset. #3336
|
|
43
|
+
*/
|
|
44
|
+
this.handleGroupResize = () => {
|
|
45
|
+
if (!this.sizeInitialized && this.groupSize > 0) {
|
|
46
|
+
this.initSpace();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
34
49
|
this.registerEvents = () => {
|
|
35
50
|
this._adapter.registerEvents(this.type);
|
|
36
51
|
};
|
|
@@ -194,6 +209,9 @@ class ResizeGroupFoundation extends _foundation.default {
|
|
|
194
209
|
// calculate accurate space for group item
|
|
195
210
|
let handlerSizes = new Array(this._adapter.getHandlerCount()).fill(0);
|
|
196
211
|
let parentSize = this.groupSize;
|
|
212
|
+
// Mark whether the group is measurable now; if not (e.g. inside display:none),
|
|
213
|
+
// handleGroupResize will re-run initSpace once it becomes visible. #3336
|
|
214
|
+
this.sizeInitialized = parentSize > 0;
|
|
197
215
|
this.totalMinus = 0;
|
|
198
216
|
for (let i = 0; i < this._adapter.getHandlerCount(); i++) {
|
|
199
217
|
let handlerSize = direction === 'horizontal' ? this._adapter.getHandler(i).offsetWidth : this._adapter.getHandler(i).offsetHeight;
|
|
@@ -125,7 +125,8 @@ const isTimeFormatLike = (time, formatToken) => {
|
|
|
125
125
|
const hmsReg = /[H|m|s]{1,2}/;
|
|
126
126
|
const formatSplitted = formatToken.split(formatNotSupportChReg); // => ['HH', 'mm'];
|
|
127
127
|
const timeSeparator = formatToken.replace(formatSupportChReg, ''); // => :
|
|
128
|
-
const
|
|
128
|
+
const escapedTimeSeparator = timeSeparator.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); // escape regExp special characters to avoid invalid regExp, e.g. format="HH\\mm"
|
|
129
|
+
const timeReg = new RegExp(`[${escapedTimeSeparator}]`, 'g'); // => /[:]/g
|
|
129
130
|
const timeSplitted = time.split(timeReg); // => ['12', '0]
|
|
130
131
|
if (formatSplitted.length !== timeSplitted.length) {
|
|
131
132
|
isLike = false;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import BaseFoundation from '../base/foundation';
|
|
2
2
|
import KeyCode from '../utils/keyCode';
|
|
3
|
+
/**
|
|
4
|
+
* Stack of `handleKeyDown` handlers for modals that currently listen on
|
|
5
|
+
* `document`. Every ModalContent registers its own document-level keydown
|
|
6
|
+
* listener, so `stopPropagation()` cannot stop sibling listeners on the same
|
|
7
|
+
* node — one ESC used to close every open dialog. Only the most recently
|
|
8
|
+
* mounted (top-most) listener should respond.
|
|
9
|
+
*/
|
|
10
|
+
const escListenerStack = [];
|
|
3
11
|
export default class ModalContentFoundation extends BaseFoundation {
|
|
4
12
|
constructor(adapter) {
|
|
5
13
|
super(Object.assign(Object.assign({}, ModalContentFoundation.defaultAdapter), adapter));
|
|
@@ -8,6 +16,12 @@ export default class ModalContentFoundation extends BaseFoundation {
|
|
|
8
16
|
closeOnEsc
|
|
9
17
|
} = this.getProps();
|
|
10
18
|
if (closeOnEsc && e.keyCode === KeyCode.ESC) {
|
|
19
|
+
// Multiple open modals each registered a document-level keydown
|
|
20
|
+
// listener; only the top-most (most recently mounted) one may
|
|
21
|
+
// close, so a single ESC closes dialogs one at a time.
|
|
22
|
+
if (escListenerStack[escListenerStack.length - 1] !== this.handleKeyDown) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
11
25
|
e.stopPropagation();
|
|
12
26
|
this.close(e);
|
|
13
27
|
return;
|
|
@@ -27,9 +41,16 @@ export default class ModalContentFoundation extends BaseFoundation {
|
|
|
27
41
|
}
|
|
28
42
|
handleKeyDownEventListenerMount() {
|
|
29
43
|
this._adapter.addKeyDownEventListener();
|
|
44
|
+
if (this.getProps().closeOnEsc) {
|
|
45
|
+
escListenerStack.push(this.handleKeyDown);
|
|
46
|
+
}
|
|
30
47
|
}
|
|
31
48
|
handleKeyDownEventListenerUnmount() {
|
|
32
49
|
this._adapter.removeKeyDownEventListener();
|
|
50
|
+
const index = escListenerStack.indexOf(this.handleKeyDown);
|
|
51
|
+
if (index !== -1) {
|
|
52
|
+
escListenerStack.splice(index, 1);
|
|
53
|
+
}
|
|
33
54
|
}
|
|
34
55
|
getMouseState() {
|
|
35
56
|
this._adapter.getMouseState();
|
package/lib/es/radio/radio.css
CHANGED
package/lib/es/radio/radio.scss
CHANGED
|
@@ -236,6 +236,15 @@ $inner-width: $width-icon-medium;
|
|
|
236
236
|
width: 100%;
|
|
237
237
|
height: 100%;
|
|
238
238
|
font-size: 14px;
|
|
239
|
+
|
|
240
|
+
// #3350: 显式设置 svg 尺寸并 block 化,替代 svg 自带的 width/height="1em"。
|
|
241
|
+
// Safari 对以 em 指定尺寸的内联 SVG 存在渲染偏差,会导致 checked 状态
|
|
242
|
+
// 的白点视觉偏移;100% 让 svg 与图标容器严格同尺寸,无偏移空间。
|
|
243
|
+
svg {
|
|
244
|
+
display: block;
|
|
245
|
+
width: 100%;
|
|
246
|
+
height: 100%;
|
|
247
|
+
}
|
|
239
248
|
}
|
|
240
249
|
}
|
|
241
250
|
}
|
|
@@ -41,7 +41,16 @@ export declare class ResizeGroupFoundation<P = Record<string, any>, S = Record<s
|
|
|
41
41
|
totalMinus: number;
|
|
42
42
|
itemPercentMap: Map<number, number>;
|
|
43
43
|
type?: ResizeEventType;
|
|
44
|
+
sizeInitialized: boolean;
|
|
44
45
|
init(): void;
|
|
46
|
+
/**
|
|
47
|
+
* When the group is initially mounted inside a display:none container, its own size
|
|
48
|
+
* and the handler sizes are all 0, so item sizes are computed with a `- 0px` handler
|
|
49
|
+
* offset and never corrected once the container becomes visible. Recalculate the layout
|
|
50
|
+
* the first time the group becomes measurable. Once it has a valid size, later resizes
|
|
51
|
+
* must NOT re-run initSpace, otherwise the user's manual drag results would be reset. #3336
|
|
52
|
+
*/
|
|
53
|
+
handleGroupResize: () => void;
|
|
45
54
|
get window(): Window | null;
|
|
46
55
|
registerEvents: () => void;
|
|
47
56
|
unregisterEvents: () => void;
|
|
@@ -23,6 +23,21 @@ export class ResizeItemFoundation extends BaseFoundation {
|
|
|
23
23
|
export class ResizeGroupFoundation extends BaseFoundation {
|
|
24
24
|
constructor(adapter) {
|
|
25
25
|
super(Object.assign({}, adapter));
|
|
26
|
+
// 首次 initSpace 时 group 是否可测量(非 display:none)。
|
|
27
|
+
// Whether the group was measurable (not inside display:none) on the first initSpace run. #3336
|
|
28
|
+
this.sizeInitialized = false;
|
|
29
|
+
/**
|
|
30
|
+
* When the group is initially mounted inside a display:none container, its own size
|
|
31
|
+
* and the handler sizes are all 0, so item sizes are computed with a `- 0px` handler
|
|
32
|
+
* offset and never corrected once the container becomes visible. Recalculate the layout
|
|
33
|
+
* the first time the group becomes measurable. Once it has a valid size, later resizes
|
|
34
|
+
* must NOT re-run initSpace, otherwise the user's manual drag results would be reset. #3336
|
|
35
|
+
*/
|
|
36
|
+
this.handleGroupResize = () => {
|
|
37
|
+
if (!this.sizeInitialized && this.groupSize > 0) {
|
|
38
|
+
this.initSpace();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
26
41
|
this.registerEvents = () => {
|
|
27
42
|
this._adapter.registerEvents(this.type);
|
|
28
43
|
};
|
|
@@ -186,6 +201,9 @@ export class ResizeGroupFoundation extends BaseFoundation {
|
|
|
186
201
|
// calculate accurate space for group item
|
|
187
202
|
let handlerSizes = new Array(this._adapter.getHandlerCount()).fill(0);
|
|
188
203
|
let parentSize = this.groupSize;
|
|
204
|
+
// Mark whether the group is measurable now; if not (e.g. inside display:none),
|
|
205
|
+
// handleGroupResize will re-run initSpace once it becomes visible. #3336
|
|
206
|
+
this.sizeInitialized = parentSize > 0;
|
|
189
207
|
this.totalMinus = 0;
|
|
190
208
|
for (let i = 0; i < this._adapter.getHandlerCount(); i++) {
|
|
191
209
|
let handlerSize = direction === 'horizontal' ? this._adapter.getHandler(i).offsetWidth : this._adapter.getHandler(i).offsetHeight;
|
|
@@ -111,7 +111,8 @@ export const isTimeFormatLike = (time, formatToken) => {
|
|
|
111
111
|
const hmsReg = /[H|m|s]{1,2}/;
|
|
112
112
|
const formatSplitted = formatToken.split(formatNotSupportChReg); // => ['HH', 'mm'];
|
|
113
113
|
const timeSeparator = formatToken.replace(formatSupportChReg, ''); // => :
|
|
114
|
-
const
|
|
114
|
+
const escapedTimeSeparator = timeSeparator.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); // escape regExp special characters to avoid invalid regExp, e.g. format="HH\\mm"
|
|
115
|
+
const timeReg = new RegExp(`[${escapedTimeSeparator}]`, 'g'); // => /[:]/g
|
|
115
116
|
const timeSplitted = time.split(timeReg); // => ['12', '0]
|
|
116
117
|
if (formatSplitted.length !== timeSplitted.length) {
|
|
117
118
|
isLike = false;
|
|
@@ -30,6 +30,15 @@ export interface ModalContentAdapter extends DefaultAdapter<ModalContentProps, M
|
|
|
30
30
|
prevFocusElementReFocus: () => void
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Stack of `handleKeyDown` handlers for modals that currently listen on
|
|
35
|
+
* `document`. Every ModalContent registers its own document-level keydown
|
|
36
|
+
* listener, so `stopPropagation()` cannot stop sibling listeners on the same
|
|
37
|
+
* node — one ESC used to close every open dialog. Only the most recently
|
|
38
|
+
* mounted (top-most) listener should respond.
|
|
39
|
+
*/
|
|
40
|
+
const escListenerStack: Array<(e: any) => void> = [];
|
|
41
|
+
|
|
33
42
|
export default class ModalContentFoundation extends BaseFoundation<ModalContentAdapter> {
|
|
34
43
|
|
|
35
44
|
constructor(adapter: ModalContentAdapter) {
|
|
@@ -53,6 +62,12 @@ export default class ModalContentFoundation extends BaseFoundation<ModalContentA
|
|
|
53
62
|
handleKeyDown = (e: any) => {
|
|
54
63
|
const { closeOnEsc } = this.getProps();
|
|
55
64
|
if (closeOnEsc && e.keyCode === KeyCode.ESC) {
|
|
65
|
+
// Multiple open modals each registered a document-level keydown
|
|
66
|
+
// listener; only the top-most (most recently mounted) one may
|
|
67
|
+
// close, so a single ESC closes dialogs one at a time.
|
|
68
|
+
if (escListenerStack[escListenerStack.length - 1] !== this.handleKeyDown) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
56
71
|
e.stopPropagation();
|
|
57
72
|
this.close(e);
|
|
58
73
|
return;
|
|
@@ -61,10 +76,17 @@ export default class ModalContentFoundation extends BaseFoundation<ModalContentA
|
|
|
61
76
|
|
|
62
77
|
handleKeyDownEventListenerMount() {
|
|
63
78
|
this._adapter.addKeyDownEventListener();
|
|
79
|
+
if (this.getProps().closeOnEsc) {
|
|
80
|
+
escListenerStack.push(this.handleKeyDown);
|
|
81
|
+
}
|
|
64
82
|
}
|
|
65
83
|
|
|
66
84
|
handleKeyDownEventListenerUnmount() {
|
|
67
85
|
this._adapter.removeKeyDownEventListener();
|
|
86
|
+
const index = escListenerStack.indexOf(this.handleKeyDown);
|
|
87
|
+
if (index !== -1) {
|
|
88
|
+
escListenerStack.splice(index, 1);
|
|
89
|
+
}
|
|
68
90
|
}
|
|
69
91
|
|
|
70
92
|
getMouseState() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@douyinfe/semi-foundation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.104.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rimraf lib",
|
|
@@ -14225,8 +14225,8 @@
|
|
|
14225
14225
|
}
|
|
14226
14226
|
},
|
|
14227
14227
|
"dependencies": {
|
|
14228
|
-
"@douyinfe/semi-animation": "2.
|
|
14229
|
-
"@douyinfe/semi-json-viewer-core": "2.
|
|
14228
|
+
"@douyinfe/semi-animation": "2.104.0",
|
|
14229
|
+
"@douyinfe/semi-json-viewer-core": "2.104.0",
|
|
14230
14230
|
"@mdx-js/mdx": "^3.0.1",
|
|
14231
14231
|
"async-validator": "^3.5.0",
|
|
14232
14232
|
"classnames": "^2.2.6",
|
|
@@ -14247,7 +14247,7 @@
|
|
|
14247
14247
|
"*.scss",
|
|
14248
14248
|
"*.css"
|
|
14249
14249
|
],
|
|
14250
|
-
"gitHead": "
|
|
14250
|
+
"gitHead": "c69b9e013ab7b45cc617ed32f1ed548e96058bcd",
|
|
14251
14251
|
"devDependencies": {
|
|
14252
14252
|
"@babel/plugin-transform-runtime": "^7.15.8",
|
|
14253
14253
|
"@babel/preset-env": "^7.15.8",
|
package/radio/radio.scss
CHANGED
|
@@ -236,6 +236,15 @@ $inner-width: $width-icon-medium;
|
|
|
236
236
|
width: 100%;
|
|
237
237
|
height: 100%;
|
|
238
238
|
font-size: 14px;
|
|
239
|
+
|
|
240
|
+
// #3350: 显式设置 svg 尺寸并 block 化,替代 svg 自带的 width/height="1em"。
|
|
241
|
+
// Safari 对以 em 指定尺寸的内联 SVG 存在渲染偏差,会导致 checked 状态
|
|
242
|
+
// 的白点视觉偏移;100% 让 svg 与图标容器严格同尺寸,无偏移空间。
|
|
243
|
+
svg {
|
|
244
|
+
display: block;
|
|
245
|
+
width: 100%;
|
|
246
|
+
height: 100%;
|
|
247
|
+
}
|
|
239
248
|
}
|
|
240
249
|
}
|
|
241
250
|
}
|
package/resizable/group/index.ts
CHANGED
|
@@ -73,6 +73,9 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
|
|
|
73
73
|
totalMinus: number;
|
|
74
74
|
itemPercentMap: Map<number, number>; // 内部维护一个百分比数组,消除浮点计算误差
|
|
75
75
|
type?: ResizeEventType;
|
|
76
|
+
// 首次 initSpace 时 group 是否可测量(非 display:none)。
|
|
77
|
+
// Whether the group was measurable (not inside display:none) on the first initSpace run. #3336
|
|
78
|
+
sizeInitialized: boolean = false;
|
|
76
79
|
|
|
77
80
|
|
|
78
81
|
init(): void {
|
|
@@ -81,6 +84,19 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
|
|
|
81
84
|
this.itemPercentMap = new Map();
|
|
82
85
|
this.initSpace();
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* When the group is initially mounted inside a display:none container, its own size
|
|
90
|
+
* and the handler sizes are all 0, so item sizes are computed with a `- 0px` handler
|
|
91
|
+
* offset and never corrected once the container becomes visible. Recalculate the layout
|
|
92
|
+
* the first time the group becomes measurable. Once it has a valid size, later resizes
|
|
93
|
+
* must NOT re-run initSpace, otherwise the user's manual drag results would be reset. #3336
|
|
94
|
+
*/
|
|
95
|
+
handleGroupResize = () => {
|
|
96
|
+
if (!this.sizeInitialized && this.groupSize > 0) {
|
|
97
|
+
this.initSpace();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
84
100
|
get window(): Window | null {
|
|
85
101
|
return this.groupRef.ownerDocument.defaultView as Window ?? null;
|
|
86
102
|
}
|
|
@@ -231,6 +247,9 @@ export class ResizeGroupFoundation<P = Record<string, any>, S = Record<string, a
|
|
|
231
247
|
// calculate accurate space for group item
|
|
232
248
|
let handlerSizes = new Array(this._adapter.getHandlerCount()).fill(0);
|
|
233
249
|
let parentSize = this.groupSize;
|
|
250
|
+
// Mark whether the group is measurable now; if not (e.g. inside display:none),
|
|
251
|
+
// handleGroupResize will re-run initSpace once it becomes visible. #3336
|
|
252
|
+
this.sizeInitialized = parentSize > 0;
|
|
234
253
|
this.totalMinus = 0;
|
|
235
254
|
for (let i = 0; i < this._adapter.getHandlerCount(); i++) {
|
|
236
255
|
let handlerSize = direction === 'horizontal' ? this._adapter.getHandler(i).offsetWidth : this._adapter.getHandler(i).offsetHeight;
|
|
@@ -131,7 +131,8 @@ export const isTimeFormatLike = (time: string, formatToken: string) => {
|
|
|
131
131
|
const hmsReg = /[H|m|s]{1,2}/;
|
|
132
132
|
const formatSplitted = formatToken.split(formatNotSupportChReg); // => ['HH', 'mm'];
|
|
133
133
|
const timeSeparator = formatToken.replace(formatSupportChReg, ''); // => :
|
|
134
|
-
const
|
|
134
|
+
const escapedTimeSeparator = timeSeparator.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'); // escape regExp special characters to avoid invalid regExp, e.g. format="HH\\mm"
|
|
135
|
+
const timeReg = new RegExp(`[${escapedTimeSeparator}]`, 'g'); // => /[:]/g
|
|
135
136
|
const timeSplitted = time.split(timeReg); // => ['12', '0]
|
|
136
137
|
|
|
137
138
|
if (formatSplitted.length !== timeSplitted.length) {
|