@king-design/intact 2.0.17-beta.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/components/cascader/index.md +18 -0
  2. package/components/cascader/index.spec.ts +56 -0
  3. package/components/cascader/index.ts +35 -12
  4. package/components/cascader/index.vdt +9 -8
  5. package/components/cascader/useFields.ts +22 -0
  6. package/components/cascader/useFilterable.ts +23 -8
  7. package/components/cascader/useLabel.ts +7 -4
  8. package/components/cascader/useLoad.ts +4 -2
  9. package/components/code/demos/basic.md +1 -1
  10. package/components/colorpicker/index.md +16 -0
  11. package/components/colorpicker/index.ts +4 -0
  12. package/components/colorpicker/index.vdt +3 -2
  13. package/components/datepicker/index.md +11 -0
  14. package/components/dialog/index.spec.ts +2 -2
  15. package/components/dropdown/dropdown.ts +34 -71
  16. package/components/dropdown/index.spec.ts +53 -4
  17. package/components/dropdown/item.ts +18 -7
  18. package/components/dropdown/menu.ts +3 -3
  19. package/components/dropdown/usePosition.ts +12 -1
  20. package/components/editable/index.ts +17 -3
  21. package/components/editable/index.vdt +1 -0
  22. package/components/input/demos/autoRows.md +44 -0
  23. package/components/input/demos/password.md +12 -0
  24. package/components/input/demos/textarea.md +2 -2
  25. package/components/input/index.md +1 -0
  26. package/components/input/index.spec.ts +97 -1
  27. package/components/input/index.ts +17 -3
  28. package/components/input/index.vdt +29 -6
  29. package/components/input/styles.ts +18 -1
  30. package/components/input/useAutoRows.ts +65 -0
  31. package/components/input/useAutoWidth.ts +12 -3
  32. package/components/input/useShowPassword.ts +27 -0
  33. package/components/menu/demos/collapse.md +1 -1
  34. package/components/menu/index.spec.ts +9 -1
  35. package/components/menu/item.ts +7 -0
  36. package/components/pagination/index.spec.ts +24 -1
  37. package/components/pagination/index.ts +2 -1
  38. package/components/portal.ts +4 -4
  39. package/components/position.ts +5 -1
  40. package/components/select/base.ts +3 -1
  41. package/components/select/base.vdt +2 -0
  42. package/components/select/index.md +11 -1
  43. package/components/table/cell.ts +4 -5
  44. package/components/table/demos/hideHeader.md +33 -0
  45. package/components/table/demos/pagination.md +53 -0
  46. package/components/table/index.md +22 -0
  47. package/components/table/index.spec.ts +73 -1
  48. package/components/table/row.ts +3 -3
  49. package/components/table/styles.ts +5 -0
  50. package/components/table/table.ts +29 -4
  51. package/components/table/table.vdt +21 -3
  52. package/components/table/useChecked.ts +21 -6
  53. package/components/table/useDisableRow.ts +3 -2
  54. package/components/table/useDraggable.ts +11 -8
  55. package/components/table/useGroup.ts +2 -0
  56. package/components/table/useMerge.ts +6 -3
  57. package/components/table/usePagination.ts +71 -0
  58. package/components/table/useRestRowStatus.ts +4 -1
  59. package/components/table/useTree.ts +4 -3
  60. package/components/timepicker/index.md +11 -0
  61. package/components/tooltip/content.ts +15 -1
  62. package/components/tooltip/content.vdt +6 -1
  63. package/components/tooltip/demos/trigger.md +1 -1
  64. package/components/tooltip/index.md +1 -1
  65. package/components/tooltip/index.spec.ts +65 -6
  66. package/components/tooltip/styles.ts +1 -1
  67. package/components/tooltip/tooltip.ts +8 -0
  68. package/components/treeSelect/index.md +9 -0
  69. package/components/virtual.ts +98 -0
  70. package/es/components/cascader/index.d.ts +22 -11
  71. package/es/components/cascader/index.js +9 -12
  72. package/es/components/cascader/index.spec.js +81 -0
  73. package/es/components/cascader/index.vdt.js +10 -8
  74. package/es/components/cascader/useFields.d.ts +2 -0
  75. package/es/components/cascader/useFields.js +18 -0
  76. package/es/components/cascader/useFilterable.d.ts +2 -1
  77. package/es/components/cascader/useFilterable.js +17 -6
  78. package/es/components/cascader/useLabel.d.ts +2 -1
  79. package/es/components/cascader/useLabel.js +4 -4
  80. package/es/components/cascader/useLoad.d.ts +2 -1
  81. package/es/components/cascader/useLoad.js +9 -7
  82. package/es/components/colorpicker/index.d.ts +2 -0
  83. package/es/components/colorpicker/index.js +7 -2
  84. package/es/components/colorpicker/index.vdt.js +3 -6
  85. package/es/components/dialog/index.spec.js +2 -2
  86. package/es/components/dropdown/dropdown.d.ts +6 -5
  87. package/es/components/dropdown/dropdown.js +40 -69
  88. package/es/components/dropdown/index.spec.js +96 -17
  89. package/es/components/dropdown/item.d.ts +1 -1
  90. package/es/components/dropdown/item.js +19 -7
  91. package/es/components/dropdown/usePosition.js +11 -2
  92. package/es/components/editable/index.d.ts +1 -0
  93. package/es/components/editable/index.js +20 -6
  94. package/es/components/editable/index.vdt.js +2 -1
  95. package/es/components/input/index.d.ts +10 -2
  96. package/es/components/input/index.js +10 -3
  97. package/es/components/input/index.spec.js +169 -1
  98. package/es/components/input/index.vdt.js +26 -7
  99. package/es/components/input/styles.js +8 -3
  100. package/es/components/input/useAutoRows.d.ts +2 -0
  101. package/es/components/input/useAutoRows.js +79 -0
  102. package/es/components/input/useAutoWidth.js +13 -3
  103. package/es/components/input/useShowPassword.d.ts +7 -0
  104. package/es/components/input/useShowPassword.js +31 -0
  105. package/es/components/menu/index.spec.js +26 -15
  106. package/es/components/menu/item.d.ts +2 -0
  107. package/es/components/menu/item.js +5 -0
  108. package/es/components/pagination/index.js +2 -1
  109. package/es/components/pagination/index.spec.js +51 -4
  110. package/es/components/portal.d.ts +6 -2
  111. package/es/components/portal.js +4 -3
  112. package/es/components/position.js +2 -1
  113. package/es/components/select/base.d.ts +2 -1
  114. package/es/components/select/base.js +3 -1
  115. package/es/components/select/base.vdt.js +3 -1
  116. package/es/components/table/cell.js +1 -6
  117. package/es/components/table/index.spec.js +130 -19
  118. package/es/components/table/row.d.ts +1 -1
  119. package/es/components/table/row.js +2 -1
  120. package/es/components/table/styles.js +1 -1
  121. package/es/components/table/table.d.ts +15 -0
  122. package/es/components/table/table.js +16 -7
  123. package/es/components/table/table.vdt.js +20 -6
  124. package/es/components/table/useChecked.d.ts +3 -2
  125. package/es/components/table/useChecked.js +23 -12
  126. package/es/components/table/useDisableRow.d.ts +2 -1
  127. package/es/components/table/useDisableRow.js +4 -4
  128. package/es/components/table/useDraggable.d.ts +3 -2
  129. package/es/components/table/useDraggable.js +11 -8
  130. package/es/components/table/useGroup.js +3 -0
  131. package/es/components/table/useMerge.d.ts +2 -1
  132. package/es/components/table/useMerge.js +5 -4
  133. package/es/components/table/usePagination.d.ts +8 -0
  134. package/es/components/table/usePagination.js +81 -0
  135. package/es/components/table/useTree.d.ts +2 -1
  136. package/es/components/table/useTree.js +3 -4
  137. package/es/components/tooltip/content.d.ts +1 -0
  138. package/es/components/tooltip/content.js +18 -1
  139. package/es/components/tooltip/content.vdt.js +3 -1
  140. package/es/components/tooltip/index.spec.js +117 -10
  141. package/es/components/tooltip/styles.d.ts +22 -0
  142. package/es/components/tooltip/styles.js +1 -1
  143. package/es/components/tooltip/tooltip.d.ts +1 -0
  144. package/es/components/tooltip/tooltip.js +11 -0
  145. package/es/components/virtual.d.ts +8 -0
  146. package/es/components/virtual.js +126 -0
  147. package/es/index.d.ts +3 -3
  148. package/es/index.js +3 -3
  149. package/es/packages/kpc-react/__tests__/components/cascader.spec.d.ts +1 -0
  150. package/es/packages/kpc-react/__tests__/components/cascader.spec.js +79 -0
  151. package/es/site/data/components/input/demos/autoRows/index.d.ts +9 -0
  152. package/es/site/data/components/input/demos/autoRows/index.js +24 -0
  153. package/es/site/data/components/input/demos/autoRows/react.d.ts +8 -0
  154. package/es/site/data/components/input/demos/autoRows/react.js +62 -0
  155. package/es/site/data/components/input/demos/password/index.d.ts +5 -0
  156. package/es/site/data/components/input/demos/password/index.js +17 -0
  157. package/es/site/data/components/input/demos/password/react.d.ts +5 -0
  158. package/es/site/data/components/input/demos/password/react.js +41 -0
  159. package/es/site/data/components/input/demos/textarea/react.js +4 -2
  160. package/es/site/data/components/menu/demos/collapse/index.js +1 -1
  161. package/es/site/data/components/menu/demos/collapse/react.js +1 -1
  162. package/es/site/data/components/table/demos/hideHeader/index.d.ts +12 -0
  163. package/es/site/data/components/table/demos/hideHeader/index.js +30 -0
  164. package/es/site/data/components/table/demos/hideHeader/react.d.ts +11 -0
  165. package/es/site/data/components/table/demos/hideHeader/react.js +60 -0
  166. package/es/site/data/components/table/demos/pagination/index.d.ts +12 -0
  167. package/es/site/data/components/table/demos/pagination/index.js +35 -0
  168. package/es/site/data/components/table/demos/pagination/react.d.ts +16 -0
  169. package/es/site/data/components/table/demos/pagination/react.js +65 -0
  170. package/es/styles/fonts/ionicons.js +1 -1
  171. package/index.ts +3 -3
  172. package/package.json +5 -4
  173. package/styles/fonts/ionicons.ts +0 -1
