@king-design/intact 2.1.0 → 2.1.2

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.
Files changed (134) hide show
  1. package/components/dropdown/dropdown.ts +35 -70
  2. package/components/dropdown/index.spec.ts +53 -4
  3. package/components/dropdown/item.ts +15 -5
  4. package/components/dropdown/menu.ts +3 -3
  5. package/components/dropdown/usePosition.ts +3 -0
  6. package/components/form/index.spec.ts +22 -1
  7. package/components/menu/demos/collapse.md +1 -1
  8. package/components/menu/index.spec.ts +9 -1
  9. package/components/menu/item.ts +7 -0
  10. package/components/pagination/index.spec.ts +23 -0
  11. package/components/pagination/index.ts +3 -1
  12. package/components/tooltip/content.ts +15 -1
  13. package/components/tooltip/content.vdt +6 -1
  14. package/components/tooltip/index.spec.ts +87 -1
  15. package/components/tooltip/styles.ts +1 -1
  16. package/components/tooltip/tooltip.ts +11 -0
  17. package/components/virtual.ts +98 -0
  18. package/es/components/dropdown/dropdown.d.ts +6 -5
  19. package/es/components/dropdown/dropdown.js +42 -69
  20. package/es/components/dropdown/index.spec.js +96 -17
  21. package/es/components/dropdown/item.d.ts +1 -1
  22. package/es/components/dropdown/item.js +16 -4
  23. package/es/components/dropdown/usePosition.js +4 -2
  24. package/es/components/form/index.spec.js +49 -2
  25. package/es/components/menu/index.spec.js +26 -15
  26. package/es/components/menu/item.d.ts +2 -0
  27. package/es/components/menu/item.js +5 -0
  28. package/es/components/pagination/index.js +4 -1
  29. package/es/components/pagination/index.spec.js +49 -0
  30. package/es/components/tooltip/content.d.ts +1 -0
  31. package/es/components/tooltip/content.js +18 -1
  32. package/es/components/tooltip/content.vdt.js +3 -1
  33. package/es/components/tooltip/index.spec.js +165 -0
  34. package/es/components/tooltip/styles.d.ts +22 -0
  35. package/es/components/tooltip/styles.js +1 -1
  36. package/es/components/tooltip/tooltip.d.ts +1 -0
  37. package/es/components/tooltip/tooltip.js +16 -1
  38. package/es/components/virtual.d.ts +8 -0
  39. package/es/components/virtual.js +126 -0
  40. package/es/index.d.ts +2 -2
  41. package/es/index.js +2 -2
  42. package/es/site/data/components/copy/demos/basic/index.d.ts +5 -0
  43. package/es/site/data/components/copy/demos/basic/index.js +17 -0
  44. package/es/site/data/components/copy/demos/basic/react.d.ts +4 -0
  45. package/es/site/data/components/copy/demos/basic/react.js +23 -0
  46. package/es/site/data/components/copy/demos/children/index.d.ts +6 -0
  47. package/es/site/data/components/copy/demos/children/index.js +18 -0
  48. package/es/site/data/components/copy/demos/children/react.d.ts +5 -0
  49. package/es/site/data/components/copy/demos/children/react.js +44 -0
  50. package/es/site/data/components/copy/index.d.ts +57 -0
  51. package/es/site/data/components/copy/index.js +42 -0
  52. package/es/site/data/components/dialog/demos/basic/react.js +1 -4
  53. package/es/site/data/components/icon/demos/disabled/index.d.ts +6 -0
  54. package/es/site/data/components/icon/demos/disabled/index.js +18 -0
  55. package/es/site/data/components/icon/demos/disabled/react.d.ts +5 -0
  56. package/es/site/data/components/icon/demos/disabled/react.js +33 -0
  57. package/es/site/data/components/input/demos/flat/index.d.ts +5 -0
  58. package/es/site/data/components/input/demos/flat/index.js +17 -0
  59. package/es/site/data/components/input/demos/flat/react.d.ts +4 -0
  60. package/es/site/data/components/input/demos/flat/react.js +29 -0
  61. package/es/site/data/components/input/demos/showCount/index.d.ts +5 -0
  62. package/es/site/data/components/input/demos/showCount/index.js +17 -0
  63. package/es/site/data/components/input/demos/showCount/react.d.ts +4 -0
  64. package/es/site/data/components/input/demos/showCount/react.js +33 -0
  65. package/es/site/data/components/menu/demos/collapse/index.js +1 -1
  66. package/es/site/data/components/menu/demos/collapse/react.js +1 -1
  67. package/es/site/data/components/pagination/demos/flat/index.d.ts +6 -0
  68. package/es/site/data/components/pagination/demos/flat/index.js +18 -0
  69. package/es/site/data/components/pagination/demos/flat/react.d.ts +5 -0
  70. package/es/site/data/components/pagination/demos/flat/react.js +41 -0
  71. package/es/site/data/components/popover/demos/basic/index.d.ts +7 -0
  72. package/es/site/data/components/popover/demos/basic/index.js +28 -0
  73. package/es/site/data/components/popover/demos/basic/react.d.ts +8 -0
  74. package/es/site/data/components/popover/demos/basic/react.js +59 -0
  75. package/es/site/data/components/popover/demos/button/index.d.ts +8 -0
  76. package/es/site/data/components/popover/demos/button/index.js +42 -0
  77. package/es/site/data/components/popover/demos/button/react.d.ts +8 -0
  78. package/es/site/data/components/popover/demos/button/react.js +73 -0
  79. package/es/site/data/components/popover/demos/content/index.d.ts +7 -0
  80. package/es/site/data/components/popover/demos/content/index.js +28 -0
  81. package/es/site/data/components/popover/demos/content/react.d.ts +6 -0
  82. package/es/site/data/components/popover/demos/content/react.js +43 -0
  83. package/es/site/data/components/popover/demos/text/index.d.ts +7 -0
  84. package/es/site/data/components/popover/demos/text/index.js +28 -0
  85. package/es/site/data/components/popover/demos/text/react.d.ts +6 -0
  86. package/es/site/data/components/popover/demos/text/react.js +36 -0
  87. package/es/site/data/components/popover/demos/type/index.d.ts +11 -0
  88. package/es/site/data/components/popover/demos/type/index.js +34 -0
  89. package/es/site/data/components/popover/demos/type/react.d.ts +11 -0
  90. package/es/site/data/components/popover/demos/type/react.js +58 -0
  91. package/es/site/data/components/popover/index.d.ts +57 -0
  92. package/es/site/data/components/popover/index.js +42 -0
  93. package/es/site/data/components/progress/demos/circleSize/index.d.ts +14 -0
  94. package/es/site/data/components/progress/demos/circleSize/index.js +43 -0
  95. package/es/site/data/components/progress/demos/circleSize/react.d.ts +14 -0
  96. package/es/site/data/components/progress/demos/circleSize/react.js +98 -0
  97. package/es/site/data/components/select/demos/draggable/index.d.ts +10 -0
  98. package/es/site/data/components/select/demos/draggable/index.js +24 -0
  99. package/es/site/data/components/select/demos/draggable/react.d.ts +10 -0
  100. package/es/site/data/components/select/demos/draggable/react.js +85 -0
  101. package/es/site/data/components/select/demos/flat/index.d.ts +5 -0
  102. package/es/site/data/components/select/demos/flat/index.js +17 -0
  103. package/es/site/data/components/select/demos/flat/react.d.ts +4 -0
  104. package/es/site/data/components/select/demos/flat/react.js +73 -0
  105. package/es/site/data/components/select/demos/inline/index.d.ts +5 -0
  106. package/es/site/data/components/select/demos/inline/index.js +17 -0
  107. package/es/site/data/components/select/demos/inline/react.d.ts +4 -0
  108. package/es/site/data/components/select/demos/inline/react.js +27 -0
  109. package/es/site/data/components/select/demos/nowrap/index.d.ts +5 -0
  110. package/es/site/data/components/select/demos/nowrap/index.js +17 -0
  111. package/es/site/data/components/select/demos/nowrap/react.d.ts +4 -0
  112. package/es/site/data/components/select/demos/nowrap/react.js +41 -0
  113. package/es/site/data/components/steps/demos/vertical/index.d.ts +14 -0
  114. package/es/site/data/components/steps/demos/vertical/index.js +40 -0
  115. package/es/site/data/components/steps/demos/vertical/react.d.ts +14 -0
  116. package/es/site/data/components/steps/demos/vertical/react.js +124 -0
  117. package/es/site/data/components/switch/demos/disabled/index.d.ts +6 -0
  118. package/es/site/data/components/switch/demos/disabled/index.js +18 -0
  119. package/es/site/data/components/switch/demos/disabled/react.d.ts +5 -0
  120. package/es/site/data/components/switch/demos/disabled/react.js +27 -0
  121. package/es/site/data/components/tabs/demos/scroll/index.d.ts +18 -0
  122. package/es/site/data/components/tabs/demos/scroll/index.js +87 -0
  123. package/es/site/data/components/tabs/demos/scroll/react.d.ts +18 -0
  124. package/es/site/data/components/tabs/demos/scroll/react.js +166 -0
  125. package/es/site/data/components/tag/demos/draggable/index.d.ts +11 -0
  126. package/es/site/data/components/tag/demos/draggable/index.js +24 -0
  127. package/es/site/data/components/tag/demos/draggable/react.d.ts +11 -0
  128. package/es/site/data/components/tag/demos/draggable/react.js +62 -0
  129. package/es/site/data/components/tag/demos/tags/index.d.ts +12 -0
  130. package/es/site/data/components/tag/demos/tags/index.js +39 -0
  131. package/es/site/data/components/tag/demos/tags/react.d.ts +12 -0
  132. package/es/site/data/components/tag/demos/tags/react.js +83 -0
  133. package/index.ts +2 -2
  134. package/package.json +4 -3
