isu-elements
Version:
Polymer components for building web apps.
401 lines (367 loc) • 10.5 kB
JavaScript
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class'
import '@webcomponents/shadycss/entrypoints/apply-shim.js'
import { BaseBehavior } from './behaviors/base-behavior'
import { html, PolymerElement } from '@polymer/polymer'
import './behaviors/isu-elements-shared-styles'
import './isu-button'
import './isu-iron-fit'
import { dom } from '@polymer/polymer/lib/legacy/polymer.dom.js'
/**
*
* `isu-button-group`
*
* Example:
* ```html
* <isu-button-group label="测试">
* <div bind-item="1">测试1</div>
* <div bind-item="2">测试2</div>
* <div bind-item="3">测试3</div>
* </isu-button-group>
*
*
* <isu-button-group items="[[ items ]]" label="测试" attr-for-label="label"></isu-button-group>
*
* items = [
* {label: "测试1", value: "1"},
* {label: "测试2", value: "2"},
* {label: "测试3", value: "3"}
* ]
*
* ```
*
* ## Styling
*
* The following custom properties and mixins are available for styling:
*
* |Custom property | Description | Default|
* |----------------|-------------|----------|
* |`--isu-button-group-button` | The style of the trigger button | {}
* |`--isu-button-group-dropdown` | The style of the dropdown menu | {}
* |`--isu-button-group-height` | The height of the trigger button | 100%
*
* @customElement
* @polymer
* @demo demo/isu-button-group/index.html
*/
class IsuButtonGroup extends mixinBehaviors([BaseBehavior], PolymerElement) {
static get template () {
return html`
<style include="isu-elements-shared-styles">
:host {
display: inline-block;
position: relative;
min-width: 70px;
outline: none;
font-family: var(--isu-ui-font-family), sans-serif;
font-size: var(--isu-ui-font-size);
}
.trigger {
width: 100%;
height: var(--isu-button-group-height, 100%);
position: relative;
display: flex;
border-radius: var(--isu-ui-border-radius);
@apply --isu-button-group-button;
}
.trigger__label {
@apply --isu-button-group-trigger__label;
}
:host([divided]) .trigger__label::after {
width: 2px;
border-right: 1px solid lightgray;
content: '|';
color: transparent;
float: right;
}
/*下拉列表*/
:host .dropdown-menu {
background: #fff;
color: var(--isu-ui-color_skyblue);
flex-flow: column nowrap;
box-sizing: border-box;
z-index: 999;
font-size: 1em;
text-align: center;
background-clip: padding-box;
--iron-collapse-transition-duration: 200ms;
overflow: auto;
@apply --isu-button-group-dropdown;
}
.dropdown-menu::-webkit-scrollbar {
display: none;
}
.container {
border-radius: var(--isu-ui-border-radius);
border: 1px solid var(--isu-ui-color_skyblue);
width: 100%;
font-size: 12px;
border-collapse: separate;
border-spacing: 0;
text-align: left;
border-radius: 4px;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
}
.item, ::slotted(*) {
display: block;
cursor: pointer;
margin: 0px;
line-height: 20px;
white-space: nowrap;
font-size: 0.9em;
text-align: center;
outline: none;
}
/*hover*/
.item:hover, ::slotted(*:hover) {
color: #fff;
background: var(--isu-ui-bg);
}
.trigger__icon {
transition: transform .2s ease-in-out
}
:host([opened]) .trigger__icon {
transform: rotate(180deg);
transition: transform .2s ease-in-out
}
:host([size=small]) {
width: 90px;
height: 30px;
}
:host([size=medium]) {
width: 120px;
height: 34px;
}
:host([size=large]) {
width: 150px;
height: 40px;
}
:host([disabled]) {
cursor: not-allowed;
color: #fff;
}
.item([disabled]) {
background: #aeaeae ;
cursor: not-allowed;
color: #fff;
}
#group-collapse {
display: flex;
position: absolute;
margin-top: 1px;
border-radius: 4px;
font-size: 12px;
padding: 0;
background: white;
color: black;
visibility: visible;
opacity: 1;
@apply --isu-picker-dropdown;
}
#group-collapse[hidden] {
visibility: hidden;
height: 0;
opacity: 0;
}
.relative {
position: relative;
}
</style>
<div class$="relative [[fontSize]]" >
<isu-button on-click="_onButtonClick" id="group-button" class="trigger select-button" exportparts="btn" disabled="[[disabled]]" type="[[type]]" part="btn">
<div class="trigger__label select-button">[[ label ]]</div>
<iron-icon class="trigger__icon select-button" icon="icons:expand-more"></iron-icon>
</isu-button>
<isu-iron-fit id="group-collapse" auto-fit-on-attach vertical-align="auto" horizontal-align="auto" class="dropdown-menu" no-overlap dynamic-align hidden="{{!opened}}">
<div class="container" on-click="_onButtonDropdownClick">
<template is="dom-repeat" items="[[ items ]]" filter="_hasPermission">
<paper-button class="item" bind-item="[[ item ]]" disabled="[[item.disabled]]">[[ getValueByKey(item, attrForLabel, 'Unknown') ]]</paper-button>
</template>
<slot id="itemSlot"></slot>
</div>
</isu-iron-fit>
</div>
`
}
static get properties () {
return {
/**
* Size of the action group button.options:small/medium/large.Default option:medium
*
* @type String
* @default medium
*/
size: {
type: String,
value: 'medium',
reflectToAttribute: true
},
/**
* Properties can be selected as default, primary, warning, danger or success
*
* @type String
* @default default
*/
type: {
type: String,
reflectToAttribute: true
},
/**
* Label of the action group.
*
* @type String
* @default
*/
label: {
type: String
},
/**
* Return true if the action group is expanded.
* @type Boolean
* @default false
*/
opened: {
type: Boolean,
value: false,
reflectToAttribute: true
},
/**
* The dropdown items.
* @type Array
*/
items: {
type: Array
},
/**
* Attribute name for label.
* @type String
* @default 'label'
*/
attrForLabel: {
type: String,
value: 'label'
},
/**
* The Function called when user click on every item on dropdownlist.
* @type Object
* @default
*/
onItemClick: {
type: Object
},
/**
* Return true if the button-group element is disabled
* @type Boolean
* @default false
*/
disabled: {
type: Boolean,
reflectToAttribute: true,
value: false
},
/**
* The items will hide when user clicks one item
* @type Boolean
* @default true
* */
hideItemsOnClick: {
type: Boolean,
value: true
},
/**
* Whether to show itself or not
*/
permission: {
type: Boolean,
value: true
},
hidden: {
type: Boolean,
reflectToAttribute: true,
computed: '__isHiddenButton(permission,items)'
}
}
}
static get is () {
return 'isu-button-group'
}
__isHiddenButton (permission, items) {
const flag = permission && items && items.some(item => item.permission || item.permission === undefined)
return !flag
}
connectedCallback () {
super.connectedCallback()
window.addEventListener('scroll', e => {
this.close()
})
const target = dom(this.$['group-collapse']).rootTarget
const myFit = this.$['group-collapse']
myFit.positionTarget = target || this.$['group-button']
}
/**
* Expand the group.
*/
open (e) {
console.log('e.open.target', e.target)
this.set('opened', true)
}
/**
* Collpase the group.
*/
close (e) {
this.set('opened', false)
}
/**
* Toggle the group.
*/
toggle (e) {
if (!this.disabled) {
// const { top, left } = this.getElemPos(this)
// const _top = top + this.clientHeight
//
// this.$.collapse.style.top = _top + 'px'
// this.$.collapse.style.left = left + 'px'
// 当外界设置了下拉框的宽度时,取外界的宽度,否则取按钮的宽度
// this.$.collapse.style.width = (window.getComputedStyle(this.$.collapse).inlineSize !== 'auto') ? window.getComputedStyle(this.$.collapse).inlineSize : this.clientWidth + 'px'
this.opened = !this.opened
}
}
_onButtonClick () {
const self = this
this.toggle()
/*
* 在选择面板打开的时候给body注册click监听事件。以防止多个实例的时候body click事件和实例自身引用错乱的问题。
*/
const bodyClick = function (e) {
const path = Array.from(e.path || e.composedPath())
if (!path.includes(self.$['group-button']) && self.opened) {
self.toggle()
}
document.removeEventListener('click', bodyClick, true)
}
document.addEventListener('click', bodyClick, true)
}
getElemPos (obj) {
const { x, y } = obj.getBoundingClientRect()
return { top: y + 2, left: x }
}
_onButtonDropdownClick (e) {
e.stopPropagation()
const self = this
const target = e.target
const bindItem = e.target.bindItem || e.target.getAttribute('bind-item')
if (self.hideItemsOnClick) {
self.opened = false
}
setTimeout(() => {
self.dispatchEvent(new CustomEvent('item-click', { detail: { target, bindItem } }))
}, 100)
}
/**
* Whether the item has the permission to show or not
* */
_hasPermission (item) {
const permission = 'permission' in item
return !permission || (permission && item.permission)
}
}
window.customElements.define(IsuButtonGroup.is, IsuButtonGroup)