[improvement] rename packages dir to src (#3659)

This commit is contained in:
neverland
2019-06-27 11:25:57 +08:00
committed by GitHub
parent 8489918dca
commit 75c79b7044
619 changed files with 21 additions and 21 deletions
+143
View File
@@ -0,0 +1,143 @@
import { createNamespace } from '../utils';
import { PopupMixin } from '../mixins/popup';
import Button from '../button';
const [createComponent, bem, t] = createNamespace('dialog');
export default createComponent({
mixins: [PopupMixin],
props: {
title: String,
message: String,
className: null,
callback: Function,
beforeClose: Function,
messageAlign: String,
cancelButtonText: String,
cancelButtonColor: String,
confirmButtonText: String,
confirmButtonColor: String,
showCancelButton: Boolean,
showConfirmButton: {
type: Boolean,
default: true
},
overlay: {
type: Boolean,
default: true
},
closeOnClickOverlay: {
type: Boolean,
default: false
}
},
data() {
return {
loading: {
confirm: false,
cancel: false
}
};
},
methods: {
onClickOverlay() {
this.handleAction('overlay');
},
handleAction(action) {
this.$emit(action);
if (this.beforeClose) {
this.loading[action] = true;
this.beforeClose(action, state => {
if (state !== false) {
this.onClose(action);
}
this.loading[action] = false;
});
} else {
this.onClose(action);
}
},
onClose(action) {
this.close();
if (this.callback) {
this.callback(action);
}
}
},
render(h) {
if (!this.shouldRender) {
return;
}
const { title, message, messageAlign } = this;
const children = this.slots();
const Title = title && (
<div class={bem('header', { isolated: !message && !children })}>{title}</div>
);
const Content = (children || message) && (
<div class={bem('content')}>
{children || (
<div
domPropsInnerHTML={message}
class={bem('message', { 'has-title': title, [messageAlign]: messageAlign })}
/>
)}
</div>
);
const hasButtons = this.showCancelButton && this.showConfirmButton;
const ButtonGroup = (
<div class={['van-hairline--top', bem('footer', { buttons: hasButtons })]}>
{this.showCancelButton && (
<Button
size="large"
class={bem('cancel')}
loading={this.loading.cancel}
text={this.cancelButtonText || t('cancel')}
style={{ color: this.cancelButtonColor }}
onClick={() => {
this.handleAction('cancel');
}}
/>
)}
{this.showConfirmButton && (
<Button
size="large"
class={[bem('confirm'), { 'van-hairline--left': hasButtons }]}
loading={this.loading.confirm}
text={this.confirmButtonText || t('confirm')}
style={{ color: this.confirmButtonColor }}
onClick={() => {
this.handleAction('confirm');
}}
/>
)}
</div>
);
return (
<transition name="van-dialog-bounce">
<div
vShow={this.value}
role="dialog"
aria-labelledby={title || message}
class={[bem(), this.className]}
>
{Title}
{Content}
{ButtonGroup}
</div>
</transition>
);
}
});
+142
View File
@@ -0,0 +1,142 @@
<template>
<demo-section>
<demo-block :title="$t('alert1')">
<van-button
type="primary"
@click="onClickAlert"
>
{{ $t('alert1') }}
</van-button>
<van-button
type="primary"
@click="onClickAlert2"
>
{{ $t('alert2') }}
</van-button>
</demo-block>
<demo-block :title="$t('confirm')">
<van-button
type="primary"
@click="onClickConfirm"
>
{{ $t('confirm') }}
</van-button>
</demo-block>
<demo-block :title="$t('asyncClose')">
<van-button
type="primary"
@click="onClickAsyncClose"
>
{{ $t('asyncClose') }}
</van-button>
</demo-block>
<demo-block
v-if="!$attrs.weapp"
:title="$t('componentCall')"
>
<van-button
type="primary"
@click="show = true"
>
{{ $t('componentCall') }}
</van-button>
<van-dialog
v-model="show"
:title="$t('title')"
show-cancel-button
:lazy-render="false"
>
<img :src="image">
</van-dialog>
</demo-block>
</demo-section>
</template>
<script>
export default {
i18n: {
'zh-CN': {
alert1: '提示弹窗',
alert2: '提示弹窗(无标题)',
confirm: '确认弹窗',
asyncClose: '异步关闭',
componentCall: '组件调用',
content: '代码是写出来给人看的,附带能在机器上运行'
},
'en-US': {
alert1: 'Alert',
alert2: 'Alert without title',
confirm: 'Confirm dialog',
asyncClose: 'Async Close',
componentCall: 'Component Call',
}
},
data() {
return {
show: false,
currentRate: 0,
image: 'https://img.yzcdn.cn/public_files/2017/09/05/4e3ea0898b1c2c416eec8c11c5360833.jpg'
};
},
methods: {
onClickAlert() {
this.$dialog.alert({
title: this.$t('title'),
message: this.$t('content')
});
},
onClickAlert2() {
this.$dialog.alert({
message: this.$t('content')
});
},
onClickConfirm() {
this.$dialog.confirm({
title: this.$t('title'),
message: this.$t('content')
});
},
onClickAsyncClose() {
function beforeClose(action, done) {
if (action === 'confirm') {
setTimeout(done, 1000);
} else {
done();
}
}
this.$dialog.confirm({
title: this.$t('title'),
message: this.$t('content'),
beforeClose
});
}
}
};
</script>
<style lang="less">
@import "../../style/var";
.demo-dialog {
background-color: @white;
.van-doc-demo-block > .van-button {
margin-left: 15px;
}
img {
box-sizing: border-box;
width: 100%;
padding: 25px 20px 0;
}
}
</style>
+161
View File
@@ -0,0 +1,161 @@
# Dialog
### Install
```js
import { Dialog } from 'vant';
Vue.use(Dialog);
```
## Usage
### Alert dialog
Used to prompt for some messages, only including one confirm button
```javascript
Dialog.alert({
title: 'Title',
message: 'Content'
}).then(() => {
// on close
});
Dialog.alert({
message: 'Content'
}).then(() => {
// on close
});
```
### Confirm dialog
Used to confirm some messages, including a confirm button and a cancel button
```javascript
Dialog.confirm({
title: 'Title',
message: 'Content'
}).then(() => {
// on confirm
}).catch(() => {
// on cancel
});
```
### Asnyc Close
```js
function beforeClose(action, done) {
if (action === 'confirm') {
setTimeout(done, 1000);
} else {
done();
}
}
Dialog.confirm({
title: 'Title',
message: 'Content',
beforeClose
});
```
### $dialog Method
After import the Dialog component, the $dialog method is automatically mounted on Vue.prototype, making it easy to call within a vue component.
```js
export default {
mounted() {
this.$dialog.alert({
message: 'Content'
});
}
}
```
### Advanced Usage
If you need to render vue components within a dialog, you can use dialog component.
```html
<van-dialog
v-model="show"
title="Title"
show-cancel-button
>
<img src="https://img.yzcdn.cn/1.jpg">
</van-dialog>
```
```js
export default {
data() {
return {
show: false
};
}
}
```
## API
### Methods
| Name | Attribute | Return value | Description |
|------|------|------|------|
| Dialog | `options` | `Promise` | Show dialog |
| Dialog.alert | `options` | `Promise` | Show alert dialog |
| Dialog.confirm | `options` | `Promise` | Show confim dialog |
| Dialog.setDefaultOptions | `options` | `void` | Set default options of all dialogs |
| Dialog.resetDefaultOptions | - | `void` | Reset default options of all dialogs |
| Dialog.close | - | `void` | Close dialog |
### Options
| Attribute | Description | Type | Default |
|------|------|------|------|
| title | Title | `String` | - |
| message | Message | `String` | - |
| messageAlign | Message text aligncan be set to `left` `right` | `String` | `center` |
| className | Custom className | `String | Array | Object` | - |
| showConfirmButton | Whether to show confirm button | `Boolean` | `true` |
| showCancelButton | Whether to show cancel button | `Boolean` | `false` |
| cancelButtonText | Cancel button text | `String` | `Cancel` |
| cancelButtonColor | Cancel button color | `String` | `#000` |
| confirmButtonText | Confirm button text | `String` | `Confirm` |
| confirmButtonColor | Confirm button color | `String` | `#1989fa` |
| overlay | Whether to show overlay | `Boolean` | `true` |
| closeOnClickOverlay | Whether to close when click overlay | `Boolean` | `false` |
| lockScroll | Whether to lock body scroll | `Boolean` | `true` |
| beforeClose | Callback before close,<br>call done() to close dialog,<br>call done(false) to cancel loading | (action: string, done: function) => void | - |
| getContainer | Return the mount node for Dialog | `String | () => HTMLElement` | `body` |
### Props
| Attribute | Description | Type | Default |
|------|------|------|------|
| v-model | Whether to show dialog | `Boolean` | - |
| title | Title | `String` | - |
| message | Message | `String` | - |
| message-align | Message aligncan be set to `left` `right` | `String` | `center` |
| show-confirm-button | Whether to show confirm button | `Boolean` | `true` |
| show-cancel-button | Whether to show cancel button | `Boolean` | `false` |
| cancel-button-text | Cancel button text | `String` | `Cancel` |
| cancel-button-color | Cancel button color | `String` | `#000` |
| confirm-button-text | Confirm button text | `String` | `Confirm` |
| confirm-button-color | Confirm button color | `String` | `#1989fa` |
| overlay | Whether to show overlay | `Boolean` | `true` |
| close-on-click-overlay | Whether to close when click overlay | `Boolean` | `false` |
| lock-scroll | Whether to lock background scroll | `Boolean` | `true` |
| before-close | Callback before close,<br>call done() to close dialog,<br>call done(false) to cancel loading | (action: string, done: function) => void | - |
| get-container | Return the mount node for Dialog | `String | () => HTMLElement` | `body` |
### Events
| Event | Description | Parameters |
|------|------|------|
| confirm | Triggered when click confirm button | - |
| cancel | Triggered when click cancel button | - |
+100
View File
@@ -0,0 +1,100 @@
import Vue from 'vue';
import VanDialog from './Dialog';
import { isServer } from '../utils';
let instance;
function isInDocument(element) {
return document.body.contains(element);
}
function initInstance() {
if (instance) {
instance.$destroy();
}
instance = new (Vue.extend(VanDialog))({
el: document.createElement('div'),
// avoid missing animation when first rendered
propsData: {
lazyRender: false
}
});
instance.$on('input', value => {
instance.value = value;
});
}
function Dialog(options) {
/* istanbul ignore if */
if (isServer) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
if (!instance || !isInDocument(instance.$el)) {
initInstance();
}
Object.assign(instance, Dialog.currentOptions, options, {
resolve,
reject
});
});
}
Dialog.defaultOptions = {
value: true,
title: '',
message: '',
overlay: true,
className: '',
lockScroll: true,
beforeClose: null,
messageAlign: '',
getContainer: 'body',
cancelButtonText: '',
cancelButtonColor: null,
confirmButtonText: '',
confirmButtonColor: null,
showConfirmButton: true,
showCancelButton: false,
closeOnClickOverlay: false,
callback: action => {
instance[action === 'confirm' ? 'resolve' : 'reject'](action);
}
};
Dialog.alert = Dialog;
Dialog.confirm = options => Dialog({
showCancelButton: true,
...options
});
Dialog.close = () => {
if (instance) {
instance.value = false;
}
};
Dialog.setDefaultOptions = options => {
Object.assign(Dialog.currentOptions, options);
};
Dialog.resetDefaultOptions = () => {
Dialog.currentOptions = { ...Dialog.defaultOptions };
};
Dialog.resetDefaultOptions();
Dialog.install = () => {
Vue.use(VanDialog);
};
Dialog.Component = VanDialog;
Vue.prototype.$dialog = Dialog;
export default Dialog;
+85
View File
@@ -0,0 +1,85 @@
@import '../style/var';
.van-dialog {
position: fixed;
top: 50%;
left: 50%;
width: @dialog-width;
overflow: hidden;
font-size: @dialog-font-size;
background-color: @dialog-background-color;
border-radius: @dialog-border-radius;
transform: translate3d(-50%, -50%, 0);
backface-visibility: hidden; // avoid blurry text after scale animation
transition: @dialog-transition;
&__header {
padding-top: @dialog-header-padding-top;
font-weight: @dialog-header-font-weight;
text-align: center;
&--isolated {
padding: @dialog-header-isolated-padding;
}
}
&__message {
max-height: @dialog-message-max-height;
padding: @dialog-message-padding;
overflow-y: auto;
font-size: @dialog-message-font-size;
line-height: @dialog-message-line-height;
// allow newline charactor
white-space: pre-wrap;
text-align: center;
-webkit-overflow-scrolling: touch;
&--has-title {
padding-top: @dialog-has-title-message-padding-top;
color: @dialog-has-title-message-text-color;
}
&--left {
text-align: left;
}
&--right {
text-align: right;
}
}
&__footer {
overflow: hidden;
user-select: none;
&--buttons {
display: flex;
.van-button {
flex: 1;
}
}
}
.van-button {
border: 0;
}
&__confirm {
&,
&:active {
color: @dialog-confirm-button-text-color;
}
}
&-bounce-enter {
transform: translate3d(-50%, -50%, 0) scale(0.7);
opacity: 0;
}
&-bounce-leave-active {
transform: translate3d(-50%, -50%, 0) scale(0.9);
opacity: 0;
}
}
@@ -0,0 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders demo correctly 1`] = `
<div>
<div><button class="van-button van-button--primary van-button--normal"><span class="van-button__text">
提示弹窗
</span></button> <button class="van-button van-button--primary van-button--normal"><span class="van-button__text">
提示弹窗(无标题)
</span></button></div>
<div><button class="van-button van-button--primary van-button--normal"><span class="van-button__text">
确认弹窗
</span></button></div>
<div><button class="van-button van-button--primary van-button--normal"><span class="van-button__text">
异步关闭
</span></button></div>
<div><button class="van-button van-button--primary van-button--normal"><span class="van-button__text">
组件调用
</span></button>
<div role="dialog" aria-labelledby="标题" class="van-dialog" style="display: none;" name="van-dialog-bounce">
<div class="van-dialog__header">标题</div>
<div class="van-dialog__content"><img src="https://img.yzcdn.cn/public_files/2017/09/05/4e3ea0898b1c2c416eec8c11c5360833.jpg"></div>
<div class="van-hairline--top van-dialog__footer van-dialog__footer--buttons"><button class="van-button van-button--default van-button--large van-dialog__cancel"><span class="van-button__text">取消</span></button><button class="van-button van-button--default van-button--large van-dialog__confirm van-hairline--left"><span class="van-button__text">确认弹窗</span></button></div>
</div>
</div>
</div>
`;
@@ -0,0 +1,13 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`button color 1`] = `
<div role="dialog" class="van-dialog" name="van-dialog-bounce">
<div class="van-hairline--top van-dialog__footer van-dialog__footer--buttons"><button class="van-button van-button--default van-button--large van-dialog__cancel" style="color: white;"><span class="van-button__text">取消</span></button><button class="van-button van-button--default van-button--large van-dialog__confirm van-hairline--left" style="color: red;"><span class="van-button__text">确认</span></button></div>
</div>
`;
exports[`button text 1`] = `
<div role="dialog" class="van-dialog" name="van-dialog-bounce">
<div class="van-hairline--top van-dialog__footer van-dialog__footer--buttons"><button class="van-button van-button--default van-button--large van-dialog__cancel"><span class="van-button__text">Custom cancel</span></button><button class="van-button van-button--default van-button--large van-dialog__confirm van-hairline--left"><span class="van-button__text">Custom confirm</span></button></div>
</div>
`;
+4
View File
@@ -0,0 +1,4 @@
import Demo from '../demo';
import demoTest from '../../../test/demo-test';
demoTest(Demo);
+106
View File
@@ -0,0 +1,106 @@
import Vue from 'vue';
import Dialog from '..';
import DialogVue from '../Dialog';
import { mount, later, trigger, transitionStub } from '../../../test/utils';
transitionStub();
test('Dialog function call', async () => {
Dialog.close();
Dialog.alert({
message: '1',
showCancelButton: true
});
await later();
const callback = jest.fn();
const dialog = document.querySelector('.van-dialog');
expect(dialog.style.display).toEqual('');
Dialog.close();
await later();
expect(dialog.style.display).toEqual('none');
Dialog.confirm().catch(callback);
document.querySelector('.van-dialog__cancel').click();
await later();
expect(callback).toHaveBeenCalledWith('cancel');
Dialog.confirm().then(callback);
document.querySelector('.van-dialog__confirm').click();
await later();
expect(callback).toHaveBeenNthCalledWith(2, 'confirm');
});
test('before close', () => {
const wrapper = mount(DialogVue, {
propsData: {
value: true,
showCancelButton: true,
closeOnClickOverlay: true,
beforeClose: (action, done) => done(false)
}
});
const cancel = wrapper.find('.van-dialog__cancel');
cancel.trigger('click');
expect(wrapper.emitted('input')).toBeFalsy();
wrapper.setProps({
beforeClose: (action, done) => {
if (action === 'cancel') {
done();
}
}
});
const overlay = document.querySelector('.van-overlay');
trigger(overlay, 'click');
expect(wrapper.emitted('input')).toBeFalsy();
cancel.trigger('click');
expect(wrapper.emitted('input')[0]).toBeTruthy();
});
test('set default options', () => {
Dialog.setDefaultOptions({ lockScroll: false });
expect(Dialog.currentOptions.lockScroll).toBeFalsy();
Dialog.resetDefaultOptions();
expect(Dialog.currentOptions.lockScroll).toBeTruthy();
});
test('register component', () => {
Vue.use(Dialog);
expect(Vue.component(DialogVue.name)).toBeTruthy();
});
test('button color', () => {
const wrapper = mount(DialogVue, {
propsData: {
value: true,
showCancelButton: true,
cancelButtonColor: 'white',
confirmButtonColor: 'red'
}
});
expect(wrapper).toMatchSnapshot();
});
test('button text', () => {
const wrapper = mount(DialogVue, {
propsData: {
value: true,
showCancelButton: true,
cancelButtonText: 'Custom cancel',
confirmButtonText: 'Custom confirm'
}
});
expect(wrapper).toMatchSnapshot();
});
test('dialog component', () => {
expect(Dialog.Component).toEqual(DialogVue);
});
+194
View File
@@ -0,0 +1,194 @@
# Dialog 弹出框
### 介绍
弹出模态框,常用于消息提示、消息确认、在当前页面内完成特定的交互操作
弹出框组件支持函数调用和组件调用两种方式
### 函数调用
Dialog 是一个函数而不是组件,因此可以直接调用,展示对应的提示弹窗
```js
import { Dialog } from 'vant';
Dialog({ message: '提示' });
```
### 组件调用
通过组件调用 Dialog 时,可以通过下面的方式进行注册
```js
import { Dialog } from 'vant';
// 全局注册
Vue.use(Dialog);
// 局部注册
export default {
components: {
[Dialog.Component.name]: Dialog.Component
}
}
```
## 代码演示
### 消息提示
用于提示一些消息,只包含一个确认按钮
```javascript
Dialog.alert({
title: '标题',
message: '弹窗内容'
}).then(() => {
// on close
});
Dialog.alert({
message: '弹窗内容'
}).then(() => {
// on close
});
```
### 消息确认
用于确认消息,包含取消和确认按钮
```javascript
Dialog.confirm({
title: '标题',
message: '弹窗内容'
}).then(() => {
// on confirm
}).catch(() => {
// on cancel
});
```
### 异步关闭
```js
function beforeClose(action, done) {
if (action === 'confirm') {
setTimeout(done, 1000);
} else {
done();
}
}
Dialog.confirm({
title: '标题',
message: '弹窗内容',
beforeClose
});
```
### 全局方法
引入 Dialog 组件后,会自动在 Vue 的 prototype 上挂载 $dialog 方法,在所有组件内部都可以直接调用此方法
```js
export default {
mounted() {
this.$dialog.alert({
message: '弹窗内容'
});
}
}
```
### 组件调用
如果需要在弹窗内嵌入组件或其他自定义内容,可以使用组件调用的方式
```html
<van-dialog
v-model="show"
title="标题"
show-cancel-button
>
<img src="https://img.yzcdn.cn/1.jpg">
</van-dialog>
```
```js
export default {
data() {
return {
show: false
};
}
}
```
## API
### 方法
| 方法名 | 参数 | 返回值 | 介绍 |
|------|------|------|------|
| Dialog | `options` | `Promise` | 展示弹窗 |
| Dialog.alert | `options` | `Promise` | 展示消息提示弹窗 |
| Dialog.confirm | `options` | `Promise` | 展示消息确认弹窗 |
| Dialog.setDefaultOptions | `options` | `void` | 修改默认配置,对所有 Dialog 生效 |
| Dialog.resetDefaultOptions | - | `void` | 重置默认配置,对所有 Dialog 生效 |
| Dialog.close | - | `void` | 关闭弹窗 |
### Options
通过函数调用 `Dialog` 时,支持传入以下选项:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| title | 标题 | `String` | - | - |
| message | 文本内容,支持通过`\n`换行 | `String` | - | - |
| messageAlign | 内容对齐方式,可选值为`left` `right` | `String` | `center` | 1.5.0 |
| className | 自定义类名 | `String | Array | Object` | - | 1.1.7 |
| showConfirmButton | 是否展示确认按钮 | `Boolean` | `true` | - |
| showCancelButton | 是否展示取消按钮 | `Boolean` | `false` | - |
| cancelButtonText | 取消按钮文案 | `String` | `取消` | - |
| cancelButtonColor | 取消按钮颜色 | `String` | `#000` | 1.6.14 |
| confirmButtonText | 确认按钮文案 | `String` | `确认` | - |
| confirmButtonColor | 确认按钮颜色 | `String` | `#1989fa` | 1.6.14 |
| overlay | 是否展示遮罩层 | `Boolean` | `true` | - |
| closeOnClickOverlay | 点击遮罩层时是否关闭弹窗 | `Boolean` | `false` | - |
| lockScroll | 是否锁定背景滚动 | `Boolean` | `true` | - |
| beforeClose | 关闭前的回调函数,<br>调用 done() 后关闭弹窗,<br>调用 done(false) 阻止弹窗关闭 | `(action, done) => void` | - | 1.1.6 |
| getContainer | 指定挂载的节点,可以传入选择器,<br>或一个返回节点的函数 | `String | () => HTMLElement` | `body` | 1.6.11 |
### Props
通过组件调用 `Dialog` 时,支持以下 Props
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|------|------|------|------|------|
| v-model | 是否显示弹窗 | `Boolean` | - | - |
| title | 标题 | `String` | - | - |
| message | 内容 | `String` | - | - |
| message-align | 内容对齐方式,可选值为`left` `right` | `String` | `center` | 1.5.0 |
| show-confirm-button | 是否展示确认按钮 | `Boolean` | `true` | - |
| show-cancel-button | 是否展示取消按钮 | `Boolean` | `false` | - |
| cancel-button-text | 取消按钮文案 | `String` | `取消` | - |
| cancel-button-color | 取消按钮颜色 | `String` | `#000` | 1.6.14 |
| confirm-button-text | 确认按钮文案 | `String` | `确认` | - |
| confirm-button-color | 确认按钮颜色 | `String` | `#1989fa` | 1.6.14 |
| overlay | 是否展示遮罩层 | `Boolean` | `true` | - |
| close-on-click-overlay | 是否在点击遮罩层后关闭 | `Boolean` | `false` | - |
| lock-scroll | 是否锁定背景滚动 | `Boolean` | `true` | - |
| before-close | 关闭前的回调函数,<br>调用 done() 后关闭弹窗,<br>调用 done(false) 阻止弹窗关闭 | `(action, done) => void` | - | 1.1.6 |
| get-container | 指定挂载的节点,可以传入选择器,<br>或一个返回节点的函数 | `String | () => HTMLElement` | `body` | 1.1.6 |
### Events
通过组件调用 `Dialog` 时,支持以下事件:
| 事件 | 说明 | 回调参数 |
|------|------|------|
| confirm | 点击确认按钮时触发 | - |
| cancel | 点击取消按钮时触发 | - |