feat: Switch支持不同尺寸 (#4682)

This commit is contained in:
RUNZE LU 2022-06-23 19:16:32 +08:00 committed by GitHub
parent be5df5e838
commit 672c5c7f96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 308 additions and 85 deletions

View File

@ -103,6 +103,30 @@ order: 51
}
```
## 不同尺寸
> 2.0.0 及以上版本
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"name": "switch",
"type": "switch",
"label": ""
},
{
"name": "switch-sm",
"type": "switch",
"label": "",
"size": "sm"
}
]
}
```
## 属性表
除了支持 [普通表单项属性表](./formitem#%E5%B1%9E%E6%80%A7%E8%A1%A8) 中的配置以外,还支持下面一些配置
@ -114,6 +138,7 @@ order: 51
| offText | `string / IconSchema` | | 关闭时开关显示的内容 |
| trueValue | `boolean / string / number` | `true` | 标识真值 |
| falseValue | `boolean / string / number` | `false` | 标识假值 |
| size | `"sm" \| "md"` | `"md"` | 开关大小 |
IconSchema 配置
| 属性名 | 类型 | 默认值 | 说明 |

View File

@ -1280,8 +1280,27 @@
--Switch-onDisabled-bgColor: #ccc;
--Switch-onDisabled-circle-BackgroundColor: var(--white);
--Switch-onDisabled-color: #fff;
--Switch-onHover-bgColor: var(--Switch-bgColor);
--Switch-valueColor: var(--white);
--Switch-width: #{px2rem(50px)};
--Switch-slider-margin: #{px2rem(1px)};
--Switch-slider-width: calc(
var(--Switch-height) - var(--Switch-slider-margin) * 2
);
--Switch-slider-transition: margin-left var(--animation-duration);
--Switch-text-marginRight: #{px2rem(8px)};
--Switch-text-marginLeft: #{px2rem(25px)};
--Switch-width--sm: #{px2rem(28px)};
--Switch-height--sm: #{px2rem(16px)};
--Switch-slider-width--sm: calc(
var(--Switch-height--sm) - var(--Switch-slider-margin) * 2
);
--Switch-text-marginRight--sm: calc(
var(--Switch-slider-margin) * 2 + var(--Switch-text-marginRight) / 2
);
--Switch-text-marginLeft--sm: calc(
var(--Switch-slider-margin) * 2 + var(--Switch-text-marginLeft) / 2
);
--Table--unsaved-heading-bg: #e8f0fe;
--Table--unsaved-heading-color: #4285f4;

View File

@ -18,12 +18,13 @@
}
.text {
margin: 0 px2rem(7px) 0 px2rem(25px);
margin: 0 var(--Switch-text-marginRight) 0 var(--Switch-text-marginLeft);
color: var(--Switch-valueColor);
text-indent: var(--gap-xs);
text-transform: uppercase;
font-size: var(--fontSizeSm);
line-height: var(--Switch-height);
vertical-align: super;
font-style: normal;
font-weight: bold;
transition: all var(--animation-duration);
@ -40,27 +41,31 @@
content: '';
position: absolute;
background: var(--white);
width: calc(var(--Switch-height) - #{px2rem(2px)});
top: px2rem(1px);
bottom: px2rem(1px);
left: px2rem(1px);
width: var(--Switch-slider-width);
top: var(--Switch-slider-margin);
bottom: var(--Switch-slider-margin);
left: var(--Switch-slider-margin);
border-radius: 50%;
transition: margin-left var(--animation-duration);
transition: var(--Switch-slider-transition);
}
}
&:hover {
background: var(--Switch-onHover-bgColor);
}
&.is-checked {
background: var(--Switch-onActive-bgColor);
.slider::before {
left: auto;
right: px2rem(1px);
right: var(--Switch-slider-margin);
border-width: 0;
}
.text {
color: var(--white);
margin: 0 px2rem(25px) 0 px2rem(7px);
margin: 0 var(--Switch-text-marginLeft) 0 var(--Switch-text-marginRight);
}
}
@ -78,6 +83,36 @@
position: absolute;
opacity: 0;
}
&--sm {
height: var(--Switch-height--sm);
min-width: var(--Switch-width--sm);
.text {
line-height: var(--Switch-height--sm);
margin: 0 var(--Switch-text-marginRight--sm) 0
var(--Switch-text-marginLeft--sm);
> svg {
margin-top: calc((var(--Switch-height--sm) - var(--fontSizeSm)) / 2);
}
}
.slider::before {
width: var(--Switch-slider-width--sm);
}
&.is-checked {
.slider::before {
right: var(--Switch-slider-margin);
}
.text {
margin: 0 var(--Switch-text-marginLeft--sm) 0
var(--Switch-text-marginRight--sm);
}
}
}
}
.#{$ns}Switch-option {

