@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rokkit/core",
3
- "version": "1.0.0-next.130",
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.130"
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
+ }