@tamagui/theme-builder 1.121.12-1737270844392 → 1.121.12-1737332968773

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.
Files changed (84) hide show
  1. package/dist/cjs/ThemeBuilder.cjs +3 -1
  2. package/dist/cjs/ThemeBuilder.js +5 -1
  3. package/dist/cjs/ThemeBuilder.js.map +1 -1
  4. package/dist/cjs/ThemeBuilder.native.js +3 -1
  5. package/dist/cjs/ThemeBuilder.native.js.map +1 -1
  6. package/dist/cjs/createThemeSuite.cjs +205 -0
  7. package/dist/cjs/createThemeSuite.js +214 -0
  8. package/dist/cjs/createThemeSuite.js.map +6 -0
  9. package/dist/cjs/createThemeSuite.native.js +234 -0
  10. package/dist/cjs/createThemeSuite.native.js.map +6 -0
  11. package/dist/cjs/defaultComponentThemes.cjs +81 -0
  12. package/dist/cjs/defaultComponentThemes.js +40 -0
  13. package/dist/cjs/defaultComponentThemes.js.map +6 -0
  14. package/dist/cjs/defaultComponentThemes.native.js +81 -0
  15. package/dist/cjs/defaultComponentThemes.native.js.map +6 -0
  16. package/dist/cjs/defaultTemplates.cjs +139 -0
  17. package/dist/cjs/defaultTemplates.js +130 -0
  18. package/dist/cjs/defaultTemplates.js.map +6 -0
  19. package/dist/cjs/defaultTemplates.native.js +140 -0
  20. package/dist/cjs/defaultTemplates.native.js.map +6 -0
  21. package/dist/cjs/getThemeSuitePalettes.cjs +81 -0
  22. package/dist/cjs/getThemeSuitePalettes.js +63 -0
  23. package/dist/cjs/getThemeSuitePalettes.js.map +6 -0
  24. package/dist/cjs/getThemeSuitePalettes.native.js +94 -0
  25. package/dist/cjs/getThemeSuitePalettes.native.js.map +6 -0
  26. package/dist/cjs/index.cjs +12 -1
  27. package/dist/cjs/index.js +8 -1
  28. package/dist/cjs/index.js.map +1 -1
  29. package/dist/cjs/index.native.js +15 -1
  30. package/dist/cjs/index.native.js.map +1 -1
  31. package/dist/esm/ThemeBuilder.js +5 -1
  32. package/dist/esm/ThemeBuilder.js.map +1 -1
  33. package/dist/esm/ThemeBuilder.mjs +3 -1
  34. package/dist/esm/ThemeBuilder.mjs.map +1 -1
  35. package/dist/esm/ThemeBuilder.native.js +3 -1
  36. package/dist/esm/ThemeBuilder.native.js.map +1 -1
  37. package/dist/esm/createThemeSuite.js +204 -0
  38. package/dist/esm/createThemeSuite.js.map +6 -0
  39. package/dist/esm/createThemeSuite.mjs +174 -0
  40. package/dist/esm/createThemeSuite.mjs.map +1 -0
  41. package/dist/esm/createThemeSuite.native.js +211 -0
  42. package/dist/esm/createThemeSuite.native.js.map +6 -0
  43. package/dist/esm/defaultComponentThemes.js +24 -0
  44. package/dist/esm/defaultComponentThemes.js.map +6 -0
  45. package/dist/esm/defaultComponentThemes.mjs +58 -0
  46. package/dist/esm/defaultComponentThemes.mjs.map +1 -0
  47. package/dist/esm/defaultComponentThemes.native.js +60 -0
  48. package/dist/esm/defaultComponentThemes.native.js.map +6 -0
  49. package/dist/esm/defaultTemplates.js +114 -0
  50. package/dist/esm/defaultTemplates.js.map +6 -0
  51. package/dist/esm/defaultTemplates.mjs +116 -0
  52. package/dist/esm/defaultTemplates.mjs.map +1 -0
  53. package/dist/esm/defaultTemplates.native.js +120 -0
  54. package/dist/esm/defaultTemplates.native.js.map +6 -0
  55. package/dist/esm/getThemeSuitePalettes.js +47 -0
  56. package/dist/esm/getThemeSuitePalettes.js.map +6 -0
  57. package/dist/esm/getThemeSuitePalettes.mjs +57 -0
  58. package/dist/esm/getThemeSuitePalettes.mjs.map +1 -0
  59. package/dist/esm/getThemeSuitePalettes.native.js +73 -0
  60. package/dist/esm/getThemeSuitePalettes.native.js.map +6 -0
  61. package/dist/esm/index.js +16 -0
  62. package/dist/esm/index.js.map +1 -1
  63. package/dist/esm/index.mjs +5 -1
  64. package/dist/esm/index.mjs.map +1 -1
  65. package/dist/esm/index.native.js +11 -0
  66. package/dist/esm/index.native.js.map +2 -2
  67. package/package.json +3 -3
  68. package/src/ThemeBuilder.ts +3 -1
  69. package/src/createThemeSuite.ts +394 -0
  70. package/src/defaultComponentThemes.ts +22 -0
  71. package/src/defaultTemplates.ts +142 -0
  72. package/src/getThemeSuitePalettes.ts +94 -0
  73. package/src/index.ts +13 -0
  74. package/types/ThemeBuilder.d.ts.map +1 -1
  75. package/types/createThemeSuite.d.ts +86 -0
  76. package/types/createThemeSuite.d.ts.map +1 -0
  77. package/types/defaultComponentThemes.d.ts +57 -0
  78. package/types/defaultComponentThemes.d.ts.map +1 -0
  79. package/types/defaultTemplates.d.ts +2 -0
  80. package/types/defaultTemplates.d.ts.map +1 -0
  81. package/types/getThemeSuitePalettes.d.ts +7 -0
  82. package/types/getThemeSuitePalettes.d.ts.map +1 -0
  83. package/types/index.d.ts +4 -0
  84. package/types/index.d.ts.map +1 -1
