@tamagui/create-theme 1.31.3 → 1.32.0

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.
@@ -0,0 +1,72 @@
1
+ import { isMinusZero } from './isMinusZero'
2
+ import { setThemeInfo } from './themeInfo'
3
+ import { CreateThemeOptions, CreateThemePalette, GenericTheme, ThemeMask } from './types'
4
+
5
+ const identityCache = new Map()
6
+
7
+ export function createTheme<
8
+ Definition extends ThemeMask,
9
+ Extras extends GenericTheme = {}
10
+ >(
11
+ palette: CreateThemePalette,
12
+ definition: Definition,
13
+ options?: CreateThemeOptions
14
+ ): {
15
+ [key in keyof Definition | keyof Extras]: string
16
+ } {
17
+ const cacheKey = JSON.stringify([palette, definition, options])
18
+ if (identityCache.has(cacheKey)) {
19
+ return identityCache.get(cacheKey)
20
+ }
21
+
22
+ const theme = {
23
+ ...(Object.fromEntries(
24
+ Object.entries(definition).map(([key, offset]) => {
25
+ return [key, getValue(palette, offset)]
26
+ })
27
+ ) as any),
28
+ ...options?.nonInheritedValues,
29
+ }
30
+
31
+ setThemeInfo(theme, { palette, definition, options })
32
+ identityCache.set(cacheKey, theme)
33
+
34
+ return theme
35
+ }
36
+
37
+ const getValue = (palette: CreateThemePalette, value: string | number) => {
38
+ if (typeof value === 'string') return value
39
+ const max = palette.length - 1
40
+ const isPositive = value === 0 ? !isMinusZero(value) : value >= 0
41
+ const next = isPositive ? value : max + value
42
+ const index = Math.min(Math.max(0, next), max)
43
+ return palette[index]
44
+ }
45
+
46
+ type SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string
47
+ ? ParentKeys
48
+ : never}_${ChildKeys extends string ? ChildKeys : never}`
49
+
50
+ type ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (
51
+ name: Name,
52
+ theme: Theme
53
+ ) => { [key: string]: Theme }
54
+
55
+ export function addChildren<
56
+ Themes extends { [key: string]: GenericTheme },
57
+ GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>
58
+ >(
59
+ themes: Themes,
60
+ getChildren: GetChildren
61
+ ): Themes & {
62
+ [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]
63
+ } {
64
+ const out = { ...themes }
65
+ for (const key in themes) {
66
+ const subThemes = getChildren(key, themes[key])
67
+ for (const sKey in subThemes) {
68
+ out[`${key}_${sKey}`] = subThemes[sKey] as any
69
+ }
70
+ }
71
+ return out as any
72
+ }
@@ -0,0 +1,44 @@
1
+ type ObjectType = Record<PropertyKey, unknown>
2
+
3
+ type PickByValue<OBJ_T, VALUE_T> = // From https://stackoverflow.com/a/55153000
4
+ Pick<OBJ_T, { [K in keyof OBJ_T]: OBJ_T[K] extends VALUE_T ? K : never }[keyof OBJ_T]>
5
+
6
+ type ObjectEntries<OBJ_T> = // From https://stackoverflow.com/a/60142095
7
+ { [K in keyof OBJ_T]: [keyof PickByValue<OBJ_T, OBJ_T[K]>, OBJ_T[K]] }[keyof OBJ_T][]
8
+
9
+ export const objectKeys = <O extends Object>(obj: O) => Object.keys(obj) as Array<keyof O>
10
+
11
+ export function objectEntries<OBJ_T extends ObjectType>(
12
+ obj: OBJ_T
13
+ ): ObjectEntries<OBJ_T> {
14
+ return Object.entries(obj) as ObjectEntries<OBJ_T>
15
+ }
16
+
17
+ type EntriesType =
18
+ | [PropertyKey, unknown][]
19
+ | ReadonlyArray<readonly [PropertyKey, unknown]>
20
+
21
+ // Existing Utils
22
+ type DeepWritable<OBJ_T> = { -readonly [P in keyof OBJ_T]: DeepWritable<OBJ_T[P]> }
23
+ type UnionToIntersection<UNION_T> = // From https://stackoverflow.com/a/50375286
24
+ (UNION_T extends any ? (k: UNION_T) => void : never) extends (k: infer I) => void
25
+ ? I
26
+ : never
27
+
28
+ // New Utils
29
+ type UnionObjectFromArrayOfPairs<ARR_T extends EntriesType> =
30
+ DeepWritable<ARR_T> extends (infer R)[]
31
+ ? R extends [infer key, infer val]
32
+ ? { [prop in key & PropertyKey]: val }
33
+ : never
34
+ : never
35
+ type MergeIntersectingObjects<ObjT> = { [key in keyof ObjT]: ObjT[key] }
36
+ type EntriesToObject<ARR_T extends EntriesType> = MergeIntersectingObjects<
37
+ UnionToIntersection<UnionObjectFromArrayOfPairs<ARR_T>>
38
+ >
39
+
40
+ export function objectFromEntries<ARR_T extends EntriesType>(
41
+ arr: ARR_T
42
+ ): EntriesToObject<ARR_T> {
43
+ return Object.fromEntries(arr) as EntriesToObject<ARR_T>
44
+ }
package/src/index.tsx CHANGED
@@ -1,174 +1,4 @@
1
- import type { Variable } from '@tamagui/web'
2
-
3
- export type ThemeMask = Record<string, string | number>
4
- export type Palette = (string | Variable)[]
5
-
6
- export type MaskOptions = {
7
- palette?: Palette
8
- override?: Partial<ThemeMask>
9
- skip?: Partial<ThemeMask>
10
- strength?: number
11
- max?: number
12
- min?: number
13
- }
14
-
15
- type GenericTheme = { [key: string]: string | Variable }
16
-
17
- export type CreateMask = <A extends ThemeMask>(template: A, options: MaskOptions) => A
18
-
19
- const THEME_INFO = new WeakMap<
20
- any,
21
- { palette: Palette; definition: ThemeMask; cache: Map<any, any> }
22
- >()
23
-
24
- export function createTheme<
25
- Definition extends ThemeMask,
26
- Extras extends Record<string, string> = {}
27
- >(
28
- palette: Palette,
29
- definition: Definition,
30
- options?: {
31
- nonInheritedValues?: Extras
32
- }
33
- ): {
34
- [key in keyof Definition | keyof Extras]: string
35
- } {
36
- const theme = {
37
- ...(Object.fromEntries(
38
- Object.entries(definition).map(([key, offset]) => {
39
- return [key, getValue(palette, offset)]
40
- })
41
- ) as any),
42
- ...options?.nonInheritedValues,
43
- }
44
- THEME_INFO.set(theme, { palette, definition, cache: new Map() })
45
- return theme
46
- }
47
-
48
- const getValue = (palette: Palette, value: string | number) => {
49
- if (typeof value === 'string') return value
50
- const max = palette.length - 1
51
- const isPositive = value === 0 ? !isMinusZero(value) : value >= 0
52
- const next = isPositive ? value : max + value
53
- const index = Math.min(Math.max(0, next), max)
54
- return palette[index]
55
- }
56
-
57
- type SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string
58
- ? ParentKeys
59
- : never}_${ChildKeys extends string ? ChildKeys : never}`
60
-
61
- type ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (
62
- name: Name,
63
- theme: Theme
64
- ) => { [key: string]: Theme }
65
-
66
- export function addChildren<
67
- Themes extends { [key: string]: GenericTheme },
68
- GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>
69
- >(
70
- themes: Themes,
71
- getChildren: GetChildren
72
- ): Themes & {
73
- [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes]
74
- } {
75
- const out = { ...themes }
76
- for (const key in themes) {
77
- const subThemes = getChildren(key, themes[key])
78
- for (const sKey in subThemes) {
79
- out[`${key}_${sKey}`] = subThemes[sKey] as any
80
- }
81
- }
82
- return out as any
83
- }
84
-
85
- export const skipMask: CreateMask = (template, { skip }) => {
86
- if (!skip) return template
87
- return Object.fromEntries(
88
- Object.entries(template).filter(([k]) => !(k in skip))
89
- ) as typeof template
90
- }
91
-
92
- export const createShiftMask = ({ inverse }: { inverse?: boolean } = {}) => {
93
- return ((template, opts) => {
94
- const { override, max: maxIn, palette, min = 0, strength = 1 } = opts
95
- const values = Object.entries(template)
96
- const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)
97
- const out = {}
98
- for (const [key, value] of values) {
99
- if (typeof value === 'string') continue
100
- if (typeof override?.[key] === 'number') {
101
- const overrideShift = override[key] as number
102
- out[key] = value + overrideShift
103
- continue
104
- }
105
- const isPositive = value === 0 ? !isMinusZero(value) : value >= 0
106
- const direction = isPositive ? 1 : -1
107
- const invert = inverse ? -1 : 1
108
- const next = value + strength * direction * invert
109
- const clamped = isPositive
110
- ? Math.max(min, Math.min(max, next))
111
- : Math.min(-min, Math.max(-max, next))
112
-
113
- out[key] = clamped
114
- }
115
-
116
- return skipMask(out, opts) as typeof template
117
- }) as CreateMask
118
- }
119
-
120
- export const createWeakenMask = () => createShiftMask()
121
- export const createStrengthenMask = () => createShiftMask({ inverse: true })
122
-
123
- function isMinusZero(value) {
124
- return 1 / value === -Infinity
125
- }
126
-
127
- export function applyMask<Theme extends GenericTheme>(
128
- theme: Theme,
129
- mask: CreateMask,
130
- options: MaskOptions = {}
131
- ): Theme {
132
- const info = THEME_INFO.get(theme)
133
- if (!info) {
134
- throw new Error(
135
- process.env.NODE_ENV !== 'production'
136
- ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`
137
- : `❌ Err2`
138
- )
139
- }
140
-
141
- const template = mask(info.definition, {
142
- palette: info.palette,
143
- ...options,
144
- })
145
- const next = createTheme(info.palette, template) as Theme
146
-
147
- return next
148
- }
149
-
150
- // --- tests ---
151
-
152
- if (process.env.NODE_ENV === 'development') {
153
- const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']
154
- const template = { bg: 1, fg: -1 }
155
-
156
- const stongerMask = createStrengthenMask()
157
- const weakerMask = createWeakenMask()
158
-
159
- const theme = createTheme(palette, template)
160
- if (theme.bg !== '1') throw `❌`
161
- if (theme.fg !== '-1') throw `❌`
162
-
163
- const str = applyMask(theme, stongerMask)
164
- if (str.bg !== '0') throw `❌`
165
- if (str.fg !== '-0') throw `❌`
166
-
167
- const weak = applyMask(theme, weakerMask)
168
- if (weak.bg !== '2') throw `❌`
169
- if (weak.fg !== '-2') throw `❌`
170
-
171
- const weak2 = applyMask(theme, weakerMask, { strength: 2 })
172
- if (weak2.bg !== '3') throw `❌`
173
- if (weak2.fg !== '-3') throw `❌`
174
- }
1
+ export * from './createTheme'
2
+ export * from './masks'
3
+ export * from './types'
4
+ export * from './ThemeBuilder'
@@ -0,0 +1,3 @@
1
+ export function isMinusZero(value) {
2
+ return 1 / value === -Infinity
3
+ }
package/src/masks.tsx ADDED
@@ -0,0 +1,155 @@
1
+ import { createTheme } from './createTheme'
2
+ import { objectEntries, objectFromEntries } from './helpers'
3
+ import { isMinusZero } from './isMinusZero'
4
+ import { getThemeInfo, setThemeInfo } from './themeInfo'
5
+ import { CreateMask, GenericTheme, MaskFunction, MaskOptions, ThemeMask } from './types'
6
+
7
+ export const createMask = <C extends CreateMask | MaskFunction>(
8
+ createMask: C
9
+ ): CreateMask =>
10
+ typeof createMask === 'function'
11
+ ? { name: createMask.name || 'unnamed', mask: createMask }
12
+ : createMask
13
+
14
+ export const combineMasks = (...masks: CreateMask[]) => {
15
+ const mask: CreateMask = {
16
+ name: 'combine-mask',
17
+ mask: (template, opts) => {
18
+ let current = template
19
+ for (const mask of masks) {
20
+ current = applyMask(current, mask, opts)
21
+ }
22
+ return current
23
+ },
24
+ }
25
+ return mask
26
+ }
27
+
28
+ export const skipMask: CreateMask = {
29
+ name: 'skip-mask',
30
+ mask: (template, { skip }) => {
31
+ if (!skip) return template
32
+ return Object.fromEntries(
33
+ Object.entries(template).filter(([k]) => !(k in skip))
34
+ ) as typeof template
35
+ },
36
+ }
37
+
38
+ export const createIdentityMask = (): CreateMask => ({
39
+ name: 'identity-mask',
40
+ mask: (template) => template,
41
+ })
42
+
43
+ export const createInverseMask = () => {
44
+ const mask: CreateMask = {
45
+ name: 'inverse-mask',
46
+ mask: (template, opts) => {
47
+ const inversed = objectFromEntries(
48
+ objectEntries(template).map(([k, v]) => [k, -v])
49
+ ) as any
50
+ return skipMask.mask(inversed, opts)
51
+ },
52
+ }
53
+ return mask
54
+ }
55
+
56
+ type ShiftMaskOptions = { inverse?: boolean }
57
+
58
+ export const createShiftMask = (
59
+ { inverse }: ShiftMaskOptions = {},
60
+ defaultOptions?: MaskOptions
61
+ ) => {
62
+ const mask: CreateMask = {
63
+ name: 'shift-mask',
64
+ mask: (template, opts) => {
65
+ const {
66
+ override,
67
+ max: maxIn,
68
+ palette,
69
+ min = 0,
70
+ strength = 1,
71
+ } = { ...defaultOptions, ...opts }
72
+ const values = Object.entries(template)
73
+ const max = maxIn ?? (palette ? Object.values(palette).length - 1 : Infinity)
74
+ const out = {}
75
+ for (const [key, value] of values) {
76
+ if (typeof value === 'string') continue
77
+ if (typeof override?.[key] === 'number') {
78
+ const overrideShift = override[key] as number
79
+ out[key] = value + overrideShift
80
+ continue
81
+ } else if (typeof override?.[key] === 'string') {
82
+ out[key] = override[key]
83
+ continue
84
+ }
85
+ const isPositive = value === 0 ? !isMinusZero(value) : value >= 0
86
+ const direction = isPositive ? 1 : -1
87
+ const invert = inverse ? -1 : 1
88
+ const next = value + strength * direction * invert
89
+ const clamped = isPositive
90
+ ? Math.max(min, Math.min(max, next))
91
+ : Math.min(-min, Math.max(-max, next))
92
+
93
+ out[key] = clamped
94
+ }
95
+
96
+ return skipMask.mask(out, opts) as typeof template
97
+ },
98
+ }
99
+ return mask
100
+ }
101
+
102
+ export const createWeakenMask = (defaultOptions?: MaskOptions): CreateMask => ({
103
+ name: 'soften-mask',
104
+ mask: createShiftMask({}, defaultOptions).mask,
105
+ })
106
+
107
+ export const createSoftenMask = createWeakenMask
108
+
109
+ export const createStrengthenMask = (defaultOptions?: MaskOptions): CreateMask => ({
110
+ name: 'strengthen-mask',
111
+ mask: createShiftMask({ inverse: true }, defaultOptions).mask,
112
+ })
113
+
114
+ export function applyMask<Theme extends GenericTheme | ThemeMask>(
115
+ theme: Theme,
116
+ mask: CreateMask,
117
+ options: MaskOptions = {}
118
+ ): Theme {
119
+ const info = getThemeInfo(theme)
120
+
121
+ if (!info) {
122
+ throw new Error(
123
+ process.env.NODE_ENV !== 'production'
124
+ ? `No info found for theme, you must pass the theme created by createThemeFromPalette directly to extendTheme`
125
+ : `❌ Err2`
126
+ )
127
+ }
128
+
129
+ const skip = {
130
+ ...options.skip,
131
+ }
132
+
133
+ // skip nonInheritedValues from parent theme
134
+ if (info.options?.nonInheritedValues) {
135
+ for (const key in info.options.nonInheritedValues) {
136
+ skip[key] = 1
137
+ }
138
+ }
139
+
140
+ // convert theme back to template first
141
+ const template = mask.mask(info.definition, {
142
+ palette: info.palette,
143
+ ...options,
144
+ skip,
145
+ })
146
+
147
+ const next = createTheme(info.palette, template) as Theme
148
+
149
+ setThemeInfo(next, {
150
+ definition: template,
151
+ palette: info.palette,
152
+ })
153
+
154
+ return next
155
+ }
package/src/tests.tsx ADDED
@@ -0,0 +1,27 @@
1
+ import { createTheme } from './createTheme'
2
+ import { applyMask, createStrengthenMask, createWeakenMask } from './masks'
3
+
4
+ // --- tests ---
5
+ if (process.env.NODE_ENV === 'development') {
6
+ const palette = ['0', '1', '2', '3', '-3', '-2', '-1', '-0']
7
+ const template = { bg: 1, fg: -1 }
8
+
9
+ const stongerMask = createStrengthenMask()
10
+ const weakerMask = createWeakenMask()
11
+
12
+ const theme = createTheme(palette, template)
13
+ if (theme.bg !== '1') throw `❌`
14
+ if (theme.fg !== '-1') throw `❌`
15
+
16
+ const str = applyMask(theme, stongerMask)
17
+ if (str.bg !== '0') throw `❌`
18
+ if (str.fg !== '-0') throw `❌`
19
+
20
+ const weak = applyMask(theme, weakerMask)
21
+ if (weak.bg !== '2') throw `❌`
22
+ if (weak.fg !== '-2') throw `❌`
23
+
24
+ const weak2 = applyMask(theme, weakerMask, { strength: 2 })
25
+ if (weak2.bg !== '3') throw `❌`
26
+ if (weak2.fg !== '-3') throw `❌`
27
+ }
@@ -0,0 +1,26 @@
1
+ import { CreateThemeOptions, CreateThemePalette, GenericTheme, ThemeMask } from './types'
2
+
3
+ export type ThemeInfo = {
4
+ palette: CreateThemePalette
5
+ definition: ThemeMask
6
+ options?: CreateThemeOptions
7
+ cache: Map<any, any>
8
+ }
9
+
10
+ const THEME_INFO = new Map<string, ThemeInfo>()
11
+
12
+ export const getThemeInfo = (theme: GenericTheme | ThemeMask): ThemeInfo | undefined => {
13
+ return THEME_INFO.get(JSON.stringify(theme))
14
+ }
15
+
16
+ export const setThemeInfo = (
17
+ theme: GenericTheme | ThemeMask,
18
+ info: Pick<ThemeInfo, 'palette' | 'definition' | 'options'>
19
+ ) => {
20
+ const next = {
21
+ ...info,
22
+ cache: new Map(),
23
+ }
24
+ THEME_INFO.set(JSON.stringify(theme), next)
25
+ THEME_INFO.set(JSON.stringify(info.definition), next)
26
+ }
package/src/types.tsx ADDED
@@ -0,0 +1,27 @@
1
+ import type { Variable } from '@tamagui/web'
2
+
3
+ export type CreateThemePalette = (string | Variable)[]
4
+
5
+ export type ThemeMask = Record<string, string | number>
6
+
7
+ export type MaskOptions = {
8
+ palette?: CreateThemePalette
9
+ override?: Partial<ThemeMask>
10
+ skip?: Partial<ThemeMask>
11
+ strength?: number
12
+ max?: number
13
+ min?: number
14
+ }
15
+
16
+ export type GenericTheme = { [key: string]: string | Variable }
17
+
18
+ export type MaskFunction = <A extends ThemeMask>(template: A, options: MaskOptions) => A
19
+
20
+ export type CreateMask = {
21
+ name: string
22
+ mask: MaskFunction
23
+ }
24
+
25
+ export type CreateThemeOptions = {
26
+ nonInheritedValues?: GenericTheme
27
+ }
@@ -0,0 +1,86 @@
1
+ import { Narrow } from '@tamagui/web';
2
+ import { CreateMask, CreateThemeOptions, MaskOptions } from './types';
3
+ export type Palette = string[];
4
+ type GenericTheme = {
5
+ [key: string]: string;
6
+ };
7
+ export type Template = {
8
+ [key: string]: number;
9
+ };
10
+ type ThemeUsingMask<Masks = string> = MaskOptions & {
11
+ mask: Masks;
12
+ };
13
+ type ThemeUsingTemplate = CreateThemeOptions & {
14
+ palette: string;
15
+ template: string;
16
+ };
17
+ type ThemePreDefined = {
18
+ theme: GenericTheme;
19
+ };
20
+ export type Theme<Masks = string> = ThemePreDefined | ThemeUsingTemplate | ThemeUsingMask<Masks>;
21
+ type ThemeWithParent<Masks = string> = Theme<Masks> & {
22
+ parent: string;
23
+ };
24
+ type PaletteDefinitions = {
25
+ [key: string]: Palette;
26
+ };
27
+ type ThemeDefinition<Masks extends string = string> = Theme<Masks> | ThemeWithParent<Masks>[];
28
+ type UnionableString = string & {};
29
+ type ThemeDefinitions<Masks extends string = string> = {
30
+ [key: string]: ThemeDefinition<Masks | UnionableString>;
31
+ };
32
+ type TemplateDefinitions = {
33
+ [key: string]: Template;
34
+ };
35
+ type MaskDefinitions = {
36
+ [key: string]: CreateMask | CreateMask['mask'];
37
+ };
38
+ type ThemeBuilderState = {
39
+ palettes?: PaletteDefinitions;
40
+ templates?: TemplateDefinitions;
41
+ themes?: ThemeDefinitions;
42
+ masks?: MaskDefinitions;
43
+ };
44
+ type ObjectStringKeys<A extends Object | undefined> = A extends Object ? Exclude<keyof A, symbol | number> : never;
45
+ type GetGeneratedThemeFromTemplate<Template> = {
46
+ [key in keyof Template]: string;
47
+ };
48
+ type GetParentTheme<P, Themes extends ThemeDefinitions | undefined> = P extends string ? P extends keyof Themes ? Themes[P] : GetParentName<P> extends keyof Themes ? Themes[GetParentName<P>] : GetParentName<GetParentName<P>> extends keyof Themes ? Themes[GetParentName<GetParentName<P>>] : GetParentName<GetParentName<GetParentName<P>>> extends keyof Themes ? Themes[GetParentName<GetParentName<GetParentName<P>>>] : never : never;
49
+ type GetGeneratedTheme<TD extends any, S extends ThemeBuilderState> = TD extends {
50
+ theme: infer T;
51
+ } ? T : TD extends {
52
+ parent: infer P;
53
+ } ? GetGeneratedTheme<GetParentTheme<P, S['themes']>, S> : TD extends {
54
+ template: infer T;
55
+ } ? T extends keyof S['templates'] ? GetGeneratedThemeFromTemplate<S['templates'][T]> : TD : TD;
56
+ type GetGeneratedThemes<S extends ThemeBuilderState> = {
57
+ [Key in keyof S['themes']]: GetGeneratedTheme<S['themes'][Key], S>;
58
+ };
59
+ type GetParentName<N extends string> = N extends `${infer A}_${infer B}_${infer C}_${infer D}_${string}` ? `${A}_${B}_${C}_${D}` : N extends `${infer A}_${infer B}_${infer C}_${string}` ? `${A}_${B}_${C}` : N extends `${infer A}_${infer B}_${string}` ? `${A}_${B}` : N extends `${infer A}_${string}` ? `${A}` : never;
60
+ declare class ThemeBuilder<State extends ThemeBuilderState> {
61
+ state: State;
62
+ constructor(state: State);
63
+ addPalettes<const P extends PaletteDefinitions>(palettes: P): ThemeBuilder<State & {
64
+ readonly palettes: P;
65
+ }>;
66
+ addTemplates<const T extends TemplateDefinitions>(templates: T): ThemeBuilder<State & {
67
+ templates: T;
68
+ }>;
69
+ addMasks<const T extends MaskDefinitions>(masks: T): ThemeBuilder<State & {
70
+ masks: T;
71
+ }>;
72
+ addThemes<const T extends ThemeDefinitions<ObjectStringKeys<State['masks']>>>(themes: T): ThemeBuilder<State & {
73
+ themes: T;
74
+ }>;
75
+ addChildThemes<CTD extends Narrow<ThemeDefinitions<ObjectStringKeys<State['masks']>>>, const AvoidNestingWithin extends string[] = []>(childThemeDefinition: CTD, options?: {
76
+ avoidNestingWithin?: AvoidNestingWithin;
77
+ }): ThemeBuilder<State & {
78
+ themes: { [key in `${Exclude<keyof NonNullable<State["themes"]>, number | symbol>}_${Exclude<keyof CTD, number | symbol>}`]: CTD & {
79
+ parent: GetParentName<key>;
80
+ }; };
81
+ }>;
82
+ build(): GetGeneratedThemes<State>;
83
+ }
84
+ export declare function createThemeBuilder(): ThemeBuilder<{}>;
85
+ export {};
86
+ //# sourceMappingURL=ThemeBuilder.d.ts.map
@@ -0,0 +1,15 @@
1
+ import { CreateThemeOptions, CreateThemePalette, GenericTheme, ThemeMask } from './types';
2
+ export declare function createTheme<Definition extends ThemeMask, Extras extends GenericTheme = {}>(palette: CreateThemePalette, definition: Definition, options?: CreateThemeOptions): {
3
+ [key in keyof Definition | keyof Extras]: string;
4
+ };
5
+ type SubThemeKeys<ParentKeys, ChildKeys> = `${ParentKeys extends string ? ParentKeys : never}_${ChildKeys extends string ? ChildKeys : never}`;
6
+ type ChildGetter<Name extends string | number | symbol, Theme extends GenericTheme> = (name: Name, theme: Theme) => {
7
+ [key: string]: Theme;
8
+ };
9
+ export declare function addChildren<Themes extends {
10
+ [key: string]: GenericTheme;
11
+ }, GetChildren extends ChildGetter<keyof Themes, Themes[keyof Themes]>>(themes: Themes, getChildren: GetChildren): Themes & {
12
+ [key in SubThemeKeys<keyof Themes, keyof ReturnType<GetChildren>>]: Themes[keyof Themes];
13
+ };
14
+ export {};
15
+ //# sourceMappingURL=createTheme.d.ts.map
@@ -0,0 +1,24 @@
1
+ type ObjectType = Record<PropertyKey, unknown>;
2
+ type PickByValue<OBJ_T, VALUE_T> = Pick<OBJ_T, {
3
+ [K in keyof OBJ_T]: OBJ_T[K] extends VALUE_T ? K : never;
4
+ }[keyof OBJ_T]>;
5
+ type ObjectEntries<OBJ_T> = {
6
+ [K in keyof OBJ_T]: [keyof PickByValue<OBJ_T, OBJ_T[K]>, OBJ_T[K]];
7
+ }[keyof OBJ_T][];
8
+ export declare const objectKeys: <O extends Object>(obj: O) => (keyof O)[];
9
+ export declare function objectEntries<OBJ_T extends ObjectType>(obj: OBJ_T): ObjectEntries<OBJ_T>;
10
+ type EntriesType = [PropertyKey, unknown][] | ReadonlyArray<readonly [PropertyKey, unknown]>;
11
+ type DeepWritable<OBJ_T> = {
12
+ -readonly [P in keyof OBJ_T]: DeepWritable<OBJ_T[P]>;
13
+ };
14
+ type UnionToIntersection<UNION_T> = (UNION_T extends any ? (k: UNION_T) => void : never) extends (k: infer I) => void ? I : never;
15
+ type UnionObjectFromArrayOfPairs<ARR_T extends EntriesType> = DeepWritable<ARR_T> extends (infer R)[] ? R extends [infer key, infer val] ? {
16
+ [prop in key & PropertyKey]: val;
17
+ } : never : never;
18
+ type MergeIntersectingObjects<ObjT> = {
19
+ [key in keyof ObjT]: ObjT[key];
20
+ };
21
+ type EntriesToObject<ARR_T extends EntriesType> = MergeIntersectingObjects<UnionToIntersection<UnionObjectFromArrayOfPairs<ARR_T>>>;
22
+ export declare function objectFromEntries<ARR_T extends EntriesType>(arr: ARR_T): EntriesToObject<ARR_T>;
23
+ export {};
24
+ //# sourceMappingURL=helpers.d.ts.map