@rokkit/core 1.0.5 → 1.1.1
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/index.d.ts +1 -0
- package/dist/named-tokens.d.ts +55 -0
- package/dist/theme.d.ts +54 -0
- package/dist/utils.d.ts +9 -2
- package/package.json +2 -2
- package/src/constants.js +18 -1
- package/src/index.js +1 -0
- package/src/named-tokens.ts +161 -0
- package/src/theme.ts +198 -2
- package/src/utils.js +12 -3
package/dist/index.d.ts
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 24 canonical named tokens that constitute the "core" emit vocabulary.
|
|
3
|
+
* Order is significant for tests and for predictable CSS-var output ordering.
|
|
4
|
+
*/
|
|
5
|
+
export declare const NAMED_TOKENS: readonly ["paper", "paper-soft", "paper-mute", "paper-edge", "ink", "ink-mute", "ink-soft", "ink-faint", "primary", "on-primary", "accent", "accent-soft", "success", "success-soft", "warning", "warning-soft", "danger", "danger-soft", "error", "error-soft", "info", "info-soft", "focus-ring", "shadow-tint"];
|
|
6
|
+
export type NamedToken = (typeof NAMED_TOKENS)[number];
|
|
7
|
+
export type SkinRole = 'surface' | 'ink' | 'primary' | 'accent' | 'success' | 'warning' | 'danger' | 'error' | 'info';
|
|
8
|
+
export type ZSlot = 'z0' | 'z1' | 'z2' | 'z3' | 'z4' | 'z5' | 'z6' | 'z7' | 'z8' | 'z9' | 'z10';
|
|
9
|
+
export declare const Z_SLOTS: ZSlot[];
|
|
10
|
+
/**
|
|
11
|
+
* Maps each named token to the palette shade index that backs it.
|
|
12
|
+
* 'derived' indicates the token is computed from another palette (e.g., on-primary
|
|
13
|
+
* picks the paper shade of the surface palette by default for white-on-primary).
|
|
14
|
+
*
|
|
15
|
+
* paper: 50 (lightest surface tone, canvas)
|
|
16
|
+
* paper-soft: 100 (card background)
|
|
17
|
+
* paper-mute: 200 (subdued panel)
|
|
18
|
+
* paper-edge: 400 (hairline border tone)
|
|
19
|
+
* ink: 900 (primary text)
|
|
20
|
+
* ink-mute: 700 (secondary text)
|
|
21
|
+
* ink-soft: 500 (placeholder)
|
|
22
|
+
* ink-faint: 300 (disabled)
|
|
23
|
+
* primary: 500 (CTA fill)
|
|
24
|
+
* on-primary: derived — surface.50 default (white-on-primary)
|
|
25
|
+
* accent / status: 500 (solid)
|
|
26
|
+
* *-soft: 100 (tinted-bg companion)
|
|
27
|
+
* focus-ring: 500 of accent
|
|
28
|
+
* shadow-tint: 900 of ink
|
|
29
|
+
*/
|
|
30
|
+
export declare const NAMED_TOKEN_SHADE_MAP: Record<NamedToken, number | 'derived'>;
|
|
31
|
+
/**
|
|
32
|
+
* Maps each named token to the skin role whose palette it draws from.
|
|
33
|
+
*/
|
|
34
|
+
export declare const NAMED_TOKEN_ROLE_MAP: Record<NamedToken, SkinRole>;
|
|
35
|
+
/**
|
|
36
|
+
* Surface z-slot → named slot. Used to emit back-compat aliases like
|
|
37
|
+
* `--color-surface-z1: var(--paper-soft);` in core mode.
|
|
38
|
+
*
|
|
39
|
+
* z2/z3 collapse to paper-mute, z5/z6 to ink-soft, z7/z8 to ink-mute,
|
|
40
|
+
* z9/z10 to ink. This collapse is the contract: 4 surface tones in core mode.
|
|
41
|
+
*/
|
|
42
|
+
export declare const Z_COLLAPSE_MAP_SURFACE: Record<ZSlot, NamedToken>;
|
|
43
|
+
/**
|
|
44
|
+
* Ink role uses the inverted z-scale (z0 = darkest = primary text).
|
|
45
|
+
* In core mode, the same 4+4 named ladder is reused; this table just inverts.
|
|
46
|
+
*/
|
|
47
|
+
export declare const Z_COLLAPSE_MAP_INK: Record<ZSlot, NamedToken>;
|
|
48
|
+
/**
|
|
49
|
+
* Returns true when the role has a `-soft` companion in the named vocabulary.
|
|
50
|
+
* Used to decide whether the role's tinted-background slot collapses to
|
|
51
|
+
* `var(--{role}-soft)` or to `var(--{role})`.
|
|
52
|
+
*/
|
|
53
|
+
export declare function hasSoftCompanion(role: string): boolean;
|
|
54
|
+
export declare function shadeForNamedToken(name: string): number | 'derived' | undefined;
|
|
55
|
+
export declare function roleForNamedToken(name: string): SkinRole | undefined;
|
package/dist/theme.d.ts
CHANGED
|
@@ -80,6 +80,60 @@ export declare class Theme {
|
|
|
80
80
|
mapVariant(color: any, variant: any): {};
|
|
81
81
|
getColorRules(mapping?: null): {};
|
|
82
82
|
getPalette(mapping?: null): {};
|
|
83
|
+
/**
|
|
84
|
+
* Returns the named-token layer as a map of `--{name}: <resolved value>` entries.
|
|
85
|
+
*
|
|
86
|
+
* Palette values are inlined — there is no `var(--color-{role}-{shade})` indirection.
|
|
87
|
+
*
|
|
88
|
+
* `on-primary` is derived: it picks the paper shade (50) of the surface palette so the
|
|
89
|
+
* default contrast pair is "primary fill + white-ish text." Skins that need a different
|
|
90
|
+
* pair should override via custom tokens.
|
|
91
|
+
*
|
|
92
|
+
* `*-soft` variants resolve to shade 100 of their role's palette.
|
|
93
|
+
* `shadow-tint` resolves to shade 900 of the ink palette.
|
|
94
|
+
*
|
|
95
|
+
* @param {'light' | 'dark'} _mode — accepted for symmetry with future
|
|
96
|
+
* dark-aware derivations. Today the Theme is constructed with a mode-resolved
|
|
97
|
+
* mapping, so this parameter is informational.
|
|
98
|
+
* @param perRoleModes — optional map of role → 'core' | 'extended'. When a token's
|
|
99
|
+
* role is 'extended', the value is a `var(--color-{role}-{shade})` alias instead
|
|
100
|
+
* of the inlined palette value. Defaults to 'core' for all unspecified roles
|
|
101
|
+
* (and for the whole map when undefined).
|
|
102
|
+
*/
|
|
103
|
+
getNamedTokens(_mode?: string, perRoleModes?: Record<string, 'core' | 'extended'>): Record<string, string>;
|
|
104
|
+
/**
|
|
105
|
+
* Returns z-alias CSS-var assignments for back-compat in core mode.
|
|
106
|
+
* `--color-{role}-z{n}` → `var(--{namedSlot})`.
|
|
107
|
+
*
|
|
108
|
+
* - surface: uses Z_COLLAPSE_MAP_SURFACE (z2/z3 → paper-mute, z9/z10 → ink, etc.)
|
|
109
|
+
* - ink: uses Z_COLLAPSE_MAP_INK (inverted scale)
|
|
110
|
+
* - primary/accent/status: tint-vs-solid 2-state collapse.
|
|
111
|
+
* z0–z2 → role-soft (if it exists) else role; z3+ → role.
|
|
112
|
+
*
|
|
113
|
+
* This is the back-compat layer: existing `@apply bg-surface-z3` etc. resolves
|
|
114
|
+
* through these aliases until consumers migrate to the named vocabulary.
|
|
115
|
+
*/
|
|
116
|
+
/** Accepts SkinRole and any custom skin roles beyond the SkinRole literal union. */
|
|
117
|
+
getZAliasesForCore(role: string): Record<string, string>;
|
|
118
|
+
/**
|
|
119
|
+
* Returns named tokens as CSS-var aliases pointing at the palette layer.
|
|
120
|
+
* Used in extended mode where the preset emits the full --color-{role}-{shade}
|
|
121
|
+
* palette; named tokens become thin syntactic aliases over the palette.
|
|
122
|
+
*
|
|
123
|
+
* `on-primary` aliases to `var(--color-surface-50)` (derived: paper of surface,
|
|
124
|
+
* matching the core-mode resolution).
|
|
125
|
+
*/
|
|
126
|
+
getZAliasesForExtended(): Record<string, string>;
|
|
127
|
+
/**
|
|
128
|
+
* Emit the full --color-{role}-{shade} palette CSS vars for a single role.
|
|
129
|
+
* Mirrors what getPalette does for all roles, but scoped to one.
|
|
130
|
+
*/
|
|
131
|
+
getPaletteForRole(role: string): Record<string, string>;
|
|
132
|
+
/**
|
|
133
|
+
* Emit z-aliases for one role in extended mode — they point at the palette vars,
|
|
134
|
+
* using TONE_MAP for surface/non-inverted roles and the inverted map for ink.
|
|
135
|
+
*/
|
|
136
|
+
getZAliasesForRoleExtended(role: string): Record<string, string>;
|
|
83
137
|
getShortcuts(name: any): (string[] | (RegExp | (([, variant, end]: [any, any, any]) => string))[] | (RegExp | (([, end]: [any, any]) => string))[])[];
|
|
84
138
|
/**
|
|
85
139
|
* Generates CSS custom property declarations for the semantic z0–z10 tone scale.
|
package/dist/utils.d.ts
CHANGED
|
@@ -101,9 +101,16 @@ export function hex2oklch(hex: string): string;
|
|
|
101
101
|
*/
|
|
102
102
|
export function oklch2hex(L: number, C: number, H: number): string;
|
|
103
103
|
/**
|
|
104
|
-
* Detects whether an icon value is a CSS class
|
|
104
|
+
* Detects whether an icon value is a CSS class or a literal character
|
|
105
|
+
* (kanji, emoji, single letter, etc.).
|
|
106
|
+
*
|
|
107
|
+
* Anything more than one grapheme is treated as a class — including bare
|
|
108
|
+
* semantic names like `file-svelte` which UnoCSS expands to the configured
|
|
109
|
+
* icon collection via `iconShortcuts(DEFAULT_ICONS, …)`. Single characters
|
|
110
|
+
* (kanji, emoji, single letters) render as literal text.
|
|
111
|
+
*
|
|
105
112
|
* @param {string | null | undefined} icon
|
|
106
|
-
* @returns {boolean} true if icon
|
|
113
|
+
* @returns {boolean} true if icon should render as a CSS class
|
|
107
114
|
*/
|
|
108
115
|
export function isIconClass(icon: string | null | undefined): boolean;
|
|
109
116
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rokkit/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Contains core utility functions and classes that can be used in various components.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"ramda": "^0.32.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@rokkit/icons": "1.
|
|
49
|
+
"@rokkit/icons": "1.1.1"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/src/constants.js
CHANGED
|
@@ -79,6 +79,7 @@ export const DEFAULT_ICONS = [
|
|
|
79
79
|
'action-close',
|
|
80
80
|
'action-copy',
|
|
81
81
|
'action-copysuccess',
|
|
82
|
+
'action-download',
|
|
82
83
|
'action-check',
|
|
83
84
|
'action-pin',
|
|
84
85
|
'action-save',
|
|
@@ -87,6 +88,20 @@ export const DEFAULT_ICONS = [
|
|
|
87
88
|
'node-closed',
|
|
88
89
|
'folder-opened',
|
|
89
90
|
'folder-closed',
|
|
91
|
+
'doc-default',
|
|
92
|
+
'doc-svelte',
|
|
93
|
+
'doc-js',
|
|
94
|
+
'doc-ts',
|
|
95
|
+
'doc-css',
|
|
96
|
+
'doc-html',
|
|
97
|
+
'doc-json',
|
|
98
|
+
'doc-md',
|
|
99
|
+
'doc-text',
|
|
100
|
+
'doc-pdf',
|
|
101
|
+
'doc-archive',
|
|
102
|
+
'media-image',
|
|
103
|
+
'media-video',
|
|
104
|
+
'media-audio',
|
|
90
105
|
'selector-opened',
|
|
91
106
|
'selector-closed',
|
|
92
107
|
'menu-opened',
|
|
@@ -133,7 +148,9 @@ export const DEFAULT_ICONS = [
|
|
|
133
148
|
'align-vertical-bottom',
|
|
134
149
|
'align-vertical-middle',
|
|
135
150
|
'view-code',
|
|
136
|
-
'view-chart'
|
|
151
|
+
'view-chart',
|
|
152
|
+
'view-preview',
|
|
153
|
+
'view-off'
|
|
137
154
|
]
|
|
138
155
|
|
|
139
156
|
export const DEFAULT_OPTIONS = {
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export * from './types.js'
|
|
3
3
|
// skipcq: JS-E1004 - Needed for exposing all constants
|
|
4
4
|
export * from './constants.js'
|
|
5
|
+
export * from './named-tokens.ts'
|
|
5
6
|
// skipcq: JS-E1004 - Needed for exposing all functions
|
|
6
7
|
export * from './utils.js'
|
|
7
8
|
// skipcq: JS-E1004 - Needed for exposing all functions
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 24 canonical named tokens that constitute the "core" emit vocabulary.
|
|
3
|
+
* Order is significant for tests and for predictable CSS-var output ordering.
|
|
4
|
+
*/
|
|
5
|
+
export const NAMED_TOKENS = [
|
|
6
|
+
'paper', 'paper-soft', 'paper-mute', 'paper-edge',
|
|
7
|
+
'ink', 'ink-mute', 'ink-soft', 'ink-faint',
|
|
8
|
+
'primary', 'on-primary',
|
|
9
|
+
'accent', 'accent-soft',
|
|
10
|
+
'success', 'success-soft',
|
|
11
|
+
'warning', 'warning-soft',
|
|
12
|
+
'danger', 'danger-soft',
|
|
13
|
+
'error', 'error-soft',
|
|
14
|
+
'info', 'info-soft',
|
|
15
|
+
'focus-ring', 'shadow-tint'
|
|
16
|
+
] as const
|
|
17
|
+
|
|
18
|
+
export type NamedToken = (typeof NAMED_TOKENS)[number]
|
|
19
|
+
|
|
20
|
+
export type SkinRole =
|
|
21
|
+
| 'surface' | 'ink' | 'primary' | 'accent'
|
|
22
|
+
| 'success' | 'warning' | 'danger' | 'error' | 'info'
|
|
23
|
+
|
|
24
|
+
export type ZSlot = 'z0' | 'z1' | 'z2' | 'z3' | 'z4' | 'z5' | 'z6' | 'z7' | 'z8' | 'z9' | 'z10'
|
|
25
|
+
|
|
26
|
+
export const Z_SLOTS: ZSlot[] = ['z0', 'z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8', 'z9', 'z10']
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Maps each named token to the palette shade index that backs it.
|
|
30
|
+
* 'derived' indicates the token is computed from another palette (e.g., on-primary
|
|
31
|
+
* picks the paper shade of the surface palette by default for white-on-primary).
|
|
32
|
+
*
|
|
33
|
+
* paper: 50 (lightest surface tone, canvas)
|
|
34
|
+
* paper-soft: 100 (card background)
|
|
35
|
+
* paper-mute: 200 (subdued panel)
|
|
36
|
+
* paper-edge: 400 (hairline border tone)
|
|
37
|
+
* ink: 900 (primary text)
|
|
38
|
+
* ink-mute: 700 (secondary text)
|
|
39
|
+
* ink-soft: 500 (placeholder)
|
|
40
|
+
* ink-faint: 300 (disabled)
|
|
41
|
+
* primary: 500 (CTA fill)
|
|
42
|
+
* on-primary: derived — surface.50 default (white-on-primary)
|
|
43
|
+
* accent / status: 500 (solid)
|
|
44
|
+
* *-soft: 100 (tinted-bg companion)
|
|
45
|
+
* focus-ring: 500 of accent
|
|
46
|
+
* shadow-tint: 900 of ink
|
|
47
|
+
*/
|
|
48
|
+
export const NAMED_TOKEN_SHADE_MAP: Record<NamedToken, number | 'derived'> = {
|
|
49
|
+
paper: 50,
|
|
50
|
+
'paper-soft': 100,
|
|
51
|
+
'paper-mute': 200,
|
|
52
|
+
'paper-edge': 400,
|
|
53
|
+
ink: 900,
|
|
54
|
+
'ink-mute': 700,
|
|
55
|
+
'ink-soft': 500,
|
|
56
|
+
'ink-faint': 300,
|
|
57
|
+
primary: 500,
|
|
58
|
+
'on-primary': 'derived',
|
|
59
|
+
accent: 500,
|
|
60
|
+
'accent-soft': 100,
|
|
61
|
+
success: 500,
|
|
62
|
+
'success-soft': 100,
|
|
63
|
+
warning: 500,
|
|
64
|
+
'warning-soft': 100,
|
|
65
|
+
danger: 500,
|
|
66
|
+
'danger-soft': 100,
|
|
67
|
+
error: 500,
|
|
68
|
+
'error-soft': 100,
|
|
69
|
+
info: 500,
|
|
70
|
+
'info-soft': 100,
|
|
71
|
+
'focus-ring': 500,
|
|
72
|
+
'shadow-tint': 900
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Maps each named token to the skin role whose palette it draws from.
|
|
77
|
+
*/
|
|
78
|
+
export const NAMED_TOKEN_ROLE_MAP: Record<NamedToken, SkinRole> = {
|
|
79
|
+
paper: 'surface',
|
|
80
|
+
'paper-soft': 'surface',
|
|
81
|
+
'paper-mute': 'surface',
|
|
82
|
+
'paper-edge': 'surface',
|
|
83
|
+
ink: 'ink',
|
|
84
|
+
'ink-mute': 'ink',
|
|
85
|
+
'ink-soft': 'ink',
|
|
86
|
+
'ink-faint': 'ink',
|
|
87
|
+
primary: 'primary',
|
|
88
|
+
'on-primary': 'primary',
|
|
89
|
+
accent: 'accent',
|
|
90
|
+
'accent-soft': 'accent',
|
|
91
|
+
success: 'success',
|
|
92
|
+
'success-soft': 'success',
|
|
93
|
+
warning: 'warning',
|
|
94
|
+
'warning-soft': 'warning',
|
|
95
|
+
danger: 'danger',
|
|
96
|
+
'danger-soft': 'danger',
|
|
97
|
+
error: 'error',
|
|
98
|
+
'error-soft': 'error',
|
|
99
|
+
info: 'info',
|
|
100
|
+
'info-soft': 'info',
|
|
101
|
+
'focus-ring': 'accent',
|
|
102
|
+
'shadow-tint': 'ink'
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Surface z-slot → named slot. Used to emit back-compat aliases like
|
|
107
|
+
* `--color-surface-z1: var(--paper-soft);` in core mode.
|
|
108
|
+
*
|
|
109
|
+
* z2/z3 collapse to paper-mute, z5/z6 to ink-soft, z7/z8 to ink-mute,
|
|
110
|
+
* z9/z10 to ink. This collapse is the contract: 4 surface tones in core mode.
|
|
111
|
+
*/
|
|
112
|
+
export const Z_COLLAPSE_MAP_SURFACE: Record<ZSlot, NamedToken> = {
|
|
113
|
+
z0: 'paper',
|
|
114
|
+
z1: 'paper-soft',
|
|
115
|
+
z2: 'paper-mute',
|
|
116
|
+
z3: 'paper-mute',
|
|
117
|
+
z4: 'paper-edge',
|
|
118
|
+
z5: 'ink-soft',
|
|
119
|
+
z6: 'ink-soft',
|
|
120
|
+
z7: 'ink-mute',
|
|
121
|
+
z8: 'ink-mute',
|
|
122
|
+
z9: 'ink',
|
|
123
|
+
z10: 'ink'
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Ink role uses the inverted z-scale (z0 = darkest = primary text).
|
|
128
|
+
* In core mode, the same 4+4 named ladder is reused; this table just inverts.
|
|
129
|
+
*/
|
|
130
|
+
export const Z_COLLAPSE_MAP_INK: Record<ZSlot, NamedToken> = {
|
|
131
|
+
z0: 'ink',
|
|
132
|
+
z1: 'ink-mute',
|
|
133
|
+
z2: 'ink-mute',
|
|
134
|
+
z3: 'ink-soft',
|
|
135
|
+
z4: 'ink-soft',
|
|
136
|
+
z5: 'paper-edge',
|
|
137
|
+
z6: 'paper-edge',
|
|
138
|
+
z7: 'paper-mute',
|
|
139
|
+
z8: 'paper-mute',
|
|
140
|
+
z9: 'paper-soft',
|
|
141
|
+
z10: 'paper'
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const SOFT_TOKENS: Set<string> = new Set(NAMED_TOKENS.filter((t) => t.endsWith('-soft')))
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Returns true when the role has a `-soft` companion in the named vocabulary.
|
|
148
|
+
* Used to decide whether the role's tinted-background slot collapses to
|
|
149
|
+
* `var(--{role}-soft)` or to `var(--{role})`.
|
|
150
|
+
*/
|
|
151
|
+
export function hasSoftCompanion(role: string): boolean {
|
|
152
|
+
return SOFT_TOKENS.has(`${role}-soft`)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function shadeForNamedToken(name: string): number | 'derived' | undefined {
|
|
156
|
+
return NAMED_TOKEN_SHADE_MAP[name as NamedToken]
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function roleForNamedToken(name: string): SkinRole | undefined {
|
|
160
|
+
return NAMED_TOKEN_ROLE_MAP[name as NamedToken]
|
|
161
|
+
}
|
package/src/theme.ts
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
import { DEFAULT_THEME_MAPPING, defaultColors, TONE_MAP, INVERTED_ROLES } from './constants'
|
|
4
4
|
import { shades } from './colors/index'
|
|
5
5
|
import { ColorSpace } from './color-space'
|
|
6
|
+
import {
|
|
7
|
+
NAMED_TOKENS,
|
|
8
|
+
NAMED_TOKEN_SHADE_MAP,
|
|
9
|
+
NAMED_TOKEN_ROLE_MAP,
|
|
10
|
+
Z_COLLAPSE_MAP_SURFACE,
|
|
11
|
+
Z_COLLAPSE_MAP_INK,
|
|
12
|
+
Z_SLOTS,
|
|
13
|
+
hasSoftCompanion
|
|
14
|
+
} from './named-tokens'
|
|
6
15
|
|
|
7
16
|
/**
|
|
8
17
|
* Generate shades for a color using css variable and a ColorSpace adapter.
|
|
@@ -109,9 +118,11 @@ function toneShortcuts({ prefix, name, toneName, lightValue, darkValue }) {
|
|
|
109
118
|
* @returns {Array} Array of shortcut definitions
|
|
110
119
|
*/
|
|
111
120
|
export function semanticShortcuts(name) {
|
|
121
|
+
const inverted = INVERTED_ROLES.has(name)
|
|
112
122
|
const shortcuts = []
|
|
113
|
-
for (const [toneName,
|
|
114
|
-
const
|
|
123
|
+
for (const [toneName, toneValue] of Object.entries(TONE_MAP)) {
|
|
124
|
+
const lightValue = inverted ? 1000 - toneValue : toneValue
|
|
125
|
+
const darkValue = inverted ? toneValue : 1000 - toneValue
|
|
115
126
|
for (const prefix of SEMANTIC_PREFIXES) {
|
|
116
127
|
shortcuts.push(...toneShortcuts({ prefix, name, toneName, lightValue, darkValue }))
|
|
117
128
|
}
|
|
@@ -241,6 +252,191 @@ export class Theme {
|
|
|
241
252
|
return rules
|
|
242
253
|
}
|
|
243
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Returns the named-token layer as a map of `--{name}: <resolved value>` entries.
|
|
257
|
+
*
|
|
258
|
+
* Palette values are inlined — there is no `var(--color-{role}-{shade})` indirection.
|
|
259
|
+
*
|
|
260
|
+
* `on-primary` is derived: it picks the paper shade (50) of the surface palette so the
|
|
261
|
+
* default contrast pair is "primary fill + white-ish text." Skins that need a different
|
|
262
|
+
* pair should override via custom tokens.
|
|
263
|
+
*
|
|
264
|
+
* `*-soft` variants resolve to shade 100 of their role's palette.
|
|
265
|
+
* `shadow-tint` resolves to shade 900 of the ink palette.
|
|
266
|
+
*
|
|
267
|
+
* @param {'light' | 'dark'} _mode — accepted for symmetry with future
|
|
268
|
+
* dark-aware derivations. Today the Theme is constructed with a mode-resolved
|
|
269
|
+
* mapping, so this parameter is informational.
|
|
270
|
+
* @param perRoleModes — optional map of role → 'core' | 'extended'. When a token's
|
|
271
|
+
* role is 'extended', the value is a `var(--color-{role}-{shade})` alias instead
|
|
272
|
+
* of the inlined palette value. Defaults to 'core' for all unspecified roles
|
|
273
|
+
* (and for the whole map when undefined).
|
|
274
|
+
*/
|
|
275
|
+
getNamedTokens(_mode = 'light', perRoleModes?: Record<string, 'core' | 'extended'>) {
|
|
276
|
+
const colors = { ...defaultColors, ...this.#colors }
|
|
277
|
+
const result: Record<string, string> = {}
|
|
278
|
+
for (const name of NAMED_TOKENS) {
|
|
279
|
+
const value = this.#resolveNamedToken(name, colors, perRoleModes)
|
|
280
|
+
if (value !== undefined) result[`--${name}`] = value
|
|
281
|
+
}
|
|
282
|
+
return result
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Resolves a single named token to its CSS value, respecting per-role mode.
|
|
287
|
+
* Returns undefined when the role's palette is missing.
|
|
288
|
+
*/
|
|
289
|
+
#resolveNamedToken(name: string, colors: Record<string, Record<string, string>>, perRoleModes?: Record<string, 'core' | 'extended'>): string | undefined {
|
|
290
|
+
const role = NAMED_TOKEN_ROLE_MAP[name]
|
|
291
|
+
const shadeOrDerived = NAMED_TOKEN_SHADE_MAP[name]
|
|
292
|
+
const paletteName = this.#mapping[role]
|
|
293
|
+
if (!paletteName || !colors[paletteName]) return undefined
|
|
294
|
+
if (shadeOrDerived === 'derived') return this.#resolveDerivedToken(name, colors, perRoleModes)
|
|
295
|
+
return this.#resolveShadeToken(role, shadeOrDerived as number, colors[paletteName], perRoleModes)
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Resolves a shade-based named token value in either core (inline) or extended (alias) mode.
|
|
300
|
+
*/
|
|
301
|
+
#resolveShadeToken(role: string, shade: number, palette: Record<string, string>, perRoleModes?: Record<string, 'core' | 'extended'>): string | undefined {
|
|
302
|
+
const roleMode = perRoleModes?.[role] ?? 'core'
|
|
303
|
+
if (roleMode === 'extended') return `var(--color-${role}-${shade})`
|
|
304
|
+
const raw = palette[String(shade)]
|
|
305
|
+
return raw !== undefined ? this.#adapter.wrap(raw) : undefined
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Resolves a 'derived' named token. Today only `on-primary` is derived — it picks
|
|
310
|
+
* shade 50 from the surface palette for the default white-on-primary contrast pair.
|
|
311
|
+
*/
|
|
312
|
+
#resolveDerivedToken(name: string, colors: Record<string, Record<string, string>>, perRoleModes?: Record<string, 'core' | 'extended'>): string | undefined {
|
|
313
|
+
if (name === 'on-primary') {
|
|
314
|
+
const surfacePaletteName = this.#mapping['surface']
|
|
315
|
+
const surfacePalette = colors[surfacePaletteName]
|
|
316
|
+
if (!surfacePalette?.['50']) return undefined
|
|
317
|
+
const surfaceMode = perRoleModes?.['surface'] ?? 'core'
|
|
318
|
+
if (surfaceMode === 'extended') {
|
|
319
|
+
return `var(--color-surface-50)`
|
|
320
|
+
}
|
|
321
|
+
return this.#adapter.wrap(surfacePalette['50'])
|
|
322
|
+
}
|
|
323
|
+
return undefined
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Generate z-aliases for surface or ink role using the provided map.
|
|
328
|
+
*/
|
|
329
|
+
#getZAliasesFromMap(role: 'surface' | 'ink', map: Record<ZSlot, NamedToken>): Record<string, string> {
|
|
330
|
+
const result: Record<string, string> = {}
|
|
331
|
+
// Bare `--color-{role}` alias — points at the role's primary named
|
|
332
|
+
// slot. Lets preset-wind3 color utilities (bg-surface, from-surface,
|
|
333
|
+
// to-surface, etc.) resolve in core mode without forcing the full
|
|
334
|
+
// palette emit. Surface → paper, Ink → ink.
|
|
335
|
+
result[`--color-${role}`] = role === 'surface' ? 'var(--paper)' : 'var(--ink)'
|
|
336
|
+
for (const z of Z_SLOTS) {
|
|
337
|
+
result[`--color-${role}-${z}`] = `var(--${map[z]})`
|
|
338
|
+
}
|
|
339
|
+
return result
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Generate z-aliases for other roles using tint-vs-solid 2-state collapse.
|
|
344
|
+
*/
|
|
345
|
+
#getZAliasesOther(role: string): Record<string, string> {
|
|
346
|
+
const result: Record<string, string> = {}
|
|
347
|
+
const hasSoft = hasSoftCompanion(role)
|
|
348
|
+
const softTarget = hasSoft ? `${role}-soft` : role
|
|
349
|
+
// Bare `--color-{role}` alias points at the named token so
|
|
350
|
+
// preset-wind3 color utilities (from-{role}, to-{role}, divide-{role},
|
|
351
|
+
// etc.) resolve in core mode — they read `--color-{role}` and we'd
|
|
352
|
+
// otherwise leave it undefined since core mode skips the palette emit.
|
|
353
|
+
result[`--color-${role}`] = `var(--${role})`
|
|
354
|
+
for (const z of Z_SLOTS) {
|
|
355
|
+
const zNum = parseInt(z.slice(1), 10)
|
|
356
|
+
const target = zNum <= 2 ? softTarget : role
|
|
357
|
+
result[`--color-${role}-${z}`] = `var(--${target})`
|
|
358
|
+
}
|
|
359
|
+
return result
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Returns z-alias CSS-var assignments for back-compat in core mode.
|
|
364
|
+
* `--color-{role}-z{n}` → `var(--{namedSlot})`.
|
|
365
|
+
*
|
|
366
|
+
* - surface: uses Z_COLLAPSE_MAP_SURFACE (z2/z3 → paper-mute, z9/z10 → ink, etc.)
|
|
367
|
+
* - ink: uses Z_COLLAPSE_MAP_INK (inverted scale)
|
|
368
|
+
* - primary/accent/status: tint-vs-solid 2-state collapse.
|
|
369
|
+
* z0–z2 → role-soft (if it exists) else role; z3+ → role.
|
|
370
|
+
*
|
|
371
|
+
* This is the back-compat layer: existing `@apply bg-surface-z3` etc. resolves
|
|
372
|
+
* through these aliases until consumers migrate to the named vocabulary.
|
|
373
|
+
*/
|
|
374
|
+
/** Accepts SkinRole and any custom skin roles beyond the SkinRole literal union. */
|
|
375
|
+
getZAliasesForCore(role: string): Record<string, string> {
|
|
376
|
+
if (role === 'surface') {
|
|
377
|
+
return this.#getZAliasesFromMap('surface', Z_COLLAPSE_MAP_SURFACE)
|
|
378
|
+
}
|
|
379
|
+
if (role === 'ink') {
|
|
380
|
+
return this.#getZAliasesFromMap('ink', Z_COLLAPSE_MAP_INK)
|
|
381
|
+
}
|
|
382
|
+
return this.#getZAliasesOther(role)
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Returns named tokens as CSS-var aliases pointing at the palette layer.
|
|
387
|
+
* Used in extended mode where the preset emits the full --color-{role}-{shade}
|
|
388
|
+
* palette; named tokens become thin syntactic aliases over the palette.
|
|
389
|
+
*
|
|
390
|
+
* `on-primary` aliases to `var(--color-surface-50)` (derived: paper of surface,
|
|
391
|
+
* matching the core-mode resolution).
|
|
392
|
+
*/
|
|
393
|
+
getZAliasesForExtended(): Record<string, string> {
|
|
394
|
+
const result: Record<string, string> = {}
|
|
395
|
+
for (const name of NAMED_TOKENS) {
|
|
396
|
+
const role = NAMED_TOKEN_ROLE_MAP[name]
|
|
397
|
+
const shadeOrDerived = NAMED_TOKEN_SHADE_MAP[name]
|
|
398
|
+
if (shadeOrDerived === 'derived') {
|
|
399
|
+
// on-primary → surface.50
|
|
400
|
+
result[`--${name}`] = `var(--color-surface-50)`
|
|
401
|
+
continue
|
|
402
|
+
}
|
|
403
|
+
result[`--${name}`] = `var(--color-${role}-${shadeOrDerived})`
|
|
404
|
+
}
|
|
405
|
+
return result
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Emit the full --color-{role}-{shade} palette CSS vars for a single role.
|
|
410
|
+
* Mirrors what getPalette does for all roles, but scoped to one.
|
|
411
|
+
*/
|
|
412
|
+
getPaletteForRole(role: string): Record<string, string> {
|
|
413
|
+
const colors = { ...defaultColors, ...this.#colors }
|
|
414
|
+
const paletteName = this.#mapping[role]
|
|
415
|
+
if (!paletteName || !colors[paletteName]) return {}
|
|
416
|
+
const palette = colors[paletteName]
|
|
417
|
+
const result: Record<string, string> = {}
|
|
418
|
+
for (const shade of shades) {
|
|
419
|
+
if (palette[shade] !== undefined) {
|
|
420
|
+
result[`--color-${role}-${shade}`] = this.#adapter.wrap(palette[shade])
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return result
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Emit z-aliases for one role in extended mode — they point at the palette vars,
|
|
428
|
+
* using TONE_MAP for surface/non-inverted roles and the inverted map for ink.
|
|
429
|
+
*/
|
|
430
|
+
getZAliasesForRoleExtended(role: string): Record<string, string> {
|
|
431
|
+
const result: Record<string, string> = {}
|
|
432
|
+
const isInverted = INVERTED_ROLES.has(role)
|
|
433
|
+
for (const [zone, light] of Object.entries(TONE_MAP)) {
|
|
434
|
+
const shade = isInverted ? 1000 - light : light
|
|
435
|
+
result[`--color-${role}-${zone}`] = `var(--color-${role}-${shade})`
|
|
436
|
+
}
|
|
437
|
+
return result
|
|
438
|
+
}
|
|
439
|
+
|
|
244
440
|
getShortcuts(name) {
|
|
245
441
|
return [...semanticShortcuts(name), ...contrastShortcuts(name)]
|
|
246
442
|
}
|
package/src/utils.js
CHANGED
|
@@ -318,13 +318,22 @@ export function oklch2hex(L, C, H) {
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
/**
|
|
321
|
-
* Detects whether an icon value is a CSS class
|
|
321
|
+
* Detects whether an icon value is a CSS class or a literal character
|
|
322
|
+
* (kanji, emoji, single letter, etc.).
|
|
323
|
+
*
|
|
324
|
+
* Anything more than one grapheme is treated as a class — including bare
|
|
325
|
+
* semantic names like `file-svelte` which UnoCSS expands to the configured
|
|
326
|
+
* icon collection via `iconShortcuts(DEFAULT_ICONS, …)`. Single characters
|
|
327
|
+
* (kanji, emoji, single letters) render as literal text.
|
|
328
|
+
*
|
|
322
329
|
* @param {string | null | undefined} icon
|
|
323
|
-
* @returns {boolean} true if icon
|
|
330
|
+
* @returns {boolean} true if icon should render as a CSS class
|
|
324
331
|
*/
|
|
325
332
|
export function isIconClass(icon) {
|
|
326
333
|
if (!icon || typeof icon !== 'string') return false
|
|
327
|
-
|
|
334
|
+
// Spread to count graphemes, not UTF-16 code units, so multi-codepoint
|
|
335
|
+
// emoji (e.g. 👨👩👧👦) and single CJK characters don't get misread.
|
|
336
|
+
return [...icon].length > 1
|
|
328
337
|
}
|
|
329
338
|
|
|
330
339
|
/**
|