Merge pull request #174 in YR/star-web-components from loading to master
* commit '8fcc32289b60c95868034744805cee4ff0ea3d20': 添加loading组件
This commit is contained in:
commit
85acd240e6
|
@ -385,7 +385,7 @@ const baseStyle = css`
|
|||
`
|
||||
|
||||
const baseDarkStyle = css`
|
||||
@media (prefers-color-scheme: light) {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
/****************************文字颜色*************************************/
|
||||
--font-normal-color: var(--font-secondary-white);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './loading.js'
|
|
@ -0,0 +1,34 @@
|
|||
import {css} from 'lit'
|
||||
|
||||
export default css`
|
||||
:host {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
transition: opacity 0.2s;
|
||||
pointer-events: all;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--base-normal-bgc);
|
||||
box-shadow: var(--business-light-shaded);
|
||||
border-radius: var(--auto-20px);
|
||||
padding: var(--auto-4px) var(--auto-20px) var(--auto-4px) var(--auto-10px);
|
||||
}
|
||||
|
||||
#loading {
|
||||
margin-right: var(--auto-10px);
|
||||
}
|
||||
|
||||
#notice {
|
||||
color: var(--font-normal-color);
|
||||
font-size: var(--auto-16px);
|
||||
}
|
||||
`
|
|
@ -0,0 +1,177 @@
|
|||
import {
|
||||
customElement,
|
||||
html,
|
||||
property,
|
||||
StarBaseElement,
|
||||
state,
|
||||
} from '@star-web-components/base'
|
||||
import {
|
||||
loading_lm_1x,
|
||||
loading_lm_2x,
|
||||
loading_dm_1x,
|
||||
loading_dm_2x,
|
||||
} from '@star-web-components/asset'
|
||||
import loadingStyles from './loading.css.js'
|
||||
|
||||
const assets = {
|
||||
lm1x: loading_lm_1x,
|
||||
lm2x: loading_lm_2x,
|
||||
dm1x: loading_dm_1x,
|
||||
dm2x: loading_dm_2x,
|
||||
}
|
||||
|
||||
interface Options {
|
||||
notice?: string // 提示语
|
||||
size?: 'large' | 'small' // 大小
|
||||
mode?: 'light' | 'dark' // 模式
|
||||
|
||||
canCancel?: boolean // 是否能取消
|
||||
cancelCallback?: (value: any) => any // 取消回调
|
||||
|
||||
showUntil?: Promise<any> | Promise<any>[] // 关闭条件,无论成功与否 settled 即关闭
|
||||
successfulCallback?: (value: any) => any // 成功回调
|
||||
failedCallback?: (value: any) => any // 失败回调
|
||||
settledCallback?: Function // 结束回调
|
||||
|
||||
timeout?: number // 最长显示时长, 超时时无超时回调则默认为失败, 小于等于0意为无时限
|
||||
timeoutCallback?: Function // 超时回调
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
* 1. 待 Overlay 组件完善后, 与其结合使用
|
||||
* 2. 需要知道最长宽度和高度, 以添加省略号
|
||||
*/
|
||||
@customElement('star-loading')
|
||||
export class StarLoading extends StarBaseElement {
|
||||
@property() notice: string = ''
|
||||
// loading 状态是否能取消
|
||||
@property() canCancel: boolean = false
|
||||
// 取消回调
|
||||
cancelCallback?: Function
|
||||
cancel = () => {
|
||||
if (!this.canCancel) return
|
||||
this.cancelCallback?.()
|
||||
this.clearAndRemove()
|
||||
}
|
||||
// 图标大小
|
||||
@property() size: 'large' | 'small' = 'small'
|
||||
|
||||
@state() mode: 'light' | 'dark' = 'light'
|
||||
timeout?: number
|
||||
timeoutCallback?: Function
|
||||
successfulCallback?: Function
|
||||
failedCallback?: Function
|
||||
settledCallback?: Function
|
||||
constructor(opts: Options) {
|
||||
super()
|
||||
if (opts.notice !== undefined) {
|
||||
this.notice = opts.notice
|
||||
}
|
||||
|
||||
if (opts.mode) {
|
||||
this.mode = opts.mode
|
||||
} else {
|
||||
this.addColorSchemeListener()
|
||||
}
|
||||
|
||||
this.canCancel = !!opts.canCancel
|
||||
this.cancelCallback = opts.cancelCallback
|
||||
this.observeStatus(opts)
|
||||
this.timeout = opts.timeout
|
||||
this.timeoutCallback = opts.timeoutCallback
|
||||
}
|
||||
|
||||
blankCallback = () => {}
|
||||
clearAndRemove = () => {
|
||||
this.cancelCallback = undefined
|
||||
this.successfulCallback = undefined
|
||||
this.failedCallback = undefined
|
||||
this.settledCallback = undefined
|
||||
this.timeoutCallback = undefined
|
||||
this.remove()
|
||||
}
|
||||
|
||||
observeStatus = ({
|
||||
showUntil,
|
||||
successfulCallback = this.blankCallback,
|
||||
failedCallback = this.blankCallback,
|
||||
settledCallback = this.blankCallback,
|
||||
}: Options) => {
|
||||
if (!showUntil) return
|
||||
let until!: Promise<any>
|
||||
if (showUntil instanceof Array) {
|
||||
until = Promise.all(showUntil)
|
||||
} else {
|
||||
until = showUntil
|
||||
}
|
||||
|
||||
this.successfulCallback = successfulCallback
|
||||
this.failedCallback = failedCallback
|
||||
this.settledCallback = settledCallback
|
||||
|
||||
until
|
||||
.then((value) => {
|
||||
this.successfulCallback?.(value)
|
||||
})
|
||||
.catch((value) => {
|
||||
this.failedCallback?.(value)
|
||||
})
|
||||
.finally(() => {
|
||||
this.settledCallback?.()
|
||||
this.clearAndRemove()
|
||||
})
|
||||
}
|
||||
|
||||
listener?: EventListener
|
||||
addColorSchemeListener = () => {
|
||||
const media = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
if (media.matches) {
|
||||
this.mode = 'dark'
|
||||
}
|
||||
|
||||
this.listener = (evt: any) => {
|
||||
this.mode = evt.matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
media.addEventListener('change', this.listener)
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.listener &&
|
||||
window
|
||||
.matchMedia('(prefers-color-scheme: dark)')
|
||||
.removeEventListener('change', this.listener)
|
||||
}
|
||||
|
||||
firstUpdated() {
|
||||
if (this.timeout) {
|
||||
setTimeout(() => {
|
||||
this.timeoutCallback?.()
|
||||
this.clearAndRemove()
|
||||
}, this.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let img = this.mode == 'dark' ? 'dm' : 'lm'
|
||||
img += this.size == 'large' ? '2x' : '1x'
|
||||
|
||||
return html`
|
||||
<div id="container">
|
||||
<img id="loading" src=${assets[img as keyof typeof assets]} />
|
||||
<span id="notice">${this.notice}</span>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
static override get styles() {
|
||||
return [loadingStyles]
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'star-loading': StarLoading
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "@star-web-components/loading",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "./index.js",
|
||||
"module": "./index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./index": {
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./li.js": {
|
||||
"default": "./loading.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
import {html, customElement, LitElement} from '@star-web-components/base'
|
||||
import {StarLoading} from '@star-web-components/loading'
|
||||
|
||||
import '@star-web-components/li'
|
||||
import '@star-web-components/button'
|
||||
|
||||
@customElement('panel-loading')
|
||||
export class PanelLoading extends LitElement {
|
||||
createClick() {
|
||||
const loading = new StarLoading({
|
||||
notice: 'loading...',
|
||||
canCancel: true,
|
||||
cancelCallback: () => {
|
||||
console.log('cancel')
|
||||
},
|
||||
})
|
||||
loading.onclick = loading.cancel
|
||||
document.body.appendChild(loading)
|
||||
}
|
||||
|
||||
createTimeout() {
|
||||
const loading = new StarLoading({
|
||||
notice: 'loading...',
|
||||
timeout: 3000,
|
||||
timeoutCallback: () => console.log('loadend'),
|
||||
})
|
||||
document.body.appendChild(loading)
|
||||
}
|
||||
|
||||
createAsync() {
|
||||
const p1 = new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
const num = Math.random()
|
||||
num > 0.5 ? res(num) : rej(num)
|
||||
}, 1000)
|
||||
})
|
||||
const p2 = new Promise((res, rej) => {
|
||||
setTimeout(() => {
|
||||
const num = Math.random()
|
||||
num < 0.5 ? res(num) : rej(num)
|
||||
}, 2000)
|
||||
})
|
||||
const loading = new StarLoading({
|
||||
notice: 'loading...',
|
||||
showUntil: [p1, p2],
|
||||
successfulCallback: (value) => {
|
||||
console.log('success number:', value)
|
||||
},
|
||||
failedCallback: (value) => {
|
||||
console.log('fail number:', value)
|
||||
},
|
||||
settledCallback: () => {
|
||||
console.log('settled')
|
||||
},
|
||||
})
|
||||
document.body.appendChild(loading)
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<star-button
|
||||
type="normal"
|
||||
variant="primary"
|
||||
size="small"
|
||||
label="点击消失"
|
||||
@click=${this.createClick}
|
||||
></star-button>
|
||||
<br />
|
||||
|
||||
<star-button
|
||||
type="normal"
|
||||
variant="primary"
|
||||
size="small"
|
||||
label="3s后消失并打印"
|
||||
@click=${this.createTimeout}
|
||||
></star-button>
|
||||
<br />
|
||||
|
||||
<star-button
|
||||
type="normal"
|
||||
variant="primary"
|
||||
size="small"
|
||||
label="模拟异步事件"
|
||||
@click=${this.createAsync}
|
||||
></star-button>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'panel-loading': PanelLoading
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ import './switch/switch'
|
|||
import './toast/toast'
|
||||
import './weather/weather'
|
||||
import './swiper/swiper'
|
||||
import './loading/loading'
|
||||
|
||||
import './animation/animation'
|
||||
type SEID = string
|
||||
|
@ -128,6 +129,8 @@ export class PanelRoot extends LitElement {
|
|||
<hr />
|
||||
<star-li label="AllConfirm" icon="messages" href="#confirm"></star-li>
|
||||
<hr />
|
||||
<star-li label="loading状态" icon="play-circle" href="#loading"></star-li>
|
||||
<hr />
|
||||
</star-ul>
|
||||
|
||||
<star-ul type=${UlType.BASE}>
|
||||
|
|
Loading…
Reference in New Issue