UNPKG

@nopwdio/ui

Version:
187 lines (182 loc) 5.7 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { css, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators.js"; import { moon, sun, computer } from "../icons/solid.js"; /** * Enum for theme states. * @readonly * @enum {string} */ var State; (function (State) { State["DARK"] = "dark"; State["LIGHT"] = "light"; State["AUTO"] = "auto"; })(State || (State = {})); /** * `ui-darkmode` is a custom element that allows users to switch between light, dark, and system themes. * * @element ui-darkmode */ let UiDarkMode = class UiDarkMode extends LitElement { constructor() { super(...arguments); /** * The current theme state. * @type {State} */ this.state = State.AUTO; } /** * Called when the element is added to a document. * @returns {void} */ connectedCallback() { super.connectedCallback(); this.setTheme(this.getPreferedTheme()); window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => { this.setTheme(this.getPreferedTheme()); }); } /** * Gets the preferred theme from local storage or system preference. * @returns {State} The preferred theme state. */ getPreferedTheme() { const storedTheme = localStorage.getItem("np:theme"); switch (storedTheme) { case State.DARK: return State.DARK; case State.LIGHT: return State.LIGHT; } return State.AUTO; } /** * Sets the theme and dispatches a custom event with the theme state. * @param {State} state - The theme state to set. * @returns {void} */ setTheme(state) { localStorage.setItem("np:theme", state); this.state = state; if (state === State.DARK) { this.dispatchEvent(new CustomEvent("np:theme", { detail: State.DARK, bubbles: true, composed: true, cancelable: true, })); } if (state === State.LIGHT) { this.dispatchEvent(new CustomEvent("np:theme", { detail: State.LIGHT, bubbles: true, composed: true, cancelable: true, })); } if (state === State.AUTO) { if (window.matchMedia("(prefers-color-scheme: dark)").matches) { this.dispatchEvent(new CustomEvent("np:theme", { detail: State.DARK, bubbles: true, composed: true, cancelable: true, })); } else { this.dispatchEvent(new CustomEvent("np:theme", { detail: State.LIGHT, bubbles: true, composed: true, cancelable: true, })); } } } /** * Renders the content of the element. * @returns {import('lit').TemplateResult} */ render() { return html ` <button aria-label="Light theme" ?data-selected=${this.state === State.LIGHT} @click=${() => this.setTheme(State.LIGHT)} > ${sun} </button> <button aria-label="Dark theme" ?data-selected=${this.state === State.DARK} @click=${() => this.setTheme(State.DARK)} > ${moon} </button> <button aria-label="System theme" ?data-selected=${this.state === State.AUTO} @click=${() => this.setTheme(State.AUTO)} > ${computer} </button>`; } }; /** * Styles for the `ui-darkmode` element. * @type {import('lit').CSSResult[]} */ UiDarkMode.styles = [ css ` :host { display: flex; padding: var(--np-padding-muted); justify-content: space-between; border: var(--np-border-color) var(--np-border-width) solid; border-radius: var(--np-border-radius-emphasis); gap: var(--np-gap); } :host(:hover) { border-color: var(--np-border-color-emphasis); } button { display: flex; flex: 1; justify-content: center; align-items: center; background: transparent; padding: var(--np-padding-muted) var(--np-padding); margin: 0; border: none; border-radius: var(--np-border-radius-emphasis); color: var(--np-text-color-muted); font-size: var(--np-text-size); transition: all var(--np-transition-duration-muted) ease; } button:hover { color: var(--np-fill-color-accent); } button[data-selected] { background-color: var(--np-bg-color-emphasis); color: var(--np-fill-color-accent); } .icon { width: 1em; height: 1em; } `, ]; __decorate([ property() ], UiDarkMode.prototype, "state", void 0); UiDarkMode = __decorate([ customElement("ui-darkmode") ], UiDarkMode); export { UiDarkMode }; //# sourceMappingURL=ui-darkmode.js.map