@king-design/intact 3.6.0-beta.0 → 3.6.1
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/button/demos/basic.md +0 -1
- package/components/cascader/index.spec.ts +7 -6
- package/components/copy/index.spec.ts +9 -14
- package/components/datepicker/basepicker.ts +26 -314
- package/components/datepicker/calendar.ts +3 -1
- package/components/datepicker/calendar.vdt +5 -2
- package/components/datepicker/dayjs.ts +2 -16
- package/components/datepicker/demos/multiple.md +5 -0
- package/components/datepicker/demos/yearMonth.md +2 -8
- package/components/datepicker/helpers.ts +5 -7
- package/components/datepicker/index.md +1 -2
- package/components/datepicker/index.spec.ts +596 -157
- package/components/datepicker/index.ts +16 -33
- package/components/datepicker/index.vdt +41 -35
- package/components/datepicker/shortcuts.ts +1 -1
- package/components/datepicker/styles.ts +27 -18
- package/components/datepicker/useConfirm.ts +82 -0
- package/components/datepicker/useDisabled.ts +29 -31
- package/components/datepicker/useFormats.ts +8 -4
- package/components/datepicker/useHighlight.ts +81 -0
- package/components/datepicker/useKeyboards.ts +2 -1
- package/components/datepicker/useMergeRange.ts +12 -12
- package/components/datepicker/useMonths.ts +6 -3
- package/components/datepicker/usePanel.ts +19 -19
- package/components/datepicker/useShowDate.ts +21 -41
- package/components/datepicker/useStatus.ts +34 -15
- package/components/datepicker/useValue.ts +43 -72
- package/components/datepicker/useValueBase.ts +312 -0
- package/components/datepicker/useWeeks.ts +1 -1
- package/components/datepicker/useYears.ts +7 -3
- 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/form/form.ts +4 -0
- package/components/form/index.md +2 -1
- package/components/form/index.spec.ts +2 -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/demos/horizontal.md +7 -1
- package/components/menu/index.spec.ts +19 -0
- package/components/menu/styles.ts +2 -1
- package/components/scrollSelect/useMouseEvents.ts +5 -4
- package/components/select/base.ts +3 -2
- package/components/select/base.vdt +2 -1
- package/components/select/demos/creatable.md +2 -2
- package/components/select/index.md +1 -1
- package/components/select/index.spec.ts +142 -36
- package/components/select/menu.ts +1 -1
- package/components/select/option.ts +2 -1
- package/components/select/select.ts +1 -0
- package/components/select/styles.ts +3 -1
- package/components/select/useCard.ts +22 -4
- package/components/select/useInput.ts +5 -9
- package/components/spinner/index.spec.ts +18 -0
- package/components/spinner/useValue.ts +2 -1
- package/components/table/index.spec.ts +69 -1
- package/components/table/useStickyHeader.ts +1 -1
- package/components/timepicker/index.spec.ts +145 -27
- package/components/timepicker/panelPicker.ts +10 -4
- package/components/timepicker/panelPicker.vdt +3 -5
- package/components/timepicker/styles.ts +1 -0
- 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/index.spec.ts +1 -1
- package/es/components/cascader/index.spec.js +18 -19
- package/es/components/copy/index.spec.js +14 -31
- package/es/components/datepicker/basepicker.d.ts +6 -27
- package/es/components/datepicker/basepicker.js +23 -268
- package/es/components/datepicker/calendar.d.ts +4 -2
- package/es/components/datepicker/dayjs.d.ts +2 -13
- package/es/components/datepicker/helpers.d.ts +3 -2
- package/es/components/datepicker/helpers.js +2 -3
- package/es/components/datepicker/index.d.ts +21 -29
- package/es/components/datepicker/index.js +22 -32
- package/es/components/datepicker/index.spec.js +1277 -484
- package/es/components/datepicker/index.vdt.js +39 -38
- package/es/components/datepicker/shortcuts.d.ts +1 -1
- package/es/components/datepicker/styles.d.ts +7 -2
- package/es/components/datepicker/styles.js +10 -15
- package/es/components/datepicker/useConfirm.d.ts +6 -0
- package/es/components/datepicker/useConfirm.js +65 -0
- package/es/components/datepicker/useDisabled.d.ts +5 -3
- package/es/components/datepicker/useDisabled.js +22 -27
- package/es/components/datepicker/useFormats.d.ts +2 -2
- package/es/components/datepicker/useFormats.js +6 -2
- 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 +1 -1
- package/es/components/datepicker/useMergeRange.js +11 -16
- 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/useShowDate.d.ts +1 -1
- package/es/components/datepicker/useShowDate.js +15 -40
- package/es/components/datepicker/useStatus.js +33 -16
- package/es/components/datepicker/useValue.d.ts +11 -6
- package/es/components/datepicker/useValue.js +49 -69
- package/es/components/datepicker/useValueBase.d.ts +28 -0
- package/es/components/datepicker/useValueBase.js +280 -0
- package/es/components/datepicker/useYears.js +6 -3
- package/es/components/dropdown/dropdown.d.ts +1 -0
- package/es/components/dropdown/dropdown.js +7 -4
- package/es/components/form/form.d.ts +1 -0
- package/es/components/form/form.js +7 -0
- package/es/components/form/index.spec.js +10 -8
- 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/menu/index.spec.js +28 -0
- package/es/components/menu/styles.js +2 -2
- package/es/components/scrollSelect/useMouseEvents.js +5 -4
- package/es/components/select/base.d.ts +1 -1
- package/es/components/select/base.js +3 -2
- package/es/components/select/base.vdt.js +4 -3
- package/es/components/select/index.spec.js +346 -218
- package/es/components/select/menu.js +1 -1
- package/es/components/select/option.js +2 -1
- package/es/components/select/select.js +2 -1
- package/es/components/select/styles.d.ts +79 -0
- package/es/components/select/styles.js +1 -0
- package/es/components/select/useCard.d.ts +4 -3
- package/es/components/select/useCard.js +15 -4
- package/es/components/select/useInput.d.ts +1 -1
- package/es/components/select/useInput.js +4 -4
- package/es/components/spinner/index.spec.js +82 -44
- package/es/components/spinner/useValue.js +2 -1
- 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 +21 -16
- package/es/components/timepicker/panelPicker.js +7 -4
- package/es/components/timepicker/panelPicker.vdt.js +5 -9
- package/es/components/timepicker/selectPicker.d.ts +4 -3
- package/es/components/timepicker/styles.js +1 -1
- 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 +6 -3
- package/es/components/timepicker/useDisabled.js +13 -4
- package/es/components/timepicker/useFormats.d.ts +1 -1
- package/es/components/timepicker/useValue.d.ts +13 -8
- package/es/components/timepicker/useValue.js +14 -15
- package/es/components/tour/index.spec.js +1 -1
- package/es/index.d.ts +2 -2
- package/es/index.js +2 -2
- package/es/site/data/components/button/demos/basic/react.js +0 -2
- package/es/site/data/components/datepicker/demos/multiple/index.d.ts +1 -0
- package/es/site/data/components/datepicker/demos/multiple/index.js +2 -1
- package/es/site/data/components/datepicker/demos/multiple/react.d.ts +1 -0
- package/es/site/data/components/datepicker/demos/multiple/react.js +13 -2
- package/es/site/data/components/datepicker/demos/yearMonth/index.d.ts +0 -2
- package/es/site/data/components/datepicker/demos/yearMonth/index.js +1 -3
- package/es/site/data/components/datepicker/demos/yearMonth/react.d.ts +0 -2
- package/es/site/data/components/datepicker/demos/yearMonth/react.js +1 -21
- package/es/site/data/components/menu/demos/horizontal/react.js +5 -1
- package/es/site/data/components/select/demos/creatable/react.js +2 -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/customText/index.d.ts +19 -6
- package/es/site/data/components/tour/demos/customText/index.js +18 -17
- package/es/site/data/components/tour/demos/customText/react.d.ts +20 -6
- package/es/site/data/components/tour/demos/customText/react.js +31 -27
- package/es/test/demos.js +1 -1
- package/index.ts +2 -2
- package/package.json +2 -2
- package/components/datepicker/demos/nowrap.md +0 -35
- package/components/datepicker/usePosition.ts +0 -169
- package/es/components/datepicker/usePosition.d.ts +0 -10
- package/es/components/datepicker/usePosition.js +0 -166
- package/es/site/data/components/datepicker/demos/nowrap/index.d.ts +0 -10
- package/es/site/data/components/datepicker/demos/nowrap/index.js +0 -19
- package/es/site/data/components/datepicker/demos/nowrap/react.d.ts +0 -10
- package/es/site/data/components/datepicker/demos/nowrap/react.js +0 -49
- package/es/site/data/components/tour/demos/customButtons/index.d.ts +0 -33
- package/es/site/data/components/tour/demos/customButtons/index.js +0 -55
- package/es/site/data/components/tour/demos/customButtons/react.d.ts +0 -33
- package/es/site/data/components/tour/demos/customButtons/react.js +0 -99
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import {useInstance, Component, TypeDefs} from 'intact';
|
|
2
|
+
import {useState, watchState, State} from '../../hooks/useState';
|
|
3
|
+
import dayjs, {Dayjs, OpUnitType, QUnitType} from './dayjs';
|
|
4
|
+
import {findValueIndex} from './helpers';
|
|
5
|
+
import type {useFormats} from './useFormats';
|
|
6
|
+
import type {useDisabled} from './useDisabled';
|
|
7
|
+
import {isEqualArray, last, bind} from '../utils';
|
|
8
|
+
import {PanelFlags, usePanel} from './usePanel';
|
|
9
|
+
import type {BasePicker, BasePickerProps} from './basepicker';
|
|
10
|
+
|
|
11
|
+
export type Value = string | Date | number | Dayjs;
|
|
12
|
+
|
|
13
|
+
export type StateValueRange = [Dayjs] | [Dayjs, Dayjs];
|
|
14
|
+
export type StateValueItem = Dayjs | StateValueRange;
|
|
15
|
+
export type StateValue = StateValueItem[]
|
|
16
|
+
|
|
17
|
+
export type StringValue = string | string[] | [string, string] | [string, string][]
|
|
18
|
+
export type DayjsValueRange = [Dayjs, Dayjs]
|
|
19
|
+
export type DayjsValueItem = Dayjs | DayjsValueRange
|
|
20
|
+
export type DayjsValue = DayjsValueItem[]
|
|
21
|
+
|
|
22
|
+
export function useValueBase(
|
|
23
|
+
{
|
|
24
|
+
createDateByValueFormat,
|
|
25
|
+
createDateByShowFormat,
|
|
26
|
+
getShowString,
|
|
27
|
+
getValueString,
|
|
28
|
+
}: ReturnType<typeof useFormats>,
|
|
29
|
+
{isDisabled, minDate}: ReturnType<typeof useDisabled>,
|
|
30
|
+
panel: ReturnType<typeof usePanel>,
|
|
31
|
+
shouldUpdateValue: (v: StateValueItem) => boolean,
|
|
32
|
+
updateValueOnInput: (v: DayjsValueItem) => void,
|
|
33
|
+
getEqualType: () => OpUnitType | QUnitType,
|
|
34
|
+
updateStateValue: (v: DayjsValue, value: State<StateValue>) => void,
|
|
35
|
+
) {
|
|
36
|
+
// Normalize the value to multipe values, no matter it's multipe or not
|
|
37
|
+
const value = useState<StateValue>([]);
|
|
38
|
+
const instance = useInstance() as BasePicker<BasePickerProps<Value>>;
|
|
39
|
+
let dayjsValue: DayjsValue = [];
|
|
40
|
+
|
|
41
|
+
instance.watch('value', (newValue, oldValue) => {
|
|
42
|
+
if (isEqualArray(newValue, oldValue)) return;
|
|
43
|
+
dayjsValue = convertToDayjs(newValue);
|
|
44
|
+
updateStateValue(dayjsValue, value);
|
|
45
|
+
// should update keywords
|
|
46
|
+
instance.resetKeywords();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
watchState(value, (value) => {
|
|
50
|
+
// silently update the keywords to display the currently selected value
|
|
51
|
+
instance.resetKeywords(true);
|
|
52
|
+
/**
|
|
53
|
+
* the position may changed after the input break line in multipe mode
|
|
54
|
+
* use Macro task instead of nextTick, because it has too many Micro tasks
|
|
55
|
+
*/
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
instance.position();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
instance.on('hide', () => {
|
|
61
|
+
// reset the value after hiding
|
|
62
|
+
value.set(dayjsValue.slice(0));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
watchState(instance.input.keywords, v => {
|
|
66
|
+
const {range, multiple} = instance.get();
|
|
67
|
+
if (!multiple && v === '') return instance.set('value', null);
|
|
68
|
+
|
|
69
|
+
if (range) {
|
|
70
|
+
const [start, end] = v.split(/\s*~\s*/).map(s => s.trim());
|
|
71
|
+
if (start && end) {
|
|
72
|
+
const startDate = createDateByShowFormat(start);
|
|
73
|
+
if (!isValidDate(startDate)) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const endDate = createDateByShowFormat(end);
|
|
77
|
+
if (!isValidDate(endDate)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (endDate.isAfter(startDate)) {
|
|
81
|
+
updateValueOnInput([startDate, endDate]);
|
|
82
|
+
} else {
|
|
83
|
+
updateValueOnInput([endDate, startDate]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} else {
|
|
87
|
+
const date = createDateByShowFormat(v);
|
|
88
|
+
if (isValidDate(date)) {
|
|
89
|
+
updateValueOnInput(date);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
function convertToDayjs(v: BasePickerProps<Value>['value']): DayjsValue {
|
|
95
|
+
if (!v || Array.isArray(v) && !v.length) return [];
|
|
96
|
+
const {multiple} = instance.get();
|
|
97
|
+
if (!multiple) {
|
|
98
|
+
v = [v] as any;
|
|
99
|
+
}
|
|
100
|
+
return (v as (Value | [Value, Value])[]).map(value => {
|
|
101
|
+
if (Array.isArray(value)) {
|
|
102
|
+
// range
|
|
103
|
+
return value.map(createDateByValueFormat);
|
|
104
|
+
}
|
|
105
|
+
return createDateByValueFormat(value);
|
|
106
|
+
}) as DayjsValue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function convertToValueString(v: DayjsValue): StringValue | null {
|
|
110
|
+
const results = v.map(value => {
|
|
111
|
+
if (Array.isArray(value)) {
|
|
112
|
+
return value.map(getValueString);
|
|
113
|
+
}
|
|
114
|
+
return getValueString(value);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (!instance.get('multiple')) {
|
|
118
|
+
return results[0] || null;
|
|
119
|
+
}
|
|
120
|
+
return results as StringValue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function format(): string | string[] {
|
|
124
|
+
const { multiple } = instance.get();
|
|
125
|
+
let labelValue = value.value;
|
|
126
|
+
if (multiple) {
|
|
127
|
+
labelValue = dayjsValue;
|
|
128
|
+
}
|
|
129
|
+
const results = labelValue.map(formatSingleValue);
|
|
130
|
+
|
|
131
|
+
if (!instance.get('multiple')) {
|
|
132
|
+
return results[0];
|
|
133
|
+
}
|
|
134
|
+
return results;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function formatSingleValue(value: StateValueItem) {
|
|
138
|
+
if (Array.isArray(value)) {
|
|
139
|
+
if (value.length === 1) {
|
|
140
|
+
return getShowString(value[0]) + ' ~';
|
|
141
|
+
}
|
|
142
|
+
return value.map(getShowString).join(' ~ ');
|
|
143
|
+
}
|
|
144
|
+
return getShowString(value);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function setSingleDate(v: StateValueItem, fromInput: boolean) {
|
|
148
|
+
value.set([v]);
|
|
149
|
+
if (fromInput || shouldUpdateValue(v)) {
|
|
150
|
+
updateValue();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function addMultipeDate(v: StateValueItem, fromInput: boolean) {
|
|
155
|
+
const {range} = instance.get();
|
|
156
|
+
let _value = value.value as StateValueItem[];
|
|
157
|
+
_value = !_value ? [] : _value.slice();
|
|
158
|
+
|
|
159
|
+
if (range && (v as StateValueRange).length === 2) {
|
|
160
|
+
// pop the last value firstly, if it only has the start date
|
|
161
|
+
const lastValue = last(_value);
|
|
162
|
+
if (lastValue && (lastValue as StateValueRange).length < 2) {
|
|
163
|
+
_value.pop();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (_value.length > dayjsValue.length) {
|
|
168
|
+
// remove the temporary value added by selecting time directly
|
|
169
|
+
_value.pop();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let _shouldUpdateValue = true;
|
|
173
|
+
if (fromInput || shouldUpdateValue(v)) {
|
|
174
|
+
// if select the date/year/month, then toggle the value.
|
|
175
|
+
// if from input, treat the value as the final value
|
|
176
|
+
const index = findValueIndex(_value, v, getEqualType());
|
|
177
|
+
if (index > -1) {
|
|
178
|
+
_value.splice(index, 1);
|
|
179
|
+
} else {
|
|
180
|
+
_value.push(v);
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
// select the datetime, only push the value,
|
|
184
|
+
// and unique the array on click confirm button
|
|
185
|
+
_value.push(v);
|
|
186
|
+
_shouldUpdateValue = false;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
value.set(_value);
|
|
190
|
+
|
|
191
|
+
if (_shouldUpdateValue) {
|
|
192
|
+
updateValue();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function setValue(v: StateValueItem, fromInput: boolean) {
|
|
197
|
+
const multiple = instance.get('multiple');
|
|
198
|
+
if (multiple) {
|
|
199
|
+
addMultipeDate(v, fromInput);
|
|
200
|
+
} else {
|
|
201
|
+
setSingleDate(v, fromInput);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function updateValue() {
|
|
206
|
+
const _value = value.value as DayjsValue;
|
|
207
|
+
const { range } = instance.get();
|
|
208
|
+
if (range) {
|
|
209
|
+
// only fix the last value, since the others are already fixed
|
|
210
|
+
const lastValue = last(_value) as DayjsValueRange;
|
|
211
|
+
if (lastValue) {
|
|
212
|
+
lastValue.sort((a, b) => a.isAfter(b) ? 1 : -1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const valueStr = convertToValueString(_value);
|
|
217
|
+
// only trigger change event once
|
|
218
|
+
if (!isEqualArray(valueStr, instance.get('value'))) {
|
|
219
|
+
instance.set('value', valueStr);
|
|
220
|
+
instance.resetKeywords();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// TODO
|
|
225
|
+
function setMoment() {
|
|
226
|
+
const now = dayjs();
|
|
227
|
+
setValue(now, true);
|
|
228
|
+
instance.hide();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function unique() {
|
|
232
|
+
const _value = value.value;
|
|
233
|
+
const map: Record<string, true> = {};
|
|
234
|
+
const results: StateValue = [];
|
|
235
|
+
_value.forEach(value => {
|
|
236
|
+
let key: string;
|
|
237
|
+
if (Array.isArray(value)) {
|
|
238
|
+
key = (value as DayjsValueRange).map(getValueString).join(' ~ ');
|
|
239
|
+
} else {
|
|
240
|
+
key = getValueString(value);
|
|
241
|
+
}
|
|
242
|
+
if (!map[key]) {
|
|
243
|
+
map[key] = true;
|
|
244
|
+
results.push(value);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
value.set(results);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function isValidDate(date: Dayjs) {
|
|
252
|
+
return date.isValid() && !isDisabled(date, getEqualType());
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function onChangeTime(date: Dayjs, flag: PanelFlags) {
|
|
256
|
+
const {range, multiple} = instance.get();
|
|
257
|
+
const values = value.value.slice();
|
|
258
|
+
// maybe we select time directly
|
|
259
|
+
let lastIndex = Math.max(values.length - 1, 0);
|
|
260
|
+
if (allValuesUpdatedInMultipleMode()) {
|
|
261
|
+
// need add new value, if all value.value has updated to dayjsValue
|
|
262
|
+
lastIndex = values.length;
|
|
263
|
+
}
|
|
264
|
+
let _value: StateValueItem = date;
|
|
265
|
+
|
|
266
|
+
if (range) {
|
|
267
|
+
_value = (values as DayjsValueRange[])[lastIndex];
|
|
268
|
+
if (_value) {
|
|
269
|
+
_value = _value.slice() as DayjsValueRange;
|
|
270
|
+
} else {
|
|
271
|
+
_value = [] as unknown as DayjsValueRange;
|
|
272
|
+
}
|
|
273
|
+
_value[flag] = date;
|
|
274
|
+
instance.trigger('selecting', _value, false);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
values[lastIndex] = _value;
|
|
278
|
+
value.set(values);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function getTimeValue(flag: PanelFlags): Dayjs | null | undefined {
|
|
282
|
+
const _value = value.value;
|
|
283
|
+
if (!_value.length) return null;
|
|
284
|
+
|
|
285
|
+
const {range, min} = instance.get();
|
|
286
|
+
const lastValue = last(_value);
|
|
287
|
+
return range ? (lastValue as StateValueRange)[flag] : lastValue as Dayjs;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function getDayjsValue() {
|
|
291
|
+
return dayjsValue;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function allValuesUpdatedInMultipleMode() {
|
|
295
|
+
return instance.get('multiple') && value.value.length === dayjsValue.length;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return {
|
|
299
|
+
value,
|
|
300
|
+
format,
|
|
301
|
+
formatSingleValue,
|
|
302
|
+
onChangeTime,
|
|
303
|
+
getTimeValue,
|
|
304
|
+
setValue,
|
|
305
|
+
convertToDayjs,
|
|
306
|
+
getDayjsValue,
|
|
307
|
+
unique,
|
|
308
|
+
setMoment,
|
|
309
|
+
updateValue,
|
|
310
|
+
allValuesUpdatedInMultipleMode,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
@@ -39,7 +39,7 @@ export function useWeeks(
|
|
|
39
39
|
isDisabled: status.isDisabled(day),
|
|
40
40
|
isHover: day.isSame(focusDate.value, 'week'),
|
|
41
41
|
isInRange: !isFirstOrLastDay && status.isActive(day, 'week')
|
|
42
|
-
});
|
|
42
|
+
});
|
|
43
43
|
}
|
|
44
44
|
// 每周的数据,包括周数和7天的信息
|
|
45
45
|
weeks.push({week: weekNumber, days});
|
|
@@ -55,10 +55,14 @@ export function useYears(
|
|
|
55
55
|
|
|
56
56
|
function onClick(date: Dayjs) {
|
|
57
57
|
showDate.set(date);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const datepickerType = instance.datepicker.get('type');
|
|
59
|
+
|
|
60
|
+
if (datepickerType === 'year') {
|
|
61
61
|
instance.triggerChange(date);
|
|
62
|
+
} else if (datepickerType === 'quarter') {
|
|
63
|
+
instance.type.set('quarter');
|
|
64
|
+
} else {
|
|
65
|
+
instance.type.set('month');
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -15,7 +15,6 @@ import {bind, isTextChildren, getRestProps} from '../utils';
|
|
|
15
15
|
import {EMPTY_OBJ, isFunction, noop} from 'intact-shared';
|
|
16
16
|
import {Options, position, Feedback} from '../position';
|
|
17
17
|
import {cx} from '@emotion/css';
|
|
18
|
-
import {DropdownMenu} from './menu';
|
|
19
18
|
import {useDocumentClick, containsOrEqual} from '../../hooks/useDocumentClick';
|
|
20
19
|
import {Portal, PortalProps} from '../portal';
|
|
21
20
|
import {useShowHideEvents} from '../../hooks/useShowHideEvents';
|
|
@@ -40,6 +39,7 @@ export interface DropdownProps {
|
|
|
40
39
|
collison?: Position['collision']
|
|
41
40
|
of?: 'self' | 'parent' | Event
|
|
42
41
|
container?: PortalProps['container']
|
|
42
|
+
alwaysShowOnClick?: boolean
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export interface DropdownEvents {
|
|
@@ -64,6 +64,7 @@ const typeDefs: Required<TypeDefs<DropdownProps>> = {
|
|
|
64
64
|
of: ['self', 'parent', typeof Event === 'undefined' ? undefined : Event],
|
|
65
65
|
container: [String, Function],
|
|
66
66
|
collison: ['none', 'fit', 'flip', 'flipfit', Array],
|
|
67
|
+
alwaysShowOnClick: Boolean,
|
|
67
68
|
};
|
|
68
69
|
|
|
69
70
|
const defaults = (): Partial<DropdownProps> => ({
|
|
@@ -266,15 +267,15 @@ function useDocumentClickForDropdown(dropdown: Dropdown) {
|
|
|
266
267
|
// case 2: if right click on a trigger and its trigger type is contextmenu, ignore it
|
|
267
268
|
// case 3: if click on a trigger and its trigger type is focus, do nothing
|
|
268
269
|
// case 3: if click on sub-dropdown, we should also show the parent dropdown, so ignore it
|
|
269
|
-
const trigger = dropdown.get(
|
|
270
|
+
const { trigger, alwaysShowOnClick }= dropdown.get();
|
|
270
271
|
if (trigger === 'focus') return;
|
|
271
272
|
|
|
272
273
|
const isHover = trigger === 'hover';
|
|
273
|
-
if (isHover || trigger === 'contextmenu') {
|
|
274
|
+
if (isHover || trigger === 'contextmenu' || alwaysShowOnClick) {
|
|
274
275
|
const triggerDom = findDomFromVNode(dropdown.$lastInput!, true) as Element;
|
|
275
276
|
const target = e.target as Element;
|
|
276
277
|
if (containsOrEqual(triggerDom, target)) {
|
|
277
|
-
if (isHover) return;
|
|
278
|
+
if (isHover || alwaysShowOnClick) return;
|
|
278
279
|
if (!isHover && e.type === 'contextmenu') return;
|
|
279
280
|
}
|
|
280
281
|
}
|
|
@@ -17,6 +17,7 @@ sidebar: doc
|
|
|
17
17
|
| position | 菜单弹出的位置,默认与触发器左侧对齐向下偏移`8px`的地方 | `Position` | `"left"` | `"bottom"` | `"right"` | `"top"` | `{my: 'left top+8', 'left bottom'}` |
|
|
18
18
|
| of | 弹出菜单的位置是相对当前触发元素,还是触发元素所在的菜单元素,这在嵌套菜单中可能会用到,可以使所有子菜单保持统一的对齐方式,例如:级联选择(Cascader)组件 | `"self"` | `"parent"` | `Event` | `"self"` |
|
|
19
19
|
| container | 指定弹出菜单追加的位置,默认:`Dialog`类型的组件会追加到`Dialog`中,其他会追加到`body`中。你可以传入函数返回一个DOM用来作为插入的容器,或者传入字符串用来给`querySelector`进行查询 | `Container` | `undefined` |
|
|
20
|
+
| alwaysShowOnClick | 不管什么触发方式,重复点击触发器,都不隐藏弹层 | `boolean` | `false` |
|
|
20
21
|
|
|
21
22
|
```ts
|
|
22
23
|
type Position = {
|
|
@@ -3,7 +3,7 @@ import template from './item.vdt';
|
|
|
3
3
|
import {bind} from '../utils';
|
|
4
4
|
import {useItemKeyboard, MenuKeyboardMethods} from './useKeyboard';
|
|
5
5
|
import {Dropdown, DROPDOWN} from './dropdown';
|
|
6
|
-
import {DropdownMenu, DROPDOWN_MENU} from './menu';
|
|
6
|
+
import {type DropdownMenu, DROPDOWN_MENU} from './menu';
|
|
7
7
|
import {IgnoreClickEvent} from '../../hooks/useDocumentClick';
|
|
8
8
|
import { Dropdown as ExportDropdown, DropdownMenu as ExportDropdownMenu } from '.';
|
|
9
9
|
import { useConfigContext } from '../config';
|
|
@@ -20,7 +20,6 @@ import {useKeyboard} from '../../hooks/useKeyboard';
|
|
|
20
20
|
import {useState} from '../../hooks/useState';
|
|
21
21
|
import {eachChildren, isComponentVNode} from '../utils';
|
|
22
22
|
import {DropdownItem} from './item';
|
|
23
|
-
import {isStringOrNumber} from 'intact-shared';
|
|
24
23
|
// can not import DropdownMenu from index.ts, otherwise it will cause circle reference
|
|
25
24
|
// import {DropdownMenu} from './';
|
|
26
25
|
import {DropdownMenu} from './menu';
|
package/components/form/form.ts
CHANGED
package/components/form/index.md
CHANGED
|
@@ -63,7 +63,8 @@ export declare type ClassName = string | ((value: any, param: any) => string)
|
|
|
63
63
|
| --- | --- | --- | --- |
|
|
64
64
|
| validate | 验证表单所有规则 | - | `Promise<boolean>`: `.then(valid => {})`,`valid`为`true`验证成功,否则失败 |
|
|
65
65
|
| reset | 重置表单验证状态 | - | `undefined` |
|
|
66
|
-
| getFirstInvalidFormItem |
|
|
66
|
+
| getFirstInvalidFormItem | 获取第一条校验失败的`FormItem` | - | `FormItem` |
|
|
67
|
+
| getAllInvalidFormItems | 获取所有校验失败的`FormItem` | - | `FormItem[]` |
|
|
67
68
|
|
|
68
69
|
# 静态方法
|
|
69
70
|
|
|
@@ -33,6 +33,8 @@ describe('Form', () => {
|
|
|
33
33
|
expect(element.innerHTML).to.matchSnapshot();
|
|
34
34
|
const item = form.getFirstInvalidFormItem()!;
|
|
35
35
|
expect(item.get('label')).to.eql('Input');
|
|
36
|
+
const items = form.getAllInvalidFormItems();
|
|
37
|
+
expect(items.length).to.eql(10);
|
|
36
38
|
|
|
37
39
|
instance.reset();
|
|
38
40
|
await wait();
|
|
@@ -177,4 +177,46 @@ describe('Input', () => {
|
|
|
177
177
|
await wait(50);
|
|
178
178
|
expect(input.offsetWidth).to.gt(16);
|
|
179
179
|
});
|
|
180
|
+
|
|
181
|
+
it('should handle textarea resize correctly', async () => {
|
|
182
|
+
class ResizeDemo extends Component {
|
|
183
|
+
static template = `
|
|
184
|
+
const {Input} = this;
|
|
185
|
+
<div>
|
|
186
|
+
<Input type="textarea" resize="none" placeholder="resize none" />
|
|
187
|
+
<Input type="textarea" resize="vertical" placeholder="resize vertical" />
|
|
188
|
+
<Input type="textarea" resize="none" rows="auto" placeholder="resize none with auto rows" />
|
|
189
|
+
</div>
|
|
190
|
+
`;
|
|
191
|
+
private Input = Input;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const [instance, element] = mount(ResizeDemo as any);
|
|
195
|
+
|
|
196
|
+
const inputElements = element.querySelectorAll('.k-input');
|
|
197
|
+
|
|
198
|
+
// should have k-resize-none class
|
|
199
|
+
const resizeNoneElement = inputElements[0];
|
|
200
|
+
expect(resizeNoneElement.classList.contains('k-resize-none')).to.be.true;
|
|
201
|
+
expect(resizeNoneElement.classList.contains('k-resize-vertical')).to.be.false;
|
|
202
|
+
|
|
203
|
+
const resizeVerticalElement = inputElements[1];
|
|
204
|
+
expect(resizeVerticalElement.classList.contains('k-resize-vertical')).to.be.true;
|
|
205
|
+
expect(resizeVerticalElement.classList.contains('k-resize-none')).to.be.false;
|
|
206
|
+
|
|
207
|
+
// resize="none" with rows="auto" (should have k-resize-none class)
|
|
208
|
+
const resizeNoneAutoElement = inputElements[2];
|
|
209
|
+
expect(resizeNoneAutoElement.classList.contains('k-resize-none')).to.be.true;
|
|
210
|
+
|
|
211
|
+
// Test CSS computed styles to ensure resize is applied correctly
|
|
212
|
+
const textareas = element.querySelectorAll('.k-textarea');
|
|
213
|
+
const textarea1 = textareas[0] as HTMLTextAreaElement;
|
|
214
|
+
const textarea2 = textareas[1] as HTMLTextAreaElement;
|
|
215
|
+
|
|
216
|
+
const computedStyle1 = getComputedStyle(textarea1);
|
|
217
|
+
const computedStyle2 = getComputedStyle(textarea2);
|
|
218
|
+
|
|
219
|
+
expect(computedStyle1.resize).to.eql('none');
|
|
220
|
+
expect(computedStyle2.resize).to.eql('vertical');
|
|
221
|
+
});
|
|
180
222
|
});
|
|
@@ -157,6 +157,14 @@ export class Input<V extends Value = Value> extends Component<InputProps<V>, Inp
|
|
|
157
157
|
selectValue(this.inputRef.value!);
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
getStringWidth(str: string) {
|
|
161
|
+
return this.autoWidth.getStringWidth(str);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getSelectionStart() {
|
|
165
|
+
return this.inputRef.value!.selectionStart;
|
|
166
|
+
}
|
|
167
|
+
|
|
160
168
|
@bind
|
|
161
169
|
private clear(e: MouseEvent) {
|
|
162
170
|
this.set<string>('value', '');
|
|
@@ -41,8 +41,7 @@ const classNameObj = {
|
|
|
41
41
|
[`${k}-flat`]: flat,
|
|
42
42
|
[`${k}-type-textarea`]: type === 'textarea',
|
|
43
43
|
[`${k}-focus`]: isFocus.value,
|
|
44
|
-
[`${k}-resize-${resize}`]: type === 'textarea'
|
|
45
|
-
[`${k}-resize-none`]: type === 'textarea' && !isNotAutoRows,
|
|
44
|
+
[`${k}-resize-${isNotAutoRows ? resize : 'none'}`]: type === 'textarea',
|
|
46
45
|
[className]: className,
|
|
47
46
|
[makeStyles(k)]: true,
|
|
48
47
|
}
|
|
@@ -54,7 +53,7 @@ const {
|
|
|
54
53
|
showIcon: showPasswordIcon,
|
|
55
54
|
} = this.showPassword;
|
|
56
55
|
|
|
57
|
-
const {fakeRef, width: {value: fakeWidth}} = this.autoWidth;
|
|
56
|
+
const {fakeRef, width: {value: fakeWidth}, forceShowFake} = this.autoWidth;
|
|
58
57
|
const height = this.autoRows;
|
|
59
58
|
|
|
60
59
|
const inputValue = frozenOnInput && inputing ? originalValue : value;
|
|
@@ -142,7 +141,7 @@ if (hasInputValue) {
|
|
|
142
141
|
</span>
|
|
143
142
|
<b:suffix />
|
|
144
143
|
</div>
|
|
145
|
-
<div class={`${k}-input-fake`} v-if={autoWidth}>
|
|
144
|
+
<div class={`${k}-input-fake`} v-if={autoWidth || forceShowFake.value}>
|
|
146
145
|
<pre ref={fakeRef}>{!hasValue ? (hasInputValue || !defaultValue ? placeholder : defaultValue) : inputValue}</pre>
|
|
147
146
|
</div>
|
|
148
147
|
</div>
|
|
@@ -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) {
|
|
@@ -27,7 +27,13 @@ import {Menu, MenuItem, Switch, Icon} from 'kpc';
|
|
|
27
27
|
</MenuItem>
|
|
28
28
|
</Menu>
|
|
29
29
|
</MenuItem>
|
|
30
|
-
<MenuItem key="4"
|
|
30
|
+
<MenuItem key="4">
|
|
31
|
+
<Icon class="ion-gear-b" />menu 4
|
|
32
|
+
<Menu>
|
|
33
|
+
<MenuItem key="4-1">sub menu 1</MenuItem>
|
|
34
|
+
<MenuItem key="4-2">sub menu 2</MenuItem>
|
|
35
|
+
</Menu>
|
|
36
|
+
</MenuItem>
|
|
31
37
|
</Menu>
|
|
32
38
|
<br /><br />
|
|
33
39
|
<Switch
|
|
@@ -3,6 +3,7 @@ import BasicDemo from '~/components/menu/demos/basic';
|
|
|
3
3
|
import CollapseDemo from '~/components/menu/demos/collapse';
|
|
4
4
|
import AccordionDemo from '~/components/menu/demos/accordion';
|
|
5
5
|
import CollapseArrowDemo from '~/components/menu/demos/showCollapseArrow';
|
|
6
|
+
import HorizontalDemo from '~/components/menu/demos/horizontal';
|
|
6
7
|
import {mount, unmount, dispatchEvent, getElement, wait} from '../../test/utils';
|
|
7
8
|
import {Menu, MenuItem} from './';
|
|
8
9
|
|
|
@@ -190,4 +191,22 @@ describe('Menu', () => {
|
|
|
190
191
|
expect(element.outerHTML).to.matchSnapshot();
|
|
191
192
|
expect(getElement('.k-menu-arrow-box')).to.be.undefined;
|
|
192
193
|
});
|
|
194
|
+
|
|
195
|
+
it('detecting pop-up position during rapid mouse hover over menus', async () => {
|
|
196
|
+
const [instance, element] = mount(HorizontalDemo);
|
|
197
|
+
|
|
198
|
+
const [, , menu3, menu4] = element.querySelectorAll<HTMLElement>('.k-menu-item-title');
|
|
199
|
+
dispatchEvent(menu3, 'mouseenter');
|
|
200
|
+
await wait(500);
|
|
201
|
+
const dropdownmenu1 = getElement('.k-dropdown-menu')!;
|
|
202
|
+
const top1 = dropdownmenu1.getBoundingClientRect().top;
|
|
203
|
+
|
|
204
|
+
dispatchEvent(menu3, 'mouseleave');
|
|
205
|
+
dispatchEvent(menu4, 'mouseenter');
|
|
206
|
+
await wait(1000);
|
|
207
|
+
const dropdownmenu2 = getElement('.k-dropdown-menu')!;
|
|
208
|
+
const top2 = dropdownmenu2.getBoundingClientRect().top;
|
|
209
|
+
|
|
210
|
+
expect(top1).to.eql(top2);
|
|
211
|
+
});
|
|
193
212
|
});
|
|
@@ -18,7 +18,7 @@ const defaults = {
|
|
|
18
18
|
item: {
|
|
19
19
|
height: '40px',
|
|
20
20
|
padding: '0 12px',
|
|
21
|
-
bodyPadding: '
|
|
21
|
+
bodyPadding: '4px',
|
|
22
22
|
color: '#aeaeb9',
|
|
23
23
|
hoverColor: '#fff',
|
|
24
24
|
disabledColor: '#53535a',
|
|
@@ -292,6 +292,7 @@ export const makeMenuStyles = cache(function makeMenuStyles(k: string) {
|
|
|
292
292
|
&.${k}-dropdown-menu {
|
|
293
293
|
width: fit-content;
|
|
294
294
|
min-width: ${menu.dropdown.minWidth};
|
|
295
|
+
position: absolute;
|
|
295
296
|
.${k}-menu-item-arrow {
|
|
296
297
|
transform: rotate(-90deg)
|
|
297
298
|
}
|
|
@@ -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;
|
|
@@ -67,15 +68,15 @@ export function useMouseEvents(
|
|
|
67
68
|
itemHeight = getItemHeight();
|
|
68
69
|
|
|
69
70
|
const threshold = itemHeight * 0.6;
|
|
70
|
-
|
|
71
|
+
wheelDeltaY += e.deltaY;
|
|
71
72
|
|
|
72
|
-
if (Math.abs(
|
|
73
|
-
if (
|
|
73
|
+
if (Math.abs(wheelDeltaY) >= threshold) {
|
|
74
|
+
if (wheelDeltaY > 0) {
|
|
74
75
|
setByRelativeIndex(1, null, true);
|
|
75
76
|
} else {
|
|
76
77
|
setByRelativeIndex(-1, null, true);
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
+
wheelDeltaY = 0;
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -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() {
|