@rokkit/core 1.0.0-next.130 → 1.0.0-next.132
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/package.json +3 -2
- package/src/colors/index.ts +24 -0
- package/src/theme.ts +192 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rokkit/core",
|
|
3
|
-
"version": "1.0.0-next.
|
|
3
|
+
"version": "1.0.0-next.132",
|
|
4
4
|
"description": "Contains core utility functions and classes that can be used in various components.",
|
|
5
5
|
"author": "Jerry Thomas <me@jerrythomas.name>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"src/**/*.js",
|
|
18
|
+
"src/**/*.ts",
|
|
18
19
|
"src/**/*.json",
|
|
19
20
|
"dist/**/*.d.ts",
|
|
20
21
|
"README.md",
|
|
@@ -39,6 +40,6 @@
|
|
|
39
40
|
"ramda": "^0.32.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@rokkit/icons": "1.0.0-next.
|
|
43
|
+
"@rokkit/icons": "1.0.0-next.132"
|
|
43
44
|
}
|
|
44
45
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { colors } from '@unocss/preset-mini/colors'
|
|
4
|
+
import type { PresetMiniColors } from '@unocss/preset-mini/colors'
|
|
5
|
+
import syntaxColorPalette from './syntax.json' with { type: 'json' }
|
|
6
|
+
import extraColors from './extra.json' with { type: 'json' }
|
|
7
|
+
|
|
8
|
+
export const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
|
|
9
|
+
export const defaultPalette = [
|
|
10
|
+
'surface',
|
|
11
|
+
'primary',
|
|
12
|
+
'secondary',
|
|
13
|
+
'accent',
|
|
14
|
+
'success',
|
|
15
|
+
'warning',
|
|
16
|
+
'danger',
|
|
17
|
+
'info'
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
export const syntaxColors = syntaxColorPalette
|
|
21
|
+
export const defaultColors: PresetMiniColors & typeof extraColors = {
|
|
22
|
+
...colors,
|
|
23
|
+
...extraColors
|
|
24
|
+
}
|
package/src/theme.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { DEFAULT_THEME_MAPPING, defaultColors, TONE_MAP } from './constants'
|
|
4
|
+
import { shades } from './colors/index'
|
|
5
|
+
import { hex2rgb } from './utils'
|
|
6
|
+
|
|
7
|
+
const modifiers = {
|
|
8
|
+
hsl: (value) => `hsl(${value} / <alpha-value>)`,
|
|
9
|
+
rgb: (value) => `rgb(${value} / <alpha-value>)`,
|
|
10
|
+
none: (value) => value
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate shades for a color using css varuable
|
|
15
|
+
*
|
|
16
|
+
* @param {string} name
|
|
17
|
+
* @param {string} modifier
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export function shadesOf(name, modifier = 'none') {
|
|
21
|
+
const fn = modifier in modifiers ? modifiers[modifier] : modifiers.none
|
|
22
|
+
|
|
23
|
+
return shades.reduce(
|
|
24
|
+
(result, shade) => ({
|
|
25
|
+
...result,
|
|
26
|
+
[shade]: fn(`var(--color-${name}-${shade})`)
|
|
27
|
+
}),
|
|
28
|
+
{
|
|
29
|
+
DEFAULT: fn(`var(--color-${name}-500)`)
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Generates color rules for a specific theme variant, for both light and dark modes.
|
|
36
|
+
*
|
|
37
|
+
* @param {string} variant - The name of the variant to generate rules for.
|
|
38
|
+
* @param {Object} colors - The object containing color definitions.
|
|
39
|
+
* @param {Object} mapping - An object that maps variant names to color property names.
|
|
40
|
+
* @returns {import('./types').ShadeMappings} An array containing the color rules for both light and dark modes.
|
|
41
|
+
*/
|
|
42
|
+
function generateColorRules(variant, colors, mapping) {
|
|
43
|
+
return ['DEFAULT', ...shades].flatMap((shade) => [
|
|
44
|
+
{
|
|
45
|
+
key: shade === 'DEFAULT' ? `--color-${variant}` : `--color-${variant}-${shade}`,
|
|
46
|
+
value: hex2rgb(colors[mapping[variant]][`${shade}`])
|
|
47
|
+
}
|
|
48
|
+
])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Constructs and returns the light and dark theme variants based on provided color mapping and color definitions.
|
|
53
|
+
*
|
|
54
|
+
* @param {Object} [mapping=DEFAULT_THEME_MAPPING] - An object mapping variant names to color property names.
|
|
55
|
+
* @param {Object} [colors=defaultColors] - The object containing default color definitions.
|
|
56
|
+
* @returns {Array<Array>} An array containing two arrays, one for the light theme variant and another for the dark theme.
|
|
57
|
+
*/
|
|
58
|
+
export function themeRules(mapping = DEFAULT_THEME_MAPPING, colors = defaultColors) {
|
|
59
|
+
mapping = { ...DEFAULT_THEME_MAPPING, ...mapping }
|
|
60
|
+
colors = { ...defaultColors, ...colors }
|
|
61
|
+
const variants = Object.keys(mapping)
|
|
62
|
+
const rules = variants
|
|
63
|
+
.flatMap((variant) => generateColorRules(variant, colors, mapping))
|
|
64
|
+
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
65
|
+
|
|
66
|
+
return rules
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Generates UnoCSS shortcut definitions for semantic tones with bg, border, text.
|
|
71
|
+
* @param {string} name - Color name (e.g., 'primary')
|
|
72
|
+
* @returns {Array} Array of shortcut definitions
|
|
73
|
+
*/
|
|
74
|
+
export function semanticShortcuts(name) {
|
|
75
|
+
const prefixes = ['bg', 'border', 'border-l', 'border-r', 'border-t', 'border-b', 'text', 'ring', 'outline', 'from', 'to', 'divide']
|
|
76
|
+
const shortcuts = []
|
|
77
|
+
|
|
78
|
+
for (const [toneName, lightValue] of Object.entries(TONE_MAP)) {
|
|
79
|
+
const darkValue = 1000 - lightValue
|
|
80
|
+
|
|
81
|
+
for (const prefix of prefixes) {
|
|
82
|
+
// Variant-prefixed regex (e.g., hover:bg-primary-base)
|
|
83
|
+
const variantPattern = new RegExp(`^(.+):${prefix}-${name}-${toneName}(\/\\d+)?$`)
|
|
84
|
+
shortcuts.push([
|
|
85
|
+
variantPattern,
|
|
86
|
+
([, variant, end]) =>
|
|
87
|
+
`${variant}:${prefix}-${name}-${lightValue}${end || ''} ${variant}:dark:${prefix}-${name}-${darkValue}${end || ''}`
|
|
88
|
+
])
|
|
89
|
+
|
|
90
|
+
const opacityPattern = new RegExp(`^${prefix}-${name}-${toneName}(\/\\d+)?$`)
|
|
91
|
+
shortcuts.push([
|
|
92
|
+
opacityPattern,
|
|
93
|
+
([, end]) =>
|
|
94
|
+
`${prefix}-${name}-${lightValue}${end || ''} dark:${prefix}-${name}-${darkValue}${end || ''}`
|
|
95
|
+
])
|
|
96
|
+
|
|
97
|
+
// Exact static shortcut (e.g., bg-primary-base)
|
|
98
|
+
const exactPattern = `${prefix}-${name}-${toneName}`
|
|
99
|
+
shortcuts.push([
|
|
100
|
+
exactPattern,
|
|
101
|
+
`${prefix}-${name}-${lightValue} dark:${prefix}-${name}-${darkValue}`
|
|
102
|
+
])
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return shortcuts
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Generates "on-color" text shortcuts for readable text on colored backgrounds.
|
|
111
|
+
*
|
|
112
|
+
* - `text-on-{name}` → high contrast text for use on z5+ backgrounds (always light text)
|
|
113
|
+
* - `text-on-{name}-muted` → slightly muted but still readable on z5+ backgrounds
|
|
114
|
+
*
|
|
115
|
+
* @param {string} name - Color name (e.g., 'primary', 'surface')
|
|
116
|
+
* @returns {Array} Array of shortcut definitions
|
|
117
|
+
*/
|
|
118
|
+
export function contrastShortcuts(name) {
|
|
119
|
+
return [
|
|
120
|
+
[`text-on-${name}`, `text-${name}-50 dark:text-${name}-50`],
|
|
121
|
+
[`text-on-${name}-muted`, `text-${name}-100 dark:text-${name}-200`]
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Theme class for managing color palettes, mappings, and semantic shortcuts.
|
|
127
|
+
*/
|
|
128
|
+
export class Theme {
|
|
129
|
+
#colors
|
|
130
|
+
#mapping
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
*
|
|
134
|
+
* @param {import('./types.js').ColorTheme} param0
|
|
135
|
+
*/
|
|
136
|
+
constructor({ colors = defaultColors, mapping = DEFAULT_THEME_MAPPING } = {}) {
|
|
137
|
+
this.#colors = { ...defaultColors, ...colors }
|
|
138
|
+
this.#mapping = { ...DEFAULT_THEME_MAPPING, ...mapping }
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
get colors() {
|
|
142
|
+
return this.#colors
|
|
143
|
+
}
|
|
144
|
+
set colors(colors) {
|
|
145
|
+
this.#colors = { ...colors }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
get mapping() {
|
|
149
|
+
return this.#mapping
|
|
150
|
+
}
|
|
151
|
+
set mapping(mapping) {
|
|
152
|
+
this.#mapping = { ...mapping }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
mapVariant(color, variant) {
|
|
156
|
+
return Object.keys(color).reduce(
|
|
157
|
+
(acc, key) => ({
|
|
158
|
+
...acc,
|
|
159
|
+
[key]:
|
|
160
|
+
key === 'DEFAULT'
|
|
161
|
+
? `rgba(var(--color-${variant}),<alpha-value>)`
|
|
162
|
+
: `rgba(var(--color-${variant}-${key}),<alpha-value>)`
|
|
163
|
+
}),
|
|
164
|
+
{}
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getColorRules(mapping = null) {
|
|
169
|
+
const variants = Object.entries({ ...this.#mapping, ...mapping })
|
|
170
|
+
return variants.reduce(
|
|
171
|
+
(acc, [variant, key]) => ({
|
|
172
|
+
...acc,
|
|
173
|
+
[variant]: this.mapVariant(this.#colors[key], variant)
|
|
174
|
+
}),
|
|
175
|
+
{}
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getPalette(mapping = null) {
|
|
180
|
+
const useMapping = { ...this.#mapping, ...mapping }
|
|
181
|
+
const useColors = { ...defaultColors, ...this.#colors }
|
|
182
|
+
const variants = Object.keys(useMapping)
|
|
183
|
+
const rules = variants
|
|
184
|
+
.flatMap((variant) => generateColorRules(variant, useColors, useMapping))
|
|
185
|
+
.reduce((acc, { key, value }) => ({ ...acc, [key]: value }), {})
|
|
186
|
+
return rules
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
getShortcuts(name) {
|
|
190
|
+
return [...semanticShortcuts(name), ...contrastShortcuts(name)]
|
|
191
|
+
}
|
|
192
|
+
}
|