Skip to content

Commit 12074a0

Browse files
committed
Merge remote-tracking branch 'origin/feat-v4'
2 parents cb0abe5 + 8f95cdd commit 12074a0

File tree

12 files changed

+534
-2
lines changed

12 files changed

+534
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`renders ./components/app/demo/basic.vue correctly 1`] = `
4+
<div class="ant-app">
5+
<!--teleport start-->
6+
<!--teleport end-->
7+
<!--teleport start-->
8+
<!--teleport end-->
9+
<div class="ant-space ant-space-horizontal ant-space-align-center">
10+
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button">
11+
<!----><span>Open message</span>
12+
</button></div>
13+
<!---->
14+
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button">
15+
<!----><span>Open modal</span>
16+
</button></div>
17+
<!---->
18+
<div class="ant-space-item"><button class="ant-btn ant-btn-primary" type="button">
19+
<!----><span>Open notification</span>
20+
</button></div>
21+
<!---->
22+
</div>
23+
</div>
24+
`;
25+
26+
exports[`renders ./components/app/demo/myPage.vue correctly 1`] = `
27+
<div class="ant-space ant-space-horizontal ant-space-align-center">
28+
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button">
29+
<!----><span>Open message</span>
30+
</button></div>
31+
<!---->
32+
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button">
33+
<!----><span>Open modal</span>
34+
</button></div>
35+
<!---->
36+
<div class="ant-space-item"><button class="ant-btn ant-btn-primary" type="button">
37+
<!----><span>Open notification</span>
38+
</button></div>
39+
<!---->
40+
</div>
41+
`;

components/app/__tests__/demo.test.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import demoTest from '../../../tests/shared/demoTest';
2+
3+
demoTest('app');

components/app/context.ts

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { provide, inject, reactive } from 'vue';
2+
import type { InjectionKey } from 'vue';
3+
import type { MessageInstance, ConfigOptions as MessageConfig } from '../message/interface';
4+
import type { NotificationInstance, NotificationConfig } from '../notification/interface';
5+
import type { ModalStaticFunctions } from '../modal/confirm';
6+
7+
export type AppConfig = {
8+
message?: MessageConfig;
9+
notification?: NotificationConfig;
10+
};
11+
12+
export const AppConfigContextKey: InjectionKey<AppConfig> = Symbol('appConfigContext');
13+
14+
export const useProvideAppConfigContext = (appConfigContext: AppConfig) => {
15+
return provide(AppConfigContextKey, appConfigContext);
16+
};
17+
18+
export const useInjectAppConfigContext = () => {
19+
return inject(AppConfigContextKey, {});
20+
};
21+
22+
type ModalType = Omit<ModalStaticFunctions, 'warn'>;
23+
24+
export interface useAppProps {
25+
message: MessageInstance;
26+
notification: NotificationInstance;
27+
modal: ModalType;
28+
}
29+
30+
export const AppContextKey: InjectionKey<useAppProps> = Symbol('appContext');
31+
32+
export const useProvideAppContext = (appContext: useAppProps) => {
33+
return provide(AppContextKey, appContext);
34+
};
35+
36+
const defaultAppContext: useAppProps = reactive({
37+
message: {},
38+
notification: {},
39+
modal: {},
40+
} as useAppProps);
41+
42+
export const useInjectAppContext = () => {
43+
return inject(AppContextKey, defaultAppContext);
44+
};

components/app/demo/basic.vue

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<docs>
2+
---
3+
order: 0
4+
title:
5+
zh-CN: 基本使用
6+
en-US: Basic Usage
7+
---
8+
9+
## zh-CN
10+
11+
获取 `message`、`notification`、`modal` 静态方法。
12+
13+
## en-US
14+
15+
Static method for `message`, `notification`, `modal`.
16+
</docs>
17+
18+
<template>
19+
<a-app>
20+
<my-page />
21+
</a-app>
22+
</template>
23+
24+
<script lang="ts" setup>
25+
import myPage from './myPage.vue';
26+
</script>