@@ -0,0 +1,71 @@
1
+ import {useInstance, createRef} from 'intact';
2
+ import type {Table, TableRowKey, TableCheckType} from './table';
3
+ import {useState} from '../../hooks/useState';
4
+ import {Pagination, PaginationChangeData} from '../pagination';
5
+ import {isObject} from 'intact-shared';
6
+ import { useReceive } from '../../hooks/useReceive';
7
+
8
+ const defaultPagination = Pagination.defaults();
9
+
10
+ export function usePagination() {
11
+ const instance = useInstance() as Table<any, TableRowKey, TableCheckType>
12
+ const data = useState<any[] | undefined>(instance.get('data'));
13
+ const value = useState<number>(defaultPagination.value!);
14
+ const limit = useState<number>(defaultPagination.limit!);
15
+ const paginationRef = createRef<Pagination>(); // for unit test
16
+
17
+ useReceive<Table>(['data', 'pagination'], () => {
18
+ handleData();
19
+ });
20
+
21
+ function handleData() {
22
+ let { data: _data, pagination } = instance.get();
23
+
24
+ if (!_data) {
25
+ data.set(undefined);
26
+ return;
27
+ }
28
+
29
+ if (!pagination) {
30
+ data.set(_data);
31
+ return;
32
+ }
33
+
34
+ if (isObject(pagination)) {
35
+ if (pagination.value) {
36
+ value.set(pagination.value);
37
+ }
38
+ if (pagination.limit) {
39
+ limit.set(pagination.limit);
40
+ }
41
+ }
42
+
43
+ updateDataByPage();
44
+ }
45
+
46
+ function updateDataByPage() {
47
+ const { data: _data } = instance.get();
48
+ const index = (value.value - 1) * limit.value;
49
+ data.set(_data!.slice(index, index + limit.value));
50
+ }
51
+
52
+ function onChange(data: PaginationChangeData) {
53
+ const { pagination } = instance.get();
54
+
55
+ value.set(data.value);
56
+ limit.set(data.limit);
57
+ updateDataByPage();
58
+
59
+ if (isObject(pagination)) {
60
+ instance.set('pagination', {
61
+ ...pagination,
62
+ value: value.value,
63
+ limit: limit.value,
64
+ });
65
+ }
66
+
67
+ instance.trigger('changePage', data);
68
+ }
69
+
70
+ return { data, value, limit, onChange, paginationRef };
71
+ }
@@ -29,7 +29,10 @@ export function useRestRowStatus(
29
29
  }
