@codeleap/styles 5.5.0 → 5.5.3
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 +6 -4
- package/package.json.bak +5 -3
- package/src/index.ts +1 -0
- package/src/lib/Cacher.ts +49 -68
- package/src/lib/StyleCache.ts +1 -1
- package/src/lib/StylePersistor.ts +1 -1
- package/src/lib/StyleRegistry.ts +13 -19
- package/src/lib/borderCreator.ts +2 -2
- package/src/lib/createAppVariants.ts +1 -1
- package/src/lib/createStyles.ts +1 -1
- package/src/lib/createTheme.ts +48 -15
- package/src/lib/hooks.ts +13 -5
- package/src/lib/themeStore.ts +87 -10
- package/src/tools/colors.ts +106 -0
- package/src/tools/index.ts +1 -0
- package/src/types/store.ts +5 -0
- package/src/types/theme.ts +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/styles",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.3",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"directory": "packages/styles"
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
-
"@codeleap/config": "5.5.
|
|
12
|
+
"@codeleap/config": "5.5.3",
|
|
13
13
|
"ts-node-dev": "^1.1.8"
|
|
14
14
|
},
|
|
15
15
|
"scripts": {
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@fastify/deepmerge": "1.3.0",
|
|
29
|
+
"@nanostores/persistent": "^1.1.0",
|
|
30
|
+
"@nanostores/react": "^1.0.0",
|
|
29
31
|
"js-sha256": "0.11.0",
|
|
30
32
|
"lz-string": "^1.5.0",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
+
"nanostores": "^1.0.1",
|
|
34
|
+
"rfdc": "^1.4.1"
|
|
33
35
|
}
|
|
34
36
|
}
|
package/package.json.bak
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/styles",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.3",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@fastify/deepmerge": "1.3.0",
|
|
29
|
+
"@nanostores/persistent": "^1.1.0",
|
|
30
|
+
"@nanostores/react": "^1.0.0",
|
|
29
31
|
"js-sha256": "0.11.0",
|
|
30
32
|
"lz-string": "^1.5.0",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
+
"nanostores": "^1.0.1",
|
|
34
|
+
"rfdc": "^1.4.1"
|
|
33
35
|
}
|
|
34
36
|
}
|
package/src/index.ts
CHANGED
package/src/lib/Cacher.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { create } from 'zustand'
|
|
2
|
-
import { createJSONStorage, persist, StateStorage } from 'zustand/middleware'
|
|
3
|
-
import { AnyRecord } from '../types'
|
|
4
1
|
import { CacheType } from '../types/cache'
|
|
5
2
|
import { StyleConstants } from './constants'
|
|
6
3
|
import { hashKey } from './hashKey'
|
|
4
|
+
import { StateStorage } from '../types/store'
|
|
7
5
|
|
|
8
6
|
function getStaleTime() {
|
|
9
7
|
const time = 7
|
|
@@ -15,23 +13,15 @@ function getStaleTime() {
|
|
|
15
13
|
return currentTime
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
type StorePersistor = {
|
|
19
|
-
cached: AnyRecord
|
|
20
|
-
cacheFor: (key: string, value: any) => void
|
|
21
|
-
staleTime: Date
|
|
22
|
-
reset: () => void
|
|
23
|
-
}
|
|
24
|
-
|
|
25
16
|
export class Cache<T extends any = any> {
|
|
26
17
|
cache: Record<string, T> = {}
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
get persistKeyCache() {
|
|
20
|
+
return `@styles.caches.${this.registryName}.cache`
|
|
21
|
+
}
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
cacheFor: () => null,
|
|
33
|
-
reset: () => null,
|
|
34
|
-
staleTime: null
|
|
23
|
+
get persistKeyStaleTime() {
|
|
24
|
+
return `@styles.caches.${this.registryName}.staleTime`
|
|
35
25
|
}
|
|
36
26
|
|
|
37
27
|
constructor(
|
|
@@ -39,23 +29,21 @@ export class Cache<T extends any = any> {
|
|
|
39
29
|
private storage: StateStorage = null,
|
|
40
30
|
public persistCache: boolean = !!storage,
|
|
41
31
|
) {
|
|
42
|
-
if (!persistCache) return
|
|
32
|
+
if (!persistCache || !StyleConstants.STORE_CACHE_ENABLED) return
|
|
43
33
|
|
|
44
|
-
this.
|
|
45
|
-
|
|
46
|
-
if (!StyleConstants.STORE_CACHE_ENABLED || !this.persistor) return
|
|
34
|
+
const { persistedCache, persistedStaleTime } = this.loadStorage()
|
|
47
35
|
|
|
48
36
|
const currentTime = new Date()
|
|
49
|
-
const staleTime = new Date(this.store.staleTime)
|
|
50
37
|
|
|
51
|
-
const isStaled = currentTime >
|
|
38
|
+
const isStaled = currentTime > persistedStaleTime
|
|
52
39
|
|
|
53
40
|
if (isStaled) {
|
|
54
|
-
this.
|
|
41
|
+
this.clearStorage()
|
|
55
42
|
return
|
|
56
43
|
}
|
|
57
44
|
|
|
58
|
-
this.setCache(
|
|
45
|
+
this.setCache(persistedCache)
|
|
46
|
+
this.storeStaleTime(persistedStaleTime)
|
|
59
47
|
}
|
|
60
48
|
|
|
61
49
|
keyFor(cacheBaseKey: string, data: Array<any> | any) {
|
|
@@ -72,60 +60,53 @@ export class Cache<T extends any = any> {
|
|
|
72
60
|
|
|
73
61
|
cacheFor(key: string, cache: T) {
|
|
74
62
|
this.cache[key] = cache
|
|
75
|
-
if (this.persistCache) this.
|
|
63
|
+
if (this.persistCache) this.storeCache()
|
|
76
64
|
return cache
|
|
77
65
|
}
|
|
78
66
|
|
|
67
|
+
// utils
|
|
68
|
+
|
|
79
69
|
setCache(cache: Record<string, T>) {
|
|
80
70
|
this.cache = cache
|
|
81
71
|
}
|
|
82
72
|
|
|
83
73
|
clear() {
|
|
84
74
|
this.cache = {}
|
|
85
|
-
|
|
75
|
+
this.clearStorage()
|
|
86
76
|
}
|
|
87
77
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
},
|
|
122
|
-
storage: createJSONStorage(() => this.storage),
|
|
123
|
-
}
|
|
124
|
-
))
|
|
125
|
-
|
|
126
|
-
this.persistor = persistor
|
|
127
|
-
this.store = persistor.getState()
|
|
128
|
-
|
|
129
|
-
return persistor
|
|
78
|
+
// storage
|
|
79
|
+
|
|
80
|
+
loadStorage() {
|
|
81
|
+
if (!this.persistCache) return
|
|
82
|
+
|
|
83
|
+
const persistedStaleTime = this.storage.getItem(this.persistKeyStaleTime)
|
|
84
|
+
const persistedCache = JSON.parse(this.storage.getItem(this.persistKeyCache))
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
persistedStaleTime: !persistedStaleTime ? getStaleTime() : new Date(persistedStaleTime),
|
|
88
|
+
persistedCache,
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
clearStorage() {
|
|
93
|
+
if (!this.persistCache) return
|
|
94
|
+
|
|
95
|
+
this.storage.removeItem(this.persistKeyStaleTime)
|
|
96
|
+
this.storage.removeItem(this.persistKeyCache)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
storeCache(cache: Record<string, T> = null) {
|
|
100
|
+
if (!this.persistCache) return
|
|
101
|
+
|
|
102
|
+
const value = JSON.stringify(cache ?? this.cache)
|
|
103
|
+
this.storage.setItem(this.persistKeyCache, value)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
storeStaleTime(staleTime: Date) {
|
|
107
|
+
if (!this.persistCache) return
|
|
108
|
+
|
|
109
|
+
const value = staleTime.toISOString()
|
|
110
|
+
this.storage.setItem(this.persistKeyStaleTime, value)
|
|
130
111
|
}
|
|
131
112
|
}
|
package/src/lib/StyleCache.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { hashKey } from './hashKey'
|
|
|
3
3
|
import { StyleConstants } from './constants'
|
|
4
4
|
import { CacheType } from '../types/cache'
|
|
5
5
|
import { minifier } from './minifier'
|
|
6
|
-
import { StateStorage } from '
|
|
6
|
+
import { StateStorage } from '../types/store'
|
|
7
7
|
|
|
8
8
|
export class StyleCache {
|
|
9
9
|
baseKey: string
|
package/src/lib/StyleRegistry.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable dot-notation */
|
|
2
2
|
import { AnyRecord, AnyStyledComponent, ICSS, ITheme, StyleAggregator, StyleProp, VariantStyleSheet } from '../types'
|
|
3
|
-
import {
|
|
3
|
+
import { themeStore } from './themeStore'
|
|
4
4
|
import deepmerge from '@fastify/deepmerge'
|
|
5
5
|
import { MultiplierFunction } from './spacing'
|
|
6
6
|
import { defaultVariants } from './defaultVariants'
|
|
@@ -8,8 +8,8 @@ import { dynamicVariants } from './dynamicVariants'
|
|
|
8
8
|
import { capitalize, ignoredStyleKeys, isSpacingKey } from './utils'
|
|
9
9
|
import { StyleCache } from './StyleCache'
|
|
10
10
|
import { minifier } from './minifier'
|
|
11
|
-
import { StateStorage } from 'zustand/middleware'
|
|
12
11
|
import rfdc from 'rfdc'
|
|
12
|
+
import { StateStorage } from '../types/store'
|
|
13
13
|
|
|
14
14
|
const deepClone = rfdc()
|
|
15
15
|
|
|
@@ -22,20 +22,16 @@ export class CodeleapStyleRegistry {
|
|
|
22
22
|
|
|
23
23
|
components: Record<string, AnyStyledComponent> = {}
|
|
24
24
|
|
|
25
|
-
private theme: ThemeStore
|
|
26
|
-
|
|
27
25
|
private styleCache: StyleCache
|
|
28
26
|
|
|
29
27
|
constructor(storage: StateStorage) {
|
|
30
28
|
this.styleCache = new StyleCache(storage)
|
|
31
29
|
|
|
32
|
-
this.theme = themeStore.getState()
|
|
33
|
-
|
|
34
30
|
this.registerCommonVariants()
|
|
35
31
|
|
|
36
|
-
const currentColorScheme =
|
|
32
|
+
const currentColorScheme = themeStore.theme?.['currentColorScheme']?.() ?? themeStore.colorScheme ?? 'default'
|
|
37
33
|
|
|
38
|
-
this.styleCache.registerBaseKey([currentColorScheme,
|
|
34
|
+
this.styleCache.registerBaseKey([currentColorScheme, themeStore.theme, this.commonVariants])
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
computeCommonVariantStyle(componentName: string, variant: string, component = null) {
|
|
@@ -47,7 +43,7 @@ export class CodeleapStyleRegistry {
|
|
|
47
43
|
}
|
|
48
44
|
}
|
|
49
45
|
|
|
50
|
-
const theme =
|
|
46
|
+
const theme = themeStore.theme
|
|
51
47
|
|
|
52
48
|
let mediaQuery = null
|
|
53
49
|
|
|
@@ -104,7 +100,7 @@ export class CodeleapStyleRegistry {
|
|
|
104
100
|
return cache.value
|
|
105
101
|
}
|
|
106
102
|
|
|
107
|
-
const theme =
|
|
103
|
+
const theme = themeStore.theme
|
|
108
104
|
|
|
109
105
|
const variantStyles = variants.map((variant) => {
|
|
110
106
|
if (!!stylesheet[variant]) {
|
|
@@ -294,7 +290,7 @@ export class CodeleapStyleRegistry {
|
|
|
294
290
|
const [breakpoint, query] = responsiveKey?.includes(':') ? responsiveKey?.split(':') : [responsiveKey, 'down']
|
|
295
291
|
|
|
296
292
|
// @ts-expect-error - media not has type
|
|
297
|
-
const mediaQuery =
|
|
293
|
+
const mediaQuery = themeStore.theme?.media?.[query]?.(breakpoint)
|
|
298
294
|
|
|
299
295
|
return mediaQuery
|
|
300
296
|
}
|
|
@@ -471,11 +467,11 @@ export class CodeleapStyleRegistry {
|
|
|
471
467
|
}
|
|
472
468
|
|
|
473
469
|
registerCommonVariants() {
|
|
474
|
-
const spacingVariants =
|
|
470
|
+
const spacingVariants = themeStore.theme?.['spacing']
|
|
475
471
|
|
|
476
|
-
const insetVariants =
|
|
472
|
+
const insetVariants = themeStore.theme?.['inset']
|
|
477
473
|
|
|
478
|
-
const appVariants =
|
|
474
|
+
const appVariants = themeStore.variants
|
|
479
475
|
|
|
480
476
|
const commonVariants = deepmerge({ all: true })(
|
|
481
477
|
defaultVariants,
|
|
@@ -516,11 +512,9 @@ export class CodeleapStyleRegistry {
|
|
|
516
512
|
}
|
|
517
513
|
|
|
518
514
|
update() {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
const currentColorScheme = this.theme?.current?.['currentColorScheme']?.() ?? this.theme?.colorScheme ?? 'default'
|
|
515
|
+
const currentColorScheme = themeStore.theme?.['currentColorScheme']?.() ?? themeStore.colorScheme ?? 'default'
|
|
522
516
|
|
|
523
|
-
this.styleCache.registerBaseKey([currentColorScheme,
|
|
517
|
+
this.styleCache.registerBaseKey([currentColorScheme, themeStore.theme, this.commonVariants])
|
|
524
518
|
}
|
|
525
519
|
|
|
526
520
|
private copyStyle(style: any) {
|
|
@@ -529,7 +523,7 @@ export class CodeleapStyleRegistry {
|
|
|
529
523
|
|
|
530
524
|
createStyles<K extends string = string>(styles: Record<K, StyleProp<AnyRecord, ''>> | ((theme: ITheme) => Record<K, StyleProp<AnyRecord, ''>>)): Record<K, ICSS> {
|
|
531
525
|
const compute = () => {
|
|
532
|
-
const current = themeStore.
|
|
526
|
+
const current = themeStore.theme
|
|
533
527
|
|
|
534
528
|
const stylesObj = typeof styles === 'function' ? styles(current) : styles
|
|
535
529
|
|
package/src/lib/borderCreator.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IColors, ICSS } from '../types'
|
|
2
2
|
import { borderDirection } from './dynamicVariants'
|
|
3
3
|
import { themeStore } from './themeStore'
|
|
4
4
|
import { capitalize } from './utils'
|
|
@@ -21,7 +21,7 @@ export const borderCreator: BorderCreator = (args) => {
|
|
|
21
21
|
directions = ['left', 'top', 'bottom', 'right'],
|
|
22
22
|
} = args
|
|
23
23
|
|
|
24
|
-
const theme = themeStore.
|
|
24
|
+
const theme = themeStore.themeTyped
|
|
25
25
|
|
|
26
26
|
const color = theme?.baseColors?.[colorKey] ?? colorKey
|
|
27
27
|
|
package/src/lib/createStyles.ts
CHANGED
|
@@ -9,7 +9,7 @@ export function createStyles<K extends string, V extends Value = {}>(
|
|
|
9
9
|
styles: StylesShape<K, V> | ((theme: ITheme) => StylesShape<K, V>),
|
|
10
10
|
) {
|
|
11
11
|
const compute = () => {
|
|
12
|
-
const current = themeStore.
|
|
12
|
+
const current = themeStore.theme
|
|
13
13
|
|
|
14
14
|
if (typeof styles === 'function') {
|
|
15
15
|
return !current ? {} as StylesShape<K, V> : styles(current)
|
package/src/lib/createTheme.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppTheme,
|
|
1
|
+
import { AppTheme, Theme } from '../types'
|
|
2
2
|
import { borderCreator } from './borderCreator'
|
|
3
3
|
import { createMediaQueries } from './mediaQuery'
|
|
4
4
|
import { multiplierProperty } from './multiplierProperty'
|
|
@@ -6,12 +6,15 @@ import { defaultVariants } from './defaultVariants'
|
|
|
6
6
|
import { spacingFactory } from './spacing'
|
|
7
7
|
import { themeStore } from './themeStore'
|
|
8
8
|
|
|
9
|
-
type
|
|
10
|
-
get: () =>
|
|
11
|
-
set: (
|
|
9
|
+
type ThemePersistor = {
|
|
10
|
+
get: (name: string) => any
|
|
11
|
+
set: (name: string, value: any) => void
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const colorSchemeKey = '@styles.theme.colorScheme'
|
|
15
|
+
const alternateColorsKey = '@styles.theme.alternateColors'
|
|
16
|
+
|
|
17
|
+
export const createTheme = <T extends Theme>(theme: T, themePersistor: ThemePersistor): AppTheme<T> => {
|
|
15
18
|
const {
|
|
16
19
|
colors,
|
|
17
20
|
breakpoints,
|
|
@@ -27,23 +30,34 @@ export const createTheme = <T extends Theme>(theme: T, colorSchemaPersistor: Col
|
|
|
27
30
|
...otherThemeValues
|
|
28
31
|
} = theme
|
|
29
32
|
|
|
33
|
+
themeStore.setColorScheme(themePersistor.get(colorSchemeKey) ?? 'default')
|
|
34
|
+
|
|
35
|
+
const persistedAlternateColors = themePersistor.get(alternateColorsKey)
|
|
36
|
+
|
|
37
|
+
const currentAlternateColors = {
|
|
38
|
+
...(persistedAlternateColors ?? {}),
|
|
39
|
+
...otherThemeValues?.alternateColors,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
themeStore.setAlternateColorsScheme(currentAlternateColors)
|
|
43
|
+
|
|
30
44
|
const themeObj: AppTheme<T> = {
|
|
31
45
|
...otherThemeValues,
|
|
32
46
|
|
|
33
47
|
baseColors,
|
|
34
48
|
|
|
35
49
|
currentColorScheme() {
|
|
36
|
-
return themeStore.
|
|
50
|
+
return themeStore.colorScheme
|
|
37
51
|
},
|
|
38
52
|
|
|
39
53
|
breakpoints: breakpoints ?? {},
|
|
40
54
|
|
|
41
55
|
get colors() {
|
|
42
|
-
const colorScheme = themeStore.
|
|
56
|
+
const colorScheme = themeStore.colorScheme ?? 'default'
|
|
43
57
|
|
|
44
58
|
if (colorScheme === 'default') return colors
|
|
45
59
|
|
|
46
|
-
const scheme =
|
|
60
|
+
const scheme = themeStore.alternateColorsScheme?.[colorScheme]
|
|
47
61
|
|
|
48
62
|
if (!scheme) {
|
|
49
63
|
console.warn(`Color scheme ${colorScheme} not found in theme`)
|
|
@@ -52,12 +66,34 @@ export const createTheme = <T extends Theme>(theme: T, colorSchemaPersistor: Col
|
|
|
52
66
|
return scheme ?? colors
|
|
53
67
|
},
|
|
54
68
|
|
|
55
|
-
setColorScheme(colorScheme:
|
|
56
|
-
|
|
57
|
-
|
|
69
|
+
setColorScheme(colorScheme: string) {
|
|
70
|
+
const hasScheme = colorScheme === 'default' ? true : !!themeStore.alternateColorsScheme?.[colorScheme]
|
|
71
|
+
|
|
72
|
+
if (!hasScheme) {
|
|
73
|
+
console.warn(`Color scheme ${colorScheme} not found in theme`)
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
themeStore.setColorScheme(colorScheme)
|
|
78
|
+
|
|
79
|
+
themePersistor.set(colorSchemeKey, colorScheme)
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
injectColorScheme(name, colorMap) {
|
|
83
|
+
themeStore.injectColorScheme(name, colorMap)
|
|
84
|
+
|
|
85
|
+
const persistedAlternateColors = themePersistor.get(alternateColorsKey)
|
|
86
|
+
|
|
87
|
+
const unpersistedAlternateColors = {
|
|
88
|
+
...(persistedAlternateColors ?? {}),
|
|
89
|
+
[name]: colorMap,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
themePersistor.set(alternateColorsKey, unpersistedAlternateColors)
|
|
58
93
|
},
|
|
59
94
|
|
|
60
95
|
baseSpacing: theme.baseSpacing,
|
|
96
|
+
|
|
61
97
|
value: (n = 1) => theme.baseSpacing * n,
|
|
62
98
|
|
|
63
99
|
spacing: {
|
|
@@ -109,10 +145,7 @@ export const createTheme = <T extends Theme>(theme: T, colorSchemaPersistor: Col
|
|
|
109
145
|
},
|
|
110
146
|
}
|
|
111
147
|
|
|
112
|
-
themeStore.
|
|
113
|
-
current: themeObj,
|
|
114
|
-
colorScheme: colorSchemaPersistor.get() ?? 'default',
|
|
115
|
-
})
|
|
148
|
+
themeStore.setTheme(themeObj)
|
|
116
149
|
|
|
117
150
|
return themeObj
|
|
118
151
|
}
|
package/src/lib/hooks.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
2
|
import { ICSS } from '../types'
|
|
3
3
|
import { getNestedStylesByKey } from './utils'
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ThemeState, themeStoreComputed } from './themeStore'
|
|
5
|
+
import { useStore } from '@nanostores/react'
|
|
6
6
|
|
|
7
7
|
export const useStyleObserver = (style) => {
|
|
8
8
|
return useMemo(() => {
|
|
@@ -26,10 +26,18 @@ export function useNestedStylesByKey<T extends string>(match: string, componentS
|
|
|
26
26
|
}, [styles])
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
type ThemeSelector<T =
|
|
29
|
+
type ThemeSelector<T> = (state: ThemeState) => T
|
|
30
30
|
|
|
31
|
-
export const useTheme = <T =
|
|
32
|
-
|
|
31
|
+
export const useTheme = <T = ThemeState>(
|
|
32
|
+
selector?: ThemeSelector<T>
|
|
33
|
+
): T => {
|
|
34
|
+
const state = useStore(themeStoreComputed)
|
|
35
|
+
|
|
36
|
+
if (!selector) {
|
|
37
|
+
return state as T
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return selector(state)
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
export function useCompositionStyles<T extends string, C extends string>(
|
package/src/lib/themeStore.ts
CHANGED
|
@@ -1,14 +1,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AppTheme, ColorMap, IAppVariants, ITheme, Theme } from '../types'
|
|
2
|
+
import { map, computed } from 'nanostores'
|
|
3
3
|
|
|
4
|
-
export type
|
|
5
|
-
|
|
6
|
-
current: ITheme | null
|
|
7
|
-
variants: IAppVariants
|
|
4
|
+
export type ThemeState = {
|
|
5
|
+
theme: AppTheme<Theme> | null
|
|
8
6
|
}
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
class ThemeStore {
|
|
9
|
+
private alternateColorsSchemeStore: { [key: string]: ColorMap } = {}
|
|
10
|
+
|
|
11
|
+
public colorSchemeStore: string = null
|
|
12
|
+
|
|
13
|
+
public themeStore = map<ITheme | null>(null)
|
|
14
|
+
|
|
15
|
+
public variantsStore: IAppVariants = {} as IAppVariants
|
|
16
|
+
|
|
17
|
+
get theme() {
|
|
18
|
+
return this.themeStore.get()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get themeTyped() {
|
|
22
|
+
return this.themeStore.get() as unknown as AppTheme<Theme>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get colorScheme() {
|
|
26
|
+
return this.colorSchemeStore
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get variants() {
|
|
30
|
+
return this.variantsStore
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get alternateColorsScheme() {
|
|
34
|
+
return this.alternateColorsSchemeStore ?? {}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setVariants<T>(variants: T) {
|
|
38
|
+
this.variantsStore = variants as unknown as IAppVariants
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setColorScheme(colorScheme: string) {
|
|
42
|
+
this.colorSchemeStore = colorScheme
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setTheme(theme: ITheme) {
|
|
46
|
+
this.themeStore.set(theme)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setAlternateColorsScheme(colors: { [key: string]: ColorMap }) {
|
|
50
|
+
this.alternateColorsSchemeStore = colors
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// utils
|
|
54
|
+
|
|
55
|
+
private getBaseColorScheme(): ColorMap {
|
|
56
|
+
const alternateColors = this.alternateColorsScheme ?? {}
|
|
57
|
+
const colorSchemeKeys = Object.keys(alternateColors)
|
|
58
|
+
|
|
59
|
+
if (colorSchemeKeys.length === 0) {
|
|
60
|
+
return {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return alternateColors[colorSchemeKeys[0]] ?? {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
injectColorScheme(name: string, colors: ColorMap) {
|
|
67
|
+
const baseColors = this.getBaseColorScheme()
|
|
68
|
+
const currentAlternateColors = this.alternateColorsScheme ?? {}
|
|
69
|
+
|
|
70
|
+
const alternateColors = {
|
|
71
|
+
...currentAlternateColors,
|
|
72
|
+
|
|
73
|
+
[name]: {
|
|
74
|
+
...baseColors,
|
|
75
|
+
...colors,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this.setAlternateColorsScheme(alternateColors)
|
|
80
|
+
|
|
81
|
+
return alternateColors
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const themeStore = new ThemeStore()
|
|
86
|
+
|
|
87
|
+
export const themeStoreComputed = computed([
|
|
88
|
+
themeStore['themeStore'],
|
|
89
|
+
], (theme) => ({
|
|
90
|
+
theme: theme as unknown as AppTheme<Theme>,
|
|
14
91
|
}))
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ColorMap } from '../types'
|
|
2
|
+
|
|
3
|
+
export function hexToHSL(hex: string) {
|
|
4
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255
|
|
5
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255
|
|
6
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255
|
|
7
|
+
|
|
8
|
+
const max = Math.max(r, g, b), min = Math.min(r, g, b)
|
|
9
|
+
let h = 0, s = 0, l = (max + min) / 2
|
|
10
|
+
|
|
11
|
+
if (max !== min) {
|
|
12
|
+
const d = max - min
|
|
13
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
|
|
14
|
+
switch (max) {
|
|
15
|
+
case r: h = (g - b) / d + (g < b ? 6 : 0); break
|
|
16
|
+
case g: h = (b - r) / d + 2; break
|
|
17
|
+
case b: h = (r - g) / d + 4; break
|
|
18
|
+
}
|
|
19
|
+
h /= 6
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
h: Math.round(h * 360),
|
|
24
|
+
s: Math.round(s * 100),
|
|
25
|
+
l: Math.round(l * 100)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function hslToHex(h: number, s: number, l: number): string {
|
|
30
|
+
s /= 100
|
|
31
|
+
l /= 100
|
|
32
|
+
|
|
33
|
+
const k = (n: number) => (n + h / 30) % 12
|
|
34
|
+
const a = s * Math.min(l, 1 - l)
|
|
35
|
+
const f = (n: number) =>
|
|
36
|
+
Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))))
|
|
37
|
+
|
|
38
|
+
return `#${[f(0), f(8), f(4)].map(x => x.toString(16).padStart(2, '0')).join('')}`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function hexToRGB(hex: string) {
|
|
42
|
+
const r = parseInt(hex.slice(1, 3), 16)
|
|
43
|
+
const g = parseInt(hex.slice(3, 5), 16)
|
|
44
|
+
const b = parseInt(hex.slice(5, 7), 16)
|
|
45
|
+
return { r, g, b }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function hslToRGB(h: number, s: number, l: number) {
|
|
49
|
+
s /= 100
|
|
50
|
+
l /= 100
|
|
51
|
+
|
|
52
|
+
const k = (n: number) => (n + h / 30) % 12
|
|
53
|
+
const a = s * Math.min(l, 1 - l)
|
|
54
|
+
const f = (n: number) =>
|
|
55
|
+
Math.round(255 * (l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))))
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
r: f(0),
|
|
59
|
+
g: f(8),
|
|
60
|
+
b: f(4)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function generateColorScheme(
|
|
65
|
+
anchorHex: string,
|
|
66
|
+
prefix: string = 'primary'
|
|
67
|
+
): ColorMap {
|
|
68
|
+
const { h, s } = hexToHSL(anchorHex)
|
|
69
|
+
const baseRGB = hexToRGB(anchorHex)
|
|
70
|
+
|
|
71
|
+
const scheme: ColorMap = {}
|
|
72
|
+
|
|
73
|
+
const lightnesses = [95, 85, 75, 60, 45, 30, 27, 21, 16, 10]
|
|
74
|
+
|
|
75
|
+
lightnesses.forEach((lightness, index) => {
|
|
76
|
+
const step = (index + 1) * 100
|
|
77
|
+
const rgb = hslToRGB(h, s, lightness)
|
|
78
|
+
scheme[`${prefix}Solid${step}`] = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 1.00)`
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const alphas = [0.05, 0.10, 0.20, 0.30, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90]
|
|
82
|
+
|
|
83
|
+
alphas.forEach((alpha, index) => {
|
|
84
|
+
const step = (index + 1) * 100
|
|
85
|
+
scheme[`${prefix}Transparent${step}`] = `rgba(${baseRGB.r}, ${baseRGB.g}, ${baseRGB.b}, ${alpha.toFixed(2)})`
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return scheme
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function getLuminance({ r, g, b }: { r: number; g: number; b: number }): number {
|
|
92
|
+
const [R, G, B] = [r, g, b].map(c => {
|
|
93
|
+
const channel = c / 255
|
|
94
|
+
return channel <= 0.03928
|
|
95
|
+
? channel / 12.92
|
|
96
|
+
: Math.pow((channel + 0.055) / 1.055, 2.4)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
return 0.2126 * R + 0.7152 * G + 0.0722 * B
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function getTextColor(backgroundHex: string, darkColor = 'black', lightColor = 'white'): string {
|
|
103
|
+
const rgb = hexToRGB(backgroundHex)
|
|
104
|
+
const luminance = getLuminance(rgb)
|
|
105
|
+
return luminance > 0.5 ? darkColor : lightColor
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * as colorTools from './colors'
|
package/src/types/theme.ts
CHANGED
|
@@ -8,7 +8,7 @@ type AnyMap = {
|
|
|
8
8
|
[key: string]: any
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
type ColorMap = {
|
|
11
|
+
export type ColorMap = {
|
|
12
12
|
[key: string]: string
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -75,8 +75,9 @@ type PredefinedThemeDerivedValues<T extends Theme> = {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
type PredefinedAppTheme<T extends Theme> = PredefinedThemeDerivedValues<T> & {
|
|
78
|
-
setColorScheme: (colorScheme:
|
|
78
|
+
setColorScheme: (colorScheme: string) => void
|
|
79
79
|
currentColorScheme: () => ColorScheme<T>
|
|
80
|
+
injectColorScheme: (name: string, colorMap: ColorMap) => void
|
|
80
81
|
spacing: SpacingMap
|
|
81
82
|
media: MediaQueries
|
|
82
83
|
border: BorderCreator
|