diff --git a/packages/varlet-vue2-ui/src/input/Input.vue b/packages/varlet-vue2-ui/src/input/Input.vue
index 3f34421..9d9965a 100644
--- a/packages/varlet-vue2-ui/src/input/Input.vue
+++ b/packages/varlet-vue2-ui/src/input/Input.vue
@@ -244,7 +244,7 @@ export default defineComponent({
const { disabled, readonly, clearable, getListeners } = this
const { onInput, onClear } = getListeners()
- if (this.form?.disabled.value || this.form?.readonly.value || disabled || readonly || !clearable) {
+ if (this.form?.disabled || this.form?.readonly || disabled || readonly || !clearable) {
return
}
@@ -257,7 +257,7 @@ export default defineComponent({
handleClick(e) {
const { disabled, getListeners } = this
- if (this.form?.disabled.value || disabled) {
+ if (this.form?.disabled || disabled) {
return
}
diff --git a/packages/varlet-vue2-ui/src/switch/Switch.vue b/packages/varlet-vue2-ui/src/switch/Switch.vue
new file mode 100644
index 0000000..fd269ea
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/Switch.vue
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
diff --git a/packages/varlet-vue2-ui/src/switch/__tests__/__snapshots__/index.spec.js.snap b/packages/varlet-vue2-ui/src/switch/__tests__/__snapshots__/index.spec.js.snap
new file mode 100644
index 0000000..3042495
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/__tests__/__snapshots__/index.spec.js.snap
@@ -0,0 +1,278 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`test switch color and size 1`] = `
+"
"
+`;
+
+exports[`test switch color and size 2`] = `
+""
+`;
+
+exports[`test switch example 1`] = `
+"
+
基本使用
+
+
不可用
+
+
自定义颜色
+
+
不同大小
+
+
加载状态
+
+
值的校验
+
+
"
+`;
+
+exports[`test switch loading prop 1`] = `
+""
+`;
+
+exports[`test switch rules prop 1`] = `
+""
+`;
+
+exports[`test switch rules prop 2`] = `
+""
+`;
diff --git a/packages/varlet-vue2-ui/src/switch/__tests__/index.spec.js b/packages/varlet-vue2-ui/src/switch/__tests__/index.spec.js
new file mode 100644
index 0000000..ee88c8c
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/__tests__/index.spec.js
@@ -0,0 +1,164 @@
+import example from '../example'
+import Switch from '..'
+import VarSwitch from '../Switch'
+import { mount } from '@vue/test-utils'
+import Vue from 'vue'
+import { delay } from '../../utils/jest'
+
+test('test switch example', () => {
+ const wrapper = mount(example)
+ expect(wrapper.html()).toMatchSnapshot()
+})
+
+test('test switch plugin', () => {
+ Vue.use(Switch)
+ expect(Vue.component(Switch.name)).toBeTruthy()
+})
+
+test('test switch value props and events', async () => {
+ const clickFn = jest.fn()
+ const changeFn = jest.fn()
+ const template = `
+
+ `
+
+ const wrapper = mount({
+ components: {
+ [VarSwitch.name]: VarSwitch,
+ },
+ data() {
+ return {
+ value: 2,
+ }
+ },
+ methods: {
+ clickFn,
+ changeFn,
+ },
+ template,
+ })
+
+ await delay(0)
+
+ expect(wrapper.find('.var-switch__track').classes()).toContain('var-switch__track-active')
+
+ await wrapper.find('.var-switch-block').trigger('click')
+
+ expect(clickFn).toHaveBeenCalledTimes(1)
+ expect(changeFn).toHaveBeenCalledTimes(1)
+
+ await delay(0)
+
+ expect(wrapper.vm.value).toBe(1)
+ expect(wrapper.find('.var-switch__track').classes()).not.toContain('var-switch__track-active')
+})
+
+test('test switch not available', async () => {
+ const clickFn = jest.fn()
+ const changeFn = jest.fn()
+ const template = `
+
+ `
+
+ const wrapper = mount({
+ components: {
+ [VarSwitch.name]: VarSwitch,
+ },
+ data() {
+ return {
+ value: true,
+ disabled: true,
+ readonly: false,
+ }
+ },
+ methods: {
+ clickFn,
+ changeFn,
+ },
+ template,
+ })
+
+ await delay(0)
+
+ expect(wrapper.find('.var-switch__disable')).toBeTruthy()
+
+ await wrapper.find('.var-switch-block').trigger('click')
+
+ expect(clickFn).toHaveBeenCalledTimes(1)
+ expect(changeFn).toHaveBeenCalledTimes(0)
+ expect(wrapper.vm.value).toBe(true)
+
+ await wrapper.setData({
+ disabled: false,
+ readonly: true,
+ })
+
+ await wrapper.find('.var-switch-block').trigger('click')
+ expect(clickFn).toHaveBeenCalledTimes(2)
+ expect(changeFn).toHaveBeenCalledTimes(0)
+ expect(wrapper.vm.value).toBe(true)
+})
+
+test('test switch color and size', async () => {
+ const template = `
+
+ `
+ const wrapper = mount({
+ components: {
+ [VarSwitch.name]: VarSwitch,
+ },
+ data() {
+ return {
+ value: true,
+ }
+ },
+ template,
+ })
+
+ await delay(0)
+
+ expect(wrapper.html()).toMatchSnapshot()
+
+ await wrapper.setData({ value: false })
+
+ await delay(0)
+
+ expect(wrapper.html()).toMatchSnapshot()
+})
+
+test('test switch loading prop', () => {
+ const wrapper = mount(VarSwitch, {
+ propsData: {
+ loading: true,
+ modelValue: true,
+ loadingColor: '#ff9800',
+ },
+ })
+
+ expect(wrapper.html()).toMatchSnapshot()
+})
+
+test('test switch rules prop', async () => {
+ const template = ``
+ const wrapper = mount({
+ components: {
+ [VarSwitch.name]: VarSwitch,
+ },
+ data() {
+ return {
+ value: true,
+ }
+ },
+ template,
+ })
+
+ await delay(0)
+
+ expect(wrapper.html()).toMatchSnapshot()
+
+ await wrapper.find('.var-switch-block').trigger('click')
+
+ await delay(0)
+
+ expect(wrapper.html()).toMatchSnapshot()
+})
diff --git a/packages/varlet-vue2-ui/src/switch/docs/en-US.md b/packages/varlet-vue2-ui/src/switch/docs/en-US.md
new file mode 100644
index 0000000..cb6f84e
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/docs/en-US.md
@@ -0,0 +1,111 @@
+# Switch
+
+### Intro
+
+Switching Selector.
+
+### Install
+
+```js
+import Vue from 'vue'
+import { Switch } from '@varlet/ui'
+
+Vue.use(Switch)
+```
+
+### Basic Usage
+
+```html
+
+```
+
+```javascript
+export default {
+ data() {
+ return {
+ value: true
+ }
+ }
+}
+```
+
+### Not Available
+
+```html
+
+
+```
+
+### Custom color
+
+```html
+
+
+```
+
+### Size
+
+Use `size` prop to change size of Switch.
+
+```html
+
+
+
+```
+
+### Loading
+
+```html
+
+
+```
+
+### Validate value
+
+The values are validated by passing in an array of validators,If the validator returns `true`, the validation passes.
+Other values are converted to text as a user prompt.
+
+```html
+
+```
+
+## API
+
+### Props
+
+| Prop | Description | Type | Default |
+| ----- | -------------- | -------- | ---------- |
+| `v-model` | Check status of Switch | _any_ | `false` |
+| `active-value` | The value when the switch is turned on | _any_ | `true` |
+| `inactive-value` | The value when the switch is turned off | _any_ | `false` |
+| `disabled` | Whether to disable switch| _boolean_ | `false` |
+| `readonly` | Whether to readonly switch | _boolean_ | `false` |
+| `loading` | Whether to show loading icon | _boolean_ | `false` |
+| `ripple` | Whether to open ripple | _boolean_ | `true` |
+| `color` | Background color when open | _string_ | `#2979ff` |
+| `close-color` | Background color when close | _string_ | `#fff` |
+| `loading-color` | Color of loading icon | _string_ | `#fff` |
+| `size` | Size of switch | _string \| number_ | `20` |
+| `rules`| Validation rules | _array_ | - |
+
+### Events
+
+| Event | Description | arguments |
+| ----- | -------------- | -------- |
+| `click` | Emitted when component is clicked | `event: Event` |
+| `change` | Emitted when check status changed | `value: any` |
+
+### Style Variables
+
+Here are the CSS variables used by the component, Styles can be customized using [StyleProvider](#/en-US/style-provider)
+
+| Variable | Default |
+| --- | --- |
+| `--switch-track-background` | `#fff` |
+| `--switch-track-active-background` | `var(--color-primary)` |
+| `--switch-track-error-background` | `var(--color-danger)` |
+| `--switch-ripple-color` | `var(--color-primary)` |
+| `--switch-handle-background` | `#fff` |
+| `--switch-handle-color` | `#fff` |
+| `--switch-handle-active-background` | `var(--color-primary)` |
+| `--switch-handle-error-background` | `var(--color-danger)` |
diff --git a/packages/varlet-vue2-ui/src/switch/docs/zh-CN.md b/packages/varlet-vue2-ui/src/switch/docs/zh-CN.md
new file mode 100644
index 0000000..77be976
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/docs/zh-CN.md
@@ -0,0 +1,111 @@
+# 开关
+
+### 介绍
+
+开关选择器。
+
+### 引入
+
+```js
+import Vue from 'vue'
+import { Switch } from '@varlet/ui'
+
+Vue.use(Switch)
+```
+
+### 基本使用
+
+```html
+
+```
+
+```javascript
+export default {
+ data() {
+ return {
+ value: true
+ }
+ }
+}
+```
+
+### 不可用
+
+```html
+
+
+```
+
+### 自定义颜色
+
+```html
+
+
+```
+
+### 不同大小
+
+通过 `size` 属性改变 Switch 大小。
+
+```html
+
+
+
+```
+
+### 加载状态
+
+```html
+
+
+```
+
+### 值的校验
+
+通过传入一个校验器数组可以对值进行校验,校验器返回 `true` 则为校验通过。
+以外的值将转换为文本作为用户提示。
+
+```html
+
+```
+
+## API
+
+### 属性
+
+| 参数 | 说明 | 类型 | 默认值 |
+| ----- | -------------- | -------- | ---------- |
+| `v-model` | 开关选中状态 | _any_ | `false` |
+| `active-value` | 开关打开时的值 | _any_ | `true` |
+| `inactive-value` | 开关关闭时的值 | _any_ | `false` |
+| `disabled` | 是否禁用| _boolean_ | `false` |
+| `readonly` | 是否只读 | _boolean_ | `false` |
+| `loading` | 是否为加载状态 | _boolean_ | `false` |
+| `ripple` | 是否启用水波纹 | _boolean_ | `true` |
+| `color` | 打开状态下的颜色 | _string_ | `#2979ff` |
+| `loading-color` | 加载图标的颜色 | _string_ | `#fff` |
+| `close-color` | 关闭状态下的颜色 | _string_ | `#fff` |
+| `size` | switch 的大小 | _string \| number_ | `20` |
+| `rules`| 校验规则 | _array_ | - |
+
+### 事件
+
+| 事件名 | 说明 | 回调参数 |
+| ----- | -------------- | -------- |
+| `click` | 点击时触发 | `event: Event` |
+| `change` | 开关状态切换时触发 | `value: any` |
+
+### 样式变量
+
+以下为组件使用的 css 变量,可以使用 [StyleProvider 组件](#/zh-CN/style-provider)进行样式定制
+
+| 变量名 | 默认值 |
+| --- | --- |
+| `--switch-track-background` | `#fff` |
+| `--switch-track-active-background` | `var(--color-primary)` |
+| `--switch-track-error-background` | `var(--color-danger)` |
+| `--switch-ripple-color` | `var(--color-primary)` |
+| `--switch-handle-background` | `#fff` |
+| `--switch-handle-color` | `#fff` |
+| `--switch-handle-active-background` | `var(--color-primary)` |
+| `--switch-handle-error-background` | `var(--color-danger)` |
diff --git a/packages/varlet-vue2-ui/src/switch/example/index.vue b/packages/varlet-vue2-ui/src/switch/example/index.vue
new file mode 100644
index 0000000..0fd1269
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/example/index.vue
@@ -0,0 +1,80 @@
+
+
+
{{ pack.basicUsage }}
+
+
+
+
{{ pack.notAvailable }}
+
+
+
+
+
{{ pack.customColor }}
+
+
+
+
+
{{ pack.size }}
+
+
+
+
+
+
{{ pack.loading }}
+
+
+
+
+
{{ pack.validateValue }}
+
+
+
+
+
+
+
diff --git a/packages/varlet-vue2-ui/src/switch/example/locale/en-US.ts b/packages/varlet-vue2-ui/src/switch/example/locale/en-US.ts
new file mode 100644
index 0000000..32d356b
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/example/locale/en-US.ts
@@ -0,0 +1,10 @@
+export default {
+ basicUsage: 'Basic Usage',
+ customColor: 'Custom Color',
+ notAvailable: 'Not Available',
+ size: 'Size',
+ loading: 'Loading',
+ validateValue: 'Validate Value',
+ text: 'Whether to open the switch',
+ state: 'Error!',
+}
diff --git a/packages/varlet-vue2-ui/src/switch/example/locale/index.ts b/packages/varlet-vue2-ui/src/switch/example/locale/index.ts
new file mode 100644
index 0000000..d2e375e
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/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/switch/example/locale/zh-CN.ts b/packages/varlet-vue2-ui/src/switch/example/locale/zh-CN.ts
new file mode 100644
index 0000000..54aaa33
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/example/locale/zh-CN.ts
@@ -0,0 +1,10 @@
+export default {
+ basicUsage: '基本使用',
+ customColor: '自定义颜色',
+ notAvailable: '不可用',
+ size: '不同大小',
+ loading: '加载状态',
+ validateValue: '值的校验',
+ text: '是否打开开关',
+ state: '错误!',
+}
diff --git a/packages/varlet-vue2-ui/src/switch/index.ts b/packages/varlet-vue2-ui/src/switch/index.ts
new file mode 100644
index 0000000..310aaca
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/index.ts
@@ -0,0 +1,10 @@
+import type { VueConstructor } from 'vue'
+import Switch from './Switch.vue'
+
+Switch.install = function (app: VueConstructor) {
+ app.component(Switch.name, Switch)
+}
+
+export const _SwitchComponent = Switch
+
+export default Switch
diff --git a/packages/varlet-vue2-ui/src/switch/props.ts b/packages/varlet-vue2-ui/src/switch/props.ts
new file mode 100644
index 0000000..7779015
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/props.ts
@@ -0,0 +1,54 @@
+import type { PropType } from 'vue'
+
+export const props = {
+ value: {
+ default: false,
+ },
+ activeValue: {
+ default: true,
+ },
+ inactiveValue: {
+ default: false,
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
+ },
+ readonly: {
+ type: Boolean,
+ default: false,
+ },
+ loading: {
+ type: Boolean,
+ default: false,
+ },
+ color: {
+ type: String,
+ },
+ loadingColor: {
+ type: String,
+ },
+ closeColor: {
+ type: String,
+ },
+ size: {
+ type: [String, Number],
+ default: 20,
+ },
+ rules: {
+ type: Array as PropType any>>,
+ },
+ ripple: {
+ type: Boolean,
+ default: true,
+ },
+ onClick: {
+ type: Function as PropType<(event: MouseEvent) => void>,
+ },
+ onChange: {
+ type: Function as PropType<(value: boolean) => void>,
+ },
+ onInput: {
+ type: Function as PropType<(value: boolean) => void>,
+ },
+}
diff --git a/packages/varlet-vue2-ui/src/switch/switch.less b/packages/varlet-vue2-ui/src/switch/switch.less
new file mode 100644
index 0000000..0a173f8
--- /dev/null
+++ b/packages/varlet-vue2-ui/src/switch/switch.less
@@ -0,0 +1,80 @@
+@switch-track-background: #fff;
+@switch-track-active-background: var(--color-primary);
+@switch-track-error-background: var(--color-danger);
+@switch-ripple-color: var(--color-primary);
+@switch-handle-background: #fff;
+@switch-handle-color: #fff;
+@switch-handle-active-background: var(--color-primary);
+@switch-handle-error-background: var(--color-danger);
+
+:root {
+ --switch-track-background: @switch-track-background;
+ --switch-track-active-background: @switch-track-active-background;
+ --switch-track-error-background: @switch-track-error-background;
+ --switch-ripple-color: @switch-ripple-color;
+ --switch-handle-background: @switch-handle-background;
+ --switch-handle-color: @switch-handle-color;
+ --switch-handle-active-background: @switch-handle-active-background;
+ --switch-handle-error-background: @switch-handle-error-background;
+}
+
+.var-switch {
+ display: inline-block;
+
+ &-block {
+ position: relative;
+ display: flex;
+ cursor: pointer;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__disable {
+ filter: opacity(0.6);
+ cursor: not-allowed;
+ }
+
+ &__track {
+ background: var(--switch-track-background);
+ transition: background-color 0.25s;
+ filter: opacity(0.6);
+
+ &-active {
+ background-color: var(--switch-track-active-background);
+ }
+
+ &-error {
+ background-color: var(--switch-track-error-background) !important;
+ }
+ }
+
+ &__ripple {
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--switch-ripple-color);
+ border-radius: 50%;
+ overflow: hidden;
+ transition: 0.3s var(--cubic-bezier);
+ }
+
+ &__handle {
+ border-radius: 50%;
+ background-color: var(--switch-handle-background);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--switch-handle-color);
+ transition: background-color 0.25s;
+
+ &-active {
+ background-color: var(--switch-handle-active-background);
+ }
+
+ &-error {
+ background-color: var(--switch-handle-error-background) !important;
+ }
+ }
+}
diff --git a/packages/varlet-vue2-ui/types/global.d.ts b/packages/varlet-vue2-ui/types/global.d.ts
index 7f8c166..6150846 100644
--- a/packages/varlet-vue2-ui/types/global.d.ts
+++ b/packages/varlet-vue2-ui/types/global.d.ts
@@ -21,6 +21,7 @@ declare module 'vue' {
VarRate: typeof import('@varlet-vue2/ui')['_RateComponent']
VarSkeleton: typeof import('@varlet-vue2/ui')['_SkeletonComponent']
VarSnackbar: typeof import('@varlet-vue2/ui')['_SnackbarComponent']
+ VarSwitch: typeof import('@varlet-vue2/ui')['_SwitchComponent']
VarSticky: typeof import('@varlet-vue2/ui')['_StickyComponent']
}
}
diff --git a/packages/varlet-vue2-ui/types/index.d.ts b/packages/varlet-vue2-ui/types/index.d.ts
index 657c34a..5de106e 100644
--- a/packages/varlet-vue2-ui/types/index.d.ts
+++ b/packages/varlet-vue2-ui/types/index.d.ts
@@ -29,5 +29,6 @@ export * from './loading'
export * from './menu'
export * from './input'
export * from './table'
+export * from './switch'
export * from './varComponent'
export * from './varDirective'
diff --git a/packages/varlet-vue2-ui/types/switch.d.ts b/packages/varlet-vue2-ui/types/switch.d.ts
new file mode 100644
index 0000000..ccb31a5
--- /dev/null
+++ b/packages/varlet-vue2-ui/types/switch.d.ts
@@ -0,0 +1,25 @@
+import { VarComponent } from './varComponent'
+
+export interface SwitchProps {
+ value?: any
+ activeValue?: any
+ inactiveValue?: any
+ disabled?: boolean
+ readonly?: boolean
+ loading?: boolean
+ ripple?: boolean
+ color?: string
+ loadingColor?: string
+ closeColor?: string
+ size?: string | number
+ rules?: Array<(value: any) => any>
+ onClick?: (event: MouseEvent) => void
+ onChange?: (value: boolean) => void
+ onInput?: (value: boolean) => void
+}
+
+export class Switch extends VarComponent {
+ $props: SwitchProps
+}
+
+export class _SwitchComponent extends Switch {}