UNPKG

@schukai/monster

Version:

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

227 lines (200 loc) 6.8 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. */ import { instanceSymbol } from "../../constants.mjs"; import { addAttributeToken } from "../../dom/attributes.mjs"; import { ATTRIBUTE_ERRORMESSAGE, ATTRIBUTE_ROLE, } from "../../dom/constants.mjs"; import { CustomControl } from "../../dom/customcontrol.mjs"; import { CustomElement } from "../../dom/customelement.mjs"; import { assembleMethodSymbol, registerCustomElement, } from "../../dom/customelement.mjs"; import { findTargetElementFromEvent } from "../../dom/events.mjs"; import { isFunction } from "../../types/is.mjs"; import { FullScreenStyleSheet } from "./stylesheet/full-screen.mjs"; import { fireCustomEvent } from "../../dom/events.mjs"; export { FullScreen }; /** * @private * @type {symbol} */ export const fullScreenControlElementSymbol = Symbol( "fullScreenControlElement", ); /** * @private * @type {symbol} */ export const fullScreenElementSymbol = Symbol("fullScreenElement"); /** * @private * @type {symbol} */ export const fullScreenExitElementSymbol = Symbol("fullScreenExitElement"); /** * A FullScreen * * @fragments /fragments/components/layout/full-screen/ * * @example /examples/components/layout/full-screen-simple * * @since 4.10.0 * @copyright Volker Schukai * @summary A beautiful FullScreen that can make your life easier and also looks good. */ class FullScreen extends CustomElement { /** * This method is called by the `instanceof` operator. * @returns {symbol} */ static get [instanceSymbol]() { return Symbol.for( "@schukai/monster/components/layout/full-screen@@instance", ); } /** * * @return {Components.Layout.FullScreen */ [assembleMethodSymbol]() { super[assembleMethodSymbol](); initControlReferences.call(this); initEventHandler.call(this); return this; } /** * To set the options via the HTML Tag, the attribute `data-monster-options` must be used. * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control} * * The individual configuration values can be found in the table. * * @property {Object} templates Template definitions * @property {string} templates.main Main template * @property {string} selector Selector for the control */ get defaults() { return Object.assign({}, super.defaults, { templates: { main: getTemplate(), }, selector: ":first-child", }); } /** * @return {string} */ static getTag() { return "monster-full-screen"; } /** * @return {CSSStyleSheet[]} */ static getCSSStyleSheet() { return [FullScreenStyleSheet]; } } /** * @private * @return {initEventHandler} */ function initEventHandler() { const self = this; const element = this[fullScreenControlElementSymbol]; document.addEventListener("fullscreenchange", (event) => { const control = findTargetControl.call(self); if (document.fullscreenElement === control) { self[fullScreenElementSymbol].classList.add("hidden"); self[fullScreenExitElementSymbol].classList.remove("hidden"); } else { self[fullScreenExitElementSymbol].classList.add("hidden"); self[fullScreenElementSymbol].classList.remove("hidden"); } }); const type = "click"; element.addEventListener(type, function (event) { const control = findTargetControl.call(self); if (!control) { addAttributeToken(self, ATTRIBUTE_ERRORMESSAGE, "No control found"); return; } fireCustomEvent(self, "monster-full-screen-clicked", { element: control, }); toggleFullscreen.call(self, control); }); return this; } /** * @private * @return {void} */ function initControlReferences() { this[fullScreenControlElementSymbol] = this.shadowRoot.querySelector( `[${ATTRIBUTE_ROLE}="control"]`, ); this[fullScreenElementSymbol] = this.shadowRoot.querySelector( `[${ATTRIBUTE_ROLE}="fullscreen"]`, ); this[fullScreenExitElementSymbol] = this.shadowRoot.querySelector( `[${ATTRIBUTE_ROLE}="fullscreen-exit"]`, ); } /** * @private * @param self * @returns {*} */ function findTargetControl(self) { const rootNode = this.getRootNode?.() ?? document; const selector = this.getOption("selector"); return rootNode.querySelector(selector); } /** * @private * @param element */ function toggleFullscreen(element) { if (!document.fullscreenElement) { element.requestFullscreen().catch((err) => { addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, err.message); }); } else { document.exitFullscreen(); } } /** * @private * @return {string} */ function getTemplate() { // language=HTML return ` <div data-monster-role="control" part="control"> <div data-monster-role="fullscreen"> <svg part="fullscreen" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path fill-rule="evenodd" d="M5.828 10.172a.5.5 0 0 0-.707 0l-4.096 4.096V11.5a.5.5 0 0 0-1 0v3.975a.5.5 0 0 0 .5.5H4.5a.5.5 0 0 0 0-1H1.732l4.096-4.096a.5.5 0 0 0 0-.707m4.344 0a.5.5 0 0 1 .707 0l4.096 4.096V11.5a.5.5 0 1 1 1 0v3.975a.5.5 0 0 1-.5.5H11.5a.5.5 0 0 1 0-1h2.768l-4.096-4.096a.5.5 0 0 1 0-.707m0-4.344a.5.5 0 0 0 .707 0l4.096-4.096V4.5a.5.5 0 1 0 1 0V.525a.5.5 0 0 0-.5-.5H11.5a.5.5 0 0 0 0 1h2.768l-4.096 4.096a.5.5 0 0 0 0 .707m-4.344 0a.5.5 0 0 1-.707 0L1.025 1.732V4.5a.5.5 0 0 1-1 0V.525a.5.5 0 0 1 .5-.5H4.5a.5.5 0 0 1 0 1H1.732l4.096 4.096a.5.5 0 0 1 0 .707"/> </svg> </div> <div data-monster-role="fullscreen-exit" class="hidden"> <svg part="fullscreen-exit" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M5.5 0a.5.5 0 0 1 .5.5v4A1.5 1.5 0 0 1 4.5 6h-4a.5.5 0 0 1 0-1h4a.5.5 0 0 0 .5-.5v-4a.5.5 0 0 1 .5-.5m5 0a.5.5 0 0 1 .5.5v4a.5.5 0 0 0 .5.5h4a.5.5 0 0 1 0 1h-4A1.5 1.5 0 0 1 10 4.5v-4a.5.5 0 0 1 .5-.5M0 10.5a.5.5 0 0 1 .5-.5h4A1.5 1.5 0 0 1 6 11.5v4a.5.5 0 0 1-1 0v-4a.5.5 0 0 0-.5-.5h-4a.5.5 0 0 1-.5-.5m10 1a1.5 1.5 0 0 1 1.5-1.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 0-.5.5v4a.5.5 0 0 1-1 0z"/> </svg> </div> </div>`; } registerCustomElement(FullScreen);