UNPKG

@schukai/monster

Version:

Monster is a simple library for creating fast, robust and lightweight websites.

304 lines (272 loc) 8.85 kB
/** * Copyright © Volker Schukai and all contributing authors, {{copyRightYear}}. All rights reserved. * Node module: @schukai/monster * * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3). * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html * * For those who do not wish to adhere to the AGPLv3, a commercial license is available. * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms. * For more information about purchasing a commercial license, please contact Volker Schukai. * * SPDX-License-Identifier: AGPL-3.0 */ import { instanceSymbol } from "../../constants.mjs"; import { ATTRIBUTE_ROLE } from "../../dom/constants.mjs"; import { assembleMethodSymbol, registerCustomElement, } from "../../dom/customelement.mjs"; import { typeOf } from "../../types/typeof.mjs"; import { Button } from "./button.mjs"; import { PopperButton } from "./popper-button.mjs"; import { ConfirmButtonStyleSheet } from "./stylesheet/confirm-button.mjs"; import { fireCustomEvent } from "../../dom/events.mjs"; import "./button.mjs"; import "./message-state-button.mjs"; import { PopperButtonStyleSheet } from "./stylesheet/popper-button.mjs"; import { StateButtonStyleSheet } from "./stylesheet/state-button.mjs"; export { ConfirmButton }; /** * @private * @type {symbol} */ const confirmButtonElementSymbol = Symbol("confirmButtonElement"); /** * @private * @type {symbol} */ const cancelButtonElementSymbol = Symbol("cancelButtonElement"); /** * A confirmation button control. * * @fragments /fragments/components/form/confirm-button/ * * @example /examples/components/form/confirm-button-simple simple confirm button * * @issue https://localhost.alvine.dev:8440/development/issues/closed/283.html * * @since 1.5.0 * @copyright Volker Schukai * @summary A confirm button control allowing the user to confirm or cancel an action */ class ConfirmButton extends PopperButton { /** * This method is called by the `instanceof` operator. * @return {symbol} * @since 2.1.0 */ static get [instanceSymbol]() { return Symbol.for( "@schukai/monster/components/form/confirm-button@@instance", ); } /** * The individual configuration values can be found in the table. * * @property {Object} templates Template definitions * @property {string} templates.main Main template * @property {Object} labels Label definitions * @property {string} labels.button Button label * @property {string} labels.message Message label * @property {string} labels.confirm Confirm label * @property {string} labels.cancel Cancel label * @property {Object} classes Class definitions * @property {string} classes.confirmButton Confirm button class * @property {string} classes.cancelButton Cancel button class * @property {Object} actions Action definitions * @property {function} actions.confirm Confirm action * @property {function} actions.cancel Cancel action */ get defaults() { const obj = Object.assign({}, super.defaults, { templates: { main: getTemplate(), }, labels: { button: '<slot name="button"></slot>', message: "<slot>Should I Stay or Should I Go?</slot>", confirm: '<slot name="confirm">Confirm</slot>', cancel: '<slot name="cancel">Cancel</slot>', }, }); obj["classes"]["confirmButton"] = "monster-button-primary"; obj["classes"]["cancelButton"] = "monster-button-secondary"; obj["actions"]["cancel"] = (e) => { this.hideDialog(); }; obj["actions"]["confirm"] = () => {}; return obj; } hideDialog() { super.hideDialog(); this[confirmButtonElementSymbol].removeState(); return this; } /** * * @return {PopperButton} */ [assembleMethodSymbol]() { super[assembleMethodSymbol](); initControlReferences.call(this); initEventhandler.call(this); } /** * @return {string} */ static getTag() { return "monster-confirm-button"; } /** * @return {Array} */ static getCSSStyleSheet() { const styles = PopperButton.getCSSStyleSheet(); styles.push(ConfirmButtonStyleSheet); return styles; } /** * * @return {ConfirmButton} */ showDialog() { const confirmButtonClass = this.getOption("classes.confirmButton"); if (confirmButtonClass) { this[confirmButtonElementSymbol].setOption( "classes.button", confirmButtonClass, ); } const cancelButtonClass = this.getOption("classes.cancelButton"); if (cancelButtonClass) { this[cancelButtonElementSymbol].setOption( "classes.button", cancelButtonClass, ); } return super.showDialog(); } /** * Set the confirm button state * * @param {string} state * @param {number} timeout * @return {ConfirmButton} */ setConfirmButtonState(state, timeout) { this[confirmButtonElementSymbol].setState(state, timeout); return this; } /** * Set and show the confirm button message * * @param {string} message * @param {number} timeout * @return {ConfirmButton} */ showConfirmButtonMessage(message, timeout) { this[confirmButtonElementSymbol].setMessage(message); setTimeout(() => { this[confirmButtonElementSymbol].showMessage(timeout); }, 0); return this; } } /** * @private * @param type * @return {function} */ function getAction(type) { const self = this; return function (event) { const callback = self.getOption(`actions.${type}`); if (typeOf(callback) !== "function") { return; } callback.call(this, event); }; } /** * @private * @return {initEventhandler} * @fires ConfirmButton#monster-confirm * @fires ConfirmButton#monster-confirmed */ function initEventhandler() { this[cancelButtonElementSymbol].setOption( "clickEventType", this.getOption("clickEventType", ["click"]), ); this[cancelButtonElementSymbol].setOption( "actions.click", getAction.call(this, "cancel"), ); this[confirmButtonElementSymbol].setOption( "clickEventType", this.getOption("clickEventType", ["click"]), ); this[confirmButtonElementSymbol].setOption("actions.click", () => { const callback = getAction.call(this, "confirm"); fireCustomEvent(this, "monster-confirm", { button: this, }); callback.call(this); fireCustomEvent(this, "monster-confirmed", { button: this, }); }); return this; } /** * @private * @return {Select} */ function initControlReferences() { this[confirmButtonElementSymbol] = this.shadowRoot.querySelector( `[${ATTRIBUTE_ROLE}=confirm]`, ); this[cancelButtonElementSymbol] = this.shadowRoot.querySelector( `[${ATTRIBUTE_ROLE}=cancel]`, ); } /** * @private * @return {string} */ function getTemplate() { // language=HTML return ` <div data-monster-role="control" part="control"> <button data-monster-attributes="disabled path:disabled | if:true, class path:classes.button" data-monster-role="button" part="button" data-monster-replace="path:labels.button"></button> <div data-monster-role="popper" part="popper" tabindex="-1" class="monster-color-primary-1"> <div data-monster-role="arrow"></div> <div part="message" class="flex" data-monster-replace="path:labels.message"></div> <div data-monster-role="decision"> <monster-message-state-button exportparts="monster-state-button:confirm-button, control:confirm-control, button-button:confirm-control-button, button-control:confirm-button-control, popper:confirm-popper, message:confirm-popper-message-message, icon:confirm-popper-message-icon, title:confirm-popper-message-title" data-monster-attributes="data-monster-button-class path:classes.confirmButton" data-monster-role="confirm" part="confirm"> <span data-monster-replace="path:labels.confirm"></span> </monster-message-state-button> <monster-button exportparts="button:cancel-button,control:cancel-control" data-monster-attributes="data-monster-button-class path:classes.cancelButton" data-monster-role="cancel" part="cancel"> <span data-monster-replace="path:labels.cancel"></span> </monster-button> </div> </div> </div> `; } registerCustomElement(ConfirmButton);