@nopwdio/ui
Version:
Nopwd Design System
187 lines (182 loc) • 5.7 kB
JavaScript
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