@tujyane/alf 1.0.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.
Files changed (87) hide show
  1. package/README.md +226 -0
  2. package/dist/atoms/common.d.ts +992 -0
  3. package/dist/atoms/common.d.ts.map +1 -0
  4. package/dist/atoms/common.js +1067 -0
  5. package/dist/atoms/common.js.map +1 -0
  6. package/dist/atoms/index.d.ts +2 -0
  7. package/dist/atoms/index.d.ts.map +1 -0
  8. package/dist/atoms/index.js +18 -0
  9. package/dist/atoms/index.js.map +1 -0
  10. package/dist/atoms/index.native.d.ts +1020 -0
  11. package/dist/atoms/index.native.d.ts.map +1 -0
  12. package/dist/atoms/index.native.js +119 -0
  13. package/dist/atoms/index.native.js.map +1 -0
  14. package/dist/atoms/types.d.ts +3 -0
  15. package/dist/atoms/types.d.ts.map +1 -0
  16. package/dist/atoms/types.js +3 -0
  17. package/dist/atoms/types.js.map +1 -0
  18. package/dist/index.d.ts +23 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +64 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/palette.d.ts +72 -0
  23. package/dist/palette.d.ts.map +1 -0
  24. package/dist/palette.js +152 -0
  25. package/dist/palette.js.map +1 -0
  26. package/dist/platform/index.d.ts +45 -0
  27. package/dist/platform/index.d.ts.map +1 -0
  28. package/dist/platform/index.js +55 -0
  29. package/dist/platform/index.js.map +1 -0
  30. package/dist/platform/index.native.d.ts +16 -0
  31. package/dist/platform/index.native.d.ts.map +1 -0
  32. package/dist/platform/index.native.js +20 -0
  33. package/dist/platform/index.native.js.map +1 -0
  34. package/dist/themes.d.ts +151 -0
  35. package/dist/themes.d.ts.map +1 -0
  36. package/dist/themes.js +191 -0
  37. package/dist/themes.js.map +1 -0
  38. package/dist/tokens.d.ts +49 -0
  39. package/dist/tokens.d.ts.map +1 -0
  40. package/dist/tokens.js +52 -0
  41. package/dist/tokens.js.map +1 -0
  42. package/dist/utils/alpha.d.ts +2 -0
  43. package/dist/utils/alpha.d.ts.map +1 -0
  44. package/dist/utils/alpha.js +30 -0
  45. package/dist/utils/alpha.js.map +1 -0
  46. package/dist/utils/flatten/index.d.ts +3 -0
  47. package/dist/utils/flatten/index.d.ts.map +1 -0
  48. package/dist/utils/flatten/index.js +9 -0
  49. package/dist/utils/flatten/index.js.map +1 -0
  50. package/dist/utils/flatten/index.native.d.ts +3 -0
  51. package/dist/utils/flatten/index.native.d.ts.map +1 -0
  52. package/dist/utils/flatten/index.native.js +6 -0
  53. package/dist/utils/flatten/index.native.js.map +1 -0
  54. package/dist/utils/flatten/index.web.d.ts +3 -0
  55. package/dist/utils/flatten/index.web.d.ts.map +1 -0
  56. package/dist/utils/flatten/index.web.js +6 -0
  57. package/dist/utils/flatten/index.web.js.map +1 -0
  58. package/dist/utils/index.d.ts +5 -0
  59. package/dist/utils/index.d.ts.map +1 -0
  60. package/dist/utils/index.js +21 -0
  61. package/dist/utils/index.js.map +1 -0
  62. package/dist/utils/leading.d.ts +14 -0
  63. package/dist/utils/leading.d.ts.map +1 -0
  64. package/dist/utils/leading.js +64 -0
  65. package/dist/utils/leading.js.map +1 -0
  66. package/dist/utils/select.d.ts +7 -0
  67. package/dist/utils/select.d.ts.map +1 -0
  68. package/dist/utils/select.js +16 -0
  69. package/dist/utils/select.js.map +1 -0
  70. package/package.json +45 -0
  71. package/src/atoms/common.ts +1049 -0
  72. package/src/atoms/index.native.ts +84 -0
  73. package/src/atoms/index.ts +1 -0
  74. package/src/atoms/types.ts +11 -0
  75. package/src/index.tsx +46 -0
  76. package/src/palette.ts +237 -0
  77. package/src/platform/index.native.ts +16 -0
  78. package/src/platform/index.ts +54 -0
  79. package/src/themes.ts +332 -0
  80. package/src/tokens.ts +54 -0
  81. package/src/utils/alpha.ts +25 -0
  82. package/src/utils/flatten/index.native.ts +3 -0
  83. package/src/utils/flatten/index.ts +8 -0
  84. package/src/utils/flatten/index.web.ts +3 -0
  85. package/src/utils/index.ts +4 -0
  86. package/src/utils/leading.ts +30 -0
  87. package/src/utils/select.ts +19 -0
