@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
@@ -6,8 +6,10 @@ import ContentDemo from '~/components/tooltip/demos/content';
6
6
  import ConfirmDemo from '~/components/tooltip/demos/confirm';
7
7
  import AlwaysDemo from '~/components/tooltip/demos/always';
8
8
  import {Tooltip} from './';
9
- import {Radio} from '../radio';
9
+ import {Dialog} from '../dialog';
10
10
  import {mount, unmount, dispatchEvent, getElement, wait} from '../../test/utils';
11
+ import { tooltip as tooltipTheme } from './styles';
12
+ import { Select, Option } from '../select';
11
13
 
12
14
  describe('Tooltip', () => {
13
15
  afterEach((done) => {
@@ -352,4 +354,88 @@ describe('Tooltip', () => {
352
354
  console.log(JSON.stringify(content.getBoundingClientRect()));
353
355
  expect(content.getBoundingClientRect().top < 0).to.be.true;
354
356
  });
357
+
358
+ it('should add className', async () => {
359
+ class Demo extends Component {
360
+ static template = `
361
+ const Tooltip = this.Tooltip;
362
+ <div>
363
+ <Tooltip content="hello" class="a">
364
+ <div ref="test" class="b">test</div>
365
+ </Tooltip>
366
+ </div>
367
+ `;
368
+ Tooltip = Tooltip;
369
+ }
370
+
371
+ const [instance, element] = mount(Demo);
372
+ const trigger = instance.refs.test;
373
+ expect(trigger.className).to.eql('b a');
374
+
375
+ dispatchEvent(trigger, 'mouseenter');
376
+ await wait();
377
+ const dropdown = getElement('.k-tooltip-content')!;
378
+ expect(dropdown.classList.contains('a')).to.be.true;
379
+ });
380
+
381
+ it('should fix the width in small container', async () => {
382
+ class Demo extends Component {
383
+ static template = `
384
+ const {Tooltip, Dialog} = this;
385
+ <div style="text-align: right; position: relative; width: 300px;">
386
+ <Tooltip content="这是一段很长的描述文字,这是一段很长的描述文字" container={dom => dom}>
387
+ <span class="trigger">test</span>
388
+ </Tooltip>
389
+ </div>
390
+ `
391
+ private Tooltip = Tooltip;
392
+ private Dialog = Dialog;
393
+ }
394
+
395
+ const [instance, element] = mount(Demo);
396
+ const trigger = element.querySelector<HTMLDivElement>('.trigger')!;
397
+ const expecedWidth = parseInt(tooltipTheme.maxWidth);
398
+
399
+ dispatchEvent(trigger, 'mouseenter');
400
+ await wait();
401
+ const content = getElement('.k-tooltip-content')!;
402
+ const width = content.offsetWidth;
403
+ expect(width).to.eql(expecedWidth);
404
+
405
+ dispatchEvent(trigger, 'mouseleave');
406
+ await wait();
407
+ dispatchEvent(trigger, 'mouseenter');
408
+ await wait();
409
+ const newWidth = content.offsetWidth;
410
+ expect(newWidth).to.eql(width);
411
+ });
412
+
413
+ it('should not impact select when wrap select with tooltip', async () => {
414
+ class Demo extends Component {
415
+ static template = `
416
+ const {Tooltip, Select, Option} = this;
417
+ <Tooltip>
418
+ <Select>
419
+ <Option value="1">Option 1</Option>
420
+ <Option value="2">Option 2</Option>
421
+ </Select>
422
+ </Tooltip>
423
+ `
424
+ private Tooltip = Tooltip;
425
+ private Select = Select;
426
+ private Option = Option;
427
+ }
428
+
429
+ const [instance, element] = mount(Demo);
430
+ dispatchEvent(element, 'mouseenter');
431
+ await wait();
432
+ dispatchEvent(element, 'click');
433
+ await wait();
434
+
435
+ const menu = getElement(".k-select-menu")!;
436
+ dispatchEvent(element, 'mouseleave');
437
+ await wait(500);
438
+
439
+ expect(menu.style.display).to.eql('');
440
+ });
355
441
  });
@@ -31,7 +31,7 @@ const defaults = {
31
31
  smallPadding: '4px',
32
32
  };
33
33
 
34
- let tooltip: typeof defaults;
34
+ export let tooltip: typeof defaults;
35
35
  setDefault(() => {
36
36
  tooltip = deepDefaults(theme, {tooltip: defaults}).tooltip;
37
37
  });
@@ -49,6 +49,7 @@ const defaults = (): Partial<TooltipProps> => ({
49
49
  showArrow: true,
50
50
  theme: 'dark',
51
51
  position: {my: 'center bottom-10', at: 'center top', collision: 'flipfit'},
52
+ collison: 'flipfit',
52
53
  hoverable: false,
53
54
  always: false,
54
55
  confirm: false,
@@ -72,12 +73,22 @@ export class Tooltip<
72
73
  static defaults = defaults;
73
74
  static events = events;
74
75
 
76
+ show(shouldFocus: boolean = false) {
77
+ if (this.get('disabled')) return;
78
+
79
+ clearTimeout(this.timer);
80
+ this.set('value', true);
81
+ }
82
+
75
83
  hide(immediately: boolean) {
76
84
  if (this.get('always')) return;
77
85
 
78
86
  if (this.get('hoverable')) {
79
87
  return super.hide(immediately);
80
88
  }
89
+ // tooltip can show any number sub-tooltips, we should not close the showed tooltip
90
+ // #885
91
+ this.showedDropdown = null;
81
92
  super.hide(true);
82
93
  }
83
94
  }
@@ -0,0 +1,98 @@
1
+ import {
2
+ Component,
3
+ VNode,
4
+ directClone,
5
+ createVNode,
6
+ } from 'intact';
7
+ import { isTextChildren } from './utils';
8
+ import { EMPTY_OBJ, isFunction, hasOwn } from 'intact-shared';
9
+ import { cx } from '@emotion/css';
10
+
11
+ const reactEventReg = /on[A-Z]/;
12
+
13
+ export class Virtual extends Component<any> {
14
+ static template(this: Virtual) {
15
+ const { children, ...props } = this.get();
16
+
17
+ if (process.env.NODE_ENV !== 'production') {
18
+ if (!children || (Array.isArray(children) && children.length !== 1)) {
19
+ throw new Error('Component must receive one children');
20
+ }
21
+ }
22
+
23
+ const vNode = Array.isArray(children) ? children[0] : children;
24
+ const clonedVNode = isTextChildren(vNode)
25
+ ? createVNode('span', null, vNode)
26
+ : directClone(vNode as VNode);
27
+
28
+ const vNodeProps = this.vNodeProps = this.getVNodeProps(clonedVNode.props || EMPTY_OBJ);
29
+ const eventProps = this.getEventProps();
30
+
31
+ // merge className
32
+ let className = clonedVNode.className || vNodeProps.className;
33
+ className = cx({
34
+ [className!]: !!className,
35
+ [props.className!]: !!props.className,
36
+ });
37
+
38
+ clonedVNode.props = { ...props, ...vNodeProps, ...eventProps, className };
39
+ clonedVNode.className = className;
40
+
41
+ return clonedVNode;
42
+ }
43
+
44
+ private vNodeProps: any = null;
45
+
46
+ private getVNodeProps(props: any) {
47
+ const vnode = props.vnode;
48
+
49
+ if (!vnode) return props;
50
+
51
+ // maybe we render the intact component in react slot property, in this case
52
+ // the $isReact is false. so use the vnode $$typeof field as gauge
53
+ if (vnode.$$typeof || vnode.__v_isVNode /* vue3 vnode */) {
54
+ const _props = vnode.props;
55
+ if (!_props) return props;
56
+
57
+ const events: Record<string, Function> = {};
58
+ for (let key in _props) {
59
+ if (reactEventReg.test(key)) {
60
+ events[`ev-${key.substring(2).toLowerCase()}`] = _props[key];
61
+ }
62
+ }
63
+
64
+ return {...props, ...events, className: _props.className || _props.class /* vue-next */};
65
+ } else if (hasOwn.call(vnode, 'componentOptions') /* vue2 vnode */) {
66
+ const data = vnode.data;
67
+ const on = data && data.on || EMPTY_OBJ;
68
+ const events: Record<string, Function> = {};
69
+ for (let key in on) {
70
+ events[`ev-${key}`] = on[key];
71
+ }
72
+
73
+ return {...props, ...events};
74
+ }
75
+
76
+ return props;
77
+ }
78
+
79
+ private getEventProps() {
80
+ const props: Record<string, Function> = {};
81
+
82
+ for (let prop in this.get()) {
83
+ if (prop.startsWith('ev-')) {
84
+ props[prop] = (e: MouseEvent) => this.callEvent(prop, e);
85
+ }
86
+ }
87
+
88
+ return props;
89
+ }
90
+
91
+
92
+ private callEvent(name: string, e: MouseEvent) {
93
+ const callback = this.vNodeProps[name];
94
+ const callbackOnVirtual = this.get<Function>(name);
95
+ if (isFunction(callback)) callback(e);
96
+ if (isFunction(callbackOnVirtual)) callbackOnVirtual(e);
97
+ }
98
+ }
@@ -3,6 +3,7 @@ import { Options, Feedback } from '../position';
3
3
  import { Portal, PortalProps } from '../portal';
4
4
  import { FeedbackCallback } from './usePosition';
5
5
  import type { Events } from '../types';
6
+ import { Virtual } from '../virtual';
6
7
  export declare type Position = Options;
7
8
  export declare type PositionShorthand = 'left' | 'bottom' | 'right' | 'top';
8
9
  export declare const DROPDOWN = "Dropdown";
@@ -12,6 +13,7 @@ export interface DropdownProps {
12
13
  disabled?: boolean;
13
14
  value?: boolean;
14
15
  position?: Position | 'left' | 'bottom' | 'right' | 'top';
16
+ collison?: Position['collision'];
15
17
  of?: 'self' | 'parent' | Event;
16
18
  container?: PortalProps['container'];
17
19
  }
@@ -21,6 +23,8 @@ export interface DropdownEvents {
21
23
  hide: [];
22
24
  mouseenter: [MouseEvent];
23
25
  mouseleave: [MouseEvent];
26
+ click: [MouseEvent];
27
+ contextmenu: [MouseEvent];
24
28
  positioned: [Feedback];
25
29
  }
26
30
  export interface DropdownBlocks {
@@ -30,7 +34,7 @@ export declare class Dropdown<T extends DropdownProps = DropdownProps, E extends
30
34
  static typeDefs: Required<TypeDefs<DropdownProps>>;
31
35
  static defaults: () => Partial<DropdownProps>;
32
36
  static events: Events<DropdownEvents>;
33
- static template: (this: Dropdown) => (VNode<import("intact").VNodeTag> | VNode<typeof Portal>)[];
37
+ static template: (this: Dropdown) => (VNode<typeof Virtual> | VNode<typeof Portal>)[];
34
38
  menuVNode: VNode | null;
35
39
  dropdown: Dropdown | null;
36
40
  rootDropdown: Dropdown | null;
@@ -41,8 +45,7 @@ export declare class Dropdown<T extends DropdownProps = DropdownProps, E extends
41
45
  value: boolean;
42
46
  };
43
47
  };
44
- private timer;
45
- private triggerProps;
48
+ protected timer: number | undefined;
46
49
  init(): void;
47
50
  show(shouldFocus?: boolean): void;
48
51
  hide(immediately?: boolean): void;
@@ -52,6 +55,4 @@ export declare class Dropdown<T extends DropdownProps = DropdownProps, E extends
52
55
  private onContextMenu;
53
56
  private onLeave;
54
57
  private initEventCallbacks;
55
- private callOriginalCallback;
56
- private normalizeTriggerProps;
57
58
  }
@@ -3,14 +3,15 @@ import _inheritsLoose from "@babel/runtime-corejs3/helpers/inheritsLoose";
3
3
  import _concatInstanceProperty from "@babel/runtime-corejs3/core-js/instance/concat";
4
4
  import _filterInstanceProperty from "@babel/runtime-corejs3/core-js/instance/filter";
5
5
  import { __decorate } from "tslib";
6
- import { Component, createVNode as h, directClone, provide, inject, findDomFromVNode, createVNode, nextTick } from 'intact';
7
- import { bind, isTextChildren } from '../utils';
8
- import { EMPTY_OBJ, isFunction, noop } from 'intact-shared';
6
+ import { Component, createVNode as h, provide, inject, findDomFromVNode, nextTick } from 'intact';
7
+ import { bind, getRestProps } from '../utils';
8
+ import { noop } from 'intact-shared';
9
9
  import { cx } from '@emotion/css';
10
10
  import { useDocumentClick, containsOrEqual } from '../../hooks/useDocumentClick';
11
11
  import { Portal } from '../portal';
12
12
  import { useShowHideEvents } from '../../hooks/useShowHideEvents';
13
13
  import { usePosition } from './usePosition';
14
+ import { Virtual } from '../virtual';
14
15
  export var DROPDOWN = 'Dropdown';
15
16
  export var ROOT_DROPDOWN = 'RootDropdown';
16
17
  var typeDefs = {
@@ -20,13 +21,15 @@ var typeDefs = {
20
21
  position: [Object, 'left', 'bottom', 'right', 'top'],
21
22
  // Event is undefined in NodeJs
22
23
  of: ['self', 'parent', typeof Event === 'undefined' ? undefined : Event],
23
- container: [String, Function]
24
+ container: [String, Function],
25
+ collison: ['none', 'fit', 'flip', 'flipfit', Array]
24
26
  };
25
27
 
26
28
  var defaults = function defaults() {
27
29
  return {
28
30
  trigger: 'hover',
29
- of: 'self'
31
+ of: 'self',
32
+ value: false
30
33
  };
31
34
  };
32
35
 
@@ -36,6 +39,8 @@ var events = {
36
39
  hide: true,
37
40
  mouseenter: true,
38
41
  mouseleave: true,
42
+ click: true,
43
+ contextmenu: true,
39
44
  positioned: true
40
45
  };
41
46
  export var Dropdown = /*#__PURE__*/function (_Component) {
@@ -57,7 +62,6 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
57
62
  _this.showedDropdown = null;
58
63
  _this.positionHook = usePosition();
59
64
  _this.timer = undefined;
60
- _this.triggerProps = null;
61
65
  return _this;
62
66
  }
63
67
 
@@ -95,7 +99,13 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
95
99
 
96
100
  if (this.get('disabled')) return;
97
101
  clearTimeout(this.timer);
98
- this.set('value', true);
102
+ this.set('value', true); // should show parent dropdown
103
+
104
+ var parentDropdown = this.dropdown;
105
+
106
+ if (parentDropdown) {
107
+ parentDropdown.show();
108
+ }
99
109
 
100
110
  if (shouldFocus) {
101
111
  nextTick(function () {
@@ -113,10 +123,16 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
113
123
 
114
124
  if (this.get('disabled')) return;
115
125
  if (!this.get('value')) return;
126
+ var showedDropdown = this.showedDropdown;
127
+
128
+ if (showedDropdown) {
129
+ showedDropdown.hide(immediately);
130
+ }
116
131
 
117
132
  if (immediately) {
118
133
  this.set('value', false);
119
134
  } else {
135
+ clearTimeout(this.timer);
120
136
  this.timer = window.setTimeout(function () {
121
137
  _this4.set('value', false);
122
138
  }, 200);
@@ -136,23 +152,24 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
136
152
  };
137
153
 
138
154
  _proto.onEnter = function onEnter(e) {
139
- this.callOriginalCallback(e.type === 'click' ? 'ev-click' : 'ev-mouseenter', e);
140
155
  this.show();
156
+ this.trigger(e.type, e);
141
157
  };
142
158
 
143
159
  _proto.onContextMenu = function onContextMenu(e) {
144
- this.callOriginalCallback('ev-contextmenu', e);
145
160
  e.preventDefault();
146
161
  this.set('of', e);
147
162
  this.show();
163
+ this.trigger('contextmenu', e);
148
164
  };
149
165
 
150
166
  _proto.onLeave = function onLeave(e) {
151
- this.callOriginalCallback('ev-mouseleave', e);
152
167
  this.hide();
168
+ this.trigger(e.type, e);
153
169
  };
154
170
 
155
- _proto.initEventCallbacks = function initEventCallbacks(trigger) {
171
+ _proto.initEventCallbacks = function initEventCallbacks() {
172
+ var trigger = this.get('trigger');
156
173
  var props = {};
157
174
 
158
175
  switch (trigger) {
@@ -179,51 +196,6 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
179
196
  return props;
180
197
  };
181
198
 
182
- _proto.callOriginalCallback = function callOriginalCallback(name, e) {
183
- var callback = this.triggerProps[name];
184
- var callbackOnDropdown = this.get(name);
185
- if (isFunction(callback)) callback(e);
186
- if (isFunction(callbackOnDropdown)) callbackOnDropdown(e);
187
- };
188
-
189
- _proto.normalizeTriggerProps = function normalizeTriggerProps(props) {
190
- // if use kpc in react or vue, normalize props by Wrapper.props.vnode;
191
- var vnode = props.vnode;
192
- if (!vnode) return props; // maybe we render the intact component in react slot property, in this case
193
- // the $isReact is false. so use the vnode $$typeof field as gauge
194
-
195
- if (vnode.$$typeof || this.$isVueNext) {
196
- var _props = vnode.props;
197
- if (!_props) return props;
198
- return {
199
- vnode: vnode,
200
- 'ev-click': _props.onClick,
201
- 'ev-mouseenter': _props.onMouseEnter,
202
- 'ev-mouseleave': _props.onMouseLeave,
203
- 'ev-contextmenu': _props.onContextMenu,
204
- className: _props.className || _props.class
205
- /* vue-next */
206
-
207
- };
208
- } else if (this.$isVue) {
209
- var data = vnode.data;
210
- var on = data && data.on || EMPTY_OBJ;
211
- var ret = {
212
- vnode: vnode
213
- };
214
- ['click', 'mouseenter', 'mouseleave', 'contextmenu'].forEach(function (event) {
215
- var method = on[event];
216
-
217
- if (method) {
218
- ret["ev-" + event] = method;
219
- }
220
- });
221
- return ret;
222
- }
223
-
224
- return props;
225
- };
226
-
227
199
  return Dropdown;
228
200
  }(Component);
229
201
  Dropdown.$doubleVNodes = true;
@@ -253,21 +225,22 @@ Dropdown.template = function () {
253
225
  var _children = children,
254
226
  trigger = _children[0],
255
227
  menu = _children[1];
256
- var triggerType = this.get('trigger');
257
- var props = this.initEventCallbacks(triggerType);
258
- var clonedTrigger = isTextChildren(trigger) ? createVNode('span', null, trigger) : directClone(trigger);
259
- var triggerProps = this.triggerProps = this.normalizeTriggerProps(trigger.props || EMPTY_OBJ); // add a className for opening status
260
-
261
- var className = trigger.className || triggerProps.className;
262
- className = cx((_cx = {}, _cx[className] = className, _cx['k-dropdown-open'] = this.get('value'), _cx));
263
- clonedTrigger.props = _extends({}, triggerProps, props, {
264
- className: className
265
- });
266
- clonedTrigger.className = className;
228
+ var props = this.initEventCallbacks();
229
+
230
+ var _this$get = this.get(),
231
+ className = _this$get.className,
232
+ value = _this$get.value,
233
+ container = _this$get.container;
234
+
235
+ className = cx((_cx = {
236
+ 'k-dropdown-open': value
237
+ }, _cx[className] = !!className, _cx));
267
238
  this.menuVNode = menu;
268
- return [clonedTrigger, h(Portal, {
239
+ return [h(Virtual, _extends({}, props, getRestProps(this), {
240
+ className: className
241
+ }), trigger), h(Portal, {
269
242
  children: menu,
270
- container: this.get('container')
243
+ container: container
271
244
  })];
272
245
  };
273
246
 
@@ -8,6 +8,7 @@ import { Dropdown, DropdownMenu, DropdownItem } from '../dropdown';
8
8
  import BasicDemo from '~/components/dropdown/demos/basic';
9
9
  import NestedDemo from '~/components/dropdown/demos/nested';
10
10
  import ContextMenuDemo from '~/components/dropdown/demos/contextmenu';
11
+ import TooltipDemo from '~/components/dropdown/demos/tooltip';
11
12
  describe('Dropdown', function () {
12
13
  afterEach(function (done) {
13
14
  unmount();
@@ -113,42 +114,61 @@ describe('Dropdown', function () {
113
114
  }, _callee2);
114
115
  })));
115
116
  it('nested dropdown', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3() {
116
- var _mount3, instance, element, dropdown, _dropdown$querySelect, hoverItem, clickItem, clickSubDropdown, hoverSubDropdown;
117
+ var _mount3, instance, element, dropdown, _dropdown$querySelect, hoverItem, clickItem, clickSubDropdown, hoverSubDropdown, _hoverSubDropdown$que, hoverItem1, hoverSubDropdown1, _hoverSubDropdown1$qu, hoverItem2, hoverSubDropdown2;
117
118
 
118
119
  return _regeneratorRuntime.wrap(function _callee3$(_context4) {
119
120
  while (1) {
120
121
  switch (_context4.prev = _context4.next) {
121
122
  case 0:
123
+ this.timeout(0);
122
124
  _mount3 = mount(NestedDemo), instance = _mount3[0], element = _mount3[1];
123
125
  element.firstElementChild.click();
124
- _context4.next = 4;
126
+ _context4.next = 5;
125
127
  return wait();
126
128
 
127
- case 4:
129
+ case 5:
128
130
  dropdown = getElement('.k-dropdown-menu');
129
131
  _dropdown$querySelect = dropdown.querySelectorAll(':scope > .k-dropdown-item'), hoverItem = _dropdown$querySelect[3], clickItem = _dropdown$querySelect[4];
130
132
  clickItem.click();
131
- _context4.next = 9;
133
+ _context4.next = 10;
132
134
  return wait(500);
133
135
 
134
- case 9:
136
+ case 10:
135
137
  clickSubDropdown = getElement('.k-dropdown-menu');
136
138
  expect(clickSubDropdown.innerHTML).to.matchSnapshot(); // should hide last sub-dropdown and show next
137
139
 
138
140
  dispatchEvent(hoverItem, 'mouseenter');
139
- _context4.next = 14;
141
+ _context4.next = 15;
140
142
  return wait(500);
141
143
 
142
- case 14:
144
+ case 15:
143
145
  hoverSubDropdown = getElement('.k-dropdown-menu');
144
146
  expect(hoverSubDropdown.innerHTML).to.matchSnapshot();
147
+ _hoverSubDropdown$que = hoverSubDropdown.querySelectorAll('.k-dropdown-item'), hoverItem1 = _hoverSubDropdown$que[0];
148
+ dispatchEvent(hoverItem, 'mouseleave');
149
+ dispatchEvent(hoverItem1, 'mouseenter');
150
+ _context4.next = 22;
151
+ return wait(500);
145
152
 
146
- case 16:
153
+ case 22:
154
+ hoverSubDropdown1 = getElement('.k-dropdown-menu');
155
+ expect(hoverSubDropdown1.textContent).to.eql('item 1item 2');
156
+ _hoverSubDropdown1$qu = hoverSubDropdown1.querySelectorAll('.k-dropdown-item'), hoverItem2 = _hoverSubDropdown1$qu[0];
157
+ dispatchEvent(hoverItem1, 'mouseleave');
158
+ dispatchEvent(hoverItem2, 'mouseenter');
159
+ _context4.next = 29;
160
+ return wait(1000);
161
+
162
+ case 29:
163
+ hoverSubDropdown2 = getElement('.k-dropdown-menu');
164
+ expect(hoverSubDropdown2 === hoverSubDropdown1).to.be.true;
165
+
166
+ case 31:
147
167
  case "end":
148
168
  return _context4.stop();
149
169
  }
150
170
  }
151
- }, _callee3);
171
+ }, _callee3, this);
152
172
  })));
153
173
  it('hide on click document', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4() {
154
174
  var _mount4, instance, element;
@@ -483,7 +503,7 @@ describe('Dropdown', function () {
483
503
  }
484
504
  }, _callee9);
485
505
  })));
486
- it('trigger: focus', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
506
+ it('focus trigger type', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
487
507
  var Demo, _mount9, instance;
488
508
 
489
509
  return _regeneratorRuntime.wrap(function _callee10$(_context14) {
@@ -506,39 +526,98 @@ describe('Dropdown', function () {
506
526
  _this4.Dropdown = Dropdown;
507
527
  _this4.DropdownItem = DropdownItem;
508
528
  _this4.DropdownMenu = DropdownMenu;
529
+ _this4.onFocus = sinon.spy(function (e) {
530
+ return console.log(e);
531
+ });
509
532
  return _this4;
510
533
  }
511
534
 
512
535
  return Demo;
513
536
  }(Component);
514
537
 
515
- Demo.template = "\n const {Dropdown, DropdownMenu, DropdownItem} = this;\n <div>\n <Dropdown trigger=\"focus\">\n <input ref=\"trigger\" />\n <DropdownMenu>\n <DropdownItem>test1</DropdownItem>\n <DropdownItem>test2</DropdownItem>\n </DropdownMenu>\n </Dropdown>\n </div>\n ";
538
+ Demo.template = "\n const {Dropdown, DropdownMenu, DropdownItem} = this;\n <div>\n <Dropdown trigger=\"focus\">\n <input ref=\"trigger\" ev-focusin={this.onFocus} />\n <DropdownMenu>\n <DropdownItem>test1</DropdownItem>\n <DropdownItem>test2</DropdownItem>\n </DropdownMenu>\n </Dropdown>\n </div>\n ";
516
539
  _mount9 = mount(Demo), instance = _mount9[0];
517
540
  dispatchEvent(instance.refs.trigger, 'focusin');
518
541
  _context14.next = 6;
519
542
  return wait(500);
520
543
 
521
544
  case 6:
522
- expect(getElement('.k-dropdown-menu')).to.be.exist; // clicking anywhere should not hide menu
545
+ expect(getElement('.k-dropdown-menu')).to.be.exist;
546
+ expect(instance.onFocus.callCount).to.eql(1); // clicking anywhere should not hide menu
523
547
 
524
548
  dispatchEvent(document, 'click');
525
- _context14.next = 10;
549
+ _context14.next = 11;
526
550
  return wait(500);
527
551
 
528
- case 10:
552
+ case 11:
529
553
  expect(getElement('.k-dropdown-menu')).to.be.exist;
530
554
  dispatchEvent(instance.refs.trigger, 'focusout');
531
- _context14.next = 14;
555
+ _context14.next = 15;
532
556
  return wait(700);
533
557
 
534
- case 14:
558
+ case 15:
535
559
  expect(getElement('.k-dropdown-menu')).to.not.be.exist;
536
560
 
537
- case 15:
561
+ case 16:
538
562
  case "end":
539
563
  return _context14.stop();
540
564
  }
541
565
  }
542
566
  }, _callee10);
543
567
  })));
