@rokkit/core 1.8.0 → 1.8.2
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/dist/colors/index.d.ts +2 -2
- package/dist/dom.d.ts +18 -0
- package/dist/icons.d.ts +29 -0
- package/dist/keys.d.ts +13 -0
- package/dist/oklch.d.ts +23 -0
- package/dist/snippets.d.ts +24 -0
- package/dist/theme.d.ts +23 -40
- package/dist/utils.d.ts +6 -122
- package/dist/values.d.ts +32 -0
- package/package.json +2 -2
- package/src/colors/index.ts +3 -4
- package/src/dom.js +60 -0
- package/src/icons.js +94 -0
- package/src/keys.js +19 -0
- package/src/oklch.js +124 -0
- package/src/snippets.js +45 -0
- package/src/theme.ts +61 -35
- package/src/utils.js +9 -388
- package/src/values.js +56 -0
package/src/oklch.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** Colour conversion: hex ↔ `r,g,b` and hex ↔ OKLCH (CSS Color Level 4, via XYZ D65). */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* convert hex string to `{r},{g},{b}`
|
|
5
|
+
* @param {string} hex
|
|
6
|
+
* @return {string}
|
|
7
|
+
*/
|
|
8
|
+
export function hex2rgb(hex) {
|
|
9
|
+
const [r, g, b] = hex.match(/\w\w/g).map((x) => parseInt(x, 16))
|
|
10
|
+
return `${r},${g},${b}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Convert sRGB component (0-255) to linear RGB.
|
|
15
|
+
* @param {number} c - sRGB value 0-255
|
|
16
|
+
* @returns {number}
|
|
17
|
+
*/
|
|
18
|
+
function srgbToLinear(c) {
|
|
19
|
+
const s = c / 255
|
|
20
|
+
return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Convert linear RGB to sRGB component (0-255).
|
|
25
|
+
* @param {number} c - linear value 0-1
|
|
26
|
+
* @returns {number}
|
|
27
|
+
*/
|
|
28
|
+
function linearToSrgb(c) {
|
|
29
|
+
const s = c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055
|
|
30
|
+
return Math.round(Math.max(0, Math.min(255, s * 255)))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// CSS Color Level 4 two-step matrices (via XYZ D65) for round-trip fidelity.
|
|
34
|
+
// Linear sRGB → XYZ D65
|
|
35
|
+
const SRGB_TO_XYZ = [
|
|
36
|
+
[0.4123907993, 0.3575843394, 0.1804807884],
|
|
37
|
+
[0.2126390059, 0.7151686788, 0.0721923154],
|
|
38
|
+
[0.0193308187, 0.1191947798, 0.9505321522]
|
|
39
|
+
]
|
|
40
|
+
// XYZ D65 → LMS
|
|
41
|
+
const XYZ_TO_LMS = [
|
|
42
|
+
[0.8189330101, 0.3618667424, -0.1288597137],
|
|
43
|
+
[0.0329845436, 0.9293118715, 0.0361456387],
|
|
44
|
+
[0.0482003018, 0.2643662691, 0.633851707]
|
|
45
|
+
]
|
|
46
|
+
// LMS^(1/3) → OKLab
|
|
47
|
+
const LMS3_TO_OKLAB = [
|
|
48
|
+
[0.2104542553, 0.793617785, -0.0040720468],
|
|
49
|
+
[1.9779984951, -2.428592205, 0.4505937099],
|
|
50
|
+
[0.0259040371, 0.7827717662, -0.808675766]
|
|
51
|
+
]
|
|
52
|
+
// OKLab → LMS^(1/3)
|
|
53
|
+
const OKLAB_TO_LMS3 = [
|
|
54
|
+
[1.0, 0.3963377774, 0.2158037573],
|
|
55
|
+
[1.0, -0.1055613458, -0.0638541728],
|
|
56
|
+
[1.0, -0.0894841775, -1.291485548]
|
|
57
|
+
]
|
|
58
|
+
// LMS → XYZ D65
|
|
59
|
+
const LMS_TO_XYZ = [
|
|
60
|
+
[1.2270138511, -0.5577999807, 0.281256149],
|
|
61
|
+
[-0.0405801784, 1.1122568696, -0.0716766787],
|
|
62
|
+
[-0.0763812845, -0.4214819784, 1.5861632204]
|
|
63
|
+
]
|
|
64
|
+
// XYZ D65 → linear sRGB
|
|
65
|
+
const XYZ_TO_SRGB = [
|
|
66
|
+
[3.2409699419, -1.5373831776, -0.4986107603],
|
|
67
|
+
[-0.9692436363, 1.8759675015, 0.0415550574],
|
|
68
|
+
[0.0556300797, -0.2039769589, 1.0569715142]
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
/** @param {number[][]} m @param {number[]} v */
|
|
72
|
+
function matMul(m, v) {
|
|
73
|
+
return m.map((row) => row[0] * v[0] + row[1] * v[1] + row[2] * v[2])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Convert hex string to OKLCH components: `{L} {C} {H}`
|
|
78
|
+
* Uses CSS Color Level 4 two-step conversion via XYZ D65 for precision.
|
|
79
|
+
* @param {string} hex - 6-digit hex color (with or without #)
|
|
80
|
+
* @returns {string} space-separated OKLCH components for CSS `oklch(L C H / alpha)`
|
|
81
|
+
*/
|
|
82
|
+
export function hex2oklch(hex) {
|
|
83
|
+
const [r, g, b] = hex.match(/\w\w/g).map((x) => parseInt(x, 16))
|
|
84
|
+
const lin = [srgbToLinear(r), srgbToLinear(g), srgbToLinear(b)]
|
|
85
|
+
|
|
86
|
+
const xyz = matMul(SRGB_TO_XYZ, lin)
|
|
87
|
+
const lms = matMul(XYZ_TO_LMS, xyz)
|
|
88
|
+
const lms3 = [Math.cbrt(lms[0]), Math.cbrt(lms[1]), Math.cbrt(lms[2])]
|
|
89
|
+
const [L, a, bk] = matMul(LMS3_TO_OKLAB, lms3)
|
|
90
|
+
|
|
91
|
+
const C = Math.sqrt(a * a + bk * bk)
|
|
92
|
+
let H = (Math.atan2(bk, a) * 180) / Math.PI
|
|
93
|
+
if (H < 0) H += 360
|
|
94
|
+
|
|
95
|
+
const Lr = Math.round(L * 1000000) / 1000000
|
|
96
|
+
const Cr = Math.round(C * 1000000) / 1000000
|
|
97
|
+
const Hr = Math.round(H * 10000) / 10000
|
|
98
|
+
|
|
99
|
+
return `${Lr} ${Cr} ${Hr}`
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Convert OKLCH components back to hex string.
|
|
104
|
+
* Uses CSS Color Level 4 two-step conversion via XYZ D65 for precision.
|
|
105
|
+
* @param {number} L - Lightness 0-1
|
|
106
|
+
* @param {number} C - Chroma >= 0
|
|
107
|
+
* @param {number} H - Hue 0-360 degrees
|
|
108
|
+
* @returns {string} hex color string (#rrggbb)
|
|
109
|
+
*/
|
|
110
|
+
export function oklch2hex(L, C, H) {
|
|
111
|
+
const hRad = (H * Math.PI) / 180
|
|
112
|
+
const lab = [L, C * Math.cos(hRad), C * Math.sin(hRad)]
|
|
113
|
+
|
|
114
|
+
const lms3 = matMul(OKLAB_TO_LMS3, lab)
|
|
115
|
+
const lms = [lms3[0] ** 3, lms3[1] ** 3, lms3[2] ** 3]
|
|
116
|
+
const xyz = matMul(LMS_TO_XYZ, lms)
|
|
117
|
+
const lin = matMul(XYZ_TO_SRGB, xyz)
|
|
118
|
+
|
|
119
|
+
const toHex = (n) => {
|
|
120
|
+
const hex = linearToSrgb(n).toString(16)
|
|
121
|
+
return hex.length === 1 ? `0${hex}` : hex
|
|
122
|
+
}
|
|
123
|
+
return `#${toHex(lin[0])}${toHex(lin[1])}${toHex(lin[2])}`
|
|
124
|
+
}
|
package/src/snippets.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Snippet lookup for data-driven rendering. */
|
|
2
|
+
import { has } from 'ramda'
|
|
3
|
+
import { ITEM_SNIPPET } from './constants'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get snippet function from an object
|
|
7
|
+
* @param {Object} obj
|
|
8
|
+
* @param {string} key
|
|
9
|
+
* @param {null|Function} defaultSnippet
|
|
10
|
+
* @returns {Function|undefined}
|
|
11
|
+
*/
|
|
12
|
+
export function getSnippet(obj, key, defaultSnippet = null) {
|
|
13
|
+
if (has(key, obj) && typeof obj[key] === 'function') {
|
|
14
|
+
return obj[key]
|
|
15
|
+
}
|
|
16
|
+
return defaultSnippet
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {unknown} value
|
|
21
|
+
* @returns {Function|null}
|
|
22
|
+
*/
|
|
23
|
+
function asSnippet(value) {
|
|
24
|
+
return typeof value === 'function' ? value : null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolve which snippet to render for a proxy item.
|
|
29
|
+
*
|
|
30
|
+
* Reads the proxy's `snippet` field (via proxy.get('snippet'), honoring fields.snippet)
|
|
31
|
+
* for a per-item named override first (e.g. item.snippet = 'highlighted').
|
|
32
|
+
* Falls back to the component-level fallback snippet name (e.g. 'itemContent' / 'groupContent').
|
|
33
|
+
* Returns null if neither is found.
|
|
34
|
+
*
|
|
35
|
+
* @param {Record<string, unknown>} snippets - snippets passed to the component
|
|
36
|
+
* @param {{ get: (key: string) => unknown }} proxy - a ProxyItem; its snippet field is read via proxy.get('snippet')
|
|
37
|
+
* @param {string} [fallback] - fallback snippet name; defaults to ITEM_SNIPPET ('itemContent')
|
|
38
|
+
* @returns {Function | null}
|
|
39
|
+
*/
|
|
40
|
+
export function resolveSnippet(snippets, proxy, fallback = ITEM_SNIPPET) {
|
|
41
|
+
// `snippet` is a field-mapped prop like icon/href — read it via the proxy's
|
|
42
|
+
// field accessor (honors fields.snippet), not as a direct property.
|
|
43
|
+
const name = proxy?.get('snippet')
|
|
44
|
+
return asSnippet(name && snippets[name]) || asSnippet(snippets[fallback])
|
|
45
|
+
}
|
package/src/theme.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
-
// @ts-nocheck
|
|
3
1
|
import { DEFAULT_THEME_MAPPING, defaultColors } from './constants'
|
|
4
2
|
import { shades } from './colors/index'
|
|
5
3
|
import { ColorSpace, relativeLuminance } from './color-space'
|
|
@@ -8,6 +6,23 @@ import {
|
|
|
8
6
|
NAMED_TOKEN_SHADE_MAP,
|
|
9
7
|
NAMED_TOKEN_ROLE_MAP
|
|
10
8
|
} from './named-tokens'
|
|
9
|
+
import type { NamedToken } from './named-tokens'
|
|
10
|
+
|
|
11
|
+
/** One palette: shade (`'50'`…`'950'`, `'DEFAULT'`) → colour value in the adapter's notation. */
|
|
12
|
+
type Palette = Record<string, string>
|
|
13
|
+
/** Palette name → palette. */
|
|
14
|
+
type Colors = Record<string, Palette>
|
|
15
|
+
/** Role (`primary`, `surface`…) → palette name. */
|
|
16
|
+
type Mapping = Record<string, string>
|
|
17
|
+
type Adapter = ReturnType<typeof ColorSpace.create>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The default colours seen as palettes only. preset-mini's map also holds keyword entries
|
|
21
|
+
* (`inherit`, `current`, `transparent`…) that are plain strings, but a Theme only reaches a
|
|
22
|
+
* colour through a role mapping, and roles map to palette names — so the keyword entries are
|
|
23
|
+
* never indexed by shade here.
|
|
24
|
+
*/
|
|
25
|
+
const DEFAULT_COLORS = defaultColors as unknown as Colors
|
|
11
26
|
|
|
12
27
|
/**
|
|
13
28
|
* Generate shades for a color using css variable and a ColorSpace adapter.
|
|
@@ -16,10 +31,10 @@ import {
|
|
|
16
31
|
* @param {string|import('./color-space').ColorSpace} space - color space name or adapter instance
|
|
17
32
|
* @returns {Record<string|number, string>}
|
|
18
33
|
*/
|
|
19
|
-
export function shadesOf(name, space = 'rgb') {
|
|
34
|
+
export function shadesOf(name: string, space: string | Adapter = 'rgb'): Record<string, string> {
|
|
20
35
|
const adapter = typeof space === 'string' ? ColorSpace.create(space) : space
|
|
21
36
|
|
|
22
|
-
return shades.reduce(
|
|
37
|
+
return shades.reduce<Record<string, string>>(
|
|
23
38
|
(result, shade) => ({
|
|
24
39
|
...result,
|
|
25
40
|
[shade]: adapter.themeColor(`--color-${name}-${shade}`)
|
|
@@ -39,7 +54,7 @@ export function shadesOf(name, space = 'rgb') {
|
|
|
39
54
|
* @param {import('./color-space').ColorSpace} adapter - ColorSpace adapter instance.
|
|
40
55
|
* @returns {import('./types').ShadeMappings} An array containing the color rules for both light and dark modes.
|
|
41
56
|
*/
|
|
42
|
-
function generateColorRules(variant, colors, mapping, adapter) {
|
|
57
|
+
function generateColorRules(variant: string, colors: Colors, mapping: Mapping, adapter: Adapter) {
|
|
43
58
|
return ['DEFAULT', ...shades].flatMap((shade) => [
|
|
44
59
|
{
|
|
45
60
|
key: shade === 'DEFAULT' ? `--color-${variant}` : `--color-${variant}-${shade}`,
|
|
@@ -56,14 +71,18 @@ function generateColorRules(variant, colors, mapping, adapter) {
|
|
|
56
71
|
* @param {string} [colorSpace] - Color space name for CSS variable values.
|
|
57
72
|
* @returns {Array<Array>} An array containing two arrays, one for the light theme variant and another for the dark theme.
|
|
58
73
|
*/
|
|
59
|
-
export function themeRules(
|
|
74
|
+
export function themeRules(
|
|
75
|
+
mapping: Mapping = DEFAULT_THEME_MAPPING,
|
|
76
|
+
colors: Colors = DEFAULT_COLORS,
|
|
77
|
+
colorSpace?: string
|
|
78
|
+
): Record<string, string> {
|
|
60
79
|
mapping = { ...DEFAULT_THEME_MAPPING, ...mapping }
|
|
61
|
-
colors = { ...
|
|
80
|
+
colors = { ...(DEFAULT_COLORS), ...colors }
|
|
62
81
|
const adapter = ColorSpace.create(colorSpace || 'rgb')
|
|
63
82
|
const variants = Object.keys(mapping)
|
|
64
83
|
const rules = variants
|
|
65
84
|
.flatMap((variant) => generateColorRules(variant, colors, mapping, adapter))
|
|
66
|
-
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
85
|
+
.reduce<Record<string, string>>((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
67
86
|
|
|
68
87
|
return rules
|
|
69
88
|
}
|
|
@@ -84,10 +103,13 @@ export function themeRules(mapping = DEFAULT_THEME_MAPPING, colors = defaultColo
|
|
|
84
103
|
* @param {string} [onColor='#fafafa'] - resolved on-color hex for this role
|
|
85
104
|
* @returns {Array} Array of shortcut definitions
|
|
86
105
|
*/
|
|
87
|
-
export function contrastShortcuts(name, onColor = '#fafafa') {
|
|
106
|
+
export function contrastShortcuts(name: string, onColor = '#fafafa') {
|
|
88
107
|
return [
|
|
89
|
-
[new RegExp(`^text-on-${name}(\\/\\d+)?$`), ([, end]) => `text-[${onColor}]${end || ''}`],
|
|
90
|
-
[
|
|
108
|
+
[new RegExp(`^text-on-${name}(\\/\\d+)?$`), ([, end]: string[]) => `text-[${onColor}]${end || ''}`],
|
|
109
|
+
[
|
|
110
|
+
new RegExp(`^text-on-${name}-muted(\\/\\d+)?$`),
|
|
111
|
+
([, end]: string[]) => `text-[${onColor}]${end || ''}`
|
|
112
|
+
]
|
|
91
113
|
]
|
|
92
114
|
}
|
|
93
115
|
|
|
@@ -128,7 +150,7 @@ export function pickOnColor(y: number | null): string {
|
|
|
128
150
|
* Fallback chain for nullable color mappings.
|
|
129
151
|
* If a semantic color is null, it inherits from another semantic color.
|
|
130
152
|
*/
|
|
131
|
-
const COLOR_FALLBACKS = {
|
|
153
|
+
const COLOR_FALLBACKS: Record<string, keyof typeof DEFAULT_THEME_MAPPING> = {
|
|
132
154
|
ink: 'surface',
|
|
133
155
|
tertiary: 'primary',
|
|
134
156
|
secondary: 'primary',
|
|
@@ -141,30 +163,34 @@ const COLOR_FALLBACKS = {
|
|
|
141
163
|
* @param {Record<string, string | null>} mapping
|
|
142
164
|
* @returns {Record<string, string>}
|
|
143
165
|
*/
|
|
144
|
-
function resolveColors(mapping) {
|
|
166
|
+
function resolveColors(mapping: Record<string, string | null | undefined>): Mapping {
|
|
145
167
|
const resolved = { ...mapping }
|
|
146
168
|
for (const [key, fallbackKey] of Object.entries(COLOR_FALLBACKS)) {
|
|
147
169
|
if (resolved[key] === null || resolved[key] === undefined) {
|
|
148
170
|
resolved[key] = resolved[fallbackKey] ?? DEFAULT_THEME_MAPPING[fallbackKey]
|
|
149
171
|
}
|
|
150
172
|
}
|
|
151
|
-
return resolved
|
|
173
|
+
return resolved as Mapping
|
|
152
174
|
}
|
|
153
175
|
|
|
154
176
|
/**
|
|
155
177
|
* Theme class for managing color palettes, mappings, and semantic shortcuts.
|
|
156
178
|
*/
|
|
157
179
|
export class Theme {
|
|
158
|
-
#colors
|
|
159
|
-
#mapping
|
|
160
|
-
#adapter
|
|
180
|
+
#colors: Colors
|
|
181
|
+
#mapping: Mapping
|
|
182
|
+
#adapter: Adapter
|
|
161
183
|
|
|
162
184
|
/**
|
|
163
185
|
*
|
|
164
186
|
* @param {import('./types.js').ColorTheme & { colorSpace?: string }} param0
|
|
165
187
|
*/
|
|
166
|
-
constructor({
|
|
167
|
-
|
|
188
|
+
constructor({
|
|
189
|
+
colors = DEFAULT_COLORS,
|
|
190
|
+
mapping = DEFAULT_THEME_MAPPING as Record<string, string | null>,
|
|
191
|
+
colorSpace = 'rgb'
|
|
192
|
+
}: { colors?: Colors; mapping?: Record<string, string | null>; colorSpace?: string } = {}) {
|
|
193
|
+
this.#colors = { ...(DEFAULT_COLORS), ...colors }
|
|
168
194
|
this.#mapping = resolveColors({ ...DEFAULT_THEME_MAPPING, ...mapping })
|
|
169
195
|
this.#adapter = ColorSpace.create(colorSpace)
|
|
170
196
|
}
|
|
@@ -172,26 +198,26 @@ export class Theme {
|
|
|
172
198
|
get colors() {
|
|
173
199
|
return this.#colors
|
|
174
200
|
}
|
|
175
|
-
set colors(colors) {
|
|
201
|
+
set colors(colors: Colors) {
|
|
176
202
|
this.#colors = { ...colors }
|
|
177
203
|
}
|
|
178
204
|
|
|
179
205
|
get mapping() {
|
|
180
206
|
return this.#mapping
|
|
181
207
|
}
|
|
182
|
-
set mapping(mapping) {
|
|
208
|
+
set mapping(mapping: Record<string, string | null>) {
|
|
183
209
|
this.#mapping = resolveColors({ ...mapping })
|
|
184
210
|
}
|
|
185
211
|
|
|
186
212
|
get colorSpace() {
|
|
187
213
|
return this.#adapter.name
|
|
188
214
|
}
|
|
189
|
-
set colorSpace(colorSpace) {
|
|
215
|
+
set colorSpace(colorSpace: string) {
|
|
190
216
|
this.#adapter = ColorSpace.create(colorSpace)
|
|
191
217
|
}
|
|
192
218
|
|
|
193
|
-
mapVariant(color, variant) {
|
|
194
|
-
return Object.keys(color).reduce(
|
|
219
|
+
mapVariant(color: Palette, variant: string): Record<string, string> {
|
|
220
|
+
return Object.keys(color).reduce<Record<string, string>>(
|
|
195
221
|
(acc, key) => ({
|
|
196
222
|
...acc,
|
|
197
223
|
[key]:
|
|
@@ -203,9 +229,9 @@ export class Theme {
|
|
|
203
229
|
)
|
|
204
230
|
}
|
|
205
231
|
|
|
206
|
-
getColorRules(mapping = null) {
|
|
232
|
+
getColorRules(mapping: Mapping | null = null): Record<string, Record<string, string>> {
|
|
207
233
|
const variants = Object.entries({ ...this.#mapping, ...mapping })
|
|
208
|
-
return variants.reduce(
|
|
234
|
+
return variants.reduce<Record<string, Record<string, string>>>(
|
|
209
235
|
(acc, [variant, key]) => ({
|
|
210
236
|
...acc,
|
|
211
237
|
[variant]: this.mapVariant(this.#colors[key], variant)
|
|
@@ -214,13 +240,13 @@ export class Theme {
|
|
|
214
240
|
)
|
|
215
241
|
}
|
|
216
242
|
|
|
217
|
-
getPalette(mapping = null) {
|
|
243
|
+
getPalette(mapping: Mapping | null = null): Record<string, string> {
|
|
218
244
|
const useMapping = { ...this.#mapping, ...mapping }
|
|
219
|
-
const useColors = { ...
|
|
245
|
+
const useColors = { ...(DEFAULT_COLORS), ...this.#colors }
|
|
220
246
|
const variants = Object.keys(useMapping)
|
|
221
247
|
const rules = variants
|
|
222
248
|
.flatMap((variant) => generateColorRules(variant, useColors, useMapping, this.#adapter))
|
|
223
|
-
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
249
|
+
.reduce<Record<string, string>>((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
224
250
|
return rules
|
|
225
251
|
}
|
|
226
252
|
|
|
@@ -245,7 +271,7 @@ export class Theme {
|
|
|
245
271
|
* (and for the whole map when undefined).
|
|
246
272
|
*/
|
|
247
273
|
getNamedTokens(_mode = 'light', perRoleModes?: Record<string, 'core' | 'extended'>) {
|
|
248
|
-
const colors = { ...
|
|
274
|
+
const colors: Colors = { ...(DEFAULT_COLORS), ...this.#colors }
|
|
249
275
|
const result: Record<string, string> = {}
|
|
250
276
|
for (const name of NAMED_TOKENS) {
|
|
251
277
|
const value = this.#resolveNamedToken(name, colors, perRoleModes)
|
|
@@ -258,7 +284,7 @@ export class Theme {
|
|
|
258
284
|
* Resolves a single named token to its CSS value, respecting per-role mode.
|
|
259
285
|
* Returns undefined when the role's palette is missing.
|
|
260
286
|
*/
|
|
261
|
-
#resolveNamedToken(name:
|
|
287
|
+
#resolveNamedToken(name: NamedToken, colors: Record<string, Record<string, string>>, perRoleModes?: Record<string, 'core' | 'extended'>): string | undefined {
|
|
262
288
|
const role = NAMED_TOKEN_ROLE_MAP[name]
|
|
263
289
|
const shadeOrDerived = NAMED_TOKEN_SHADE_MAP[name]
|
|
264
290
|
const paletteName = this.#mapping[role]
|
|
@@ -330,7 +356,7 @@ export class Theme {
|
|
|
330
356
|
* or near-white), matching the core-mode derivation.
|
|
331
357
|
*/
|
|
332
358
|
getZAliasesForExtended(): Record<string, string> {
|
|
333
|
-
const colors = { ...
|
|
359
|
+
const colors: Colors = { ...(DEFAULT_COLORS), ...this.#colors }
|
|
334
360
|
const result: Record<string, string> = {}
|
|
335
361
|
for (const name of NAMED_TOKENS) {
|
|
336
362
|
const role = NAMED_TOKEN_ROLE_MAP[name]
|
|
@@ -350,7 +376,7 @@ export class Theme {
|
|
|
350
376
|
* Mirrors what getPalette does for all roles, but scoped to one.
|
|
351
377
|
*/
|
|
352
378
|
getPaletteForRole(role: string): Record<string, string> {
|
|
353
|
-
const colors = { ...
|
|
379
|
+
const colors: Colors = { ...(DEFAULT_COLORS), ...this.#colors }
|
|
354
380
|
const paletteName = this.#mapping[role]
|
|
355
381
|
if (!paletteName || !colors[paletteName]) return {}
|
|
356
382
|
const palette = colors[paletteName]
|
|
@@ -363,8 +389,8 @@ export class Theme {
|
|
|
363
389
|
return result
|
|
364
390
|
}
|
|
365
391
|
|
|
366
|
-
getShortcuts(name) {
|
|
367
|
-
const colors = { ...
|
|
392
|
+
getShortcuts(name: string) {
|
|
393
|
+
const colors: Colors = { ...(DEFAULT_COLORS), ...this.#colors }
|
|
368
394
|
return contrastShortcuts(name, this.#onColorHex(name, colors))
|
|
369
395
|
}
|
|
370
396
|
|