完成分页组件的迁移;优化button组件
parent
211e90e4f0
commit
1665e881fb
|
@ -42,7 +42,7 @@
|
|||
- [x] `wc-markd`markdown 组件
|
||||
- [ ] `wc-meditor`md 文本编辑器
|
||||
- [ ] `wc-neditor`富文本编辑器
|
||||
- [ ] `wc-pager`分页组件
|
||||
- [x] `wc-pager`分页组件
|
||||
- [x] `wc-color`颜色选择器
|
||||
- [ ] `wc-datepicker`日期选择器
|
||||
- [ ] `wc-timepicker`时间选择器
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* @date 2023/03/06 15:17:25
|
||||
*/
|
||||
|
||||
import { css, html, Component, nextTick } from '@bd/core'
|
||||
import { css, html, Component, nextTick, styleMap } from '@bd/core'
|
||||
import '../icon/index.js'
|
||||
|
||||
class Button extends Component {
|
||||
|
@ -62,7 +62,7 @@ class Button extends Component {
|
|||
outline: none;
|
||||
color: inherit;
|
||||
cursor: inherit;
|
||||
transition: background 0.15s linear;
|
||||
transition: background 0.15s linear, color 0.15s linear;
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: none;
|
||||
|
@ -70,8 +70,7 @@ class Button extends Component {
|
|||
}
|
||||
|
||||
.icon {
|
||||
--size: var(--icon-size, 18px);
|
||||
margin-right: 4px;
|
||||
--size: var(--icon-size, 14px);
|
||||
}
|
||||
}
|
||||
:host(:focus-within) {
|
||||
|
@ -121,7 +120,7 @@ class Button extends Component {
|
|||
font-size: map.get($v, 'f');
|
||||
|
||||
.icon {
|
||||
--size: #{map.get($v, 'f')};
|
||||
--size: var(--icon-size, #{map.get($v, 'f')});
|
||||
}
|
||||
}
|
||||
:host([size='#{$s}'][circle]) {
|
||||
|
@ -161,18 +160,19 @@ class Button extends Component {
|
|||
warning: 'orange',
|
||||
danger: 'red',
|
||||
secondary: 'dark',
|
||||
help: 'grey'
|
||||
help: 'grey',
|
||||
plain: 'plain'
|
||||
);
|
||||
|
||||
@loop $t, $c in $colors {
|
||||
:host([type='#{$t}']) {
|
||||
button {
|
||||
color: var(--color-#{$c}-2);
|
||||
border-color: var(--color-#{$c}-2);
|
||||
border-color: var(--color-#{$c}-1);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-#{$c}-1);
|
||||
border-color: var(--color-#{$c}-1);
|
||||
border-color: var(--color-#{$c}-2);
|
||||
}
|
||||
&:active {
|
||||
color: var(--color-#{$c}-3);
|
||||
|
@ -184,7 +184,11 @@ class Button extends Component {
|
|||
|
||||
&:host([solid]) button {
|
||||
border: 0;
|
||||
@if $t == 'plain' {
|
||||
color: var(--color-dark-1);
|
||||
} @else {
|
||||
color: #fff;
|
||||
}
|
||||
background: var(--color-#{$c}-2);
|
||||
|
||||
&:hover {
|
||||
|
@ -215,6 +219,13 @@ class Button extends Component {
|
|||
`
|
||||
]
|
||||
|
||||
#empty = true
|
||||
|
||||
fixStyle() {
|
||||
this.#empty = this.$refs.cont?.assignedNodes().length === 0
|
||||
this.$requestUpdate()
|
||||
}
|
||||
|
||||
created() {
|
||||
this.stamp = 0
|
||||
|
||||
|
@ -241,13 +252,15 @@ class Button extends Component {
|
|||
if (this.autofocus) {
|
||||
nextTick(_ => this.$refs.btn.focus())
|
||||
}
|
||||
nextTick(_ => this.fixStyle())
|
||||
}
|
||||
|
||||
render() {
|
||||
let style = styleMap({ 'margin-right': this.#empty ? 0 : '4px' })
|
||||
return html`
|
||||
<button ref="btn" disabled=${this.disabled}>
|
||||
<wc-icon class="icon" name=${this.icon}></wc-icon>
|
||||
<slot></slot>
|
||||
<wc-icon class="icon" name=${this.icon} style=${style}></wc-icon>
|
||||
<slot ref="cont"></slot>
|
||||
</button>
|
||||
`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2023/04/18 09:38:01
|
||||
*/
|
||||
|
||||
import { css, html, Component, bind, styleMap } from '@bd/core'
|
||||
import '../form/button.js'
|
||||
|
||||
const LAYOUT_DICT = {
|
||||
home: e =>
|
||||
html`<wc-button
|
||||
solid
|
||||
type="plain"
|
||||
data-act="1"
|
||||
disabled=${e}
|
||||
class="item"
|
||||
icon="dbl-left"
|
||||
></wc-button>`,
|
||||
end: e =>
|
||||
html`<wc-button
|
||||
solid
|
||||
type="plain"
|
||||
data-act="end"
|
||||
disabled=${e}
|
||||
class="item"
|
||||
icon="dbl-right"
|
||||
></wc-button>`,
|
||||
prev: e =>
|
||||
html`<wc-button
|
||||
solid
|
||||
type="plain"
|
||||
data-act="prev"
|
||||
disabled=${e}
|
||||
class="item"
|
||||
icon="left"
|
||||
></wc-button>`,
|
||||
next: e =>
|
||||
html`<wc-button
|
||||
solid
|
||||
type="plain"
|
||||
data-act="next"
|
||||
disabled=${e}
|
||||
class="item"
|
||||
icon="right"
|
||||
></wc-button>`,
|
||||
curr: n => html`<span class="curr item">${n}</span>`,
|
||||
info: (t, p) => html`<span class="item">共 ${t}条, ${p}页</span>`,
|
||||
jump(n) {
|
||||
return html`<section class="item jump">
|
||||
<span>Go to</span>
|
||||
<input ref="input" @keydown=${this.gotoPage} maxlength="6" value=${n} />
|
||||
</section>`
|
||||
}
|
||||
}
|
||||
|
||||
// 计算页码
|
||||
function calculate(curr, total) {
|
||||
var arr = []
|
||||
var fixed = 0
|
||||
var half = curr < 3 ? 6 - curr : 2 // 中间页码
|
||||
|
||||
// 总页码小于2
|
||||
if (total < 2) {
|
||||
arr.push({ to: curr, txt: curr })
|
||||
return arr
|
||||
}
|
||||
|
||||
// 当前页面比半数多时, 前面的用省略号代替
|
||||
if (curr - half > 1 && total > 5) {
|
||||
var to = curr - 2 * half
|
||||
to = to < 1 ? 1 : to
|
||||
arr.push({ to, txt: '...' })
|
||||
}
|
||||
|
||||
if (total - curr < half) {
|
||||
fixed = half - total + curr
|
||||
}
|
||||
|
||||
// 把页码拆成2部分来
|
||||
for (var i = curr - half - fixed; i < curr + half + 1 && i <= total; i++) {
|
||||
if (i > 0) {
|
||||
arr.push({ to: i, txt: i })
|
||||
}
|
||||
}
|
||||
|
||||
// 总页码太多时, 以省略号代替
|
||||
if (curr + half < total) {
|
||||
var to = curr + 2 * half
|
||||
to = to > total ? total : to
|
||||
arr.push({ to, txt: '...' })
|
||||
}
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
class Pager extends Component {
|
||||
static props = {
|
||||
layout: {
|
||||
type: String,
|
||||
default: 'home, prev, pages, next, end',
|
||||
attribute: false
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
attribute: false,
|
||||
observer(v) {
|
||||
if (this.#mounted) {
|
||||
this.totalpage = Math.ceil(v / this.pagesize)
|
||||
}
|
||||
}
|
||||
},
|
||||
totalpage: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
attribute: false,
|
||||
observer(v) {
|
||||
if (this.page > v) {
|
||||
this.page = v
|
||||
}
|
||||
}
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
attribute: false,
|
||||
observer(v) {
|
||||
if (v > this.totalpage) {
|
||||
this.page = this.totalpage
|
||||
} else if (v < 1) {
|
||||
this.page = 1
|
||||
}
|
||||
}
|
||||
},
|
||||
pagesize: {
|
||||
type: Number,
|
||||
default: 20,
|
||||
attribute: false,
|
||||
observer(v) {
|
||||
if (this.total > 0) {
|
||||
this.totalpage = Math.ceil(this.total / v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
color: var(--color-dark-1);
|
||||
|
||||
.layout {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 10px auto;
|
||||
}
|
||||
|
||||
.item {
|
||||
min-width: 32px;
|
||||
width: auto;
|
||||
--padding: 0;
|
||||
margin: 0 5px;
|
||||
--icon-size: 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
&.curr {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 32px;
|
||||
background: var(--color-teal-1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.jump {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&[size='l'] {
|
||||
--icon-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
width: 48px;
|
||||
height: 24px;
|
||||
padding: 0 4px;
|
||||
margin-left: 4px;
|
||||
border: 1px solid var(--color-grey-2);
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
outline: none;
|
||||
transition: box-shadow 0.15s linear;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px var(--color-plain-a);
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
css``
|
||||
]
|
||||
|
||||
#mounted = false
|
||||
|
||||
handleBtnClick(ev) {
|
||||
let elem = ev.target
|
||||
if (elem.tagName === 'WC-BUTTON') {
|
||||
let { page, totalpage } = this
|
||||
let num = elem.dataset.act
|
||||
|
||||
if (elem.disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
switch (num) {
|
||||
case 'prev':
|
||||
num = page - 1
|
||||
break
|
||||
|
||||
case 'next':
|
||||
console.log(num, page)
|
||||
num = page + 1
|
||||
break
|
||||
|
||||
case 'end':
|
||||
num = totalpage
|
||||
break
|
||||
}
|
||||
|
||||
if (+num === page) {
|
||||
return
|
||||
}
|
||||
|
||||
this.page = num
|
||||
|
||||
this.$emit('page-changed', { data: num })
|
||||
}
|
||||
}
|
||||
|
||||
gotoPage(ev) {
|
||||
if (ev.keyCode === 13) {
|
||||
let n = +ev.target.value
|
||||
if (n === n) {
|
||||
this.page = n
|
||||
this.$emit('page-changed', { data: this.page })
|
||||
}
|
||||
ev.target.value = this.page
|
||||
}
|
||||
}
|
||||
|
||||
mounted() {
|
||||
this.#mounted = true
|
||||
}
|
||||
|
||||
render() {
|
||||
let layout = this.layout.split(',').map(s => s.trim())
|
||||
let { page, total, totalpage } = this
|
||||
|
||||
return html`
|
||||
<div class="layout" @click=${this.handleBtnClick}>
|
||||
${layout.map(n => {
|
||||
switch (n) {
|
||||
case 'pages':
|
||||
return calculate(page, totalpage).map(it =>
|
||||
page === it.to
|
||||
? LAYOUT_DICT.curr(page)
|
||||
: html`<wc-button
|
||||
type="plain"
|
||||
solid
|
||||
class="item"
|
||||
data-act="${it.to}"
|
||||
>${it.txt}</wc-button
|
||||
>`
|
||||
)
|
||||
|
||||
case 'home':
|
||||
return LAYOUT_DICT.home(page === 1)
|
||||
|
||||
case 'prev':
|
||||
return LAYOUT_DICT.prev(page === 1)
|
||||
|
||||
case 'next':
|
||||
return LAYOUT_DICT.next(page >= totalpage)
|
||||
|
||||
case 'end':
|
||||
return LAYOUT_DICT.end(page >= totalpage)
|
||||
|
||||
case 'curr':
|
||||
return LAYOUT_DICT.curr(page)
|
||||
|
||||
case 'info':
|
||||
return LAYOUT_DICT.info(total, totalpage)
|
||||
|
||||
case 'jump':
|
||||
return LAYOUT_DICT.jump.call(this, page)
|
||||
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
Pager.reg('pager')
|
Loading…
Reference in New Issue