components/app/demo/index.vue

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<template>
2+
<demo-sort :cols="1">
3+
<basic />
4+
</demo-sort>
5+
</template>
6+
7+
<script lang="ts">
8+
import { defineComponent } from 'vue';
9+
import Basic from './basic.vue';
10+
import CN from '../index.zh-CN.md';
11+
import US from '../index.en-US.md';
12+
export default defineComponent({
13+
CN,
14+
US,
15+
components: {
16+
Basic,
17+
},
18+
});
19+
</script>

components/app/demo/myPage.vue

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<template>
2+
<a-space>
3+
<a-button type="primary" @click="showMessage">Open message</a-button>
4+
<a-button type="primary" @click="showModal">Open modal</a-button>
5+
<a-button type="primary" @click="showNotification">Open notification</a-button>
6+
</a-space>
7+
</template>
8+
9+
<script setup lang="ts">
10+
import { App } from 'ant-design-vue';
11+
12+
const { message, modal, notification } = App.useApp();
13+
14+
const showMessage = () => {
15+
message.success('Success!');
16+
};
17+
18+
const showModal = () => {
19+
modal.warning({
20+
title: 'This is a warning message',
21+
content: 'some messages...some messages...',
22+
});
23+
};
24+
25+
const showNotification = () => {
26+
notification.info({
27+
message: `Notification topLeft`,
28+
description: 'Hello, Ant Design Vue!!',
29+
placement: 'topLeft',
30+
});
31+
};
32+
</script>

