import { html, LitElement, css } from "lit"; import { customElement, property } from "lit/decorators.js"; import { coreVariables } from "@supersoniks/concorde/core/components/ui/theme/theme-collection/core-variables"; import { light } from "@supersoniks/concorde/core/components/ui/theme/theme-collection/light"; import { dark } from "@supersoniks/concorde/core/components/ui/theme/theme-collection/dark"; import { PublisherManager } from "@supersoniks/concorde/utils"; const tagName = "sonic-theme"; @customElement(tagName) export class Theme extends LitElement { static styles = [ light, dark, coreVariables, css` :host([color]) { color: var(--sc-base-content, #000); } :host([font]) { font-family: var(--sc-font-family-base, sans-serif); font-weight: var(--sc-font-weight-base, 400); font-style: var(--sc-font-style-base, normal); } ::slotted(.sonic-pop-content) { max-width: 100vw; background-color: var(--sc-base, #fff); position: fixed; z-index: 99999; display: block; transform: translateY(1rem) scale(0.95); pointer-events: none; transition-duration: 0.15s; transition-timing-function: ease; transition-property: scale, opacity; border-radius: min(calc(var(--sc-btn-rounded) * 2), 0.4em); } ::slotted(.sonic-pop-content).is-open:not(.is-empty) { transform: translateY(0) scale(1); opacity: 1; pointer-events: auto; transition-property: scale, opacity; transition-timing-function: cubic-bezier(0.25, 0.25, 0.42, 1.225); } `, ]; static instance: Theme | undefined; constructor() { super(); Theme.instance = this; } /** * retourne le conteneur de tout ce qui pop : popups / modale / tooltip? / dropdown / ... */ public static getPopContainer() { return Theme.instance || document.body; } @property({ type: String, reflect: true }) theme?: "light" | "dark"; @property({ type: Boolean, reflect: true }) background = false; @property({ type: Boolean, reflect: true }) color = false; @property({ type: Boolean, reflect: true }) font = false; connectedCallback(): void { super.connectedCallback(); window.addEventListener("message", (e) => this.receiveMessage(e), false); window.dispatchEvent(new CustomEvent("SonicThemeReady")); this.postCSSVars(); } postCSSVars() { const stylesheets = document.styleSheets; const ssLength = stylesheets.length; const fontUrls: string[] = []; for (let i = 0; i < ssLength; i++) { const ss = stylesheets[i]; if ( ss.href && (ss.href.includes("googleapis") || ss.href.includes("typekit.net")) ) fontUrls.push(ss.href); } const theme = { variables: this.getCssVariables(), fonts: fontUrls, }; PublisherManager.get("sonic-theme")?.set(theme); document.querySelectorAll("iframe").forEach((elt) => elt.contentWindow?.postMessage( { type: "SonicTheme", ...theme, }, "*", ), ); } receiveMessage(event: MessageEvent) { const data = event.data; if (!data.type || data.type != "GetSonicTheme") return; this.postCSSVars(); } getCssVariables() { const names: Array = []; const stylesheets = [ ...Theme.styles.map((s) => s.styleSheet), ...Array.from(document.styleSheets), ] as { cssRules: { style: string[] }[] | CSSRuleList; }[]; for (const stylesheet of stylesheets) { try { if (!stylesheet) continue; const rules = stylesheet.cssRules; for (const rule of rules) { if (!("style" in rule)) continue; const style = rule.style; for (const name of style) { if (names.includes(name) || name.indexOf("--sc") !== 0) continue; names.push(name); } } } catch (e) { console.warn("Erreur lors de la récupération des variables CSS"); } } const style = window.getComputedStyle(this); const result: Record = {}; names.forEach((name) => (result[name] = style.getPropertyValue(name))); return result; } render() { return html``; } }