@@ -11,7 +11,7 @@ import {
11
11
  createVNode,
12
12
  nextTick,
13
13
  } from 'intact';
14
- import {bind, isTextChildren} from '../utils';
14
+ 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';
@@ -21,6 +21,7 @@ import {Portal, PortalProps} from '../portal';
21
21
  import {useShowHideEvents} from '../../hooks/useShowHideEvents';
22
22
  import {usePosition, FeedbackCallback} from './usePosition';
23
23
  import type {Events} from '../types';
24
+ import { Virtual } from '../virtual';
24
25
 
25
26
  export type Position = Options
26
27
  export type PositionShorthand = 'left' | 'bottom' | 'right' | 'top'
@@ -35,6 +36,7 @@ export interface DropdownProps {
35
36
  disabled?: boolean
36
37
  value?: boolean
37
38
  position?: Position | 'left' | 'bottom' | 'right' | 'top'
39
+ collison?: Position['collision']
38
40
  of?: 'self' | 'parent' | Event
39
41
  container?: PortalProps['container']
40
42
  }
@@ -45,6 +47,8 @@ export interface DropdownEvents {
45
47
  hide: []
46
48
  mouseenter: [MouseEvent]
47
49
  mouseleave: [MouseEvent]
50
+ click: [MouseEvent]
51
+ contextmenu: [MouseEvent]
48
52
  positioned: [Feedback]
49
53
  }
