@hanzogui/theme 2.0.0-rc.41-hanzoai.5
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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/cjs/_mutateTheme.cjs +141 -0
- package/dist/cjs/_mutateTheme.native.js +137 -0
- package/dist/cjs/_mutateTheme.native.js.map +1 -0
- package/dist/cjs/addTheme.cjs +35 -0
- package/dist/cjs/addTheme.native.js +38 -0
- package/dist/cjs/addTheme.native.js.map +1 -0
- package/dist/cjs/index.cjs +32 -0
- package/dist/cjs/index.native.js +35 -0
- package/dist/cjs/index.native.js.map +1 -0
- package/dist/cjs/replaceTheme.cjs +40 -0
- package/dist/cjs/replaceTheme.native.js +44 -0
- package/dist/cjs/replaceTheme.native.js.map +1 -0
- package/dist/cjs/updateTheme.cjs +39 -0
- package/dist/cjs/updateTheme.native.js +43 -0
- package/dist/cjs/updateTheme.native.js.map +1 -0
- package/dist/esm/_mutateTheme.mjs +115 -0
- package/dist/esm/_mutateTheme.mjs.map +1 -0
- package/dist/esm/_mutateTheme.native.js +108 -0
- package/dist/esm/_mutateTheme.native.js.map +1 -0
- package/dist/esm/addTheme.mjs +10 -0
- package/dist/esm/addTheme.mjs.map +1 -0
- package/dist/esm/addTheme.native.js +10 -0
- package/dist/esm/addTheme.native.js.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/index.mjs +6 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/index.native.js +6 -0
- package/dist/esm/index.native.js.map +1 -0
- package/dist/esm/replaceTheme.mjs +15 -0
- package/dist/esm/replaceTheme.mjs.map +1 -0
- package/dist/esm/replaceTheme.native.js +16 -0
- package/dist/esm/replaceTheme.native.js.map +1 -0
- package/dist/esm/updateTheme.mjs +14 -0
- package/dist/esm/updateTheme.mjs.map +1 -0
- package/dist/esm/updateTheme.native.js +15 -0
- package/dist/esm/updateTheme.native.js.map +1 -0
- package/package.json +48 -0
- package/src/_mutateTheme.ts +197 -0
- package/src/addTheme.ts +11 -0
- package/src/index.ts +5 -0
- package/src/replaceTheme.ts +14 -0
- package/src/updateTheme.ts +13 -0
- package/types/_mutateTheme.d.ts +27 -0
- package/types/_mutateTheme.d.ts.map +1 -0
- package/types/addTheme.d.ts +11 -0
- package/types/addTheme.d.ts.map +1 -0
- package/types/index.d.ts +6 -0
- package/types/index.d.ts.map +1 -0
- package/types/replaceTheme.d.ts +10 -0
- package/types/replaceTheme.d.ts.map +1 -0
- package/types/updateTheme.d.ts +10 -0
- package/types/updateTheme.d.ts.map +1 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { isServer } from '@hanzogui/constants'
|
|
2
|
+
import { startTransition } from '@hanzogui/start-transition'
|
|
3
|
+
import type { ThemeDefinition, ThemeParsed } from '@hanzogui/web'
|
|
4
|
+
import {
|
|
5
|
+
ensureThemeVariable,
|
|
6
|
+
forceUpdateThemes,
|
|
7
|
+
getConfig,
|
|
8
|
+
getThemeCSSRules,
|
|
9
|
+
mutatedAutoVariables,
|
|
10
|
+
proxyThemeToParents,
|
|
11
|
+
simpleHash,
|
|
12
|
+
updateConfig,
|
|
13
|
+
} from '@hanzogui/web'
|
|
14
|
+
|
|
15
|
+
type MutateThemeOptions = {
|
|
16
|
+
mutationType: 'replace' | 'update' | 'add'
|
|
17
|
+
insertCSS?: boolean
|
|
18
|
+
avoidUpdate?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type PartialTheme = Partial<Record<keyof ThemeDefinition, any>>
|
|
22
|
+
|
|
23
|
+
export type MutateOneThemeProps = {
|
|
24
|
+
name: string
|
|
25
|
+
theme: PartialTheme
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// need to name the batch in case the theme amount changes so it removes properly
|
|
29
|
+
type Batch = boolean | string
|
|
30
|
+
|
|
31
|
+
// more advanced helper used only internally in studio for now
|
|
32
|
+
export function mutateThemes({
|
|
33
|
+
themes,
|
|
34
|
+
batch,
|
|
35
|
+
insertCSS = true,
|
|
36
|
+
...props
|
|
37
|
+
}: Omit<MutateThemeOptions, 'mutationType'> & {
|
|
38
|
+
themes: MutateOneThemeProps[] // if using batch, know that if you later on do addTheme/etc it will break things
|
|
39
|
+
// batch is only useful if you know youre only ever going to change these themes using batch
|
|
40
|
+
// aka only in studio as a preview mode
|
|
41
|
+
batch?: Batch
|
|
42
|
+
}) {
|
|
43
|
+
const allThemesProxied: Record<string, ThemeParsed> = {}
|
|
44
|
+
const allThemesRaw: Record<string, ThemeParsed> = {}
|
|
45
|
+
for (const { name, theme } of themes) {
|
|
46
|
+
const res = _mutateTheme({
|
|
47
|
+
...props,
|
|
48
|
+
name,
|
|
49
|
+
theme,
|
|
50
|
+
// we'll do one update at the end
|
|
51
|
+
avoidUpdate: true,
|
|
52
|
+
// always add which also replaces but doesnt fail first time
|
|
53
|
+
mutationType: 'add',
|
|
54
|
+
})
|
|
55
|
+
if (res) {
|
|
56
|
+
allThemesProxied[name] = res.theme
|
|
57
|
+
allThemesRaw[name] = res.themeRaw
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const cssRules = insertCSS ? insertThemeCSS(allThemesRaw, batch) : []
|
|
62
|
+
|
|
63
|
+
startTransition(() => {
|
|
64
|
+
for (const themeName in allThemesProxied) {
|
|
65
|
+
const theme = allThemesProxied[themeName]
|
|
66
|
+
updateThemeConfig(themeName, theme)
|
|
67
|
+
}
|
|
68
|
+
updateThemeStates()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
themes: allThemesProxied,
|
|
73
|
+
themesRaw: allThemesRaw,
|
|
74
|
+
cssRules,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function _mutateTheme(props: MutateThemeOptions & MutateOneThemeProps) {
|
|
79
|
+
if (isServer) {
|
|
80
|
+
if (process.env.NODE_ENV === 'development') {
|
|
81
|
+
console.warn('Theme mutation is not supported on server side')
|
|
82
|
+
}
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
const config = getConfig()
|
|
86
|
+
const { name: themeName, theme: themeIn, insertCSS, mutationType } = props
|
|
87
|
+
|
|
88
|
+
if (process.env.NODE_ENV === 'development') {
|
|
89
|
+
if (!config) {
|
|
90
|
+
throw new Error('No config')
|
|
91
|
+
}
|
|
92
|
+
const theme = config.themes[props.name]
|
|
93
|
+
|
|
94
|
+
if (mutationType !== 'add' && !theme) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`${mutationType === 'replace' ? 'Replace' : 'Update'} theme failed! Theme ${
|
|
97
|
+
props.name
|
|
98
|
+
} does not exist`
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const theme = {
|
|
104
|
+
...(mutationType === 'update' ? (config.themes[themeName] ?? {}) : {}),
|
|
105
|
+
...themeIn,
|
|
106
|
+
} as ThemeParsed
|
|
107
|
+
|
|
108
|
+
for (const key in theme) {
|
|
109
|
+
ensureThemeVariable(theme, key)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const themeProxied = proxyThemeToParents(themeName, theme)
|
|
113
|
+
|
|
114
|
+
const response = {
|
|
115
|
+
themeRaw: theme,
|
|
116
|
+
theme: themeProxied,
|
|
117
|
+
cssRules: [] as string[],
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (props.avoidUpdate) {
|
|
121
|
+
return response
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (insertCSS) {
|
|
125
|
+
response.cssRules = insertThemeCSS({
|
|
126
|
+
[themeName]: theme,
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
updateThemeConfig(themeName, themeProxied)
|
|
131
|
+
updateThemeStates()
|
|
132
|
+
|
|
133
|
+
return response
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function updateThemeConfig(themeName: string, theme: ThemeParsed) {
|
|
137
|
+
const config = getConfig()
|
|
138
|
+
config.themes[themeName] = theme
|
|
139
|
+
updateConfig('themes', config.themes)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function updateThemeStates() {
|
|
143
|
+
forceUpdateThemes()
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function insertThemeCSS(themes: Record<string, PartialTheme>, batch: Batch = false) {
|
|
147
|
+
if (process.env.TAMAGUI_TARGET !== 'web') {
|
|
148
|
+
return []
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const config = getConfig()
|
|
152
|
+
let cssRules: string[] = []
|
|
153
|
+
|
|
154
|
+
for (const themeName in themes) {
|
|
155
|
+
const theme = themes[themeName]
|
|
156
|
+
|
|
157
|
+
const rules = getThemeCSSRules({
|
|
158
|
+
config,
|
|
159
|
+
themeName,
|
|
160
|
+
names: [themeName],
|
|
161
|
+
hasDarkLight: true,
|
|
162
|
+
theme,
|
|
163
|
+
// Use mutated variable creator which starts from high index to avoid conflicts
|
|
164
|
+
useMutatedVariables: true,
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
cssRules = [...cssRules, ...rules]
|
|
168
|
+
|
|
169
|
+
if (!batch) {
|
|
170
|
+
updateStyle(`t_theme_style_${themeName}`, rules)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Output ALL mutated auto variables (since updateStyle replaces the element)
|
|
175
|
+
if (mutatedAutoVariables.length > 0) {
|
|
176
|
+
const autoVarCSS = `:root{${mutatedAutoVariables.map((v) => `--${v.name}:${v.val}`).join(';')}}`
|
|
177
|
+
updateStyle(`t_mutate_vars`, [autoVarCSS])
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (batch) {
|
|
181
|
+
const id = typeof batch == 'string' ? batch : simpleHash(Object.keys(themes).join(''))
|
|
182
|
+
updateStyle(`t_theme_style_${id}`, cssRules)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return cssRules
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function updateStyle(id: string, rules: string[]) {
|
|
189
|
+
const existing = document.querySelector(`#${id}`)
|
|
190
|
+
const style = document.createElement('style')
|
|
191
|
+
style.id = id
|
|
192
|
+
style.appendChild(document.createTextNode(rules.join('\n')))
|
|
193
|
+
document.head.appendChild(style)
|
|
194
|
+
if (existing) {
|
|
195
|
+
existing.parentElement?.removeChild(existing)
|
|
196
|
+
}
|
|
197
|
+
}
|
package/src/addTheme.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ThemeDefinition, ThemeParsed } from '@hanzogui/web'
|
|
2
|
+
|
|
3
|
+
import { _mutateTheme } from './_mutateTheme'
|
|
4
|
+
|
|
5
|
+
export function addTheme(props: {
|
|
6
|
+
name: string
|
|
7
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>
|
|
8
|
+
insertCSS?: boolean
|
|
9
|
+
}) {
|
|
10
|
+
return _mutateTheme({ ...props, insertCSS: true, mutationType: 'add' })
|
|
11
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ThemeDefinition } from '@hanzogui/web'
|
|
2
|
+
|
|
3
|
+
import { _mutateTheme } from './_mutateTheme'
|
|
4
|
+
|
|
5
|
+
export function replaceTheme({
|
|
6
|
+
name,
|
|
7
|
+
theme,
|
|
8
|
+
}: {
|
|
9
|
+
name: string
|
|
10
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>
|
|
11
|
+
}) {
|
|
12
|
+
const next = _mutateTheme({ name, theme, insertCSS: true, mutationType: 'replace' })
|
|
13
|
+
return next
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ThemeDefinition, ThemeName } from '@hanzogui/web'
|
|
2
|
+
|
|
3
|
+
import { _mutateTheme } from './_mutateTheme'
|
|
4
|
+
|
|
5
|
+
export function updateTheme({
|
|
6
|
+
name,
|
|
7
|
+
theme,
|
|
8
|
+
}: {
|
|
9
|
+
name: ThemeName | (string & {})
|
|
10
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>
|
|
11
|
+
}) {
|
|
12
|
+
return _mutateTheme({ name, theme, insertCSS: true, mutationType: 'update' })
|
|
13
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ThemeDefinition, ThemeParsed } from '@hanzogui/web';
|
|
2
|
+
type MutateThemeOptions = {
|
|
3
|
+
mutationType: 'replace' | 'update' | 'add';
|
|
4
|
+
insertCSS?: boolean;
|
|
5
|
+
avoidUpdate?: boolean;
|
|
6
|
+
};
|
|
7
|
+
type PartialTheme = Partial<Record<keyof ThemeDefinition, any>>;
|
|
8
|
+
export type MutateOneThemeProps = {
|
|
9
|
+
name: string;
|
|
10
|
+
theme: PartialTheme;
|
|
11
|
+
};
|
|
12
|
+
type Batch = boolean | string;
|
|
13
|
+
export declare function mutateThemes({ themes, batch, insertCSS, ...props }: Omit<MutateThemeOptions, 'mutationType'> & {
|
|
14
|
+
themes: MutateOneThemeProps[];
|
|
15
|
+
batch?: Batch;
|
|
16
|
+
}): {
|
|
17
|
+
themes: Record<string, ThemeParsed>;
|
|
18
|
+
themesRaw: Record<string, ThemeParsed>;
|
|
19
|
+
cssRules: string[];
|
|
20
|
+
};
|
|
21
|
+
export declare function _mutateTheme(props: MutateThemeOptions & MutateOneThemeProps): {
|
|
22
|
+
themeRaw: ThemeParsed;
|
|
23
|
+
theme: {};
|
|
24
|
+
cssRules: string[];
|
|
25
|
+
} | undefined;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=_mutateTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_mutateTheme.d.ts","sourceRoot":"","sources":["../src/_mutateTheme.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAYjE,KAAK,kBAAkB,GAAG;IACxB,YAAY,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAA;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AAED,KAAK,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,eAAe,EAAE,GAAG,CAAC,CAAC,CAAA;AAE/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,YAAY,CAAA;CACpB,CAAA;AAGD,KAAK,KAAK,GAAG,OAAO,GAAG,MAAM,CAAA;AAG7B,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,KAAK,EACL,SAAgB,EAChB,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,kBAAkB,EAAE,cAAc,CAAC,GAAG;IAC5C,MAAM,EAAE,mBAAmB,EAAE,CAAA;IAG7B,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;;;;EAkCA;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,kBAAkB,GAAG,mBAAmB;;;cAuCxD,MAAM,EAAE;cAiB3B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ThemeDefinition, ThemeParsed } from '@hanzogui/web';
|
|
2
|
+
export declare function addTheme(props: {
|
|
3
|
+
name: string;
|
|
4
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>;
|
|
5
|
+
insertCSS?: boolean;
|
|
6
|
+
}): {
|
|
7
|
+
themeRaw: ThemeParsed;
|
|
8
|
+
theme: {};
|
|
9
|
+
cssRules: string[];
|
|
10
|
+
} | undefined;
|
|
11
|
+
//# sourceMappingURL=addTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addTheme.d.ts","sourceRoot":"","sources":["../src/addTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAIjE,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,eAAe,EAAE,GAAG,CAAC,CAAC,CAAA;IAClD,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;;;;cAEA"}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ThemeDefinition } from '@hanzogui/web';
|
|
2
|
+
export declare function replaceTheme({ name, theme, }: {
|
|
3
|
+
name: string;
|
|
4
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>;
|
|
5
|
+
}): {
|
|
6
|
+
themeRaw: import("@hanzogui/web").ThemeParsed;
|
|
7
|
+
theme: {};
|
|
8
|
+
cssRules: string[];
|
|
9
|
+
} | undefined;
|
|
10
|
+
//# sourceMappingURL=replaceTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replaceTheme.d.ts","sourceRoot":"","sources":["../src/replaceTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAIpD,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,KAAK,GACN,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,eAAe,EAAE,GAAG,CAAC,CAAC,CAAA;CACnD;;;;cAGA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ThemeDefinition, ThemeName } from '@hanzogui/web';
|
|
2
|
+
export declare function updateTheme({ name, theme, }: {
|
|
3
|
+
name: ThemeName | (string & {});
|
|
4
|
+
theme: Partial<Record<keyof ThemeDefinition, any>>;
|
|
5
|
+
}): {
|
|
6
|
+
themeRaw: import("@hanzogui/web").ThemeParsed;
|
|
7
|
+
theme: {};
|
|
8
|
+
cssRules: string[];
|
|
9
|
+
} | undefined;
|
|
10
|
+
//# sourceMappingURL=updateTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updateTheme.d.ts","sourceRoot":"","sources":["../src/updateTheme.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI/D,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,KAAK,GACN,EAAE;IACD,IAAI,EAAE,SAAS,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAC/B,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,eAAe,EAAE,GAAG,CAAC,CAAC,CAAA;CACnD;;;;cAEA"}
|