@king-design/intact 3.5.1 → 3.6.0-beta.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/components/breadcrumb/demos/separator.md +4 -4
- package/components/breadcrumb/index.vdt +1 -1
- package/components/breadcrumb/styles.ts +3 -2
- package/components/button/index.md +1 -0
- package/components/datepicker/basepicker.ts +60 -13
- package/components/datepicker/calendar.ts +5 -1
- package/components/datepicker/calendar.vdt +20 -6
- package/components/datepicker/dayjs.ts +22 -2
- package/components/datepicker/demos/multiple.md +0 -5
- package/components/datepicker/demos/nowrap.md +35 -0
- package/components/datepicker/demos/yearMonth.md +8 -2
- package/components/datepicker/helpers.ts +5 -5
- package/components/datepicker/index.md +3 -2
- package/components/datepicker/index.spec.ts +107 -90
- package/components/datepicker/index.ts +23 -5
- package/components/datepicker/index.vdt +34 -35
- package/components/datepicker/styles.ts +102 -3
- package/components/datepicker/useDisabled.ts +3 -3
- package/components/datepicker/useFormats.ts +2 -0
- package/components/datepicker/useMergeRange.ts +54 -0
- package/components/datepicker/usePosition.ts +169 -0
- package/components/datepicker/useQuarters.ts +47 -0
- package/components/datepicker/useShowDate.ts +42 -11
- package/components/datepicker/useValue.ts +35 -4
- package/components/datepicker/useWeeks.ts +58 -0
- package/components/dialog/useFixBody.ts +7 -64
- package/components/ellipsis/styles.ts +4 -0
- package/components/form/styles.ts +1 -0
- package/components/scrollSelect/index.spec.ts +3 -3
- package/components/scrollSelect/useMouseEvents.ts +23 -10
- package/components/select/base.vdt +2 -1
- package/components/select/demos/creatable.md +13 -0
- package/components/select/index.md +1 -0
- package/components/select/index.spec.ts +180 -0
- package/components/select/option.ts +9 -1
- package/components/select/select.ts +2 -0
- package/components/select/useFilterable.ts +1 -1
- package/components/select/useInput.ts +4 -2
- package/components/select/useSearchable.ts +2 -2
- package/components/table/table.vdt +3 -3
- package/components/timepicker/demos/step.md +1 -1
- package/components/timepicker/panelPicker.vdt +5 -1
- package/components/timepicker/styles.ts +0 -1
- package/components/tour/demos/basic.md +73 -0
- package/components/tour/demos/beforeChange.md +109 -0
- package/components/tour/demos/closable.md +70 -0
- package/components/tour/demos/custom.md +98 -0
- package/components/tour/demos/customText.md +94 -0
- package/components/tour/demos/declarative.md +72 -0
- package/components/tour/demos/events.md +101 -0
- package/components/tour/demos/maskClosable.md +76 -0
- package/components/tour/demos/notarget.md +59 -0
- package/components/tour/index.md +48 -0
- package/components/tour/index.spec.ts +259 -0
- package/components/tour/index.ts +2 -0
- package/components/tour/step.ts +55 -0
- package/components/tour/step.vdt +75 -0
- package/components/tour/styles.ts +283 -0
- package/components/tour/tour.ts +107 -0
- package/components/tour/tour.vdt +83 -0
- package/components/tour/useArrow.ts +46 -0
- package/components/tour/useFixBody.ts +22 -0
- package/components/tour/useHighlight.ts +36 -0
- package/components/tour/useMaskClosable.ts +26 -0
- package/components/tour/useNavigation.ts +46 -0
- package/components/tour/usePosition.ts +91 -0
- package/components/tour/useSteps.ts +80 -0
- package/components/tree/useChecked.ts +6 -4
- package/components/treeSelect/index.spec.ts +13 -1
- package/components/virtualList/useVirtualRows.ts +1 -1
- package/es/components/breadcrumb/index.vdt.js +2 -1
- package/es/components/breadcrumb/styles.js +5 -3
- package/es/components/datepicker/basepicker.d.ts +4 -2
- package/es/components/datepicker/basepicker.js +46 -13
- package/es/components/datepicker/calendar.d.ts +34 -6
- package/es/components/datepicker/calendar.js +4 -0
- package/es/components/datepicker/calendar.vdt.js +21 -5
- package/es/components/datepicker/dayjs.d.ts +13 -2
- package/es/components/datepicker/dayjs.js +6 -0
- package/es/components/datepicker/helpers.d.ts +5 -5
- package/es/components/datepicker/index.d.ts +17 -2
- package/es/components/datepicker/index.js +23 -5
- package/es/components/datepicker/index.spec.js +356 -355
- package/es/components/datepicker/index.vdt.js +25 -29
- package/es/components/datepicker/styles.d.ts +17 -0
- package/es/components/datepicker/styles.js +29 -2
- package/es/components/datepicker/useDisabled.d.ts +2 -2
- package/es/components/datepicker/useDisabled.js +1 -1
- package/es/components/datepicker/useFormats.js +3 -1
- package/es/components/datepicker/useMergeRange.d.ts +5 -0
- package/es/components/datepicker/useMergeRange.js +50 -0
- package/es/components/datepicker/usePosition.d.ts +10 -0
- package/es/components/datepicker/usePosition.js +166 -0
- package/es/components/datepicker/useQuarters.d.ts +15 -0
- package/es/components/datepicker/useQuarters.js +36 -0
- package/es/components/datepicker/useShowDate.d.ts +1 -1
- package/es/components/datepicker/useShowDate.js +42 -9
- package/es/components/datepicker/useStatus.d.ts +1 -1
- package/es/components/datepicker/useValue.d.ts +1 -0
- package/es/components/datepicker/useValue.js +26 -2
- package/es/components/datepicker/useWeeks.d.ts +19 -0
- package/es/components/datepicker/useWeeks.js +48 -0
- package/es/components/dialog/useFixBody.js +6 -58
- package/es/components/ellipsis/styles.js +1 -1
- package/es/components/form/styles.js +1 -1
- package/es/components/scrollSelect/index.spec.js +4 -6
- package/es/components/scrollSelect/useMouseEvents.js +21 -9
- package/es/components/select/base.vdt.js +4 -2
- package/es/components/select/index.spec.js +269 -42
- package/es/components/select/option.d.ts +1 -0
- package/es/components/select/option.js +9 -2
- package/es/components/select/select.d.ts +1 -0
- package/es/components/select/select.js +2 -1
- package/es/components/select/useFilterable.js +2 -1
- package/es/components/select/useInput.js +5 -2
- package/es/components/select/useSearchable.js +1 -0
- package/es/components/table/table.vdt.js +4 -2
- package/es/components/timepicker/panelPicker.d.ts +2 -1
- package/es/components/timepicker/panelPicker.vdt.js +12 -4
- package/es/components/timepicker/selectPicker.d.ts +1 -1
- package/es/components/timepicker/styles.js +1 -1
- package/es/components/timepicker/useDisabled.d.ts +1 -1
- package/es/components/timepicker/useValue.d.ts +1 -0
- package/es/components/tour/index.d.ts +2 -0
- package/es/components/tour/index.js +2 -0
- package/es/components/tour/index.spec.d.ts +1 -0
- package/es/components/tour/index.spec.js +356 -0
- package/es/components/tour/step.d.ts +23 -0
- package/es/components/tour/step.js +46 -0
- package/es/components/tour/step.vdt.js +74 -0
- package/es/components/tour/styles.d.ts +7 -0
- package/es/components/tour/styles.js +84 -0
- package/es/components/tour/tour.d.ts +73 -0
- package/es/components/tour/tour.js +70 -0
- package/es/components/tour/tour.vdt.js +66 -0
- package/es/components/tour/useArrow.d.ts +4 -0
- package/es/components/tour/useArrow.js +40 -0
- package/es/components/tour/useFixBody.d.ts +4 -0
- package/es/components/tour/useFixBody.js +17 -0
- package/es/components/tour/useHighlight.d.ts +4 -0
- package/es/components/tour/useHighlight.js +31 -0
- package/es/components/tour/useMaskClosable.d.ts +1 -0
- package/es/components/tour/useMaskClosable.js +25 -0
- package/es/components/tour/useNavigation.d.ts +5 -0
- package/es/components/tour/useNavigation.js +103 -0
- package/es/components/tour/usePosition.d.ts +6 -0
- package/es/components/tour/usePosition.js +93 -0
- package/es/components/tour/useSteps.d.ts +6 -0
- package/es/components/tour/useSteps.js +68 -0
- package/es/components/tree/useChecked.js +6 -4
- package/es/components/treeSelect/index.spec.js +20 -5
- package/es/components/virtualList/useVirtualRows.js +1 -1
- package/es/hooks/useDocumentClick.js +3 -3
- package/es/hooks/useFixBody.d.ts +11 -0
- package/es/hooks/useFixBody.js +72 -0
- package/es/index.d.ts +3 -2
- package/es/index.js +3 -2
- package/es/site/data/components/breadcrumb/demos/separator/react.js +7 -5
- package/es/site/data/components/datepicker/demos/multiple/index.d.ts +0 -1
- package/es/site/data/components/datepicker/demos/multiple/index.js +1 -2
- package/es/site/data/components/datepicker/demos/multiple/react.d.ts +0 -1
- package/es/site/data/components/datepicker/demos/multiple/react.js +2 -13
- package/es/site/data/components/datepicker/demos/nowrap/index.d.ts +10 -0
- package/es/site/data/components/datepicker/demos/nowrap/index.js +19 -0
- package/es/site/data/components/datepicker/demos/nowrap/react.d.ts +10 -0
- package/es/site/data/components/datepicker/demos/nowrap/react.js +49 -0
- package/es/site/data/components/datepicker/demos/yearMonth/index.d.ts +2 -0
- package/es/site/data/components/datepicker/demos/yearMonth/index.js +3 -1
- package/es/site/data/components/datepicker/demos/yearMonth/react.d.ts +2 -0
- package/es/site/data/components/datepicker/demos/yearMonth/react.js +21 -1
- package/es/site/data/components/select/demos/creatable/index.d.ts +1 -0
- package/es/site/data/components/select/demos/creatable/index.js +2 -1
- package/es/site/data/components/select/demos/creatable/react.d.ts +1 -0
- package/es/site/data/components/select/demos/creatable/react.js +31 -2
- package/es/site/data/components/select/demos/searchable/index.js +1 -1
- package/es/site/data/components/select/demos/searchable/react.js +1 -1
- package/es/site/data/components/tour/demos/basic/index.d.ts +17 -0
- package/es/site/data/components/tour/demos/basic/index.js +46 -0
- package/es/site/data/components/tour/demos/basic/react.d.ts +16 -0
- package/es/site/data/components/tour/demos/basic/react.js +82 -0
- package/es/site/data/components/tour/demos/beforeChange/index.d.ts +20 -0
- package/es/site/data/components/tour/demos/beforeChange/index.js +69 -0
- package/es/site/data/components/tour/demos/beforeChange/react.d.ts +19 -0
- package/es/site/data/components/tour/demos/beforeChange/react.js +129 -0
- package/es/site/data/components/tour/demos/closable/index.d.ts +18 -0
- package/es/site/data/components/tour/demos/closable/index.js +42 -0
- package/es/site/data/components/tour/demos/closable/react.d.ts +17 -0
- package/es/site/data/components/tour/demos/closable/react.js +85 -0
- package/es/site/data/components/tour/demos/custom/index.d.ts +11 -0
- package/es/site/data/components/tour/demos/custom/index.js +35 -0
- package/es/site/data/components/tour/demos/custom/react.d.ts +11 -0
- package/es/site/data/components/tour/demos/custom/react.js +108 -0
- package/es/site/data/components/tour/demos/customButtons/index.d.ts +33 -0
- package/es/site/data/components/tour/demos/customButtons/index.js +55 -0
- package/es/site/data/components/tour/demos/customButtons/react.d.ts +33 -0
- package/es/site/data/components/tour/demos/customButtons/react.js +99 -0
- package/es/site/data/components/tour/demos/customText/index.d.ts +20 -0
- package/es/site/data/components/tour/demos/customText/index.js +54 -0
- package/es/site/data/components/tour/demos/customText/react.d.ts +19 -0
- package/es/site/data/components/tour/demos/customText/react.js +95 -0
- package/es/site/data/components/tour/demos/declarative/index.d.ts +11 -0
- package/es/site/data/components/tour/demos/declarative/index.js +36 -0
- package/es/site/data/components/tour/demos/declarative/react.d.ts +10 -0
- package/es/site/data/components/tour/demos/declarative/react.js +80 -0
- package/es/site/data/components/tour/demos/events/index.d.ts +18 -0
- package/es/site/data/components/tour/demos/events/index.js +58 -0
- package/es/site/data/components/tour/demos/events/react.d.ts +18 -0
- package/es/site/data/components/tour/demos/events/react.js +101 -0
- package/es/site/data/components/tour/demos/maskClosable/index.d.ts +18 -0
- package/es/site/data/components/tour/demos/maskClosable/index.js +47 -0
- package/es/site/data/components/tour/demos/maskClosable/react.d.ts +17 -0
- package/es/site/data/components/tour/demos/maskClosable/react.js +95 -0
- package/es/site/data/components/tour/demos/notarget/index.d.ts +11 -0
- package/es/site/data/components/tour/demos/notarget/index.js +35 -0
- package/es/site/data/components/tour/demos/notarget/react.d.ts +10 -0
- package/es/site/data/components/tour/demos/notarget/react.js +61 -0
- package/es/site/data/components/tour/index.d.ts +57 -0
- package/es/site/data/components/tour/index.js +32 -0
- package/es/site/src/pages/resource/index.js +1 -1
- package/es/styles/fonts/iconfont.js +2 -1
- package/es/styles/global.js +2 -1
- package/hooks/useDocumentClick.ts +3 -3
- package/hooks/useFixBody.ts +87 -0
- package/index.ts +3 -2
- package/package.json +1 -1
- package/styles/fonts/iconfont.ts +2 -1
- package/styles/global.ts +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {useInstance} from 'intact';
|
|
2
2
|
import {useState, State} from '../../hooks/useState';
|
|
3
|
-
import {Dayjs, OpUnitType} from 'dayjs';
|
|
3
|
+
import {Dayjs, OpUnitType, QUnitType} from './dayjs';
|
|
4
4
|
import type {Datepicker} from './index';
|
|
5
5
|
import {isNullOrUndefined} from 'intact-shared';
|
|
6
6
|
import {isGT, isLT, last} from './helpers';
|
|
@@ -28,7 +28,7 @@ export function useDisabled({createDateByValueFormat}: ReturnType<typeof useForm
|
|
|
28
28
|
convertToDayjs(minDate, v);
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
function isDisabled(value: Dayjs, type: OpUnitType = 'date') {
|
|
31
|
+
function isDisabled(value: Dayjs, type: OpUnitType | QUnitType = 'date') {
|
|
32
32
|
const {disabledDate} = instance.get();
|
|
33
33
|
return isGT(value, maxDate.value, type) ||
|
|
34
34
|
isLT(value, minDate.value, type) ||
|
|
@@ -58,7 +58,7 @@ export function useDisabled({createDateByValueFormat}: ReturnType<typeof useForm
|
|
|
58
58
|
if (!lastValue) return true;
|
|
59
59
|
|
|
60
60
|
const {range} = instance.get();
|
|
61
|
-
if (range && (lastValue as [Dayjs, Dayjs?]).length
|
|
61
|
+
if (range && (lastValue as [Dayjs, Dayjs?]).length === 1) return false;
|
|
62
62
|
|
|
63
63
|
const {startPanel, endPanel} = instance.panel;
|
|
64
64
|
if (startPanel.value === PanelTypes.Date && endPanel.value === PanelTypes.Date) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {useInstance} from 'intact';
|
|
2
|
+
import {Dayjs} from './dayjs';
|
|
3
|
+
import type {Datepicker} from './index';
|
|
4
|
+
import {DayjsValueRange, DayjsValue} from './basepicker';
|
|
5
|
+
import type {useFormats} from './useFormats';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export function useMergeRange(formats: ReturnType<typeof useFormats>) {
|
|
9
|
+
const instance = useInstance() as Datepicker;
|
|
10
|
+
|
|
11
|
+
function _mergeRanges(dayjsValue: DayjsValue, getShowString: (value: Dayjs) => string) {
|
|
12
|
+
const ranges = dayjsValue
|
|
13
|
+
.filter(Array.isArray)
|
|
14
|
+
.map(range => ({
|
|
15
|
+
start: (range as DayjsValueRange)[0],
|
|
16
|
+
end: (range as DayjsValueRange)[1]
|
|
17
|
+
}))
|
|
18
|
+
.sort((a, b) => a.start.valueOf() - b.start.valueOf());
|
|
19
|
+
|
|
20
|
+
if (ranges.length === 0) return [];
|
|
21
|
+
|
|
22
|
+
// 合并有交集的时间范围
|
|
23
|
+
const mergedRange = ranges.reduce((acc, curr) => {
|
|
24
|
+
if (!acc) return curr;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
start: acc.start,
|
|
28
|
+
end: curr.end.valueOf() > acc.end.valueOf() ? curr.end : acc.end
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return [`${getShowString(mergedRange.start)} ~ ${getShowString(mergedRange.end)}`];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatMultipleValues(dayjsValue: DayjsValue, results: string[]): string[] {
|
|
36
|
+
const {isMerge, nowrap} = instance.get();
|
|
37
|
+
|
|
38
|
+
if (isMerge && nowrap) {
|
|
39
|
+
const mergedResults = _mergeRanges(dayjsValue, (v: Dayjs) => v.format(formats.getShowFormat()));
|
|
40
|
+
if (mergedResults.length > 0) {
|
|
41
|
+
return [
|
|
42
|
+
...mergedResults,
|
|
43
|
+
...results.slice(1).map((result, index) => `${result}-${index}`)
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return results;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
formatMultipleValues
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {useInstance} from 'intact';
|
|
2
|
+
import type {Datepicker} from './';
|
|
3
|
+
import { useState } from '../../hooks/useState';
|
|
4
|
+
import {last} from '../utils';
|
|
5
|
+
|
|
6
|
+
export function usePosition() {
|
|
7
|
+
const instance = useInstance() as Datepicker;
|
|
8
|
+
const position = useState<'start' | 'end'>('start');
|
|
9
|
+
|
|
10
|
+
// 根据类型获取默认字符长度
|
|
11
|
+
function getDefaultCharLength() {
|
|
12
|
+
const {type} = instance.get();
|
|
13
|
+
switch (type) {
|
|
14
|
+
case 'datetime':
|
|
15
|
+
return 16 ; // "2025-07-10 00:00:00"
|
|
16
|
+
case 'date':
|
|
17
|
+
return 10; // "2025-07-09"
|
|
18
|
+
default:
|
|
19
|
+
return 10;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const charLength = useState<number>(getDefaultCharLength()); // 当前活动部分的字符长度
|
|
24
|
+
const startTextLength = useState<number>(getDefaultCharLength()); // 开始文本的长度,用于计算结束文本位置
|
|
25
|
+
|
|
26
|
+
// 监听类型变化,更新默认字符长度
|
|
27
|
+
instance.watch('type', () => {
|
|
28
|
+
const defaultLength = getDefaultCharLength();
|
|
29
|
+
charLength.set(defaultLength);
|
|
30
|
+
startTextLength.set(defaultLength);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
function handleInputClick(e: MouseEvent) {
|
|
34
|
+
const { range, type } = instance.get();
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if (!range) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// 对于日期时间范围选择器,如果当前没有值或值不完整,总是设置为开始时间
|
|
41
|
+
if (type === 'datetime') {
|
|
42
|
+
const currentValue = instance.value.value.value;
|
|
43
|
+
const lastValue = last(currentValue);
|
|
44
|
+
// 如果没有值或者当前范围值不完整(只有开始时间没有结束时间),强制设置为开始时间
|
|
45
|
+
if (!lastValue || !Array.isArray(lastValue) || lastValue.length < 2 || !lastValue[1]) {
|
|
46
|
+
position.set('start');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 获取事件目标元素
|
|
52
|
+
let target = e.currentTarget as HTMLElement;
|
|
53
|
+
// 如果目标元素不是 .k-select-main,则查找父元素
|
|
54
|
+
if (!target.classList.contains(`.k-select-main`)) {
|
|
55
|
+
target = target.closest(`.k-select-main`) as HTMLElement;
|
|
56
|
+
if (!target) return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const hiddenInput = target.querySelector('input[type="hidden"]') as HTMLInputElement;
|
|
60
|
+
const { width: totalVisualWidth } = target.getBoundingClientRect();
|
|
61
|
+
let midPoint;
|
|
62
|
+
if (hiddenInput && hiddenInput.value && hiddenInput.value.includes(',')) {
|
|
63
|
+
// 分割字符串获取开始和结束日期的文本
|
|
64
|
+
const [startText, endText] = hiddenInput.value.split(',');
|
|
65
|
+
// 确保两部分都存在,避免计算错误
|
|
66
|
+
if (startText && endText) {
|
|
67
|
+
const totalCharLength = startText.length + endText.length;
|
|
68
|
+
// 计算开始日期文本长度所占的比例
|
|
69
|
+
const startRatio = startText.length / totalCharLength;
|
|
70
|
+
|
|
71
|
+
// 估算每个字符的宽度(与样式中保持一致)
|
|
72
|
+
const charWidthPx = 8;
|
|
73
|
+
|
|
74
|
+
// 计算实际文本占用的宽度
|
|
75
|
+
const startTextWidth = startText.length * charWidthPx;
|
|
76
|
+
const endTextWidth = endText.length * charWidthPx;
|
|
77
|
+
const separatorWidth = 3 * charWidthPx; // " ~ " 大约3个字符宽度
|
|
78
|
+
const totalTextWidth = startTextWidth + separatorWidth + endTextWidth;
|
|
79
|
+
|
|
80
|
+
// 如果文本宽度超过input宽度,使用比例分割
|
|
81
|
+
if (totalTextWidth >= totalVisualWidth) {
|
|
82
|
+
midPoint = totalVisualWidth * startRatio;
|
|
83
|
+
} else {
|
|
84
|
+
// 如果文本宽度小于input宽度,使用实际文本宽度计算分割点
|
|
85
|
+
midPoint = startTextWidth + separatorWidth / 2;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 更新开始文本长度状态,限制为默认长度以保证结束时间高亮位置正确
|
|
89
|
+
startTextLength.set(Math.min(startText.length, getDefaultCharLength()));
|
|
90
|
+
|
|
91
|
+
} else {
|
|
92
|
+
// 如果值格式不正确(例如 "2025-07-09,"),则退回使用几何中心点
|
|
93
|
+
const defaultLength = getDefaultCharLength();
|
|
94
|
+
charLength.set(defaultLength);
|
|
95
|
+
startTextLength.set(defaultLength);
|
|
96
|
+
midPoint = totalVisualWidth / 2;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
// 如果没有找到 hiddenInput 或其值不是范围,则退回原始的几何中心点
|
|
100
|
+
const defaultLength = getDefaultCharLength();
|
|
101
|
+
charLength.set(defaultLength);
|
|
102
|
+
startTextLength.set(defaultLength);
|
|
103
|
+
midPoint = totalVisualWidth / 2;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 计算相对于 target 的 offsetX
|
|
107
|
+
const rect = target.getBoundingClientRect();
|
|
108
|
+
const offsetX = e.clientX - rect.left;
|
|
109
|
+
// 根据点击位置判断是点击了左半边(开始)还是右半边(结束)
|
|
110
|
+
if (offsetX < midPoint) {
|
|
111
|
+
position.set('start');
|
|
112
|
+
// 更新为开始部分的字符长度,限制为默认长度
|
|
113
|
+
if (hiddenInput && hiddenInput.value && hiddenInput.value.includes(',')) {
|
|
114
|
+
const [startText] = hiddenInput.value.split(',');
|
|
115
|
+
charLength.set(Math.min(startText.length, getDefaultCharLength()));
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
position.set('end');
|
|
119
|
+
// 更新为结束部分的字符长度,限制为默认长度
|
|
120
|
+
if (hiddenInput && hiddenInput.value && hiddenInput.value.includes(',')) {
|
|
121
|
+
const [, endText] = hiddenInput.value.split(',');
|
|
122
|
+
charLength.set(Math.min(endText.length, getDefaultCharLength()));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// 重置位置到指定值
|
|
128
|
+
function resetPosition(pos: 'start' | 'end' = 'start') {
|
|
129
|
+
if (position.value === pos) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
position.set(pos);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 切换位置
|
|
136
|
+
function togglePosition() {
|
|
137
|
+
const currentPosition = position.value;
|
|
138
|
+
if (currentPosition === 'start') {
|
|
139
|
+
position.set('end');
|
|
140
|
+
} else {
|
|
141
|
+
position.set('start');
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 在组件初始化时设置事件监听
|
|
146
|
+
function setupEventListeners() {
|
|
147
|
+
// instance.on('resetPosition', resetPosition);
|
|
148
|
+
instance.on('togglePosition', togglePosition);
|
|
149
|
+
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function resetToStart() {
|
|
153
|
+
const {range, type} = instance.get();
|
|
154
|
+
if (range && type === 'date') {
|
|
155
|
+
position.set('start');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
position,
|
|
161
|
+
charLength,
|
|
162
|
+
startTextLength,
|
|
163
|
+
handleInputClick,
|
|
164
|
+
resetPosition,
|
|
165
|
+
togglePosition,
|
|
166
|
+
setupEventListeners,
|
|
167
|
+
resetToStart
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import {useInstance} from 'intact';
|
|
2
|
+
import dayjs, {Dayjs} from 'dayjs';
|
|
3
|
+
import {isEqual} from './helpers';
|
|
4
|
+
import type {DatepickerCalendar} from './calendar';
|
|
5
|
+
import {State} from '../../hooks/useState';
|
|
6
|
+
import {_$} from '../../i18n';
|
|
7
|
+
import type {useStatus} from './useStatus';
|
|
8
|
+
|
|
9
|
+
export function useQuarters(
|
|
10
|
+
showDate: State<Dayjs>,
|
|
11
|
+
status: ReturnType<typeof useStatus>,
|
|
12
|
+
focusDate: State<Dayjs | null>
|
|
13
|
+
) {
|
|
14
|
+
const instance = useInstance() as DatepickerCalendar;
|
|
15
|
+
|
|
16
|
+
function getQuarters(now: Dayjs) {
|
|
17
|
+
const ret = [];
|
|
18
|
+
const year = showDate.value.year();
|
|
19
|
+
|
|
20
|
+
for (let i = 1; i <= 4; i++) {
|
|
21
|
+
const quarterStart = dayjs().year(year).quarter(i).startOf('quarter');
|
|
22
|
+
|
|
23
|
+
ret.push({
|
|
24
|
+
isActive: status.isActive(quarterStart, 'quarter'),
|
|
25
|
+
isToday: now.isSame(quarterStart, 'quarter'),
|
|
26
|
+
isDisabled: status.isDisabled(quarterStart),
|
|
27
|
+
isHover: isEqual(quarterStart, focusDate.value, 'quarter'),
|
|
28
|
+
isInRange: status.isInRange(quarterStart, 'quarter'),
|
|
29
|
+
label: _$(`Q${i}`),
|
|
30
|
+
value: quarterStart,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return ret;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function onClick(date: Dayjs) {
|
|
38
|
+
const quarterStart = date.startOf('quarter');
|
|
39
|
+
showDate.set(quarterStart);
|
|
40
|
+
const datepickerType = instance.datepicker.get('type');
|
|
41
|
+
if (datepickerType === 'quarter') {
|
|
42
|
+
instance.triggerChange(quarterStart);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return {getQuarters, onClick};
|
|
47
|
+
}
|
|
@@ -77,6 +77,12 @@ export function useShowDate(panel: ReturnType<typeof usePanel>) {
|
|
|
77
77
|
case 'month':
|
|
78
78
|
return date.add(isEnd ? 1 : -1, 'year');
|
|
79
79
|
break;
|
|
80
|
+
case 'week':
|
|
81
|
+
return date.add(isEnd ? 1 : -1, 'week');
|
|
82
|
+
break;
|
|
83
|
+
case 'quarter':
|
|
84
|
+
return date.add(isEnd ? 1 : -1, 'quarter');
|
|
85
|
+
break;
|
|
80
86
|
default:
|
|
81
87
|
return date.add(isEnd ? 1 : -1, 'month');
|
|
82
88
|
break;
|
|
@@ -84,22 +90,47 @@ export function useShowDate(panel: ReturnType<typeof usePanel>) {
|
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
function getDateLabel() {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
const year = showDate.value.get('year');
|
|
94
|
+
const month = showDate.value.get('month') + 1;
|
|
95
|
+
|
|
96
|
+
const map: { [key: string]: string } = {
|
|
97
|
+
'MM': _$(`${month}月`), // 月标签
|
|
98
|
+
'YYYY': _$(`{n}年`, {n: year}), // 年标签
|
|
99
|
+
'YYYY MM': _$(`{n}年{y}月`, {n: year, y: month}) // 年月组合标签
|
|
90
100
|
};
|
|
91
101
|
|
|
92
|
-
let
|
|
93
|
-
|
|
94
|
-
|
|
102
|
+
let format;
|
|
103
|
+
switch (type) {
|
|
104
|
+
case 'week':
|
|
105
|
+
format = ['YYYY MM']; // week 类型显示年月组合
|
|
106
|
+
break;
|
|
107
|
+
case 'quarter':
|
|
108
|
+
format = ['YYYY']; // quarter 类型仅显示年
|
|
109
|
+
break;
|
|
110
|
+
default:
|
|
111
|
+
let yearMonthFormat = _$('yearMonthFormat');
|
|
112
|
+
if (yearMonthFormat === 'yearMonthFormat') {
|
|
113
|
+
yearMonthFormat = 'YYYY MM'; // 默认格式
|
|
114
|
+
}
|
|
115
|
+
format = yearMonthFormat.split(' '); // 其他类型按配置拆分
|
|
116
|
+
break;
|
|
95
117
|
}
|
|
96
|
-
const format = yearMonthFormat.split(' ') as (keyof typeof map)[];
|
|
97
118
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
119
|
+
// 根据 type 动态调整显示的格式
|
|
120
|
+
return format.map(item => ({
|
|
121
|
+
value: map[item], // 根据 format 项目生成标签
|
|
122
|
+
onClick: (e: IgnoreClickEvent) => {
|
|
101
123
|
e._ignore = true;
|
|
102
|
-
|
|
124
|
+
// 根据点击的项设置不同的 type
|
|
125
|
+
if (item === 'YYYY MM') {
|
|
126
|
+
instance.type.set('week'); // 点击年月组合,保持 week
|
|
127
|
+
} else if (item === 'YYYY') {
|
|
128
|
+
instance.type.set(type === 'quarter' ? 'quarter' : 'year'); // 根据当前 type 决定
|
|
129
|
+
} else if (item === 'MM') {
|
|
130
|
+
instance.type.set('month'); // 点击月,切换到 month
|
|
131
|
+
} else {
|
|
132
|
+
instance.type.set('date'); // 默认切换到 date
|
|
133
|
+
}
|
|
103
134
|
}
|
|
104
135
|
}));
|
|
105
136
|
}
|
|
@@ -51,8 +51,8 @@ export function useValue(
|
|
|
51
51
|
|
|
52
52
|
function onChangeDate(v: Dayjs, flag: PanelFlags) {
|
|
53
53
|
const {multiple, type, range} = instance.get();
|
|
54
|
+
const activePosition = instance.activePosition.position.value;
|
|
54
55
|
let _value: StateValueItem;
|
|
55
|
-
|
|
56
56
|
if (range) {
|
|
57
57
|
const oldValue = last(value.value as StateValueRange[]);
|
|
58
58
|
if (!oldValue || oldValue.length === 2) {
|
|
@@ -62,10 +62,33 @@ export function useValue(
|
|
|
62
62
|
* #877
|
|
63
63
|
*/
|
|
64
64
|
flag = PanelFlags.Start;
|
|
65
|
-
|
|
65
|
+
if((type === 'datetime' || type === 'date') && oldValue?.length === 2) {
|
|
66
|
+
// Use activePosition instead of Coordinate
|
|
67
|
+
_value = activePosition === 'end' ?
|
|
68
|
+
[oldValue[0], fixDatetimeWithMinDate(v)] : multiple ?
|
|
69
|
+
[fixDatetimeWithMinDate(v)] :
|
|
70
|
+
[fixDatetimeWithMinDate(v), oldValue[1]];
|
|
71
|
+
} else {
|
|
72
|
+
_value = [fixDatetimeWithMinDate(v)];
|
|
73
|
+
}
|
|
66
74
|
} else {
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
if (type === 'datetime') {
|
|
76
|
+
if (oldValue.length === 1) {
|
|
77
|
+
// 如果只有开始日期,根据activePosition决定是替换开始日期还是设置结束日期
|
|
78
|
+
_value = activePosition === 'end' ?
|
|
79
|
+
[oldValue[0], fixDatetimeWithMaxDate(v)] :
|
|
80
|
+
[fixDatetimeWithMaxDate(v)];
|
|
81
|
+
} else {
|
|
82
|
+
// oldValue.length === 2的情况
|
|
83
|
+
_value = activePosition === 'end' ?
|
|
84
|
+
[oldValue[0], fixDatetimeWithMaxDate(v)] : multiple ?
|
|
85
|
+
[fixDatetimeWithMaxDate(v)] :
|
|
86
|
+
[fixDatetimeWithMaxDate(v), oldValue[1]];
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
_value = [oldValue[0], fixDatetimeWithMaxDate(v)];
|
|
90
|
+
}
|
|
91
|
+
(_value as DayjsValueRange).sort((a, b) => a.isAfter(b) ? 1 : -1);
|
|
69
92
|
}
|
|
70
93
|
instance.trigger('selecting', _value);
|
|
71
94
|
} else {
|
|
@@ -84,6 +107,14 @@ export function useValue(
|
|
|
84
107
|
} else {
|
|
85
108
|
panel.changePanel(PanelTypes.Time, flag);
|
|
86
109
|
}
|
|
110
|
+
} else if(type === 'week') {
|
|
111
|
+
_value = v.startOf('week')
|
|
112
|
+
setValue(_value, false);
|
|
113
|
+
instance.hide();
|
|
114
|
+
} else if(type === 'quarter') {
|
|
115
|
+
_value = v.startOf('quarter');
|
|
116
|
+
setValue(_value, false);
|
|
117
|
+
instance.hide();
|
|
87
118
|
} else if (!multiple && (!range || (_value as StateValueRange).length === 2)) {
|
|
88
119
|
instance.hide();
|
|
89
120
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {useInstance} from 'intact';
|
|
2
|
+
import dayjs, {Dayjs} from 'dayjs';
|
|
3
|
+
import {isEqual, clearTime} from './helpers';
|
|
4
|
+
import type {DatepickerCalendar} from './calendar';
|
|
5
|
+
import {State} from '../../hooks/useState';
|
|
6
|
+
import {_$} from '../../i18n';
|
|
7
|
+
import type {useStatus} from './useStatus';
|
|
8
|
+
|
|
9
|
+
export function useWeeks(
|
|
10
|
+
showDate: State<Dayjs>,
|
|
11
|
+
status: ReturnType<typeof useStatus>,
|
|
12
|
+
focusDate: State<Dayjs | null>
|
|
13
|
+
) {
|
|
14
|
+
const instance = useInstance() as DatepickerCalendar;
|
|
15
|
+
|
|
16
|
+
function getWeeks(now: Dayjs) {
|
|
17
|
+
const weeks = [];
|
|
18
|
+
// 从当前显示月份的月初开始,并调整到该周的开始
|
|
19
|
+
const startOfMonth = showDate.value.startOf('month');
|
|
20
|
+
const start = startOfMonth.startOf('week');
|
|
21
|
+
let current = start;
|
|
22
|
+
const currentMonth = showDate.value.month();
|
|
23
|
+
|
|
24
|
+
// 遍历6周,以覆盖整个月份
|
|
25
|
+
for (let weekIndex = 0; weekIndex < 6; weekIndex++) {
|
|
26
|
+
const weekNumber = current.week(); // 获取当前周的周数
|
|
27
|
+
const days = [];
|
|
28
|
+
|
|
29
|
+
// 遍历一周的7天
|
|
30
|
+
for (let i = 0; i < 7; i++) {
|
|
31
|
+
const day = current.add(i, 'day');
|
|
32
|
+
const isFirstOrLastDay = i === 0 || i === 6;
|
|
33
|
+
days.push({
|
|
34
|
+
isExceed: day.month() !== currentMonth,
|
|
35
|
+
label: day.date(),
|
|
36
|
+
value: day,
|
|
37
|
+
isActive:isFirstOrLastDay && status.isActive(day, 'week'),
|
|
38
|
+
isToday: day.isSame(now, 'week'),
|
|
39
|
+
isDisabled: status.isDisabled(day),
|
|
40
|
+
isHover: day.isSame(focusDate.value, 'week'),
|
|
41
|
+
isInRange: !isFirstOrLastDay && status.isActive(day, 'week')
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// 每周的数据,包括周数和7天的信息
|
|
45
|
+
weeks.push({week: weekNumber, days});
|
|
46
|
+
current = current.add(1, 'week'); // 移动到下一周的开始
|
|
47
|
+
}
|
|
48
|
+
return weeks;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function onClick(day: Dayjs) {
|
|
52
|
+
const weekStart = day.startOf('week');
|
|
53
|
+
showDate.set(weekStart); // 设置显示日期为周的开始
|
|
54
|
+
instance.triggerChange(weekStart); // 触发日期改变事件
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { getWeeks, onClick };
|
|
58
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {useInstance, RefObject
|
|
1
|
+
import {useInstance, RefObject} from 'intact';
|
|
2
2
|
import type {BaseDialog} from './base';
|
|
3
|
-
import {
|
|
4
|
-
import {scrollbarWidth} from '../position';
|
|
3
|
+
import {useFixBody as useFixBodyHook, setHooks as setFixBodyHooks} from '../../hooks/useFixBody';
|
|
5
4
|
import {SHOW} from './constants';
|
|
6
5
|
|
|
7
6
|
type Hooks = {
|
|
@@ -9,81 +8,25 @@ type Hooks = {
|
|
|
9
8
|
onEnd?: () => void
|
|
10
9
|
}
|
|
11
10
|
|
|
12
|
-
const dialogs = new Set<BaseDialog>();
|
|
13
|
-
let originalStyle: string | null = null;
|
|
14
|
-
let hooks: Hooks | null = null;
|
|
15
|
-
|
|
16
11
|
export function useFixBody(elementRef: RefObject<HTMLDivElement>) {
|
|
17
12
|
const instance = useInstance() as BaseDialog;
|
|
18
|
-
|
|
13
|
+
|
|
14
|
+
const fixBodyHook = useFixBodyHook();
|
|
19
15
|
|
|
20
16
|
instance.on(SHOW, onEnter);
|
|
21
17
|
instance.on('afterClose', onAfterLeave);
|
|
22
|
-
|
|
23
|
-
onBeforeUnmount(() => {
|
|
24
|
-
// should also remove body style when dialog is removed, #805
|
|
25
|
-
// if (fixedBody && instance.get('value')) {
|
|
26
|
-
if (fixedBody) {
|
|
27
|
-
// maybe HIDE event has not triggered
|
|
28
|
-
onClosed(instance);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
18
|
|
|
32
19
|
function onEnter() {
|
|
33
20
|
if (instance.get('overlay')) {
|
|
34
|
-
|
|
35
|
-
onOpen(instance);
|
|
21
|
+
fixBodyHook.onOpen();
|
|
36
22
|
}
|
|
37
23
|
}
|
|
38
24
|
|
|
39
25
|
function onAfterLeave() {
|
|
40
|
-
|
|
41
|
-
fixedBody = false;
|
|
42
|
-
onClosed(instance);
|
|
43
|
-
}
|
|
26
|
+
fixBodyHook.onClose();
|
|
44
27
|
}
|
|
45
28
|
}
|
|
46
29
|
|
|
47
30
|
export function setHooks(h: Hooks | null) {
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function onOpen(dialog: BaseDialog) {
|
|
52
|
-
const body = document.body;
|
|
53
|
-
if (dialogs.size === 0) {
|
|
54
|
-
const bodyStyle = body.style;
|
|
55
|
-
originalStyle = body.getAttribute('style');
|
|
56
|
-
bodyStyle.overflow = 'hidden';
|
|
57
|
-
|
|
58
|
-
const scrollBarWidth = shouldFixBody();
|
|
59
|
-
if (scrollBarWidth) {
|
|
60
|
-
bodyStyle.paddingRight = `${scrollBarWidth}px`;
|
|
61
|
-
}
|
|
62
|
-
if (hooks && hooks.onStart) {
|
|
63
|
-
hooks.onStart(scrollBarWidth);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
dialogs.add(dialog);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function onClosed(dialog: BaseDialog) {
|
|
70
|
-
const body = document.body;
|
|
71
|
-
dialogs.delete(dialog);
|
|
72
|
-
if (dialogs.size === 0) {
|
|
73
|
-
if (originalStyle) {
|
|
74
|
-
// console.log(originalStyle);
|
|
75
|
-
body.setAttribute('style', originalStyle);
|
|
76
|
-
} else {
|
|
77
|
-
body.removeAttribute('style');
|
|
78
|
-
}
|
|
79
|
-
if (hooks && hooks.onEnd) {
|
|
80
|
-
hooks.onEnd();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function shouldFixBody() {
|
|
86
|
-
if (document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight)) {
|
|
87
|
-
return scrollbarWidth();
|
|
88
|
-
}
|
|
31
|
+
setFixBodyHooks(h);
|
|
89
32
|
}
|
|
@@ -16,6 +16,10 @@ export const makeStyles = cache(function makeStyles(k: string, maxLines: number)
|
|
|
16
16
|
display: -webkit-box;
|
|
17
17
|
-webkit-line-clamp: ${maxLines};
|
|
18
18
|
-webkit-box-orient: vertical;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
text-overflow: ellipsis;
|
|
21
|
+
line-clamp: ${maxLines};
|
|
22
|
+
box-orient: vertical;
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
`;
|
|
@@ -4,17 +4,17 @@ import {ScrollSelect} from './';
|
|
|
4
4
|
import {Component} from 'intact';
|
|
5
5
|
|
|
6
6
|
describe('ScrollSelect', () => {
|
|
7
|
-
afterEach(() => unmount());
|
|
7
|
+
// afterEach(() => unmount());
|
|
8
8
|
|
|
9
9
|
it('should select by scroll', async () => {
|
|
10
10
|
const [instance, element] = mount(BasicDemo);
|
|
11
11
|
|
|
12
12
|
// scroll
|
|
13
|
-
dispatchEvent(element.firstElementChild!, 'wheel', {deltaY:
|
|
13
|
+
dispatchEvent(element.firstElementChild!, 'wheel', {deltaY: 30});
|
|
14
14
|
await wait(100);
|
|
15
15
|
expect(instance.get('value')).to.eql(1);
|
|
16
16
|
|
|
17
|
-
dispatchEvent(element.firstElementChild!, 'wheel', {deltaY: -
|
|
17
|
+
dispatchEvent(element.firstElementChild!, 'wheel', {deltaY: -30});
|
|
18
18
|
await wait(100);
|
|
19
19
|
expect(instance.get('value')).to.eql(0);
|
|
20
20
|
});
|