Files
webawesome/docs/_data/themes.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

62 lines
2.2 KiB
JavaScript

import fs from 'fs';
import path from 'path';
// import { inlined } from '../../dist/components/icon/library.wa.js';
const __dirname = path.resolve();
const THEME_DIR = path.join(__dirname, 'dist/styles/themes/');
const themeFiles = fs.readdirSync(THEME_DIR).filter(file => file.endsWith('.css') && !file.endsWith('base.css'));
const declarationRegex = /^\s*--wa-(?<property>[a-z-]+)?:\s*(?<value>.+?)\s*(\/\*.+?\*\/)?\s*;$/gm;
const importRegex = /^\s*@import\s+url\(['"](?<path>.+?)['"]\);$/gm;
const themes = {};
for (const file of themeFiles) {
const id = file.replace('.css', '');
const { imports, declarations } = readCSSFile(file);
let theme = { palette: 'default', declarations, imports };
for (const url of imports) {
if (url.endsWith('/color.css')) {
// Color settings
const color = readCSSFile(url);
for (const colorUrl of color.imports) {
if (colorUrl.startsWith('../../color/')) {
// Color palette
theme.palette = getFileSlug(colorUrl);
} else if (colorUrl.startsWith('../../brand/')) {
// Brand color
theme.brand = getFileSlug(colorUrl);
}
}
} else if (url.endsWith('/dimension.css')) {
theme.dimension = true;
}
}
let icon = {};
icon.family = theme.declarations['icon-family'] ?? theme.default?.iconFamily ?? 'classic';
icon.variant = theme.declarations['icon-variant'] ?? theme.default?.iconVariant ?? 'solid';
theme.icons = icon;
theme.rounding = Number(theme.declarations['border-radius-scale'] ?? theme.default?.rounding ?? 1);
theme.spacing = Number(theme.declarations['space-scale'] ?? theme.default?.spacing ?? 1);
theme.borderWidth = Number(theme.declarations['border-width-scale'] ?? theme.default?.borderWidth ?? 1);
themes[id] = theme;
}
export default themes;
function readCSSFile(url) {
const contents = fs.readFileSync(path.join(THEME_DIR, url), 'utf8');
const imports = [...contents.matchAll(importRegex)].map(match => match.groups.path);
const declarations = Object.fromEntries(
[...contents.matchAll(declarationRegex)].map(match => [match.groups.property, match.groups.value]),
);
return { imports, declarations };
}
function getFileSlug(url) {
return url.split('/').pop().replace('.css', '');
}