UNPKG

isu-elements

Version:

Polymer components for building web apps.

398 lines (378 loc) 13.8 kB
import { html, PolymerElement } from '@polymer/polymer' import '@webcomponents/shadycss/entrypoints/apply-shim.js' import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class' import '@polymer/paper-tabs/paper-tabs' import '@polymer/paper-tabs/paper-tab' import '@polymer/paper-styles/color' import '@polymer/iron-icon/iron-icon' import '@polymer/iron-icons/iron-icons' import './behaviors/isu-elements-shared-styles' /** * `isu-paper-tabs` * * Example: * ```html * <isu-paper-tabs value="0" id="iSuPaperTabs1"></isu-paper-tabs> * <isu-paper-tabs value="one" attr-for-selected="name" id="iSuPaperTabsRight" tab-position="right"></isu-paper-tabs> * <isu-paper-tabs value="0" id="iSuPaperTabsLeft" tab-position="left"></isu-paper-tabs> * <isu-paper-tabs value="0" id="iSuBottomPaperTabs" tab-position="bottom"></isu-paper-tabs> * <isu-paper-tabs value="0" id="iSuCardPaperTabs" tab-type="card"></isu-paper-tabs> * <isu-paper-tabs value="0" id="iSuBorderCardPaperTabs" tab-type="border-card"></isu-paper-tabs> * <isu-paper-tabs value="0" id="iSuWidthBarPaperTabs" tab-type="width-bar"></isu-paper-tabs> * ``` * @customElement * @polymer * @demo demo/isu-paper-tabs/index.html */ class IsuPaperTabs extends mixinBehaviors([], PolymerElement) { static get template () { return html` <style include="isu-elements-shared-styles"> :host { --paper-tabs:{ height: 100%; } --paper-tab-content:{ height: 48px; line-height: 48px; } --paper-tabs-selection-bar:{ border-bottom-color: var(--paper-blue-a200); } } :host paper-tab{ color:#6a6969; } :host .paper-tabs-card paper-tab { position: relative; padding: 0 12px; overflow: hidden; cursor: pointer; color:#6a6969; background-color: #f5f7fa; border-top-left-radius: 4px; border-top-right-radius: 4px; border:1px solid #dddddd; border-bottom: none; @apply --paper-tabs-card-paper-card } :host .paper-tabs-card { --layout-horizontal: { display: inline-flex; } border-bottom: 1px solid #ddd; @apply --paper-tabs-card } :host .iron-selected{ color:var(--paper-blue-a200); } :host .paper-tabs-card paper-tab.iron-selected { color: #337ab7; background-color: #ffffff; @apply --paper-tabs-card-paper-tab-selected } :host .paper-tabs-card-border-card{ --layout-horizontal: { display: inline-flex; } border: 1px solid #dddddd; background-color: #f5f7fa; @apply paper-tabs-card-border-card } :host .paper-tabs-card-border-card paper-tab{ position: relative; padding: 0 12px; overflow: hidden; cursor: pointer; background-color: #f5f7fa; @apply paper-tabs-card-border-card-paper-tab } :host .paper-tabs-card-border-card paper-tab:first-child.iron-selected{ border-left: none; } :host .paper-tabs-card-border-card paper-tab:last-child.iron-selected{ border-right: none; } :host .paper-tabs-card-border-card paper-tab.iron-selected { color: #337ab7; border-left: 1px solid #ddd; border-right: 1px solid #ddd; background-color: #ffffff; @apply --paper-tabs-card-border-card-selected } :host paper-tab[disabled]{ opacity: 0.5; } :host([tab-position=right]) #positionSelectionBar { display:block; left: -2px; position: absolute; height: 48px; top:0; border-right: 2px solid #337ab7; -webkit-transform: scale(0); transform: scale(0); -webkit-transform-origin: center top; transform-origin: center top; transition: -webkit-transform; transition: transform; transition-duration:1000ms; @apply --paper-tabs-position-selection-bar-right; } :host([tab-position=left]) #positionSelectionBar { display:block; right: -2px; position: absolute; height: 48px; top:0; border-right: 2px solid #337ab7; -webkit-transform: scale(0); transform: scale(0); -webkit-transform-origin: center top; transform-origin: center top; transition: -webkit-transform; transition: transform; transition-duration:1000ms; @apply --paper-tabs-position-selection-bar-left; } :host .tab-position-left-right{ position: relative; display: inline-block; --layout-horizontal: { display: inline-grid; } } :host .tab-position-left { border-right: 2px solid #cccccc; } :host .tab-position-right { border-left: 2px solid #cccccc; right: calc(-100% + 120px); } :host .paper-tab-iron-icon{ @apply --paper-tab-iron-icon } :host .paper-tab-clear-icon{ font-size: 10px; width: 18px; height: 18px; margin-left: 15px; margin-bottom: 2px; border-radius: 10px; @apply --paper-tab-clear-icon } :host .paper-tab-clear-icon:hover{ background-color: #dddddd; @apply --paper-tab-clear-icon-hover } </style> <div class$="[[getTabPositionClass(tabPosition)]] [[getTabTypeClass(tabType)]]"> <paper-tabs selected="{{value}}" attr-for-selected="[[__attrForSelected]]" selected-item="{{selectedItem}}" noink="[[noink]]" align-bottom="[[alignBottom]]" no-bar="[[noBar]]" no-slide="[[noSlide]]" scrollable="[[scrollable]]" autoselect="[[autoSelect]]" autoselect-delay="[[autoSelectDelay]]" hide-scroll-buttons="[[hideScrollButtons]]" disable-drag="[[disableDrag]]"> <template is="dom-repeat" items="[[tabList]]"> <template is="dom-if" if="[[item.permission]]"> <paper-tab name="[[__getForSelectedName(item, attrForSelected)]]" disabled="[[item.disabled]]" part="paper-tab"> <template is="dom-if" if="[[item.iconName]]"> <iron-icon icon="[[item.iconName]]" class="paper-tab-iron-icon"></iron-icon> </template> [[item.label]] <template is="dom-if" if="[[_isAppearClearIcon(isClear,tabType)]]"> <iron-icon icon="icons:clear" class="paper-tab-clear-icon" on-click="clearPaperTab" data-args="[[item]]"></iron-icon> </template> </paper-tab> </template> </template> </paper-tabs> <div id="positionSelectionBar"></div> </div> ` } static get properties () { return { /** * TabList:Must-Pass,is a Array. * Child element * requirements:{label:String,value:Number||String,permission:Boolean,iconName:String, disabled:Boolean}. * if permission === false ,paper-tab hidden. * if disabled === false,paper-tab can't click. */ tabList: { type: Array, value: [ { label: 'Paper-tab', value: 0, permission: true, disabled: false } ], notify: true }, /** * The selected value, if attrForSelected === 'name',the name of the selectedItem is returned, * otherwise the number is returned, the default value is 0 */ value: { type: String | Number, value: 0, notify: true }, /** * selectedItem */ selectedItem: { type: Object, observer: '_selectedItemChange' }, /** * Tab position, the default value is top, there are three types:top/left/right/bottom */ tabPosition: { type: String, value: 'top', notify: true, observer: '_tabPositionChange' }, /** * tab type, the default value is card, there are three types:card/border-card/width-bar */ tabType: { type: String, value: 'card', notify: true, observer: '_tabTypeChange' }, /** * If you want to use an attribute value or property of an element for * `selected` instead of the index, set this to the name of the attribute * or property. Hyphenated values are converted to camel case when used to * look up the property of a selectable element. Camel cased values are * *not* converted to hyphenated values for attribute lookup. It's * recommended that you provide the hyphenated form of the name so that * selection works in both cases. (Use `attr-or-property-name` instead of * `attrOrPropertyName`.) */ attrForSelected: { type: String, notify: true }, __attrForSelected: { type: String, computed: '__attrForSelectedChanged(attrForSelected)' }, /** * If true, ink ripple effect is disabled. When this property is changed, * all descendant `<paper-tab>` elements have their `noink` property * changed to the new value as well. */ noink: { type: Boolean, value: true, notify: true }, /** * If true, the bottom bar to indicate the selected tab will not be shown. */ noBar: { type: Boolean, value: true, notify: true }, /** * If true, the slide effect for the bottom bar is disabled. */ noSlide: { type: Boolean, value: true, notify: true }, /** * If true, tabs are scrollable and the tab width is based on the label * width. */ scrollable: { type: Boolean, value: false, notify: true }, /** * If true, tabs expand to fit their container. This currently only applies * when scrollable is true. */ fitContainer: { type: Boolean, value: false, notify: true }, /** * If true, the tabs are aligned to bottom (the selection bar appears at the * top). */ alignBottom: { type: Boolean, value: false, notify: true }, /** * If true, tabs are automatically selected when focused using the * keyboard. */ autoSelect: { type: Boolean, value: false, notify: true }, /** * The delay (in milliseconds) between when the user stops interacting * with the tabs through the keyboard and when the focused item is * automatically selected (if `autoselect` is true). */ autoSelectDelay: { type: Number, value: 0, notify: true }, /** * If true, dragging on the tabs to scroll is disabled. */ disableDrag: { type: Boolean, value: false }, /** * If true, scroll buttons (left/right arrow) will be hidden for scrollable * tabs. */ hideScrollButtons: { type: Boolean, value: false }, /** * If true, the paper-tab will have clear icon.On click it,can clear this paper-tab. */ isClear: { type: Boolean, value: false } } } static get is () { return 'isu-paper-tabs' } __attrForSelectedChanged (attrForSelected) { return attrForSelected ? 'name' : undefined } _selectedItemChange (newVal) { if (newVal && ['left', 'right'].includes(this.tabPosition)) { return Promise.resolve(this._computedPositionSelectionBarHeight(newVal)) } } _computedPositionSelectionBarHeight (selectedItem) { const tab = selectedItem.offsetTop const paperTabs = this.shadowRoot.querySelector('paper-tabs').offsetTop const translateTop = tab - paperTabs return this.transform(`translateY(${translateTop}px)scaleY(1)`, this.shadowRoot.querySelector('#positionSelectionBar')) } _tabPositionChange (newVal) { if (newVal !== 'top') { this.set('tabType', '') } if (newVal === 'bottom') { this.set('alignBottom', true) this.set('noBar', false) } if (['left', 'right'].includes(newVal)) { this.set('noBar', true) } } _tabTypeChange (newVal) { if (newVal === 'width-bar') { return this.noBar = false } } getTabPositionClass (type) { const tabPositionObj = { left: 'tab-position-left-right tab-position-left', right: 'tab-position-left-right tab-position-right', top: 'tab-position-top' } return typeof tabPositionObj[type] !== 'undefined' ? tabPositionObj[type] : '' } getTabTypeClass (type) { const typeClassObj = { card: 'paper-tabs-card', 'border-card': 'paper-tabs-card-border-card', 'width-bar': '' } return typeClassObj[type] } _isAppearClearIcon (isClear, tabType) { return isClear && tabType === 'card' } clearPaperTab (e) { const data = e.currentTarget.dataArgs this.set('tabList', this.tabList.filter(item => { return item.value !== data.value })) if (this.tabList.indexOf(item => { item.value = this.selectedItem.value }) === -1) { this.set('selected', this.attrForSelected ? this.tabList[0].value : 0) } } __getForSelectedName (item, attrForSelected) { if (!item || !attrForSelected) { return undefined } else { return item[attrForSelected] } } } window.customElements.define(IsuPaperTabs.is, IsuPaperTabs)