UNPKG

isu-elements

Version:

Polymer components for building web apps.

371 lines (339 loc) 9.59 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 '@polymer/iron-icons' import '@polymer/iron-icon' import './behaviors/isu-elements-shared-styles' import './isu-button.js' import './isu-input.js' import './isu-dialog.js' /** * `isu-tip` * * Example: * ```html * <isu-tip type="success" message="success" id="tip"></isu-tip> * <isu-button id="btn" onclick="tip.open();">Success</isu-button> * * <isu-tip type="warn" message="warn" id="tip2"></isu-tip> * <isu-button id="btn2" onclick='tip2.open(2000);'>Warn</isu-button> * * <isu-tip type="error" message="alert" id="tip3"></isu-tip> * <isu-button id="btn3" onclick='tip3.open(5000);'>Error</isu-button> * ``` * @customElement * @polymer * @demo demo/isu-tip/index.html */ class IsuTip extends mixinBehaviors([BaseBehavior], PolymerElement) { static get template () { return html` <style include="isu-elements-shared-styles"> :host { min-width: 330px; min-height: 100px; overflow: hidden; font-family: var(--isu-ui-font-family), sans-serif; font-size: var(--isu-ui-font-size); } #dialog { --isu-dialog-content: { display: flex; flex-flow: column nowrap; } --isu-dialog-title: { font-size: 18px; } } .tip-icon { @apply --isu-custom-tip; } .tip { vertical-align: middle; box-sizing: border-box; font-size: 14px; display: flex; flex-flow: row nowrap; flex: 1; padding: 0 4px; } :host([type=warn]) #tip { color: var(--isu-ui-color_yellow); } :host([type=success]) #tip { color: #46d23a; } :host([type=error]) #tip { color: var(--isu-ui-color_pink); } .tip-content { color: #848484; flex: 1; word-break: break-all; } :host([type=success]) #dialog, :host([type=warn]) #dialog, :host([type=error]) #dialog, :host([type=custom]) #dialog{ --isu-dialog-width: 400px; --isu-dialog-height: auto; } :host([type=success]) .tip-content, :host([type=warn]) .tip-content, :host([type=error]) .tip-content, :host([type=custom]) .tip-content{ padding: 5px 12px; padding-right: 34px; } :host([type=prompt]) #dialog, :host([type=confirm]) #dialog { --isu-dialog-width: 440px; --isu-dialog-height: 200px; } :host([type=success]) #operate-panel, :host([type=warn]) #operate-panel, :host([type=error]) #operate-panel, :host([type=custom]) #operate-panel, :host([type=success]) #remark-input, :host([type=warn]) #remark-input, :host([type=error]) #remark-input, :host([type=confirm]) #remark-input, :host([type=custom]) #remark-input { display: none; } .tip-icon { width: 36px; height: 36px; } #remark-input { width: inherit; } #operate-panel { text-align: right; margin-top: 10px; } :host([center]) #tip { margin: auto; } </style> <isu-dialog id="dialog" modal="[[ isOneOf(type, 'confirm', 'prompt') ]]" no-cancel-on-outside-click title="[[orElse(title, config.title)]]"> <div id="tip" class="tip"> <template is="dom-if" if="[[ isEqual(type, 'success') ]]"> <iron-icon class="tip-icon" icon="icons:check-circle"></iron-icon> </template> <template is="dom-if" if="[[ isEqual(type, 'warn') ]]"> <iron-icon class="tip-icon" icon="icons:error"></iron-icon> </template> <template is="dom-if" if="[[ isEqual(type, 'error') ]]"> <iron-icon class="tip-icon" icon="icons:cancel"></iron-icon> </template> <template is="dom-if" if="[[ isEqual(type, 'custom') ]]"> <iron-icon class="tip-icon" icon$="[[ iconClass ]]"></iron-icon> </template> <div class="tip-content" id="messageContainer"></div> </div> <isu-input id="remark-input" value="{{ remark }}"></isu-input> <div id="operate-panel"> <isu-button on-click="_confirm" type="[[orElse(config.confirmBtnType, 'primary')]]" size="small">[[orElse(config.confirmBtnLabel, '确定')]]</isu-button> <isu-button on-click="_cancel" type="[[orElse(config.cancelBtnType, 'default')]]" size="small">[[orElse(config.cancelBtnLabel, '取消')]]</isu-button> </div> </isu-dialog> ` } static get is () { return 'isu-tip' } static get properties () { return { /** * Message of the tip. * @type {string} */ message: { type: String }, /** * Tip type [success | warn | error | confirm | prompt] * @type {string} type * @default 'success' */ type: { type: String, value: 'success' }, /** * User input when `type` is `prompt`. * @type {string} */ remark: { type: String }, /** * The callback function by clicking the confirm、prompt message box`s sure button * @type {function} */ _confirmCallback: { type: Function }, /** * The callback function by clicking the confirm、prompt message box`s cancel button * @type {function} */ _cancelCallback: { type: Function }, /** * When `type` is `success`, `warn` or `error`, the tip will disappear after [duration] ms. * @type {number} * @default 1500 ms */ duration: { type: Number, value: 1500 }, /** * If true, no duration is required. The tip will displayed until you close it. * @type {boolean} * @default false */ noDuration: { type: Boolean, value: false }, /** * Set to true, if you want that `isu-tip` can auto detach from its parentElement. * @type {boolean} * @default false */ autoDetach: { type: Boolean, value: false }, /** * The title of the tip * @type {string} */ title: { type: String }, /** * The width of the tip box * @type {string} */ width: { type: String }, /** * The height of the tip box * @type {string} */ height: { type: String }, /** * Custom configuration.eg: {"title":"Notice!!!", "cancelBtnLabel": "NO", "confirmBtnLabel": "YES", "cancelBtnType": "warning", "confirmBtnType": "default"} * * @type {string} */ config: { type: Object, value: function () { return {} } }, /** * The icon`s class in the tip box. eg: `icons:build` * * @type {string} * */ iconClass: { type: String }, /** * Whether the tip content is centered or not * * @type {boolean} * @default false * */ center: { type: Boolean, value: false, reflectToAttribute: true } } } static get observers () { return [ '__sizeChanged(width, "width")', '__sizeChanged(height, "height")', '__messageChanged(message)' ] } __sizeChanged (size, sizeAttr) { if (size) { this.$.dialog.updateStyles({ ['--isu-dialog-' + sizeAttr]: size }) } } __messageChanged (message) { this.$.messageContainer.innerHTML = message } /** * Cancel handler */ _cancel () { this.close() this.isFunction(this._cancelCallback) && this._cancelCallback() } /** * Confirm handler */ async _confirm () { const cbParam = this.type === 'prompt' ? { remark: this.remark } : null const callbackResult = this.isFunction(this._confirmCallback) && await this._confirmCallback(cbParam) if (this.type === 'prompt' && callbackResult === false) return this.close() } /** * Open the tip dialog. * * 3 ways to use the open api: * * - open(duration) * - open(confirmCallback) * - open(confirmCallback, cancelCallback) * @param args */ open (...args) { let confirmCallback; let cancelCallback; let duration = this.duration if (args.length > 0 && typeof args[0] === 'function') { confirmCallback = args.shift() } if (args.length > 0 && typeof args[0] === 'function') { cancelCallback = args.shift() } if (args.length > 0 && (typeof args[0] === 'number' || typeof args[0] === 'string')) { duration = Number(args[0]) } this._confirmCallback = confirmCallback this._cancelCallback = cancelCallback this.$.dialog.open() if (this.type !== 'confirm' && this.type !== 'prompt') { if (!this.noDuration) { setTimeout(() => { this.close() }, duration) } } } /** * Hide the tip. */ close () { this.$.dialog.close() if (this.autoDetach && this.parentElement && this.parentElement.removeChild) { this.parentElement.removeChild(this) } } } window.customElements.define(IsuTip.is, IsuTip)