Files
webawesome/docs/assets/scripts/tweak/code.js
Lea Verou 0b4c1a5934 Themer 2nd slice: Look & Feel (#920)
* Exclude Create link from sidebar, for reals this time

* Fix bug

* Very rough prototype of look & feel

* a11y

* Clean up data files

* Automatically generate theme metadata

* Read look & feel params straight from theme

* First stab at dimensionality icons

* Fix rounding 0 bug

* Add border width slider

* [Image-comparer] Expose wrapper as part

* [Comparer] `pointer-events: none` while dragging

* Dark mode slider

* Adjust increments and ranges for look + feel sliders

* Fix preview

* Fix bug where dark mode was not inverted

* Ability to select panel from URL

* Create mixin for Vue form controls and use it in `<swatch-select>`

* Prototype of slider min/max icon buttons

* Nx tooltip

* Icons

* Prevent failed request

* info-tip: Support passing text as prop

* Clearable

* [Brutalist] Match `--wa-shadow-offset-x-scale` to `--wa-shadow-offset-y-scale`

* Add 'Blocky' dimension (derived from Awesome theme)

* Only show Reset button when `clearable` is set

* Remove `clearable` from Look & Feel sliders

* Add tooltips to min/max buttons

* Remove superfluous `aria-label`

* Do not assume that all hyphens in URLs mean nesting, make it explicit

* Formatting

* Fix bug where styles were not applied on page load

* Update Subtle dimension to maximize compatibility

* `<wa-scoped>`: Do not allow non-template children

* Workaround for card not updating

* Update Glossy dimension to maximize compatibility

* Sync scrolling between regular and inverted preview

* Fix bug

* Make changing the base theme reset customizations

* Fix palette page

* Remove cancel button from editable text

* Don't error in theme pages

* Update Playful dimension to maximize compatibility

* Rename 'Look and Feel' to 'Elements' for better parallel structure

* Hide dimensionality controls

* Make back icon motion more subtle

* Expand spacing slider bounds

* Add `tabindex="-1"` where missing in theme showcase

* Remove extraneous gap from theme headers

* fix edit button bug

* rename comparer => comparison; fix aria-controls

* Always save theme name on blur

* Add changelog for themer and new patterns category

---------

Co-authored-by: lindsaym-fa <dev@lindsaym.design>
Co-authored-by: Cory LaViska <cory@abeautifulsite.net>
2025-05-20 10:16:49 -04:00

92 lines
2.5 KiB
JavaScript

/**
* Get import code for remixed themes and tweaked palettes.
*/
import { selectors, themeConfig } from '../../data/theming.js';
import { deepEach, deepGet } from '/assets/scripts/util/deep.js';
export function cssImport(url, options = {}) {
let { language = 'html', cdnUrl = '/dist/', attributes } = options;
url = cdnUrl + url;
if (language === 'css') {
return `@import url('${url}');`;
} else {
attributes = attributes ? ` ${attributes}` : '';
return `<link rel="stylesheet" href="${url}"${attributes} />`;
}
}
export function cssLiteral(value, options = {}) {
let { language = 'html' } = options;
if (language === 'css') {
return value;
} else {
return `<style${options.attributes ?? ''}>\n${value}\n</style>`;
}
}
/**
* Get code for a theme, including tweaks
* @param {*} theme
* @param {*} options
* @returns
*/
export function getThemeCode(theme, options = {}) {
let urls = [];
let declarations = [];
let id = options.id ?? theme.base ?? 'default';
deepEach(themeConfig, (config, aspect, obj, path) => {
if (!config?.default) {
// We're not in a config object
return;
}
let value = deepGet(theme, [...path, aspect]);
if (!value && value !== 0) {
return;
}
if (config.url) {
// This is implemented by pulling in different CSS files
urls.push(config.url(value));
} else {
if (config.cssProperty) {
declarations.push(`${config.cssProperty}: ${value};`);
}
}
});
let ret = urls.map(url => cssImport(url, options)).join('\n');
if (declarations.length > 0) {
let cssCode = cssRule(selectors.theme(id), declarations, options);
if (theme.icon?.kit) {
let faKitAttribute = ` data-fa-kit-code="${theme.icon.kit}"`;
options.attributes ??= '';
options.attributes += faKitAttribute;
cssCode =
`/* Note: To use Font Awesome Pro icons,\n set ${faKitAttribute} on the <link> (or any other) element */\n\n` +
cssCode;
}
cssCode = cssLiteral(cssCode, options);
if (ret) {
ret += '\n\n' + cssCode;
}
}
return ret;
}
export function cssRule(selector, declarations, { indent = ' ' } = {}) {
selector = Array.isArray(selector) ? selector.flat().join(',\n') : selector;
declarations = Array.isArray(declarations) ? declarations.flat() : declarations;
declarations = declarations.map(declaration => indent + declaration.trim()).join('\n');
return `${selector} {\n${declarations.trimEnd()}\n}`;
}