From 9213839980a44a45d2290beb5d839529407e1636 Mon Sep 17 00:00:00 2001 From: Hex Date: Tue, 17 Nov 2020 21:56:17 +0800 Subject: [PATCH 01/23] fix(ActionSheet): The height of the flex container is lost under iOS 10 (#7578) --- src/action-sheet/index.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/action-sheet/index.less b/src/action-sheet/index.less index 9928c7bcb..17b2e124f 100644 --- a/src/action-sheet/index.less +++ b/src/action-sheet/index.less @@ -9,7 +9,7 @@ color: @action-sheet-item-text-color; &__content { - flex: 1; + flex: 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch; } From cd6ce609f5011c74a25d38519a4483d278a03aca Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Tue, 17 Nov 2020 22:04:34 +0800 Subject: [PATCH 02/23] docs(theme): update less-loader version tip #5877 --- docs/markdown/theme.zh-CN.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/markdown/theme.zh-CN.md b/docs/markdown/theme.zh-CN.md index 2287b65bb..bc62ba87f 100644 --- a/docs/markdown/theme.zh-CN.md +++ b/docs/markdown/theme.zh-CN.md @@ -75,7 +75,7 @@ module.exports = { { loader: 'less-loader', options: { - // 若使用 less-loader@5,请移除 lessOptions 这一级,直接配置选项。 + // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。 lessOptions: { modifyVars: { // 直接覆盖变量 @@ -101,7 +101,7 @@ module.exports = { css: { loaderOptions: { less: { - // 若使用 less-loader@5,请移除 lessOptions 这一级,直接配置选项。 + // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。 lessOptions: { modifyVars: { // 直接覆盖变量 From 8f5a84ceecee85ed516b072c359642713f8fce4a Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Mon, 16 Nov 2020 20:49:46 +0800 Subject: [PATCH 03/23] feat: add popover component --- src/popover/README.md | 32 ++++++++ src/popover/README.zh-CN.md | 66 ++++++++++++++++ src/popover/demo/index.vue | 60 +++++++++++++++ src/popover/index.js | 76 +++++++++++++++++++ src/popover/index.less | 61 +++++++++++++++ .../test/__snapshots__/demo.spec.js.snap | 58 ++++++++++++++ .../test/__snapshots__/index.spec.js.snap | 22 ++++++ src/popover/test/demo.spec.js | 4 + src/popover/test/index.spec.js | 2 + vant.config.js | 8 ++ 10 files changed, 389 insertions(+) create mode 100644 src/popover/README.md create mode 100644 src/popover/README.zh-CN.md create mode 100644 src/popover/demo/index.vue create mode 100644 src/popover/index.js create mode 100644 src/popover/index.less create mode 100644 src/popover/test/__snapshots__/demo.spec.js.snap create mode 100644 src/popover/test/__snapshots__/index.spec.js.snap create mode 100644 src/popover/test/demo.spec.js create mode 100644 src/popover/test/index.spec.js diff --git a/src/popover/README.md b/src/popover/README.md new file mode 100644 index 000000000..5772a8d1b --- /dev/null +++ b/src/popover/README.md @@ -0,0 +1,32 @@ +# Popover + +### Install + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## Usage + +### Basic Usage + +```html + +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +| --------- | ----------- | ---- | ------- | + + +### Events + +| Event | Description | Arguments | +| ----- | ----------- | --------- | + diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md new file mode 100644 index 000000000..e67674d25 --- /dev/null +++ b/src/popover/README.zh-CN.md @@ -0,0 +1,66 @@ +# Popover 气泡弹出框 + +### 介绍 + +### 引入 + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## 代码演示 + +### 基础用法 + +```html + +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| v-model | 是否展示气泡弹出层 | _boolean_ | `false` | +| actions | 选项列表 | _Action[]_ | `[]` | +| placement | 弹出位置 | _string_ | - | +| theme | 主题风格,可选值为 `light` | _string_ | `dark` | +| text-color | 自定义文字颜色 | _string_ | - | +| background-color | 自定义背景颜色 | _string_ | - | +| overlay | 是否显示遮罩层 | _boolean_ | `false` | +| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `false` | +| close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | +| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - | + +### Action 数据结构 + +`actions` 属性是一个由对象构成的数组,数组中的每个对象配置一列,对象可以包含以下值: + +| 键名 | 说明 | 类型 | +| --------- | ------------------------ | -------- | +| text | 文字内容 | _string_ | +| className | 为对应选项添加额外的类名 | _any_ | + +### placement 可选值 + +top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom + +### Events + +| 事件名 | 说明 | 回调参数 | +| ------ | ------------------------ | ------------------------------- | +| select | 点击选项时触发 | _action: Action, index: number_ | +| open | 打开菜单时触发 | - | +| close | 关闭菜单时触发 | - | +| opened | 打开菜单且动画结束后触发 | - | +| closed | 关闭菜单且动画结束后触发 | - | + +### Slots + +| 名称 | 说明 | +| ------- | -------------------- | +| default | 自定义菜单的展示内容 | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue new file mode 100644 index 000000000..98940a1db --- /dev/null +++ b/src/popover/demo/index.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/src/popover/index.js b/src/popover/index.js new file mode 100644 index 000000000..93b722a53 --- /dev/null +++ b/src/popover/index.js @@ -0,0 +1,76 @@ +import { createNamespace } from '../utils'; + +// Mixins +import { ClickOutsideMixin } from '../mixins/click-outside'; + +// Components +import Popup from '../popup'; + +const [createComponent, bem] = createNamespace('popover'); + +export default createComponent({ + mixins: [ + ClickOutsideMixin({ + event: 'click', + method: 'onClickOutside', + }), + ], + + props: { + value: Boolean, + overlay: Boolean, + placement: String, + textColor: String, + getContainer: [String, Function], + backgroundColor: String, + closeOnClickAction: Boolean, + theme: { + type: String, + default: 'dark', + }, + actions: { + type: Array, + default: () => [], + }, + }, + + methods: { + renderAction(action) { + return
{action.text}
; + }, + + onToggle(value) { + this.$emit('input', value); + }, + + onClickAction(action, index) { + this.$emit('select', action, index); + + if (this.closeOnClickAction) { + this.$emit('input', false); + } + }, + + onClickOutside() { + this.$emit('input', false); + }, + }, + + render() { + return ( + + + {this.actions.map(this.renderAction)} + + {this.slots('default')} + + ); + }, +}); diff --git a/src/popover/index.less b/src/popover/index.less new file mode 100644 index 000000000..a51896139 --- /dev/null +++ b/src/popover/index.less @@ -0,0 +1,61 @@ +@import '../style/var'; +@import '../style/mixins/hairline'; + +.van-popover { + position: absolute; + border-radius: @border-radius-lg; + transform: none; + transition: all 0.3s; + + &__action { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 128px; + height: 44px; + font-size: @font-size-md; + + &::after { + .hairline-bottom(@cell-border-color, @padding-md, @padding-md); + } + + &:last-child::after { + display: none; + } + } + + &--light { + color: @text-color; + background-color: @white; + box-shadow: 0 2px 12px rgba(50, 50, 51, 0.12); + + .van-popover__action { + &:active { + background-color: @active-color; + } + } + } + + &--dark { + color: @white; + background-color: @gray-8; + opacity: 0.9; + + .van-popover__action { + &::after { + border-color: @gray-7; + } + + &:active { + opacity: @active-opacity; + } + } + } + + &-zoom-enter, + &-zoom-leave-active { + transform: scale(0.8); + opacity: 0; + } +} diff --git a/src/popover/test/__snapshots__/demo.spec.js.snap b/src/popover/test/__snapshots__/demo.spec.js.snap new file mode 100644 index 000000000..7c04f9b40 --- /dev/null +++ b/src/popover/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
span: 8
+
span: 8
+
span: 8
+
+
+
span: 4
+
+ offset: 4, span: 10 +
+
+
+
+ offset: 12, span: 12 +
+
+
+
+
+
span: 8
+
span: 8
+
span: 8
+
+
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
span: 6
+
span: 6
+
span: 6
+
+
+
+`; diff --git a/src/popover/test/__snapshots__/index.spec.js.snap b/src/popover/test/__snapshots__/index.spec.js.snap new file mode 100644 index 000000000..2d4588095 --- /dev/null +++ b/src/popover/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`gutter prop 1`] = ` +
+
24
+
12
+
12
+
8
+
8
+
8
+
6
+
6
+
6
+
6
+
7
+
6
+
5
+
4
+
3
+
2
+
+`; diff --git a/src/popover/test/demo.spec.js b/src/popover/test/demo.spec.js new file mode 100644 index 000000000..5c70922b5 --- /dev/null +++ b/src/popover/test/demo.spec.js @@ -0,0 +1,4 @@ +import Demo from '../demo'; +import { snapshotDemo } from '../../../test/demo'; + +snapshotDemo(Demo); diff --git a/src/popover/test/index.spec.js b/src/popover/test/index.spec.js new file mode 100644 index 000000000..0ccd98fb1 --- /dev/null +++ b/src/popover/test/index.spec.js @@ -0,0 +1,2 @@ +// import Popover from '..'; +// import { mount } from '../../../test'; diff --git a/vant.config.js b/vant.config.js index d025939c2..d7c9046dc 100644 --- a/vant.config.js +++ b/vant.config.js @@ -275,6 +275,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar 通知栏', }, + { + path: 'popover', + title: 'Popover 气泡弹出框', + }, { path: 'progress', title: 'Progress 进度条', @@ -638,6 +642,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar', }, + { + path: 'popover', + title: 'Popover', + }, { path: 'progress', title: 'Progress', From 49a8d87845e553dfff56c2c2cc56973df499f9d9 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Tue, 17 Nov 2020 17:00:45 +0800 Subject: [PATCH 04/23] feat(Popover): using popperjs --- package.json | 1 + src/popover/demo/index.vue | 14 +++++++--- src/popover/index.js | 56 +++++++++++++++++++++++++++++++++++++- src/popover/index.less | 18 +++++++----- yarn.lock | 5 ++++ 5 files changed, 82 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 35ad5970b..d2f990b5e 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "7.x", + "@popperjs/core": "^2.5.4", "@vant/icons": "1.4.0", "@vue/babel-helper-vue-jsx-merge-props": "^1.0.0", "vue-lazyload": "1.2.3" diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 98940a1db..644a69370 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -4,9 +4,9 @@ - + {{ t('showPopover') }} @@ -17,9 +17,9 @@ v-model="show.lightTheme" theme="light" :actions="t('actions')" - placement="bottom-left" + placement="bottom" > - + {{ t('lightTheme') }} @@ -57,4 +57,10 @@ export default { diff --git a/src/popover/index.js b/src/popover/index.js index 93b722a53..39dbc01ed 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -1,4 +1,5 @@ import { createNamespace } from '../utils'; +import { createPopper } from '@popperjs/core'; // Mixins import { ClickOutsideMixin } from '../mixins/click-outside'; @@ -21,9 +22,12 @@ export default createComponent({ overlay: Boolean, placement: String, textColor: String, - getContainer: [String, Function], backgroundColor: String, closeOnClickAction: Boolean, + offset: { + type: Array, + default: [0, 0], + }, theme: { type: String, default: 'dark', @@ -32,9 +36,55 @@ export default createComponent({ type: Array, default: () => [], }, + getContainer: { + type: [String, Function], + default: 'body', + }, + }, + + data() { + return { + location: null, + }; + }, + + watch: { + value(value) { + if (value) { + this.updateLocation(); + } + }, + }, + + mounted() { + if (this.value) { + this.updateLocation(); + } }, methods: { + updateLocation() { + this.$nextTick(() => { + createPopper(this.$refs.wrapper, this.$refs.popover.$el, { + placement: this.placement, + modifiers: [ + { + name: 'computeStyles', + options: { + adaptive: false, + }, + }, + { + name: 'offset', + options: { + offset: this.offset, + }, + }, + ], + }); + }); + }, + renderAction(action) { return
{action.text}
; }, @@ -60,10 +110,14 @@ export default createComponent({ return ( diff --git a/src/popover/index.less b/src/popover/index.less index a51896139..f27fe55db 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -4,8 +4,11 @@ .van-popover { position: absolute; border-radius: @border-radius-lg; - transform: none; - transition: all 0.3s; + transition-duration: 0s; + + &__wrapper { + display: inline-block; + } &__action { position: relative; @@ -53,9 +56,10 @@ } } - &-zoom-enter, - &-zoom-leave-active { - transform: scale(0.8); - opacity: 0; - } + // &-zoom-enter, + // &-zoom-leave-active { + // transform: scale(0.8); + // opacity: 0; + // transition: all 0.3s; + // } } diff --git a/yarn.lock b/yarn.lock index dfca40127..891acde56 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1524,6 +1524,11 @@ dependencies: "@types/node" ">= 8" +"@popperjs/core@^2.5.4": + version "2.5.4" + resolved "https://registry.npm.taobao.org/@popperjs/core/download/@popperjs/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a" + integrity sha1-3iW12p9yeYWjdX/Vm10Cirp1hBo= + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" From f58fa0f7465675ecd0e51410714062ef7bace537 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Tue, 17 Nov 2020 20:48:08 +0800 Subject: [PATCH 05/23] feat(Popover): add arrow --- src/popover/demo/index.vue | 2 +- src/popover/index.js | 5 +- src/popover/index.less | 134 +++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 644a69370..07d4cfea6 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -17,7 +17,7 @@ v-model="show.lightTheme" theme="light" :actions="t('actions')" - placement="bottom" + placement="right-end" > {{ t('lightTheme') }} diff --git a/src/popover/index.js b/src/popover/index.js index 39dbc01ed..ed6e72535 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -26,7 +26,7 @@ export default createComponent({ closeOnClickAction: Boolean, offset: { type: Array, - default: [0, 0], + default: () => [0, 8], }, theme: { type: String, @@ -113,7 +113,7 @@ export default createComponent({ ref="popover" value={this.value} style={this.location} - class={bem([this.theme])} + class={bem([this.theme, `placement-${this.placement}`])} overlay={this.overlay} position="" transition="van-popover-zoom" @@ -121,6 +121,7 @@ export default createComponent({ getContainer={this.getContainer} onInput={this.onToggle} > +
{this.actions.map(this.renderAction)} {this.slots('default')} diff --git a/src/popover/index.less b/src/popover/index.less index f27fe55db..7f8a4fb7a 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -3,6 +3,7 @@ .van-popover { position: absolute; + overflow: visible; border-radius: @border-radius-lg; transition-duration: 0s; @@ -10,6 +11,15 @@ display: inline-block; } + &__arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 6px; + } + &__action { position: relative; display: flex; @@ -28,11 +38,131 @@ } } + &--placement-top, + &--placement-top-start, + &--placement-top-end { + .van-popover__arrow { + bottom: 0; + border-top-color: currentColor; + border-bottom-width: 0; + transform: translate(-50%, 100%); + } + } + + &--placement-top { + .van-popover__arrow { + left: 50%; + } + } + + &--placement-top-start { + .van-popover__arrow { + left: @padding-md; + } + } + + &--placement-top-end { + .van-popover__arrow { + right: @padding-md; + } + } + + &--placement-left, + &--placement-left-start, + &--placement-left-end { + .van-popover__arrow { + right: 0; + border-right-width: 0; + border-left-color: currentColor; + transform: translate(100%, -50%); + } + } + + &--placement-left { + .van-popover__arrow { + top: 50%; + } + } + + &--placement-left-start { + .van-popover__arrow { + top: @padding-md; + } + } + + &--placement-left-end { + .van-popover__arrow { + bottom: @padding-md; + } + } + + &--placement-right, + &--placement-right-start, + &--placement-right-end { + .van-popover__arrow { + left: 0; + border-right-color: currentColor; + border-left-width: 0; + transform: translate(-100%, -50%); + } + } + + &--placement-right { + .van-popover__arrow { + top: 50%; + } + } + + &--placement-right-start { + .van-popover__arrow { + top: @padding-md; + } + } + + &--placement-right-end { + .van-popover__arrow { + bottom: @padding-md; + } + } + + &--placement-bottom, + &--placement-bottom-start, + &--placement-bottom-end { + .van-popover__arrow { + top: 0; + border-top-width: 0; + border-bottom-color: currentColor; + transform: translate(-50%, -100%); + } + } + + &--placement-bottom { + .van-popover__arrow { + left: 50%; + } + } + + &--placement-bottom-start { + .van-popover__arrow { + left: @padding-md; + } + } + + &--placement-bottom-end { + .van-popover__arrow { + right: @padding-md; + } + } + &--light { color: @text-color; background-color: @white; box-shadow: 0 2px 12px rgba(50, 50, 51, 0.12); + .van-popover__arrow { + color: @white; + } + .van-popover__action { &:active { background-color: @active-color; @@ -45,6 +175,10 @@ background-color: @gray-8; opacity: 0.9; + .van-popover__arrow { + color: @gray-8; + } + .van-popover__action { &::after { border-color: @gray-7; From 03fd1f297d0c325160eb9116783f9f291f7b3557 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 10:05:34 +0800 Subject: [PATCH 06/23] docs(Popover): add choose placement demo --- src/popover/README.zh-CN.md | 2 +- src/popover/demo/index.vue | 115 ++++++++++++++++++++++++++++++------ src/popover/index.js | 12 +++- src/style/demo/index.vue | 2 +- 4 files changed, 109 insertions(+), 22 deletions(-) diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md index e67674d25..3b582b61f 100644 --- a/src/popover/README.zh-CN.md +++ b/src/popover/README.zh-CN.md @@ -28,7 +28,7 @@ Vue.use(Popover); | v-model | 是否展示气泡弹出层 | _boolean_ | `false` | | actions | 选项列表 | _Action[]_ | `[]` | | placement | 弹出位置 | _string_ | - | -| theme | 主题风格,可选值为 `light` | _string_ | `dark` | +| theme | 主题风格,可选值为 `dark` | _string_ | `light` | | text-color | 自定义文字颜色 | _string_ | - | | background-color | 自定义背景颜色 | _string_ | - | | overlay | 是否显示遮罩层 | _boolean_ | `false` | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 07d4cfea6..fa57dfdad 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -2,27 +2,62 @@ - - {{ t('showPopover') }} - - - - - - {{ t('lightTheme') }} + + + {{ t('darkTheme') }} + + + + + + + + + + + +
+ +
+ +
@@ -32,26 +67,54 @@ export default { i18n: { 'zh-CN': { actions: [{ text: '文本' }, { text: '文本' }, { text: '文本' }], + placement: '弹出位置', + darkTheme: '深色风格', lightTheme: '浅色风格', showPopover: '点击弹出气泡', + choosePlacement: '选择弹出位置', }, 'en-US': { actions: [{ text: 'Text' }, { text: 'Text' }, { text: 'Text' }], + placement: 'Placement', + darkTheme: 'Dark Theme', lightTheme: 'Light Theme', showPopover: 'Show Popover', + choosePlacement: 'Choose Placement', }, }, data() { return { show: { - basic: false, + placement: false, + darkTheme: false, lightTheme: false, }, + showPicker: false, + currentPlacement: 'top', + placements: [ + 'top', + 'top-start', + 'top-end', + 'left', + 'left-start', + 'left-end', + 'right', + 'right-start', + 'right-end', + 'bottom', + 'bottom-start', + 'bottom-end', + ], }; }, - methods: {}, + methods: { + onConfirm(value) { + this.showPicker = false; + this.currentPlacement = value; + }, + }, }; @@ -59,8 +122,24 @@ export default { @import '../../style/var'; .demo-popover { - .van-popover__wrapper { - margin-left: @padding-md; + &-refer { + width: 60px; + height: 60px; + background-color: @blue; + border-radius: 8px; + } + + .van-field { + width: auto; + margin: 0 12px; + overflow: hidden; + border-radius: 8px; + } + + &-box { + display: flex; + justify-content: center; + margin-top: 160px; } } diff --git a/src/popover/index.js b/src/popover/index.js index ed6e72535..981b89862 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -30,7 +30,7 @@ export default createComponent({ }, theme: { type: String, - default: 'dark', + default: 'light', }, actions: { type: Array, @@ -49,6 +49,8 @@ export default createComponent({ }, watch: { + placement: 'updateLocation', + value(value) { if (value) { this.updateLocation(); @@ -93,6 +95,11 @@ export default createComponent({ this.$emit('input', value); }, + onClick(event) { + event.stopPropagation(); + this.$emit('click', event); + }, + onClickAction(action, index) { this.$emit('select', action, index); @@ -115,11 +122,12 @@ export default createComponent({ style={this.location} class={bem([this.theme, `placement-${this.placement}`])} overlay={this.overlay} - position="" + position={null} transition="van-popover-zoom" lockScroll={false} getContainer={this.getContainer} onInput={this.onToggle} + onClick={this.onClick} >
{this.actions.map(this.renderAction)} diff --git a/src/style/demo/index.vue b/src/style/demo/index.vue index df01ad4a7..7ca53cfed 100644 --- a/src/style/demo/index.vue +++ b/src/style/demo/index.vue @@ -104,7 +104,7 @@ export default { height: 100px; margin: -50px 0 0 -50px; background-color: @blue; - border-radius: 3px; + border-radius: 8px; } } From 7b51efa5726ab9bd32022f5aaf67609b1012b739 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:04:23 +0800 Subject: [PATCH 07/23] feat(Popover): support add icon --- src/popover/README.zh-CN.md | 13 ++++--- src/popover/demo/index.vue | 40 ++++++++++++++++++--- src/popover/index.js | 69 ++++++++++++++++++++++++----------- src/popover/index.less | 71 ++++++++++++++++++++----------------- 4 files changed, 129 insertions(+), 64 deletions(-) diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md index 3b582b61f..cbdb6af8f 100644 --- a/src/popover/README.zh-CN.md +++ b/src/popover/README.zh-CN.md @@ -29,10 +29,8 @@ Vue.use(Popover); | actions | 选项列表 | _Action[]_ | `[]` | | placement | 弹出位置 | _string_ | - | | theme | 主题风格,可选值为 `dark` | _string_ | `light` | -| text-color | 自定义文字颜色 | _string_ | - | -| background-color | 自定义背景颜色 | _string_ | - | | overlay | 是否显示遮罩层 | _boolean_ | `false` | -| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `false` | +| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `true` | | close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | | get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - | @@ -40,10 +38,11 @@ Vue.use(Popover); `actions` 属性是一个由对象构成的数组,数组中的每个对象配置一列,对象可以包含以下值: -| 键名 | 说明 | 类型 | -| --------- | ------------------------ | -------- | -| text | 文字内容 | _string_ | -| className | 为对应选项添加额外的类名 | _any_ | +| 键名 | 说明 | 类型 | +| --- | --- | --- | +| text | 文字内容 | _string_ | +| icon | 文字左侧的图标,支持传入[图标名称](#/zh-CN/icon)或图片链接 | _string_ | +| className | 为对应选项添加额外的类名 | _any_ | ### placement 可选值 diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index fa57dfdad..2f4ea5762 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -52,13 +52,26 @@
+ + + + + {{ t('showPopover') }} + + + @@ -66,7 +79,14 @@ export default { i18n: { 'zh-CN': { - actions: [{ text: '文本' }, { text: '文本' }, { text: '文本' }], + actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }], + shortActions: [{ text: '选项一' }, { text: '选项二' }], + actionsWithIcon: [ + { text: '选项一', icon: 'add-o' }, + { text: '选项二', icon: 'music-o' }, + { text: '选项三', icon: 'more-o' }, + ], + showIcon: '展示图标', placement: '弹出位置', darkTheme: '深色风格', lightTheme: '浅色风格', @@ -74,7 +94,18 @@ export default { choosePlacement: '选择弹出位置', }, 'en-US': { - actions: [{ text: 'Text' }, { text: 'Text' }, { text: 'Text' }], + actions: [ + { text: 'Option 1' }, + { text: 'Option 2' }, + { text: 'Option 3' }, + ], + shortActions: [{ text: 'Option 1' }, { text: 'Option 2' }], + actionsWithIcon: [ + { text: 'Option 1', icon: 'add-o' }, + { text: 'Option 2', icon: 'music-o' }, + { text: 'Option 3', icon: 'more-o' }, + ], + showIcon: 'Show Icon', placement: 'Placement', darkTheme: 'Dark Theme', lightTheme: 'Light Theme', @@ -86,6 +117,7 @@ export default { data() { return { show: { + showIcon: false, placement: false, darkTheme: false, lightTheme: false, @@ -139,7 +171,7 @@ export default { &-box { display: flex; justify-content: center; - margin-top: 160px; + margin: 110px 0 80px; } } diff --git a/src/popover/index.js b/src/popover/index.js index 981b89862..775cc1b3c 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -1,10 +1,12 @@ -import { createNamespace } from '../utils'; import { createPopper } from '@popperjs/core'; +import { createNamespace } from '../utils'; +import { BORDER_BOTTOM } from '../utils/constant'; // Mixins import { ClickOutsideMixin } from '../mixins/click-outside'; // Components +import Icon from '../icon'; import Popup from '../popup'; const [createComponent, bem] = createNamespace('popover'); @@ -23,7 +25,6 @@ export default createComponent({ placement: String, textColor: String, backgroundColor: String, - closeOnClickAction: Boolean, offset: { type: Array, default: () => [0, 8], @@ -40,6 +41,10 @@ export default createComponent({ type: [String, Function], default: 'body', }, + closeOnClickAction: { + type: Boolean, + default: true, + }, }, data() { @@ -64,31 +69,55 @@ export default createComponent({ } }, + beforeDestroy() { + if (this.popper) { + this.popper.destroy(); + this.popper = null; + } + }, + methods: { + createPopper() { + return createPopper(this.$refs.wrapper, this.$refs.popover.$el, { + placement: this.placement, + modifiers: [ + { + name: 'computeStyles', + options: { + adaptive: false, + }, + }, + { + name: 'offset', + options: { + offset: this.offset, + }, + }, + ], + }); + }, + updateLocation() { this.$nextTick(() => { - createPopper(this.$refs.wrapper, this.$refs.popover.$el, { - placement: this.placement, - modifiers: [ - { - name: 'computeStyles', - options: { - adaptive: false, - }, - }, - { - name: 'offset', - options: { - offset: this.offset, - }, - }, - ], - }); + if (!this.popper) { + this.popper = this.createPopper(); + } else { + this.popper.setOptions({ + placement: this.placement, + }); + } }); }, renderAction(action) { - return
{action.text}
; + return ( +
+ {action.icon && ( + + )} +
{action.text}
+
+ ); }, onToggle(value) { diff --git a/src/popover/index.less b/src/popover/index.less index 7f8a4fb7a..5ef0cc9c4 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -24,23 +24,32 @@ position: relative; display: flex; align-items: center; - justify-content: center; + box-sizing: border-box; width: 128px; height: 44px; + padding: 0 @padding-md; font-size: @font-size-md; - &::after { - .hairline-bottom(@cell-border-color, @padding-md, @padding-md); + &:last-child { + .van-popover__action-text::after { + display: none; + } } - &:last-child::after { - display: none; + &-text { + display: flex; + flex: 1; + align-items: center; + justify-content: center; + height: 100%; + } + + &-icon { + font-size: 16px; } } - &--placement-top, - &--placement-top-start, - &--placement-top-end { + &[data-popper-placement^='top'] { .van-popover__arrow { bottom: 0; border-top-color: currentColor; @@ -49,27 +58,25 @@ } } - &--placement-top { + &[data-popper-placement='top'] { .van-popover__arrow { left: 50%; } } - &--placement-top-start { + &[data-popper-placement='top-start'] { .van-popover__arrow { left: @padding-md; } } - &--placement-top-end { + &[data-popper-placement='top-end'] { .van-popover__arrow { right: @padding-md; } } - &--placement-left, - &--placement-left-start, - &--placement-left-end { + &[data-popper-placement^='left'] { .van-popover__arrow { right: 0; border-right-width: 0; @@ -78,27 +85,25 @@ } } - &--placement-left { + &[data-popper-placement='left'] { .van-popover__arrow { top: 50%; } } - &--placement-left-start { + &[data-popper-placement='left-start'] { .van-popover__arrow { top: @padding-md; } } - &--placement-left-end { + &[data-popper-placement='left-end'] { .van-popover__arrow { bottom: @padding-md; } } - &--placement-right, - &--placement-right-start, - &--placement-right-end { + &[data-popper-placement^='right'] { .van-popover__arrow { left: 0; border-right-color: currentColor; @@ -107,27 +112,25 @@ } } - &--placement-right { + &[data-popper-placement='right'] { .van-popover__arrow { top: 50%; } } - &--placement-right-start { + &[data-popper-placement='right-start'] { .van-popover__arrow { top: @padding-md; } } - &--placement-right-end { + &[data-popper-placement='right-end'] { .van-popover__arrow { bottom: @padding-md; } } - &--placement-bottom, - &--placement-bottom-start, - &--placement-bottom-end { + &[data-popper-placement^='bottom'] { .van-popover__arrow { top: 0; border-top-width: 0; @@ -136,19 +139,19 @@ } } - &--placement-bottom { + &[data-popper-placement='bottom'] { .van-popover__arrow { left: 50%; } } - &--placement-bottom-start { + &[data-popper-placement='bottom-start'] { .van-popover__arrow { left: @padding-md; } } - &--placement-bottom-end { + &[data-popper-placement='bottom-end'] { .van-popover__arrow { right: @padding-md; } @@ -180,14 +183,16 @@ } .van-popover__action { - &::after { - border-color: @gray-7; - } - &:active { opacity: @active-opacity; } } + + .van-popover__action-text { + &::after { + border-color: @gray-7; + } + } } // &-zoom-enter, From ae29b095206c0848131ef8a63d7d227915fa03b4 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:19:10 +0800 Subject: [PATCH 08/23] perf(Popover): using popper lite --- src/popover/index.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/popover/index.js b/src/popover/index.js index 775cc1b3c..be194ab56 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -1,4 +1,5 @@ -import { createPopper } from '@popperjs/core'; +import { createPopper } from '@popperjs/core/lib/popper-lite'; +import offsetModifier from '@popperjs/core/lib/modifiers/offset'; import { createNamespace } from '../utils'; import { BORDER_BOTTOM } from '../utils/constant'; @@ -88,7 +89,7 @@ export default createComponent({ }, }, { - name: 'offset', + ...offsetModifier, options: { offset: this.offset, }, @@ -110,12 +111,14 @@ export default createComponent({ }, renderAction(action) { + const { icon, text, disabled, className } = action; return ( -
- {action.icon && ( - - )} -
{action.text}
+
+ {icon && } +
{text}
); }, From 699a5ebe51b2448e04d8aaef58eb833ce27d3dbb Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:29:24 +0800 Subject: [PATCH 09/23] feat(Popover): add disabled option --- src/popover/README.zh-CN.md | 9 +++------ src/popover/demo/index.vue | 32 +++++++++++++++++++++++++++++--- src/popover/index.js | 8 ++++++-- src/popover/index.less | 19 ++++++++++++++++++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md index cbdb6af8f..c57c34be8 100644 --- a/src/popover/README.zh-CN.md +++ b/src/popover/README.zh-CN.md @@ -32,7 +32,7 @@ Vue.use(Popover); | overlay | 是否显示遮罩层 | _boolean_ | `false` | | close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `true` | | close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | -| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | - | +| get-container `v2.4.4` | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | `body` | ### Action 数据结构 @@ -40,14 +40,11 @@ Vue.use(Popover); | 键名 | 说明 | 类型 | | --- | --- | --- | -| text | 文字内容 | _string_ | +| text | 选项文字 | _string_ | | icon | 文字左侧的图标,支持传入[图标名称](#/zh-CN/icon)或图片链接 | _string_ | +| disabled | 是否为禁用状态 | _boolean_ | | className | 为对应选项添加额外的类名 | _any_ | -### placement 可选值 - -top left right bottom topLeft topRight bottomLeft bottomRight leftTop leftBottom rightTop rightBottom - ### Events | 事件名 | 说明 | 回调参数 | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 2f4ea5762..3d470819c 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -60,15 +60,26 @@
- + - {{ t('showPopover') }} + {{ t('showIcon') }} + + + + + + {{ t('disabled') }} @@ -86,11 +97,17 @@ export default { { text: '选项二', icon: 'music-o' }, { text: '选项三', icon: 'more-o' }, ], + actionsDisabled: [ + { text: '选项一', disabled: true }, + { text: '选项二', disabled: true }, + { text: '选项三' }, + ], showIcon: '展示图标', placement: '弹出位置', darkTheme: '深色风格', lightTheme: '浅色风格', showPopover: '点击弹出气泡', + actionOptions: '选项配置', choosePlacement: '选择弹出位置', }, 'en-US': { @@ -105,11 +122,17 @@ export default { { text: 'Option 2', icon: 'music-o' }, { text: 'Option 3', icon: 'more-o' }, ], + actionsDisabled: [ + { text: 'Option 1', disabled: true }, + { text: 'Option 2', disabled: true }, + { text: 'Option 3' }, + ], showIcon: 'Show Icon', placement: 'Placement', darkTheme: 'Dark Theme', lightTheme: 'Light Theme', showPopover: 'Show Popover', + actionOptions: 'Action Options', choosePlacement: 'Choose Placement', }, }, @@ -117,6 +140,7 @@ export default { data() { return { show: { + disabled: false, showIcon: false, placement: false, darkTheme: false, @@ -154,6 +178,8 @@ export default { @import '../../style/var'; .demo-popover { + min-height: 200vh; + &-refer { width: 60px; height: 60px; diff --git a/src/popover/index.js b/src/popover/index.js index be194ab56..7c362c14d 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -110,12 +110,12 @@ export default createComponent({ }); }, - renderAction(action) { + renderAction(action, index) { const { icon, text, disabled, className } = action; return (
this.onClickAction(action, index)} > {icon && }
{text}
@@ -133,6 +133,10 @@ export default createComponent({ }, onClickAction(action, index) { + if (action.disabled) { + return; + } + this.$emit('select', action, index); if (this.closeOnClickAction) { diff --git a/src/popover/index.less b/src/popover/index.less index 5ef0cc9c4..01d6b8677 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -29,6 +29,7 @@ height: 44px; padding: 0 @padding-md; font-size: @font-size-md; + line-height: @line-height-md; &:last-child { .van-popover__action-text::after { @@ -170,6 +171,14 @@ &:active { background-color: @active-color; } + + &--disabled { + color: @gray-5; + + &:active { + background-color: transparent; + } + } } } @@ -184,7 +193,15 @@ .van-popover__action { &:active { - opacity: @active-opacity; + background-color: rgba(0, 0, 0, 0.2); + } + + &--disabled { + color: @gray-7; + + &:active { + background-color: transparent; + } } } From 64e17bcd082cebc630bbdbb337caee0bd40d4369 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:32:56 +0800 Subject: [PATCH 10/23] chore(Popover): change name of default slot to reference --- src/popover/README.zh-CN.md | 6 +++--- src/popover/demo/index.vue | 36 +++++++++++++++++++++++------------- src/popover/index.js | 2 +- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md index c57c34be8..40abfde06 100644 --- a/src/popover/README.zh-CN.md +++ b/src/popover/README.zh-CN.md @@ -57,6 +57,6 @@ Vue.use(Popover); ### Slots -| 名称 | 说明 | -| ------- | -------------------- | -| default | 自定义菜单的展示内容 | +| 名称 | 说明 | +| --------- | --------------------------- | +| reference | 触发 Popover 显示的元素内容 | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 3d470819c..2f7260536 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -7,9 +7,11 @@ placement="bottom" style="margin-left: 16px;" > - - {{ t('lightTheme') }} - + - - {{ t('darkTheme') }} - + @@ -55,7 +59,9 @@ :actions="t('shortActions')" :placement="currentPlacement" > -
+
@@ -67,9 +73,11 @@ placement="top" style="margin-left: 16px;" > - - {{ t('showIcon') }} - + - - {{ t('disabled') }} - + diff --git a/src/popover/index.js b/src/popover/index.js index 7c362c14d..b1a977526 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -168,7 +168,7 @@ export default createComponent({
{this.actions.map(this.renderAction)} - {this.slots('default')} + {this.slots('reference')} ); }, From 1302f13e7228ab3993f5d42f65b6b6e7322a4b66 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:38:02 +0800 Subject: [PATCH 11/23] feat(Popover): add more event --- src/popover/index.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/popover/index.js b/src/popover/index.js index b1a977526..6731b1713 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -147,6 +147,22 @@ export default createComponent({ onClickOutside() { this.$emit('input', false); }, + + onOpen() { + this.$emit('open'); + }, + + onOpened() { + this.$emit('opened'); + }, + + onClose() { + this.$emit('close'); + }, + + onClosed() { + this.$emit('closed'); + }, }, render() { @@ -162,8 +178,12 @@ export default createComponent({ transition="van-popover-zoom" lockScroll={false} getContainer={this.getContainer} - onInput={this.onToggle} + onOpen={this.onOpen} onClick={this.onClick} + onClose={this.onClose} + onInput={this.onToggle} + onOpened={this.onOpened} + onClosed={this.onClosed} >
{this.actions.map(this.renderAction)} From 6d670935897830041776c80b900c068e9804c460 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Wed, 18 Nov 2020 15:49:11 +0800 Subject: [PATCH 12/23] style(Popover): adjust dark theme background color --- src/popover/index.js | 2 +- src/popover/index.less | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/popover/index.js b/src/popover/index.js index 6731b1713..5a1ed6bd4 100644 --- a/src/popover/index.js +++ b/src/popover/index.js @@ -172,7 +172,7 @@ export default createComponent({ ref="popover" value={this.value} style={this.location} - class={bem([this.theme, `placement-${this.placement}`])} + class={bem([this.theme])} overlay={this.overlay} position={null} transition="van-popover-zoom" diff --git a/src/popover/index.less b/src/popover/index.less index 01d6b8677..99b4e2fb1 100644 --- a/src/popover/index.less +++ b/src/popover/index.less @@ -184,8 +184,7 @@ &--dark { color: @white; - background-color: @gray-8; - opacity: 0.9; + background-color: #4a4a4a; .van-popover__arrow { color: @gray-8; From acf92e1fea55b9539b00ae20ab77f72aee27e416 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Thu, 19 Nov 2020 14:26:37 +0800 Subject: [PATCH 13/23] feat(Popover): add animation --- src/popover/demo/index.vue | 14 +++++---- src/popover/index.js | 14 ++++----- src/popover/index.less | 58 +++++++++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 23 deletions(-) diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue index 2f7260536..a5710dbbf 100644 --- a/src/popover/demo/index.vue +++ b/src/popover/demo/index.vue @@ -4,7 +4,7 @@