theme-vir
Version:
Create an entire web theme.
120 lines (115 loc) • 3.85 kB
JavaScript
import { getEnumValues, getObjectTypedValues, typedObjectFromEntries } from '@augment-vir/common';
import { css, defineElement, html, unsafeCSS } from 'element-vir';
import { createFontStyleCss } from './font-css.js';
import { HeadingLevel } from './theme-options.js';
export function defineThemeElements(options) {
const themeElements = {
bold: defineElement()({
tagName: `${options.elementTagPrefix}-b`,
styles: css `
:host {
display: inline;
${createFontStyleCss(options.font.bold)}
}
b {
all: inherit;
}
`,
render() {
return html `
<b><slot></slot></b>
`;
},
}),
monospace: defineElement()({
tagName: `${options.elementTagPrefix}-monospace`,
styles: css `
:host {
display: inline;
${createFontStyleCss(options.font.monospace)}
}
`,
render() {
return html `
<slot></slot>
`;
},
}),
code: defineElement()({
tagName: `${options.elementTagPrefix}-code`,
styles: css `
:host {
display: inline;
${createFontStyleCss(options.font.monospace)}
}
`,
render() {
return html `
<code><slot></slot></code>
`;
},
}),
paragraph: defineElement()({
tagName: `${options.elementTagPrefix}-p`,
styles: css `
:host {
display: block;
${createFontStyleCss(options.font.bold)}
}
p {
all: inherit;
}
`,
render() {
return html `
<p><slot></slot></p>
`;
},
}),
heading: defineHeadingElement(options),
};
return themeElements;
}
function defineHeadingElement(options) {
const headingTag = `${options.elementTagPrefix}-heading`;
const headingSelectors = unsafeCSS(getEnumValues(HeadingLevel).join(', '));
return defineElement()({
tagName: headingTag,
hostClasses: typedObjectFromEntries(getEnumValues(HeadingLevel).map((headingLevel) => {
return [
`${headingTag}-${headingLevel}`,
({ inputs }) => inputs.headingLevel === headingLevel,
];
})),
styles: ({ hostClasses }) => {
const hostClassValues = getObjectTypedValues(hostClasses);
return css `
:host {
display: block;
}
${unsafeCSS(hostClassValues
.map((hostClass) => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const headingLevel = String(hostClass.name)
.split('-')
.slice(-1)[0];
return css `
${hostClass.selector} {
${createFontStyleCss(options.font.headings[headingLevel])}
}
`;
})
.join('\n'))}
${headingSelectors} {
all: inherit;
}
`;
},
render({ inputs }) {
const headingTag = inputs.headingLevel;
return html `
<${headingTag}><slot></slot></${headingTag}>
`;
},
});
}