30
30
  }
31
31
 
32
- function omit(type: 'checkedKeys' | 'selectedKeys' | 'spreadKeys' | 'expandedKeys', keys: TableRowKey[]) {
32
+ function omit(
33
+ type: 'checkedKeys' | 'selectedKeys' | 'spreadKeys' | 'expandedKeys',
34
+ keys: TableRowKey[]
35
+ ) {
33
36
  let originKeys = instance.get(type);
34
37
  if (!originKeys) return;
35
38
 
@@ -2,8 +2,9 @@ import {useInstance} from 'intact';
2
2
  import type {Table, TableRowKey} from './table';
3
3
  import {inArray} from './useChecked';
4
4
  import {toggleArray} from '../utils';
5
+ import { State } from '../../hooks/useState';
5
6
 
6
- export function useTree() {
7
+ export function useTree(data: State<any[] | undefined>) {
7
8
  const instance = useInstance() as Table;
8
9
 
9
10
  function isSpreaded(key: TableRowKey) {
@@ -18,8 +19,8 @@ export function useTree() {
18
19
  cb: (value: any, index: number, level: number, meta: T | null) => T,
19
20
  shouldBreak: boolean = false,
20
21
  ) {
21
- const {childrenKey, data} = instance.get();
22
- loopDataWithChildrenKey(data, childrenKey, cb, shouldBreak);
22
+ const {childrenKey} = instance.get();
23
+ loopDataWithChildrenKey(data.value, childrenKey, cb, shouldBreak);
23
24
  }
24
25
 
25
26
  return {isSpreaded, toggleSpreadRow, loopData};
@@ -29,12 +29,23 @@ sidebar: doc
29
29
  | min | 最小可选时间 | `Value` | `undefind` |
30
30
  | disabledDate | 该属性值是一个函数,用于定义那些日期被禁止选择,函数参数为日期字符串,返回`true`则表示禁用该日期 | `(v: Dayjs) => boolean` | `undefined` |
31
31
  | step | 固定时间点的步长 | `string` | `undefined` |
32
+ | position | 菜单弹出的位置,默认与触发器左侧对齐向下偏移`8px`的地方 | `Position` &#124; `"left"` &#124; `"bottom"` &#124; `"right"` &#124; `"top"` | `{my: 'left top+8', 'left bottom'}` |
32
33
 
33
34
  ```ts
34
35
  import {Dayjs} from 'dayjs';
35
36
  import {VNode} from 'intact';
36
37
 
37
38
  export type Value = string | Date | number | Dayjs;
39
+
40
+ type Position = {
41
+ my?: string | [string, string]
42
+ at?: string | [string, string]
43
+ collision?: Collision | [Collision, Collision]
44
+ collisionDirection?: ['left'] | ['top'] | ['left', 'top']
45
+ }
46
+
47
+ type Collision = 'fit' | 'flip' | 'flipfit' | 'none'
48
+
38
49
  export type Container = string | ((parentDom: Element, anchor: Node | null) => Element)
39
50
  ```
40
51
 
@@ -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>
@@ -4,7 +4,7 @@ order: 2
4
4
  ---
5
5
 
6
6
  使用`trigger`指定触发方式,`click`点击触发,`hover`悬浮触发,`foucs`聚焦触发,默认为`hover`,在悬浮触发情况下,
7
- 鼠标离开触发器,弹层就会消失,如果我们需要鼠标能离开触发器并悬浮在弹层上,需要添加`canHover`属性
7
+ 鼠标离开触发器,弹层就会消失,如果我们需要鼠标能离开触发器并悬浮在弹层上,需要添加`hoverable`属性
8
8
 
9
9
  ```vdt
10
10
  import {Tooltip, ButtonGroup, Button, Input} from 'kpc';
@@ -21,7 +21,7 @@ sidebar: doc
21
21
  | always | 是否一直保持当前展示/隐藏状态 | `boolean` | `false` |
22
22
  | size | 弹层尺寸 | `"default"` &#124; `"small"` | `"default"` |
23
23
  | confirm | 带“确认”和“取消”按钮的确认弹层 | `boolean` | `false` |
24
- | onText | `confirm`模式下的“确认”按钮文案 | `string` | `"确认"` |
24
+ | okText | `confirm`模式下的“确认”按钮文案 | `string` | `"确认"` |
25
25
  | cancelText | `confirm`模式下的“取消”按钮文案 | `string` | `"取消"` |
26
26
  | content | 指定提示的内容,当然你也可以用`content`扩展点指定 | `string` &#124; `VNode` | `undefined` |
27
27
 
@@ -6,8 +6,9 @@ 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';
11
12
 
12
13
  describe('Tooltip', () => {
13
14
  afterEach((done) => {
@@ -330,16 +331,19 @@ describe('Tooltip', () => {
330
331
  static defaults = () => ({show: false});
331
332
  Tooltip = Tooltip;
332
333
  mounted() {
333
- const element = findDomFromVNode(this.$lastInput!, true) as Element;
334
- const windowHeight = window.innerHeight || document.documentElement.clientHeight;
335
- (element.parentNode as HTMLElement).style.height = `${windowHeight * 2}px`;
334
+ const element = findDomFromVNode(this.$lastInput!, true) as HTMLElement;
335
+ const style = element.style;
336
+ style.position = 'fixed';
337
+ style.top = '-200px';
338
+ // const windowHeight = window.innerHeight || document.documentElement.clientHeight;
339
+ // (element.parentNode as HTMLElement).style.height = `${windowHeight * 2}px`;
336
340
  }
337
341
  }
338
342
 
339
343
  const [i] = mount(Demo);
340
344
 
341
- await wait(500);
342
- window.scrollTo(0, 10000);
345
+ // await wait(500);
346
+ // window.scrollTo(0, 10000);
343
347
 
344
348
  i.set('show', true);
345
349
 
@@ -349,4 +353,59 @@ describe('Tooltip', () => {
349
353
  console.log(JSON.stringify(content.getBoundingClientRect()));
350
354
  expect(content.getBoundingClientRect().top < 0).to.be.true;
351
355
  });
356
+
357
+ it('should add className', async () => {
358
+ class Demo extends Component {
359
+ static template = `
360
+ const Tooltip = this.Tooltip;
361
+ <div>
362
+ <Tooltip content="hello" class="a">
363
+ <div ref="test" class="b">test</div>
364
+ </Tooltip>
365
+ </div>
366
+ `;
367
+ Tooltip = Tooltip;
368
+ }
369
+
370
+ const [instance, element] = mount(Demo);
371
+ const trigger = instance.refs.test;
372
+ expect(trigger.className).to.eql('b a');
373
+
374
+ dispatchEvent(trigger, 'mouseenter');
375
+ await wait();
376
+ const dropdown = getElement('.k-tooltip-content')!;
377
+ expect(dropdown.classList.contains('a')).to.be.true;
378
+ });
379
+
380
+ it('should fix the width in small container', async () => {
381
+ class Demo extends Component {
382
+ static template = `
383
+ const {Tooltip, Dialog} = this;
384
+ <div style="text-align: right; position: relative; width: 300px;">
385
+ <Tooltip content="这是一段很长的描述文字,这是一段很长的描述文字" container={dom => dom}>
386
+ <span class="trigger">test</span>
387
+ </Tooltip>
388
+ </div>
389
+ `
390
+ private Tooltip = Tooltip;
391
+ private Dialog = Dialog;
392
+ }
393
+
394
+ const [instance, element] = mount(Demo);
395
+ const trigger = element.querySelector<HTMLDivElement>('.trigger')!;
396
+ const expecedWidth = parseInt(tooltipTheme.maxWidth);
397
+
398
+ dispatchEvent(trigger, 'mouseenter');
399
+ await wait();
400
+ const content = getElement('.k-tooltip-content')!;
401
+ const width = content.offsetWidth;
402
+ expect(width).to.eql(expecedWidth);
403
+
404
+ dispatchEvent(trigger, 'mouseleave');
405
+ await wait();
406
+ dispatchEvent(trigger, 'mouseenter');
407
+ await wait();
408
+ const newWidth = content.offsetWidth;
409
+ expect(newWidth).to.eql(width);
410
+ });
352
411
  });
@@ -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,6 +73,13 @@ 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
 
@@ -33,6 +33,7 @@ sidebar: doc
33
33
  | checkbox | 是否展示复选框 | `boolean` | `false` |
34
34
  | filter | 当支持筛选时,可以自定义筛选规则 | `(keywords: string, data: TreeDataItem<K>) => boolean` | `undefined` |
35
35
  | show | 是否展示菜单项 | `boolean` | `false` |
36
+ | position | 菜单弹出的位置,默认与触发器左侧对齐向下偏移`8px`的地方 | `Position` &#124; `"left"` &#124; `"bottom"` &#124; `"right"` &#124; `"top"` | `{my: 'left top+8', 'left bottom'}` |
36
37
 
37
38
  ```ts
38
39
  import {Key, Children} from 'intact';
@@ -47,6 +48,14 @@ export type TreeDataItem<K extends Key> = {
47
48
  children?: TreeDataItem<K>[]
48
49
  }
49
50
 
51
+ type Position = {
52
+ my?: string | [string, string]
53
+ at?: string | [string, string]
54
+ collision?: Collision | [Collision, Collision]
55
+ collisionDirection?: ['left'] | ['top'] | ['left', 'top']
56
+ }
57
+
58
+ type Collision = 'fit' | 'flip' | 'flipfit' | 'none'
50
59
  ```
51
60
 
52
61
  # 扩展点
@@ -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
+ }
@@ -1,28 +1,39 @@
1
1
  import { TypeDefs } from 'intact';
2
2
  import { BaseSelect, BaseSelectProps, BaseSelectEvents, BaseSelectBlocks } from '../select/base';
3
- export interface CascaderProps<V = any, Multipe extends boolean = boolean> extends BaseSelectProps<V[], Multipe> {
4
- data?: CascaderData<V>[];
3
+ export interface CascaderProps<V = any, Multipe extends boolean = boolean, Data extends BaseCascaderData = CascaderData<V>> extends BaseSelectProps<V[], Multipe> {
4
+ data?: Data[];
5
5
  trigger?: 'click' | 'hover';
6
6
  changeOnSelect?: boolean;
7
7
  format?: (labels: string[]) => string;
8
- loadData?: (data: CascaderData<V>) => any;
9
- filter?: (keywords: string, data: CascaderData<V>) => boolean;
8
+ loadData?: (data: Data) => any;
9
+ filter?: (keywords: string, data: Data) => boolean;
10
+ fields?: CascaderFields<Data>;
10
11
  }
11
- export declare type CascaderData<V> = {
12
+ export declare type CascaderFields<Data> = {
13
+ value?: keyof Data;
14
+ label?: keyof Data;
15
+ children?: keyof Data;
16
+ disabled?: keyof Data;
17
+ };
18
+ export interface BaseCascaderData {
19
+ loaded?: boolean;
20
+ [key: string]: any;
21
+ }
22
+ export interface CascaderData<V> extends BaseCascaderData {
12
23
  value: V;
13
24
  label: string;
14
- disabled?: boolean;
15
- loaded?: boolean;
16
25
  children?: CascaderData<V>[];
17
- };
26
+ disabled?: boolean;
27
+ }
18
28
  export interface CascaderEvents extends BaseSelectEvents {
19
29
  }
20
30
  export interface CascaderBlocks<V> extends BaseSelectBlocks<V> {
21
31
  }
22
- export declare class Cascader<V = any, Multipe extends boolean = false> extends BaseSelect<CascaderProps<V, Multipe>, CascaderEvents, CascaderBlocks<V>> {
32
+ export declare class Cascader<V = any, Multipe extends boolean = false, Data extends BaseCascaderData = CascaderData<V>> extends BaseSelect<CascaderProps<V, Multipe, Data>, CascaderEvents, CascaderBlocks<V>> {
23
33
  static template: string | import("intact").Template<any>;
24
- static typeDefs: Required<TypeDefs<CascaderProps<any, boolean>>>;
25
- static defaults: () => Partial<CascaderProps<any, boolean>>;
34
+ static typeDefs: Required<TypeDefs<CascaderProps<any, boolean, CascaderData<any>>>>;
35
+ static defaults: () => Partial<CascaderProps<any, boolean, CascaderData<any>>>;
36
+ private fields;
26
37
  private value;
27
38
  private label;
28
39
  private load;
@@ -1,6 +1,5 @@
1
1
  import _inheritsLoose from "@babel/runtime-corejs3/helpers/inheritsLoose";
2
2
  import _extends from "@babel/runtime-corejs3/helpers/extends";
3
- import _includesInstanceProperty from "@babel/runtime-corejs3/core-js/instance/includes";
4
3
  import _concatInstanceProperty from "@babel/runtime-corejs3/core-js/instance/concat";
5
4
  import template from './index.vdt';
6
5
  import { BaseSelect } from '../select/base';
@@ -10,6 +9,7 @@ import { useValue } from './useValue';
10
9
  import { useLabel } from './useLabel';
11
10
  import { useLoad } from './useLoad';
12
11
  import { useFilterable } from './useFilterable';
12
+ import { useFields } from './useFields';
13
13
 
14
14
  var typeDefs = _extends({}, BaseSelect.typeDefs, {
15
15
  data: Array,
@@ -17,7 +17,8 @@ var typeDefs = _extends({}, BaseSelect.typeDefs, {
17
17
  changeOnSelect: Boolean,
18
18
  format: Function,
19
19
  loadData: Function,
20
- filter: Function
20
+ filter: Function,
21
+ fields: Object
21
22
  });
22
23
 
23
24
  var defaults = function defaults() {
@@ -26,11 +27,6 @@ var defaults = function defaults() {
26
27
  trigger: 'click',
27
28
  format: function format(labels) {
28
29
  return labels.join(' / ');
29
- },
30
- filter: function filter(keywords, data) {
31
- var _context;
32
-
33
- return _includesInstanceProperty(_context = data.label).call(_context, keywords);
34
30
  }
35
31
  });
36
32
  };
@@ -39,7 +35,7 @@ export var Cascader = /*#__PURE__*/function (_BaseSelect) {
39
35
  _inheritsLoose(Cascader, _BaseSelect);
40
36
 
41
37
  function Cascader() {
42
- var _context2;
38
+ var _context;
43
39
 
44
40
  var _this;
45
41
 
@@ -47,11 +43,12 @@ export var Cascader = /*#__PURE__*/function (_BaseSelect) {
47
43
  args[_key] = arguments[_key];
48
44
  }
49
45
 
50
- _this = _BaseSelect.call.apply(_BaseSelect, _concatInstanceProperty(_context2 = [this]).call(_context2, args)) || this;
46
+ _this = _BaseSelect.call.apply(_BaseSelect, _concatInstanceProperty(_context = [this]).call(_context, args)) || this;
47
+ _this.fields = useFields();
51
48
  _this.value = useValue();
52
- _this.label = useLabel();
53
- _this.load = useLoad();
54
- _this.filterable = useFilterable(_this.input.keywords, _this.value.setValue);
49
+ _this.label = useLabel(_this.fields);
50
+ _this.load = useLoad(_this.fields);
51
+ _this.filterable = useFilterable(_this.input.keywords, _this.value.setValue, _this.fields);
55
52
  _this.positionObj = {
56
53
  my: 'left top',
57
54
  at: 'right top',
@@ -366,4 +366,85 @@ describe('Cascader', function () {
366
366
  }
367
367
  }, _callee8);
368
368
  })));
369
+ it('specify fields', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee9() {
370
+ var Demo, _mount8, instance, element, select, dropdown1, _dropdown1$querySelec5, item1, dropdown2, _dropdown2$querySelec4, item11;
371
+
372
+ return _regeneratorRuntime.wrap(function _callee9$(_context11) {
373
+ while (1) {
374
+ switch (_context11.prev = _context11.next) {
375
+ case 0:
376
+ Demo = /*#__PURE__*/function (_Component2) {
377
+ _inheritsLoose(Demo, _Component2);
378
+
379
+ function Demo() {
380
+ var _context10;
381
+
382
+ var _this2;
383
+
384
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
385
+ args[_key2] = arguments[_key2];
386
+ }
387
+
388
+ _this2 = _Component2.call.apply(_Component2, _concatInstanceProperty(_context10 = [this]).call(_context10, args)) || this;
389
+ _this2.Cascader = Cascader;
390
+ return _this2;
391
+ }
392
+
393
+ Demo.defaults = function defaults() {
394
+ return {
395
+ value: [],
396
+ data: [{
397
+ v: 'beijing',
398
+ l: '北京',
399
+ c: [{
400
+ v: 'haidian',
401
+ l: '海淀区'
402
+ }]
403
+ }, {
404
+ v: 'hunan',
405
+ l: '湖南',
406
+ c: [{
407
+ v: 'haidian',
408
+ l: '海淀区'
409
+ }]
410
+ }]
411
+ };
412
+ };
413
+
414
+ return Demo;
415
+ }(Component);
416
+
417
+ Demo.template = "\n const {Cascader} = this;\n <Cascader data={this.get('data')}\n v-model=\"value\"\n fields={{value: 'v', label: 'l', children: 'c'}}\n />\n ";
418
+ _mount8 = mount(Demo), instance = _mount8[0], element = _mount8[1];
419
+ select = element;
420
+ select.click();
421
+ _context11.next = 7;
422
+ return wait();
423
+
424
+ case 7:
425
+ dropdown1 = getElement('.k-cascader-menu');
426
+ _dropdown1$querySelec5 = dropdown1.querySelectorAll(':scope > .k-dropdown-item'), item1 = _dropdown1$querySelec5[0];
427
+ item1.click();
428
+ _context11.next = 12;
429
+ return wait();
430
+
431
+ case 12:
432
+ expect(dropdown1.innerHTML).to.matchSnapshot();
433
+ dropdown2 = getElement('.k-cascader-menu');
434
+ _dropdown2$querySelec4 = dropdown2.querySelectorAll(':scope > .k-dropdown-item'), item11 = _dropdown2$querySelec4[0];
435
+ item11.click();
436
+ _context11.next = 18;
437
+ return wait();
438
+
439
+ case 18:
440
+ expect(element.innerHTML).to.matchSnapshot();
441
+ expect(instance.get('value')).to.eql(['beijing', 'haidian']);
442
+
443
+ case 20:
444
+ case "end":
445
+ return _context11.stop();
446
+ }
447
+ }
448
+ }, _callee9);
449
+ })));
369
450
  });