@yarcl/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/dist/color.d.ts +12 -0
- package/dist/color.js +41 -0
- package/dist/css.d.ts +10 -0
- package/dist/css.js +175 -0
- package/dist/define.d.ts +383 -0
- package/dist/define.js +29 -0
- package/dist/plugin.d.ts +33 -0
- package/dist/plugin.js +80 -0
- package/package.json +66 -0
- package/src/apply.ts +46 -0
- package/src/classes.ts +23 -0
- package/src/color.ts +48 -0
- package/src/components/Accordion.tsx +274 -0
- package/src/components/Alert.tsx +85 -0
- package/src/components/Badge.tsx +79 -0
- package/src/components/Breadcrumb.tsx +239 -0
- package/src/components/Button.tsx +58 -0
- package/src/components/ButtonGroup.tsx +61 -0
- package/src/components/Card.tsx +50 -0
- package/src/components/Checkbox.tsx +49 -0
- package/src/components/Combobox.tsx +522 -0
- package/src/components/CommandPalette.tsx +452 -0
- package/src/components/DatePicker.tsx +432 -0
- package/src/components/Dialog.tsx +39 -0
- package/src/components/Divider.tsx +34 -0
- package/src/components/Drawer.tsx +31 -0
- package/src/components/Field.tsx +61 -0
- package/src/components/Heading.tsx +40 -0
- package/src/components/HoverCard.tsx +108 -0
- package/src/components/IconButton.tsx +59 -0
- package/src/components/Inline.tsx +42 -0
- package/src/components/Input.tsx +28 -0
- package/src/components/Label.tsx +58 -0
- package/src/components/Link.tsx +41 -0
- package/src/components/Menu.tsx +207 -0
- package/src/components/Modal.tsx +164 -0
- package/src/components/NumberInput.tsx +208 -0
- package/src/components/Pagination.tsx +227 -0
- package/src/components/Popover.tsx +140 -0
- package/src/components/Progress.tsx +122 -0
- package/src/components/Radio.tsx +59 -0
- package/src/components/RadioGroup.tsx +114 -0
- package/src/components/Select.tsx +197 -0
- package/src/components/Skeleton.tsx +95 -0
- package/src/components/Slider.tsx +315 -0
- package/src/components/Spinner.tsx +38 -0
- package/src/components/Stack.tsx +57 -0
- package/src/components/Switch.tsx +42 -0
- package/src/components/Table.tsx +99 -0
- package/src/components/Tabs.tsx +159 -0
- package/src/components/Text.tsx +67 -0
- package/src/components/Textarea.tsx +26 -0
- package/src/components/Toast.tsx +190 -0
- package/src/components/ToggleGroup.tsx +227 -0
- package/src/components/Tooltip.tsx +78 -0
- package/src/contrast.ts +82 -0
- package/src/css.ts +228 -0
- package/src/define.check.ts +259 -0
- package/src/define.ts +379 -0
- package/src/field-context.ts +31 -0
- package/src/floating.tsx +61 -0
- package/src/hooks.ts +19 -0
- package/src/index.ts +119 -0
- package/src/plugin.ts +94 -0
- package/src/reference/DesignReference.tsx +374 -0
- package/src/reference/index.ts +2 -0
- package/src/reference/reference.css +58 -0
- package/src/runtime.ts +38 -0
- package/src/styles.css +1971 -0
- package/src/themes/bloom.ts +72 -0
- package/src/themes/brutalist.ts +63 -0
- package/src/themes/compact.ts +63 -0
- package/src/themes/contract.ts +24 -0
- package/src/themes/editorial.ts +55 -0
- package/src/themes/index.ts +47 -0
- package/src/types.ts +69 -0
- package/src/yarcl.config.ts +104 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eugene Yakhnenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @yarcl/react
|
|
2
|
+
|
|
3
|
+
Yet another react component library. Your config file is the design system: every key becomes a typed prop and a rendered style.
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm install @yarcl/react
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// vite.config.ts
|
|
11
|
+
import react from '@vitejs/plugin-react';
|
|
12
|
+
import { defineConfig } from 'vite';
|
|
13
|
+
import { yarcl } from '@yarcl/react/plugin';
|
|
14
|
+
|
|
15
|
+
export default defineConfig({ plugins: [react(), yarcl({ config: 'src/yarcl.config.ts' })] });
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```jsonc
|
|
19
|
+
// tsconfig.json
|
|
20
|
+
{
|
|
21
|
+
"compilerOptions": {
|
|
22
|
+
"paths": {
|
|
23
|
+
"@yarcl/config": ["./src/yarcl.config.ts", "./node_modules/@yarcl/react/src/yarcl.config.ts"]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
// src/yarcl.config.ts
|
|
31
|
+
import { defineConfig } from '@yarcl/react/define';
|
|
32
|
+
import defaults from '@yarcl/react/defaults';
|
|
33
|
+
|
|
34
|
+
export default defineConfig({
|
|
35
|
+
...defaults,
|
|
36
|
+
colors: {
|
|
37
|
+
...defaults.colors,
|
|
38
|
+
brand: { light: '#4f46e5', dark: '#a5b4fc' },
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { Button } from '@yarcl/react';
|
|
45
|
+
|
|
46
|
+
<Button color="brand">Save</Button>;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Documentation: [yarcl.dev](https://yarcl.dev)
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type Rgb = [number, number, number];
|
|
2
|
+
export declare function parseHex(value: string): Rgb | null;
|
|
3
|
+
export declare function contrast(a: Rgb, b: Rgb): number;
|
|
4
|
+
export declare function mix(a: Rgb, b: Rgb, amount: number): Rgb;
|
|
5
|
+
export declare function toHex(rgb: Rgb): string;
|
|
6
|
+
/**
|
|
7
|
+
* The color, mixed toward `toward` in small steps until it reaches `min` contrast
|
|
8
|
+
* against every background. Returns the color unchanged when it already passes.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readableText(color: Rgb, backgrounds: Rgb[], toward: Rgb, min: number): Rgb;
|
|
11
|
+
export declare function readableOn(background: Rgb): string;
|
|
12
|
+
export {};
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function parseHex(value) {
|
|
2
|
+
const hex = value.trim().replace(/^#/, '');
|
|
3
|
+
if (!/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(hex))
|
|
4
|
+
return null;
|
|
5
|
+
const full = hex.length === 3 ? [...hex].map((c) => c + c).join('') : hex;
|
|
6
|
+
return [0, 2, 4].map((i) => parseInt(full.slice(i, i + 2), 16));
|
|
7
|
+
}
|
|
8
|
+
function luminance([r, g, b]) {
|
|
9
|
+
const [lr, lg, lb] = [r, g, b].map((c) => {
|
|
10
|
+
const s = c / 255;
|
|
11
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
12
|
+
});
|
|
13
|
+
return 0.2126 * lr + 0.7152 * lg + 0.0722 * lb;
|
|
14
|
+
}
|
|
15
|
+
export function contrast(a, b) {
|
|
16
|
+
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
|
|
17
|
+
return (hi + 0.05) / (lo + 0.05);
|
|
18
|
+
}
|
|
19
|
+
const WHITE = [255, 255, 255];
|
|
20
|
+
const BLACK = [0, 0, 0];
|
|
21
|
+
export function mix(a, b, amount) {
|
|
22
|
+
return a.map((channel, i) => Math.round(channel + (b[i] - channel) * amount));
|
|
23
|
+
}
|
|
24
|
+
export function toHex(rgb) {
|
|
25
|
+
return `#${rgb.map((c) => c.toString(16).padStart(2, '0')).join('')}`;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The color, mixed toward `toward` in small steps until it reaches `min` contrast
|
|
29
|
+
* against every background. Returns the color unchanged when it already passes.
|
|
30
|
+
*/
|
|
31
|
+
export function readableText(color, backgrounds, toward, min) {
|
|
32
|
+
for (let step = 0; step <= 20; step++) {
|
|
33
|
+
const candidate = mix(color, toward, step / 20);
|
|
34
|
+
if (backgrounds.every((bg) => contrast(candidate, bg) >= min))
|
|
35
|
+
return candidate;
|
|
36
|
+
}
|
|
37
|
+
return toward;
|
|
38
|
+
}
|
|
39
|
+
export function readableOn(background) {
|
|
40
|
+
return contrast(background, WHITE) >= contrast(background, BLACK) ? '#ffffff' : '#000000';
|
|
41
|
+
}
|
package/dist/css.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { YarclShape } from './define.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the stylesheet for a config: CSS variables on `:root`, one class per key and
|
|
4
|
+
* `@font-face` rules. The Vite plugin calls this at build time; call it yourself to preview
|
|
5
|
+
* or switch themes at runtime (inject the result into a `<style>` element).
|
|
6
|
+
*
|
|
7
|
+
* @param config A config from `defineConfig`, e.g. one of `@yarcl/react/themes`.
|
|
8
|
+
* @param warn Receives contrast warnings.
|
|
9
|
+
*/
|
|
10
|
+
export declare function generateCss(config: YarclShape, warn?: (message: string) => void): string;
|
package/dist/css.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { contrast, mix, parseHex, readableOn, readableText, toHex } from "./color.js";
|
|
2
|
+
const MIN_CONTRAST = 4.5;
|
|
3
|
+
function ident(key) {
|
|
4
|
+
return key.replace(/[^a-zA-Z0-9_-]/g, (c) => `\\${c}`);
|
|
5
|
+
}
|
|
6
|
+
function pair({ light, dark }) {
|
|
7
|
+
return light === dark ? light : `light-dark(${light}, ${dark})`;
|
|
8
|
+
}
|
|
9
|
+
function foreground(name, token, warn) {
|
|
10
|
+
const modes = ['light', 'dark'];
|
|
11
|
+
const on = typeof token.on === 'string' ? { light: token.on, dark: token.on } : token.on;
|
|
12
|
+
const resolved = modes.map((mode) => {
|
|
13
|
+
const bg = parseHex(token[mode]);
|
|
14
|
+
if (on) {
|
|
15
|
+
const fg = parseHex(on[mode]);
|
|
16
|
+
if (bg && fg && contrast(bg, fg) < MIN_CONTRAST) {
|
|
17
|
+
warn(`colors.${name}: ${mode} foreground contrast ${contrast(bg, fg).toFixed(2)}:1 is below ${MIN_CONTRAST}:1`);
|
|
18
|
+
}
|
|
19
|
+
return on[mode];
|
|
20
|
+
}
|
|
21
|
+
if (!bg) {
|
|
22
|
+
warn(`colors.${name}: cannot compute a ${mode} foreground from "${token[mode]}"; use a hex value or set \`on\``);
|
|
23
|
+
return '#ffffff';
|
|
24
|
+
}
|
|
25
|
+
const fg = readableOn(bg);
|
|
26
|
+
const ratio = contrast(bg, parseHex(fg));
|
|
27
|
+
if (ratio < MIN_CONTRAST) {
|
|
28
|
+
warn(`colors.${name}: best ${mode} foreground contrast is ${ratio.toFixed(2)}:1, below ${MIN_CONTRAST}:1`);
|
|
29
|
+
}
|
|
30
|
+
return fg;
|
|
31
|
+
});
|
|
32
|
+
return pair({ light: resolved[0], dark: resolved[1] });
|
|
33
|
+
}
|
|
34
|
+
const tint = (percent) => `color-mix(in oklab, var(--yarcl-c) ${percent}%, transparent)`;
|
|
35
|
+
const shade = (percent) => `color-mix(in oklab, var(--yarcl-c), var(--yarcl-c-on) ${percent}%)`;
|
|
36
|
+
const backgrounds = {
|
|
37
|
+
fill: ['var(--yarcl-c)', shade(12), shade(20)],
|
|
38
|
+
tint: [tint(14), tint(22), tint(30)],
|
|
39
|
+
none: ['transparent', tint(10), tint(18)],
|
|
40
|
+
};
|
|
41
|
+
const borders = {
|
|
42
|
+
color: 'var(--yarcl-c)',
|
|
43
|
+
neutral: 'var(--yarcl-neutral-border)',
|
|
44
|
+
none: 'transparent',
|
|
45
|
+
};
|
|
46
|
+
const texts = {
|
|
47
|
+
on: 'var(--yarcl-c-on)',
|
|
48
|
+
color: 'var(--yarcl-c-text)',
|
|
49
|
+
neutral: 'var(--yarcl-neutral-text)',
|
|
50
|
+
};
|
|
51
|
+
const formats = { woff2: 'woff2', woff: 'woff', ttf: 'truetype', otf: 'opentype' };
|
|
52
|
+
function fontFace(face) {
|
|
53
|
+
const sources = (Array.isArray(face.src) ? face.src : [face.src]).map((src) => {
|
|
54
|
+
if (src.startsWith('local('))
|
|
55
|
+
return src;
|
|
56
|
+
const format = formats[src.split(/[?#]/)[0].split('.').pop()?.toLowerCase() ?? ''];
|
|
57
|
+
return `url(${JSON.stringify(src)})${format ? ` format("${format}")` : ''}`;
|
|
58
|
+
});
|
|
59
|
+
return rule('@font-face', [
|
|
60
|
+
['font-family', JSON.stringify(face.family)],
|
|
61
|
+
['src', sources.join(', ')],
|
|
62
|
+
...(face.weight != null ? [['font-weight', face.weight]] : []),
|
|
63
|
+
...(face.style ? [['font-style', face.style]] : []),
|
|
64
|
+
['font-display', face.display ?? 'swap'],
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
const TEXT_TINTS = [0, 0.14, 0.22];
|
|
68
|
+
function textShade(name, token, neutrals) {
|
|
69
|
+
if (token.text)
|
|
70
|
+
return pair(typeof token.text === 'string' ? { light: token.text, dark: token.text } : token.text);
|
|
71
|
+
const modes = ['light', 'dark'];
|
|
72
|
+
const resolved = modes.map((mode) => {
|
|
73
|
+
const color = parseHex(token[mode]);
|
|
74
|
+
const text = parseHex(neutrals.text[mode]);
|
|
75
|
+
const grounds = [parseHex(neutrals.bg[mode]), parseHex(neutrals.surface[mode])];
|
|
76
|
+
if (!color || !text || grounds.some((g) => !g))
|
|
77
|
+
return token[mode];
|
|
78
|
+
const backgrounds = grounds.flatMap((ground) => TEXT_TINTS.map((alpha) => mix(ground, color, alpha)));
|
|
79
|
+
return toHex(readableText(color, backgrounds, text, MIN_CONTRAST));
|
|
80
|
+
});
|
|
81
|
+
return pair({ light: resolved[0], dark: resolved[1] });
|
|
82
|
+
}
|
|
83
|
+
function rule(selector, declarations) {
|
|
84
|
+
return `${selector} {\n${declarations.map(([p, v]) => ` ${p}: ${v};`).join('\n')}\n}`;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Generates the stylesheet for a config: CSS variables on `:root`, one class per key and
|
|
88
|
+
* `@font-face` rules. The Vite plugin calls this at build time; call it yourself to preview
|
|
89
|
+
* or switch themes at runtime (inject the result into a `<style>` element).
|
|
90
|
+
*
|
|
91
|
+
* @param config A config from `defineConfig`, e.g. one of `@yarcl/react/themes`.
|
|
92
|
+
* @param warn Receives contrast warnings.
|
|
93
|
+
*/
|
|
94
|
+
export function generateCss(config, warn = () => { }) {
|
|
95
|
+
const root = [['color-scheme', 'light dark']];
|
|
96
|
+
const rules = [];
|
|
97
|
+
for (const [key, token] of Object.entries(config.colors)) {
|
|
98
|
+
const k = ident(key);
|
|
99
|
+
root.push([`--yarcl-color-${k}`, pair(token)], [`--yarcl-color-${k}-on`, foreground(key, token, warn)], [`--yarcl-color-${k}-text`, textShade(key, token, config.neutrals)]);
|
|
100
|
+
rules.push(rule(`.yarcl-color-${k}`, [
|
|
101
|
+
['--yarcl-c', `var(--yarcl-color-${k})`],
|
|
102
|
+
['--yarcl-c-on', `var(--yarcl-color-${k}-on)`],
|
|
103
|
+
['--yarcl-c-text', `var(--yarcl-color-${k}-text)`],
|
|
104
|
+
]));
|
|
105
|
+
}
|
|
106
|
+
for (const [key, value] of Object.entries(config.neutrals))
|
|
107
|
+
root.push([`--yarcl-neutral-${ident(key)}`, pair(value)]);
|
|
108
|
+
for (const [key, size] of Object.entries(config.sizes)) {
|
|
109
|
+
const k = ident(key);
|
|
110
|
+
root.push([`--yarcl-size-${k}-height`, size.height], [`--yarcl-size-${k}-padding-x`, size.paddingX], [`--yarcl-size-${k}-font-size`, size.fontSize], [`--yarcl-size-${k}-icon-size`, size.iconSize]);
|
|
111
|
+
rules.push(rule(`.yarcl-size-${k}`, [
|
|
112
|
+
['--yarcl-h', `var(--yarcl-size-${k}-height)`],
|
|
113
|
+
['--yarcl-px', `var(--yarcl-size-${k}-padding-x)`],
|
|
114
|
+
['--yarcl-fs', `var(--yarcl-size-${k}-font-size)`],
|
|
115
|
+
['--yarcl-icon', `var(--yarcl-size-${k}-icon-size)`],
|
|
116
|
+
]));
|
|
117
|
+
}
|
|
118
|
+
for (const [key, value] of Object.entries(config.radii)) {
|
|
119
|
+
const k = ident(key);
|
|
120
|
+
root.push([`--yarcl-radius-${k}`, value]);
|
|
121
|
+
rules.push(rule(`.yarcl-radius-${k}`, [['--yarcl-r', `var(--yarcl-radius-${k})`]]));
|
|
122
|
+
}
|
|
123
|
+
for (const [key, variant] of Object.entries(config.variants)) {
|
|
124
|
+
const [bg, hover, active] = backgrounds[variant.background];
|
|
125
|
+
rules.push(rule(`.yarcl-variant-${ident(key)}`, [
|
|
126
|
+
['--yarcl-v-bg', bg],
|
|
127
|
+
['--yarcl-v-bg-hover', hover],
|
|
128
|
+
['--yarcl-v-bg-active', active],
|
|
129
|
+
['--yarcl-v-border', borders[variant.border]],
|
|
130
|
+
['--yarcl-v-fg', texts[variant.text]],
|
|
131
|
+
]));
|
|
132
|
+
}
|
|
133
|
+
for (const [key, value] of Object.entries(config.spacing)) {
|
|
134
|
+
const k = ident(key);
|
|
135
|
+
root.push([`--yarcl-space-${k}`, value]);
|
|
136
|
+
rules.push(rule(`.yarcl-gap-${k}`, [['gap', `var(--yarcl-space-${k})`]]), rule(`.yarcl-padding-${k}`, [['padding', `var(--yarcl-space-${k})`]]));
|
|
137
|
+
}
|
|
138
|
+
for (const [key, value] of Object.entries(config.shadows)) {
|
|
139
|
+
const k = ident(key);
|
|
140
|
+
root.push([`--yarcl-shadow-${k}`, value]);
|
|
141
|
+
rules.push(rule(`.yarcl-shadow-${k}`, [['box-shadow', `var(--yarcl-shadow-${k})`]]));
|
|
142
|
+
}
|
|
143
|
+
for (const [key, value] of Object.entries(config.modalSizes)) {
|
|
144
|
+
const k = ident(key);
|
|
145
|
+
root.push([`--yarcl-modal-${k}`, value]);
|
|
146
|
+
rules.push(rule(`.yarcl-modal-size-${k}`, [['--yarcl-modal-width', `var(--yarcl-modal-${k})`]]));
|
|
147
|
+
}
|
|
148
|
+
for (const [key, density] of Object.entries(config.density)) {
|
|
149
|
+
rules.push(rule(`.yarcl-density-${ident(key)}`, [
|
|
150
|
+
['--yarcl-cell-px', density.paddingX],
|
|
151
|
+
['--yarcl-cell-py', density.paddingY],
|
|
152
|
+
['--yarcl-cell-fs', density.fontSize],
|
|
153
|
+
]));
|
|
154
|
+
}
|
|
155
|
+
for (const [key, value] of Object.entries(config.typography.families))
|
|
156
|
+
root.push([`--yarcl-font-${ident(key)}`, value]);
|
|
157
|
+
for (const [key, style] of Object.entries(config.typography.styles)) {
|
|
158
|
+
rules.push(rule(`.yarcl-type-${ident(key)}`, [
|
|
159
|
+
['font-family', `var(--yarcl-font-${ident(style.family)})`],
|
|
160
|
+
['font-size', style.size],
|
|
161
|
+
['font-weight', style.weight],
|
|
162
|
+
['line-height', style.lineHeight],
|
|
163
|
+
...(style.letterSpacing ? [['letter-spacing', style.letterSpacing]] : []),
|
|
164
|
+
]));
|
|
165
|
+
}
|
|
166
|
+
for (const [key, value] of Object.entries(config.zIndex))
|
|
167
|
+
root.push([`--yarcl-z-${ident(key)}`, value]);
|
|
168
|
+
for (const [key, value] of Object.entries(config.motion))
|
|
169
|
+
root.push([`--yarcl-motion-${ident(key)}`, value]);
|
|
170
|
+
for (const [key, value] of Object.entries(config.borders))
|
|
171
|
+
root.push([`--yarcl-border-${ident(key)}`, value]);
|
|
172
|
+
root.push(['--yarcl-focus-width', config.focusRing.width], ['--yarcl-focus-offset', config.focusRing.offset], ['--yarcl-focus-style', config.focusRing.style ?? 'solid'], ['--yarcl-focus-color', `var(--yarcl-color-${ident(config.focusRing.color)})`], ['--yarcl-error', `var(--yarcl-color-${ident(config.defaults.errorColor)})`], ['--yarcl-floating-shadow', `var(--yarcl-shadow-${ident(config.defaults.floatingShadow)})`], ['--yarcl-padding', `var(--yarcl-space-${ident(config.defaults.padding)})`], ['--yarcl-gap', `var(--yarcl-space-${ident(config.defaults.gap)})`]);
|
|
173
|
+
const faces = (config.typography.fontFaces ?? []).map(fontFace);
|
|
174
|
+
return [...faces, rule(':root', root), ...rules].join('\n\n') + '\n';
|
|
175
|
+
}
|