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``;
}
}