package/src/themes.ts ADDED
@@ -0,0 +1,332 @@
1
+ import { atoms } from "./atoms";
2
+ import { alpha } from "./utils/alpha";
3
+
4
+ import { Palette, DEFAULT_PALETTE, invertPalette } from "./palette";
5
+ import { type ShadowStyle } from "./atoms/types";
6
+
7
+ export const themes = createThemes({
8
+ defaultPalette: DEFAULT_PALETTE,
9
+ });
10
+
11
+ export type ThemeAtoms = {
12
+ // Base text colors (using primary neutral scale)
13
+ text: {
14
+ color: string;
15
+ };
16
+ text_low: {
17
+ color: string;
18
+ };
19
+ text_medium: {
20
+ color: string;
21
+ };
22
+ text_high: {
23
+ color: string;
24
+ };
25
+ text_inverted: {
26
+ color: string;
27
+ };
28
+
29
+ // Base backgrounds (using primary neutral scale)
30
+ bg: {
31
+ backgroundColor: string;
32
+ };
33
+ bg_25: {
34
+ backgroundColor: string;
35
+ };
36
+ bg_50: {
37
+ backgroundColor: string;
38
+ };
39
+
40
+ // Base borders (using primary neutral scale)
41
+ border_low: {
42
+ borderColor: string;
43
+ };
44
+ border_medium: {
45
+ borderColor: string;
46
+ };
47
+ border_high: {
48
+ borderColor: string;
49
+ };
50
+
51
+ // Semantic text atoms
52
+ text_primary: { color: string };
53
+ text_success: { color: string };
54
+ text_error: { color: string };
55
+ text_warning: { color: string };
56
+ text_info: { color: string };
57
+ text_secondary: { color: string };
58
+
59
+ // Semantic background atoms
60
+ bg_primary: { backgroundColor: string };
61
+ bg_success: { backgroundColor: string };
62
+ bg_error: { backgroundColor: string };
63
+ bg_warning: { backgroundColor: string };
64
+ bg_info: { backgroundColor: string };
65
+ bg_secondary: { backgroundColor: string };
66
+
67
+ // Semantic border atoms
68
+ border_primary: { borderColor: string };
69
+ border_success: { borderColor: string };
70
+ border_error: { borderColor: string };
71
+ border_warning: { borderColor: string };
72
+ border_info: { borderColor: string };
73
+ border_secondary: { borderColor: string };
74
+
75
+ // Shadows
76
+ shadow_sm: ShadowStyle;
77
+ shadow_md: ShadowStyle;
78
+ shadow_lg: ShadowStyle;
79
+ };
80
+
81
+ /**
82
+ * Categorical representation of the theme
83
+ */
84
+ export type ThemeScheme = "light" | "dark";
85
+
86
+ /**
87
+ * Specific theme name, including low-contrast variants
88
+ */
89
+ export type ThemeName = "light" | "dark" | "dim";
90
+
91
+ /**
92
+ * A theme object, containing the color palette and atoms for the theme
93
+ */
94
+ export type Theme = {
95
+ scheme: ThemeScheme;
96
+ name: ThemeName;
97
+ palette: Palette;
98
+ semantic: SemanticColors;
99
+ atoms: ThemeAtoms;
100
+ };
101
+
102
+ export type ScaleSteps = {
103
+ 100: string;
104
+ 200: string;
105
+ 300: string;
106
+ 400: string;
107
+ 500: string;
108
+ 600: string;
109
+ 700: string;
110
+ 800: string;
111
+ 900: string;
112
+ };
113
+
114
+ export type SemanticColors = {
115
+ primary: ScaleSteps;
116
+ success: ScaleSteps;
117
+ error: ScaleSteps;
118
+ warning: ScaleSteps;
119
+ info: ScaleSteps;
120
+ secondary: ScaleSteps;
121
+ };
122
+
123
+ function buildDefaultSemantic(palette: Palette): SemanticColors {
124
+ return {
125
+ primary: {
126
+ 100: palette.primary_100,
127
+ 200: palette.primary_200,
128
+ 300: palette.primary_300,
129
+ 400: palette.primary_400,
130
+ 500: palette.primary_500,
131
+ 600: palette.primary_600,
132
+ 700: palette.primary_700,
133
+ 800: palette.primary_800,
134
+ 900: palette.primary_900,
135
+ },
136
+ success: {
137
+ 100: palette.positive_100,
138
+ 200: palette.positive_200,
139
+ 300: palette.positive_300,
140
+ 400: palette.positive_400,
141
+ 500: palette.positive_500,
142
+ 600: palette.positive_600,
143
+ 700: palette.positive_700,
144
+ 800: palette.positive_800,
145
+ 900: palette.positive_900,
146
+ },
147
+ error: {
148
+ 100: palette.negative_100,
149
+ 200: palette.negative_200,
150
+ 300: palette.negative_300,
151
+ 400: palette.negative_400,
152
+ 500: palette.negative_500,
153
+ 600: palette.negative_600,
154
+ 700: palette.negative_700,
155
+ 800: palette.negative_800,
156
+ 900: palette.negative_900,
157
+ },
158
+ warning: {
159
+ 100: palette.warning_100,
160
+ 200: palette.warning_200,
161
+ 300: palette.warning_300,
162
+ 400: palette.warning_400,
163
+ 500: palette.warning_500,
164
+ 600: palette.warning_600,
165
+ 700: palette.warning_700,
166
+ 800: palette.warning_800,
167
+ 900: palette.warning_900,
168
+ },
169
+ info: {
170
+ 100: palette.info_100,
171
+ 200: palette.info_200,
172
+ 300: palette.info_300,
173
+ 400: palette.info_400,
174
+ 500: palette.info_500,
175
+ 600: palette.info_600,
176
+ 700: palette.info_700,
177
+ 800: palette.info_800,
178
+ 900: palette.info_900,
179
+ },
180
+ secondary: {
181
+ 100: palette.secondary_100,
182
+ 200: palette.secondary_200,
183
+ 300: palette.secondary_300,
184
+ 400: palette.secondary_400,
185
+ 500: palette.secondary_500,
186
+ 600: palette.secondary_600,
187
+ 700: palette.secondary_700,
188
+ 800: palette.secondary_800,
189
+ 900: palette.secondary_900,
190
+ },
191
+ };
192
+ }
193
+
194
+ export function createTheme({
195
+ scheme,
196
+ name,
197
+ palette,
198
+ options = {},
199
+ }: {
200
+ scheme: ThemeScheme;
201
+ name: ThemeName;
202
+ palette: Palette;
203
+ options?: {
204
+ shadowOpacity?: number;
205
+ semanticOverrides?: Partial<SemanticColors>;
206
+ };
207
+ }): Theme {
208
+ const shadowOpacity = options.shadowOpacity ?? 0.1;
209
+ const shadowColor = alpha(palette.black, shadowOpacity);
210
+ const baseSemantic = buildDefaultSemantic(palette);
211
+ const semantic: SemanticColors = {
212
+ ...baseSemantic,
213
+ ...options.semanticOverrides,
214
+ } as SemanticColors;
215
+ return {
216
+ scheme,
217
+ name,
218
+ palette,
219
+ semantic,
220
+ atoms: {
221
+ // Base text colors using primary neutral (scheme-dependent)
222
+ text: {
223
+ color: scheme === "light" ? palette.primary_900 : palette.white,
224
+ },
225
+ text_low: {
226
+ color: scheme === "light" ? palette.primary_400 : palette.primary_300,
227
+ },
228
+ text_medium: {
229
+ color: scheme === "light" ? palette.primary_700 : palette.primary_200,
230
+ },
231
+ text_high: {
232
+ color: scheme === "light" ? palette.primary_900 : palette.primary_100,
233
+ },
234
+ text_inverted: {
235
+ color: scheme === "light" ? palette.white : palette.primary_900,
236
+ },
237
+
238
+ // Base backgrounds using primary neutral
239
+ bg: {
240
+ backgroundColor:
241
+ scheme === "light" ? palette.white : palette.primary_900,
242
+ },
243
+ bg_25: {
244
+ backgroundColor:
245
+ scheme === "light" ? palette.primary_25 : palette.primary_800,
246
+ },
247
+ bg_50: {
248
+ backgroundColor:
249
+ scheme === "light" ? palette.primary_50 : palette.primary_700,
250
+ },
251
+
252
+ // Base borders using primary neutral
253
+ border_low: {
254
+ borderColor:
255
+ scheme === "light" ? palette.primary_100 : palette.primary_700,
256
+ },
257
+ border_medium: {
258
+ borderColor:
259
+ scheme === "light" ? palette.primary_200 : palette.primary_600,
260
+ },
261
+ border_high: {
262
+ borderColor:
263
+ scheme === "light" ? palette.primary_300 : palette.primary_500,
264
+ },
265
+
266
+ // Semantic text atoms (900 for text)
267
+ text_primary: { color: semantic.primary[900] },
268
+ text_success: { color: semantic.success[900] },
269
+ text_error: { color: semantic.error[900] },
270
+ text_warning: { color: semantic.warning[900] },
271
+ text_info: { color: semantic.info[900] },
272
+ text_secondary: { color: semantic.secondary[900] },
273
+
274
+ // Semantic background atoms (500 for bg)
275
+ bg_primary: { backgroundColor: semantic.primary[500] },
276
+ bg_success: { backgroundColor: semantic.success[500] },
277
+ bg_error: { backgroundColor: semantic.error[500] },
278
+ bg_warning: { backgroundColor: semantic.warning[500] },
279
+ bg_info: { backgroundColor: semantic.info[500] },
280
+ bg_secondary: { backgroundColor: semantic.secondary[500] },
281
+
282
+ // Semantic border atoms (300 for border)
283
+ border_primary: { borderColor: semantic.primary[300] },
284
+ border_success: { borderColor: semantic.success[300] },
285
+ border_error: { borderColor: semantic.error[300] },
286
+ border_warning: { borderColor: semantic.warning[300] },
287
+ border_info: { borderColor: semantic.info[300] },
288
+ border_secondary: { borderColor: semantic.secondary[300] },
289
+
290
+ // Shadows
291
+ shadow_sm: {
292
+ ...atoms.shadow_sm,
293
+ shadowColor: palette.black,
294
+ boxShadow: `0 4px 6px -1px ${shadowColor}, 0 2px 4px -2px ${shadowColor}`,
295
+ },
296
+ shadow_md: {
297
+ ...atoms.shadow_md,
298
+ shadowColor: palette.black,
299
+ boxShadow: `0 10px 15px -3px ${shadowColor}, 0 4px 6px -4px ${shadowColor}`,
300
+ },
301
+ shadow_lg: {
302
+ ...atoms.shadow_lg,
303
+ shadowColor: palette.black,
304
+ boxShadow: `0 20px 25px -5px ${shadowColor}, 0 8px 10px -6px ${shadowColor}`,
305
+ },
306
+ },
307
+ };
308
+ }
309
+
310
+ export function createThemes({ defaultPalette }: { defaultPalette: Palette }): {
311
+ light: Theme;
312
+ dark: Theme;
313
+ } {
314
+ const light = createTheme({
315
+ scheme: "light",
316
+ name: "light",
317
+ palette: defaultPalette,
318
+ });
319
+ const dark = createTheme({
320
+ scheme: "dark",
321
+ name: "dark",
322
+ palette: invertPalette(defaultPalette),
323
+ options: {
324
+ shadowOpacity: 0.4,
325
+ },
326
+ });
327
+
328
+ return {
329
+ light,
330
+ dark,
331
+ };
332
+ }
package/src/tokens.ts ADDED
@@ -0,0 +1,54 @@
1
+ export const TRACKING = 0;
2
+
3
+ export const space = {
4
+ _2xs: 2,
5
+ xs: 4,
6
+ sm: 8,
7
+ md: 12,
8
+ lg: 16,
9
+ xl: 20,
10
+ _2xl: 24,
11
+ _3xl: 28,
12
+ _4xl: 32,
13
+ _5xl: 40,
14
+ } as const;
15
+
16
+ export const fontSize = {
17
+ _2xs: 9.4,
18
+ xs: 11.3,
19
+ sm: 13.1,
20
+ md: 15,
21
+ lg: 16.9,
22
+ xl: 18.8,
23
+ _2xl: 20.6,
24
+ _3xl: 24.3,
25
+ _4xl: 30,
26
+ _5xl: 37.5,
27
+ } as const;
28
+
29
+ export const lineHeight = {
30
+ tight: 1.15,
31
+ snug: 1.3,
32
+ relaxed: 1.5,
33
+ } as const;
34
+
35
+ export const borderRadius = {
36
+ _2xs: 2,
37
+ xs: 4,
38
+ sm: 8,
39
+ md: 12,
40
+ lg: 16,
41
+ full: 999,
42
+ } as const;
43
+
44
+ export const fontWeight = {
45
+ normal: "400",
46
+ medium: "500",
47
+ semiBold: "600",
48
+ bold: "700",
49
+ } as const;
50
+
51
+ export const labelerColor = {
52
+ purple: "rgb(105 0 255)",
53
+ purple_dark: "rgb(83 0 202)",
54
+ } as const;
@@ -0,0 +1,25 @@
1
+ export function alpha(color: string, opacity: number) {
2
+ if (color.startsWith("hsl(")) {
3
+ return "hsla(" + color.slice("hsl(".length, -1) + `, ${opacity})`;
4
+ } else if (color.startsWith("rgb(")) {
5
+ return "rgba(" + color.slice("rgb(".length, -1) + `, ${opacity})`;
6
+ } else if (color.startsWith("#")) {
7
+ if (color.length === 7) {
8
+ const alphaHex = Math.round(opacity * 255).toString(16);
9
+ // Per MDN: If there is only one number, it is duplicated: e means ee
10
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
11
+ return color.slice(0, 7) + alphaHex.padStart(2, alphaHex);
12
+ } else if (color.length === 4) {
13
+ // convert to 6-digit hex before adding opacity
14
+ const hex = color.slice(1);
15
+ if (hex.length !== 3) return color;
16
+ const [r, g, b] = hex.split("") as [string, string, string];
17
+ const alphaHex = Math.round(opacity * 255).toString(16);
18
+ return `#${r.repeat(2)}${g.repeat(2)}${b.repeat(2)}${alphaHex.padStart(
19
+ 2,
20
+ alphaHex
21
+ )}`;
22
+ }
23
+ }
24
+ return color;
25
+ }
@@ -0,0 +1,3 @@
1
+ import { StyleSheet } from "react-native";
2
+
3
+ export const flatten = StyleSheet.flatten;
@@ -0,0 +1,8 @@
1
+ import { type StyleProp } from "react-native";
2
+
3
+ export const flatten = <T>(
4
+ style: StyleProp<T>
5
+ ): T extends (infer U)[] ? U : T => {
6
+ const defs = ([] as any).concat(style);
7
+ return Object.assign({}, ...defs.filter(Boolean).flat());
8
+ };
@@ -0,0 +1,3 @@
1
+ import { StyleSheet } from "react-native";
2
+
3
+ export const flatten = StyleSheet.flatten;
@@ -0,0 +1,4 @@
1
+ export * from "./alpha";
2
+ export * from "./leading";
3
+ export * from "./flatten";
4
+ export * from "./select";
@@ -0,0 +1,30 @@
1
+ import { type TextStyle } from "react-native";
2
+
3
+ import { isWeb } from "../platform";
4
+ import * as tokens from "../tokens";
5
+
6
+ /**
7
+ * Util to calculate lineHeight from a text size atom and a leading atom (which
8
+ * are unitless). On native, this will evaluate to a rounded pixel value. On
9
+ * web, it will be a unitless string.
10
+ *
11
+ * Example:
12
+ * `leading({
13
+ * fontSize: 15,
14
+ * lineHeight: 1.2
15
+ * })` // => { lineHeight: 17 }
16
+ */
17
+ export function leading(textStyle: TextStyle): Pick<TextStyle, "lineHeight"> {
18
+ const lineHeight = textStyle?.lineHeight || tokens.lineHeight.snug;
19
+
20
+ if (isWeb) {
21
+ return {
22
+ lineHeight: String(lineHeight) as unknown as TextStyle["lineHeight"],
23
+ };
24
+ } else {
25
+ const size = textStyle?.fontSize || tokens.fontSize.sm;
26
+ return {
27
+ lineHeight: Math.round(size * lineHeight),
28
+ };
29
+ }
30
+ }
@@ -0,0 +1,19 @@
1
+ import { type ThemeName } from "../themes";
2
+
3
+ export function select<T>(
4
+ name: ThemeName,
5
+ options:
6
+ | (Record<ThemeName, T> & { default?: undefined })
7
+ | (Partial<Record<ThemeName, T>> & { default: T })
8
+ ): T {
9
+ switch (name) {
10
+ case "light":
11
+ return options.light as T;
12
+ case "dark":
13
+ return options.dark as T;
14
+ case "dim":
15
+ return options.dim as T;
16
+ default:
17
+ return options.default as T;
18
+ }
19
+ }