@oceanbase/ui 1.0.0-alpha.16 → 1.0.0-alpha.18
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/dist/ui.min.js +1 -1
- package/es/DateRanger/EditableDateTimeInput.d.ts +6 -1
- package/es/DateRanger/EditableDateTimeInput.js +21 -11
- package/es/DateRanger/Ranger.d.ts +4 -1
- package/es/DateRanger/Ranger.js +25 -9
- package/es/DateRanger/hooks/index.d.ts +1 -1
- package/es/DateRanger/hooks/useSegmentedInput.d.ts +8 -16
- package/es/DateRanger/hooks/useSegmentedInput.js +228 -351
- package/es/DateRanger/style/index.js +12 -4
- package/es/Highlight/index.d.ts +1 -1
- package/lib/DateRanger/EditableDateTimeInput.d.ts +6 -1
- package/lib/DateRanger/EditableDateTimeInput.js +17 -10
- package/lib/DateRanger/Ranger.d.ts +4 -1
- package/lib/DateRanger/Ranger.js +23 -7
- package/lib/DateRanger/hooks/index.d.ts +1 -1
- package/lib/DateRanger/hooks/useSegmentedInput.d.ts +8 -16
- package/lib/DateRanger/hooks/useSegmentedInput.js +158 -298
- package/lib/DateRanger/style/index.js +14 -1
- package/lib/Highlight/index.d.ts +1 -1
- package/package.json +3 -3
|
@@ -6,114 +6,49 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.useSegmentedInput = exports.default = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _dayjs = _interopRequireDefault(require("dayjs"));
|
|
9
|
+
require("dayjs/locale/en");
|
|
10
|
+
require("dayjs/locale/zh-cn");
|
|
9
11
|
var _moment = _interopRequireDefault(require("moment"));
|
|
10
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
MM: {
|
|
25
|
-
type: 'month',
|
|
26
|
-
length: 2,
|
|
27
|
-
min: 1,
|
|
28
|
-
max: 12
|
|
29
|
-
},
|
|
30
|
-
DD: {
|
|
31
|
-
type: 'day',
|
|
32
|
-
length: 2,
|
|
33
|
-
min: 1,
|
|
34
|
-
max: 31
|
|
35
|
-
},
|
|
36
|
-
HH: {
|
|
37
|
-
type: 'hour',
|
|
38
|
-
length: 2,
|
|
39
|
-
min: 0,
|
|
40
|
-
max: 23
|
|
41
|
-
},
|
|
42
|
-
mm: {
|
|
43
|
-
type: 'minute',
|
|
44
|
-
length: 2,
|
|
45
|
-
min: 0,
|
|
46
|
-
max: 59
|
|
47
|
-
},
|
|
48
|
-
ss: {
|
|
49
|
-
type: 'second',
|
|
50
|
-
length: 2,
|
|
51
|
-
min: 0,
|
|
52
|
-
max: 59
|
|
13
|
+
// 常量
|
|
14
|
+
const RANGE_SEPARATORS = [' ~ ', '~', ' - ', ' – ', ' — '];
|
|
15
|
+
const TIMEZONE_PATTERN = /(\s*\(?(?:UTC|GMT)[+-]?\d*\)?)\s*$/i;
|
|
16
|
+
|
|
17
|
+
// 格式化日期值,确保使用正确的 locale
|
|
18
|
+
const formatDateValue = (date, formatStr, isMoment, isCn) => {
|
|
19
|
+
if (!date) return '';
|
|
20
|
+
const locale = isCn ? 'zh-cn' : 'en';
|
|
21
|
+
if (isMoment || _moment.default.isMoment(date)) {
|
|
22
|
+
return date.locale(locale).format(formatStr);
|
|
23
|
+
} else {
|
|
24
|
+
const dayjsInstance = _dayjs.default.isDayjs(date) ? date : (0, _dayjs.default)(date);
|
|
25
|
+
return dayjsInstance.locale(locale).format(formatStr);
|
|
53
26
|
}
|
|
54
27
|
};
|
|
55
28
|
|
|
56
|
-
//
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const config = SEGMENT_CONFIG[pattern];
|
|
65
|
-
const valueStart = formatIndex;
|
|
66
|
-
const valueEnd = formatIndex + config.length;
|
|
67
|
-
segments.push({
|
|
68
|
-
type: config.type,
|
|
69
|
-
range: rangeType,
|
|
70
|
-
start: offset + valueStart,
|
|
71
|
-
end: offset + valueEnd,
|
|
72
|
-
value: dateValue.substring(valueStart, valueEnd),
|
|
73
|
-
min: config.min,
|
|
74
|
-
max: config.max,
|
|
75
|
-
padLength: config.length
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
segments.sort((a, b) => a.start - b.start);
|
|
79
|
-
return segments;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// 根据光标位置找到当前段落
|
|
83
|
-
const findSegmentByPosition = (segments, position) => {
|
|
84
|
-
for (const segment of segments) {
|
|
85
|
-
if (position >= segment.start && position <= segment.end) {
|
|
86
|
-
return segment;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
let minDistance = Infinity;
|
|
90
|
-
let closestSegment = null;
|
|
91
|
-
for (const segment of segments) {
|
|
92
|
-
const distance = Math.min(Math.abs(position - segment.start), Math.abs(position - segment.end));
|
|
93
|
-
if (distance < minDistance) {
|
|
94
|
-
minDistance = distance;
|
|
95
|
-
closestSegment = segment;
|
|
29
|
+
// 解析粘贴文本,提取开始和结束时间字符串
|
|
30
|
+
const parsePastedText = text => {
|
|
31
|
+
for (const sep of RANGE_SEPARATORS) {
|
|
32
|
+
if (text.includes(sep)) {
|
|
33
|
+
const parts = text.split(sep);
|
|
34
|
+
if (parts.length === 2) {
|
|
35
|
+
return [parts[0].trim(), parts[1].trim()];
|
|
36
|
+
}
|
|
96
37
|
}
|
|
97
38
|
}
|
|
98
|
-
|
|
39
|
+
// 如果没有找到分隔符,使用整个文本作为开始和结束时间
|
|
40
|
+
return [text, text];
|
|
99
41
|
};
|
|
100
42
|
|
|
101
|
-
//
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
if (currentIndex < segments.length - 1) {
|
|
105
|
-
return segments[currentIndex + 1];
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
108
|
-
};
|
|
43
|
+
// 解析日期字符串
|
|
44
|
+
const parseDateString = (dateStr, formatStr, isMoment) => {
|
|
45
|
+
const strictParsed = isMoment ? (0, _moment.default)(dateStr, formatStr, true) : (0, _dayjs.default)(dateStr, formatStr, true);
|
|
109
46
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (currentIndex > 0) {
|
|
114
|
-
return segments[currentIndex - 1];
|
|
47
|
+
// 如果严格解析失败,尝试宽松解析
|
|
48
|
+
if (strictParsed.isValid()) {
|
|
49
|
+
return strictParsed;
|
|
115
50
|
}
|
|
116
|
-
return
|
|
51
|
+
return isMoment ? (0, _moment.default)(dateStr) : (0, _dayjs.default)(dateStr);
|
|
117
52
|
};
|
|
118
53
|
const useSegmentedInput = options => {
|
|
119
54
|
const {
|
|
@@ -123,250 +58,175 @@ const useSegmentedInput = options => {
|
|
|
123
58
|
baseFormat,
|
|
124
59
|
isMoment = false,
|
|
125
60
|
isCn = true,
|
|
126
|
-
onClick
|
|
61
|
+
onClick,
|
|
62
|
+
open = false
|
|
127
63
|
} = options;
|
|
128
64
|
const inputRef = (0, _react.useRef)(null);
|
|
129
65
|
const [isEditing, setIsEditing] = (0, _react.useState)(false);
|
|
130
|
-
|
|
131
|
-
const [
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (!startValue && !endValue)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return allSegments.find(s => `${s.range}-${s.type}` === currentSegmentKey) || null;
|
|
162
|
-
}, [currentSegmentKey, allSegments]);
|
|
163
|
-
|
|
164
|
-
// 创建新的日期对象
|
|
165
|
-
const createDate = (0, _react.useCallback)((dateStr, rangeType) => {
|
|
166
|
-
const formatToUse = rangeType === 'start' ? baseFormat : format;
|
|
167
|
-
if (isMoment) {
|
|
168
|
-
return (0, _moment.default)(dateStr, formatToUse);
|
|
66
|
+
// 粘贴值:仅作为预览,只有确认后才触发 onChange
|
|
67
|
+
const [pastedValue, setPastedValue] = (0, _react.useState)(null);
|
|
68
|
+
|
|
69
|
+
// 根据语言环境设置分隔符
|
|
70
|
+
const rangeSeparator = (0, _react.useMemo)(() => isCn ? ' ~ ' : ' - ', [isCn]);
|
|
71
|
+
|
|
72
|
+
// 显示值:有粘贴值时显示粘贴值(预览),否则显示原始 value
|
|
73
|
+
const [displayValue, setDisplayValue] = (0, _react.useState)('');
|
|
74
|
+
|
|
75
|
+
// 同步更新显示值
|
|
76
|
+
(0, _react.useEffect)(() => {
|
|
77
|
+
const displayDate = pastedValue || value;
|
|
78
|
+
const startDate = displayDate?.[0];
|
|
79
|
+
const endDate = displayDate?.[1];
|
|
80
|
+
const startValue = formatDateValue(startDate, baseFormat, isMoment, isCn);
|
|
81
|
+
const endValue = formatDateValue(endDate, format, isMoment, isCn);
|
|
82
|
+
if (!startValue && !endValue) {
|
|
83
|
+
setDisplayValue('');
|
|
84
|
+
} else {
|
|
85
|
+
setDisplayValue(`${startValue}${rangeSeparator}${endValue}`);
|
|
86
|
+
}
|
|
87
|
+
}, [pastedValue, value, baseFormat, format, rangeSeparator, isMoment, isCn]);
|
|
88
|
+
|
|
89
|
+
// 当 value 更新为 pastedValue 时,清除 pastedValue(说明确定按钮已生效)
|
|
90
|
+
(0, _react.useEffect)(() => {
|
|
91
|
+
if (pastedValue && value) {
|
|
92
|
+
const isSameAsPasted = pastedValue[0]?.valueOf() === value[0]?.valueOf() && pastedValue[1]?.valueOf() === value[1]?.valueOf();
|
|
93
|
+
if (isSameAsPasted) {
|
|
94
|
+
setPastedValue(null);
|
|
95
|
+
setIsEditing(false);
|
|
96
|
+
}
|
|
169
97
|
}
|
|
170
|
-
|
|
171
|
-
}, [isMoment, format, baseFormat]);
|
|
98
|
+
}, [value, pastedValue]);
|
|
172
99
|
|
|
173
|
-
//
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const localStart = segment.start - baseOffset;
|
|
180
|
-
const localEnd = segment.end - baseOffset;
|
|
181
|
-
const newDateValue = currentDateValue.substring(0, localStart) + paddedValue + currentDateValue.substring(localEnd);
|
|
182
|
-
const newDate = createDate(newDateValue, which);
|
|
183
|
-
if (newDate.isValid()) {
|
|
184
|
-
const newRange = which === 'start' ? [newDate, value?.[1] || newDate] : [value?.[0] || newDate, newDate];
|
|
185
|
-
onChange?.(newRange);
|
|
100
|
+
// 确认粘贴:触发 onChange,清除粘贴状态
|
|
101
|
+
const confirmPastedValue = (0, _react.useCallback)(() => {
|
|
102
|
+
if (pastedValue) {
|
|
103
|
+
onChange?.(pastedValue);
|
|
104
|
+
setPastedValue(null);
|
|
105
|
+
setIsEditing(false);
|
|
186
106
|
}
|
|
187
|
-
}, [
|
|
107
|
+
}, [pastedValue, onChange]);
|
|
188
108
|
|
|
189
|
-
//
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
setCurrentSegmentKey(`${segment.range}-${segment.type}`);
|
|
195
|
-
setInputBuffer('');
|
|
196
|
-
}
|
|
109
|
+
// 取消粘贴:清除粘贴值,回到初始值
|
|
110
|
+
const cancelPastedValue = (0, _react.useCallback)(() => {
|
|
111
|
+
setPastedValue(null);
|
|
112
|
+
setIsEditing(false);
|
|
113
|
+
inputRef.current?.input?.blur();
|
|
197
114
|
}, []);
|
|
198
115
|
|
|
199
|
-
//
|
|
116
|
+
// 单击获取焦点
|
|
200
117
|
const handleClick = (0, _react.useCallback)(e => {
|
|
201
118
|
e.stopPropagation();
|
|
202
119
|
setIsEditing(true);
|
|
120
|
+
// 让 input 获得焦点
|
|
121
|
+
setTimeout(() => {
|
|
122
|
+
inputRef.current?.input?.focus();
|
|
123
|
+
}, 0);
|
|
203
124
|
onClick?.();
|
|
204
|
-
|
|
205
|
-
const segment = findSegmentByPosition(allSegments, cursorPos);
|
|
206
|
-
if (segment) {
|
|
207
|
-
selectSegment(segment);
|
|
208
|
-
}
|
|
209
|
-
}, [allSegments, selectSegment, onClick]);
|
|
125
|
+
}, [onClick]);
|
|
210
126
|
|
|
211
|
-
//
|
|
127
|
+
// 双击获取焦点并全选
|
|
212
128
|
const handleDoubleClick = (0, _react.useCallback)(e => {
|
|
213
129
|
e.stopPropagation();
|
|
214
|
-
e.preventDefault();
|
|
215
130
|
setIsEditing(true);
|
|
216
|
-
setCurrentSegmentKey(null);
|
|
217
131
|
inputRef.current?.input?.select();
|
|
218
132
|
}, []);
|
|
219
133
|
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
if (
|
|
223
|
-
|
|
134
|
+
// 面板打开时,让 input 获得焦点
|
|
135
|
+
(0, _react.useEffect)(() => {
|
|
136
|
+
if (open) {
|
|
137
|
+
// 延迟获取焦点,确保面板已渲染
|
|
138
|
+
const timer = setTimeout(() => {
|
|
139
|
+
inputRef.current?.input?.focus();
|
|
140
|
+
}, 100);
|
|
141
|
+
return () => clearTimeout(timer);
|
|
142
|
+
}
|
|
143
|
+
}, [open]);
|
|
144
|
+
|
|
145
|
+
// 检查焦点是否在面板内(参考 ant-design 的实现)
|
|
146
|
+
const isFocusInPanel = (0, _react.useCallback)(relatedTarget => {
|
|
147
|
+
if (!relatedTarget) return false;
|
|
148
|
+
const panelElement = document.querySelector('.ant-picker-dropdown, .ant-dropdown, [class*="ranger-picker-panel"]');
|
|
149
|
+
return panelElement ? panelElement.contains(relatedTarget) : false;
|
|
150
|
+
}, []);
|
|
224
151
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const newBuffer = inputBuffer + key;
|
|
229
|
-
setInputBuffer(newBuffer);
|
|
230
|
-
const numValue = parseInt(newBuffer, 10);
|
|
231
|
-
const shouldJump = newBuffer.length >= currentSegment.padLength || numValue * 10 > currentSegment.max;
|
|
232
|
-
if (shouldJump) {
|
|
233
|
-
const clampedValue = Math.max(currentSegment.min, Math.min(currentSegment.max, numValue));
|
|
234
|
-
updateValue(currentSegment, String(clampedValue));
|
|
235
|
-
const nextSegment = getNextSegment(allSegments, currentSegment);
|
|
236
|
-
if (nextSegment) {
|
|
237
|
-
setTimeout(() => selectSegment(nextSegment), 0);
|
|
238
|
-
}
|
|
239
|
-
} else {
|
|
240
|
-
updateValue(currentSegment, newBuffer);
|
|
241
|
-
}
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
152
|
+
// 失去焦点处理(如果焦点在面板内,直接返回,不处理)
|
|
153
|
+
const handleBlur = (0, _react.useCallback)(e => {
|
|
154
|
+
const relatedTarget = e.relatedTarget;
|
|
244
155
|
|
|
245
|
-
//
|
|
246
|
-
if (
|
|
247
|
-
e.preventDefault();
|
|
248
|
-
const prevSegment = getPrevSegment(allSegments, currentSegment);
|
|
249
|
-
if (prevSegment) {
|
|
250
|
-
selectSegment(prevSegment);
|
|
251
|
-
}
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
if (key === 'ArrowRight') {
|
|
255
|
-
e.preventDefault();
|
|
256
|
-
const nextSegment = getNextSegment(allSegments, currentSegment);
|
|
257
|
-
if (nextSegment) {
|
|
258
|
-
selectSegment(nextSegment);
|
|
259
|
-
}
|
|
156
|
+
// 不强制重新获取焦点,允许用户在面板中的 input 正常编辑
|
|
157
|
+
if (isFocusInPanel(relatedTarget)) {
|
|
260
158
|
return;
|
|
261
159
|
}
|
|
262
160
|
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
161
|
+
// 焦点不在面板内,清除粘贴值
|
|
162
|
+
// 但是,如果 value 已经更新为 pastedValue,说明确定按钮已经生效,不应该清除
|
|
163
|
+
if (pastedValue) {
|
|
164
|
+
// 检查 value 是否已经更新为 pastedValue
|
|
165
|
+
const isValueUpdated = value && pastedValue[0]?.valueOf() === value[0]?.valueOf() && pastedValue[1]?.valueOf() === value[1]?.valueOf();
|
|
166
|
+
|
|
167
|
+
// 只有当 value 还没有更新为 pastedValue 时,才清除 pastedValue
|
|
168
|
+
// 这样可以避免在确定按钮点击后,失去焦点时清除已确认的值
|
|
169
|
+
if (!isValueUpdated) {
|
|
170
|
+
setPastedValue(null);
|
|
171
|
+
setIsEditing(false);
|
|
273
172
|
}
|
|
274
|
-
updateValue(currentSegment, String(newNum));
|
|
275
|
-
setTimeout(() => {
|
|
276
|
-
if (inputRef.current?.input && currentSegment) {
|
|
277
|
-
inputRef.current.input.setSelectionRange(currentSegment.start, currentSegment.end);
|
|
278
|
-
}
|
|
279
|
-
}, 0);
|
|
280
|
-
return;
|
|
281
173
|
}
|
|
174
|
+
}, [isFocusInPanel, pastedValue, value]);
|
|
282
175
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
176
|
+
// 解析粘贴文本并设置预览值
|
|
177
|
+
const processPaste = (0, _react.useCallback)(async pastedText => {
|
|
178
|
+
if (!pastedText.trim()) return;
|
|
179
|
+
const [startStr, endStr] = parsePastedText(pastedText.trim());
|
|
180
|
+
const formatWithoutTimezone = format.replace(TIMEZONE_PATTERN, '');
|
|
181
|
+
const parsedStart = parseDateString(startStr, baseFormat, isMoment);
|
|
182
|
+
const parsedEnd = parseDateString(endStr, formatWithoutTimezone, isMoment);
|
|
183
|
+
if (parsedStart.isValid() && parsedEnd.isValid()) {
|
|
184
|
+
setPastedValue([parsedStart, parsedEnd]);
|
|
185
|
+
setIsEditing(true);
|
|
291
186
|
}
|
|
187
|
+
}, [isMoment, format, baseFormat]);
|
|
292
188
|
|
|
293
|
-
|
|
294
|
-
|
|
189
|
+
// 键盘事件:Ctrl+V 粘贴,Enter 确认,Escape 取消
|
|
190
|
+
const handleKeyDown = (0, _react.useCallback)(async e => {
|
|
191
|
+
// Ctrl+V / Cmd+V 粘贴
|
|
192
|
+
if ((e.ctrlKey || e.metaKey) && e.key === 'v') {
|
|
295
193
|
e.preventDefault();
|
|
194
|
+
try {
|
|
195
|
+
const text = await navigator.clipboard.readText();
|
|
196
|
+
await processPaste(text);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.warn('Failed to read clipboard:', error);
|
|
199
|
+
}
|
|
296
200
|
return;
|
|
297
201
|
}
|
|
298
|
-
|
|
202
|
+
if (!pastedValue) return;
|
|
299
203
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const clampedValue = Math.max(currentSegment.min, Math.min(currentSegment.max, numValue));
|
|
305
|
-
updateValue(currentSegment, String(clampedValue));
|
|
306
|
-
}
|
|
307
|
-
setIsEditing(false);
|
|
308
|
-
setCurrentSegmentKey(null);
|
|
309
|
-
setInputBuffer('');
|
|
310
|
-
}, [currentSegment, inputBuffer, updateValue]);
|
|
311
|
-
|
|
312
|
-
// 处理粘贴事件
|
|
313
|
-
const handlePaste = (0, _react.useCallback)(e => {
|
|
314
|
-
e.preventDefault();
|
|
315
|
-
const pastedText = e.clipboardData.getData('text').trim();
|
|
316
|
-
if (!pastedText) return;
|
|
317
|
-
const separators = [' ~ ', '~', ' - ', ' – ', ' — '];
|
|
318
|
-
let startStr = '';
|
|
319
|
-
let endStr = '';
|
|
320
|
-
for (const sep of separators) {
|
|
321
|
-
if (pastedText.includes(sep)) {
|
|
322
|
-
const parts = pastedText.split(sep);
|
|
323
|
-
if (parts.length === 2) {
|
|
324
|
-
startStr = parts[0].trim();
|
|
325
|
-
endStr = parts[1].trim();
|
|
326
|
-
break;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
if (!startStr && !endStr) {
|
|
331
|
-
startStr = pastedText;
|
|
332
|
-
endStr = pastedText;
|
|
333
|
-
}
|
|
334
|
-
const formats = ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm', 'YYYY/MM/DD HH:mm:ss', 'YYYY/MM/DD HH:mm', 'MM/DD/YYYY HH:mm:ss', 'MM/DD/YYYY HH:mm', 'YYYY-MM-DD', 'YYYY/MM/DD', 'MM/DD/YYYY'];
|
|
335
|
-
let parsedStart = null;
|
|
336
|
-
let parsedEnd = null;
|
|
337
|
-
for (const fmt of formats) {
|
|
338
|
-
const tryStart = isMoment ? (0, _moment.default)(startStr, fmt, true) : (0, _dayjs.default)(startStr, fmt, true);
|
|
339
|
-
if (tryStart.isValid()) {
|
|
340
|
-
parsedStart = tryStart;
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
for (const fmt of formats) {
|
|
345
|
-
const tryEnd = isMoment ? (0, _moment.default)(endStr, fmt, true) : (0, _dayjs.default)(endStr, fmt, true);
|
|
346
|
-
if (tryEnd.isValid()) {
|
|
347
|
-
parsedEnd = tryEnd;
|
|
348
|
-
break;
|
|
349
|
-
}
|
|
204
|
+
// Enter 确认粘贴
|
|
205
|
+
if (e.key === 'Enter') {
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
confirmPastedValue();
|
|
350
208
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
} else if (parsedEnd) {
|
|
356
|
-
onChange?.([value?.[0] || parsedEnd, parsedEnd]);
|
|
209
|
+
// Escape 取消粘贴
|
|
210
|
+
else if (e.key === 'Escape') {
|
|
211
|
+
e.preventDefault();
|
|
212
|
+
cancelPastedValue();
|
|
357
213
|
}
|
|
358
|
-
}, [
|
|
214
|
+
}, [pastedValue, confirmPastedValue, cancelPastedValue, processPaste]);
|
|
215
|
+
// 获取粘贴值
|
|
216
|
+
const getPastedValue = (0, _react.useCallback)(() => {
|
|
217
|
+
return pastedValue;
|
|
218
|
+
}, [pastedValue]);
|
|
359
219
|
return {
|
|
360
220
|
inputRef,
|
|
361
221
|
isEditing,
|
|
362
222
|
displayValue,
|
|
363
|
-
currentSegment,
|
|
364
|
-
allSegments,
|
|
365
223
|
handleClick,
|
|
366
224
|
handleDoubleClick,
|
|
367
|
-
handleKeyDown,
|
|
368
225
|
handleBlur,
|
|
369
|
-
|
|
226
|
+
handleKeyDown,
|
|
227
|
+
confirmPastedValue,
|
|
228
|
+
hasPastedValue: !!pastedValue,
|
|
229
|
+
getPastedValue
|
|
370
230
|
};
|
|
371
231
|
};
|
|
372
232
|
exports.useSegmentedInput = useSegmentedInput;
|
|
@@ -130,6 +130,19 @@ const genDateRangerStyle = token => {
|
|
|
130
130
|
borderRadius: token.borderRadiusSM,
|
|
131
131
|
textAlign: 'center'
|
|
132
132
|
},
|
|
133
|
+
[`${componentCls}-dashed`]: {
|
|
134
|
+
[`${componentCls}-wrapper`]: {
|
|
135
|
+
borderStyle: 'dashed'
|
|
136
|
+
},
|
|
137
|
+
[`${componentCls}-playback-control`]: {
|
|
138
|
+
[`${antCls}-radio-button-wrapper`]: {
|
|
139
|
+
borderStyle: 'dashed',
|
|
140
|
+
'&::before': {
|
|
141
|
+
borderStyle: 'dashed'
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
133
146
|
[`${componentCls}-back-radio-focused`]: {
|
|
134
147
|
[`${componentCls}-wrapper`]: {
|
|
135
148
|
borderRightColor: token.gray7
|
|
@@ -177,7 +190,7 @@ const genDateRangerStyle = token => {
|
|
|
177
190
|
}
|
|
178
191
|
},
|
|
179
192
|
[`${componentCls}-range-editable-input`]: {
|
|
180
|
-
width:
|
|
193
|
+
width: 310,
|
|
181
194
|
cursor: 'text',
|
|
182
195
|
caretColor: 'transparent',
|
|
183
196
|
'&:focus, &:focus-within': {
|
package/lib/Highlight/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export declare const THEME_DARK = "dark";
|
|
|
28
28
|
export declare const THEME_LIGHT = "light";
|
|
29
29
|
declare const ThemeTypes: ["dark", "light"];
|
|
30
30
|
export type ThemeType = (typeof ThemeTypes)[number];
|
|
31
|
-
declare const supportedLanguages: ("
|
|
31
|
+
declare const supportedLanguages: ("css" | "json" | "jsx" | "tsx" | "ruby" | "javascript" | "typescript" | "groovy" | "java" | "python" | "bash" | "cpp" | "http" | "markdown" | "nginx" | "sql" | "xml" | "dockerfile" | "go" | "yaml" | "solidity")[];
|
|
32
32
|
export type LanguageType = (typeof supportedLanguages)[number] | 'html';
|
|
33
33
|
export interface HighlightProps extends LocaleWrapperProps {
|
|
34
34
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oceanbase/ui",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.18",
|
|
4
4
|
"description": "The UI library based on OceanBase Design",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"oceanbase",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@ant-design/cssinjs": "^1.24.0",
|
|
39
39
|
"@ant-design/pro-components": "^2.8.10",
|
|
40
40
|
"@inline-svg-unique-id/react": "^1.2.3",
|
|
41
|
-
"@oceanbase/design": "^1.0.0-alpha.
|
|
41
|
+
"@oceanbase/design": "^1.0.0-alpha.18",
|
|
42
42
|
"@oceanbase/icons": "^1.0.0-alpha.1",
|
|
43
43
|
"@oceanbase/util": "^1.0.0-alpha.2",
|
|
44
44
|
"ahooks": "^2.10.14",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"react": ">=16.9.0",
|
|
68
68
|
"react-dom": ">=16.9.0"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "fc43201ca1a59d2d8d54d0fece7fbb9dba9f7eb9"
|
|
71
71
|
}
|