diff --git a/Readme.md b/Readme.md index be58a4e..0609e49 100644 --- a/Readme.md +++ b/Readme.md @@ -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`时间选择器 diff --git a/src/form/button.js b/src/form/button.js index 89f5b2d..9549dfd 100644 --- a/src/form/button.js +++ b/src/form/button.js @@ -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; - color: #fff; + @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` ` } diff --git a/src/pager/index.js b/src/pager/index.js new file mode 100644 index 0000000..21c6bfc --- /dev/null +++ b/src/pager/index.js @@ -0,0 +1,316 @@ +/** + * {} + * @author yutent + * @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``, + end: e => + html``, + prev: e => + html``, + next: e => + html``, + curr: n => html`${n}`, + info: (t, p) => html`共 ${t}条, ${p}页`, + jump(n) { + return html`
+ Go to + +
` + } +} + +// 计算页码 +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` +
+ ${layout.map(n => { + switch (n) { + case 'pages': + return calculate(page, totalpage).map(it => + page === it.to + ? LAYOUT_DICT.curr(page) + : html`${it.txt}` + ) + + 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 '' + } + })} +
+ ` + } +} + +Pager.reg('pager')