@laser-ui/components 2.5.0 → 2.6.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/CHANGELOG.md +6 -0
- package/date-picker/DatePicker.js +176 -168
- package/dropdown/Dropdown.js +1 -5
- package/hooks/useNestedPopup.d.ts +3 -4
- package/hooks/useNestedPopup.js +7 -12
- package/image/Image.js +14 -20
- package/input/InputNumber.js +39 -35
- package/menu/Menu.js +1 -2
- package/package.json +2 -2
- package/spinner/Spinner.js +8 -10
- package/time-picker/TimePicker.js +173 -149
- package/transition/Transition.js +7 -9
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
# [2.6.0](https://github.com/laser-ui/laser-ui/compare/v2.5.0...v2.6.0) (2026-04-08)
|
|
6
|
+
|
|
7
|
+
### Bug Fixes
|
|
8
|
+
|
|
9
|
+
- **components:** fix number input cant enter `0.01` ([483f7f0](https://github.com/laser-ui/laser-ui/commit/483f7f099a25d68a89ba3899bc07fcd380513531))
|
|
10
|
+
|
|
5
11
|
# [2.5.0](https://github.com/laser-ui/laser-ui/compare/v2.4.0...v2.5.0) (2026-04-03)
|
|
6
12
|
|
|
7
13
|
### Features
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import { createElement as _createElement } from "react";
|
|
3
3
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { useAsync, useEventCallback,
|
|
4
|
+
import { useAsync, useEventCallback, useImmer, useIsomorphicLayoutEffect, useResize } from '@laser-ui/hooks';
|
|
5
5
|
import { setRef } from '@laser-ui/utils';
|
|
6
6
|
import CancelFilled from '@material-design-icons/svg/filled/cancel.svg?react';
|
|
7
7
|
import CalendarTodayOutlined from '@material-design-icons/svg/outlined/calendar_today.svg?react';
|
|
8
8
|
import SwapHorizOutlined from '@material-design-icons/svg/outlined/swap_horiz.svg?react';
|
|
9
9
|
import { isArray, isBoolean, isNull, isUndefined } from 'lodash';
|
|
10
|
-
import {
|
|
10
|
+
import { useImperativeHandle, useRef } from 'react';
|
|
11
11
|
import { DatePickerPanel } from './internal/DatePickerPanel';
|
|
12
12
|
import { CLASSES } from './vars';
|
|
13
13
|
import { BaseInput } from '../base-input';
|
|
@@ -23,8 +23,8 @@ import { Transition } from '../transition';
|
|
|
23
23
|
import { getVerticalSidePosition, mergeCS } from '../utils';
|
|
24
24
|
import { TTANSITION_DURING_POPUP, WINDOW_SPACE } from '../vars';
|
|
25
25
|
export function DatePicker(props) {
|
|
26
|
-
var _a
|
|
27
|
-
const
|
|
26
|
+
var _a;
|
|
27
|
+
const _b = useComponentProps('DatePicker', props), { ref, styleOverrides, styleProvider, formControl, model, defaultModel, visible: visibleProp, defaultVisible, placeholder, range = false, format: formatProp, order: orderProp = 'ascend', clearable: clearableProp = false, size: sizeProp, disabled: disabledProp = false, presetDate, config, showTime = false, escClosable = true, inputProps, onModelChange, onVisibleChange, onClear, afterVisibleChange } = _b, restProps = __rest(_b, ["ref", "styleOverrides", "styleProvider", "formControl", "model", "defaultModel", "visible", "defaultVisible", "placeholder", "range", "format", "order", "clearable", "size", "disabled", "presetDate", "config", "showTime", "escClosable", "inputProps", "onModelChange", "onVisibleChange", "onClear", "afterVisibleChange"]);
|
|
28
28
|
const namespace = useNamespace();
|
|
29
29
|
const styled = useStyled(CLASSES, {
|
|
30
30
|
'date-picker': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['date-picker'],
|
|
@@ -32,87 +32,130 @@ export function DatePicker(props) {
|
|
|
32
32
|
'date-picker-popup': styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider['date-picker-popup'],
|
|
33
33
|
}, styleOverrides);
|
|
34
34
|
const { t } = useTranslation();
|
|
35
|
-
const forceUpdate = useForceUpdate();
|
|
36
35
|
const async = useAsync();
|
|
37
36
|
const { contentResizeRef } = useLayout();
|
|
38
37
|
const boxRef = useRef(null);
|
|
39
38
|
const popupRef = useRef(null);
|
|
40
|
-
const
|
|
41
|
-
const
|
|
39
|
+
const inputStartRef = useRef(null);
|
|
40
|
+
const inputEndRef = useRef(null);
|
|
42
41
|
const indicatorRef = useRef(null);
|
|
43
42
|
const panelRef = useRef(null);
|
|
44
43
|
const timePickerPanelRef = useRef(null);
|
|
45
44
|
const updatePanel = (date) => {
|
|
46
45
|
var _a, _b;
|
|
47
|
-
(
|
|
48
|
-
|
|
46
|
+
if (visible) {
|
|
47
|
+
(_a = panelRef.current) === null || _a === void 0 ? void 0 : _a.call(panelRef, date);
|
|
48
|
+
(_b = timePickerPanelRef.current) === null || _b === void 0 ? void 0 : _b.call(timePickerPanelRef, date);
|
|
49
|
+
}
|
|
49
50
|
};
|
|
50
|
-
const dataRef = useRef({
|
|
51
|
-
latestFocused: 'start',
|
|
52
|
-
onceVisible: false,
|
|
53
|
-
focusAnother: false,
|
|
54
|
-
inputValue: [undefined, undefined],
|
|
55
|
-
rangeDate: [null, null],
|
|
56
|
-
});
|
|
51
|
+
const dataRef = useRef({ focusWithoutUser: false });
|
|
57
52
|
const format = isUndefined(formatProp) ? (showTime ? 'YYYY-MM-DD HH:mm:ss' : `YYYY-MM-DD`) : formatProp;
|
|
58
|
-
const order = (date) => orderDate(date, orderProp, showTime ? undefined : 'date');
|
|
59
53
|
const [visible, changeVisible] = useControlled(defaultVisible !== null && defaultVisible !== void 0 ? defaultVisible : false, visibleProp, onVisibleChange);
|
|
60
54
|
const [focused, setFocused] = useImmer([false, false]);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
const [value, _changeValue] = useControlled(defaultModel !== null && defaultModel !== void 0 ? defaultModel : null, model, onModelChange, (a, b) => deepCompareDate(a, b, format), formControl === null || formControl === void 0 ? void 0 : formControl.control);
|
|
56
|
+
const [placeholderValues, setPlaceholderValues] = useImmer(() => {
|
|
57
|
+
let values = ['', ''];
|
|
58
|
+
if (value) {
|
|
59
|
+
if (range) {
|
|
60
|
+
values = value.map((v) => dayjs(v).format(format));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
values[0] = dayjs(value).format(format);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return values;
|
|
67
|
+
});
|
|
68
|
+
const newPlaceholderValues = (() => {
|
|
69
|
+
if (focused.some((f) => f)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (isNull(value)) {
|
|
73
|
+
if (placeholderValues.some((p) => p)) {
|
|
74
|
+
return ['', ''];
|
|
75
|
+
}
|
|
72
76
|
}
|
|
73
77
|
else {
|
|
74
|
-
|
|
78
|
+
if (isArray(value)) {
|
|
79
|
+
const currentPlaceholder = value.map((v) => dayjs(v).format(format));
|
|
80
|
+
if (currentPlaceholder.some((p, i) => p !== placeholderValues[i])) {
|
|
81
|
+
return currentPlaceholder;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
const currentPlaceholder = dayjs(value).format(format);
|
|
86
|
+
if (currentPlaceholder !== placeholderValues[0]) {
|
|
87
|
+
return [currentPlaceholder, ''];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
75
90
|
}
|
|
91
|
+
})();
|
|
92
|
+
if (!isUndefined(newPlaceholderValues)) {
|
|
93
|
+
setPlaceholderValues(newPlaceholderValues);
|
|
76
94
|
}
|
|
77
|
-
const
|
|
78
|
-
? dataRef.current.inputValue[index]
|
|
79
|
-
: (() => {
|
|
80
|
-
const value = index === 0 ? valueLeft : valueRight;
|
|
81
|
-
return isNull(value) ? '' : dayjs(value).format(format);
|
|
82
|
-
})());
|
|
95
|
+
const placeholderDates = placeholderValues.map((v) => (v && dayjs(v, format, true).isValid() ? dayjs(v, format).toDate() : null));
|
|
83
96
|
const changeValue = (date) => {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
if (isNull(date)) {
|
|
98
|
+
_changeValue(null);
|
|
99
|
+
setPlaceholderValues(['', '']);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (range) {
|
|
103
|
+
let newValue = [...placeholderDates];
|
|
104
|
+
if (isArray(date)) {
|
|
105
|
+
newValue = date;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
newValue[focused[0] ? 0 : 1] = date;
|
|
109
|
+
}
|
|
110
|
+
if (newValue.every((v) => !isNull(v))) {
|
|
111
|
+
const reverse = orderDate(newValue, orderProp, showTime ? undefined : 'date');
|
|
112
|
+
if (reverse) {
|
|
113
|
+
newValue.reverse();
|
|
114
|
+
const inputEl = focused[0] ? inputEndRef.current : inputStartRef.current;
|
|
115
|
+
if (inputEl) {
|
|
116
|
+
dataRef.current.focusWithoutUser = true;
|
|
117
|
+
inputEl.focus({ preventScroll: true });
|
|
118
|
+
}
|
|
92
119
|
}
|
|
93
|
-
|
|
94
|
-
_changeValue(dataRef.current.rangeDate);
|
|
120
|
+
_changeValue(newValue);
|
|
95
121
|
}
|
|
122
|
+
setPlaceholderValues(newValue.map((v) => (v ? dayjs(v).format(format) : '')));
|
|
96
123
|
}
|
|
97
124
|
else {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
draft[index] = date;
|
|
101
|
-
dataRef.current.focusAnother = order(draft);
|
|
102
|
-
if (dataRef.current.focusAnother) {
|
|
103
|
-
draft.reverse();
|
|
104
|
-
}
|
|
105
|
-
});
|
|
125
|
+
_changeValue(date);
|
|
126
|
+
setPlaceholderValues([dayjs(date).format(format), '']);
|
|
106
127
|
}
|
|
107
128
|
}
|
|
129
|
+
};
|
|
130
|
+
const handleEnter = (date) => {
|
|
131
|
+
if (isArray(date)) {
|
|
132
|
+
updatePanel(date[focused[0] ? 0 : 1]);
|
|
133
|
+
changeVisible(false);
|
|
134
|
+
dataRef.current.lastVisible = focused[0] ? 'start' : 'end';
|
|
135
|
+
}
|
|
108
136
|
else {
|
|
109
|
-
|
|
110
|
-
|
|
137
|
+
updatePanel(date);
|
|
138
|
+
if (range) {
|
|
139
|
+
if (placeholderDates[focused[0] ? 1 : 0]) {
|
|
140
|
+
changeVisible(false);
|
|
141
|
+
dataRef.current.lastVisible = focused[0] ? 'start' : 'end';
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
const inputEl = focused[0] ? inputEndRef.current : inputStartRef.current;
|
|
145
|
+
if (inputEl) {
|
|
146
|
+
dataRef.current.focusWithoutUser = true;
|
|
147
|
+
inputEl.focus({ preventScroll: true });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
changeVisible(false);
|
|
153
|
+
dataRef.current.lastVisible = 'start';
|
|
154
|
+
}
|
|
111
155
|
}
|
|
112
|
-
forceUpdate();
|
|
113
156
|
};
|
|
114
|
-
const [
|
|
115
|
-
? ((
|
|
157
|
+
const [placeholderStart = t('DatePicker', range ? 'Start date' : 'Select date'), placeholderEnd = t('DatePicker', 'End date')] = range
|
|
158
|
+
? ((_a = placeholder) !== null && _a !== void 0 ? _a : [])
|
|
116
159
|
: [placeholder];
|
|
117
160
|
const { size, disabled } = useScopedProps({ size: sizeProp, disabled: disabledProp || (formControl === null || formControl === void 0 ? void 0 : formControl.control.disabled) });
|
|
118
161
|
const zIndexValue = useZIndex(visible);
|
|
@@ -132,6 +175,24 @@ export function DatePicker(props) {
|
|
|
132
175
|
popupRef.current.style.maxWidth = maxWidth + 'px';
|
|
133
176
|
}
|
|
134
177
|
});
|
|
178
|
+
const updatePanelWhenEnter = useEventCallback(() => {
|
|
179
|
+
const update = () => {
|
|
180
|
+
const date = placeholderDates[focused[0] ? 0 : 1];
|
|
181
|
+
if (date) {
|
|
182
|
+
updatePanel(date);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
if (range) {
|
|
186
|
+
if ((focused[0] ? 'start' : 'end') !== dataRef.current.lastVisible) {
|
|
187
|
+
update();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
if (dataRef.current.lastVisible !== 'start') {
|
|
192
|
+
update();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
135
196
|
useContainerScrolling(boxRef, updatePosition, !visible);
|
|
136
197
|
useResize(boxRef, updatePosition, undefined, !visible);
|
|
137
198
|
useResize(popupRef, updatePosition, undefined, !visible);
|
|
@@ -143,13 +204,13 @@ export function DatePicker(props) {
|
|
|
143
204
|
if (boxRef.current && indicatorRef.current) {
|
|
144
205
|
let focus = false;
|
|
145
206
|
const boxRect = boxRef.current.getBoundingClientRect();
|
|
146
|
-
if (
|
|
147
|
-
const rect =
|
|
207
|
+
if (inputStartRef.current && document.activeElement === inputStartRef.current) {
|
|
208
|
+
const rect = inputStartRef.current.getBoundingClientRect();
|
|
148
209
|
indicatorRef.current.style.cssText = `left:${rect.left - boxRect.left}px;width:${rect.width}px;opacity:1;`;
|
|
149
210
|
focus = true;
|
|
150
211
|
}
|
|
151
|
-
if (
|
|
152
|
-
const rect =
|
|
212
|
+
if (inputEndRef.current && document.activeElement === inputEndRef.current) {
|
|
213
|
+
const rect = inputEndRef.current.getBoundingClientRect();
|
|
153
214
|
indicatorRef.current.style.cssText = `left:${rect.left - boxRect.left}px;width:${rect.width}px;opacity:1;`;
|
|
154
215
|
focus = true;
|
|
155
216
|
}
|
|
@@ -158,43 +219,11 @@ export function DatePicker(props) {
|
|
|
158
219
|
}
|
|
159
220
|
}
|
|
160
221
|
});
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const el = document.activeElement.parentElement;
|
|
164
|
-
for (let index = 0; index < el.childElementCount; index++) {
|
|
165
|
-
const element = el.children.item(index);
|
|
166
|
-
if (element.tagName.toLowerCase() === 'input' && element !== document.activeElement) {
|
|
167
|
-
element.focus({ preventScroll: true });
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
dataRef.current.focusAnother = false;
|
|
173
|
-
});
|
|
174
|
-
const handleEnter = (date) => {
|
|
175
|
-
if (range) {
|
|
176
|
-
const index = focused.findIndex((f) => f);
|
|
177
|
-
if (isNull(index === 0 ? valueRight : valueLeft)) {
|
|
178
|
-
dataRef.current.focusAnother = true;
|
|
179
|
-
forceUpdate();
|
|
180
|
-
}
|
|
181
|
-
else {
|
|
182
|
-
changeVisible(false);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
changeVisible(false);
|
|
187
|
-
}
|
|
188
|
-
if (!dataRef.current.focusAnother) {
|
|
189
|
-
updatePanel(date);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
const clearable = clearableProp && !isNull(_value) && !visible && !disabled;
|
|
193
|
-
const inputNode = (isLeft) => {
|
|
222
|
+
const clearable = clearableProp && !disabled && !visible && placeholderValues.some((p) => p);
|
|
223
|
+
const inputNode = (isStart) => {
|
|
194
224
|
var _a, _b;
|
|
195
|
-
const index =
|
|
196
|
-
const
|
|
197
|
-
const inputRef = isLeft ? inputLeftRef : inputRightRef;
|
|
225
|
+
const index = isStart ? 0 : 1;
|
|
226
|
+
const inputRef = isStart ? inputStartRef : inputEndRef;
|
|
198
227
|
return (_jsx(BaseInput, Object.assign({}, inputProps === null || inputProps === void 0 ? void 0 : inputProps[index], mergeCS(styled('date-picker__input'), {
|
|
199
228
|
className: (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps[index]) === null || _a === void 0 ? void 0 : _a.className,
|
|
200
229
|
style: (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps[index]) === null || _b === void 0 ? void 0 : _b.style,
|
|
@@ -206,13 +235,29 @@ export function DatePicker(props) {
|
|
|
206
235
|
inputRef.current = null;
|
|
207
236
|
ret();
|
|
208
237
|
};
|
|
209
|
-
}, type: "text", autoComplete: "off", value:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
238
|
+
}, type: "text", autoComplete: "off", value: placeholderValues[index], size: 22, placeholder: isStart ? placeholderStart : placeholderEnd, disabled: disabled, onValueChange: (val) => {
|
|
239
|
+
const values = [...placeholderValues];
|
|
240
|
+
values[index] = val;
|
|
241
|
+
setPlaceholderValues(values);
|
|
242
|
+
if (range) {
|
|
243
|
+
if (values.every((v) => !v)) {
|
|
244
|
+
_changeValue(null);
|
|
245
|
+
}
|
|
246
|
+
else if (values.every((v) => v && dayjs(v, format, true).isValid())) {
|
|
247
|
+
const dates = values.map((v) => dayjs(v, format).toDate());
|
|
248
|
+
_changeValue(dates);
|
|
249
|
+
updatePanel(dates[index]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
if (!values[index]) {
|
|
254
|
+
_changeValue(null);
|
|
255
|
+
}
|
|
256
|
+
else if (values[index] && dayjs(values[index], format, true).isValid()) {
|
|
257
|
+
const date = dayjs(values[index], format).toDate();
|
|
258
|
+
_changeValue(date);
|
|
259
|
+
updatePanel(date);
|
|
260
|
+
}
|
|
216
261
|
}
|
|
217
262
|
}, onKeyDown: (e) => {
|
|
218
263
|
var _a, _b;
|
|
@@ -222,12 +267,14 @@ export function DatePicker(props) {
|
|
|
222
267
|
e.stopPropagation();
|
|
223
268
|
e.preventDefault();
|
|
224
269
|
changeVisible(false);
|
|
270
|
+
dataRef.current.lastVisible = isStart ? 'start' : 'end';
|
|
225
271
|
}
|
|
226
272
|
}
|
|
227
|
-
else if (e.code === 'Enter'
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
273
|
+
else if (e.code === 'Enter') {
|
|
274
|
+
if (placeholderDates[index]) {
|
|
275
|
+
e.preventDefault();
|
|
276
|
+
handleEnter(placeholderDates[index]);
|
|
277
|
+
}
|
|
231
278
|
}
|
|
232
279
|
}, onFocus: (e) => {
|
|
233
280
|
var _a, _b, _c, _d;
|
|
@@ -235,25 +282,26 @@ export function DatePicker(props) {
|
|
|
235
282
|
(_d = (_c = dataRef.current).clearTid) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
236
283
|
setFocused((draft) => {
|
|
237
284
|
draft.fill(false);
|
|
238
|
-
draft[
|
|
285
|
+
draft[index] = true;
|
|
239
286
|
});
|
|
240
|
-
dataRef.current.
|
|
241
|
-
|
|
242
|
-
updatePanel(value);
|
|
287
|
+
if (range && !dataRef.current.focusWithoutUser && placeholderDates[index]) {
|
|
288
|
+
updatePanel(placeholderDates[index]);
|
|
243
289
|
}
|
|
290
|
+
dataRef.current.focusWithoutUser = false;
|
|
244
291
|
}, onBlur: (e) => {
|
|
245
292
|
var _a, _b;
|
|
246
293
|
(_b = (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps[index]) === null || _a === void 0 ? void 0 : _a.onBlur) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
247
294
|
dataRef.current.clearTid = async.setTimeout(() => {
|
|
248
295
|
setFocused([false, false]);
|
|
249
296
|
changeVisible(false);
|
|
297
|
+
dataRef.current.lastVisible = isStart ? 'start' : 'end';
|
|
250
298
|
}, 20);
|
|
251
299
|
} })));
|
|
252
300
|
};
|
|
253
301
|
const preventBlur = (e) => {
|
|
254
|
-
if ((document.activeElement ===
|
|
255
|
-
e.target !==
|
|
256
|
-
e.target !==
|
|
302
|
+
if ((document.activeElement === inputStartRef.current || document.activeElement === inputEndRef.current) &&
|
|
303
|
+
e.target !== inputStartRef.current &&
|
|
304
|
+
e.target !== inputEndRef.current &&
|
|
257
305
|
e.button === 0) {
|
|
258
306
|
e.preventDefault();
|
|
259
307
|
}
|
|
@@ -281,7 +329,8 @@ export function DatePicker(props) {
|
|
|
281
329
|
var _a, _b;
|
|
282
330
|
(_a = restProps.onClick) === null || _a === void 0 ? void 0 : _a.call(restProps, e);
|
|
283
331
|
if (!focused.some((f) => f)) {
|
|
284
|
-
|
|
332
|
+
dataRef.current.focusWithoutUser = true;
|
|
333
|
+
(_b = inputStartRef.current) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true });
|
|
285
334
|
}
|
|
286
335
|
changeVisible(true);
|
|
287
336
|
}, children: [inputNode(true), range && (_jsxs(_Fragment, { children: [_jsx("div", Object.assign({}, styled('date-picker__indicator'), { ref: (instance) => {
|
|
@@ -291,8 +340,7 @@ export function DatePicker(props) {
|
|
|
291
340
|
};
|
|
292
341
|
} })), _jsx("div", Object.assign({}, styled('date-picker__separator'), { children: _jsx(Icon, { children: _jsx(SwapHorizOutlined, {}) }) })), inputNode(false)] })), clearable && (_jsx("div", Object.assign({}, styled('date-picker__clear'), { role: "button", "aria-label": t('Clear'), onClick: (e) => {
|
|
293
342
|
e.stopPropagation();
|
|
294
|
-
|
|
295
|
-
_changeValue(null);
|
|
343
|
+
changeValue(null);
|
|
296
344
|
onClear === null || onClear === void 0 ? void 0 : onClear();
|
|
297
345
|
}, children: _jsx(Icon, { children: _jsx(CancelFilled, {}) }) }))), _jsx("div", Object.assign({}, mergeCS(styled('date-picker__icon'), {
|
|
298
346
|
style: { visibility: clearable ? 'hidden' : undefined },
|
|
@@ -306,34 +354,10 @@ export function DatePicker(props) {
|
|
|
306
354
|
return el;
|
|
307
355
|
}, children: _jsx(Transition, { enter: visible, name: `${namespace}-popup-down`, duration: TTANSITION_DURING_POPUP, onSkipEnter: () => {
|
|
308
356
|
updatePosition();
|
|
309
|
-
|
|
310
|
-
const value = focused[0] ? valueLeft : valueRight;
|
|
311
|
-
if (value) {
|
|
312
|
-
updatePanel(value);
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
if (range) {
|
|
316
|
-
cb();
|
|
317
|
-
}
|
|
318
|
-
else if (!dataRef.current.onceVisible) {
|
|
319
|
-
dataRef.current.onceVisible = true;
|
|
320
|
-
cb();
|
|
321
|
-
}
|
|
357
|
+
updatePanelWhenEnter();
|
|
322
358
|
}, onBeforeEnter: () => {
|
|
323
359
|
updatePosition();
|
|
324
|
-
|
|
325
|
-
const value = focused[0] ? valueLeft : valueRight;
|
|
326
|
-
if (value) {
|
|
327
|
-
updatePanel(value);
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
if (range) {
|
|
331
|
-
cb();
|
|
332
|
-
}
|
|
333
|
-
else if (!dataRef.current.onceVisible) {
|
|
334
|
-
dataRef.current.onceVisible = true;
|
|
335
|
-
cb();
|
|
336
|
-
}
|
|
360
|
+
updatePanelWhenEnter();
|
|
337
361
|
}, onAfterEnter: () => {
|
|
338
362
|
afterVisibleChange === null || afterVisibleChange === void 0 ? void 0 : afterVisibleChange(true);
|
|
339
363
|
}, onAfterLeave: () => {
|
|
@@ -351,32 +375,16 @@ export function DatePicker(props) {
|
|
|
351
375
|
preventBlur(e);
|
|
352
376
|
}, onMouseUp: (e) => {
|
|
353
377
|
preventBlur(e);
|
|
354
|
-
}, children: [presetDate && (_jsx("ul", Object.assign({}, styled('date-picker__preset'), { children: Object.keys(presetDate).map((name) => {
|
|
355
|
-
const handleClick = () => {
|
|
378
|
+
}, children: [presetDate && (_jsx("ul", Object.assign({}, styled('date-picker__preset'), { children: Object.keys(presetDate).map((name) => (_createElement("li", Object.assign({}, styled('date-picker__preset-option'), { key: name, role: "button", onClick: () => {
|
|
356
379
|
const date = presetDate[name]();
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
_changeValue(date);
|
|
361
|
-
changeVisible(false);
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
changeValue(date);
|
|
365
|
-
handleEnter(date);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
_changeValue(date);
|
|
370
|
-
handleEnter(date);
|
|
371
|
-
}
|
|
372
|
-
};
|
|
373
|
-
return (_createElement("li", Object.assign({}, styled('date-picker__preset-option'), { key: name, role: "button", onClick: handleClick }), name));
|
|
374
|
-
}) }))), _jsxs("div", Object.assign({}, styled('date-picker__panel-wrapper'), { children: [_jsx(DatePickerPanel, { ref: (instance) => {
|
|
380
|
+
changeValue(date);
|
|
381
|
+
handleEnter(date);
|
|
382
|
+
} }), name))) }))), _jsxs("div", Object.assign({}, styled('date-picker__panel-wrapper'), { children: [_jsx(DatePickerPanel, { ref: (instance) => {
|
|
375
383
|
panelRef.current = instance;
|
|
376
384
|
return () => {
|
|
377
385
|
panelRef.current = null;
|
|
378
386
|
};
|
|
379
|
-
}, styled: styled, currentSelected:
|
|
387
|
+
}, styled: styled, currentSelected: placeholderDates[focused[0] ? 0 : 1], anotherSelected: placeholderDates[focused[0] ? 1 : 0], config: config ? (...args) => config(...args, focused[0] ? 'start' : 'end', placeholderDates) : undefined, range: range, onDateChange: (date) => {
|
|
380
388
|
changeValue(date);
|
|
381
389
|
if (!showTime) {
|
|
382
390
|
handleEnter(date);
|
|
@@ -386,11 +394,11 @@ export function DatePicker(props) {
|
|
|
386
394
|
return () => {
|
|
387
395
|
timePickerPanelRef.current = null;
|
|
388
396
|
};
|
|
389
|
-
}, styled: styled, time:
|
|
397
|
+
}, styled: styled, time: placeholderDates[focused[0] ? 0 : 1], format: format, config: (() => {
|
|
390
398
|
if (showTime && !isBoolean(showTime)) {
|
|
391
399
|
const fn = showTime.config;
|
|
392
400
|
if (fn) {
|
|
393
|
-
return (...args) => fn(...args,
|
|
401
|
+
return (...args) => fn(...args, focused[0] ? 'start' : 'end', placeholderDates);
|
|
394
402
|
}
|
|
395
403
|
}
|
|
396
404
|
})(), inDatePicker: true, onTimeChange: (time) => {
|
package/dropdown/Dropdown.js
CHANGED
|
@@ -27,11 +27,7 @@ export function Dropdown(props) {
|
|
|
27
27
|
const updateSubPosition = useRef(new Map());
|
|
28
28
|
const [focusVisible, focusVisibleProps] = useFocusVisible((code) => code.startsWith('Arrow') || ['Home', 'End', 'Enter', 'Space'].includes(code));
|
|
29
29
|
const [visible, changeVisible] = useControlled(defaultVisible !== null && defaultVisible !== void 0 ? defaultVisible : false, visibleProp, onVisibleChange);
|
|
30
|
-
const {
|
|
31
|
-
if (!visible) {
|
|
32
|
-
popupIdsRef.current = [];
|
|
33
|
-
}
|
|
34
|
-
const popupIds = popupIdsRef.current;
|
|
30
|
+
const { popupIds, setPopupIds, addPopupId, removePopupId } = useNestedPopup(visible);
|
|
35
31
|
const [focusIds, setFocusIds] = useState([]);
|
|
36
32
|
const focusId = (() => {
|
|
37
33
|
var _a;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import type { DraftFunction } from '@laser-ui/hooks/useImmer';
|
|
2
1
|
interface PopupId<ID> {
|
|
3
2
|
id: ID;
|
|
4
3
|
visible: boolean;
|
|
5
4
|
}
|
|
6
|
-
export declare function useNestedPopup<ID>(): {
|
|
7
|
-
|
|
8
|
-
setPopupIds: (
|
|
5
|
+
export declare function useNestedPopup<ID>(visible?: boolean): {
|
|
6
|
+
popupIds: PopupId<ID>[];
|
|
7
|
+
setPopupIds: import("@laser-ui/hooks/useImmer").Updater<PopupId<ID>[]>;
|
|
9
8
|
addPopupId: (id: ID) => void;
|
|
10
9
|
removePopupId: (id: ID) => void;
|
|
11
10
|
};
|
package/hooks/useNestedPopup.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const popupIdsRef = useRef([]);
|
|
8
|
-
const setPopupIds = (value) => {
|
|
9
|
-
popupIdsRef.current = isFunction(value) ? produce(popupIdsRef.current, value) : freeze(value);
|
|
10
|
-
forceUpdate();
|
|
11
|
-
};
|
|
1
|
+
import { useImmer } from '@laser-ui/hooks';
|
|
2
|
+
export function useNestedPopup(visible = true) {
|
|
3
|
+
const [popupIds, setPopupIds] = useImmer([]);
|
|
4
|
+
if (!visible && popupIds.length > 0) {
|
|
5
|
+
setPopupIds([]);
|
|
6
|
+
}
|
|
12
7
|
return {
|
|
13
|
-
|
|
8
|
+
popupIds,
|
|
14
9
|
setPopupIds,
|
|
15
10
|
addPopupId: (id) => {
|
|
16
11
|
setPopupIds((draft) => {
|
package/image/Image.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useForceUpdate } from '@laser-ui/hooks';
|
|
4
3
|
import { checkNodeExist } from '@laser-ui/utils';
|
|
5
4
|
import { has } from 'lodash';
|
|
6
|
-
import { Fragment,
|
|
5
|
+
import { Fragment, useState } from 'react';
|
|
7
6
|
import { ImageAction } from './ImageAction';
|
|
8
7
|
import { ImageLoader } from './ImageLoader';
|
|
9
8
|
import { ImagePreview } from './ImagePreview';
|
|
@@ -13,42 +12,37 @@ import { mergeCS } from '../utils';
|
|
|
13
12
|
export const Image = (props) => {
|
|
14
13
|
const _a = useComponentProps('Image', props), { styleOverrides, styleProvider, loading, error, actions, imgProps } = _a, restProps = __rest(_a, ["styleOverrides", "styleProvider", "loading", "error", "actions", "imgProps"]);
|
|
15
14
|
const styled = useStyled(CLASSES, { image: styleProvider === null || styleProvider === void 0 ? void 0 : styleProvider.image }, styleOverrides);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
dataRef.current.isLoading = true;
|
|
24
|
-
dataRef.current.isError = false;
|
|
15
|
+
const [previousSrc, setPreviousSrc] = useState(imgProps.src);
|
|
16
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
17
|
+
const [isError, setIsError] = useState(false);
|
|
18
|
+
if (imgProps.src !== previousSrc) {
|
|
19
|
+
setPreviousSrc(imgProps.src);
|
|
20
|
+
setIsLoading(true);
|
|
21
|
+
setIsError(false);
|
|
25
22
|
}
|
|
26
23
|
return (_jsxs("div", Object.assign({}, restProps, mergeCS(styled('image'), {
|
|
27
24
|
className: restProps.className,
|
|
28
25
|
style: restProps.style,
|
|
29
|
-
}), { children: [
|
|
26
|
+
}), { children: [isLoading && checkNodeExist(loading) && loading, isError && checkNodeExist(error) && error, actions && (_jsx("div", Object.assign({}, styled('image__actions'), { children: actions.map((node, index) => {
|
|
30
27
|
const { id, action } = (has(node, ['id', 'action']) ? node : { id: index, action: node });
|
|
31
28
|
return _jsx(Fragment, { children: action }, id);
|
|
32
29
|
}) }))), _jsx("img", Object.assign({}, imgProps, mergeCS(styled('image__img'), {
|
|
33
30
|
className: imgProps === null || imgProps === void 0 ? void 0 : imgProps.className,
|
|
34
|
-
style: Object.assign(Object.assign({}, imgProps === null || imgProps === void 0 ? void 0 : imgProps.style), { display: (
|
|
31
|
+
style: Object.assign(Object.assign({}, imgProps === null || imgProps === void 0 ? void 0 : imgProps.style), { display: (isLoading && loading) || (isError && error) ? 'none' : undefined }),
|
|
35
32
|
}), { onLoadStart: (e) => {
|
|
36
33
|
var _a;
|
|
37
34
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=458851
|
|
38
35
|
(_a = imgProps === null || imgProps === void 0 ? void 0 : imgProps.onLoadStart) === null || _a === void 0 ? void 0 : _a.call(imgProps, e);
|
|
39
|
-
|
|
40
|
-
forceUpdate();
|
|
36
|
+
setIsLoading(true);
|
|
41
37
|
}, onLoad: (e) => {
|
|
42
38
|
var _a;
|
|
43
39
|
(_a = imgProps === null || imgProps === void 0 ? void 0 : imgProps.onLoad) === null || _a === void 0 ? void 0 : _a.call(imgProps, e);
|
|
44
|
-
|
|
45
|
-
forceUpdate();
|
|
40
|
+
setIsLoading(false);
|
|
46
41
|
}, onError: (e) => {
|
|
47
42
|
var _a;
|
|
48
43
|
(_a = imgProps === null || imgProps === void 0 ? void 0 : imgProps.onError) === null || _a === void 0 ? void 0 : _a.call(imgProps, e);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
forceUpdate();
|
|
44
|
+
setIsLoading(false);
|
|
45
|
+
setIsError(true);
|
|
52
46
|
} }))] })));
|
|
53
47
|
};
|
|
54
48
|
Image.Loader = ImageLoader;
|