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: { // 直接覆盖变量 diff --git a/package.json b/package.json index 0c422cc63..83427ac82 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "license": "MIT", "dependencies": { "@babel/runtime": "7.x", + "@popperjs/core": "^2.5.4", "@vant/icons": "1.4.0", "@vant/use": "^0.1.0", "vue-lazyload": "1.2.3" diff --git a/src/popover/README.md b/src/popover/README.md new file mode 100644 index 000000000..4d9499ece --- /dev/null +++ b/src/popover/README.md @@ -0,0 +1,195 @@ +# Popover + +### Install + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## Usage + +### Basic Usage + +```html + + + +``` + +```js +import { Toast } from 'vant'; + +export default { + data() { + return { + showPopover: false, + actions: [ + { text: 'Option 1' }, + { text: 'Option 2' }, + { text: 'Option 3' }, + ], + }; + }, + methods: { + onSelect(action) { + Toast(action.text); + }, + }, +}; +``` + +### Dark theme + +Using the `theme` prop to change the style of Popover. + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [ + { text: 'Option 1' }, + { text: 'Option 2' }, + { text: 'Option 3' }, + ], + }; + }, +}; +``` + +### Placement + +```html + +``` + +`placement` supports the following values: + +```bash +top # Top middle +top-start # Top left +top-end # Top right +left # Left middle +left-start # Left top +left-end # Left bottom +right # Right middle +right-start # Right top +right-end # Right bottom +bottom # Bottom middle +bottom-start # Bottom left +bottom-end # Bottom right +``` + +### Show Icon + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [ + { text: 'Option 1', icon: 'add-o' }, + { text: 'Option 2', icon: 'music-o' }, + { text: 'Option 3', icon: 'more-o' }, + ], + }; + }, +}; +``` + +### Disable Action + +Using the `disabled` option to disable an action. + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [ + { text: 'Option 1', disabled: true }, + { text: 'Option 2', disabled: true }, + { text: 'Option 3' }, + ], + }; + }, +}; +``` + +## API + +### Props + +| Attribute | Description | Type | Default | +| --- | --- | --- | --- | +| v-model | Whether to show Popover | _boolean_ | `false` | +| actions | Actions | _Action[]_ | `[]` | +| placement | Placement | _string_ | `bottom` | +| theme | Theme,can be set to `dark` | _string_ | `light` | +| overlay | Whether to show overlay | _boolean_ | `false` | +| close-on-click-action | Whether to close when clicking action | _boolean_ | `true` | +| close-on-click-outside | Whether to close when clicking outside | _boolean_ | `true` | +| get-container | Return the mount node for Popover | _string \| () => Element_ | `body` | + +### Data Structure of Action + +| Key | Description | Type | +| --------- | ----------------------- | --------- | +| text | Action Text | _string_ | +| icon | Icon | _string_ | +| disabled | Whether to be disabled | _boolean_ | +| className | className of the option | _any_ | + +### Events + +| Event | Description | Arguments | +| ------ | -------------------------------- | ------------------------------- | +| select | Triggered when clicking action | _action: Action, index: number_ | +| open | Triggered when opening Popover | - | +| close | Triggered when closing Popover | - | +| opened | Triggered when Popover is opened | - | +| closed | Triggered when Popover is closed | - | + +### Slots + +| Name | Description | +| --------- | ----------------- | +| default | Custom content | +| reference | Reference Element | diff --git a/src/popover/README.zh-CN.md b/src/popover/README.zh-CN.md new file mode 100644 index 000000000..12ade4c26 --- /dev/null +++ b/src/popover/README.zh-CN.md @@ -0,0 +1,239 @@ +# Popover 气泡弹出框 + +### 介绍 + +弹出式的气泡菜单。 + +### 引入 + +```js +import Vue from 'vue'; +import { Popover } from 'vant'; + +Vue.use(Popover); +``` + +## 代码演示 + +### 基础用法 + +当 Popover 弹出时,会基于 `reference` 插槽的内容进行定位。 + +```html + + + +``` + +```js +import { Toast } from 'vant'; + +export default { + data() { + return { + showPopover: false, + // 通过 actions 属性来定义菜单选项 + actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }], + }; + }, + methods: { + onSelect(action) { + Toast(action.text); + }, + }, +}; +``` + +### 深色风格 + +Popover 支持浅色和深色两种风格,默认为浅色风格,将 `theme` 属性设置为 `dark` 可切换为深色风格。 + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }], + }; + }, +}; +``` + +### 弹出位置 + +通过 `placement` 属性来控制气泡的弹出位置。 + +```html + +``` + +`placement` 支持以下值: + +```bash +top # 顶部中间位置 +top-start # 顶部左侧位置 +top-end # 顶部右侧位置 +left # 左侧中间位置 +left-start # 左侧上方位置 +left-end # 左侧下方位置 +right # 右侧中间位置 +right-start # 右侧上方位置 +right-end # 右侧下方位置 +bottom # 底部中间位置 +bottom-start # 底部左侧位置 +bottom-end # 底部右侧位置 +``` + +### 展示图标 + +在 `actions` 数组中,可以通过 `icon` 字段来定义选项的图标,支持传入[图标名称](#/zh-CN/icon)或图片链接。 + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [ + { text: '选项一', icon: 'add-o' }, + { text: '选项二', icon: 'music-o' }, + { text: '选项三', icon: 'more-o' }, + ], + }; + }, +}; +``` + +### 禁用选项 + +在 `actions` 数组中,可以通过 `disabled` 字段来禁用某个选项。 + +```html + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + actions: [ + { text: '选项一', disabled: true }, + { text: '选项二', disabled: true }, + { text: '选项三' }, + ], + }; + }, +}; +``` + +### 自定义内容 + +通过默认插槽,可以在 Popover 内部放置任意内容。 + +```html + + + + + + +``` + +```js +export default { + data() { + return { + showPopover: false, + }; + }, +}; +``` + +## API + +### Props + +| 参数 | 说明 | 类型 | 默认值 | +| --- | --- | --- | --- | +| v-model | 是否展示气泡弹出层 | _boolean_ | `false` | +| actions | 选项列表 | _Action[]_ | `[]` | +| placement | 弹出位置 | _string_ | `bottom` | +| theme | 主题风格,可选值为 `dark` | _string_ | `light` | +| overlay | 是否显示遮罩层 | _boolean_ | `false` | +| close-on-click-action | 是否在点击选项后关闭 | _boolean_ | `true` | +| close-on-click-outside | 是否在点击外部元素后关闭菜单 | _boolean_ | `true` | +| get-container | 指定挂载的节点,[用法示例](#/zh-CN/popup#zhi-ding-gua-zai-wei-zhi) | _string \| () => Element_ | `body` | + +### Action 数据结构 + +`actions` 属性是一个由对象构成的数组,数组中的每个对象配置一列,对象可以包含以下值: + +| 键名 | 说明 | 类型 | +| --- | --- | --- | +| text | 选项文字 | _string_ | +| icon | 文字左侧的图标,支持传入[图标名称](#/zh-CN/icon)或图片链接 | _string_ | +| disabled | 是否为禁用状态 | _boolean_ | +| className | 为对应选项添加额外的类名 | _any_ | + +### Events + +| 事件名 | 说明 | 回调参数 | +| ------ | ------------------------ | ------------------------------- | +| select | 点击选项时触发 | _action: Action, index: number_ | +| open | 打开菜单时触发 | - | +| close | 关闭菜单时触发 | - | +| opened | 打开菜单且动画结束后触发 | - | +| closed | 关闭菜单且动画结束后触发 | - | + +### Slots + +| 名称 | 说明 | +| --------- | --------------------------- | +| default | 自定义菜单内容 | +| reference | 触发 Popover 显示的元素内容 | diff --git a/src/popover/demo/index.vue b/src/popover/demo/index.vue new file mode 100644 index 000000000..b23669027 --- /dev/null +++ b/src/popover/demo/index.vue @@ -0,0 +1,249 @@ + + + + + diff --git a/src/popover/index.js b/src/popover/index.js new file mode 100644 index 000000000..943fda9f9 --- /dev/null +++ b/src/popover/index.js @@ -0,0 +1,201 @@ +import { createPopper } from '@popperjs/core/lib/popper-lite'; +import offsetModifier from '@popperjs/core/lib/modifiers/offset'; +import extendsHelper from '@babel/runtime/helpers/esm/extends'; +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'; + +// add Object.assign polyfill for popper.js +// see: https://popper.js.org/docs/v2/browser-support/ +/* istanbul ignore if */ +if (!Object.assign) { + Object.assign = extendsHelper; +} + +const [createComponent, bem] = createNamespace('popover'); + +export default createComponent({ + mixins: [ + ClickOutsideMixin({ + event: 'touchstart', + method: 'onClickOutside', + }), + ], + + props: { + value: Boolean, + overlay: Boolean, + textColor: String, + backgroundColor: String, + offset: { + type: Array, + default: () => [0, 8], + }, + theme: { + type: String, + default: 'light', + }, + actions: { + type: Array, + default: () => [], + }, + placement: { + type: String, + default: 'bottom', + }, + getContainer: { + type: [String, Function], + default: 'body', + }, + closeOnClickAction: { + type: Boolean, + default: true, + }, + }, + + watch: { + value: 'updateLocation', + placement: 'updateLocation', + }, + + mounted() { + this.updateLocation(); + }, + + 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, + gpuAcceleration: false, + }, + }, + { + ...offsetModifier, + options: { + offset: this.offset, + }, + }, + ], + }); + }, + + updateLocation() { + this.$nextTick(() => { + if (!this.value) { + return; + } + + if (!this.popper) { + this.popper = this.createPopper(); + } else { + this.popper.setOptions({ + placement: this.placement, + }); + } + }); + }, + + renderAction(action, index) { + const { icon, text, disabled, className } = action; + return ( +
this.onClickAction(action, index)} + > + {icon && } +
{text}
+
+ ); + }, + + onToggle(value) { + this.$emit('input', value); + }, + + onTouchstart(event) { + event.stopPropagation(); + this.$emit('touchstart', event); + }, + + onClickAction(action, index) { + if (action.disabled) { + return; + } + + this.$emit('select', action, index); + + if (this.closeOnClickAction) { + this.$emit('input', false); + } + }, + + onClickOutside() { + this.$emit('input', false); + }, + + onOpen() { + this.$emit('open'); + }, + + /* istanbul ignore next */ + onOpened() { + this.$emit('opened'); + }, + + onClose() { + this.$emit('close'); + }, + + /* istanbul ignore next */ + onClosed() { + this.$emit('closed'); + }, + }, + + render() { + return ( + + +
+
+ {this.slots('default') || this.actions.map(this.renderAction)} +
+ + {this.slots('reference')} + + ); + }, +}); diff --git a/src/popover/index.less b/src/popover/index.less new file mode 100644 index 000000000..a97e0ec6a --- /dev/null +++ b/src/popover/index.less @@ -0,0 +1,269 @@ +@import '../style/var'; +@import '../style/mixins/hairline'; + +.van-popover { + position: absolute; + overflow: visible; + background-color: transparent; + transition: opacity 0.15s, transform 0.15s; + + &__wrapper { + display: inline-block; + } + + &__arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: @popover-arrow-size; + } + + &__content { + overflow: hidden; + border-radius: @popover-border-radius; + } + + &__action { + position: relative; + display: flex; + align-items: center; + box-sizing: border-box; + width: @popover-action-width; + height: @popover-action-height; + padding: 0 @padding-md; + font-size: @popover-action-font-size; + line-height: @line-height-md; + + &:last-child { + .van-popover__action-text::after { + display: none; + } + } + + &-text { + display: flex; + flex: 1; + align-items: center; + justify-content: center; + height: 100%; + } + + &-icon { + margin-right: @padding-xs; + font-size: @popover-action-icon-size; + } + + &--with-icon { + .van-popover__action-text { + justify-content: flex-start; + } + } + } + + &[data-popper-placement^='top'] { + .van-popover__arrow { + bottom: 0; + border-top-color: currentColor; + border-bottom-width: 0; + transform: translate(-50%, 100%); + } + } + + &[data-popper-placement='top'] { + transform-origin: 50% 100%; + + .van-popover__arrow { + left: 50%; + } + } + + &[data-popper-placement='top-start'] { + transform-origin: 0 100%; + + .van-popover__arrow { + left: @padding-md; + } + } + + &[data-popper-placement='top-end'] { + transform-origin: 100% 100%; + + .van-popover__arrow { + right: @padding-md; + } + } + + &[data-popper-placement^='left'] { + .van-popover__arrow { + right: 0; + border-right-width: 0; + border-left-color: currentColor; + transform: translate(100%, -50%); + } + } + + &[data-popper-placement='left'] { + transform-origin: 100% 50%; + + .van-popover__arrow { + top: 50%; + } + } + + &[data-popper-placement='left-start'] { + transform-origin: 100% 0; + + .van-popover__arrow { + top: @padding-md; + } + } + + &[data-popper-placement='left-end'] { + transform-origin: 100% 100%; + + .van-popover__arrow { + bottom: @padding-md; + } + } + + &[data-popper-placement^='right'] { + .van-popover__arrow { + left: 0; + border-right-color: currentColor; + border-left-width: 0; + transform: translate(-100%, -50%); + } + } + + &[data-popper-placement='right'] { + transform-origin: 0 50%; + + .van-popover__arrow { + top: 50%; + } + } + + &[data-popper-placement='right-start'] { + transform-origin: 0 0; + + .van-popover__arrow { + top: @padding-md; + } + } + + &[data-popper-placement='right-end'] { + transform-origin: 0 100%; + + .van-popover__arrow { + bottom: @padding-md; + } + } + + &[data-popper-placement^='bottom'] { + .van-popover__arrow { + top: 0; + border-top-width: 0; + border-bottom-color: currentColor; + transform: translate(-50%, -100%); + } + } + + &[data-popper-placement='bottom'] { + transform-origin: 50% 0; + + .van-popover__arrow { + left: 50%; + } + } + + &[data-popper-placement='bottom-start'] { + transform-origin: 0 0; + + .van-popover__arrow { + left: @padding-md; + } + } + + &[data-popper-placement='bottom-end'] { + transform-origin: 100% 0; + + .van-popover__arrow { + right: @padding-md; + } + } + + &--light { + color: @popover-light-text-color; + + .van-popover__content { + background-color: @popover-light-background-color; + box-shadow: 0 2px 12px rgba(50, 50, 51, 0.12); + } + + .van-popover__arrow { + color: @popover-light-background-color; + } + + .van-popover__action { + &:active { + background-color: @active-color; + } + + &--disabled { + color: @popover-light-action-disabled-text-color; + + &:active { + background-color: transparent; + } + } + } + } + + &--dark { + color: @popover-dark-text-color; + + .van-popover__content { + background-color: @popover-dark-background-color; + } + + .van-popover__arrow { + color: @popover-dark-background-color; + } + + .van-popover__action { + &:active { + background-color: rgba(0, 0, 0, 0.2); + } + + &--disabled { + color: @popover-dark-action-disabled-text-color; + + &:active { + background-color: transparent; + } + } + } + + .van-popover__action-text { + &::after { + border-color: @gray-7; + } + } + } + + &-zoom-enter, + &-zoom-leave-active { + transform: scale(0.8); + opacity: 0; + } + + &-zoom-enter-active { + transition-timing-function: @animation-timing-function-enter; + } + + &-zoom-leave-active { + transition-timing-function: @animation-timing-function-leave; + } +} 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..643cfa927 --- /dev/null +++ b/src/popover/test/__snapshots__/demo.spec.js.snap @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders demo correctly 1`] = ` +
+
+
+
+
选择弹出位置
+
+
+
+ +
+
+
+
+
+`; 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..5cb3f0706 --- /dev/null +++ b/src/popover/test/__snapshots__/index.spec.js.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should allow to custom the className of action 1`] = ` +
+
Option
+
+`; + +exports[`should locate to reference element when showed 1`] = ``; + +exports[`should locate to reference element when showed 2`] = ` +
+
+
+
+`; + +exports[`should locate to reference element when showed 3`] = ` + +`; + +exports[`should watch placement prop and update location 1`] = ` +
+
+
+
+`; 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..3a64d5e6d --- /dev/null +++ b/src/popover/test/index.spec.js @@ -0,0 +1,131 @@ +import Popover from '..'; +import { later, mount, trigger } from '../../../test'; + +const baseActions = [ + { text: 'Option 1' }, + { text: 'Option 2' }, + { text: 'Option 3' }, +]; + +test('should emit select event when clicking the action', () => { + const wrapper = mount(Popover, { + propsData: { + value: true, + actions: baseActions, + }, + }); + + wrapper.find('.van-popover__action').trigger('click'); + expect(wrapper.emitted('select')[0]).toEqual([baseActions[0], 0]); +}); + +test('should not emit select event when the action is disabled', () => { + const wrapper = mount(Popover, { + propsData: { + value: true, + actions: [{ text: 'Option', disabled: true }], + }, + }); + + wrapper.find('.van-popover__action').trigger('click'); + expect(wrapper.emitted('select')).toBeFalsy(); +}); + +test('should close popover when clicking the action', () => { + const wrapper = mount(Popover, { + propsData: { + value: true, + actions: baseActions, + }, + }); + + wrapper.find('.van-popover__action').trigger('click'); + expect(wrapper.emitted('input')[0][0]).toEqual(false); + + wrapper.setProps({ closeOnClickAction: false }); + wrapper.find('.van-popover__action').trigger('click'); + expect(wrapper.emitted('input').length).toEqual(1); +}); + +test('should allow to custom the className of action', () => { + const wrapper = mount(Popover, { + propsData: { + value: true, + actions: [{ text: 'Option', className: 'foo' }], + }, + }); + + expect(wrapper.find('.van-popover__action').html()).toMatchSnapshot(); +}); + +test('should not init popper.js instance before showed', async () => { + const wrapper = mount(Popover); + expect(wrapper.vm.popper).toBeFalsy(); + wrapper.destroy(); +}); + +test('should destroy popper.js instance when unmouted', async () => { + const wrapper = mount(Popover, { + propsData: { + value: true, + }, + }); + + await later(); + expect(wrapper.vm.popper).toBeTruthy(); + wrapper.destroy(); + expect(wrapper.vm.popper).toEqual(null); +}); + +test('should locate to reference element when showed', async () => { + const root = document.createElement('div'); + const wrapper = mount(Popover, { + propsData: { + getContainer: () => root, + }, + }); + + expect(root.innerHTML).toMatchSnapshot(); + + wrapper.setProps({ value: true }); + await later(); + expect(root.innerHTML).toMatchSnapshot(); + + wrapper.setProps({ value: false }); + expect(root.innerHTML).toMatchSnapshot(); +}); + +test('should watch placement prop and update location', async () => { + const root = document.createElement('div'); + const wrapper = mount(Popover, { + propsData: { + value: true, + getContainer: () => root, + }, + }); + + wrapper.setProps({ + placement: 'top', + }); + + await later(); + expect(root.innerHTML).toMatchSnapshot(); +}); + +test('should close popover when touch outside content', async () => { + const root = document.createElement('div'); + const wrapper = mount(Popover, { + propsData: { + value: true, + getContainer: () => root, + }, + }); + + const popover = root.querySelector('.van-popover'); + trigger(popover, 'touchstart'); + expect(wrapper.emitted('input')).toBeFalsy(); + + document.body.appendChild(root); + trigger(document.body, 'touchstart'); + expect(wrapper.emitted('input')[0][0]).toEqual(false); +}); diff --git a/src/popup/index.less b/src/popup/index.less index 88eec745b..cf9dddeb2 100644 --- a/src/popup/index.less +++ b/src/popup/index.less @@ -72,14 +72,14 @@ &-slide-left-enter-active, &-slide-right-enter-active, &-slide-bottom-enter-active { - transition-timing-function: ease-out; + transition-timing-function: @animation-timing-function-enter; } &-slide-top-leave-active, &-slide-left-leave-active, &-slide-right-leave-active, &-slide-bottom-leave-active { - transition-timing-function: ease-in; + transition-timing-function: @animation-timing-function-leave; } &-slide-top-enter-from, diff --git a/src/style/demo/index.vue b/src/style/demo/index.vue index 8f7fbea01..959d8e27a 100644 --- a/src/style/demo/index.vue +++ b/src/style/demo/index.vue @@ -98,7 +98,7 @@ export default { height: 100px; margin: -50px 0 0 -50px; background-color: @blue; - border-radius: 3px; + border-radius: 8px; } } diff --git a/src/style/var.less b/src/style/var.less index 6738d6f89..f881793f4 100644 --- a/src/style/var.less +++ b/src/style/var.less @@ -550,6 +550,21 @@ @picker-loading-icon-color: @blue; @picker-loading-mask-color: rgba(255, 255, 255, 0.9); +// Popover +@popover-arrow-size: 6px; +@popover-border-radius: @border-radius-lg; +@popover-action-width: 128px; +@popover-action-height: 44px; +@popover-action-font-size: @font-size-md; +@popover-action-line-height: @line-height-md; +@popover-action-icon-size: 20px; +@popover-light-text-color: @text-color; +@popover-light-background-color: @white; +@popover-light-action-disabled-text-color: @gray-5; +@popover-dark-text-color: @white; +@popover-dark-background-color: #4a4a4a; +@popover-dark-action-disabled-text-color: @gray-6; + // Popup @popup-background-color: @white; @popup-transition: transform @animation-duration-base; diff --git a/types/index.d.ts b/types/index.d.ts index 35631a6c5..4a41ea3ea 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -66,6 +66,7 @@ export class Overlay extends VanComponent {} export class Pagination extends VanComponent {} export class Panel extends VanComponent {} export class PasswordInput extends VanComponent {} +export class Popover extends VanComponent {} export class Popup extends VanComponent {} export class PullRefresh extends VanComponent {} export class Radio extends VanComponent {} diff --git a/vant.config.js b/vant.config.js index 0df4f0e4e..a8ff72d9b 100644 --- a/vant.config.js +++ b/vant.config.js @@ -286,6 +286,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar 通知栏', }, + { + path: 'popover', + title: 'Popover 气泡弹出框', + }, { path: 'progress', title: 'Progress 进度条', @@ -632,6 +636,10 @@ module.exports = { path: 'notice-bar', title: 'NoticeBar', }, + { + path: 'popover', + title: 'Popover', + }, { path: 'progress', title: 'Progress', diff --git a/yarn.lock b/yarn.lock index 8643d67e1..fa9f9153e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1319,6 +1319,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"