mirror of
				https://gitee.com/vant-contrib/vant.git
				synced 2025-11-04 04:42:09 +08:00 
			
		
		
		
	Merge branch '2.x' into dev
This commit is contained in:
		
						commit
						27706b023b
					
				@ -75,7 +75,7 @@ module.exports = {
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
          loader: 'less-loader',
 | 
					          loader: 'less-loader',
 | 
				
			||||||
          options: {
 | 
					          options: {
 | 
				
			||||||
            // 若使用 less-loader@5,请移除 lessOptions 这一级,直接配置选项。
 | 
					            // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
 | 
				
			||||||
            lessOptions: {
 | 
					            lessOptions: {
 | 
				
			||||||
              modifyVars: {
 | 
					              modifyVars: {
 | 
				
			||||||
                // 直接覆盖变量
 | 
					                // 直接覆盖变量
 | 
				
			||||||
@ -101,7 +101,7 @@ module.exports = {
 | 
				
			|||||||
  css: {
 | 
					  css: {
 | 
				
			||||||
    loaderOptions: {
 | 
					    loaderOptions: {
 | 
				
			||||||
      less: {
 | 
					      less: {
 | 
				
			||||||
        // 若使用 less-loader@5,请移除 lessOptions 这一级,直接配置选项。
 | 
					        // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
 | 
				
			||||||
        lessOptions: {
 | 
					        lessOptions: {
 | 
				
			||||||
          modifyVars: {
 | 
					          modifyVars: {
 | 
				
			||||||
            // 直接覆盖变量
 | 
					            // 直接覆盖变量
 | 
				
			||||||
 | 
				
			|||||||
@ -58,6 +58,7 @@
 | 
				
			|||||||
  "license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "@babel/runtime": "7.x",
 | 
					    "@babel/runtime": "7.x",
 | 
				
			||||||
 | 
					    "@popperjs/core": "^2.5.4",
 | 
				
			||||||
    "@vant/icons": "1.4.0",
 | 
					    "@vant/icons": "1.4.0",
 | 
				
			||||||
    "@vant/use": "^0.1.0",
 | 
					    "@vant/use": "^0.1.0",
 | 
				
			||||||
    "vue-lazyload": "1.2.3"
 | 
					    "vue-lazyload": "1.2.3"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										195
									
								
								src/popover/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								src/popover/README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,195 @@
 | 
				
			|||||||
 | 
					# Popover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import { Popover } from 'vant';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vue.use(Popover);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Basic Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions" @select="onSelect">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      Light Theme
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" theme="dark" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      Dark Theme
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      showPopover: false,
 | 
				
			||||||
 | 
					      actions: [
 | 
				
			||||||
 | 
					        { text: 'Option 1' },
 | 
				
			||||||
 | 
					        { text: 'Option 2' },
 | 
				
			||||||
 | 
					        { text: 'Option 3' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Placement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover placement="top" />
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`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
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      Show Icon
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      Disable Action
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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 |
 | 
				
			||||||
							
								
								
									
										239
									
								
								src/popover/README.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								src/popover/README.zh-CN.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,239 @@
 | 
				
			|||||||
 | 
					# Popover 气泡弹出框
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 介绍
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					弹出式的气泡菜单。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 引入
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					import Vue from 'vue';
 | 
				
			||||||
 | 
					import { Popover } from 'vant';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vue.use(Popover);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 代码演示
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 基础用法
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					当 Popover 弹出时,会基于 `reference` 插槽的内容进行定位。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions" @select="onSelect">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      浅色风格
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" theme="dark" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      深色风格
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      showPopover: false,
 | 
				
			||||||
 | 
					      actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 弹出位置
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					通过 `placement` 属性来控制气泡的弹出位置。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover placement="top" />
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`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
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      展示图标
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      showPopover: false,
 | 
				
			||||||
 | 
					      actions: [
 | 
				
			||||||
 | 
					        { text: '选项一', icon: 'add-o' },
 | 
				
			||||||
 | 
					        { text: '选项二', icon: 'music-o' },
 | 
				
			||||||
 | 
					        { text: '选项三', icon: 'more-o' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 禁用选项
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					在 `actions` 数组中,可以通过 `disabled` 字段来禁用某个选项。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover" :actions="actions">
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      禁用选项
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      showPopover: false,
 | 
				
			||||||
 | 
					      actions: [
 | 
				
			||||||
 | 
					        { text: '选项一', disabled: true },
 | 
				
			||||||
 | 
					        { text: '选项二', disabled: true },
 | 
				
			||||||
 | 
					        { text: '选项三' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 自定义内容
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					通过默认插槽,可以在 Popover 内部放置任意内容。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```html
 | 
				
			||||||
 | 
					<van-popover v-model="showPopover">
 | 
				
			||||||
 | 
					  <van-grid
 | 
				
			||||||
 | 
					    square
 | 
				
			||||||
 | 
					    clickable
 | 
				
			||||||
 | 
					    :border="false"
 | 
				
			||||||
 | 
					    column-num="3"
 | 
				
			||||||
 | 
					    style="width: 240px;"
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <van-grid-item
 | 
				
			||||||
 | 
					      v-for="i in 6"
 | 
				
			||||||
 | 
					      :key="i"
 | 
				
			||||||
 | 
					      text="选项"
 | 
				
			||||||
 | 
					      icon="photo-o"
 | 
				
			||||||
 | 
					      @click="showPopover = false"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  </van-grid>
 | 
				
			||||||
 | 
					  <template #reference>
 | 
				
			||||||
 | 
					    <van-button type="primary" @click="showPopover = true">
 | 
				
			||||||
 | 
					      自定义内容
 | 
				
			||||||
 | 
					    </van-button>
 | 
				
			||||||
 | 
					  </template>
 | 
				
			||||||
 | 
					</van-popover>
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```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 显示的元素内容 |
 | 
				
			||||||
							
								
								
									
										249
									
								
								src/popover/demo/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/popover/demo/index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,249 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <demo-section>
 | 
				
			||||||
 | 
					    <demo-block :title="t('basicUsage')">
 | 
				
			||||||
 | 
					      <van-popover
 | 
				
			||||||
 | 
					        v-model="show.lightTheme"
 | 
				
			||||||
 | 
					        :actions="t('actions')"
 | 
				
			||||||
 | 
					        placement="bottom-start"
 | 
				
			||||||
 | 
					        style="margin-left: 16px;"
 | 
				
			||||||
 | 
					        @select="onSelect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <template #reference>
 | 
				
			||||||
 | 
					          <van-button type="primary" @click="show.lightTheme = true">
 | 
				
			||||||
 | 
					            {{ t('lightTheme') }}
 | 
				
			||||||
 | 
					          </van-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </van-popover>
 | 
				
			||||||
 | 
					      <van-popover
 | 
				
			||||||
 | 
					        v-model="show.darkTheme"
 | 
				
			||||||
 | 
					        theme="dark"
 | 
				
			||||||
 | 
					        :actions="t('actions')"
 | 
				
			||||||
 | 
					        style="margin-left: 16px;"
 | 
				
			||||||
 | 
					        @select="onSelect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <template #reference>
 | 
				
			||||||
 | 
					          <van-button type="primary" @click="show.darkTheme = true">
 | 
				
			||||||
 | 
					            {{ t('darkTheme') }}
 | 
				
			||||||
 | 
					          </van-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </van-popover>
 | 
				
			||||||
 | 
					    </demo-block>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <demo-block :title="t('placement')">
 | 
				
			||||||
 | 
					      <van-field
 | 
				
			||||||
 | 
					        is-link
 | 
				
			||||||
 | 
					        readonly
 | 
				
			||||||
 | 
					        name="picker"
 | 
				
			||||||
 | 
					        :label="t('choosePlacement')"
 | 
				
			||||||
 | 
					        @click="showPicker = true"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <van-popup
 | 
				
			||||||
 | 
					        v-model="showPicker"
 | 
				
			||||||
 | 
					        round
 | 
				
			||||||
 | 
					        position="bottom"
 | 
				
			||||||
 | 
					        get-container="body"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <div class="demo-popover-box">
 | 
				
			||||||
 | 
					          <van-popover
 | 
				
			||||||
 | 
					            v-model="show.placement"
 | 
				
			||||||
 | 
					            theme="dark"
 | 
				
			||||||
 | 
					            :actions="t('shortActions')"
 | 
				
			||||||
 | 
					            :placement="currentPlacement"
 | 
				
			||||||
 | 
					            @select="onSelect"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <template #reference>
 | 
				
			||||||
 | 
					              <div class="demo-popover-refer" />
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					          </van-popover>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <van-picker :columns="placements" @change="onPickerChange" />
 | 
				
			||||||
 | 
					      </van-popup>
 | 
				
			||||||
 | 
					    </demo-block>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <demo-block :title="t('actionOptions')">
 | 
				
			||||||
 | 
					      <van-popover
 | 
				
			||||||
 | 
					        v-model="show.showIcon"
 | 
				
			||||||
 | 
					        :actions="t('actionsWithIcon')"
 | 
				
			||||||
 | 
					        placement="bottom-start"
 | 
				
			||||||
 | 
					        style="margin-left: 16px;"
 | 
				
			||||||
 | 
					        @select="onSelect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <template #reference>
 | 
				
			||||||
 | 
					          <van-button type="primary" @click="show.showIcon = true">
 | 
				
			||||||
 | 
					            {{ t('showIcon') }}
 | 
				
			||||||
 | 
					          </van-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </van-popover>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <van-popover
 | 
				
			||||||
 | 
					        v-model="show.disableAction"
 | 
				
			||||||
 | 
					        :actions="t('actionsDisabled')"
 | 
				
			||||||
 | 
					        style="margin-left: 16px;"
 | 
				
			||||||
 | 
					        @select="onSelect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <template #reference>
 | 
				
			||||||
 | 
					          <van-button type="primary" @click="show.disableAction = true">
 | 
				
			||||||
 | 
					            {{ t('disableAction') }}
 | 
				
			||||||
 | 
					          </van-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </van-popover>
 | 
				
			||||||
 | 
					    </demo-block>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <demo-block :title="t('customContent')">
 | 
				
			||||||
 | 
					      <van-popover
 | 
				
			||||||
 | 
					        v-model="show.customContent"
 | 
				
			||||||
 | 
					        placement="top-start"
 | 
				
			||||||
 | 
					        style="margin-left: 16px;"
 | 
				
			||||||
 | 
					        @select="onSelect"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <van-grid
 | 
				
			||||||
 | 
					          square
 | 
				
			||||||
 | 
					          clickable
 | 
				
			||||||
 | 
					          :border="false"
 | 
				
			||||||
 | 
					          column-num="3"
 | 
				
			||||||
 | 
					          style="width: 240px;"
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <van-grid-item
 | 
				
			||||||
 | 
					            v-for="i in 6"
 | 
				
			||||||
 | 
					            :key="i"
 | 
				
			||||||
 | 
					            icon="photo-o"
 | 
				
			||||||
 | 
					            :text="t('option')"
 | 
				
			||||||
 | 
					            @click="show.customContent = false"
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </van-grid>
 | 
				
			||||||
 | 
					        <template #reference>
 | 
				
			||||||
 | 
					          <van-button type="primary" @click="show.customContent = true">
 | 
				
			||||||
 | 
					            {{ t('customContent') }}
 | 
				
			||||||
 | 
					          </van-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </van-popover>
 | 
				
			||||||
 | 
					    </demo-block>
 | 
				
			||||||
 | 
					  </demo-section>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import Toast from '../../toast';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					  i18n: {
 | 
				
			||||||
 | 
					    'zh-CN': {
 | 
				
			||||||
 | 
					      actions: [{ text: '选项一' }, { text: '选项二' }, { text: '选项三' }],
 | 
				
			||||||
 | 
					      shortActions: [{ text: '选项一' }, { text: '选项二' }],
 | 
				
			||||||
 | 
					      actionsWithIcon: [
 | 
				
			||||||
 | 
					        { text: '选项一', icon: 'add-o' },
 | 
				
			||||||
 | 
					        { text: '选项二', icon: 'music-o' },
 | 
				
			||||||
 | 
					        { text: '选项三', icon: 'more-o' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      actionsDisabled: [
 | 
				
			||||||
 | 
					        { text: '选项一', disabled: true },
 | 
				
			||||||
 | 
					        { text: '选项二', disabled: true },
 | 
				
			||||||
 | 
					        { text: '选项三' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      showIcon: '展示图标',
 | 
				
			||||||
 | 
					      placement: '弹出位置',
 | 
				
			||||||
 | 
					      darkTheme: '深色风格',
 | 
				
			||||||
 | 
					      lightTheme: '浅色风格',
 | 
				
			||||||
 | 
					      showPopover: '点击弹出气泡',
 | 
				
			||||||
 | 
					      actionOptions: '选项配置',
 | 
				
			||||||
 | 
					      customContent: '自定义内容',
 | 
				
			||||||
 | 
					      disableAction: '禁用选项',
 | 
				
			||||||
 | 
					      choosePlacement: '选择弹出位置',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    'en-US': {
 | 
				
			||||||
 | 
					      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' },
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					      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',
 | 
				
			||||||
 | 
					      customContent: 'Custom Content',
 | 
				
			||||||
 | 
					      disableAction: 'Disable Action',
 | 
				
			||||||
 | 
					      choosePlacement: 'Placement',
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  data() {
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					      show: {
 | 
				
			||||||
 | 
					        showIcon: false,
 | 
				
			||||||
 | 
					        placement: false,
 | 
				
			||||||
 | 
					        darkTheme: false,
 | 
				
			||||||
 | 
					        lightTheme: false,
 | 
				
			||||||
 | 
					        customContent: false,
 | 
				
			||||||
 | 
					        disableAction: false,
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      showPicker: false,
 | 
				
			||||||
 | 
					      currentPlacement: '',
 | 
				
			||||||
 | 
					      placements: [
 | 
				
			||||||
 | 
					        'top',
 | 
				
			||||||
 | 
					        'top-start',
 | 
				
			||||||
 | 
					        'top-end',
 | 
				
			||||||
 | 
					        'left',
 | 
				
			||||||
 | 
					        'left-start',
 | 
				
			||||||
 | 
					        'left-end',
 | 
				
			||||||
 | 
					        'right',
 | 
				
			||||||
 | 
					        'right-start',
 | 
				
			||||||
 | 
					        'right-end',
 | 
				
			||||||
 | 
					        'bottom',
 | 
				
			||||||
 | 
					        'bottom-start',
 | 
				
			||||||
 | 
					        'bottom-end',
 | 
				
			||||||
 | 
					      ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  methods: {
 | 
				
			||||||
 | 
					    onPickerChange(picker, value) {
 | 
				
			||||||
 | 
					      setTimeout(() => {
 | 
				
			||||||
 | 
					        this.show.placement = true;
 | 
				
			||||||
 | 
					        this.currentPlacement = value;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    onSelect(action) {
 | 
				
			||||||
 | 
					      Toast(action.text);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<style lang="less">
 | 
				
			||||||
 | 
					@import '../../style/var';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.demo-popover {
 | 
				
			||||||
 | 
					  &-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: 110px 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</style>
 | 
				
			||||||
							
								
								
									
										201
									
								
								src/popover/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								src/popover/index.js
									
									
									
									
									
										Normal file
									
								
							@ -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 (
 | 
				
			||||||
 | 
					        <div
 | 
				
			||||||
 | 
					          class={[bem('action', { disabled, 'with-icon': icon }), className]}
 | 
				
			||||||
 | 
					          onClick={() => this.onClickAction(action, index)}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          {icon && <Icon name={icon} class={bem('action-icon')} />}
 | 
				
			||||||
 | 
					          <div class={[bem('action-text'), BORDER_BOTTOM]}>{text}</div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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 (
 | 
				
			||||||
 | 
					      <span ref="wrapper" class={bem('wrapper')}>
 | 
				
			||||||
 | 
					        <Popup
 | 
				
			||||||
 | 
					          ref="popover"
 | 
				
			||||||
 | 
					          value={this.value}
 | 
				
			||||||
 | 
					          class={bem([this.theme])}
 | 
				
			||||||
 | 
					          overlay={this.overlay}
 | 
				
			||||||
 | 
					          position={null}
 | 
				
			||||||
 | 
					          transition="van-popover-zoom"
 | 
				
			||||||
 | 
					          lockScroll={false}
 | 
				
			||||||
 | 
					          getContainer={this.getContainer}
 | 
				
			||||||
 | 
					          onOpen={this.onOpen}
 | 
				
			||||||
 | 
					          onClose={this.onClose}
 | 
				
			||||||
 | 
					          onInput={this.onToggle}
 | 
				
			||||||
 | 
					          onOpened={this.onOpened}
 | 
				
			||||||
 | 
					          onClosed={this.onClosed}
 | 
				
			||||||
 | 
					          nativeOnTouchstart={this.onTouchstart}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          <div class={bem('arrow')} />
 | 
				
			||||||
 | 
					          <div class={bem('content')}>
 | 
				
			||||||
 | 
					            {this.slots('default') || this.actions.map(this.renderAction)}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </Popup>
 | 
				
			||||||
 | 
					        {this.slots('reference')}
 | 
				
			||||||
 | 
					      </span>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										269
									
								
								src/popover/index.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								src/popover/index.less
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/popover/test/__snapshots__/demo.spec.js.snap
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/popover/test/__snapshots__/demo.spec.js.snap
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`renders demo correctly 1`] = `
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					  <div><span class="van-popover__wrapper" style="margin-left: 16px;"><button class="van-button van-button--primary van-button--normal"><div class="van-button__content"><span class="van-button__text">
 | 
				
			||||||
 | 
					          浅色风格
 | 
				
			||||||
 | 
					        </span></div></button></span> <span class="van-popover__wrapper" style="margin-left: 16px;"><button class="van-button van-button--primary van-button--normal"><div class="van-button__content"><span class="van-button__text">
 | 
				
			||||||
 | 
					          深色风格
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					</div></button></span></div>
 | 
				
			||||||
 | 
					<div>
 | 
				
			||||||
 | 
					  <div role="button" tabindex="0" class="van-cell van-cell--clickable van-field">
 | 
				
			||||||
 | 
					    <div class="van-cell__title van-field__label"><span>选择弹出位置</span></div>
 | 
				
			||||||
 | 
					    <div class="van-cell__value van-field__value">
 | 
				
			||||||
 | 
					      <div class="van-field__body"><input type="text" name="picker" readonly="readonly" class="van-field__control"></div>
 | 
				
			||||||
 | 
					    </div><i class="van-icon van-icon-arrow van-cell__right-icon">
 | 
				
			||||||
 | 
					      <!----></i>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<div><span class="van-popover__wrapper" style="margin-left: 16px;"><button class="van-button van-button--primary van-button--normal"><div class="van-button__content"><span class="van-button__text">
 | 
				
			||||||
 | 
					          展示图标
 | 
				
			||||||
 | 
					        </span></div></button></span> <span class="van-popover__wrapper" style="margin-left: 16px;"><button class="van-button van-button--primary van-button--normal"><div class="van-button__content"><span class="van-button__text">
 | 
				
			||||||
 | 
					          禁用选项
 | 
				
			||||||
 | 
					        </span></div></button></span></div>
 | 
				
			||||||
 | 
					<div><span class="van-popover__wrapper" style="margin-left: 16px;"><button class="van-button van-button--primary van-button--normal"><div class="van-button__content"><span class="van-button__text">
 | 
				
			||||||
 | 
					          自定义内容
 | 
				
			||||||
 | 
					        </span></div></button></span></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										30
									
								
								src/popover/test/__snapshots__/index.spec.js.snap
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/popover/test/__snapshots__/index.spec.js.snap
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`should allow to custom the className of action 1`] = `
 | 
				
			||||||
 | 
					<div class="van-popover__action foo">
 | 
				
			||||||
 | 
					  <div class="van-popover__action-text van-hairline--bottom">Option</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`should locate to reference element when showed 1`] = `<!---->`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`should locate to reference element when showed 2`] = `
 | 
				
			||||||
 | 
					<div class="van-popup van-popover van-popover--light" name="van-popover-zoom" style="position: absolute; left: 0px; top: 8px; margin: 0px; z-index: 2006;" data-popper-placement="bottom">
 | 
				
			||||||
 | 
					  <div class="van-popover__arrow"></div>
 | 
				
			||||||
 | 
					  <div class="van-popover__content"></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`should locate to reference element when showed 3`] = `
 | 
				
			||||||
 | 
					<div class="van-popup van-popover van-popover--light" name="van-popover-zoom" style="position: absolute; left: 0px; top: 8px; margin: 0px; z-index: 2006; display: none;" data-popper-placement="bottom">
 | 
				
			||||||
 | 
					  <div class="van-popover__arrow"></div>
 | 
				
			||||||
 | 
					  <div class="van-popover__content"></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exports[`should watch placement prop and update location 1`] = `
 | 
				
			||||||
 | 
					<div class="van-popup van-popover van-popover--light" name="van-popover-zoom" style="z-index: 2007; position: absolute; left: 0px; top: -8px; margin: 0px;" data-popper-placement="top">
 | 
				
			||||||
 | 
					  <div class="van-popover__arrow"></div>
 | 
				
			||||||
 | 
					  <div class="van-popover__content"></div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					`;
 | 
				
			||||||
							
								
								
									
										4
									
								
								src/popover/test/demo.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/popover/test/demo.spec.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					import Demo from '../demo';
 | 
				
			||||||
 | 
					import { snapshotDemo } from '../../../test/demo';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					snapshotDemo(Demo);
 | 
				
			||||||
							
								
								
									
										131
									
								
								src/popover/test/index.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								src/popover/test/index.spec.js
									
									
									
									
									
										Normal file
									
								
							@ -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);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
@ -72,14 +72,14 @@
 | 
				
			|||||||
    &-slide-left-enter-active,
 | 
					    &-slide-left-enter-active,
 | 
				
			||||||
    &-slide-right-enter-active,
 | 
					    &-slide-right-enter-active,
 | 
				
			||||||
    &-slide-bottom-enter-active {
 | 
					    &-slide-bottom-enter-active {
 | 
				
			||||||
      transition-timing-function: ease-out;
 | 
					      transition-timing-function: @animation-timing-function-enter;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &-slide-top-leave-active,
 | 
					    &-slide-top-leave-active,
 | 
				
			||||||
    &-slide-left-leave-active,
 | 
					    &-slide-left-leave-active,
 | 
				
			||||||
    &-slide-right-leave-active,
 | 
					    &-slide-right-leave-active,
 | 
				
			||||||
    &-slide-bottom-leave-active {
 | 
					    &-slide-bottom-leave-active {
 | 
				
			||||||
      transition-timing-function: ease-in;
 | 
					      transition-timing-function: @animation-timing-function-leave;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    &-slide-top-enter-from,
 | 
					    &-slide-top-enter-from,
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@ export default {
 | 
				
			|||||||
    height: 100px;
 | 
					    height: 100px;
 | 
				
			||||||
    margin: -50px 0 0 -50px;
 | 
					    margin: -50px 0 0 -50px;
 | 
				
			||||||
    background-color: @blue;
 | 
					    background-color: @blue;
 | 
				
			||||||
    border-radius: 3px;
 | 
					    border-radius: 8px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 | 
				
			|||||||
@ -550,6 +550,21 @@
 | 
				
			|||||||
@picker-loading-icon-color: @blue;
 | 
					@picker-loading-icon-color: @blue;
 | 
				
			||||||
@picker-loading-mask-color: rgba(255, 255, 255, 0.9);
 | 
					@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
 | 
				
			||||||
@popup-background-color: @white;
 | 
					@popup-background-color: @white;
 | 
				
			||||||
@popup-transition: transform @animation-duration-base;
 | 
					@popup-transition: transform @animation-duration-base;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								types/index.d.ts
									
									
									
									
										vendored
									
									
								
							@ -66,6 +66,7 @@ export class Overlay extends VanComponent {}
 | 
				
			|||||||
export class Pagination extends VanComponent {}
 | 
					export class Pagination extends VanComponent {}
 | 
				
			||||||
export class Panel extends VanComponent {}
 | 
					export class Panel extends VanComponent {}
 | 
				
			||||||
export class PasswordInput extends VanComponent {}
 | 
					export class PasswordInput extends VanComponent {}
 | 
				
			||||||
 | 
					export class Popover extends VanComponent {}
 | 
				
			||||||
export class Popup extends VanComponent {}
 | 
					export class Popup extends VanComponent {}
 | 
				
			||||||
export class PullRefresh extends VanComponent {}
 | 
					export class PullRefresh extends VanComponent {}
 | 
				
			||||||
export class Radio extends VanComponent {}
 | 
					export class Radio extends VanComponent {}
 | 
				
			||||||
 | 
				
			|||||||
@ -286,6 +286,10 @@ module.exports = {
 | 
				
			|||||||
                path: 'notice-bar',
 | 
					                path: 'notice-bar',
 | 
				
			||||||
                title: 'NoticeBar 通知栏',
 | 
					                title: 'NoticeBar 通知栏',
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                path: 'popover',
 | 
				
			||||||
 | 
					                title: 'Popover 气泡弹出框',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
              {
 | 
					              {
 | 
				
			||||||
                path: 'progress',
 | 
					                path: 'progress',
 | 
				
			||||||
                title: 'Progress 进度条',
 | 
					                title: 'Progress 进度条',
 | 
				
			||||||
@ -632,6 +636,10 @@ module.exports = {
 | 
				
			|||||||
                path: 'notice-bar',
 | 
					                path: 'notice-bar',
 | 
				
			||||||
                title: 'NoticeBar',
 | 
					                title: 'NoticeBar',
 | 
				
			||||||
              },
 | 
					              },
 | 
				
			||||||
 | 
					              {
 | 
				
			||||||
 | 
					                path: 'popover',
 | 
				
			||||||
 | 
					                title: 'Popover',
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
              {
 | 
					              {
 | 
				
			||||||
                path: 'progress',
 | 
					                path: 'progress',
 | 
				
			||||||
                title: 'Progress',
 | 
					                title: 'Progress',
 | 
				
			||||||
 | 
				
			|||||||
@ -1319,6 +1319,11 @@
 | 
				
			|||||||
  dependencies:
 | 
					  dependencies:
 | 
				
			||||||
    "@types/node" ">= 8"
 | 
					    "@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":
 | 
					"@sindresorhus/is@^0.14.0":
 | 
				
			||||||
  version "0.14.0"
 | 
					  version "0.14.0"
 | 
				
			||||||
  resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
 | 
					  resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user