@king-design/intact 2.0.11 → 2.0.13-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/components/cascader/styles.ts +1 -1
  2. package/components/drawer/index.spec.ts +20 -0
  3. package/components/dropdown/demos/trigger.md +13 -2
  4. package/components/dropdown/dropdown.ts +29 -13
  5. package/components/dropdown/index.md +1 -1
  6. package/components/dropdown/index.spec.ts +34 -0
  7. package/components/form/demos/basic.md +1 -1
  8. package/components/form/index.md +7 -4
  9. package/components/form/methods.ts +2 -1
  10. package/components/portal.ts +8 -2
  11. package/components/select/demos/format.md +3 -2
  12. package/components/select/styles.ts +10 -5
  13. package/components/table/table.ts +0 -1
  14. package/components/table/useResizeObserver.ts +22 -0
  15. package/components/table/useStickyScrollbar.ts +2 -8
  16. package/components/table/useWidth.ts +4 -18
  17. package/components/timepicker/index.ts +1 -0
  18. package/components/tooltip/demos/trigger.md +5 -2
  19. package/components/tooltip/index.md +1 -1
  20. package/es/components/cascader/styles.js +1 -1
  21. package/es/components/drawer/index.spec.js +48 -0
  22. package/es/components/dropdown/dropdown.d.ts +2 -1
  23. package/es/components/dropdown/dropdown.js +31 -14
  24. package/es/components/dropdown/index.spec.js +58 -0
  25. package/es/components/form/methods.d.ts +2 -1
  26. package/es/components/portal.js +9 -2
  27. package/es/components/select/styles.js +2 -2
  28. package/es/components/table/table.js +1 -1
  29. package/es/components/table/useResizeObserver.d.ts +2 -0
  30. package/es/components/table/useResizeObserver.js +20 -0
  31. package/es/components/table/useStickyScrollbar.d.ts +1 -1
  32. package/es/components/table/useStickyScrollbar.js +4 -9
  33. package/es/components/table/useWidth.js +5 -15
  34. package/es/components/timepicker/index.d.ts +1 -0
  35. package/es/components/timepicker/index.js +1 -0
  36. package/es/hooks/useDocumentClick.js +29 -2
  37. package/es/index.d.ts +2 -2
  38. package/es/index.js +2 -2
  39. package/es/packages/kpc-react/__tests__/components/drawer.spec.js +34 -18
  40. package/es/site/data/components/dropdown/demos/trigger/react.js +6 -2
  41. package/es/site/data/components/select/demos/format/react.js +1 -1
  42. package/es/site/data/components/tooltip/demos/trigger/react.js +7 -2
  43. package/hooks/useDocumentClick.ts +29 -1
  44. package/index.ts +2 -2
  45. package/package.json +3 -3
  46. package/dist/fonts/ionicons.eot +0 -0
  47. package/dist/fonts/ionicons.svg +0 -2230
  48. package/dist/fonts/ionicons.ttf +0 -0
  49. package/dist/fonts/ionicons.woff +0 -0
  50. package/dist/i18n/en-US.js +0 -218
  51. package/dist/i18n/en-US.min.js +0 -1
  52. package/dist/kpc.css +0 -3
  53. package/dist/kpc.js +0 -39860
  54. package/dist/kpc.min.js +0 -1
  55. package/dist/kpc.react.js +0 -90483
  56. package/dist/kpc.react.min.js +0 -1
  57. package/dist/kpc.vue.js +0 -48096
  58. package/dist/kpc.vue.min.js +0 -1
  59. package/dist/ksyun.css +0 -3