50
54
 
@@ -58,11 +62,13 @@ const typeDefs: Required<TypeDefs<DropdownProps>> = {
58
62
  // Event is undefined in NodeJs
59
63
  of: ['self', 'parent', typeof Event === 'undefined' ? undefined : Event],
60
64
  container: [String, Function],
65
+ collison: ['none', 'fit', 'flip', 'flipfit', Array],
61
66
  };
62
67
 
63
68
  const defaults = (): Partial<DropdownProps> => ({
64
69
  trigger: 'hover',
65
70
  of: 'self',
71
+ value: false,
66
72
  });
67
73
 
68
74
  const events: Events<DropdownEvents> = {
@@ -71,6 +77,8 @@ const events: Events<DropdownEvents> = {
71
77
  hide: true,
72
78
  mouseenter: true,
73
79
  mouseleave: true,
80
+ click: true,
81
+ contextmenu: true,
74
82
  positioned: true,
75
83
  };
76
84
 
@@ -104,28 +112,18 @@ export class Dropdown<
104
112
  }
105
113
 
106
114
  const [trigger, menu] = children as DropdownChildren;
107
- const triggerType = this.get('trigger');
108
- const props = this.initEventCallbacks(triggerType);
109
-
110
- const clonedTrigger = isTextChildren(trigger) ?
111
- createVNode('span', null, trigger) :
112
- directClone(trigger);
113
- const triggerProps = this.triggerProps = this.normalizeTriggerProps(trigger.props || EMPTY_OBJ);
114
- // add a className for opening status
115
- let className = trigger.className || triggerProps.className;
115
+ const props = this.initEventCallbacks();
116
+ let {className, value, container} = this.get();
116
117
  className = cx({
117
- [className]: className,
118
- 'k-dropdown-open': this.get('value'),
118
+ 'k-dropdown-open': value,
119
+ [className!]: !!className,
119
120
  });
120
-
121
- clonedTrigger.props = {...triggerProps, ...props, className};
122
- clonedTrigger.className = className;
123
-
121
+
124
122
  this.menuVNode = menu;
