From 5218f9cad4abcf163baab6c30852b8ad15b09465 Mon Sep 17 00:00:00 2001
From: ayang <473033518@qq.com>
Date: Fri, 25 Feb 2022 23:13:25 +0800
Subject: [PATCH] feat(ui/swipe): add component swipe
---
packages/varlet-vue2-ui/src/col/Col.vue | 11 +-
packages/varlet-vue2-ui/src/row/Row.vue | 9 +-
.../src/swipe-item/SwipeItem.vue | 48 +++
.../src/swipe-item/docs/zh-CN.md | 1 +
.../varlet-vue2-ui/src/swipe-item/index.ts | 10 +
.../src/swipe-item/swipeItem.less | 5 +
packages/varlet-vue2-ui/src/swipe/Swipe.vue | 380 ++++++++++++++++++
.../__snapshots__/index.spec.js.snap | 106 +++++
.../src/swipe/__tests__/index.spec.js | 206 ++++++++++
.../varlet-vue2-ui/src/swipe/docs/en-US.md | 206 ++++++++++
.../varlet-vue2-ui/src/swipe/docs/zh-CN.md | 206 ++++++++++
.../src/swipe/example/index.vue | 150 +++++++
.../src/swipe/example/locale/en-US.ts | 8 +
.../src/swipe/example/locale/index.ts | 23 ++
.../src/swipe/example/locale/zh-CN.ts | 8 +
packages/varlet-vue2-ui/src/swipe/index.ts | 10 +
packages/varlet-vue2-ui/src/swipe/props.ts | 37 ++
packages/varlet-vue2-ui/src/swipe/swipe.less | 59 +++
packages/varlet-vue2-ui/src/utils/elements.ts | 14 +-
packages/varlet-vue2-ui/types/index.d.ts | 2 +
packages/varlet-vue2-ui/types/swipe.d.ts | 27 ++
packages/varlet-vue2-ui/types/swipeItem.d.ts | 5 +
22 files changed, 1524 insertions(+), 7 deletions(-)
create mode 100644 packages/varlet-vue2-ui/src/swipe-item/SwipeItem.vue
create mode 100644 packages/varlet-vue2-ui/src/swipe-item/docs/zh-CN.md
create mode 100644 packages/varlet-vue2-ui/src/swipe-item/index.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe-item/swipeItem.less
create mode 100644 packages/varlet-vue2-ui/src/swipe/Swipe.vue
create mode 100644 packages/varlet-vue2-ui/src/swipe/__tests__/__snapshots__/index.spec.js.snap
create mode 100644 packages/varlet-vue2-ui/src/swipe/__tests__/index.spec.js
create mode 100644 packages/varlet-vue2-ui/src/swipe/docs/en-US.md
create mode 100644 packages/varlet-vue2-ui/src/swipe/docs/zh-CN.md
create mode 100644 packages/varlet-vue2-ui/src/swipe/example/index.vue
create mode 100644 packages/varlet-vue2-ui/src/swipe/example/locale/en-US.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe/example/locale/index.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe/example/locale/zh-CN.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe/index.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe/props.ts
create mode 100644 packages/varlet-vue2-ui/src/swipe/swipe.less
create mode 100644 packages/varlet-vue2-ui/types/swipe.d.ts
create mode 100644 packages/varlet-vue2-ui/types/swipeItem.d.ts
diff --git a/packages/varlet-vue2-ui/src/col/Col.vue b/packages/varlet-vue2-ui/src/col/Col.vue
index 83d656e..6e4b18e 100644
--- a/packages/varlet-vue2-ui/src/col/Col.vue
+++ b/packages/varlet-vue2-ui/src/col/Col.vue
@@ -29,12 +29,16 @@ import { createChildrenMixin } from '../utils/mixins/relation'
export default defineComponent({
name: 'VarCol',
+
+ mixins: [createChildrenMixin('row', { childrenKey: 'cols' })],
+
+ props,
+
data: () => ({
padding: { left: 0, right: 0 },
toSizeUnit,
}),
- mixins: [createChildrenMixin('row', { childrenKey: 'cols' })],
- props,
+
watch: {
span: {
handler() {
@@ -43,6 +47,7 @@ export default defineComponent({
immediate: true,
},
},
+
methods: {
handleClick(e) {
const { getListeners } = this
@@ -53,9 +58,11 @@ export default defineComponent({
}
onClick(e)
},
+
setPadding(pad) {
this.padding = pad
},
+
getSize(mode, size) {
const classes = []
diff --git a/packages/varlet-vue2-ui/src/row/Row.vue b/packages/varlet-vue2-ui/src/row/Row.vue
index 05d970a..5774187 100644
--- a/packages/varlet-vue2-ui/src/row/Row.vue
+++ b/packages/varlet-vue2-ui/src/row/Row.vue
@@ -22,21 +22,27 @@ import { createParentMixin } from '../utils/mixins/relation'
export default defineComponent({
name: 'VarRow',
- props,
+
mixins: [createParentMixin('row', { childrenKey: 'cols' })],
+
+ props,
+
computed: {
average() {
return toPxNum(this.gutter) / 2
},
},
+
watch: {
gutter() {
this.computePadding()
},
+
cols() {
this.computePadding()
},
},
+
methods: {
computePadding() {
const { average } = this
@@ -44,6 +50,7 @@ export default defineComponent({
col.setPadding({ left: average.value, right: average.value })
})
},
+
handleClick(e) {
const { getListeners } = this
const { onClick } = getListeners()
diff --git a/packages/varlet-vue2-ui/src/swipe-item/SwipeItem.vue b/packages/varlet-vue2-ui/src/swipe-item/SwipeItem.vue
new file mode 100644
index 0000000..a253352
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe-item/SwipeItem.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/varlet-vue2-ui/src/swipe-item/docs/zh-CN.md b/packages/varlet-vue2-ui/src/swipe-item/docs/zh-CN.md
new file mode 100644
index 0000000..5d5ae50
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe-item/docs/zh-CN.md
@@ -0,0 +1 @@
+# 轮播项
\ No newline at end of file
diff --git a/packages/varlet-vue2-ui/src/swipe-item/index.ts b/packages/varlet-vue2-ui/src/swipe-item/index.ts
new file mode 100644
index 0000000..21b9e74
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe-item/index.ts
@@ -0,0 +1,10 @@
+import type { VueConstructor } from 'vue'
+import SwipeItem from './SwipeItem.vue'
+
+SwipeItem.install = function (app: VueConstructor) {
+ app.component(SwipeItem.name, SwipeItem)
+}
+
+export const _SwipeItemComponent = SwipeItem
+
+export default SwipeItem
diff --git a/packages/varlet-vue2-ui/src/swipe-item/swipeItem.less b/packages/varlet-vue2-ui/src/swipe-item/swipeItem.less
new file mode 100644
index 0000000..6b73d41
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe-item/swipeItem.less
@@ -0,0 +1,5 @@
+.var-swipe-item {
+ flex-shrink: 0;
+ width: 100%;
+ height: 100%;
+}
diff --git a/packages/varlet-vue2-ui/src/swipe/Swipe.vue b/packages/varlet-vue2-ui/src/swipe/Swipe.vue
new file mode 100644
index 0000000..7bcc849
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/Swipe.vue
@@ -0,0 +1,380 @@
+
+
+
+
+
+
+
diff --git a/packages/varlet-vue2-ui/src/swipe/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-vue2-ui/src/swipe/__tests__/__snapshots__/index.spec.js.snap
new file mode 100644
index 0000000..8918f67
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/__tests__/__snapshots__/index.spec.js.snap
@@ -0,0 +1,106 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`test render initial index 1`] = `
+"
"
+`;
+
+exports[`test swipe next & prev & to method 1`] = `
+""
+`;
+
+exports[`test swipe next & prev & to method 2`] = `
+""
+`;
+
+exports[`test swipe next & prev & to method 3`] = `
+""
+`;
+
+exports[`test swipe next & prev & to method 4`] = `
+""
+`;
+
+exports[`test swipe next & prev & to method 5`] = `
+""
+`;
+
+exports[`test swipe next & prev & to method 6`] = `
+""
+`;
diff --git a/packages/varlet-vue2-ui/src/swipe/__tests__/index.spec.js b/packages/varlet-vue2-ui/src/swipe/__tests__/index.spec.js
new file mode 100644
index 0000000..dfdf2b3
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/__tests__/index.spec.js
@@ -0,0 +1,206 @@
+import Swipe from '..'
+import SwipeItem from '../../swipe-item'
+import VarSwipe from '../Swipe'
+import VarSwipeItem from '../../swipe-item/SwipeItem'
+import { mount } from '@vue/test-utils'
+import Vue from 'vue'
+import { delay, mockOffset, triggerDrag } from '../../utils/jest'
+
+mockOffset()
+
+test('test swipe & swipe-item plugin', () => {
+ Vue.use(Swipe).use(SwipeItem)
+ expect(Vue.component(Swipe.name)).toBeTruthy()
+ expect(Vue.component(SwipeItem.name)).toBeTruthy()
+})
+
+const Wrapper = {
+ components: {
+ [VarSwipe.name]: VarSwipe,
+ [VarSwipeItem.name]: VarSwipeItem,
+ },
+ props: ['onChange', 'initialIndex'],
+ template: `
+
+ 1
+ 2
+ 3
+
+ `,
+}
+
+test('test swipe next & prev & to method', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(50)
+
+ const {
+ swipe: { prev, next, to },
+ } = wrapper.vm.$refs
+
+ to(0)
+ expect(onChange).toHaveBeenCalledTimes(0)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ next()
+ expect(onChange).toHaveBeenLastCalledWith(1)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ prev()
+ expect(onChange).toHaveBeenLastCalledWith(0)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ to(2)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ next()
+ expect(onChange).toHaveBeenLastCalledWith(0)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ prev()
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ await delay(100)
+ expect(wrapper.html()).toMatchSnapshot()
+
+ wrapper.destroy()
+})
+
+test('test render initial index', async () => {
+ const wrapper = mount(Wrapper, {
+ propsData: {
+ initialIndex: 2,
+ },
+ })
+ await delay(50)
+ expect(wrapper.html()).toMatchSnapshot()
+ wrapper.destroy()
+})
+
+test('test touch with loop', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(50)
+
+ const track = wrapper.find('.var-swipe__track')
+
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(1)
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(0)
+ await triggerDrag(track, 100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ await triggerDrag(track, 100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(1)
+ await triggerDrag(track, 100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(0)
+
+ wrapper.destroy()
+})
+
+test('test touch without loop', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ propsData: {
+ loop: false,
+ },
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(50)
+
+ const track = wrapper.find('.var-swipe__track')
+
+ await triggerDrag(track, 100, 0)
+ expect(onChange).toHaveBeenCalledTimes(0)
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(1)
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+
+ wrapper.destroy()
+})
+
+test('test touch with vertical', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ propsData: {
+ vertical: true,
+ },
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(50)
+
+ const track = wrapper.find('.var-swipe__track')
+
+ await triggerDrag(track, 0, -100)
+ expect(onChange).toHaveBeenCalledTimes(1)
+ await triggerDrag(track, 0, -100)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+
+ wrapper.destroy()
+})
+
+test('test touch forbid touchable', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ propsData: {
+ touchable: false,
+ },
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(50)
+
+ const track = wrapper.find('.var-swipe__track')
+
+ await triggerDrag(track, -100, 0)
+ expect(onChange).toHaveBeenCalledTimes(0)
+
+ wrapper.destroy()
+})
+
+test('test autoplay', async () => {
+ const onChange = jest.fn()
+
+ const wrapper = mount(Wrapper, {
+ propsData: {
+ autoplay: 100,
+ },
+ listeners: {
+ change: onChange,
+ },
+ })
+ await delay(100)
+ await delay(100)
+ expect(onChange).toHaveBeenLastCalledWith(1)
+ await delay(100)
+ expect(onChange).toHaveBeenLastCalledWith(2)
+ wrapper.destroy()
+})
diff --git a/packages/varlet-vue2-ui/src/swipe/docs/en-US.md b/packages/varlet-vue2-ui/src/swipe/docs/en-US.md
new file mode 100644
index 0000000..83beeab
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/docs/en-US.md
@@ -0,0 +1,206 @@
+# Swipe
+
+### Install
+
+```js
+import Vue from 'vue'
+import { Swipe, SwipeItem } from '@varlet-vue2/ui'
+
+Vue.use(Swipe).use(SwipeItem)
+```
+
+### Basic Usage
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+.swipe {
+ height: 160px;
+}
+
+.swipe-item {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+```
+
+### Forbid Loop
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Autoplay
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Vertical Swipe
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Handle Change
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```js
+import { Snackbar } from '@varlet-vue2/ui'
+
+export default {
+ methods: {
+ Snackbar
+ }
+}
+```
+
+### Custom Indicator
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }} / {{ length }}
+
+
+
+```
+
+```css
+.swipe {
+ height: 160px;
+}
+
+.swipe-item {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.indicators {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ text-align: center;
+ padding: 4px 0;
+ color: #fff;
+ font-size: 14px;
+ background: rgba(0, 0, 0, 0.6);
+}
+```
+
+## API
+
+### Props
+
+| Prop | Description | Type | Default |
+| --- | --- | --- | --- |
+| `loop` | Whether to swipe the loop | _boolean_ | `true` |
+| `autoplay` | Auto play interval time(ms) | _string \| number_ | `-` |
+| `duration` | Transition time | _string \| number_ | `300` |
+| `initial-index` | Initializes the index displayed | _string \| number_ | `0` |
+| `indicator` | Whether to display the indicator | _boolean_ | `true` |
+| `indicator-color` | Indicator color | _string_ | `-` |
+| `vertical` | Whether to enable vertical swipe | _boolean_ | `false` |
+| `touchable` | Whether to enable touch | _boolean_ | `true` |
+
+### Methods
+
+| Method | Description | Arguments | Return |
+| --- | --- | --- | --- |
+| `resize` | You can call this method to redraw when a tabs changes position size | `-` | `-` |
+| `prev` | Previous page | `-` | `-` |
+| `next` | Next page | `-` | `-` |
+| `to` | To index page | `index: number` | `-` |
+
+### Events
+
+| Event | Description | Arguments |
+| --- | --- | --- |
+| `change` | Triggered when change swipe | `index: number` swipe index |
+
+### Slots
+
+| Slot | Description | Arguments |
+| --- | --- | --- |
+| `default` | Swipe content | `-` |
+| `indicator` | Swipe indicator content | `index: number`
`length: number` |
+
+### Style Variables
+
+Here are the CSS variables used by the component, Styles can be customized using [StyleProvider](#/en-US/style-provider)
+
+| Variable | Default |
+| --- | --- |
+| `--swipe-indicator-color` | `#fff` |
+| `--swipe-indicators-offset` | `10px` |
+| `--swipe-indicator-offset` | `4px` |
\ No newline at end of file
diff --git a/packages/varlet-vue2-ui/src/swipe/docs/zh-CN.md b/packages/varlet-vue2-ui/src/swipe/docs/zh-CN.md
new file mode 100644
index 0000000..f65234a
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/docs/zh-CN.md
@@ -0,0 +1,206 @@
+# 轮播
+
+### 引入
+
+```js
+import Vue from 'vue'
+import { Swipe, SwipeItem } from '@varlet-vue2/ui'
+
+Vue.use(Swipe).use(SwipeItem)
+```
+
+### 基本使用
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```css
+.swipe {
+ height: 160px;
+}
+
+.swipe-item {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+```
+
+### 禁止循环轮播
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 开启自动播放
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 垂直轮播
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 监听切换
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```js
+import { Snackbar } from '@varlet-vue2/ui'
+
+export default {
+ methods: {
+ Snackbar
+ }
+}
+```
+
+### 自定义指示器
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }} / {{ length }}
+
+
+
+```
+
+```css
+.swipe {
+ height: 160px;
+}
+
+.swipe-item {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+}
+
+.indicators {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ text-align: center;
+ padding: 4px 0;
+ color: #fff;
+ font-size: 14px;
+ background: rgba(0, 0, 0, 0.6);
+}
+```
+
+## API
+
+### 属性
+
+| 参数 | 说明 | 类型 | 默认值 |
+| --- | --- | --- | --- |
+| `loop` | 是否开启循环轮播 | _boolean_ | `true` |
+| `autoplay` | 自动播放间隔时间 (ms) | _string \| number_ | `-` |
+| `duration` | 切换过度时间 | _string \| number_ | `300` |
+| `initial-index` | 初始化显示的索引 | _string \| number_ | `0` |
+| `indicator` | 是否显示指示器 | _boolean_ | `true` |
+| `indicator-color` | 指示器颜色 | _string_ | `-` |
+| `vertical` | 是否开启垂直轮播 | _boolean_ | `false` |
+| `touchable` | 是否可以拖动 | _boolean_ | `true` |
+
+### 方法
+
+| 方法名 | 说明 | 参数 | 返回值 |
+| --- | --- | --- | --- |
+| `resize` | 产生位置大小变化时可以调用此方法进行重绘 | `-` | `-` |
+| `prev` | 上一页 | `-` | `-` |
+| `next` | 下一页 | `-` | `-` |
+| `to` | 跳转到指定下标 | `index: number` | `-` |
+
+### 事件
+
+| 事件名 | 说明 | 参数 |
+| --- | --- | --- |
+| `change` | 切换轮播时触发 | `index: number` 轮播索引 |
+
+### 插槽
+
+| 插槽名 | 说明 | 参数 |
+| --- | --- | --- |
+| `default` | 轮播内容 | `-` |
+| `indicator` | 指示器内容 | `index: number` 轮播索引
`length: number` 轮播总数 |
+
+### 样式变量
+
+以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider)进行样式定制
+
+| 变量名 | 默认值 |
+| --- | --- |
+| `--swipe-indicator-color` | `#fff` |
+| `--swipe-indicators-offset` | `10px` |
+| `--swipe-indicator-offset` | `4px` |
diff --git a/packages/varlet-vue2-ui/src/swipe/example/index.vue b/packages/varlet-vue2-ui/src/swipe/example/index.vue
new file mode 100644
index 0000000..2d8929e
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/example/index.vue
@@ -0,0 +1,150 @@
+
+
+
{{ pack.basicUsage }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ pack.forbidLoop }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ pack.autoplay }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ pack.vertical }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ pack.handleChange }}
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ pack.customIndicator }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }} / {{ length }}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/varlet-vue2-ui/src/swipe/example/locale/en-US.ts b/packages/varlet-vue2-ui/src/swipe/example/locale/en-US.ts
new file mode 100644
index 0000000..ce45a75
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/example/locale/en-US.ts
@@ -0,0 +1,8 @@
+export default {
+ basicUsage: 'Basic Usage',
+ forbidLoop: 'Forbid Loop',
+ autoplay: 'Autoplay',
+ vertical: 'Vertical Swipe',
+ handleChange: 'Handle Change',
+ customIndicator: 'Custom Indicator',
+}
diff --git a/packages/varlet-vue2-ui/src/swipe/example/locale/index.ts b/packages/varlet-vue2-ui/src/swipe/example/locale/index.ts
new file mode 100644
index 0000000..d2e375e
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/example/locale/index.ts
@@ -0,0 +1,23 @@
+// lib
+import _zhCN from '../../../locale/zh-CN'
+import _enCN from '../../../locale/en-US'
+// mobile example doc
+import zhCN from './zh-CN'
+import enUS from './en-US'
+import { useLocale, add as _add, use as _use } from '../../../locale'
+
+const { add, use: exampleUse, pack, packs, merge } = useLocale()
+
+const use = (lang: string) => {
+ _use(lang)
+ exampleUse(lang)
+}
+
+export { add, pack, packs, merge, use }
+
+// lib
+_add('zh-CN', _zhCN)
+_add('en-US', _enCN)
+// mobile example doc
+add('zh-CN', zhCN as any)
+add('en-US', enUS as any)
diff --git a/packages/varlet-vue2-ui/src/swipe/example/locale/zh-CN.ts b/packages/varlet-vue2-ui/src/swipe/example/locale/zh-CN.ts
new file mode 100644
index 0000000..8a53444
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/example/locale/zh-CN.ts
@@ -0,0 +1,8 @@
+export default {
+ basicUsage: '基本使用',
+ forbidLoop: '禁止循环轮播',
+ autoplay: '开启自动播放',
+ vertical: '垂直轮播',
+ handleChange: '监听切换',
+ customIndicator: '自定义指示器',
+}
diff --git a/packages/varlet-vue2-ui/src/swipe/index.ts b/packages/varlet-vue2-ui/src/swipe/index.ts
new file mode 100644
index 0000000..d02db4e
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/index.ts
@@ -0,0 +1,10 @@
+import type { VueConstructor } from 'vue'
+import Swipe from './Swipe.vue'
+
+Swipe.install = function (app: VueConstructor) {
+ app.component(Swipe.name, Swipe)
+}
+
+export const _SwipeComponent = Swipe
+
+export default Swipe
diff --git a/packages/varlet-vue2-ui/src/swipe/props.ts b/packages/varlet-vue2-ui/src/swipe/props.ts
new file mode 100644
index 0000000..a076ba5
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/props.ts
@@ -0,0 +1,37 @@
+import type { PropType } from 'vue'
+
+export const props = {
+ loop: {
+ type: Boolean,
+ default: true,
+ },
+ autoplay: {
+ type: [String, Number],
+ },
+ duration: {
+ type: [String, Number],
+ default: 300,
+ },
+ initialIndex: {
+ type: [String, Number],
+ default: 0,
+ },
+ indicator: {
+ type: Boolean,
+ default: true,
+ },
+ indicatorColor: {
+ type: String,
+ },
+ vertical: {
+ type: Boolean,
+ default: false,
+ },
+ touchable: {
+ type: Boolean,
+ default: true,
+ },
+ onChange: {
+ type: Function as PropType<(index: number) => void>,
+ },
+}
diff --git a/packages/varlet-vue2-ui/src/swipe/swipe.less b/packages/varlet-vue2-ui/src/swipe/swipe.less
new file mode 100644
index 0000000..086cbb4
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/swipe/swipe.less
@@ -0,0 +1,59 @@
+@swipe-indicator-color: #fff;
+@swipe-indicators-offset: 10px;
+@swipe-indicator-offset: 4px;
+
+:root {
+ --swipe-indicator-color: @swipe-indicator-color;
+ --swipe-indicators-offset: @swipe-indicators-offset;
+ --swipe-indicator-offset: @swipe-indicator-offset;
+}
+
+.var-swipe {
+ position: relative;
+ overflow: hidden;
+ user-select: none;
+
+ &__track {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ transition-property: transform;
+ }
+
+ &__indicators {
+ position: absolute;
+ display: flex;
+ bottom: var(--swipe-indicators-offset);
+ left: 50%;
+ transform: translateX(-50%);
+ }
+
+ &__indicator {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--swipe-indicator-color);
+ opacity: 0.3;
+ margin: 0 var(--swipe-indicator-offset);
+ transition: opacity 0.3s;
+ }
+
+ &--vertical {
+ flex-direction: column;
+ }
+
+ &--indicators-vertical {
+ flex-direction: column;
+ left: var(--swipe-indicators-offset);
+ bottom: 50%;
+ transform: translateY(50%);
+ }
+
+ &--indicator-active {
+ opacity: 1;
+ }
+
+ &--indicator-vertical {
+ margin: var(--swipe-indicator-offset) 0;
+ }
+}
diff --git a/packages/varlet-vue2-ui/src/utils/elements.ts b/packages/varlet-vue2-ui/src/utils/elements.ts
index da84a91..2bfd0f6 100644
--- a/packages/varlet-vue2-ui/src/utils/elements.ts
+++ b/packages/varlet-vue2-ui/src/utils/elements.ts
@@ -33,6 +33,12 @@ export function doubleRaf() {
})
}
+export function nextTickFrame(fn: FrameRequestCallback) {
+ window.requestAnimationFrame(() => {
+ window.requestAnimationFrame(fn)
+ })
+}
+
export async function inViewport(element: HTMLElement): Promise {
await doubleRaf()
const { top, bottom, left, right } = element.getBoundingClientRect()
@@ -152,10 +158,10 @@ export function cancelAnimationFrame(handle: number): void {
}
interface ScrollToOptions {
- top?: number;
- left?: number;
- duration?: number;
- animation: (progress: number) => number;
+ top?: number
+ left?: number
+ duration?: number
+ animation: (progress: number) => number
}
export function scrollTo(
diff --git a/packages/varlet-vue2-ui/types/index.d.ts b/packages/varlet-vue2-ui/types/index.d.ts
index f5686d2..17249bd 100644
--- a/packages/varlet-vue2-ui/types/index.d.ts
+++ b/packages/varlet-vue2-ui/types/index.d.ts
@@ -38,5 +38,7 @@ export * from './timePicker'
export * from './ripple'
export * from './checkbox'
export * from './checkboxGroup'
+export * from './swipe'
+export * from './swipeItem'
export * from './varComponent'
export * from './varDirective'
diff --git a/packages/varlet-vue2-ui/types/swipe.d.ts b/packages/varlet-vue2-ui/types/swipe.d.ts
new file mode 100644
index 0000000..34ba1fd
--- /dev/null
+++ b/packages/varlet-vue2-ui/types/swipe.d.ts
@@ -0,0 +1,27 @@
+import { VarComponent } from './varComponent'
+
+export interface SwipeProps {
+ loop?: boolean
+ autoplay?: string | number
+ duration?: string | number
+ initialIndex?: string | number
+ indicator?: boolean
+ indicatorColor?: string
+ vertical?: boolean
+ touchable?: boolean
+ onChange?: (index: number) => void
+}
+
+export class Swipe extends VarComponent {
+ $props: SwipeProps
+
+ resize(): void
+
+ prev(): void
+
+ next(): void
+
+ to(index: number): void
+}
+
+export class _SwipeComponent extends Swipe {}
diff --git a/packages/varlet-vue2-ui/types/swipeItem.d.ts b/packages/varlet-vue2-ui/types/swipeItem.d.ts
new file mode 100644
index 0000000..13c579f
--- /dev/null
+++ b/packages/varlet-vue2-ui/types/swipeItem.d.ts
@@ -0,0 +1,5 @@
+import { VarComponent } from './varComponent'
+
+export class SwipeItem extends VarComponent {}
+
+export class _SwipeItemComponent extends SwipeItem {}