@@ -33,7 +33,7 @@ setDefault(() => {
33
33
  export function makeMenuStyles() {
34
34
  return css`
35
35
  min-width: ${cascader.width} !important;
36
- height: ${cascader.height};
36
+ min-height: ${cascader.height};
37
37
  .k-cascader-arrow {
38
38
  float: right;
39
39
  height: 100%;
@@ -2,6 +2,9 @@ import BasicDemo from '~/components/drawer/demos/basic';
2
2
  import PlacementDemo from '~/components/drawer/demos/placement';
3
3
  import overlayDemo from '~/components/drawer/demos/overlay';
4
4
  import {mount, unmount, dispatchEvent, getElement, wait} from '../../test/utils';
5
+ import {Component} from 'intact';
6
+ import {Drawer} from '.';
7
+ import {Dialog} from '../dialog';
5
8
 
6
9
  describe('Drawer', () => {
7
10
  afterEach((done) => {
@@ -67,4 +70,21 @@ describe('Drawer', () => {
67
70
  await wait(500);
68
71
  expect(getElement('.k-drawer')).to.be.undefined;
69
72
  });
73
+
74
+ it('nested dialog', async () => {
75
+ class Demo extends Component {
76
+ static template = `
77
+ const {Dialog, Drawer} = this;
78
+ <Drawer value={true}>
79
+ <Dialog value={true} ref="dialog">Dialog</Dialog>
80
+ </Drawer>
81
+ `;
82
+ private Dialog = Dialog;
83
+ private Drawer = Drawer;
84
+ }
85
+ const [instance, element] = mount(Demo);
86
+
87
+ await wait();
88
+ expect(instance.refs.dialog.dialogRef.value.parentElement.parentElement).to.eql(document.body);
89
+ });
70
90
  });
@@ -3,11 +3,13 @@ title: 触发方式
3
3
  order: 0
4
4
  ---
5
5
 
6
- `Dropdown`提供了两种触发方式来弹窗菜单,`hover`悬停触发(默认),`click`点击触发。
6
+ `Dropdown`提供了两种触发方式来弹窗菜单,`hover`悬停触发(默认),`click`点击触发,当使用`Input`组件时,还可以
7
+ 指定为`foucs`来触发。
8
+
7
9
  通过`trigger`属性来指定它们。
8
10
 
9
11
  ```vdt
10
- import {Dropdown, DropdownMenu, DropdownItem, Button, Icon} from 'kpc';
12
+ import {Dropdown, DropdownMenu, DropdownItem, Button, Icon, Input} from 'kpc';
11
13
 
12
14
  <div>
13
15
  <Dropdown>
@@ -31,6 +33,15 @@ import {Dropdown, DropdownMenu, DropdownItem, Button, Icon} from 'kpc';
31
33
  <DropdownItem>item 3</DropdownItem>
32
34
  </DropdownMenu>
33
35
  </Dropdown>
36
+
37
+ <Dropdown trigger="focus">
38
+ <Input placeholder="focus" />
39
+ <DropdownMenu>
40
+ <DropdownItem>item 1</DropdownItem>
41
+ <DropdownItem>item 2</DropdownItem>
42
+ <DropdownItem>item 3</DropdownItem>
43
+ </DropdownMenu>
44
+ </Dropdown>
34
45
  </div>
35
46
  ```
36
47
 
@@ -31,7 +31,7 @@ export const DROPDOWN = 'Dropdown';
31
31
  export const ROOT_DROPDOWN = 'RootDropdown';
32
32
 
33
33
  export interface DropdownProps {
34
- trigger?: 'hover' | 'click' | 'contextmenu'
34
+ trigger?: 'hover' | 'click' | 'contextmenu' | 'focus'
35
35
  disabled?: boolean
36
36
  value?: boolean
37
37
  position?: Position | 'left' | 'bottom' | 'right' | 'top'
@@ -51,7 +51,7 @@ export interface DropdownEvents {
51
51
  export interface DropdownBlocks { }
52
52
 
53
53
  const typeDefs: Required<TypeDefs<DropdownProps>> = {
54
- trigger: ['hover', 'click', 'contextmenu'],
54
+ trigger: ['hover', 'click', 'contextmenu', 'focus'],
55
55
  disabled: Boolean,
56
56
  value: Boolean,
57
57
  position: [Object, 'left', 'bottom', 'right', 'top'],
@@ -106,17 +106,7 @@ export class Dropdown<
106
106
 
107
107
  const [trigger, menu] = children as DropdownChildren;
108
108
  const triggerType = this.get('trigger');
109
- const props: Record<string, Function> = {};
110
-
111
- if (triggerType !== 'contextmenu') {
112
- props['ev-click'] = this.onEnter;
113
- if (triggerType === 'hover') {
114
- props['ev-mouseenter'] = this.onEnter;
115
- props['ev-mouseleave'] = this.onLeave;
116
- }
117
- } else {
118
- props['ev-contextmenu'] = this.onContextMenu;
119
- }
109
+ const props = this.initEventCallbacks(triggerType);
120
110
 
121
111
  const clonedTrigger = isTextChildren(trigger) ?
122
112
  createVNode('span', null, trigger) :
@@ -235,6 +225,29 @@ export class Dropdown<
235
225
  this.hide();
236
226
  }
237
227
 
228
+ private initEventCallbacks(trigger: DropdownProps['trigger']) {
229
+ const props: Record<string, Function> = {};
230
+
231
+ switch (trigger) {
232
+ case 'focus':
233
+ props['ev-focusin'] = this.onEnter;
234
+ props['ev-focusout'] = this.onLeave;
235
+ break;
236
+ case 'contextmenu':
237
+ props['ev-contextmenu'] = this.onContextMenu;
238
+ break;
239
+ default:
240
+ props['ev-click'] = this.onEnter;
241
+ if (trigger === 'hover') {
242
+ props['ev-mouseenter'] = this.onEnter;
243
+ props['ev-mouseleave'] = this.onLeave;
244
+ }
245
+ break;
246
+ }
247
+
248
+ return props;
249
+ }
250
+
238
251
  private callOriginalCallback(name: string, e: MouseEvent) {
239
252
  const callback = this.triggerProps[name];
240
253
  const callbackOnDropdown = this.get<Function>(name);
@@ -283,7 +296,10 @@ function useDocumentClickForDropdown(dropdown: Dropdown) {
283
296
  const [addDocumentClick, removeDocumentClick] = useDocumentClick(elementRef, (e) => {
284
297
  // case 1: if click an trigger and the trigger type is hover, ignore it
285
298
  // case 2: if right click on trigger and the trigger type is contextmenu, ignore it
299
+ // case 3: if click on trigger and the trigger type is focus, do nothing
286
300
  const trigger = dropdown.get('trigger');
301
+ if (trigger === 'focus') return;
302
+
287
303
  const isHover = trigger === 'hover';
288
304
  if (isHover || trigger === 'contextmenu') {
289
305
  const triggerDom = findDomFromVNode(dropdown.$lastInput!, true) as Element;
@@ -11,7 +11,7 @@ sidebar: doc
11
11
 
12
12
  | 属性 | 说明 | 类型 | 默认值 |
13
13
  | --- | --- | --- | --- |
14
- | trigger | 触发方式,`hover`为悬停触发,`click`为点击触发 | `"hover"` &#124; `"click"` | `"hover"` |
14
+ | trigger | 触发方式,`hover`为悬停触发,`click`为点击触发 | `"hover"` &#124; `"click"` &#124; `"contextmenu"` &#124; `"focus"` | `"hover"` |
15
15
  | disabled | 是否禁用整个菜单 | `boolean` | `false` |
16
16
  | value | 是否将弹出菜单展示出来,可通过`v-model`双向绑定 | `boolean` | `false` |
17
17
  | position | 菜单弹出的位置,默认与触发器左侧对齐向下偏移`8px`的地方 | `Position` &#124; `"left"` &#124; `"bottom"` &#124; `"right"` &#124; `"top"` | `{my: 'left top+8', 'left bottom'}` |
@@ -280,4 +280,38 @@ describe('Dropdown', () => {
280
280
  await wait();
281
281
  expect(parent.scrollTop).to.eql(item.offsetHeight * 2 - 40);
282
282
  });
283
+
284
+ it('trigger: focus', async() => {
285
+ class Demo extends Component {
286
+ static template = `
287
+ const {Dropdown, DropdownMenu, DropdownItem} = this;
288
+ <div>
289
+ <Dropdown trigger="focus">
290
+ <input ref="trigger" />
291
+ <DropdownMenu>
292
+ <DropdownItem>test1</DropdownItem>
293
+ <DropdownItem>test2</DropdownItem>
294
+ </DropdownMenu>
295
+ </Dropdown>
296
+ </div>
297
+ `;
298
+ private Dropdown = Dropdown;
299
+ private DropdownItem = DropdownItem;
300
+ private DropdownMenu = DropdownMenu;
301
+ }
302
+ const [instance] = mount(Demo);
303
+
304
+ dispatchEvent(instance.refs.trigger, 'focusin');
305
+ await wait(500);
306
+ expect(getElement('.k-dropdown-menu')).to.be.exist;
307
+
308
+ // clicking anywhere should not hide menu
309
+ dispatchEvent(document, 'click');
310
+ await wait(500);
311
+ expect(getElement('.k-dropdown-menu')).to.be.exist;
312
+
313
+ dispatchEvent(instance.refs.trigger, 'focusout');
314
+ await wait(700);
315
+ expect(getElement('.k-dropdown-menu')).to.not.be.exist;
316
+ });
283
317
  });
@@ -23,7 +23,7 @@ order: 0
23
23
  12. `min {number}`:请输入不小于n的数
24
24
  13. `range {Array<number>}`:请输入min到max之间的数
25
25
  14. `step {number}`:请输入步长为n的数
26
- 15. `equalTo {string}`:两次输入不一致
26
+ 15. `equal {string}`:两次输入不一致
27
27
  3. 给`FormItem`添加`messages`属性,指定验证失败时展示的错误提示。默认内容如上所示
28
28
  4. 给`FormItem`添加`classNames`属性,指定验证失败时错误元素需要额外添加的`className`,默认不添加
29
29
 
@@ -31,9 +31,9 @@ sidebar: doc
31
31
  | fluid | `FormItem`的宽度默认是被子元素撑开的,添加该属性可以渲染`100%`的宽度 | `boolean` | `false` |
32
32
 
33
33
  ```ts
34
- type Method = (value: any, param: any) => boolean | string
35
- type Message = string | ((value: any, param: any) => string)
36
- type ClassName = string | ((value: any, param: any) => string)
34
+ export declare type Method = (value: any, param: any) => boolean | string | Promise<boolean | string>
35
+ export declare type Message = string | ((value: any, param: any) => string)
36
+ export declare type ClassName = string | ((value: any, param: any) => string)
37
37
  ```
38
38
 
39
39
  # 扩展点
@@ -72,9 +72,12 @@ type ClassName = string | ((value: any, param: any) => string)
72
72
 
73
73
  | 方法名 | 说明 | 参数 | 返回值 |
74
74
  | --- | --- | --- | --- |
75
- | addMethod | 添加全局验证规则,这样在所有`FormItem`中如果需要使用该规则,只需要在`rules`中写上该规则名即可 | 1. `name` 指定规则名称,不能重复 <br /> 2. `method` 指定该规则的验证函数,该函数返回`true`或`false`来标识验证成功或失败,如果返回字符串,则直接当做错误文案展示,该函数将传入3个参数:1. 当前验证的值,2. 当前验证的`FormItem`实例,3. 当前规则的参数,即使用该规则时指定的值 <br /> 3. `message` 验证失败时的错误提示文案,该值可以为字符串或者函数,如果为函数,传入参数同`method`,用于个性化文案提示 <br /> 4. `className` 验证失败时添加的类名 | `undefined` |
75
+ | addMethod | 添加全局验证规则,这样在所有`FormItem`中如果需要使用该规则,只需要在`rules`中写上该规则名即可 | 1. `name` 指定规则名称,不能重复 <br /> 2. `method` 指定该规则的验证函数,该函数返回`true`或`false`来标识验证成功或失败,如果返回字符串,则直接当做错误文案展示,该函数将传入2个参数:1. 当前验证的值,2. 当前规则的参数,即使用该规则时指定的值 <br /> 3. `message` 验证失败时的错误提示文案,该值可以为字符串或者函数,如果为函数,传入参数同`method`,用于个性化文案提示 <br /> 4. `className` 验证失败时添加的类名 | `undefined` |
76
76
 
77
77
  ```ts
78
+ export declare type Method = (value: any, param: any) => boolean | string | Promise<boolean | string>
79
+ export declare type Message = string | ((value: any, param: any) => string)
80
+ export declare type ClassName = string | ((value: any, param: any) => string)
78
81
  export declare const addMethod: (
79
82
  name: string,
80
83
  method: Method,
@@ -1,7 +1,8 @@
1
1
  import {_$} from '../../i18n';
2
2
  import {isNumber, isNullOrUndefined, isString} from 'intact-shared';
3
3
 
4
- export type Method = (value: any, param: any) => boolean | string
4
+ export type MethodReturn = boolean | string
5
+ export type Method = (value: any, param: any) => MethodReturn | Promise<MethodReturn>
5
6
  export type Message = string | ((value: any, param: any) => string)
6
7
  export type ClassName = string | ((value: any, param: any) => string)
7
8
 
@@ -14,6 +14,7 @@ import {
14
14
  import {isString} from 'intact-shared';
15
15
  import {DIALOG} from './dialog/constants';
16
16
  import type {Dialog} from './dialog';
17
+ import {BaseDialog} from './dialog/base';
17
18
 
18
19
  export interface PortalProps {
19
20
  container?: Container
@@ -131,8 +132,13 @@ export class Portal<T extends PortalProps = PortalProps> extends Component<T> {
131
132
  }
132
133
  }
133
134
  if (!this.container) {
134
- // find the closest dialog if exists
135
- this.container = parentDom.closest('.k-dialog') || document.body;
135
+ if (this.$senior instanceof BaseDialog) {
136
+ // Dialog and Drawer must be inserted into document.body
137
+ this.container = document.body;
138
+ } else {
139
+ // find the closest dialog if exists
140
+ this.container = parentDom.closest('.k-dialog') || document.body;
141
+ }
136
142
 
137
143
  /**
138
144
  * @FIXME: We cannot get parent ref from sub component in Vue
@@ -34,7 +34,7 @@ import {Select, Option, Icon} from 'kpc';
34
34
  </Option>
35
35
  <b:value args="[value, label]">
36
36
  <Icon class={value} style="vertical-align: middle;" />
37
- <span class="c-middle">{value}</span>
37
+ <span class="middle">{value}</span>
38
38
  </b:value>
39
39
  </Select>
40
40
  </div>
@@ -67,8 +67,9 @@ import {Select, Option, Icon} from 'kpc';
67
67
  height 60px
68
68
  line-height 60px
69
69
  text-align center
70
- .c-middle
70
+ .middle
71
71
  margin-left 6px
72
+ vertical-align middle
72
73
  .label
73
74
  display inline-block
74
75
  width 100px
@@ -58,7 +58,7 @@ const defaults = deepDefaults(
58
58
  },
59
59
  tag: {
60
60
  margin: `3px 8px 3px 0`,
61
- padding: `5px 8px`,
61
+ padding: `3px 8px`,
62
62
  get borderRadius() { return theme.borderRadius },
63
63
  get bgColor() { return theme.color.bg },
64
64
  disabledBgColor: '#eee',
@@ -225,6 +225,7 @@ export default function makeStyles() {
225
225
  .k-select-values {
226
226
  display: inline-block;
227
227
  margin-right: -${getRight(select.tag.margin)};
228
+ width: 100%;
228
229
  &.k-with-values {
229
230
  margin: 0;
230
231
  }
@@ -236,16 +237,20 @@ export default function makeStyles() {
236
237
  background: ${select.tag.bgColor};
237
238
  border-radius: ${select.tag.borderRadius};
238
239
  margin: ${select.tag.margin};
239
- line-height: 1;
240
+ max-width: calc(100% - ${getRight(select.tag.margin)} - 1px);
241
+ }
242
+ .k-select-text {
243
+ max-width: calc(100% - 18px);
244
+ word-break: break-word;
240
245
  }
241
246
  .k-select-close {
242
247
  margin-left: ${select.tag.delete.gap};
243
248
  font-size: ${select.tag.delete.fontSize};
244
249
  color: ${select.tag.delete.color};
245
250
  }
246
- .k-select-input {
247
- margin-right: ${getRight(select.tag.margin)};
248
- }
251
+ // .k-select-input {
252
+ // margin-right: ${getRight(select.tag.margin)};
253
+ // }
249
254
 
250
255
  // size
251
256
  ${sizes.map(size => {
@@ -185,7 +185,6 @@ export class Table<
185
185
  this.scroll,
186
186
  this.width.tableRef,
187
187
  this.fixedColumns.setScrollPosition,
188
- this.width.tableWidth,
189
188
  );
190
189
 
191
190
  public checkAll() {
@@ -0,0 +1,22 @@
1
+ import {onMounted, onBeforeUnmount, RefObject, useInstance} from "intact";
2
+ import {debounce} from '../utils';
3
+ import ResizeObserver from 'resize-observer-polyfill';
4
+
5
+ export function useResizeObserver(elementRef: RefObject<HTMLElement>, callback: Function) {
6
+ const instance = useInstance()!;
7
+
8
+ let ro: ResizeObserver;
9
+ onMounted(() => {
10
+ // use debounce instead of throttle, because if there is
11
+ // transition on parent container, the width is weired
12
+ // #342
13
+ ro = new ResizeObserver(debounce(() => {
14
+ if (instance.$unmounted) return;
15
+ callback();
16
+ }, 100, true));
17
+ ro.observe(elementRef.value!);
18
+ });
19
+ onBeforeUnmount(() => {
20
+ ro.disconnect();
21
+ });
22
+ }
@@ -5,13 +5,13 @@ import type {Table} from './';
5
5
  import {isStringOrNumber, isNull} from 'intact-shared';
6
6
  import {debounce} from '../utils';
7
7
  import type {useScroll} from './useScroll';
8
+ import {useResizeObserver} from './useResizeObserver';
8
9
 
9
10
  export function useStickyScrollbar(
10
11
  elementRef: RefObject<HTMLElement>,
11
12
  {scrollRef, callbacks}: ReturnType<typeof useScroll>,
12
13
  tableRef: RefObject<HTMLElement>,
13
14
  tableScroll: (scrollLeft: number) => void,
14
- tableWidth: State<number | null>,
15
15
  ) {
16
16
  const instance = useInstance() as Table;
17
17
  const stick = useState<number | null>(null);
@@ -23,13 +23,7 @@ export function useStickyScrollbar(
23
23
  stick.set(v === true ? 0 : isStringOrNumber(v) ? +v : null);
24
24
  });
25
25
 
26
- watchState(tableWidth, v => {
27
- if (v) {
28
- tableActualWidth.set(v + 'px');
29
- } else {
30
- setTableActualWidth();
31
- }
32
- });
26
+ useResizeObserver(scrollRef, setTableActualWidth);
33
27
 
34
28
  onMounted(() => {
35
29
  setTableActualWidth();
@@ -1,10 +1,9 @@
1
- import {useInstance, RefObject, onMounted, onBeforeUnmount, VNodeComponentClass, createRef} from 'intact';
2
- import ResizeObserver from 'resize-observer-polyfill';
1
+ import {useInstance, RefObject, onMounted, VNodeComponentClass, createRef} from 'intact';
3
2
  import type {Table, TableRowKey} from './table';
4
3
  import type {TableColumn} from './column';
5
4
  import {useState} from '../../hooks/useState';
6
- import {debounce} from '../utils';
7
5
  import {scrollbarWidth} from '../position';
6
+ import {useResizeObserver} from './useResizeObserver';
8
7
 
9
8
  const hasLocalStorage = typeof localStorage !== 'undefined';
10
9
 
@@ -19,21 +18,8 @@ export function useWidth(
19
18
 
20
19
  initWidthFromStore();
21
20
 
22
- let ro: ResizeObserver;
23
- onMounted(() => {
24
- checkTableWidth(true);
25
- // use debounce instead of throttle, because if there is
26
- // transition on parent container, the width is weired
27
- // #342
28
- ro = new ResizeObserver(debounce(() => {
29
- if (instance.$unmounted) return;
30
- checkTableWidth(false);
31
- }, 100, true));
32
- ro.observe(scrollRef.value!);
33
- });
34
- onBeforeUnmount(() => {
35
- ro.disconnect();
36
- });
21
+ onMounted(() => checkTableWidth(true));
22
+ useResizeObserver(scrollRef, () => checkTableWidth(false));
37
23
 
38
24
  // if exist widthStoreKey, we get the default width from localStorage
39
25
  function initWidthFromStore() {
@@ -9,6 +9,7 @@ export class Timepicker<
9
9
  Multipe extends boolean = false,
10
10
  Range extends boolean = false,
11
11
  > extends Component<TimepickerProps<Multipe, Range>, TimepickerEvents, TimepickerBlocks<Range>> {
12
+ static $doubleVNodes = true;
12
13
  static template(this: Timepicker) {
13
14
  const props = this.get();
14
15
  if (props.step && !props.range) {
@@ -3,11 +3,11 @@ title: 触发方式
3
3
  order: 2
4
4
  ---
5
5
 
6
- 使用`trigger`指定触发方式,`click`点击触发,`hover`悬浮触发,默认为`hover`,在悬浮触发情况下,
6
+ 使用`trigger`指定触发方式,`click`点击触发,`hover`悬浮触发,`foucs`聚焦触发,默认为`hover`,在悬浮触发情况下,
7
7
  鼠标离开触发器,弹层就会消失,如果我们需要鼠标能离开触发器并悬浮在弹层上,需要添加`canHover`属性
8
8
 
9
9
  ```vdt
10
- import {Tooltip, ButtonGroup, Button} from 'kpc';
10
+ import {Tooltip, ButtonGroup, Button, Input} from 'kpc';
11
11
 
12
12
  <ButtonGroup>
13
13
  <Tooltip content="hover">
@@ -19,5 +19,8 @@ import {Tooltip, ButtonGroup, Button} from 'kpc';
19
19
  <Tooltip hoverable content="the text can be hovered">
20
20
  <Button>hoverable</Button>
21
21
  </Tooltip>
22
+ <Tooltip trigger="focus" content="foucs">
23
+ <Input placeholder="focus" />
24
+ </Tooltip>
22
25
  </ButtonGroup>
23
26
  ```
@@ -9,7 +9,7 @@ sidebar: doc
9
9
 
10
10
  | 属性 | 说明 | 类型 | 默认值 |
11
11
  | --- | --- | --- | --- |
12
- | trigger | 触发方式,`hover`为悬停触发,`click`为点击触发 | `"hover"` &#124; `"click"` | `"hover"` |
12
+ | trigger | 触发方式,`hover`为悬停触发,`click`为点击触发 | `"hover"` &#124; `"click"` &#124; `"focus"` | `"hover"` |
13
13
  | disabled | 是否禁用整个菜单 | `boolean` | `false` |
14
14
  | value | 是否将弹出菜单展示出来,可通过`v-model`双向绑定 | `boolean` | `false` |
15
15
  | position | 菜单弹出的位置,默认在触发器正上方向上偏移`10px`的地方 | `Position` &#124; `"left"` &#124; `"bottom"` &#124; `"right"` &#124; `"top"` | `{my: 'center bottom-10', at: 'center top', collision: 'flipfit'}` |
@@ -43,7 +43,7 @@ setDefault(function () {
43
43
  }).cascader;
44
44
  });
45
45
  export function makeMenuStyles() {
46
- return /*#__PURE__*/css("min-width:", cascader.width, "!important;height:", cascader.height, ";.k-cascader-arrow{float:right;height:100%;margin-left:", cascader.arrowGap, ";line-height:inherit;}.k-cascader-loading{display:block;text-align:center;margin-top:", cascader.loadingGap, ";}.k-cascader-empty{padding:", cascader.empty.padding, ";color:", cascader.empty.color, ";text-align:center;}.k-cascader-option{&.k-selected{color:", cascader.selectedColor, ";}&.k-active{background:", cascader.activeBgColor, ";}}");
46
+ return /*#__PURE__*/css("min-width:", cascader.width, "!important;min-height:", cascader.height, ";.k-cascader-arrow{float:right;height:100%;margin-left:", cascader.arrowGap, ";line-height:inherit;}.k-cascader-loading{display:block;text-align:center;margin-top:", cascader.loadingGap, ";}.k-cascader-empty{padding:", cascader.empty.padding, ";color:", cascader.empty.color, ";text-align:center;}.k-cascader-option{&.k-selected{color:", cascader.selectedColor, ";}&.k-active{background:", cascader.activeBgColor, ";}}");
47
47
  }
48
48
  export function makeFilterMenuStyles() {
49
49
  return /*#__PURE__*/css("min-width:", _filterInstanceProperty(cascader).minWidth, "!important;height:auto;max-height:", _filterInstanceProperty(cascader).maxHeight, ";em{font-style:normal;color:", _filterInstanceProperty(cascader).highlightColor, ";}");
@@ -1,9 +1,14 @@
1
+ import _inheritsLoose from "@babel/runtime-corejs3/helpers/inheritsLoose";
1
2
  import _asyncToGenerator from "@babel/runtime-corejs3/helpers/asyncToGenerator";
3
+ import _concatInstanceProperty from "@babel/runtime-corejs3/core-js/instance/concat";
2
4
  import _regeneratorRuntime from "@babel/runtime-corejs3/regenerator";
3
5
  import BasicDemo from '~/components/drawer/demos/basic';
4
6
  import PlacementDemo from '~/components/drawer/demos/placement';
5
7
  import overlayDemo from '~/components/drawer/demos/overlay';
6
8
  import { mount, unmount, dispatchEvent, getElement, wait } from '../../test/utils';
9
+ import { Component } from 'intact';
10
+ import { Drawer } from '.';
11
+ import { Dialog } from '../dialog';
7
12
  describe('Drawer', function () {
8
13
  afterEach(function (done) {
9
14
  unmount();
@@ -159,4 +164,47 @@ describe('Drawer', function () {
159
164
  }
160
165
  }, _callee4);
161
166
  })));
167
+ it('nested dialog', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
168
+ var Demo, _mount4, instance, element;
169
+
170
+ return _regeneratorRuntime.wrap(function _callee5$(_context6) {
171
+ while (1) {
172
+ switch (_context6.prev = _context6.next) {
173
+ case 0:
174
+ Demo = /*#__PURE__*/function (_Component) {
175
+ _inheritsLoose(Demo, _Component);
176
+
177
+ function Demo() {
178
+ var _context5;
179
+
180
+ var _this;
181
+
182
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
183
+ args[_key] = arguments[_key];
184
+ }
185
+
186
+ _this = _Component.call.apply(_Component, _concatInstanceProperty(_context5 = [this]).call(_context5, args)) || this;
187
+ _this.Dialog = Dialog;
188
+ _this.Drawer = Drawer;
189
+ return _this;
190
+ }
191
+
192
+ return Demo;
193
+ }(Component);
194
+
195
+ Demo.template = "\n const {Dialog, Drawer} = this;\n <Drawer value={true}>\n <Dialog value={true} ref=\"dialog\">Dialog</Dialog>\n </Drawer>\n ";
196
+ _mount4 = mount(Demo), instance = _mount4[0], element = _mount4[1];
197
+ _context6.next = 5;
198
+ return wait();
199
+
200
+ case 5:
201
+ expect(instance.refs.dialog.dialogRef.value.parentElement.parentElement).to.eql(document.body);
202
+
203
+ case 6:
204
+ case "end":
205
+ return _context6.stop();
206
+ }
207
+ }
208
+ }, _callee5);
209
+ })));
162
210
  });