@@ -0,0 +1,394 @@
1
+ import { createThemeBuilder, type ThemeBuilder } from '@tamagui/theme-builder'
2
+ import type { BuildPalettes, BuildTemplates, BuildThemeSuiteProps } from '@tamagui/themes'
3
+ import { parseToHsla } from 'color2k'
4
+ import { defaultTemplates } from './defaultTemplates'
5
+ import { getThemeSuitePalettes } from './getThemeSuitePalettes'
6
+ import { defaultComponentThemes } from './defaultComponentThemes'
7
+
8
+ export { defaultTemplates } from './defaultTemplates'
9
+ export { getThemeSuitePalettes, PALETTE_BACKGROUND_OFFSET } from './getThemeSuitePalettes'
10
+
11
+ // for studio
12
+ // allows more detailed configuration, used by studio
13
+ // eventually we should merge this down into simple and have it handle what we need
14
+ export function createStudioThemes(props: BuildThemeSuiteProps) {
15
+ const palettes = createPalettes(props.palettes)
16
+ return createSimpleThemeBuilder({
17
+ palettes,
18
+ templates: defaultTemplates,
19
+ componentThemes: defaultComponentThemes,
20
+ })
21
+ }
22
+
23
+ /**
24
+ * TODO
25
+ *
26
+ * - we avoidNestingWithin accent, but sometimes want it eg v4-tamagui grandChildren
27
+ * a good default would be to IF palette is set, dont nest, IF only template, nest
28
+ * needs to update both runtime logic and types
29
+ */
30
+
31
+ type ExtraThemeValues = Record<string, string>
32
+ type ExtraThemeValuesByScheme<Values extends ExtraThemeValues = ExtraThemeValues> = {
33
+ dark: Values
34
+ light: Values
35
+ }
36
+
37
+ type SimpleThemeDefinition = { palette?: Palette; template?: string }
38
+ type BaseThemeDefinition<Extra extends ExtraThemeValuesByScheme> = {
39
+ palette: Palette
40
+ template?: string
41
+ extra?: Extra
42
+ }
43
+
44
+ export type SimpleThemesDefinition = Record<string, SimpleThemeDefinition>
45
+ type SimplePaletteDefinitions = Record<string, string[]>
46
+
47
+ type SinglePalette = string[]
48
+ type SchemePalette = { light: SinglePalette; dark: SinglePalette }
49
+ type Palette = SinglePalette | SchemePalette
50
+
51
+ export type CreateThemeSuiteProps<
52
+ Accent extends BaseThemeDefinition<Extra> | undefined = undefined,
53
+ GrandChildrenThemes extends SimpleThemesDefinition | undefined = undefined,
54
+ Extra extends ExtraThemeValuesByScheme = ExtraThemeValuesByScheme,
55
+ ChildrenThemes extends SimpleThemesDefinition = SimpleThemesDefinition,
56
+ ComponentThemes extends SimpleThemesDefinition = SimpleThemesDefinition,
57
+ Templates extends BuildTemplates = typeof defaultTemplates,
58
+ > = {
59
+ base: BaseThemeDefinition<Extra>
60
+ accent?: Accent
61
+ childrenThemes?: ChildrenThemes
62
+ grandChildrenThemes?: GrandChildrenThemes
63
+ templates?: Templates
64
+ componentThemes?: ComponentThemes
65
+ colorsToTheme?: (props: {
66
+ colors: string[]
67
+ name: string
68
+ scheme?: 'light' | 'dark'
69
+ }) => Record<string, string>
70
+ }
71
+
72
+ // TODO we moved studio over to mostly just control palette, so the need for this can basically go away
73
+ export function createThemeSuite<
74
+ Extra extends ExtraThemeValuesByScheme,
75
+ SubThemes extends SimpleThemesDefinition,
76
+ ComponentThemes extends SimpleThemesDefinition,
77
+ GrandChildrenThemes extends SimpleThemesDefinition | undefined = undefined,
78
+ Accent extends BaseThemeDefinition<Extra> | undefined = undefined,
79
+ >(
80
+ props: CreateThemeSuiteProps<
81
+ Accent,
82
+ GrandChildrenThemes,
83
+ Extra,
84
+ SubThemes,
85
+ ComponentThemes
86
+ >
87
+ ) {
88
+ const {
89
+ accent,
90
+ childrenThemes,
91
+ grandChildrenThemes,
92
+ templates = defaultTemplates,
93
+ componentThemes = defaultComponentThemes as unknown as any,
94
+ } = props
95
+
96
+ const builder = createSimpleThemeBuilder({
97
+ extra: props.base.extra,
98
+ componentThemes,
99
+ palettes: createPalettes(getThemesPalettes(props)),
100
+ templates: templates as typeof defaultTemplates,
101
+ accentTheme: !!accent as Accent extends undefined ? false : true,
102
+ childrenThemes: normalizeSubThemes(childrenThemes),
103
+ grandChildrenThemes: (grandChildrenThemes
104
+ ? normalizeSubThemes(grandChildrenThemes)
105
+ : undefined) as GrandChildrenThemes extends undefined
106
+ ? undefined
107
+ : Record<keyof GrandChildrenThemes, any>,
108
+ })
109
+
110
+ lastBuilder = builder.themeBuilder
111
+
112
+ return builder.themes
113
+ }
114
+
115
+ let lastBuilder: ThemeBuilder | null = null
116
+
117
+ export const getLastBuilder = () => lastBuilder
118
+
119
+ function normalizeSubThemes<A extends SimpleThemesDefinition>(defs?: A) {
120
+ return Object.fromEntries(
121
+ Object.entries(defs || {}).map(([name, value]) => {
122
+ return [
123
+ name,
124
+ {
125
+ palette: name,
126
+ template: value.template || 'base',
127
+ },
128
+ ]
129
+ })
130
+ ) as Record<keyof A, any>
131
+ }
132
+
133
+ const defaultPalettes: SimplePaletteDefinitions = createPalettes(
134
+ getThemesPalettes({
135
+ base: {
136
+ palette: ['#fff', '#000'],
137
+ },
138
+ accent: {
139
+ palette: ['#ff0000', '#ff9999'],
140
+ },
141
+ })
142
+ )
143
+
144
+ type NamesWithChildrenNames<ParentNames extends string, ChildNames> =
145
+ | ParentNames
146
+ | (ChildNames extends string ? `${ParentNames}_${ChildNames}` : never)
147
+
148
+ // a simpler API surface
149
+ export function createSimpleThemeBuilder<
150
+ Extra extends ExtraThemeValuesByScheme,
151
+ Templates extends BuildTemplates,
152
+ Palettes extends SimplePaletteDefinitions,
153
+ ChildrenThemes extends Record<
154
+ string,
155
+ {
156
+ template: keyof Templates extends string ? keyof Templates : never
157
+ palette?: string
158
+ }
159
+ >,
160
+ GrandChildrenThemes extends
161
+ | undefined
162
+ | Record<
163
+ string,
164
+ {
165
+ template: keyof Templates extends string ? keyof Templates : never
166
+ palette?: string
167
+ }
168
+ >,
169
+ HasAccent extends boolean,
170
+ ComponentThemes extends SimpleThemesDefinition | false,
171
+ FullTheme = {
172
+ [ThemeKey in keyof Templates['light_base'] | keyof Extra['dark']]: string
173
+ },
174
+ ThemeNames extends string =
175
+ | 'light'
176
+ | 'dark'
177
+ | (HasAccent extends true ? 'light_accent' | 'dark_accent' : never)
178
+ | (keyof ChildrenThemes extends string
179
+ ? `${'light' | 'dark'}_${GrandChildrenThemes extends undefined
180
+ ? keyof ChildrenThemes
181
+ : NamesWithChildrenNames<keyof ChildrenThemes, keyof GrandChildrenThemes>}`
182
+ : never),
183
+ >(props: {
184
+ palettes?: Palettes
185
+ accentTheme?: HasAccent
186
+ templates?: Templates
187
+ childrenThemes?: ChildrenThemes
188
+ grandChildrenThemes?: GrandChildrenThemes
189
+ componentThemes?: ComponentThemes
190
+ extra?: Extra
191
+ }): {
192
+ themeBuilder: ThemeBuilder<any>
193
+ themes: Record<ThemeNames, FullTheme>
194
+ } {
195
+ const {
196
+ extra,
197
+ childrenThemes = null as unknown as ChildrenThemes,
198
+ grandChildrenThemes = null as unknown as GrandChildrenThemes,
199
+ templates = defaultTemplates as unknown as Templates,
200
+ palettes = defaultPalettes as unknown as Palettes,
201
+ componentThemes = templates === (defaultTemplates as any)
202
+ ? (defaultComponentThemes as unknown as ComponentThemes)
203
+ : undefined,
204
+ } = props
205
+
206
+ // start theme-builder
207
+ let themeBuilder = createThemeBuilder()
208
+ .addPalettes(palettes)
209
+ .addTemplates(templates)
210
+ .addThemes({
211
+ light: {
212
+ template: 'base',
213
+ palette: 'light',
214
+ nonInheritedValues: extra?.light,
215
+ },
216
+ dark: {
217
+ template: 'base',
218
+ palette: 'dark',
219
+ nonInheritedValues: extra?.dark,
220
+ },
221
+ })
222
+
223
+ if (palettes.light_accent) {
224
+ themeBuilder = themeBuilder.addChildThemes({
225
+ accent: [
226
+ {
227
+ parent: 'light',
228
+ template: 'base',
229
+ palette: 'light_accent',
230
+ },
231
+ {
232
+ parent: 'dark',
233
+ template: 'base',
234
+ palette: 'dark_accent',
235
+ },
236
+ ],
237
+ })
238
+ }
239
+
240
+ if (childrenThemes) {
241
+ themeBuilder = themeBuilder.addChildThemes(childrenThemes, {
242
+ avoidNestingWithin: ['accent'],
243
+ }) as any
244
+ }
245
+
246
+ if (grandChildrenThemes) {
247
+ themeBuilder = themeBuilder.addChildThemes(grandChildrenThemes, {
248
+ avoidNestingWithin: ['accent'],
249
+ }) as any
250
+ }
251
+
252
+ if (componentThemes) {
253
+ themeBuilder = themeBuilder.addComponentThemes(getComponentThemes(componentThemes), {
254
+ avoidNestingWithin: [
255
+ 'accent',
256
+ // ...Object.keys(childrenThemes || {}),
257
+ ...Object.keys(grandChildrenThemes || {}),
258
+ ],
259
+ })
260
+ }
261
+
262
+ return {
263
+ themeBuilder,
264
+ themes: themeBuilder.build() as any,
265
+ }
266
+ }
267
+
268
+ function getSchemePalette(colors: SinglePalette): SchemePalette {
269
+ return {
270
+ light: colors,
271
+ dark: colors.toReversed(),
272
+ }
273
+ }
274
+
275
+ function getAnchors(palette: SchemePalette) {
276
+ const maxIndex = 11
277
+ const numItems = palette.light.length
278
+
279
+ const anchors = palette.light.map((lcolor, index) => {
280
+ const dcolor = palette.dark[index]
281
+ const [lhue, lsat, llum] = parseToHsla(lcolor)
282
+ const [dhue, dsat, dlum] = parseToHsla(dcolor)
283
+ return {
284
+ index: spreadIndex(maxIndex, numItems, index),
285
+ hue: { light: lhue, dark: dhue },
286
+ sat: { light: lsat, dark: dsat },
287
+ lum: { light: llum, dark: dlum },
288
+ } as const
289
+ })
290
+
291
+ return anchors
292
+ }
293
+
294
+ function spreadIndex(maxIndex: number, numItems: number, index: number) {
295
+ return Math.round((index / (numItems - 1)) * maxIndex)
296
+ }
297
+
298
+ function coerceSimplePaletteToSchemePalette(def: Palette) {
299
+ return Array.isArray(def) ? getSchemePalette(def) : def
300
+ }
301
+
302
+ function getThemesPalettes(props: CreateThemeSuiteProps<any, any>): BuildPalettes {
303
+ const base = coerceSimplePaletteToSchemePalette(props.base.palette)
304
+ const accent = props.accent
305
+ ? coerceSimplePaletteToSchemePalette(props.accent.palette)
306
+ : null
307
+
308
+ const baseAnchors = getAnchors(base)
309
+
310
+ function getSubThemesPalettes(defs: SimpleThemesDefinition) {
311
+ return Object.fromEntries(
312
+ Object.entries(defs).map(([key, value]) => {
313
+ return [
314
+ key,
315
+ {
316
+ name: key,
317
+ anchors: value.palette
318
+ ? getAnchors(coerceSimplePaletteToSchemePalette(value.palette))
319
+ : baseAnchors,
320
+ },
321
+ ]
322
+ })
323
+ )
324
+ }
325
+
326
+ return {
327
+ base: {
328
+ name: 'base',
329
+ anchors: baseAnchors,
330
+ },
331
+ ...(accent && {
332
+ accent: {
333
+ name: 'accent',
334
+ anchors: getAnchors(accent),
335
+ },
336
+ }),
337
+ ...(props.childrenThemes && getSubThemesPalettes(props.childrenThemes)),
338
+ ...(props.grandChildrenThemes && getSubThemesPalettes(props.grandChildrenThemes)),
339
+ }
340
+ }
341
+
342
+ export const getComponentThemes = (components: SimpleThemesDefinition) => {
343
+ return Object.fromEntries(
344
+ Object.entries(components).map(([componentName, { template }]) => {
345
+ return [
346
+ componentName,
347
+ {
348
+ parent: '',
349
+ template: template || 'base',
350
+ },
351
+ ]
352
+ })
353
+ )
354
+ }
355
+
356
+ export function createPalettes(palettes: BuildPalettes): SimplePaletteDefinitions {
357
+ const accentPalettes = palettes.accent ? getThemeSuitePalettes(palettes.accent) : null
358
+ const basePalettes = getThemeSuitePalettes(palettes.base)
359
+
360
+ const next = Object.fromEntries(
361
+ Object.entries(palettes).flatMap(([name, palette]) => {
362
+ const palettes = getThemeSuitePalettes(palette)
363
+ const isAccent = name.startsWith('accent')
364
+ const oppositePalettes = isAccent ? basePalettes : accentPalettes
365
+ const oppositeLight = oppositePalettes!.light
366
+ const oppositeDark = oppositePalettes!.dark
367
+
368
+ const bgOffset = 7
369
+
370
+ const out = [
371
+ [
372
+ name === 'base' ? 'light' : `light_${name}`,
373
+ [
374
+ oppositeLight[bgOffset],
375
+ ...palettes.light,
376
+ oppositeLight[oppositeLight.length - bgOffset - 1],
377
+ ],
378
+ ],
379
+ [
380
+ name === 'base' ? 'dark' : `dark_${name}`,
381
+ [
382
+ oppositeDark[oppositeDark.length - bgOffset - 1],
383
+ ...palettes.dark,
384
+ oppositeDark[bgOffset],
385
+ ],
386
+ ],
387
+ ] as const
388
+
389
+ return out
390
+ })
391
+ )
392
+
393
+ return next as any
394
+ }
@@ -0,0 +1,22 @@
1
+ import { SimpleThemesDefinition } from './createThemeSuite'
2
+
3
+ export const defaultComponentThemes = {
4
+ ListItem: { template: 'surface1' },
5
+ SelectTrigger: { template: 'surface1' },
6
+ Card: { template: 'surface1' },
7
+ Button: { template: 'surface3' },
8
+ Checkbox: { template: 'surface2' },
9
+ Switch: { template: 'surface2' },
10
+ SwitchThumb: { template: 'inverse' },
11
+ TooltipContent: { template: 'surface2' },
12
+ Progress: { template: 'surface1' },
13
+ RadioGroupItem: { template: 'surface2' },
14
+ TooltipArrow: { template: 'surface1' },
15
+ SliderTrackActive: { template: 'surface3' },
16
+ SliderTrack: { template: 'surface1' },
17
+ SliderThumb: { template: 'inverse' },
18
+ Tooltip: { template: 'inverse' },
19
+ ProgressIndicator: { template: 'inverse' },
20
+ Input: { template: 'surface1' },
21
+ TextArea: { template: 'surface1' },
22
+ } satisfies SimpleThemesDefinition
@@ -0,0 +1,142 @@
1
+ import { objectFromEntries, objectKeys, type BuildTemplates } from '@tamagui/themes'
2
+
3
+ const getTemplates = () => {
4
+ const lightTemplates = getBaseTemplates('light')
5
+ const darkTemplates = getBaseTemplates('dark')
6
+ const templates = {
7
+ ...objectFromEntries(
8
+ objectKeys(lightTemplates).map(
9
+ (name) => [`light_${name}`, lightTemplates[name]] as const
10
+ )
11
+ ),
12
+ ...objectFromEntries(
13
+ objectKeys(darkTemplates).map(
14
+ (name) => [`dark_${name}`, darkTemplates[name]] as const
15
+ )
16
+ ),
17
+ }
18
+ return templates as Record<keyof typeof templates, typeof lightTemplates.base>
19
+ }
20
+
21
+ const getBaseTemplates = (scheme: 'dark' | 'light') => {
22
+ const isLight = scheme === 'light'
23
+
24
+ // our palettes have 4 things padding each end until you get to bg/color:
25
+ // [accentBg, transparent1, transparent2, transparent3, transparent4, background, ...]
26
+ const bgIndex = 5
27
+ const lighten = isLight ? -1 : 1
28
+ const darken = -lighten
29
+ const borderColor = bgIndex + 3
30
+
31
+ // templates use the palette and specify index
32
+ // negative goes backwards from end so -1 is the last item
33
+ const base = {
34
+ accentBackground: 0,
35
+ accentColor: -0,
36
+
37
+ background0: 1,
38
+ background025: 2,
39
+ background05: 3,
40
+ background075: 4,
41
+ color1: bgIndex,
42
+ color2: bgIndex + 1,
43
+ color3: bgIndex + 2,
44
+ color4: bgIndex + 3,
45
+ color5: bgIndex + 4,
46
+ color6: bgIndex + 5,
47
+ color7: bgIndex + 6,
48
+ color8: bgIndex + 7,
49
+ color9: bgIndex + 8,
50
+ color10: bgIndex + 9,
51
+ color11: bgIndex + 10,
52
+ color12: bgIndex + 11,
53
+ color0: -1,
54
+ color025: -2,
55
+ color05: -3,
56
+ color075: -4,
57
+ // the background, color, etc keys here work like generics - they make it so you
58
+ // can publish components for others to use without mandating a specific color scale
59
+ // the @tamagui/button Button component looks for `$background`, so you set the
60
+ // dark_red_Button theme to have a stronger background than the dark_red theme.
61
+ background: bgIndex,
62
+ backgroundHover: bgIndex + lighten, // always lighten on hover no matter the scheme
63
+ backgroundPress: bgIndex + darken, // always darken on press no matter the theme
64
+ backgroundFocus: bgIndex + darken,
65
+ borderColor,
66
+ borderColorHover: borderColor + lighten,
67
+ borderColorPress: borderColor + darken,
68
+ borderColorFocus: borderColor,
69
+ color: -bgIndex,
70
+ colorHover: -bgIndex - 1,
71
+ colorPress: -bgIndex,
72
+ colorFocus: -bgIndex - 1,
73
+ colorTransparent: -1,
74
+ placeholderColor: -bgIndex - 3,
75
+ outlineColor: -2,
76
+ }
77
+
78
+ const surface1 = {
79
+ background: base.background + 1,
80
+ backgroundHover: base.backgroundHover + 1,
81
+ backgroundPress: base.backgroundPress + 1,
82
+ backgroundFocus: base.backgroundFocus + 1,
83
+ borderColor: base.borderColor + 1,
84
+ borderColorHover: base.borderColorHover + 1,
85
+ borderColorFocus: base.borderColorFocus + 1,
86
+ borderColorPress: base.borderColorPress + 1,
87
+ }
88
+
89
+ const surface2 = {
90
+ background: base.background + 2,
91
+ backgroundHover: base.backgroundHover + 2,
92
+ backgroundPress: base.backgroundPress + 2,
93
+ backgroundFocus: base.backgroundFocus + 2,
94
+ borderColor: base.borderColor + 2,
95
+ borderColorHover: base.borderColorHover + 2,
96
+ borderColorFocus: base.borderColorFocus + 2,
97
+ borderColorPress: base.borderColorPress + 2,
98
+ }
99
+
100
+ const surface3 = {
101
+ background: base.background + 3,
102
+ backgroundHover: base.backgroundHover + 3,
103
+ backgroundPress: base.backgroundPress + 3,
104
+ backgroundFocus: base.backgroundFocus + 3,
105
+ borderColor: base.borderColor + 3,
106
+ borderColorHover: base.borderColorHover + 3,
107
+ borderColorFocus: base.borderColorFocus + 3,
108
+ borderColorPress: base.borderColorPress + 3,
109
+ }
110
+
111
+ const alt1 = {
112
+ color: base.color - 1,
113
+ colorHover: base.colorHover - 1,
114
+ colorPress: base.colorPress - 1,
115
+ colorFocus: base.colorFocus - 1,
116
+ }
117
+
118
+ const alt2 = {
119
+ color: base.color - 2,
120
+ colorHover: base.colorHover - 2,
121
+ colorPress: base.colorPress - 2,
122
+ colorFocus: base.colorFocus - 2,
123
+ }
124
+
125
+ const inverse = Object.fromEntries(
126
+ Object.entries(base).map(([key, index]) => {
127
+ return [key, -index]
128
+ })
129
+ )
130
+
131
+ return {
132
+ base,
133
+ surface1,
134
+ surface2,
135
+ surface3,
136
+ alt1,
137
+ alt2,
138
+ inverse,
139
+ } satisfies BuildTemplates
140
+ }
141
+
142
+ export const defaultTemplates = getTemplates()
@@ -0,0 +1,94 @@
1
+ import { hsla, parseToHsla } from 'color2k'
2
+ import type { BuildPalette } from '@tamagui/themes'
3
+
4
+ /**
5
+ * palette generally is:
6
+ *
7
+ * [constrastBackground, backgroundTransparent, ...background, ...foreground, foregroundTransparent, accentForeground]
8
+ */
9
+
10
+ const paletteSize = 12
11
+
12
+ // how many things come before the actual bg color (transparencies etc)
13
+ export const PALETTE_BACKGROUND_OFFSET = 4
14
+
15
+ const generateColorPalette = ({
16
+ palette: buildPalette,
17
+ scheme,
18
+ }: {
19
+ palette: BuildPalette
20
+ scheme: 'light' | 'dark'
21
+ }) => {
22
+ if (!buildPalette) {
23
+ return [] as string[]
24
+ }
25
+
26
+ const { anchors } = buildPalette
27
+
28
+ let palette: string[] = []
29
+
30
+ const add = (h: number, s: number, l: number) => {
31
+ palette.push(hsla(h, s, l, 1))
32
+ }
33
+
34
+ const numAnchors = Object.keys(anchors).length
35
+
36
+ for (const [anchorIndex, anchor] of anchors.entries()) {
37
+ const [h, s, l] = [anchor.hue[scheme], anchor.sat[scheme], anchor.lum[scheme]]
38
+
39
+ if (anchorIndex !== 0) {
40
+ const lastAnchor = anchors[anchorIndex - 1]
41
+ const steps = anchor.index - lastAnchor.index
42
+
43
+ const lastHue = lastAnchor.hue[scheme]
44
+ const lastSat = lastAnchor.sat[scheme]
45
+ const lastLum = lastAnchor.lum[scheme]
46
+
47
+ const stepHue = (lastHue - h) / steps
48
+ const stepSat = (lastSat - s) / steps
49
+ const stepLum = (lastLum - l) / steps
50
+
51
+ // backfill:
52
+ for (let step = lastAnchor.index + 1; step < anchor.index; step++) {
53
+ const str = anchor.index - step
54
+ add(h + stepHue * str, s + stepSat * str, l + stepLum * str)
55
+ }
56
+ }
57
+
58
+ add(h, s, l)
59
+
60
+ const isLastAnchor = anchorIndex === numAnchors - 1
61
+ if (isLastAnchor && palette.length < paletteSize) {
62
+ // forwardfill:
63
+ for (let step = anchor.index + 1; step < paletteSize; step++) {
64
+ add(h, s, l)
65
+ }
66
+ }
67
+ }
68
+
69
+ // add transparent values
70
+ const [background] = palette
71
+ const foreground = palette[palette.length - 1]
72
+
73
+ const transparentValues = [background, foreground].map((color) => {
74
+ const [h, s, l] = parseToHsla(color)
75
+ // fully transparent to partially
76
+ return [
77
+ hsla(h, s, l, 0),
78
+ hsla(h, s, l, 0.25),
79
+ hsla(h, s, l, 0.5),
80
+ hsla(h, s, l, 0.75),
81
+ ] as const
82
+ })
83
+ const reverseForeground = [...transparentValues[1]].reverse()
84
+ palette = [...transparentValues[0], ...palette, ...reverseForeground]
85
+
86
+ return palette
87
+ }
88
+
89
+ export function getThemeSuitePalettes(palette: BuildPalette) {
90
+ return {
91
+ light: generateColorPalette({ palette, scheme: 'light' }),
92
+ dark: generateColorPalette({ palette, scheme: 'dark' }),
93
+ }
94
+ }
package/src/index.ts CHANGED
@@ -1,5 +1,18 @@
1
1
  export * from './ThemeBuilder'
2
2
  export * from '@tamagui/create-theme'
3
3
 
4
+ export {
5
+ createStudioThemes,
6
+ createThemeSuite,
7
+ getThemeSuitePalettes,
8
+ createPalettes,
9
+ type CreateThemeSuiteProps,
10
+ } from './createThemeSuite'
11
+
12
+ export { defaultTemplates } from './defaultTemplates'
13
+ export { defaultComponentThemes } from './defaultComponentThemes'
14
+
15
+ export { PALETTE_BACKGROUND_OFFSET } from './getThemeSuitePalettes'
16
+
4
17
  // copied from themes to avoid cyclic dep
5
18
  export { masks } from './masks'
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeBuilder.d.ts","sourceRoot":"","sources":["../src/ThemeBuilder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ThemeBuilder.d.ts","sourceRoot":"","sources":["../src/ThemeBuilder.ts"],"names":[],"mappings":"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"}