@resolve-components/theme 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/collection.json +10 -0
- package/fesm2022/resolve-components-theme.mjs +8946 -0
- package/fesm2022/resolve-components-theme.mjs.map +1 -0
- package/package.json +45 -0
- package/schematics/ng-add/index.js +147 -0
- package/schematics/ng-add/schema.json +15 -0
- package/src/lib/styles/_all.scss +52 -0
- package/src/lib/styles/_globals.scss +66 -0
- package/src/lib/styles/_themes.scss +9 -0
- package/src/lib/styles/_theming.scss +20 -0
- package/src/lib/styles/themes/_dark.scss +107 -0
- package/src/lib/styles/themes/_default.scss +341 -0
- package/src/lib/styles/theming/_animation.scss +92 -0
- package/src/lib/styles/theming/_functions.scss +34 -0
- package/src/lib/styles/theming/_get-value.scss +70 -0
- package/src/lib/styles/theming/_install.scss +141 -0
- package/src/lib/styles/theming/_mapping.scss +701 -0
- package/src/lib/styles/theming/_register.scss +58 -0
- package/src/lib/styles/theming/_theming-variables.scss +30 -0
- package/types/resolve-components-theme.d.ts +3214 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Resolve Components — Default Theme (Microsoft Fluent-Inspired)
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// This is the base light theme. All other themes inherit from it.
|
|
5
|
+
//
|
|
6
|
+
// The palette is inspired by Microsoft Fluent Design System:
|
|
7
|
+
// Primary: #0078D4 (Microsoft Blue)
|
|
8
|
+
// Success: #107C10 (Microsoft Green)
|
|
9
|
+
// Warning: #FFB900 (Microsoft Yellow)
|
|
10
|
+
// Danger: #D13438 (Microsoft Red)
|
|
11
|
+
// Info: #00B7C3 (Microsoft Teal)
|
|
12
|
+
//
|
|
13
|
+
// Each color has a 100–900 ramp. Semantic aliases (e.g. color-primary-default)
|
|
14
|
+
// point to specific ramp steps. Users override these to re-theme.
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
@use 'sass:string';
|
|
18
|
+
@use '../theming/theming-variables' as vars;
|
|
19
|
+
@use '../theming/register' as reg;
|
|
20
|
+
|
|
21
|
+
$theme: (
|
|
22
|
+
// Direct CSS properties (emitted without -- prefix)
|
|
23
|
+
_color-scheme: light,
|
|
24
|
+
|
|
25
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
26
|
+
// COLOR PALETTE
|
|
27
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
28
|
+
// ── Primary (Microsoft Blue) ────────────────────────────────────────────
|
|
29
|
+
color-primary-100: #eff6fc,
|
|
30
|
+
color-primary-200: #deecf9,
|
|
31
|
+
color-primary-300: #b4d6fa,
|
|
32
|
+
color-primary-400: #5ba3e6,
|
|
33
|
+
color-primary-500: #0078d4,
|
|
34
|
+
color-primary-600: #106ebe,
|
|
35
|
+
color-primary-700: #005a9e,
|
|
36
|
+
color-primary-800: #004578,
|
|
37
|
+
color-primary-900: #003356,
|
|
38
|
+
|
|
39
|
+
// Semantic primary aliases
|
|
40
|
+
color-primary-default: color-primary-500,
|
|
41
|
+
color-primary-hover: color-primary-600,
|
|
42
|
+
color-primary-active: color-primary-700,
|
|
43
|
+
color-primary-focus: color-primary-500,
|
|
44
|
+
color-primary-disabled: color-primary-300,
|
|
45
|
+
color-primary-transparent-default: rgba(0, 120, 212, 0.08),
|
|
46
|
+
color-primary-transparent-hover: rgba(0, 120, 212, 0.12),
|
|
47
|
+
color-primary-transparent-active: rgba(0, 120, 212, 0.16),
|
|
48
|
+
// ── Success (Microsoft Green) ───────────────────────────────────────────
|
|
49
|
+
color-success-100: #dff6dd,
|
|
50
|
+
color-success-200: #c8f0c2,
|
|
51
|
+
color-success-300: #9ae08f,
|
|
52
|
+
color-success-400: #54b054,
|
|
53
|
+
color-success-500: #107c10,
|
|
54
|
+
color-success-600: #0e6b0e,
|
|
55
|
+
color-success-700: #094509,
|
|
56
|
+
color-success-800: #063006,
|
|
57
|
+
color-success-900: #042004,
|
|
58
|
+
|
|
59
|
+
color-success-default: color-success-500,
|
|
60
|
+
color-success-hover: color-success-600,
|
|
61
|
+
color-success-active: color-success-700,
|
|
62
|
+
|
|
63
|
+
// ── Warning (Microsoft Yellow/Amber) ────────────────────────────────────
|
|
64
|
+
color-warning-100: #fff8e1,
|
|
65
|
+
color-warning-200: #ffecb3,
|
|
66
|
+
color-warning-300: #ffe082,
|
|
67
|
+
color-warning-400: #ffd54f,
|
|
68
|
+
color-warning-500: #ffb900,
|
|
69
|
+
color-warning-600: #e6a700,
|
|
70
|
+
color-warning-700: #cc9500,
|
|
71
|
+
color-warning-800: #997000,
|
|
72
|
+
color-warning-900: #664b00,
|
|
73
|
+
|
|
74
|
+
color-warning-default: color-warning-500,
|
|
75
|
+
color-warning-hover: color-warning-600,
|
|
76
|
+
color-warning-active: color-warning-700,
|
|
77
|
+
|
|
78
|
+
// ── Danger (Microsoft Red) ──────────────────────────────────────────────
|
|
79
|
+
color-danger-100: #fde7e9,
|
|
80
|
+
color-danger-200: #f9c6ca,
|
|
81
|
+
color-danger-300: #f3a3a6,
|
|
82
|
+
color-danger-400: #e74856,
|
|
83
|
+
color-danger-500: #d13438,
|
|
84
|
+
color-danger-600: #bc2f32,
|
|
85
|
+
color-danger-700: #a4262c,
|
|
86
|
+
color-danger-800: #8b2025,
|
|
87
|
+
color-danger-900: #6e191d,
|
|
88
|
+
|
|
89
|
+
color-danger-default: color-danger-500,
|
|
90
|
+
color-danger-hover: color-danger-600,
|
|
91
|
+
color-danger-active: color-danger-700,
|
|
92
|
+
|
|
93
|
+
// ── Info (Microsoft Teal) ───────────────────────────────────────────────
|
|
94
|
+
color-info-100: #e0f7fa,
|
|
95
|
+
color-info-200: #b2ebf2,
|
|
96
|
+
color-info-300: #80deea,
|
|
97
|
+
color-info-400: #26c6da,
|
|
98
|
+
color-info-500: #00b7c3,
|
|
99
|
+
color-info-600: #009da5,
|
|
100
|
+
color-info-700: #008387,
|
|
101
|
+
color-info-800: #006b6b,
|
|
102
|
+
color-info-900: #00524f,
|
|
103
|
+
|
|
104
|
+
color-info-default: color-info-500,
|
|
105
|
+
color-info-hover: color-info-600,
|
|
106
|
+
color-info-active: color-info-700,
|
|
107
|
+
|
|
108
|
+
// ── Basic / Neutral (Microsoft Grays) ───────────────────────────────────
|
|
109
|
+
color-basic-100: #ffffff,
|
|
110
|
+
color-basic-200: #faf9f8,
|
|
111
|
+
color-basic-300: #f3f2f1,
|
|
112
|
+
color-basic-400: #edebe9,
|
|
113
|
+
color-basic-500: #d2d0ce,
|
|
114
|
+
color-basic-600: #a19f9d,
|
|
115
|
+
color-basic-700: #605e5c,
|
|
116
|
+
color-basic-800: #3b3a39,
|
|
117
|
+
color-basic-900: #323130,
|
|
118
|
+
color-basic-1000: #201f1e,
|
|
119
|
+
color-basic-1100: #11100f,
|
|
120
|
+
|
|
121
|
+
// ── Control (text on filled backgrounds) ────────────────────────────────
|
|
122
|
+
color-control: #ffffff,
|
|
123
|
+
color-control-muted: rgba(255, 255, 255, 0.72),
|
|
124
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
125
|
+
// SEMANTIC BACKGROUND COLORS
|
|
126
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
+
background-basic-color-1: color-basic-100,
|
|
128
|
+
background-basic-color-2: color-basic-200,
|
|
129
|
+
background-basic-color-3: color-basic-300,
|
|
130
|
+
background-basic-color-4: color-basic-400,
|
|
131
|
+
background-alternative-color-1: color-basic-900,
|
|
132
|
+
background-alternative-color-2: color-basic-1000,
|
|
133
|
+
|
|
134
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
135
|
+
// SEMANTIC TEXT COLORS
|
|
136
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
137
|
+
text-basic-color: color-basic-1000,
|
|
138
|
+
text-alternate-color: color-basic-100,
|
|
139
|
+
text-control-color: color-control,
|
|
140
|
+
text-hint-color: color-basic-600,
|
|
141
|
+
text-disabled-color: color-basic-500,
|
|
142
|
+
|
|
143
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
144
|
+
// BORDERS
|
|
145
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
146
|
+
border-basic-color: color-basic-400,
|
|
147
|
+
border-basic-color-2: color-basic-500,
|
|
148
|
+
border-basic-color-3: color-basic-300,
|
|
149
|
+
border-primary-color: color-primary-default,
|
|
150
|
+
|
|
151
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
152
|
+
// TYPOGRAPHY
|
|
153
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
154
|
+
font-family-primary: string.unquote(
|
|
155
|
+
"'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif"
|
|
156
|
+
),
|
|
157
|
+
font-family-secondary: string.unquote(
|
|
158
|
+
"'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', sans-serif"
|
|
159
|
+
),
|
|
160
|
+
font-family-mono: string.unquote(
|
|
161
|
+
"'Cascadia Code', 'Fira Code', 'Consolas', monospace"
|
|
162
|
+
),
|
|
163
|
+
font-size-xs: 0.75rem,
|
|
164
|
+
font-size-sm: 0.875rem,
|
|
165
|
+
font-size-md: 0.9375rem,
|
|
166
|
+
font-size-lg: 1.125rem,
|
|
167
|
+
font-size-xl: 1.25rem,
|
|
168
|
+
font-size-2xl: 1.5rem,
|
|
169
|
+
font-size-3xl: 2rem,
|
|
170
|
+
|
|
171
|
+
font-weight-normal: 400,
|
|
172
|
+
font-weight-medium: 500,
|
|
173
|
+
font-weight-semibold: 600,
|
|
174
|
+
font-weight-bold: 700,
|
|
175
|
+
|
|
176
|
+
line-height-sm: 1.25,
|
|
177
|
+
line-height-md: 1.5,
|
|
178
|
+
line-height-lg: 1.75,
|
|
179
|
+
|
|
180
|
+
// Heading sizes
|
|
181
|
+
text-heading-1-font-size: 2rem,
|
|
182
|
+
text-heading-1-font-weight: font-weight-semibold,
|
|
183
|
+
text-heading-2-font-size: 1.5rem,
|
|
184
|
+
text-heading-2-font-weight: font-weight-semibold,
|
|
185
|
+
text-heading-3-font-size: 1.25rem,
|
|
186
|
+
text-heading-3-font-weight: font-weight-semibold,
|
|
187
|
+
text-heading-4-font-size: 1.125rem,
|
|
188
|
+
text-heading-4-font-weight: font-weight-semibold,
|
|
189
|
+
|
|
190
|
+
text-body-font-size: font-size-md,
|
|
191
|
+
text-body-font-weight: font-weight-normal,
|
|
192
|
+
text-caption-font-size: font-size-xs,
|
|
193
|
+
text-caption-font-weight: font-weight-normal,
|
|
194
|
+
|
|
195
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
196
|
+
// SPACING
|
|
197
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
198
|
+
spacing-xs: 0.25rem,
|
|
199
|
+
spacing-sm: 0.5rem,
|
|
200
|
+
spacing-md: 1rem,
|
|
201
|
+
spacing-lg: 1.5rem,
|
|
202
|
+
spacing-xl: 2rem,
|
|
203
|
+
spacing-2xl: 3rem,
|
|
204
|
+
|
|
205
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
206
|
+
// BORDER RADIUS
|
|
207
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
208
|
+
border-radius: 4px,
|
|
209
|
+
radius-sm: 2px,
|
|
210
|
+
radius-md: 4px,
|
|
211
|
+
radius-lg: 8px,
|
|
212
|
+
radius-xl: 12px,
|
|
213
|
+
radius-full: 9999px,
|
|
214
|
+
|
|
215
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
216
|
+
// SHADOWS (Fluent elevation)
|
|
217
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
218
|
+
shadow: string.unquote(
|
|
219
|
+
'0 1.6px 3.6px 0 rgba(0, 0, 0, 0.132), 0 0.3px 0.9px 0 rgba(0, 0, 0, 0.108)'
|
|
220
|
+
),
|
|
221
|
+
shadow-sm: string.unquote(
|
|
222
|
+
'0 0.8px 1.8px 0 rgba(0, 0, 0, 0.108), 0 0.15px 0.45px 0 rgba(0, 0, 0, 0.084)'
|
|
223
|
+
),
|
|
224
|
+
shadow-md: string.unquote(
|
|
225
|
+
'0 3.2px 7.2px 0 rgba(0, 0, 0, 0.132), 0 0.6px 1.8px 0 rgba(0, 0, 0, 0.108)'
|
|
226
|
+
),
|
|
227
|
+
shadow-lg: string.unquote(
|
|
228
|
+
'0 6.4px 14.4px 0 rgba(0, 0, 0, 0.132), 0 1.2px 3.6px 0 rgba(0, 0, 0, 0.108)'
|
|
229
|
+
),
|
|
230
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
231
|
+
// TRANSITIONS
|
|
232
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
233
|
+
transition-duration-fast: 100ms,
|
|
234
|
+
transition-duration-medium: 150ms,
|
|
235
|
+
transition-duration-normal: 200ms,
|
|
236
|
+
transition-duration-slow: 300ms,
|
|
237
|
+
transition-timing: cubic-bezier(0.33, 0, 0.67, 1),
|
|
238
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
239
|
+
// OUTLINE / FOCUS
|
|
240
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
241
|
+
outline-color: color-basic-1000,
|
|
242
|
+
outline-width: 2px,
|
|
243
|
+
focus-ring-color: color-primary-focus,
|
|
244
|
+
focus-ring-width: 2px,
|
|
245
|
+
focus-ring-offset: 2px,
|
|
246
|
+
|
|
247
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
248
|
+
// DIVIDER
|
|
249
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
250
|
+
divider-color: border-basic-color-3,
|
|
251
|
+
divider-width: 1px,
|
|
252
|
+
|
|
253
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
254
|
+
// ALERT COMPONENT
|
|
255
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
256
|
+
alert-border-radius: radius-md,
|
|
257
|
+
alert-padding: string.unquote('0.875rem 1rem'),
|
|
258
|
+
alert-gap: spacing-sm,
|
|
259
|
+
alert-font-size: font-size-sm,
|
|
260
|
+
alert-title-font-weight: font-weight-semibold,
|
|
261
|
+
alert-title-font-size: font-size-sm,
|
|
262
|
+
alert-close-size: 1rem,
|
|
263
|
+
|
|
264
|
+
// Alert — info (subtle)
|
|
265
|
+
alert-info-subtle-background: color-info-100,
|
|
266
|
+
alert-info-subtle-color: color-info-700,
|
|
267
|
+
alert-info-subtle-border: color-info-300,
|
|
268
|
+
// Alert — info (filled)
|
|
269
|
+
alert-info-filled-background: color-info-default,
|
|
270
|
+
alert-info-filled-color: color-control,
|
|
271
|
+
alert-info-filled-border: color-info-default,
|
|
272
|
+
// Alert — info (outline)
|
|
273
|
+
alert-info-outline-background: transparent,
|
|
274
|
+
alert-info-outline-color: color-info-700,
|
|
275
|
+
alert-info-outline-border: color-info-default,
|
|
276
|
+
|
|
277
|
+
// Alert — success (subtle)
|
|
278
|
+
alert-success-subtle-background: color-success-100,
|
|
279
|
+
alert-success-subtle-color: color-success-700,
|
|
280
|
+
alert-success-subtle-border: color-success-300,
|
|
281
|
+
// Alert — success (filled)
|
|
282
|
+
alert-success-filled-background: color-success-default,
|
|
283
|
+
alert-success-filled-color: color-control,
|
|
284
|
+
alert-success-filled-border: color-success-default,
|
|
285
|
+
// Alert — success (outline)
|
|
286
|
+
alert-success-outline-background: transparent,
|
|
287
|
+
alert-success-outline-color: color-success-700,
|
|
288
|
+
alert-success-outline-border: color-success-default,
|
|
289
|
+
|
|
290
|
+
// Alert — warning (subtle)
|
|
291
|
+
alert-warning-subtle-background: color-warning-100,
|
|
292
|
+
alert-warning-subtle-color: color-warning-800,
|
|
293
|
+
alert-warning-subtle-border: color-warning-400,
|
|
294
|
+
// Alert — warning (filled)
|
|
295
|
+
alert-warning-filled-background: color-warning-default,
|
|
296
|
+
alert-warning-filled-color: color-basic-1100,
|
|
297
|
+
alert-warning-filled-border: color-warning-default,
|
|
298
|
+
// Alert — warning (outline)
|
|
299
|
+
alert-warning-outline-background: transparent,
|
|
300
|
+
alert-warning-outline-color: color-warning-700,
|
|
301
|
+
alert-warning-outline-border: color-warning-default,
|
|
302
|
+
|
|
303
|
+
// Alert — danger (subtle)
|
|
304
|
+
alert-danger-subtle-background: color-danger-100,
|
|
305
|
+
alert-danger-subtle-color: color-danger-700,
|
|
306
|
+
alert-danger-subtle-border: color-danger-300,
|
|
307
|
+
// Alert — danger (filled)
|
|
308
|
+
alert-danger-filled-background: color-danger-default,
|
|
309
|
+
alert-danger-filled-color: color-control,
|
|
310
|
+
alert-danger-filled-border: color-danger-default,
|
|
311
|
+
// Alert — danger (outline)
|
|
312
|
+
alert-danger-outline-background: transparent,
|
|
313
|
+
alert-danger-outline-color: color-danger-700,
|
|
314
|
+
alert-danger-outline-border: color-danger-default,
|
|
315
|
+
|
|
316
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
317
|
+
// TOAST COMPONENT
|
|
318
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
319
|
+
toast-border-radius: radius-lg,
|
|
320
|
+
toast-padding: string.unquote('0.875rem 1rem'),
|
|
321
|
+
toast-gap: spacing-sm,
|
|
322
|
+
toast-min-width: 20rem,
|
|
323
|
+
toast-max-width: 24rem,
|
|
324
|
+
toast-font-size: font-size-sm,
|
|
325
|
+
toast-title-font-weight: font-weight-semibold,
|
|
326
|
+
toast-title-font-size: font-size-sm,
|
|
327
|
+
toast-shadow: shadow-md,
|
|
328
|
+
toast-background: background-basic-color-1,
|
|
329
|
+
toast-color: text-basic-color,
|
|
330
|
+
toast-border-color: border-basic-color,
|
|
331
|
+
toast-close-size: 1rem,
|
|
332
|
+
toast-progress-height: 3px,
|
|
333
|
+
|
|
334
|
+
toast-info-accent: color-info-default,
|
|
335
|
+
toast-success-accent: color-success-default,
|
|
336
|
+
toast-warning-accent: color-warning-default,
|
|
337
|
+
toast-danger-accent: color-danger-default
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
// Register as the default theme (no parent)
|
|
341
|
+
vars.$rc-themes: reg.rc-register-theme($theme, default);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Resolve Components — rc-component-animation mixin
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Wraps CSS `transition` declarations in `@media (prefers-reduced-motion: no-preference)`
|
|
5
|
+
// so that users who opt out of motion receive no transitions whatsoever.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// @use '../styles/theming/animation' as *;
|
|
9
|
+
//
|
|
10
|
+
// .my-element {
|
|
11
|
+
// @include rc-component-animation(background color);
|
|
12
|
+
// @include rc-component-animation(transform, $speed: 'normal');
|
|
13
|
+
// @include rc-component-animation(border-color, $speed: 'medium');
|
|
14
|
+
// @include rc-component-animation(
|
|
15
|
+
// background,
|
|
16
|
+
// $duration: rc-theme('accordion-transition-duration'),
|
|
17
|
+
// $timing: rc-theme('accordion-transition-timing')
|
|
18
|
+
// );
|
|
19
|
+
// }
|
|
20
|
+
// =============================================================================
|
|
21
|
+
|
|
22
|
+
@use 'sass:list';
|
|
23
|
+
@use 'get-value' as *;
|
|
24
|
+
|
|
25
|
+
/// Emits a CSS `transition` declaration wrapped in
|
|
26
|
+
/// `@media (prefers-reduced-motion: no-preference)`.
|
|
27
|
+
///
|
|
28
|
+
/// @param {List} $properties Space-separated CSS properties to animate.
|
|
29
|
+
/// E.g. `background color` or just `transform`.
|
|
30
|
+
///
|
|
31
|
+
/// @param {String} $speed Pre-defined duration tier.
|
|
32
|
+
/// `'fast'` → 100ms · `'medium'` → 150ms ·
|
|
33
|
+
/// `'normal'` → 200ms · `'slow'` → 300ms.
|
|
34
|
+
/// Default: `'fast'`. Ignored when `$duration` is given.
|
|
35
|
+
///
|
|
36
|
+
/// @param {*} $timing Custom CSS timing function.
|
|
37
|
+
/// Defaults to the `transition-timing` theme token.
|
|
38
|
+
///
|
|
39
|
+
/// @param {*} $duration Raw duration value (e.g. `rc-theme('accordion-transition-duration')`).
|
|
40
|
+
/// When provided, `$speed` is ignored for the duration.
|
|
41
|
+
///
|
|
42
|
+
/// @example scss — simple, multiple props
|
|
43
|
+
/// .rc-button { @include rc-component-animation(background color); }
|
|
44
|
+
///
|
|
45
|
+
/// @example scss — speed tier
|
|
46
|
+
/// .rc-toggle-thumb { @include rc-component-animation(transform, $speed: 'normal'); }
|
|
47
|
+
///
|
|
48
|
+
/// @example scss — component token
|
|
49
|
+
/// .rc-accordion-header {
|
|
50
|
+
/// @include rc-component-animation(
|
|
51
|
+
/// background,
|
|
52
|
+
/// $duration: rc-theme('accordion-transition-duration'),
|
|
53
|
+
/// $timing: rc-theme('accordion-transition-timing')
|
|
54
|
+
/// );
|
|
55
|
+
/// }
|
|
56
|
+
@mixin rc-component-animation(
|
|
57
|
+
$properties,
|
|
58
|
+
$speed: 'fast',
|
|
59
|
+
$timing: null,
|
|
60
|
+
$duration: null
|
|
61
|
+
) {
|
|
62
|
+
$d: $duration;
|
|
63
|
+
|
|
64
|
+
@if $d == null {
|
|
65
|
+
@if $speed == 'fast' {
|
|
66
|
+
$d: rc-theme('transition-duration-fast');
|
|
67
|
+
} @else if $speed == 'medium' {
|
|
68
|
+
$d: rc-theme('transition-duration-medium');
|
|
69
|
+
} @else if $speed == 'normal' {
|
|
70
|
+
$d: rc-theme('transition-duration-normal');
|
|
71
|
+
} @else {
|
|
72
|
+
$d: rc-theme('transition-duration-slow');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
$t: null;
|
|
77
|
+
@if $timing != null {
|
|
78
|
+
$t: $timing;
|
|
79
|
+
} @else {
|
|
80
|
+
$t: rc-theme('transition-timing');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
$result: ();
|
|
84
|
+
|
|
85
|
+
@each $prop in $properties {
|
|
86
|
+
$result: list.append($result, $prop $d $t, $separator: comma);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
90
|
+
transition: $result;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Resolve Components — Helper Functions
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
@use 'sass:map';
|
|
6
|
+
@use 'sass:meta';
|
|
7
|
+
@use 'sass:list';
|
|
8
|
+
|
|
9
|
+
/// Deeply merge two maps recursively.
|
|
10
|
+
/// @param {Map} $map1 - Base map.
|
|
11
|
+
/// @param {Map} $map2 - Override map.
|
|
12
|
+
/// @return {Map} Merged map.
|
|
13
|
+
@function rc-map-deep-merge($map1, $map2) {
|
|
14
|
+
$result: $map1;
|
|
15
|
+
|
|
16
|
+
@each $key, $value in $map2 {
|
|
17
|
+
@if meta.type-of($value) == 'map' and map.has-key($result, $key) and meta.type-of(map.get($result, $key)) == 'map' {
|
|
18
|
+
$result: map.set($result, $key, rc-map-deep-merge(map.get($result, $key), $value));
|
|
19
|
+
} @else {
|
|
20
|
+
$result: map.set($result, $key, $value);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@return $result;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// Set a key in a map, returning the new map.
|
|
28
|
+
/// @param {Map} $map
|
|
29
|
+
/// @param {String} $key
|
|
30
|
+
/// @param {*} $value
|
|
31
|
+
/// @return {Map}
|
|
32
|
+
@function rc-map-set($map, $key, $value) {
|
|
33
|
+
@return map.merge($map, ($key: $value));
|
|
34
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Resolve Components — Theme Value Resolution
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
@use 'sass:map';
|
|
6
|
+
@use 'sass:meta';
|
|
7
|
+
@use 'theming-variables' as vars;
|
|
8
|
+
@use 'register' as reg;
|
|
9
|
+
|
|
10
|
+
/// Recursively resolve an alias chain in a theme map.
|
|
11
|
+
///
|
|
12
|
+
/// If the value of a key is itself a key in the same map, follow the chain
|
|
13
|
+
/// until a terminal (non-key) value is found.
|
|
14
|
+
///
|
|
15
|
+
/// Example: card-bg → background-basic-color-1 → color-basic-100 → #ffffff
|
|
16
|
+
///
|
|
17
|
+
/// @param {Map} $theme - The theme map.
|
|
18
|
+
/// @param {String} $key - Original key (for error reporting).
|
|
19
|
+
/// @param {*} $value - Current value to resolve.
|
|
20
|
+
/// @return {*} Terminal value.
|
|
21
|
+
@function rc-deep-find-value($theme, $key, $value) {
|
|
22
|
+
@if $value == null {
|
|
23
|
+
@return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
$parent-value: map.get($theme, $value);
|
|
27
|
+
|
|
28
|
+
@if $parent-value != null and $parent-value != $value {
|
|
29
|
+
@return rc-deep-find-value($theme, $value, $parent-value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@return $value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Retrieve a themed value by variable name.
|
|
36
|
+
///
|
|
37
|
+
/// In CSS custom properties mode (default), returns `var(--variable-name)`.
|
|
38
|
+
/// In pre-process mode, returns the resolved SCSS value.
|
|
39
|
+
/// In lazy-process mode, resolves at compile time by walking the alias chain.
|
|
40
|
+
///
|
|
41
|
+
/// @param {String} $key - The theme variable name.
|
|
42
|
+
/// @return {*} The resolved value or CSS var() reference.
|
|
43
|
+
///
|
|
44
|
+
/// @example scss
|
|
45
|
+
/// .my-component {
|
|
46
|
+
/// background: rc-theme('card-background-color');
|
|
47
|
+
/// // → var(--card-background-color) in CSS custom properties mode
|
|
48
|
+
/// }
|
|
49
|
+
@function rc-theme($key) {
|
|
50
|
+
$value: null;
|
|
51
|
+
|
|
52
|
+
@if vars.$rc-enable-css-custom-properties == true {
|
|
53
|
+
// CSS custom properties mode → emit var(--key)
|
|
54
|
+
$value: var(--#{$key});
|
|
55
|
+
} @else if vars.$rc-theme-process-mode == 'pre-process' {
|
|
56
|
+
// Pre-processed: value already resolved
|
|
57
|
+
$value: map.get(vars.$rc-processed-theme, $key);
|
|
58
|
+
} @else {
|
|
59
|
+
// Lazy mode: resolve at call time
|
|
60
|
+
$theme: reg.rc-get-registered-theme(vars.$rc-theme-name);
|
|
61
|
+
$raw: map.get($theme, $key);
|
|
62
|
+
$value: rc-deep-find-value($theme, $key, $raw);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@if $value == null {
|
|
66
|
+
@warn 'rc-theme: Variable "#{$key}" not found in theme "#{vars.$rc-theme-name}".';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@return $value;
|
|
70
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Resolve Components — Theme Installation
|
|
3
|
+
// =============================================================================
|
|
4
|
+
|
|
5
|
+
@use 'sass:map';
|
|
6
|
+
@use 'sass:meta';
|
|
7
|
+
@use 'sass:string';
|
|
8
|
+
@use 'theming-variables' as vars;
|
|
9
|
+
@use 'register' as reg;
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// Public API
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
/// Main install mixin. Call this once in your application's global stylesheet.
|
|
16
|
+
///
|
|
17
|
+
/// In CSS custom properties mode (default), it:
|
|
18
|
+
/// 1. Emits the @content block (global styles) once.
|
|
19
|
+
/// 2. Emits `.rc-theme-{name} { --var: value; }` blocks for each theme.
|
|
20
|
+
///
|
|
21
|
+
/// @example scss
|
|
22
|
+
/// // In your styles.scss:
|
|
23
|
+
/// @use '@resolve-components/styles/theming' as *;
|
|
24
|
+
///
|
|
25
|
+
/// @include rc-install() {
|
|
26
|
+
/// // Optional global styles
|
|
27
|
+
/// body { margin: 0; font-family: var(--font-family-primary); }
|
|
28
|
+
/// }
|
|
29
|
+
@mixin rc-install() {
|
|
30
|
+
@if vars.$rc-enable-css-custom-properties {
|
|
31
|
+
@include _rc-install-global-with-css-props() {
|
|
32
|
+
@content;
|
|
33
|
+
}
|
|
34
|
+
} @else {
|
|
35
|
+
@include _rc-install-global-without-css-props() {
|
|
36
|
+
@content;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Wraps component styles. Use this in every component's SCSS file.
|
|
42
|
+
///
|
|
43
|
+
/// In CSS custom properties mode, simply emits the content.
|
|
44
|
+
/// In legacy mode, duplicates styles for each `.rc-theme-{name} :host { ... }`.
|
|
45
|
+
///
|
|
46
|
+
/// @example scss
|
|
47
|
+
/// @use '@resolve-components/styles/theming' as *;
|
|
48
|
+
///
|
|
49
|
+
/// @include rc-install-component() {
|
|
50
|
+
/// :host {
|
|
51
|
+
/// background: rc-theme('card-background-color');
|
|
52
|
+
/// }
|
|
53
|
+
/// }
|
|
54
|
+
@mixin rc-install-component() {
|
|
55
|
+
@if vars.$rc-enable-css-custom-properties {
|
|
56
|
+
@content;
|
|
57
|
+
} @else {
|
|
58
|
+
@each $theme-name in reg.rc-get-enabled-themes() {
|
|
59
|
+
.rc-theme-#{$theme-name} {
|
|
60
|
+
@content;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Conditional Theme Mixins
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
/// Only emit styles for a specific theme.
|
|
71
|
+
/// @param {String} $name - Theme name.
|
|
72
|
+
@mixin rc-for-theme($name) {
|
|
73
|
+
@if vars.$rc-theme-name == $name {
|
|
74
|
+
@content;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/// Emit styles for all themes except the named one.
|
|
79
|
+
/// @param {String} $name - Theme name to exclude.
|
|
80
|
+
@mixin rc-except-theme($name) {
|
|
81
|
+
@if vars.$rc-theme-name != $name {
|
|
82
|
+
@content;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Private Implementation
|
|
88
|
+
// =============================================================================
|
|
89
|
+
|
|
90
|
+
/// CSS Custom Properties installation (modern mode).
|
|
91
|
+
@mixin _rc-install-global-with-css-props() {
|
|
92
|
+
// Emit global styles once
|
|
93
|
+
@content;
|
|
94
|
+
|
|
95
|
+
// Emit CSS custom property blocks per theme
|
|
96
|
+
@each $theme-name in reg.rc-get-enabled-themes() {
|
|
97
|
+
$theme: reg.rc-get-registered-theme($theme-name);
|
|
98
|
+
@include _rc-install-css-properties($theme-name, $theme);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// Emit CSS custom properties for a single theme.
|
|
103
|
+
/// Keys prefixed with `_` are emitted as direct CSS properties (e.g. `_color-scheme` → `color-scheme: dark`).
|
|
104
|
+
/// Aliases become `var(--other-var)` references, terminal values are emitted directly.
|
|
105
|
+
@mixin _rc-install-css-properties($theme-name, $theme) {
|
|
106
|
+
.rc-theme-#{$theme-name} {
|
|
107
|
+
@each $var, $value in $theme {
|
|
108
|
+
@if string.slice('#{$var}', 1, 1) == '_' {
|
|
109
|
+
// Direct CSS property — strip the leading underscore
|
|
110
|
+
#{string.slice('#{$var}', 2)}: #{$value};
|
|
111
|
+
} @else if
|
|
112
|
+
meta.type-of($value) ==
|
|
113
|
+
'string' and
|
|
114
|
+
map.has-key($theme, $value)
|
|
115
|
+
{
|
|
116
|
+
// Value is an alias to another theme variable → CSS var reference
|
|
117
|
+
--#{$var}: var(--#{$value});
|
|
118
|
+
} @else {
|
|
119
|
+
// Terminal value → emit directly
|
|
120
|
+
--#{$var}: #{$value};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Legacy (non-CSS-props) installation.
|
|
127
|
+
@mixin _rc-install-global-without-css-props() {
|
|
128
|
+
@each $theme-name in reg.rc-get-enabled-themes() {
|
|
129
|
+
$theme: reg.rc-get-registered-theme($theme-name);
|
|
130
|
+
|
|
131
|
+
vars.$rc-theme-name: $theme-name;
|
|
132
|
+
vars.$rc-theme: $theme;
|
|
133
|
+
|
|
134
|
+
.rc-theme-#{$theme-name} {
|
|
135
|
+
@content;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
vars.$rc-theme-name: null;
|
|
140
|
+
vars.$rc-theme: ();
|
|
141
|
+
}
|