@ethlete/core 5.0.0-next.7 → 5.0.0-next.71
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/CHANGELOG.md +849 -0
- package/README.md +28 -4
- package/design/interactive-styles.ts +5 -0
- package/design/theme-css.js +392 -0
- package/design/theme-css.ts +547 -0
- package/fesm2022/ethlete-core.mjs +9357 -5667
- package/fesm2022/ethlete-core.mjs.map +1 -1
- package/generators/devtools-about/generator.js +122 -0
- package/generators/devtools-about/schema.json +25 -0
- package/generators/generators.json +41 -5
- package/generators/migrate-color-theme-variants/color-theme-variants.js +136 -0
- package/generators/migrate-color-theme-variants/migration.js +46 -0
- package/generators/migrate-color-theme-variants/schema.json +26 -0
- package/generators/migrate-create-destroy/create-destroy.js +317 -0
- package/generators/migrate-create-destroy/migration.js +46 -0
- package/generators/migrate-create-destroy/schema.json +26 -0
- package/generators/migrate-legacy-color-themes/legacy-color-themes.js +123 -0
- package/generators/migrate-legacy-color-themes/migration.js +93 -0
- package/generators/migrate-legacy-color-themes/schema.json +26 -0
- package/generators/migrate-provider-shape/migration-scope.js +35 -0
- package/generators/migrate-provider-shape/migration.js +50 -0
- package/generators/migrate-provider-shape/provider-shape.js +284 -0
- package/generators/migrate-provider-shape/schema.json +26 -0
- package/generators/migrate-surface-interaction-swatch/interaction-swatch.js +63 -0
- package/generators/migrate-surface-interaction-swatch/migration.js +36 -0
- package/generators/migrate-surface-interaction-swatch/schema.json +26 -0
- package/generators/migrate-to-v5/apply-replacements.js +14 -0
- package/generators/migrate-to-v5/color-naming.js +124 -0
- package/generators/migrate-to-v5/create-provider.js +67 -55
- package/generators/migrate-to-v5/migration-files.js +13 -0
- package/generators/migrate-to-v5/migration.js +33 -19
- package/generators/migrate-to-v5/removed-exports.js +161 -0
- package/generators/migrate-to-v5/router-state-service.js +125 -330
- package/generators/migrate-to-v5/schema.json +22 -0
- package/generators/migrate-to-v5/service-classes.js +108 -0
- package/generators/migrate-to-v5/sync-observable-consumers.js +80 -0
- package/generators/migrate-to-v5/viewport-service.js +226 -491
- package/generators/tailwind-4-color-theme/generator.js +411 -0
- package/generators/tailwind-4-color-theme/schema.json +44 -0
- package/generators/tailwind-4-surface-theme/generator.js +379 -0
- package/generators/tailwind-4-surface-theme/schema.json +48 -0
- package/migrations/legacy-color-themes.md +38 -0
- package/migrations/seo-directive-removed.md +81 -0
- package/migrations/surface-theme-regenerate.md +20 -0
- package/migrations.json +59 -0
- package/package.json +38 -21
- package/src/lib/animations/easing-tokens-styles.component.css +155 -0
- package/src/lib/providers/visually-hidden-styles.component.css +13 -0
- package/src/lib/resize-handles/resize-handles.component.css +137 -0
- package/src/lib/theming/color-interactive-styles.component.css +147 -0
- package/src/lib/theming/surface-interactive-styles.component.css +42 -0
- package/types/ethlete-core.d.ts +3842 -2205
- package/generators/tailwind-4-theme/generator.js +0 -514
- package/generators/tailwind-4-theme/schema.json +0 -32
package/README.md
CHANGED
|
@@ -1,7 +1,31 @@
|
|
|
1
|
-
# core
|
|
1
|
+
# @ethlete/core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Angular framework primitives for the Ethlete SDK - signal-based DOM observation, the surface/color theming systems, the animation and overlay engines, and a toolbox of directives, pipes and utilities. Component-less; every other `@ethlete/*` UI library builds on it.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
yarn add @ethlete/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { injectCurrentBreakpoint, signalHostElementDimensions } from '@ethlete/core';
|
|
15
|
+
|
|
16
|
+
@Component({/* … */})
|
|
17
|
+
export class ExampleComponent {
|
|
18
|
+
breakpoint = injectCurrentBreakpoint();
|
|
19
|
+
dimensions = signalHostElementDimensions();
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Documentation
|
|
24
|
+
|
|
25
|
+
Full guides on the docs site:
|
|
26
|
+
|
|
27
|
+
- [Overview](https://ethlete-sdk-docs.web.app/core/)
|
|
28
|
+
- [Element signals](https://ethlete-sdk-docs.web.app/core/element-signals) & [signal utilities](https://ethlete-sdk-docs.web.app/core/signal-utils)
|
|
29
|
+
- [Theming](https://ethlete-sdk-docs.web.app/core/theming)
|
|
30
|
+
- [Animations](https://ethlete-sdk-docs.web.app/core/animations) & [overlay runtime](https://ethlete-sdk-docs.web.app/core/overlay-runtime)
|
|
31
|
+
- [Providers](https://ethlete-sdk-docs.web.app/core/providers), [SEO](https://ethlete-sdk-docs.web.app/core/seo) & [utilities](https://ethlete-sdk-docs.web.app/core/utilities)
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import colorInteractive from '../src/lib/theming/color-interactive-styles.component.css?inline';
|
|
2
|
+
import surfaceInteractive from '../src/lib/theming/surface-interactive-styles.component.css?inline';
|
|
3
|
+
|
|
4
|
+
/** The stylesheets of `ColorInteractiveDirective` and `SurfaceInteractiveDirective`, for a design drawing. */
|
|
5
|
+
export const interactiveStyles = `${colorInteractive}\n${surfaceInteractive}`;
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
const resolveOptions = (options) => {
|
|
2
|
+
const utilityPrefix = options.prefix || 'et';
|
|
3
|
+
return {
|
|
4
|
+
utilityPrefix,
|
|
5
|
+
runtimePrefix: options.runtimePrefix || utilityPrefix,
|
|
6
|
+
themeBlock: options.tailwind === false ? ':root' : '@theme',
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
/** The CSS-safe form of a theme name, as the scope classes `.et-surface--<name>` and `.et-color--<name>` use it. */
|
|
10
|
+
export const cssThemeName = (name) => name
|
|
11
|
+
.toLowerCase()
|
|
12
|
+
.replace(/\s+/g, '-')
|
|
13
|
+
.replace(/[^a-z0-9-]/g, '');
|
|
14
|
+
/** The static CSS for an app's surface themes, as the `tailwind-4-surface-theme` generator writes it. */
|
|
15
|
+
export const surfaceThemeCss = (themes, options = {}) => {
|
|
16
|
+
const { utilityPrefix, runtimePrefix, themeBlock } = resolveOptions(options);
|
|
17
|
+
const tailwindVars = [];
|
|
18
|
+
const themeVars = [];
|
|
19
|
+
for (const theme of themes) {
|
|
20
|
+
const name = cssThemeName(theme.name);
|
|
21
|
+
tailwindVars.push(` /* ${theme.name} surface */`);
|
|
22
|
+
tailwindVars.push(` --color-${utilityPrefix}-surface-${name}-bg: rgb(${theme.background});`);
|
|
23
|
+
tailwindVars.push(` --color-${utilityPrefix}-surface-${name}: rgb(${theme.color});`);
|
|
24
|
+
tailwindVars.push(` --color-${utilityPrefix}-surface-${name}-muted: rgb(${theme.colorMuted});`);
|
|
25
|
+
tailwindVars.push(` --color-${utilityPrefix}-surface-${name}-subtle: rgb(${theme.colorSubtle});`);
|
|
26
|
+
tailwindVars.push(` --color-${utilityPrefix}-surface-${name}-border: rgb(${theme.border});`);
|
|
27
|
+
if (theme.interactionColor) {
|
|
28
|
+
const { color, onColor, inkColor } = theme.interactionColor;
|
|
29
|
+
pushStaticInteractionColors(tailwindVars, `--color-${utilityPrefix}-surface-${name}-interaction`, color);
|
|
30
|
+
if (onColor) {
|
|
31
|
+
pushStaticInteractionColors(tailwindVars, `--color-${utilityPrefix}-surface-${name}-on-interaction`, onColor);
|
|
32
|
+
}
|
|
33
|
+
if (inkColor) {
|
|
34
|
+
pushStaticInteractionColors(tailwindVars, `--color-${utilityPrefix}-surface-${name}-interaction-ink`, inkColor);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
tailwindVars.push('');
|
|
38
|
+
}
|
|
39
|
+
// A Tailwind `@theme` variable only lands on `:root`, so these are re-declared on every surface
|
|
40
|
+
// scope in the alias block, or `bg-<prefix>-surface-*` would ignore a nested surface.
|
|
41
|
+
const dynamicSurfaceColors = buildDynamicSurfaceColors(utilityPrefix, runtimePrefix);
|
|
42
|
+
tailwindVars.push(' /* Dynamic surface colors (references runtime CSS variables) */');
|
|
43
|
+
tailwindVars.push(...dynamicSurfaceColors.map((decl) => ` ${decl}`));
|
|
44
|
+
for (const theme of themes) {
|
|
45
|
+
const name = cssThemeName(theme.name);
|
|
46
|
+
if (theme.isDefault) {
|
|
47
|
+
const selectors = [`.${runtimePrefix}-surface--default-${theme.type}`, `.${runtimePrefix}-surface--${name}`];
|
|
48
|
+
themeVars.push(`${selectors.join(', ')} {`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
themeVars.push(`.${runtimePrefix}-surface--${name} {`);
|
|
52
|
+
}
|
|
53
|
+
pushSurfaceVars(themeVars, runtimePrefix, theme, ' ');
|
|
54
|
+
themeVars.push('}\n');
|
|
55
|
+
}
|
|
56
|
+
const defaultLight = themes.find((t) => t.isDefault && t.type === 'light');
|
|
57
|
+
const defaultDark = themes.find((t) => t.isDefault && t.type === 'dark');
|
|
58
|
+
if (defaultLight && defaultDark) {
|
|
59
|
+
pushSchemeSurfaceVars(themeVars, runtimePrefix, defaultLight);
|
|
60
|
+
pushSchemeSurfaceVars(themeVars, runtimePrefix, defaultDark);
|
|
61
|
+
pushForcedSchemeSurfaceVars(themeVars, runtimePrefix, defaultLight);
|
|
62
|
+
pushForcedSchemeSurfaceVars(themeVars, runtimePrefix, defaultDark);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Behind prefers-color-scheme, a lone surface type would leave every variable undefined for a
|
|
66
|
+
// user whose OS asks for the scheme the app lacks.
|
|
67
|
+
pushRootSurfaceVars(themeVars, runtimePrefix, defaultLight ?? defaultDark);
|
|
68
|
+
}
|
|
69
|
+
const aliasBlock = `/* Convenience aliases (rgb + solid variants) */
|
|
70
|
+
@layer base {
|
|
71
|
+
:root, :where([class*="${runtimePrefix}-surface--"]) {
|
|
72
|
+
--${runtimePrefix}-surface-background-rgb: var(--${runtimePrefix}-surface-background);
|
|
73
|
+
--${runtimePrefix}-surface-background-solid: rgb(var(--${runtimePrefix}-surface-background-rgb));
|
|
74
|
+
|
|
75
|
+
--${runtimePrefix}-surface-color-rgb: var(--${runtimePrefix}-surface-color);
|
|
76
|
+
--${runtimePrefix}-surface-color-solid: rgb(var(--${runtimePrefix}-surface-color-rgb));
|
|
77
|
+
|
|
78
|
+
--${runtimePrefix}-surface-color-muted-rgb: var(--${runtimePrefix}-surface-color-muted);
|
|
79
|
+
--${runtimePrefix}-surface-color-muted-solid: rgb(var(--${runtimePrefix}-surface-color-muted-rgb));
|
|
80
|
+
|
|
81
|
+
--${runtimePrefix}-surface-color-subtle-rgb: var(--${runtimePrefix}-surface-color-subtle);
|
|
82
|
+
--${runtimePrefix}-surface-color-subtle-solid: rgb(var(--${runtimePrefix}-surface-color-subtle-rgb));
|
|
83
|
+
|
|
84
|
+
--${runtimePrefix}-surface-border-rgb: var(--${runtimePrefix}-surface-border);
|
|
85
|
+
--${runtimePrefix}-surface-border-solid: rgb(var(--${runtimePrefix}-surface-border-rgb));
|
|
86
|
+
|
|
87
|
+
--${runtimePrefix}-surface-interaction-rgb: var(--${runtimePrefix}-surface-interaction);
|
|
88
|
+
--${runtimePrefix}-surface-interaction-solid: rgb(var(--${runtimePrefix}-surface-interaction-rgb));
|
|
89
|
+
|
|
90
|
+
--${runtimePrefix}-surface-interaction-hover-rgb: var(--${runtimePrefix}-surface-interaction-hover);
|
|
91
|
+
--${runtimePrefix}-surface-interaction-hover-solid: rgb(var(--${runtimePrefix}-surface-interaction-hover-rgb));
|
|
92
|
+
|
|
93
|
+
--${runtimePrefix}-surface-interaction-focus-rgb: var(--${runtimePrefix}-surface-interaction-focus);
|
|
94
|
+
--${runtimePrefix}-surface-interaction-focus-solid: rgb(var(--${runtimePrefix}-surface-interaction-focus-rgb));
|
|
95
|
+
|
|
96
|
+
--${runtimePrefix}-surface-interaction-active-rgb: var(--${runtimePrefix}-surface-interaction-active);
|
|
97
|
+
--${runtimePrefix}-surface-interaction-active-solid: rgb(var(--${runtimePrefix}-surface-interaction-active-rgb));
|
|
98
|
+
|
|
99
|
+
--${runtimePrefix}-surface-interaction-disabled-rgb: var(--${runtimePrefix}-surface-interaction-disabled);
|
|
100
|
+
--${runtimePrefix}-surface-interaction-disabled-solid: rgb(var(--${runtimePrefix}-surface-interaction-disabled-rgb));
|
|
101
|
+
|
|
102
|
+
/* Dynamic Tailwind surface colors - re-declared per surface scope so that
|
|
103
|
+
bg-${utilityPrefix}-surface-* utilities resolve against the nearest surface
|
|
104
|
+
(e.g. a nested elevated surface) instead of the value computed once at :root. */
|
|
105
|
+
${dynamicSurfaceColors.map((decl) => ` ${decl}`).join('\n')}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
return `${themeBlock} {
|
|
110
|
+
${tailwindVars.join('\n')}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@layer base {
|
|
114
|
+
${themeVars.join('\n')}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
${aliasBlock}
|
|
118
|
+
${buildSurfaceColorScope(runtimePrefix)}`;
|
|
119
|
+
};
|
|
120
|
+
/** The static CSS for an app's color themes, as the `tailwind-4-color-theme` generator writes it. */
|
|
121
|
+
export const colorThemeCss = (themes, options = {}) => {
|
|
122
|
+
const { utilityPrefix, runtimePrefix, themeBlock } = resolveOptions(options);
|
|
123
|
+
const tailwindVars = [];
|
|
124
|
+
const themeVars = [];
|
|
125
|
+
for (const theme of themes) {
|
|
126
|
+
const name = cssThemeName(theme.name);
|
|
127
|
+
tailwindVars.push(` /* ${theme.name} theme */`);
|
|
128
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}`, theme.primary.color);
|
|
129
|
+
tailwindVars.push('');
|
|
130
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}`, theme.primary.onColor);
|
|
131
|
+
tailwindVars.push('');
|
|
132
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-ink`, theme.primary.inkColor || theme.primary.color);
|
|
133
|
+
tailwindVars.push('');
|
|
134
|
+
if (theme.secondary) {
|
|
135
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-secondary`, theme.secondary.color);
|
|
136
|
+
tailwindVars.push('');
|
|
137
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-secondary`, theme.secondary.onColor);
|
|
138
|
+
tailwindVars.push('');
|
|
139
|
+
}
|
|
140
|
+
if (theme.tertiary) {
|
|
141
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-${name}-tertiary`, theme.tertiary.color);
|
|
142
|
+
tailwindVars.push('');
|
|
143
|
+
addTailwindColorVariants(tailwindVars, `${utilityPrefix}-on-${name}-tertiary`, theme.tertiary.onColor);
|
|
144
|
+
tailwindVars.push('');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
tailwindVars.push('');
|
|
148
|
+
const hasSecondary = themes.some((t) => t.secondary);
|
|
149
|
+
const hasTertiary = themes.some((t) => t.tertiary);
|
|
150
|
+
// A Tailwind `@theme` variable only lands on `:root`, so these are re-declared on every color
|
|
151
|
+
// scope in the alias block, or `bg-<prefix>-theme-*` would ignore a nested `.<runtime>-color--*`.
|
|
152
|
+
const dynamicColorVars = [];
|
|
153
|
+
addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme', 'primary');
|
|
154
|
+
addDynamicInkColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-ink', 'primary-ink');
|
|
155
|
+
if (hasSecondary) {
|
|
156
|
+
addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-secondary', 'secondary');
|
|
157
|
+
}
|
|
158
|
+
if (hasTertiary) {
|
|
159
|
+
addDynamicThemeColors(dynamicColorVars, utilityPrefix, runtimePrefix, 'theme-tertiary', 'tertiary');
|
|
160
|
+
}
|
|
161
|
+
tailwindVars.push(' /* Dynamic theme colors (references runtime CSS variables) */');
|
|
162
|
+
tailwindVars.push(...dynamicColorVars);
|
|
163
|
+
for (const theme of themes) {
|
|
164
|
+
const name = cssThemeName(theme.name);
|
|
165
|
+
if (theme.isDefault) {
|
|
166
|
+
const selectors = [':root', `.${runtimePrefix}-color--default`, `.${runtimePrefix}-color--${name}`];
|
|
167
|
+
themeVars.push(`${selectors.join(', ')} {`);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
themeVars.push(`.${runtimePrefix}-color--${name} {`);
|
|
171
|
+
}
|
|
172
|
+
addThemeColorVariants(themeVars, runtimePrefix, theme);
|
|
173
|
+
themeVars.push('}\n');
|
|
174
|
+
}
|
|
175
|
+
const dynamicColorAliasLines = dynamicColorVars.map((line) => (line === '' ? '' : ` ${line}`));
|
|
176
|
+
while (dynamicColorAliasLines.length && dynamicColorAliasLines[dynamicColorAliasLines.length - 1] === '') {
|
|
177
|
+
dynamicColorAliasLines.pop();
|
|
178
|
+
}
|
|
179
|
+
const aliasBlock = `/* Convenience aliases (rgb + solid + opacity variants) */
|
|
180
|
+
@layer base {
|
|
181
|
+
:root, :where([class*="${runtimePrefix}-color--"]) {
|
|
182
|
+
--${runtimePrefix}-theme-color-primary-rgb: var(--${runtimePrefix}-color-primary);
|
|
183
|
+
--${runtimePrefix}-theme-color-primary-opacity: 1;
|
|
184
|
+
--${runtimePrefix}-theme-color-primary-solid: rgb(var(--${runtimePrefix}-theme-color-primary-rgb));
|
|
185
|
+
--${runtimePrefix}-theme-color-primary: rgb(var(--${runtimePrefix}-theme-color-primary-rgb) / var(--${runtimePrefix}-theme-color-primary-opacity));
|
|
186
|
+
|
|
187
|
+
--${runtimePrefix}-theme-color-on-primary-rgb: var(--${runtimePrefix}-color-on-primary);
|
|
188
|
+
--${runtimePrefix}-theme-color-on-primary-opacity: 1;
|
|
189
|
+
--${runtimePrefix}-theme-color-on-primary-solid: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
|
|
190
|
+
--${runtimePrefix}-theme-color-on-primary: rgb(var(--${runtimePrefix}-theme-color-on-primary-rgb) / var(--${runtimePrefix}-theme-color-on-primary-opacity));
|
|
191
|
+
|
|
192
|
+
--${runtimePrefix}-theme-color-ink-rgb: var(--${runtimePrefix}-color-primary-ink, var(--${runtimePrefix}-color-primary));
|
|
193
|
+
--${runtimePrefix}-theme-color-ink-opacity: 1;
|
|
194
|
+
--${runtimePrefix}-theme-color-ink-solid: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
|
|
195
|
+
--${runtimePrefix}-theme-color-ink: rgb(var(--${runtimePrefix}-theme-color-ink-rgb) / var(--${runtimePrefix}-theme-color-ink-opacity));
|
|
196
|
+
|
|
197
|
+
/* Dynamic Tailwind theme colors - re-declared per color scope so that
|
|
198
|
+
bg-${utilityPrefix}-theme-* utilities resolve against the nearest .${runtimePrefix}-color--*
|
|
199
|
+
scope instead of the value computed once at :root. */
|
|
200
|
+
${dynamicColorAliasLines.join('\n')}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
return `${themeBlock} {
|
|
205
|
+
${tailwindVars.join('\n')}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@layer base {
|
|
209
|
+
${themeVars.join('\n')}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
${aliasBlock}`;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* The surface and color theme CSS of an app as one plain stylesheet, without Tailwind, for a
|
|
216
|
+
* design drawing: `drawing({ body, styles: themeCss({ surfaceThemes, colorThemes }) + … })`.
|
|
217
|
+
*/
|
|
218
|
+
export const themeCss = (themes) => {
|
|
219
|
+
const options = { prefix: themes.prefix, tailwind: false };
|
|
220
|
+
return `${surfaceThemeCss(themes.surfaceThemes, options)}\n${colorThemeCss(themes.colorThemes, options)}`;
|
|
221
|
+
};
|
|
222
|
+
const INTERACTION_STATE_SUFFIXES = ['', '-hover', '-focus', '-active', '-disabled'];
|
|
223
|
+
// The reserved `surface` color scope lives here and not in the SDK's own CSS, so only apps that
|
|
224
|
+
// use `[etProvideColor]="'surface'"` pay for it.
|
|
225
|
+
const buildSurfaceColorScope = (runtimePrefix) => {
|
|
226
|
+
const tint = `var(--${runtimePrefix}-surface-interaction, var(--${runtimePrefix}-surface-color))`;
|
|
227
|
+
const on = `var(--${runtimePrefix}-surface-on-interaction, var(--${runtimePrefix}-surface-background))`;
|
|
228
|
+
const ink = `var(--${runtimePrefix}-surface-interaction-ink, var(--${runtimePrefix}-surface-color))`;
|
|
229
|
+
const state = (name, source, fallback) => INTERACTION_STATE_SUFFIXES.map((suffix) => ` --${runtimePrefix}-color-${name}${suffix}: ${suffix ? `var(--${runtimePrefix}-surface-${source}${suffix}, ${fallback})` : fallback};`).join('\n');
|
|
230
|
+
return `/* The reserved \`surface\` color: resolves the color tokens from the ambient surface's neutral swatch. */
|
|
231
|
+
@layer base {
|
|
232
|
+
.${runtimePrefix}-color--surface {
|
|
233
|
+
${state('primary', 'interaction', tint)}
|
|
234
|
+
|
|
235
|
+
${state('on-primary', 'on-interaction', on)}
|
|
236
|
+
|
|
237
|
+
${state('primary-ink', 'interaction-ink', ink)}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
`;
|
|
241
|
+
};
|
|
242
|
+
const buildDynamicSurfaceColors = (utilityPrefix, runtimePrefix) => {
|
|
243
|
+
const onFallback = `var(--${runtimePrefix}-surface-background)`;
|
|
244
|
+
const inkFallback = `var(--${runtimePrefix}-surface-color)`;
|
|
245
|
+
return [
|
|
246
|
+
`--color-${utilityPrefix}-surface-bg: rgb(var(--${runtimePrefix}-surface-background));`,
|
|
247
|
+
`--color-${utilityPrefix}-surface: rgb(var(--${runtimePrefix}-surface-color));`,
|
|
248
|
+
`--color-${utilityPrefix}-surface-muted: rgb(var(--${runtimePrefix}-surface-color-muted));`,
|
|
249
|
+
`--color-${utilityPrefix}-surface-subtle: rgb(var(--${runtimePrefix}-surface-color-subtle));`,
|
|
250
|
+
`--color-${utilityPrefix}-surface-border: rgb(var(--${runtimePrefix}-surface-border));`,
|
|
251
|
+
`--color-${utilityPrefix}-surface-interaction: rgb(var(--${runtimePrefix}-surface-interaction));`,
|
|
252
|
+
`--color-${utilityPrefix}-surface-interaction-hover: rgb(var(--${runtimePrefix}-surface-interaction-hover));`,
|
|
253
|
+
`--color-${utilityPrefix}-surface-interaction-focus: rgb(var(--${runtimePrefix}-surface-interaction-focus));`,
|
|
254
|
+
`--color-${utilityPrefix}-surface-interaction-active: rgb(var(--${runtimePrefix}-surface-interaction-active));`,
|
|
255
|
+
`--color-${utilityPrefix}-surface-interaction-disabled: rgb(var(--${runtimePrefix}-surface-interaction-disabled));`,
|
|
256
|
+
...INTERACTION_STATE_SUFFIXES.map((suffix) => `--color-${utilityPrefix}-surface-on-interaction${suffix}: rgb(var(--${runtimePrefix}-surface-on-interaction${suffix}, ${onFallback}));`),
|
|
257
|
+
...INTERACTION_STATE_SUFFIXES.map((suffix) => `--color-${utilityPrefix}-surface-interaction-ink${suffix}: rgb(var(--${runtimePrefix}-surface-interaction-ink${suffix}, ${inkFallback}));`),
|
|
258
|
+
];
|
|
259
|
+
};
|
|
260
|
+
const resolveInteractionStates = (map) => {
|
|
261
|
+
const hover = map.hover || map.default;
|
|
262
|
+
return {
|
|
263
|
+
'': map.default,
|
|
264
|
+
'-hover': hover,
|
|
265
|
+
'-focus': map.focus || hover,
|
|
266
|
+
'-active': map.active || map.default,
|
|
267
|
+
'-disabled': map.disabled || map.default,
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
const pushStaticInteractionColors = (vars, name, map) => {
|
|
271
|
+
const states = resolveInteractionStates(map);
|
|
272
|
+
for (const suffix of INTERACTION_STATE_SUFFIXES) {
|
|
273
|
+
vars.push(` ${name}${suffix}: rgb(${states[suffix]});`);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const pushRuntimeInteractionVars = (vars, name, map, indent) => {
|
|
277
|
+
const states = resolveInteractionStates(map);
|
|
278
|
+
for (const suffix of INTERACTION_STATE_SUFFIXES) {
|
|
279
|
+
vars.push(`${indent}${name}${suffix}: ${states[suffix]};`);
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const pushRootSurfaceVars = (vars, runtimePrefix, theme) => {
|
|
283
|
+
if (!theme)
|
|
284
|
+
return;
|
|
285
|
+
vars.push(`:root {`);
|
|
286
|
+
pushSurfaceVars(vars, runtimePrefix, theme, ' ');
|
|
287
|
+
vars.push(` color-scheme: ${theme.type};`);
|
|
288
|
+
vars.push(`}\n`);
|
|
289
|
+
};
|
|
290
|
+
const pushSchemeSurfaceVars = (vars, runtimePrefix, theme) => {
|
|
291
|
+
vars.push(`@media (prefers-color-scheme: ${theme.type}) {`);
|
|
292
|
+
vars.push(` :root {`);
|
|
293
|
+
pushSurfaceVars(vars, runtimePrefix, theme, ' ');
|
|
294
|
+
vars.push(` color-scheme: ${theme.type};`);
|
|
295
|
+
vars.push(` }`);
|
|
296
|
+
vars.push(`}\n`);
|
|
297
|
+
};
|
|
298
|
+
// `:root.<prefix>-scheme--<type>` must out-specify the `:root` inside the media query above, so the
|
|
299
|
+
// class set by `provideColorScheme()` overrides the OS preference regardless of source order.
|
|
300
|
+
const pushForcedSchemeSurfaceVars = (vars, runtimePrefix, theme) => {
|
|
301
|
+
vars.push(`:root.${runtimePrefix}-scheme--${theme.type} {`);
|
|
302
|
+
pushSurfaceVars(vars, runtimePrefix, theme, ' ');
|
|
303
|
+
vars.push(` color-scheme: ${theme.type};`);
|
|
304
|
+
vars.push(`}\n`);
|
|
305
|
+
};
|
|
306
|
+
const pushSurfaceVars = (vars, runtimePrefix, theme, indent) => {
|
|
307
|
+
vars.push(`${indent}--${runtimePrefix}-surface-background: ${theme.background};`);
|
|
308
|
+
vars.push(`${indent}--${runtimePrefix}-surface-color: ${theme.color};`);
|
|
309
|
+
vars.push(`${indent}--${runtimePrefix}-surface-color-muted: ${theme.colorMuted};`);
|
|
310
|
+
vars.push(`${indent}--${runtimePrefix}-surface-color-subtle: ${theme.colorSubtle};`);
|
|
311
|
+
vars.push(`${indent}--${runtimePrefix}-surface-border: ${theme.border};`);
|
|
312
|
+
vars.push(`${indent}--${runtimePrefix}-surface-type: ${theme.type};`);
|
|
313
|
+
vars.push(`${indent}--${runtimePrefix}-surface-elevation: ${theme.elevation};`);
|
|
314
|
+
if (theme.interactionColor) {
|
|
315
|
+
const { color, onColor, inkColor } = theme.interactionColor;
|
|
316
|
+
pushRuntimeInteractionVars(vars, `--${runtimePrefix}-surface-interaction`, color, indent);
|
|
317
|
+
if (onColor) {
|
|
318
|
+
pushRuntimeInteractionVars(vars, `--${runtimePrefix}-surface-on-interaction`, onColor, indent);
|
|
319
|
+
}
|
|
320
|
+
if (inkColor) {
|
|
321
|
+
pushRuntimeInteractionVars(vars, `--${runtimePrefix}-surface-interaction-ink`, inkColor, indent);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const addDynamicColorStates = (vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName) => {
|
|
326
|
+
for (const suffix of INTERACTION_STATE_SUFFIXES) {
|
|
327
|
+
vars.push(` --color-${utilityPrefix}-${tailwindName}${suffix}: rgb(var(--${runtimePrefix}-color-${cssVarName}${suffix}));`);
|
|
328
|
+
}
|
|
329
|
+
vars.push('');
|
|
330
|
+
};
|
|
331
|
+
const addDynamicThemeColors = (vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName) => {
|
|
332
|
+
addDynamicColorStates(vars, utilityPrefix, runtimePrefix, tailwindName, cssVarName);
|
|
333
|
+
addDynamicColorStates(vars, utilityPrefix, runtimePrefix, `on-${tailwindName}`, `on-${cssVarName}`);
|
|
334
|
+
};
|
|
335
|
+
const addDynamicInkColors = addDynamicColorStates;
|
|
336
|
+
const addTailwindColorVariants = (vars, colorName, colorSet) => {
|
|
337
|
+
vars.push(` --color-${colorName}: rgb(${colorSet.default});`);
|
|
338
|
+
const hoverValue = colorSet.hover || colorSet.default;
|
|
339
|
+
vars.push(` --color-${colorName}-hover: rgb(${hoverValue});`);
|
|
340
|
+
const focusValue = colorSet.focus || hoverValue;
|
|
341
|
+
vars.push(` --color-${colorName}-focus: rgb(${focusValue});`);
|
|
342
|
+
const activeValue = colorSet.active || hoverValue;
|
|
343
|
+
vars.push(` --color-${colorName}-active: rgb(${activeValue});`);
|
|
344
|
+
const disabledValue = colorSet.disabled || colorSet.default;
|
|
345
|
+
vars.push(` --color-${colorName}-disabled: rgb(${disabledValue});`);
|
|
346
|
+
};
|
|
347
|
+
const addThemeColorVariants = (vars, prefix, theme) => {
|
|
348
|
+
const addSwatch = (level, swatch) => {
|
|
349
|
+
const defaultColor = swatch.color.default;
|
|
350
|
+
const hoverColor = swatch.color.hover || defaultColor;
|
|
351
|
+
const focusColor = swatch.color.focus || hoverColor;
|
|
352
|
+
const activeColor = swatch.color.active || hoverColor;
|
|
353
|
+
const disabledColor = swatch.color.disabled || defaultColor;
|
|
354
|
+
vars.push(` --${prefix}-color-${level}: ${defaultColor};`);
|
|
355
|
+
vars.push(` --${prefix}-color-${level}-hover: ${hoverColor};`);
|
|
356
|
+
vars.push(` --${prefix}-color-${level}-focus: ${focusColor};`);
|
|
357
|
+
vars.push(` --${prefix}-color-${level}-active: ${activeColor};`);
|
|
358
|
+
vars.push(` --${prefix}-color-${level}-disabled: ${disabledColor};`);
|
|
359
|
+
vars.push('');
|
|
360
|
+
const onDefaultColor = swatch.onColor.default;
|
|
361
|
+
const onHoverColor = swatch.onColor.hover || onDefaultColor;
|
|
362
|
+
const onFocusColor = swatch.onColor.focus || onHoverColor;
|
|
363
|
+
const onActiveColor = swatch.onColor.active || onDefaultColor;
|
|
364
|
+
const onDisabledColor = swatch.onColor.disabled || onDefaultColor;
|
|
365
|
+
vars.push(` --${prefix}-color-on-${level}: ${onDefaultColor};`);
|
|
366
|
+
vars.push(` --${prefix}-color-on-${level}-hover: ${onHoverColor};`);
|
|
367
|
+
vars.push(` --${prefix}-color-on-${level}-focus: ${onFocusColor};`);
|
|
368
|
+
vars.push(` --${prefix}-color-on-${level}-active: ${onActiveColor};`);
|
|
369
|
+
vars.push(` --${prefix}-color-on-${level}-disabled: ${onDisabledColor};`);
|
|
370
|
+
const inkDefaultColor = swatch.inkColor?.default || defaultColor;
|
|
371
|
+
const inkHoverColor = swatch.inkColor?.hover || inkDefaultColor;
|
|
372
|
+
const inkFocusColor = swatch.inkColor?.focus || inkHoverColor;
|
|
373
|
+
const inkActiveColor = swatch.inkColor?.active || inkDefaultColor;
|
|
374
|
+
const inkDisabledColor = swatch.inkColor?.disabled || inkDefaultColor;
|
|
375
|
+
vars.push('');
|
|
376
|
+
vars.push(` --${prefix}-color-${level}-ink: ${inkDefaultColor};`);
|
|
377
|
+
vars.push(` --${prefix}-color-${level}-ink-hover: ${inkHoverColor};`);
|
|
378
|
+
vars.push(` --${prefix}-color-${level}-ink-focus: ${inkFocusColor};`);
|
|
379
|
+
vars.push(` --${prefix}-color-${level}-ink-active: ${inkActiveColor};`);
|
|
380
|
+
vars.push(` --${prefix}-color-${level}-ink-disabled: ${inkDisabledColor};`);
|
|
381
|
+
if (theme.secondary || theme.tertiary) {
|
|
382
|
+
vars.push('');
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
addSwatch('primary', theme.primary);
|
|
386
|
+
if (theme.secondary) {
|
|
387
|
+
addSwatch('secondary', theme.secondary);
|
|
388
|
+
}
|
|
389
|
+
if (theme.tertiary) {
|
|
390
|
+
addSwatch('tertiary', theme.tertiary);
|
|
391
|
+
}
|
|
392
|
+
};
|