568
+ it('wrap by tooltip', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
569
+ var _mount10, instance, element, dropdown, _dropdown$querySelect4, item1, item2, item3, item4;
570
+
571
+ return _regeneratorRuntime.wrap(function _callee11$(_context15) {
572
+ while (1) {
573
+ switch (_context15.prev = _context15.next) {
574
+ case 0:
575
+ _mount10 = mount(TooltipDemo), instance = _mount10[0], element = _mount10[1];
576
+ dispatchEvent(element.firstChild, 'mouseenter');
577
+ _context15.next = 4;
578
+ return wait();
579
+
580
+ case 4:
581
+ dropdown = getElement('.k-dropdown-menu');
582
+ _dropdown$querySelect4 = dropdown.querySelectorAll('.k-dropdown-item'), item1 = _dropdown$querySelect4[0], item2 = _dropdown$querySelect4[1], item3 = _dropdown$querySelect4[2], item4 = _dropdown$querySelect4[3];
583
+ dispatchEvent(item1, 'mouseenter');
584
+ _context15.next = 9;
585
+ return wait();
586
+
587
+ case 9:
588
+ expect(getElement('.k-tooltip-content').textContent).to.eql('item 1');
589
+ dispatchEvent(item1, 'mouseleave');
590
+ dispatchEvent(item3, 'mouseenter');
591
+ _context15.next = 14;
592
+ return wait();
593
+
594
+ case 14:
595
+ expect(getElement('.k-tooltip-content').textContent).to.eql('disabled');
596
+ dispatchEvent(item3, 'mouseleave');
597
+ dispatchEvent(item4, 'mouseenter');
598
+ _context15.next = 19;
599
+ return wait();
600
+
601
+ case 19:
602
+ expect(getElement('.k-tooltip-content').textContent).to.eql('This is a nested Dropdown.');
603
+ dispatchEvent(item4, 'click');
604
+ _context15.next = 23;
605
+ return wait();
606
+
607
+ case 23:
608
+ expect(getElement('.k-dropdown-menu').textContent).to.eql('item 1item 2');
609
+ dispatchEvent(item4, 'mouseleave');
610
+ _context15.next = 27;
611
+ return wait(800);
612
+
613
+ case 27:
614
+ expect(getElement('.k-dropdown-menu')).to.not.be.exist;
615
+
616
+ case 28:
617
+ case "end":
618
+ return _context15.stop();
619
+ }
620
+ }
621
+ }, _callee11);
622
+ })));
544
623
  });