125
123
 
126
124
  return [
127
- clonedTrigger,
128
- h(Portal, {children: menu, container: this.get('container')})
125
+ h(Virtual, {...props, ...getRestProps(this), className}, trigger),
126
+ h(Portal, {children: menu, container})
129
127
  ];
130
128
  };
131
129
 
@@ -135,8 +133,7 @@ export class Dropdown<
135
133
  public showedDropdown: Dropdown | null = null;
136
134
  public positionHook = usePosition();
137
135
 
138
- private timer: number | undefined = undefined;
139
- private triggerProps: any = null;
136
+ protected timer: number | undefined = undefined;
140
137
 
141
138
  init() {
142
139
  provide(DROPDOWN, this);
@@ -167,6 +164,12 @@ export class Dropdown<
167
164
  clearTimeout(this.timer);
168
165
  this.set('value', true);
169
166
 
167
+ // should show parent dropdown
168
+ const parentDropdown = this.dropdown;
169
+ if (parentDropdown) {
170
+ parentDropdown.show();
171
+ }
172
+
170
173
  if (shouldFocus) {
171
174
  nextTick(() => {
172
175
  this.focusFirst();
@@ -178,9 +181,15 @@ export class Dropdown<
178
181
  if (this.get('disabled')) return;
179
182
  if (!this.get('value')) return;
180
183
 
184
+ const showedDropdown = this.showedDropdown;
185
+ if (showedDropdown) {
186
+ showedDropdown.hide(immediately);
187
+ }
188
+
181
189
  if (immediately) {
182
190
  this.set('value', false);
183
191
  } else {
192
+ clearTimeout(this.timer);
184
193
  this.timer = window.setTimeout(() => {
185
194
  this.set('value', false);
186
195
  }, 200);
@@ -198,29 +207,27 @@ export class Dropdown<
198
207
 
199
208
  @bind
200
209
  private onEnter(e: MouseEvent) {
201
- this.callOriginalCallback(e.type === 'click' ? 'ev-click' : 'ev-mouseenter', e);
202
-
203
210
  this.show();
211
+ this.trigger(e.type as 'mouseenter', e);
204
212
  }
205
213
 
206
214
  @bind
207
215
  private onContextMenu(e: MouseEvent) {
208
- this.callOriginalCallback('ev-contextmenu', e);
209
-
210
216
  e.preventDefault();
211
217
  this.set('of', e);
212
218
  this.show();
219
+ this.trigger('contextmenu', e);
213
220
  }
214
221
 
215
222
  @bind
216
223
  private onLeave(e: MouseEvent) {
217
- this.callOriginalCallback('ev-mouseleave', e);
218
-
219
224
  this.hide();
225
+ this.trigger(e.type as 'mouseleave', e);
220
226
  }
221
227
 
222
- private initEventCallbacks(trigger: DropdownProps['trigger']) {
223
- const props: Record<string, Function> = {};
228
+ private initEventCallbacks() {
229
+ const trigger = this.get('trigger');
230
+ const props: Record<string, Function | string> = {};
224
231
 
225
232
  switch (trigger) {
226
233
  case 'focus':
@@ -241,48 +248,6 @@ export class Dropdown<
241
248
 
242
249
  return props;
243
250
  }
244
-
245
- private callOriginalCallback(name: string, e: MouseEvent) {
246
- const callback = this.triggerProps[name];
247
- const callbackOnDropdown = this.get<Function>(name);
248
- if (isFunction(callback)) callback(e);
249
- if (isFunction(callbackOnDropdown)) callbackOnDropdown(e);
250
- }
251
-
252
- private normalizeTriggerProps(props: any) {
253
- // if use kpc in react or vue, normalize props by Wrapper.props.vnode;
254
- const vnode = props.vnode;
255
- if (!vnode) return props;
256
-
257
- // maybe we render the intact component in react slot property, in this case
258
- // the $isReact is false. so use the vnode $$typeof field as gauge
259
- if (vnode.$$typeof || (this as any).$isVueNext) {
260
- const _props = vnode.props;
261
- if (!_props) return props;
262
-
263
- return {
264
- vnode,
265
- 'ev-click': _props.onClick,
266
- 'ev-mouseenter': _props.onMouseEnter,
267
- 'ev-mouseleave': _props.onMouseLeave,
268
- 'ev-contextmenu': _props.onContextMenu,
269
- className: _props.className || _props.class /* vue-next */,
270
- };
271
- } else if ((this as any).$isVue) {
272
- const data = vnode.data;
273
- const on = data && data.on || EMPTY_OBJ;
274
- const ret: Record<string, any> = {vnode};
275
- ['click', 'mouseenter', 'mouseleave', 'contextmenu'].forEach(event => {
276
- const method = on[event];
277
- if (method) {
278
- ret[`ev-${event}`] = method;
279
- }
280
- });
281
- return ret;
282
- }
283
-
284
- return props;
285
- }
286
251
  }
287
252
 
288
253
  function useDocumentClickForDropdown(dropdown: Dropdown) {
@@ -4,6 +4,7 @@ import {Dropdown, DropdownMenu, DropdownItem} from '../dropdown';
4
4
  import BasicDemo from '~/components/dropdown/demos/basic';
5
5
  import NestedDemo from '~/components/dropdown/demos/nested';
6
6
  import ContextMenuDemo from '~/components/dropdown/demos/contextmenu';
7
+ import TooltipDemo from '~/components/dropdown/demos/tooltip';
7
8
 
8
9
  describe('Dropdown', () => {
9
10
  afterEach((done) => {
@@ -72,7 +73,8 @@ describe('Dropdown', () => {
72
73
  expect(dropdown.parentNode).to.exist;
73
74
  });
74
75
 
75
- it('nested dropdown', async () => {
76
+ it('nested dropdown', async function() {
77
+ this.timeout(0);
76
78
  const [instance, element] = mount(NestedDemo);
77
79
 
78
80
  (element.firstElementChild as HTMLElement).click();
@@ -89,6 +91,20 @@ describe('Dropdown', () => {
89
91
  await wait(500);
90
92
  const hoverSubDropdown = getElement('.k-dropdown-menu')!;
91
93
  expect(hoverSubDropdown.innerHTML).to.matchSnapshot();
94
+
95
+ const [hoverItem1] = hoverSubDropdown.querySelectorAll<HTMLElement>('.k-dropdown-item');
96
+ dispatchEvent(hoverItem, 'mouseleave');
97
+ dispatchEvent(hoverItem1, 'mouseenter');
98
+ await wait(500);
99
+ const hoverSubDropdown1 = getElement('.k-dropdown-menu')!;
100
+ expect(hoverSubDropdown1.textContent).to.eql('item 1item 2');
101
+
102
+ const [hoverItem2] = hoverSubDropdown1.querySelectorAll<HTMLElement>('.k-dropdown-item');
103
+ dispatchEvent(hoverItem1, 'mouseleave');
104
+ dispatchEvent(hoverItem2, 'mouseenter');
105
+ await wait(1000);
106
+ const hoverSubDropdown2 = getElement('.k-dropdown-menu')!;
107
+ expect(hoverSubDropdown2 === hoverSubDropdown1).to.be.true;
92
108
  });
93
109
 
94
110
  it('hide on click document', async () => {
@@ -281,13 +297,13 @@ describe('Dropdown', () => {
281
297
  expect(parent.scrollTop).to.eql(item.offsetHeight * 2 - 40);
282
298
  });
283
299
 
284
- it('trigger: focus', async() => {
300
+ it('focus trigger type', async () => {
285
301
  class Demo extends Component {
286
302
  static template = `
287
303
  const {Dropdown, DropdownMenu, DropdownItem} = this;
288
304
  <div>
289
305
  <Dropdown trigger="focus">
290
- <input ref="trigger" />
306
+ <input ref="trigger" ev-focusin={this.onFocus} />
291
307
  <DropdownMenu>
292
308
  <DropdownItem>test1</DropdownItem>
293
309
  <DropdownItem>test2</DropdownItem>
@@ -298,12 +314,14 @@ describe('Dropdown', () => {
298
314
  private Dropdown = Dropdown;
299
315
  private DropdownItem = DropdownItem;
300
316
  private DropdownMenu = DropdownMenu;
317
+ public onFocus = sinon.spy((e: MouseEvent) => console.log(e));
301
318
  }
302
319
  const [instance] = mount(Demo);
303
320
 
304
321
  dispatchEvent(instance.refs.trigger, 'focusin');
305
322
  await wait(500);
306
323
  expect(getElement('.k-dropdown-menu')).to.be.exist;
324
+ expect(instance.onFocus.callCount).to.eql(1);
307
325
 
308
326
  // clicking anywhere should not hide menu
309
327
  dispatchEvent(document, 'click');
@@ -314,4 +332,35 @@ describe('Dropdown', () => {
314
332
  await wait(700);
315
333
  expect(getElement('.k-dropdown-menu')).to.not.be.exist;
316
334
  });
317
- });
335
+
336
+ it('wrap by tooltip', async () => {
337
+ const [instance, element] = mount(TooltipDemo);
338
+
339
+ dispatchEvent(element.firstChild as HTMLElement, 'mouseenter');
340
+ await wait();
341
+ const dropdown = getElement('.k-dropdown-menu')!;
342
+ const [item1, item2, item3, item4] = dropdown.querySelectorAll('.k-dropdown-item');
343
+
344
+ dispatchEvent(item1, 'mouseenter');
345
+ await wait();
346
+ expect(getElement('.k-tooltip-content')!.textContent).to.eql('item 1')
347
+
348
+ dispatchEvent(item1, 'mouseleave');
349
+ dispatchEvent(item3, 'mouseenter');
350
+ await wait();
351
+ expect(getElement('.k-tooltip-content')!.textContent).to.eql('disabled')
352
+
353
+ dispatchEvent(item3, 'mouseleave');
354
+ dispatchEvent(item4, 'mouseenter');
355
+ await wait();
356
+ expect(getElement('.k-tooltip-content')!.textContent).to.eql('This is a nested Dropdown.');
357
+
358
+ dispatchEvent(item4, 'click');
359
+ await wait();
360
+ expect(getElement('.k-dropdown-menu')!.textContent).to.eql('item 1item 2');
361
+
362
+ dispatchEvent(item4, 'mouseleave');
363
+ await wait(800);
364
+ expect(getElement('.k-dropdown-menu')).to.not.be.exist;
365
+ });
366
+ });
@@ -5,6 +5,7 @@ import {useItemKeyboard, MenuKeyboardMethods} from './useKeyboard';
5
5
  import {Dropdown, DROPDOWN} from './dropdown';
6
6
  import {DropdownMenu, DROPDOWN_MENU} from './menu';
7
7
  import {IgnoreClickEvent} from '../../hooks/useDocumentClick';
8
+ import { Dropdown as ExportDropdown, DropdownMenu as ExportDropdownMenu } from '.';
8
9
 
9
10
  export interface DropdownItemProps {
10
11
  disabled?: boolean
@@ -64,10 +65,19 @@ export class DropdownItem extends Component<DropdownItemProps, DropdownItemEvent
64
65
  }
65
66
 
66
67
  hasSubMenu() {
67
- // TODO: wrapped by Tooltip
68
- const parent = this.$senior;
69
- if (parent instanceof Dropdown) {
70
- return parent
68
+ // wrapped by Dropdown rather than DropdownMenu
69
+ let parent = this.$senior;
70
+ while (parent) {
71
+ // Tooltip extends Dropdown, it's also a instance of Dropdown
72
+ // so use constructor to detect
73
+ // if (parent instanceof DropdownMenu) {
74
+ if (parent.constructor === ExportDropdownMenu) {
75
+ return;
76
+ }
77
+ if (parent.constructor === ExportDropdown) {
78
+ return parent;
79
+ }
80
+ parent = parent.$senior;
71
81
  }
72
82
  }
73
83
 
@@ -105,4 +115,4 @@ function useKeyboardForDropdownItem(instance: DropdownItem) {
105
115
  instance.select();
106
116
  },
107
117
  });
108
- }
118
+ }
@@ -35,8 +35,8 @@ export class DropdownMenu<
35
35
  @bind
36
36
  protected onMouseEnter(e: MouseEvent) {
37
37
  const dropdown = this.dropdown!;
38
- dropdown!.show();
39
- dropdown!.trigger('mouseenter', e);
38
+ dropdown.show();
39
+ dropdown.trigger('mouseenter', e);
40
40
  }
41
41
 
42
42
  @bind
@@ -78,4 +78,4 @@ function useKeyboardForDropdownMenu(dropdown: Dropdown) {
78
78
  });
79
79
 
80
80
  return {lock};
81
- }
81
+ }
@@ -21,6 +21,8 @@ export function usePosition() {
21
21
  // return if object is the same
22
22
  if (
23
23
  isObject(newValue) && isObject(oldValue) &&
24
+ // is not event object
25
+ !(newValue instanceof Event) &&
24
26
  JSON.stringify(newValue) === JSON.stringify(oldValue)
25
27
  ) {
26
28
  return;
@@ -56,6 +58,7 @@ export function usePosition() {
56
58
  position(findDomFromVNode(instance.menuVNode!, true) as HTMLElement, {
57
59
  my: 'left top+8',
58
60
  at: 'left bottom',
61
+ collision: instance.get('collison'),
59
62
  ...pos,
60
63
  of: ofElement,
61
64
  using: _feedback => {
@@ -6,6 +6,7 @@ import {mount, unmount, dispatchEvent, wait} from '../../test/utils';
6
6
  import {Component, findDomFromVNode} from 'intact';
7
7
  import {Form, FormItem} from './';
8
8
  import {Input} from '../input';
9
+ import { Select } from '../select';
9
10
 
10
11
  RemoteDemo.prototype.validateUserName = function(value) {
11
12
  // mock api
@@ -21,7 +22,7 @@ RemoteDemo.prototype.validateUserName = function(value) {
21
22
  };
22
23
 
23
24
  describe('Form', () => {
24
- // afterEach(() => unmount());
25
+ afterEach(() => unmount());
25
26
 
26
27
  it('validate', async () => {
27
28
  const [instance, element] = mount(BasicDemo, null, basicDemoData);
@@ -440,4 +441,24 @@ describe('Form', () => {
440
441
  await wait();
441
442
  expect(classList.contains('k-ellipsis')).to.be.true;
442
443
  });
444
+
445
+ it('should not validate when select is disabled on init', async () => {
446
+ class Demo extends Component {
447
+ static template = `
448
+ const {Form, FormItem, Select} = this;
449
+ <Form ref="form">
450
+ <FormItem rules={{required: true}}>
451
+ <Select disabled />
452
+ </FormItem>
453
+ </Form>
454
+ `;
455
+ Form = Form;
456
+ FormItem = FormItem;
457
+ Select = Select;
458
+ }
459
+ const [instance, element] = mount(Demo);
460
+
461
+ await wait(500);
462
+ expect(element.querySelector('.k-form-error')).to.be.null;
463
+ });
443
464
  });
@@ -64,7 +64,7 @@ export default class extends Component<Props> {
64
64
  return {
65
65
  expandedKeys: ['3'],
66
66
  selectedKey: '3-2',
67
- collapse: false,
67
+ collapse: true,
68
68
  theme: 'dark'
69
69
  } as MenuProps;
70
70
  }
@@ -1,4 +1,5 @@
1
1
  import {Component} from 'intact';
2
+ import BasicDemo from '~/components/menu/demos/basic';
2
3
  import CollapseDemo from '~/components/menu/demos/collapse';
3
4
  import AccordionDemo from '~/components/menu/demos/accordion';
4
5
  import {mount, unmount, dispatchEvent, getElement, wait} from '../../test/utils';
@@ -8,13 +9,17 @@ describe('Menu', () => {
8
9
  afterEach(() => unmount());
9
10
 
10
11
  it('expand and shrink sub menu', async () => {
11
- const [instance, element] = mount(CollapseDemo);
12
+ const [instance, element] = mount(BasicDemo);
13
+
14
+ await wait();
12
15
 
16
+ // shrink
13
17
  const title = element.querySelector('.k-expanded .k-menu-title') as HTMLElement;
14
18
  title.click();
15
19
  await wait(500);
16
20
  expect(element.outerHTML).to.matchSnapshot();
17
21
  expect(instance.get('expandedKeys')).to.eql([]);
22
+
18
23
  title.click();
19
24
  await wait(500);
20
25
  expect(element.outerHTML).to.matchSnapshot();
@@ -24,6 +29,9 @@ describe('Menu', () => {
24
29
  it('select', async () => {
25
30
  const [instance, element] = mount(CollapseDemo);
26
31
 
32
+ instance.set('collapse', false);
33
+ await wait();
34
+
27
35
  expect(element.innerHTML).to.matchSnapshot();
28
36
 
29
37
  const [title, disabledTitle] = element.querySelectorAll<HTMLElement>('.k-menu-title');
@@ -9,6 +9,7 @@ import {useDropdown} from './useDropdown';
9
9
  import {useRouter, navigate} from '../../hooks/useRouter';
10
10
  import {useRecordItem} from '../../hooks/useRecordComponent';
11
11
  import {MENU_RECORD_KEY, useHighlightItem} from './useHighlight';
12
+ import {Events} from '../types';
12
13
 
13
14
  export interface MenuItemProps {
14
15
  key: Key
@@ -32,11 +33,17 @@ const typeDefs: Required<TypeDefs<MenuItemProps>> = {
32
33
  disabled: Boolean,
33
34
  };
34
35
 
36
+ const events: Events<MenuItemEvents> = {
37
+ click: true,
38
+ select: true,
39
+ };
40
+
35
41
  export const MENU_ITEM = 'MenuItem';
36
42
 
37
43
  export class MenuItem extends Component<MenuItemProps, MenuItemEvents> {
38
44
  static template = template;
39
45
  static typeDefs = typeDefs;
46
+ static events = events;
40
47
 
41
48
  public rootMenu = inject<Menu>(ROOT_MENU)!;
42
49
  public parentMenu = inject<Menu>(MENU)!;
@@ -3,6 +3,8 @@ import GotoDemo from '~/components/pagination/demos/goto';
3
3
  import CurrentDemo from '~/components/pagination/demos/current';
4
4
  import DisableDemo from '~/components/pagination/demos/disable';
5
5
  import {mount, unmount, dispatchEvent, wait} from '../../test/utils';
6
+ import { Component } from 'intact';
7
+ import { Pagination } from '.';
6
8
 
7
9
  describe('Pagination', () => {
8
10
  // afterEach(() => unmount());
@@ -89,4 +91,25 @@ describe('Pagination', () => {
89
91
  expect(input.value).to.eql('10');
90
92
  expect(instance.get('value2')).to.eql(10);
91
93
  });
94
+
95
+ it('should not set value to 0 when total is 0 on intialization', async () => {
96
+ class Demo extends Component {
97
+ static template = `
98
+ const { Pagination } = this;
99
+ <Pagination total={0} v-model="page" />
100
+ `;
101
+
102
+ static defaults() {
103
+ return {
104
+ page: 1,
105
+ }
106
+ }
107
+
108
+ private Pagination = Pagination;
109
+ }
110
+
111
+ const [instance] = mount(Demo);
112
+ // await wait();
113
+ expect(instance.get('page')).to.eql(1);
114
+ });
92
115
  });
@@ -100,7 +100,9 @@ export class Pagination extends Component<PaginationProps, PaginationEvents> {
100
100
 
101
101
  if (page > totalPages) {
102
102
  page = totalPages;
103
- } else if (page < 1) {
103
+ }
104
+ // perhaps totalPages is 0
105
+ if (page < 1) {
104
106
  page = 1;
105
107
  }
106
108
 
@@ -9,6 +9,7 @@ import template from './content.vdt';
9
9
  import {bind} from '../utils';
10
10
  import {Tooltip} from './tooltip';
11
11
  import {useArrow} from './useArrow';
12
+ import { tooltip as tooltipTheme } from './styles';
12
13
 
13
14
  export interface TooltipContentProps extends DropdownMenuProps { }
14
15
  export interface TooltipContentEvents extends DropdownMenuEvents { }
@@ -35,10 +36,23 @@ export class TooltipContent extends DropdownMenu<
35
36
  }
36
37
 
37
38
  @bind
38
- private onEnter() {
39
+ private onEnter(elem: HTMLElement) {
40
+ // fix the width, https://github.com/ksc-fe/kpc/issues/873
41
+ const maxWidth = parseInt(tooltipTheme.maxWidth);
42
+ const width = elem.offsetWidth;
43
+ if (width === maxWidth) {
44
+ elem.style.width = `${width}px`;
45
+ }
39
46
  this.dropdown!.position();
40
47
  }
41
48
 
49
+ @bind
50
+ private onAfterLeave(elem: HTMLElement) {
51
+ // remove the position after leave, https://github.com/ksc-fe/kpc/issues/873
52
+ const style = elem.style;
53
+ style.left = style.top = style.width = '';
54
+ }
55
+
42
56
  @bind
43
57
  protected onMouseEnter(e: MouseEvent) {
44
58
  const dropdown = this.dropdown as Tooltip;
@@ -22,7 +22,12 @@ const classNameObj = {
22
22
 
23
23
  <t:super
24
24
  value={!!value && !this.isEmptyChildren}
25
- transition={{name: 'k-fade', onEnter: this.onEnter}}
25
+ transition={{
26
+ name: 'k-fade',
27
+ onEnter: this.onEnter,
28
+ onAfterLeave: this.onAfterLeave,
29
+ onLeaveCancelled: this.onAfterLeave,
30
+ }}
26
31
  class={classNameObj}
27
32
  >
28
33
  <b:children>