components/app/index.en-US.md

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
---
2+
category: Components
3+
cols: 1
4+
type: Other
5+
title: App
6+
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*TBTSR4PyVmkAAAAAAAAAAAAADrJ8AQ/original
7+
coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JGb3RIzyOCkAAAAAAAAAAAAADrJ8AQ/original
8+
---
9+
10+
Application wrapper for some global usages.
11+
12+
## When To Use
13+
14+
- Provide reset styles based on `.ant-app` element.
15+
- You could use static methods of `message/notification/Modal` form `useApp` without writing `contextHolder` manually.
16+
17+
## API
18+
19+
### App
20+
21+
| Property | Description | Type | Default | Version |
22+
| --- | --- | --- | --- | --- |
23+
| message | Global config for Message | [MessageConfig](/components/message/#messageconfig) | - | 4.x |
24+
| notification | Global config for Notification | [NotificationConfig](/components/notification/#notificationconfig) | - | 4.x |
25+
26+
## How to use
27+
28+
### Basic usage
29+
30+
App provides upstream and downstream method calls through `provide/inject`, because useApp needs to be used as a subcomponent, we recommend encapsulating App at the top level in the application.
31+
32+
```html
33+
/*myPage.vue*/
34+
<template>
35+
<a-space>
36+
<a-button type="primary" @click="showMessage">Open message</a-button>
37+
<a-button type="primary" @click="showModal">Open modal</a-button>
38+
<a-button type="primary" @click="showNotification">Open notification</a-button>
39+
</a-space>
40+
</template>
41+
42+
<script setup lang="ts">
43+
import { App } from 'ant-design-vue';
44+
45+
const { message, modal, notification } = App.useApp();
46+
47+
const showMessage = () => {
48+
message.success('Success!');
49+
};
50+
51+
const showModal = () => {
52+
modal.warning({
53+
title: 'This is a warning message',
54+
content: 'some messages...some messages...',
55+
});
56+
};
57+
58+
const showNotification = () => {
59+
notification.info({
60+
message: `Notification topLeft`,
61+
description: 'Hello, Ant Design Vue!!',
62+
placement: 'topLeft',
63+
});
64+
};
65+
</script>
66+
```
67+
68+
Note: App.useApp must be available under App.
69+
70+
#### Embedded usage scenarios (if not necessary, try not to do nesting)
71+
72+
```html
73+
<a-app>
74+
<a-space>
75+
...
76+
<a-app>...</a-app>
77+
</a-space>
78+
</a-app>
79+
```
80+
81+
#### Sequence with ConfigProvider
82+
83+
The App component can only use the token in the `ConfigProvider`, if you need to use the Token, the ConfigProvider and the App component must appear in pairs.
84+
85+
```html
86+
<a-config-provider theme="{{ ... }}">
87+
<a-app>...</a-app>
88+
</a-config-provider>
89+
```
90+
91+
#### Global scene (pinia scene)
92+
93+
```ts
94+
import { App } from 'ant-design-vue';
95+
import type { MessageInstance } from 'ant-design-vue/es/message/interface';
96+
import type { ModalStaticFunctions } from 'ant-design-vue/es/modal/confirm';
97+
import type { NotificationInstance } from 'ant-design-vue/es/notification/interface';
98+
99+
export const useGloablStore = defineStore('global', () => {
100+
const message: MessageInstance = ref();
101+
const notification: NotificationInstance = ref();
102+
const modal: Omit<ModalStaticFunctions, 'warn'> = ref();
103+
(() => {
104+
const staticFunction = App.useApp();
105+
message.value = staticFunction.message;
106+
modal.value = staticFunction.modal;
107+
notification.value = staticFunction.notification;
108+
})();
109+
110+
return { message, notification, modal };
111+
});
112+
```
113+
114+
```html
115+
// sub page
116+
<template>
117+
<a-space>
118+
<a-button type="primary" @click="showMessage">Open message</a-button>
119+
</a-space>
120+
</template>
121+
122+
<script setup>
123+
import { useGlobalStore } from '@/stores/global';
124+
const global = useGlobalStore();
125+
const showMessage = () => {
126+
global.message.success('Success!');
127+
};
128+
</script>
129+
```

components/app/index.tsx

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { defineComponent, computed } from 'vue';
2+
import type { App as TypeApp, Plugin } from 'vue';
3+
import { initDefaultProps } from '../_util/props-util';
4+
import classNames from '../_util/classNames';
5+
import { objectType } from '../_util/type';
6+
import useConfigInject from '../config-provider/hooks/useConfigInject';
7+
import useMessage from '../message/useMessage';
8+
import useModal from '../modal/useModal';
9+
import useNotification from '../notification/useNotification';
10+
import type { AppConfig } from './context';
11+
import {
12+
useProvideAppConfigContext,
13+
useInjectAppConfigContext,
14+
useProvideAppContext,
15+
useInjectAppContext,
16+
} from './context';
17+
import useStyle from './style';
18+
19+
export const AppProps = () => {
20+
return {
21+
rootClassName: String,
22+
message: objectType<AppConfig['message']>(),
23+
notification: objectType<AppConfig['notification']>(),
24+
};
25+
};
26+
27+
const useApp = () => {
28+
return useInjectAppContext();
29+
};
30+
31+
const App = defineComponent({
32+
name: 'AApp',
33+
props: initDefaultProps(AppProps(), {}),
34+
setup(props, { slots }) {
35+
const { prefixCls } = useConfigInject('app', props);
36+
const [wrapSSR, hashId] = useStyle(prefixCls);
37+
const customClassName = computed(() => {
38+
return classNames(hashId.value, prefixCls.value, props.rootClassName);
39+
});
40+
41+
const appConfig = useInjectAppConfigContext();
42+
const mergedAppConfig = computed(() => ({
43+
message: { ...appConfig.message, ...props.message },
44+
notification: { ...appConfig.notification, ...props.notification },
45+
}));
46+
useProvideAppConfigContext(mergedAppConfig.value);
47+
48+
const [messageApi, messageContextHolder] = useMessage(mergedAppConfig.value.message);
49+
const [notificationApi, notificationContextHolder] = useNotification(
50+
mergedAppConfig.value.notification,
51+
);
52+
const [ModalApi, ModalContextHolder] = useModal();
53+
54+
const memoizedContextValue = computed(() => ({
55+
message: messageApi,
56+
notification: notificationApi,
57+
modal: ModalApi,
58+
}));
59+
useProvideAppContext(memoizedContextValue.value);
60+
61+
return () => {
62+
return wrapSSR(
63+
<div class={customClassName.value}>
64+
{ModalContextHolder()}
65+
{messageContextHolder()}
66+
{notificationContextHolder()}
67+
{slots.default?.()}
68+
</div>,
69+
);
70+
};
71+
},
72+
});
73+
74+
App.useApp = useApp;
75+
76+
App.install = function (app: TypeApp) {
77+
app.component(App.name, App);
78+
};
79+
80+
export default App as typeof App &
81+
Plugin & {
82+
readonly useApp: typeof useApp;
83+
};

0 commit comments

Comments
 (0)