@@ -8,7 +8,7 @@ export declare type PositionShorthand = 'left' | 'bottom' | 'right' | 'top';
8
8
  export declare const DROPDOWN = "Dropdown";
9
9
  export declare const ROOT_DROPDOWN = "RootDropdown";
10
10
  export interface DropdownProps {
11
- trigger?: 'hover' | 'click' | 'contextmenu';
11
+ trigger?: 'hover' | 'click' | 'contextmenu' | 'focus';
12
12
  disabled?: boolean;
13
13
  value?: boolean;
14
14
  position?: Position | 'left' | 'bottom' | 'right' | 'top';
@@ -52,6 +52,7 @@ export declare class Dropdown<T extends DropdownProps = DropdownProps, E extends
52
52
  private onEnter;
53
53
  private onContextMenu;
54
54
  private onLeave;
55
+ private initEventCallbacks;
55
56
  private callOriginalCallback;
56
57
  private normalizeTriggerProps;
57
58
  }
@@ -14,7 +14,7 @@ import { usePosition } from './usePosition';
14
14
  export var DROPDOWN = 'Dropdown';
15
15
  export var ROOT_DROPDOWN = 'RootDropdown';
16
16
  var typeDefs = {
17
- trigger: ['hover', 'click', 'contextmenu'],
17
+ trigger: ['hover', 'click', 'contextmenu', 'focus'],
18
18
  disabled: Boolean,
19
19
  value: Boolean,
20
20
  position: [Object, 'left', 'bottom', 'right', 'top'],
@@ -154,6 +154,33 @@ export var Dropdown = /*#__PURE__*/function (_Component) {
154
154
  this.hide();
155
155
  };
156
156
 
157
+ _proto.initEventCallbacks = function initEventCallbacks(trigger) {
158
+ var props = {};
159
+
160
+ switch (trigger) {
161
+ case 'focus':
162
+ props['ev-focusin'] = this.onEnter;
163
+ props['ev-focusout'] = this.onLeave;
164
+ break;
165
+
166
+ case 'contextmenu':
167
+ props['ev-contextmenu'] = this.onContextMenu;
168
+ break;
169
+
170
+ default:
171
+ props['ev-click'] = this.onEnter;
172
+
173
+ if (trigger === 'hover') {
174
+ props['ev-mouseenter'] = this.onEnter;
175
+ props['ev-mouseleave'] = this.onLeave;
176
+ }
177
+
178
+ break;
179
+ }
180
+
181
+ return props;
182
+ };
183
+
157
184
  _proto.callOriginalCallback = function callOriginalCallback(name, e) {
158
185
  var callback = this.triggerProps[name];
159
186
  var callbackOnDropdown = this.get(name);
@@ -229,19 +256,7 @@ Dropdown.template = function () {
229
256
  trigger = _children[0],
230
257
  menu = _children[1];
231
258
  var triggerType = this.get('trigger');
232
- var props = {};
233
-
234
- if (triggerType !== 'contextmenu') {
235
- props['ev-click'] = this.onEnter;
236
-
237
- if (triggerType === 'hover') {
238
- props['ev-mouseenter'] = this.onEnter;
239
- props['ev-mouseleave'] = this.onLeave;
240
- }
241
- } else {
242
- props['ev-contextmenu'] = this.onContextMenu;
243
- }
244
-
259
+ var props = this.initEventCallbacks(triggerType);
245
260
  var clonedTrigger = isTextChildren(trigger) ? createVNode('span', null, trigger) : directClone(trigger);
246
261
  var triggerProps = this.triggerProps = this.normalizeTriggerProps(trigger.props || EMPTY_OBJ); // add a className for opening status
247
262
 
@@ -275,7 +290,9 @@ function useDocumentClickForDropdown(dropdown) {
275
290
  var _useDocumentClick = useDocumentClick(elementRef, function (e) {
276
291
  // case 1: if click an trigger and the trigger type is hover, ignore it
277
292
  // case 2: if right click on trigger and the trigger type is contextmenu, ignore it
293
+ // case 3: if click on trigger and the trigger type is focus, do nothing
278
294
  var trigger = dropdown.get('trigger');
295
+ if (trigger === 'focus') return;
279
296
  var isHover = trigger === 'hover';
280
297
 
281
298
  if (isHover || trigger === 'contextmenu') {