@acorex/core 22.1.0-next.31 → 22.1.0-next.32
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/constants/README.md +7 -1
- package/fesm2022/acorex-core-components.mjs +3 -3
- package/fesm2022/acorex-core-config.mjs +3 -3
- package/fesm2022/acorex-core-constants.mjs +27809 -1
- package/fesm2022/acorex-core-constants.mjs.map +1 -1
- package/fesm2022/acorex-core-date-time.mjs +55 -41
- package/fesm2022/acorex-core-date-time.mjs.map +1 -1
- package/fesm2022/acorex-core-events.mjs +3 -3
- package/fesm2022/acorex-core-file.mjs +53 -46
- package/fesm2022/acorex-core-file.mjs.map +1 -1
- package/fesm2022/acorex-core-format.mjs +19 -19
- package/fesm2022/acorex-core-full-screen.mjs +232 -59
- package/fesm2022/acorex-core-full-screen.mjs.map +1 -1
- package/fesm2022/acorex-core-icon.mjs +3 -3
- package/fesm2022/acorex-core-image.mjs +3 -3
- package/fesm2022/acorex-core-locale.mjs +13 -10
- package/fesm2022/acorex-core-locale.mjs.map +1 -1
- package/fesm2022/acorex-core-network.mjs +3 -3
- package/fesm2022/acorex-core-pipes.mjs +3 -3
- package/fesm2022/acorex-core-platform.mjs +4 -3
- package/fesm2022/acorex-core-platform.mjs.map +1 -1
- package/fesm2022/acorex-core-storage.mjs +9 -9
- package/fesm2022/acorex-core-theme-builder.mjs +1329 -0
- package/fesm2022/acorex-core-theme-builder.mjs.map +1 -0
- package/fesm2022/acorex-core-translation.mjs +36 -24
- package/fesm2022/acorex-core-translation.mjs.map +1 -1
- package/fesm2022/acorex-core-utils.mjs +256 -80
- package/fesm2022/acorex-core-utils.mjs.map +1 -1
- package/fesm2022/acorex-core-validation.mjs +40 -40
- package/fesm2022/acorex-core-z-index.mjs +3 -3
- package/i18n/en-AU/acorex.json +1101 -0
- package/i18n/en-AU/common.json +290 -0
- package/i18n/en-US/acorex.json +1101 -0
- package/i18n/en-US/common.json +285 -0
- package/i18n/fa-IR/acorex.json +1101 -0
- package/i18n/fa-IR/common.json +284 -0
- package/package.json +8 -2
- package/theme-builder/README.md +53 -0
- package/types/acorex-core-components.d.ts +1 -1
- package/types/acorex-core-config.d.ts +1 -1
- package/types/acorex-core-constants.d.ts +58 -2
- package/types/acorex-core-date-time.d.ts +9 -4
- package/types/acorex-core-events.d.ts +1 -1
- package/types/acorex-core-file.d.ts +12 -11
- package/types/acorex-core-format.d.ts +3 -3
- package/types/acorex-core-full-screen.d.ts +67 -18
- package/types/acorex-core-icon.d.ts +1 -1
- package/types/acorex-core-image.d.ts +1 -1
- package/types/acorex-core-locale.d.ts +4 -2
- package/types/acorex-core-network.d.ts +1 -1
- package/types/acorex-core-platform.d.ts +1 -1
- package/types/acorex-core-storage.d.ts +3 -3
- package/types/acorex-core-theme-builder.d.ts +42 -0
- package/types/acorex-core-translation.d.ts +12 -6
- package/types/acorex-core-utils.d.ts +54 -16
- package/types/acorex-core-validation.d.ts +12 -12
- package/types/acorex-core-z-index.d.ts +1 -1
|
@@ -0,0 +1,1329 @@
|
|
|
1
|
+
import * as culori from 'culori';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canonical role order for full-theme CSS export (must stay in sync with theme tail + `:root` generation).
|
|
5
|
+
*/
|
|
6
|
+
/** Roles that produce `--ax-sys-color-{role}-*` tokens under `:root` / `.ax-dark`. */
|
|
7
|
+
const EXPORT_ROOT_ROLE_ORDER = [
|
|
8
|
+
'primary',
|
|
9
|
+
'secondary',
|
|
10
|
+
'success',
|
|
11
|
+
'warning',
|
|
12
|
+
'danger',
|
|
13
|
+
'surface',
|
|
14
|
+
'accent',
|
|
15
|
+
'accent1',
|
|
16
|
+
'accent2',
|
|
17
|
+
'accent3',
|
|
18
|
+
'accent4',
|
|
19
|
+
'accent5',
|
|
20
|
+
'accent6',
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Roles mirrored in `@theme` and compound `@utility` blocks.
|
|
24
|
+
* Omits grayscale `surface` (handled via neutral tokens + `--ax-sys-color-surface-*` scale only).
|
|
25
|
+
*/
|
|
26
|
+
const EXPORT_TAIL_THEME_PALETTE_ORDER = [
|
|
27
|
+
'primary',
|
|
28
|
+
'secondary',
|
|
29
|
+
'success',
|
|
30
|
+
'warning',
|
|
31
|
+
'danger',
|
|
32
|
+
'accent',
|
|
33
|
+
'accent1',
|
|
34
|
+
'accent2',
|
|
35
|
+
'accent3',
|
|
36
|
+
'accent4',
|
|
37
|
+
'accent5',
|
|
38
|
+
'accent6',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Mirrors `packages/styles/themes/default.css` from `@theme inline {` through the end:
|
|
43
|
+
* `@theme inline`, `.ax-dark .ax-light` subtree overrides, `.ax-dark` color-alias re-declaration,
|
|
44
|
+
* role utilities, typography, headings, spacing.
|
|
45
|
+
* Only `--ax-sys-*` RGB triplets in `:root` / `.ax-dark` vary (handled in ThemeBuilderService).
|
|
46
|
+
* Extends the package theme with `accent1`…`accent6` after `accent` (seven accent palettes total).
|
|
47
|
+
*/
|
|
48
|
+
const SEMANTIC_LEVELS = ['lightest', 'lighter', 'light', 'surface', 'dark', 'darker', 'darkest'];
|
|
49
|
+
/**
|
|
50
|
+
* Default Tailwind scale (matches `ax-md`) wired to `--ax-sys-*-base` tokens.
|
|
51
|
+
* Mirrors `packages/styles/themes/default.css` `:root` and `@theme inline` blocks.
|
|
52
|
+
*/
|
|
53
|
+
function buildDefaultTailwindScaleBlock(scope = 'root') {
|
|
54
|
+
const comment = scope === 'theme'
|
|
55
|
+
? ' /* Standard Tailwind scale (matches ax-md) — wired to base tokens so all utilities respond to theme changes */\n'
|
|
56
|
+
: ' /* Standard Tailwind type scale (matches ax-md) — used when no ax-* size class is applied */\n';
|
|
57
|
+
return (comment +
|
|
58
|
+
` --spacing: var(--ax-sys-spacing-base);
|
|
59
|
+
--text-xs: var(--ax-sys-text-xs-base);
|
|
60
|
+
--text-sm: var(--ax-sys-text-sm-base);
|
|
61
|
+
--text-base: var(--ax-sys-body-font-size);
|
|
62
|
+
--text-lg: var(--ax-sys-text-lg-base);
|
|
63
|
+
--text-xl: var(--ax-sys-text-xl-base);
|
|
64
|
+
--leading-3: var(--ax-sys-leading-3-base);
|
|
65
|
+
--leading-4: var(--ax-sys-leading-4-base);
|
|
66
|
+
--leading-5: var(--ax-sys-leading-5-base);
|
|
67
|
+
--leading-6: var(--ax-sys-leading-6-base);
|
|
68
|
+
|
|
69
|
+
`);
|
|
70
|
+
}
|
|
71
|
+
/** Verbatim Tailwind utilities after `ax-accent`; matches default.css § max-w-8xl … ax-xl */
|
|
72
|
+
const THEME_TAIL_VERBATIM_FOOTER = `
|
|
73
|
+
@utility max-w-8xl {
|
|
74
|
+
max-width: 90rem;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@utility ax-state-disabled {
|
|
78
|
+
@apply cursor-not-allowed opacity-50 *:cursor-not-allowed;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@utility ax-state-readonly {
|
|
82
|
+
@apply cursor-text opacity-70 *:cursor-text;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@utility ax-fill {
|
|
86
|
+
&.ax-default {
|
|
87
|
+
@apply light-surface dark:dark-surface;
|
|
88
|
+
}
|
|
89
|
+
&.ax-editor-container {
|
|
90
|
+
@apply focus-within:ring-primary/30 focus-within:border-primary focus-within:ring-3;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@utility ax-flat {
|
|
95
|
+
@apply rounded-none;
|
|
96
|
+
&.ax-default {
|
|
97
|
+
@apply border-border-lightest dark:border-border-darkest border-b bg-transparent;
|
|
98
|
+
}
|
|
99
|
+
&.ax-editor-container {
|
|
100
|
+
@apply focus-within:border-primary!;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@utility ax-solid {
|
|
105
|
+
@apply bg-(--ax-comp-bg,var(--color-lightest)) text-(--ax-comp-text,var(--color-on-lightest)) dark:bg-(--ax-comp-bg,var(--color-darkest)) dark:text-(--ax-comp-text,var(--color-on-darkest));
|
|
106
|
+
&.ax-default {
|
|
107
|
+
@apply lightest-surface dark:darkest-surface border;
|
|
108
|
+
}
|
|
109
|
+
&.ax-state-selected {
|
|
110
|
+
@apply bg-(--ax-comp-bg-darker,var(--color-light)) text-(--ax-comp-text-darker,var(--color-on-light)) dark:bg-(--ax-comp-bg-darker,var(--color-dark)) dark:text-(--ax-comp-text-darker,var(--color-on-dark));
|
|
111
|
+
}
|
|
112
|
+
&.ax-editor-container {
|
|
113
|
+
@apply focus-within:ring-primary/30 focus-within:border-primary focus-within:ring-3;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@utility ax-solid-interactive {
|
|
118
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
119
|
+
--ax-comp-ripple-color: color-mix(in oklab, var(--ax-comp-bg-lightest, var(--color-on-lightest)) 25%, transparent);
|
|
120
|
+
}
|
|
121
|
+
@apply ax-solid transition-colors;
|
|
122
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected) {
|
|
123
|
+
&:hover,
|
|
124
|
+
&:focus,
|
|
125
|
+
&:focus-within,
|
|
126
|
+
&:focus-visible {
|
|
127
|
+
@apply bg-(--ax-comp-bg-dark,var(--color-lighter)) text-(--ax-comp-text-dark,var(--color-on-lighter)) dark:bg-(--ax-comp-bg-dark,var(--color-darker)) dark:text-(--ax-comp-text-dark,var(--color-on-darker));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected):active {
|
|
131
|
+
@apply bg-(--ax-comp-bg-darker,var(--color-light)) text-(--ax-comp-text-darker,var(--color-on-light)) ring-1 ring-(--ax-comp-bg-dark) ring-offset-1 dark:bg-(--ax-comp-bg-darker,var(--color-dark)) dark:text-(--ax-comp-text-darker,var(--color-on-dark));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@utility ax-outline {
|
|
136
|
+
@apply border bg-transparent;
|
|
137
|
+
border-color: var(--ax-comp-edge, var(--ax-comp-bg, var(--color-border-lightest)));
|
|
138
|
+
color: var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-lightest)));
|
|
139
|
+
&.ax-default {
|
|
140
|
+
@apply border-border-lightest dark:border-border-darkest border;
|
|
141
|
+
}
|
|
142
|
+
&.ax-state-selected {
|
|
143
|
+
border-color: var(--ax-comp-edge-darker, var(--ax-comp-bg-darker, var(--color-border-light)));
|
|
144
|
+
color: var(--ax-comp-ink-darker, var(--ax-comp-bg-darker, var(--color-on-light)));
|
|
145
|
+
}
|
|
146
|
+
&.ax-editor-container {
|
|
147
|
+
@apply focus-within:ring-primary/30 focus-within:border-primary focus-within:ring-3;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@utility ax-outline-interactive {
|
|
152
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
153
|
+
--ax-comp-ripple-color: color-mix(in oklab, var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-lightest))) 25%, transparent);
|
|
154
|
+
}
|
|
155
|
+
@apply ax-outline transition-colors;
|
|
156
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected) {
|
|
157
|
+
&:hover,
|
|
158
|
+
&:focus,
|
|
159
|
+
&:focus-within,
|
|
160
|
+
&:focus-visible {
|
|
161
|
+
border-color: var(--ax-comp-edge-dark, var(--ax-comp-bg-dark, var(--color-border-lighter)));
|
|
162
|
+
color: var(--ax-comp-ink-dark, var(--ax-comp-bg-dark, var(--color-on-lighter)));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected):active {
|
|
166
|
+
border-color: var(--ax-comp-edge-darker, var(--ax-comp-bg-darker, var(--color-border-light)));
|
|
167
|
+
color: var(--ax-comp-ink-darker, var(--ax-comp-bg-darker, var(--color-on-light)));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@utility ax-twotone {
|
|
172
|
+
@apply bg-(--ax-comp-bg-lightest,var(--color-lighter)) text-(--ax-comp-text-lightest,var(--color-on-lighter)) dark:bg-(--ax-comp-bg-lightest,var(--color-darker)) dark:text-(--ax-comp-text-lightest,var(--color-on-darker));
|
|
173
|
+
&.ax-state-selected {
|
|
174
|
+
@apply bg-(--ax-comp-bg-light,var(--color-surface)) text-(--ax-comp-text-light,var(--color-on-surface));
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@utility ax-twotone-interactive {
|
|
179
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
180
|
+
--ax-comp-ripple-color: color-mix(in oklab, var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-lightest))) 25%, transparent);
|
|
181
|
+
}
|
|
182
|
+
@apply ax-twotone transition-colors;
|
|
183
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected) {
|
|
184
|
+
&:hover,
|
|
185
|
+
&:focus,
|
|
186
|
+
&:focus-within,
|
|
187
|
+
&:focus-visible {
|
|
188
|
+
@apply bg-(--ax-comp-bg-lighter,var(--color-light)) text-(--ax-comp-text-lighter,var(--color-on-light)) dark:bg-(--ax-comp-bg-lighter,var(--color-dark)) dark:text-(--ax-comp-text-lighter,var(--color-on-dark));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected):active {
|
|
192
|
+
@apply bg-(--ax-comp-bg-light,var(--color-surface)) text-(--ax-comp-text-light,var(--color-on-surface));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@utility ax-blank {
|
|
197
|
+
@apply bg-transparent;
|
|
198
|
+
color: var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-surface)));
|
|
199
|
+
&.ax-state-selected {
|
|
200
|
+
@apply bg-(--ax-comp-bg-lighter,var(--color-surface)) text-(--ax-comp-text-lighter,var(--color-on-surface));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@utility ax-blank-interactive {
|
|
205
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
206
|
+
--ax-comp-ripple-color: color-mix(in oklab, var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-lightest))) 25%, transparent);
|
|
207
|
+
}
|
|
208
|
+
@apply ax-blank transition-colors;
|
|
209
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected) {
|
|
210
|
+
&:hover,
|
|
211
|
+
&:focus,
|
|
212
|
+
&:focus-within,
|
|
213
|
+
&:focus-visible {
|
|
214
|
+
@apply bg-(--ax-comp-bg-lightest,var(--color-lighter)) text-(--ax-comp-text-lightest,var(--color-on-lighter)) dark:bg-(--ax-comp-bg-lightest,var(--color-darker)) dark:text-(--ax-comp-text-lightest,var(--color-on-darker));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected):active {
|
|
218
|
+
@apply bg-(--ax-comp-bg-lighter,var(--color-surface)) text-(--ax-comp-text-lighter,var(--color-on-surface));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
@utility links {
|
|
223
|
+
@apply bg-transparent;
|
|
224
|
+
color: var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-surface)));
|
|
225
|
+
&.ax-state-selected {
|
|
226
|
+
color: var(--ax-comp-ink-darker, var(--ax-comp-bg-darker, var(--color-on-surface)));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
@utility links-interactive {
|
|
231
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
232
|
+
--ax-comp-ripple-color: color-mix(in oklab, var(--ax-comp-ink, var(--ax-comp-bg, var(--color-on-lightest))) 25%, transparent);
|
|
233
|
+
}
|
|
234
|
+
@apply links transition-colors;
|
|
235
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected) {
|
|
236
|
+
&:hover,
|
|
237
|
+
&:focus,
|
|
238
|
+
&:focus-within,
|
|
239
|
+
&:focus-visible {
|
|
240
|
+
color: var(--ax-comp-ink-dark, var(--ax-comp-bg-dark, var(--color-on-surface)));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
&:not(.ax-state-disabled, .ax-state-loading, .ax-state-selected):active {
|
|
244
|
+
color: var(--ax-comp-ink-darker, var(--ax-comp-bg-darker, var(--color-on-surface)));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
@utility h1 {
|
|
248
|
+
font-size: 2.5rem;
|
|
249
|
+
font-weight: 500;
|
|
250
|
+
line-height: 2.5rem;
|
|
251
|
+
}
|
|
252
|
+
@utility h2 {
|
|
253
|
+
font-size: 2rem;
|
|
254
|
+
font-weight: 500;
|
|
255
|
+
line-height: 2rem;
|
|
256
|
+
}
|
|
257
|
+
@utility h3 {
|
|
258
|
+
font-size: 1.75rem;
|
|
259
|
+
font-weight: 500;
|
|
260
|
+
line-height: 1.75rem;
|
|
261
|
+
}
|
|
262
|
+
@utility h4 {
|
|
263
|
+
font-size: 1.5rem;
|
|
264
|
+
font-weight: 500;
|
|
265
|
+
line-height: 1.5rem;
|
|
266
|
+
}
|
|
267
|
+
@utility h5 {
|
|
268
|
+
font-size: 1.125rem;
|
|
269
|
+
font-weight: 500;
|
|
270
|
+
line-height: 1.125rem;
|
|
271
|
+
}
|
|
272
|
+
@utility h6 {
|
|
273
|
+
font-size: 1rem;
|
|
274
|
+
font-weight: 500;
|
|
275
|
+
line-height: 1rem;
|
|
276
|
+
}
|
|
277
|
+
@utility heading {
|
|
278
|
+
width: 100%;
|
|
279
|
+
border-bottom: 1px solid;
|
|
280
|
+
border-color: rgba(var(--ax-sys-color-border-lightest-surface));
|
|
281
|
+
line-height: 0.1em;
|
|
282
|
+
margin: 1rem auto;
|
|
283
|
+
}
|
|
284
|
+
@utility heading-start {
|
|
285
|
+
text-align: start;
|
|
286
|
+
}
|
|
287
|
+
@utility heading-center {
|
|
288
|
+
text-align: center;
|
|
289
|
+
}
|
|
290
|
+
@utility heading-end {
|
|
291
|
+
text-align: end;
|
|
292
|
+
}
|
|
293
|
+
@utility subtitle {
|
|
294
|
+
opacity: 74%;
|
|
295
|
+
display: block;
|
|
296
|
+
font-size: 1rem;
|
|
297
|
+
font-weight: 400;
|
|
298
|
+
line-height: 1.625rem;
|
|
299
|
+
}
|
|
300
|
+
@utility tabs-fit {
|
|
301
|
+
width: 100%;
|
|
302
|
+
}
|
|
303
|
+
@utility ax-xs {
|
|
304
|
+
/* Spacing */
|
|
305
|
+
--spacing: calc(var(--ax-sys-spacing-base) * 0.5);
|
|
306
|
+
--ax-sys-border-radius: calc(var(--ax-sys-border-radius-base) * 0.5);
|
|
307
|
+
|
|
308
|
+
/* Typography */
|
|
309
|
+
--text-xs: calc(var(--ax-sys-text-xs-base) * 5 / 6);
|
|
310
|
+
--text-sm: calc(var(--ax-sys-text-sm-base) * 11 / 14);
|
|
311
|
+
--text-base: calc(var(--ax-sys-body-font-size) * 0.75);
|
|
312
|
+
--text-lg: calc(var(--ax-sys-text-lg-base) * 7 / 9);
|
|
313
|
+
--text-xl: calc(var(--ax-sys-text-xl-base) * 0.8);
|
|
314
|
+
|
|
315
|
+
/* Line Heights */
|
|
316
|
+
--leading-3: var(--ax-sys-leading-3-base);
|
|
317
|
+
--leading-4: calc(var(--ax-sys-leading-4-base) * 0.875);
|
|
318
|
+
--leading-5: calc(var(--ax-sys-leading-5-base) * 0.8);
|
|
319
|
+
--leading-6: calc(var(--ax-sys-leading-6-base) * 5 / 6);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@utility ax-sm {
|
|
323
|
+
/* Spacing */
|
|
324
|
+
--spacing: calc(var(--ax-sys-spacing-base) * 0.75);
|
|
325
|
+
--ax-sys-border-radius: calc(var(--ax-sys-border-radius-base) * 0.75);
|
|
326
|
+
|
|
327
|
+
/* Typography */
|
|
328
|
+
--text-xs: calc(var(--ax-sys-text-xs-base) * 11 / 12);
|
|
329
|
+
--text-sm: calc(var(--ax-sys-text-sm-base) * 6 / 7);
|
|
330
|
+
--text-base: calc(var(--ax-sys-body-font-size) * 0.875);
|
|
331
|
+
--text-lg: calc(var(--ax-sys-text-lg-base) * 8 / 9);
|
|
332
|
+
--text-xl: calc(var(--ax-sys-text-xl-base) * 0.9);
|
|
333
|
+
|
|
334
|
+
/* Line Heights */
|
|
335
|
+
--leading-3: calc(var(--ax-sys-leading-3-base) * 7 / 6);
|
|
336
|
+
--leading-4: var(--ax-sys-leading-4-base);
|
|
337
|
+
--leading-5: calc(var(--ax-sys-leading-5-base) * 0.9);
|
|
338
|
+
--leading-6: calc(var(--ax-sys-leading-6-base) * 11 / 12);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
@utility ax-md {
|
|
342
|
+
/* Tailwind Default Scale */
|
|
343
|
+
--spacing: var(--ax-sys-spacing-base);
|
|
344
|
+
--ax-sys-border-radius: var(--ax-sys-border-radius-base);
|
|
345
|
+
|
|
346
|
+
/* Typography */
|
|
347
|
+
--text-xs: var(--ax-sys-text-xs-base);
|
|
348
|
+
--text-sm: var(--ax-sys-text-sm-base);
|
|
349
|
+
--text-base: var(--ax-sys-body-font-size);
|
|
350
|
+
--text-lg: var(--ax-sys-text-lg-base);
|
|
351
|
+
--text-xl: var(--ax-sys-text-xl-base);
|
|
352
|
+
|
|
353
|
+
/* Line Heights */
|
|
354
|
+
--leading-3: var(--ax-sys-leading-3-base);
|
|
355
|
+
--leading-4: var(--ax-sys-leading-4-base);
|
|
356
|
+
--leading-5: var(--ax-sys-leading-5-base);
|
|
357
|
+
--leading-6: var(--ax-sys-leading-6-base);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
@utility ax-lg {
|
|
361
|
+
/* Spacing */
|
|
362
|
+
--spacing: calc(var(--ax-sys-spacing-base) * 1.25);
|
|
363
|
+
--ax-sys-border-radius: calc(var(--ax-sys-border-radius-base) * 1.25);
|
|
364
|
+
|
|
365
|
+
/* Typography */
|
|
366
|
+
--text-xs: calc(var(--ax-sys-text-xs-base) * 13 / 12);
|
|
367
|
+
--text-sm: calc(var(--ax-sys-text-sm-base) * 15 / 14);
|
|
368
|
+
--text-base: calc(var(--ax-sys-body-font-size) * 17 / 16);
|
|
369
|
+
--text-lg: calc(var(--ax-sys-text-lg-base) * 10 / 9);
|
|
370
|
+
--text-xl: calc(var(--ax-sys-text-xl-base) * 1.1);
|
|
371
|
+
|
|
372
|
+
/* Line Heights */
|
|
373
|
+
--leading-3: calc(var(--ax-sys-leading-3-base) * 4 / 3);
|
|
374
|
+
--leading-4: calc(var(--ax-sys-leading-4-base) * 1.125);
|
|
375
|
+
--leading-5: calc(var(--ax-sys-leading-5-base) * 1.1);
|
|
376
|
+
--leading-6: calc(var(--ax-sys-leading-6-base) * 13 / 12);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
@utility ax-xl {
|
|
380
|
+
/* Spacing */
|
|
381
|
+
--spacing: calc(var(--ax-sys-spacing-base) * 1.5);
|
|
382
|
+
--ax-sys-border-radius: calc(var(--ax-sys-border-radius-base) * 1.5);
|
|
383
|
+
|
|
384
|
+
/* Typography */
|
|
385
|
+
--text-xs: calc(var(--ax-sys-text-xs-base) * 7 / 6);
|
|
386
|
+
--text-sm: calc(var(--ax-sys-text-sm-base) * 8 / 7);
|
|
387
|
+
--text-base: calc(var(--ax-sys-body-font-size) * 1.125);
|
|
388
|
+
--text-lg: calc(var(--ax-sys-text-lg-base) * 11 / 9);
|
|
389
|
+
--text-xl: calc(var(--ax-sys-text-xl-base) * 1.2);
|
|
390
|
+
|
|
391
|
+
/* Line Heights */
|
|
392
|
+
--leading-3: calc(var(--ax-sys-leading-3-base) * 1.5);
|
|
393
|
+
--leading-4: calc(var(--ax-sys-leading-4-base) * 1.25);
|
|
394
|
+
--leading-5: calc(var(--ax-sys-leading-5-base) * 1.2);
|
|
395
|
+
--leading-6: calc(var(--ax-sys-leading-6-base) * 7 / 6);
|
|
396
|
+
}
|
|
397
|
+
`;
|
|
398
|
+
const SHADE_KEYS = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950'];
|
|
399
|
+
function roleSectionTitle(role) {
|
|
400
|
+
if (role === 'accent')
|
|
401
|
+
return 'Accent Surfaces';
|
|
402
|
+
const accentN = /^accent(\d+)$/.exec(role);
|
|
403
|
+
if (accentN?.[1])
|
|
404
|
+
return `Accent ${accentN[1]} Surfaces`;
|
|
405
|
+
return `${role.charAt(0).toUpperCase()}${role.slice(1)} Surfaces`;
|
|
406
|
+
}
|
|
407
|
+
/** @theme semantic lines for neutral UI surfaces (matches default.css) */
|
|
408
|
+
function neutralThemeSemanticBlock(options) {
|
|
409
|
+
let css = `\n`;
|
|
410
|
+
css += ` --color-lightest: rgba(var(--ax-sys-color-lightest-surface));\n`;
|
|
411
|
+
css += ` --color-on-lightest: rgba(var(--ax-sys-color-on-lightest-surface));\n`;
|
|
412
|
+
css += ` --color-border-lightest: rgba(var(--ax-sys-color-border-lightest-surface));\n`;
|
|
413
|
+
css += ` --color-lighter: rgba(var(--ax-sys-color-lighter-surface));\n`;
|
|
414
|
+
css += ` --color-on-lighter: rgba(var(--ax-sys-color-on-lighter-surface));\n`;
|
|
415
|
+
css += ` --color-border-lighter: rgba(var(--ax-sys-color-border-lighter-surface));\n`;
|
|
416
|
+
css += ` --color-light: rgba(var(--ax-sys-color-light-surface));\n`;
|
|
417
|
+
css += ` --color-on-light: rgba(var(--ax-sys-color-on-light-surface));\n`;
|
|
418
|
+
css += ` --color-border-light: rgba(var(--ax-sys-color-border-light-surface));\n`;
|
|
419
|
+
if (!options?.omitDuplicateSurfaceLine) {
|
|
420
|
+
css += ` --color-surface: rgba(var(--ax-sys-color-surface));\n`;
|
|
421
|
+
}
|
|
422
|
+
css += ` --color-on-surface: rgba(var(--ax-sys-color-on-surface));\n`;
|
|
423
|
+
css += ` --color-border-surface: rgba(var(--ax-sys-color-border-surface));\n`;
|
|
424
|
+
css += ` --color-dark: rgba(var(--ax-sys-color-dark-surface));\n`;
|
|
425
|
+
css += ` --color-on-dark: rgba(var(--ax-sys-color-on-dark-surface));\n`;
|
|
426
|
+
css += ` --color-border-dark: rgba(var(--ax-sys-color-border-dark-surface));\n`;
|
|
427
|
+
css += ` --color-darker: rgba(var(--ax-sys-color-darker-surface));\n`;
|
|
428
|
+
css += ` --color-on-darker: rgba(var(--ax-sys-color-on-darker-surface));\n`;
|
|
429
|
+
css += ` --color-border-darker: rgba(var(--ax-sys-color-border-darker-surface));\n`;
|
|
430
|
+
css += ` --color-darkest: rgba(var(--ax-sys-color-darkest-surface));\n`;
|
|
431
|
+
css += ` --color-on-darkest: rgba(var(--ax-sys-color-on-darkest-surface));\n`;
|
|
432
|
+
css += ` --color-border-darkest: rgba(var(--ax-sys-color-border-darkest-surface));\n`;
|
|
433
|
+
return css;
|
|
434
|
+
}
|
|
435
|
+
/** Matches default.css `@theme inline` block per palette role (ordering and duplicate `--color-{role}` lines). */
|
|
436
|
+
function themeNumericAndSemanticForRole(role, options) {
|
|
437
|
+
let css = ` /* ${roleSectionTitle(role)} */\n`;
|
|
438
|
+
css += ` --color-${role}: rgba(var(--ax-sys-color-${role}-surface));\n`;
|
|
439
|
+
for (const shade of SHADE_KEYS) {
|
|
440
|
+
css += ` --color-${role}-${shade}: rgba(var(--ax-sys-color-${role}-${shade}));\n`;
|
|
441
|
+
}
|
|
442
|
+
css += `\n`;
|
|
443
|
+
const emitTriplet = (level) => {
|
|
444
|
+
css += ` --color-${role}-${level}: rgba(var(--ax-sys-color-${role}-${level}-surface));\n`;
|
|
445
|
+
css += ` --color-on-${role}-${level}: rgba(var(--ax-sys-color-on-${role}-${level}-surface));\n`;
|
|
446
|
+
css += ` --color-border-${role}-${level}: rgba(var(--ax-sys-color-border-${role}-${level}-surface));\n`;
|
|
447
|
+
};
|
|
448
|
+
emitTriplet('lightest');
|
|
449
|
+
emitTriplet('lighter');
|
|
450
|
+
emitTriplet('light');
|
|
451
|
+
if (!options?.omitMiddleRoleSurfaceColorDup) {
|
|
452
|
+
css += ` --color-${role}: rgba(var(--ax-sys-color-${role}-surface));\n`;
|
|
453
|
+
}
|
|
454
|
+
css += ` --color-on-${role}: rgba(var(--ax-sys-color-on-${role}-surface));\n`;
|
|
455
|
+
css += ` --color-border-${role}: rgba(var(--ax-sys-color-border-${role}-surface));\n`;
|
|
456
|
+
emitTriplet('dark');
|
|
457
|
+
emitTriplet('darker');
|
|
458
|
+
emitTriplet('darkest');
|
|
459
|
+
const last = EXPORT_TAIL_THEME_PALETTE_ORDER[EXPORT_TAIL_THEME_PALETTE_ORDER.length - 1];
|
|
460
|
+
if (role !== last)
|
|
461
|
+
css += `\n`;
|
|
462
|
+
return css;
|
|
463
|
+
}
|
|
464
|
+
/** Surface scale (--color-surface-50…) at top of @theme */
|
|
465
|
+
function themeSurfaceScaleBlock() {
|
|
466
|
+
let css = ` /* Surface Surfaces */\n`;
|
|
467
|
+
css += ` --color-surface: rgba(var(--ax-sys-color-surface));\n`;
|
|
468
|
+
for (const shade of SHADE_KEYS) {
|
|
469
|
+
css += ` --color-surface-${shade}: rgba(var(--ax-sys-color-surface-${shade}));\n`;
|
|
470
|
+
}
|
|
471
|
+
css += `\n`;
|
|
472
|
+
return css;
|
|
473
|
+
}
|
|
474
|
+
function utilitiesPrefixBlock() {
|
|
475
|
+
return `@utility bg-default {
|
|
476
|
+
background-color: var(--color-bg-default);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
@utility text-default {
|
|
480
|
+
color: var(--color-text-default);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
@utility border-default {
|
|
484
|
+
border-color: var(--color-border-default);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
@utility text {
|
|
488
|
+
color: var(--color-text-default);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
@utility border-s-default {
|
|
492
|
+
border-inline-start-width: 1px;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
@utility border-e-default {
|
|
496
|
+
border-inline-end-width: 1px;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
@utility border-t-default {
|
|
500
|
+
border-top-width: 1px;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
@utility border-b-default {
|
|
504
|
+
border-bottom-width: 1px;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
@utility border-x-default {
|
|
508
|
+
border-left-width: 1px;
|
|
509
|
+
border-right-width: 1px;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
@utility border-y-default {
|
|
513
|
+
border-top-width: 1px;
|
|
514
|
+
border-bottom-width: 1px;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
`;
|
|
518
|
+
}
|
|
519
|
+
function utilityClassName(role, level) {
|
|
520
|
+
return level === 'surface' ? `${role}-surface` : `${role}-${level}-surface`;
|
|
521
|
+
}
|
|
522
|
+
/** Background / foreground / border for one semantic level */
|
|
523
|
+
function cssTripletVars(role, level) {
|
|
524
|
+
if (level === 'surface') {
|
|
525
|
+
return {
|
|
526
|
+
bg: `var(--color-${role})`,
|
|
527
|
+
fg: `var(--color-on-${role})`,
|
|
528
|
+
bd: `var(--color-border-${role})`,
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
bg: `var(--color-${role}-${level})`,
|
|
533
|
+
fg: `var(--color-on-${role}-${level})`,
|
|
534
|
+
bd: `var(--color-border-${role}-${level})`,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
const AX_DARK_THEME_ALIAS_COMMENT = `/*
|
|
538
|
+
* Re-declare every Tailwind theme color alias for the \`.ax-dark\` subtree.
|
|
539
|
+
* \`@theme inline\` resolves inner \`var(--ax-sys-*)\` at :root; this block recomputes \`--color-*\`
|
|
540
|
+
* on \`.ax-dark\` so localized dark regions track updated primitives.
|
|
541
|
+
* Static tokens (\`--radius-default\`, breakpoints) are omitted — same rationale as default.css.
|
|
542
|
+
*/
|
|
543
|
+
|
|
544
|
+
`;
|
|
545
|
+
const AX_LIGHT_SUBTREE_COMMENT = `/*
|
|
546
|
+
* Re-declare light theme primitives and Tailwind color aliases for the \`.ax-light\` subtree.
|
|
547
|
+
* Mirrors the \`.ax-dark\` override pattern so localized light zones work inside a dark page.
|
|
548
|
+
*/
|
|
549
|
+
|
|
550
|
+
`;
|
|
551
|
+
/** Shared \`--color-*\` alias body for \`@theme inline\`, \`.ax-dark .ax-light\`, and \`.ax-dark\` alias blocks. */
|
|
552
|
+
function buildThemeColorAliasesBody(options) {
|
|
553
|
+
let css = ` --color-bg-default: rgba(var(--ax-sys-color-bg-default));\n`;
|
|
554
|
+
css += ` --color-text-default: rgba(var(--ax-sys-color-text-default));\n`;
|
|
555
|
+
css += ` --color-border-default: rgba(var(--ax-sys-color-border-default));\n\n`;
|
|
556
|
+
css += themeSurfaceScaleBlock();
|
|
557
|
+
css += neutralThemeSemanticBlock({ omitDuplicateSurfaceLine: options?.omitDuplicateSurfaceLine });
|
|
558
|
+
for (const role of EXPORT_TAIL_THEME_PALETTE_ORDER) {
|
|
559
|
+
css += themeNumericAndSemanticForRole(role, {
|
|
560
|
+
omitMiddleRoleSurfaceColorDup: options?.omitMiddleRoleSurfaceColorDup,
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
return css;
|
|
564
|
+
}
|
|
565
|
+
function buildAxDarkThemeColorAliases() {
|
|
566
|
+
let css = AX_DARK_THEME_ALIAS_COMMENT;
|
|
567
|
+
css += `.ax-dark {\n`;
|
|
568
|
+
css += ` --ax-sys-theme-isDark: 1;\n`;
|
|
569
|
+
css += buildThemeColorAliasesBody({
|
|
570
|
+
omitMiddleRoleSurfaceColorDup: true,
|
|
571
|
+
omitDuplicateSurfaceLine: true,
|
|
572
|
+
});
|
|
573
|
+
css += `}\n\n`;
|
|
574
|
+
return css;
|
|
575
|
+
}
|
|
576
|
+
/** Light subtree inside a dark page — primitives are generated from the light palette in ThemeBuilderService. */
|
|
577
|
+
function buildAxLightSubtreeBlock(primitivesCss) {
|
|
578
|
+
let css = AX_LIGHT_SUBTREE_COMMENT;
|
|
579
|
+
css += `.ax-dark .ax-light {\n`;
|
|
580
|
+
css += ` --ax-sys-theme-isDark: 0;\n`;
|
|
581
|
+
css += ` --ax-sys-scroller-track-color: rgba(var(--ax-sys-color-light-surface));\n`;
|
|
582
|
+
css += ` --ax-sys-scroller-thumb-color: rgba(var(--ax-sys-color-darkest-surface));\n\n`;
|
|
583
|
+
css += primitivesCss;
|
|
584
|
+
css += buildThemeColorAliasesBody({
|
|
585
|
+
omitMiddleRoleSurfaceColorDup: true,
|
|
586
|
+
omitDuplicateSurfaceLine: true,
|
|
587
|
+
});
|
|
588
|
+
css += `}\n\n`;
|
|
589
|
+
return css;
|
|
590
|
+
}
|
|
591
|
+
function compoundSurfaceUtilities(role) {
|
|
592
|
+
let css = `/* ${roleSectionTitle(role)} */\n\n`;
|
|
593
|
+
for (const level of SEMANTIC_LEVELS) {
|
|
594
|
+
const name = utilityClassName(role, level);
|
|
595
|
+
const { bg, fg, bd } = cssTripletVars(role, level);
|
|
596
|
+
css += `@utility ${name} {
|
|
597
|
+
background-color: ${bg};
|
|
598
|
+
color: ${fg};
|
|
599
|
+
border-color: ${bd};
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
`;
|
|
603
|
+
}
|
|
604
|
+
css += `@utility ax-${role} {\n`;
|
|
605
|
+
for (const level of SEMANTIC_LEVELS) {
|
|
606
|
+
const suf = level === 'surface' ? '' : `-${level}`;
|
|
607
|
+
const refs = cssTripletVars(role, level);
|
|
608
|
+
css += ` --ax-comp-bg${suf}: ${refs.bg};\n`;
|
|
609
|
+
css += ` --ax-comp-text${suf}: ${refs.fg};\n`;
|
|
610
|
+
css += ` --ax-comp-border${suf}: ${refs.bd};\n`;
|
|
611
|
+
}
|
|
612
|
+
css += ` --ax-comp-ink: var(--color-${role});\n`;
|
|
613
|
+
css += ` --ax-comp-ink-dark: var(--color-${role}-dark);\n`;
|
|
614
|
+
css += ` --ax-comp-ink-darker: var(--color-${role}-darker);\n`;
|
|
615
|
+
css += ` --ax-comp-edge: var(--color-${role});\n`;
|
|
616
|
+
css += ` --ax-comp-edge-dark: var(--color-${role}-dark);\n`;
|
|
617
|
+
css += ` --ax-comp-edge-darker: var(--color-${role}-darker);\n`;
|
|
618
|
+
css += `}
|
|
619
|
+
|
|
620
|
+
`;
|
|
621
|
+
return css;
|
|
622
|
+
}
|
|
623
|
+
/** Neutral lightest … darkest utilities (between Danger and Accent in default.css) */
|
|
624
|
+
function neutralCompoundSurfaceUtilities() {
|
|
625
|
+
return `/* Surface Surfaces */
|
|
626
|
+
|
|
627
|
+
@utility lightest-surface {
|
|
628
|
+
background-color: var(--color-lightest);
|
|
629
|
+
color: var(--color-on-lightest);
|
|
630
|
+
border-color: var(--color-border-lightest);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
@utility lighter-surface {
|
|
634
|
+
background-color: var(--color-lighter);
|
|
635
|
+
color: var(--color-on-lighter);
|
|
636
|
+
border-color: var(--color-border-lighter);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
@utility light-surface {
|
|
640
|
+
background-color: var(--color-light);
|
|
641
|
+
color: var(--color-on-light);
|
|
642
|
+
border-color: var(--color-border-light);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
@utility surface {
|
|
646
|
+
background-color: var(--color-surface);
|
|
647
|
+
color: var(--color-on-surface);
|
|
648
|
+
border-color: var(--color-border-surface);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
@utility dark-surface {
|
|
652
|
+
background-color: var(--color-dark);
|
|
653
|
+
color: var(--color-on-dark);
|
|
654
|
+
border-color: var(--color-border-dark);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
@utility darker-surface {
|
|
658
|
+
background-color: var(--color-darker);
|
|
659
|
+
color: var(--color-on-darker);
|
|
660
|
+
border-color: var(--color-border-darker);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
@utility darkest-surface {
|
|
664
|
+
background-color: var(--color-darkest);
|
|
665
|
+
color: var(--color-on-darkest);
|
|
666
|
+
border-color: var(--color-border-darkest);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
@utility ax-surface {
|
|
670
|
+
--ax-comp-bg-lightest: var(--color-light);
|
|
671
|
+
--ax-comp-text-lightest: var(--color-on-light);
|
|
672
|
+
--ax-comp-border-lightest: var(--color-border-light);
|
|
673
|
+
--ax-comp-bg-lighter: var(--color-surface);
|
|
674
|
+
--ax-comp-text-lighter: var(--color-on-surface);
|
|
675
|
+
--ax-comp-border-lighter: var(--color-border-surface);
|
|
676
|
+
--ax-comp-bg-light: var(--color-dark);
|
|
677
|
+
--ax-comp-text-light: var(--color-on-dark);
|
|
678
|
+
--ax-comp-border-light: var(--color-border-dark);
|
|
679
|
+
--ax-comp-bg: var(--color-surface);
|
|
680
|
+
--ax-comp-text: var(--color-on-surface);
|
|
681
|
+
--ax-comp-border: var(--color-border-surface);
|
|
682
|
+
--ax-comp-bg-dark: var(--color-dark);
|
|
683
|
+
--ax-comp-text-dark: var(--color-on-dark);
|
|
684
|
+
--ax-comp-border-dark: var(--color-border-dark);
|
|
685
|
+
--ax-comp-bg-darker: var(--color-darker);
|
|
686
|
+
--ax-comp-text-darker: var(--color-on-darker);
|
|
687
|
+
--ax-comp-border-darker: var(--color-border-darker);
|
|
688
|
+
--ax-comp-bg-darkest: var(--color-darkest);
|
|
689
|
+
--ax-comp-text-darkest: var(--color-on-darkest);
|
|
690
|
+
--ax-comp-border-darkest: var(--color-border-darkest);
|
|
691
|
+
--ax-comp-ink: var(--color-on-surface);
|
|
692
|
+
--ax-comp-ink-dark: var(--color-on-dark);
|
|
693
|
+
--ax-comp-ink-darker: var(--color-on-darker);
|
|
694
|
+
--ax-comp-edge: var(--color-border-surface);
|
|
695
|
+
--ax-comp-edge-dark: var(--color-border-dark);
|
|
696
|
+
--ax-comp-edge-darker: var(--color-border-darker);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
`;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Tailwind \`--color-*\` aliases for theme-builder live preview.
|
|
703
|
+
* Recomputes against container-scoped \`--ax-sys-color-*\` (same roles as default.css \`@theme inline\`).
|
|
704
|
+
*/
|
|
705
|
+
function buildPreviewThemeColorAliases() {
|
|
706
|
+
let css = ` --color-bg-default: rgba(var(--ax-sys-color-bg-default));\n`;
|
|
707
|
+
css += ` --color-text-default: rgba(var(--ax-sys-color-text-default));\n`;
|
|
708
|
+
css += ` --color-border-default: rgba(var(--ax-sys-color-border-default));\n`;
|
|
709
|
+
css += neutralThemeSemanticBlock();
|
|
710
|
+
for (const role of EXPORT_TAIL_THEME_PALETTE_ORDER) {
|
|
711
|
+
css += ` --color-${role}: rgba(var(--ax-sys-color-${role}-surface));\n`;
|
|
712
|
+
css += ` --color-on-${role}: rgba(var(--ax-sys-color-on-${role}-surface));\n`;
|
|
713
|
+
css += ` --color-border-${role}: rgba(var(--ax-sys-color-border-${role}-surface));\n`;
|
|
714
|
+
}
|
|
715
|
+
return css;
|
|
716
|
+
}
|
|
717
|
+
function buildDefaultThemeCssTailLikePackage(axLightPrimitives) {
|
|
718
|
+
let css = `@theme inline {
|
|
719
|
+
--color-bg-default: rgba(var(--ax-sys-color-bg-default));
|
|
720
|
+
--color-text-default: rgba(var(--ax-sys-color-text-default));
|
|
721
|
+
--color-border-default: rgba(var(--ax-sys-color-border-default));
|
|
722
|
+
--radius-default: var(--ax-sys-border-radius);
|
|
723
|
+
--breakpoint-3xl: 1920px;
|
|
724
|
+
--breakpoint-4xl: 2560px;
|
|
725
|
+
`;
|
|
726
|
+
css += themeSurfaceScaleBlock();
|
|
727
|
+
css += neutralThemeSemanticBlock();
|
|
728
|
+
for (const role of EXPORT_TAIL_THEME_PALETTE_ORDER) {
|
|
729
|
+
css += themeNumericAndSemanticForRole(role);
|
|
730
|
+
}
|
|
731
|
+
css += buildDefaultTailwindScaleBlock('theme');
|
|
732
|
+
css += `}
|
|
733
|
+
|
|
734
|
+
`;
|
|
735
|
+
if (axLightPrimitives) {
|
|
736
|
+
css += buildAxLightSubtreeBlock(axLightPrimitives);
|
|
737
|
+
}
|
|
738
|
+
css += buildAxDarkThemeColorAliases();
|
|
739
|
+
css += utilitiesPrefixBlock();
|
|
740
|
+
for (const role of EXPORT_TAIL_THEME_PALETTE_ORDER) {
|
|
741
|
+
if (role.startsWith('accent'))
|
|
742
|
+
continue;
|
|
743
|
+
css += compoundSurfaceUtilities(role);
|
|
744
|
+
}
|
|
745
|
+
css += neutralCompoundSurfaceUtilities();
|
|
746
|
+
for (const role of EXPORT_TAIL_THEME_PALETTE_ORDER) {
|
|
747
|
+
if (role.startsWith('accent')) {
|
|
748
|
+
css += compoundSurfaceUtilities(role);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
css += THEME_TAIL_VERBATIM_FOOTER;
|
|
752
|
+
return css;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
const AX_THEME_SHADES = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];
|
|
756
|
+
const ROLE_SURFACE_SHADE_MAP = {
|
|
757
|
+
'lightest-surface': 100,
|
|
758
|
+
'lighter-surface': 200,
|
|
759
|
+
'light-surface': 300,
|
|
760
|
+
surface: 500,
|
|
761
|
+
'dark-surface': 600,
|
|
762
|
+
'darker-surface': 700,
|
|
763
|
+
'darkest-surface': 800,
|
|
764
|
+
};
|
|
765
|
+
const toOklch = culori.converter('oklch');
|
|
766
|
+
const toRgb = culori.converter('rgb');
|
|
767
|
+
const toHsl = culori.converter('hsl');
|
|
768
|
+
const toGamut = culori.toGamut('rgb');
|
|
769
|
+
const lightSurfaceColors = {
|
|
770
|
+
'lightest-surface': { bg: '255, 255, 255', on: '10, 10, 10', border: '233, 233, 233' },
|
|
771
|
+
'lighter-surface': { bg: '250, 250, 250', on: '10, 10, 10', border: '228, 228, 228' },
|
|
772
|
+
'light-surface': { bg: '245, 245, 245', on: '10, 10, 10', border: '223, 223, 223' },
|
|
773
|
+
surface: { bg: '240, 240, 241', on: '10, 10, 10', border: '218, 218, 218' },
|
|
774
|
+
'dark-surface': { bg: '235, 235, 236', on: '10, 10, 10', border: '213, 213, 213' },
|
|
775
|
+
'darker-surface': { bg: '230, 230, 231', on: '10, 10, 10', border: '208, 208, 208' },
|
|
776
|
+
'darkest-surface': { bg: '224, 224, 225', on: '10, 10, 10', border: '202, 202, 202' },
|
|
777
|
+
};
|
|
778
|
+
const darkSurfaceColors = {
|
|
779
|
+
'lightest-surface': { bg: '56, 56, 56', on: '245, 245, 245', border: '64, 64, 64' },
|
|
780
|
+
'lighter-surface': { bg: '49, 49, 49', on: '245, 245, 245', border: '56, 56, 56' },
|
|
781
|
+
'light-surface': { bg: '42, 42, 42', on: '245, 245, 245', border: '50, 50, 50' },
|
|
782
|
+
surface: { bg: '33, 33, 33', on: '245, 245, 245', border: '44, 44, 44' },
|
|
783
|
+
'dark-surface': { bg: '27, 27, 27', on: '245, 245, 245', border: '38, 38, 38' },
|
|
784
|
+
'darker-surface': { bg: '20, 20, 20', on: '245, 245, 245', border: '32, 32, 32' },
|
|
785
|
+
'darkest-surface': { bg: '10, 10, 10', on: '245, 245, 245', border: '28, 28, 28' },
|
|
786
|
+
};
|
|
787
|
+
const DEFAULT_EXPORT_SEEDS_LIGHT = {
|
|
788
|
+
primary: 'rgb(43, 127, 255)',
|
|
789
|
+
secondary: 'rgb(106, 114, 130)',
|
|
790
|
+
success: 'rgb(0, 188, 125)',
|
|
791
|
+
warning: 'rgb(253, 154, 0)',
|
|
792
|
+
danger: 'rgb(255, 32, 86)',
|
|
793
|
+
surface: 'rgb(194, 194, 194)',
|
|
794
|
+
accent: 'rgb(6, 182, 212)',
|
|
795
|
+
accent1: 'rgb(217, 70, 239)',
|
|
796
|
+
accent2: 'rgb(249, 115, 22)',
|
|
797
|
+
accent3: 'rgb(20, 184, 166)',
|
|
798
|
+
accent4: 'rgb(99, 102, 241)',
|
|
799
|
+
accent5: 'rgb(236, 72, 153)',
|
|
800
|
+
accent6: 'rgb(120, 113, 108)',
|
|
801
|
+
};
|
|
802
|
+
const DEFAULT_EXPORT_SEEDS_DARK = {
|
|
803
|
+
primary: 'rgb(43, 127, 255)',
|
|
804
|
+
secondary: 'rgb(153, 161, 175)',
|
|
805
|
+
success: 'rgb(0, 188, 125)',
|
|
806
|
+
warning: 'rgb(253, 154, 0)',
|
|
807
|
+
danger: 'rgb(255, 99, 126)',
|
|
808
|
+
surface: 'rgb(33, 33, 33)',
|
|
809
|
+
accent: 'rgb(6, 182, 212)',
|
|
810
|
+
accent1: 'rgb(217, 70, 239)',
|
|
811
|
+
accent2: 'rgb(249, 115, 22)',
|
|
812
|
+
accent3: 'rgb(20, 184, 166)',
|
|
813
|
+
accent4: 'rgb(99, 102, 241)',
|
|
814
|
+
accent5: 'rgb(236, 72, 153)',
|
|
815
|
+
accent6: 'rgb(120, 113, 108)',
|
|
816
|
+
};
|
|
817
|
+
const THEME_CSS_PREAMBLE = `@import 'tailwindcss';
|
|
818
|
+
@import 'tw-animate';
|
|
819
|
+
|
|
820
|
+
@custom-variant dark (&:where(.ax-dark, .ax-dark *):not(:where(.ax-light, .ax-light *)));
|
|
821
|
+
@custom-variant hover (&:hover);
|
|
822
|
+
|
|
823
|
+
input:-webkit-autofill,
|
|
824
|
+
input:-webkit-autofill:hover,
|
|
825
|
+
input:-webkit-autofill:focus,
|
|
826
|
+
textarea:-webkit-autofill,
|
|
827
|
+
select:-webkit-autofill {
|
|
828
|
+
-webkit-box-shadow: 0 0 0 1000px transparent inset !important;
|
|
829
|
+
-webkit-text-fill-color: inherit !important;
|
|
830
|
+
transition: background-color 9999s ease-in-out 0s;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
@layer base {
|
|
834
|
+
* {
|
|
835
|
+
border-color: var(--color-border-default);
|
|
836
|
+
scrollbar-width: thin;
|
|
837
|
+
scrollbar-color: var(--ax-sys-scroller-thumb-color) var(--ax-sys-scroller-track-color);
|
|
838
|
+
|
|
839
|
+
::-webkit-scrollbar {
|
|
840
|
+
width: var(--ax-sys-scroller-size);
|
|
841
|
+
height: var(--ax-sys-scroller-size);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
::-webkit-scrollbar-track {
|
|
845
|
+
background: var(--ax-sys-scroller-track-color);
|
|
846
|
+
border-radius: var(--ax-sys-scroller-size-radius);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
::-webkit-scrollbar-thumb {
|
|
850
|
+
background: var(--ax-sys-scroller-thumb-color);
|
|
851
|
+
border-radius: var(--ax-sys-scroller-size-radius);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
html {
|
|
857
|
+
background-color: rgba(var(--ax-sys-color-lightest-surface));
|
|
858
|
+
color: rgba(var(--ax-sys-color-on-lightest-surface));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
html.ax-dark {
|
|
862
|
+
background-color: rgba(var(--ax-sys-color-darkest-surface));
|
|
863
|
+
color: rgba(var(--ax-sys-color-on-darkest-surface));
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
`;
|
|
867
|
+
/** Size scope classes before \`:root\` (matches default.css). */
|
|
868
|
+
const THEME_SIZE_SCOPE_CLASSES = `.ax-xs {
|
|
869
|
+
--ax-sys-size: ax-xs;
|
|
870
|
+
}
|
|
871
|
+
.ax-sm {
|
|
872
|
+
--ax-sys-size: ax-sm;
|
|
873
|
+
}
|
|
874
|
+
.ax-md {
|
|
875
|
+
--ax-sys-size: ax-md;
|
|
876
|
+
}
|
|
877
|
+
.ax-lg {
|
|
878
|
+
--ax-sys-size: ax-lg;
|
|
879
|
+
}
|
|
880
|
+
.ax-xl {
|
|
881
|
+
--ax-sys-size: ax-xl;
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
`;
|
|
885
|
+
const THEME_EXPORT_ROOT_METADATA = `:root {
|
|
886
|
+
--ax-sys-theme-isDark: 0;
|
|
887
|
+
--ax-sys-icon-size: 100%;
|
|
888
|
+
--ax-sys-icon-weight: 400;
|
|
889
|
+
--ax-sys-size-base: 2.5rem;
|
|
890
|
+
--ax-overlay-full-width: 93;
|
|
891
|
+
--ax-sys-icon-width: inherit;
|
|
892
|
+
--ax-sys-icon-height: inherit;
|
|
893
|
+
--ax-sys-body-font-size: 1rem;
|
|
894
|
+
--ax-sys-border-radius-base: 0.5rem;
|
|
895
|
+
--ax-sys-spacing-base: 0.25rem;
|
|
896
|
+
--ax-sys-text-xs-base: 0.75rem;
|
|
897
|
+
--ax-sys-text-sm-base: 0.875rem;
|
|
898
|
+
--ax-sys-text-lg-base: 1.125rem;
|
|
899
|
+
--ax-sys-text-xl-base: 1.25rem;
|
|
900
|
+
--ax-sys-leading-3-base: 0.75rem;
|
|
901
|
+
--ax-sys-leading-4-base: 1rem;
|
|
902
|
+
--ax-sys-leading-5-base: 1.25rem;
|
|
903
|
+
--ax-sys-leading-6-base: 1.5rem;
|
|
904
|
+
|
|
905
|
+
${buildDefaultTailwindScaleBlock('root')} --ax-sys-border-radius: var(--ax-sys-border-radius-base);
|
|
906
|
+
--ax-sys-transition-duration: 150ms;
|
|
907
|
+
--ax-sys-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
908
|
+
|
|
909
|
+
--ax-sys-scroller-size: 5px;
|
|
910
|
+
--ax-sys-scroller-size-radius: 3px;
|
|
911
|
+
--ax-sys-scroller-track-color: rgba(var(--ax-sys-color-light-surface));
|
|
912
|
+
--ax-sys-scroller-thumb-color: rgba(var(--ax-sys-color-darkest-surface));
|
|
913
|
+
|
|
914
|
+
`;
|
|
915
|
+
function generateLightPalette(seedHex) {
|
|
916
|
+
const shadeValueMap = {
|
|
917
|
+
50: 40,
|
|
918
|
+
100: 90,
|
|
919
|
+
200: 160,
|
|
920
|
+
300: 270,
|
|
921
|
+
400: 410,
|
|
922
|
+
500: 500,
|
|
923
|
+
600: 590,
|
|
924
|
+
700: 700,
|
|
925
|
+
800: 790,
|
|
926
|
+
900: 860,
|
|
927
|
+
950: 1060,
|
|
928
|
+
};
|
|
929
|
+
const initialColor = toOklch(normalizeCssColor(seedHex));
|
|
930
|
+
if (!initialColor)
|
|
931
|
+
return {};
|
|
932
|
+
const { l: initialLightness, c: initialChroma, h: initialHue } = initialColor;
|
|
933
|
+
const lightModeTones = {};
|
|
934
|
+
AX_THEME_SHADES.forEach((shadeKey) => {
|
|
935
|
+
const shadeValue = shadeValueMap[shadeKey];
|
|
936
|
+
if (shadeValue <= 500) {
|
|
937
|
+
lightModeTones[shadeKey] = (-shadeValue + shadeValue * initialLightness + 500) / 500;
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
lightModeTones[shadeKey] = (1 - (shadeValue - 500) / 500) * (initialLightness - 0.3) + 0.3;
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
const lightMode = {};
|
|
944
|
+
AX_THEME_SHADES.forEach((shade) => {
|
|
945
|
+
const oklchColor = {
|
|
946
|
+
l: lightModeTones[shade],
|
|
947
|
+
c: initialChroma,
|
|
948
|
+
h: initialHue ?? 0,
|
|
949
|
+
mode: 'oklch',
|
|
950
|
+
};
|
|
951
|
+
let gamutMappedColor = toGamut(oklchColor) || oklchColor;
|
|
952
|
+
if (shade === 950 || shade === 900 || shade === 800) {
|
|
953
|
+
const oklchGamutMapped = toOklch(gamutMappedColor);
|
|
954
|
+
if (oklchGamutMapped) {
|
|
955
|
+
if (shade === 950) {
|
|
956
|
+
oklchGamutMapped.c *= 1 - 0.5;
|
|
957
|
+
}
|
|
958
|
+
else if (shade === 900) {
|
|
959
|
+
oklchGamutMapped.c *= 1 - 0.33;
|
|
960
|
+
}
|
|
961
|
+
else if (shade === 800) {
|
|
962
|
+
oklchGamutMapped.c *= 1 - 0.08;
|
|
963
|
+
}
|
|
964
|
+
gamutMappedColor = oklchGamutMapped;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
const rgbColor = toRgb(gamutMappedColor);
|
|
968
|
+
if (rgbColor) {
|
|
969
|
+
lightMode[String(shade)] = formatRgbTriplet(rgbColor);
|
|
970
|
+
}
|
|
971
|
+
});
|
|
972
|
+
const color500 = parseRgbTriplet(lightMode['500']);
|
|
973
|
+
if (color500) {
|
|
974
|
+
lightMode['on'] = contrastText(color500, false);
|
|
975
|
+
}
|
|
976
|
+
lightMode['on-contrast'] = lightMode['900'];
|
|
977
|
+
return lightMode;
|
|
978
|
+
}
|
|
979
|
+
function generateDarkPalette(seedHex) {
|
|
980
|
+
const initialColor = toOklch(normalizeCssColor(seedHex));
|
|
981
|
+
if (!initialColor)
|
|
982
|
+
return {};
|
|
983
|
+
const { l: initialLightness, c: initialChroma, h: initialHue } = initialColor;
|
|
984
|
+
const darkModeTones = {};
|
|
985
|
+
AX_THEME_SHADES.forEach((shade) => {
|
|
986
|
+
if (shade <= 700) {
|
|
987
|
+
darkModeTones[shade] = (-shade + shade * initialLightness + 700) / 700;
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
darkModeTones[shade] = (1 - (shade - 700) / 700) * (initialLightness - 0.3) + 0.3;
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
const darkMode = {};
|
|
994
|
+
AX_THEME_SHADES.forEach((shade) => {
|
|
995
|
+
const oklchColor = {
|
|
996
|
+
l: darkModeTones[shade],
|
|
997
|
+
c: initialChroma,
|
|
998
|
+
h: initialHue ?? 0,
|
|
999
|
+
mode: 'oklch',
|
|
1000
|
+
};
|
|
1001
|
+
const gamutMapped = toGamut(oklchColor) || oklchColor;
|
|
1002
|
+
const rgbColor = toRgb(gamutMapped);
|
|
1003
|
+
if (rgbColor) {
|
|
1004
|
+
darkMode[String(shade)] = formatRgbTriplet(rgbColor);
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
const color500 = parseRgbTriplet(darkMode['500']);
|
|
1008
|
+
const color200 = parseRgbTriplet(darkMode['200']);
|
|
1009
|
+
if (color500) {
|
|
1010
|
+
darkMode['on'] = contrastText(color500, true);
|
|
1011
|
+
}
|
|
1012
|
+
if (color200) {
|
|
1013
|
+
darkMode['on-contrast'] = contrastText(color200, true);
|
|
1014
|
+
}
|
|
1015
|
+
return darkMode;
|
|
1016
|
+
}
|
|
1017
|
+
function lightnessCalc(hue) {
|
|
1018
|
+
if (hue <= 80)
|
|
1019
|
+
return 0.06 * hue + 75;
|
|
1020
|
+
if (hue < 270)
|
|
1021
|
+
return -0.07 * hue + 85.82;
|
|
1022
|
+
return 0.09 * hue + 42.6;
|
|
1023
|
+
}
|
|
1024
|
+
function isDarkOnSurface(lightness, hue, isDark) {
|
|
1025
|
+
const threshold = lightnessCalc(hue);
|
|
1026
|
+
if (isDark) {
|
|
1027
|
+
return lightness >= (threshold - 15) / 100;
|
|
1028
|
+
}
|
|
1029
|
+
return lightness >= threshold / 100;
|
|
1030
|
+
}
|
|
1031
|
+
function contrastText(color, isDark) {
|
|
1032
|
+
const oklchColor = toOklch(color);
|
|
1033
|
+
if (!oklchColor)
|
|
1034
|
+
return '0, 0, 0';
|
|
1035
|
+
const { l: oklchLightness, c: chroma, h: hue } = oklchColor;
|
|
1036
|
+
let newLightness;
|
|
1037
|
+
if (isDark) {
|
|
1038
|
+
newLightness = isDarkOnSurface(oklchLightness, hue ?? 0, true) ? 0.2 : 0.995;
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
newLightness = isDarkOnSurface(oklchLightness, hue ?? 0, false) ? 0.3 : 0.995;
|
|
1042
|
+
}
|
|
1043
|
+
const contrastOklch = { l: newLightness, c: chroma, h: hue, mode: 'oklch' };
|
|
1044
|
+
const gamutMapped = toGamut(contrastOklch) || contrastOklch;
|
|
1045
|
+
const finalRgb = toRgb(gamutMapped);
|
|
1046
|
+
return formatRgbTriplet(finalRgb);
|
|
1047
|
+
}
|
|
1048
|
+
function borderColor(color, isDark) {
|
|
1049
|
+
const hslColor = toHsl(color);
|
|
1050
|
+
if (!hslColor)
|
|
1051
|
+
return '0, 0, 0';
|
|
1052
|
+
if (isDark) {
|
|
1053
|
+
hslColor.l += 0.09;
|
|
1054
|
+
}
|
|
1055
|
+
else {
|
|
1056
|
+
hslColor.l -= 0.07;
|
|
1057
|
+
}
|
|
1058
|
+
hslColor.l = Math.max(0, Math.min(1, hslColor.l));
|
|
1059
|
+
const finalRgb = toRgb(hslColor);
|
|
1060
|
+
return formatRgbTriplet(finalRgb);
|
|
1061
|
+
}
|
|
1062
|
+
function parseRgbTriplet(rgbStr) {
|
|
1063
|
+
if (!rgbStr)
|
|
1064
|
+
return undefined;
|
|
1065
|
+
const [r, g, b] = rgbStr.split(',').map(Number);
|
|
1066
|
+
return { mode: 'rgb', r: r / 255, g: g / 255, b: b / 255 };
|
|
1067
|
+
}
|
|
1068
|
+
function formatRgbTriplet(color) {
|
|
1069
|
+
const r = Math.min(255, Math.max(0, Math.round(color.r * 255)));
|
|
1070
|
+
const g = Math.min(255, Math.max(0, Math.round(color.g * 255)));
|
|
1071
|
+
const b = Math.min(255, Math.max(0, Math.round(color.b * 255)));
|
|
1072
|
+
return `${r}, ${g}, ${b}`;
|
|
1073
|
+
}
|
|
1074
|
+
/** Accepts `#hex`, `rgb()`, `rgba()`, named colors … for culori. */
|
|
1075
|
+
function normalizeCssColor(css) {
|
|
1076
|
+
const t = css.trim();
|
|
1077
|
+
const parsed = culori.parse(t);
|
|
1078
|
+
if (!parsed)
|
|
1079
|
+
return t;
|
|
1080
|
+
const hex = culori.formatHex(parsed);
|
|
1081
|
+
return hex ?? t;
|
|
1082
|
+
}
|
|
1083
|
+
/** Neutral UI surfaces for live preview (static values from default.css \`:root\`). */
|
|
1084
|
+
function buildPreviewNeutralSurfaces(isDark) {
|
|
1085
|
+
return buildNeutralRgbVariables(isDark ? darkSurfaceColors : lightSurfaceColors);
|
|
1086
|
+
}
|
|
1087
|
+
/** Default bg/text/border primitives for live preview. */
|
|
1088
|
+
function buildPreviewSemanticDefaults(isDark) {
|
|
1089
|
+
if (isDark) {
|
|
1090
|
+
return (` --ax-sys-color-bg-default: var(--ax-sys-color-darkest-surface);\n` +
|
|
1091
|
+
` --ax-sys-color-text-default: var(--ax-sys-color-on-darkest-surface);\n` +
|
|
1092
|
+
` --ax-sys-color-border-default: var(--ax-sys-color-border-darkest-surface);\n`);
|
|
1093
|
+
}
|
|
1094
|
+
return (` --ax-sys-color-bg-default: var(--ax-sys-color-lightest-surface);\n` +
|
|
1095
|
+
` --ax-sys-color-text-default: var(--ax-sys-color-on-lightest-surface);\n` +
|
|
1096
|
+
` --ax-sys-color-border-default: var(--ax-sys-color-border-lightest-surface);\n`);
|
|
1097
|
+
}
|
|
1098
|
+
function generateCSSForRoles(palette, role) {
|
|
1099
|
+
let css = '\n';
|
|
1100
|
+
Object.entries(palette).forEach(([shade, rgbColor]) => {
|
|
1101
|
+
if (shade === 'on') {
|
|
1102
|
+
css += ` --ax-sys-color-on-${role}: ${rgbColor};\n`;
|
|
1103
|
+
}
|
|
1104
|
+
else if (shade === 'on-contrast') {
|
|
1105
|
+
css += ` --ax-sys-color-on-contrast-${role}: ${rgbColor};\n`;
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
css += ` --ax-sys-color-${role}-${shade}: ${rgbColor};\n`;
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
return css;
|
|
1112
|
+
}
|
|
1113
|
+
/**
|
|
1114
|
+
* Produces CSS aligned with `packages/styles/themes/default.css`: same sections, directives,
|
|
1115
|
+
* `@theme inline`, `.ax-dark .ax-light` / `.ax-dark` color-alias re-declaration, and utility layout.
|
|
1116
|
+
* Only `--ax-sys-color-*` RGB triplets (and thus derived contrasts/borders) differ from the packaged default theme.
|
|
1117
|
+
* Includes all roles in {@link EXPORT_ROOT_ROLE_ORDER}: `accent` plus `accent1`–`accent6`.
|
|
1118
|
+
*/
|
|
1119
|
+
function generateFullThemeCSS(seeds) {
|
|
1120
|
+
const merged = mergeExportSeeds(seeds);
|
|
1121
|
+
const allPalettes = {
|
|
1122
|
+
light: {},
|
|
1123
|
+
dark: {},
|
|
1124
|
+
};
|
|
1125
|
+
for (const role of EXPORT_ROOT_ROLE_ORDER) {
|
|
1126
|
+
allPalettes.light[role] = generateLightPalette(merged.light[role]);
|
|
1127
|
+
allPalettes.dark[role] = generateDarkPalette(merged.dark[role]);
|
|
1128
|
+
}
|
|
1129
|
+
let css = THEME_CSS_PREAMBLE;
|
|
1130
|
+
css += THEME_SIZE_SCOPE_CLASSES;
|
|
1131
|
+
css += THEME_EXPORT_ROOT_METADATA;
|
|
1132
|
+
css += buildNeutralRgbVariables(lightSurfaceColors);
|
|
1133
|
+
css += buildRoleRgbScales(allPalettes.light);
|
|
1134
|
+
css += buildSemanticSurfaceRgbTuples(allPalettes.light, false);
|
|
1135
|
+
css += ` --ax-sys-color-bg-default: var(--ax-sys-color-lightest-surface);\n`;
|
|
1136
|
+
css += ` --ax-sys-color-text-default: var(--ax-sys-color-on-lightest-surface);\n`;
|
|
1137
|
+
css += ` --ax-sys-color-border-default: var(--ax-sys-color-border-lightest-surface);\n`;
|
|
1138
|
+
css += `}\n\n`;
|
|
1139
|
+
css += `.ax-dark {
|
|
1140
|
+
--ax-sys-theme-isDark: 1;
|
|
1141
|
+
--ax-sys-scroller-track-color: rgba(var(--ax-sys-color-darker-surface));
|
|
1142
|
+
--ax-sys-scroller-thumb-color: rgba(var(--ax-sys-color-lightest-surface));
|
|
1143
|
+
|
|
1144
|
+
`;
|
|
1145
|
+
css += buildNeutralRgbVariables(darkSurfaceColors);
|
|
1146
|
+
css += buildRoleRgbScales(allPalettes.dark);
|
|
1147
|
+
css += buildSemanticSurfaceRgbTuples(allPalettes.dark, true);
|
|
1148
|
+
css += ` --ax-sys-color-bg-default: var(--ax-sys-color-darkest-surface);\n`;
|
|
1149
|
+
css += ` --ax-sys-color-text-default: var(--ax-sys-color-on-darkest-surface);\n`;
|
|
1150
|
+
css += ` --ax-sys-color-border-default: var(--ax-sys-color-border-darkest-surface);\n`;
|
|
1151
|
+
css += `}\n\n`;
|
|
1152
|
+
css += buildDefaultThemeCssTailLikePackage(buildAxLightPrimitivesBlock(allPalettes.light));
|
|
1153
|
+
return css;
|
|
1154
|
+
}
|
|
1155
|
+
function buildAxLightPrimitivesBlock(palettes) {
|
|
1156
|
+
let css = buildNeutralRgbVariables(lightSurfaceColors);
|
|
1157
|
+
css += buildRoleRgbScales(palettes);
|
|
1158
|
+
css += buildSemanticSurfaceRgbTuples(palettes, false);
|
|
1159
|
+
css += ` --ax-sys-color-bg-default: var(--ax-sys-color-lightest-surface);\n`;
|
|
1160
|
+
css += ` --ax-sys-color-text-default: var(--ax-sys-color-on-lightest-surface);\n`;
|
|
1161
|
+
css += ` --ax-sys-color-border-default: var(--ax-sys-color-border-lightest-surface);\n\n`;
|
|
1162
|
+
return css;
|
|
1163
|
+
}
|
|
1164
|
+
function mergeExportSeeds(seeds) {
|
|
1165
|
+
const out = {
|
|
1166
|
+
light: { ...DEFAULT_EXPORT_SEEDS_LIGHT },
|
|
1167
|
+
dark: { ...DEFAULT_EXPORT_SEEDS_DARK },
|
|
1168
|
+
};
|
|
1169
|
+
for (const role of EXPORT_ROOT_ROLE_ORDER) {
|
|
1170
|
+
const l = seeds.light[role]?.trim();
|
|
1171
|
+
const d = seeds.dark[role]?.trim();
|
|
1172
|
+
if (l)
|
|
1173
|
+
out.light[role] = l;
|
|
1174
|
+
if (d)
|
|
1175
|
+
out.dark[role] = d;
|
|
1176
|
+
}
|
|
1177
|
+
return out;
|
|
1178
|
+
}
|
|
1179
|
+
function buildNeutralRgbVariables(surfaceColors) {
|
|
1180
|
+
let css = '';
|
|
1181
|
+
for (const [name, colors] of Object.entries(surfaceColors)) {
|
|
1182
|
+
css += ` --ax-sys-color-${name}: ${colors.bg};\n`;
|
|
1183
|
+
css += ` --ax-sys-color-on-${name}: ${colors.on};\n`;
|
|
1184
|
+
css += ` --ax-sys-color-border-${name}: ${colors.border};\n\n`;
|
|
1185
|
+
}
|
|
1186
|
+
return css;
|
|
1187
|
+
}
|
|
1188
|
+
function buildRoleRgbScales(palettes) {
|
|
1189
|
+
let css = '';
|
|
1190
|
+
for (const role of EXPORT_ROOT_ROLE_ORDER) {
|
|
1191
|
+
for (const shade of AX_THEME_SHADES) {
|
|
1192
|
+
const v = palettes[role]?.[String(shade)];
|
|
1193
|
+
if (v) {
|
|
1194
|
+
css += ` --ax-sys-color-${role}-${shade}: ${v};\n`;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
css += `\n`;
|
|
1198
|
+
}
|
|
1199
|
+
return css;
|
|
1200
|
+
}
|
|
1201
|
+
/** Semantic layering (`*-lightest-surface`, …): omitted for grayscale `surface` role (matches default.css). */
|
|
1202
|
+
function buildSemanticSurfaceRgbTuples(palettes, isDark) {
|
|
1203
|
+
const surfaceMap = {
|
|
1204
|
+
'lightest-surface': '100',
|
|
1205
|
+
'lighter-surface': '200',
|
|
1206
|
+
'light-surface': '300',
|
|
1207
|
+
surface: '500',
|
|
1208
|
+
'dark-surface': '600',
|
|
1209
|
+
'darker-surface': '700',
|
|
1210
|
+
'darkest-surface': '800',
|
|
1211
|
+
};
|
|
1212
|
+
let css = '';
|
|
1213
|
+
for (const role of EXPORT_ROOT_ROLE_ORDER) {
|
|
1214
|
+
if (role === 'surface')
|
|
1215
|
+
continue;
|
|
1216
|
+
for (const [surfName, shadeKey] of Object.entries(surfaceMap)) {
|
|
1217
|
+
const surfaceColorStr = palettes[role]?.[shadeKey];
|
|
1218
|
+
const surfaceRgb = surfaceColorStr ? parseRgbTriplet(surfaceColorStr) : undefined;
|
|
1219
|
+
if (surfaceRgb) {
|
|
1220
|
+
const suffix = surfName === 'surface' ? 'surface' : surfName;
|
|
1221
|
+
css += ` --ax-sys-color-${role}-${suffix}: ${surfaceColorStr};\n`;
|
|
1222
|
+
css += ` --ax-sys-color-on-${role}-${suffix}: ${contrastText(surfaceRgb, isDark)};\n`;
|
|
1223
|
+
css += ` --ax-sys-color-border-${role}-${suffix}: ${borderColor(surfaceRgb, isDark)};\n\n`;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
return css;
|
|
1228
|
+
}
|
|
1229
|
+
/** Resolves a flat color map into per-mode seed maps, applying user values to both modes. */
|
|
1230
|
+
function resolveSeedsFromFlat(colors) {
|
|
1231
|
+
const out = {
|
|
1232
|
+
light: { ...DEFAULT_EXPORT_SEEDS_LIGHT },
|
|
1233
|
+
dark: { ...DEFAULT_EXPORT_SEEDS_DARK },
|
|
1234
|
+
};
|
|
1235
|
+
if (!colors) {
|
|
1236
|
+
return out;
|
|
1237
|
+
}
|
|
1238
|
+
for (const role of EXPORT_ROOT_ROLE_ORDER) {
|
|
1239
|
+
const value = colors[role]?.trim();
|
|
1240
|
+
if (value) {
|
|
1241
|
+
out.light[role] = value;
|
|
1242
|
+
out.dark[role] = value;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
return out;
|
|
1246
|
+
}
|
|
1247
|
+
/** Builds full light/dark palettes from resolved per-mode seeds. */
|
|
1248
|
+
function buildFullPalette(seeds, roles) {
|
|
1249
|
+
const roleList = roles ?? [...EXPORT_ROOT_ROLE_ORDER];
|
|
1250
|
+
const palette = {
|
|
1251
|
+
light: {},
|
|
1252
|
+
dark: {},
|
|
1253
|
+
};
|
|
1254
|
+
for (const role of roleList) {
|
|
1255
|
+
palette.light[role] = generateLightPalette(seeds.light[role]);
|
|
1256
|
+
palette.dark[role] = generateDarkPalette(seeds.dark[role]);
|
|
1257
|
+
}
|
|
1258
|
+
return palette;
|
|
1259
|
+
}
|
|
1260
|
+
function buildThemeVariableBlock(mode, variants, roles) {
|
|
1261
|
+
const isDark = mode === 'dark';
|
|
1262
|
+
let css = buildPreviewNeutralSurfaces(isDark);
|
|
1263
|
+
for (const colorName of roles) {
|
|
1264
|
+
const roleVariants = variants[colorName];
|
|
1265
|
+
if (roleVariants) {
|
|
1266
|
+
css += generateCSSForRoles(roleVariants, colorName);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
css += buildSemanticSurfaceColorsForRoles(variants, roles, isDark);
|
|
1270
|
+
css += buildPreviewSemanticDefaults(isDark);
|
|
1271
|
+
css += buildPreviewThemeColorAliases();
|
|
1272
|
+
return css;
|
|
1273
|
+
}
|
|
1274
|
+
function buildSemanticSurfaceColorsForRoles(variants, roles, isDark) {
|
|
1275
|
+
let css = '';
|
|
1276
|
+
for (const role of roles) {
|
|
1277
|
+
if (role === 'surface')
|
|
1278
|
+
continue;
|
|
1279
|
+
const roleVariants = variants[role];
|
|
1280
|
+
for (const [surfaceName, shade] of Object.entries(ROLE_SURFACE_SHADE_MAP)) {
|
|
1281
|
+
const surfaceColorStr = roleVariants?.[String(shade)];
|
|
1282
|
+
const surfaceRgb = surfaceColorStr ? parseRgbTriplet(surfaceColorStr) : undefined;
|
|
1283
|
+
if (surfaceRgb) {
|
|
1284
|
+
css += ` --ax-sys-color-${role}-${surfaceName}: ${surfaceColorStr};\n`;
|
|
1285
|
+
css += ` --ax-sys-color-on-${role}-${surfaceName}: ${contrastText(surfaceRgb, isDark)};\n`;
|
|
1286
|
+
css += ` --ax-sys-color-border-${role}-${surfaceName}: ${borderColor(surfaceRgb, isDark)};\n\n`;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return css;
|
|
1291
|
+
}
|
|
1292
|
+
/** Scoped CSS for live theme preview (variables only, no Tailwind layer). */
|
|
1293
|
+
function buildPreviewThemeCSS(palette, scope, roles) {
|
|
1294
|
+
const roleList = roles ?? [...EXPORT_ROOT_ROLE_ORDER];
|
|
1295
|
+
const lightScope = scope?.light ?? ':root';
|
|
1296
|
+
const darkScope = scope?.dark ?? '.ax-dark';
|
|
1297
|
+
let css = `${lightScope} {\n`;
|
|
1298
|
+
css += buildThemeVariableBlock('light', palette.light, roleList);
|
|
1299
|
+
css += '}\n\n';
|
|
1300
|
+
css += `${darkScope} {\n`;
|
|
1301
|
+
css += buildThemeVariableBlock('dark', palette.dark, roleList);
|
|
1302
|
+
css += '}\n\n';
|
|
1303
|
+
return css;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Creates an ACoreX theme from a flat map of role seed colors.
|
|
1308
|
+
*
|
|
1309
|
+
* Each provided color is applied to both light and dark modes; dark shades are
|
|
1310
|
+
* derived via the dark-palette tone mapping. Omitted roles fall back to the
|
|
1311
|
+
* packaged default seeds (which may differ per mode for `secondary`, `danger`, and `surface`).
|
|
1312
|
+
*/
|
|
1313
|
+
function createTheme(colors, options) {
|
|
1314
|
+
const target = options?.target ?? 'file';
|
|
1315
|
+
const seeds = resolveSeedsFromFlat(colors);
|
|
1316
|
+
const roles = options?.roles;
|
|
1317
|
+
const palette = buildFullPalette(seeds, roles);
|
|
1318
|
+
const css = target === 'preview'
|
|
1319
|
+
? buildPreviewThemeCSS(palette, options?.scope, roles)
|
|
1320
|
+
: generateFullThemeCSS({ light: seeds.light, dark: seeds.dark });
|
|
1321
|
+
return { css, palette };
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
/**
|
|
1325
|
+
* Generated bundle index. Do not edit.
|
|
1326
|
+
*/
|
|
1327
|
+
|
|
1328
|
+
export { createTheme };
|
|
1329
|
+
//# sourceMappingURL=acorex-core-theme-builder.mjs.map
|