UNPKG

isu-elements

Version:

Polymer components for building web apps.

339 lines (307 loc) 8.95 kB
import { html, PolymerElement } from '@polymer/polymer' import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class' import '@webcomponents/shadycss/entrypoints/apply-shim.js' import { BaseBehavior } from './behaviors/base-behavior' import './behaviors/isu-elements-shared-styles.js' import '@polymer/paper-checkbox' /** * * `isu-checkbox-group` * * Example: * ```html * <isu-checkbox-group label="材料" value="0" items="{{items}}"></isu-checkbox-group> * * ``` * * ## Styling * * The following custom properties and mixins are available for styling: * * |Custom property | Description | Default| * |----------------|-------------|----------| * |`--isu-checkbox-group-label` | Mixin applied to the label of checkbox | {} * |`--isu-checkbox-group-checked-color` | Mixin applied to color of the checkbox when it is checked | #0099FF * * @customElement * @polymer * @demo demo/isu-checkbox-group/index.html */ class IsuCheckboxGroup extends mixinBehaviors(BaseBehavior, PolymerElement) { static get template () { return html` <style include="isu-elements-shared-styles"> :host { display: flex; flex-wrap: nowrap; position: relative; line-height: var(--isu-checkbox-group-height, var(--isu-default-line-height, 34px)); font-family: var(--isu-ui-font-family), sans-serif; font-size: var(--isu-ui-font-size); } #checkbox-container { position: relative; display: flex; align-items: center; flex-direction: row; @apply --isu-checkbox-group-container; } :host([direction=column]) #checkbox-container { flex-direction: column; align-items: start; } :host([direction=column]) .checkbox-item { margin-bottom: 6px; } .checkbox-item { margin-left: 6px; --paper-checkbox-checked-color: var(--isu-ui-color_skyblue); } :host([border]) .checkbox-item { border: 1px solid lightgray; padding: 7px 13px; border-radius: 4px; } :host([border]) .checkbox-item[checked] { border: 1px solid var(--isu-ui-color_skyblue); } .readonly-shade { min-width: 100px; width: 100%; height: 34px; position: absolute; z-index: 999; top: 0; } :host([required]) .checkbox-container::before { content: "*"; color: red; position: absolute; left: -8px; line-height: inherit; @apply --isu-required } .inline-block { display: inline-block; position: relative; } :host([readonly]) .inline-block { background: #f4f4f4; } </style> <template is="dom-if" if="[[ toBoolean(label) ]]"> <div class="isu-label-div"><span class$="isu-label [[fontSize]]">[[label]]</span><span class="isu-label-after-extension"></span></div> </template> <div id="checkbox-container" class$="checkbox-container [[fontSize]]"> <div class="checkboxes"> <template is="dom-repeat" items="[[ _items ]]" index-as="index"> <div class="inline-block"> <paper-checkbox noink class="checkbox-item" part="checkbox-item" checked="{{ item.checked }}" disabled="{{ item.disabled }}" on-change="__checkedChangeHandler" value="[[ getValueByKey(item, attrForValue) ]]"> [[ getValueByKey(item, attrForLabel) ]] </paper-checkbox> <template is="dom-if" if="[[readonly]]"> <div id$="readonly[[index]]" class="readonly-shade"></div> </template> </div> </template> </div> <!--<div id="readonly" class="readonly-shade">--> <!--</div>--> <div class="prompt-tip__container" data-prompt$="[[prompt]]"> <div class="prompt-tip"> <iron-icon class="prompt-tip-icon" icon="social:sentiment-very-dissatisfied"></iron-icon> [[prompt]] </div> <div class="mask" part="mask"></div> </div> ` } static get properties () { return { /** * The label of the Checkbox * * @attribute label * @type {string} */ label: { type: String }, /** * Candidates of the checkbox group. * @attribute items * @type {array} */ items: { type: Array }, _items: { type: Array, computed: '__computedInnerItems(items, value)' }, /** * The selected value of checkbox group. * @attribute value * @type {string} */ value: { type: String, notify: true }, /** * The selected value items of checkbox group. * @attribute value * @type {array} */ selectedValues: { type: Array, notify: true }, /** * Attribute name for value. * @type {string} * @default 'value' */ attrForValue: { type: String, value: 'value' }, /** * Attribute name for label. * @type {string} * @default 'label' */ attrForLabel: { type: String, value: 'label' }, /** * Set to true if the selection is required. * @type {boolean} * @default false */ required: { type: Boolean, value: false, reflectToAttribute: true }, /** * A limit on the number of optional items, smallest optional * @type Number * @default * */ min: { type: Number }, /** * A limit on the number of optional items, biggest optional * @type Number * @default * */ max: { type: Number }, /** * The prompt tip to show when input is invalid. * @type String */ prompt: { type: String }, /** * The prompt tip's position. top/bottom * @type String * @default '' */ promptPosition: { type: String, value: '' }, /** * Set to true if the selection is readonly. * @type {boolean} * @default false */ readonly: { type: Boolean, value: false, reflectToAttribute: true } } } static get is () { return 'isu-checkbox-group' } static get observers () { return [ '__valueChanged(value, items)', 'getInvalidAttribute(required, min, max, value)', '__readonlyChanged(readonly)' ] } __readonlyChanged (readonly) { // if (readonly) { // this.$.readonly.style.width = this.querySelector('.checkboxes') // } } __computedInnerItems (items = [], value = '') { const _value = value || '' const values = this.__parseValues(_value) const selectValues = _value.split(',') const _items = items.map(item => Object.assign({}, item, { checked: values.some(val => val === item[this.attrForValue] + '') })) if (this.min) { if (selectValues.length <= this.min && selectValues.length > 0) { _items.forEach(item => { if (item.checked) item.disabled = true }) } } if (this.max) { if (selectValues.length >= this.max) { _items.forEach(item => { if (!item.checked) item.disabled = true }) } } this.set('_items', _items) return _items } __checkedChangeHandler () { const selectValues = this._items.filter(item => !!item.checked).map(item => item[this.attrForValue]) this.value = selectValues.length > 0 ? selectValues.join(',') : undefined } /** * @private */ __valueChanged (value = '', items = []) { const values = this.__parseValues(value) this.selectedValues = items.filter(item => values.some(val => val === item[this.attrForValue] + '')) } /** * @private */ __parseValues (value = '') { const _value = value || '' return _value.split(',').map(val => val.trim()) } /** * Validate, true if the select is set to be required and this.selectedValues.length > 0, or else false. * @return {boolean} */ validate () { super.validate() let valid = true if (this.required) { valid = this.selectedValues && this.selectedValues.length > 0 } if (this.min) { valid = this.selectedValues && this.selectedValues.length >= this.min } if (this.max) { valid = this.selectedValues && this.selectedValues.length <= this.max } return valid } } window.customElements.define(IsuCheckboxGroup.is, IsuCheckboxGroup)