mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-01 19:47:56 +08:00
feat:Spinner组件功能升级 (#3427)
Co-authored-by: gongchengxiang <gongchengxiang@baidu.com>
This commit is contained in:
parent
28821fdb98
commit
d961b42753
@ -178,12 +178,6 @@ exports[`Renderer:Form initApi 1`] = `
|
||||
style="display: none;"
|
||||
type="submit"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal"
|
||||
data-role="form-item"
|
||||
@ -345,12 +339,6 @@ exports[`Renderer:Form sendOn:true 1`] = `
|
||||
style="display: none;"
|
||||
type="submit"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal"
|
||||
data-role="form-item"
|
||||
@ -865,12 +853,6 @@ exports[`Renderer:Form:remoteValidate 1`] = `
|
||||
style="display: none;"
|
||||
type="submit"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal is-error"
|
||||
data-role="form-item"
|
||||
|
@ -104,11 +104,16 @@ exports[`Form:initData:remote 1`] = `
|
||||
type="submit"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner-overlay in"
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner in cxd-Spinner--overlay"
|
||||
/>
|
||||
class="cxd-Spinner cxd-Spinner--overlay"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-icon cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal"
|
||||
data-role="form-item"
|
||||
@ -253,12 +258,6 @@ exports[`Form:initData:remote 3`] = `
|
||||
style="display: none;"
|
||||
type="submit"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal"
|
||||
data-role="form-item"
|
||||
|
@ -165,12 +165,6 @@ exports[`Renderer:service 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -8,7 +8,12 @@ exports[`Renderer:markdown 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-Spinner in"
|
||||
/>
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-icon cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -209,12 +209,6 @@ exports[`Renderer:Page handleAction actionType=ajax & feedback 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -357,12 +351,6 @@ exports[`Renderer:Page handleAction actionType=ajax 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -828,8 +816,13 @@ exports[`Renderer:Page handleAction actionType=drawer 1`] = `
|
||||
class="cxd-Spinner-overlay in"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner in cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
class="cxd-Spinner cxd-Spinner--overlay in"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-Drawer-footer"
|
||||
@ -1068,12 +1061,6 @@ exports[`Renderer:Page initApi 1`] = `
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -1101,12 +1088,6 @@ exports[`Renderer:Page initApi error show Message 1`] = `
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Alert cxd-Alert--danger"
|
||||
>
|
||||
@ -1150,12 +1131,6 @@ exports[`Renderer:Page initApi reFetch when condition changes 1`] = `
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -1222,12 +1197,6 @@ exports[`Renderer:Page initApi reload by Dialog action 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -1442,12 +1411,6 @@ exports[`Renderer:Page initApi reload by Drawer action 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -1755,12 +1718,6 @@ exports[`Renderer:Page initApi reload by Form submit 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -1902,12 +1859,6 @@ exports[`Renderer:Page initApi reload by Form submit 2`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -1948,12 +1899,6 @@ exports[`Renderer:Page initApi reload by action 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -1994,12 +1939,6 @@ exports[`Renderer:Page initApi reload by action 2`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -2032,8 +1971,13 @@ exports[`Renderer:Page initApi show loading 1`] = `
|
||||
className="cxd-Spinner-overlay in"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner in cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
className="cxd-Spinner cxd-Spinner--overlay in"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -2061,12 +2005,6 @@ exports[`Renderer:Page initApi show loading 2`] = `
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -2098,8 +2036,13 @@ exports[`Renderer:Page initApi silentPolling 1`] = `
|
||||
className="cxd-Spinner-overlay in"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner in cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
className="cxd-Spinner cxd-Spinner--overlay in"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -2127,12 +2070,6 @@ exports[`Renderer:Page initApi silentPolling 2`] = `
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
@ -2241,12 +2178,6 @@ exports[`Renderer:Page initFetchOn trigger initApi fetch when condition becomes
|
||||
<div
|
||||
className="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
className="cxd-TplField"
|
||||
>
|
||||
|
@ -1750,8 +1750,13 @@ exports[`Renderer:Wizard initApi show loading 1`] = `
|
||||
className="cxd-Spinner-overlay in"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner in cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
className="cxd-Spinner cxd-Spinner--overlay in"
|
||||
>
|
||||
<div
|
||||
className="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1939,12 +1944,6 @@ exports[`Renderer:Wizard initApi show loading 2`] = `
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
className="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -26,12 +26,6 @@ exports[`api:cache 1`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
@ -72,12 +66,6 @@ exports[`api:cache 2`] = `
|
||||
<div
|
||||
class="cxd-Page-body"
|
||||
>
|
||||
<div
|
||||
class="cxd-Spinner-overlay"
|
||||
/>
|
||||
<div
|
||||
class="cxd-Spinner cxd-Spinner--overlay cxd-Spinner--lg"
|
||||
/>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
|
@ -8,13 +8,191 @@ icon:
|
||||
order: 64
|
||||
---
|
||||
|
||||
一般用来做 `loading` 使用。
|
||||
|
||||
## 基本使用
|
||||
|
||||
`show` 属性控制 `spinner` 是否渲染。
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": {
|
||||
"type": "spinner"
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`size` 属性控制 `spinner` 的大小,有三种配置:`sm`, `lg` 和 空值。
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": [
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"size": "sm",
|
||||
"className": "mr-4"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"size": "",
|
||||
"className": "mr-4"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"size": "lg"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`className` 属性、 `spinnerClassName`属性和 `spinnerWrapClassName`属性可以配置 spinner 自定义的 class,`className`会添加到 spinner 组件的最外层标签上,`spinnerClassName`会添加到 icon 对应的标签上,`spinnerWrapClassName` 在作为组件容器使用时,会作用于整个 Spinner 组件的最外层元素上。
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": [
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"className": "my-spinner",
|
||||
"spinnerClassName": "my-spinner-custom-icon",
|
||||
"spinnerWrapClassName": "my-spinner-wrap",
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`icon` 属性可以配置自定义的图标,可以是 `amis` 内置的图标名称(需要是在 icons.tsx 组件中注册过的); 可以是字体图标库的名称(需要引入对应的图标库),比如`fa fa-spinner`; 也可以是网络图片,比如 `/examples/static/logo.png`;
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": [
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"icon": "",
|
||||
"className": "mr-4"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"icon": "reload",
|
||||
"className": "mr-4"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"icon": "fa fa-spinner",
|
||||
"className": "mr-4"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"icon": "/examples/static/logo.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`tip` 属性可以配置 spinner 的文案,同时 `tipPlacement`可以配置 tip 的相对于 icon 的位置,有四种配置:`top`,`right`,`bottom`(默认),`left`;
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": [
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"tip": "加载中...",
|
||||
"className": "mr-10"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"tip": "加载中...",
|
||||
"tipPlacement": "right",
|
||||
"className": "mr-10"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"tip": "加载中...",
|
||||
"tipPlacement": "top",
|
||||
"className": "mr-10"
|
||||
},
|
||||
{
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"tip": "加载中...",
|
||||
"tipPlacement": "left"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`delay` 属性可以配置 spinner 的延迟显示时间,例如 delay=1000,`show` 属性设为 `true` 后,1000ms 后才会显示出来。
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": {
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"delay": 1000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 作为容器使用
|
||||
|
||||
`spinner` 组件可以作为容器使用,被包裹的内容可通过 `body` 配置, 且作为容器使用的时候可以使用 `overlay` 属性来配置显示 spinner 的时候是否显示遮罩层(遮罩层背景颜色默认是透明的,可通过外层 className 自定义遮罩层颜色)。
|
||||
|
||||
```schema
|
||||
{
|
||||
"type": "page",
|
||||
"body": {
|
||||
"type": "spinner",
|
||||
"show": true,
|
||||
"overlay": true,
|
||||
"body": {
|
||||
"type": "form",
|
||||
"body": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "name",
|
||||
"label": "姓名:"
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"type": "input-email",
|
||||
"label": "邮箱:"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| -------------------- | ----------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| type | `string` | `spinner` | 指定为 Spinner 渲染器 |
|
||||
| show | `boolean` | `true` | 是否显示 spinner 组件 |
|
||||
| className | `string` | | spinner 图标父级标签的自定义 class |
|
||||
| spinnerClassName | `string` | | 组件中 icon 所在标签的自定义 class |
|
||||
| spinnerWrapClassName | `string` | | 作为容器使用时组件最外层标签的自定义 class |
|
||||
| size | `string` | | 组件大小 `sm` `lg` |
|
||||
| icon | `string` | | 组件图标,可以是`amis`内置图标,也可以是字体图标或者网络图片链接,作为 ui 库使用时也可以是自定义组件 |
|
||||
| tip | `string` | | 配置组件文案,例如`加载中...` |
|
||||
| tipPlacement | `top`, `right`, `bottom`, `left` | `bottom` | 配置组件 `tip` 相对于 `icon` 的位置 |
|
||||
| delay | `number` | `0` | 配置组件显示延迟的时间(毫秒) |
|
||||
| overlay | `boolean` | `true` | 配置组件显示 spinner 时是否显示遮罩层 |
|
||||
| body | [SchemaNode](../../docs/types/schemanode) | | 作为容器使用时,被包裹的内容 |
|
||||
|
@ -1238,15 +1238,16 @@
|
||||
--Sparkline-line-color: var(--info);
|
||||
--Sparkline-area-color: #{rgba($info, 0.1)};
|
||||
|
||||
--Spinner--lg-height: #{px2rem(50px)};
|
||||
--Spinner--lg-width: #{px2rem(50px)};
|
||||
--Spinner--lg-height: #{px2rem(48px)};
|
||||
--Spinner--lg-width: #{px2rem(48px)};
|
||||
--Spinner--sm-height: #{px2rem(16px)};
|
||||
--Spinner--sm-width: #{px2rem(16px)};
|
||||
// 修改自 https://github.com/SamHerbert/SVG-Loaders/blob/master/svg-loaders/tail-spin.svg
|
||||
--Spinner-bg: url("data:image/svg+xml,%0A%3Csvg width='38' height='38' viewBox='0 0 38 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3ClinearGradient x1='8.042%25' y1='0%25' x2='65.682%25' y2='23.865%25' id='a'%3E%3Cstop stop-color='%23eee' stop-opacity='0' offset='0%25'/%3E%3Cstop stop-color='%23999' stop-opacity='.631' offset='63.146%25'/%3E%3Cstop stop-color='%23666' offset='100%25'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg transform='translate(1 1)'%3E%3Cpath d='M36 18c0-9.94-8.06-18-18-18' id='Oval-2' stroke='url(%23a)' stroke-width='2'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 18 18' to='360 18 18' dur='0.9s' repeatCount='indefinite' /%3E%3C/path%3E%3Ccircle fill='%23eee' cx='36' cy='18' r='1'%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 18 18' to='360 18 18' dur='0.9s' repeatCount='indefinite' /%3E%3C/circle%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A");
|
||||
--Spinner-height: #{px2rem(26px)};
|
||||
--Spinner-height: #{px2rem(32px)};
|
||||
--Spinner-overlay-bg: rgba(255, 255, 255, 0.4);
|
||||
--Spinner-width: #{px2rem(26px)};
|
||||
--Spinner-width: #{px2rem(32px)};
|
||||
--Spinner-color: #2468f2;
|
||||
|
||||
--Switch-bgColor: #{$gray600};
|
||||
--Switch-borderColor: #{darken($gray600, 10%)};
|
||||
|
@ -18,8 +18,130 @@
|
||||
}
|
||||
}
|
||||
|
||||
.is-spin {
|
||||
animation: spin 2s linear infinite;
|
||||
.#{$ns}Spinner {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: ease-out opacity var(--animation-duration);
|
||||
|
||||
&.in {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.#{$ns}Spinner-icon {
|
||||
width: var(--Spinner-width);
|
||||
height: var(--Spinner-height);
|
||||
position: relative;
|
||||
transform: translateZ(0);
|
||||
animation: spin 2s linear infinite;
|
||||
transition: ease-out all var(--animation-duration);
|
||||
|
||||
&--default {
|
||||
background: var(--Spinner-bg);
|
||||
background-size: 100%;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
&--simple {
|
||||
background: transparent;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: var(--Spinner-color);
|
||||
}
|
||||
|
||||
svg.icon {
|
||||
top: 0;
|
||||
|
||||
path {
|
||||
fill: var(--Spinner-color);
|
||||
}
|
||||
}
|
||||
|
||||
i.icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: var(--Spinner-width);
|
||||
}
|
||||
}
|
||||
|
||||
&--custom {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
&--lg {
|
||||
width: var(--Spinner--lg-width);
|
||||
height: var(--Spinner--lg-height);
|
||||
|
||||
i.icon {
|
||||
font-size: var(--Spinner--lg-height);
|
||||
}
|
||||
}
|
||||
|
||||
&--sm {
|
||||
width: var(--Spinner--sm-width);
|
||||
height: var(--Spinner--sm-height);
|
||||
|
||||
i.icon {
|
||||
font-size: var(--Spinner--sm-height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}Spinner-tip {
|
||||
margin: px2rem(12px) 0 0 0;
|
||||
word-break: keep-all;
|
||||
white-space: nowrap;
|
||||
color: var(--Spinner-color);
|
||||
}
|
||||
|
||||
&.#{$ns}Spinner-tip--top {
|
||||
flex-direction: column-reverse;
|
||||
|
||||
.#{$ns}Spinner-tip {
|
||||
margin: 0 0 px2rem(12px) 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.#{$ns}Spinner-tip--right {
|
||||
flex-direction: row;
|
||||
|
||||
.#{$ns}Spinner-tip {
|
||||
margin: 0 0 0 px2rem(12px);
|
||||
}
|
||||
}
|
||||
|
||||
&.#{$ns}Spinner-tip--bottom {
|
||||
flex-direction: column;
|
||||
|
||||
.#{$ns}Spinner-tip {
|
||||
margin: px2rem(12px) 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.#{$ns}Spinner-tip--left {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.#{$ns}Spinner-tip {
|
||||
margin: 0 px2rem(12px) 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--overlay {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}Spinner-overlay {
|
||||
@ -31,7 +153,6 @@
|
||||
bottom: 0;
|
||||
background: var(--Spinner-overlay-bg);
|
||||
transition: ease-out opacity var(--animation-duration);
|
||||
|
||||
opacity: 0;
|
||||
|
||||
&.in {
|
||||
@ -39,60 +160,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}Spinner {
|
||||
width: var(--Spinner-width);
|
||||
height: var(--Spinner-height);
|
||||
transform: translateZ(0);
|
||||
display: inline-flex;
|
||||
background: var(--Spinner-bg);
|
||||
background-size: 100%;
|
||||
// spinner渲染器scss
|
||||
.#{$ns}Spinner-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&--lg {
|
||||
width: var(--Spinner--lg-width);
|
||||
height: var(--Spinner--lg-height);
|
||||
}
|
||||
|
||||
&--sm {
|
||||
width: var(--Spinner--sm-width);
|
||||
height: var(--Spinner--sm-height);
|
||||
}
|
||||
|
||||
transition: ease-out all var(--animation-duration);
|
||||
|
||||
&--icon {
|
||||
background: transparent;
|
||||
animation: spin 2s linear infinite;
|
||||
width: 16px; // reload 那个 icon 必须用这个高宽
|
||||
height: 16px;
|
||||
svg.icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 当启用 overlay 的时候,应该是居中模式。
|
||||
.#{$ns}Spinner--overlay {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
}
|
||||
|
||||
.#{$ns}Spinner--overlay.#{$ns}Spinner--lg {
|
||||
width: var(--Spinner--lg-width);
|
||||
height: var(--Spinner--lg-height);
|
||||
line-height: var(--Spinner--lg-height);
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
.#{$ns}Layout .#{$ns}Page-body > .#{$ns}Spinner-overlay {
|
||||
left: var(--Layout-aside-width);
|
||||
}
|
||||
|
||||
.#{$ns}Layout--folded .#{$ns}Page-body > .#{$ns}Spinner-overlay {
|
||||
left: var(--Layout-aside--folded-width);
|
||||
.#{$ns}Spinner {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ import {PaginationSchema} from './renderers/Pagination';
|
||||
import {AnchorNavSchema} from './renderers/AnchorNav';
|
||||
import {AvatarSchema} from './renderers/Avatar';
|
||||
import {StepsSchema} from './renderers/Steps';
|
||||
import {SpinnerSchema} from './renderers/Spinner';
|
||||
import {TimelineSchema} from './renderers/Timeline';
|
||||
import {ArrayControlSchema} from './renderers/Form/InputArray';
|
||||
import {ButtonGroupControlSchema} from './renderers/Form/ButtonGroupSelect';
|
||||
@ -150,6 +151,7 @@ export type SchemaType =
|
||||
| 'month'
|
||||
| 'static-month' // 这个几个跟表单项同名,再form下面用必须带前缀 static-
|
||||
| 'dialog'
|
||||
| 'spinner'
|
||||
| 'divider'
|
||||
| 'dropdown-button'
|
||||
| 'drawer'
|
||||
@ -384,6 +386,7 @@ export type SchemaObject =
|
||||
| ServiceSchema
|
||||
| SparkLineSchema
|
||||
| StatusSchema
|
||||
| SpinnerSchema
|
||||
| TableSchema
|
||||
| TabsSchema
|
||||
| TasksSchema
|
||||
|
@ -7,77 +7,112 @@
|
||||
|
||||
import React from 'react';
|
||||
import {themeable, ThemeProps} from '../theme';
|
||||
import Transition, {ENTERED, ENTERING} from 'react-transition-group/Transition';
|
||||
import {Icon} from './icons';
|
||||
import Transition, {ENTERED} from 'react-transition-group/Transition';
|
||||
import {Icon, hasIcon} from './icons';
|
||||
import {generateIcon} from '../utils/icon';
|
||||
|
||||
const fadeStyles: {
|
||||
[propName: string]: string;
|
||||
} = {
|
||||
[ENTERING]: 'in',
|
||||
[ENTERED]: 'in'
|
||||
};
|
||||
|
||||
interface SpinnerProps extends ThemeProps {
|
||||
overlay: boolean;
|
||||
spinnerClassName: string;
|
||||
mode: string;
|
||||
size: 'sm' | 'lg' | '';
|
||||
show: boolean;
|
||||
icon?: string;
|
||||
// Spinner Props
|
||||
export interface SpinnerProps extends ThemeProps {
|
||||
show: boolean; // 控制Spinner显示与隐藏
|
||||
className?: string; // 自定义最外层元素class
|
||||
spinnerClassName?: string; // spin图标位置包裹元素的自定义class
|
||||
/**
|
||||
* @deprecated 已废弃,没有作用
|
||||
*/
|
||||
mode?: string;
|
||||
size?: 'sm' | 'lg' | ''; // spinner Icon 大小
|
||||
icon?: string | React.ReactNode; // 自定义icon
|
||||
tip?: string; // spinner文案
|
||||
tipPlacement?: 'top' | 'right' | 'bottom' | 'left'; // spinner文案位置
|
||||
delay?: number; // 延迟显示
|
||||
overlay?: boolean; // 是否显示遮罩层,有children属性才生效
|
||||
}
|
||||
|
||||
export class Spinner extends React.Component<SpinnerProps, object> {
|
||||
export class Spinner extends React.Component<SpinnerProps> {
|
||||
static defaultProps = {
|
||||
overlay: false,
|
||||
show: true,
|
||||
className: '',
|
||||
spinnerClassName: '',
|
||||
mode: '',
|
||||
size: '' as '',
|
||||
show: true
|
||||
icon: '',
|
||||
tip: '',
|
||||
tipPlacement: 'bottom' as 'bottom',
|
||||
delay: 0,
|
||||
overlay: false
|
||||
};
|
||||
|
||||
div: React.RefObject<HTMLDivElement> = React.createRef();
|
||||
overlay: React.RefObject<HTMLDivElement> = React.createRef();
|
||||
|
||||
render() {
|
||||
const {
|
||||
show,
|
||||
classnames: cx,
|
||||
show,
|
||||
className,
|
||||
spinnerClassName,
|
||||
mode,
|
||||
size,
|
||||
size = '',
|
||||
overlay,
|
||||
icon
|
||||
delay,
|
||||
icon,
|
||||
tip,
|
||||
tipPlacement = ''
|
||||
} = this.props;
|
||||
return (
|
||||
<Transition mountOnEnter unmountOnExit in={show} timeout={350}>
|
||||
{(status: string) => {
|
||||
if (status === ENTERING) {
|
||||
// force reflow
|
||||
// 由于从 mount 进来到加上 in 这个 class 估计是时间太短,上次的样式还没应用进去,所以这里强制reflow一把。
|
||||
// 否则看不到动画。
|
||||
// this.div.current!.offsetWidth;
|
||||
this.overlay.current && this.overlay.current.offsetWidth;
|
||||
}
|
||||
const isCustomIcon = icon && React.isValidElement(icon);
|
||||
const timeout = {enter: delay, exit: 0};
|
||||
|
||||
return (
|
||||
<Transition mountOnEnter unmountOnExit in={show} timeout={timeout}>
|
||||
{(status: string) => {
|
||||
return (
|
||||
<>
|
||||
{/* 遮罩层 */}
|
||||
{overlay ? (
|
||||
<div
|
||||
ref={this.overlay}
|
||||
className={cx(`Spinner-overlay`, fadeStyles[status])}
|
||||
/>
|
||||
<div className={cx(`Spinner-overlay`, fadeStyles[status])} />
|
||||
) : null}
|
||||
|
||||
{/* spinner图标和文案 */}
|
||||
<div
|
||||
ref={this.div}
|
||||
className={cx(`Spinner`, spinnerClassName, fadeStyles[status], {
|
||||
[`Spinner--${mode}`]: mode,
|
||||
[`Spinner--overlay`]: overlay,
|
||||
[`Spinner--${size}`]: size,
|
||||
[`Spinner--icon`]: icon
|
||||
})}
|
||||
className={cx(
|
||||
`Spinner`,
|
||||
tip && {
|
||||
[`Spinner-tip--${tipPlacement}`]: [
|
||||
'top',
|
||||
'right',
|
||||
'bottom',
|
||||
'left'
|
||||
].includes(tipPlacement)
|
||||
},
|
||||
{[`Spinner--overlay`]: overlay},
|
||||
fadeStyles[status],
|
||||
className
|
||||
)}
|
||||
>
|
||||
{icon ? <Icon icon={icon} className="icon" /> : null}
|
||||
<div
|
||||
className={cx(
|
||||
`Spinner-icon`,
|
||||
{
|
||||
[`Spinner-icon--${size}`]: ['lg', 'sm'].includes(size),
|
||||
[`Spinner-icon--default`]: !icon,
|
||||
[`Spinner-icon--simple`]: !isCustomIcon && icon,
|
||||
[`Spinner-icon--custom`]: isCustomIcon
|
||||
},
|
||||
spinnerClassName
|
||||
)}
|
||||
>
|
||||
{icon ? (
|
||||
isCustomIcon ? (
|
||||
icon
|
||||
) : hasIcon(icon as string) ? (
|
||||
<Icon icon={icon} className="icon" />
|
||||
) : (
|
||||
generateIcon(cx, icon as string, 'icon')
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
{tip ? <span className={cx(`Spinner-tip`)}>{tip}</span> : ''}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -1,14 +1,96 @@
|
||||
import Spinner from '../components/Spinner';
|
||||
import {Renderer, RendererProps} from '../factory';
|
||||
import React from 'react';
|
||||
import {BaseSchema, SchemaCollection} from '../Schema';
|
||||
|
||||
interface SpinnerProps extends RendererProps {}
|
||||
export interface SpinnerSchema extends BaseSchema {
|
||||
/**
|
||||
* 组件类型
|
||||
*/
|
||||
type: 'spinner';
|
||||
|
||||
/**
|
||||
* 控制Spinner显示与隐藏
|
||||
*/
|
||||
show: boolean;
|
||||
|
||||
/**
|
||||
* 自定义spinner的class
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* spin图标位置包裹元素的自定义class
|
||||
*/
|
||||
spinnerClassName?: string;
|
||||
|
||||
/**
|
||||
* 作为容器使用时最外层元素的class
|
||||
*/
|
||||
spinnerWrapClassName?: string;
|
||||
|
||||
/**
|
||||
* @deprecated 已废弃,没有作用
|
||||
*/
|
||||
mode?: string;
|
||||
|
||||
/**
|
||||
* spinner Icon 大小
|
||||
*/
|
||||
size?: 'sm' | 'lg' | '';
|
||||
|
||||
/**
|
||||
* 自定义icon
|
||||
*/
|
||||
icon?: string;
|
||||
|
||||
/**
|
||||
* spinner文案
|
||||
*/
|
||||
tip?: string;
|
||||
|
||||
/**
|
||||
* spinner文案位置
|
||||
*/
|
||||
tipPlacement?: 'top' | 'right' | 'bottom' | 'left';
|
||||
|
||||
/**
|
||||
* 延迟显示
|
||||
*/
|
||||
delay?: number;
|
||||
|
||||
/**
|
||||
* 是否显示遮罩层
|
||||
*/
|
||||
overlay?: boolean;
|
||||
|
||||
/**
|
||||
* 作为容器使用时内容
|
||||
*/
|
||||
body?: SchemaCollection;
|
||||
}
|
||||
|
||||
interface SpinnerRenderProps
|
||||
extends RendererProps,
|
||||
Omit<SpinnerSchema, 'className'> {}
|
||||
|
||||
@Renderer({
|
||||
type: 'spinner'
|
||||
})
|
||||
export class SpinnerRenderer extends React.Component<SpinnerProps> {
|
||||
export class SpinnerRenderer extends React.Component<SpinnerRenderProps> {
|
||||
renderBody() {
|
||||
const {body, render} = this.props;
|
||||
return body ? render('body', body) : null;
|
||||
}
|
||||
render() {
|
||||
return <Spinner {...this.props} />;
|
||||
const {classnames: cx, spinnerWrapClassName, body, ...rest} = this.props;
|
||||
return body ? (
|
||||
<div className={cx(`Spinner-wrap`, spinnerWrapClassName)}>
|
||||
<Spinner {...rest}></Spinner>
|
||||
{this.renderBody()}
|
||||
</div>
|
||||
) : (
|
||||
<Spinner {...rest}></Spinner>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user