@king-design/intact 2.0.0 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -118
- package/components/cascader/index.spec.ts +59 -0
- package/components/cascader/index.vdt +4 -4
- package/components/cascader/useLabel.ts +9 -9
- package/components/datepicker/index.vdt +7 -6
- package/components/dropdown/dropdown.ts +7 -6
- package/components/form/index.spec.ts +1 -1
- package/components/menu/demos/collapse.md +3 -1
- package/components/menu/index.spec.ts +10 -4
- package/components/menu/item.ts +5 -4
- package/components/menu/item.vdt +3 -3
- package/components/menu/menu.ts +4 -0
- package/components/menu/useExpanded.ts +1 -1
- package/components/menu/useHighlight.ts +45 -40
- package/components/portal.ts +1 -1
- package/components/skeleton/demos/animate.md +30 -0
- package/components/skeleton/demos/avator.md +30 -0
- package/components/skeleton/demos/basic.md +30 -0
- package/components/skeleton/demos/custom.md +39 -0
- package/components/skeleton/demos/rows.md +32 -0
- package/components/skeleton/index.md +24 -0
- package/components/skeleton/index.ts +2 -0
- package/components/skeleton/item.ts +30 -0
- package/components/skeleton/item.vdt +28 -0
- package/components/skeleton/skeleton.ts +33 -0
- package/components/skeleton/skeleton.vdt +32 -0
- package/components/skeleton/style.ts +105 -0
- package/components/tooltip/index.spec.ts +6 -1
- package/components/transfer/styles.ts +2 -8
- package/components/tree/useFilter.ts +1 -2
- package/es/components/cascader/index.spec.js +88 -0
- package/es/components/cascader/index.vdt.js +4 -4
- package/es/components/cascader/useLabel.js +8 -12
- package/es/components/datepicker/index.vdt.js +10 -5
- package/es/components/diagram/index.d.ts +1 -1
- package/es/components/dropdown/dropdown.js +8 -7
- package/es/components/form/index.spec.js +2 -4
- package/es/components/menu/index.spec.js +13 -6
- package/es/components/menu/item.d.ts +0 -1
- package/es/components/menu/item.js +6 -4
- package/es/components/menu/item.vdt.js +4 -4
- package/es/components/menu/menu.d.ts +3 -0
- package/es/components/menu/menu.js +4 -0
- package/es/components/menu/useExpanded.d.ts +1 -4
- package/es/components/menu/useHighlight.d.ts +5 -8
- package/es/components/menu/useHighlight.js +44 -33
- package/es/components/portal.js +1 -1
- package/es/components/skeleton/index.d.ts +2 -0
- package/es/components/skeleton/index.js +2 -0
- package/es/components/skeleton/item.d.ts +16 -0
- package/es/components/skeleton/item.js +26 -0
- package/es/components/skeleton/item.vdt.js +35 -0
- package/es/components/skeleton/skeleton.d.ts +17 -0
- package/es/components/skeleton/skeleton.js +30 -0
- package/es/components/skeleton/skeleton.vdt.js +37 -0
- package/es/components/skeleton/style.d.ts +6 -0
- package/es/components/skeleton/style.js +35 -0
- package/es/components/steps/context.d.ts +2 -2
- package/es/components/tooltip/index.spec.js +4 -1
- package/es/components/transfer/styles.js +2 -6
- package/es/components/tree/useFilter.js +1 -2
- package/es/i18n/en-US.d.ts +1 -0
- package/es/i18n/en-US.js +1 -0
- package/es/index.d.ts +3 -2
- package/es/index.js +3 -2
- package/es/packages/kpc-react/__tests__/components/form.spec.d.ts +1 -0
- package/es/packages/kpc-react/__tests__/components/form.spec.js +46 -0
- package/es/site/data/components/menu/demos/collapse/index.js +1 -0
- package/es/site/data/components/menu/demos/collapse/react.d.ts +1 -1
- package/es/site/data/components/menu/demos/collapse/react.js +7 -0
- package/es/site/data/components/menu/demos/size/react.d.ts +1 -1
- package/es/site/data/components/skeleton/demos/animate/index.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/animate/index.js +23 -0
- package/es/site/data/components/skeleton/demos/animate/react.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/animate/react.js +38 -0
- package/es/site/data/components/skeleton/demos/avator/index.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/avator/index.js +23 -0
- package/es/site/data/components/skeleton/demos/avator/react.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/avator/react.js +37 -0
- package/es/site/data/components/skeleton/demos/basic/index.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/basic/index.js +23 -0
- package/es/site/data/components/skeleton/demos/basic/react.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/basic/react.js +36 -0
- package/es/site/data/components/skeleton/demos/custom/index.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/custom/index.js +23 -0
- package/es/site/data/components/skeleton/demos/custom/react.d.ts +11 -0
- package/es/site/data/components/skeleton/demos/custom/react.js +60 -0
- package/es/site/data/components/skeleton/demos/rows/index.d.ts +13 -0
- package/es/site/data/components/skeleton/demos/rows/index.js +24 -0
- package/es/site/data/components/skeleton/demos/rows/react.d.ts +13 -0
- package/es/site/data/components/skeleton/demos/rows/react.js +38 -0
- package/es/site/data/components/skeleton/index.d.ts +57 -0
- package/es/site/data/components/skeleton/index.js +42 -0
- package/es/site/src/client.js +4 -1
- package/es/site/src/components/footer/styles.js +1 -1
- package/es/site/src/pages/colorProcess/index.d.ts +21 -0
- package/es/site/src/pages/colorProcess/index.js +79 -0
- package/es/site/src/pages/colorProcess/style.d.ts +3 -0
- package/es/site/src/pages/colorProcess/style.js +53 -0
- package/es/site/src/pages/font/index.d.ts +12 -0
- package/es/site/src/pages/font/index.js +22 -0
- package/es/site/src/pages/font/styles.d.ts +1 -0
- package/es/site/src/pages/font/styles.js +9 -0
- package/es/site/src/pages/iframe/colorProcess/styles.js +2 -2
- package/es/site/src/pages/index/BestPractice/styles.js +1 -1
- package/es/site/src/pages/index/ColorProcess/styles.js +2 -2
- package/es/site/src/pages/index/KingVersion/styles.js +1 -1
- package/es/site/src/pages/index/NewFunction/index.d.ts +2 -0
- package/es/site/src/pages/index/NewFunction/index.js +8 -2
- package/es/site/src/pages/index/NewFunction/styles.js +1 -1
- package/es/site/src/pages/index/styles.js +2 -1
- package/es/site/src/pages/layout.d.ts +1 -0
- package/es/site/src/pages/layout.js +9 -1
- package/es/site/src/pages/resource/index.d.ts +1 -0
- package/es/site/src/pages/resource/index.js +7 -4
- package/es/site/src/pages/solution/index.js +1 -2
- package/es/site/src/pages/styles.js +2 -2
- package/es/site/src/router/index.js +75 -5
- package/i18n/en-US.ts +1 -0
- package/index.ts +3 -2
- package/package.json +5 -4
- package/es/components/cascader/index.d.ts +0 -34
- package/es/components/datepicker/index.d.ts +0 -63
- package/es/components/select/select.d.ts +0 -33
- package/es/components/timepicker/panelPicker.d.ts +0 -54
- package/es/components/treeSelect/index.d.ts +0 -27
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
<a href="https://
|
|
4
|
-
<img src="/site/src/imgs/
|
|
3
|
+
<a href="https://design.ksyun.com" rel="nofollow">
|
|
4
|
+
<img src="/site/src/imgs/header_logo_x2.png" alt="LOGO" />
|
|
5
5
|
</a>
|
|
6
6
|
|
|
7
7
|
<p></p>
|
|
8
8
|
|
|
9
9
|
[](https://github.com/ksc-fe/kpc/actions?query=workflow%3A%22Node.js+CI%22)
|
|
10
10
|
[](https://codecov.io/gh/ksc-fe/kpc/branch/master)
|
|
11
|
-
[](https://cdn.jsdelivr.net/npm/kpc/dist/)
|
|
11
|
+
[](https://www.npmjs.com/package/@king-design/vue)
|
|
13
12
|
|
|
14
|
-
[](https://www.npmjs.com/package/@king-design/react)
|
|
14
|
+
[](https://www.npmjs.com/package/@king-design/vue)
|
|
15
|
+
[](https://www.npmjs.com/package/@king-design/vue-legacy)
|
|
16
16
|
|
|
17
17
|
</div>
|
|
18
18
|
|
|
@@ -20,11 +20,11 @@ English | [简体中文](./README-zh_CN.md)
|
|
|
20
20
|
|
|
21
21
|
## Features
|
|
22
22
|
|
|
23
|
-
* Support multiple frameworks: [Intact][1] / [Vue][2] / [React][3]
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Support multiple frameworks: [Intact][1] / [Vue][2] / [React][3].
|
|
24
|
+
* Support TypeScript.
|
|
25
|
+
* Change theme on runtime.
|
|
26
26
|
* Declarative form validation.
|
|
27
|
-
* Excellent [documents](https://
|
|
27
|
+
* Excellent [documents](https://design.ksyun.com) and design
|
|
28
28
|
* 90% coverage unit tests.
|
|
29
29
|
|
|
30
30
|
## Browsers Support
|
|
@@ -38,7 +38,11 @@ English | [简体中文](./README-zh_CN.md)
|
|
|
38
38
|
### Installation
|
|
39
39
|
|
|
40
40
|
```shell
|
|
41
|
-
|
|
41
|
+
# Vue3
|
|
42
|
+
npm install @king-design/vue --save
|
|
43
|
+
|
|
44
|
+
# Vue2
|
|
45
|
+
npm install @king-desing/vue-legacy --save
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
### Usage
|
|
@@ -48,7 +52,7 @@ npm install kpc-vue --save
|
|
|
48
52
|
<Button>Hello</Button>
|
|
49
53
|
</template>
|
|
50
54
|
<script>
|
|
51
|
-
import {Button} from '
|
|
55
|
+
import {Button} from '@king-design/vue';
|
|
52
56
|
|
|
53
57
|
export default {
|
|
54
58
|
components: {
|
|
@@ -63,114 +67,16 @@ export default {
|
|
|
63
67
|
### Installation
|
|
64
68
|
|
|
65
69
|
```shell
|
|
66
|
-
npm install
|
|
70
|
+
npm install @king-design/react--save
|
|
67
71
|
```
|
|
68
72
|
|
|
69
73
|
### Usage
|
|
70
74
|
|
|
71
75
|
```jsx
|
|
72
|
-
import
|
|
73
|
-
import {Button} from 'kpc-react';
|
|
74
|
-
|
|
75
|
-
class App extends React.Component {
|
|
76
|
-
render() {
|
|
77
|
-
return <Button>Hello</Button>
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Intact
|
|
83
|
-
|
|
84
|
-
### Installation
|
|
85
|
-
|
|
86
|
-
```shell
|
|
87
|
-
npm install kpc --save
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### Usage
|
|
91
|
-
|
|
92
|
-
```js
|
|
93
|
-
import {Button} from 'kpc';
|
|
94
|
-
|
|
95
|
-
<Button>Hello</Button>
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Angular
|
|
99
|
-
|
|
100
|
-
Read [more][5]
|
|
76
|
+
import {Button} from '@king-design/react';
|
|
101
77
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```shell
|
|
105
|
-
npm install kpc-angular -S
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### Configure `webpack.config.js`
|
|
109
|
-
|
|
110
|
-
You need use `@angular-builders/custom-webapck` to configure webpack, if your project initialized by Angular CLI.
|
|
111
|
-
|
|
112
|
-
```js
|
|
113
|
-
const path = require('path');
|
|
114
|
-
|
|
115
|
-
module.exports = function(config) {
|
|
116
|
-
config.module.rules.find(rule => {
|
|
117
|
-
if (rule.test.toString() === '/\\.css$/') {
|
|
118
|
-
rule.exclude.push(path.resolve(__dirname, 'node_modules/kpc-angular'));
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
return config;
|
|
124
|
-
};
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Usage
|
|
128
|
-
|
|
129
|
-
`src/app/app.module.ts`
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
import { KpcBrowserModule, KpcModule } from 'kpc-angular';
|
|
133
|
-
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
134
|
-
|
|
135
|
-
import { AppRoutingModule } from './app-routing.module';
|
|
136
|
-
import { AppComponent } from './app.component';
|
|
137
|
-
|
|
138
|
-
@NgModule({
|
|
139
|
-
declarations: [
|
|
140
|
-
AppComponent
|
|
141
|
-
],
|
|
142
|
-
imports: [
|
|
143
|
-
KpcBrowserModule,
|
|
144
|
-
AppRoutingModule,
|
|
145
|
-
KpcModule,
|
|
146
|
-
],
|
|
147
|
-
providers: [],
|
|
148
|
-
bootstrap: [AppComponent],
|
|
149
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
150
|
-
})
|
|
151
|
-
export class AppModule { }
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
```ts
|
|
155
|
-
import { Component, ViewEncapsulation } from '@angular/core';
|
|
156
|
-
import { MessageComponent } from 'kpc-angular';
|
|
157
|
-
|
|
158
|
-
@Component({
|
|
159
|
-
selector: 'app-root',
|
|
160
|
-
template: `
|
|
161
|
-
<k-button type="primary" (click)="onClick()">Hello World</k-button>
|
|
162
|
-
`,
|
|
163
|
-
style: `
|
|
164
|
-
.k-button {
|
|
165
|
-
margin: 10px;
|
|
166
|
-
}
|
|
167
|
-
`,
|
|
168
|
-
encapsulation: ViewEncapsulation.None,
|
|
169
|
-
})
|
|
170
|
-
export class AppComponent {
|
|
171
|
-
onClick() {
|
|
172
|
-
MessageComponent.success('Welcome to kpc world!');
|
|
173
|
-
}
|
|
78
|
+
function App() {
|
|
79
|
+
return <Button>Hello</Button>
|
|
174
80
|
}
|
|
175
81
|
```
|
|
176
82
|
|
|
@@ -187,10 +93,6 @@ Welcome to join us by QQ. Group Number: 529739732
|
|
|
187
93
|
|
|
188
94
|
* [KPC Document](https://design.ksyun.com)
|
|
189
95
|
* [Intact MVVM Framework][1]
|
|
190
|
-
* [Vdt Template Engine](http://javey.github.io/vdt.js/)
|
|
191
|
-
* [Intact-Vue Compatibility Layer](https://github.com/Javey/intact-vue)
|
|
192
|
-
* [Intact-React Compatibility Layer](https://github.com/ksc-fe/intact-react)
|
|
193
|
-
* [Intact-Angular Compatibility Layer](https://github.com/ksc-fe/intact-angular)
|
|
194
96
|
|
|
195
97
|
## Develop
|
|
196
98
|
|
|
@@ -5,6 +5,7 @@ import LoadDataDemo from '~/components/cascader/demos/loadData';
|
|
|
5
5
|
import FilterDemo from '~/components/cascader/demos/filterable';
|
|
6
6
|
import {mount, unmount, dispatchEvent, getElement, getElements, wait} from '../../test/utils';
|
|
7
7
|
import {Cascader} from './';
|
|
8
|
+
import {Component} from 'intact';
|
|
8
9
|
|
|
9
10
|
describe('Cascader', () => {
|
|
10
11
|
afterEach(async () => {
|
|
@@ -146,4 +147,62 @@ describe('Cascader', () => {
|
|
|
146
147
|
expect(dropdown.innerHTML).to.matchSnapshot();
|
|
147
148
|
expect(dropdown.innerText).to.eql('无数据');
|
|
148
149
|
});
|
|
150
|
+
|
|
151
|
+
it('duplicated sub data', async () => {
|
|
152
|
+
class Demo extends Component {
|
|
153
|
+
static template = `const {Cascader} = this; <Cascader data={this.get('data')} v-model="value" />`;
|
|
154
|
+
static defaults() {
|
|
155
|
+
return {
|
|
156
|
+
value: ['beijing', 'haidian'],
|
|
157
|
+
data: [
|
|
158
|
+
{
|
|
159
|
+
value: 'beijing',
|
|
160
|
+
label: '北京',
|
|
161
|
+
children: [
|
|
162
|
+
{
|
|
163
|
+
value: 'haidian',
|
|
164
|
+
label: '海淀区'
|
|
165
|
+
},
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
value: 'hunan',
|
|
170
|
+
label: '湖南',
|
|
171
|
+
children: [
|
|
172
|
+
{
|
|
173
|
+
value: 'haidian',
|
|
174
|
+
label: '海淀区'
|
|
175
|
+
},
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
private Cascader = Cascader;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const [instance, element] = mount(Demo);
|
|
185
|
+
dispatchEvent(element, 'click');
|
|
186
|
+
await wait();
|
|
187
|
+
|
|
188
|
+
const [dropdown1, dropdown2] = getElements('.k-cascader-menu');
|
|
189
|
+
const [item1, item2] = dropdown1.querySelectorAll(':scope > .k-dropdown-item');
|
|
190
|
+
expect(item1.classList.contains('k-selected')).to.be.true;
|
|
191
|
+
expect(item2.classList.contains('k-selected')).to.be.false;
|
|
192
|
+
const [item21] = dropdown2.querySelectorAll(':scope > .k-dropdown-item');
|
|
193
|
+
expect(item21.classList.contains('k-selected')).to.be.true;
|
|
194
|
+
|
|
195
|
+
dispatchEvent(item2, 'click');
|
|
196
|
+
await wait();
|
|
197
|
+
|
|
198
|
+
const dropdown3 = getElement('.k-cascader-menu')!;
|
|
199
|
+
const [item31] = dropdown3.querySelectorAll(':scope > .k-dropdown-item');
|
|
200
|
+
expect(item31.classList.contains('k-selected')).to.be.false;
|
|
201
|
+
|
|
202
|
+
dispatchEvent(item31, 'click');
|
|
203
|
+
await wait();
|
|
204
|
+
|
|
205
|
+
expect(instance.get('value')).to.eql(['hunan', 'haidian']);
|
|
206
|
+
expect(element.textContent).to.eql('湖南 / 海淀区');
|
|
207
|
+
});
|
|
149
208
|
});
|
|
@@ -11,7 +11,7 @@ const classNameObj = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
const {values, isShowed, isSelected, onSelect, toggleShowedValue} = this.value;
|
|
14
|
-
const Options = (data, level, loaded) => {
|
|
14
|
+
const Options = (data, level, loaded, parentSelected) => {
|
|
15
15
|
if (!data.length) {
|
|
16
16
|
if (!loaded) {
|
|
17
17
|
return <Icon class="ion-load-c k-cascader-loading" rotate />
|
|
@@ -23,7 +23,7 @@ const Options = (data, level, loaded) => {
|
|
|
23
23
|
return data.map((item, index) => {
|
|
24
24
|
const value = item.value;
|
|
25
25
|
const showed = isShowed(value, level);
|
|
26
|
-
const selected = isSelected(value, level);
|
|
26
|
+
const selected = parentSelected && isSelected(value, level);
|
|
27
27
|
const children = item.children;
|
|
28
28
|
|
|
29
29
|
const Item = () => {
|
|
@@ -58,7 +58,7 @@ const Options = (data, level, loaded) => {
|
|
|
58
58
|
>
|
|
59
59
|
{Item()}
|
|
60
60
|
<DropdownMenu class={classNameObj}>
|
|
61
|
-
{showed ? Options(children, level + 1, item.loaded) : null}
|
|
61
|
+
{showed ? Options(children, level + 1, item.loaded, selected) : null}
|
|
62
62
|
</DropdownMenu>
|
|
63
63
|
</Dropdown> :
|
|
64
64
|
Item()
|
|
@@ -74,7 +74,7 @@ const {filter, keywords: {value: keywords}, selectByFilter} = this.filterable;
|
|
|
74
74
|
class={classNameObj}
|
|
75
75
|
key="common"
|
|
76
76
|
>
|
|
77
|
-
{Options(data, 0, true)}
|
|
77
|
+
{Options(data, 0, true, true)}
|
|
78
78
|
</DropdownMenu>
|
|
79
79
|
<DropdownMenu v-else
|
|
80
80
|
key="filter"
|
|
@@ -14,23 +14,23 @@ export function useLabel() {
|
|
|
14
14
|
const {format} = instance.get();
|
|
15
15
|
const labels: string[] = [];
|
|
16
16
|
const length = value.length;
|
|
17
|
-
const loop = (data: CascaderStringData[]) => {
|
|
17
|
+
const loop = (data: CascaderStringData[], level: number) => {
|
|
18
|
+
if (level === length) return;
|
|
19
|
+
|
|
18
20
|
for (let i = 0; i < data.length; i++) {
|
|
19
21
|
const item = data[i];
|
|
20
|
-
if (
|
|
22
|
+
if (item.value === value[level]) {
|
|
21
23
|
labels.push(item.label);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
|
|
25
|
+
const children = item.children;
|
|
26
|
+
if (children) {
|
|
27
|
+
loop(children, level + 1);
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
|
-
const children = item.children;
|
|
27
|
-
if (children) {
|
|
28
|
-
loop(children);
|
|
29
|
-
}
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
loop(data);
|
|
33
|
+
loop(data, 0);
|
|
34
34
|
|
|
35
35
|
return labels.length ? format!(labels) : null;
|
|
36
36
|
}
|
|
@@ -76,12 +76,13 @@ const generatePanel = (flag) => {
|
|
|
76
76
|
<b:base-menu>
|
|
77
77
|
<DropdownMenu class={classNameObj}>
|
|
78
78
|
<div class="k-datepicker-shortcuts" v-if={shortcuts && shortcuts.length}>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
{shortcuts.map($value => {
|
|
80
|
+
const label = isFunction($value.label) ? $value.label() : $value.label;
|
|
81
|
+
return <div class="k-datepicker-shortcut c-ellipsis"
|
|
82
|
+
title={label}
|
|
83
|
+
ev-click={linkEvent($value, this.setByShortcut)}
|
|
84
|
+
>{label}</div>
|
|
85
|
+
})}
|
|
85
86
|
</div>
|
|
86
87
|
<div class="k-datepicker-wrapper">
|
|
87
88
|
<div class="k-datepicker-calendars">
|
|
@@ -244,11 +244,15 @@ export class Dropdown<
|
|
|
244
244
|
|
|
245
245
|
private normalizeTriggerProps(props: any) {
|
|
246
246
|
// if use kpc in react or vue, normalize props by Wrapper.props.vnode;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
if (!vnode) return props;
|
|
247
|
+
const vnode = props.vnode;
|
|
248
|
+
if (!vnode) return props;
|
|
250
249
|
|
|
250
|
+
// maybe we render the intact component in react slot property, in this case
|
|
251
|
+
// the $isReact is false. so use the vnode $$typeof field as gauge
|
|
252
|
+
if (vnode.$$typeof || (this as any).$isVueNext) {
|
|
251
253
|
const _props = vnode.props;
|
|
254
|
+
if (!_props) return props;
|
|
255
|
+
|
|
252
256
|
return {
|
|
253
257
|
vnode,
|
|
254
258
|
'ev-click': _props.onClick,
|
|
@@ -258,9 +262,6 @@ export class Dropdown<
|
|
|
258
262
|
className: _props.className || _props.class /* vue-next */,
|
|
259
263
|
};
|
|
260
264
|
} else if ((this as any).$isVue) {
|
|
261
|
-
const vnode = props.vnode;
|
|
262
|
-
if (!vnode) return props;
|
|
263
|
-
|
|
264
265
|
const data = vnode.data;
|
|
265
266
|
const on = data && data.on || EMPTY_OBJ;
|
|
266
267
|
const ret: Record<string, any> = {vnode};
|
|
@@ -21,7 +21,7 @@ RemoteDemo.prototype.validateUserName = function(value) {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
describe('Form', () => {
|
|
24
|
-
afterEach(() => unmount());
|
|
24
|
+
// afterEach(() => unmount());
|
|
25
25
|
|
|
26
26
|
it('validate', async () => {
|
|
27
27
|
const [instance, element] = mount(BasicDemo, null, basicDemoData);
|
|
@@ -24,7 +24,8 @@ import {Menu, MenuItem, Switch, Icon} from 'kpc';
|
|
|
24
24
|
falseValue="dark"
|
|
25
25
|
/>
|
|
26
26
|
<br /><br />
|
|
27
|
-
<Menu v-model:expandedKeys="expandedKeys"
|
|
27
|
+
<Menu v-model:expandedKeys="expandedKeys"
|
|
28
|
+
v-model:selectedKey="selectedKey"
|
|
28
29
|
collapse={this.get('collapse')}
|
|
29
30
|
theme={this.get('theme')}
|
|
30
31
|
ref="__test"
|
|
@@ -62,6 +63,7 @@ export default class extends Component<Props> {
|
|
|
62
63
|
static defaults() {
|
|
63
64
|
return {
|
|
64
65
|
expandedKeys: ['3'],
|
|
66
|
+
selectedKey: '3-2',
|
|
65
67
|
collapse: false,
|
|
66
68
|
theme: 'dark'
|
|
67
69
|
} as MenuProps;
|
|
@@ -22,23 +22,29 @@ describe('Menu', () => {
|
|
|
22
22
|
|
|
23
23
|
it('select', async () => {
|
|
24
24
|
const [instance, element] = mount(CollapseDemo);
|
|
25
|
-
|
|
25
|
+
|
|
26
|
+
expect(element.innerHTML).to.matchSnapshot();
|
|
26
27
|
|
|
27
28
|
const [title, disabledTitle] = element.querySelectorAll<HTMLElement>('.k-menu-title');
|
|
28
29
|
title.click();
|
|
29
30
|
await wait();
|
|
30
31
|
expect(element.outerHTML).to.matchSnapshot();
|
|
31
|
-
expect(
|
|
32
|
+
expect(instance.get('selectedKey')).to.eql('1');
|
|
32
33
|
disabledTitle.click();
|
|
33
34
|
await wait();
|
|
34
35
|
expect(element.outerHTML).to.matchSnapshot();
|
|
35
|
-
expect(
|
|
36
|
+
expect(instance.get('selectedKey')).to.eql('1');
|
|
36
37
|
|
|
37
38
|
const subTitle = element.querySelector('.k-expanded .k-menu .k-menu-title') as HTMLElement;
|
|
38
39
|
subTitle.click();
|
|
39
40
|
await wait();
|
|
40
41
|
expect(element.outerHTML).to.matchSnapshot();
|
|
41
|
-
expect(
|
|
42
|
+
expect(instance.get('selectedKey')).to.eql('3-1');
|
|
43
|
+
|
|
44
|
+
// clear
|
|
45
|
+
instance.set('selectedKey', '');
|
|
46
|
+
await wait();
|
|
47
|
+
expect(element.querySelector('.k-highlighted')).to.be.null;
|
|
42
48
|
});
|
|
43
49
|
|
|
44
50
|
it('collapse', async () => {
|
package/components/menu/item.ts
CHANGED
|
@@ -4,10 +4,11 @@ import {Dropdown, DropdownMenu} from '../dropdown';
|
|
|
4
4
|
import template from './item.vdt';
|
|
5
5
|
import {bind} from '../utils';
|
|
6
6
|
import {useState} from '../../hooks/useState';
|
|
7
|
-
import {useHighlight} from './useHighlight';
|
|
8
7
|
import {useExpanded} from './useExpanded';
|
|
9
8
|
import {useDropdown} from './useDropdown';
|
|
10
9
|
import {useRouter, navigate} from '../../hooks/useRouter';
|
|
10
|
+
import {useRecordItem} from '../../hooks/useRecordComponent';
|
|
11
|
+
import {MENU_RECORD_KEY} from './useHighlight';
|
|
11
12
|
|
|
12
13
|
export interface MenuItemProps {
|
|
13
14
|
key: Key
|
|
@@ -42,23 +43,23 @@ export class MenuItem extends Component<MenuItemProps, MenuItemEvents> {
|
|
|
42
43
|
public parentMenuItem = inject<MenuItem | null>(MENU_ITEM, null);
|
|
43
44
|
|
|
44
45
|
private expanded = useExpanded(this.rootMenu, this.parentMenu);
|
|
45
|
-
private highlight = useHighlight(this.rootMenu, this.parentMenuItem);
|
|
46
46
|
private dropdown = useDropdown(this.rootMenu, this.parentMenu);
|
|
47
47
|
private router = useRouter();
|
|
48
48
|
|
|
49
49
|
init() {
|
|
50
50
|
provide(MENU_ITEM, this);
|
|
51
|
+
useRecordItem(MENU_RECORD_KEY);
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
@bind
|
|
54
55
|
public onClick(hasSubMenu: Menu, e: MouseEvent) {
|
|
55
|
-
const {disabled, to} = this.get();
|
|
56
|
+
const {disabled, to, key} = this.get();
|
|
56
57
|
if (disabled) return;
|
|
57
58
|
|
|
58
59
|
if (hasSubMenu) {
|
|
59
60
|
this.expanded.toggle();
|
|
60
61
|
} else {
|
|
61
|
-
this.highlight
|
|
62
|
+
this.rootMenu.highlight!.select(key);
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
this.trigger('click', e);
|
package/components/menu/item.vdt
CHANGED
|
@@ -10,7 +10,7 @@ import {makeItemStyles, makeTitleStyles} from './styles';
|
|
|
10
10
|
const rootMenu = this.rootMenu;
|
|
11
11
|
const {theme, type, dot: rootDot} = rootMenu.get();
|
|
12
12
|
const {children, key, className, disabled, dot} = this.get();
|
|
13
|
-
const {isHighlighted, isSelected} =
|
|
13
|
+
const {isHighlighted, isSelected} = rootMenu.highlight;
|
|
14
14
|
const {isExpanded: isExpandedKey} = this.expanded;
|
|
15
15
|
const isExpanded = isExpandedKey(key);
|
|
16
16
|
const {
|
|
@@ -23,8 +23,8 @@ const classNameObj = {
|
|
|
23
23
|
[className]: className,
|
|
24
24
|
'k-expanded': isExpanded,
|
|
25
25
|
'k-disabled': disabled,
|
|
26
|
-
'k-active': isSelected(),
|
|
27
|
-
'k-highlighted': isHighlighted(),
|
|
26
|
+
'k-active': isSelected(key),
|
|
27
|
+
'k-highlighted': isHighlighted(key),
|
|
28
28
|
[makeItemStyles()]: true,
|
|
29
29
|
};
|
|
30
30
|
|
package/components/menu/menu.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {Component, TypeDefs, provide, inject, Key} from 'intact';
|
|
2
2
|
import template from './menu.vdt';
|
|
3
|
+
import {useHighlight} from './useHighlight';
|
|
3
4
|
|
|
4
5
|
export interface MenuProps<K extends Key = Key> {
|
|
5
6
|
expandedKeys?: K[]
|
|
@@ -46,6 +47,8 @@ export class Menu<K extends Key = Key> extends Component<MenuProps<K>, MenuEvent
|
|
|
46
47
|
|
|
47
48
|
public rootMenu = inject<Menu | null>(ROOT_MENU, null);
|
|
48
49
|
public parentMenu = inject<Menu | null>(MENU, null);
|
|
50
|
+
public subExpandedKeys?: Set<K>;
|
|
51
|
+
public highlight?: ReturnType<typeof useHighlight>;
|
|
49
52
|
|
|
50
53
|
init() {
|
|
51
54
|
provide(MENU, this);
|
|
@@ -53,6 +56,7 @@ export class Menu<K extends Key = Key> extends Component<MenuProps<K>, MenuEvent
|
|
|
53
56
|
// is root menu or not
|
|
54
57
|
if (!this.rootMenu) {
|
|
55
58
|
provide(ROOT_MENU, this);
|
|
59
|
+
this.highlight = useHighlight();
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -3,7 +3,7 @@ import type {Menu, MenuItem} from './';
|
|
|
3
3
|
import {inArray, addOrRemove} from '../table/useChecked';
|
|
4
4
|
import {isDropdown} from './useDropdown';
|
|
5
5
|
|
|
6
|
-
export function useExpanded(rootMenu: Menu, parentMenu: Menu
|
|
6
|
+
export function useExpanded(rootMenu: Menu, parentMenu: Menu) {
|
|
7
7
|
const instance = useInstance() as MenuItem;
|
|
8
8
|
|
|
9
9
|
onBeforeUnmount(removeSubExpandedKey);
|
|
@@ -1,52 +1,57 @@
|
|
|
1
|
-
import {useInstance,
|
|
1
|
+
import {useInstance, Key} from 'intact';
|
|
2
2
|
import type {Menu, MenuItem} from './';
|
|
3
|
+
import {useRecordParent} from '../../hooks/useRecordComponent';
|
|
3
4
|
import {inArray} from '../table/useChecked';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
)
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
updateStatus(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
5
|
+
import {useState} from '../../hooks/useState';
|
|
6
|
+
|
|
7
|
+
export const MENU_RECORD_KEY = 'MenuKeys';
|
|
8
|
+
|
|
9
|
+
export function useHighlight() {
|
|
10
|
+
const instance = useInstance() as Menu;
|
|
11
|
+
const menuItems = useRecordParent<MenuItem>(MENU_RECORD_KEY);
|
|
12
|
+
const highlightedKeys = useState<Key[]>([]);
|
|
13
|
+
|
|
14
|
+
instance.watch('selectedKey', updateStatus, {presented: true});
|
|
15
|
+
|
|
16
|
+
function updateStatus(newValue: Key | undefined) {
|
|
17
|
+
for (let i = 0; i < menuItems.length; i++) {
|
|
18
|
+
const menuItem = menuItems[i];
|
|
19
|
+
const key = menuItem.get('key');
|
|
20
|
+
|
|
21
|
+
if (newValue !== key) continue;
|
|
22
|
+
|
|
23
|
+
const items = [];
|
|
24
|
+
let parentItem = menuItem.parentMenuItem;
|
|
25
|
+
while (parentItem) {
|
|
26
|
+
items.push(parentItem);
|
|
27
|
+
parentItem = parentItem.parentMenuItem;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const expandedKeys = new Set(instance.get('expandedKeys'));
|
|
31
|
+
highlightedKeys.set(items.map(item => {
|
|
32
|
+
const key = item.get('key');
|
|
33
|
+
expandedKeys.add(key);
|
|
34
|
+
return key;
|
|
35
|
+
}));
|
|
36
|
+
instance.set('expandedKeys', Array.from(expandedKeys))
|
|
37
|
+
|
|
38
|
+
return;
|
|
27
39
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const highlightedKeys = items.map(item => {
|
|
31
|
-
const key = item.get('key');
|
|
32
|
-
expandedKeys.add(key);
|
|
33
|
-
return key;
|
|
34
|
-
});
|
|
35
|
-
rootMenu.highlightedKeys = highlightedKeys;
|
|
36
|
-
rootMenu.set('expandedKeys', Array.from(expandedKeys))
|
|
40
|
+
|
|
41
|
+
highlightedKeys.set([]);
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
function isHighlighted() {
|
|
40
|
-
return inArray(
|
|
44
|
+
function isHighlighted(key: Key) {
|
|
45
|
+
return inArray(highlightedKeys.value, key);
|
|
41
46
|
}
|
|
42
47
|
|
|
43
|
-
function select() {
|
|
44
|
-
|
|
48
|
+
function select(key: Key) {
|
|
49
|
+
instance.set('selectedKey', key);
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
function isSelected() {
|
|
48
|
-
return
|
|
52
|
+
function isSelected(key: Key) {
|
|
53
|
+
return instance.get('selectedKey') === key;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
|
-
return {isHighlighted,
|
|
56
|
+
return {isHighlighted, select, isSelected};
|
|
52
57
|
}
|
package/components/portal.ts
CHANGED
|
@@ -100,7 +100,7 @@ export class Portal<T extends PortalProps = PortalProps> extends Component<T> {
|
|
|
100
100
|
}
|
|
101
101
|
} else {
|
|
102
102
|
mountedQueue.push(() => {
|
|
103
|
-
parentDom = this.$lastInput!.dom!.parentElement!;
|
|
103
|
+
const parentDom = this.$lastInput!.dom!.parentElement!;
|
|
104
104
|
this.initContainer(nextProps.container, parentDom, anchor);
|
|
105
105
|
|
|
106
106
|
mount(
|