View File

@ -232,14 +232,19 @@ $L1: 0px 4px 6px 0px rgba(8, 14, 26, 0.06),
--Switch-width: #{px2rem(44px)};
--Switch-valueColor: #{$G11};
--Switch-bgColor: #{$G7};
--Switch-onActive-bgColor: #{$G6};
--Switch-onActive-bgColor: var(--primary);
--Switch-onHover-bgColor: #{$G6};
--Switch-checked-bgColor: var(--primary);
--Switch-checked-onHover-bgColor: #{$B7};
--Switch-checked-onActive-bgColor: #{$B7};
--Switch-onDisabled-bgColor: #{$B2};
--Switch-onDisabled-color: #{$G11};
// --Switch-onDisabled-circle-BackgroundColor: #fff;
--Switch-slider-margin: #{px2rem(2px)};
--Switch-slider-width: calc(
var(--Switch-height) - var(--Switch-slider-margin) * 2
);
--Switch-slider-transition: all 0.5s ease;
--Switch-text-margin: 0 px2rem(8px) 0 px2rem(25px);
--Calendar-icon-bottom: #{px2rem(-4px)};
--Calendar-icon-width: #{px2rem(10px)};

View File

@ -1,54 +1,36 @@
// 百度云舍主题http://console.yunshe.design/docs/index
@import './cxd-variables';
@import './common';
.#{$ns}Switch {
.text {
margin: 0 px2rem(8px) 0 px2rem(25px);
vertical-align: super;
}
.slider {
&:before {
width: calc(var(--Switch-height) - #{px2rem(4px)});
top: px2rem(2px);
bottom: px2rem(2px);
left: px2rem(2px);
transition: all 0.5s ease;
}
}
&:active {
.slider::before {
width: calc(var(--Switch-height) + #{px2rem(2px)});
width: calc(var(--Switch-slider-width) + var(--Switch-slider-margin) * 2);
border-radius: 10px;
}
}
&:hover {
background: var(--Switch-onHover-bgColor);
}
&.is-checked {
background: var(--Switch-checked-bgColor);
.slider::before {
right: auto;
left: calc(
100% - (var(--Switch-height) - #{px2rem(4px)}) - #{px2rem(2px)}
);
}
.text {
margin: 0 px2rem(25px) 0 px2rem(8px);
}
&:hover {
background: var(--Switch-checked-onHover-bgColor);
}
&:active {
background: var(--Switch-checked-onActive-bgColor);
.slider::before {
left: calc(
100% - (var(--Switch-height) + #{px2rem(2px)}) - #{px2rem(2px)}
right: calc(var(--Switch-slider-margin) * 2);
}
}
}
&--sm {
&:active {
.slider::before {
width: calc(
var(--Switch-slider-width--sm) + var(--Switch-slider-margin) * 2
);
border-radius: 10px;
}
}
}

View File

@ -9,10 +9,11 @@ import {ClassNamesFn, themeable} from 'amis-core';
import {classPrefix, classnames} from '../themes/default';
const sizeMap = {
md: 'i-switch-md',
lg: 'i-switch-lg',
middle: 'i-switch-md',
large: 'i-switch-lg'
sm: 'Switch--sm',
md: 'Switch--md',
middle: 'Switch--md',
lg: 'Switch--lg',
large: 'Switch--lg'
};
const levelMap = {
@ -23,7 +24,7 @@ const levelMap = {
interface SwitchProps {
id?: string;
size?: 'md' | 'lg' | 'middle' | 'large';
size?: 'sm' | 'md' | 'lg' | 'middle' | 'large';
level?: 'info' | 'primary' | 'danger';
className?: string;
classPrefix: string;

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Renderer:switch 1`] = `
exports[`Renderer:Switch Switch basic props 1`] = `
<div>
<div
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
@ -16,7 +16,7 @@ exports[`Renderer:switch 1`] = `
class="cxd-TplField"
>
<span>
The form
表单
</span>
</span>
</h3>
@ -110,6 +110,138 @@ exports[`Renderer:switch 1`] = `
</div>
<div
class="resize-sensor-appear"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;animation-name: apearSensor; animation-duration: 0.2s;"
/>
</div>
</div>
</div>
`;
exports[`Renderer:Switch Switch size 1`] = `
<div>
<div
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
style="position: relative;"
>
<div
class="cxd-Panel-heading"
>
<h3
class="cxd-Panel-title"
>
<span
class="cxd-TplField"
>
<span>
表单
</span>
</span>
</h3>
</div>
<div
class="cxd-Panel-body"
>
<form
class="cxd-Form cxd-Form--normal"
novalidate=""
>
<input
style="display: none;"
type="submit"
/>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
开关
</span>
</span>
</span>
</label>
<div
class="cxd-SwitchControl cxd-Form-control"
>
<label
class="cxd-Switch cxd-Switch--sm"
>
<input
theme="cxd"
type="checkbox"
/>
<span
class="text"
/>
<span
class="slider"
/>
</label>
<span
class="cxd-Switch-option"
/>
</div>
</div>
</form>
</div>
<div
class="cxd-Panel-footerWrap"
>
<div
class="cxd-Panel-btnToolbar cxd-Panel-footer"
>
<button
class="cxd-Button cxd-Button--primary"
type="submit"
>
<span>
提交
</span>
</button>
</div>
</div>
<div
class="resize-sensor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
class="resize-sensor-expand"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0px; top: 0px; width: 10px; height: 10px;"
/>
</div>
<div
class="resize-sensor-shrink"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0; top: 0; width: 200%; height: 200%"
/>
</div>
<div
class="resize-sensor-appear"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;animation-name: apearSensor; animation-duration: 0.2s;"

View File

@ -1,4 +1,3 @@
import React = require('react');
import {render, cleanup} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
@ -10,39 +9,58 @@ afterEach(() => {
clearStoresCache();
});
test('Renderer:switch', async () => {
const {container} = render(
amisRender(
{
type: 'form',
title: 'The form',
controls: [
{
name: 'switch',
className: 'block',
label: '开关',
type: 'switch',
addable: true,
removeable: true,
minLength: 1,
maxLength: 4,
addButtonText: '新增',
draggable: true,
draggableTip: '可通过拖动每行中的【交换】按钮进行顺序调整',
value: true,
trueValue: true,
falseValue: false,
disabled: false,
option: 'switch',
optionAtLeft: false
}
],
submitText: null,
actions: []
},
{},
makeEnv()
)
);
expect(container).toMatchSnapshot();
describe('Renderer:Switch', () => {
test('Switch basic props', async () => {
const {container} = render(
amisRender(
{
type: 'form',
body: [
{
name: 'switch',
className: 'block',
label: '开关',
type: 'switch',
value: true,
trueValue: true,
falseValue: false,
disabled: false,
option: 'switch',
optionAtLeft: false
}
],
submitText: null,
actions: []
},
{},
makeEnv()
)
);
expect(container).toMatchSnapshot();
});
test('Switch size', async () => {
const {container} = render(
amisRender(
{
type: 'form',
body: [
{
name: 'switch',
label: '开关',
type: 'switch',
size: 'sm'
}
]
},
{},
makeEnv()
)
);
const SwitchDom = container.querySelector('.cxd-Switch--sm');
expect(SwitchDom).toBeTruthy();
expect(container).toMatchSnapshot();
});
});

View File

@ -41,12 +41,16 @@ export interface SwitchControlSchema extends FormBaseControlSchema {
*
*/
offText?: string | IconSchema;
/** 开关尺寸 */
size?: 'sm' | 'md';
}
export interface SwitchProps extends FormControlProps {
option?: string;
trueValue?: any;
falseValue?: any;
size?: 'sm';
}
export type SwitchRendererEvent = 'change';
@ -76,6 +80,7 @@ export default class SwitchControl extends React.Component<SwitchProps, any> {
render() {
const {
size,
className,
classPrefix: ns,
classnames: cx,
@ -112,6 +117,7 @@ export default class SwitchControl extends React.Component<SwitchProps, any> {
offText={off}
disabled={disabled}
onChange={this.handleChange}
size={size as any}
/>
{optionAtLeft ? null : (