@king-design/intact 3.5.2 → 3.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/components/.DS_Store +0 -0
- package/components/button/index.md +1 -0
- package/components/cascader/index.spec.ts +7 -6
- package/components/datepicker/basepicker.ts +26 -267
- package/components/datepicker/calendar.ts +8 -2
- package/components/datepicker/calendar.vdt +23 -6
- package/components/datepicker/dayjs.ts +8 -2
- package/components/datepicker/demos/multiple.md +1 -1
- package/components/datepicker/demos/yearMonth.md +1 -1
- package/components/datepicker/helpers.ts +10 -12
- package/components/datepicker/index.md +2 -2
- package/components/datepicker/index.spec.ts +619 -190
- package/components/datepicker/index.ts +22 -21
- package/components/datepicker/index.vdt +47 -42
- package/components/datepicker/shortcuts.ts +1 -1
- package/components/datepicker/styles.ts +112 -4
- package/components/datepicker/useConfirm.ts +82 -0
- package/components/datepicker/useDisabled.ts +31 -33
- package/components/datepicker/useFormats.ts +10 -4
- package/components/datepicker/useHighlight.ts +81 -0
- package/components/datepicker/useKeyboards.ts +2 -1
- package/components/datepicker/useMergeRange.ts +54 -0
- package/components/datepicker/useMonths.ts +6 -3
- package/components/datepicker/usePanel.ts +19 -19
- package/components/datepicker/useQuarters.ts +47 -0
- package/components/datepicker/useShowDate.ts +14 -3
- package/components/datepicker/useStatus.ts +34 -15
- package/components/datepicker/useValue.ts +41 -39
- package/components/datepicker/useValueBase.ts +309 -0
- package/components/datepicker/useWeeks.ts +58 -0
- package/components/datepicker/useYears.ts +7 -3
- package/components/descriptions/.DS_Store +0 -0
- package/components/dialog/useFixBody.ts +7 -64
- package/components/dropdown/dropdown.ts +5 -4
- package/components/dropdown/index.md +1 -0
- package/components/dropdown/item.ts +1 -1
- package/components/dropdown/useKeyboard.ts +0 -1
- package/components/ellipsis/styles.ts +4 -0
- package/components/form/styles.ts +1 -0
- package/components/input/index.spec.ts +42 -0
- package/components/input/index.ts +8 -0
- package/components/input/index.vdt +3 -4
- package/components/input/useAutoWidth.ts +19 -1
- package/components/menu/.DS_Store +0 -0
- package/components/menu/demos/.DS_Store +0 -0
- package/components/scrollSelect/index.spec.ts +3 -3
- package/components/scrollSelect/useMouseEvents.ts +24 -10
- package/components/select/base.ts +3 -2
- package/components/select/base.vdt +3 -1
- package/components/select/demos/creatable.md +13 -0
- package/components/select/index.md +1 -0
- package/components/select/index.spec.ts +225 -6
- package/components/select/option.ts +10 -1
- package/components/select/select.ts +3 -0
- package/components/select/styles.ts +3 -1
- package/components/select/useFilterable.ts +1 -1
- package/components/select/useInput.ts +7 -9
- package/components/select/useSearchable.ts +2 -2
- package/components/table/.DS_Store +0 -0
- package/components/table/index.spec.ts +69 -1
- package/components/table/useStickyHeader.ts +1 -1
- package/components/timepicker/demos/step.md +1 -1
- package/components/timepicker/index.spec.ts +145 -27
- package/components/timepicker/panelPicker.ts +10 -4
- package/components/timepicker/panelPicker.vdt +5 -3
- package/components/timepicker/useConfirm.ts +33 -0
- package/components/timepicker/useDefaultValue.ts +30 -0
- package/components/timepicker/useDisabled.ts +17 -4
- package/components/timepicker/useFormats.ts +1 -1
- package/components/timepicker/useValue.ts +22 -19
- package/components/tour/.DS_Store +0 -0
- 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/virtualList/.DS_Store +0 -0
- package/components/virtualList/demos/.DS_Store +0 -0
- package/es/components/cascader/index.spec.js +18 -19
- package/es/components/datepicker/basepicker.d.ts +6 -25
- package/es/components/datepicker/basepicker.js +22 -234
- package/es/components/datepicker/calendar.d.ts +36 -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 +2 -2
- package/es/components/datepicker/dayjs.js +6 -0
- package/es/components/datepicker/helpers.d.ts +8 -7
- package/es/components/datepicker/helpers.js +2 -3
- package/es/components/datepicker/index.d.ts +26 -19
- package/es/components/datepicker/index.js +21 -13
- package/es/components/datepicker/index.spec.js +1389 -633
- package/es/components/datepicker/index.vdt.js +43 -46
- package/es/components/datepicker/shortcuts.d.ts +1 -1
- package/es/components/datepicker/styles.d.ts +22 -0
- package/es/components/datepicker/styles.js +26 -4
- package/es/components/datepicker/useConfirm.d.ts +6 -0
- package/es/components/datepicker/useConfirm.js +65 -0
- package/es/components/datepicker/useDisabled.d.ts +7 -5
- package/es/components/datepicker/useDisabled.js +22 -27
- package/es/components/datepicker/useFormats.d.ts +2 -2
- package/es/components/datepicker/useFormats.js +9 -3
- package/es/components/datepicker/useHighlight.d.ts +14 -0
- package/es/components/datepicker/useHighlight.js +60 -0
- package/es/components/datepicker/useKeyboards.js +2 -1
- package/es/components/datepicker/useMergeRange.d.ts +5 -0
- package/es/components/datepicker/useMergeRange.js +45 -0
- package/es/components/datepicker/useMonths.js +5 -3
- package/es/components/datepicker/usePanel.d.ts +1 -10
- package/es/components/datepicker/usePanel.js +19 -32
- package/es/components/datepicker/useQuarters.d.ts +15 -0
- package/es/components/datepicker/useQuarters.js +36 -0
- package/es/components/datepicker/useShowDate.js +10 -2
- package/es/components/datepicker/useStatus.d.ts +1 -1
- package/es/components/datepicker/useStatus.js +33 -16
- package/es/components/datepicker/useValue.d.ts +12 -6
- package/es/components/datepicker/useValue.js +49 -45
- package/es/components/datepicker/useValueBase.d.ts +28 -0
- package/es/components/datepicker/useValueBase.js +277 -0
- package/es/components/datepicker/useWeeks.d.ts +19 -0
- package/es/components/datepicker/useWeeks.js +48 -0
- package/es/components/datepicker/useYears.js +6 -3
- package/es/components/dialog/useFixBody.js +6 -58
- package/es/components/dropdown/dropdown.d.ts +1 -0
- package/es/components/dropdown/dropdown.js +7 -4
- package/es/components/ellipsis/styles.js +1 -1
- package/es/components/form/styles.js +1 -1
- package/es/components/input/index.d.ts +2 -0
- package/es/components/input/index.js +6 -0
- package/es/components/input/index.spec.js +45 -0
- package/es/components/input/index.vdt.js +4 -3
- package/es/components/input/useAutoWidth.d.ts +2 -0
- package/es/components/input/useAutoWidth.js +19 -1
- package/es/components/scrollSelect/index.spec.js +4 -6
- package/es/components/scrollSelect/useMouseEvents.js +22 -9
- package/es/components/select/base.d.ts +1 -1
- package/es/components/select/base.js +3 -2
- package/es/components/select/base.vdt.js +5 -2
- package/es/components/select/index.spec.js +329 -82
- package/es/components/select/option.d.ts +1 -0
- package/es/components/select/option.js +10 -2
- package/es/components/select/select.d.ts +1 -0
- package/es/components/select/select.js +4 -2
- package/es/components/select/styles.d.ts +79 -0
- package/es/components/select/styles.js +1 -0
- package/es/components/select/useFilterable.js +2 -1
- package/es/components/select/useInput.d.ts +1 -1
- package/es/components/select/useInput.js +7 -4
- package/es/components/select/useSearchable.js +1 -0
- package/es/components/table/index.spec.js +84 -6
- package/es/components/table/useStickyHeader.js +1 -1
- package/es/components/timepicker/index.spec.js +298 -128
- package/es/components/timepicker/panelPicker.d.ts +23 -17
- package/es/components/timepicker/panelPicker.js +7 -4
- package/es/components/timepicker/panelPicker.vdt.js +8 -4
- package/es/components/timepicker/selectPicker.d.ts +5 -4
- package/es/components/timepicker/useConfirm.d.ts +6 -0
- package/es/components/timepicker/useConfirm.js +19 -0
- package/es/components/timepicker/useDefaultValue.d.ts +4 -0
- package/es/components/timepicker/useDefaultValue.js +27 -0
- package/es/components/timepicker/useDisabled.d.ts +7 -4
- package/es/components/timepicker/useDisabled.js +13 -4
- package/es/components/timepicker/useFormats.d.ts +1 -1
- package/es/components/timepicker/useValue.d.ts +14 -8
- package/es/components/timepicker/useValue.js +14 -15
- 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/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/datepicker/demos/multiple/react.js +2 -2
- 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/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/customText/index.d.ts +33 -0
- package/es/site/data/components/tour/demos/customText/index.js +55 -0
- package/es/site/data/components/tour/demos/customText/react.d.ts +33 -0
- package/es/site/data/components/tour/demos/customText/react.js +99 -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/hooks/useFixBody.ts +87 -0
- package/index.ts +3 -2
- package/package.json +2 -2
- package/styles/.DS_Store +0 -0
|
@@ -6,6 +6,7 @@ export function useAutoWidth() {
|
|
|
6
6
|
const instance = useInstance() as Input;
|
|
7
7
|
const fakeRef = createRef<HTMLDivElement>();
|
|
8
8
|
const width = useState<number>(0);
|
|
9
|
+
const forceShowFake = useState(false);
|
|
9
10
|
|
|
10
11
|
instance.watch('value', adjustWidth, {inited: true, presented: true});
|
|
11
12
|
instance.watch('placeholder', adjustWidth, {inited: true, presented: true});
|
|
@@ -23,7 +24,24 @@ export function useAutoWidth() {
|
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
function getStringWidth(str: string) {
|
|
28
|
+
forceShowFake.set(true);
|
|
29
|
+
return new Promise<number>((resolve) => {
|
|
30
|
+
nextTick(() => {
|
|
31
|
+
const fakeElem = fakeRef.value!;
|
|
32
|
+
const textNode = fakeElem.firstChild!;
|
|
33
|
+
const oldStr = textNode.nodeValue;
|
|
34
|
+
textNode.nodeValue = str;
|
|
35
|
+
|
|
36
|
+
resolve(fakeElem.offsetWidth);
|
|
37
|
+
|
|
38
|
+
textNode.nodeValue = oldStr;
|
|
39
|
+
forceShowFake.set(false);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {fakeRef, width, forceShowFake, getStringWidth};
|
|
27
45
|
}
|
|
28
46
|
|
|
29
47
|
function isVisible(elem: HTMLDivElement | null) {
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
});
|
|
@@ -18,6 +18,7 @@ export function useMouseEvents(
|
|
|
18
18
|
let y: number;
|
|
19
19
|
let itemHeight: number;
|
|
20
20
|
let deltaY: number;
|
|
21
|
+
let wheelDeltaY: number = 0;
|
|
21
22
|
const {start, dragging} = useDraggable({
|
|
22
23
|
onStart(e: MouseEvent) {
|
|
23
24
|
dragged = false;
|
|
@@ -28,12 +29,12 @@ export function useMouseEvents(
|
|
|
28
29
|
},
|
|
29
30
|
|
|
30
31
|
onMove(e: MouseEvent) {
|
|
31
|
-
const deltaY = e.clientY - y;
|
|
32
|
+
const deltaY = (e.clientY - y) * 0.8;
|
|
32
33
|
dragged = !!deltaY;
|
|
33
34
|
y = e.clientY;
|
|
34
35
|
|
|
35
36
|
const _deltaY = y - initY;
|
|
36
|
-
let offsetIndex = Math.floor(Math.abs(_deltaY) / itemHeight);
|
|
37
|
+
let offsetIndex = Math.floor(Math.abs(_deltaY) / itemHeight * 1.2);
|
|
37
38
|
if (offsetIndex) {
|
|
38
39
|
if (_deltaY < 0) {
|
|
39
40
|
offsetIndex = -offsetIndex;
|
|
@@ -63,25 +64,38 @@ export function useMouseEvents(
|
|
|
63
64
|
|
|
64
65
|
function onWheel(e: WheelEvent) {
|
|
65
66
|
e.preventDefault();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
|
|
68
|
+
itemHeight = getItemHeight();
|
|
69
|
+
|
|
70
|
+
const threshold = itemHeight * 0.6;
|
|
71
|
+
wheelDeltaY += e.deltaY;
|
|
72
|
+
|
|
73
|
+
if (Math.abs(wheelDeltaY) >= threshold) {
|
|
74
|
+
if (wheelDeltaY > 0) {
|
|
75
|
+
setByRelativeIndex(1, null, true);
|
|
76
|
+
} else {
|
|
77
|
+
setByRelativeIndex(-1, null, true);
|
|
78
|
+
}
|
|
79
|
+
wheelDeltaY = 0;
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
|
|
75
83
|
// throttle onWheel
|
|
76
|
-
const _onWheel = throttle(onWheel,
|
|
84
|
+
const _onWheel = throttle(onWheel, 50, e => e.preventDefault());
|
|
77
85
|
|
|
78
86
|
function onClick(item: any, index: number) {
|
|
79
|
-
// if
|
|
87
|
+
// if dragged, do not trigger click event
|
|
80
88
|
if (dragged) return;
|
|
81
89
|
|
|
82
90
|
const {count} = instance.get();
|
|
83
91
|
const half = Math.floor(count! / 2);
|
|
84
92
|
const itemHeight = getItemHeight();
|
|
93
|
+
|
|
94
|
+
const currentIndex = list.data.value.findIndex(v => v.value === list.value.value);
|
|
95
|
+
const targetOffset = index - half;
|
|
96
|
+
if (currentIndex + targetOffset < 0 || currentIndex + targetOffset >= list.data.value.length) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
85
99
|
|
|
86
100
|
translate.set(translate.value - itemHeight * (index - half));
|
|
87
101
|
marginTop.set(marginTop.value + itemHeight * (index - half));
|
|
@@ -142,8 +142,9 @@ export abstract class BaseSelect<
|
|
|
142
142
|
this.set('show', false);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
@bind
|
|
146
|
+
public resetKeywords() {
|
|
147
|
+
this.input.keywords.set('');
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
protected hasValue() {
|
|
@@ -17,7 +17,7 @@ const {
|
|
|
17
17
|
className, container,
|
|
18
18
|
inline, style, width, show,
|
|
19
19
|
position, flat, nowrap,
|
|
20
|
-
draggable,
|
|
20
|
+
draggable, range,
|
|
21
21
|
} = this.get();
|
|
22
22
|
const { k } = this.config;
|
|
23
23
|
|
|
@@ -66,6 +66,7 @@ const filterInput = <Input v-if={filterable}
|
|
|
66
66
|
container={container}
|
|
67
67
|
v-model="show"
|
|
68
68
|
position={position}
|
|
69
|
+
alwaysShowOnClick={$props.alwaysShowOnClick}
|
|
69
70
|
>
|
|
70
71
|
<div {...getRestProps(this)}
|
|
71
72
|
class={classNameObj}
|
|
@@ -74,6 +75,7 @@ const filterInput = <Input v-if={filterable}
|
|
|
74
75
|
ev-focusout={onFocusout}
|
|
75
76
|
style={!isNullOrUndefined(width) ? addStyle(style, {width: `${width}px`}) : style}
|
|
76
77
|
ref={triggerRef}
|
|
78
|
+
ev-click={$props.onClick}
|
|
77
79
|
>
|
|
78
80
|
<div class={`${k}-select-prefix`} v-if={$blocks.prefix}>
|
|
79
81
|
<b:prefix />
|
|
@@ -30,6 +30,17 @@ import {Select, Option} from 'kpc';
|
|
|
30
30
|
<Option value="Sunday">星期天</Option>
|
|
31
31
|
</Select>
|
|
32
32
|
Days: {JSON.stringify(this.get('days'))}
|
|
33
|
+
<br /><br />
|
|
34
|
+
<Select v-model="dayWithKeywords" filterable multiple creatable keepKeywords={false} style="margin-right: 10px">
|
|
35
|
+
<Option value="Monday">星期一</Option>
|
|
36
|
+
<Option value="Tuesday">星期二</Option>
|
|
37
|
+
<Option value="Wednesday">星期三</Option>
|
|
38
|
+
<Option value="Thursday">星期四</Option>
|
|
39
|
+
<Option value="Friday">星期五</Option>
|
|
40
|
+
<Option value="Saturday">星期六</Option>
|
|
41
|
+
<Option value="Sunday">星期天</Option>
|
|
42
|
+
</Select>
|
|
43
|
+
Day with keepKeywords=false: {JSON.stringify(this.get('dayWithKeywords'))}
|
|
33
44
|
</div>
|
|
34
45
|
```
|
|
35
46
|
|
|
@@ -37,6 +48,7 @@ import {Select, Option} from 'kpc';
|
|
|
37
48
|
interface Props {
|
|
38
49
|
day?: string | null
|
|
39
50
|
days?: string[]
|
|
51
|
+
dayWithKeywords?: string[]
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
export default class extends Component<Props> {
|
|
@@ -45,6 +57,7 @@ export default class extends Component<Props> {
|
|
|
45
57
|
return {
|
|
46
58
|
day: null,
|
|
47
59
|
days: [],
|
|
60
|
+
dayWithKeywords: [],
|
|
48
61
|
} as Props;
|
|
49
62
|
}
|
|
50
63
|
}
|
|
@@ -31,6 +31,7 @@ sidebar: doc
|
|
|
31
31
|
| labelMap | 建立值`value`到展示标签`label`的映射,可以在`value`不在`Option`集合中时,依然能够正确展示相应的`label` | `Map<any, string>` | `new Map()` |
|
|
32
32
|
| card | 是否展示`card`模式 | `boolean` | `false` |
|
|
33
33
|
| autoDisableArrow | 是否在没有更多可选项时,给箭头一个`disabled`状态来提示用户 | `boolean` | `false` |
|
|
34
|
+
| keepKeywords | 是否在选中选项后保留搜索关键字,配合`filterable`使用 | `boolean` | `true` |
|
|
34
35
|
| show | 是否展示菜单项 | `boolean` | `false` |
|
|
35
36
|
| position | 菜单弹出的位置,默认与触发器左侧对齐向下偏移`8px`的地方 | `Position` | `"left"` | `"bottom"` | `"right"` | `"top"` | `{my: 'left top+8', 'left bottom'}` |
|
|
36
37
|
| flat | 是否展示扁平样式 | `boolean` | `false` |
|
|
@@ -206,6 +206,9 @@ describe('Select', () => {
|
|
|
206
206
|
const [instance, element] = mount(CreatableDemo);
|
|
207
207
|
|
|
208
208
|
const input = element.querySelector('.k-input-inner') as HTMLInputElement;
|
|
209
|
+
|
|
210
|
+
expect(instance.get('day')).to.be.null;
|
|
211
|
+
|
|
209
212
|
input.click();
|
|
210
213
|
await wait();
|
|
211
214
|
input.value = 'xxx';
|
|
@@ -213,29 +216,157 @@ describe('Select', () => {
|
|
|
213
216
|
await wait();
|
|
214
217
|
const dropdown = getElement('.k-select-menu')!;
|
|
215
218
|
expect(dropdown.innerHTML).to.matchSnapshot();
|
|
216
|
-
|
|
219
|
+
|
|
220
|
+
// check the created option appears in dropdown
|
|
221
|
+
const createOption = dropdown.querySelector('.k-select-option');
|
|
222
|
+
expect(createOption).to.exist;
|
|
223
|
+
expect(createOption!.textContent).to.contain('xxx');
|
|
224
|
+
|
|
225
|
+
// press enter to select the custom option
|
|
217
226
|
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
218
227
|
await wait();
|
|
219
228
|
expect(instance.get('day')).to.eql('xxx');
|
|
229
|
+
expect(input.value).to.eql('xxx');
|
|
220
230
|
|
|
221
|
-
//
|
|
231
|
+
// reopen dropdown
|
|
222
232
|
input.click();
|
|
223
233
|
await wait();
|
|
224
234
|
expect(element.innerHTML).to.matchSnapshot();
|
|
225
235
|
expect(dropdown.innerHTML).to.matchSnapshot();
|
|
226
|
-
|
|
227
|
-
// input
|
|
236
|
+
|
|
237
|
+
// input another custom option
|
|
228
238
|
input.value = 'yyy';
|
|
229
239
|
dispatchEvent(input, 'input');
|
|
230
240
|
await wait();
|
|
231
241
|
expect(element.innerHTML).to.matchSnapshot();
|
|
232
242
|
expect(dropdown.innerHTML).to.matchSnapshot();
|
|
233
243
|
|
|
234
|
-
|
|
244
|
+
const newCreateOption = dropdown.querySelector('.k-select-option');
|
|
245
|
+
expect(newCreateOption).to.exist;
|
|
246
|
+
expect(newCreateOption!.textContent).to.contain('yyy');
|
|
247
|
+
|
|
248
|
+
// click outside to cancel selection
|
|
235
249
|
dispatchEvent(document, 'click');
|
|
236
250
|
await wait();
|
|
237
251
|
expect(element.innerHTML).to.matchSnapshot();
|
|
238
|
-
expect(instance.get('day')).to.eql('xxx');
|
|
252
|
+
expect(instance.get('day')).to.eql('xxx'); // should keep the original value
|
|
253
|
+
expect(input.value).to.eql('xxx'); // should restore the original value
|
|
254
|
+
|
|
255
|
+
// test multiple creatable
|
|
256
|
+
const [, multipleInput] = element.querySelectorAll<HTMLInputElement>('.k-input-inner');
|
|
257
|
+
expect(instance.get('days')).to.eql([]);
|
|
258
|
+
|
|
259
|
+
multipleInput.click();
|
|
260
|
+
await wait();
|
|
261
|
+
multipleInput.value = 'custom1';
|
|
262
|
+
dispatchEvent(multipleInput, 'input');
|
|
263
|
+
await wait();
|
|
264
|
+
|
|
265
|
+
// press enter to create and select the first custom option
|
|
266
|
+
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
267
|
+
await wait();
|
|
268
|
+
expect(instance.get('days')).to.include('custom1');
|
|
269
|
+
expect(multipleInput.value).to.eql('custom1');
|
|
270
|
+
|
|
271
|
+
// input the same option again
|
|
272
|
+
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
273
|
+
await wait();
|
|
274
|
+
expect(instance.get('days')).to.eql([]);
|
|
275
|
+
expect(multipleInput.value).to.eql('custom1');
|
|
276
|
+
|
|
277
|
+
// test select original options
|
|
278
|
+
multipleInput.value = 'Monday';
|
|
279
|
+
dispatchEvent(multipleInput, 'input');
|
|
280
|
+
await wait();
|
|
281
|
+
const multipleDropdown = getElement('.k-select-menu')!;
|
|
282
|
+
const mondayOption = multipleDropdown.querySelector('.k-select-option') as HTMLElement;
|
|
283
|
+
expect(mondayOption.textContent).to.eql('星期一');
|
|
284
|
+
mondayOption.click();
|
|
285
|
+
await wait();
|
|
286
|
+
expect(instance.get('days')).to.include('Monday');
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('keepKeywords', async () => {
|
|
290
|
+
class KeepKeywordsDemo extends Component<{days: string[]}> {
|
|
291
|
+
static template = `
|
|
292
|
+
const {Select, Option} = this;
|
|
293
|
+
<div>
|
|
294
|
+
<Select v-model="days" filterable multiple creatable keepKeywords={false}>
|
|
295
|
+
<Option value="Monday">星期一</Option>
|
|
296
|
+
<Option value="Tuesday">星期二</Option>
|
|
297
|
+
<Option value="Wednesday">星期三</Option>
|
|
298
|
+
</Select>
|
|
299
|
+
</div>
|
|
300
|
+
`;
|
|
301
|
+
static defaults() {
|
|
302
|
+
return {
|
|
303
|
+
days: [] as string[],
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
private Select = Select as any;
|
|
307
|
+
private Option = Option as any;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const [instance, element] = mount(KeepKeywordsDemo);
|
|
311
|
+
const input = element.querySelector('.k-input-inner') as HTMLInputElement;
|
|
312
|
+
|
|
313
|
+
// input custom option "custom1"
|
|
314
|
+
input.click();
|
|
315
|
+
await wait();
|
|
316
|
+
input.value = 'custom1';
|
|
317
|
+
dispatchEvent(input, 'input');
|
|
318
|
+
await wait();
|
|
319
|
+
|
|
320
|
+
// check the created option appears in dropdown
|
|
321
|
+
const dropdown = getElement('.k-select-menu')!;
|
|
322
|
+
expect(dropdown.innerHTML).to.contain('custom1');
|
|
323
|
+
|
|
324
|
+
// press enter to create and select
|
|
325
|
+
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
326
|
+
await wait();
|
|
327
|
+
|
|
328
|
+
// check the option is selected, and the input is cleared
|
|
329
|
+
expect(instance.get('days')).to.eql(['custom1']);
|
|
330
|
+
expect(input.value).to.eql('');
|
|
331
|
+
|
|
332
|
+
// input the same option "custom1" again
|
|
333
|
+
input.value = 'custom1';
|
|
334
|
+
dispatchEvent(input, 'input');
|
|
335
|
+
await wait();
|
|
336
|
+
|
|
337
|
+
// press enter again
|
|
338
|
+
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
339
|
+
await wait();
|
|
340
|
+
|
|
341
|
+
// check the option is still selected (not be unselected), and the input is cleared
|
|
342
|
+
expect(instance.get('days')).to.eql(['custom1']); // should be selected
|
|
343
|
+
expect(input.value).to.eql(''); // should be cleared
|
|
344
|
+
|
|
345
|
+
// input another custom option "custom2"
|
|
346
|
+
input.value = 'custom2';
|
|
347
|
+
dispatchEvent(input, 'input');
|
|
348
|
+
await wait();
|
|
349
|
+
dispatchEvent(document, 'keydown', {keyCode: 13});
|
|
350
|
+
await wait();
|
|
351
|
+
|
|
352
|
+
// check two options are selected
|
|
353
|
+
expect(instance.get('days')).to.eql(['custom1', 'custom2']);
|
|
354
|
+
expect(input.value).to.eql('');
|
|
355
|
+
|
|
356
|
+
// test the normal behavior of original options
|
|
357
|
+
input.click();
|
|
358
|
+
await wait();
|
|
359
|
+
const mondayOption = dropdown.querySelector('[data-value="Monday"]') as HTMLElement;
|
|
360
|
+
if (mondayOption) {
|
|
361
|
+
mondayOption.click();
|
|
362
|
+
await wait();
|
|
363
|
+
expect(instance.get('days')).to.include('Monday');
|
|
364
|
+
|
|
365
|
+
// click again should be unselected (original options are not affected by keepKeywords)
|
|
366
|
+
mondayOption.click();
|
|
367
|
+
await wait();
|
|
368
|
+
expect(instance.get('days')).to.not.include('Monday');
|
|
369
|
+
}
|
|
239
370
|
});
|
|
240
371
|
|
|
241
372
|
it('Tooltip with Select', async () => {
|
|
@@ -298,6 +429,94 @@ describe('Select', () => {
|
|
|
298
429
|
expect(instance.get('days')).include('Monday')
|
|
299
430
|
});
|
|
300
431
|
|
|
432
|
+
it('Searchable with multiple should show correct initial checkbox state', async () => {
|
|
433
|
+
class Demo extends Component {
|
|
434
|
+
static template = `
|
|
435
|
+
const {Select, Option} = this;
|
|
436
|
+
<Select v-model="days" searchable multiple>
|
|
437
|
+
<Option value="Monday" disabled>星期一</Option>
|
|
438
|
+
<Option value="Tuesday">星期二</Option>
|
|
439
|
+
<Option value="Wednesday">星期三</Option>
|
|
440
|
+
<Option value="Thursday">星期四</Option>
|
|
441
|
+
<Option value="Friday">星期五</Option>
|
|
442
|
+
<Option value="Saturday">星期六</Option>
|
|
443
|
+
<Option value="Sunday">星期天</Option>
|
|
444
|
+
<b:values args="[value]">
|
|
445
|
+
<div class="k-value">
|
|
446
|
+
已选择{value.length}项 / 共7项
|
|
447
|
+
</div>
|
|
448
|
+
</b:values>
|
|
449
|
+
</Select>
|
|
450
|
+
`;
|
|
451
|
+
static defaults() {
|
|
452
|
+
return {
|
|
453
|
+
days: ['Tuesday']
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
private Tooltip = Tooltip;
|
|
457
|
+
private Select = Select;
|
|
458
|
+
private Option = Option;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const [instance, element] = mount(Demo as any);
|
|
462
|
+
|
|
463
|
+
expect(instance.get('days')).to.eql(['Tuesday']);
|
|
464
|
+
|
|
465
|
+
// first open dropdown, check initial state
|
|
466
|
+
element.click();
|
|
467
|
+
await wait();
|
|
468
|
+
|
|
469
|
+
const dropdown = getElement('.k-select-menu')!;
|
|
470
|
+
const checkboxes = dropdown.querySelectorAll<HTMLInputElement>('.k-checkbox input[type="checkbox"]');
|
|
471
|
+
const options = dropdown.querySelectorAll<HTMLElement>('.k-select-option');
|
|
472
|
+
|
|
473
|
+
// find the checkbox of Tuesday option
|
|
474
|
+
let tuesdayCheckbox: HTMLInputElement | null = null;
|
|
475
|
+
let tuesdayOption: HTMLElement | null = null;
|
|
476
|
+
|
|
477
|
+
options.forEach((option, index) => {
|
|
478
|
+
if (option.textContent?.includes('星期二')) {
|
|
479
|
+
tuesdayCheckbox = checkboxes[index];
|
|
480
|
+
tuesdayOption = option;
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
// check the checkbox of Tuesday should be checked
|
|
485
|
+
expect(tuesdayCheckbox).to.exist;
|
|
486
|
+
expect(tuesdayCheckbox!.checked).to.be.true;
|
|
487
|
+
|
|
488
|
+
// check the Tuesday option should have active style
|
|
489
|
+
expect(tuesdayOption).to.exist;
|
|
490
|
+
expect(tuesdayOption!.className).to.include('k-active');
|
|
491
|
+
|
|
492
|
+
// close dropdown
|
|
493
|
+
const [cancel] = dropdown.querySelectorAll<HTMLElement>('.k-select-footer .k-btn');
|
|
494
|
+
cancel.click();
|
|
495
|
+
await wait();
|
|
496
|
+
|
|
497
|
+
// reopen dropdown, check the state is still correct
|
|
498
|
+
element.click();
|
|
499
|
+
await wait();
|
|
500
|
+
|
|
501
|
+
const dropdown2 = getElement('.k-select-menu')!;
|
|
502
|
+
const checkboxes2 = dropdown2.querySelectorAll<HTMLInputElement>('.k-checkbox input[type="checkbox"]');
|
|
503
|
+
const options2 = dropdown2.querySelectorAll<HTMLElement>('.k-select-option');
|
|
504
|
+
|
|
505
|
+
let tuesdayCheckbox2: HTMLInputElement | null = null;
|
|
506
|
+
let tuesdayOption2: HTMLElement | null = null;
|
|
507
|
+
|
|
508
|
+
options2.forEach((option, index) => {
|
|
509
|
+
if (option.textContent?.includes('星期二')) {
|
|
510
|
+
tuesdayCheckbox2 = checkboxes2[index];
|
|
511
|
+
tuesdayOption2 = option;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// check the state is still correct when reopen
|
|
516
|
+
expect(tuesdayCheckbox2!.checked).to.be.true;
|
|
517
|
+
expect(tuesdayOption2!.className).to.include('k-active');
|
|
518
|
+
});
|
|
519
|
+
|
|
301
520
|
it('disabled option does not allow clearable and close', async () => {
|
|
302
521
|
const [instance, element] = mount(ImmutableDemo);
|
|
303
522
|
|
|
@@ -9,6 +9,7 @@ export interface OptionProps {
|
|
|
9
9
|
value: any
|
|
10
10
|
label?: string
|
|
11
11
|
disabled?: boolean
|
|
12
|
+
isCreated?: boolean
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
const typeDefs: Required<TypeDefs<OptionProps>> = {
|
|
@@ -17,6 +18,7 @@ const typeDefs: Required<TypeDefs<OptionProps>> = {
|
|
|
17
18
|
},
|
|
18
19
|
label: String,
|
|
19
20
|
disabled: Boolean,
|
|
21
|
+
isCreated: Boolean,
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export class Option extends Component<OptionProps> {
|
|
@@ -29,13 +31,20 @@ export class Option extends Component<OptionProps> {
|
|
|
29
31
|
@bind
|
|
30
32
|
private onSelect() {
|
|
31
33
|
const select = this.select!;
|
|
32
|
-
const multiple = select.get(
|
|
34
|
+
const {multiple, keepKeywords} = select.get();
|
|
33
35
|
const value = this.get('value');
|
|
36
|
+
const isCreated = this.get('isCreated');
|
|
34
37
|
|
|
35
38
|
if (!multiple) {
|
|
36
39
|
select.set('value', this.get('value'));
|
|
37
40
|
} else {
|
|
38
41
|
let values = select.get('value');
|
|
42
|
+
|
|
43
|
+
if (!keepKeywords && isCreated && Array.isArray(values) && values.includes(value)) {
|
|
44
|
+
select.resetKeywords();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
values = toggleArray(values, value);
|
|
40
49
|
select.set('value', values);
|
|
41
50
|
}
|
|
@@ -21,6 +21,7 @@ export interface SelectProps<T = string, Multipe extends boolean = boolean> exte
|
|
|
21
21
|
labelMap?: Map<any, Children>
|
|
22
22
|
card?: boolean
|
|
23
23
|
autoDisableArrow?: boolean
|
|
24
|
+
keepKeywords?: boolean
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface SelectEvents extends BaseSelectEvents { }
|
|
@@ -37,11 +38,13 @@ const typeDefs: Required<TypeDefs<SelectProps>> = {
|
|
|
37
38
|
labelMap: Map,
|
|
38
39
|
card: Boolean,
|
|
39
40
|
autoDisableArrow: Boolean,
|
|
41
|
+
keepKeywords: Boolean,
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
const defaults = (): Partial<SelectProps> => ({
|
|
43
45
|
...BaseSelect.defaults(),
|
|
44
46
|
labelMap: new Map(),
|
|
47
|
+
keepKeywords: true,
|
|
45
48
|
});
|
|
46
49
|
|
|
47
50
|
export class Select<
|
|
@@ -5,7 +5,7 @@ import '../../styles/global';
|
|
|
5
5
|
import { cache } from '../utils';
|
|
6
6
|
|
|
7
7
|
type SizeStyles = {
|
|
8
|
-
padding
|
|
8
|
+
padding: string,
|
|
9
9
|
height: string,
|
|
10
10
|
fontSize: string,
|
|
11
11
|
}
|
|
@@ -118,6 +118,8 @@ setDefault(() => {
|
|
|
118
118
|
makeGroupStyles?.clearCache();
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
+
export { select }
|
|
122
|
+
|
|
121
123
|
export const makeStyles = cache(function makeStyles(k: string) {
|
|
122
124
|
return css`
|
|
123
125
|
display: inline-flex;
|
|
@@ -11,13 +11,9 @@ import {
|
|
|
11
11
|
} from 'intact';
|
|
12
12
|
import {useState, State} from '../../hooks/useState';
|
|
13
13
|
import type {Select, SelectProps} from './select';
|
|
14
|
-
import {Option, OptionProps} from './option';
|
|
15
|
-
import {OptionGroup, OptionGroupProps} from './group';
|
|
16
|
-
import {isNullOrUndefined, EMPTY_OBJ, isStringOrNumber} from 'intact-shared';
|
|
17
|
-
import {getTextByChildren, mapChildren, isComponentVNode} from '../utils';
|
|
18
14
|
import type {Input} from '../input';
|
|
19
15
|
|
|
20
|
-
export function useInput(resetKeywords: (
|
|
16
|
+
export function useInput(resetKeywords: () => void) {
|
|
21
17
|
const component = useInstance() as Select;
|
|
22
18
|
const keywords = useState('');
|
|
23
19
|
const inputRef = createRef<Input>();
|
|
@@ -50,20 +46,22 @@ export function useInput(resetKeywords: (keywords: State<string>) => void) {
|
|
|
50
46
|
component.on('$changed:show', show => {
|
|
51
47
|
if (show) {
|
|
52
48
|
focusInput();
|
|
53
|
-
resetKeywords(
|
|
49
|
+
resetKeywords();
|
|
54
50
|
} else if (component.get('multiple')) {
|
|
55
|
-
resetKeywords(
|
|
51
|
+
resetKeywords();
|
|
56
52
|
}
|
|
57
53
|
});
|
|
58
54
|
component.on('$changed:value', () => {
|
|
59
|
-
const {multiple, filterable} = component.get();
|
|
55
|
+
const {multiple, filterable, keepKeywords} = component.get();
|
|
60
56
|
if (multiple && filterable) {
|
|
61
57
|
focusInput();
|
|
62
58
|
/**
|
|
63
59
|
* don't reset keywords on multiple mode for continue selection
|
|
64
60
|
* https://github.com/ksc-fe/kpc/issues/983
|
|
65
61
|
*/
|
|
66
|
-
|
|
62
|
+
if (!keepKeywords) {
|
|
63
|
+
resetKeywords();
|
|
64
|
+
}
|
|
67
65
|
}
|
|
68
66
|
});
|
|
69
67
|
|
|
@@ -47,8 +47,8 @@ export function useSearchable() {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
select.watch('value', initCheckedKeys);
|
|
50
|
-
select.on('hide', initCheckedKeys)
|
|
51
|
-
|
|
50
|
+
select.on('hide', initCheckedKeys);
|
|
51
|
+
initCheckedKeys();
|
|
52
52
|
return {checkedKeys, selectAll, unselectAll, toggleSelect, confirm};
|
|
53
53
|
}
|
|
54
54
|
|
|
Binary file
|