@schukai/monster
Version:
Monster is a simple library for creating fast, robust and lightweight websites.
304 lines (272 loc) • 8.84 kB
JavaScript
/**
* Copyright © schukai GmbH 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 schukai GmbH.
*
* 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 schukai GmbH
* @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);